MADNESS  version 0.9
tensor.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30 
31 
32  $Id$
33 */
34 
35 #ifndef MADNESS_TENSOR_TENSOR_H__INCLUDED
36 #define MADNESS_TENSOR_TENSOR_H__INCLUDED
37 
38 #include <madness/madness_config.h>
39 #include <madness/misc/ran.h>
40 #include <madness/world/posixmem.h>
42 
43 #include <complex>
44 #include <vector>
45 #include <cmath>
46 #include <cstdlib>
47 
48 #include <madness/world/archive.h>
49 // #include <madness/world/print.h>
50 //
51 // typedef std::complex<float> float_complex;
52 // typedef std::complex<double> double_complex;
53 //
54 // // These probably have to be included in this order
55 // #include <madness/tensor/tensor_macros.h>
56 // #include <madness/tensor/type_data.h>
57 // #include <madness/tensor/slice.h>
58 // #include <madness/tensor/vector_factory.h>
60 #include <madness/tensor/aligned.h>
61 #include <madness/tensor/mxm.h>
62 #include <madness/tensor/mtxmq.h>
65 
66 #ifdef USE_GENTENSOR
67 #define HAVE_GENTENSOR 1
68 #else
69 #define HAVE_GENTENSOR 0
70 #endif
71 
72 
217 #ifndef HAVE_STD_ABS_LONG
218 #ifndef HAVE_STD_LABS
219 namespace std {
220  static long abs(long a) {
221  return a>=0 ? a : -a;
222  }
223 }
224 #else
225 namespace std {
226  static long abs(long a) {
227  return std::labs(a);
228  }
229 }
230 #endif
231 #endif
232 
233 
234 namespace madness {
235 #define IS_ODD(n) ((n)&0x1)
236 #define IS_UNALIGNED(p) (((unsigned long)(p))&0x7)
237 
238 
240  template <typename Q, bool iscomplex>
242  static Q op(const Q& coeff) {
243  return coeff;
244  }
245  };
246 
248  template <typename Q>
249  struct conditional_conj_struct<Q,true> {
250  static Q op(const Q& coeff) {
251  return conj(coeff);
252  }
253  };
254 
256  template <typename Q>
257  Q conditional_conj(const Q& coeff) {
259  }
260 
261  namespace detail {
262  template <typename T> T mynorm(T t) {
263  return t*t;
264  }
265 
266  template <typename T> T mynorm(std::complex<T> t) {
267  return std::norm(t);
268  }
269  }
270 
271  template <class T> class SliceTensor;
272 
273 
276 
277  static
278  inline
279  std::ostream& operator << (std::ostream& s, const TensorType& tt) {
280  std::string str="confused tensor type";
281  if (tt==TT_FULL) str="full rank tensor";
282  if (tt==TT_2D) str="low rank tensor 2-way";
283  if (tt==TT_NONE) str="no tensor type specified";
284  s << str.c_str();
285  return s;
286  }
287 
288 
289 
291 
293  template <class T> class Tensor : public BaseTensor {
294  template <class U> friend class SliceTensor;
295 
296  protected:
297  T* restrict _p;
298  std::shared_ptr<T> _shptr;
299 
300 
301  void allocate(long nd, const long d[], bool dozero) {
302  _id = TensorTypeData<T>::id;
303  if (nd < 0) {
304  _p = 0;
305  _shptr.reset();
306  _size = 0;
307  _ndim = -1;
308  return;
309  }
310 
311  TENSOR_ASSERT(nd>0 && nd <= TENSOR_MAXDIM,"invalid ndim in new tensor", nd, 0);
312  // sanity check ... 2GB in doubles
313  for (int i=0; i<nd; ++i) {
314  TENSOR_ASSERT(d[i]>=0 && d[i]<268435456, "invalid dimension size in new tensor",d[i],0);
315  }
316  set_dims_and_size(nd, d);
317  if (_size) {
318  TENSOR_ASSERT(_size>=0 && _size<268435456, "invalid size in new tensor",_size,0);
319  try {
320 #if HAVE_IBMBGP
321 #define TENSOR_ALIGNMENT 16
322 #elif HAVE_IBMBGQ
323 #define TENSOR_ALIGNMENT 32
324 #else
325 #define TENSOR_ALIGNMENT 16
326 #endif
327 
328 #ifdef WORLD_GATHER_MEM_STATS
329  _p = new T[size];
330  _shptr = std::shared_ptr<T>(_p);
331 #else
332  if (posix_memalign((void **) &_p, TENSOR_ALIGNMENT, sizeof(T)*_size)) throw 1;
333  _shptr.reset(_p, &::madness::detail::checked_free<T>);
334 #endif
335  }
336  catch (...) {
337  std::printf("new failed nd=%ld type=%ld size=%ld\n", nd, id(), _size);
338  std::printf(" %ld %ld %ld %ld %ld %ld\n",
339  d[0], d[1], d[2], d[3], d[4], d[5]);
340  TENSOR_EXCEPTION("new failed",_size,this);
341  }
342  //std::printf("allocated %p [%ld] %ld\n", _p, size, p.use_count());
343  if (dozero) {
344  //T zero = 0; for (long i=0; i<_size; ++i) _p[i] = zero;
345  // or
346 #ifdef HAVE_MEMSET
347  memset((void *) _p, 0, _size*sizeof(T));
348 #else
349  aligned_zero(_size, _p);
350 #endif
351  }
352  }
353  else {
354  _p = 0;
355  _shptr.reset();
356  }
357  }
358 
359  // Free memory and restore default constructor state
360  void deallocate() {
361  _p = 0;
362  _shptr.reset();
363  _size = 0;
364  _ndim = -1;
365  }
366 
367  public:
369  typedef T type;
370 
372  typedef typename TensorTypeData<T>::scalar_type scalar_type;
373 
375  typedef typename TensorTypeData<T>::float_scalar_type float_scalar_type;
376 
378  Tensor() : _p(0) {
379  _id = TensorTypeData<T>::id;
380  }
381 
383 
391  Tensor(const Tensor<T>& t) {
392  _id = TensorTypeData<T>::id;
393  *this = t;
394  }
395 
397 
406  Tensor<T>& operator=(const Tensor<T>& t) {
407  if (this != &t) {
408  _p = t._p;
409  _shptr = t._shptr;
410  _size = t._size;
411  _ndim = t._ndim;
412  for (int i=0; i<TENSOR_MAXDIM; ++i) {
413  _dim[i] = t._dim[i];
414  _stride[i] = t._stride[i];
415  }
416  }
417  return *this;
418  }
419 
420 
422  template <class Q> operator Tensor<Q>() const { // type conv => deep copy
423  Tensor<Q> result = Tensor<Q>(this->_ndim,this->_dim,false);
424  BINARY_OPTIMIZED_ITERATOR(Q, result, const T, (*this), *_p0 = (Q)(*_p1));
425  return result;
426  }
427 
428 
430 
432  explicit Tensor(long d0) : _p(0) {
433  _dim[0] = d0;
434  allocate(1, _dim, true);
435  }
436 
438 
441  explicit Tensor(long d0, long d1) : _p(0) {
442  _dim[0] = d0; _dim[1] = d1;
443  allocate(2, _dim, true);
444  }
445 
447 
451  explicit Tensor(long d0, long d1, long d2) : _p(0) {
452  _dim[0] = d0; _dim[1] = d1; _dim[2] = d2;
453  allocate(3, _dim, true);
454  }
455 
457 
462  explicit Tensor(long d0, long d1, long d2, long d3) : _p(0) {
463  _dim[0] = d0; _dim[1] = d1; _dim[2] = d2; _dim[3] = d3;
464  allocate(4, _dim, true);
465  }
466 
468 
474  explicit Tensor(long d0, long d1, long d2, long d3, long d4) : _p(0) {
475  _dim[0] = d0; _dim[1] = d1; _dim[2] = d2; _dim[3] = d3; _dim[4] = d4;
476  allocate(5, _dim, true);
477  }
478 
480 
487  explicit Tensor(long d0, long d1, long d2, long d3, long d4, long d5) {
488  _dim[0] = d0; _dim[1] = d1; _dim[2] = d2; _dim[3] = d3; _dim[4] = d4; _dim[5] = d5;
489  allocate(6, _dim, true);
490  }
491 
493 
496  explicit Tensor(const std::vector<long>& d, bool dozero=true) : _p(0) {
497  allocate(d.size(), d.size() ? &(d[0]) : 0, dozero);
498  }
499 
501 
505  explicit Tensor(long nd, const long d[], bool dozero=true) : _p(0) {
506  allocate(nd,d,dozero);
507  }
508 
510 
513  Tensor<T>& operator=(T x) {
514  UNARY_OPTIMIZED_ITERATOR(T,(*this),*_p0 = x);
515  return *this;
516  }
517 
519 
522  Tensor<T>& fill(T x) {
523  *this = x;
524  return *this;
525  }
526 
528 
531  template <typename Q>
532  Tensor<T>& operator+=(const Tensor<Q>& t) {
533  BINARY_OPTIMIZED_ITERATOR(T, (*this), const T, t, *_p0 += *_p1);
534  return *this;
535  }
536 
538 
541  template <typename Q>
542  Tensor<T>& operator-=(const Tensor<Q>& t) {
543  BINARY_OPTIMIZED_ITERATOR(T, (*this), const T, t, *_p0 -= *_p1);
544  return *this;
545  }
546 
548 
551  template <typename Q>
552  Tensor< TENSOR_RESULT_TYPE(T,Q) > operator+(const Tensor<Q>& t) const {
553  typedef TENSOR_RESULT_TYPE(T,Q) resultT;
554  Tensor<resultT> result(_ndim,_dim,false);
555  TERNARY_OPTIMIZED_ITERATOR(resultT, result, const T, (*this), const Q, t, *_p0 = *_p1 + *_p2);
556  return result;
557  }
558 
560 
563  template <typename Q>
564  Tensor< TENSOR_RESULT_TYPE(T,Q) > operator-(const Tensor<Q>& t) const {
565  typedef TENSOR_RESULT_TYPE(T,Q) resultT;
566  Tensor<resultT> result(_ndim,_dim,false);
567  TERNARY_OPTIMIZED_ITERATOR(resultT, result, const T, (*this), const Q, t, *_p0 = *_p1 - *_p2);
568  return result;
569  }
570 
572 
575  template <typename Q>
576  typename IsSupported<TensorTypeData<Q>, Tensor<TENSOR_RESULT_TYPE(T,Q)> >::type
577  operator*(const Q& x) const {
578  typedef TENSOR_RESULT_TYPE(T,Q) resultT;
579  Tensor<resultT> result(_ndim,_dim,false);
580  BINARY_OPTIMIZED_ITERATOR(resultT, result, const T, (*this), *_p0 = *_p1 * x);
581  return result;
582  }
583 
585 
588  template <typename Q>
589  typename IsSupported<TensorTypeData<Q>, Tensor<TENSOR_RESULT_TYPE(T,Q)> >::type
590  operator/(const Q& x) const {
591  typedef TENSOR_RESULT_TYPE(T,Q) resultT;
592  Tensor<resultT> result(_ndim,_dim);
593  BINARY_OPTIMIZED_ITERATOR(resultT, result, const T, (*this), *_p0 = *_p1 / x);
594  return result;
595  }
596 
598 
601  template <typename Q>
602  typename IsSupported<TensorTypeData<Q>, Tensor<TENSOR_RESULT_TYPE(T,Q)> >::type
603  operator+(const Q& x) const {
604  typedef TENSOR_RESULT_TYPE(T,Q) resultT;
605  Tensor<resultT> result(_ndim,_dim);
606  BINARY_OPTIMIZED_ITERATOR(resultT, result, const T, (*this), *_p0 = *_p1 + x);
607  return result;
608  }
609 
611 
614  template <typename Q>
615  typename IsSupported<TensorTypeData<Q>, Tensor<TENSOR_RESULT_TYPE(T,Q)> >::type
616  operator-(const Q& x) const {
617  return (*this) + (-x);
618  }
619 
621 
623  Tensor<T> operator-() const {
624  Tensor<T> result = Tensor<T>(_ndim,_dim,false);
625  BINARY_OPTIMIZED_ITERATOR(T, result, const T, (*this), *(_p0) = - (*_p1));
626  return result;
627  }
628 
630 
633  template <typename Q>
634  typename IsSupported<TensorTypeData<Q>,Tensor<T>&>::type
635  operator*=(const Q& x) {
636  UNARY_OPTIMIZED_ITERATOR(T, (*this), *_p0 *= x);
637  return *this;
638  }
639 
641 
644  template <typename Q>
645  typename IsSupported<TensorTypeData<Q>,Tensor<T>&>::type
646  scale(Q x) {
647  return (*this)*=x;
648  }
649 
651 
654  template <typename Q>
655  typename IsSupported<TensorTypeData<Q>,Tensor<T>&>::type
656  operator+=(const Q& x) {
657  UNARY_OPTIMIZED_ITERATOR(T, (*this), *_p0 += x);
658  return *this;
659  }
660 
662 
665  template <typename Q>
666  typename IsSupported<TensorTypeData<Q>,Tensor<T>&>::type
667  operator-=(const Q& x) {
668  UNARY_OPTIMIZED_ITERATOR(T, (*this), *_p0 -= x);
669  return *this;
670  }
671 
672 
674 
676  Tensor<T>& conj() {
677  UNARY_OPTIMIZED_ITERATOR(T, (*this), *_p0 = conditional_conj(*_p0));
678  return *this;
679  }
680 
682 
684  Tensor<T>& fillrandom() {
685  if (iscontiguous()) {
686  madness::RandomVector<T>(size(), ptr());
687  }
688  else {
689  UNARY_OPTIMIZED_ITERATOR(T,(*this), *_p0 = madness::RandomValue<T>());
690  }
691  return *this;
692  }
693 
695 
708  Tensor<T>& fillindex() {
709  long count = 0;
710  UNARY_UNOPTIMIZED_ITERATOR(T,(*this), *_p0 = count++); // Fusedim would be OK
711  return *this;
712  }
713 
715 
718  Tensor<T>& screen(double x) {
719  T zero = 0;
720  UNARY_OPTIMIZED_ITERATOR(T,(*this), if (std::abs(*_p0)<x) *_p0=zero);
721  return *this;
722  }
723 
724 
726 
728  static bool bounds_checking() {
729 #ifdef TENSOR_BOUNDS_CHECKING
730  return true;
731 #else
732  return false;
733 #endif
734  }
735 
737 
740  T& operator[](long i) {
741 #ifdef TENSOR_BOUNDS_CHECKING
742  TENSOR_ASSERT(i>=0 && i<_dim[0],"1d bounds check failed dim=0",i,this);
743 #endif
744  return _p[i*_stride[0]];
745  }
746 
748 
751  const T& operator[](long i) const {
752 #ifdef TENSOR_BOUNDS_CHECKING
753  TENSOR_ASSERT(i>=0 && i<_dim[0],"1d bounds check failed dim=0",i,this);
754 #endif
755  return _p[i*_stride[0]];
756  }
757 
759 
762  T& operator()(long i) {
763 #ifdef TENSOR_BOUNDS_CHECKING
764  TENSOR_ASSERT(i>=0 && i<_dim[0],"1d bounds check failed dim=0",i,this);
765 #endif
766  return _p[i*_stride[0]];
767  }
768 
770 
773  const T& operator()(long i) const {
774 #ifdef TENSOR_BOUNDS_CHECKING
775  TENSOR_ASSERT(i>=0 && i<_dim[0],"1d bounds check failed dim=0",i,this);
776 #endif
777  return _p[i*_stride[0]];
778  }
779 
781 
785  T& operator()(long i, long j) {
786 #ifdef TENSOR_BOUNDS_CHECKING
787  TENSOR_ASSERT(i>=0 && i<_dim[0],"2d bounds check failed dim=0",i,this);
788  TENSOR_ASSERT(j>=0 && j<_dim[1],"2d bounds check failed dim=1",j,this);
789 #endif
790  return _p[i*_stride[0]+j*_stride[1]];
791  }
792 
794 
798  const T& operator()(long i, long j) const {
799 #ifdef TENSOR_BOUNDS_CHECKING
800  TENSOR_ASSERT(i>=0 && i<_dim[0],"2d bounds check failed dim=0",i,this);
801  TENSOR_ASSERT(j>=0 && j<_dim[1],"2d bounds check failed dim=1",j,this);
802 #endif
803  return _p[i*_stride[0]+j*_stride[1]];
804  }
805 
807 
812  T& operator()(long i, long j, long k) {
813 #ifdef TENSOR_BOUNDS_CHECKING
814  TENSOR_ASSERT(i>=0 && i<_dim[0],"3d bounds check failed dim=0",i,this);
815  TENSOR_ASSERT(j>=0 && j<_dim[1],"3d bounds check failed dim=1",j,this);
816  TENSOR_ASSERT(k>=0 && k<_dim[2],"3d bounds check failed dim=2",k,this);
817 #endif
818  return _p[i*_stride[0]+j*_stride[1]+k*_stride[2]];
819  }
820 
822 
827  const T& operator()(long i, long j, long k) const {
828 #ifdef TENSOR_BOUNDS_CHECKING
829  TENSOR_ASSERT(i>=0 && i<_dim[0],"3d bounds check failed dim=0",i,this);
830  TENSOR_ASSERT(j>=0 && j<_dim[1],"3d bounds check failed dim=1",j,this);
831  TENSOR_ASSERT(k>=0 && k<_dim[2],"3d bounds check failed dim=2",k,this);
832 #endif
833  return _p[i*_stride[0]+j*_stride[1]+k*_stride[2]];
834  }
835 
837 
843  T& operator()(long i, long j, long k, long l) {
844 #ifdef TENSOR_BOUNDS_CHECKING
845  TENSOR_ASSERT(i>=0 && i<_dim[0],"4d bounds check failed dim=0",i,this);
846  TENSOR_ASSERT(j>=0 && j<_dim[1],"4d bounds check failed dim=1",j,this);
847  TENSOR_ASSERT(k>=0 && k<_dim[2],"4d bounds check failed dim=2",k,this);
848  TENSOR_ASSERT(l>=0 && l<_dim[3],"4d bounds check failed dim=3",l,this);
849 #endif
850  return _p[i*_stride[0]+j*_stride[1]+k*_stride[2]+
851  l*_stride[3]];
852  }
853 
855 
861  const T& operator()(long i, long j, long k, long l) const {
862 #ifdef TENSOR_BOUNDS_CHECKING
863  TENSOR_ASSERT(i>=0 && i<_dim[0],"4d bounds check failed dim=0",i,this);
864  TENSOR_ASSERT(j>=0 && j<_dim[1],"4d bounds check failed dim=1",j,this);
865  TENSOR_ASSERT(k>=0 && k<_dim[2],"4d bounds check failed dim=2",k,this);
866  TENSOR_ASSERT(l>=0 && l<_dim[3],"4d bounds check failed dim=3",l,this);
867 #endif
868  return _p[i*_stride[0]+j*_stride[1]+k*_stride[2]+
869  l*_stride[3]];
870  }
871 
873 
880  T& operator()(long i, long j, long k, long l, long m) {
881 #ifdef TENSOR_BOUNDS_CHECKING
882  TENSOR_ASSERT(i>=0 && i<_dim[0],"5d bounds check failed dim=0",i,this);
883  TENSOR_ASSERT(j>=0 && j<_dim[1],"5d bounds check failed dim=1",j,this);
884  TENSOR_ASSERT(k>=0 && k<_dim[2],"5d bounds check failed dim=2",k,this);
885  TENSOR_ASSERT(l>=0 && l<_dim[3],"5d bounds check failed dim=3",l,this);
886  TENSOR_ASSERT(m>=0 && m<_dim[4],"5d bounds check failed dim=4",m,this);
887 #endif
888  return _p[i*_stride[0]+j*_stride[1]+k*_stride[2]+
889  l*_stride[3]+m*_stride[4]];
890  }
891 
893 
900  const T& operator()(long i, long j, long k, long l, long m) const {
901 #ifdef TENSOR_BOUNDS_CHECKING
902  TENSOR_ASSERT(i>=0 && i<_dim[0],"5d bounds check failed dim=0",i,this);
903  TENSOR_ASSERT(j>=0 && j<_dim[1],"5d bounds check failed dim=1",j,this);
904  TENSOR_ASSERT(k>=0 && k<_dim[2],"5d bounds check failed dim=2",k,this);
905  TENSOR_ASSERT(l>=0 && l<_dim[3],"5d bounds check failed dim=3",l,this);
906  TENSOR_ASSERT(m>=0 && m<_dim[4],"5d bounds check failed dim=4",m,this);
907 #endif
908  return _p[i*_stride[0]+j*_stride[1]+k*_stride[2]+
909  l*_stride[3]+m*_stride[4]];
910  }
911 
913 
921  T& operator()(long i, long j, long k, long l, long m, long n) {
922 #ifdef TENSOR_BOUNDS_CHECKING
923  TENSOR_ASSERT(i>=0 && i<_dim[0],"6d bounds check failed dim=0",i,this);
924  TENSOR_ASSERT(j>=0 && j<_dim[1],"6d bounds check failed dim=1",j,this);
925  TENSOR_ASSERT(k>=0 && k<_dim[2],"6d bounds check failed dim=2",k,this);
926  TENSOR_ASSERT(l>=0 && l<_dim[3],"6d bounds check failed dim=3",l,this);
927  TENSOR_ASSERT(m>=0 && m<_dim[4],"6d bounds check failed dim=4",m,this);
928  TENSOR_ASSERT(n>=0 && n<_dim[5],"6d bounds check failed dim=5",n,this);
929 #endif
930  return _p[i*_stride[0]+j*_stride[1]+k*_stride[2]+
931  l*_stride[3]+m*_stride[4]+n*_stride[5]];
932  }
933 
935 
943  const T& operator()(long i, long j, long k, long l, long m, long n) const {
944 #ifdef TENSOR_BOUNDS_CHECKING
945  TENSOR_ASSERT(i>=0 && i<_dim[0],"6d bounds check failed dim=0",i,this);
946  TENSOR_ASSERT(j>=0 && j<_dim[1],"6d bounds check failed dim=1",j,this);
947  TENSOR_ASSERT(k>=0 && k<_dim[2],"6d bounds check failed dim=2",k,this);
948  TENSOR_ASSERT(l>=0 && l<_dim[3],"6d bounds check failed dim=3",l,this);
949  TENSOR_ASSERT(m>=0 && m<_dim[4],"6d bounds check failed dim=4",m,this);
950  TENSOR_ASSERT(n>=0 && n<_dim[5],"6d bounds check failed dim=5",n,this);
951 #endif
952  return _p[i*_stride[0]+j*_stride[1]+k*_stride[2]+
953  l*_stride[3]+m*_stride[4]+n*_stride[5]];
954  }
955 
957 
960  T& operator()(const long ind[]) {
961  long offset = 0;
962  for (int d=0; d<_ndim; ++d) {
963  long i = ind[d];
964 #ifdef TENSOR_BOUNDS_CHECKING
965  TENSOR_ASSERT(i>=0 && i<_dim[0],"non-PC general indexing bounds check failed dim=",d,this);
966 #endif
967  offset += i*_stride[d];
968  }
969  return _p[offset];
970  }
971 
973 
976  const T& operator()(const long ind[]) const {
977  long offset = 0;
978  for (int d=0; d<_ndim; ++d) {
979  long i = ind[d];
980 #ifdef TENSOR_BOUNDS_CHECKING
981  TENSOR_ASSERT(i>=0 && i<_dim[0],"non-PC general indexing bounds check failed dim=",d,this);
982 #endif
983  offset += i*_stride[d];
984  }
985  return _p[offset];
986  }
987 
989 
992  T& operator()(const std::vector<long> ind) {
993  TENSOR_ASSERT(ind.size()>=(unsigned int) _ndim,"invalid number of dimensions",ind.size(),this);
994  long index=0;
995  for (long d=0; d<_ndim; ++d) {
996  TENSOR_ASSERT(ind[d]>=0 && ind[d]<_dim[d],"out-of-bounds access",ind[d],this);
997  index += ind[d]*_stride[d];
998  }
999  return _p[index];
1000  }
1001 
1003 
1006  const T& operator()(const std::vector<long> ind) const {
1007  TENSOR_ASSERT(ind.size()>=(unsigned int) _ndim,"invalid number of dimensions",ind.size(),this);
1008  long index=0;
1009  for (long d=0; d<_ndim; ++d) {
1010  TENSOR_ASSERT(ind[d]>=0 && ind[d]<_dim[d],"out-of-bounds access",ind[d],this);
1011  index += ind[d]*_stride[d];
1012  }
1013  return _p[index];
1014  }
1015 
1017 
1020  SliceTensor<T> operator()(const std::vector<Slice>& s) {
1021  TENSOR_ASSERT(s.size()>=(unsigned)(this->ndim()), "invalid number of dimensions",
1022  this->ndim(),this);
1023  return SliceTensor<T>(*this,&(s[0]));
1024  }
1025 
1027 
1030  const Tensor<T> operator()(const std::vector<Slice>& s) const {
1031  TENSOR_ASSERT(s.size()>=(unsigned)(this->ndim()), "invalid number of dimensions",
1032  this->ndim(),this);
1033  return SliceTensor<T>(*this,&(s[0]));
1034  }
1035 
1037 
1039  SliceTensor<T> operator()(const Slice& s0) {
1040  TENSOR_ASSERT(this->ndim()==1,"invalid number of dimensions",
1041  this->ndim(),this);
1042  Slice s[1] = {s0};
1043  return SliceTensor<T>(*this,s);
1044  }
1045 
1047 
1049  const Tensor<T> operator()(const Slice& s0) const {
1050  TENSOR_ASSERT(this->ndim()==1,"invalid number of dimensions",
1051  this->ndim(),this);
1052  Slice s[1] = {s0};
1053  return SliceTensor<T>(*this,s);
1054  }
1055 
1057 
1059  SliceTensor<T> operator()(long i, const Slice& s1) {
1060  TENSOR_ASSERT(this->ndim()==2,"invalid number of dimensions",
1061  this->ndim(),this);
1062  Slice s[2] = {Slice(i,i,0),s1};
1063  return SliceTensor<T>(*this,s);
1064  }
1065 
1067 
1069  const Tensor<T> operator()(long i, const Slice& s1) const {
1070  TENSOR_ASSERT(this->ndim()==2,"invalid number of dimensions",
1071  this->ndim(),this);
1072  Slice s[2] = {Slice(i,i,0),s1};
1073  return SliceTensor<T>(*this,s);
1074  }
1075 
1077 
1079  SliceTensor<T> operator()(const Slice& s0, long j) {
1080  TENSOR_ASSERT(this->ndim()==2,"invalid number of dimensions",
1081  this->ndim(),this);
1082  Slice s[2] = {s0,Slice(j,j,0)};
1083  return SliceTensor<T>(*this,s);
1084  }
1085 
1087 
1089  const Tensor<T> operator()(const Slice& s0, long j) const {
1090  TENSOR_ASSERT(this->ndim()==2,"invalid number of dimensions",
1091  this->ndim(),this);
1092  Slice s[2] = {s0,Slice(j,j,0)};
1093  return SliceTensor<T>(*this,s);
1094  }
1095 
1097 
1099  SliceTensor<T> operator()(const Slice& s0, const Slice& s1) {
1100  TENSOR_ASSERT(this->ndim()==2,"invalid number of dimensions",
1101  this->ndim(),this);
1102  Slice s[2] = {s0,s1};
1103  return SliceTensor<T>(*this,s);
1104  }
1105 
1107 
1109  const Tensor<T> operator()(const Slice& s0, const Slice& s1) const {
1110  TENSOR_ASSERT(this->ndim()==2,"invalid number of dimensions",
1111  this->ndim(),this);
1112  Slice s[2] = {s0,s1};
1113  return SliceTensor<T>(*this,s);
1114  }
1115 
1117 
1119  SliceTensor<T> operator()(const Slice& s0, const Slice& s1, const Slice& s2) {
1120  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1121  this->ndim(),this);
1122  Slice s[3] = {s0,s1,s2};
1123  return SliceTensor<T>(*this,s);
1124  }
1125 
1127 
1129  const Tensor<T> operator()(const Slice& s0, const Slice& s1, const Slice& s2) const {
1130  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1131  this->ndim(),this);
1132  Slice s[3] = {s0,s1,s2};
1133  return SliceTensor<T>(*this,s);
1134  }
1135 
1137 
1139  SliceTensor<T> operator()(long i, const Slice& s1, const Slice& s2) {
1140  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1141  this->ndim(),this);
1142  Slice s[3] = {Slice(i,i,0),s1,s2};
1143  return SliceTensor<T>(*this,s);
1144  }
1145 
1147 
1149  const Tensor<T> operator()(long i, const Slice& s1, const Slice& s2) const {
1150  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1151  this->ndim(),this);
1152  Slice s[3] = {Slice(i,i,0),s1,s2};
1153  return SliceTensor<T>(*this,s);
1154  }
1155 
1157 
1159  SliceTensor<T> operator()(const Slice& s0, long j, const Slice& s2) {
1160  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1161  this->ndim(),this);
1162  Slice s[3] = {s0,Slice(j,j,0),s2};
1163  return SliceTensor<T>(*this,s);
1164  }
1165 
1167 
1169  const Tensor<T> operator()(const Slice& s0, long j, const Slice& s2) const {
1170  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1171  this->ndim(),this);
1172  Slice s[3] = {s0,Slice(j,j,0),s2};
1173  return SliceTensor<T>(*this,s);
1174  }
1175 
1177 
1179  SliceTensor<T> operator()(const Slice& s0, const Slice& s1, long k) {
1180  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1181  this->ndim(),this);
1182  Slice s[3] = {s0,s1,Slice(k,k,0)};
1183  return SliceTensor<T>(*this,s);
1184  }
1185 
1187 
1189  const Tensor<T> operator()(const Slice& s0, const Slice& s1, long k) const {
1190  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1191  this->ndim(),this);
1192  Slice s[3] = {s0,s1,Slice(k,k,0)};
1193  return SliceTensor<T>(*this,s);
1194  }
1195 
1197 
1199  SliceTensor<T> operator()(long i, long j, const Slice& s2) {
1200  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1201  this->ndim(),this);
1202  Slice s[3] = {Slice(i,i,0),Slice(j,j,0),s2};
1203  return SliceTensor<T>(*this,s);
1204  }
1205 
1207 
1209  const Tensor<T> operator()(long i, long j, const Slice& s2) const {
1210  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1211  this->ndim(),this);
1212  Slice s[3] = {Slice(i,i,0),Slice(j,j,0),s2};
1213  return SliceTensor<T>(*this,s);
1214  }
1215 
1217 
1219  SliceTensor<T> operator()(long i, const Slice& s1, long k) {
1220  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1221  this->ndim(),this);
1222  Slice s[3] = {Slice(i,i,0),s1,Slice(k,k,0)};
1223  return SliceTensor<T>(*this,s);
1224  }
1225 
1227 
1229  const Tensor<T> operator()(long i, const Slice& s1, long k) const {
1230  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1231  this->ndim(),this);
1232  Slice s[3] = {Slice(i,i,0),s1,Slice(k,k,0)};
1233  return SliceTensor<T>(*this,s);
1234  }
1235 
1237 
1239  SliceTensor<T> operator()(const Slice& s0, long j, long k) {
1240  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1241  this->ndim(),this);
1242  Slice s[3] = {s0,Slice(j,j,0),Slice(k,k,0)};
1243  return SliceTensor<T>(*this,s);
1244  }
1245 
1247 
1249  const Tensor<T> operator()(const Slice& s0, long j, long k) const {
1250  TENSOR_ASSERT(this->ndim()==3,"invalid number of dimensions",
1251  this->ndim(),this);
1252  Slice s[3] = {s0,Slice(j,j,0),Slice(k,k,0)};
1253  return SliceTensor<T>(*this,s);
1254  }
1255 
1257 
1259  SliceTensor<T> operator()(const Slice& s0, const Slice& s1, const Slice& s2,
1260  const Slice& s3) {
1261  TENSOR_ASSERT(this->ndim()==4,"invalid number of dimensions",
1262  this->ndim(),this);
1263  Slice s[4] = {s0,s1,s2,s3};
1264  return SliceTensor<T>(*this,s);
1265  }
1266 
1268 
1270  const Tensor<T> operator()(const Slice& s0, const Slice& s1, const Slice& s2,
1271  const Slice& s3) const {
1272  TENSOR_ASSERT(this->ndim()==4,"invalid number of dimensions",
1273  this->ndim(),this);
1274  Slice s[4] = {s0,s1,s2,s3};
1275  return SliceTensor<T>(*this,s);
1276  }
1277 
1279 
1281  SliceTensor<T> operator()(const Slice& s0, const Slice& s1, const Slice& s2,
1282  const Slice& s3, const Slice& s4) {
1283  TENSOR_ASSERT(this->ndim()==5,"invalid number of dimensions",
1284  this->ndim(),this);
1285  Slice s[5] = {s0,s1,s2,s3,s4};
1286  return SliceTensor<T>(*this,s);
1287  }
1288 
1290 
1292  const Tensor<T> operator()(const Slice& s0, const Slice& s1, const Slice& s2,
1293  const Slice& s3, const Slice& s4) const {
1294  TENSOR_ASSERT(this->ndim()==5,"invalid number of dimensions",
1295  this->ndim(),this);
1296  Slice s[5] = {s0,s1,s2,s3,s4};
1297  return SliceTensor<T>(*this,s);
1298  }
1299 
1301 
1303  SliceTensor<T> operator()(const Slice& s0, const Slice& s1, const Slice& s2,
1304  const Slice& s3, const Slice& s4, const Slice& s5) {
1305  TENSOR_ASSERT(this->ndim()==6,"invalid number of dimensions",
1306  this->ndim(),this);
1307  Slice s[6] = {s0,s1,s2,s3,s4,s5};
1308  return SliceTensor<T>(*this,s);
1309  }
1310 
1311 
1313 
1315  const Tensor<T> operator()(const Slice& s0, const Slice& s1, const Slice& s2,
1316  const Slice& s3, const Slice& s4, const Slice& s5) const {
1317  TENSOR_ASSERT(this->ndim()==6,"invalid number of dimensions",
1318  this->ndim(),this);
1319  Slice s[6] = {s0,s1,s2,s3,s4,s5};
1320  return SliceTensor<T>(*this,s);
1321  }
1322 
1324 
1328  Tensor<T> reshape(int ndimnew, const long* d) {
1329  Tensor<T> result(*this);
1330  result.reshape_inplace(ndimnew,d);
1331  return result;
1332  }
1333 
1335 
1339  const Tensor<T> reshape(int ndimnew, const long* d) const {
1340  Tensor<T> result(*const_cast<Tensor<T>*>(this));
1341  result.reshape_inplace(ndimnew,d);
1342  return result;
1343  }
1344 
1346 
1349  Tensor<T> reshape(const std::vector<long>& d) {
1350  return reshape(d.size(), d.size() ? &d[0] : 0);
1351  }
1352 
1354 
1357  const Tensor<T> reshape(const std::vector<long>& d) const {
1358  return reshape(d.size(), d.size() ? &d[0] : 0);
1359  }
1360 
1362 
1365  Tensor<T> reshape(long dim0) {
1366  long d[1] = {dim0};
1367  return reshape(1,d);
1368  }
1370 
1373  const Tensor<T> reshape(long dim0) const {
1374  long d[1] = {dim0};
1375  return reshape(1,d);
1376  }
1377 
1379 
1383  Tensor<T> reshape(long dim0, long dim1) {
1384  long d[2] = {dim0,dim1};
1385  return reshape(2,d);
1386  }
1387 
1389 
1393  const Tensor<T> reshape(long dim0, long dim1) const {
1394  long d[2] = {dim0,dim1};
1395  return reshape(2,d);
1396  }
1397 
1399 
1404  Tensor<T> reshape(long dim0, long dim1, long dim2) {
1405  long d[3] = {dim0,dim1,dim2};
1406  return reshape(3,d);
1407  }
1408 
1410 
1415  const Tensor<T> reshape(long dim0, long dim1, long dim2) const {
1416  long d[3] = {dim0,dim1,dim2};
1417  return reshape(3,d);
1418  }
1419 
1421 
1427  Tensor<T> reshape(long dim0, long dim1, long dim2, long dim3) {
1428  long d[4] = {dim0,dim1,dim2,dim3};
1429  return reshape(4,d);
1430  }
1431 
1433 
1439  const Tensor<T> reshape(long dim0, long dim1, long dim2, long dim3) const {
1440  long d[4] = {dim0,dim1,dim2,dim3};
1441  return reshape(4,d);
1442  }
1443 
1445 
1452  Tensor<T> reshape(long dim0, long dim1, long dim2, long dim3, long dim4) {
1453  long d[5] = {dim0,dim1,dim2,dim3,dim4};
1454  return reshape(5,d);
1455  }
1456 
1458 
1465  const Tensor<T> reshape(long dim0, long dim1, long dim2, long dim3, long dim4) const {
1466  long d[5] = {dim0,dim1,dim2,dim3,dim4};
1467  return reshape(5,d);
1468  }
1469 
1471 
1479  Tensor<T> reshape(long dim0, long dim1, long dim2, long dim3, long dim4, long dim5) {
1480  long d[6] = {dim0,dim1,dim2,dim3,dim4,dim5};
1481  return reshape(6,d);
1482  }
1483 
1485 
1493  const Tensor<T> reshape(long dim0, long dim1, long dim2, long dim3, long dim4, long dim5) const {
1494  long d[6] = {dim0,dim1,dim2,dim3,dim4,dim5};
1495  return reshape(6,d);
1496  }
1497 
1499  Tensor<T> flat() {
1500  long d[1] = {_size};
1501  return reshape(1,d);
1502  }
1503 
1505  const Tensor<T> flat() const {
1506  long d[1] = {_size};
1507  return reshape(1,d);
1508  }
1509 
1511 
1513  Tensor<T> splitdim(long i, long dimi0, long dimi1) {
1514  Tensor<T> result(*this);
1515  result.splitdim_inplace(i, dimi0, dimi1);
1516  return result;
1517  }
1518 
1520 
1522  const Tensor<T> splitdim(long i, long dimi0, long dimi1) const {
1523  Tensor<T> result(*const_cast<Tensor<T>*>(this));
1524  result.splitdim_inplace(i, dimi0, dimi1);
1525  return result;
1526  }
1527 
1529 
1531  Tensor<T> fusedim(long i) {
1532  Tensor<T> result(*this);
1533  result.fusedim_inplace(i);
1534  return result;
1535  }
1536 
1538 
1540  const Tensor<T> fusedim(long i) const {
1541  Tensor<T> result(*const_cast<Tensor<T>*>(this));
1542  result.fusedim_inplace(i);
1543  return result;
1544  }
1545 
1547 
1549  Tensor<T> swapdim(long idim, long jdim) {
1550  Tensor<T> result(*this);
1551  result.swapdim_inplace(idim, jdim);
1552  return result;
1553  }
1554 
1556 
1558  const Tensor<T> swapdim(long idim, long jdim) const {
1559  Tensor<T> result(*const_cast<Tensor<T>*>(this));
1560  result.swapdim_inplace(idim, jdim);
1561  return result;
1562  }
1563 
1565 
1568  Tensor<T> mapdim(const std::vector<long>& map) {
1569  Tensor<T> result(*this);
1570  result.mapdim_inplace(map);
1571  return result;
1572  }
1573 
1575 
1577  const Tensor<T> mapdim(const std::vector<long>& map) const {
1578  Tensor<T> result(*const_cast<Tensor<T>*>(this));
1579  result.mapdim_inplace(map);
1580  return result;
1581  }
1582 
1583 
1585  Tensor<T> cycledim(long nshift, long start, long end) {
1586  Tensor<T> result(*this);
1587  result.cycledim_inplace(nshift, start, end);
1588  return result;
1589  }
1590 
1591 
1593  const Tensor<T> cycledim(long nshift, long start, long end) const {
1594  Tensor<T> result(*const_cast<Tensor<T>*>(this));
1595  result.cycledim_inplace(nshift, start, end);
1596  return result;
1597  }
1598 
1599 
1601  template <class Q> bool conforms(const Tensor<Q>& t) const {
1602  return BaseTensor::conforms(&t);
1603  }
1604 
1606  T sum() const {
1607  T result = 0;
1608  UNARY_OPTIMIZED_ITERATOR(const T,(*this),result += *_p0);
1609  return result;
1610  }
1611 
1613  T sumsq() const {
1614  T result = 0;
1615  UNARY_OPTIMIZED_ITERATOR(const T,(*this),result += (*_p0) * (*_p0));
1616  return result;
1617  }
1618 
1620  T product() const {
1621  T result = 1;
1622  UNARY_OPTIMIZED_ITERATOR(const T,(*this),result *= *_p0);
1623  return result;
1624  }
1625 
1627  T min(long* ind=0) const {
1628  T result = *(this->_p);
1629  if (ind) {
1630  for (long i=0; i<_ndim; ++i) ind[i]=0;
1631  long nd = _ndim-1;
1632  UNARY_UNOPTIMIZED_ITERATOR(const T,(*this),
1633  if (result > *_p0) {
1634  result = *_p0;
1635  for (long i=0; i<nd; ++i) ind[i]=iter.ind[i];
1636  ind[nd] = _j;
1637  }
1638  );
1639  }
1640  else {
1641  UNARY_OPTIMIZED_ITERATOR(const T,(*this),result=std::min<T>(result,*_p0));
1642  }
1643  return result;
1644  }
1645 
1647  T max(long* ind=0) const {
1648  T result = *(this->_p);
1649  if (ind) {
1650  for (long i=0; i<_ndim; ++i) ind[i]=0;
1651  long nd = _ndim-1;
1652  UNARY_UNOPTIMIZED_ITERATOR(const T,(*this),
1653  if (result < *_p0) {
1654  result = *_p0;
1655  for (long i=0; i<nd; ++i) ind[i]=iter.ind[i];
1656  ind[nd] = _j;
1657  }
1658  );
1659  }
1660  else {
1661  UNARY_OPTIMIZED_ITERATOR(const T,(*this),result=std::max<T>(result,*_p0));
1662  }
1663  return result;
1664  }
1665 
1666  // For complex types, this next group returns the appropriate real type
1667  // For real types, the same type as T is returned (type_data.h)
1668 
1670  float_scalar_type normf() const {
1671  float_scalar_type result = 0;
1672  UNARY_OPTIMIZED_ITERATOR(const T,(*this),result += ::madness::detail::mynorm(*_p0));
1673  return (float_scalar_type) std::sqrt(result);
1674  }
1675 
1677  scalar_type absmin(long *ind = 0) const {
1678  scalar_type result = std::abs(*(this->_p));
1679  if (ind) {
1680  for (long i=0; i<_ndim; ++i) ind[i]=0;
1681  long nd = _ndim-1;
1682  UNARY_UNOPTIMIZED_ITERATOR(const T,(*this),
1683  scalar_type absval = std::abs(*_p0);
1684  if (result > absval) {
1685  result = absval;
1686  for (long i=0; i<nd; ++i) ind[i]=iter.ind[i];
1687  ind[nd] = _j;
1688  }
1689  );
1690  }
1691  else {
1692  UNARY_OPTIMIZED_ITERATOR(const T,(*this),result=std::min<scalar_type>(result,std::abs(*_p0)));
1693  }
1694  return result;
1695  }
1696 
1698  scalar_type absmax(long *ind = 0) const {
1699  scalar_type result = std::abs(*(this->_p));
1700  if (ind) {
1701  for (long i=0; i<_ndim; ++i) ind[i]=0;
1702  long nd = _ndim-1;
1703  UNARY_UNOPTIMIZED_ITERATOR(T,(*this),
1704  scalar_type absval = std::abs(*_p0);
1705  if (result < absval) {
1706  result = absval;
1707  for (long i=0; i<nd; ++i) ind[i]=iter.ind[i];
1708  ind[nd] = _j;
1709  }
1710  );
1711  }
1712  else {
1713  UNARY_OPTIMIZED_ITERATOR(const T,(*this),result=std::max<scalar_type>(result,std::abs(*_p0)));
1714  }
1715  return result;
1716  }
1717 
1718 
1720  T trace(const Tensor<T>& t) const {
1721  T result = 0;
1722  BINARY_OPTIMIZED_ITERATOR(const T,(*this),const T,t,result += (*_p0)*(*_p1));
1723  return result;
1724  }
1725 
1727  template <class Q>
1728  TENSOR_RESULT_TYPE(T,Q) trace_conj(const Tensor<Q>& t) const {
1729  TENSOR_RESULT_TYPE(T,Q) result = 0;
1730  BINARY_OPTIMIZED_ITERATOR(const T,(*this),const Q,t,result += conditional_conj(*_p0)*(*_p1));
1731  return result;
1732  }
1733 
1735  template <typename opT>
1736  Tensor<T>& unaryop(opT& op) {
1737  UNARY_OPTIMIZED_ITERATOR(T,(*this),*_p0=op(*_p0));
1738  return *this;
1739  }
1740 
1742  Tensor<T>& emul(const Tensor<T>& t) {
1743  BINARY_OPTIMIZED_ITERATOR(T,(*this),const T,t,*_p0 *= *_p1);
1744  return *this;
1745  }
1746 
1748  Tensor<T>& gaxpy(T alpha, const Tensor<T>& t, T beta) {
1749  if (iscontiguous() && t.iscontiguous()) {
1750  T* restrict a = ptr();
1751  const T* restrict b = t.ptr();
1752  if (alpha == T(1.0)) {
1753  for (long i=0; i<_size; ++i) a[i] += b[i]*beta;
1754  }
1755  else {
1756  for (long i=0; i<_size; ++i) a[i] = a[i]*alpha + b[i]*beta;
1757  }
1758  }
1759  else {
1760  //BINARYITERATOR(T,(*this),T,t, (*_p0) = alpha*(*_p0) + beta*(*_p1));
1761  BINARY_OPTIMIZED_ITERATOR(T,(*this),const T,t, (*_p0) = alpha*(*_p0) + beta*(*_p1));
1762  //ITERATOR((*this),(*this)(IND) = alpha*(*this)(IND) + beta*t(IND));
1763  }
1764  return *this;
1765  }
1766 
1768  T* ptr() {
1769  return _p;
1770  }
1771 
1773  const T* ptr() const {
1774  return _p;
1775  }
1776 
1778  BaseTensor* base() {
1779  return static_cast<BaseTensor*>(this);
1780  }
1781 
1783  const BaseTensor* base() const {
1784  return static_cast<BaseTensor*>(this);
1785  }
1786 
1788  TensorIterator<T> unary_iterator(long iterlevel=0,
1789  bool optimize=true,
1790  bool fusedim=true,
1791  long jdim=default_jdim) const {
1792  return TensorIterator<T>(this,(const Tensor<T>*) 0, (const Tensor<T>*) 0,
1793  iterlevel, optimize, fusedim, jdim);
1794  }
1795 
1797  template <class Q>
1798  TensorIterator<T,Q> binary_iterator(const Tensor<Q>& q,
1799  long iterlevel=0,
1800  bool optimize=true,
1801  bool fusedim=true,
1802  long jdim=default_jdim) const {
1803  return TensorIterator<T,Q>(this,&q,(const Tensor<T>*) 0,
1804  iterlevel, optimize, fusedim, jdim);
1805  }
1806 
1808  template <class Q, class R>
1809  TensorIterator<T,Q,R> ternary_iterator(const Tensor<Q>& q,
1810  const Tensor<R>& r,
1811  long iterlevel=0,
1812  bool optimize=true,
1813  bool fusedim=true,
1814  long jdim=default_jdim) const {
1815  return TensorIterator<T,Q,R>(this,&q,&r,
1816  iterlevel, optimize, fusedim, jdim);
1817  }
1818 
1820  const TensorIterator<T>& end() const {
1821  static TensorIterator<T> theend(0,0,0,0,0,0);
1822  return theend;
1823  }
1824 
1825  virtual ~Tensor() {}
1826 
1828  void clear() {deallocate();}
1829 
1830  bool has_data() const {return size()!=0;};
1831 
1832  };
1833 
1834  template <class T>
1835  std::ostream& operator << (std::ostream& out, const Tensor<T>& t);
1836 
1837 
1838  namespace archive {
1840  template <class Archive, typename T>
1841  struct ArchiveStoreImpl< Archive, Tensor<T> > {
1842  static void store(const Archive& s, const Tensor<T>& t) {
1843  if (t.iscontiguous()) {
1844  s & t.size() & t.id();
1845  if (t.size()) s & t.ndim() & wrap(t.dims(),TENSOR_MAXDIM) & wrap(t.ptr(),t.size());
1846  }
1847  else {
1848  s & copy(t);
1849  }
1850  };
1851  };
1852 
1853 
1855  template <class Archive, typename T>
1856  struct ArchiveLoadImpl< Archive, Tensor<T> > {
1857  static void load(const Archive& s, Tensor<T>& t) {
1858  long sz = 0l, id = 0l;
1859  s & sz & id;
1860  if (id != t.id()) throw "type mismatch deserializing a tensor";
1861  if (sz) {
1862  long _ndim = 0l, _dim[TENSOR_MAXDIM];
1863  s & _ndim & wrap(_dim,TENSOR_MAXDIM);
1864  t = Tensor<T>(_ndim, _dim, false);
1865  if (sz != t.size()) throw "size mismatch deserializing a tensor";
1866  s & wrap(t.ptr(), t.size());
1867  }
1868  else {
1869  t = Tensor<T>();
1870  }
1871  };
1872  };
1873 
1874  }
1875 
1877 
1879  template <typename T, typename Q>
1880  typename IsSupported < TensorTypeData<Q>, Tensor<T> >::type
1881  operator+(Q x, const Tensor<T>& t) {
1882  return t+x;
1883  }
1884 
1886 
1888  template <typename T, typename Q>
1889  typename IsSupported < TensorTypeData<Q>, Tensor<T> >::type
1890  operator*(const Q& x, const Tensor<T>& t) {
1891  return t*x;
1892  }
1893 
1895 
1897  template <typename T, typename Q>
1898  typename IsSupported < TensorTypeData<Q>, Tensor<T> >::type
1899  operator-(Q x, const Tensor<T>& t) {
1900  return (-t)+=x;
1901  }
1902 
1904 
1907  template <class T> Tensor<T> copy(const Tensor<T>& t) {
1908  if (t.size()) {
1909  Tensor<T> result = Tensor<T>(t.ndim(),t.dims(),false);
1910  BINARY_OPTIMIZED_ITERATOR(T, result, const T, t, *_p0 = *_p1);
1911  return result;
1912  }
1913  else {
1914  return Tensor<T>();
1915  }
1916  }
1917 
1919 
1928  template <class T, class Q>
1929  Tensor<TENSOR_RESULT_TYPE(T,Q)> transform_dir(const Tensor<T>& t, const Tensor<Q>& c, int axis) {
1930  if (axis == 0) {
1931  return inner(c,t,0,axis);
1932  }
1933  else if (axis == t.ndim()-1) {
1934  return inner(t,c,axis,0);
1935  }
1936  else {
1937  return copy(inner(t,c,axis,0).cycledim(1,axis, -1)); // Copy to make contiguous
1938  }
1939  }
1940 
1942 
1944  template <class T>
1945  Tensor<T> transpose(const Tensor<T>& t) {
1946  TENSOR_ASSERT(t.ndim() == 2, "transpose requires a matrix", t.ndim(), &t);
1947  return copy(t.swapdim(0,1));
1948  }
1949 
1951 
1953  template <class T>
1954  Tensor<T> conj_transpose(const Tensor<T>& t) {
1955  TENSOR_ASSERT(t.ndim() == 2, "conj_transpose requires a matrix", t.ndim(), &t);
1956  return conj(t.swapdim(0,1));
1957  }
1958 
1960 
1968  template <class T> class SliceTensor : public Tensor<T> {
1969  private:
1970  SliceTensor<T>();
1971 
1972  public:
1973  SliceTensor(const Tensor<T>& t, const Slice s[])
1974  : Tensor<T>(const_cast<Tensor<T>&>(t))
1975  {
1976  // C++ standard says class derived from parameterized base class cannot
1977  // directly access the base class elements ... must explicitly reference.
1978 
1979  long nd = 0, size=1;
1980  for (long i=0; i<t._ndim; ++i) {
1981  long start=s[i].start, end=s[i].end, step=s[i].step;
1982  //std::printf("%ld input start=%ld end=%ld step=%ld\n",
1983  //i, start, end, step);
1984  if (start < 0) start += this->_dim[i];
1985  if (end < 0) end += this->_dim[i];
1986  long len = end-start+1;
1987  if (step) len /= step; // Rounds len towards zero
1988 
1989  // if input length is not exact multiple of step, round end towards start
1990  // for the same behaviour of for (i=start; i<=end; i+=step);
1991  end = start + (len-1)*step;
1992 
1993  //std::printf("%ld munged start=%ld end=%ld step=%ld len=%ld _dim=%ld\n",
1994  // i, start, end, step, len, this->_dim[i]);
1995 
1996  TENSOR_ASSERT(start>=0 && start<this->_dim[i],"slice start invalid",start,this);
1997  TENSOR_ASSERT(end>=0 && end<this->_dim[i],"slice end invalid",end,this);
1998  TENSOR_ASSERT(len>0,"slice length must be non-zero",len,this);
1999 
2000  this->_p += start * t._stride[i];
2001 
2002  if (step) {
2003  size *= len;
2004  this->_dim[nd] = len;
2005  this->_stride[nd] = step * t._stride[i];
2006  ++nd;
2007  }
2008  }
2009  //For Python interface need to be able to return a scalar inside a tensor with nd=0
2010  //TENSOR_ASSERT(nd>0,"slicing produced a scalar, but cannot return one",nd,this);
2011  for (long i=nd; i<TENSOR_MAXDIM; ++i) { // So can iterate over missing dimensions
2012  this->_dim[i] = 1;
2013  this->_stride[i] = 0;
2014  }
2015 
2016  this->_ndim = nd;
2017  this->_size = size;
2018  }
2019 
2020  SliceTensor<T>& operator=(const SliceTensor<T>& t) {
2021  BINARY_OPTIMIZED_ITERATOR(T, (*this), const T, t, *_p0 = (T)(*_p1));
2022  return *this;
2023  }
2024 
2025  template <class Q>
2026  SliceTensor<T>& operator=(const SliceTensor<Q>& t) {
2027  BINARY_OPTIMIZED_ITERATOR(T, (*this), const Q, t, *_p0 = (T)(*_p1));
2028  return *this;
2029  }
2030 
2031  SliceTensor<T>& operator=(const Tensor<T>& t) {
2032  BINARY_OPTIMIZED_ITERATOR(T, (*this), const T, t, *_p0 = (T)(*_p1));
2033  return *this;
2034  }
2035 
2036  template <class Q>
2037  SliceTensor<T>& operator=(const Tensor<Q>& t) {
2038  BINARY_OPTIMIZED_ITERATOR(T, (*this), const Q, t, *_p0 = (T)(*_p1));
2039  return *this;
2040  }
2041 
2042  SliceTensor<T>& operator=(const T& t) {
2043  UNARY_OPTIMIZED_ITERATOR(T, (*this), *_p0 = t);
2044  return *this;
2045  }
2046 
2047  virtual ~SliceTensor() {}; // Tensor<T> destructor does enough
2048  };
2049 
2050 
2051  // Specializations for complex types
2052  template<> float_complex Tensor<float_complex>::min(long* ind) const ;
2053  template<> double_complex Tensor<double_complex>::min(long* ind) const ;
2054  template<> float_complex Tensor<float_complex>::max(long* ind) const ;
2055  template<> double_complex Tensor<double_complex>::max(long* ind) const ;
2056 
2057  // Stream stuff
2058 
2060 
2062  template <class T>
2063  std::ostream& operator << (std::ostream& s, const Tensor<T>& t) {
2064  if (t.size() == 0) {
2065  s << "[empty tensor]\n";
2066  return s;
2067  }
2068 
2069  long maxdim = 0;
2070  long index_width = 0;
2071  for (int i = 0; i<(t.ndim()-1); ++i) {
2072  if (maxdim < t.dim(i)) maxdim = t.dim(i);
2073  }
2074  if (maxdim < 10)
2075  index_width = 1;
2076  else if (maxdim < 100)
2077  index_width = 2;
2078  else if (maxdim < 1000)
2079  index_width = 3;
2080  else if (maxdim < 10000)
2081  index_width = 4;
2082  else
2083  index_width = 6;
2084 
2085  std::ios::fmtflags oldflags = s.setf(std::ios::scientific);
2086  long oldprec = s.precision();
2087  long oldwidth = s.width();
2088 
2089  // C++ formatted IO is worse than Fortran !!
2090  for (TensorIterator<T> iter=t.unary_iterator(1,false,false); iter!=t.end(); ++iter) {
2091  const T* p = iter._p0;
2092  long inc = iter._s0;
2093  long dimj = iter.dimj;
2094  s.unsetf(std::ios::scientific);
2095  s << '[';
2096  for (long i=0; i<iter.ndim; ++i) {
2097  s.width(index_width);
2098  s << iter.ind[i];
2099  if (i != iter.ndim) s << ",";
2100  }
2101  s << "*]";
2102 //flo s.setf(std::ios::scientific);
2103  s.setf(std::ios::fixed);
2104  for (long j=0; j<dimj; ++j, p+=inc) {
2105 //flo s.precision(4);
2106  s.precision(8);
2107  s.width(12);
2108  s << *p;
2109  }
2110  s.unsetf(std::ios::scientific);
2111  s << std::endl;
2112  }
2113  s.setf(oldflags,std::ios::floatfield);
2114  s.precision(oldprec);
2115  s.width(oldwidth);
2116 
2117  return s;
2118  }
2119 
2120 
2122 
2124  template <class T>
2125  Tensor<T> outer(const Tensor<T>& left, const Tensor<T>& right) {
2126  long nd = left.ndim() + right.ndim();
2127  TENSOR_ASSERT(nd <= TENSOR_MAXDIM,"too many dimensions in result",
2128  nd,0);
2129  long d[TENSOR_MAXDIM];
2130  for (long i=0; i<left.ndim(); ++i) d[i] = left.dim(i);
2131  for (long i=0; i<right.ndim(); ++i) d[i+left.ndim()] = right.dim(i);
2132  Tensor<T> result(nd,d,false);
2133  T* ptr = result.ptr();
2134 
2135  TensorIterator<T> iter=right.unary_iterator(1,false,true);
2136  for (TensorIterator<T> p=left.unary_iterator(); p!=left.end(); ++p) {
2137  T val1 = *p;
2138  // Cannot reorder dimensions, but can fuse contiguous dimensions
2139  for (iter.reset(); iter._p0; ++iter) {
2140  long dimj = iter.dimj;
2141  T* _p0 = iter._p0;
2142  long Tstride = iter._s0;
2143  for (long _j=0; _j<dimj; ++_j, _p0+=Tstride) {
2144  *ptr++ = val1 * (*_p0);
2145  }
2146  }
2147  }
2148 
2149  return result;
2150  }
2151 
2152 
2154 
2161  template <class T, class Q>
2162  Tensor<TENSOR_RESULT_TYPE(T,Q)> inner(const Tensor<T>& left, const Tensor<Q>& right,
2163  long k0=-1, long k1=0) {
2164  if (k0 < 0) k0 += left.ndim();
2165  if (k1 < 0) k1 += right.ndim();
2166  long nd = left.ndim() + right.ndim() - 2;
2167  TENSOR_ASSERT(nd!=0, "result is a scalar but cannot return one ... use dot",
2168  nd, &left);
2169  TENSOR_ASSERT(left.dim(k0) == right.dim(k1),"common index must be same length",
2170  right.dim(k1), &left);
2171 
2172  TENSOR_ASSERT(nd > 0 && nd <= TENSOR_MAXDIM,
2173  "invalid number of dimensions in the result", nd,0);
2174 
2175  long d[TENSOR_MAXDIM];
2176 
2177  long base=0;
2178  for (long i=0; i<k0; ++i) d[i] = left.dim(i);
2179  for (long i=k0+1; i<left.ndim(); ++i) d[i-1] = left.dim(i);
2180  base = left.ndim()-1;
2181  for (long i=0; i<k1; ++i) d[i+base] = right.dim(i);
2182  base--;
2183  for (long i=k1+1; i<right.ndim(); ++i) d[i+base] = right.dim(i);
2184 
2185  Tensor<TENSOR_RESULT_TYPE(T,Q)> result(nd,d);
2186 
2187  inner_result(left,right,k0,k1,result);
2188 
2189  return result;
2190  }
2191 
2193 
2203  template <class T, class Q>
2204  void inner_result(const Tensor<T>& left, const Tensor<Q>& right,
2205  long k0, long k1, Tensor< TENSOR_RESULT_TYPE(T,Q) >& result) {
2206 
2207  typedef TENSOR_RESULT_TYPE(T,Q) resultT;
2208  // Need to include explicit optimizations for common special cases
2209  // E.g., contiguous, matrix-matrix, and 3d-tensor*matrix
2210 
2211  resultT* ptr = result.ptr();
2212 
2213  if (k0 < 0) k0 += left.ndim();
2214  if (k1 < 0) k1 += right.ndim();
2215 
2216  if (left.iscontiguous() && right.iscontiguous()) {
2217  if (k0==0 && k1==0) {
2218  // c[i,j] = a[k,i]*b[k,j] ... collapsing extra indices to i & j
2219  long dimk = left.dim(k0);
2220  long dimj = right.stride(0);
2221  long dimi = left.stride(0);
2222  ::mTxm(dimi,dimj,dimk,ptr,left.ptr(),right.ptr());
2223  return;
2224  }
2225  else if (k0==(left.ndim()-1) && k1==(right.ndim()-1)) {
2226  // c[i,j] = a[i,k]*b[j,k] ... collapsing extra indices to i & j
2227  long dimk = left.dim(k0);
2228  long dimi = left.size()/dimk;
2229  long dimj = right.size()/dimk;
2230  ::mxmT(dimi,dimj,dimk,ptr,left.ptr(),right.ptr());
2231  return;
2232  }
2233  else if (k0==0 && k1==(right.ndim()-1)) {
2234  // c[i,j] = a[k,i]*b[j,k] ... collapsing extra indices to i & j
2235  long dimk = left.dim(k0);
2236  long dimi = left.stride(0);
2237  long dimj = right.size()/dimk;
2238  ::mTxmT(dimi,dimj,dimk,ptr,left.ptr(),right.ptr());
2239  return;
2240  }
2241  else if (k0==(left.ndim()-1) && k1==0) {
2242  // c[i,j] = a[i,k]*b[k,j] ... collapsing extra indices to i & j
2243  long dimk = left.dim(k0);
2244  long dimi = left.size()/dimk;
2245  long dimj = right.stride(0);
2246  ::mxm(dimi,dimj,dimk,ptr,left.ptr(),right.ptr());
2247  return;
2248  }
2249  }
2250 
2251  long dimj = left.dim(k0);
2252  TensorIterator<Q> iter1=right.unary_iterator(1,false,false,k1);
2253 
2254  for (TensorIterator<T> iter0=left.unary_iterator(1,false,false,k0);
2255  iter0._p0; ++iter0) {
2256  T* restrict xp0 = iter0._p0;
2257  long s0 = iter0._s0;
2258  for (iter1.reset(); iter1._p0; ++iter1) {
2259  T* restrict p0 = xp0;
2260  Q* restrict p1 = iter1._p0;
2261  long s1 = iter1._s0;
2262  resultT sum = 0;
2263  for (long j=0; j<dimj; ++j,p0+=s0,p1+=s1) {
2264  sum += (*p0) * (*p1);
2265  }
2266  *ptr++ += sum;
2267  }
2268  }
2269  }
2270 
2272 
2285  template <class T, class Q>
2286  Tensor<TENSOR_RESULT_TYPE(T,Q)> transform(const Tensor<T>& t, const Tensor<Q>& c) {
2287  typedef TENSOR_RESULT_TYPE(T,Q) resultT;
2288  TENSOR_ASSERT(c.ndim() == 2,"second argument must be a matrix",c.ndim(),&c);
2289  if (c.dim(0)==c.dim(1) && t.iscontiguous() && c.iscontiguous()) {
2290  Tensor<resultT> result(t.ndim(),t.dims(),false);
2291  Tensor<resultT> work(t.ndim(),t.dims(),false);
2292  return fast_transform(t, c, result, work);
2293  }
2294  else {
2295  Tensor<resultT> result = t;
2296  for (long i=0; i<t.ndim(); ++i) {
2297  result = inner(result,c,0,0);
2298  }
2299  return result;
2300  }
2301  }
2302 
2304 
2313  template <class T, class Q>
2314  Tensor<TENSOR_RESULT_TYPE(T,Q)> general_transform(const Tensor<T>& t, const Tensor<Q> c[]) {
2315  typedef TENSOR_RESULT_TYPE(T,Q) resultT;
2316  Tensor<resultT> result = t;
2317  for (long i=0; i<t.ndim(); ++i) {
2318  result = inner(result,c[i],0,0);
2319  }
2320  return result;
2321  }
2322 
2324 
2350  template <class T, class Q>
2351  Tensor< TENSOR_RESULT_TYPE(T,Q) >& fast_transform(const Tensor<T>& t, const Tensor<Q>& c, Tensor< TENSOR_RESULT_TYPE(T,Q) >& result,
2352  Tensor< TENSOR_RESULT_TYPE(T,Q) >& workspace) {
2353  typedef TENSOR_RESULT_TYPE(T,Q) resultT;
2354  const Q *pc=c.ptr();
2355  resultT *t0=workspace.ptr(), *t1=result.ptr();
2356  if (t.ndim()&1) {
2357  t0 = result.ptr();
2358  t1 = workspace.ptr();
2359  }
2360 
2361  long dimj = c.dim(1);
2362  long dimi = 1;
2363  for (int n=1; n<t.ndim(); ++n) dimi *= dimj;
2364 
2365 #ifdef AVX_MTXMQ_TEST
2366  // The new AVX code is smokin' fast and has no restrictions
2367  mTxmq(dimi, dimj, dimj, t0, t.ptr(), pc);
2368  for (int n=1; n<t.ndim(); ++n) {
2369  mTxmq(dimi, dimj, dimj, t1, t0, pc);
2370  std::swap(t0,t1);
2371  }
2372 #elif HAVE_IBMBGQ
2373  long nij = dimi*dimj;
2374  if (IS_UNALIGNED(pc) || IS_UNALIGNED(t0) || IS_UNALIGNED(t1)) {
2375  for (long i=0; i<nij; ++i) t0[i] = 0.0;
2376  mTxm(dimi, dimj, dimj, t0, t.ptr(), pc);
2377  for (int n=1; n<t.ndim(); ++n) {
2378  for (long i=0; i<nij; ++i) t1[i] = 0.0;
2379  mTxm(dimi, dimj, dimj, t1, t0, pc);
2380  std::swap(t0,t1);
2381  }
2382  }
2383  else {
2384  mTxmq_padding(dimi, dimj, dimj, dimj, t0, t.ptr(), pc);
2385  for (int n=1; n<t.ndim(); ++n) {
2386  mTxmq_padding(dimi, dimj, dimj, dimj, t1, t0, pc);
2387  std::swap(t0,t1);
2388  }
2389  }
2390 #else
2391  long nij = dimi*dimj;
2392  if (IS_ODD(dimi) || IS_ODD(dimj) ||
2393  IS_UNALIGNED(pc) || IS_UNALIGNED(t0) || IS_UNALIGNED(t1)) {
2394  for (long i=0; i<nij; ++i) t0[i] = 0.0;
2395  mTxm(dimi, dimj, dimj, t0, t.ptr(), pc);
2396  for (int n=1; n<t.ndim(); ++n) {
2397  for (long i=0; i<nij; ++i) t1[i] = 0.0;
2398  mTxm(dimi, dimj, dimj, t1, t0, pc);
2399  std::swap(t0,t1);
2400  }
2401  }
2402  else {
2403  mTxmq(dimi, dimj, dimj, t0, t.ptr(), pc);
2404  for (int n=1; n<t.ndim(); ++n) {
2405  mTxmq(dimi, dimj, dimj, t1, t0, pc);
2406  std::swap(t0,t1);
2407  }
2408  }
2409 #endif
2410 
2411  return result;
2412  }
2413 
2415 
2417  template <class T>
2418  Tensor< typename Tensor<T>::scalar_type > abs(const Tensor<T>& t) {
2419  typedef typename Tensor<T>::scalar_type scalar_type;
2420  Tensor<scalar_type> result(t.ndim(),t.dims(),false);
2421  BINARY_OPTIMIZED_ITERATOR(scalar_type,result,const T,t,*_p0 = std::abs(*_p1));
2422  return result;
2423  }
2424 
2426 
2428  template <class T>
2429  Tensor< typename Tensor<T>::scalar_type > arg(const Tensor<T>& t) {
2430  typedef typename Tensor<T>::scalar_type scalar_type;
2431  Tensor<scalar_type> result(t.ndim(),t.dims(),false);
2432  BINARY_OPTIMIZED_ITERATOR(scalar_type,result,T,t,*_p0 = std::arg(*_p1));
2433  return result;
2434  }
2435 
2437 
2439  template <class T>
2440  Tensor< typename Tensor<T>::scalar_type > real(const Tensor<T>& t) {
2441  typedef typename Tensor<T>::scalar_type scalar_type;
2442  Tensor<scalar_type> result(t.ndim(),t.dims(),false);
2443  BINARY_OPTIMIZED_ITERATOR(scalar_type,result,const T,t,*_p0 = std::real(*_p1));
2444  return result;
2445  }
2446 
2448 
2450  template <class T>
2451  Tensor< typename Tensor<T>::scalar_type > imag(const Tensor<T>& t) {
2452  typedef typename Tensor<T>::scalar_type scalar_type;
2453  Tensor<scalar_type> result(t.ndim(),t.dims(),false);
2454  BINARY_OPTIMIZED_ITERATOR(scalar_type,result,const T,t,*_p0 = std::imag(*_p1));
2455  return result;
2456  }
2457 
2459 
2461  template <class T>
2462  Tensor<T> conj(const Tensor<T>& t) {
2463  Tensor<T> result(t.ndim(),t.dims(),false);
2464  BINARY_OPTIMIZED_ITERATOR(T,result,const T,t,*_p0 = std::conj(*_p1));
2465  return result;
2466  }
2467 }
2468 
2469 #endif // MADNESS_TENSOR_TENSOR_H__INCLUDED
long _size
Number of elements in the tensor.
Definition: basetensor.h:93
Function< TENSOR_RESULT_TYPE(L, R), NDIM > operator+(const Function< L, NDIM > &left, const Function< R, NDIM > &right)
Adds two functions with the new result being of type TensorResultType
Definition: mra.h:1759
double norm(const T &t)
Definition: adquad.h:42
BaseTensor()
Definition: basetensor.h:116
Definition: shared_ptr_bits.h:38
#define TENSOR_ASSERT(condition, msg, value, t)
Definition: tensorexcept.h:130
std::complex< double > double_complex
Definition: lineplot.cc:16
double imag(double x)
Definition: complexfun.h:56
Tensor< T > conj_transpose(const Tensor< T > &t)
Returns a new deep copy of the complex conjugate transpose of the input tensor.
Definition: tensor.h:1954
void gaxpy(World &world, Q alpha, std::vector< Function< T, NDIM > > &a, Q beta, const std::vector< Function< R, NDIM > > &b, bool fence=true)
Generalized A*X+Y for vectors of functions -— a[i] = alpha*a[i] + beta*b[i].
Definition: vmra.h:680
TensorType
low rank representations of tensors (see gentensor.h)
Definition: tensor.h:275
Internal use only.
long ndim() const
Returns the number of dimensions in the tensor.
Definition: basetensor.h:144
void inner_result(const Tensor< T > &left, const Tensor< Q > &right, long k0, long k1, Tensor< TENSOR_RESULT_TYPE(T, Q) > &result)
Accumulate inner product into user provided, contiguous, correctly sized result tensor.
Definition: tensor.h:2204
#define TERNARY_OPTIMIZED_ITERATOR(X, x, Y, y, Z, z, exp)
Definition: tensor_macros.h:719
archive_array< T > wrap(const T *, unsigned int)
Factory function to wrap dynamically allocated pointer as typed archive_array.
Definition: archive.h:820
GenTensor< T > outer(const GenTensor< T > &left, const GenTensor< T > &right)
Outer product ... result(i,j,...,p,q,...) = left(i,k,...)*right(p,q,...)
Definition: gentensor.h:230
Declares TensorIterator.
::std::string string
Definition: gtest-port.h:872
Definition: mpreal.h:3066
void mTxmq_padding(long dimi, long dimj, long dimk, long ext_b, cT *c, const aT *a, const bT *b)
Definition: mtxmq.h:74
Interface templates for the archives (serialization)
#define BINARY_OPTIMIZED_ITERATOR(X, x, Y, y, exp)
Definition: tensor_macros.h:701
T * _p0
Definition: tensoriter.h:66
static void store(const Archive &s, const Tensor< T > &t)
Definition: tensor.h:1842
Provides routines for internal use optimized for aligned data.
Tensor< typename Tensor< T >::scalar_type > imag(const Tensor< T > &t)
Return a new tensor holding the imaginary part of each element of t (complex types only) ...
Definition: tensor.h:2451
TENSOR_RESULT_TYPE(T, R) inner(const Function<T
Computes the scalar/inner product between two functions.
Default store of a thingy via serialize(ar,t)
Definition: archive.h:708
const double beta
Definition: gygi_soltion.cc:63
Tensor< typename Tensor< T >::scalar_type > arg(const Tensor< T > &t)
Return a new tensor holding the argument of each element of t (complex types only) ...
Definition: tensor.h:2429
T inner(const vecfunc< T, NDIM > &a, const vecfunc< T, NDIM > &b)
the non-linear solver requires an inner product
Definition: nemo.h:112
void set_dims_and_size(long nd, const long d[])
Definition: basetensor.h:99
#define IS_ODD(n)
Definition: tensor.h:235
static void load(const Archive &s, Tensor< T > &t)
Definition: tensor.h:1857
const T1 &f1 return GTEST_2_TUPLE_() T(f0, f1)
Definition: tensor.h:275
#define max(a, b)
Definition: lda.h:53
void scale(World &world, std::vector< Function< T, NDIM > > &v, const std::vector< Q > &factors, bool fence=true)
Scales inplace a vector of functions by distinct values.
Definition: vmra.h:290
bool conforms(const BaseTensor *t) const
Returns true if this and *t are the same shape and size.
Definition: basetensor.h:159
Function< T, NDIM > copy(const Function< T, NDIM > &f, const std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > &pmap, bool fence=true)
Create a new copy of the function with different distribution and optional fence. ...
Definition: mra.h:1835
const mpreal min(const mpreal &x, const mpreal &y)
Definition: mpreal.h:2675
long _ndim
Number of dimensions (-1=invalid; 0=scalar; >0=tensor)
Definition: basetensor.h:94
Tensor< TENSOR_RESULT_TYPE(T, Q)> transform_dir(const Tensor< T > &t, const Tensor< Q > &c, int axis)
Transforms one dimension of the tensor t by the matrix c, returns new contiguous tensor.
Definition: tensor.h:1929
FLOAT a(int j, FLOAT z)
Definition: y1.cc:86
#define TENSOR_MAXDIM
Definition: tensor_macros.h:194
Default load of a thingy via serialize(ar,t)
Definition: archive.h:718
bool iscontiguous() const
Returns true if the tensor refers to contiguous memory locations.
Definition: basetensor.h:168
#define UNARY_OPTIMIZED_ITERATOR(X, x, exp)
Definition: tensor_macros.h:658
Definition: tensor.h:275
#define UNARY_UNOPTIMIZED_ITERATOR(X, x, exp)
Definition: tensor_macros.h:678
tensorT sqrt(const tensorT &s, double tol=1e-8)
Computes matrix square root (not used any more?)
Definition: DFcode/moldft.cc:446
void mTxmq(long dimi, long dimj, long dimk, cT *restrict c, const aT *a, const bT *b)
Definition: mtxmq.h:50
long _id
Id from TensorTypeData in type_data.h.
Definition: basetensor.h:95
void mxmT(long dimi, long dimj, long dimk, double *restrict c, const double *restrict a, const double *restrict b)
Matrix * matrix transpose (hand unrolled version)
Definition: mxm.h:215
For real types return value, for complex return conjugate.
Definition: tensor.h:241
Function< T, NDIM > mapdim(const Function< T, NDIM > &f, const std::vector< long > &map, bool fence=true)
Generate a new function by reordering dimensions ... optional fence.
Definition: mra.h:2059
long _stride[TENSOR_MAXDIM]
Increment between elements in each dimension.
Definition: basetensor.h:97
void mxm(long dimi, long dimj, long dimk, double *restrict c, const double *restrict a, const double *restrict b)
Matrix * matrix (hand unrolled version)
Definition: mxm.h:264
void mTxm(long dimi, long dimj, long dimk, double *restrict c, const double *restrict a, const double *restrict b)
Matrix transpose * matrix (hand unrolled version)
Definition: mxm.h:168
const mpreal sum(const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
Definition: mpreal.cc:241
const double m
Definition: gfit.cc:199
double real(double x)
Definition: complexfun.h:52
Tensor< T > conj(const Tensor< T > &t)
Returns a new deep copy of the complex conjugate of the input tensor (complex types only) ...
Definition: tensor.h:2462
void reset()
Definition: shared_ptr_bits.h:459
static Q op(const Q &coeff)
Definition: tensor.h:242
Function< TENSOR_RESULT_TYPE(Q, T), NDIM > operator*(const Function< T, NDIM > &f, const Q alpha)
Returns new function equal to f(x)*alpha.
Definition: mra.h:1553
#define TENSOR_ALIGNMENT
GenTensor< TENSOR_RESULT_TYPE(T, Q)> general_transform(const GenTensor< T > &t, const Tensor< Q > c[])
Transform all dimensions of the tensor t by distinct matrices c.
Definition: gentensor.h:1342
static Q op(const Q &coeff)
Definition: tensor.h:250
double abs(double x)
Definition: complexfun.h:48
std::complex< float > float_complex
Definition: ran.h:40
#define TENSOR_EXCEPTION(msg, value, t)
Definition: tensorexcept.h:126
std::ostream & operator<<(std::ostream &s, const ContractedGaussianShell &c)
Definition: chem/molecularbasis.cc:38
long size() const
Returns the number of elements in the tensor.
Definition: basetensor.h:138
long _s0
Definition: tensoriter.h:71
#define IS_UNALIGNED(p)
Definition: tensor.h:236
long _dim[TENSOR_MAXDIM]
Size of each dimension.
Definition: basetensor.h:96
Function< TENSOR_RESULT_TYPE(L, R), NDIM > operator-(const Function< L, NDIM > &left, const Function< R, NDIM > &right)
Subtracts two functions with the new result being of type TensorResultType
Definition: mra.h:1789
void reset()
Reset the iterator back to the start ...
Definition: tensoriter.h:354
T mynorm(T t)
Definition: tensor.h:262
Implement dummy posix_memalign if it is missing on the system.
Declares BaseTensor.
Tensor< TENSOR_RESULT_TYPE(T, Q) > & fast_transform(const Tensor< T > &t, const Tensor< Q > &c, Tensor< TENSOR_RESULT_TYPE(T, Q) > &result, Tensor< TENSOR_RESULT_TYPE(T, Q) > &workspace)
Restricted but heavily optimized form of transform()
Definition: tensor.h:2351
Tensor< T > transpose(const Tensor< T > &t)
Returns a new deep copy of the transpose of the input tensor.
Definition: tensor.h:1945
Tensor< double > op(const Tensor< double > &x)
Definition: kain.cc:508
Definition: tensoriter.h:61
Q conditional_conj(const Q &coeff)
For real types return value, for complex return conjugate.
Definition: tensor.h:257
long dimj
Definition: tensoriter.h:70
Declares and implements TensorException.
Definition: tensor.h:275
#define restrict
Definition: config.h:403
Tensor< typename Tensor< T >::scalar_type > real(const Tensor< T > &t)
Return a new tensor holding the real part of each element of t (complex types only) ...
Definition: tensor.h:2440
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
const double c
Definition: gfit.cc:200
std::vector< Function< TENSOR_RESULT_TYPE(T, R), NDIM > > transform(World &world, const std::vector< Function< T, NDIM > > &v, const DistributedMatrix< R > &c, bool fence=true)
Definition: chem/SCF.cc:86
FLOAT b(int j, FLOAT z)
Definition: y1.cc:79
void swap(mpfr::mpreal &x, mpfr::mpreal &y)
Definition: mpreal.h:3069
void mTxmT(long dimi, long dimj, long dimk, double *restrict csave, const double *restrict asave, const double *restrict b)
Matrix transpose * matrix transpose (hand tiled and unrolled)
Definition: mxm.h:303
Function< T, NDIM > conj(const Function< T, NDIM > &f, bool fence=true)
Return the complex conjugate of the input function with the same distribution and optional fence...
Definition: mra.h:1879