v0.16.0
Loading...
Searching...
No Matches
Tensor2_pointer.hpp
Go to the documentation of this file.
1/* A version for pointers. */
2
3#pragma once
4
5namespace FTensor {
6
7template <class T, int Tensor_Dim0, int Tensor_Dim1>
8class Tensor2<T *, Tensor_Dim0, Tensor_Dim1> {
9
10protected:
11 mutable T *restrict data[Tensor_Dim0][Tensor_Dim1];
12 const int inc;
13
14public:
15 /* Initializations for varying numbers of elements. */
16
17 Tensor2(T *d00, T *d01, T *d10, T *d11, const int i) : inc(i) {
19 data, d00, d01, d10, d11);
20 }
21 Tensor2(T *d00, T *d01, T *d10, T *d11, T *d20, T *d21, const int i)
22 : inc(i) {
24 data, d00, d01, d10, d11, d20, d21);
25 }
26 Tensor2(T *d00, T *d01, T *d02, T *d10, T *d11, T *d12, T *d20, T *d21,
27 T *d22, const int i)
28 : inc(i) {
30 data, d00, d01, d02, d10, d11, d12, d20, d21, d22);
31 }
32 Tensor2(T *d00, T *d01, T *d02, T *d03, T *d10, T *d11, T *d12, T *d13,
33 T *d20, T *d21, T *d22, T *d23, T *d30, T *d31, T *d32, T *d33,
34 const int i)
35 : inc(i) {
37 data, d00, d01, d02, d03, d10, d11, d12, d13, d20, d21, d22, d23, d30,
38 d31, d32, d33);
39 }
40
41 /* Initializations for varying numbers of elements. */
42 template <class... U> Tensor2(U *...d) : data{d...}, inc(1) {}
43
44 template <class U>
45 Tensor2(std::array<U *, Tensor_Dim0 * Tensor_Dim1> &a, const int i = 1)
46 : inc(i) {
47 int k = 0;
48 for (int i = 0; i != Tensor_Dim0; ++i) {
49 for (int j = 0; j != Tensor_Dim1; ++j, ++k) {
50 data[i][j] = a[k];
51 }
52 }
53 }
54
56
57 Tensor2(const int i = 1) : inc(i) {}
58
59 /* There are two operator(int,int)'s, one for non-consts that lets you
60 change the value, and one for consts that doesn't. */
61
62 T &operator()(const int N1, const int N2) {
63#ifdef FTENSOR_DEBUG
64 if (N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) {
65 std::stringstream s;
66 s << "Bad index in Tensor2<T*," << Tensor_Dim0 << "," << Tensor_Dim1
67 << ">.operator(" << N1 << "," << N2 << ")" << std::endl;
68 throw std::out_of_range(s.str());
69 }
70#endif
71 return *data[N1][N2];
72 }
73
74 T operator()(const int N1, const int N2) const {
75#ifdef FTENSOR_DEBUG
76 if (N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) {
77 std::stringstream s;
78 s << "Bad index in Tensor2<T*," << Tensor_Dim0 << "," << Tensor_Dim1
79 << ">.operator(" << N1 << "," << N2 << ") const" << std::endl;
80 throw std::out_of_range(s.str());
81 }
82#endif
83 return *data[N1][N2];
84 }
85
86 T *ptr(const int N1, const int N2) const {
87#ifdef FTENSOR_DEBUG
88 if (N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) {
89 std::stringstream s;
90 s << "Bad index in Tensor2<T*," << Tensor_Dim0 << "," << Tensor_Dim1
91 << ">.ptr(" << N1 << "," << N2 << ")" << std::endl;
92 throw std::out_of_range(s.str());
93 }
94#endif
95 return data[N1][N2];
96 }
97
98 /* These operator()'s are the first part in constructing template
99 expressions. They can be used to slice off lower dimensional
100 parts. They are not entirely safe, since you can accidentaly use a
101 higher dimension than what is really allowed (like Dim=5). */
102
103 template <char i, char j, int Dim0, int Dim1>
107 i, j>(*this);
108 }
109
110 template <char i, char j, int Dim0, int Dim1>
112 j>
113 operator()(const Index<i, Dim0>, const Index<j, Dim1> index2) const {
115 Dim1, i, j>(*this);
116 }
117
118 /* This is for expressions where a number is used for one slot, and
119 an index for another, yielding a Tensor1_Expr. The non-const
120 versions don't actually create a Tensor2_number_rhs_[01] object.
121 They create a Tensor1_Expr directly, which provides the
122 appropriate indexing operators. The const versions do create a
123 Tensor2_number_[01]. */
124
125 template <char i, int Dim, int N>
128 Dim, i>
134
135 template <char i, int Dim, int N>
138 Dim, i>
144
145 template <char i, int Dim, int N>
148 T, Dim, i>
149 operator()(const Index<i, Dim>, const Number<N>) const {
150 using TensorExpr =
152 return Tensor1_Expr<TensorExpr, T, Dim, i>(TensorExpr(*this));
153 }
154
155 template <char i, int Dim, int N>
158 T, Dim, i>
159 operator()(const Number<N>, const Index<i, Dim>) const {
160 using TensorExpr =
162 return Tensor1_Expr<TensorExpr, T, Dim, i>(TensorExpr(*this));
163 }
164
165 /* The ++ operator increments the pointer, not the number that the
166 pointer points to. This allows iterating over a grid. */
167
168 const Tensor2 &operator++() const {
169 for (int i = 0; i < Tensor_Dim0; ++i)
170 for (int j = 0; j < Tensor_Dim1; ++j)
171 data[i][j] += inc;
172 return *this;
173 }
174
175 /* These two operator()'s return the Tensor2 with internal
176 contractions, yielding a T. I have to specify one for both
177 const and non-const because otherwise they compiler will use the
178 operator() which gives a Tensor2_Expr<>. */
179
180 template <char i, int Dim>
181 T operator()(const Index<i, Dim>, const Index<i, Dim> index2) {
182 return internal_contract(Number<Dim>());
183 }
184
185 template <char i, int Dim>
186 T operator()(const Index<i, Dim>, const Index<i, Dim> index2) const {
187 return internal_contract(Number<Dim>());
188 }
189
190private:
191 template <int N> T internal_contract(Number<N>) const {
192 return *data[N - 1][N - 1] + internal_contract(Number<N - 1>());
193 }
194
195 T internal_contract(Number<1>) const { return *data[0][0]; }
196
197private:
198 /**
199 * @brief Preventing casting on derived class
200 *
201 * That can be source of errors
202 *
203 */
204 template <int I>
205 Tensor2(const Tensor2<PackPtr<T *, I>, Tensor_Dim0, Tensor_Dim1> &) = delete;
206
207 template <int G>
208 Tensor2(const Tensor2<CursorPtr<T *, G>, Tensor_Dim0, Tensor_Dim1> &) =
209 delete;
210};
211
212template <class T, int Tensor_Dim0, int Tensor_Dim1, int I>
213class Tensor2<PackPtr<T *, I>, Tensor_Dim0, Tensor_Dim1>
215
216public:
217 /* Initializations for varying numbers of elements. */
218 template <class... U>
219 Tensor2(U *...d) : Tensor2<T *, Tensor_Dim0, Tensor_Dim1>(d...) {}
220
221 Tensor2() : Tensor2<T *, Tensor_Dim0, Tensor_Dim1>() {}
222
223 template <class U>
224 Tensor2(std::array<U *, Tensor_Dim0 * Tensor_Dim1> &a)
225 : Tensor2<T *, Tensor_Dim0, Tensor_Dim1>(a) {}
226
227 /* The ++ operator increments the pointer, not the number that the
228 pointer points to. This allows iterating over a grid. */
229
230 const Tensor2 &operator++() const {
231 for (int i = 0; i < Tensor_Dim0; ++i)
232 for (int j = 0; j < Tensor_Dim1; ++j)
234 return *this;
235 }
236};
237
238template <class T, int Tensor_Dim0, int Tensor_Dim1, int G>
239class Tensor2<CursorPtr<T *, G>, Tensor_Dim0, Tensor_Dim1> {
240
241 using Self = Tensor2<CursorPtr<T *, G>, Tensor_Dim0, Tensor_Dim1>;
242
243 mutable T *restrict data;
244
245 static constexpr int getFlatIndex(const int N1, const int N2) {
246 return Tensor_Dim1 * N1 + N2;
247 }
248
249public:
250 explicit Tensor2(T *d) : data(d) {}
251
252 Tensor2() = delete;
253
254 T &operator()(const int N1, const int N2) {
255#ifdef FTENSOR_DEBUG
256 if (N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) {
257 std::stringstream s;
258 s << "Bad index in Tensor2<CursorPtr<T*," << G << ">," << Tensor_Dim0
259 << "," << Tensor_Dim1 << ">.operator(" << N1 << "," << N2 << ")"
260 << std::endl;
261 throw std::out_of_range(s.str());
262 }
263#endif
264 return *(data + getFlatIndex(N1, N2));
265 }
266
267 T operator()(const int N1, const int N2) const {
268#ifdef FTENSOR_DEBUG
269 if (N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) {
270 std::stringstream s;
271 s << "Bad index in Tensor2<CursorPtr<T*," << G << ">," << Tensor_Dim0
272 << "," << Tensor_Dim1 << ">.operator(" << N1 << "," << N2 << ") const"
273 << std::endl;
274 throw std::out_of_range(s.str());
275 }
276#endif
277 return *(data + getFlatIndex(N1, N2));
278 }
279
280 T *ptr(const int N1, const int N2) const {
281#ifdef FTENSOR_DEBUG
282 if (N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) {
283 std::stringstream s;
284 s << "Bad index in Tensor2<CursorPtr<T*," << G << ">," << Tensor_Dim0
285 << "," << Tensor_Dim1 << ">.ptr(" << N1 << "," << N2 << ")"
286 << std::endl;
287 throw std::out_of_range(s.str());
288 }
289#endif
290 const int flat_index = getFlatIndex(N1, N2);
291 return data + flat_index;
292 }
293
294 template <char i, char j, int Dim0, int Dim1>
299
300 template <char i, char j, int Dim0, int Dim1>
305
306 template <char i, int Dim, int N>
309 using TensorExpr = Tensor2_number_rhs_1<Self, T, N>;
311 }
312
313 template <char i, int Dim, int N>
316 using TensorExpr = Tensor2_number_rhs_0<Self, T, N>;
318 }
319
320 template <char i, int Dim, int N>
322 operator()(const Index<i, Dim>, const Number<N>) const {
323 using TensorExpr = Tensor2_number_1<const Self, T, N>;
324 return Tensor1_Expr<TensorExpr, T, Dim, i>(TensorExpr(*this));
325 }
326
327 template <char i, int Dim, int N>
329 operator()(const Number<N>, const Index<i, Dim>) const {
330 using TensorExpr = Tensor2_number_0<const Self, T, N>;
331 return Tensor1_Expr<TensorExpr, T, Dim, i>(TensorExpr(*this));
332 }
333
334 const Tensor2 &operator++() const {
335 data += G;
336 return *this;
337 }
338
339 template <char i, int Dim>
341 return internal_contract(Number<Dim>());
342 }
343
344 template <char i, int Dim>
345 T operator()(const Index<i, Dim>, const Index<i, Dim>) const {
346 return internal_contract(Number<Dim>());
347 }
348
349private:
350 template <int N> T internal_contract(Number<N>) const {
351 return (*this)(N - 1, N - 1) + internal_contract(Number<N - 1>());
352 }
353
354 T internal_contract(Number<1>) const { return (*this)(0, 0); }
355};
356
357} // namespace FTensor
constexpr double a
Tensor1_Expr< const Tensor2_number_0< const Self, T, N >, T, Dim, i > operator()(const Number< N >, const Index< i, Dim >) const
Tensor2_Expr< const Self, T, Dim0, Dim1, i, j > operator()(const Index< i, Dim0 >, const Index< j, Dim1 >) const
Tensor1_Expr< const Tensor2_number_1< const Self, T, N >, T, Dim, i > operator()(const Index< i, Dim >, const Number< N >) const
static constexpr int getFlatIndex(const int N1, const int N2)
T operator()(const Index< i, Dim >, const Index< i, Dim >) const
Tensor1_Expr< Tensor2_number_rhs_1< Self, T, N >, T, Dim, i > operator()(const Index< i, Dim >, const Number< N >)
Tensor1_Expr< Tensor2_number_rhs_0< Self, T, N >, T, Dim, i > operator()(const Number< N >, const Index< i, Dim >)
T operator()(const Index< i, Dim >, const Index< i, Dim >)
Tensor2_Expr< Self, T, Dim0, Dim1, i, j > operator()(const Index< i, Dim0 >, const Index< j, Dim1 >)
Tensor2(std::array< U *, Tensor_Dim0 *Tensor_Dim1 > &a)
Tensor2(const Tensor2< PackPtr< T *, I >, Tensor_Dim0, Tensor_Dim1 > &)=delete
Preventing casting on derived class.
Tensor1_Expr< const Tensor2_number_0< const Tensor2< T *, Tensor_Dim0, Tensor_Dim1 >, T, N >, T, Dim, i > operator()(const Number< N >, const Index< i, Dim >) const
Tensor2(T *d00, T *d01, T *d10, T *d11, T *d20, T *d21, const int i)
T operator()(const int N1, const int N2) const
Tensor1_Expr< Tensor2_number_rhs_1< Tensor2< T *, Tensor_Dim0, Tensor_Dim1 >, T, N >, T, Dim, i > operator()(const Index< i, Dim >, const Number< N >)
Tensor1_Expr< const Tensor2_number_1< const Tensor2< T *, Tensor_Dim0, Tensor_Dim1 >, T, N >, T, Dim, i > operator()(const Index< i, Dim >, const Number< N >) const
Tensor2(T *d00, T *d01, T *d10, T *d11, const int i)
Tensor2(T *d00, T *d01, T *d02, T *d03, T *d10, T *d11, T *d12, T *d13, T *d20, T *d21, T *d22, T *d23, T *d30, T *d31, T *d32, T *d33, const int i)
Tensor2_Expr< Tensor2< T *, Tensor_Dim0, Tensor_Dim1 >, T, Dim0, Dim1, i, j > operator()(const Index< i, Dim0 >, const Index< j, Dim1 > index2)
Tensor2(std::array< U *, Tensor_Dim0 *Tensor_Dim1 > &a, const int i=1)
Tensor1_Expr< Tensor2_number_rhs_0< Tensor2< T *, Tensor_Dim0, Tensor_Dim1 >, T, N >, T, Dim, i > operator()(const Number< N >, const Index< i, Dim >)
Tensor2(T *d00, T *d01, T *d02, T *d10, T *d11, T *d12, T *d20, T *d21, T *d22, const int i)
T operator()(const Index< i, Dim >, const Index< i, Dim > index2) const
Tensor2_Expr< const Tensor2< T *, Tensor_Dim0, Tensor_Dim1 >, T, Dim0, Dim1, i, j > operator()(const Index< i, Dim0 >, const Index< j, Dim1 > index2) const
T * ptr(const int N1, const int N2) const
Tensor2(const Tensor2< CursorPtr< T *, G >, Tensor_Dim0, Tensor_Dim1 > &)=delete
T operator()(const Index< i, Dim >, const Index< i, Dim > index2)
FTensor::Index< 'i', SPACE_DIM > i
constexpr IntegrationType G
Definition level_set.cpp:33
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
Tensors class implemented by Walter Landry.
Definition FTensor.hpp:51
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
constexpr IntegrationType I
const int N
Definition speed_test.cpp:3