v0.9.0
Ddg_value.hpp
Go to the documentation of this file.
1 /* A general version, not for pointers. */
2 
3 #pragma once
4 
5 namespace FTensor
6 {
7  template <class T, int Tensor_Dim01, int Tensor_Dim23> class Ddg
8  {
9  T data[(Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2]
10  [(Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2];
11 
12  public:
13  /* There are two operator(int,int,int,int)'s, one for non-consts
14  that lets you change the value, and one for consts that
15  doesn't. */
16 
17  T &operator()(const int N1, const int N2, const int N3, const int N4)
18  {
19 #ifdef FTENSOR_DEBUG
20  if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0
21  || N3 >= Tensor_Dim23 || N3 < 0 || N4 >= Tensor_Dim23 || N4 < 0)
22  {
23  std::stringstream s;
24  s << "Bad index in Dg<T," << Tensor_Dim01 << "," << Tensor_Dim23
25  << ">.operator(" << N1 << "," << N2 << "," << N3 << "," << N4
26  << ")" << std::endl;
27  throw std::out_of_range(s.str());
28  }
29 #endif
30  return N1 > N2
31  ? (N3 > N4 ? data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2]
32  [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2]
33  : data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2]
34  [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2])
35  : (N3 > N4 ? data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2]
36  [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2]
37  : data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2]
38  [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]);
39  }
40 
41  T operator()(const int N1, const int N2, const int N3, const int N4) const
42  {
43 #ifdef FTENSOR_DEBUG
44  if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0
45  || N3 >= Tensor_Dim23 || N3 < 0 || N4 >= Tensor_Dim23 || N4 < 0)
46  {
47  std::stringstream s;
48  s << "Bad index in Dg<T," << Tensor_Dim01 << "," << Tensor_Dim23
49  << ">.operator(" << N1 << "," << N2 << "," << N3 << "," << N4
50  << ") const" << std::endl;
51  throw std::out_of_range(s.str());
52  }
53 #endif
54  return N1 > N2
55  ? (N3 > N4 ? data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2]
56  [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2]
57  : data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2]
58  [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2])
59  : (N3 > N4 ? data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2]
60  [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2]
61  : data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2]
62  [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 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  template <char i, char j, char k, char l, int Dim01, int Dim23>
71  typename std::enable_if<(Tensor_Dim01 >= Dim01 && Tensor_Dim23 >= Dim23),
73  Dim01, Dim23, i, j, k, l>>::type
74  operator()(const Index<i, Dim01>, const Index<j, Dim01>,
75  const Index<k, Dim23>, const Index<l, Dim23>)
76  {
77  return Ddg_Expr<Ddg<T, Tensor_Dim01, Tensor_Dim23>, T, Dim01, Dim23, i,
78  j, k, l>(*this);
79  }
80 
81  template <char i, char j, char k, char l, int Dim01, int Dim23>
82  typename std::enable_if<(Tensor_Dim01 >= Dim01 && Tensor_Dim23 >= Dim23),
84  T, Dim01, Dim23, i, j, k, l>>::type
85  operator()(const Index<i, Dim01>, const Index<j, Dim01>,
86  const Index<k, Dim23>, const Index<l, Dim23>) const
87  {
89  Dim23, i, j, k, l>(*this);
90  }
91 
92  /* This is for expressions where a number is used for two slots, and
93  an index for the other two, yielding a Tensor2_symmetric_Expr. */
94 
95  template <char i, char j, int N0, int N1, int Dim>
96  typename std::enable_if<
97  (Tensor_Dim01 > N0 && Tensor_Dim01 > N1 && Tensor_Dim23 >= Dim),
100  Dim, i, j>>::type
101  operator()(const Number<N0>, const Number<N1>, const Index<i, Dim>,
102  const Index<j, Dim>) const
103  {
104  using TensorExpr
107  TensorExpr(*this));
108  }
109 
110  template <char i, char j, int N0, int N1, int Dim>
111  typename std::enable_if<
112  (Tensor_Dim01 > N0 && Tensor_Dim01 > N1 && Tensor_Dim23 >= Dim),
115  Dim, i, j>>::type
116  operator()(const Number<N0>, const Number<N1>, const Index<i, Dim>,
117  const Index<j, Dim>)
118  {
119  using TensorExpr
122  }
123 
124  /* This is for expressions where a number is used for one slot, and
125  an index for the other three, yielding a Dg_Expr. */
126 
127  template <char i, char j, char k, int N0, int Dim1, int Dim23>
128  typename std::enable_if<
129  (Tensor_Dim01 > N0 && Tensor_Dim01 >= Dim1 && Tensor_Dim23 >= Dim23),
131  Dim23, Dim1, i, j, k>>::type
132  operator()(const Number<N0>, const Index<k, Dim1>, const Index<i, Dim23>,
133  const Index<j, Dim23>) const
134  {
135  using TensorExpr
137  return Dg_Expr<TensorExpr, T, Dim23, Dim1, i, j, k>(TensorExpr(*this));
138  }
139 
140  template <char i, char j, char k, int N0, int Dim1, int Dim23>
141  typename std::enable_if<
142  (Tensor_Dim01 > N0 && Tensor_Dim01 >= Dim1 && Tensor_Dim23 >= Dim23),
144  Dim23, Dim1, i, j, k>>::type
145  operator()(const Number<N0>, const Index<k, Dim1>, const Index<i, Dim23>,
146  const Index<j, Dim23>)
147  {
148  using TensorExpr
151  }
152 
153  /* This is for expressions where an int (not a Number) is used for
154  two slots, and an index for the other two, yielding a
155  Tensor2_symmetric_Expr. */
156 
157  template <char i, char j, int Dim>
158  typename std::enable_if<
159  (Tensor_Dim23 >= Dim),
162  j>>::type
163  operator()(const int N0, const int N1, const Index<i, Dim>,
164  const Index<j, Dim>) const
165  {
166  using TensorExpr
169  TensorExpr(*this, N0, N1));
170  }
171 
172  template <char i, char j, int Dim>
173  typename std::enable_if<
174  (Tensor_Dim01 >= Dim),
177  j>>::type
178  operator()(const Index<i, Dim>, const Index<j, Dim>, const int N2,
179  const int N3) const
180  {
181  using TensorExpr
184  TensorExpr(*this, N2, N3));
185  }
186 
187  /* int in two slots but yielding a Tensor2 */
188 
189  template <char i, char j, int Dim1, int Dim3>
190  typename std::enable_if<
191  (Tensor_Dim01 >= Dim1 && Tensor_Dim23 >= Dim3),
193  T, Dim1, Dim3, i, j>>::type
194  operator()(const int N0, const Index<i, Dim1>, const int N2,
195  const Index<j, Dim3>) const
196  {
197  using TensorExpr
200  TensorExpr(*this, N0, N2));
201  }
202 
203  /* int in three slots, Index in the other yielding a Tensor1_Expr. */
204 
205  template <char i, int Dim>
206  typename std::enable_if<
207  (Tensor_Dim01 >= Dim),
209  T, Dim, i>>::type
210  operator()(const Index<i, Dim>, const int N1, const int N2, const int N3)
211  {
212  using TensorExpr
215  TensorExpr(*this, N1, N2, N3));
216  }
217 
218  template <char i, int Dim>
219  typename std::enable_if<
220  (Tensor_Dim01 >= Dim),
222  T, Dim, i>>::type
223  operator()(const int N1, const Index<i, Dim>, const int N2, const int N3)
224  {
225  using TensorExpr
228  TensorExpr(*this, N1, N2, N3));
229  }
230 
231  /* This is for expressions where an int (not a Number) is used for
232  one slot, and an index for the other three, yielding a
233  Dg_Expr. */
234 
235  template <char i, char j, char k, int Dim1, int Dim23>
236  typename std::enable_if<
237  (Tensor_Dim01 >= Dim1 && Tensor_Dim23 >= Dim23),
239  Dim23, Dim1, i, j, k>>::type
240  operator()(const int N0, const Index<k, Dim1>, const Index<i, Dim23>,
241  const Index<j, Dim23>) const
242  {
243  using TensorExpr
246  TensorExpr(*this, N0));
247  }
248  };
249 }
Fully Antisymmetric Levi-Civita Tensor.
T data[(Tensor_Dim01 *(Tensor_Dim01+1))/2][(Tensor_Dim23 *(Tensor_Dim23+1))/2]
Definition: Ddg_value.hpp:10
T & operator()(const int N1, const int N2, const int N3, const int N4)
Definition: Ddg_value.hpp:17
T operator()(const int N1, const int N2, const int N3, const int N4) const
Definition: Ddg_value.hpp:41