#ifndef _MODE_MAPPING_IMPL_H #define _MODE_MAPPING_IMPL_H /////////Work out the unmapping for a single type template struct computeModeUnmapping{ typedef typename IndexVector::Type VectorType; static void doit(VectorType &v,modeIndexSet &coord, const DilutionType &dil){ int nidx = IndexConvention::getNidx(); v.resize(nidx); for(int i=0;i::set(coord,i); computeModeUnmapping::doit(v[i],coord, dil); } } }; template struct computeModeUnmapping<0,DilutionType>{ typedef typename IndexVector<0>::Type VectorType; static void doit(VectorType &v,modeIndexSet &coord, const DilutionType &dil){ std::vector &std_to_dil = v.first; std::vector &non_zeroes = v.second; dil.getIndexMapping(std_to_dil, non_zeroes, coord); } }; //Compute the mode map between types recursively //First move through packed nested coords //spincolor=3, flavor=2, time=1 template struct computeModeMap{ typedef typename IndexVector::Type VectorTypePacked; typedef typename IndexVector::Type VectorTypeUnpacked; typedef typename IndexTensor::Type TensorType; static void doit(TensorType &v,const VectorTypePacked &packed_unmap, const VectorTypeUnpacked &unpacked_unmap){ int nidx = IndexConvention::getNidx(); v.resize(nidx); for(int i=0;i::doit(v[i],packed_unmap[i],unpacked_unmap); } }; template struct computeModeMap<0,DepthUnpacked,PackedType,UnpackedType>{ //gotten down to the base modes for packed, start on unpacked typedef typename IndexVector<0>::Type VectorTypePacked; typedef typename IndexVector::Type VectorTypeUnpacked; typedef typename IndexTensor<0, DepthUnpacked>::Type TensorType; static void doit(TensorType &v,const VectorTypePacked &packed_unmap, const VectorTypeUnpacked &unpacked_unmap){ int nidx = IndexConvention::getNidx(); v.resize(nidx); for(int i=0;i::doit(v[i],packed_unmap,unpacked_unmap[i]); } }; template struct computeModeMap<0,0,PackedType,UnpackedType>{ //gotten down to the base modes for packed, start on unpacked typedef typename IndexVector<0>::Type VectorTypePacked; typedef typename IndexVector<0>::Type VectorTypeUnpacked; typedef typename IndexTensor<0, 0>::Type TensorType; //mode * mode static void doit(TensorType &v,const VectorTypePacked &packed_unmap, const VectorTypeUnpacked &unpacked_unmap){ //Fully unpack both and find the overlap between the sets of non-zero indices const std::vector &non_zeroes_packed = packed_unmap.second; const std::vector &non_zeroes_unpacked = unpacked_unmap.second; const std::vector &std_to_packed = packed_unmap.first; const std::vector &std_to_unpacked = unpacked_unmap.first; std::vector overlap; compute_overlap(overlap, non_zeroes_packed, non_zeroes_unpacked); int n_std = overlap.size(); assert(std_to_packed.size() == n_std); assert(std_to_unpacked.size() == n_std); v.resize(0); v.reserve(n_std); for(int i=0;i idx_pair(std_to_packed[i], std_to_unpacked[i]); v.push_back(idx_pair); } } }; template void ModeMapping::compute(TensorType &idx_map, const A2Aparams &p){ modeIndexSet tmp; const PackedType &packed = static_cast(p); const UnpackedType &unpacked = static_cast(p); //Completely unpack the 'packed' and 'unpacked' (or *less* packed anyway - it doesn't have to be a fully unpacked index) type VectorTypePacked packed_unmap; computeModeUnmapping::doit(packed_unmap,tmp,packed); VectorTypeUnpacked unpacked_unmap; computeModeUnmapping::doit(unpacked_unmap,tmp,unpacked); computeModeMap::doit(idx_map,packed_unmap,unpacked_unmap); } #endif