25 #ifndef _chemistry_qc_lmp2_contract_h
26 #define _chemistry_qc_lmp2_contract_h
28 #include <chemistry/qc/lmp2/dgemminfo.h>
32 #include <math/scmat/blas.h>
34 #define USE_BOUNDS_IN_CONTRACT_UNION 1
48 need_repack(
const Array<N> *A,
const IndexList &row_indices,
const IndexList &col_indices,
49 const IndexList &fixed,
const BlockInfo<N> *fixedvals)
54 std::vector<int> indices;
56 for (
int i=0; i<row_indices.n(); i++) {
57 int index = row_indices.i(i);
58 if (A->index(index).max_block_size() > 1) {
59 indices.push_back(index);
63 for (
int i=0; i<col_indices.n(); i++) {
64 int index = col_indices.i(i);
65 if (A->index(index).max_block_size() > 1) {
66 indices.push_back(index);
70 for (
int i=1; i<indices.size(); i++) {
71 if (indices[i] < indices[i-1])
return true;
85 repack_cost(
const Array<N> *A,
86 const IndexList &row_indices,
const IndexList &col_indices,
87 const IndexList &fixed,
const BlockInfo<N> *fixedvals)
96 double cost = A->n_element_allocated();
97 for (
int i=0; i<fixed.n(); i++) {
98 cost = cost/A->index(fixed.i(i)).nblock();
104 template <
int NC,
int NA,
int NB>
107 bool need_repack_A_, transpose_A_;
108 bool need_repack_B_, transpose_B_;
109 bool need_repack_C_, transpose_C_;
123 need_repack_A_ =
false;
124 transpose_A_ =
false;
125 if (need_repack(A_, extA_, intA_, fixA_, fixvalA_)) {
126 if (need_repack(A_, intA_, extA_, fixA_, fixvalA_)) {
127 need_repack_A_ =
true;
128 cost_ += 2.0 * repack_cost(A_,extA_,intA_,fixA_,fixvalA_);
135 need_repack_B_ =
false;
136 transpose_B_ =
false;
137 if (need_repack(B_, intB_, extB_, fixB_, fixvalB_)) {
138 if (need_repack(B_, extB_, intB_, fixB_, fixvalB_)) {
139 need_repack_B_ =
true;
140 cost_ += 2.0 * repack_cost(B_,intB_,extB_,fixB_,fixvalB_);
147 need_repack_C_ =
false;
148 transpose_C_ =
false;
149 if (need_repack(C_, extCA_, extCB_, fixC_, fixvalC_)) {
150 if (need_repack(C_, extCB_, extCA_, fixC_, fixvalC_)) {
151 need_repack_C_ =
true;
153 * repack_cost(C_,extCA_,extCB_,fixC_,fixvalC_);
161 std::map<int,int> index_map;
162 for (
int i=0; i<i1.n(); i++) {
163 index_map[i1.i(i)] = i2.i(i);
166 for (std::map<int,int>::iterator
167 iter=index_map.begin();
168 iter!=index_map.end(); i++,iter++) {
169 i1.i(i) = iter->first;
170 i2.i(i) = iter->second;
187 extA_(extA), intA_(intA), fixA_(fixA), fixvalA_(fixvalA),
188 extB_(extB), intB_(intB), fixB_(fixB), fixvalB_(fixvalB),
189 extCA_(extCA), extCB_(extCB), fixC_(fixC), fixvalC_(fixvalC),
191 n_C_repack_(n_C_repack) {
198 reorder_indices(extCA_,extA_);
199 reorder_indices(extCB_,extB_);
202 reorder_indices(extA_,extCA_);
203 reorder_indices(intA_,intB_);
206 reorder_indices(extB_,extCB_);
207 reorder_indices(intB_,intA_);
224 double cost()
const {
return cost_; }
249 repack(Array<N> &A,
const IndexList &row_indices,
const IndexList &col_indices,
250 const IndexList &fixed,
const BlockInfo<N> &fixedvals,
251 bool reverse =
false)
253 double *tmp_data = 0;
256 const typename Array<N>::blockmap_t &amap = A.blockmap();
258 typename Array<N>::blockmap_t::const_iterator begin, end;
259 if (fixed.n() == 0) {
260 begin = amap.begin();
267 sbi.assign_blocks(fixed, fixedvals);
269 sbi.set_bound(DBL_MAX);
271 begin = amap.lower_bound(sbi);
273 for (
int i=0; i<N; i++) sbi.block(i) = A.index(i).nblock();
274 sbi.assign_blocks(fixed, fixedvals);
278 end = amap.upper_bound(sbi);
281 for (
typename Array<N>::blockmap_t::const_iterator aiter = begin;
284 const BlockInfo<N> &bi = aiter->first;
285 double *data = aiter->second;
286 int ndata = bi.size(A.indices());
287 if (n_tmp_data < ndata) {
289 tmp_data =
new double[ndata];
292 int nrow = bi.subset_size(A.indices(), row_indices);
293 int ncol = bi.subset_size(A.indices(), col_indices);
294 if (ndata != nrow * ncol) {
295 throw std::length_error(
"sma::repack: ntotal != nrow * ncol");
297 memcpy(tmp_data,data,
sizeof(
double)*ndata);
298 BlockIter<N> a_iter(A.indices(), bi);
299 for (a_iter.start(); a_iter.ready(); a_iter++) {
300 int row_index = a_iter.subset_offset(row_indices);
301 int col_index = a_iter.subset_offset(col_indices);
302 int index = a_iter.offset();
303 int repacked_index = row_index*ncol + col_index;
305 data[repacked_index] = tmp_data[index];
308 data[index] = tmp_data[repacked_index];
344 template <
int NC,
int NA,
int NB>
347 Array<NC> &C,
const IndexList &c_extCA,
const IndexList &c_extCB,
348 const IndexList &fixextCA,
const IndexList &fixextCB,
349 const IndexList &fixC,
const BlockInfo<NC> &fixvalC,
350 Array<NA> &A,
const IndexList &c_extA,
const IndexList &fixextA,
351 const IndexList &c_intA,
352 const IndexList &fixA,
const BlockInfo<NA> &fixvalA,
353 bool clear_A_after_use,
354 Array<NB> &B,
const IndexList &c_extB,
const IndexList &fixextB,
355 const IndexList &c_intB,
356 const IndexList &fixB,
const BlockInfo<NB> &fixvalB,
357 bool clear_B_after_use,
359 bool C_is_zero_on_entry =
false,
365 IndexList extCA(c_extCA), extCB(c_extCB);
366 IndexList extA(c_extA), extB(c_extB);
367 IndexList intA(c_intA), intB(c_intB);
369 if (C.n_element_allocated() == 0
370 || A.n_element_allocated() == 0
371 || B.n_element_allocated() == 0) {
375 for (
int i=0; i<fixC.n(); i++)
376 if (fixC.i(i) >= fixC.n())
377 throw std::invalid_argument(
"contract: C's fixed indices must be first");
380 if (extA.n() + extB.n() != NC - fixC.n() + fixextCA.n() + fixextCB.n()) {
381 throw std::invalid_argument(
"contract: Number of externals on A + B != C");
383 if (extCA.n() + extCB.n() != NC - fixC.n() + fixextCA.n() + fixextCB.n()) {
384 throw std::invalid_argument(
"contract: Number of indices on C inconsistent");
386 if (intA.n() != intB.n()) {
387 throw std::invalid_argument(
388 "contract: Number of internals on A and B inconsistent");
390 if (intA.n() + extA.n() != NA - fixA.n() + fixextA.n()) {
391 throw std::invalid_argument(
"contract: Number of indices on A inconsistent");
393 if (intB.n() + extB.n() != NB - fixB.n() + fixextB.n()) {
394 throw std::invalid_argument(
"contract: Number of indices on B inconsistent");
396 for (
int i=0; i<extA.n(); i++) {
397 if (A.index(extA.i(i)) != C.index(extCA.i(i))) {
398 throw std::invalid_argument(
"contract: Range conflict between A and C");
401 for (
int i=0; i<extB.n(); i++) {
402 if (B.index(extB.i(i)) != C.index(extCB.i(i))) {
403 throw std::invalid_argument(
"contract: Range conflict between B and C");
406 for (
int i=0; i<intA.n(); i++) {
407 if (A.index(intA.i(i)) != B.index(intB.i(i))) {
408 throw std::invalid_argument(
"contract: Range conflict between A and B");
412 RepackScheme<NC,NA,NB> repack_scheme(&A, extA, intA, fixA, &fixvalA,
413 &B, intB, extB, fixB, &fixvalB,
414 &C, extCA,extCB,fixC, &fixvalC,
415 C_is_zero_on_entry?1:2);
427 if (repack_scheme.cost() != 0.0) {
428 RepackScheme<NC,NA,NB> tmp_repack_scheme(repack_scheme);
429 for (
int driver1 = 0; driver1 < 3; driver1++) {
430 for (
int driver2 = 0; driver2 < 3; driver2++) {
431 if (driver1 == driver2)
continue;
432 tmp_repack_scheme.driver(driver1);
433 tmp_repack_scheme.driver(driver2);
451 if (tmp_repack_scheme.cost() < repack_scheme.cost()) {
452 repack_scheme = tmp_repack_scheme;
453 repack_scheme.assign_indices(extA, intA,
458 if (repack_scheme.cost() == 0.0)
break;
460 if (repack_scheme.cost() == 0.0)
break;
466 if (timer) timer->enter(
"remap A");
467 IndexList cmpAlist(extA,fixA);
468 IndexListLess<NA> cmpA(cmpAlist);
469 typename Array<NA>::cached_blockmap_t remappedAbm_local(cmpA);
470 typename Array<NA>::cached_blockmap_t *remappedAbm_ptr;
471 if (fixA.n() == 0 && A.use_blockmap_cache()) {
472 remappedAbm_ptr = &A.blockmap_cache_entry(cmpAlist);
475 remap(remappedAbm_local, A, fixA, fixvalA);
476 remappedAbm_ptr = &remappedAbm_local;
478 typename Array<NA>::cached_blockmap_t &remappedAbm=*remappedAbm_ptr;
479 if (timer) timer->exit();
485 if (timer) timer->enter(
"repack1");
486 if (repack_scheme.need_repack_A()) repack(A, extA, intA, fixA, fixvalA);
487 if (repack_scheme.need_repack_B()) repack(B, intB, extB, fixB, fixvalB);
488 if (repack_scheme.need_repack_C() && !C_is_zero_on_entry) {
489 repack(C, extCA, extCB, fixC, fixvalC);
491 if (timer) timer->exit();
505 std::set<int> fixed_all, fixed_A, fixed_B, fixed_C;
506 for (
int i=0; i<fixA.n(); i++) {
507 fixed_all.insert(fixvalA.block(i));
508 fixed_A.insert(fixvalA.block(i));
510 for (
int i=0; i<fixB.n(); i++) {
511 fixed_all.insert(fixvalB.block(i));
512 fixed_B.insert(fixvalB.block(i));
514 for (
int i=0; i<fixC.n(); i++) {
515 fixed_all.insert(fixvalC.block(i));
516 fixed_C.insert(fixvalC.block(i));
518 if (repack_scheme.need_repack_A()
519 && fixed_A.size() > 0
520 && fixed_A != fixed_all) {
521 std::cout <<
"PERFORMANCE WARNING: contract needed to repack A"
522 <<
" but B and/or C have different fixed indices"
524 throw std::runtime_error(
"contract: performance exception");
526 if (repack_scheme.need_repack_B()
527 && fixed_B.size() > 0
528 && fixed_B != fixed_all) {
529 std::cout <<
"PERFORMANCE WARNING: contract needed to repack B"
530 <<
" but A and/or C have different fixed indices"
532 throw std::runtime_error(
"contract: performance exception");
534 if (repack_scheme.need_repack_C()
535 && fixed_C.size() > 0
536 && fixed_C != fixed_all) {
537 std::cout <<
"PERFORMANCE WARNING: contract needed to repack C"
538 <<
" but A and/or B have different fixed indices"
540 throw std::runtime_error(
"contract: performance exception");
544 const typename Array<NB>::blockmap_t &
547 const typename Array<NB>::blockhash_t &
550 const typename Array<NC>::blockmap_t &
554 Abi.assign_blocks(fixA,fixvalA);
558 Bbi.assign_blocks(fixB,fixvalB);
561 typename Array<NB>::blockmap_t::const_iterator B_fixed_hint
562 = Bbm.lower_bound(Bbi);
565 typename Array<NC>::blockmap_t::const_iterator C_begin, C_end;
566 BlockInfo<NC> Cbi_lb;
567 BlockInfo<NC> Cbi_ub;
568 for (
int i=0; i<NC; i++) {
570 Cbi_ub.block(i) = C.index(i).nblock();
572 Cbi_lb.assign_blocks(fixC,fixvalC);
573 Cbi_ub.assign_blocks(fixC,fixvalC);
574 C_begin = Cbm.lower_bound(Cbi_lb);
575 C_end = Cbm.upper_bound(Cbi_ub);
577 if (timer) timer->enter(
"C loop");
578 for (
typename Array<NC>::blockmap_t::const_iterator
582 const BlockInfo<NC> &Cbi = Citer->first;
583 double *Cdata = Citer->second;
584 Abi.assign_blocks(extA, Cbi, extCA);
586 typename Array<NA>::cached_blockmap_t::const_iterator,
587 typename Array<NA>::cached_blockmap_t::const_iterator >
592 Abi.set_bound(DBL_MAX);
593 rangeA.first = remappedAbm.lower_bound(Abi);
595 rangeA.second = remappedAbm.upper_bound(Abi);
597 rangeA = remappedAbm.equal_range(Abi);
599 typename Array<NA>::cached_blockmap_t::const_iterator
600 firstA = rangeA.first,
601 fenceA = rangeA.second;
602 Bbi.assign_blocks(extB, Cbi, extCB);
603 blasint n_extB = Cbi.subset_size(C.indices(), extCB);
604 blasint n_extA = Cbi.subset_size(C.indices(), extCA);
606 typename Array<NB>::blockhash_t::const_iterator Biter;
608 typename Array<NB>::blockmap_t::const_iterator Biter = Bbm.begin();
610 if (timer) timer->enter(
"A loop");
611 for (
typename Array<NA>::cached_blockmap_t::const_iterator
615 const BlockInfo<NA> &Abi = Aiter->first;
616 double *Adata = Aiter->second;
617 Bbi.assign_blocks(intB, Abi, intA);
619 Biter = Bbh.find(Bbi);
620 if (Biter == Bbh.end())
continue;
624 Biter = Bbm.find(Bbi);
626 Biter = Bbm.find(B_fixed_hint, Bbi);
632 Biter = Bbm.find(Bbi);
634 if (Biter == Bbm.end())
continue;
636 double *Bdata = Biter->second;
637 blasint n_int = Abi.subset_size(A.indices(), intA);
640 if (timer) timer->enter(
"dgemm");
642 double t0 = cpu_walltime();
644 if (n_extA == 1 && n_int == 1) {
645 double tmp = ABfactor * Adata[0];
646 for (
int i=0; i<n_extB; i++) {
647 Cdata[i] += tmp*Bdata[i];
650 else if (n_extA == 1 && n_extB == 1) {
652 for (
int i=0; i<n_int; i++) {
653 tmp += Adata[i]*Bdata[i];
655 Cdata[0] += ABfactor*tmp;
657 else if (n_int == 1 && n_extB == 1) {
658 double tmp = ABfactor*Bdata[0];
659 for (
int i=0; i<n_extA; i++) {
660 Cdata[i] += Adata[i]*tmp;
663 else if (n_int == 1) {
664 if (repack_scheme.transpose_C()) {
665 for (
int i=0,ij=0; i<n_extB; i++) {
666 for (
int j=0; j<n_extA; j++,ij++) {
667 Cdata[ij] += ABfactor*Adata[j]*Bdata[i];
672 for (
int i=0,ij=0; i<n_extA; i++) {
673 for (
int j=0; j<n_extB; j++,ij++) {
674 Cdata[ij] += ABfactor*Adata[i]*Bdata[j];
679 else if (n_extA == 1) {
680 if (repack_scheme.transpose_B()) {
681 for (
int i=0,ij=0; i<n_extB; i++) {
683 for (
int j=0; j<n_int; j++,ij++) {
684 tmp += Adata[j]*Bdata[ij];
686 Cdata[i] += tmp * ABfactor;
690 for (
int i=0; i<n_extB; i++) {
692 for (
int j=0,ij=i; j<n_int; j++,ij+=n_extB) {
693 tmp += Adata[j]*Bdata[ij];
695 Cdata[i] += tmp * ABfactor;
699 else if (n_extB == 1) {
700 if (repack_scheme.transpose_A()) {
701 for (
int i=0; i<n_extA; i++) {
703 for (
int j=0,ij=i; j<n_int; j++,ij+=n_extA) {
704 tmp += Bdata[j]*Adata[ij];
706 Cdata[i] += tmp * ABfactor;
710 for (
int i=0,ij=0; i<n_extA; i++) {
712 for (
int j=0; j<n_int; j++,ij++) {
713 tmp += Bdata[j]*Adata[ij];
715 Cdata[i] += tmp * ABfactor;
719 else if (repack_scheme.transpose_C()) {
720 const char *tA =
"T";
722 if (repack_scheme.transpose_A()) { tA =
"N"; lda = n_extA; }
724 const char *tB =
"T";
725 blasint ldb = n_extB;
726 if (repack_scheme.transpose_B()) { tB =
"N"; ldb = n_int; }
728 blasint ldc = n_extA;
740 F77_DGEMM(tA, tB, &n_extA, &n_extB, &n_int,
741 &ABfactor,Adata,&lda,Bdata,&ldb,
745 const char *tA =
"N";
747 if (repack_scheme.transpose_A()) { tA =
"T"; lda = n_extA; }
749 const char *tB =
"N";
750 blasint ldb = n_extB;
751 if (repack_scheme.transpose_B()) { tB =
"T"; ldb = n_int; }
753 blasint ldc = n_extB;
755 F77_DGEMM(tB, tA, &n_extB, &n_extA, &n_int,
756 &ABfactor,Bdata,&ldb,Adata,&lda,
759 #ifdef USE_COUNT_DGEMM
763 if (timer) timer->exit();
765 if (timer) timer->exit();
767 if (timer) timer->exit();
770 if (timer) timer->enter(
"repack2");
771 if (clear_A_after_use) A.clear();
773 if (repack_scheme.need_repack_A()) {
774 repack(A, extA, intA, fixA, fixvalA,
true);
778 if (clear_B_after_use) B.clear();
780 if (repack_scheme.need_repack_B()) {
781 repack(B, intB, extB, fixB, fixvalB,
true);
785 if (repack_scheme.need_repack_C()) {
786 repack(C, extCA, extCB, fixC, fixvalC,
true);
788 if (timer) timer->exit();
790 if (timer) timer->enter(
"bounds");
792 if (timer) timer->exit();
800 Array<N> &a,
const IndexList &alist)
803 if (alist.n() != N) {
804 throw std::invalid_argument(
805 "sma::scalar_contract: # of indices inconsistent");
807 for (
int i=0; i<N; i++) {
808 if (c.index(i) != a.index(alist.i(i)))
809 throw std::invalid_argument(
810 "sma::scalar_contract: indices don't agree");
813 bool same_index_order = alist.is_identity();
816 const typename Array<N>::blockmap_t &amap = a.blockmap();
817 const typename Array<N>::blockmap_t &cmap = c.blockmap();
818 IndexList clist = alist.reverse_mapping();
820 if (clist.i(0) == 0) use_hint =
true;
821 else use_hint =
false;
822 typename Array<N>::blockmap_t::const_iterator citer = cmap.begin();
823 for (
typename Array<N>::blockmap_t::const_iterator aiter = amap.begin();
826 BlockInfo<N> cbi(aiter->first,clist);
828 citer = cmap.find(cbi);
830 if (use_hint) citer = cmap.find(citer,cbi);
831 else citer = cmap.find(cbi);
833 if (citer == cmap.end())
continue;
834 double *cdata = citer->second;
835 double *adata = aiter->second;
836 if (same_index_order) {
837 int sz = c.block_size(cbi);
838 for (
int i=0; i<sz; i++) r += cdata[i] * adata[i];
841 BlockIter<N> cbiter(c.indices(),cbi);
843 for (cbiter.start(); cbiter.ready(); cbiter++,coff++) {
844 r += cdata[coff] * adata[cbiter.subset_offset(alist)];
858 template <
int NC,
int NA,
int NB>
861 Array<NC> &C,
const IndexList &extCA,
const IndexList &extCB,
862 const IndexList &fixC,
const BlockInfo<NC> &fixvalC,
863 Array<NA> &A,
const IndexList &extA,
const IndexList &intA,
864 const IndexList &fixA,
const BlockInfo<NA> &fixvalA,
865 Array<NB> &B,
const IndexList &extB,
const IndexList &intB,
866 const IndexList &fixB,
const BlockInfo<NB> &fixvalB)
869 if (extA.n() + extB.n() != NC - fixC.n()) {
870 std::cerr <<
"NA = " << NA << std::endl;
871 std::cerr <<
"intA = " << intA << std::endl;
872 std::cerr <<
"extA = " << extA << std::endl;
873 std::cerr <<
"fixA = " << fixA << std::endl;
874 std::cerr <<
"NB = " << NB << std::endl;
875 std::cerr <<
"intB = " << intB << std::endl;
876 std::cerr <<
"extB = " << extB << std::endl;
877 std::cerr <<
"fixB = " << fixB << std::endl;
878 std::cerr <<
"NC = " << NC << std::endl;
879 std::cerr <<
"extCA = " << extCA << std::endl;
880 std::cerr <<
"extCB = " << extCB << std::endl;
881 std::cerr <<
"fixC = " << fixC << std::endl;
882 throw std::invalid_argument(
"contract_union: Number of externals on A + B != C");
884 if (extCA.n() + extCB.n() != NC - fixC.n()) {
885 throw std::invalid_argument(
"contract_union: Number of indices on C inconsistent");
887 if (intA.n() != intB.n()) {
888 throw std::invalid_argument(
889 "contract_union: Number of internals on A and B inconsistent");
891 if (intA.n() + extA.n() != NA - fixA.n()) {
892 std::cerr <<
"NA = " << NA << std::endl;
893 std::cerr <<
"extA.n() = " << extA.n() << std::endl;
894 std::cerr <<
"fixA.n() = " << fixA.n() << std::endl;
895 std::cerr <<
"intA.n() = " << intA.n() <<
" (";
896 for (
int i=0; i<intA.n(); i++) {
897 std::cerr <<
" " << intA.i(i);
899 std::cerr <<
")" << std::endl;
900 throw std::invalid_argument(
"contract_union: Number of indices on A inconsistent");
902 if (intB.n() + extB.n() != NB - fixB.n()) {
903 throw std::invalid_argument(
"contract_union: Number of indices on B inconsistent");
905 for (
int i=0; i<extB.n(); i++) {
906 if (B.index(extB.i(i)) != C.index(extCB.i(i))) {
907 throw std::invalid_argument(
"contract_union: Range conflict between B and C");
910 for (
int i=0; i<intA.n(); i++) {
911 if (A.index(intA.i(i)) != B.index(intB.i(i))) {
912 throw std::invalid_argument(
"contract_union: Range conflict between A and B");
921 IndexList cmpAlist(fixA, intA);
922 IndexListLess<NA> cmpA(cmpAlist);
923 typename Array<NA>::cached_blockmap_t remappedAbm_local(cmpA);
924 typename Array<NA>::cached_blockmap_t *remappedAbm_ptr;
925 if (fixA.n() == 0 && A.use_blockmap_cache()) {
926 remappedAbm_ptr = &A.blockmap_cache_entry(cmpAlist);
929 remap(remappedAbm_local, A, fixA, fixvalA);
930 remappedAbm_ptr = &remappedAbm_local;
932 typename Array<NA>::cached_blockmap_t &remappedAbm=*remappedAbm_ptr;
936 IndexList cmpBlist(intB, fixB);
937 IndexListLess<NB> cmpB(cmpBlist);
938 typename Array<NB>::cached_blockmap_t remappedBbm_local(cmpB);
939 typename Array<NB>::cached_blockmap_t *remappedBbm_ptr;
940 if (fixB.n() == 0 && B.use_blockmap_cache()) {
941 remappedBbm_ptr = &B.blockmap_cache_entry(cmpBlist);
944 remap(remappedBbm_local, B, fixB, fixvalB);
945 remappedBbm_ptr = &remappedBbm_local;
947 typename Array<NB>::cached_blockmap_t &remappedBbm=*remappedBbm_ptr;
956 BlockInfo<NA> ablockinfo;
957 for (
int i=0; i<NA; i++) ablockinfo.block(i) = 0;
959 ablockinfo.set_bound(DBL_MAX);
961 ablockinfo.assign_blocks(fixA, fixvalA);
962 typename Array<NA>::cached_blockmap_t::const_iterator abegin;
963 abegin = remappedAbm.lower_bound(ablockinfo);
965 BlockInfo<NB> bblockinfo;
966 bblockinfo.assign_blocks(fixB, fixvalB);
968 BlockInfo<NC> cblockinfo;
969 cblockinfo.assign_blocks(fixC, fixvalC);
971 while (abegin != remappedAbm.end()) {
972 ablockinfo = abegin->first;
976 if (!ablockinfo.equiv_blocks(fixA, fixvalA))
break;
979 #if 0 && USE_BOUNDS_IN_CONTRACT_UNION
980 if (B.bound() < DBL_EPSILON) {
981 ablockinfo.set_bound(C.tolerance()/DBL_EPSILON);
984 ablockinfo.set_bound(C.tolerance()/B.bound());
987 ablockinfo.set_bound(0.0);
990 typename Array<NA>::cached_blockmap_t::const_iterator
991 afence = remappedAbm.upper_bound(ablockinfo);
992 bblockinfo.assign_blocks(intB,ablockinfo,intA);
993 std::pair<typename Array<NB>::cached_blockmap_t::const_iterator,
994 typename Array<NB>::cached_blockmap_t::const_iterator>
999 bblockinfo.set_bound(DBL_MAX);
1001 brange.first = remappedBbm.lower_bound(bblockinfo);
1003 #if 0 && USE_BOUNDS_IN_CONTRACT_UNION
1004 if (A.bound() < DBL_EPSILON) {
1005 bblockinfo.set_bound(C.tolerance()/DBL_EPSILON);
1008 bblockinfo.set_bound(C.tolerance()/A.bound());
1011 bblockinfo.set_bound(0.0);
1014 brange.second = remappedBbm.upper_bound(bblockinfo);
1015 typename Array<NB>::cached_blockmap_t::const_iterator
1016 bbegin = brange.first,
1017 bfence = brange.second;
1019 for (
typename Array<NA>::cached_blockmap_t::const_iterator
1024 double a_block_bound = aiter->first.bound();
1026 cblockinfo.assign_blocks(extCA,aiter->first,extA);
1028 for (
typename Array<NB>::cached_blockmap_t::const_iterator
1033 #if 0 && USE_BOUNDS_IN_CONTRACT_UNION
1034 if (a_block_bound * biter->first.bound() < C.tolerance()) {
1039 cblockinfo.assign_blocks(extCB,biter->first,extB);
1042 C.add_unallocated_block(cblockinfo);
1046 ablockinfo.set_bound(0.0);
1048 abegin = remappedAbm.upper_bound(ablockinfo);