25 #ifndef _chemistry_qc_lmp2_sma_h
26 #define _chemistry_qc_lmp2_sma_h
31 #include <chemistry/qc/basis/basis.h>
32 #include <chemistry/qc/basis/integral.h>
33 #include <util/misc/autovec.h>
34 #include <util/misc/scint.h>
35 #include <util/misc/exenv.h>
36 #include <util/state/statein.h>
37 #include <util/state/stateout.h>
38 #include <util/misc/regtime.h>
39 #include <util/misc/scexception.h>
41 #ifndef TWO_INDEX_SPECIALIZATIONS
42 # define THREE_INDEX_SPECIALIZATIONS 1
45 #ifndef THREE_INDEX_SPECIALIZATIONS
46 # define THREE_INDEX_SPECIALIZATIONS 1
49 #ifndef FOUR_INDEX_SPECIALIZATIONS
50 # define FOUR_INDEX_SPECIALIZATIONS 1
53 #ifndef USE_STL_MULTIMAP
54 # define USE_STL_MULTIMAP 0
57 #if ! USE_STL_MULTIMAP
58 # include <chemistry/qc/lmp2/avlmmap.h>
66 # include <ext/hash_map>
71 #ifdef WORDS_BIGENDIAN
81 # define r2(i) ((~(i))&1)
82 # define r4(i) ((~(i))&3)
96 std::vector<int> block_size_;
97 std::vector<int> block_offset_;
98 std::vector<int> index_to_block_;
99 std::vector<int> function_order_;
100 std::vector<int> range_order_;
106 void init_order(
int nbasis);
108 enum BlockingMethod { AtomBlocking,
114 BlockingMethod b = ShellBlocking,
int blocksize = 1);
120 BlockingMethod b = ShellBlocking,
int blocksize = 1);
127 int nblock()
const {
return block_size_.size(); }
139 return i - block_offset_[index_to_block_[i]];
146 int range_index_to_basis_index(
int i)
const;
147 bool operator == (
const Range &r)
const;
148 bool operator != (
const Range &r)
const {
return ! operator == (r); }
162 std::vector<int> indices_;
175 void append_additional_indices(
const IndexList &);
176 int &i(
int a) {
return indices_[a]; }
177 const int &i(
int a)
const {
return indices_[a]; }
178 int n()
const {
return indices_.size(); }
179 void set_n(
int n) { indices_.resize(n); }
186 bool operator>(
const IndexList&il)
const{
return indices_>il.indices_;}
187 bool operator<(
const IndexList&il)
const{
return indices_<il.indices_;}
188 bool operator==(
const IndexList&il)
const{
return indices_==il.indices_;}
189 bool operator!=(
const IndexList&il)
const{
return indices_!=il.indices_;}
190 bool operator>=(
const IndexList&il)
const{
return indices_>=il.indices_;}
191 bool operator<=(
const IndexList&il)
const{
return indices_<=il.indices_;}
195 typedef unsigned short bi_t;
203 mutable double bound_;
218 for (
int i=0; i<N && i <v.size(); i++) block_[i] = v[i];
227 for (
int i=0; i<l.n(); i++) block_[i] = b.block_[l.i(i)];
236 for (
int i=0; i<l.n(); i++) block_[l.i(i)] = b.block(lb.i(i));
239 void zero() {
for (
int i=0; i<N; i++) block_[i] = 0; }
241 double bound()
const {
return bound_; }
242 void set_bound(
double b)
const { bound_ = b; }
244 bi_t &block(
int i) {
return block_[i]; }
245 const bi_t &block(
int i)
const {
return block_[i]; }
249 for (
int i=0; i<N; i++) r *= indices[i].block_size(block_[i]);
257 for (
int i=0; i<indexlist.n(); i++) {
258 int index = indexlist.i(i);
259 r *= indices[index].
block_size(block_[index]);
270 for (
int i=0; i<il.n(); i++) {
271 block_[il.i(i)] = bi2.block(il2.i(i));
280 for (
int i=0; i<il.n(); i++) {
281 block_[il.i(i)] = bi2.block(i);
290 for (
int i=0; i<il.n(); i++) {
291 if (block_[il.i(i)] != bi2.block(i))
return false;
296 void print_block_sizes(
const Range *indices,
299 for (
int i=0; i<N; i++) {
309 for (
int i=0; i<N; i++) {
310 so.
put(
int(block_[i]));
317 for (
int i=0; i<N; i++) {
325 inline std::ostream&
operator << (std::ostream&o,
const BlockInfo<N> &b)
336 int b1b = b1.block(0), b2b = b2.block(0);
337 if (b1b < b2b)
return true;
338 if (b1b > b2b)
return false;
339 for (
int i=1; i<N; i++) {
340 b1b = b1.block(i); b2b = b2.block(i);
341 if (b1b < b2b)
return true;
342 if (b1b > b2b)
return false;
347 int b1b = b1.block(0), b2b = b2.block(0);
348 if (b1b < b2b)
return -1;
349 if (b1b > b2b)
return 1;
350 for (
int i=1; i<N; i++) {
351 b1b = b1.block(i); b2b = b2.block(i);
352 if (b1b < b2b)
return -1;
353 if (b1b > b2b)
return 1;
364 mutable double bound_;
393 double bound()
const {
return bound_; }
394 void set_bound(
double b)
const { bound_ = b; }
400 const bi_t &block(
int i)
const {
442 void print_block_sizes(
const Range *indices,
469 #if TWO_INDEX_SPECIALIZATIONS
475 mutable double bound_;
480 sc::sc_uint16_t s[2];
483 friend class IndicesLess<2>;
490 BlockInfo(
const std::vector<bi_t> &v) {
494 for (
int i=0; i<2 && i<v.size(); i++) b_.s[r2(i)] = v[i];
496 BlockInfo(
const BlockInfo<2> &b,
const IndexList &l) {
500 for (
int i=0; i<l.n(); i++) b_.s[r2(i)] = b.b_.s[r2(l.i(i))];
503 BlockInfo(
const IndexList &l,
504 const BlockInfo<NB> &b,
505 const IndexList &lb) {
509 for (
int i=0; i<l.n(); i++) b_.s[r2(l.i(i))] = b.block(lb.i(i));
512 double bound()
const {
return bound_; }
513 void set_bound(
double b)
const { bound_ = b; }
515 bi_t &block(
int i) {
return b_.s[r2(i)]; }
516 const bi_t &block(
int i)
const {
return b_.s[r2(i)]; }
518 unsigned int size(
const Range *indices)
const {
520 for (
int i=0; i<2; i++) r *= indices[i].block_size(b_.s[r2(i)]);
526 const IndexList &indexlist)
const {
528 for (
int i=0; i<indexlist.n(); i++) {
529 int index = indexlist.i(i);
530 r *= indices[index].block_size(b_.s[r2(index)]);
540 const BlockInfo<N2> &bi2,
const IndexList &il2) {
541 for (
int i=0; i<il.n(); i++) {
542 b_.s[r2(il.i(i))] = bi2.block(il2.i(i));
550 const BlockInfo<N2> &bi2) {
551 for (
int i=0; i<il.n(); i++) {
552 b_.s[r2(il.i(i))] = bi2.block(i);
560 const BlockInfo<N2> &bi2) {
561 for (
int i=0; i<il.n(); i++) {
562 if (b_.s[r2(il.i(i))] != bi2.block(i))
return false;
567 void zero() { b_.i = 0; }
570 for (
int i=0; i<2; i++) {
576 void print_block_sizes(
const Range *indices,
579 for (
int i=0; i<2; i++) {
581 o << indices[i].block_size(b_.s[r2(i)]);
589 for (
int i=0; i<2; i++) {
590 so.
put(
int(block(i)));
597 for (
int i=0; i<2; i++) {
606 bool IndicesLess<2>::operator() (
const BlockInfo<2>&b1,
607 const BlockInfo<2>&b2)
const
609 if (b1.b_.i < b2.b_.i)
return true;
614 int IndicesLess<2>::compare(
const BlockInfo<2>&b1,
615 const BlockInfo<2>&b2)
const
617 if (b1.b_.i < b2.b_.i)
return -1;
618 else if (b1.b_.i > b2.b_.i)
return 1;
621 #endif // TWO_INDEX_SPECIALIZATIONS
623 #if THREE_INDEX_SPECIALIZATIONS
629 mutable double bound_;
634 sc::sc_uint32_t i[2];
635 sc::sc_uint16_t s[4];
651 for (
int i=0; i<3 && i<v.size(); i++) b_.s[r4(i)] = v[i];
658 for (
int i=0; i<l.n(); i++) b_.s[r4(i)] = b.b_.s[r4(l.i(i))];
668 for (
int i=0; i<l.n(); i++) b_.s[r4(l.i(i))] = b.block(lb.i(i));
671 double bound()
const {
return bound_; }
672 void set_bound(
double b)
const { bound_ = b; }
674 bi_t &block(
int i) {
return b_.s[r4(i)]; }
675 const bi_t &block(
int i)
const {
return b_.s[r4(i)]; }
679 for (
int i=0; i<3; i++) r *= indices[i].block_size(b_.s[r4(i)]);
687 for (
int i=0; i<indexlist.n(); i++) {
688 int index = indexlist.i(i);
689 r *= indices[index].
block_size(b_.s[r4(index)]);
700 for (
int i=0; i<il.n(); i++) {
701 b_.s[r4(il.i(i))] = bi2.block(il2.i(i));
710 for (
int i=0; i<il.n(); i++) {
711 b_.s[r4(il.i(i))] = bi2.block(i);
720 for (
int i=0; i<il.n(); i++) {
721 if (b_.s[r4(il.i(i))] != bi2.block(i))
return false;
729 for (
int i=0; i<3; i++) {
735 void print_block_sizes(
const Range *indices,
738 for (
int i=0; i<3; i++) {
740 o << indices[i].block_size(b_.s[r4(i)]);
748 for (
int i=0; i<3; i++) {
749 so.
put(
int(block(i)));
756 for (
int i=0; i<3; i++) {
765 bool IndicesLess<3>::operator() (
const BlockInfo<3>&b1,
766 const BlockInfo<3>&b2)
const
768 if (b1.b_.l < b2.b_.l)
return true;
773 int IndicesLess<3>::compare(
const BlockInfo<3>&b1,
774 const BlockInfo<3>&b2)
const
776 if (b1.b_.l < b2.b_.l)
return -1;
777 else if (b1.b_.l > b2.b_.l)
return 1;
780 #endif // THREE_INDEX_SPECIALIZATIONS
782 #if FOUR_INDEX_SPECIALIZATIONS
788 mutable double bound_;
793 sc::sc_uint32_t i[2];
794 sc::sc_uint16_t s[4];
808 for (
int i=0; i<4 && i<v.size(); i++) b_.s[r4(i)] = v[i];
810 BlockInfo(bi_t b0,bi_t b1,bi_t b2,bi_t b3) {
823 for (
int i=0; i<l.n(); i++) b_.s[r4(i)] = b.b_.s[r4(l.i(i))];
832 for (
int i=0; i<l.n(); i++) b_.s[r4(l.i(i))] = b.block(lb.i(i));
835 double bound()
const {
return bound_; }
836 void set_bound(
double b)
const { bound_ = b; }
838 bi_t &block(
int i) {
return b_.s[r4(i)]; }
839 const bi_t &block(
int i)
const {
return b_.s[r4(i)]; }
843 for (
int i=0; i<4; i++) r *= indices[i].block_size(b_.s[r4(i)]);
851 for (
int i=0; i<indexlist.n(); i++) {
852 int index = indexlist.i(i);
853 r *= indices[index].
block_size(b_.s[r4(index)]);
864 for (
int i=0; i<il.n(); i++) {
865 b_.s[r4(il.i(i))] = bi2.block(il2.i(i));
874 for (
int i=0; i<il.n(); i++) {
875 b_.s[r4(il.i(i))] = bi2.block(i);
884 for (
int i=0; i<il.n(); i++) {
885 if (b_.s[r4(il.i(i))] != bi2.block(i))
return false;
893 for (
int i=0; i<4; i++) {
899 void print_block_sizes(
const Range *indices,
902 for (
int i=0; i<4; i++) {
904 o << indices[i].block_size(b_.s[r4(i)]);
912 for (
int i=0; i<4; i++) {
913 so.
put(
int(block(i)));
920 for (
int i=0; i<4; i++) {
929 bool IndicesLess<4>::operator() (
const BlockInfo<4>&b1,
930 const BlockInfo<4>&b2)
const
932 if (b1.b_.l < b2.b_.l)
return true;
937 int IndicesLess<4>::compare(
const BlockInfo<4>&b1,
938 const BlockInfo<4>&b2)
const
940 if (b1.b_.l < b2.b_.l)
return -1;
941 else if (b1.b_.l > b2.b_.l)
return 1;
944 #endif // FOUR_INDEX_SPECIALIZATIONS
949 class BlockInfoHash {
951 size_t operator()(
const BlockInfo<N> &b)
const {
953 for (
int i=0; i<N; i++) r ^= b.block(i);
962 class BlockInfoEqual {
964 bool operator()(
const BlockInfo<N> &b1,
const BlockInfo<N> &b2)
const {
965 for (
int i=0; i<N; i++)
if (b1.block(i) != b2.block(i))
return false;
987 if (il_.n() == 0)
return false;
989 int b1b = b1.block(i0), b2b = b2.block(i0);
990 if (b1b < b2b)
return true;
991 if (b1b > b2b)
return false;
992 for (
int l=1; l<il_.n(); l++) {
994 b1b = b1.block(i); b2b = b2.block(i);
995 if (b1b < b2b)
return true;
996 if (b1b > b2b)
return false;
1000 if (b1.bound() > b2.bound())
return true;
1004 int compare(
const BlockInfo<N>&b1,
const BlockInfo<N>&b2)
const {
1005 if (il_.n() == 0)
return 0;
1007 int b1b = b1.block(i0), b2b = b2.block(i0);
1008 if (b1b < b2b)
return -1;
1009 if (b1b > b2b)
return 1;
1010 for (
int l=1; l<il_.n(); l++) {
1012 b1b = b1.block(i); b2b = b2.block(i);
1013 if (b1b < b2b)
return -1;
1014 if (b1b > b2b)
return 1;
1018 if (b1.bound() > b2.bound())
return -1;
1019 else if (b1.bound() < b2.bound())
return 1;
1031 int default_chunksize_;
1033 typedef std::multimap<size_t, std::pair<double *, size_t> > memmap_t;
1035 typedef std::map<double*,memmap_t::iterator> memitermap_t;
1036 memitermap_t memitermap_;
1040 virtual double *allocate(
long size);
1041 virtual void deallocate(
double *);
1042 double *data()
const;
1043 long ndata()
const {
return ndata_; }
1068 const std::string
name()
const {
return name_; }
1080 {
return name_.size() > 0 && name_ == i.
name(); }
1083 {
return name_ == i.
name() && value_ == i.value_; }
1097 std::vector<Index> indices_;
1099 bool clear_after_use_;
1100 bool skip_bounds_update_;
1102 template <
int N2,
class Op>
1104 bool initarray, Op &op)
const;
1108 bool initarray, Op &op)
const;
1110 template <
int Nl,
int Nr>
1112 bool initarray)
const;
1114 template <
int Nl,
int Nr>
1146 void apply_factor(
double f);
1147 double factor()
const;
1149 const Index &index(
int i)
const;
1150 bool clear_after_use()
const {
return clear_after_use_; }
1162 template <
int Nl,
int Nr>
1164 template <
int Nl,
int Nr>
1166 template <
int Nl,
int Nr>
1174 template <
int Nl,
int Nr>
1190 template <
int Nl,
int Nr>
1198 template <
int Nl,
int Nr>
1199 ContractUnion<Nl,Nr> operator |(
const ContractPart<Nl>&l,
1200 const ContractPart<Nr>&r)
1202 return ContractUnion<Nl,Nr>(l,r);
1205 template <
int N>
class BlockDistrib;
1212 ready(std::vector<T> &vec,
1213 const std::vector<T> &start,
const std::vector<T> &fence)
1215 if (vec.size() == 0)
return false;
1216 for (
int i=0; i<vec.size(); i++) {
1217 if (vec[i] < start[i])
return false;
1218 if (vec[i] >= fence[i])
return false;
1229 incr(std::vector<T> &vec,
1230 const std::vector<T> &start,
const std::vector<T> &fence)
1232 if (vec.size() == 0)
return;
1233 for (
int i=vec.size()-1; i>0; i--) {
1234 if (vec[i] >= fence[i]-1) vec[i] = start[i];
1250 void remap(
typename Array<N1>::cached_blockmap_t& target,
1251 const Array<N1> &source,
1252 const IndexList &fixed,
const BlockInfo<N1> &fixedvals);
1255 void remap(Array<N1>& target,
const Array<N1> &source,
1256 const IndexList &il);
1258 typedef IndicesLess<N> Compare;
1259 #if USE_STL_MULTIMAP
1260 typedef typename std::multimap<BlockInfo<N>,
double*, Compare > blockmap_t;
1261 typedef typename std::multimap<BlockInfo<N>,
double*, IndexListLess<N> > cached_blockmap_t;
1263 typedef AVLMMap<BlockInfo<N>,
double*, Compare > blockmap_t;
1264 typedef AVLMMap<BlockInfo<N>,
double*, IndexListLess<N> > cached_blockmap_t;
1267 typedef typename __gnu_cxx::hash_map<BlockInfo<N>,
double*, BlockInfoHash<N>, BlockInfoEqual<N> > blockhash_t;
1273 blockhash_t block_hash_;
1284 std::map<IndexList, cached_blockmap_t*> blockmap_cache_;
1285 bool use_blockmap_cache_;
1287 void init_indices(
int n) {
1291 if (n) indices_.
reset(
new Range[n]);
1292 else indices_.
reset(0);
1295 void basic_init(
const std::string &name,
double tol) {
1297 use_blockmap_cache_ =
true;
1313 Array(
const Array<N> &a) {
1326 tolerance_ = a.tolerance_;
1330 for (
typename blockmap_t::const_iterator i = a.blocks_.begin();
1331 i != a.blocks_.end();
1333 typename blockmap_t::iterator ithis = blocks_.find(i->first);
1334 if (ithis == blocks_.end())
continue;
1335 memcpy(ithis->second, i->second,
1336 sizeof(*ithis->second)*
block_size(ithis->first));
1353 double tol = DBL_EPSILON) { init(name,tol); }
1354 void init(
const std::string &name =
"",
1355 double tol = DBL_EPSILON) {
1356 basic_init(name,tol);
1360 const std::string & name=
"",
1361 double tol = DBL_EPSILON) { init(
index,name,tol); }
1363 const std::string & name=
"",
1364 double tol = DBL_EPSILON) {
1365 basic_init(name,tol);
1367 throw std::invalid_argument(
"Array init given too many indices");
1372 const std::string & name=
"",
1373 double tol = DBL_EPSILON) { init(i0,i1,name,tol); }
1375 const std::string & name=
"",
1376 double tol = DBL_EPSILON) {
1377 basic_init(name,tol);
1379 throw std::invalid_argument(
"Array init given too many indices");
1381 for (
int i=1; i<N; i++)
set_index(i,i1);
1385 const std::string & name=
"",
1386 double tol = DBL_EPSILON) { init(i0,i1,i2,name,tol); }
1388 const std::string & name=
"",
1389 double tol = DBL_EPSILON) {
1390 basic_init(name,tol);
1392 throw std::invalid_argument(
"Array init given too many indices");
1395 for (
int i=2; i<N; i++)
set_index(i,i2);
1401 const std::string & name=
"",
1402 double tol = DBL_EPSILON) { init(i0,i1,i2,i3,name,tol); }
1405 const std::string & name=
"",
1406 double tol = DBL_EPSILON) {
1407 basic_init(name,tol);
1409 throw std::invalid_argument(
"Array init given too many indices");
1413 for (
int i=3; i<N; i++)
set_index(i,i3);
1420 const std::string & name=
"",
1421 double tol = DBL_EPSILON) { init(i0,i1,i2,i3,i4,name,tol); }
1425 const std::string & name=
"",
1426 double tol = DBL_EPSILON) {
1427 basic_init(name,tol);
1429 throw std::invalid_argument(
"Array init given too many indices");
1434 for (
int i=4; i<N; i++)
set_index(i,i4);
1441 const std::string & name=
"",
1442 double tol = DBL_EPSILON) { init(i0,i1,i2,i3,i4,i5,name,tol); }
1446 const std::string & name=
"",
1447 double tol = DBL_EPSILON) {
1448 basic_init(name,tol);
1450 throw std::invalid_argument(
"Array init given too many indices");
1456 for (
int i=5; i<N; i++)
set_index(i,i5);
1461 double tol = DBL_EPSILON): data_(new
Data), debug_(0),
1469 double bound()
const {
return bound_; }
1470 void set_bound(
double b) { bound_ = b; }
1472 double tolerance()
const {
return tolerance_; }
1473 void set_tolerance(
double t) { tolerance_ = t; }
1480 block_hash_.clear();
1492 const blockhash_t &blockhash()
const {
return block_hash_; }
1500 for (
int i=0; i<N; i++)
set_index(i,r[i]);
1509 for (
int i=0; i<N; i++) bs *= indices_.
get()[i].block_size(bi.block(i));
1515 typename blockmap_t::value_type &
1518 throw std::runtime_error(
1519 "cannot add unalloced block to alloced array");
1522 for (
int i=0; i<N; i++) {
1524 throw std::runtime_error(
1525 "attempted to add a block with invalid block indices"
1529 #if USE_STL_MULTIMAP
1530 typename blockmap_t::iterator bi = blocks_.find(b);
1531 if (bi != blocks_.end())
return *bi;
1532 return *blocks_.insert(
typename blockmap_t::value_type(b,(
double*)0));
1534 return *blocks_.insert_unique(
typename blockmap_t::value_type(b,(
double*)0));
1540 typename blockmap_t::value_type &
1544 for (
int i=0; i<N; i++) {
1546 throw std::runtime_error(
1547 "attempted to add a block with invalid block indices"
1551 typename blockmap_t::iterator bi = blocks_.find(b);
1552 if (bi != blocks_.end())
return *bi;
1554 double *data = data_->allocate(
block_size(b));
1555 return *blocks_.insert(
typename blockmap_t::value_type(b,data));
1560 typename blockmap_t::value_type &
1564 for (
int i=0; i<N; i++) {
1566 throw std::runtime_error(
1567 "attempted to add a block with invalid block indices"
1572 typename blockmap_t::iterator bi = blocks_.find(b);
1573 if (bi != blocks_.end())
return *bi;
1576 double *data = data_->allocate(size);
1577 memset(data, 0,
sizeof(
double)*size);
1579 return *blocks_.insert(
typename blockmap_t::value_type(b,data));
1585 typename blockmap_t::iterator bi = blocks_.find(b);
1586 if (bi != blocks_.end()) {
1587 data_->deallocate(bi->second);
1592 typename blockmap_t::iterator bi = blocks_.find(b_old);
1593 if (bi != blocks_.end()) {
1594 double *data = bi->second;
1596 blocks_.insert(std::make_pair(b_new,data));
1604 typename blockmap_t::iterator
1608 throw std::runtime_error(
1609 "cannot add unalloced block to alloced array");
1612 for (
int i=0; i<N; i++) {
1614 throw std::runtime_error(
1615 "attempted to add a block with invalid block indices"
1619 #if USE_STL_MULTIMAP
1620 return blocks_.insert(blockmap_t::value_type(b,(
double*)0));
1622 return blocks_.insert_new(hint,
typename blockmap_t::value_type(b,(
double*)0));
1629 typename blockmap_t::iterator
1632 throw std::runtime_error(
1633 "cannot add unalloced block to alloced array");
1636 for (
int i=0; i<N; i++) {
1638 throw std::runtime_error(
1639 "attempted to add a block with invalid block indices"
1643 #if USE_STL_MULTIMAP
1644 return blocks_.insert(blockmap_t::value_type(b,(
double*)0));
1646 return blocks_.insert_new(
typename blockmap_t::value_type(b,(
double*)0));
1656 throw std::runtime_error(
1657 "cannot add unalloced block to alloced array");
1668 std::vector<sma2::bi_t> b_indices(N);
1669 std::vector<sma2::bi_t> b_start(N);
1670 std::vector<sma2::bi_t> b_fence(N);
1672 std::fill(b_start.begin(), b_start.end(), 0);
1673 for (
int i=0; i<N; i++) b_fence[i] =
index(i).
nblock();
1675 for (b_indices=b_start;
1676 ready(b_indices, b_start, b_fence);
1677 incr(b_indices, b_start, b_fence)) {
1685 return blocks_.end();
1689 return blocks_.size();
1694 for (
typename blockmap_t::const_iterator i = blocks_.begin();
1703 if (data_.
null())
return 0;
1704 return data_->ndata();
1706 std::string name()
const {
return name_; }
1707 double max_n_block() {
1708 double n_block_max = 1;
1709 for (
int i=0; i<N; i++) {
1714 double max_n_element() {
1715 double n_element_max = 1;
1716 for (
int i=0; i<N; i++) {
1719 return n_element_max;
1724 for (
typename blockmap_t::iterator i = blocks_.begin();
1728 double *d = i->second;
1729 for (
int j=0; j<n; j++) d[j] = val;
1731 i->first.set_bound(val);
1747 for (
typename blockmap_t::iterator i = blocks_.begin();
1751 double *d = i->second;
1752 double maxval = 0.0;
1753 for (
int j=0; j<n; j++) {
1754 double val = fabs(d[j]);
1755 if (val > maxval) maxval = val;
1757 i->first.set_bound(maxval);
1758 if (maxval > bound_) bound_ = maxval;
1765 if (allocated_)
return;
1777 double *dat = data_->allocate(n);
1778 for (
typename blockmap_t::iterator i = blocks_.begin();
1781 if (i->second == 0) {
1787 throw std::runtime_error(
"allocate_blocks: duplicate alloc");
1791 block_hash_.resize(nblock);
1792 for (
typename blockmap_t::iterator i = blocks_.begin();
1795 block_hash_.insert(*i);
1803 for (
typename blockmap_t::iterator i = blocks_.begin();
1816 ContractPart<N> operator()(
const Index &i1) {
1817 return ContractPart<N>(*
this,i1);
1819 ContractPart<N> operator()(
const Index &i1,
const Index &i2) {
1820 return ContractPart<N>(*
this,i1,i2);
1822 ContractPart<N> operator()(
const std::string &i1,
1823 const std::string &i2) {
1824 return ContractPart<N>(*
this,i1,i2);
1826 ContractPart<N> operator()(
const Index &i1,
const Index &i2,
const Index &i3) {
1827 return ContractPart<N>(*
this,i1,i2,i3);
1829 ContractPart<N> operator()(
const std::string &i1,
1830 const std::string &i2,
1831 const std::string &i3) {
1832 return ContractPart<N>(*
this,i1,i2,i3);
1834 ContractPart<N> operator()(
const Index &i1,
const Index &i2,
1835 const Index &i3,
const Index &i4) {
1836 return ContractPart<N>(*
this,i1,i2,i3,i4);
1838 ContractPart<N> operator()(
const std::string &i1,
1839 const std::string &i2,
1840 const std::string &i3,
1841 const std::string &i4) {
1842 return ContractPart<N>(*
this,i1,i2,i3,i4);
1844 ContractPart<N> operator()(
const Index &i1,
const Index &i2,
1845 const Index &i3,
const Index &i4,
1847 return ContractPart<N>(*
this,i1,i2,i3,i4,i5);
1849 ContractPart<N> operator()(
const std::string &i1,
1850 const std::string &i2,
1851 const std::string &i3,
1852 const std::string &i4,
1853 const std::string &i5) {
1854 return ContractPart<N>(*
this,i1,i2,i3,i4,i5);
1856 ContractPart<N> operator()(
const Index &i1,
const Index &i2,
1857 const Index &i3,
const Index &i4,
1858 const Index &i5,
const Index &i6) {
1859 return ContractPart<N>(*
this,i1,i2,i3,i4,i5,i6);
1861 ContractPart<N> operator()(
const std::string &i1,
1862 const std::string &i2,
1863 const std::string &i3,
1864 const std::string &i4,
1865 const std::string &i5,
1866 const std::string &i6) {
1867 return ContractPart<N>(*
this,i1,i2,i3,i4,i5,i6);
1872 for (
typename blockmap_t::const_iterator i = blocks_.begin();
1875 double fabs_f = fabs(f);
1877 double *data = i->second;
1878 for (
int j=0; j<n; j++) data[j] *= f;
1880 i->first.set_bound(fabs_f * i->first.bound());
1888 for (
typename blockmap_t::const_iterator i = a.blocks_.begin();
1889 i != a.blocks_.end();
1891 if (a.block_max_abs(i) > tol) {
1903 const double *dat = b->second;
1904 double maxabs = 0.0;
1905 for (
int i=0; i<s; i++) {
1906 double v = fabs(dat[i]);
1907 if (v > maxabs) maxabs = v;
1913 double max_abs = 0.0;
1914 for (
typename blockmap_t::const_iterator i = blocks_.begin();
1929 const int &
debug()
const {
return debug_; }
1933 for (
int i=0; i<N; i++) {
1934 indices_[i].read(si);
1935 indices_[i].print();
1938 si.
get(allocatedval);
1952 for (
int i=0; i<nblock; i++) {
1958 si.get_array_double(data_->data(), data_->ndata());
1962 for (
int i=0; i<N; i++) indices_[i].write(so);
1963 int bval = allocated_;
1970 int blocks_size = int(blocks_.size());
1971 if (blocks_.size() != blocks_size) {
1972 throw std::runtime_error(
"Array::write: blocks truncated");
1974 so.
put(blocks_size);
1975 for (
typename blockmap_t::const_iterator i = blocks_.begin();
1980 if (allocated_) so.put_array_double(data_->data(), data_->ndata());
1996 const BlockDistrib<N> &,
1998 bool clear_source_array =
false,
1999 bool ignore_block_distrib_throws =
false);
2004 __FILE__, __LINE__);
2005 return blockmap().begin()->second[0];
2009 for (
typename std::map<IndexList,cached_blockmap_t*>::iterator
2010 iter = blockmap_cache_.begin();
2011 iter != blockmap_cache_.end();
2013 delete iter->second;
2015 blockmap_cache_.clear();
2023 use_blockmap_cache_ = ubmc;
2027 return use_blockmap_cache_;
2031 return blockmap_cache_.find(il) != blockmap_cache_.end();
2040 remap(*entry,*
this,nullil,nullbi);
2046 inline std::ostream&
operator << (std::ostream&o,
const Array<N> &a)
2052 inline int offset2(
int i,
int ni,
int j,
int nj) {
2056 template <
int N>
double scalar_contract(Array<N> &c, Array<N> &a,
const IndexList &alist);
2061 template <
int Nl,
int Nr>
2062 class ContractProd {
2067 void apply_factor(
double f) { l.apply_factor(f); }
2068 ContractProd(
const ContractPart<Nl> &a1,
const ContractPart<Nr> &a2):
2071 std::vector<int> ivec;
2072 for (
int i=0; i<Nr; i++) {
2073 for (
int j=0; j<Nl; j++) {
2074 if (r.index(i) == l.index(j)) {
2081 return l.factor() * r.factor()
2082 * sma2::scalar_contract(l.array(), r.array(), il);
2085 ContractProd<Nl,Nr> ret(*
this);
2090 template <
int Nl,
int Nr>
2091 ContractProd<Nl,Nr> operator *(
const ContractPart<Nl>&l,
2092 const ContractPart<Nr>&r)
2094 return ContractProd<Nl,Nr>(l,r);
2096 template <
int Nl,
int Nr>
2097 ContractProd<Nl,Nr> operator *(
double f,
const ContractProd<Nl,Nr> &prod)
2099 ContractProd<Nl,Nr> result(prod);
2100 result.apply_factor(f);
2110 remap(Array<N>& target,
const Array<N> &source,
2111 const IndexList &il)
2113 for (
int i=0; i<N; i++) target.set_index(i,source.index(i));
2114 const typename Array<N>::blockmap_t &sourceblocks
2115 = source.blockmap();
2116 target.blocks_.clear();
2117 for (
typename Array<N>::blockmap_t::const_iterator i = sourceblocks.begin();
2118 i != sourceblocks.end();
2120 const BlockInfo<N> &orig_bi(i->first);
2121 BlockInfo<N> new_bi(orig_bi,il);
2122 target.blocks_.insert(std::pair<BlockInfo<N>,
double*>(new_bi,
2125 target.data_ = source.data_;
2135 remap(
typename Array<N>::cached_blockmap_t& target,
2136 const Array<N> &source,
2137 const IndexList &fixed,
const BlockInfo<N> &fixedvals)
2139 if (!fixed.is_identity_permutation())
2140 throw std::invalid_argument(
"remap requires fixed indices first");
2141 const typename Array<N>::blockmap_t &sourceblocks
2142 = source.blockmap();
2144 typename Array<N>::blockmap_t::const_iterator begin, end;
2145 if (fixed.n() == 0) {
2146 begin = sourceblocks.begin();
2147 end = sourceblocks.end();
2153 sbi.assign_blocks(fixed, fixedvals);
2155 sbi.set_bound(DBL_MAX);
2157 begin = sourceblocks.lower_bound(sbi);
2159 for (
int i=0; i<N; i++) sbi.block(i) = source.index(i).nblock();
2160 sbi.assign_blocks(fixed, fixedvals);
2164 end = sourceblocks.upper_bound(sbi);
2166 for (
typename Array<N>::blockmap_t::const_iterator i = begin;
2174 void extract_diagonal(Array<2> &array, std::vector<double> &diag);
2177 void scale_diagonal(Array<2> &array,
double factor);
2181 template <
int N,
class V>
2183 apply_denominator(Array<N> &array,
double denominator_offset,
2184 const std::vector<V> &eigenvalues);
2193 void init(
const Range *index,
2196 for (
int i=0; i<N; i++) {
2197 bs_[i] = index[il.i(i)].block_size(bi.block(il.i(i)));
2203 init(index,bi,IndexList::identity(N));
2211 void start() { ready_ =
true;
for (
int i=0; i<N; i++) i_[i] = 0; }
2216 for (
int i=N-1; i>=0; i--) {
2218 if (i_[i] == bs_[i]) {
2227 for (
int i=0; i<N; i++) {
2228 r = r * bs_[i] + i_[i];
2232 int subset_offset(
const IndexList &subset_indexlist) {
2234 for (
int i=0; i<subset_indexlist.n(); i++) {
2235 r = r * bs_[subset_indexlist.i(i)]
2236 + i_[subset_indexlist.i(i)];
2242 int &index(
int i) {
return i_[i]; }
2243 const int &index(
int i)
const {
return i_[i]; }
2256 void start() { ready_ =
true; }
2257 bool ready()
const {
return ready_; }
2264 int subset_offset(
const IndexList &subset_indexlist) {
2273 const int &index(
int i)
const {
2279 template <
int N,
class Op>
2282 bool skip_bounds_update, Op &op)
2285 if (alist.n() != N) {
2286 throw std::invalid_argument(
"sma2::binary_op: # of indices inconsistent");
2293 for (
int i=0; i<N; i++) {
2294 if (c.index(alist.i(i)) != a.index(i))
2295 throw std::invalid_argument(
"sma2::binary_op: indices don't agree");
2302 if (c.n_block() < a.n_block()) {
2303 const typename Array<N>::blockmap_t &amap = a.blockmap();
2304 const typename Array<N>::blockmap_t &cmap = c.blockmap();
2305 IndexList clist = alist.reverse_mapping();
2306 for (
typename Array<N>::blockmap_t::const_iterator citer = cmap.begin();
2307 citer != cmap.end();
2309 const BlockInfo<N> &cbi = citer->first;
2310 BlockInfo<N> abi(cbi,alist);
2312 typename Array<N>::blockmap_t::const_iterator ablock
2314 if (ablock == amap.end())
continue;
2315 double *cdata = citer->second;
2316 double *adata = ablock->second;
2317 if (same_index_order) {
2318 int sz = c.block_size(cbi);
2319 for (
int i=0; i<sz; i++) op(cdata[i],alpha * adata[i]);
2322 BlockIter<N> cbiter(c.indices(),cbi);
2324 for (cbiter.start(); cbiter.ready(); cbiter++,coff++) {
2326 alpha * adata[cbiter.subset_offset(alist)]);
2332 const typename Array<N>::blockmap_t &amap = a.blockmap();
2333 const typename Array<N>::blockmap_t &cmap = c.blockmap();
2334 IndexList clist = alist.reverse_mapping();
2335 for (
typename Array<N>::blockmap_t::const_iterator aiter = amap.begin();
2336 aiter != amap.end();
2338 const BlockInfo<N> &abi = aiter->first;
2339 BlockInfo<N> cbi(abi,clist);
2340 typename Array<N>::blockmap_t::const_iterator cblock
2342 if (cblock == cmap.end())
continue;
2343 double *adata = aiter->second;
2344 double *cdata = cblock->second;
2345 if (same_index_order) {
2346 int sz = a.block_size(abi);
2347 for (
int i=0; i<sz; i++) op(cdata[i], alpha * adata[i]);
2350 BlockIter<N> cbiter(c.indices(),cbi);
2352 for (cbiter.start(); cbiter.ready(); cbiter++,coff++) {
2354 alpha * adata[cbiter.subset_offset(alist)]);
2359 if (!skip_bounds_update) c.compute_bounds();
2366 void pack_matrix_into_array(
const T &m, Array<2> &smaa) {
2367 smaa.allocate_blocks();
2368 const Array<2>::blockmap_t &Abm = smaa.blockmap();
2369 for (Array<2>::blockmap_t::const_iterator i = Abm.begin();
2372 const BlockInfo<2> &Abi = i->first;
2373 int off0 = smaa.index(0).block_offset(Abi.block(0));
2374 int off1 = smaa.index(1).block_offset(Abi.block(1));
2375 BlockIter<2> j(smaa.indices(), Abi);
2376 double *dat = i->second;
2377 for (j.start(); j.ready(); j++) {
2378 dat[j.offset()] = m(off0+j.index(0), off1+j.index(1));
2381 smaa.compute_bounds();
2388 void pack_vector_into_array(
const T &m, Array<1> &smaa) {
2389 smaa.allocate_blocks();
2390 const Array<1>::blockmap_t &Abm = smaa.blockmap();
2391 for (Array<1>::blockmap_t::const_iterator i = Abm.begin();
2394 const BlockInfo<1> &Abi = i->first;
2395 int off0 = smaa.index(0).block_offset(Abi.block(0));
2396 BlockIter<1> j(smaa.indices(), Abi);
2397 double *dat = i->second;
2398 for (j.start(); j.ready(); j++) {
2399 dat[j.offset()] = m(off0+j.index(0));
2402 smaa.compute_bounds();
2413 void pack_submatrix_into_array(
const T &m, Array<2> &smaa,
2414 const std::vector<int> &index_map_i,
2415 const std::vector<int> &index_map_j) {
2417 std::vector<int> reverse_map_i(smaa.index(0).nindex());
2418 std::vector<int> reverse_map_j(smaa.index(1).nindex());
2419 std::fill(reverse_map_i.begin(), reverse_map_i.end(), -1);
2420 std::fill(reverse_map_j.begin(), reverse_map_j.end(), -1);
2421 for (
int i=0; i<index_map_i.size(); i++) {
2422 reverse_map_i[index_map_i[i]] = i;
2424 for (
int i=0; i<index_map_j.size(); i++) {
2425 reverse_map_j[index_map_j[i]] = i;
2428 smaa.allocate_blocks();
2429 const Array<2>::blockmap_t &Abm = smaa.blockmap();
2430 for (Array<2>::blockmap_t::const_iterator i = Abm.begin();
2433 const BlockInfo<2> &Abi = i->first;
2434 int off0 = smaa.index(0).block_offset(Abi.block(0));
2435 int off1 = smaa.index(1).block_offset(Abi.block(1));
2436 BlockIter<2> j(smaa.indices(), Abi);
2437 double *dat = i->second;
2438 for (j.start(); j.ready(); j++) {
2439 int m_i = reverse_map_i[off0+j.index(0)];
2440 int m_j = reverse_map_j[off1+j.index(1)];
2441 if (m_i == -1 || m_j == -1)
continue;
2442 dat[j.offset()] = m(m_i, m_j);
2445 smaa.compute_bounds();
2456 void pack_subvector_into_array(
const T &m, Array<1> &smaa,
2457 const std::vector<int> &index_map) {
2459 std::vector<int> reverse_map(smaa.index(0).nindex());
2460 std::fill(reverse_map.begin(), reverse_map.end(), -1);
2461 for (
int i=0; i<index_map.size(); i++) {
2462 reverse_map[index_map[i]] = i;
2465 smaa.allocate_blocks();
2466 const Array<1>::blockmap_t &Abm = smaa.blockmap();
2467 for (Array<1>::blockmap_t::const_iterator i = Abm.begin();
2470 const BlockInfo<1> &Abi = i->first;
2471 int off0 = smaa.index(0).block_offset(Abi.block(0));
2472 BlockIter<1> j(smaa.indices(), Abi);
2473 double *dat = i->second;
2474 for (j.start(); j.ready(); j++) {
2475 int m_i = reverse_map[off0+j.index(0)];
2476 if (m_i == -1)
continue;
2477 dat[j.offset()] = m(m_i);
2480 smaa.compute_bounds();
2488 void pack_dense_matrix_into_array(
const T &m, Array<2> &smaa,
2489 const std::set<int> &row_blocks,
2490 const std::set<int> &col_blocks) {
2493 for (std::set<int>::const_iterator it1 = row_blocks.begin();
2494 it1 != row_blocks.end(); it1++) {
2495 for (std::set<int>::const_iterator it2 = col_blocks.begin();
2496 it2 != col_blocks.end(); it2++) {
2498 bi.block(0) = *it1; bi.block(1) = *it2;
2499 smaa.add_unallocated_block(bi);
2502 smaa.allocate_blocks();
2506 std::vector<int> row_offset(smaa.index(0).nblock());
2507 for (std::set<int>::const_iterator i = row_blocks.begin();
2508 i!=row_blocks.end(); i++) {
2509 row_offset[*i] = off;
2510 off+=smaa.index(0).block_size(*i);
2513 std::vector<int> col_offset(smaa.index(1).nblock());
2514 for (std::set<int>::const_iterator i = col_blocks.begin();
2515 i!=col_blocks.end(); i++) {
2516 col_offset[*i] = off;
2517 off+=smaa.index(1).block_size(*i);
2521 const Array<2>::blockmap_t &Abm = smaa.blockmap();
2522 for (Array<2>::blockmap_t::const_iterator i = Abm.begin();
2525 const BlockInfo<2> &Abi = i->first;
2526 int off0 = row_offset[Abi.block(0)];
2527 int off1 = col_offset[Abi.block(1)];
2528 BlockIter<2> j(smaa.indices(), Abi);
2529 double *dat = i->second;
2530 for (j.start(); j.ready(); j++) {
2531 dat[j.offset()] = m(off0+j.index(0), off1+j.index(1));
2534 smaa.compute_bounds();
2541 void pack_matrix_into_empty_array(
const T &m, Array<2> &smaa,
2544 const Range &index0 = smaa.index(0);
2545 const Range &index1 = smaa.index(1);
2546 for (
int i0=0; i0 < index0.
nblock(); i0++) {
2547 int bs0 = index0.block_size(i0);
2548 int bo0 = index0.block_offset(i0);
2549 for (
int i1=0; i1 < index1.
nblock(); i1++) {
2550 int bs1 = index1.block_size(i1);
2551 int bo1 = index1.block_offset(i1);
2552 double maxval = 0.0;
2553 for (
int j0=0; j0<bs0; j0++) {
2554 for (
int j1=0; j1<bs1; j1++) {
2555 double val = fabs(m(bo0+j0,bo1+j1));
2556 if (val > maxval) maxval = val;
2559 if (maxval >= bound) {
2563 double *data = smaa.add_unallocated_block(bi).second;
2567 pack_matrix_into_array(m,smaa);
2574 void pack_vector_into_empty_array(
const T &m, Array<1> &smaa,
2576 if (m.dim().n() != smaa.index(0).nindex()) {
2577 throw std::runtime_error(
"pack_vector_into_empty_array: dims don't match");
2580 const Range &index0 = smaa.index(0);
2581 for (
int i0=0; i0 < index0.
nblock(); i0++) {
2582 int bs0 = index0.block_size(i0);
2583 int bo0 = index0.block_offset(i0);
2584 double maxval = 0.0;
2585 for (
int j0=0; j0<bs0; j0++) {
2586 double val = fabs(m(bo0+j0));
2587 if (val > maxval) maxval = val;
2589 if (maxval >= bound) {
2592 double *data = smaa.add_unallocated_block(bi).second;
2595 pack_vector_into_array(m,smaa);
2604 void pack_submatrix_into_empty_array(
const T &m, Array<2> &smaa,
2606 const std::vector<int> &index_map_i,
2607 const std::vector<int> &index_map_j) {
2609 const Range &index0 = smaa.index(0);
2610 const Range &index1 = smaa.index(1);
2611 std::vector<int> reverse_map_i(index0.nindex());
2612 std::vector<int> reverse_map_j(index1.nindex());
2613 std::fill(reverse_map_i.begin(), reverse_map_i.end(), -1);
2614 std::fill(reverse_map_j.begin(), reverse_map_j.end(), -1);
2615 for (
int i=0; i<index_map_i.size(); i++) {
2616 reverse_map_i[index_map_i[i]] = i;
2618 for (
int i=0; i<index_map_j.size(); i++) {
2619 reverse_map_j[index_map_j[i]] = i;
2621 for (
int i0=0; i0 < index0.
nblock(); i0++) {
2622 int bs0 = index0.block_size(i0);
2623 int bo0 = index0.block_offset(i0);
2624 for (
int i1=0; i1 < index1.
nblock(); i1++) {
2625 int bs1 = index1.block_size(i1);
2626 int bo1 = index1.block_offset(i1);
2627 double maxval = 0.0;
2628 for (
int j0=0; j0<bs0; j0++) {
2629 int i_m = reverse_map_i[bo0+j0];
2630 if (i_m == -1)
continue;
2631 for (
int j1=0; j1<bs1; j1++) {
2632 int j_m = reverse_map_j[bo1+j1];
2633 if (j_m == -1)
continue;
2634 double val = fabs(m(i_m, j_m));
2635 if (val > maxval) maxval = val;
2638 if (maxval >= bound) {
2642 double *data = smaa.add_unallocated_block(bi).second;
2646 pack_submatrix_into_array(m,smaa,index_map_i,index_map_j);
2655 void pack_subvector_into_empty_array(
const T &m, Array<1> &smaa,
2657 const std::vector<int> &index_map) {
2659 const Range &index0 = smaa.index(0);
2660 std::vector<int> reverse_map(index0.nindex());
2661 std::fill(reverse_map.begin(), reverse_map.end(), -1);
2662 for (
int i=0; i<index_map.size(); i++) {
2663 reverse_map[index_map[i]] = i;
2665 for (
int i0=0; i0 < index0.
nblock(); i0++) {
2666 int bs0 = index0.block_size(i0);
2667 int bo0 = index0.block_offset(i0);
2668 double maxval = 0.0;
2669 for (
int j0=0; j0<bs0; j0++) {
2670 int i_m = reverse_map[bo0+j0];
2671 if (i_m == -1)
continue;
2672 double val = fabs(m(i_m));
2673 if (val > maxval) maxval = val;
2675 if (maxval >= bound) {
2678 double *data = smaa.add_unallocated_block(bi).second;
2681 pack_subvector_into_array(m,smaa,index_map);
2688 void pack_array_into_matrix(
const Array<2> &smaa, T &m) {
2690 const Array<2>::blockmap_t &Abm = smaa.blockmap();
2691 for (Array<2>::blockmap_t::const_iterator i = Abm.begin();
2694 const BlockInfo<2> &Abi = i->first;
2695 int off0 = smaa.index(0).block_offset(Abi.block(0));
2696 int off1 = smaa.index(1).block_offset(Abi.block(1));
2697 BlockIter<2> j(smaa.indices(), Abi);
2698 double *dat = i->second;
2699 for (j.start(); j.ready(); j++) {
2700 m(off0+j.index(0), off1+j.index(1)) = dat[j.offset()];
2709 void pack_array_into_vector(
const Array<1> &smaa, T &m) {
2711 const Array<1>::blockmap_t &Abm = smaa.blockmap();
2712 for (Array<1>::blockmap_t::const_iterator i = Abm.begin();
2715 const BlockInfo<1> &Abi = i->first;
2716 int off0 = smaa.index(0).block_offset(Abi.block(0));
2717 BlockIter<1> j(smaa.indices(), Abi);
2718 double *dat = i->second;
2719 for (j.start(); j.ready(); j++) {
2720 m(off0+j.index(0)) = dat[j.offset()];
2731 void pack_array_into_subvector(
const Array<1> &smaa, T &m,
2732 const std::vector<int> &index_map) {
2734 const Array<1>::blockmap_t &Abm = smaa.blockmap();
2735 for (Array<1>::blockmap_t::const_iterator i = Abm.begin();
2738 const BlockInfo<1> &Abi = i->first;
2739 int off0 = smaa.index(0).block_offset(Abi.block(0));
2740 BlockIter<1> j(smaa.indices(), Abi);
2741 double *dat = i->second;
2742 for (j.start(); j.ready(); j++) {
2743 m(index_map[off0+j.index(0)]) = dat[j.offset()];
2754 void pack_array_into_submatrix(
const Array<2> &smaa, T &m,
2755 const std::vector<int> &index_map_i,
2756 const std::vector<int> &index_map_j) {
2758 const Array<2>::blockmap_t &Abm = smaa.blockmap();
2759 for (Array<2>::blockmap_t::const_iterator i = Abm.begin();
2762 const BlockInfo<2> &Abi = i->first;
2763 int off0 = smaa.index(0).block_offset(Abi.block(0));
2764 int off1 = smaa.index(1).block_offset(Abi.block(1));
2765 BlockIter<2> j(smaa.indices(), Abi);
2766 double *dat = i->second;
2767 for (j.start(); j.ready(); j++) {
2768 m(index_map_i[off0+j.index(0)], index_map_j[off1+j.index(1)]) = dat[j.offset()];
2775 void pack_2e_integrals_into_array(Array<4> & array,
2781 void pack_2e_integrals_into_shell_blocked_array(Array<4> & array,
2787 #include "arraydef.h"
2788 #include "blockinfodef.h"
2789 #include "contract.h"
2790 #include "contractpartdef.h"