1 // -*- C++ -*-
2 /** @file */
3 #pragma once
4 
5 /** \addtogroup FUSION
6  *  @{
7  */
8 
9 /**
10  * @brief  Unary operator
11  *
12  * @tparam Scalar Datatype for scalar
13  * @tparam Derived Datatype representing the operator expression
14  *
15  */
16 template<typename Scalar,typename Derived>
17 struct _UnaryOperator{
derived_UnaryOperator18     Derived& derived()  {return(static_cast<Derived&>(*this));}
19 
derived_UnaryOperator20     Derived const& derived() const {return(static_cast<Derived const&>(*this));}
21 
operator ()_UnaryOperator22     Scalar const operator()(const Scalar lhs) const
23     {
24         return(this->derived()(lhs));
25     }
26 
27     #if defined(HAS_VECTOR)
28     using Vector= typename vector_traits<Scalar>::vector ;
29     using pred_t = typename vector_traits<Scalar>::predicate_t;
30 
operator ()_UnaryOperator31     Vector const operator()(const Vector lhs) const
32     {
33         return(this->derived()(lhs));
34     }
35 
36     /*
37 
38     Predicated operation when exists (Helium)
39 
40     */
41     template<typename T=Scalar,
42              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_UnaryOperator43     Vector const operator()(const Vector lhs,const pred_t p0) const
44     {
45         return(this->derived()(lhs,p0));
46     }
47 
48     /*
49     Vector const to_vector(const Scalar lhs) const
50     {
51         return(this->derived().to_vector(lhs));
52     }
53     */
54 #endif
55 };
56 
57 /**
58  * @brief  Unary operator
59  *
60  * @tparam Scalar Datatype for scalar
61  * @tparam Derived Datatype representing the operator expression
62  *
63  */
64 template<typename Scalar,typename Derived>
65 struct _BinaryOperator{
derived_BinaryOperator66     Derived& derived()  {return(static_cast<Derived&>(*this));}
67 
derived_BinaryOperator68     Derived const& derived() const {return(static_cast<Derived const&>(*this));}
69 
operator ()_BinaryOperator70     Scalar const operator()(const Scalar lhs,
71                             const Scalar rhs) const
72     {
73         return(this->derived()(lhs,rhs));
74     }
75 
76     #if defined(HAS_VECTOR)
77     using Vector= typename vector_traits<Scalar>::vector ;
78     using pred_t = typename vector_traits<Scalar>::predicate_t;
79 
80 
operator ()_BinaryOperator81     Vector const operator()(const Vector lhs,
82                             const Vector rhs) const
83     {
84         return(this->derived()(lhs,rhs));
85     }
86 
operator ()_BinaryOperator87     Vector const operator()(const Vector lhs,
88                             const Scalar rhs) const
89     {
90         return(this->derived()(lhs,rhs));
91     }
92 
operator ()_BinaryOperator93     Vector const operator()(const Scalar lhs,
94                             const Vector rhs) const
95     {
96         return(this->derived()(lhs,rhs));
97     }
98 
99     template<typename T=Scalar,
100              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_BinaryOperator101     Vector const operator()(const Vector lhs,
102                             const Vector rhs,
103                             const pred_t p0) const
104     {
105         return(this->derived()(lhs,rhs,p0));
106     }
107 
108     template<typename T=Scalar,
109              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_BinaryOperator110     Vector const operator()(const Vector lhs,
111                             const Scalar rhs,
112                             const pred_t p0) const
113     {
114         return(this->derived()(lhs,rhs,p0));
115     }
116 
117     template<typename T=Scalar,
118              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_BinaryOperator119     Vector const operator()(const Scalar lhs,
120                             const Vector rhs,
121                             const pred_t p0) const
122     {
123         return(this->derived()(lhs,rhs,p0));
124     }
125 #endif
126 };
127 
128 /*
129  *
130  * BINARY
131  *
132  */
133 
134 /**
135  * @brief  Add operator
136  *
137  * @tparam Scalar Datatype for scalar
138  *
139  */
140 template<typename Scalar>
141 struct _AddOp:_BinaryOperator<Scalar,_AddOp<Scalar>>
142 {
operator ()_AddOp143     Scalar const operator()(const Scalar lhs,
144                             const Scalar rhs) const {
145         return(lhs + rhs);
146     }
147 
148 #if defined(HAS_VECTOR)
149     using Vector=typename vector_traits<Scalar>::vector ;
150     using pred_t = typename vector_traits<Scalar>::predicate_t;
151 
operator ()_AddOp152     Vector const operator()(const Vector lhs,
153                             const Vector rhs) const
154     {
155         return(inner::vadd(lhs,rhs));
156     }
157 
operator ()_AddOp158     Vector const operator()(const Vector lhs,
159                             const Scalar rhs) const
160     {
161         return(inner::vadd(lhs,rhs));
162     }
163 
operator ()_AddOp164     Vector const operator()(const Scalar lhs,
165                             const Vector rhs) const
166     {
167         return(inner::vadd(lhs,rhs));
168     }
169 
170     template<typename T=Scalar,
171              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_AddOp172     Vector const operator()(const Vector lhs,
173                             const Vector rhs,
174                             const pred_t p0) const
175     {
176         return(inner::vadd(lhs,rhs,p0));
177     }
178 
179     template<typename T=Scalar,
180              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_AddOp181     Vector const operator()(const Vector lhs,
182                             const Scalar rhs,
183                             const pred_t p0) const
184     {
185         return(inner::vadd(lhs,rhs,p0));
186     }
187 
188     template<typename T=Scalar,
189              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_AddOp190     Vector const operator()(const Scalar lhs,
191                             const Vector rhs,
192                             const pred_t p0) const
193     {
194         return(inner::vadd(lhs,rhs,p0));
195     }
196 #endif
197 };
198 
199 /**
200  * @brief  Sub operator
201  *
202  * @tparam Scalar Datatype for scalar
203  *
204  */
205 template<typename Scalar>
206 struct _SubOp:_BinaryOperator<Scalar,_SubOp<Scalar>>
207 {
operator ()_SubOp208     Scalar const operator()(const Scalar lhs,
209                             const Scalar rhs) const {
210         return(lhs - rhs);
211     }
212 
213 #if defined(HAS_VECTOR)
214     using Vector=typename vector_traits<Scalar>::vector ;
215     using pred_t = typename vector_traits<Scalar>::predicate_t;
216 
operator ()_SubOp217     Vector const operator()(const Vector lhs,
218                             const Vector rhs) const
219     {
220         return(inner::vsub(lhs,rhs));
221     }
222 
operator ()_SubOp223     Vector const operator()(const Vector lhs,
224                             const Scalar rhs) const
225     {
226         return(inner::vsub(lhs,rhs));
227     }
228 
operator ()_SubOp229     Vector const operator()(const Scalar lhs,
230                             const Vector rhs) const
231     {
232         return(inner::vsub(lhs,rhs));
233     }
234 
235     template<typename T=Scalar,
236              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_SubOp237     Vector const operator()(const Vector lhs,
238                             const Vector rhs,
239                             const pred_t p0) const
240     {
241         return(inner::vsub(lhs,rhs,p0));
242     }
243 
244     template<typename T=Scalar,
245              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_SubOp246     Vector const operator()(const Vector lhs,
247                             const Scalar rhs,
248                             const pred_t p0) const
249     {
250         return(inner::vsub(lhs,rhs,p0));
251     }
252 
253     template<typename T=Scalar,
254              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_SubOp255     Vector const operator()(const Scalar lhs,
256                             const Vector rhs,
257                             const pred_t p0) const
258     {
259         return(inner::vsub(lhs,rhs,p0));
260     }
261 #endif
262 };
263 
264 
265 /**
266  * @brief  Mul operator
267  *
268  * @tparam Scalar Datatype for scalar
269  *
270  */
271 template<typename Scalar>
272 struct _MulOp:_BinaryOperator<Scalar,_MulOp<Scalar>>
273 {
operator ()_MulOp274     Scalar const operator()(const Scalar lhs,
275                             const Scalar rhs) const {
276         return(lhs * rhs);
277     }
278 
279 #if defined(HAS_VECTOR)
280     using Vector= typename vector_traits<Scalar>::vector ;
281     using pred_t = typename vector_traits<Scalar>::predicate_t;
282 
operator ()_MulOp283     Vector const operator()(const Vector lhs,
284                             const Vector rhs) const
285     {
286         return(inner::vmul(lhs,rhs));
287     }
288 
operator ()_MulOp289     Vector const operator()(const Vector lhs,
290                             const Scalar rhs) const
291     {
292         return(inner::vmul(lhs,rhs));
293     }
294 
operator ()_MulOp295     Vector const operator()(const Scalar lhs,
296                             const Vector rhs) const
297     {
298         return(inner::vmul(lhs,rhs));
299     }
300 
301     template<typename T=Scalar,
302              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_MulOp303     Vector const operator()(const Vector lhs,
304                             const Vector rhs,
305                             const pred_t p0) const
306     {
307         return(inner::vmul(lhs,rhs,p0));
308     }
309 
310     template<typename T=Scalar,
311              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_MulOp312     Vector const operator()(const Vector lhs,
313                             const Scalar rhs,
314                             const pred_t p0) const
315     {
316         return(inner::vmul(lhs,rhs,p0));
317     }
318 
319     template<typename T=Scalar,
320              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_MulOp321     Vector const operator()(const Scalar lhs,
322                             const Vector rhs,
323                             const pred_t p0) const
324     {
325         return(inner::vmul(lhs,rhs,p0));
326     }
327 #endif
328 };
329 
330 /*
331  *
332  * UNARY
333  *
334  */
335 
336 /**
337  * @brief  Neg operator
338  *
339  * @tparam Scalar Datatype for scalar
340  *
341  */
342 template<typename Scalar>
343 struct _NegOp:_UnaryOperator<Scalar,_NegOp<Scalar>>
344 {
operator ()_NegOp345     Scalar const operator()(const Scalar lhs) const {
346         return(-lhs);
347     }
348 
349 #if defined(HAS_VECTOR)
350     using Vector= typename vector_traits<Scalar>::vector ;
351     using pred_t = typename vector_traits<Scalar>::predicate_t;
352 
operator ()_NegOp353     Vector const operator()(const Vector lhs) const
354     {
355         return(inner::vneg(lhs));
356     }
357 
358     template<typename T=Scalar,
359              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_NegOp360     Vector const operator()(const Vector lhs,
361                             const pred_t p0) const
362     {
363         return(inner::vneg(lhs,p0));
364     }
365 
366 
367 #endif
368 };
369 
370 
371 /**
372  * @brief  No operator
373  *
374  * @tparam Scalar Datatype for scalar
375  *
376  */
377 template<typename Scalar>
378 struct _NoOp:_UnaryOperator<Scalar,_NoOp<Scalar>>
379 {
operator ()_NoOp380     Scalar const operator()(const Scalar lhs) const {
381         return(lhs);
382     }
383 
384 #if defined(HAS_VECTOR)
385     using Vector= typename vector_traits<Scalar>::vector ;
386     using pred_t = typename vector_traits<Scalar>::predicate_t;
387 
operator ()_NoOp388     Vector const operator()(const Vector lhs) const
389     {
390         return(lhs);
391     }
392 
393     template<typename T=Scalar,
394              typename std::enable_if<vector_traits<T>::has_predicate,bool>::type = true>
operator ()_NoOp395     Vector const operator()(const Vector lhs,
396                             const pred_t p0) const
397     {
398         (void)p0;
399         return(lhs);
400     }
401 
402 #endif
403 };
404 
405 /*! @} */