v0.7.26
Tensor4_value.hpp
Go to the documentation of this file.
1 /* A general version, not for pointers. */
2 
3 #pragma once
4 
5 #include "Tensor4_contracted.hpp"
6 
7 #include <ostream>
8 
9 #ifdef FTENSOR_DEBUG
10 #include <sstream>
11 #include <stdexcept>
12 #endif
13 
14 namespace FTensor
15 {
16  template <class T, int Tensor_Dim0, int Tensor_Dim1, int Tensor_Dim2,
17  int Tensor_Dim3>
18  class Tensor4
19  {
20  T data[Tensor_Dim0][Tensor_Dim1][Tensor_Dim2][Tensor_Dim3];
21 
22  public:
23  /* Initialization operators */
24  template <class... U> Tensor4(U... d) : data{d...}
25  {
26  static_assert(sizeof...(d) == sizeof(data) / sizeof(T),
27  "Incorrect number of Arguments. Constructor should "
28  "initialize the entire Tensor");
29  }
30 
31  Tensor4() {}
32  /* There are two operator(int,int,int,int)'s, one for non-consts
33  that lets you change the value, and one for consts that
34  doesn't. */
35  T &operator()(const int N1, const int N2, const int N3, const int N4)
36  {
37 #ifdef FTENSOR_DEBUG
38  if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0
39  || N3 >= Tensor_Dim2 || N3 < 0 || N4 >= Tensor_Dim3 || N4 < 0)
40  {
41  std::stringstream s;
42  s << "Bad index in Tensor4<T," << Tensor_Dim0 << "," << Tensor_Dim1
43  << "," << Tensor_Dim2 << "," << Tensor_Dim3 << ">.operator(" << N1
44  << "," << N2 << "," << N3 << "," << N4 << ") const" << std::endl;
45  throw std::out_of_range(s.str());
46  }
47 #endif
48  return data[N1][N2][N3][N4];
49  }
50 
51  T operator()(const int N1, const int N2, const int N3, const int N4) const
52  {
53 #ifdef FTENSOR_DEBUG
54  if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0
55  || N3 >= Tensor_Dim2 || N3 < 0 || N4 >= Tensor_Dim3 || N4 < 0)
56  {
57  std::stringstream s;
58  s << "Bad index in Tensor4<T," << Tensor_Dim0 << "," << Tensor_Dim1
59  << "," << Tensor_Dim2 << "," << Tensor_Dim3 << ">.operator(" << N1
60  << "," << N2 << "," << N3 << "," << N4 << ")" << std::endl;
61  throw std::out_of_range(s.str());
62  }
63 #endif
64  return data[N1][N2][N3][N4];
65  }
66 
67  /* These operator()'s are the first part in constructing template
68  expressions. They can be used to slice off lower dimensional
69  parts. */
70 
71  template <char i, char j, char k, char l, int Dim0, int Dim1, int Dim2,
72  int Dim3>
73  typename std::enable_if<
74  (Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2
75  && Tensor_Dim3 >= Dim3),
77  T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>>::type
78  operator()(const Index<i, Dim0>, const Index<j, Dim1>,
79  const Index<k, Dim2>, const Index<l, Dim3>)
80  {
81  return Tensor4_Expr<
83  Dim0, Dim1, Dim2, Dim3, i, j, k, l>(*this);
84  };
85 
86  template <char i, char j, char k, char l, int Dim0, int Dim1, int Dim2,
87  int Dim3>
88  typename std::enable_if<
89  (Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2
90  && Tensor_Dim3 >= Dim3),
93  T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>>::type
94  operator()(const Index<i, Dim0>, const Index<j, Dim1>,
95  const Index<k, Dim2>, const Index<l, Dim3>) const
96  {
97  return Tensor4_Expr<
99  T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>(*this);
100  };
101 
102  /* These operators are for internal contractions, resulting in a Tensor2.
103  * For example something like A(k,i,k,j) */
104 
105  // (i,j,k,k)
106  template <char i, char j, char k, int Dim0, int Dim1, int Dim23>
107  auto operator()(const Index<i, Dim0>, const Index<j, Dim1>,
108  const Index<k, Dim23>, const Index<k, Dim23>) const
109  {
110  static_assert(Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1
111  && Tensor_Dim2 >= Dim23 && Tensor_Dim3 >= Dim23,
112  "Incompatible indices");
113 
114  using TensorExpr = Tensor4_contracted_23<
116  Dim23>;
117  return Tensor2_Expr<TensorExpr, T, Dim0, Dim1, i, j>(TensorExpr(*this));
118  };
119 
120  // (i,j,k,j)
121  template <char i, char j, char k, int Dim0, int Dim13, int Dim2>
123  const Index<k, Dim2>, const Index<j, Dim13>) const
124  {
125  static_assert(Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim13
126  && Tensor_Dim2 >= Dim2 && Tensor_Dim3 >= Dim13,
127  "Incompatible indices");
128 
129  using TensorExpr = Tensor4_contracted_13<
131  Dim13>;
132  return Tensor2_Expr<TensorExpr, T, Dim0, Dim2, i, k>(TensorExpr(*this));
133  };
134 
135  // (i,j,j,l)
136  template <char i, char j, char l, int Dim0, int Dim12, int Dim3>
138  const Index<j, Dim12>, const Index<l, Dim3>) const
139  {
140  static_assert(Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim12
141  && Tensor_Dim2 >= Dim12 && Tensor_Dim3 >= Dim3,
142  "Incompatible indices");
143 
144  using TensorExpr = Tensor4_contracted_12<
146  Dim12>;
147  return Tensor2_Expr<TensorExpr, T, Dim0, Dim3, i, l>(TensorExpr(*this));
148  };
149 
150  // (i,j,k,i)
151  template <char i, char j, char k, int Dim03, int Dim1, int Dim2>
152  auto operator()(const Index<i, Dim03>, const Index<j, Dim1>,
153  const Index<k, Dim2>, const Index<i, Dim03>) const
154  {
155  static_assert(Tensor_Dim0 >= Dim03 && Tensor_Dim1 >= Dim1
156  && Tensor_Dim2 >= Dim2 && Tensor_Dim3 >= Dim03,
157  "Incompatible indices");
158 
159  using TensorExpr = Tensor4_contracted_03<
161  Dim03>;
162  return Tensor2_Expr<TensorExpr, T, Dim1, Dim2, j, k>(TensorExpr(*this));
163  };
164 
165  // (i,j,i,l)
166  template <char i, char j, char l, int Dim02, int Dim1, int Dim3>
167  auto operator()(const Index<i, Dim02>, const Index<j, Dim1>,
168  const Index<i, Dim02>, const Index<l, Dim3>) const
169  {
170  static_assert(Tensor_Dim0 >= Dim02 && Tensor_Dim1 >= Dim1
171  && Tensor_Dim2 >= Dim02 && Tensor_Dim3 >= Dim3,
172  "Incompatible indices");
173 
174  using TensorExpr = Tensor4_contracted_02<
176  Dim02>;
177  return Tensor2_Expr<TensorExpr, T, Dim1, Dim3, j, l>(TensorExpr(*this));
178  };
179 
180  // (i,i,k,l)
181  template <char i, char k, char l, int Dim01, int Dim2, int Dim3>
183  const Index<k, Dim2>, const Index<l, Dim3>) const
184  {
185  static_assert(Tensor_Dim0 >= Dim01 && Tensor_Dim1 >= Dim01
186  && Tensor_Dim2 >= Dim2 && Tensor_Dim3 >= Dim3,
187  "Incompatible indices");
188 
189  using TensorExpr = Tensor4_contracted_01<
191  Dim01>;
192  return Tensor2_Expr<TensorExpr, T, Dim2, Dim3, k, l>(TensorExpr(*this));
193  };
194 
195  /* This is for expressions where a number is used for one slot, and
196  an index for another, yielding a Tensor3_Expr. The non-const
197  versions don't actually create a Tensor3_number_rhs_[0123] object.
198  They create a Tensor3_Expr directly, which provides the
199  appropriate indexing operators. The const versions do create a
200  Tensor3_number_[0123]. */
201  // TODO
202  };
203 }
204 
205 /// JSON compatible output
206 
207 namespace FTensor
208 {
209  template <class T, int Tensor_Dim0, int Tensor_Dim1, int Tensor_Dim2,
210  int Tensor_Dim3>
211  std::ostream &Tensor4_0001(
212  std::ostream &os,
214  const int &iterator0, const int &iterator1, const int &iterator2)
215  {
216  os << '[';
217  for(int i = 0; i < Tensor_Dim3 - 1; ++i)
218  {
219  os << t(iterator0, iterator1, iterator2, i);
220  os << ',';
221  }
222  os << t(iterator0, iterator1, iterator2, Tensor_Dim3 - 1);
223  os << ']';
224 
225  return os;
226  }
227 
228  template <class T, int Tensor_Dim0, int Tensor_Dim1, int Tensor_Dim2,
229  int Tensor_Dim3>
230  std::ostream &Tensor4_0010(
231  std::ostream &os,
233  const int &iterator0, const int &iterator1)
234  {
235  os << '[';
236  for(int i = 0; i < Tensor_Dim2 - 1; ++i)
237  {
238  FTensor::Tensor4_0001(os, t, iterator0, iterator1, i);
239  os << ',';
240  }
241  FTensor::Tensor4_0001(os, t, iterator0, iterator1, Tensor_Dim2 - 1);
242  os << ']';
243 
244  return os;
245  }
246 
247  template <class T, int Tensor_Dim0, int Tensor_Dim1, int Tensor_Dim2,
248  int Tensor_Dim3>
249  std::ostream &Tensor4_0100(
250  std::ostream &os,
252  const int &iterator0)
253  {
254  os << '[';
255  for(int i = 0; i < Tensor_Dim1 - 1; ++i)
256  {
257  FTensor::Tensor4_0010(os, t, iterator0, i);
258  os << ',';
259  }
260  FTensor::Tensor4_0010(os, t, iterator0, Tensor_Dim1 - 1);
261  os << ']';
262 
263  return os;
264  }
265 }
266 
267 template <class T, int Tensor_Dim0, int Tensor_Dim1, int Tensor_Dim2,
268  int Tensor_Dim3>
269 std::ostream &operator<<(std::ostream &os,
270  const FTensor::Tensor4<T, Tensor_Dim0, Tensor_Dim1,
271  Tensor_Dim2, Tensor_Dim3> &t)
272 {
273  os << '[';
274  for(int i = 0; i < Tensor_Dim0 - 1; ++i)
275  {
276  FTensor::Tensor4_0100(os, t, i);
277  os << ',';
278  }
279  FTensor::Tensor4_0100(os, t, Tensor_Dim0 - 1);
280  os << ']';
281 
282  return os;
283 }
std::ostream & Tensor4_0010(std::ostream &os, const Tensor4< T, Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3 > &t, const int &iterator0, const int &iterator1)
auto operator()(const Index< i, Dim0 >, const Index< j, Dim13 >, const Index< k, Dim2 >, const Index< j, Dim13 >) const
const Tensor1_Expr< const dTensor0< T, Dim, i >, typename promote< T, double >::V, Dim, i > d(const Tensor0< T *> &a, const Index< i, Dim > index, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
Definition: dTensor0.hpp:27
auto operator()(const Index< i, Dim03 >, const Index< j, Dim1 >, const Index< k, Dim2 >, const Index< i, Dim03 >) const
auto operator()(const Index< i, Dim0 >, const Index< j, Dim1 >, const Index< k, Dim23 >, const Index< k, Dim23 >) const
Fully Antisymmetric Levi-Civita Tensor.
T operator()(const int N1, const int N2, const int N3, const int N4) const
std::ostream & Tensor4_0001(std::ostream &os, const Tensor4< T, Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3 > &t, const int &iterator0, const int &iterator1, const int &iterator2)
std::ostream & operator<<(std::ostream &os, const FTensor::Tensor4< T, Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3 > &t)
auto operator()(const Index< i, Dim01 >, const Index< i, Dim01 >, const Index< k, Dim2 >, const Index< l, Dim3 >) const
T data[Tensor_Dim0][Tensor_Dim1][Tensor_Dim2][Tensor_Dim3]
T & operator()(const int N1, const int N2, const int N3, const int N4)
auto operator()(const Index< i, Dim02 >, const Index< j, Dim1 >, const Index< i, Dim02 >, const Index< l, Dim3 >) const
std::ostream & Tensor4_0100(std::ostream &os, const Tensor4< T, Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, Tensor_Dim3 > &t, const int &iterator0)
auto operator()(const Index< i, Dim0 >, const Index< j, Dim12 >, const Index< j, Dim12 >, const Index< l, Dim3 >) const