v0.7.26
Tensor3_antisymmetric_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_Dim0, int Tensor_Dim12>
9  {
10  T data[Tensor_Dim0][(Tensor_Dim12 * (Tensor_Dim12 - 1)) / 2];
11 
12  public:
13  template <class... U> Tensor3_antisymmetric(U... d) : data{d...}
14  {
15  static_assert(sizeof...(d) == sizeof(data) / sizeof(T),
16  "Incorrect number of Arguments. Constructor should "
17  "initialize the entire Tensor");
18  }
19 
21 
22  /* There are two ways of accessing the values inside,
23  unsafe(int,int,int) and operator(int,int,int).
24  unsafe(int,int,int) will give you a wrong answer if you aren't
25  careful. The problem is that we only store the minimal set of
26  components, but some have different signs. We can't return the
27  negative of a component, and assign something to it, because that
28  would assign something to a temporary. To get the correct answer
29  if you don't want to change the value, just use
30  operator(int,int,int). */
31 
32  T &unsafe(const int N1, const int N2, const int N3)
33  {
34 #ifdef FTENSOR_DEBUG
35  if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0
36  || N3 >= Tensor_Dim12 || N3 < 0 || N2 >= N3)
37  {
38  std::stringstream s;
39  s << "Bad index in Tensor3_antisymmetric<T," << Tensor_Dim0 << ","
40  << Tensor_Dim12 << ">.operator(" << N1 << "," << N2 << "," << N3
41  << ")" << std::endl;
42  throw std::out_of_range(s.str());
43  }
44 #endif
45  return data[N1][N3 - 1 + (N2 * (2 * (Tensor_Dim12 - 1) - N2 - 1)) / 2];
46  }
47 
48  T operator()(const int N1, const int N2, const int N3) const
49  {
50 #ifdef FTENSOR_DEBUG
51  if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0
52  || N3 >= Tensor_Dim12 || N3 < 0)
53  {
54  std::stringstream s;
55  s << "Bad index in Tensor3_antisymmetric<T," << Tensor_Dim0 << ","
56  << Tensor_Dim12 << ">.operator(" << N1 << "," << N2 << "," << N3
57  << ") const" << std::endl;
58  throw std::out_of_range(s.str());
59  }
60 #endif
61  return N2 < N3
62  ? data[N1][N3 - 1 + (N2 * (2 * (Tensor_Dim12 - 1) - N2 - 1)) / 2]
63  : (N2 > N3
64  ? -data[N1][N2 - 1
65  + (N3 * (2 * (Tensor_Dim12 - 1) - N3 - 1)) / 2]
66  : 0.0);
67  }
68 
69  /* These operator()'s are the first part in constructing template
70  expressions. */
71 
72  template <char i, char j, char k, int Dim0, int Dim12>
73  typename std::enable_if<
74  (Tensor_Dim0 >= Dim0 && Tensor_Dim12 >= Dim12),
77  j, k>>::type
78  operator()(const Index<i, Dim0>, const Index<j, Dim12>,
79  const Index<k, Dim12>)
80  {
83  j, k>(*this);
84  }
85 
86  template <char i, char j, char k, int Dim0, int Dim12>
87  typename std::enable_if<
88  (Tensor_Dim0 >= Dim0 && Tensor_Dim12 >= Dim12),
91  Dim12, i, j, k>>::type
92  operator()(const Index<i, Dim0>, const Index<j, Dim12>,
93  const Index<k, Dim12>) const
94  {
97  Dim12, i, j, k>(*this);
98  }
99  // TODO Add the rest of operations with partial index and numbers
100  };
101 }
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
Fully Antisymmetric Levi-Civita Tensor.
T operator()(const int N1, const int N2, const int N3) const
T & unsafe(const int N1, const int N2, const int N3)
T data[Tensor_Dim0][(Tensor_Dim12 *(Tensor_Dim12 - 1))/2]