v0.5.86
Tensor2_symmetric_value.hpp
Go to the documentation of this file.
1 /* A general version, not for pointers. */
2 
3 template <class T, int Tensor_Dim>
5 {
6  T data[(Tensor_Dim*(Tensor_Dim+1))/2];
7 public:
9 
10  /* Tensor_Dim=2 */
11  Tensor2_symmetric(T d00, T d01, T d11)
12  {
14  }
15 
16  /* Tensor_Dim=3 */
17  Tensor2_symmetric(T d00, T d01, T d02, T d11, T d12, T d22)
18  {
19  Tensor2_symmetric_constructor<T,Tensor_Dim>(data,d00,d01,d02,d11,d12,d22);
20  }
21 
22  /* Tensor_Dim=4 */
23  Tensor2_symmetric(T d00, T d01, T d02, T d03, T d11, T d12, T d13, T d22,
24  T d23, T d33)
25  {
27  (data,d00,d01,d02,d03,d11,d12,d13,d22,d23,d33);
28  }
29 
30  /* There are two operator(int,int)'s, one for non-consts that lets you
31  change the value, and one for consts that doesn't. */
32 
33  T & operator()(const int N1, const int N2)
34  {
35 #ifdef FTENSOR_DEBUG
36  if(N1>=Tensor_Dim || N1<0 || N2>=Tensor_Dim || N2<0)
37  {
38  std::stringstream s;
39  s << "Bad index in Tensor2_symmetric<T," << Tensor_Dim
40  << ">.operator(" << N1 << "," << N2 << ")"
41  << std::endl;
42  throw std::runtime_error(s.str());
43  }
44 #endif
45  return N1>N2 ? data[N1+(N2*(2*Tensor_Dim-N2-1))/2]
46  : data[N2+(N1*(2*Tensor_Dim-N1-1))/2];
47  }
48 
49  T operator()(const int N1, const int N2) const
50  {
51 #ifdef FTENSOR_DEBUG
52  if(N1>=Tensor_Dim || N1<0 || N2>=Tensor_Dim || N2<0)
53  {
54  std::stringstream s;
55  s << "Bad index in Tensor2_symmetric<T," << Tensor_Dim
56  << ">.operator(" << N1 << "," << N2 << ") const"
57  << std::endl;
58  throw std::runtime_error(s.str());
59  }
60 #endif
61  return N1>N2 ? data[N1+(N2*(2*Tensor_Dim-N2-1))/2]
62  : data[N2+(N1*(2*Tensor_Dim-N1-1))/2];
63  }
64 
65  /* These operator()'s are the first part in constructing template
66  expressions. They can be used to slice off lower dimensional
67  parts. They are not entirely safe, since you can accidently use a
68  higher dimension than what is really allowed (like Dim=5). */
69 
70  /* This returns a Tensor2_Expr, since the indices are not really
71  symmetric anymore since they cover different dimensions. */
72 
73  template<char i, char j, int Dim0, int Dim1>
76  {
77  return Tensor2_Expr<Tensor2_symmetric<T,Tensor_Dim>,T,Dim0,Dim1,i,j>
78  (*this);
79  }
80 
81  template<char i, char j, int Dim0, int Dim1>
83  operator()(const Index<i,Dim0> , const Index<j,Dim1> ) const
84  {
86  (*this);
87  }
88 
89  /* This returns a Tensor2_symmetric_Expr, since the indices are still
90  symmetric on the lower dimensions. */
91 
92  template<char i, char j, int Dim>
95  {
97  (*this);
98  }
99 
100  template<char i, char j, int Dim>
102  operator()(const Index<i,Dim> , const Index<j,Dim> ) const
103  {
105  T,Dim,i,j>(*this);
106  }
107 
108  /* This is for expressions where a number is used for one slot, and
109  an index for another, yielding a Tensor1_Expr. The non-const
110  versions don't actually create a Tensor2_number_rhs_[01] object.
111  They create a Tensor1_Expr directly, which provides the
112  appropriate indexing operators. The const versions do create a
113  Tensor2_number_[01]. */
114 
115  template<char i, int N, int Dim>
117  T,Dim,i>
119  {
121  TensorExpr;
122  return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
123  }
124 
125  template<char i, int N, int Dim>
127  T,N>,T,Dim,i>
128  operator()(const Index<i,Dim> , const Number<N> &) const
129  {
131  TensorExpr;
132  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
133  }
134 
135  template<char i, int N, int Dim>
137  T,Dim,i>
139  {
141  TensorExpr;
142  return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
143  }
144 
145  template<char i, int N, int Dim>
147  T,N>,T,Dim,i>
148  operator()(const Number<N> &, const Index<i,Dim> ) const
149  {
151  TensorExpr;
152  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
153  }
154 
155  /* Specializations for using actual numbers instead of Number<> */
156 
157  template<char i, int Dim>
159  T>,T,Dim,i>
160  operator()(const Index<i,Dim> , const int N) const
161  {
163  TensorExpr;
164  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N));
165  }
166 
167  template<char i, int Dim>
169  T>,T,Dim,i>
170  operator()(const int N, const Index<i,Dim> ) const
171  {
173  TensorExpr;
174  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N));
175  }
176 
177  /* These two operator()'s return the Tensor2 with internal
178  contractions, yielding a T. I have to specify one for both
179  const and non-const because otherwise the compiler will use the
180  operator() which gives a Tensor2_Expr<>. */
181 
182  template<char i, int Dim>
184  {
185  return internal_contract(Number<Dim>());
186  }
187 
188  template<char i, int Dim>
189  T operator()(const Index<i,Dim> , const Index<i,Dim> ) const
190  {
191  return internal_contract(Number<Dim>());
192  }
193 private:
194  template<int N>
196  {
197  return data[N-1+((N-1)*(2*Tensor_Dim-N))/2]
199  }
200 
202  {
203  return data[0];
204  }
205 };
Tensor2_symmetric(T d00, T d01, T d11)
Tensor2_symmetric(T d00, T d01, T d02, T d03, T d11, T d12, T d13, T d22, T d23, T d33)
Tensor1_Expr< const Tensor2_numeral_0< const Tensor2_symmetric< T, Tensor_Dim >, T >, T, Dim, i > operator()(const int N, const Index< i, Dim >) const
T data[(Tensor_Dim *(Tensor_Dim+1))/2]
Tensor1_Expr< const Tensor2_numeral_1< const Tensor2_symmetric< T, Tensor_Dim >, T >, T, Dim, i > operator()(const Index< i, Dim >, const int N) const
Tensor2_Expr< Tensor2_symmetric< T, Tensor_Dim >, T, Dim0, Dim1, i, j > operator()(const Index< i, Dim0 >, const Index< j, Dim1 >)
Tensor2_symmetric_Expr< Tensor2_symmetric< T, Tensor_Dim >, T, Dim, i, j > operator()(const Index< i, Dim >, const Index< j, Dim >)
Definition: Number.hpp:8
T operator()(const Index< i, Dim >, const Index< i, Dim >) const
Tensor1_Expr< Tensor2_number_rhs_1< Tensor2_symmetric< T, Tensor_Dim >, T, N >, T, Dim, i > operator()(const Index< i, Dim >, const Number< N > &)
Tensor1_Expr< const Tensor2_number_0< const Tensor2_symmetric< T, Tensor_Dim >, T, N >, T, Dim, i > operator()(const Number< N > &, const Index< i, Dim >) const
Definition: Index.hpp:20
T & operator()(const int N1, const int N2)
T internal_contract(const Number< 1 > &)
Tensor1_Expr< const Tensor2_number_1< const Tensor2_symmetric< T, Tensor_Dim >, T, N >, T, Dim, i > operator()(const Index< i, Dim >, const Number< N > &) const
T operator()(const int N1, const int N2) const
Tensor1_Expr< Tensor2_number_rhs_0< Tensor2_symmetric< T, Tensor_Dim >, T, N >, T, Dim, i > operator()(const Number< N > &, const Index< i, Dim >)
T operator()(const Index< i, Dim >, const Index< i, Dim >)
Tensor2_symmetric_Expr< const Tensor2_symmetric< T, Tensor_Dim >, T, Dim, i, j > operator()(const Index< i, Dim >, const Index< j, Dim >) const
Tensor2_symmetric(T d00, T d01, T d02, T d11, T d12, T d22)
const int N
Definition: speed_test.cpp:3
T internal_contract(const Number< N > &)
Tensor2_Expr< const Tensor2_symmetric< T, Tensor_Dim >, T, Dim0, Dim1, i, j > operator()(const Index< i, Dim0 >, const Index< j, Dim1 >) const