Skip to content

File transpositionmap.h

File List > code_source > templat > include > TempLat > lattice > memory > memorylayouts > transpositionmap.h

Go to the documentation of this file

#ifndef TEMPLAT_LATTICE_MEMORY_MEMORYLAYOUTS_TRANSPOSITIONMAP_H
#define TEMPLAT_LATTICE_MEMORY_MEMORYLAYOUTS_TRANSPOSITIONMAP_H

/* This file is part of TempLat, available at https://cosmolattice.github.io/templat .
   Copyright 2021-2026 The TempLat authors, see AUTHORS.md.
   Released under the MIT license, see LICENSE.md. */

// File info: Main contributor(s): Wessel Valkenburg, Year: 2019

#include "TempLat/util/exception.h"
#include "TempLat/parallel/device.h"

namespace TempLat
{
  MakeException(TranspositionMapOutOfBounds);

  template <size_t NDim> class TranspositionMap
  {
  public:
    TranspositionMap() : mFromAtoB{}, mFromBtoA{}
    {
      for (size_t i = 0; i < NDim; ++i) {
        mFromAtoB[i] = i;
        mFromBtoA[i] = i;
      }
    }

    static constexpr size_t size() { return NDim; }

    DEVICE_INLINE_FUNCTION
    device::Idx getForward(device::Idx index) const { return mFromAtoB[index]; }
    DEVICE_INLINE_FUNCTION
    device::Idx getInverse(device::Idx index) const { return mFromBtoA[index]; }

    void setMap(const device::IdxArray<NDim> &input)
    {
      for (size_t i = 0; i < NDim; ++i)
        mFromAtoB[i] = input[i];

      for (device::Idx i = 0, iEnd = mFromAtoB.size(); i < iEnd; ++i) {
        if (mFromAtoB[i] < 0 || mFromAtoB[i] > iEnd - 1)
          throw TranspositionMapOutOfBounds("Your map has entries that go beyond the size of the map:", input);
        mFromBtoA[mFromAtoB[i]] = i;
      }
    }

    DEVICE_INLINE_FUNCTION
    bool isUntransposed() const
    {
      bool untransposed = true;
      for (device::Idx i = 0, iEnd = mFromAtoB.size(); i < iEnd; ++i) {
        untransposed = untransposed && mFromAtoB[i] == i && mFromBtoA[i] == i;
      }
      return untransposed;
    }

    DEVICE_INLINE_FUNCTION
    bool isTransposed() const { return !isUntransposed(); }

    friend bool operator==(const TranspositionMap &a, const TranspositionMap &b)
    {
      bool equal = a.size() == b.size();
      for (device::Idx i = 0, iEnd = a.size(); i < iEnd && equal; ++i) {
        equal = equal && a.getForward(i) == b.getForward(i) && a.getInverse(i) == b.getInverse(i);
      }
      return equal;
    }

    friend std::ostream &operator<<(std::ostream &ostream, const TranspositionMap &a)
    {
      ostream << " forward " << a.mFromAtoB << ", inverse " << a.mFromBtoA;
      return ostream;
    }

  private:
    /* From C to D means that entry at position 0 in C is at position mFromCtoD[0] in D. */
    device::IdxArray<NDim> mFromAtoB;
    device::IdxArray<NDim> mFromBtoA;
  };

} // namespace TempLat

#endif