File: vsip/impl/sal/eval_elementwise.hpp
1|
2|
3|
4|
5|
6|
7|
8|
9| #ifndef VSIP_IMPL_SAL_EVAL_HPP
10| #define VSIP_IMPL_SAL_EVAL_HPP
11|
12|
13|
14|
15|
16| #include <vsip/impl/expr_serial_evaluator.hpp>
17| #include <vsip/impl/expr_scalar_block.hpp>
18| #include <vsip/impl/expr_unary_block.hpp>
19| #include <vsip/impl/expr_binary_block.hpp>
20| #include <vsip/impl/expr_ternary_block.hpp>
21| #include <vsip/impl/expr_operations.hpp>
22| #include <vsip/impl/fns_elementwise.hpp>
23| #include <vsip/impl/extdata.hpp>
24| #include <vsip/impl/metaprogramming.hpp>
25| #include <vsip/impl/sal/eval_util.hpp>
26| #include <vsip/impl/adjust-layout.hpp>
27|
28|
29|
30|
31|
32|
33|
34| namespace vsip
35| {
36| namespace impl
37| {
38| namespace sal
39| {
40|
41|
42|
43|
44|
45|
46|
47|
48|
49|
50|
51|
52|
53|
54|
55|
56| template <template <typename, typename> class Operator,
57| typename LType,
58| typename RType,
59| typename DstType>
60| struct Is_op2_supported
61| {
62| static bool const value = false;
63| };
64|
65| template <template <typename> class Operator,
66| typename SrcType,
67| typename DstType>
68| struct Is_op1_supported
69| {
70| static bool const value = false;
71| };
72|
73| template <template <typename, typename, typename> class Operator,
74| typename Type1,
75| typename Type2,
76| typename Type3,
77| typename DstType>
78| struct Is_op3_supported
79| {
80| static bool const value = false;
81| };
82|
83|
84| template <typename, typename, typename> struct cma_token;
85| template <typename> struct copy_token;
86|
87| #define VSIP_IMPL_OP1SUP(Op, T1, DT)
88| template <> struct Is_op1_supported<Op, T1, DT >
89| { static bool const value = true; }
90|
91| #define VSIP_IMPL_OP2SUP(Op, LT, RT, DT)
92| template <> struct Is_op2_supported<Op, LT, RT, DT >
93| { static bool const value = true; }
94|
95| #define VSIP_IMPL_OP3SUP(Op, T1, T2, T3, DT)
96| template <> struct Is_op3_supported<Op, T1, T2, T3, DT >
97| { static bool const value = true; }
98|
99| typedef std::pair<float*, float*> split_float;
100| typedef std::pair<double*, double*> split_double;
101|
102|
103| /***********************************************************************
104| Unary operators and functions provided by SAL
105| ***********************************************************************/
106|
107| VSIP_IMPL_OP1SUP(magsq_functor, complex<float>*, float*);
108| VSIP_IMPL_OP1SUP(magsq_functor, complex<double>*, double*);
109| VSIP_IMPL_OP1SUP(magsq_functor, split_float, float*);
110| VSIP_IMPL_OP1SUP(magsq_functor, split_double, double*);
111|
112| VSIP_IMPL_OP1SUP(op::Minus, int*, int*);
113| VSIP_IMPL_OP1SUP(op::Minus, float*, float*);
114| VSIP_IMPL_OP1SUP(op::Minus, double*, double*);
115| VSIP_IMPL_OP1SUP(op::Minus, complex<float>*, complex<float>*);
116| VSIP_IMPL_OP1SUP(op::Minus, complex<double>*, complex<double>*);
117| VSIP_IMPL_OP1SUP(op::Minus, split_float, split_float);
118| VSIP_IMPL_OP1SUP(op::Minus, split_double, split_double);
119|
120| VSIP_IMPL_OP1SUP(mag_functor, int*, int*);
121| VSIP_IMPL_OP1SUP(mag_functor, float*, float*);
122| VSIP_IMPL_OP1SUP(mag_functor, double*, double*);
123| VSIP_IMPL_OP1SUP(mag_functor, complex<float>*, float*);
124| VSIP_IMPL_OP1SUP(mag_functor, split_float, float*);
125|
126| VSIP_IMPL_OP1SUP(cos_functor, float*, float*);
127| VSIP_IMPL_OP1SUP(cos_functor, double*, double*);
128|
129| VSIP_IMPL_OP1SUP(sin_functor, float*, float*);
130| VSIP_IMPL_OP1SUP(sin_functor, double*, double*);
131|
132| VSIP_IMPL_OP1SUP(tan_functor, float*, float*);
133|
134| VSIP_IMPL_OP1SUP(atan_functor, float*, float*);
135| VSIP_IMPL_OP1SUP(atan_functor, double*, double*);
136|
137| VSIP_IMPL_OP1SUP(log_functor, float*, float*);
138| VSIP_IMPL_OP1SUP(log_functor, double*, double*);
139|
140| VSIP_IMPL_OP1SUP(log10_functor, float*, float*);
141| VSIP_IMPL_OP1SUP(log10_functor, double*, double*);
142|
143| VSIP_IMPL_OP1SUP(exp_functor, float*, float*);
144| VSIP_IMPL_OP1SUP(exp_functor, double*, double*);
145|
146| VSIP_IMPL_OP1SUP(exp10_functor, float*, float*);
147| VSIP_IMPL_OP1SUP(exp10_functor, double*, double*);
148|
149| VSIP_IMPL_OP1SUP(sqrt_functor, float*, float*);
150| VSIP_IMPL_OP1SUP(sqrt_functor, double*, double*);
151| VSIP_IMPL_OP1SUP(sqrt_functor, complex<float>*, complex<float>*);
152| VSIP_IMPL_OP1SUP(sqrt_functor, split_float, split_float);
153|
154| VSIP_IMPL_OP1SUP(rsqrt_functor, float*, float*);
155| VSIP_IMPL_OP1SUP(rsqrt_functor, double*, double*);
156|
157| VSIP_IMPL_OP1SUP(sq_functor, float*, float*);
158| VSIP_IMPL_OP1SUP(sq_functor, double*, double*);
159|
160| VSIP_IMPL_OP1SUP(recip_functor, float*, float*);
161| // no scalar double
162| VSIP_IMPL_OP1SUP(recip_functor, complex<float>*, complex<float>*);
163| VSIP_IMPL_OP1SUP(recip_functor, split_float, split_float);
164| VSIP_IMPL_OP1SUP(recip_functor, complex<double>*, complex<double>*);
165| VSIP_IMPL_OP1SUP(recip_functor, split_double, split_double);
166|
167| VSIP_IMPL_OP1SUP(copy_token, float*, float*);
168| VSIP_IMPL_OP1SUP(copy_token, complex<float>*, complex<float>*);
169| VSIP_IMPL_OP1SUP(copy_token, split_float, split_float);
170| VSIP_IMPL_OP1SUP(copy_token, complex<double>*, complex<double>*);
171| VSIP_IMPL_OP1SUP(copy_token, split_double, split_double);
172|
173| VSIP_IMPL_OP1SUP(copy_token, split_float, complex<float>*);
174| VSIP_IMPL_OP1SUP(copy_token, complex<float>*, split_float);
175| VSIP_IMPL_OP1SUP(copy_token, split_double, complex<double>*);
176| VSIP_IMPL_OP1SUP(copy_token, complex<double>*, split_double);
177|
178|
179|
180| /***********************************************************************
181| Binary operators and functions provided by SAL
182| ***********************************************************************/
183|
184| // straight-up vector add
185| VSIP_IMPL_OP2SUP(op::Add, int*, int*, int*);
186| VSIP_IMPL_OP2SUP(op::Add, float*, float*, float*);
187| VSIP_IMPL_OP2SUP(op::Add, double*, double*, double*);
188| VSIP_IMPL_OP2SUP(op::Add, complex<float>*, complex<float>*, complex<float>*);
189| VSIP_IMPL_OP2SUP(op::Add, complex<double>*, complex<double>*,complex<double>*);
190| VSIP_IMPL_OP2SUP(op::Add, split_float, split_float, split_float);
191| VSIP_IMPL_OP2SUP(op::Add, split_double, split_double, split_double);
192|
193| VSIP_IMPL_OP2SUP(op::Add, float*, complex<float>*, complex<float>*);
194| VSIP_IMPL_OP2SUP(op::Add, complex<float>*, float*, complex<float>*);
195| VSIP_IMPL_OP2SUP(op::Add, float*, split_float, split_float);
196| VSIP_IMPL_OP2SUP(op::Add, split_float, float*, split_float);
197| // not crvadddx in SAL
198|
199| // scalar-vector vector add
200| VSIP_IMPL_OP2SUP(op::Add, int, int*, int*);
201| VSIP_IMPL_OP2SUP(op::Add, int*, int, int*);
202| VSIP_IMPL_OP2SUP(op::Add, float, float*, float*);
203| VSIP_IMPL_OP2SUP(op::Add, float*, float, float*);
204| VSIP_IMPL_OP2SUP(op::Add, double, double*, double*);
205| VSIP_IMPL_OP2SUP(op::Add, double*, double, double*);
206| VSIP_IMPL_OP2SUP(op::Add, complex<float>, complex<float>*, complex<float>*);
207| VSIP_IMPL_OP2SUP(op::Add, complex<float>*, complex<float>, complex<float>*);
208| VSIP_IMPL_OP2SUP(op::Add, complex<double>, complex<double>*,complex<double>*);
209| VSIP_IMPL_OP2SUP(op::Add, complex<double>*, complex<double>, complex<double>*);
210| VSIP_IMPL_OP2SUP(op::Add, complex<float>, split_float, split_float);
211| VSIP_IMPL_OP2SUP(op::Add, split_float, complex<float>, split_float);
212| VSIP_IMPL_OP2SUP(op::Add, complex<double>, split_double, split_double);
213| VSIP_IMPL_OP2SUP(op::Add, split_double, complex<double>, split_double);
214|
215| VSIP_IMPL_OP2SUP(op::Add, float, complex<float>*, complex<float>*);
216| VSIP_IMPL_OP2SUP(op::Add, complex<float>*, float, complex<float>*);
217| VSIP_IMPL_OP2SUP(op::Add, double, complex<double>*,complex<double>*);
218| VSIP_IMPL_OP2SUP(op::Add, complex<double>*, double, complex<double>*);
219|
220| VSIP_IMPL_OP2SUP(op::Add, float, split_float, split_float);
221| VSIP_IMPL_OP2SUP(op::Add, split_float, float, split_float);
222| VSIP_IMPL_OP2SUP(op::Add, double, split_double, split_double);
223| VSIP_IMPL_OP2SUP(op::Add, split_double, double, split_double);
224|
225|
226| // straight-up vector sub
227| VSIP_IMPL_OP2SUP(op::Sub, int*, int*, int*);
228| VSIP_IMPL_OP2SUP(op::Sub, float*, float*, float*);
229| VSIP_IMPL_OP2SUP(op::Sub, double*, double*, double*);
230| VSIP_IMPL_OP2SUP(op::Sub, complex<float>*, complex<float>*, complex<float>*);
231| VSIP_IMPL_OP2SUP(op::Sub, complex<double>*, complex<double>*,complex<double>*);
232| VSIP_IMPL_OP2SUP(op::Sub, split_float, split_float, split_float);
233| VSIP_IMPL_OP2SUP(op::Sub, split_double, split_double, split_double);
234|
235| VSIP_IMPL_OP2SUP(op::Sub, complex<float>*, float*, complex<float>*);
236| VSIP_IMPL_OP2SUP(op::Sub, split_float, float*, split_float);
237|
238| // scalar-vector vector sub
239| VSIP_IMPL_OP2SUP(op::Sub, int*, int, int*);
240| // not in sal (op::Sub, float, float*, float*);
241| VSIP_IMPL_OP2SUP(op::Sub, float*, float, float*);
242| // not in sal (op::Sub, double, double*, double*);
243| VSIP_IMPL_OP2SUP(op::Sub, double*, double, double*);
244| // not in sal (op::Sub, complex<float>, complex<float>*, complex<float>*);
245| VSIP_IMPL_OP2SUP(op::Sub, complex<float>*, complex<float>, complex<float>*);
246| // not in sal (op::Sub, complex<double>, complex<double>*,complex<double>*);
247| VSIP_IMPL_OP2SUP(op::Sub, complex<double>*, complex<double>, complex<double>*);
248| // not in sal (op::Sub, complex<float>, split_float, split_float);
249| VSIP_IMPL_OP2SUP(op::Sub, split_float, complex<float>, split_float);
250| // not in sal (op::Sub, complex<double>, split_double, split_double);
251| VSIP_IMPL_OP2SUP(op::Sub, split_double, complex<double>, split_double);
252|
253| VSIP_IMPL_OP2SUP(op::Sub, complex<float>*, float, complex<float>*);
254| VSIP_IMPL_OP2SUP(op::Sub, complex<double>*, double, complex<double>*);
255| VSIP_IMPL_OP2SUP(op::Sub, split_float, float, split_float);
256| VSIP_IMPL_OP2SUP(op::Sub, split_double, double, split_double);
257|
258|
259| // straight-up vector multiply
260| VSIP_IMPL_OP2SUP(op::Mult, int*, int*, int*);
261| VSIP_IMPL_OP2SUP(op::Mult, float*, float*, float*);
262| VSIP_IMPL_OP2SUP(op::Mult, double*, double*, double*);
263| VSIP_IMPL_OP2SUP(op::Mult, complex<float>*, complex<float>*, complex<float>*);
264| VSIP_IMPL_OP2SUP(op::Mult, complex<double>*,complex<double>*,complex<double>*);
265| VSIP_IMPL_OP2SUP(op::Mult, split_float, split_float, split_float);
266| VSIP_IMPL_OP2SUP(op::Mult, split_double, split_double, split_double);
267|
268| // real-complex vector multiply
269| VSIP_IMPL_OP2SUP(op::Mult, complex<float>*, float*, complex<float>*);
270| VSIP_IMPL_OP2SUP(op::Mult, float*, complex<float>*, complex<float>*);
271| VSIP_IMPL_OP2SUP(op::Mult, split_float, float*, split_float);
272| VSIP_IMPL_OP2SUP(op::Mult, float*, split_float, split_float);
273|
274| // scalar-vector vector multiply
275| VSIP_IMPL_OP2SUP(op::Mult, int, int*, int*);
276| VSIP_IMPL_OP2SUP(op::Mult, int*, int, int*);
277| VSIP_IMPL_OP2SUP(op::Mult, float, float*, float*);
278| VSIP_IMPL_OP2SUP(op::Mult, float*, float, float*);
279| VSIP_IMPL_OP2SUP(op::Mult, double, double*, double*);
280| VSIP_IMPL_OP2SUP(op::Mult, double*, double, double*);
281| VSIP_IMPL_OP2SUP(op::Mult, complex<float>, complex<float>*, complex<float>*);
282| VSIP_IMPL_OP2SUP(op::Mult, complex<float>*, complex<float>, complex<float>*);
283| VSIP_IMPL_OP2SUP(op::Mult, complex<double>, complex<double>*,complex<double>*);
284| VSIP_IMPL_OP2SUP(op::Mult, complex<double>*,complex<double>, complex<double>*);
285| VSIP_IMPL_OP2SUP(op::Mult, complex<float>, split_float, split_float);
286| VSIP_IMPL_OP2SUP(op::Mult, split_float, complex<float>, split_float);
287| VSIP_IMPL_OP2SUP(op::Mult, complex<double>, split_double, split_double);
288| VSIP_IMPL_OP2SUP(op::Mult, split_double, complex<double>, split_double);
289|
290| VSIP_IMPL_OP2SUP(op::Mult, float, complex<float>*, complex<float>*);
291| VSIP_IMPL_OP2SUP(op::Mult, complex<float>*, float, complex<float>*);
292| VSIP_IMPL_OP2SUP(op::Mult, double, complex<double>*,complex<double>*);
293| VSIP_IMPL_OP2SUP(op::Mult, complex<double>*,double, complex<double>*);
294|
295| VSIP_IMPL_OP2SUP(op::Mult, float, split_float, split_float);
296| VSIP_IMPL_OP2SUP(op::Mult, split_float, float, split_float);
297| VSIP_IMPL_OP2SUP(op::Mult, double, split_double, split_double);
298| VSIP_IMPL_OP2SUP(op::Mult, split_double, double, split_double);
299|
300|
301|
302| // straight-up vector division
303| VSIP_IMPL_OP2SUP(op::Div, int*, int*, int*);
304| VSIP_IMPL_OP2SUP(op::Div, float*, float*, float*);
305| VSIP_IMPL_OP2SUP(op::Div, double*, double*, double*);
306| VSIP_IMPL_OP2SUP(op::Div, complex<float>*, complex<float>*, complex<float>*);
307| VSIP_IMPL_OP2SUP(op::Div, complex<double>*, complex<double>*,complex<double>*);
308| VSIP_IMPL_OP2SUP(op::Div, split_float, split_float, split_float);
309| VSIP_IMPL_OP2SUP(op::Div, split_double, split_double, split_double);
310|
311| VSIP_IMPL_OP2SUP(op::Div, complex<float>*, float*, complex<float>*);
312| VSIP_IMPL_OP2SUP(op::Div, split_float, float*, split_float);
313|
314| // scalar-vector vector division
315| // not in sal (op::Div, int, int*, int*);
316| VSIP_IMPL_OP2SUP(op::Div, int*, int, int*);
317| VSIP_IMPL_OP2SUP(op::Div, float, float*, float*);
318| VSIP_IMPL_OP2SUP(op::Div, float*, float, float*);
319| // not in sal (op::Div, complex<float>, complex<float>*, complex<float>*);
320| // not in sal (op::Div, complex<float>*, complex<float>, complex<float>*);
321| // not in sal (op::Div, double, double*, double*);
322| VSIP_IMPL_OP2SUP(op::Div, double*, double, double*);
323| // not in sal (op::Div, complex<double>, complex<double>*,complex<double>*);
324| // not in sal (op::Div, complex<double>*,complex<double>, complex<double>*);
325|
326|
327| // Logical
328|
329| VSIP_IMPL_OP2SUP(band_functor, int*, int*, int*);
330| VSIP_IMPL_OP2SUP(bor_functor, int*, int*, int*);
331|
332|
333| // vector comparisons
334|
335| VSIP_IMPL_OP2SUP(max_functor, float*, float*, float*);
336| VSIP_IMPL_OP2SUP(max_functor, double*, double*, double*);
337|
338| VSIP_IMPL_OP2SUP(min_functor, float*, float*, float*);
339| VSIP_IMPL_OP2SUP(min_functor, double*, double*, double*);
340|
341|
342|
343| /***********************************************************************
344| Ternary operators and functions provided by SAL.
345| ***********************************************************************/
346|
347| // Multiply-add
348|
349| VSIP_IMPL_OP3SUP(ma_functor, float, float*, float*, float*);
350| VSIP_IMPL_OP3SUP(ma_functor, float*, float, float*, float*);
351| VSIP_IMPL_OP3SUP(ma_functor, float*, float*, float, float*);
352| VSIP_IMPL_OP3SUP(ma_functor, float*, float*, float*, float*);
353|
354| VSIP_IMPL_OP3SUP(ma_functor, complex<float>*, complex<float>, complex<float>*,
355| complex<float>*);
356| VSIP_IMPL_OP3SUP(ma_functor, complex<float>, complex<float>*, complex<float>*,
357| complex<float>*);
358| VSIP_IMPL_OP3SUP(ma_functor, split_float, complex<float>, split_float,
359| split_float);
360| VSIP_IMPL_OP3SUP(ma_functor, complex<float>, split_float, split_float,
361| split_float);
362|
363| VSIP_IMPL_OP3SUP(ma_functor, double, double*, double*, double*);
364| VSIP_IMPL_OP3SUP(ma_functor, double*, double, double*, double*);
365| VSIP_IMPL_OP3SUP(ma_functor, double*, double*, double, double*);
366| VSIP_IMPL_OP3SUP(ma_functor, double*, double*, double*, double*);
367|
368| VSIP_IMPL_OP3SUP(ma_functor,
369| complex<double>*, complex<double>, complex<double>*,
370| complex<double>*);
371| VSIP_IMPL_OP3SUP(ma_functor,
372| complex<double>, complex<double>*, complex<double>*,
373| complex<double>*);
374|
375|
376| // Multiply-subtract
377|
378| VSIP_IMPL_OP3SUP(msb_functor, float, float*, float*, float*);
379| VSIP_IMPL_OP3SUP(msb_functor, float*, float, float*, float*);
380| // not in sal (msb_functor, float*, float*, float, float*);
381| VSIP_IMPL_OP3SUP(msb_functor, float*, float*, float*, float*);
382|
383| VSIP_IMPL_OP3SUP(msb_functor, double, double*, double*, double*);
384| VSIP_IMPL_OP3SUP(msb_functor, double*, double, double*, double*);
385| // not in sal (msb_functor, double*, double*, double, double*);
386| VSIP_IMPL_OP3SUP(msb_functor, double*, double*, double*, double*);
387|
388| // no complex msb in SAL
389|
390|
391| // Add-multiply
392|
393| // not in SAL (am_functor, float, float*, float*, float*);
394| // not in SAL (am_functor, float*, float, float*, float*);
395| VSIP_IMPL_OP3SUP(am_functor, float*, float*, float, float*);
396| VSIP_IMPL_OP3SUP(am_functor, float*, float*, float*, float*);
397|
398| // not in SAL (am_functor, double, double*, double*,double*);
399| // not in SAL (am_functor, double*, double, double*,double*);
400| // not in SAL (am_functor, double*, double*, double, double*);
401| VSIP_IMPL_OP3SUP(am_functor, double*, double*, double*,double*);
402|
403|
404| // Subtract-multiply
405| VSIP_IMPL_OP3SUP(sbm_functor, float*, float*, float, float*);
406| VSIP_IMPL_OP3SUP(sbm_functor, float*, float*, float*, float*);
407| VSIP_IMPL_OP3SUP(sbm_functor, double*, double*, double*,double*);
408|
409|
410| // Conjugate(multiply)-add
411|
412| VSIP_IMPL_OP3SUP(cma_token, complex<float>*, complex<float>*, complex<float>*,
413| complex<float>*);
414| VSIP_IMPL_OP3SUP(cma_token, split_float*, split_float*, split_float*,
415| split_float*);
416|
417|
418|
419| #undef VSIP_IMPL_OP1SUP
420| #undef VSIP_IMPL_OP2SUP
421| #undef VSIP_IMPL_OP3SUP
422|
423|
424|
425|
426|
427|
428|
429|
430|
431|
432| template <template <typename, typename> class Operator,
433| typename DstBlock,
434| typename LBlock,
435| typename RBlock,
436| typename LType,
437| typename RType>
438| struct Serial_expr_evaluator_base_mixed
439| {
440| typedef Binary_expr_block<1, Operator, LBlock, LType, RBlock, RType>
441| SrcBlock;
442|
443| typedef typename DstBlock::value_type dst_type;
444|
445| typedef typename sal::Effective_value_type<DstBlock>::type d_eff_t;
446| typedef typename sal::Effective_value_type<LBlock>::type l_eff_t;
447| typedef typename sal::Effective_value_type<RBlock>::type r_eff_t;
448|
449| static bool const ct_valid =
450| Type_equal<typename LBlock::value_type, LType>::value &&
451| Type_equal<typename RBlock::value_type, RType>::value &&
452| (!Is_expr_block<LBlock>::value || Is_scalar_block<LBlock>::value) &&
453| (!Is_expr_block<RBlock>::value || Is_scalar_block<RBlock>::value) &&
454| Is_op2_supported<Operator, l_eff_t, r_eff_t, d_eff_t>::value &&
455|
456| Ext_data_cost<DstBlock>::value == 0 &&
457| (Ext_data_cost<LBlock>::value == 0 || Is_scalar_block<LBlock>::value) &&
458| (Ext_data_cost<RBlock>::value == 0 || Is_scalar_block<RBlock>::value);
459|
460| static bool rt_valid(DstBlock&, SrcBlock const&)
461| {
462| // SAL supports all strides
463| return true;
464| }
465| };
466|
467| }
468|
469|
470|
471|
472|
473|
474|
475| #define VSIP_IMPL_SAL_COPY_EXPR(OP, FUN)
476| template <typename DstBlock,
477| typename SrcBlock>
478| struct Serial_expr_evaluator<
479| 1, DstBlock,
480| SrcBlock,
481| typename Type_if<Mercury_sal_tag,
482| Is_leaf_block<SrcBlock>::value>::type>
483| {
484| static char const* name() { return "Expr_SAL_COPY"; }
485| \
486| typedef typename DstBlock::value_type dst_type;
487| \
488| typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t;
489| typedef typename sal::Effective_value_type<SrcBlock>::type eff_src_t;
490| \
491| typedef typename Adjust_layout_dim<
492| 1, typename Block_layout<DstBlock>::layout_type>::type
493| dst_lp;
494| \
495| typedef typename Adjust_layout_dim<
496| 1, typename Block_layout<SrcBlock>::layout_type>::type
497| src_lp;
498| \
499| static bool const ct_valid =
500| (!Is_expr_block<SrcBlock>::value || Is_scalar_block<SrcBlock>::value) &&\
501| sal::Is_op1_supported<OP, eff_src_t, eff_dst_t>::value&&
502| /* check that direct access is supported */
503| Ext_data_cost<DstBlock>::value == 0 &&
504| (Ext_data_cost<SrcBlock>::value == 0 ||
505| Is_scalar_block<SrcBlock>::value);
506| \
507| static bool rt_valid(DstBlock&, SrcBlock const&)
508| {
509| /* SAL supports all strides */
510| return true;
511| }
512| \
513| static void exec(DstBlock& dst, SrcBlock const& src)
514| {
515| sal::Ext_wrapper<DstBlock, dst_lp> ext_dst(dst, SYNC_OUT);
516| sal::Ext_wrapper<SrcBlock, src_lp> ext_src(src, SYNC_IN);
517| FUN(typename sal::Ext_wrapper<SrcBlock, dst_lp>::sal_type(ext_src),
518| typename sal::Ext_wrapper<DstBlock, src_lp>::sal_type(ext_dst),
519| dst.size());
520| }
521| };
522|
523| VSIP_IMPL_SAL_COPY_EXPR(sal::copy_token, vcopy)
524|
525|
526|
527|
528|
529|
530|
531| #define VSIP_IMPL_SAL_V_EXPR(OP, FUN)
532| template <typename DstBlock,
533| typename Block1,
534| typename Type1>
535| struct Serial_expr_evaluator<
536| 1, DstBlock,
537| Unary_expr_block<1, OP, Block1, Type1> const,
538| typename Type_if<Mercury_sal_tag,
539| Is_leaf_block<Block1>::value>::type>
540| {
541| static char const* name() { return "Expr_SAL_V"; }
542| \
543| typedef Unary_expr_block<1, OP, Block1, Type1> const
544| SrcBlock;
545| \
546| typedef typename DstBlock::value_type dst_type;
547| \
548| typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t;
549| typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
550| \
551| typedef typename Adjust_layout_dim<
552| 1, typename Block_layout<DstBlock>::layout_type>::type
553| dst_lp;
554| \
555| typedef typename Adjust_layout_dim<
556| 1, typename Block_layout<Block1>::layout_type>::type
557| block1_lp;
558| \
559| static bool const ct_valid =
560| (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
561| sal::Is_op1_supported<OP, eff_1_t, eff_dst_t>::value&&
562| /* check that direct access is supported */
563| Ext_data_cost<DstBlock>::value == 0 &&
564| (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value);\
565| \
566| static bool rt_valid(DstBlock&, SrcBlock const&)
567| {
568| /* SAL supports all strides */
569| return true;
570| }
571| \
572| static void exec(DstBlock& dst, SrcBlock const& src)
573| {
574| sal::Ext_wrapper<DstBlock, dst_lp> ext_dst(dst, SYNC_OUT);
575| sal::Ext_wrapper<Block1, block1_lp> ext_1(src.op(), SYNC_IN);
576| FUN(typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),
577| typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),
578| dst.size());
579| }
580| };
581|
582| VSIP_IMPL_SAL_V_EXPR(magsq_functor, sal::vmagsq)
583| VSIP_IMPL_SAL_V_EXPR(mag_functor, sal::vmag)
584| VSIP_IMPL_SAL_V_EXPR(op::Minus, sal::vneg)
585| VSIP_IMPL_SAL_V_EXPR(cos_functor, sal::vcos)
586| VSIP_IMPL_SAL_V_EXPR(sin_functor, sal::vsin)
587| VSIP_IMPL_SAL_V_EXPR(tan_functor, sal::vtan)
588| VSIP_IMPL_SAL_V_EXPR(atan_functor, sal::vatan)
589| VSIP_IMPL_SAL_V_EXPR(log_functor, sal::vlog)
590| VSIP_IMPL_SAL_V_EXPR(log10_functor, sal::vlog10)
591| VSIP_IMPL_SAL_V_EXPR(exp_functor, sal::vexp)
592| VSIP_IMPL_SAL_V_EXPR(exp10_functor, sal::vexp10)
593| VSIP_IMPL_SAL_V_EXPR(sqrt_functor, sal::vsqrt)
594| VSIP_IMPL_SAL_V_EXPR(rsqrt_functor, sal::vrsqrt)
595| VSIP_IMPL_SAL_V_EXPR(sq_functor, sal::vsq)
596| VSIP_IMPL_SAL_V_EXPR(recip_functor, sal::vrecip)
597|
598|
599|
600|
601|
602|
603|
604| #define VSIP_IMPL_SAL_VV_EXPR(OP, FUN)
605| template <typename DstBlock,
606| typename LBlock,
607| typename RBlock,
608| typename LType,
609| typename RType>
610| struct Serial_expr_evaluator<
611| 1, DstBlock,
612| const Binary_expr_block<1, OP, LBlock, LType, RBlock, RType>,
613| typename Type_if<Mercury_sal_tag,
614| Is_leaf_block<LBlock>::value &&
615| Is_leaf_block<RBlock>::value>::type>
616| : sal::Serial_expr_evaluator_base_mixed<OP, DstBlock, LBlock, RBlock, LType, RType>
617| {
618| static char const* name() { return "Expr_SAL_VV"; }
619| \
620| typedef Binary_expr_block<1, OP, LBlock, LType, RBlock, RType>
621| SrcBlock;
622| \
623| typedef typename Adjust_layout_dim<
624| 1, typename Block_layout<DstBlock>::layout_type>::type
625| dst_lp;
626| \
627| typedef typename Adjust_layout_dim<
628| 1, typename Block_layout<LBlock>::layout_type>::type
629| lblock_lp;
630| \
631| typedef typename Adjust_layout_dim<
632| 1, typename Block_layout<RBlock>::layout_type>::type
633| rblock_lp;
634| \
635| static void exec(DstBlock& dst, SrcBlock const& src)
636| {
637| sal::Ext_wrapper<DstBlock, dst_lp> ext_dst(dst, SYNC_OUT);
638| sal::Ext_wrapper<LBlock, lblock_lp> ext_l(src.left(), SYNC_IN);
639| sal::Ext_wrapper<RBlock, rblock_lp> ext_r(src.right(), SYNC_IN);
640| \
641| assert(dst.size() <= src.left().size());
642| assert(dst.size() <= src.right().size());
643| \
644| VSIP_IMPL_COVER_BLK("SAL_VV", SrcBlock);
645| FUN(
646| typename sal::Ext_wrapper<LBlock, lblock_lp>::sal_type(ext_l),
647| typename sal::Ext_wrapper<RBlock, lblock_lp>::sal_type(ext_r),
648| typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),
649| dst.size()
650| );
651| }
652| };
653|
654| VSIP_IMPL_SAL_VV_EXPR(op::Add, sal::vadd)
655| VSIP_IMPL_SAL_VV_EXPR(op::Sub, sal::vsub)
656| VSIP_IMPL_SAL_VV_EXPR(op::Mult, sal::vmul)
657| VSIP_IMPL_SAL_VV_EXPR(op::Div, sal::vdiv)
658|
659| VSIP_IMPL_SAL_VV_EXPR(max_functor, sal::vmax)
660| VSIP_IMPL_SAL_VV_EXPR(min_functor, sal::vmin)
661|
662| VSIP_IMPL_SAL_VV_EXPR(band_functor, sal::vband)
663| VSIP_IMPL_SAL_VV_EXPR(bor_functor, sal::vbor)
664|
665|
666|
667|
668|
669|
670| #define VSIP_IMPL_SAL_VVV_EXPR(OP, FUN)
671| template <typename DstBlock,
672| typename Block1,
673| typename Type1,
674| typename Block2,
675| typename Type2,
676| typename Block3,
677| typename Type3>
678| struct Serial_expr_evaluator<
679| 1, DstBlock,
680| const Ternary_expr_block<1, OP,
681| Block1, Type1,
682| Block2, Type2,
683| Block3, Type3>,
684| Mercury_sal_tag>
685| {
686| static char const* name() { return "Expr_SAL_VVV"; }
687| \
688| typedef Ternary_expr_block<1, OP,
689| Block1, Type1,
690| Block2, Type2,
691| Block3, Type3>
692| SrcBlock;
693| \
694| typedef typename DstBlock::value_type dst_type;
695| \
696| typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t;
697| typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
698| typedef typename sal::Effective_value_type<Block2, Type2>::type eff_2_t;\
699| typedef typename sal::Effective_value_type<Block3, Type3>::type eff_3_t;\
700| \
701| typedef typename Adjust_layout_dim<
702| 1, typename Block_layout<DstBlock>::layout_type>::type
703| dst_lp;
704| \
705| typedef typename Adjust_layout_dim<
706| 1, typename Block_layout<Block1>::layout_type>::type
707| block1_lp;
708| \
709| typedef typename Adjust_layout_dim<
710| 1, typename Block_layout<Block2>::layout_type>::type
711| block2_lp;
712| \
713| typedef typename Adjust_layout_dim<
714| 1, typename Block_layout<Block3>::layout_type>::type
715| block3_lp;
716| \
717| static bool const ct_valid =
718| (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
719| (!Is_expr_block<Block2>::value || Is_scalar_block<Block2>::value) &&\
720| (!Is_expr_block<Block3>::value || Is_scalar_block<Block3>::value) &&\
721| sal::Is_op3_supported<OP, eff_1_t, eff_2_t, eff_3_t, eff_dst_t>::value&&\
722| /* check that direct access is supported */
723| Ext_data_cost<DstBlock>::value == 0 &&
724| (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value) &&\
725| (Ext_data_cost<Block2>::value == 0 || Is_scalar_block<Block2>::value) &&\
726| (Ext_data_cost<Block3>::value == 0 || Is_scalar_block<Block3>::value);\
727| \
728| static bool rt_valid(DstBlock&, SrcBlock const&)
729| {
730| /* SAL supports all strides */
731| return true;
732| }
733| \
734| static void exec(DstBlock& dst, SrcBlock const& src)
735| {
736| sal::Ext_wrapper<DstBlock, dst_lp> ext_dst(dst, SYNC_OUT);
737| sal::Ext_wrapper<Block1, block1_lp> ext_1(src.first(), SYNC_IN);
738| sal::Ext_wrapper<Block2, block2_lp> ext_2(src.second(), SYNC_IN);
739| sal::Ext_wrapper<Block3, block3_lp> ext_3(src.third(), SYNC_IN);
740| FUN(typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),
741| typename sal::Ext_wrapper<Block2, block1_lp>::sal_type(ext_2),
742| typename sal::Ext_wrapper<Block3, block1_lp>::sal_type(ext_3),
743| typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),
744| dst.size());
745| }
746| };
747|
748| VSIP_IMPL_SAL_VVV_EXPR(ma_functor, sal::vma)
749| VSIP_IMPL_SAL_VVV_EXPR(msb_functor, sal::vmsb)
750| VSIP_IMPL_SAL_VVV_EXPR(am_functor, sal::vam)
751| VSIP_IMPL_SAL_VVV_EXPR(sbm_functor, sal::vsbm)
752|
753|
754|
755|
756|
757| #define VSIP_IMPL_SAL_fVVV_EXPR(OP, UOP, FUN, LOOKUP_OP)
758| template <typename DstBlock,
759| typename Block1,
760| typename Type1,
761| typename Block2,
762| typename Type2,
763| typename Block3,
764| typename Type3>
765| struct Serial_expr_evaluator<
766| 1, DstBlock,
767| Ternary_expr_block<1, OP,
768| Unary_expr_block<1, UOP, Block1, Type1> const, Type1,
769| Block2, Type2,
770| Block3, Type3> const,
771| Mercury_sal_tag>
772| {
773| static char const* name() { return "Expr_SAL_fVVV"; }
774| \
775| typedef Ternary_expr_block<1, OP,
776| Unary_expr_block<1, UOP, Block1, Type1> const, Type1,
777| Block2, Type2,
778| Block3, Type3>
779| SrcBlock;
780| \
781| typedef typename DstBlock::value_type dst_type;
782| \
783| typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t;
784| typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
785| typedef typename sal::Effective_value_type<Block2, Type2>::type eff_2_t;\
786| typedef typename sal::Effective_value_type<Block3, Type3>::type eff_3_t;\
787| \
788| typedef typename Adjust_layout_dim<
789| 1, typename Block_layout<DstBlock>::layout_type>::type
790| dst_lp;
791| \
792| typedef typename Adjust_layout_dim<
793| 1, typename Block_layout<Block1>::layout_type>::type
794| block1_lp;
795| \
796| typedef typename Adjust_layout_dim<
797| 1, typename Block_layout<Block2>::layout_type>::type
798| block2_lp;
799| \
800| typedef typename Adjust_layout_dim<
801| 1, typename Block_layout<Block3>::layout_type>::type
802| block3_lp;
803| \
804| static bool const ct_valid =
805| (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
806| (!Is_expr_block<Block2>::value || Is_scalar_block<Block2>::value) &&\
807| (!Is_expr_block<Block3>::value || Is_scalar_block<Block3>::value) &&\
808| sal::Is_op3_supported<LOOKUP_OP, eff_1_t, eff_2_t, eff_3_t,
809| eff_dst_t>::value&&
810| /* check that direct access is supported */
811| Ext_data_cost<DstBlock>::value == 0 &&
812| (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value) &&\
813| (Ext_data_cost<Block2>::value == 0 || Is_scalar_block<Block2>::value) &&\
814| (Ext_data_cost<Block3>::value == 0 || Is_scalar_block<Block3>::value);\
815| \
816| static bool rt_valid(DstBlock&, SrcBlock const&)
817| {
818| /* SAL supports all strides */
819| return true;
820| }
821| \
822| static void exec(DstBlock& dst, SrcBlock const& src)
823| {
824| sal::Ext_wrapper<DstBlock, dst_lp> ext_dst(dst, SYNC_OUT);\
825| sal::Ext_wrapper<Block1, block1_lp> ext_1(src.first().op(), SYNC_IN);\
826| sal::Ext_wrapper<Block2, block2_lp> ext_2(src.second(), SYNC_IN);\
827| sal::Ext_wrapper<Block3, block3_lp> ext_3(src.third(), SYNC_IN);\
828| FUN(typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),
829| typename sal::Ext_wrapper<Block2, block2_lp>::sal_type(ext_2),
830| typename sal::Ext_wrapper<Block3, block3_lp>::sal_type(ext_3),
831| typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),
832| dst.size());
833| }
834| };
835|
836| VSIP_IMPL_SAL_fVVV_EXPR(ma_functor, conj_functor, sal::vcma, sal::cma_token)
837|
838|
839|
840|
841|
842| #define VSIP_IMPL_SAL_VV_V_EXPR(OP, OP1, OP2, FUN)
843| template <typename DstBlock,
844| typename Block1,
845| typename Type1,
846| typename Block2,
847| typename Type2,
848| typename Block3,
849| typename Type3,
850| typename TypeB>
851| struct Serial_expr_evaluator<
852| 1, DstBlock,
853| Binary_expr_block<
854| 1, OP2,
855| Binary_expr_block<
856| 1, OP1,
857| Block1, Type1,
858| Block2, Type2> const, TypeB,
859| Block3, Type3> const,
860| typename Type_if<Mercury_sal_tag,
861| Is_leaf_block<Block1>::value &&
862| Is_leaf_block<Block2>::value &&
863| Is_leaf_block<Block3>::value>::type>
864| {
865| static char const* name() { return "Expr_SAL_VV_V"; }
866| \
867| typedef Binary_expr_block<
868| 1, OP2,
869| Binary_expr_block<
870| 1, OP1,
871| Block1, Type1,
872| Block2, Type2> const, TypeB,
873| Block3, Type3>
874| SrcBlock;
875| \
876| typedef typename DstBlock::value_type dst_type;
877| \
878| typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t;
879| typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
880| typedef typename sal::Effective_value_type<Block2, Type2>::type eff_2_t;\
881| typedef typename sal::Effective_value_type<Block3, Type3>::type eff_3_t;\
882| \
883| typedef typename Adjust_layout_dim<
884| 1, typename Block_layout<DstBlock>::layout_type>::type
885| dst_lp;
886| \
887| typedef typename Adjust_layout_dim<
888| 1, typename Block_layout<Block1>::layout_type>::type
889| block1_lp;
890| \
891| typedef typename Adjust_layout_dim<
892| 1, typename Block_layout<Block2>::layout_type>::type
893| block2_lp;
894| \
895| typedef typename Adjust_layout_dim<
896| 1, typename Block_layout<Block3>::layout_type>::type
897| block3_lp;
898| \
899| static bool const ct_valid =
900| (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
901| (!Is_expr_block<Block2>::value || Is_scalar_block<Block2>::value) &&\
902| (!Is_expr_block<Block3>::value || Is_scalar_block<Block3>::value) &&\
903| sal::Is_op3_supported<OP, eff_1_t, eff_2_t, eff_3_t, eff_dst_t>::value&&\
904| /* check that direct access is supported */
905| Ext_data_cost<DstBlock>::value == 0 &&
906| (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value) &&\
907| (Ext_data_cost<Block2>::value == 0 || Is_scalar_block<Block2>::value) &&\
908| (Ext_data_cost<Block3>::value == 0 || Is_scalar_block<Block3>::value);\
909| \
910| static bool rt_valid(DstBlock&, SrcBlock const&)
911| {
912| /* SAL supports all strides */
913| return true;
914| }
915| \
916| static void exec(DstBlock& dst, SrcBlock const& src)
917| {
918| sal::Ext_wrapper<DstBlock, dst_lp> ext_dst(dst, SYNC_OUT);
919| sal::Ext_wrapper<Block1, block1_lp> ext_1(src.left().left(), SYNC_IN);\
920| sal::Ext_wrapper<Block2, block2_lp> ext_2(src.left().right(), SYNC_IN);\
921| sal::Ext_wrapper<Block3, block3_lp> ext_3(src.right(), SYNC_IN);
922| FUN(typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),
923| typename sal::Ext_wrapper<Block2, block2_lp>::sal_type(ext_2),
924| typename sal::Ext_wrapper<Block3, block3_lp>::sal_type(ext_3),
925| typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),
926| dst.size());
927| }
928| };
929|
930|
931|
932| #define VSIP_IMPL_SAL_V_VV_EXPR(OP, OP1, OP2, FUN)
933| template <typename DstBlock,
934| typename Block1,
935| typename Type1,
936| typename Block2,
937| typename Type2,
938| typename Block3,
939| typename Type3,
940| typename TypeB>
941| struct Serial_expr_evaluator<
942| 1, DstBlock,
943| Binary_expr_block<
944| 1, OP2,
945| Block1, Type1,
946| Binary_expr_block<
947| 1, OP1,
948| Block2, Type2,
949| Block3, Type3> const, TypeB> const,
950| typename Type_if<Mercury_sal_tag,
951| Is_leaf_block<Block1>::value &&
952| Is_leaf_block<Block2>::value &&
953| Is_leaf_block<Block3>::value>::type>
954| {
955| static char const* name() { return "Expr_SAL_V_VV"; }
956| \
957| typedef Binary_expr_block<
958| 1, OP2,
959| Block1, Type1,
960| Binary_expr_block<
961| 1, OP1,
962| Block2, Type2,
963| Block3, Type3> const, TypeB>
964| SrcBlock;
965| \
966| typedef typename DstBlock::value_type dst_type;
967| \
968| typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t;
969| typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
970| typedef typename sal::Effective_value_type<Block2, Type2>::type eff_2_t;\
971| typedef typename sal::Effective_value_type<Block3, Type3>::type eff_3_t;\
972| \
973| typedef typename Adjust_layout_dim<
974| 1, typename Block_layout<DstBlock>::layout_type>::type
975| dst_lp;
976| \
977| typedef typename Adjust_layout_dim<
978| 1, typename Block_layout<Block1>::layout_type>::type
979| block1_lp;
980| \
981| typedef typename Adjust_layout_dim<
982| 1, typename Block_layout<Block2>::layout_type>::type
983| block2_lp;
984| \
985| typedef typename Adjust_layout_dim<
986| 1, typename Block_layout<Block3>::layout_type>::type
987| block3_lp;
988| \
989| static bool const ct_valid =
990| (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
991| (!Is_expr_block<Block2>::value || Is_scalar_block<Block2>::value) &&\
992| (!Is_expr_block<Block3>::value || Is_scalar_block<Block3>::value) &&\
993| sal::Is_op3_supported<OP, eff_1_t, eff_2_t, eff_3_t, eff_dst_t>::value&&\
994| /* check that direct access is supported */
995| Ext_data_cost<DstBlock>::value == 0 &&
996| (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value) &&\
997| (Ext_data_cost<Block2>::value == 0 || Is_scalar_block<Block2>::value) &&\
998| (Ext_data_cost<Block3>::value == 0 || Is_scalar_block<Block3>::value);\
999| \
1000| static bool rt_valid(DstBlock&, SrcBlock const&)
1001| {
1002| /* SAL supports all strides */
1003| return true;
1004| }
1005| \
1006| static void exec(DstBlock& dst, SrcBlock const& src)
1007| {
1008| sal::Ext_wrapper<DstBlock, dst_lp> ext_dst(dst, SYNC_OUT);\
1009| sal::Ext_wrapper<Block1, block1_lp> ext_1(src.left(), SYNC_IN);\
1010| sal::Ext_wrapper<Block2, block2_lp> ext_2(src.right().left(), SYNC_IN);\
1011| sal::Ext_wrapper<Block3, block3_lp> ext_3(src.right().right(), SYNC_IN);\
1012| FUN(typename sal::Ext_wrapper<Block2, block2_lp>::sal_type(ext_2),
1013| typename sal::Ext_wrapper<Block3, block3_lp>::sal_type(ext_3),
1014| typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),
1015| typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),
1016| dst.size());
1017| }
1018| };
1019|
1020| VSIP_IMPL_SAL_VV_V_EXPR(ma_functor, op::Mult, op::Add, sal::vma)
1021| VSIP_IMPL_SAL_VV_V_EXPR(msb_functor, op::Mult, op::Sub, sal::vmsb)
1022| VSIP_IMPL_SAL_VV_V_EXPR(am_functor, op::Add, op::Mult, sal::vam)
1023| VSIP_IMPL_SAL_VV_V_EXPR(sbm_functor, op::Sub, op::Mult, sal::vsbm)
1024|
1025| VSIP_IMPL_SAL_V_VV_EXPR(ma_functor, op::Mult, op::Add, sal::vma)
1026| VSIP_IMPL_SAL_V_VV_EXPR(msb_functor, op::Mult, op::Sub, sal::vmsb)
1027| VSIP_IMPL_SAL_V_VV_EXPR(am_functor, op::Add, op::Mult, sal::vam)
1028| VSIP_IMPL_SAL_V_VV_EXPR(sbm_functor, op::Sub, op::Mult, sal::vsbm)
1029|
1030|
1031|
1032|
1033|
1034| #define VSIP_IMPL_SAL_fVV_V_EXPR(OP, OP1, OP2, UOP, FUN)
1035| template <typename DstBlock,
1036| typename Block1,
1037| typename Type1,
1038| typename Block2,
1039| typename Type2,
1040| typename Block3,
1041| typename Type3,
1042| typename TypeB>
1043| struct Serial_expr_evaluator<
1044| 1, DstBlock,
1045| Binary_expr_block<
1046| 1, OP2,
1047| Binary_expr_block<
1048| 1, OP1,
1049| Unary_expr_block<1, UOP, Block1, Type1> const, Type1,
1050| Block2, Type2> const, TypeB,
1051| Block3, Type3> const,
1052| Mercury_sal_tag>
1053| {
1054| static char const* name() { return "Expr_SAL_fVV_V"; }
1055| \
1056| typedef Binary_expr_block<
1057| 1, OP2,
1058| Binary_expr_block<
1059| 1, OP1,
1060| Unary_expr_block<1, UOP, Block1, Type1> const, Type1,
1061| Block2, Type2> const, TypeB,
1062| Block3, Type3>
1063| SrcBlock;
1064| \
1065| typedef typename DstBlock::value_type dst_type;
1066| \
1067| typedef typename sal::Effective_value_type<DstBlock>::type eff_dst_t;
1068| typedef typename sal::Effective_value_type<Block1, Type1>::type eff_1_t;\
1069| typedef typename sal::Effective_value_type<Block2, Type2>::type eff_2_t;\
1070| typedef typename sal::Effective_value_type<Block3, Type3>::type eff_3_t;\
1071| \
1072| typedef typename Adjust_layout_dim<
1073| 1, typename Block_layout<DstBlock>::layout_type>::type
1074| dst_lp;
1075| \
1076| typedef typename Adjust_layout_dim<
1077| 1, typename Block_layout<Block1>::layout_type>::type
1078| block1_lp;
1079| \
1080| typedef typename Adjust_layout_dim<
1081| 1, typename Block_layout<Block2>::layout_type>::type
1082| block2_lp;
1083| \
1084| typedef typename Adjust_layout_dim<
1085| 1, typename Block_layout<Block3>::layout_type>::type
1086| block3_lp;
1087| \
1088| static bool const ct_valid =
1089| (!Is_expr_block<Block1>::value || Is_scalar_block<Block1>::value) &&\
1090| (!Is_expr_block<Block2>::value || Is_scalar_block<Block2>::value) &&\
1091| (!Is_expr_block<Block3>::value || Is_scalar_block<Block3>::value) &&\
1092| sal::Is_op3_supported<OP, eff_1_t, eff_2_t, eff_3_t, eff_dst_t>::value&&\
1093| /* check that direct access is supported */
1094| Ext_data_cost<DstBlock>::value == 0 &&
1095| (Ext_data_cost<Block1>::value == 0 || Is_scalar_block<Block1>::value) &&\
1096| (Ext_data_cost<Block2>::value == 0 || Is_scalar_block<Block2>::value) &&\
1097| (Ext_data_cost<Block3>::value == 0 || Is_scalar_block<Block3>::value);\
1098| \
1099| static bool rt_valid(DstBlock&, SrcBlock const&)
1100| {
1101| /* SAL supports all strides */
1102| return true;
1103| }
1104| \
1105| static void exec(DstBlock& dst, SrcBlock const& src)
1106| {
1107| sal::Ext_wrapper<DstBlock, dst_lp> ext_dst(dst, SYNC_OUT);
1108| sal::Ext_wrapper<Block1, block1_lp> ext_1(src.left().left().op(),SYNC_IN);\
1109| sal::Ext_wrapper<Block2, block2_lp> ext_2(src.left().right(), SYNC_IN);\
1110| sal::Ext_wrapper<Block3, block3_lp> ext_3(src.right(), SYNC_IN);\
1111| FUN(typename sal::Ext_wrapper<Block1, block1_lp>::sal_type(ext_1),
1112| typename sal::Ext_wrapper<Block2, block2_lp>::sal_type(ext_2),
1113| typename sal::Ext_wrapper<Block3, block3_lp>::sal_type(ext_3),
1114| typename sal::Ext_wrapper<DstBlock, dst_lp>::sal_type(ext_dst),
1115| dst.size());
1116| }
1117| };
1118|
1119| VSIP_IMPL_SAL_fVV_V_EXPR(sal::cma_token, op::Mult, op::Add, conj_functor,
1120| sal::vcma)
1121|
1122| }
1123| }
1124|
1125| #endif // VSIP_IMPL_SAL_EVAL_HPP