File: vsip/impl/fns_elementwise.hpp
1|
2|
3|
4|
5|
6|
7|
8|
9|
10|
11| #ifndef VSIP_IMPL_FNS_ELEMENTWISE_HPP
12| #define VSIP_IMPL_FNS_ELEMENTWISE_HPP
13|
14|
15|
16|
17|
18| #include <vsip/impl/expr_functor.hpp>
19| #include <vsip/impl/promote.hpp>
20| #include <vsip/impl/fns_scalar.hpp>
21| #include <vsip/impl/metaprogramming.hpp>
22|
23| namespace vsip
24| {
25| namespace impl
26| {
27|
28|
29|
30| #define VSIP_IMPL_UNARY_FUNCTOR(fname) \
31| template <typename T> \
32| struct fname##_functor \
33| { \
34| typedef T result_type; \
35| static char const* name() { return #fname; } \
36| static result_type apply(T t) { return fn::fname(t);} \
37| result_type operator()(T t) const { return apply(t);} \
38| };
39|
40| #define VSIP_IMPL_UNARY_FUNCTOR_RETN(fname, retn) \
41| template <typename T> \
42| struct fname##_functor \
43| { \
44| typedef retn result_type; \
45| static char const* name() { return #fname; } \
46| static result_type apply(T t) { return fn::fname(t);} \
47| result_type operator()(T t) const { return apply(t);} \
48| };
49|
50| #define VSIP_IMPL_UNARY_DISPATCH(fname) \
51| template <typename T> \
52| struct Dispatch_##fname : \
53| ITE_Type<Is_view_type<T>::value, \
54| As_type<Unary_func_view<fname##_functor, T> >, \
55| As_type<fname##_functor<T> > >::type \
56| { \
57| };
58|
59| #define VSIP_IMPL_UNARY_FUNCTION(fname) \
60| template <typename T> \
61| inline \
62| typename Dispatch_##fname<T>::result_type \
63| fname(T t) { return Dispatch_##fname<T>::apply(t);}
64|
65| #define VSIP_IMPL_UNARY_FUNC(fname) \
66| VSIP_IMPL_UNARY_FUNCTOR(fname) \
67| VSIP_IMPL_UNARY_DISPATCH(fname) \
68| VSIP_IMPL_UNARY_FUNCTION(fname)
69|
70| #define VSIP_IMPL_UNARY_FUNC_RETN(fname, retn) \
71| VSIP_IMPL_UNARY_FUNCTOR_RETN(fname, retn) \
72| VSIP_IMPL_UNARY_DISPATCH(fname) \
73| VSIP_IMPL_UNARY_FUNCTION(fname)
74|
75|
76|
77| #define VSIP_IMPL_UNARY_OP(op, fname) \
78| template <typename T> \
79| typename Dispatch_##fname<typename Is_view_type<T>::type>::result_type \
80| operator op(T t) \
81| { return Dispatch_##fname<T>::apply(t);}
82|
83|
84|
85| #define VSIP_IMPL_BINARY_FUNCTOR(fname) \
86| template <typename T1, typename T2> \
87| struct fname##_functor \
88| { \
89| typedef typename Promotion<T1, T2>::type result_type; \
90| static char const* name() { return #fname; } \
91| static result_type apply(T1 t1, T2 t2) { return fn::fname(t1, t2);} \
92| result_type operator()(T1 t1, T2 t2) const { return apply(t1, t2);} \
93| };
94|
95| #define VSIP_IMPL_BINARY_FUNCTOR_RETN(fname, retn) \
96| template <typename T1, typename T2> \
97| struct fname##_functor \
98| { \
99| typedef retn result_type; \
100| static char const* name() { return #fname; } \
101| static result_type apply(T1 t1, T2 t2) { return fn::fname(t1, t2);} \
102| result_type operator()(T1 t1, T2 t2) const { return apply(t1, t2);} \
103| };
104|
105| #define VSIP_IMPL_BINARY_FUNCTOR_SCALAR_RETN(fname) \
106| template <typename T1, typename T2> \
107| struct fname##_functor \
108| { \
109| typedef typename Scalar_of<typename Promotion<T1, T2>::type>::type \
110| result_type; \
111| static char const* name() { return #fname; } \
112| static result_type apply(T1 t1, T2 t2) { return fn::fname(t1, t2);} \
113| result_type operator()(T1 t1, T2 t2) const { return apply(t1, t2);} \
114| };
115|
116| #define VSIP_IMPL_BINARY_DISPATCH(fname) \
117| template <typename T1, typename T2> \
118| struct Dispatch_##fname : \
119| ITE_Type<Is_view_type<T1>::value || Is_view_type<T2>::value, \
120| As_type<Binary_func_view<fname##_functor, T1, T2> >, \
121| As_type<fname##_functor<T1, T2> > >::type \
122| { \
123| };
124|
125|
126|
127| #define VSIP_IMPL_BINARY_OP_DISPATCH(fname) \
128| template <typename T1, typename T2, \
129| bool P = Is_view_type<T1>::value || Is_view_type<T2>::value> \
130| struct Dispatch_op_##fname \
131| : As_type<Binary_func_view<fname##_functor, T1, T2> >::type {}; \
132| template <typename T1, typename T2> \
133| struct Dispatch_op_##fname<T1, T2, false> {}; \
134|
135| #define VSIP_IMPL_BINARY_FUNCTION(fname) \
136| template <typename T1, typename T2> \
137| inline \
138| typename Dispatch_##fname<T1, T2>::result_type \
139| fname(T1 t1, T2 t2) { return Dispatch_##fname<T1, T2>::apply(t1, t2);}
140|
141| #define VSIP_IMPL_BINARY_OPERATOR_ONE(op, fname) \
142| template <typename T1, typename T2> \
143| inline \
144| typename Dispatch_op_##fname<T1, T2>::result_type \
145| operator op(T1 t1, T2 t2) { return Dispatch_op_##fname<T1, T2>::apply(t1, t2);}
146|
147| #define VSIP_IMPL_BINARY_OPERATOR_TWO(op, fname) \
148| template <template <typename, typename> class View, \
149| typename T1, typename Block1, typename T2> \
150| inline \
151| typename Dispatch_op_##fname<View<T1, Block1>, T2>::result_type \
152| operator op(View<T1, Block1> t1, T2 t2) \
153| { return Dispatch_op_##fname<View<T1, Block1>, T2>::apply(t1, t2);} \
154| \
155| template <template <typename, typename> class View, \
156| typename T1, typename T2, typename Block2> \
157| inline \
158| typename Dispatch_op_##fname<T1, View<T2, Block2> >::result_type \
159| operator op(T1 t1, View<T2, Block2> t2) \
160| { return Dispatch_op_##fname<T1, View<T2, Block2> >::apply(t1, t2);} \
161| \
162| template <template <typename, typename> class LView, \
163| template <typename, typename> class RView, \
164| typename T1, typename Block1, \
165| typename T2, typename Block2> \
166| inline \
167| typename Dispatch_op_##fname<LView<T1, Block1>, \
168| RView<T2, Block2> >::result_type \
169| operator op(LView<T1, Block1> t1, RView<T2, Block2> t2) \
170| { return Dispatch_op_##fname<LView<T1, Block1>, \
171| RView<T2, Block2> >::apply(t1, t2);}
172|
173| #if (defined(__GNUC__) && __GNUC__ < 4) || defined(__ghs__) || defined(__ICL)
174| # define VSIP_IMPL_BINARY_OPERATOR(op, fname) \
175| VSIP_IMPL_BINARY_OPERATOR_ONE(op, fname)
176| #else
177| # define VSIP_IMPL_BINARY_OPERATOR(op, fname) \
178| VSIP_IMPL_BINARY_OPERATOR_TWO(op, fname)
179| #endif
180|
181|
182| #define VSIP_IMPL_BINARY_VIEW_FUNCTION(fname) \
183| template <template <typename, typename> class V, \
184| typename T, typename B> \
185| inline \
186| typename Dispatch_##fname<V<T,B>, V<T,B> >::result_type \
187| fname(V<T,B> t1, V<T,B> t2) \
188| { return Dispatch_##fname<V<T,B>, V<T,B> >::apply(t1, t2);}
189|
190| #define VSIP_IMPL_BINARY_FUNC(fname) \
191| VSIP_IMPL_BINARY_FUNCTOR(fname) \
192| VSIP_IMPL_BINARY_DISPATCH(fname) \
193| VSIP_IMPL_BINARY_FUNCTION(fname) \
194| VSIP_IMPL_BINARY_VIEW_FUNCTION(fname)
195|
196| #define VSIP_IMPL_BINARY_FUNC_RETN(fname, retn) \
197| VSIP_IMPL_BINARY_FUNCTOR_RETN(fname, retn) \
198| VSIP_IMPL_BINARY_DISPATCH(fname) \
199| VSIP_IMPL_BINARY_FUNCTION(fname)
200|
201| #define VSIP_IMPL_BINARY_FUNC_SCALAR_RETN(fname) \
202| VSIP_IMPL_BINARY_FUNCTOR_SCALAR_RETN(fname) \
203| VSIP_IMPL_BINARY_DISPATCH(fname) \
204| VSIP_IMPL_BINARY_FUNCTION(fname)
205|
206| #define VSIP_IMPL_BINARY_OP(op, fname) \
207| VSIP_IMPL_BINARY_OP_DISPATCH(fname) \
208| VSIP_IMPL_BINARY_OPERATOR(op, fname)
209|
210|
211|
212| #define VSIP_IMPL_TERNARY_FUNC(fname) \
213| template <typename T1, typename T2, typename T3> \
214| struct fname##_functor \
215| { \
216| typedef typename Promotion<typename Promotion<T1, T2>::type, \
217| T3>::type result_type; \
218| static char const* name() { return #fname; } \
219| static result_type apply(T1 t1, T2 t2, T3 t3) \
220| { return fn::fname(t1, t2, t3);} \
221| result_type operator()(T1 t1, T2 t2, T3 t3) const \
222| { return apply(t1, t2, t3);} \
223| }; \
224| \
225| template <typename T1, typename T2, typename T3> \
226| struct Dispatch_##fname : \
227| ITE_Type<Is_view_type<T1>::value || \
228| Is_view_type<T2>::value || \
229| Is_view_type<T3>::value, \
230| As_type<Ternary_func_view<fname##_functor, T1, T2, T3> >, \
231| As_type<fname##_functor<T1, T2, T3> > >::type \
232| { \
233| }; \
234| \
235| template <typename T1, typename T2, typename T3> \
236| typename Dispatch_##fname<T1, T2, T3>::result_type \
237| fname(T1 t1, T2 t2, T3 t3) \
238| { return Dispatch_##fname<T1, T2, T3>::apply(t1, t2, t3);}
239|
240|
241|
242|
243|
244|
245| VSIP_IMPL_UNARY_FUNC(acos)
246|
247| template <typename T> struct arg_functor {};
248|
249| template <typename T>
250| struct arg_functor<std::complex<T> >
251| {
252| typedef T result_type;
253| static char const* name() { return "arg"; }
254| static result_type apply(std::complex<T> t) { return fn::arg(t);}
255| result_type operator()(std::complex<T> t) const { return apply(t);}
256| };
257|
258| VSIP_IMPL_UNARY_DISPATCH(arg)
259| VSIP_IMPL_UNARY_FUNCTION(arg)
260|
261| VSIP_IMPL_UNARY_FUNC(asin)
262| VSIP_IMPL_UNARY_FUNC(atan)
263| VSIP_IMPL_UNARY_FUNC(bnot)
264| VSIP_IMPL_UNARY_FUNC(ceil)
265| VSIP_IMPL_UNARY_FUNC(conj)
266| VSIP_IMPL_UNARY_FUNC(cos)
267| VSIP_IMPL_UNARY_FUNC(cosh)
268|
269| template <typename T>
270| struct euler_functor
271| {
272| typedef std::complex<T> result_type;
273| static char const* name() { return "euler"; }
274| static result_type apply(T t) { return fn::euler(t);}
275| result_type operator()(T t) const { return apply(t);}
276| };
277|
278| VSIP_IMPL_UNARY_DISPATCH(euler)
279| VSIP_IMPL_UNARY_FUNCTION(euler)
280|
281| VSIP_IMPL_UNARY_FUNC(exp)
282| VSIP_IMPL_UNARY_FUNC(exp10)
283| VSIP_IMPL_UNARY_FUNC(floor)
284|
285| template <typename T> struct imag_functor {};
286|
287| template <typename T>
288| struct imag_functor<std::complex<T> >
289| {
290| typedef T result_type;
291| static char const* name() { return "imag"; }
292| static result_type apply(std::complex<T> t) { return fn::imag(t);}
293| result_type operator()(std::complex<T> t) const { return apply(t);}
294| };
295|
296| VSIP_IMPL_UNARY_DISPATCH(imag)
297| VSIP_IMPL_UNARY_FUNCTION(imag)
298|
299| VSIP_IMPL_UNARY_FUNC_RETN(lnot, bool)
300| VSIP_IMPL_UNARY_FUNC(log)
301| VSIP_IMPL_UNARY_FUNC(log10)
302| VSIP_IMPL_UNARY_FUNC_RETN(mag, typename impl::Scalar_of<T>::type)
303| VSIP_IMPL_UNARY_FUNC_RETN(magsq, typename impl::Scalar_of<T>::type)
304| VSIP_IMPL_UNARY_FUNC(neg)
305|
306| template <typename T> struct real_functor {};
307|
308| template <typename T>
309| struct real_functor<std::complex<T> >
310| {
311| typedef T result_type;
312| static char const* name() { return "real"; }
313| static result_type apply(std::complex<T> t) { return fn::real(t);}
314| result_type operator()(std::complex<T> t) const { return apply(t);}
315| };
316|
317| VSIP_IMPL_UNARY_DISPATCH(real)
318| VSIP_IMPL_UNARY_FUNCTION(real)
319|
320| VSIP_IMPL_UNARY_FUNC(recip)
321| VSIP_IMPL_UNARY_FUNC(rsqrt)
322| VSIP_IMPL_UNARY_FUNC(sin)
323| VSIP_IMPL_UNARY_FUNC(sinh)
324| VSIP_IMPL_UNARY_FUNC(sq)
325| VSIP_IMPL_UNARY_FUNC(sqrt)
326| VSIP_IMPL_UNARY_FUNC(tan)
327| VSIP_IMPL_UNARY_FUNC(tanh)
328|
329| VSIP_IMPL_UNARY_FUNC(impl_conj)
330|
331| template <typename T>
332| struct impl_real_functor
333| {
334| typedef typename Scalar_of<T>::type result_type;
335| static char const* name() { return "impl_real"; }
336| static result_type apply(T t) { return fn::impl_real(t);}
337| result_type operator()(T t) const { return apply(t);}
338| };
339|
340| VSIP_IMPL_UNARY_DISPATCH(impl_real)
341| VSIP_IMPL_UNARY_FUNCTION(impl_real)
342|
343| template <typename T>
344| struct impl_imag_functor
345| {
346| typedef typename Scalar_of<T>::type result_type;
347| static char const* name() { return "impl_imag"; }
348| static result_type apply(T t) { return fn::impl_imag(t);}
349| result_type operator()(T t) const { return apply(t);}
350| };
351|
352| VSIP_IMPL_UNARY_DISPATCH(impl_imag)
353| VSIP_IMPL_UNARY_FUNCTION(impl_imag)
354|
355|
356|
357|
358|
359| VSIP_IMPL_BINARY_FUNC(add)
360| VSIP_IMPL_BINARY_FUNC(atan2)
361| VSIP_IMPL_BINARY_FUNC(band)
362| VSIP_IMPL_BINARY_FUNC(bor)
363| VSIP_IMPL_BINARY_FUNC(bxor)
364| VSIP_IMPL_BINARY_FUNC(div)
365| VSIP_IMPL_BINARY_FUNC_RETN(eq, bool)
366| VSIP_IMPL_BINARY_FUNC(fmod)
367| VSIP_IMPL_BINARY_FUNC_RETN(ge, bool)
368| VSIP_IMPL_BINARY_FUNC_RETN(gt, bool)
369| VSIP_IMPL_BINARY_FUNC(hypot)
370| VSIP_IMPL_BINARY_FUNC(jmul)
371| VSIP_IMPL_BINARY_FUNC_RETN(land, bool)
372| VSIP_IMPL_BINARY_FUNC_RETN(le, bool)
373| VSIP_IMPL_BINARY_FUNC_RETN(lt, bool)
374| VSIP_IMPL_BINARY_FUNC_RETN(lor, bool)
375| VSIP_IMPL_BINARY_FUNC_RETN(lxor, bool)
376| VSIP_IMPL_BINARY_FUNC(mul)
377| VSIP_IMPL_BINARY_FUNC(max)
378| VSIP_IMPL_BINARY_FUNC(maxmg)
379| VSIP_IMPL_BINARY_FUNC_SCALAR_RETN(maxmgsq)
380| VSIP_IMPL_BINARY_FUNC(min)
381| VSIP_IMPL_BINARY_FUNC(minmg)
382| VSIP_IMPL_BINARY_FUNC_SCALAR_RETN(minmgsq)
383| VSIP_IMPL_BINARY_FUNC_RETN(ne, bool)
384| VSIP_IMPL_BINARY_FUNC(pow)
385| VSIP_IMPL_BINARY_FUNC(sub)
386|
387|
388|
389|
390|
391| VSIP_IMPL_TERNARY_FUNC(am)
392| VSIP_IMPL_TERNARY_FUNC(expoavg)
393| VSIP_IMPL_TERNARY_FUNC(ma)
394| VSIP_IMPL_TERNARY_FUNC(msb)
395| VSIP_IMPL_TERNARY_FUNC(sbm)
396| VSIP_IMPL_TERNARY_FUNC(ite)
397|
398|
399|
400|
401|
402| VSIP_IMPL_UNARY_OP(!, lnot)
403| VSIP_IMPL_UNARY_OP(~, bnot)
404|
405|
406|
407|
408|
409| VSIP_IMPL_BINARY_OP(==, eq)
410| VSIP_IMPL_BINARY_OP(>=, ge)
411| VSIP_IMPL_BINARY_OP(>, gt)
412| VSIP_IMPL_BINARY_OP(<=, le)
413| VSIP_IMPL_BINARY_OP(<, lt)
414| VSIP_IMPL_BINARY_OP(!=, ne)
415| VSIP_IMPL_BINARY_OP(&&, land)
416| VSIP_IMPL_BINARY_OP(&, band)
417| VSIP_IMPL_BINARY_OP(||, lor)
418| VSIP_IMPL_BINARY_OP(|, bor)
419|
420| template <typename T1, typename T2>
421| struct bxor_or_lxor_functor
422| {
423| typedef typename Promotion<T1, T2>::type result_type;
424| static char const* name() { return "bxor"; }
425| static result_type apply(T1 t1, T2 t2) { return fn::bxor(t1, t2);}
426| result_type operator()(T1 t1, T2 t2) const { return apply(t1, t2);}
427| };
428|
429| template <>
430| struct bxor_or_lxor_functor<bool, bool>
431| {
432| typedef bool result_type;
433| static char const* name() { return "lxor"; }
434| static result_type apply(bool t1, bool t2) { return fn::lxor(t1, t2);}
435| result_type operator()(bool t1, bool t2) const { return apply(t1, t2);}
436| };
437|
438| VSIP_IMPL_BINARY_OP(^, bxor_or_lxor)
439|
440| } // namespace vsip::impl
441|
442| using impl::acos;
443| using impl::arg;
444| using impl::asin;
445| using impl::atan;
446| using impl::bnot;
447| using impl::ceil;
448| using impl::conj;
449| using impl::cos;
450| using impl::cosh;
451| using impl::euler;
452| using impl::exp;
453| using impl::exp10;
454| using impl::floor;
455| using impl::imag;
456| using impl::lnot;
457| using impl::log;
458| using impl::log10;
459| using impl::mag;
460| using impl::magsq;
461| using impl::neg;
462| using impl::real;
463| using impl::recip;
464| using impl::rsqrt;
465| using impl::sin;
466| using impl::sinh;
467| using impl::sq;
468| using impl::sqrt;
469| using impl::tan;
470| using impl::tanh;
471|
472| using impl::add;
473| using impl::atan2;
474| using impl::band;
475| using impl::bor;
476| using impl::bxor;
477| using impl::div;
478| using impl::eq;
479| using impl::fmod;
480| using impl::ge;
481| using impl::gt;
482| using impl::hypot;
483| using impl::jmul;
484| using impl::land;
485| using impl::le;
486| using impl::lt;
487| using impl::lor;
488| using impl::lxor;
489| using impl::max;
490| using impl::maxmg;
491| using impl::maxmgsq;
492| using impl::min;
493| using impl::minmg;
494| using impl::minmgsq;
495| using impl::mul;
496| using impl::ne;
497| using impl::pow;
498| using impl::sub;
499|
500| using impl::am;
501| using impl::expoavg;
502| using impl::ma;
503| using impl::msb;
504| using impl::sbm;
505|
506| using impl::operator!;
507| using impl::operator~;
508| using impl::operator==;
509| using impl::operator>=;
510| using impl::operator>;
511| using impl::operator<=;
512| using impl::operator<;
513| using impl::operator!=;
514| using impl::operator&&;
515| using impl::operator&;
516| using impl::operator||;
517| using impl::operator|;
518|
519| }
520|
521| #undef VSIP_IMPL_TERNARY_FUNC
522| #undef VSIP_IMPL_BINARY_FUNC_RETN
523| #undef VSIP_IMPL_BINARY_FUNC
524| #undef VSIP_IMPL_UNARY_FUNC_RETN
525| #undef VSIP_IMPL_UNARY_FUNC
526| #undef VSIP_IMPL_BINARY_FUNCTOR_RETN
527| #undef VSIP_IMPL_BINARY_FUNCTOR
528| #undef VSIP_IMPL_BINARY_DISPATCH
529| #undef VSIP_IMPL_BINARY_FUNCTION
530| #undef VSIP_IMPL_UNARY_FUNCTOR_RETN
531| #undef VSIP_IMPL_UNARY_FUNCTOR
532| #undef VSIP_IMPL_UNARY_DISPATCH
533| #undef VSIP_IMPL_UNARY_FUNCTION
534|
535| #endif