v0.13.1
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
14namespace 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
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),
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),
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),
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),
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 {
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 {
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
226namespace 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
264namespace 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}
static Number< 2 > N2
static Number< 1 > N1
T & operator()(const int N1, const int N2)
T data[Tensor_Dim0][Tensor_Dim1]
T internal_contract(Number< 1 >) const
T internal_contract(Number< N >) const
T * ptr(const int N1, const int N2) const
T operator()(const int N1, const int N2) const
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
const double T
Tensors class implemented by Walter Landry.
Definition: FTensor.hpp:51
std::ostream & Tensor2_ostream_row(std::ostream &os, const FTensor::Tensor2< T, Tensor_Dim0, Tensor_Dim1 > &t, const int &i)
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
std::istream & operator>>(std::istream &is, FTensor::Tensor1< T, Tensor_Dim > &t)
std::ostream & operator<<(std::ostream &os, const FTensor::Tensor1< T, Tensor_Dim > &t)
std::istream & Tensor2_istream_row(std::istream &is, FTensor::Tensor2< T, Tensor_Dim0, Tensor_Dim1 > &t, const int &i)
constexpr double t
plate stiffness
Definition: plate.cpp:76
const int N
Definition: speed_test.cpp:3