v0.14.0
Tensor2_value.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 /* A general version, not for pointers. */
4 
5 #include <ostream>
6 
7 #ifdef FTENSOR_DEBUG
8 #include <sstream>
9 #include <stdexcept>
10 #endif
11 
12 #pragma once
13 
14 namespace FTensor
15 {
16  template <class T, int Tensor_Dim0, int Tensor_Dim1> class Tensor2
17  {
18  T data[Tensor_Dim0][Tensor_Dim1];
19 
20  public:
21  /* Initializations for varying numbers of elements. */
22  template <class... U> Tensor2(U... d) : data{d...}
23  {
24  static_assert(sizeof...(d) == sizeof(data) / sizeof(T),
25  "Incorrect number of Arguments. Constructor should "
26  "initialize the entire Tensor");
27  }
28 
29  Tensor2() {}
30 
31  /* Get ptr */
32 
33  T *ptr(const int N1, const int N2) const {
34 #ifdef FTENSOR_DEBUG
35  if (N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) {
36  std::stringstream s;
37  s << "Bad index in Tensor2<T*," << Tensor_Dim0 << "," << Tensor_Dim1
38  << ">.ptr(" << N1 << "," << N2 << ")" << std::endl;
39  throw std::out_of_range(s.str());
40  }
41 #endif
42  return &data[N1][N2];
43  }
44 
45  /* There are two operator(int,int)'s, one for non-consts that lets you
46  change the value, and one for consts that doesn't. */
47 
48  T &operator()(const int N1, const int N2)
49  {
50 #ifdef FTENSOR_DEBUG
51  if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0)
52  {
53  std::stringstream s;
54  s << "Bad index in Tensor2<T," << Tensor_Dim0 << "," << Tensor_Dim1
55  << ">.operator(" << N1 << "," << N2 << ")" << std::endl;
56  throw std::out_of_range(s.str());
57  }
58 #endif
59  return data[N1][N2];
60  }
61 
62  T operator()(const int N1, const int N2) const
63  {
64 #ifdef FTENSOR_DEBUG
65  if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0)
66  {
67  std::stringstream s;
68  s << "Bad index in Tensor2<T," << Tensor_Dim0 << "," << Tensor_Dim1
69  << ">.operator(" << N1 << "," << N2 << ") const" << std::endl;
70  throw std::out_of_range(s.str());
71  }
72 #endif
73  return data[N1][N2];
74  }
75 
76  /* These operator()'s are the first part in constructing template
77  expressions. They can be used to slice off lower dimensional
78  parts. They are not entirely safe, since you can accidentaly use a
79  higher dimension than what is really allowed (like Dim=5). */
80 
81  template <char i, char j, int Dim0, int Dim1>
82  typename std::enable_if<(Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1),
84  T, Dim0, Dim1, i, j>>::type
85  operator()(const Index<i, Dim0>, const Index<j, Dim1>)
86  {
88  i, j>(*this);
89  }
90 
91  template <char i, char j, int Dim0, int Dim1>
92  typename std::enable_if<
93  (Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1),
95  i, j>>::type
96  operator()(const Index<i, Dim0>, const Index<j, Dim1>) const
97  {
99  Dim1, i, j>(*this);
100  }
101 
102  /* This is for expressions where a number is used for one slot, and
103  an index for another, yielding a Tensor1_Expr. The non-const
104  versions don't actually create a Tensor2_number_rhs_[01] object.
105  They create a Tensor1_Expr directly, which provides the
106  appropriate indexing operators. The const versions do create a
107  Tensor2_number_[01]. */
108 
109  template <char i, int Dim, int N>
110  typename std::enable_if<
111  (Tensor_Dim0 >= Dim && Tensor_Dim1 > N),
112  Tensor1_Expr<
114  Dim, i>>::type
115  operator()(const Index<i, Dim>, const Number<N>)
116  {
117  using TensorExpr
120  }
121 
122  template <char i, int Dim, int N>
123  typename std::enable_if<
124  (Tensor_Dim0 > N && Tensor_Dim1 >= Dim),
125  Tensor1_Expr<
127  Dim, i>>::type
128  operator()(const Number<N>, const Index<i, Dim>)
129  {
130  using TensorExpr
133  }
134 
135  template <char i, int Dim, int N>
136  typename std::enable_if<
137  (Tensor_Dim0 >= Dim && Tensor_Dim1 > N),
140  T, Dim, i>>::type
141  operator()(const Index<i, Dim>, const Number<N>) const
142  {
143  using TensorExpr
145  return Tensor1_Expr<TensorExpr, T, Dim, i>(TensorExpr(*this));
146  }
147 
148  template <char i, int Dim, int N>
149  typename std::enable_if<
150  (Tensor_Dim0 > N && Tensor_Dim1 >= Dim),
153  T, Dim, i>>::type
154  operator()(const Number<N>, const Index<i, Dim>) const
155  {
156  using TensorExpr
158  return Tensor1_Expr<TensorExpr, T, Dim, i>(TensorExpr(*this));
159  }
160 
161  /* This is for expressions where an actual number (not a Number<>)
162  is used for one slot, and an index for another, yielding a
163  Tensor1_Expr. */
164 
165  /* Unfortunately since this integers can only be checked at run time
166  i can only partially protect this expressions. We should suggest
167  when ever possible to use Number<>. */
168 
169  template <char i, int Dim>
170  typename std::enable_if<
171  (Tensor_Dim0 >= Dim),
172  Tensor1_Expr<
174  Dim, i>>::type
175  operator()(const Index<i, Dim>, const int N) const
176  {
177  using TensorExpr
179  return Tensor1_Expr<TensorExpr, T, Dim, i>(TensorExpr(*this, N));
180  }
181 
182  template <char i, int Dim>
183  typename std::enable_if<
184  (Tensor_Dim1 >= Dim),
185  Tensor1_Expr<
187  Dim, i>>::type
188  operator()(const int N, const Index<i, Dim>) const
189  {
190  using TensorExpr
192  return Tensor1_Expr<TensorExpr, T, Dim, i>(TensorExpr(*this, N));
193  }
194 
195  /* These two operator()'s return the Tensor2 with internal
196  contractions, yielding a T. I have to specify one for both
197  const and non-const because otherwise the compiler will use the
198  operator() which gives a Tensor2_Expr<>. */
199 
200  template <char i, int Dim>
201  typename std::enable_if<(Tensor_Dim0 >= Dim && Tensor_Dim1 >= Dim), T>::type
202  operator()(const Index<i, Dim>, const Index<i, Dim>)
203  {
204  return internal_contract(Number<Dim>());
205  }
206 
207  template <char i, int Dim>
208  typename std::enable_if<(Tensor_Dim0 >= Dim && Tensor_Dim1 >= Dim), T>::type
209  operator()(const Index<i, Dim>, const Index<i, Dim>) const
210  {
211  return internal_contract(Number<Dim>());
212  }
213 
214  private:
215  template <int N> T internal_contract(Number<N>) const
216  {
217  return data[N - 1][N - 1] + internal_contract(Number<N - 1>());
218  }
219 
220  T internal_contract(Number<1>) const { return data[0][0]; }
221  };
222 }
223 
224 /// JSON compatible output
225 
226 namespace FTensor
227 {
228  template <class T, int Tensor_Dim0, int Tensor_Dim1>
229  std::ostream &
230  Tensor2_ostream_row(std::ostream &os,
232  const int &i)
233  {
234  os << '[';
235  for(int j = 0; j + 1 < Tensor_Dim1; ++j)
236  {
237  os << t(i, j) << ',';
238  }
239  if(Tensor_Dim1 > 0)
240  {
241  os << t(i, Tensor_Dim1 - 1);
242  }
243  os << ']';
244  return os;
245  }
246 
247  template <class T, int Tensor_Dim0, int Tensor_Dim1>
248  std::ostream &
249  operator<<(std::ostream &os,
251  os << '[';
252  for (int i = 0; i + 1 < Tensor_Dim0; ++i) {
254  os << ',';
255  }
256  if (Tensor_Dim0 > 0) {
257  FTensor::Tensor2_ostream_row(os, t, Tensor_Dim0 - 1);
258  }
259  os << ']';
260  return os;
261  }
262 }
263 
264 namespace FTensor
265 {
266  template <class T, int Tensor_Dim0, int Tensor_Dim1>
267  std::istream &
268  Tensor2_istream_row(std::istream &is,
270  const int &i)
271  {
272  char c;
273  is >> c;
274  for(int j = 0; j + 1 < Tensor_Dim1; ++j)
275  {
276  is >> t(i, j) >> c;
277  }
278  if(Tensor_Dim1 > 0)
279  {
280  is >> t(i, Tensor_Dim1 - 1);
281  }
282  is >> c;
283  return is;
284  }
285 
286  template <class T, int Tensor_Dim0, int Tensor_Dim1>
287  std::istream &operator>>(std::istream &is,
289  char c;
290  is >> c;
291  for (int i = 0; i + 1 < Tensor_Dim0; ++i) {
293  is >> c;
294  }
295  if (Tensor_Dim0 > 0) {
296  FTensor::Tensor2_istream_row(is, t, Tensor_Dim0 - 1);
297  }
298  is >> c;
299  return is;
300  }
301 }
FTensor::Tensor2::operator()
T operator()(const int N1, const int N2) const
Definition: Tensor2_value.hpp:62
FTensor
JSON compatible output.
Definition: Christof_constructor.hpp:6
FTensor::operator>>
std::istream & operator>>(std::istream &is, FTensor::Tensor1< T, Tensor_Dim > &t)
Definition: Tensor1_value.hpp:109
FTensor::Tensor2_number_rhs_1
Definition: Tensor2_number.hpp:29
FTensor::Tensor2_numeral_1
Definition: Tensor2_numeral.hpp:8
FTensor::Tensor2_Expr
Definition: Tensor2_Expr.hpp:26
FTensor::d
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
FTensor::Tensor2
Definition: Tensor2_value.hpp:16
FTensor::Tensor2::data
T data[Tensor_Dim0][Tensor_Dim1]
Definition: Tensor2_value.hpp:18
FTensor::Tensor2_number_1
Definition: Tensor2_number.hpp:8
c
const double c
speed of light (cm/ns)
Definition: initial_diffusion.cpp:39
FTensor::Number
Definition: Number.hpp:11
FTensor::Tensor1_Expr
Definition: Tensor1_Expr.hpp:27
FTensor::Tensor2_ostream_row
std::ostream & Tensor2_ostream_row(std::ostream &os, const FTensor::Tensor2< T, Tensor_Dim0, Tensor_Dim1 > &t, const int &i)
Definition: Tensor2_value.hpp:230
convert.type
type
Definition: convert.py:64
FTensor::Tensor2::operator()
T & operator()(const int N1, const int N2)
Definition: Tensor2_value.hpp:48
FTensor::Tensor2_istream_row
std::istream & Tensor2_istream_row(std::istream &is, FTensor::Tensor2< T, Tensor_Dim0, Tensor_Dim1 > &t, const int &i)
Definition: Tensor2_value.hpp:268
FTensor::Tensor2_number_0
Definition: Tensor2_number.hpp:17
FTensor::operator<<
std::ostream & operator<<(std::ostream &os, const FTensor::Tensor1< T, Tensor_Dim > &t)
Definition: Tensor1_value.hpp:95
t
constexpr double t
plate stiffness
Definition: plate.cpp:59
i
FTensor::Index< 'i', SPACE_DIM > i
Definition: hcurl_divergence_operator_2d.cpp:27
FTensor::Tensor2::internal_contract
T internal_contract(Number< N >) const
Definition: Tensor2_value.hpp:215
FTensor::Index
Definition: Index.hpp:23
std::enable_if
Definition: enable_if.hpp:7
N
const int N
Definition: speed_test.cpp:3
FTensor::Tensor2::ptr
T * ptr(const int N1, const int N2) const
Definition: Tensor2_value.hpp:33
j
FTensor::Index< 'j', 3 > j
Definition: matrix_function.cpp:19
FTensor::Tensor2_number_rhs_0
Definition: Tensor2_number.hpp:26
FTensor::Tensor2::internal_contract
T internal_contract(Number< 1 >) const
Definition: Tensor2_value.hpp:220
FTensor::Tensor2::Tensor2
Tensor2()
Definition: Tensor2_value.hpp:29
FTensor::Tensor2::Tensor2
Tensor2(U... d)
Definition: Tensor2_value.hpp:22
EshelbianPlasticity::U
@ U
Definition: EshelbianContact.cpp:193
FTensor::Tensor2_numeral_0
Definition: Tensor2_numeral.hpp:18