Schnek
arrayexpression.hpp
1 /*
2  * arrayexpression.hpp
3  *
4  * Created on: 23 Jan 2007
5  * Author: Holger Schmitz
6  * Email: holger@notjustphysics.com
7  *
8  * Copyright 2012 Holger Schmitz
9  *
10  * This file is part of Schnek.
11  *
12  * Schnek is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * Schnek is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Schnek. If not, see <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #ifndef SCHNEK_ARREXPRESSION_H_
28 #define SCHNEK_ARREXPRESSION_H_
29 
30 #include "array.hpp"
31 
32 #include <iostream>
33 
34 namespace schnek {
35 
41 template<class Operator, size_t Length>
42 class ArrayExpression {
43  private:
47  Operator Op;
48  public:
49  typedef typename Operator::value_type value_type;
50 
51  static constexpr size_t length = Length;
52 
54  SCHNEK_INLINE ArrayExpression(const Operator Op_) : Op(Op_) {}
55 
57  SCHNEK_INLINE ArrayExpression(const ArrayExpression &Expr) : Op(Expr.Op) {}
58 
59 // template<template<size_t> class CheckingPolicy>
60 // operator Array<value_type, Length, CheckingPolicy>() {
61 // Array<value_type, Length, CheckingPolicy> value;
62 // for (size_t i=0; i<Length; ++i) value[i] = Op[i];
63 // return value;
64 // }
65 
67  SCHNEK_INLINE value_type operator[](size_t i) const
68  {
69  return Op[i];
70  }
71 };
72 
77 template<class Exp1, class OperatorType>
78 class ArrayUnaryOp {
79  private:
81  Exp1 A;
82  public:
83  typedef typename OperatorType::value_type value_type;
84 
86  SCHNEK_INLINE ArrayUnaryOp(const Exp1 &A_) : A(A_) {}
87 
89  SCHNEK_INLINE ArrayUnaryOp(const ArrayUnaryOp &Op) : A(Op.A) {}
90 
95  SCHNEK_INLINE value_type operator[](size_t i) const { return OperatorType::apply(A[i]); }
96 };
97 
98 
103 template<class Exp1, class Exp2, class OperatorType>
105  private:
107  Exp1 A;
109  Exp2 B;
110  public:
111  typedef typename OperatorType::value_type value_type;
112 
114  SCHNEK_INLINE ArrayBinaryOp(const Exp1 &A_, const Exp2 &B_) : A(A_), B(B_) {}
115 
117  SCHNEK_INLINE ArrayBinaryOp(const ArrayBinaryOp &Op) : A(Op.A), B(Op.B) {}
118 
124  SCHNEK_INLINE value_type operator[](size_t i) const {
125  return OperatorType::apply(A[i], B[i]);
126  }
127 };
128 
129 template<typename T>
131  private:
132  T val;
133  public:
134  typedef T value_type;
135  SCHNEK_INLINE ArrayConstantExp(const T& val_) : val(val_) {}
136  SCHNEK_INLINE value_type operator[](size_t) const { return val; }
137 };
138 
141 template<typename T>
142 struct ArrayOpPlus {
143  typedef T value_type;
144 
146  SCHNEK_INLINE static value_type apply(value_type x, value_type y) {
147  return x+y;
148  }
149 };
150 
153 template<typename T>
154 struct ArrayOpMinus {
155  typedef T value_type;
156 
158  static SCHNEK_INLINE value_type apply(value_type x, value_type y) { return x-y; }
159 };
160 
163 template<typename T>
164 struct ArrayOpMult {
165  typedef T value_type;
166 
168  static SCHNEK_INLINE value_type apply(value_type x, value_type y) { return x*y; }
169 };
170 
173 template<typename T>
174 struct ArrayOpDiv {
175  typedef T value_type;
176 
178  static SCHNEK_INLINE value_type apply(value_type x, value_type y) { return x/y; }
179 };
180 
183 template<typename T>
185  typedef T value_type;
186 
188  static SCHNEK_INLINE value_type apply(value_type x) { return x; }
189 };
190 
193 template<typename T>
195  typedef T value_type;
196 
198  static SCHNEK_INLINE value_type apply(value_type x) { return -x; }
199 };
200 
201 
202 #pragma GCC diagnostic push
203 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
204 
205 //================================================================
206 //======== Here we define all the operators ======================
207 //================================================================
208 
209 // Because I hate writing long lines of templated code, I define a few helper
210 // macros.
211 
212 /* Operator for two ArrayExpression objects */
213 #define EXPR_EXPR(op, symbol) \
214  template<class exp1, class exp2, size_t length> \
215  ArrayExpression< \
216  ArrayBinaryOp< \
217  ArrayExpression<exp1, length>, \
218  ArrayExpression<exp2, length>, \
219  op<typename exp1::value_type> \
220  >, \
221  length \
222  > \
223  SCHNEK_INLINE operator symbol ( \
224  const ArrayExpression<exp1, length> &A, \
225  const ArrayExpression<exp2, length> &B) \
226  { \
227  typedef ArrayBinaryOp \
228  < \
229  ArrayExpression<exp1, length>, \
230  ArrayExpression<exp2, length>, \
231  op<typename exp1::value_type> \
232  > OperatorType; \
233  \
234  return ArrayExpression<OperatorType, length>(OperatorType(A,B)); \
235  }
236 
237 
238 /* Operator for two Arrays */
239 #define ARR_ARR(op, symbol) \
240 template < \
241  class T, \
242  size_t length, \
243  template<size_t> class CheckingPolicy1, \
244  template<size_t> class CheckingPolicy2 \
245 > \
246 ArrayExpression< \
247  ArrayBinaryOp< \
248  ArrayExpression< Array<T,length,CheckingPolicy1>, length >, \
249  ArrayExpression< Array<T,length,CheckingPolicy2>, length >, \
250  op<T> \
251  >, \
252  length \
253 > \
254 SCHNEK_INLINE operator symbol ( \
255  const Array<T,length,CheckingPolicy1> &A, \
256  const Array<T,length,CheckingPolicy2> &B \
257 ) \
258 { \
259  typedef ArrayBinaryOp< \
260  ArrayExpression< Array<T,length,CheckingPolicy1>, length >, \
261  ArrayExpression< Array<T,length,CheckingPolicy2>, length >, \
262  op<T> \
263  > OperatorType; \
264  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
265 }
266 
267 /* Operator for a Array and a ArrayExpression object */
268 #define EXPR_ARR(op, symbol) \
269 template< \
270  class exp, \
271  class T, \
272  size_t length, \
273  template<size_t> class CheckingPolicy \
274 > \
275 ArrayExpression< \
276  ArrayBinaryOp< \
277  ArrayExpression<exp, length>, \
278  ArrayExpression< Array<T,length,CheckingPolicy>, length >, \
279  op<T> \
280  >, \
281  length \
282 > \
283 SCHNEK_INLINE operator symbol ( \
284  const ArrayExpression<exp, length> &A, \
285  const Array<T,length,CheckingPolicy> &B \
286 ) \
287 { \
288  typedef ArrayBinaryOp< \
289  ArrayExpression<exp, length>, \
290  ArrayExpression< Array<T,length,CheckingPolicy>, length >, \
291  op<T> \
292  > OperatorType; \
293  \
294  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
295 }
296 
297 
298 /* Operator for a Array and a ArrayExpression object */
299 #define ARR_EXPR(op, symbol) \
300 template< \
301  class exp, \
302  class T, \
303  size_t length, \
304  template<size_t> class CheckingPolicy \
305 > \
306 ArrayExpression< \
307  ArrayBinaryOp< \
308  ArrayExpression< Array<T,length,CheckingPolicy>, length >, \
309  ArrayExpression<exp, length>, \
310  op<T> \
311  >, \
312  length \
313 > \
314 SCHNEK_INLINE operator symbol ( \
315  const Array<T,length,CheckingPolicy> &A, \
316  const ArrayExpression<exp, length> &B \
317 ) \
318 { \
319  typedef ArrayBinaryOp< \
320  ArrayExpression< Array<T,length,CheckingPolicy>, length >, \
321  ArrayExpression<exp, length>, \
322  op<T> \
323  > OperatorType; \
324  \
325  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
326 }
327 
328 /* Operator for a Scalar and a ArrayExpression object */
329 #define SCAL_EXPR(op, symbol) \
330 template<class T, class exp, size_t length> \
331 ArrayExpression< \
332  ArrayBinaryOp< \
333  ArrayConstantExp<T>, \
334  ArrayExpression<exp, length>, \
335  op<T> \
336  >, \
337  length \
338 > \
339 SCHNEK_INLINE operator symbol (const T &A, const ArrayExpression<exp, length> &B) \
340 { \
341  typedef ArrayBinaryOp< \
342  ArrayConstantExp<T>, \
343  ArrayExpression<exp, length>, \
344  op<T> \
345  > OperatorType; \
346  \
347  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
348 }
349 
350 /* Operator for a ArrayExpression and a Scalar object */
351 #define EXPR_SCAL(op, symbol) \
352 template<class T, class exp, size_t length> \
353 ArrayExpression< \
354  ArrayBinaryOp< \
355  ArrayExpression<exp, length>, \
356  ArrayConstantExp<T>, \
357  op<T> \
358  >, \
359  length \
360 > \
361 SCHNEK_INLINE operator symbol (const ArrayExpression<exp, length> &A, const T &B) \
362 { \
363  typedef ArrayBinaryOp< \
364  ArrayExpression<exp, length>, \
365  ArrayConstantExp<T>, \
366  op<T> \
367  > OperatorType; \
368  \
369  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
370 }
371 /* Operator for a Scalar and a Array object */
372 #define SCAL_ARR(op, symbol) \
373 template<class T, size_t length, template<size_t> class CheckingPolicy> \
374 ArrayExpression< \
375  ArrayBinaryOp< \
376  ArrayConstantExp<T>, \
377  Array<T,length,CheckingPolicy>, \
378  op<T> \
379  >, \
380  length \
381 > \
382 SCHNEK_INLINE operator symbol (const T &A, const Array<T,length,CheckingPolicy> &B) \
383 { \
384  typedef ArrayBinaryOp< \
385  ArrayConstantExp<T>, \
386  Array<T,length,CheckingPolicy>, \
387  op<T> \
388  > OperatorType; \
389  \
390  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
391 }
392 
393 /* Operator for a Array and a Scalar object */
394 #define ARR_SCAL(op, symbol) \
395 template<class T, size_t length, template<size_t> class CheckingPolicy> \
396 ArrayExpression< \
397  ArrayBinaryOp< \
398  Array<T,length,CheckingPolicy>, \
399  ArrayConstantExp<T>, \
400  op<T> \
401  >, \
402  length \
403 > \
404 SCHNEK_INLINE operator symbol (const Array<T,length,CheckingPolicy> &A, const T &B) \
405 { \
406  typedef ArrayBinaryOp< \
407  Array<T,length,CheckingPolicy>, \
408  ArrayConstantExp<T>, \
409  op<T> \
410  > OperatorType; \
411  \
412  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
413 }
414 
415 /* Unary Operator for Arrays */
416 #define UNARY_ARR(op, symbol) \
417 template < \
418  class T, \
419  size_t length, \
420  template<size_t> class CheckingPolicy1 \
421 > \
422 ArrayExpression< \
423  ArrayUnaryOp< \
424  ArrayExpression< Array<T,length,CheckingPolicy1>, length >, \
425  op<T> \
426  >, \
427  length \
428 > \
429 SCHNEK_INLINE operator symbol ( \
430  const Array<T,length,CheckingPolicy1> &A \
431 ) \
432 { \
433  typedef ArrayUnaryOp< \
434  ArrayExpression< Array<T,length,CheckingPolicy1>, length >, \
435  op<T> \
436  > OperatorType; \
437  \
438  return ArrayExpression<OperatorType, length> (OperatorType(A)); \
439 }
440 
441 
442 /* Operator for a Array and a ArrayExpression object */
443 #define UNARY_EXPR(op, symbol) \
444 template< \
445  class exp, \
446  class T, \
447  size_t length, \
448  template<size_t> class CheckingPolicy \
449 > \
450 ArrayExpression< \
451  ArrayUnaryOp< \
452  ArrayExpression<exp, length>, \
453  op<T> \
454  >, \
455  length \
456 > \
457 SCHNEK_INLINE operator symbol ( \
458  const ArrayExpression<exp, length> &A \
459 ) \
460 { \
461  typedef ArrayUnaryOp< \
462  ArrayExpression<exp, length>, \
463  op<T> \
464  > OperatorType; \
465  \
466  return ArrayExpression<OperatorType, length> (OperatorType(A)); \
467 }
468 
469 //======== Plus ======================
470 
471 EXPR_EXPR(ArrayOpPlus,+)
472 ARR_ARR(ArrayOpPlus,+)
473 EXPR_ARR(ArrayOpPlus,+)
474 ARR_EXPR(ArrayOpPlus,+)
475 
476 EXPR_SCAL(ArrayOpPlus,+)
477 SCAL_EXPR(ArrayOpPlus,+)
478 ARR_SCAL(ArrayOpPlus,+)
479 SCAL_ARR(ArrayOpPlus,+)
480 
481 //======== Minus ======================
482 
483 EXPR_EXPR(ArrayOpMinus,-)
484 ARR_ARR(ArrayOpMinus,-)
485 EXPR_ARR(ArrayOpMinus,-)
486 ARR_EXPR(ArrayOpMinus,-)
487 
488 EXPR_SCAL(ArrayOpMinus,-)
489 SCAL_EXPR(ArrayOpMinus,-)
490 ARR_SCAL(ArrayOpMinus,-)
491 SCAL_ARR(ArrayOpMinus,-)
492 
493 
494 //======== Multiplication ======================
495 
496 EXPR_EXPR(ArrayOpMult,*)
497 ARR_ARR(ArrayOpMult,*)
498 EXPR_ARR(ArrayOpMult,*)
499 ARR_EXPR(ArrayOpMult,*)
500 
501 EXPR_SCAL(ArrayOpMult,*)
502 SCAL_EXPR(ArrayOpMult,*)
503 ARR_SCAL(ArrayOpMult,*)
504 SCAL_ARR(ArrayOpMult,*)
505 
506 //======== Division ======================
507 
508 EXPR_EXPR(ArrayOpDiv,/)
509 ARR_ARR(ArrayOpDiv,/)
510 EXPR_ARR(ArrayOpDiv,/)
511 ARR_EXPR(ArrayOpDiv,/)
512 
513 EXPR_SCAL(ArrayOpDiv,/)
514 SCAL_EXPR(ArrayOpDiv,/)
515 ARR_SCAL(ArrayOpDiv,/)
516 SCAL_ARR(ArrayOpDiv,/)
517 
518 
519 //======== Unary Plus and Minus ======================
520 
521 UNARY_ARR(ArrayOpUnaryPlus,+)
522 UNARY_EXPR(ArrayOpUnaryPlus,+)
523 
524 UNARY_ARR(ArrayOpUnaryMinus,-)
525 UNARY_EXPR(ArrayOpUnaryMinus,-)
526 
527 #undef EXPR_EXPR
528 #undef ARR_ARR
529 #undef ARR_EXPR
530 #undef EXPR_ARR
531 #undef EXPR_SCAL
532 #undef SCAL_EXPR
533 #undef ARR_SCAL
534 #undef SCAL_ARR
535 #undef UNARY_ARR
536 #undef UNARY_EXPR
537 
538 #pragma GCC diagnostic pop
539 
540 template<class T, size_t Length, template <size_t> class CheckingPolicy>
541 template<class Operator>
543 {
544  for (size_t i=0; i<Length; ++i)
545  {
546  data[i] = expr[i];
547  }
548  return *this;
549 }
550 
551 template<class T, size_t Length, template <size_t> class CheckingPolicy>
552 template<class Operator>
554 {
555  for (size_t i=0; i<Length; ++i)
556  data[i] += expr[i];
557  return *this;
558 }
559 
560 template<class T, size_t Length, template <size_t> class CheckingPolicy>
561 template<class Operator>
563 {
564  for (size_t i=0; i<Length; ++i)
565  data[i] -= expr[i];
566  return *this;
567 }
568 
569 template<class T, size_t Length, template <size_t> class CheckingPolicy>
570 template<class Operator>
572 {
573  for (size_t i=0; i<Length; ++i)
574  data[i] *= expr[i];
575  return *this;
576 }
577 
578 template<class T, size_t Length, template <size_t> class CheckingPolicy>
579 template<class Operator>
581 {
582  for (size_t i=0; i<Length; ++i)
583  data[i] /= expr[i];
584  return *this;
585 }
586 
587 
588 
589 template<class T, size_t Length, template <size_t> class CheckingPolicy>
590 template<class Operator>
592 {
593  for (size_t i=0; i<Length; ++i)
594  {
595  data[i] = expr[i];
596  }
597 }
598 } // namespace schnek
599 
600 #endif // SCHNEK_ARRAYEXPRESSION_H_
SCHNEK_INLINE Array< T, Length, CheckingPolicy > & operator+=(const Array< T2, Length, CheckingPolicy2 > &)
Definition: operators2.hpp:34
Definition: array.hpp:55
SCHNEK_INLINE Array()
The default constructor.
Definition: array.hpp:40
Definition: arrayexpression.hpp:154
static SCHNEK_INLINE value_type apply(value_type x)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:198
Definition: arrayexpression.hpp:130
Definition: algo.hpp:30
SCHNEK_INLINE ArrayBinaryOp(const Exp1 &A_, const Exp2 &B_)
Definition: arrayexpression.hpp:114
static SCHNEK_INLINE value_type apply(value_type x)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:188
Definition: arrayexpression.hpp:164
static SCHNEK_INLINE value_type apply(value_type x, value_type y)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:178
SCHNEK_INLINE value_type operator[](size_t i) const
Definition: arrayexpression.hpp:95
Definition: arrayexpression.hpp:104
SCHNEK_INLINE ArrayExpression(const Operator Op_)
Definition: arrayexpression.hpp:54
Definition: arrayexpression.hpp:142
SCHNEK_INLINE value_type operator[](size_t i) const
Definition: arrayexpression.hpp:124
Definition: arrayexpression.hpp:78
static SCHNEK_INLINE value_type apply(value_type x, value_type y)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:158
static SCHNEK_INLINE value_type apply(value_type x, value_type y)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:146
SCHNEK_INLINE Array< T, Length, CheckingPolicy > & operator*=(const Array< T2, Length, CheckingPolicy2 > &)
SCHNEK_INLINE value_type operator[](size_t i) const
Definition: arrayexpression.hpp:67
SCHNEK_INLINE ArrayUnaryOp(const ArrayUnaryOp &Op)
Definition: arrayexpression.hpp:89
SCHNEK_INLINE Array< T, Length, CheckingPolicy > & operator=(const Array< T2, Length, CheckingPolicy2 > &)
static SCHNEK_INLINE value_type apply(value_type x, value_type y)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:168
Definition: arrayexpression.hpp:194
SCHNEK_INLINE Array< T, Length, CheckingPolicy > & operator/=(const Array< T2, Length, CheckingPolicy2 > &)
SCHNEK_INLINE ArrayBinaryOp(const ArrayBinaryOp &Op)
Definition: arrayexpression.hpp:117
SCHNEK_INLINE ArrayUnaryOp(const Exp1 &A_)
Definition: arrayexpression.hpp:86
SCHNEK_INLINE Array< T, Length, CheckingPolicy > & operator-=(const Array< T2, Length, CheckingPolicy2 > &)
Definition: arrayexpression.hpp:174
SCHNEK_INLINE ArrayExpression(const ArrayExpression &Expr)
Definition: arrayexpression.hpp:57
Definition: arrayexpression.hpp:184