diff --git a/t.cc b/t.cc index e99d72e..fa24f7a 100644 --- a/t.cc +++ b/t.cc @@ -3200,7 +3200,7 @@ cout < s(4); +for(int i=0; i<4; ++i) + { + s[i].number=1; + s[i].symmetry=0; + s[i].offset=0; + s[i].range=n; + } +Tensor t(s); +t.randomize(1.); +cout < p({3,1,4,2}); +Tensor tt=t.permute_index_groups(p); +cout < -int Tensor:: calcrank() +int Tensor:: calcrank() { int r=0; for(int i=0; i *>(&shape))[i]; + if(sh->number==0) laerror("empty index group"); + r+=sh->number; } myrank=r; return r; @@ -49,19 +50,20 @@ cumsizes.resize(shape.size()); LA_largeindex s=1; for(int i=0; i *>(&shape))[i]; + if(sh->number==0) laerror("empty index group"); + if(sh->range==0) return 0; cumsizes[i]=s; - switch(shape[i].symmetry) + switch(sh->symmetry) { case 0: - s *= groupsizes[i] = longpow(shape[i].range,shape[i].number); + s *= groupsizes[i] = longpow(sh->range,sh->number); break; case 1: - s *= groupsizes[i] = simplicial(shape[i].number,shape[i].range); + s *= groupsizes[i] = simplicial(sh->number,sh->range); break; case -1: - s *= groupsizes[i] = simplicial(shape[i].number,shape[i].range-shape[i].number+1); + s *= groupsizes[i] = simplicial(sh->number,sh->range-sh->number+1); break; default: laerror("illegal index group symmetry"); @@ -376,20 +378,21 @@ template void loopingroups(Tensor &t, int ngroup, int igroup, T **p, SUPERINDEX &I, void (*callback)(const SUPERINDEX &, T *)) { LA_index istart,iend; -switch(t.shape[ngroup].symmetry) +const indexgroup *sh = &(* const_cast *>(&t.shape))[ngroup]; +switch(sh->symmetry) { case 0: - istart= t.shape[ngroup].offset; - iend= t.shape[ngroup].offset+t.shape[ngroup].range-1; + istart= sh->offset; + iend= sh->offset+sh->range-1; break; case 1: - istart= t.shape[ngroup].offset; - if(igroup==t.shape[ngroup].number-1) iend= t.shape[ngroup].offset+t.shape[ngroup].range-1; + istart= sh->offset; + if(igroup==sh->number-1) iend= sh->offset+sh->range-1; else iend = I[ngroup][igroup+1]; break; case -1: - istart= t.shape[ngroup].offset + igroup; - if(igroup==t.shape[ngroup].number-1) iend= t.shape[ngroup].offset+t.shape[ngroup].range-1; + istart= sh->offset + igroup; + if(igroup==sh->number-1) iend= sh->offset+sh->range-1; else iend = I[ngroup][igroup+1]-1; break; } @@ -410,7 +413,8 @@ for(LA_index i = istart; i<=iend; ++i) if(newigroup<0) { --newngroup; - newigroup=t.shape[newngroup].number-1; + const indexgroup *sh2 = &(* const_cast *>(&t.shape))[newngroup]; + newigroup=sh2->number-1; } loopingroups(t,newngroup,newigroup,p,I,callback); } @@ -422,9 +426,16 @@ template void Tensor::loopover(void (*callback)(const SUPERINDEX &, T *)) { SUPERINDEX I(shape.size()); -for(int i=0; i *>(&shape))[i]; + I[i].resize(sh->number); + I[i] = sh->offset; + } T *pp=&data[0]; -loopingroups(*this,shape.size()-1,shape[shape.size()-1].number-1,&pp,I,callback); +int ss=shape.size()-1; +const indexgroup *sh = &(* const_cast *>(&shape))[ss]; +loopingroups(*this,ss,sh->number-1,&pp,I,callback); } @@ -487,6 +498,60 @@ return s; +template +void loopovergroups(Tensor &t, int ngroup, T **p, GROUPINDEX &I, void (*callback)(const GROUPINDEX &, T *)) +{ +for(LA_largeindex i = 0; i +void Tensor::grouploopover(void (*callback)(const GROUPINDEX &, T *)) +{ +GROUPINDEX I(shape.size()); +T *pp=&data[0]; +loopovergroups(*this,shape.size()-1,&pp,I,callback); +} + + +const NRPerm *help_p; +template +Tensor *help_t; + +template +static void permutecallback(const GROUPINDEX &I, T *v) +{ +LA_largeindex target=0; +for(int i=0; i< help_t->shape.size(); ++i) + { + target += I[(*help_p)[i+1]-1] * help_t->cumsizes[i]; + } +help_t->data[target] = *v; +} + + + +template +Tensor Tensor::permute_index_groups(const NRPerm &p) const +{ +NRVec newshape=shape.permuted(p); +Tensor r(newshape); + +//prepare statics for the callback +help_p = &p; +help_t = &r; + +//now rearrange the data +const_cast *>(this)->grouploopover(permutecallback); +return r; +} + + + template class Tensor; template class Tensor >; template std::ostream & operator<<(std::ostream &s, const Tensor &x); diff --git a/tensor.h b/tensor.h index 884b0a7..12cd254 100644 --- a/tensor.h +++ b/tensor.h @@ -97,6 +97,7 @@ class LA_traits { typedef NRVec FLATINDEX; //all indices but in a single vector typedef NRVec > SUPERINDEX; //all indices in the INDEXGROUP structure +typedef NRVec GROUPINDEX; //set of indices in the symmetry groups template @@ -104,10 +105,9 @@ class Tensor { public: NRVec shape; NRVec data; -private: int myrank; NRVec groupsizes; //group sizes of symmetry index groups (a function of shape but precomputed for efficiency) - NRVec cumsizes; //cumulative sizes of symmetry index groups (a function of shape but precomputed for efficiency) + NRVec cumsizes; //cumulative sizes of symmetry index groups (a function of shape but precomputed for efficiency); always cumsizes[0]=1, index group 0 is the innermost-loop one public: LA_largeindex index(int *sign, const SUPERINDEX &I) const; //map the tensor indices to the position in data @@ -117,7 +117,7 @@ public: //constructors Tensor() : myrank(0) {}; - Tensor(const NRVec &s) : shape(s), data((int)calcsize()) {calcrank();}; //general tensor + Tensor(const NRVec &s) : shape(s) { data.resize(calcsize()); calcrank();}; //general tensor Tensor(const indexgroup &g) {shape.resize(1); shape[0]=g; data.resize(calcsize()); calcrank();}; //tensor with a single index group Tensor(const Tensor &rhs): myrank(rhs.myrank), shape(rhs.shape), groupsizes(rhs.groupsizes), cumsizes(rhs.cumsizes), data(rhs.data) {}; Tensor(int xrank, const NRVec &xshape, const NRVec &xgroupsizes, const NRVec xcumsizes, const NRVec &xdata) : myrank(xrank), shape(xshape), groupsizes(xgroupsizes), cumsizes(xcumsizes), data(xdata) {}; @@ -173,14 +173,17 @@ public: inline void randomize(const typename LA_traits::normtype &x) {data.randomize(x);}; - void loopover(void (*callback)(const SUPERINDEX &, T *)); + void loopover(void (*callback)(const SUPERINDEX &, T *)); //loop over all elements + void grouploopover(void (*callback)(const GROUPINDEX &, T *)); //loop over all elements disregarding the internal structure of index groups + + Tensor permute_index_groups(const NRPerm &p) const; //rearrange the tensor storage permuting index groups as a whole //@@@TODO - unwinding to full size in a specified index //@@@contraction by a whole index group or by individual single index + //@@@ general antisymmetrization operator Kucharski style //@@@TODO - contractions - basic and efficient? first contraction in a single index; between a given group+index in group at each tensor //@@@outer product and product with a contraction //@@@@symmetrize a group, antisymmetrize a group, expand a (anti)symmetric grtoup - obecne symmetry change krome +1 na -1 vse mozne - //@@@@@@permute index groups };