// -*- C++ -*- /** @file include/array/array_base.cc.h @brief Array base class template implementations. Copyright (c) 2024 Christian Zimmermann. All rights reserved. Mail: chizeta@f3l.de **/ #ifndef __cxz_array_base_cc_h__ #define __cxz_array_base_cc_h__ #include "array_base.h" #include "slice.h" namespace CNORXZ { /*=======================================================+ | Implementations for CArrayBase member functions | +=======================================================*/ template CArrayBase::CArrayBase(const RangePtr& range) : mRange(rangeCast(range)) {} template template const T& CArrayBase::operator[](const IndexInterface& i) const { if(formatIsTrivial()){ return data()[i.lex()]; } else { auto ai = itLex(i); return *ai; } } template template const T& CArrayBase::at(const IndexInterface& i) const { auto ai = itLexSave(i); return *ai; } template template const T& CArrayBase::operator[](const SPack& pack) const { if(formatIsTrivial()){ return data()[pack.lex()]; } else { auto ai = itLex(pack); return *ai; } } template template const T& CArrayBase::at(const SPack& pack) const { auto ai = itLexSave(pack); return *ai; } template const T& CArrayBase::operator[](const DPack& pack) const { auto ai = itLex(pack); return *ai; } template const T& CArrayBase::at(const DPack& pack) const { auto ai = itLexSave(pack); return *ai; } template template Sptr> CArrayBase::sl(const IndexInterface& begin, const IndexInterface& end) const { auto ai = itLexSave(begin); auto aj = itLexSave(end); return std::make_shared>(ai.prange(aj), this, ai.format(), ai.pos()); } template SizeT CArrayBase::size() const { return mRange->size(); } template RangePtr CArrayBase::range() const { return mRange; } template typename CArrayBase::const_iterator CArrayBase::begin() const { return this->cbegin(); } template typename CArrayBase::const_iterator CArrayBase::end() const { return this->cend(); } template template COpRoot CArrayBase::operator()(const Sptr& i) const { if(formatIsTrivial()){ // assert that index format is trivial and has correct extensions CXZ_ASSERT(i->formatIsTrivial(), "got non-trivial index for container with trivial format"); this->checkFormatCompatibility(*i); return coproot(*this, i); } else { if(i->formatIsTrivial()){ // try to apply container format. // if the reformat changes the index type in any manner // the format is not applicable: if constexpr(std::is_samereformat( Vector(), Vector() )),Index>::value){ auto beg = begin(); auto aformat = beg.deepFormat(); auto amax = beg.deepMax(); auto fi = i->reformat( aformat, amax ); return coproot(*this, moveToPtr( fi ) ); } else { this->checkFormatCompatibility(*i); return coproot(*this, i); } } else { // check if format is compatible this->checkFormatCompatibility(*i); return coproot(*this, i); } } } template template inline decltype(auto) CArrayBase::operator()(const SPack& pack) const { return operator()(mindexPtr(pack)); } template inline decltype(auto) CArrayBase::operator()(const DPack& pack) const { return operator()(yindexPtr(pack)); } /*=================================================================+ | Implementations for protected CArrayBase member functions | +=================================================================*/ template template typename CArrayBase::const_iterator CArrayBase::itLex(const Acc& acc) const { return begin() + acc.lex(); } template template typename CArrayBase::const_iterator CArrayBase::itLexSave(const Acc& acc) const { CXZ_ASSERT(acc.lex() < this->size(), "index out of range"); //CXZ_ASSERT(false, "IMPLEMENT CHECKS!!"); // check further compatibility of index/range format!!! return begin() + acc.lex(); } template template void CArrayBase::checkFormatCompatibility(const Acc& acc) const { auto j = begin(); CXZ_ASSERT(acc.lmax().val() == j.lmax().val(), "got index of iteration space size = " << acc.lmax().val() << ", expected size = " << acc.lmax().val()); Vector f1 = toVec(acc.deepFormat()); Vector f2 = j.deepFormat(); std::sort(f1.begin(),f1.end()); std::sort(f2.begin(),f2.end()); SizeT i1 = 0; SizeT i2 = 0; CXZ_ASSERT(f1[i1] == f2[i2], "obtained format " << toString(f1) << ", which is incompatible to target format " << toString(f2)); ++i1; ++i2; while(i1 < f1.size() and i2 < f2.size()){ if(f1[i1] < f2[i2]) { if(++i1 == f1.size()) break; CXZ_ASSERT(f1[i1] <= f2[i2], "obtained format " << toString(f1) << ", which is incompatible to target format " << toString(f2)); } else if(f1[i1] > f2[i2]) { if(++i2 == f2.size()) break; CXZ_ASSERT(f1[i1] >= f2[i2], "obtained format " << toString(f1) << ", which is incompatible to target format " << toString(f2)); } else { ++i1; ++i2; } } } /*======================================================+ | Implementations for ArrayBase member functions | +======================================================*/ template ArrayBase::ArrayBase(const RangePtr& range) : CArrayBase(range) {} template template T& ArrayBase::operator[](const IndexInterface& i) { if(this->formatIsTrivial()){ return data()[i.lex()]; } else { auto ai = itLex(i); return *ai; } } template template T& ArrayBase::at(const IndexInterface& i) { auto ai = itLexSave(i); return *ai; } template template T& ArrayBase::operator[](const SPack& pack) { if(this->formatIsTrivial()){ return data()[pack.lex()]; } else { auto ai = itLex(pack); return *ai; } } template template T& ArrayBase::at(const SPack& pack) { auto ai = itLexSave(pack); return *ai; } template T& ArrayBase::operator[](const DPack& pack) { auto ai = itLex(pack); return *ai; } template T& ArrayBase::at(const DPack& pack) { auto ai = itLexSave(pack); return *ai; } template template Sptr> ArrayBase::sl(const IndexInterface& begin, const IndexInterface& end) { auto ai = itLexSave(begin); auto aj = itLexSave(end); return std::make_shared>(ai.prange(aj), this, ai.format(), ai.pos()); } template typename ArrayBase::iterator ArrayBase::begin() { return iterator(this->data(), this->cbegin()); } template typename ArrayBase::iterator ArrayBase::end() { return iterator(this->data(), this->cend()); } template template OpRoot ArrayBase::operator()(const Sptr& i) { if(this->formatIsTrivial()){ // assert that index format is trivial and has correct extensions CXZ_ASSERT(i->formatIsTrivial(), "got non-trivial index for container with trivial format"); this->checkFormatCompatibility(*i); return oproot(*this, i); } else { if(i->formatIsTrivial()){ // try to apply container format. // if the reformat changes the index type in any manner // the format is not applicable: if constexpr(std::is_samereformat( Vector(), Vector() )),Index>::value){ auto beg = begin(); auto aformat = beg.deepFormat(); auto amax = beg.deepMax(); auto fi = i->reformat( aformat, amax ); return oproot(*this, moveToPtr( fi ) ); } else { this->checkFormatCompatibility(*i); return oproot(*this, i); } } else { // check if format is compatible this->checkFormatCompatibility(*i); return oproot(*this, i); } } } template template inline decltype(auto) ArrayBase::operator()(const SPack& pack) { return operator()(mindexPtr(pack)); } template inline decltype(auto) ArrayBase::operator()(const DPack& pack) { return operator()(yindexPtr(pack)); } /*================================================================+ | Implementations for protected ArrayBase member functions | +================================================================*/ template template typename ArrayBase::iterator ArrayBase::itLex(const Acc& acc) { return begin() + acc.lex(); } template template typename ArrayBase::iterator ArrayBase::itLexSave(const Acc& acc) { CXZ_ASSERT(acc.lex() < this->size(), "index out of range"); //CXZ_ASSERT(false, "IMPLEMENT CHECKS!!"); // check further compatibility of index/range format!!! return begin() + acc.lex(); } } #endif