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
58# include <chemistry/qc/lmp2/avlmmap.h>
66# include <ext/hash_map>
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); }
180 static IndexList identity(
int 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_;}
193 std::ostream &operator << (std::ostream &,
const IndexList &);
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;
623#if THREE_INDEX_SPECIALIZATIONS
629 mutable double bound_;
634 sc::sc_uint32_t i[2];
635 sc::sc_uint16_t s[4];
638 friend class IndicesLess<3>;
646 BlockInfo(
const std::vector<bi_t> &v) {
651 for (
int i=0; i<3 && i<v.size(); i++) b_.s[r4(i)] = v[i];
653 BlockInfo(
const BlockInfo<3> &b,
const IndexList &l) {
658 for (
int i=0; i<l.n(); i++) b_.s[r4(i)] = b.b_.s[r4(l.i(i))];
661 BlockInfo(
const IndexList &l,
662 const BlockInfo<NB> &b,
663 const IndexList &lb) {
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)]; }
677 unsigned int size(
const Range *indices)
const {
679 for (
int i=0; i<3; i++) r *= indices[i].block_size(b_.s[r4(i)]);
685 const IndexList &indexlist)
const {
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)]);
699 const BlockInfo<N2> &bi2,
const IndexList &il2) {
700 for (
int i=0; i<il.n(); i++) {
701 b_.s[r4(il.i(i))] = bi2.block(il2.i(i));
709 const BlockInfo<N2> &bi2) {
710 for (
int i=0; i<il.n(); i++) {
711 b_.s[r4(il.i(i))] = bi2.block(i);
719 const BlockInfo<N2> &bi2) {
720 for (
int i=0; i<il.n(); i++) {
721 if (b_.s[r4(il.i(i))] != bi2.block(i))
return false;
726 void zero() { b_.l = 0; }
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;
782#if FOUR_INDEX_SPECIALIZATIONS
788 mutable double bound_;
793 sc::sc_uint32_t i[2];
794 sc::sc_uint16_t s[4];
797 friend class IndicesLess<4>;
804 BlockInfo(
const std::vector<bi_t> &v) {
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) {
819 BlockInfo(
const BlockInfo<4> &b,
const IndexList &l) {
823 for (
int i=0; i<l.n(); i++) b_.s[r4(i)] = b.b_.s[r4(l.i(i))];
826 BlockInfo(
const IndexList &l,
827 const BlockInfo<NB> &b,
828 const IndexList &lb) {
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)]; }
841 unsigned int size(
const Range *indices)
const {
843 for (
int i=0; i<4; i++) r *= indices[i].block_size(b_.s[r4(i)]);
849 const IndexList &indexlist)
const {
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)]);
863 const BlockInfo<N2> &bi2,
const IndexList &il2) {
864 for (
int i=0; i<il.n(); i++) {
865 b_.s[r4(il.i(i))] = bi2.block(il2.i(i));
873 const BlockInfo<N2> &bi2) {
874 for (
int i=0; i<il.n(); i++) {
875 b_.s[r4(il.i(i))] = bi2.block(i);
883 const BlockInfo<N2> &bi2) {
884 for (
int i=0; i<il.n(); i++) {
885 if (b_.s[r4(il.i(i))] != bi2.block(i))
return false;
890 void zero() { b_.l = 0; }
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;
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_; }
1088 template <
int N>
class Array;
1089 template <
int Nl,
int Nr>
class ContractProd;
1090 template <
int Nl,
int Nr>
class ContractUnion;
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>
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];
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) {
1292 else indices_.
reset(0);
1295 void basic_init(
const std::string &name,
double tol) {
1297 use_blockmap_cache_ =
true;
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();
1493 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++) {
1523 if (b.block(i) >=
index(i).nblock()) {
1524 throw std::runtime_error(
1525 "attempted to add a block with invalid block indices"
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++) {
1545 if (b.block(i) >=
index(i).nblock()) {
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++) {
1565 if (b.block(i) >=
index(i).nblock()) {
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++) {
1613 if (b.block(i) >=
index(i).nblock()) {
1614 throw std::runtime_error(
1615 "attempted to add a block with invalid block indices"
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++) {
1637 if (b.block(i) >
index(i).nblock()) {
1638 throw std::runtime_error(
1639 "attempted to add a block with invalid block indices"
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();
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>
2067 void apply_factor(
double f) { l.apply_factor(f); }
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);
2090 template <
int Nl,
int Nr>
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++) {
2295 throw std::invalid_argument(
"sma2::binary_op: indices don't agree");
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) {
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) {
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)]);
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"
static std::ostream & outn()
Return an ostream that writes from all nodes.
Definition exenv.h:81
static std::ostream & out0()
Return an ostream that writes from node 0.
This is thrown when a situations arises that should be impossible.
Definition scexception.h:92
The base class for all reference counted objects.
Definition ref.h:192
A template class that maintains references counts.
Definition ref.h:361
bool null() const
Return true if this is a reference to a null object.
Definition ref.h:423
Restores fundamental and user-defined types from images created with StateOut.
Definition statein.h:79
virtual int get(const ClassDesc **)
This restores ClassDesc's.
virtual int getstring(char *&)
This restores strings saved with StateOut::putstring.
Serializes fundamental and user-defined types.
Definition stateout.h:71
virtual int putstring(const char *)
This is like put except the length of the char array is determined by interpreting the character arra...
virtual int put(const ClassDesc *)
Write out information about the given ClassDesc.
The auto_vec class functions much like auto_ptr, except it contains references to arrays.
Definition autovec.h:59
T * get() const MPQC__NOEXCEPT
Returns the pointer.
Definition autovec.h:82
void reset(T *d=0) MPQC__NOEXCEPT
Assign to a new value.
Definition autovec.h:98
Implements a block sparse tensor.
Definition sma.h:1247
size_t n_element_allocated() const
Returns the number of elements contained in blocks.
Definition sma.h:1702
double block_max_abs(typename blockmap_t::const_iterator &b) const
Find maximum absolute value of elements in a block.
Definition sma.h:1901
void deallocate_blocks()
Deallocate storage for all blocks.
Definition sma.h:1801
Array(const Range &i0, const Range &i1, const Range &i2, const Range &i3, const std::string &name="", double tol=DBL_EPSILON)
Initialize range 0, 1 and 2 to i0, i1, and i2, and the rest to i3.
Definition sma.h:1399
bool use_blockmap_cache() const
Return true if blockmap caches are in use.
Definition sma.h:2026
void init_blocks(const Array< N > &a)
Initialize the stored blocks to be the same as those in a.
Definition sma.h:1897
const Range * indices() const
Gets the Range array.
Definition sma.h:1505
void distributed_from_distributed(const sc::Ref< sc::MessageGrp > &, const BlockDistrib< N > &, Array< N > &, bool clear_source_array=false, bool ignore_block_distrib_throws=false)
Redistribute an array.
Definition parallel.h:360
blockmap_t::value_type & add_unallocated_block(const BlockInfo< N > &b)
Adds block b.
Definition sma.h:1516
void clear()
Make this array store nothing.
Definition sma.h:1475
bool blockmap_cache_entry_exists(const IndexList &il)
Return true if the needed blockmap cache entry exists.
Definition sma.h:2030
blockmap_t::iterator initial_hint()
Returns an initial hint.
Definition sma.h:1684
void parallel_accumulate(const sc::Ref< sc::MessageGrp > &grp)
Performs a reduce-broadcast on the data.
Definition parallel.h:51
int block_size(const BlockInfo< N > &bi) const
Return size of the given block.
Definition sma.h:1507
void set_indices(const Range *r)
Initialize each range to the ranges in the given range array.
Definition sma.h:1499
blockmap_t::value_type & add_allocated_block(const BlockInfo< N > &b)
Adds block b.
Definition sma.h:1541
int & debug()
Set/get the debug level.
Definition sma.h:1928
Array(const Range &i0, const Range &i1, const std::string &name="", double tol=DBL_EPSILON)
Initialize range 0 to i0, and the rest to i1.
Definition sma.h:1371
void assign(double val)
Assigns the given value to all elements in the array.
Definition sma.h:1722
size_t n_element() const
Returns the number of elements contained in blocks.
Definition sma.h:1692
Array(const Range &i0, const Range &i1, const Range &i2, const std::string &name="", double tol=DBL_EPSILON)
Initialize range 0 to i0, 1 to i1, and the rest to i2.
Definition sma.h:1384
void allocate_blocks()
Allocate storage for all blocks if storage has not already been allocated.
Definition sma.h:1764
void set_use_blockmap_cache(bool ubmc)
Used to indicate whether or not a blockmap cache is to be used.
Definition sma.h:2022
void assign_tol(const Array< N > &a, double tol)
Assigns this to 'a', but throws out blocks smaller than tol.
Definition sma.h:1321
void add_all_unallocated_blocks()
Adds all possible blocks to give a dense array.
Definition sma.h:1653
blockmap_t::iterator add_new_unallocated_block(const BlockInfo< N > &b)
Adds block b.
Definition sma.h:1630
int n_block() const
Returns the number of blocks.
Definition sma.h:1688
Array(const Range &index, const std::string &name="", double tol=DBL_EPSILON)
Initialize all N indices to index.
Definition sma.h:1359
void replicated_from_distributed(const sc::Ref< sc::MessageGrp > &, const Array< N > &)
Convert a distributed array to a replicated array.
Definition parallel.h:310
void remove_block(const BlockInfo< N > &b)
Removes a block.
Definition sma.h:1584
cached_blockmap_t & blockmap_cache_entry(const IndexList &il)
Return a cached blockmap.
Definition sma.h:2034
const blockmap_t & blockmap() const
Return the block map.
Definition sma.h:1490
void compute_bounds()
Computes the bound for each block.
Definition sma.h:1743
void zero()
Zeros the array.
Definition sma.h:1739
const Range & index(int i) const
Gets the i'th Range.
Definition sma.h:1503
void clear_blockmap_cache()
Get rid of cached blockmaps.
Definition sma.h:2008
Array(const Range *ranges, double tol=DBL_EPSILON)
Initialize each range to the ranges in the given range array.
Definition sma.h:1460
void operator*=(double f)
Multiplication by a scalar.
Definition sma.h:1870
void parallel_union(const sc::Ref< sc::MessageGrp > &grp)
Makes the block distribution the same on all processes.
Definition parallel.h:75
void assign_all(const Array< N > &a)
Assigns this to 'a', and keeps all blocks.
Definition sma.h:1342
double max_abs_element()
Find maximum absolute value of elements.
Definition sma.h:1912
Array(const std::string &name="", double tol=DBL_EPSILON)
This does not initialize any indices.
Definition sma.h:1352
double value()
If this is a scalar (N==0) return the value of the scalar.
Definition sma.h:2002
void print_local(std::ostream &o=sc::ExEnv::outn()) const
Print the array.
Definition arraydef.h:34
blockmap_t::value_type & add_zeroed_block(const BlockInfo< N > &b)
Adds block b.
Definition sma.h:1561
Array< N > & operator=(const Array< N > &a)
Assigns this to 'a', but throws out small blocks.
Definition sma.h:1346
void set_index(int i, const Range &idx)
Sets the i'th Range to index.
Definition sma.h:1496
blockmap_t::iterator add_new_unallocated_block(const typename blockmap_t::iterator &hint, const BlockInfo< N > &b)
Adds block b.
Definition sma.h:1605
void init_blocks(const Array< N > &a, double tol)
Initialize the stored blocks to be the same as those in a.
Definition sma.h:1885
static int nindex()
Return the number of indices.
Definition sma.h:1488
Array(const Range &i0, const Range &i1, const Range &i2, const Range &i3, const Range &i4, const Range &i5, const std::string &name="", double tol=DBL_EPSILON)
Initialize range 0, 1, 2, 3, 4, and 5 to i0, i1, i2, i3, i4, and i5, and the rest to i5.
Definition sma.h:1438
Array(const Range &i0, const Range &i1, const Range &i2, const Range &i3, const Range &i4, const std::string &name="", double tol=DBL_EPSILON)
Initialize range 0, 1, 2, 3, and 4 to i0, i1, i2, i3, and i4, and the rest to i4.
Definition sma.h:1417
Provides information about how blocks are distributed onto processes.
Definition sma.h:1205
void zero()
Set all block indices to zero.
Definition sma.h:438
unsigned int size(const Range *indices) const
Compute the size of this block.
Definition sma.h:405
void assign_blocks(const IndexList &il, const BlockInfo< N2 > &bi2, const IndexList &il2)
Assign blocks to those in another BlockInfo, bi2, given an IndexList that specifies the index mapping...
Definition sma.h:419
void assign_blocks(const IndexList &il, const BlockInfo< N2 > &bi2)
Assign blocks to those in another BlockInfo, bi2, given an IndexList that specifies the index mapping...
Definition sma.h:426
unsigned int subset_size(const Range *indices, const IndexList &indexlist) const
Compute the size of a block formed from this block by using some subset of the indices given by index...
Definition sma.h:410
bool equiv_blocks(const IndexList &il, const BlockInfo< N2 > &bi2)
Return true if blocks are the same as in another BlockInfo, bi2, given an IndexList that specifies th...
Definition sma.h:433
BlockInfo stores info about a block of data.
Definition sma.h:200
BlockInfo(const BlockInfo< N > &b, const IndexList &l)
Initialize the blocks to the values in the argument, b.
Definition sma.h:223
void zero()
Set all block indices to zero.
Definition sma.h:239
unsigned int subset_size(const Range *indices, const IndexList &indexlist) const
Compute the size of a block formed from this block by using some subset of the indices given by index...
Definition sma.h:254
unsigned int size(const Range *indices) const
Compute the size of this block.
Definition sma.h:247
BlockInfo(const std::vector< bi_t > &v)
Initialize the blocks to the values in the argument, v.
Definition sma.h:214
bool equiv_blocks(const IndexList &il, const BlockInfo< N2 > &bi2)
Return true if blocks are the same as in another BlockInfo, bi2, given an IndexList that specifies th...
Definition sma.h:288
void assign_blocks(const IndexList &il, const BlockInfo< N2 > &bi2)
Assign blocks to those in another BlockInfo, bi2, given an IndexList that specifies the index mapping...
Definition sma.h:278
void assign_blocks(const IndexList &il, const BlockInfo< N2 > &bi2, const IndexList &il2)
Assign blocks to those in another BlockInfo, bi2, given an IndexList that specifies the index mapping...
Definition sma.h:268
BlockIter loops through the all the indices within a block.
Definition sma.h:2189
bool ready() const
Returns true if the iterator is valid.
Definition sma.h:2213
void operator++(int)
Increments the iterator.
Definition sma.h:2215
void start()
Initialize the iterator.
Definition sma.h:2211
int block_size(int i) const
Returns the size of the given block.
Definition sma.h:2241
Represents an array and symbolic indices in a contraction.
Definition sma.h:1095
ContractPart< N > operator~() const
Instruct the contract routine to clear this array immediately after use.
Definition contractpartdef.h:688
double value()
Extract a value from the array.
Definition contractpartdef.h:705
ContractPart< N > skip_bounds_update() const
Causes the bounds to not be computed for the LHS operand for certain operations.
Definition contractpartdef.h:696
void operator|=(const ContractPart< N2 > &o) const
Add blocks to this corresponding the blocks already allocated in o.
Definition contractpartdef.h:549
Represents a pairs of contracted array and their symbolic indices.
Definition sma.h:2062
Data holds the values for each block.
Definition sma.h:1026
Functor for determining if one IndexList is less than another.
Definition sma.h:977
IndexListLess(const IndexList &il)
Use the IndexList il to sort the indices.
Definition sma.h:982
IndexListLess(const IndexList &il1, const IndexList &il2)
Use the indices in both IndexList objects, il1 and il2, to sort the indices.
Definition sma.h:985
An IndexList is a vector of indices.
Definition sma.h:160
IndexList(const IndexList &il1, const IndexList &il2)
Append the indices from both IndexList objects, il1 and il2, to form this IndexList.
bool is_identity() const
Returns true if this is 0, 1, ..., n-1.
bool is_identity_permutation() const
Returns true if this is a permutation of 0, 1, ..., n-1.
An Index is used in the symbolic notation for contractions.
Definition sma.h:1047
Index(int value)
Allocate an index with a specific value.
Definition sma.h:1059
bool symbolically_equivalent(const Index &i) const
Returns true if the indices have non-empty names which are the same.
Definition sma.h:1079
bool operator==(const Index &i) const
Returns true if the indices are equivalent.
Definition sma.h:1082
Index(const std::string &name)
Allocate a named index.
Definition sma.h:1053
bool has_value() const
Returns true if the index has a value, indicating that the index is to be fixed.
Definition sma.h:1074
void set_value(int value)
Set the value of the index.
Definition sma.h:1085
int value() const
Return the value of the index.
Definition sma.h:1071
const std::string name() const
Return the name of the index.
Definition sma.h:1068
Index(const std::string &name, int value)
Allocate an Index with a fixed value and a name.
Definition sma.h:1065
Functor for comparing a block's indices.
Definition sma.h:333
An Range represent a set of integers, [0, N).
Definition sma.h:93
int nindex() const
Returns the dimension of this range.
Definition sma.h:125
int block_size(int i) const
Returns the size for the given block.
Definition sma.h:129
int max_block_size() const
Returns the maximum block size.
Definition sma.h:131
int nblock() const
Returns the number of blocks.
Definition sma.h:127
int index_to_block(int i) const
Given an index, return the block in which that index is found.
Definition sma.h:135
bool all_size_one() const
Returns true if all blocks are size 1.
int block_offset(int i) const
Returns the offset for the given block.
Definition sma.h:133
int index_to_offset(int i) const
Given an index, return its offset within the block in which that index is found.
Definition sma.h:138
int basis_index_to_range_index(int i) const
Maps a basis function number to the number within this Range object.
Contains all MPQC code up to version 3.
Definition mpqcin.h:14