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, int Length>
42 class ArrayExpression {
43  private:
47  Operator Op;
48  public:
49  typedef typename Operator::value_type value_type;
50 
51  static const int length = Length;
52 
54  ArrayExpression(const Operator Op_) : Op(Op_) {}
55 
57  ArrayExpression(const ArrayExpression &Expr) : Op(Expr.Op) {}
58 
61  }
62 
63  template<template<int> class CheckingPolicy>
66  }
67 
68 // template<template<int> class CheckingPolicy>
69 // operator Array<value_type, Length, CheckingPolicy>() {
70 // Array<value_type, Length, CheckingPolicy> value;
71 // for (int i=0; i<Length; ++i) value[i] = Op[i];
72 // return value;
73 // }
74 
76  value_type operator[](int i) const
77  {
78 // value_type result = Op[i];
79 // std::cerr << "ArrayExpression -- " << result << std::endl;
80 // return result;
81  return Op[i];
82  }
83 };
84 
89 template<class Exp1, class OperatorType>
90 class ArrayUnaryOp {
91  private:
93  Exp1 A;
94  public:
95  typedef typename OperatorType::value_type value_type;
96 
98  ArrayUnaryOp(const Exp1 &A_) : A(A_) {}
99 
101  ArrayUnaryOp(const ArrayUnaryOp &Op) : A(Op.A) {}
102 
107  value_type operator[](int i) const { return OperatorType::apply(A[i]); }
108 };
109 
110 
115 template<class Exp1, class Exp2, class OperatorType>
117  private:
119  Exp1 A;
121  Exp2 B;
122  public:
123  typedef typename OperatorType::value_type value_type;
124 
126  ArrayBinaryOp(const Exp1 &A_, const Exp2 &B_) : A(A_), B(B_) {}
127 
129  ArrayBinaryOp(const ArrayBinaryOp &Op) : A(Op.A), B(Op.B) {}
130 
135  value_type operator[](int i) const { return OperatorType::apply(A[i], B[i]); }
136 };
137 
138 template<typename T>
140  private:
141  T val;
142  public:
143  typedef T value_type;
144  ArrayConstantExp(const T& val_) : val(val_) {}
145  value_type operator[](int i) const { return val; }
146 };
147 
150 template<typename T>
151 struct ArrayOpPlus {
152  typedef T value_type;
153 
155  static value_type apply(value_type x, value_type y) { return x+y; }
156 };
157 
160 template<typename T>
161 struct ArrayOpMinus {
162  typedef T value_type;
163 
165  static value_type apply(value_type x, value_type y) { return x-y; }
166 };
167 
170 template<typename T>
171 struct ArrayOpMult {
172  typedef T value_type;
173 
175  static value_type apply(value_type x, value_type y) { return x*y; }
176 };
177 
180 template<typename T>
181 struct ArrayOpDiv {
182  typedef T value_type;
183 
185  static value_type apply(value_type x, value_type y) { return x/y; }
186 };
187 
190 template<typename T>
192  typedef T value_type;
193 
195  static value_type apply(value_type x) { return x; }
196 };
197 
200 template<typename T>
202  typedef T value_type;
203 
205  static value_type apply(value_type x) { return -x; }
206 };
207 
208 
209 //================================================================
210 //======== Here we define all the operators ======================
211 //================================================================
212 
213 // Because I hate writing long lines of templated code, I define a few helper
214 // macros.
215 
216 /* Operator for two ArrayExpression objects */
217 #define EXPR_EXPR(op, symbol) \
218  template<class exp1, class exp2, int length> \
219  ArrayExpression< \
220  ArrayBinaryOp< \
221  ArrayExpression<exp1, length>, \
222  ArrayExpression<exp2, length>, \
223  op<typename exp1::value_type> \
224  >, \
225  length \
226  > \
227  operator symbol ( \
228  const ArrayExpression<exp1, length> &A, \
229  const ArrayExpression<exp2, length> &B) \
230  { \
231  typedef ArrayBinaryOp \
232  < \
233  ArrayExpression<exp1, length>, \
234  ArrayExpression<exp2, length>, \
235  op<typename exp1::value_type> \
236  > OperatorType; \
237  \
238  return ArrayExpression<OperatorType, length>(OperatorType(A,B)); \
239  }
240 
241 
242 /* Operator for two Arrays */
243 #define ARR_ARR(op, symbol) \
244 template < \
245  class T, \
246  int length, \
247  template<int> class CheckingPolicy1, \
248  template<int> class CheckingPolicy2 \
249 > \
250 ArrayExpression< \
251  ArrayBinaryOp< \
252  ArrayExpression< Array<T,length,CheckingPolicy1>, length >, \
253  ArrayExpression< Array<T,length,CheckingPolicy2>, length >, \
254  op<T> \
255  >, \
256  length \
257 > \
258 operator symbol ( \
259  const Array<T,length,CheckingPolicy1> &A, \
260  const Array<T,length,CheckingPolicy2> &B \
261 ) \
262 { \
263  typedef ArrayBinaryOp< \
264  ArrayExpression< Array<T,length,CheckingPolicy1>, length >, \
265  ArrayExpression< Array<T,length,CheckingPolicy2>, length >, \
266  op<T> \
267  > OperatorType; \
268  \
269  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
270 }
271 
272 /* Operator for a Array and a ArrayExpression object */
273 #define EXPR_ARR(op, symbol) \
274 template< \
275  class exp, \
276  class T, \
277  int length, \
278  template<int> class CheckingPolicy \
279 > \
280 ArrayExpression< \
281  ArrayBinaryOp< \
282  ArrayExpression<exp, length>, \
283  ArrayExpression< Array<T,length,CheckingPolicy>, length >, \
284  op<T> \
285  >, \
286  length \
287 > \
288 operator symbol ( \
289  const ArrayExpression<exp, length> &A, \
290  const Array<T,length,CheckingPolicy> &B \
291 ) \
292 { \
293  typedef ArrayBinaryOp< \
294  ArrayExpression<exp, length>, \
295  ArrayExpression< Array<T,length,CheckingPolicy>, length >, \
296  op<T> \
297  > OperatorType; \
298  \
299  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
300 }
301 
302 
303 /* Operator for a Array and a ArrayExpression object */
304 #define ARR_EXPR(op, symbol) \
305 template< \
306  class exp, \
307  class T, \
308  int length, \
309  template<int> class CheckingPolicy \
310 > \
311 ArrayExpression< \
312  ArrayBinaryOp< \
313  ArrayExpression< Array<T,length,CheckingPolicy>, length >, \
314  ArrayExpression<exp, length>, \
315  op<T> \
316  >, \
317  length \
318 > \
319 operator symbol ( \
320  const Array<T,length,CheckingPolicy> &A, \
321  const ArrayExpression<exp, length> &B \
322 ) \
323 { \
324  typedef ArrayBinaryOp< \
325  ArrayExpression< Array<T,length,CheckingPolicy>, length >, \
326  ArrayExpression<exp, length>, \
327  op<T> \
328  > OperatorType; \
329  \
330  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
331 }
332 
333 /* Operator for a Scalar and a ArrayExpression object */
334 #define SCAL_EXPR(op, symbol) \
335 template<class T, class exp, int length> \
336 ArrayExpression< \
337  ArrayBinaryOp< \
338  ArrayConstantExp<T>, \
339  ArrayExpression<exp, length>, \
340  op<T> \
341  >, \
342  length \
343 > \
344 operator symbol (const T &A, const ArrayExpression<exp, length> &B) \
345 { \
346  typedef ArrayBinaryOp< \
347  ArrayConstantExp<T>, \
348  ArrayExpression<exp, length>, \
349  op<T> \
350  > OperatorType; \
351  \
352  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
353 }
354 
355 /* Operator for a ArrayExpression and a Scalar object */
356 #define EXPR_SCAL(op, symbol) \
357 template<class T, class exp, int length> \
358 ArrayExpression< \
359  ArrayBinaryOp< \
360  ArrayExpression<exp, length>, \
361  ArrayConstantExp<T>, \
362  op<T> \
363  >, \
364  length \
365 > \
366 operator symbol (const ArrayExpression<exp, length> &A, const T &B) \
367 { \
368  typedef ArrayBinaryOp< \
369  ArrayExpression<exp, length>, \
370  ArrayConstantExp<T>, \
371  op<T> \
372  > OperatorType; \
373  \
374  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
375 }
376 /* Operator for a Scalar and a Array object */
377 #define SCAL_ARR(op, symbol) \
378 template<class T, int length, template<int> class CheckingPolicy> \
379 ArrayExpression< \
380  ArrayBinaryOp< \
381  ArrayConstantExp<T>, \
382  Array<T,length,CheckingPolicy>, \
383  op<T> \
384  >, \
385  length \
386 > \
387 operator symbol (const T &A, const Array<T,length,CheckingPolicy> &B) \
388 { \
389  typedef ArrayBinaryOp< \
390  ArrayConstantExp<T>, \
391  Array<T,length,CheckingPolicy>, \
392  op<T> \
393  > OperatorType; \
394  \
395  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
396 }
397 
398 /* Operator for a Array and a Scalar object */
399 #define ARR_SCAL(op, symbol) \
400 template<class T, int length, template<int> class CheckingPolicy> \
401 ArrayExpression< \
402  ArrayBinaryOp< \
403  Array<T,length,CheckingPolicy>, \
404  ArrayConstantExp<T>, \
405  op<T> \
406  >, \
407  length \
408 > \
409 operator symbol (const Array<T,length,CheckingPolicy> &A, const T &B) \
410 { \
411  typedef ArrayBinaryOp< \
412  Array<T,length,CheckingPolicy>, \
413  ArrayConstantExp<T>, \
414  op<T> \
415  > OperatorType; \
416  \
417  return ArrayExpression<OperatorType, length> (OperatorType(A,B)); \
418 }
419 
420 /* Unary Operator for Arrays */
421 #define UNARY_ARR(op, symbol) \
422 template < \
423  class T, \
424  int length, \
425  template<int> class CheckingPolicy1 \
426 > \
427 ArrayExpression< \
428  ArrayUnaryOp< \
429  ArrayExpression< Array<T,length,CheckingPolicy1>, length >, \
430  op<T> \
431  >, \
432  length \
433 > \
434 operator symbol ( \
435  const Array<T,length,CheckingPolicy1> &A \
436 ) \
437 { \
438  typedef ArrayUnaryOp< \
439  ArrayExpression< Array<T,length,CheckingPolicy1>, length >, \
440  op<T> \
441  > OperatorType; \
442  \
443  return ArrayExpression<OperatorType, length> (OperatorType(A)); \
444 }
445 
446 
447 /* Operator for a Array and a ArrayExpression object */
448 #define UNARY_EXPR(op, symbol) \
449 template< \
450  class exp, \
451  class T, \
452  int length, \
453  template<int> class CheckingPolicy \
454 > \
455 ArrayExpression< \
456  ArrayUnaryOp< \
457  ArrayExpression<exp, length>, \
458  op<T> \
459  >, \
460  length \
461 > \
462 operator symbol ( \
463  const ArrayExpression<exp, length> &A \
464 ) \
465 { \
466  typedef ArrayUnaryOp< \
467  ArrayExpression<exp, length>, \
468  op<T> \
469  > OperatorType; \
470  \
471  return ArrayExpression<OperatorType, length> (OperatorType(A)); \
472 }
473 
474 //======== Plus ======================
475 
476 EXPR_EXPR(ArrayOpPlus,+)
477 ARR_ARR(ArrayOpPlus,+)
478 EXPR_ARR(ArrayOpPlus,+)
479 ARR_EXPR(ArrayOpPlus,+)
480 
481 EXPR_SCAL(ArrayOpPlus,+)
482 SCAL_EXPR(ArrayOpPlus,+)
483 ARR_SCAL(ArrayOpPlus,+)
484 SCAL_ARR(ArrayOpPlus,+)
485 
486 //======== Minus ======================
487 
488 EXPR_EXPR(ArrayOpMinus,-)
489 ARR_ARR(ArrayOpMinus,-)
490 EXPR_ARR(ArrayOpMinus,-)
491 ARR_EXPR(ArrayOpMinus,-)
492 
493 EXPR_SCAL(ArrayOpMinus,-)
494 SCAL_EXPR(ArrayOpMinus,-)
495 ARR_SCAL(ArrayOpMinus,-)
496 SCAL_ARR(ArrayOpMinus,-)
497 
498 
499 //======== Multiplication ======================
500 
501 EXPR_EXPR(ArrayOpMult,*)
502 ARR_ARR(ArrayOpMult,*)
503 EXPR_ARR(ArrayOpMult,*)
504 ARR_EXPR(ArrayOpMult,*)
505 
506 EXPR_SCAL(ArrayOpMult,*)
507 SCAL_EXPR(ArrayOpMult,*)
508 ARR_SCAL(ArrayOpMult,*)
509 SCAL_ARR(ArrayOpMult,*)
510 
511 //======== Division ======================
512 
513 EXPR_EXPR(ArrayOpDiv,/)
514 ARR_ARR(ArrayOpDiv,/)
515 EXPR_ARR(ArrayOpDiv,/)
516 ARR_EXPR(ArrayOpDiv,/)
517 
518 EXPR_SCAL(ArrayOpDiv,/)
519 SCAL_EXPR(ArrayOpDiv,/)
520 ARR_SCAL(ArrayOpDiv,/)
521 SCAL_ARR(ArrayOpDiv,/)
522 
523 
524 //======== Unary Plus and Minus ======================
525 
526 UNARY_ARR(ArrayOpUnaryPlus,+)
527 UNARY_EXPR(ArrayOpUnaryPlus,+)
528 
529 UNARY_ARR(ArrayOpUnaryMinus,-)
530 UNARY_EXPR(ArrayOpUnaryMinus,-)
531 
532 #undef EXPR_EXPR
533 #undef ARR_ARR
534 #undef ARR_EXPR
535 #undef EXPR_ARR
536 #undef EXPR_SCAL
537 #undef SCAL_EXPR
538 #undef ARR_SCAL
539 #undef SCAL_ARR
540 #undef UNARY_ARR
541 #undef UNARY_EXPR
542 
543 
544 template<class T, int length, template <int> class CheckingPolicy>
545 template<class Operator>
547 {
548  for (int i=0; i<length; ++i)
549  data[i] = expr[i];
550  return *this;
551 }
552 
553 template<class T, int length, template <int> class CheckingPolicy>
554 template<class Operator>
556 {
557  for (int i=0; i<length; ++i)
558  data[i] += expr[i];
559  return *this;
560 }
561 
562 template<class T, int length, template <int> class CheckingPolicy>
563 template<class Operator>
565 {
566  for (int i=0; i<length; ++i)
567  data[i] -= expr[i];
568  return *this;
569 }
570 
571 template<class T, int length, template <int> class CheckingPolicy>
572 template<class Operator>
574 {
575  for (int i=0; i<length; ++i)
576  data[i] *= expr[i];
577  return *this;
578 }
579 
580 template<class T, int length, template <int> class CheckingPolicy>
581 template<class Operator>
583 {
584  for (int i=0; i<length; ++i)
585  data[i] /= expr[i];
586  return *this;
587 }
588 
589 
590 
591 template<class T, int length, template <int> class CheckingPolicy>
592 template<class Operator>
594 {
595  for (int i=0; i<length; ++i)
596  data[i] = expr[i];
597 }
598 } // namespace schnek
599 
600 #endif // SCHNEK_ARRAYEXPRESSION_H_
ArrayUnaryOp(const ArrayUnaryOp &Op)
Definition: arrayexpression.hpp:101
Array< T, length, CheckingPolicy > & operator-=(const Array< T2, length, CheckingPolicy2 > &)
value_type operator[](int i) const
Definition: arrayexpression.hpp:76
ArrayExpression(const Operator Op_)
Definition: arrayexpression.hpp:54
ArrayBinaryOp(const ArrayBinaryOp &Op)
Definition: arrayexpression.hpp:129
Definition: operators2.hpp:34
Definition: array.hpp:49
static value_type apply(value_type x, value_type y)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:165
Array()
The default constructor.
Array< T, length, CheckingPolicy > & operator*=(const Array< T2, length, CheckingPolicy2 > &)
Definition: array.hpp:34
static value_type apply(value_type x, value_type y)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:185
Definition: arrayexpression.hpp:161
ArrayBinaryOp(const Exp1 &A_, const Exp2 &B_)
Definition: arrayexpression.hpp:126
static value_type apply(value_type x, value_type y)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:175
Definition: arrayexpression.hpp:139
Definition: algo.hpp:30
Definition: arrayexpression.hpp:171
static value_type apply(value_type x)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:195
Definition: arrayexpression.hpp:116
value_type operator[](int i) const
Definition: arrayexpression.hpp:107
Definition: arrayexpression.hpp:151
static value_type apply(value_type x, value_type y)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:155
Definition: arrayexpression.hpp:90
Array< T, length, CheckingPolicy > & operator+=(const Array< T2, length, CheckingPolicy2 > &)
Array< T, length, CheckingPolicy > & operator=(const Array< T2, length, CheckingPolicy2 > &)
static value_type apply(value_type x)
Returns the sum of the two elements.
Definition: arrayexpression.hpp:205
Definition: arrayexpression.hpp:201
ArrayExpression(const ArrayExpression &Expr)
Definition: arrayexpression.hpp:57
ArrayUnaryOp(const Exp1 &A_)
Definition: arrayexpression.hpp:98
value_type operator[](int i) const
Definition: arrayexpression.hpp:135
Definition: arrayexpression.hpp:181
Array< T, length, CheckingPolicy > & operator/=(const Array< T2, length, CheckingPolicy2 > &)
Definition: arrayexpression.hpp:191