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 36 #ifndef MADNESS_TENSOR_BASETENSOR_H__INCLUDED 37 #define MADNESS_TENSOR_BASETENSOR_H__INCLUDED 38 39 /// \file basetensor.h 40 /// \brief Declares BaseTensor 41 42 #include <complex> 43 44 typedef std::complex<float> float_complex; 45 typedef std::complex<double> double_complex; 46 47 // These probably have to be included in this order 48 #include <madness/tensor/tensor_macros.h> 49 #include <madness/tensor/type_data.h> 50 #include <madness/tensor/slice.h> 51 #include <madness/tensor/vector_factory.h> 52 53 #include <madness/madness_config.h> 54 #include <madness/tensor/slice.h> 55 #include <madness/tensor/tensor_macros.h> 56 57 #ifdef TENSOR_INSTANCE_COUNT 58 #include <madness/world/atomicint.h> 59 #endif 60 61 namespace madness { 62 /*! 63 \ingroup tensor 64 \brief The base class for tensors defines generic capabilities. 65 66 The base class manages the size, dimension and 67 stride information, and provides operations to manipulate 68 them. 69 70 It also provides methods for type-safe operation on tensors using 71 just the base class pointers. This interface is primarily useful 72 only to the interface to Python, since Python is largely neutral 73 to (and ignorant of) the type. These are still being 74 re-implemented after the big clean up. 75 76 Since the base tensor class is virtual, you cannot have an 77 instance of it. Thus, in addition to methods that return information 78 or perform checks, there are two types of base tensor 79 operations. 80 - Inplace operations change \c *this , and return \c void . 81 - Operations that must return a new tensor return a pointer to a tensor 82 allocated with \c new on the heap. The caller is responsible for 83 eventually freeing the memory using \c delete . 84 */ 85 class BaseTensor { 86 private: 87 #ifdef TENSOR_INSTANCE_COUNT 88 static madness::AtomicInt instance_count; ///< For debug, count total# instances 89 #endif 90 91 protected: 92 93 long _size; ///< Number of elements in the tensor 94 long _ndim; ///< Number of dimensions (-1=invalid; 0=no supported; >0=tensor) 95 long _id; ///< Id from TensorTypeData<T> in type_data.h 96 long _dim[TENSOR_MAXDIM]; ///< Size of each dimension 97 long _stride[TENSOR_MAXDIM]; ///< Increment between elements in each dimension 98 set_dims_and_size(long nd,const long d[])99 void set_dims_and_size(long nd, const long d[]) { 100 _ndim = nd; 101 _size = 1; 102 if (_ndim < 0) _size=0; 103 for (long i=_ndim-1; i>=0; --i) { 104 _dim[i] = d[i]; 105 _stride[i] = _size; 106 _size *= d[i]; 107 } 108 for (long i=std::max(_ndim,0L); i<TENSOR_MAXDIM; ++i) { // So can iterate over missing dimensions 109 _dim[i] = 1; 110 _stride[i] = 0; 111 } 112 } 113 114 public: 115 BaseTensor()116 BaseTensor() : _size(0), _ndim(-1) { 117 #ifdef TENSOR_INSTANCE_COUNT 118 instance_count++; 119 #endif 120 } 121 ~BaseTensor()122 virtual ~BaseTensor() { 123 #ifdef TENSOR_INSTANCE_COUNT 124 instance_count--; 125 #endif 126 } 127 128 /// Returns the count of all current instances of tensors & slice tensors of all types. get_instance_count()129 static inline int get_instance_count() { 130 #ifdef TENSOR_INSTANCE_COUNT 131 return instance_count; 132 #else 133 return 0; 134 #endif 135 } 136 137 /// Returns the number of elements in the tensor size()138 long size() const {return _size;} 139 140 /// Returns the typeid of the tensor (c.f., \c TensorTypeData<T> ) id()141 long id() const {return _id;} 142 143 /// Returns the number of dimensions in the tensor ndim()144 long ndim() const {return _ndim;} 145 146 /// Returns the size of dmension \c i dim(int i)147 long dim(int i) const {return _dim[i];} 148 149 /// Returns the stride associated with dimension \c i stride(int i)150 long stride(int i) const {return _stride[i];} 151 152 /// Returns the array of tensor dimensions dims()153 const long* dims() const {return _dim;} 154 155 /// Returns the array of tensor strides strides()156 const long* strides() const {return _stride;} 157 158 /// Returns true if this and *t are the same shape and size conforms(const BaseTensor * t)159 bool conforms(const BaseTensor *t) const { 160 if (_ndim != t->_ndim) return false; 161 for (long i=0; i<_ndim; ++i) { 162 if (_dim[i] != t->_dim[i]) return false; 163 } 164 return true; 165 } 166 167 /// Returns true if the tensor refers to contiguous memory locations. iscontiguous()168 bool iscontiguous() const { 169 if (_size <= 0) return true; 170 long sz = 1; 171 for (long i=_ndim-1; i>=0; --i) { 172 if (_stride[i] != sz) return false; 173 sz *= _dim[i]; 174 } 175 return true; 176 } 177 178 protected: 179 180 /// Reshapes the tensor inplace 181 void reshape_inplace(const std::vector<long>& d); 182 183 /// Reshapes the tensor inplace 184 void reshape_inplace(int ndimnew, const long* d); 185 186 /// Reshapes the tensor inplace into 1D 187 void flat_inplace(); 188 189 /// Splits dimension \c i 190 void splitdim_inplace(long i, long dimi0, long dimi1); 191 192 /// Fuses dimensions \c i and \c i+1 193 void fusedim_inplace(long i); 194 195 /// Swaps the dimensions 196 void swapdim_inplace(long i, long j); 197 198 /// Cyclic shift of dimensions 199 void cycledim_inplace(long shift, long start, long end); 200 201 /// General permutation of dimensions 202 void mapdim_inplace(const std::vector<long>& map); 203 }; 204 205 } 206 207 #endif // MADNESS_TENSOR_BASETENSOR_H__INCLUDED 208