v0.8.23
Levi_Civita.hpp
Go to the documentation of this file.
1 /// Fully Antisymmetric Levi-Civita Tensor
2 
3 #pragma once
4 
5 #include "Levi_Civita.hpp"
6 
7 namespace FTensor
8 {
9  /// Levi_Civita Classes
10  template <class T = int> class Levi_Civita
11  {
12  public:
13  /// Rank 2
14  constexpr T operator()(const int N1, const int N2) const
15  {
16  return (N1 == N2) ? T(0) : ((N1 == 0) ? T(1) : T(-1));
17  }
18 
19  template <char i, char j, int Dim0, int Dim1>
20  typename std::enable_if<
21  (Dim0 <= 2 && Dim1 <= 2),
22  Tensor2_Expr<Levi_Civita<T>, T, Dim0, Dim1, i, j>>::type
23  operator()(const Index<i, Dim0> &, const Index<j, Dim1> &)
24  {
25  return Tensor2_Expr<Levi_Civita<T>, T, Dim0, Dim1, i, j>(*this);
26  };
27 
28  template <char i, int Dim0>
29  constexpr auto operator()(const Index<i, Dim0> &, const int &N1)
30  {
31  static_assert(
32  Dim0 <= 2,
33  "Index dimension exceeds the maximum for Rank 2 Levi-Civita Tensor");
34 #ifdef FTENSOR_DEBUG
35  if(N1 >= 2 || N1 < 0)
36  throw std::out_of_range(
37  "Bad index in Levi_Civita<T>::operator()(Index<"
38  + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
39  + std::to_string(N1) + ")\n");
40 #endif
41  auto TensorExpr
42  = [this, N1](const int &N0) { return this->operator()(N0, N1); };
44  };
45 
46  template <char j, int Dim1>
47  constexpr auto operator()(const int &N0, const Index<j, Dim1> &)
48  {
49  static_assert(
50  Dim1 <= 2,
51  "Index dimension exceeds the maximum for Rank 2 Levi-Civita Tensor");
52 #ifdef FTENSOR_DEBUG
53  if(N0 >= 2 || N0 < 0)
54  throw std::out_of_range("Bad index in Levi_Civita<T>::operator()("
55  + std::to_string(N0) + ", Index<"
56  + std::basic_string<char>{j} + ", "
57  + std::to_string(Dim1) + ">)\n");
58 #endif
59  auto TensorExpr
60  = [this, N0](const int &N1) { return this->operator()(N0, N1); };
61  return Tensor1_Expr<decltype(TensorExpr), T, Dim1, j>{TensorExpr};
62  };
63 
64  /// Rank 3
65  constexpr T operator()(const int N1, const int N2, const int N3) const
66  {
67  return (N1 == N2 || N1 == N3 || N2 == N3)
68  ? T(0)
69  : (((N1 + 1) % 3 == N2) ? T(1) : T(-1));
70  }
71 
72  template <char i, char j, char k, int Dim0, int Dim1, int Dim2>
73  typename std::enable_if<
74  (Dim0 <= 3 && Dim1 <= 3 && Dim2 <= 3),
75  Tensor3_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, i, j, k>>::type
76  operator()(const Index<i, Dim0> &, const Index<j, Dim1> &,
77  const Index<k, Dim2> &)
78  {
79  return Tensor3_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, i, j, k>(*this);
80  };
81 
82  template <char i, char j, int Dim0, int Dim1>
83  auto
84  operator()(const Index<i, Dim0> &, const Index<j, Dim1> &, const int &N2)
85  {
86  static_assert(
87  Dim0 <= 3 && Dim1 <= 3,
88  "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
89 #ifdef FTENSOR_DEBUG
90  if(N2 >= 3 || N2 < 0)
91  throw std::out_of_range(
92  "Bad index in Levi_Civita<T>::operator()("
93  "Index<"
94  + std::basic_string<char>{i} + ", " + std::to_string(Dim0)
95  + ">, "
96  "Index<"
97  + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
98  + std::to_string(N2) + ")\n");
99 #endif
100  auto TensorExpr = [this, N2](const int &N0, const int &N1) {
101  return this->operator()(N0, N1, N2);
102  };
103  return Tensor2_Expr<decltype(TensorExpr), T, Dim0, Dim1, i, j>{
104  TensorExpr};
105  }
106 
107  template <char i, char k, int Dim0, int Dim2>
108  auto
109  operator()(const Index<i, Dim0> &, const int &N1, const Index<k, Dim2> &)
110  {
111  static_assert(
112  Dim0 <= 3 && Dim2 <= 3,
113  "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
114 #ifdef FTENSOR_DEBUG
115  if(N1 >= 3 || N1 < 0)
116  throw std::out_of_range(
117  "Bad index in Levi_Civita<T>::operator()("
118  "Index<"
119  + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
120  + std::to_string(N1)
121  + ", "
122  "Index<"
123  + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">)\n");
124 #endif
125  auto TensorExpr = [this, N1](const int &N0, const int &N2) {
126  return this->operator()(N0, N1, N2);
127  };
128  return Tensor2_Expr<decltype(TensorExpr), T, Dim0, Dim2, i, k>{
129  TensorExpr};
130  }
131 
132  template <char j, char k, int Dim1, int Dim2>
133  auto
134  operator()(const int &N0, const Index<j, Dim1> &, const Index<k, Dim2> &)
135  {
136  static_assert(
137  Dim1 <= 3 && Dim2 <= 3,
138  "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
139 #ifdef FTENSOR_DEBUG
140  if(N0 >= 3 || N0 < 0)
141  throw std::out_of_range(
142  "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
143  + ", "
144  "Index<"
145  + std::basic_string<char>{j} + ", " + std::to_string(Dim1)
146  + ">, "
147  "Index<"
148  + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">)\n");
149 #endif
150  auto TensorExpr = [this, N0](const int &N1, const int &N2) {
151  return this->operator()(N0, N1, N2);
152  };
153  return Tensor2_Expr<decltype(TensorExpr), T, Dim1, Dim2, j, k>{
154  TensorExpr};
155  }
156 
157  template <char i, int Dim0>
158  auto operator()(const Index<i, Dim0> &, const int &N1, const int &N2)
159  {
160  static_assert(
161  Dim0 <= 3,
162  "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
163 #ifdef FTENSOR_DEBUG
164  if(N1 >= 3 || N1 < 0 || N2 >= 3 || N2 < 0)
165  throw std::out_of_range(
166  "Bad index in Levi_Civita<T>::operator()("
167  "Index<"
168  + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
169  + std::to_string(N1) + ", " + std::to_string(N2) + ")\n");
170 #endif
171  auto TensorExpr = [this, N1, N2](const int &N0) {
172  return this->operator()(N0, N1, N2);
173  };
174  return Tensor1_Expr<decltype(TensorExpr), T, Dim0, i>{TensorExpr};
175  }
176 
177  template <char j, int Dim1>
178  auto operator()(const int &N0, const Index<j, Dim1> &, const int &N2)
179  {
180  static_assert(
181  Dim1 <= 3,
182  "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
183 #ifdef FTENSOR_DEBUG
184  if(N0 >= 3 || N0 < 0 || N2 >= 3 || N2 < 0)
185  throw std::out_of_range(
186  "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
187  + ", "
188  "Index<"
189  + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
190  + std::to_string(N2) + ")\n");
191 #endif
192  auto TensorExpr = [this, N0, N2](const int &N1) {
193  return this->operator()(N0, N1, N2);
194  };
195  return Tensor1_Expr<decltype(TensorExpr), T, Dim1, j>{TensorExpr};
196  }
197 
198  template <char k, int Dim2>
199  auto operator()(const int &N0, const int &N1, const Index<k, Dim2> &)
200  {
201  static_assert(
202  Dim2 <= 3,
203  "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
204 #ifdef FTENSOR_DEBUG
205  if(N0 >= 3 || N0 < 0 || N1 >= 3 || N1 < 0)
206  throw std::out_of_range(
207  "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
208  + ", " + std::to_string(N1)
209  + ", "
210  "Index<"
211  + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">)\n");
212 #endif
213  auto TensorExpr = [this, N0, N1](const int &N2) {
214  return this->operator()(N0, N1, N2);
215  };
216  return Tensor1_Expr<decltype(TensorExpr), T, Dim2, k>{TensorExpr};
217  }
218 
219  /// Rank 4
220  constexpr T
221  operator()(const int N1, const int N2, const int N3, const int N4) const
222  {
223  return (N1 == N2 || N1 == N3 || N1 == N4 || N2 == N3 || N2 == N4
224  || N3 == N4)
225  ? T(0)
226  : ((N1 + N2 == 1 || N1 + N2 == 5)
227  ? (((N2 + N3) % 4 == 3) ? T(1) : T(-1))
228  : ((N1 + N2 == 2 || N1 + N2 == 4)
229  ? (((N2 + N3) % 4 == 1) ? T(1) : T(-1))
230  : (N1 + N2 == 3
231  ? (((N2 + N3) % 4 != 1) ? T(1) : T(-1))
232  : T(0))));
233  }
234 
235  template <char i, char j, char k, char l, int Dim0, int Dim1, int Dim2,
236  int Dim3>
237  typename std::enable_if<
238  (Dim0 <= 4 && Dim1 <= 4 && Dim2 <= 4 && Dim3 <= 4),
239  Tensor4_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>>::type
240  operator()(const Index<i, Dim0> &, const Index<j, Dim1> &,
241  const Index<k, Dim2> &, const Index<l, Dim3> &)
242  {
243  return Tensor4_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, Dim3, i, j, k,
244  l>(*this);
245  }
246 
247  template <char i, char j, char k, int Dim0, int Dim1, int Dim2>
248  constexpr auto operator()(const Index<i, Dim0> &, const Index<j, Dim1> &,
249  const Index<k, Dim2> &, const int &N3)
250  {
251  static_assert(
252  Dim0 <= 4 && Dim1 <= 4 && Dim2 <= 4,
253  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
254 #ifdef FTENSOR_DEBUG
255  if(N3 >= 4 || N3 < 0)
256  throw std::out_of_range(
257  "Bad index in Levi_Civita<T>::operator()("
258  "Index<"
259  + std::basic_string<char>{i} + ", " + std::to_string(Dim0)
260  + ">, "
261  "Index<"
262  + std::basic_string<char>{j} + ", " + std::to_string(Dim1)
263  + ">, "
264  "Index<"
265  + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">, "
266  + std::to_string(N3) + ")\n");
267 #endif
268  auto TensorExpr
269  = [this, N3](const int &N0, const int &N1, const int &N2) {
270  return this->operator()(N0, N1, N2, N3);
271  };
272  return Tensor3_Expr<decltype(TensorExpr), T, Dim0, Dim1, Dim2, i, j, k>{
273  TensorExpr};
274  }
275 
276  template <char i, char j, char l, int Dim0, int Dim1, int Dim3>
277  constexpr auto operator()(const Index<i, Dim0> &, const Index<j, Dim1> &,
278  const int &N2, const Index<l, Dim3> &)
279  {
280  static_assert(
281  Dim0 <= 4 && Dim1 <= 4 && Dim3 <= 4,
282  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
283 #ifdef FTENSOR_DEBUG
284  if(N2 >= 4 || N2 < 0)
285  throw std::out_of_range(
286  "Bad index in Levi_Civita<T>::operator()("
287  "Index<"
288  + std::basic_string<char>{i} + ", " + std::to_string(Dim0)
289  + ">, "
290  "Index<"
291  + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
292  + std::to_string(N2)
293  + ", "
294  "Index<"
295  + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
296 #endif
297  auto TensorExpr
298  = [this, N2](const int &N0, const int &N1, const int &N3) {
299  return this->operator()(N0, N1, N2, N3);
300  };
301  return Tensor3_Expr<decltype(TensorExpr), T, Dim0, Dim1, Dim3, i, j, l>{
302  TensorExpr};
303  }
304 
305  template <char i, char k, char l, int Dim0, int Dim2, int Dim3>
306  constexpr auto operator()(const Index<i, Dim0> &, const int &N1,
307  const Index<k, Dim2> &, const Index<l, Dim3> &)
308  {
309  static_assert(
310  Dim0 <= 4 && Dim2 <= 4 && Dim3 <= 4,
311  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
312 #ifdef FTENSOR_DEBUG
313  if(N1 >= 4 || N1 < 0)
314  throw std::out_of_range(
315  "Bad index in Levi_Civita<T>::operator()("
316  "Index<"
317  + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
318  + std::to_string(N1)
319  + ", "
320  "Index<"
321  + std::basic_string<char>{k} + ", " + std::to_string(Dim2)
322  + ">, "
323  "Index<"
324  + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
325 #endif
326  auto TensorExpr
327  = [this, N1](const int &N0, const int &N2, const int &N3) {
328  return this->operator()(N0, N1, N2, N3);
329  };
330  return Tensor3_Expr<decltype(TensorExpr), T, Dim0, Dim2, Dim3, i, k, l>{
331  TensorExpr};
332  }
333 
334  template <char j, char k, char l, int Dim1, int Dim2, int Dim3>
335  constexpr auto operator()(const int &N0, const Index<j, Dim1> &,
336  const Index<k, Dim2> &, const Index<l, Dim3> &)
337  {
338  static_assert(
339  Dim1 <= 4 && Dim2 <= 4 && Dim3 <= 4,
340  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
341 #ifdef FTENSOR_DEBUG
342  if(N0 >= 4 || N0 < 0)
343  throw std::out_of_range(
344  "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
345  + ", "
346  "Index<"
347  + std::basic_string<char>{j} + ", " + std::to_string(Dim1)
348  + ">, "
349  "Index<"
350  + std::basic_string<char>{k} + ", " + std::to_string(Dim2)
351  + ">, "
352  "Index<"
353  + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
354 #endif
355  auto TensorExpr
356  = [this, N0](const int &N1, const int &N2, const int &N3) {
357  return this->operator()(N0, N1, N2, N3);
358  };
359  return Tensor3_Expr<decltype(TensorExpr), T, Dim1, Dim2, Dim3, j, k, l>{
360  TensorExpr};
361  }
362 
363  template <char i, char j, int Dim0, int Dim1>
364  constexpr auto operator()(const Index<i, Dim0> &, const Index<j, Dim1> &,
365  const int &N2, const int &N3)
366  {
367  static_assert(
368  Dim0 <= 4 && Dim1 <= 4,
369  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
370 #ifdef FTENSOR_DEBUG
371  if(N2 >= 4 || N2 < 0 || N3 >= 4 || N3 < 0)
372  throw std::out_of_range(
373  "Bad index in Levi_Civita<T>::operator()("
374  "Index<"
375  + std::basic_string<char>{i} + ", " + std::to_string(Dim0)
376  + ">, "
377  "Index<"
378  + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
379  + std::to_string(N2) + ", " + std::to_string(N3) + ")\n");
380 #endif
381  auto TensorExpr = [this, N2, N3](const int &N0, const int &N1) {
382  return this->operator()(N0, N1, N2, N3);
383  };
384  return Tensor2_Expr<decltype(TensorExpr), T, Dim0, Dim1, i, j>{
385  TensorExpr};
386  }
387 
388  template <char i, char k, int Dim0, int Dim2>
389  constexpr auto operator()(const Index<i, Dim0> &, const int &N1,
390  const Index<k, Dim2> &, const int &N3)
391  {
392  static_assert(
393  Dim0 <= 4 && Dim2 <= 4,
394  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
395 #ifdef FTENSOR_DEBUG
396  if(N1 >= 4 || N1 < 0 || N3 >= 4 || N3 < 0)
397  throw std::out_of_range(
398  "Bad index in Levi_Civita<T>::operator()("
399  "Index<"
400  + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
401  + std::to_string(N1)
402  + ", "
403  "Index<"
404  + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">, "
405  + std::to_string(N3) + ")\n");
406 #endif
407  auto TensorExpr = [this, N1, N3](const int &N0, const int &N2) {
408  return this->operator()(N0, N1, N2, N3);
409  };
410  return Tensor2_Expr<decltype(TensorExpr), T, Dim0, Dim2, i, k>{
411  TensorExpr};
412  }
413 
414  template <char j, char k, int Dim1, int Dim2>
415  constexpr auto operator()(const int &N0, const Index<j, Dim1> &,
416  const Index<k, Dim2> &, const int &N3)
417  {
418  static_assert(
419  Dim1 <= 4 && Dim2 <= 4,
420  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
421 #ifdef FTENSOR_DEBUG
422  if(N0 >= 4 || N0 < 0 || N3 >= 4 || N3 < 0)
423  throw std::out_of_range(
424  "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
425  + ", "
426  "Index<"
427  + std::basic_string<char>{j} + ", " + std::to_string(Dim1)
428  + ">, "
429  "Index<"
430  + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">, "
431  + std::to_string(N3) + ")\n");
432 #endif
433  auto TensorExpr = [this, N0, N3](const int &N1, const int &N2) {
434  return this->operator()(N0, N1, N2, N3);
435  };
436  return Tensor2_Expr<decltype(TensorExpr), T, Dim1, Dim2, j, k>{
437  TensorExpr};
438  }
439 
440  template <char i, char l, int Dim0, int Dim3>
441  constexpr auto operator()(const Index<i, Dim0> &, const int &N1,
442  const int &N2, const Index<l, Dim3> &)
443  {
444  static_assert(
445  Dim0 <= 4 && Dim3 <= 4,
446  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
447 #ifdef FTENSOR_DEBUG
448  if(N1 >= 4 || N1 < 0 || N2 >= 4 || N2 < 0)
449  throw std::out_of_range(
450  "Bad index in Levi_Civita<T>::operator()("
451  "Index<"
452  + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
453  + std::to_string(N1) + ", " + std::to_string(N2)
454  + ", "
455  "Index<"
456  + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
457 #endif
458  auto TensorExpr = [this, N1, N2](const int &N0, const int &N3) {
459  return this->operator()(N0, N1, N2, N3);
460  };
461  return Tensor2_Expr<decltype(TensorExpr), T, Dim0, Dim3, i, l>{
462  TensorExpr};
463  }
464 
465  template <char j, char l, int Dim1, int Dim3>
466  constexpr auto operator()(const int &N0, const Index<j, Dim1> &,
467  const int &N2, const Index<l, Dim3> &)
468  {
469  static_assert(
470  Dim1 <= 4 && Dim3 <= 4,
471  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
472 #ifdef FTENSOR_DEBUG
473  if(N0 >= 4 || N0 < 0 || N2 >= 4 || N2 < 0)
474  throw std::out_of_range(
475  "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
476  + ", "
477  "Index<"
478  + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
479  + std::to_string(N2)
480  + ", "
481  "Index<"
482  + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
483 #endif
484  auto TensorExpr = [this, N0, N2](const int &N1, const int &N3) {
485  return this->operator()(N0, N1, N2, N3);
486  };
487  return Tensor2_Expr<decltype(TensorExpr), T, Dim1, Dim3, j, l>{
488  TensorExpr};
489  }
490 
491  template <char k, char l, int Dim2, int Dim3>
492  constexpr auto operator()(const int &N0, const int &N1,
493  const Index<k, Dim2> &, const Index<l, Dim3> &)
494  {
495  static_assert(
496  Dim2 <= 4 && Dim3 <= 4,
497  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
498 #ifdef FTENSOR_DEBUG
499  if(N0 >= 4 || N0 < 0 || N1 >= 4 || N1 < 0)
500  throw std::out_of_range(
501  "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
502  + ", " + std::to_string(N1)
503  + ", "
504  "Index<"
505  + std::basic_string<char>{k} + ", " + std::to_string(Dim2)
506  + ">, "
507  "Index<"
508  + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
509 #endif
510  auto TensorExpr = [this, N0, N1](const int &N2, const int &N3) {
511  return this->operator()(N0, N1, N2, N3);
512  };
513  return Tensor2_Expr<decltype(TensorExpr), T, Dim2, Dim3, k, l>{
514  TensorExpr};
515  }
516 
517  template <char i, int Dim0>
518  constexpr auto operator()(const Index<i, Dim0> &, const int &N1,
519  const int &N2, const int &N3)
520  {
521  static_assert(
522  Dim0 <= 4,
523  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
524 #ifdef FTENSOR_DEBUG
525  if(N1 >= 4 || N1 < 0 || N2 >= 4 || N2 < 0 || N3 >= 4 || N3 < 0)
526  throw std::out_of_range(
527  "Bad index in Levi_Civita<T>::operator()("
528  "Index<"
529  + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
530  + std::to_string(N1) + ", " + std::to_string(N2) + ", "
531  + std::to_string(N3) + ")\n");
532 #endif
533  auto TensorExpr = [this, N1, N2, N3](const int &N0) {
534  return this->operator()(N0, N1, N2, N3);
535  };
536  return Tensor1_Expr<decltype(TensorExpr), T, Dim0, i>{TensorExpr};
537  }
538 
539  template <char j, int Dim1>
540  constexpr auto operator()(const int &N0, const Index<j, Dim1> &,
541  const int &N2, const int &N3)
542  {
543  static_assert(
544  Dim1 <= 4,
545  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
546 #ifdef FTENSOR_DEBUG
547  if(N0 >= 4 || N0 < 0 || N2 >= 4 || N2 < 0 || N3 >= 4 || N3 < 0)
548  throw std::out_of_range(
549  "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
550  + ", "
551  "Index<"
552  + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
553  + std::to_string(N2) + ", " + std::to_string(N3) + ")\n");
554 #endif
555  auto TensorExpr = [this, N0, N2, N3](const int &N1) {
556  return this->operator()(N0, N1, N2, N3);
557  };
558  return Tensor1_Expr<decltype(TensorExpr), T, Dim1, j>{TensorExpr};
559  }
560 
561  template <char k, int Dim2>
562  constexpr auto operator()(const int &N0, const int &N1,
563  const Index<k, Dim2> &, const int &N3)
564  {
565  static_assert(
566  Dim2 <= 4,
567  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
568 #ifdef FTENSOR_DEBUG
569  if(N0 >= 4 || N0 < 0 || N1 >= 4 || N1 < 0 || N3 >= 4 || N3 < 0)
570  throw std::out_of_range(
571  "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
572  + ", " + std::to_string(N1)
573  + ", "
574  "Index<"
575  + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">, "
576  + std::to_string(N3) + ")\n");
577 #endif
578  auto TensorExpr = [this, N0, N1, N3](const int &N2) {
579  return this->operator()(N0, N1, N2, N3);
580  };
581  return Tensor1_Expr<decltype(TensorExpr), T, Dim2, k>{TensorExpr};
582  }
583 
584  template <char l, int Dim3>
585  constexpr auto operator()(const int &N0, const int &N1, const int &N2,
586  const Index<l, Dim3> &)
587  {
588  static_assert(
589  Dim3 <= 4,
590  "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
591 #ifdef FTENSOR_DEBUG
592  if(N0 >= 4 || N0 < 0 || N1 >= 4 || N1 < 0 || N2 >= 4 || N2 < 0)
593  throw std::out_of_range(
594  "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
595  + ", " + std::to_string(N1) + ", " + std::to_string(N2)
596  + ", "
597  "Index<"
598  + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
599 #endif
600  auto TensorExpr = [this, N0, N1, N2](const int &N3) {
601  return this->operator()(N0, N1, N2, N3);
602  };
603  return Tensor1_Expr<decltype(TensorExpr), T, Dim3, l>{TensorExpr};
604  }
605  };
606 
607  /// levi_civita functions to make for easy adhoc use
608 
609  /// Normally, this should go in is own file levi_civita.hpp, but
610  /// not all filesystems can handle files that differ only in case :(
611 
612  /// Rank 2
613  template <class T = int, char i, char j, int Dim0, int Dim1>
614  constexpr typename std::enable_if<
615  (Dim0 <= 2 && Dim1 <= 2),
616  Tensor2_Expr<Levi_Civita<T>, T, Dim0, Dim1, i, j>>::type
618  {
620  }
621 
622  template <class T = int, char i, int Dim0>
623  constexpr auto levi_civita(const Index<i, Dim0> &, const int &N1)
624  {
625  return Levi_Civita<T>()(Index<i, Dim0>(), N1);
626  }
627 
628  template <class T = int, char j, int Dim1>
629  constexpr auto levi_civita(const int &N0, const Index<j, Dim1> &)
630  {
631  return Levi_Civita<T>()(N0, Index<j, Dim1>());
632  }
633 
634  /// Rank 3
635  template <class T = int, char i, char j, char k, int Dim0, int Dim1, int Dim2>
636  constexpr typename std::enable_if<
637  (Dim0 <= 3 && Dim1 <= 3 && Dim2 <= 3),
638  Tensor3_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, i, j, k>>::type
640  const Index<k, Dim2> &)
641  {
643  Index<k, Dim2>());
644  }
645 
646  template <class T = int, char i, char j, int Dim0, int Dim1>
647  constexpr auto
648  levi_civita(const Index<i, Dim0> &, const Index<j, Dim1> &, const int &N2)
649  {
650  return Levi_Civita<T>()(Index<i, Dim0>(), Index<j, Dim1>(), N2);
651  }
652 
653  template <class T = int, char i, char k, int Dim0, int Dim2>
654  constexpr auto
655  levi_civita(const Index<i, Dim0> &, const int &N1, const Index<k, Dim2> &)
656  {
657  return Levi_Civita<T>()(Index<i, Dim0>(), N1, Index<k, Dim2>());
658  }
659 
660  template <class T = int, char j, char k, int Dim1, int Dim2>
661  constexpr auto
662  levi_civita(const int &N0, const Index<j, Dim1> &, const Index<k, Dim2> &)
663  {
664  return Levi_Civita<T>()(N0, Index<j, Dim1>(), Index<k, Dim2>());
665  }
666 
667  template <class T = int, char i, int Dim0>
668  constexpr auto
669  levi_civita(const Index<i, Dim0> &, const int &N1, const int &N2)
670  {
671  return Levi_Civita<T>()(Index<i, Dim0>(), N1, N2);
672  }
673 
674  template <class T = int, char j, int Dim1>
675  constexpr auto
676  levi_civita(const int &N0, const Index<j, Dim1> &, const int &N2)
677  {
678  return Levi_Civita<T>()(N0, Index<j, Dim1>(), N2);
679  }
680 
681  template <class T = int, char k, int Dim2>
682  constexpr auto
683  levi_civita(const int &N0, const int &N1, const Index<k, Dim2> &)
684  {
685  return Levi_Civita<T>()(N0, N1, Index<k, Dim2>());
686  }
687 
688  /// Rank 4
689  template <class T = int, char i, char j, char k, char l, int Dim0, int Dim1,
690  int Dim2, int Dim3>
691  constexpr typename std::enable_if<
692  (Dim0 <= 4 && Dim1 <= 4 && Dim2 <= 4 && Dim3 <= 4),
693  Tensor4_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>>::type
695  const Index<k, Dim2> &, const Index<l, Dim3> &)
696  {
699  }
700 
701  template <class T = int, char i, char j, char k, int Dim0, int Dim1, int Dim2>
702  constexpr auto levi_civita(const Index<i, Dim0> &, const Index<j, Dim1> &,
703  const Index<k, Dim2> &, const int &N3)
704  {
706  Index<k, Dim2>(), N3);
707  }
708 
709  template <class T = int, char i, char j, char l, int Dim0, int Dim1, int Dim3>
710  constexpr auto levi_civita(const Index<i, Dim0> &, const Index<j, Dim1> &,
711  const int &N2, const Index<l, Dim3> &)
712  {
713  return Levi_Civita<T>()(Index<i, Dim0>(), Index<j, Dim1>(), N2,
714  Index<l, Dim3>());
715  }
716 
717  template <class T = int, char i, char k, char l, int Dim0, int Dim2, int Dim3>
718  constexpr auto levi_civita(const Index<i, Dim0> &, const int &N1,
719  const Index<k, Dim2> &, const Index<l, Dim3> &)
720  {
721  return Levi_Civita<T>()(Index<i, Dim0>(), N1, Index<k, Dim2>(),
722  Index<l, Dim3>());
723  }
724 
725  template <class T = int, char j, char k, char l, int Dim1, int Dim2, int Dim3>
726  constexpr auto levi_civita(const int &N0, const Index<j, Dim1> &,
727  const Index<k, Dim2> &, const Index<l, Dim3> &)
728  {
729  return Levi_Civita<T>()(N0, Index<j, Dim1>(), Index<k, Dim2>(),
730  Index<l, Dim3>());
731  }
732 
733  template <class T = int, char i, char j, int Dim0, int Dim1>
734  constexpr auto levi_civita(const Index<i, Dim0> &, const Index<j, Dim1> &,
735  const int &N2, const int &N3)
736  {
737  return Levi_Civita<T>()(Index<i, Dim0>(), Index<j, Dim1>(), N2, N3);
738  }
739 
740  template <class T = int, char i, char k, int Dim0, int Dim2>
741  constexpr auto levi_civita(const Index<i, Dim0> &, const int &N1,
742  const Index<k, Dim2> &, const int &N3)
743  {
744  return Levi_Civita<T>()(Index<i, Dim0>(), N1, Index<k, Dim2>(), N3);
745  }
746 
747  template <class T = int, char j, char k, int Dim1, int Dim2>
748  constexpr auto levi_civita(const int &N0, const Index<j, Dim1> &,
749  const Index<k, Dim2> &, const int &N3)
750  {
751  return Levi_Civita<T>()(N0, Index<j, Dim1>(), Index<k, Dim2>(), N3);
752  }
753 
754  template <class T = int, char i, char l, int Dim0, int Dim3>
755  constexpr auto levi_civita(const Index<i, Dim0> &, const int &N1,
756  const int &N2, const Index<l, Dim3> &)
757  {
758  return Levi_Civita<T>()(Index<i, Dim0>(), N1, N2, Index<l, Dim3>());
759  }
760 
761  template <class T = int, char j, char l, int Dim1, int Dim3>
762  constexpr auto levi_civita(const int &N0, const Index<j, Dim1> &,
763  const int &N2, const Index<l, Dim3> &)
764  {
765  return Levi_Civita<T>()(N0, Index<j, Dim1>(), N2, Index<l, Dim3>());
766  }
767 
768  template <class T = int, char k, char l, int Dim2, int Dim3>
769  constexpr auto levi_civita(const int &N0, const int &N1,
770  const Index<k, Dim2> &, const Index<l, Dim3> &)
771  {
772  return Levi_Civita<T>()(N0, N1, Index<k, Dim2>(), Index<l, Dim3>());
773  }
774 
775  template <class T = int, char i, int Dim0>
776  constexpr auto levi_civita(const Index<i, Dim0> &, const int &N1,
777  const int &N2, const int &N3)
778  {
779  return Levi_Civita<T>()(Index<i, Dim0>(), N1, N2, N3);
780  }
781 
782  template <class T = int, char j, int Dim1>
783  constexpr auto levi_civita(const int &N0, const Index<j, Dim1> &,
784  const int &N2, const int &N3)
785  {
786  return Levi_Civita<T>()(N0, Index<j, Dim1>(), N2, N3);
787  }
788 
789  template <class T = int, char k, int Dim2>
790  constexpr auto levi_civita(const int &N0, const int &N1,
791  const Index<k, Dim2> &, const int &N3)
792  {
793  return Levi_Civita<T>()(N0, N1, Index<k, Dim2>(), N3);
794  }
795 
796  template <class T = int, char l, int Dim3>
797  constexpr auto levi_civita(const int &N0, const int &N1, const int &N2,
798  const Index<l, Dim3> &)
799  {
800  return Levi_Civita<T>()(N0, N1, N2, Index<l, Dim3>());
801  }
802 }
constexpr T operator()(const int N1, const int N2, const int N3, const int N4) const
Rank 4.
constexpr auto operator()(const int &N0, const Index< j, Dim1 > &)
Definition: Levi_Civita.hpp:47
constexpr auto operator()(const Index< i, Dim0 > &, const int &N1, const Index< k, Dim2 > &, const Index< l, Dim3 > &)
Levi_Civita Classes.
Definition: Levi_Civita.hpp:10
constexpr auto operator()(const int &N0, const int &N1, const Index< k, Dim2 > &, const int &N3)
auto operator()(const int &N0, const Index< j, Dim1 > &, const Index< k, Dim2 > &)
constexpr auto operator()(const int &N0, const int &N1, const Index< k, Dim2 > &, const Index< l, Dim3 > &)
auto operator()(const Index< i, Dim0 > &, const Index< j, Dim1 > &, const int &N2)
Definition: Levi_Civita.hpp:84
constexpr auto operator()(const Index< i, Dim0 > &, const int &N1, const int &N2, const Index< l, Dim3 > &)
constexpr T operator()(const int N1, const int N2, const int N3) const
Rank 3.
Definition: Levi_Civita.hpp:65
constexpr auto operator()(const int &N0, const Index< j, Dim1 > &, const Index< k, Dim2 > &, const Index< l, Dim3 > &)
Fully Antisymmetric Levi-Civita Tensor.
constexpr auto operator()(const Index< i, Dim0 > &, const int &N1, const int &N2, const int &N3)
constexpr auto operator()(const Index< i, Dim0 > &, const int &N1, const Index< k, Dim2 > &, const int &N3)
constexpr auto operator()(const Index< i, Dim0 > &, const Index< j, Dim1 > &, const int &N2, const Index< l, Dim3 > &)
constexpr T operator()(const int N1, const int N2) const
Rank 2.
Definition: Levi_Civita.hpp:14
auto operator()(const Index< i, Dim0 > &, const int &N1, const Index< k, Dim2 > &)
auto operator()(const int &N0, const Index< j, Dim1 > &, const int &N2)
constexpr auto operator()(const int &N0, const Index< j, Dim1 > &, const Index< k, Dim2 > &, const int &N3)
constexpr auto operator()(const Index< i, Dim0 > &, const Index< j, Dim1 > &, const Index< k, Dim2 > &, const int &N3)
constexpr auto operator()(const Index< i, Dim0 > &, const int &N1)
Definition: Levi_Civita.hpp:29
constexpr auto operator()(const int &N0, const Index< j, Dim1 > &, const int &N2, const int &N3)
constexpr auto operator()(const int &N0, const Index< j, Dim1 > &, const int &N2, const Index< l, Dim3 > &)
constexpr auto operator()(const int &N0, const int &N1, const int &N2, const Index< l, Dim3 > &)
auto operator()(const Index< i, Dim0 > &, const int &N1, const int &N2)
auto operator()(const int &N0, const int &N1, const Index< k, Dim2 > &)
constexpr auto operator()(const Index< i, Dim0 > &, const Index< j, Dim1 > &, const int &N2, const int &N3)
constexpr std::enable_if<(Dim0<=2 &&Dim1<=2), Tensor2_Expr< Levi_Civita< T >, T, Dim0, Dim1, i, j > >::type levi_civita(const Index< i, Dim0 > &, const Index< j, Dim1 > &)
levi_civita functions to make for easy adhoc use