File: vsip/impl/simd/expr_iterator.hpp
1|
2|
3|
4|
5|
6|
7|
8|
9|
10| #ifndef VSIP_IMPL_SIMD_EXPR_ITERATOR_HPP
11| #define VSIP_IMPL_SIMD_EXPR_ITERATOR_HPP
12|
13|
14|
15|
16|
17| #include <vsip/support.hpp>
18| #include <vsip/impl/simd/simd.hpp>
19| #include <vsip/impl/expr_operations.hpp>
20| #include <vsip/impl/metaprogramming.hpp>
21|
22|
23|
24|
25|
26| namespace vsip
27| {
28| namespace impl
29| {
30| namespace simd
31| {
32|
33| template <typename T, // value_type
34| template <typename> class O>
35| struct Unary_operator_map
36| {
37|
38| static bool const is_supported = false;
39| };
40|
41| template <typename T>
42| struct Unary_operator_map<T, op::Plus>
43| {
44| typedef typename Simd_traits<T>::simd_type simd_type;
45| static bool const is_supported = true;
46| static simd_type
47| apply(simd_type const &op)
48| { return Simd_traits<T>::add(Simd_traits<T>::zero(), op);}
49| };
50|
51| template <typename T>
52| struct Unary_operator_map<T, op::Minus>
53| {
54| typedef typename Simd_traits<T>::simd_type simd_type;
55| static bool const is_supported = true;
56| static simd_type
57| apply(simd_type const &op)
58| { return Simd_traits<T>::sub(Simd_traits<T>::zero(), op);}
59| };
60|
61| template <typename T, // value_type
62| template <typename, typename> class O>
63| struct Binary_operator_map
64| {
65|
66| static bool const is_supported = false;
67| };
68|
69| template <typename T>
70| struct Binary_operator_map<T, op::Add>
71| {
72| typedef typename Simd_traits<T>::simd_type simd_type;
73| static bool const is_supported = true;
74| static simd_type
75| apply(simd_type const &left, simd_type const &right)
76| { return Simd_traits<T>::add(left, right);}
77| };
78|
79| template <typename T>
80| struct Binary_operator_map<T, op::Sub>
81| {
82| typedef typename Simd_traits<T>::simd_type simd_type;
83| static bool const is_supported = true;
84| static simd_type
85| apply(simd_type const &left, simd_type const &right)
86| { return Simd_traits<T>::sub(left, right);}
87| };
88|
89| template <typename T>
90| struct Binary_operator_map<T, op::Mult>
91| {
92| typedef typename Simd_traits<T>::simd_type simd_type;
93| static bool const is_supported = true;
94| static simd_type
95| apply(simd_type const &left, simd_type const &right)
96| { return Simd_traits<T>::mul(left, right);}
97| };
98|
99| template <typename T>
100| struct Binary_operator_map<T, op::Div>
101| {
102| typedef typename Simd_traits<T>::simd_type simd_type;
103| static bool const is_supported = true;
104| static simd_type
105| apply(simd_type const &left, simd_type const &right)
106| { return Simd_traits<T>::div(left, right);}
107| };
108|
109|
110| template <typename T> struct Direct_access_traits
111| {
112| typedef T value_type;
113| };
114|
115|
116| template <typename T> struct LValue_access_traits
117| {
118| typedef T value_type;
119| };
120|
121|
122| template <typename T> struct Indirect_access_traits
123| {
124| typedef T value_type;
125| };
126|
127|
128| template <typename T> struct Scalar_access_traits
129| {
130| typedef T value_type;
131| };
132|
133| template <typename T> struct Complex_inter_access_traits
134| {
135| typedef T value_type;
136| };
137|
138| template <typename T> struct Complex_split_access_traits
139| {
140| typedef T value_type;
141| };
142|
143|
144| template <typename ProxyT, // operatory proxy
145| template <typename> class O>
146| struct Unary_access_traits
147| {
148| typedef typename ProxyT::value_type value_type;
149| };
150|
151|
152|
153|
154| template <typename L, // left operator proxy
155| typename R, // right operator proxy
156| template <typename, typename> class O>
157| struct Binary_access_traits
158| {
159| typedef typename Type_equal<typename L::value_type,
160| typename R::value_type>::type value_type;
161| };
162|
163| template <typename T> class Proxy;
164|
165|
166|
167| template <typename T>
168| class Proxy<Direct_access_traits<T> >
169| {
170| public:
171| typedef T value_type;
172| typedef typename Simd_traits<value_type>::simd_type simd_type;
173|
174| Proxy(value_type const *ptr) : ptr_(ptr) {}
175|
176| simd_type load() const { return Simd_traits<value_type>::load(ptr_);}
177|
178| void increment(length_type n = 1) { ptr_ += n * Simd_traits<value_type>::vec_size;}
179|
180| private:
181| value_type const *ptr_;
182| };
183|
184|
185|
186| template <typename T>
187| class Proxy<LValue_access_traits<T> >
188| {
189| public:
190| typedef T value_type;
191| typedef typename Simd_traits<value_type>::simd_type simd_type;
192|
193| Proxy(value_type *ptr) : ptr_(ptr) {}
194| template <typename T1>
195| Proxy operator = (Proxy<T1> const &o)
196| {
197| store(o.load());
198| return *this;
199| }
200|
201| simd_type
202| load() const { return Simd_traits<value_type>::load(ptr_);}
203| void
204| store(simd_type const &value)
205| { Simd_traits<value_type>::store(ptr_, value);}
206|
207| void increment(length_type n = 1) { ptr_ += n * Simd_traits<value_type>::vec_size;}
208|
209| private:
210| value_type *ptr_;
211| };
212|
213| template <typename T>
214| class Proxy<Scalar_access_traits<T> >
215| {
216| public:
217| typedef T value_type;
218| typedef typename Simd_traits<value_type>::simd_type simd_type;
219|
220| Proxy(value_type value) : value_(value) {}
221|
222| simd_type load() const
223| { return Simd_traits<value_type>::load_scalar_all(value_);}
224|
225| void increment(length_type) {}
226|
227| private:
228| value_type value_;
229| };
230|
231|
232| template <typename ProxyT, template <typename> class O>
233| class Proxy<Unary_access_traits<ProxyT, O> >
234| {
235| public:
236| typedef Unary_access_traits<ProxyT, O> access_traits;
237| typedef typename access_traits::value_type value_type;
238| typedef typename Simd_traits<value_type>::simd_type simd_type;
239|
240| Proxy(ProxyT const &o) : op_(o) {}
241|
242| simd_type load() const
243| {
244| simd_type op = op_.load();
245| return Unary_operator_map<value_type, O>::apply(op);
246| }
247|
248| void increment(length_type n = 1) { op_.increment(n);}
249|
250| private:
251| ProxyT op_;
252| };
253|
254|
255|
256| template <typename L, typename R, template <typename, typename> class O>
257| class Proxy<Binary_access_traits<L, R, O> >
258| {
259| public:
260| typedef Binary_access_traits<L, R, O> access_traits;
261| typedef typename access_traits::value_type value_type;
262| typedef typename Simd_traits<value_type>::simd_type simd_type;
263|
264| Proxy(L const &l, R const &r) : left_(l), right_(r) {}
265|
266| L const &left() const { return left_;}
267| R const &right() const { return right_;}
268|
269| simd_type load() const
270| {
271| simd_type l = left_.load();
272| simd_type r = right_.load();
273| return Binary_operator_map<value_type, O>::apply(l, r);
274| }
275|
276| void increment(length_type n = 1)
277| {
278| left_.increment(n);
279| right_.increment(n);
280| }
281|
282| private:
283| L left_;
284| R right_;
285| };
286|
287|
288| template <typename A, typename B, typename C>
289| class Proxy<Binary_access_traits<Proxy<Binary_access_traits<A, B, op::Mult> >,
290| C, op::Add> >
291| {
292| public:
293| typedef Proxy<Binary_access_traits<A, B, op::Mult> > AB;
294| typedef Binary_access_traits<AB, C, op::Add> access_traits;
295| typedef typename access_traits::value_type value_type;
296| typedef typename Simd_traits<value_type>::simd_type simd_type;
297|
298| Proxy(AB const &left, C const &right)
299| : left_(left), right_(right) {}
300|
301| AB const &left() const { return left_;}
302| C const &right() const { return right_;}
303|
304| simd_type load() const
305| {
306| simd_type a = left_.left().load();
307| simd_type b = left_.right().load();
308| simd_type c = right_.load();
309| return Simd_traits<value_type>::fma(a, b, c);
310| }
311|
312| void increment(length_type n = 1)
313| {
314| left_.increment(n);
315| right_.increment(n);
316| }
317|
318| private:
319| AB left_;
320| C right_;
321| };
322|
323|
324| template <typename A, typename B, typename C>
325| class Proxy<Binary_access_traits<A,
326| Proxy<Binary_access_traits<B, C, op::Mult> >,
327| op::Add> >
328| {
329| public:
330| typedef Proxy<Binary_access_traits<B, C, op::Mult> > BC;
331| typedef Binary_access_traits<A, BC, op::Add> access_traits;
332| typedef typename access_traits::value_type value_type;
333| typedef typename Simd_traits<value_type>::simd_type simd_type;
334|
335| Proxy(A const &left, BC const &right)
336| : left_(left), right_(right) {}
337|
338| A const &left() const { return left_;}
339| BC const &right() const { return right_;}
340|
341| simd_type load() const
342| {
343| simd_type a = left_.load();
344| simd_type b = right_.left().load();
345| simd_type c = right_.right().load();
346| return Simd_traits<value_type>::fma(b, c, a);
347| }
348|
349| void increment(length_type n = 1)
350| {
351| left_.increment(n);
352| right_.increment(n);
353| }
354|
355| private:
356| A left_;
357| BC right_;
358| };
359|
360|
361|
362| template <typename A, typename B, typename C, typename D>
363| class Proxy<Binary_access_traits<Proxy<Binary_access_traits<A, B, op::Mult> >,
364| Proxy<Binary_access_traits<C, D, op::Mult> >,
365| op::Add> >
366| {
367| public:
368| typedef Proxy<Binary_access_traits<A, B, op::Mult> > AB;
369| typedef Proxy<Binary_access_traits<C, D, op::Mult> > CD;
370| typedef Binary_access_traits<AB, CD, op::Add> access_traits;
371| typedef typename access_traits::value_type value_type;
372| typedef typename Simd_traits<value_type>::simd_type simd_type;
373|
374| Proxy(AB const &left, CD const &right)
375| : left_(left), right_(right) {}
376|
377| AB const &left() const { return left_;}
378| CD const &right() const { return right_;}
379|
380| simd_type load() const
381| {
382| // Implement 'a * b + c * d' as '(a*b) + c * d'.
383| simd_type ab = left_.load();
384| simd_type c = right_.left().load();
385| simd_type d = right_.right().load();
386| return Simd_traits<value_type>::fma(c, d, ab);
387| }
388|
389| void increment(length_type n = 1)
390| {
391| left_.increment(n);
392| right_.increment(n);
393| }
394|
395| private:
396| AB left_;
397| CD right_;
398| };
399|
400| template <typename T>
401| struct Iterator
402| {
403| public:
404| Iterator(Proxy<T> const &c) : cursor_(c) {}
405| bool operator== (Iterator const &i) const { return cursor_ == i.cursor_;}
406| bool operator!= (Iterator const &i) const { return !(*this==i);}
407| Proxy<T> &operator* () { return cursor_;}
408| Proxy<T> *operator-> () { return &cursor_;}
409| Iterator &operator++() { cursor_.increment(); return *this;}
410| Iterator operator++(int) { Iterator i(*this); cursor_.increment(); return i;}
411| Iterator &operator+=(length_type n) { cursor_.increment(n); return *this;}
412|
413| private:
414| Proxy<T> cursor_;
415| };
416|
417| template <typename T>
418| inline Iterator<T>
419| operator+(Iterator<T> const i, length_type n)
420| {
421| Iterator<T> r(i);
422| r += n;
423| return r;
424| }
425|
426| }
427| }
428| }
429|
430| #endif