#ifndef GRID_SERIALISATION_VECTORUTILS_H #define GRID_SERIALISATION_VECTORUTILS_H #include #include namespace Grid { // Grid scalar tensors to nested std::vectors ////////////////////////////////// template struct TensorToVec { typedef T type; }; template struct TensorToVec> { typedef typename TensorToVec::type type; }; template struct TensorToVec> { typedef typename std::vector::type> type; }; template struct TensorToVec> { typedef typename std::vector::type>> type; }; template void tensorDim(std::vector &dim, const T &t, const bool wipe = true) { if (wipe) { dim.clear(); } } template void tensorDim(std::vector &dim, const iScalar &t, const bool wipe = true) { if (wipe) { dim.clear(); } tensorDim(dim, t._internal, false); } template void tensorDim(std::vector &dim, const iVector &t, const bool wipe = true) { if (wipe) { dim.clear(); } dim.push_back(N); tensorDim(dim, t._internal[0], false); } template void tensorDim(std::vector &dim, const iMatrix &t, const bool wipe = true) { if (wipe) { dim.clear(); } dim.push_back(N); dim.push_back(N); tensorDim(dim, t._internal[0][0], false); } template typename TensorToVec::type tensorToVec(const T &t) { return t; } template typename TensorToVec>::type tensorToVec(const iScalar& t) { return tensorToVec(t._internal); } template typename TensorToVec>::type tensorToVec(const iVector& t) { typename TensorToVec>::type v; v.resize(N); for (unsigned int i = 0; i < N; i++) { v[i] = tensorToVec(t._internal[i]); } return v; } template typename TensorToVec>::type tensorToVec(const iMatrix& t) { typename TensorToVec>::type v; v.resize(N); for (unsigned int i = 0; i < N; i++) { v[i].resize(N); for (unsigned int j = 0; j < N; j++) { v[i][j] = tensorToVec(t._internal[i][j]); } } return v; } template void vecToTensor(T &t, const typename TensorToVec::type &v) { t = v; } template void vecToTensor(iScalar &t, const typename TensorToVec>::type &v) { vecToTensor(t._internal, v); } template void vecToTensor(iVector &t, const typename TensorToVec>::type &v) { for (unsigned int i = 0; i < N; i++) { vecToTensor(t._internal[i], v[i]); } } template void vecToTensor(iMatrix &t, const typename TensorToVec>::type &v) { for (unsigned int i = 0; i < N; i++) for (unsigned int j = 0; j < N; j++) { vecToTensor(t._internal[i][j], v[i][j]); } } // Vector element trait ////////////////////////////////////////////////////// template struct element { typedef T type; static constexpr bool is_number = false; }; template struct element> { typedef typename element::type type; static constexpr bool is_number = std::is_arithmetic::value or is_complex::value or element::is_number; }; // Vector flattening utility class //////////////////////////////////////////// // Class to flatten a multidimensional std::vector template class Flatten { public: typedef typename element::type Element; public: explicit Flatten(const V &vector); const V & getVector(void); const std::vector & getFlatVector(void); const std::vector & getDim(void); private: void accumulate(const Element &e); template void accumulate(const W &v); void accumulateDim(const Element &e); template void accumulateDim(const W &v); private: const V &vector_; std::vector flatVector_; std::vector dim_; }; // Class to reconstruct a multidimensional std::vector template class Reconstruct { public: typedef typename element::type Element; public: Reconstruct(const std::vector &flatVector, const std::vector &dim); const V & getVector(void); const std::vector & getFlatVector(void); const std::vector & getDim(void); private: void fill(std::vector &v); template void fill(W &v); void resize(std::vector &v, const unsigned int dim); template void resize(W &v, const unsigned int dim); private: V vector_; const std::vector &flatVector_; std::vector dim_; size_t ind_{0}; unsigned int dimInd_{0}; }; // Flatten class template implementation template void Flatten::accumulate(const Element &e) { flatVector_.push_back(e); } template template void Flatten::accumulate(const W &v) { for (auto &e: v) { accumulate(e); } } template void Flatten::accumulateDim(const Element &e) {}; template template void Flatten::accumulateDim(const W &v) { dim_.push_back(v.size()); accumulateDim(v[0]); } template Flatten::Flatten(const V &vector) : vector_(vector) { accumulate(vector_); accumulateDim(vector_); } template const V & Flatten::getVector(void) { return vector_; } template const std::vector::Element> & Flatten::getFlatVector(void) { return flatVector_; } template const std::vector & Flatten::getDim(void) { return dim_; } // Reconstruct class template implementation template void Reconstruct::fill(std::vector &v) { for (auto &e: v) { e = flatVector_[ind_++]; } } template template void Reconstruct::fill(W &v) { for (auto &e: v) { fill(e); } } template void Reconstruct::resize(std::vector &v, const unsigned int dim) { v.resize(dim_[dim]); } template template void Reconstruct::resize(W &v, const unsigned int dim) { v.resize(dim_[dim]); for (auto &e: v) { resize(e, dim + 1); } } template Reconstruct::Reconstruct(const std::vector &flatVector, const std::vector &dim) : flatVector_(flatVector) , dim_(dim) { resize(vector_, 0); fill(vector_); } template const V & Reconstruct::getVector(void) { return vector_; } template const std::vector::Element> & Reconstruct::getFlatVector(void) { return flatVector_; } template const std::vector & Reconstruct::getDim(void) { return dim_; } // Vector IO utilities /////////////////////////////////////////////////////// // helper function to read space-separated values template std::vector strToVec(const std::string s) { std::istringstream sstr(s); T buf; std::vector v; while(!sstr.eof()) { sstr >> buf; v.push_back(buf); } return v; } // output to streams for vectors template < class T > inline std::ostream & operator<<(std::ostream &os, const std::vector &v) { os << "["; for (auto &x: v) { os << x << " "; } if (v.size() > 0) { os << "\b"; } os << "]"; return os; } } #endif