NUMCXX  0.13.20181108
Numerical library for small projects and teaching purposes
expression.ixx
Go to the documentation of this file.
1 
36 
37 #ifndef NUMCXX_EXPRESSION_HXX
38 #define NUMCXX_EXPRESSION_HXX
39 #include <type_traits>
40 
41 namespace numcxx
42 {
43 
47  class ExpressionBase { };
48 
52  class MatrixExpressionBase { };
53 
57  class SparseMatrixExpressionBase { };
58 
59 
62  template<typename A, typename B,
63  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
64  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
65  class AdditionExpression: public ExpressionBase
66  {
67  const A& a;
68  const B& b;
69  public:
70  typedef typename A::value_type value_type;
71  AdditionExpression(const A& a, const B& b):a(a), b(b){}
72  unsigned int size() const { return a.size(); }
73  const value_type operator[](const unsigned int i) const {return a[i] + b[i];}
74  AdditionExpression& operator=(const AdditionExpression&)=delete;
75  };
76 
77  template<typename A, typename B,
78  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
79  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
80  const AdditionExpression<A,B> operator+(const A& a, const B& b)
81  {
82  return AdditionExpression<A,B>(a, b);
83  }
84 
85 
88  template<typename A, typename B,
89  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
90  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
91  class SubtractionExpression: public ExpressionBase
92  {
93  const A& a;
94  const B& b;
95  public:
96  typedef typename A::value_type value_type;
97  SubtractionExpression(const A& a, const B& b):a(a), b(b){}
98  unsigned int size() const { return a.size(); }
99  const value_type operator[](const unsigned int i) const { return a[i] - b[i];}
100  };
101 
102  template<typename A, typename B,
103  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
104  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
105  const SubtractionExpression<A,B> operator-(const A& a, const B& b)
106  {
107  return SubtractionExpression<A,B>(a, b);
108  }
109 
112  template<typename A, typename B,
113  typename= typename std::enable_if<std::is_fundamental<A>::value, A>::type,
114  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
115  class LeftScalarMultiplicationExpression: public ExpressionBase
116  {
117  const A a;
118  const B& b;
119  public:
120  typedef typename B::value_type value_type;
121  LeftScalarMultiplicationExpression(const A& a, const B& b):a(a), b(b){}
122  unsigned int size() const { return b.size(); }
123  const value_type operator[](const unsigned int i) const {return a*b[i];}
124  };
125 
126  template<typename A, typename B,
127  typename= typename std::enable_if<std::is_fundamental<A>::value, A>::type,
128  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
129  const LeftScalarMultiplicationExpression<A,B> operator*(const A& a, const B& b)
130  {
131  return LeftScalarMultiplicationExpression<A,B>(a, b);
132  }
133 
134 
137  template<typename A, typename B,
138  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
139  typename= typename std::enable_if<std::is_fundamental<B>::value, B>::type>
140  class RightScalarMultiplicationExpression: public ExpressionBase
141  {
142  const A& a;
143  const B b;
144  public:
145  typedef typename A::value_type value_type;
146  RightScalarMultiplicationExpression(const A& a, const B& b):a(a),b(b){;}
147  unsigned int size() const { return a.size(); }
148  const value_type operator[](const unsigned int i) const {return a[i]*b; }
149  };
150 
151  template<typename A, typename B,
152  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
153  typename= typename std::enable_if<std::is_fundamental<B>::value, B>::type>
154  const RightScalarMultiplicationExpression<A,B> operator*(const A& a, const B& b)
155  {
156  return RightScalarMultiplicationExpression<A,B>(a, b);
157  }
158 
159 
160 
163  template<typename A, typename B,
164  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
165  typename= typename std::enable_if<std::is_fundamental<B>::value, B>::type>
166  class RightScalarAdditionExpression: public ExpressionBase
167  {
168  const A& a;
169  const B b;
170  public:
171  typedef typename A::value_type value_type;
172  RightScalarAdditionExpression(const A& a, const B& b):a(a), b(b){}
173  unsigned int size() const { return a.size(); }
174  const value_type operator[](const unsigned int i) const { return a[i]+b; }
175  };
176 
177  template<typename A, typename B,
178  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
179  typename= typename std::enable_if<std::is_fundamental<B>::value, B>::type>
180  const RightScalarAdditionExpression<A,B> operator+(const A& a, const B& b)
181  {
182  return RightScalarAdditionExpression<A,B>(a, b);
183  }
184 
187  template<typename A, typename B,
188  typename= typename std::enable_if<std::is_fundamental<A>::value, A>::type,
189  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
190  class LeftScalarAdditionExpression: public ExpressionBase
191  {
192  const A a;
193  const B& b;
194  public:
195  typedef typename B::value_type value_type;
196  LeftScalarAdditionExpression(const A& a, const B& b):a(a), b(b){}
197  unsigned int size() const { return b.size(); }
198  const value_type operator[](const unsigned int i) const { return a+b[i];}
199  };
200 
201  template<typename A, typename B,
202  typename= typename std::enable_if<std::is_fundamental<A>::value, A>::type,
203  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
204  const LeftScalarAdditionExpression<A,B> operator+(const A& a, const B& b)
205  {
206  return LeftScalarAdditionExpression<A,B>(a, b);
207  }
208 
211  template<typename A, typename B,
212  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
213  typename= typename std::enable_if<std::is_fundamental<B>::value, B>::type>
214  class RightScalarSubtractionExpression: public ExpressionBase
215  {
216  const A& a;
217  const B b;
218  public:
219  typedef typename A::value_type value_type;
220  RightScalarSubtractionExpression(const A& a, const B& b):a(a), b(b){}
221  unsigned int size() const { return a.size(); }
222  const value_type operator[](const unsigned int i) const { return a[i]-b; }
223  };
224 
225  template<typename A, typename B,
226  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
227  typename= typename std::enable_if<std::is_fundamental<B>::value, B>::type>
228  const RightScalarSubtractionExpression<A,B> operator-(const A& a, const B& b)
229  {
230  return RightScalarSubtractionExpression<A,B>(a, b);
231  }
232 
235  template<typename A, typename B,
236  typename= typename std::enable_if<std::is_fundamental<A>::value, A>::type,
237  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
238  class LeftScalarSubtractionExpression: public ExpressionBase
239  {
240  const A a;
241  const B& b;
242  public:
243  typedef typename B::value_type value_type;
244  LeftScalarSubtractionExpression(const A& a, const B& b):a(a), b(b){}
245  unsigned int size() const { return b.size(); }
246  const value_type operator[](const unsigned int i) const { return a-b[i];}
247  };
248 
249  template<typename A, typename B,
250  typename= typename std::enable_if<std::is_fundamental<A>::value, A>::type,
251  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
252  const LeftScalarSubtractionExpression<A,B> operator-(const A& a, const B& b)
253  {
254  return LeftScalarSubtractionExpression<A,B>(a, b);
255  }
256 
259  template<typename A, typename B,
260  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
261  typename= typename std::enable_if<std::is_fundamental<B>::value, B>::type>
262  class RightScalarDivisionExpression: public ExpressionBase
263  {
264  const A& a;
265  const B b;
266  public:
267  typedef typename A::value_type value_type;
268  RightScalarDivisionExpression(const A& a, const B& b):a(a), b(b){}
269  unsigned int size() const { return a.size(); }
270  const value_type operator[](const unsigned int i) const { return a[i]/b;}
271  };
272 
273  template<typename A, typename B,
274  typename= typename std::enable_if<std::is_base_of<ExpressionBase,A>::value, A>::type,
275  typename= typename std::enable_if<std::is_fundamental<B>::value, B>::type>
276  const RightScalarDivisionExpression<A,B> operator/(const A& a, const B& b)
277  {
278  return RightScalarDivisionExpression<A,B>(a, b);
279  }
280 
283  template<typename A, typename B,
284  typename= typename std::enable_if<std::is_base_of<MatrixExpressionBase,A>::value, A>::type,
285  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
286  class LeftMatrixMultiplicationExpression: public ExpressionBase
287  {
288  const A& a;
289  const B& b;
290  public:
291  typedef typename A::value_type value_type;
292  LeftMatrixMultiplicationExpression(const A& a, const B& b):a(a), b(b){}
293  unsigned int size() const { return b.size(); }
294  const value_type operator[](const unsigned int i) const
295  {
296  value_type entry=0;
297  for (index j=0;j<a.shape(0);j++)
298  entry+=a.xentry(i,j)*b[j];
299  return entry;
300  }
301  };
302 
303  template<typename A, typename B,
304  typename= typename std::enable_if<std::is_base_of<MatrixExpressionBase,A>::value, A>::type,
305  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
306  const LeftMatrixMultiplicationExpression<A,B> operator*(const A& a, const B& b)
307  {
308  return LeftMatrixMultiplicationExpression<A,B>(a, b);
309  }
310 
313  template<typename A, typename B,
314  typename= typename std::enable_if<std::is_base_of<SparseMatrixExpressionBase,A>::value, A>::type,
315  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
316  class LeftSparseMatrixMultiplicationExpression: public ExpressionBase
317  {
318  const A& a;
319  const B& b;
320  public:
321  typedef typename A::value_type value_type;
322  LeftSparseMatrixMultiplicationExpression(const A& a, const B& b):a(a), b(b){}
323  unsigned int size() const { return b.size(); }
324  const value_type operator[](const unsigned int i) const
325  {
326  value_type entry=0;
327  auto &IA=*(a.pIA);
328  auto &JA=*(a.pJA);
329  auto &AA=*(a.pA);
330 
331  for (index j=IA[i];j<IA[i+1];j++)
332  entry+=AA[j]*b[JA[j]];
333  return entry;
334  }
335  };
336 
337  template<typename A, typename B,
338  typename= typename std::enable_if<std::is_base_of<SparseMatrixExpressionBase,A>::value, A>::type,
339  typename= typename std::enable_if<std::is_base_of<ExpressionBase,B>::value, B>::type>
340  const LeftSparseMatrixMultiplicationExpression<A,B> operator*(const A& a, const B& b)
341  {
342  return LeftSparseMatrixMultiplicationExpression<A,B>(a, b);
343  }
344 }
345 #endif
const LeftScalarMultiplicationExpression< A, B > operator*(const A &a, const B &b)
Definition: expression.ixx:129
const SubtractionExpression< A, B > operator-(const A &a, const B &b)
Definition: expression.ixx:105
unsigned int index
Definition: numcxx.hxx:21
const AdditionExpression< A, B > operator+(const A &a, const B &b)
Definition: expression.ixx:80
double B(double x)
Numcxx template library.
Definition: expression.ixx:41
const RightScalarDivisionExpression< A, B > operator/(const A &a, const B &b)
Definition: expression.ixx:276