DMRITool  v0.1.1-139-g860d86b4
Diffusion MRI Tool
utlExpression.h
Go to the documentation of this file.
1 
10 #ifndef __utlExpression_h
11 #define __utlExpression_h
12 
13 #include "utlTypeinfo.h"
14 #include "utlCoreMacro.h"
15 #include "utlSmartAssert.h"
16 #include "utlSTDHeaders.h"
17 
18 namespace utl
19 {
20 
27 template<class T1, class T2>
29 
30 template<class TExpr>
31 using Expr1ValueType = typename TExpr::ValueType;
32 
33 template<class TLeft, class TRight>
35 
36 template< typename SubType, typename ValueT> class Expr;
37 template<typename ValueT> class ScalarExprBase;
38 
49 
60 template< typename SubType, typename ValueT>
61 class Expr
62 {
63 public:
64  typedef ValueT ValueType;
65  typedef unsigned int SizeType;
66  typedef SizeType const* ShapeType;
67 
69  UTL_ALWAYS_INLINE const SubType& ConstRef( void ) const
70  {
71  return *static_cast<const SubType*>(this);
72  }
74  UTL_ALWAYS_INLINE SubType& Ref( void )
75  {
76  return *static_cast<SubType*>(this);
77  }
78  UTL_ALWAYS_INLINE static SizeType GetDimension()
79  { return SubType::GetDimension(); }
80 
81  UTL_ALWAYS_INLINE const ShapeType GetShape() const
82  {
83  return ConstRef().GetShape();
84  }
85 };
86 
94 template<typename ValueT>
95 class ScalarExprBase: public Expr<ScalarExprBase<ValueT>, ValueT>
96 {
97 public:
99  typedef ValueT ValueType;
100  typedef typename Superclass::SizeType SizeType;
102 
104  enum { Dimension = 0 };
105 
106  ValueT m_Scalar;
107 
108  template<typename TValue>
109  ScalarExprBase( TValue scalar ) : m_Scalar(static_cast<ValueType>(scalar)){
110  }
111 
112  UTL_ALWAYS_INLINE static SizeType GetDimension()
113  { return 0; }
114  UTL_ALWAYS_INLINE const ShapeType GetShape() const
115  { return NULL; }
116  UTL_ALWAYS_INLINE ValueType Eval( int i ) const
117  {
118  return m_Scalar;
119  }
121  UTL_ALWAYS_INLINE const ValueType ConstRef( void ) const
122  {
123  return m_Scalar;
124  }
126  UTL_ALWAYS_INLINE ValueType Ref( void )
127  {
128  return m_Scalar;
129  }
130 };
131 
132 
138 template<typename OP,typename TLeft, typename TRight>
139 class BinaryOpExpr: public Expr<BinaryOpExpr<OP,TLeft,TRight>, typename SuperFloatType<typename TLeft::ValueType, typename TRight::ValueType>::type >
140 {
141 public:
144  typedef typename Superclass::SizeType SizeType;
146 
147  const TLeft& m_Left;
148  const TRight& m_Right;
149  OP m_OP;
150 
152  BinaryOpExpr(const TLeft& lhs, const TRight& rhs): m_Left(lhs),m_Right(rhs), m_OP(OP())
153  {
154 #if UTL_VERBOSITY>1
155  SizeType lDim = TLeft::GetDimension();
156  SizeType rDim = TRight::GetDimension();
157  if (lDim>0 && rDim>0)
158  {
159  utlSAException(lDim>0 && rDim>0 && lDim!=rDim)(lDim)(rDim).msg("the dimensions of two sides are different");
160  const ShapeType leftShape=m_Left.GetShape(), rightShape=m_Right.GetShape();
161  for ( int i = 0; i < lDim; ++i )
162  utlSAException(leftShape[i]!=rightShape[i])
163  (i)(leftShape[i])(rightShape[i]).msg("the sizes of two sides are different");
164  }
165 #endif
166  }
167 
168  BinaryOpExpr(const TLeft&& lhs, const TRight&& rhs): m_Left(lhs),m_Right(rhs), m_OP(OP())
169  {
170 #if UTL_VERBOSITY>1
171  SizeType lDim = TLeft::GetDimension();
172  SizeType rDim = TRight::GetDimension();
173  if (lDim>0 && rDim>0)
174  {
175  utlSAException(lDim>0 && rDim>0 && lDim!=rDim)(lDim)(rDim).msg("the dimensions of two sides are different");
176  const ShapeType leftShape=m_Left.GetShape(), rightShape=m_Right.GetShape();
177  for ( int i = 0; i < lDim; ++i )
178  utlSAException(leftShape[i]!=rightShape[i])
179  (i)(leftShape[i])(rightShape[i]).msg("the sizes of two sides are different");
180  }
181 #endif
182  }
183 
184  BinaryOpExpr(const BinaryOpExpr&& other) : m_Left(other.m_Left),m_Right(other.m_Right), m_OP(OP())
185  {
186  }
187 
189  UTL_ALWAYS_INLINE static SizeType GetDimension()
190  {
191  SizeType lDim = TLeft::GetDimension();
192  SizeType rDim = TRight::GetDimension();
193  utlSAException(lDim>0 && rDim>0 && lDim!=rDim)(lDim)(rDim).msg("the dimensions of two sides are different");
194  if (lDim==0)
195  return rDim;
196  if (rDim==0)
197  return lDim;
198  return lDim;
199  }
201  UTL_ALWAYS_INLINE const ShapeType GetShape() const
202  {
203  if (TLeft::GetDimension()==0)
204  return m_Right.GetShape();
205  if (TRight::GetDimension()==0)
206  return m_Left.GetShape();
207  return m_Left.GetShape();
208  }
209  UTL_ALWAYS_INLINE ValueType Eval( int i ) const
210  {
211  return m_OP( m_Left.Eval(i), m_Right.Eval(i) );
212  }
213 };
214 
215 template<typename OP,typename TLeft, typename ValueT>
216 class BinaryOpExpr<OP, TLeft, ScalarExprBase<ValueT>>: public Expr<BinaryOpExpr<OP,TLeft,ScalarExprBase<ValueT>>, Expr2ValueType<TLeft, ScalarExprBase<ValueT>> >
217 {
218 public:
220  typedef typename Superclass::ValueType ValueType;
221  typedef typename Superclass::SizeType SizeType;
223 
224  const TLeft& m_Left;
225  ValueType m_Scalar;
226  OP m_OP;
227 
229  BinaryOpExpr(const TLeft& lhs, const ScalarExprBase<ValueT>& rhs): m_Left(lhs), m_Scalar(rhs.m_Scalar), m_OP(OP())
230  {
231  }
232 
234  UTL_ALWAYS_INLINE static SizeType GetDimension()
235  {
236  return TLeft::GetDimension();
237  }
239  UTL_ALWAYS_INLINE const ShapeType GetShape() const
240  {
241  return m_Left.GetShape();
242  }
243  UTL_ALWAYS_INLINE ValueType Eval( int i ) const
244  {
245  return m_OP( m_Left.Eval(i), m_Scalar );
246  }
247 };
248 
249 template<typename OP,typename TRight, typename ValueT>
250 class BinaryOpExpr<OP, ScalarExprBase<ValueT>, TRight>: public Expr<BinaryOpExpr<OP,ScalarExprBase<ValueT>, TRight>, Expr2ValueType<TRight, ScalarExprBase<ValueT>> >
251 {
252 public:
255  typedef typename Superclass::SizeType SizeType;
257 
258  const TRight& m_Right;
259  ValueType m_Scalar;
260  OP m_OP;
261 
263  BinaryOpExpr(const ScalarExprBase<ValueT>& lhs, const TRight& rhs): m_Right(rhs), m_Scalar(lhs.m_Scalar), m_OP(OP())
264  {
265  }
266 
268  UTL_ALWAYS_INLINE static SizeType GetDimension()
269  {
270  return TRight::GetDimension();
271  }
273  UTL_ALWAYS_INLINE const ShapeType GetShape() const
274  {
275  return m_Right.GetShape();
276  }
277  UTL_ALWAYS_INLINE ValueType Eval( int i ) const
278  {
279  return m_OP( m_Scalar, m_Right.Eval(i) );
280  }
281 };
282 
283 template<typename OP,typename ValueT1, typename ValueT2>
284 class BinaryOpExpr<OP, ScalarExprBase<ValueT1>, ScalarExprBase<ValueT2>>: public Expr<BinaryOpExpr<OP,ScalarExprBase<ValueT1>, ScalarExprBase<ValueT2>>, SuperType<ValueT1, ValueT2> >
285 {
286 public:
289  typedef typename Superclass::SizeType SizeType;
291 
292  ValueType m_Scalar1;
293  ValueType m_Scalar2;
294  OP m_OP;
295 
297  BinaryOpExpr(const ScalarExprBase<ValueT1>& lhs, const ScalarExprBase<ValueT2>& rhs): m_Scalar1(lhs.m_Scalar), m_Scalar2(rhs.m_Scalar), m_OP(OP())
298  {
299  }
300 
302  UTL_ALWAYS_INLINE static SizeType GetDimension()
303  {
304  return 0;
305  }
307  UTL_ALWAYS_INLINE const ShapeType GetShape() const
308  {
309  return NULL;
310  }
311  UTL_ALWAYS_INLINE ValueType Eval( int i ) const
312  {
313  return m_OP( m_Scalar1, m_Scalar2 );
314  }
315 };
316 
320 template<typename OP,typename TA, typename TB>
323 {
324  return BinaryOpExpr<OP,TA,TB>( lhs.ConstRef(), rhs.ConstRef() );
325 }
326 
330 template<typename OP,typename TLeft, typename TRight>
333 {
334  return BinaryOpExpr< OP,TLeft,TRight>(lhs.ConstRef(), rhs.ConstRef());
335 }
336 
338 template<typename OP,typename TA>
340 F( const Expr<TA, typename TA::ValueType> &lhs, const ScalarExpr &rhs ){
341  return MakeExpr<OP>( lhs, rhs );
342 }
344 template< typename OP,typename TB>
346 F( const ScalarExpr &lhs, const Expr<TB, typename TB::ValueType>& rhs ){
347  return MakeExpr<OP>( lhs, rhs );
348 }
349 template<typename OP,typename TA>
351 F( const Expr<TA, typename TA::ValueType> &lhs, const ScalarComplexExpr &rhs ){
352  return MakeExpr<OP>( lhs, rhs );
353 }
355 template< typename OP,typename TB>
357 F( const ScalarComplexExpr &lhs, const Expr<TB, typename TB::ValueType>& rhs ){
358  return MakeExpr<OP>( lhs, rhs );
359 }
360 
361 
366 #define __BinaryOpExpr_Op(name, op) \
367 template<typename TLeft, typename TRight> \
368 inline BinaryOpExpr<name<Expr2ValueType<TLeft,TRight> >,TLeft,TRight> \
369 operator op (const Expr<TLeft, typename TLeft::ValueType>& lhs, const Expr<TRight, typename TRight::ValueType>& rhs){ \
370  return MakeExpr<name<Expr2ValueType<TLeft,TRight> > >(lhs, rhs); \
371 } \
372 template<typename TRight> \
373 inline BinaryOpExpr<name<Expr2ValueType<ScalarExpr,TRight> >,ScalarExpr,TRight> \
374 operator op (const ScalarExpr &lhs, const Expr<TRight, typename TRight::ValueType>& rhs){ \
375  return MakeExpr<name<Expr2ValueType<ScalarExpr,TRight> > >(lhs, rhs); \
376 } \
377 template<typename TLeft> \
378 inline BinaryOpExpr<name<Expr2ValueType<TLeft,ScalarExpr> >, TLeft,ScalarExpr > \
379 operator op (const Expr<TLeft, typename TLeft::ValueType>& lhs, const ScalarExpr& rhs){ \
380  return MakeExpr<name<Expr2ValueType<TLeft,ScalarExpr> > >(lhs, rhs); \
381 } \
382 template<typename TRight> \
383 inline BinaryOpExpr<name<Expr2ValueType<ScalarExpr,TRight> >,ScalarExpr,TRight> \
384 operator op (const double lhs, const Expr<TRight, typename TRight::ValueType>& rhs){ \
385  return MakeExpr<name<Expr2ValueType<ScalarExpr,TRight> > >(ScalarExpr(lhs), rhs); \
386 } \
387 template<typename TLeft> \
388 inline BinaryOpExpr<name<Expr2ValueType<TLeft,ScalarExpr> >, TLeft,ScalarExpr > \
389 operator op (const Expr<TLeft, typename TLeft::ValueType>& lhs, const double rhs){ \
390  return MakeExpr<name<Expr2ValueType<TLeft,ScalarExpr> > >(lhs, ScalarExpr(rhs)); \
391 } \
392 template<typename TRight> \
393 inline BinaryOpExpr<name<Expr2ValueType<ScalarComplexExpr,TRight> >,ScalarComplexExpr,TRight> \
394 operator op (const std::complex<double> lhs, const Expr<TRight, typename TRight::ValueType>& rhs){ \
395  return MakeExpr<name<Expr2ValueType<ScalarComplexExpr,TRight> > >(ScalarComplexExpr(lhs), rhs); \
396 } \
397 template<typename TLeft> \
398 inline BinaryOpExpr<name<Expr2ValueType<TLeft,ScalarComplexExpr> >, TLeft,ScalarComplexExpr > \
399 operator op (const Expr<TLeft, typename TLeft::ValueType>& lhs, const std::complex<double> rhs){ \
400  return MakeExpr<name<Expr2ValueType<TLeft,ScalarComplexExpr> > >(lhs, ScalarComplexExpr(rhs)); \
401 } \
402 
403 
404 __BinaryOpExpr_Op(std::plus, +)
406 __BinaryOpExpr_Op(std::multiplies, %)
407 __BinaryOpExpr_Op(std::divides, /)
408 
409 
415 template<typename OP, typename EType >
416 class UnaryOpExpr: public Expr< UnaryOpExpr<OP,EType>, typename EType::ValueType >
417 {
418 public:
419  typedef Expr<UnaryOpExpr<OP,EType>, typename EType::ValueType > Superclass;
421  typedef typename Superclass::SizeType SizeType;
423 
424  const EType& m_Expr;
425  OP m_OP;
426 
427  UnaryOpExpr( const EType & expr):m_Expr(expr), m_OP(){}
428 
429  UTL_ALWAYS_INLINE static SizeType GetDimension()
430  {
431  return EType::GetDimension();
432  }
433  UTL_ALWAYS_INLINE const ShapeType GetShape() const
434  {
435  return m_Expr.GetShape();
436  }
437  UTL_ALWAYS_INLINE ValueType Eval( int i ) const
438  {
439  return m_OP( m_Expr.Eval(i) );
440  }
441 };
442 
444 template<typename OP,typename EType>
446 {
447  return UnaryOpExpr<OP,EType >( expr.ConstRef() );
448 }
450 template<typename OP,typename EType>
452  return MakeExpr<OP>(expr);
453 }
454 
457 #define __UnaryOpExpr_Op(name, op) \
458 template<typename TExpr> \
459 inline UnaryOpExpr<name<typename TExpr::ValueType>,TExpr> \
460 operator op (const Expr<TExpr, typename TExpr::ValueType>& lhs){ \
461  return MakeExpr<name<typename TExpr::ValueType>>(lhs); \
462 } \
463 
464 
465 __UnaryOpExpr_Op(std::negate, -)
466 
467 
469 }
470 
471 
472 #endif
Superclass::SizeType SizeType
Superclass::SizeType SizeType
const ShapeType GetShape() const
#define __UnaryOpExpr_Op(name, op)
define expressions for unary math operators
base class for expression
Definition: utlExpression.h:36
ScalarExprBase< std::complex< double > > ScalarComplexExpr
ScalarExprBase<std::complex<double> >
Definition: utlExpression.h:48
Created "07-04-2016.
SubType & Ref(void)
Definition: utlExpression.h:74
Superclass::ShapeType ShapeType
BinaryOpExpr(const TLeft &&lhs, const TRight &&rhs)
ValueType Eval(int i) const
BinaryOpExpr(const TLeft &lhs, const TRight &rhs)
ValueType Eval(int i) const
STL namespace.
Superclass::ValueType ValueType
scalar expression base class for double and std::complex<double>
Definition: utlExpression.h:37
ScalarExprBase< double > ScalarExpr
ScalarExprBase<double>
Definition: utlExpression.h:43
static SizeType GetDimension()
Definition: utlExpression.h:78
SizeType const * ShapeType
Definition: utlExpression.h:66
Expr< BinaryOpExpr< OP, ScalarExprBase< ValueT1 >, ScalarExprBase< ValueT2 > >, SuperType< ValueT1, ValueT2 > > Superclass
BinaryOpExpr(const BinaryOpExpr &&other)
Superclass::ShapeType ShapeType
Superclass::ShapeType ShapeType
const ShapeType GetShape() const
const ShapeType GetShape() const
ScalarExprBase(TValue scalar)
typename SuperFloatType< T1, T2 >::type SuperType
Definition: utlExpression.h:28
BinaryOpExpr(const ScalarExprBase< ValueT > &lhs, const TRight &rhs)
#define UTL_ALWAYS_INLINE
Definition: utlCoreMacro.h:76
typename SuperFloatType< typename TLeft::ValueType, typename TRight::ValueType >::type Expr2ValueType
Definition: utlExpression.h:34
BinaryOpExpr< OP, TLeft, TRight > F(const Expr< TLeft, typename TLeft::ValueType > &lhs, const Expr< TRight, typename TRight::ValueType > &rhs)
#define __BinaryOpExpr_Op(name, op)
define expressions for binary math operators
BinaryOpExpr< OP, TA, TB > MakeExpr(const Expr< TA, typename TA::ValueType > &lhs, const Expr< TB, typename TB::ValueType > &rhs)
BinaryOpExpr(const ScalarExprBase< ValueT1 > &lhs, const ScalarExprBase< ValueT2 > &rhs)
const ValueType ConstRef(void) const
const ShapeType GetShape() const
Definition: utlExpression.h:81
Definition: utl.h:90
Expr< BinaryOpExpr< OP, TLeft, ScalarExprBase< ValueT > >, Expr2ValueType< TLeft, ScalarExprBase< ValueT > > > Superclass
Superclass::ValueType ValueType
#define utlSAException(expr)
Definition: utlCoreMacro.h:543
const TLeft & m_Left
typename TExpr::ValueType Expr1ValueType
Definition: utlExpression.h:31
unary operator expression
static SizeType GetDimension()
Expr< BinaryOpExpr< OP, TLeft, TRight >, typename SuperFloatType< typename TLeft::ValueType, typename TRight::ValueType >::type > Superclass
ValueType Eval(int i) const
const SubType & ConstRef(void) const
Definition: utlExpression.h:69
Superclass::SizeType SizeType
ValueType Ref(void)
Expr< UnaryOpExpr< OP, EType >, typename EType::ValueType > Superclass
unsigned int SizeType
Definition: utlExpression.h:65
Binary operator expression class.
ValueT ValueType
Definition: utlExpression.h:64
const EType & m_Expr
Expr< ScalarExprBase< ValueT >, ValueT > Superclass
Definition: utlExpression.h:98
macros for utlCore
BinaryOpExpr(const TLeft &lhs, const ScalarExprBase< ValueT > &rhs)
UnaryOpExpr(const EType &expr)
Expr< BinaryOpExpr< OP, ScalarExprBase< ValueT >, TRight >, Expr2ValueType< ScalarExprBase< ValueT >, TRight > > Superclass
static SizeType GetDimension()
const TRight & m_Right
static SizeType GetDimension()
conditional_t< std::is_scalar< T >::value &&std::is_scalar< t >::value, double, std::complex< double > > type
Definition: utlTypeinfo.h:88