21 #include <ecolab_epilogue.h> 25 bool sorted(civita::XVector::const_iterator begin, civita::XVector::const_iterator end)
28 if (begin==end-1)
return true;
29 for (; begin!=end-1; ++begin)
30 if (!less(*begin,*(begin+1)))
41 vector<size_t> r(
rank());
43 for (
size_t dim=0; dim<
rank(); ++dim)
53 throw runtime_error(
"Rank of interpolated tensor doesn't match its argument");
57 const auto& targetHC=
hypercube().xvectors;
61 std::map<size_t,size_t> tmpRotation;
63 for (
size_t i=0; i<
rank(); ++i)
65 const auto& src=
arg->hypercube().xvectors[i];
69 const auto& dst=targetHC[i];
70 if (!dst.name.empty() || src.dimension.type!=dst.dimension.type ||
71 src.dimension.units!=dst.dimension.units)
72 throw runtime_error(
"mismatch between unnamed dimensions");
74 tmpRotation.emplace(make_pair(i,i));
78 auto dst=find_if(targetHC.begin(), targetHC.end(),
79 [&](
const XVector& i){
return i.name==src.name;});
80 if (dst==targetHC.end())
84 tmpRotation.emplace(make_pair(i,i));
89 tmpRotation.emplace(make_pair(dst-targetHC.begin(),i));
93 stride*=targetHC[i].size();
95 if (tmpRotation.size()!=
rank())
throw runtime_error(
"rotation of indices is not a permutation");
96 for (
auto& i: tmpRotation)
rotation[i.first]=i.second;
102 for (
size_t i=0; i<
size(); ++i)
105 for (
auto i:
index())
113 for (
size_t i=0; i<xv.size(); ++i)
114 s.second.push_back(i);
116 sort(s.second.begin(), s.second.end(),
117 [&](
size_t i,
size_t j){
return less(xv[i],xv[j]);});
118 for (
auto i: s.second)
119 s.first.push_back(xv[i]);
120 assert(
sorted(s.first.begin(), s.first.end()));
132 assert(i.index<
arg->hypercube().numElements());
133 r+=i.weight *
arg->atHCIndex(i.index);
143 if (
rank()>
sizeof(
size_t)*8)
144 throw runtime_error(
"Ranks > "+
to_string(
sizeof(
size_t)*8)+
" not supported");
145 size_t numNeighbours=size_t(1)<<
rank();
147 const auto& argHC=
arg->hypercube();
152 auto argIndexVector=
arg->index();
154 for (
size_t nbr=0; nbr<numNeighbours; ++nbr)
159 for (
size_t dim=0, stride=1; dim<
rank(); stride*=argHC.xvectors[dim].size(), ++dim)
163 assert(
sorted(x.begin(),x.end()));
164 auto v=
interimHC.xvectors[dim][iIdx[dim]];
165 auto lesserIt=std::upper_bound(x.begin(), x.end(), v, AnyLess());
166 if (lesserIt!=x.begin()) --lesserIt;
167 boost::any lesser=*lesserIt, greater;
168 if (diff(lesser, v)>=0)
170 else if (lesserIt+1==x.end())
173 greater=*(lesserIt+1);
175 bool greaterSide = nbr&(size_t(1)<<dim);
176 double d=diff(greater,lesser);
177 if (d==0 && greaterSide)
goto nextNeighbour;
179 idx +=
sortedArgHC[dim].second[(lesserIt-x.begin()+greaterSide)]*stride;
180 assert(idx<argHC.numElements());
182 weight *= greaterSide? diff(v,lesser): d-diff(v,lesser);
192 if (binary_search(indexV.begin(), indexV.end(), idx))
202 for (
auto& i: r) i.weight/=sumWeight;
std::vector< std::size_t > rotation
permutation of axes of interimHC and this->hypercube()
virtual const Hypercube & hypercube() const
information describing the axes, types and labels of this tensor
std::vector< std::size_t > strides
strides along each dimension of this->hypercube()
structure for referring to an argument index and its weight
virtual const Index & index() const
the index vector - assumed to be ordered and unique
virtual std::size_t size() const
return number of elements in tensor - maybe less than hypercube.numElements if sparse ...
void setArgument(const TensorPtr &a, const ITensor::Args &args={"", 0}) override
std::size_t hcIndex(const std::initializer_list< T > &indices) const
vector< WeightedIndexVector > weightedIndices
map from this tensor's index into the argument tensor
arguments relevant for tensor expressions, not always meaningful. Exception thrown if not...
std::vector< std::pair< XVector, std::vector< std::size_t > > > sortedArgHC
vector< std::size_t > splitAndRotate(std::size_t) const
std::shared_ptr< ITensor > TensorPtr
double operator[](std::size_t) const override
return or compute data at a location
WeightedIndexVector bodyCentredNeighbourhood(std::size_t idx) const
computes the neighbourhood around a target argument index when the target index is not on the hypercu...
string to_string(CONST84 char *x)
Hypercube interimHC
hypercube that's been rotated to match the arguments hypercube
bool sorted(civita::XVector::const_iterator begin, civita::XVector::const_iterator end)
void sortAndAdd(const XVector &)