1 | /* Copyright (C) 2014 Povilas Kanapickas <povilas@radix.lt> |
2 | |
3 | Distributed under the Boost Software License, Version 1.0. |
4 | (See accompanying file LICENSE_1_0.txt or copy at |
5 | http://www.boost.org/LICENSE_1_0.txt) |
6 | */ |
7 | |
8 | #ifndef LIBSIMDPP_SIMD_EXPR_H |
9 | #define LIBSIMDPP_SIMD_EXPR_H |
10 | |
11 | #include <simdpp/setup_arch.h> |
12 | |
13 | namespace simdpp { |
14 | namespace SIMDPP_ARCH_NAMESPACE { |
15 | namespace detail { |
16 | |
17 | /* The definition of expr_eval_wrapper is placed at the end of all expression |
18 | includes so that all specializations of expr_eval are visible at that point |
19 | */ |
20 | template<class R, class E> struct expr_eval_wrapper; |
21 | template<class R, class E> struct expr_eval; |
22 | |
23 | } // namespace detail |
24 | |
25 | // ----------------------------------------------------------------------------- |
26 | struct expr_empty {}; |
27 | |
28 | template<class E1, class E2> |
29 | struct expr_bit_and { |
30 | const E1& a; |
31 | const E2& b; |
32 | }; |
33 | |
34 | template<class E1, class E2> |
35 | struct expr_bit_andnot { |
36 | const E1& a; |
37 | const E2& b; |
38 | }; |
39 | |
40 | template<class E> |
41 | struct expr_bit_not { |
42 | const E& a; |
43 | }; |
44 | |
45 | template<class E1, class E2> |
46 | struct expr_bit_or { |
47 | const E1& a; |
48 | const E2& b; |
49 | }; |
50 | |
51 | template<class E1, class E2> |
52 | struct expr_bit_xor { |
53 | const E1& a; |
54 | const E2& b; |
55 | }; |
56 | |
57 | template<class E1, class E2, class E3> |
58 | struct expr_blend { |
59 | const E1& on; |
60 | const E2& off; |
61 | const E3& mask; |
62 | }; |
63 | |
64 | template<unsigned S, class E> |
65 | struct expr_splat2 { |
66 | const E& a; |
67 | }; |
68 | |
69 | template<unsigned S, class E> |
70 | struct expr_splat4 { |
71 | const E& a; |
72 | }; |
73 | |
74 | template<unsigned S, class E> |
75 | struct expr_splat8 { |
76 | const E& a; |
77 | }; |
78 | |
79 | template<unsigned S, class E> |
80 | struct expr_splat16 { |
81 | const E& a; |
82 | }; |
83 | |
84 | template<class E1, class E2> |
85 | struct expr_iadd { |
86 | const E1& a; |
87 | const E2& b; |
88 | }; |
89 | |
90 | template<class E1, class E2> |
91 | struct expr_fadd { |
92 | const E1& a; |
93 | const E2& b; |
94 | }; |
95 | |
96 | template<class E1, class E2> |
97 | struct expr_iadd_sat { |
98 | const E1& a; |
99 | const E2& b; |
100 | }; |
101 | |
102 | template<class E1, class E2> |
103 | struct expr_fsub { |
104 | const E1& a; |
105 | const E2& b; |
106 | }; |
107 | |
108 | template<class E1, class E2> |
109 | struct expr_isub { |
110 | const E1& a; |
111 | const E2& b; |
112 | }; |
113 | |
114 | template<class E1, class E2> |
115 | struct expr_isub_sat { |
116 | const E1& a; |
117 | const E2& b; |
118 | }; |
119 | |
120 | template<class E> |
121 | struct expr_fabs { |
122 | const E& a; |
123 | }; |
124 | |
125 | template<class E> |
126 | struct expr_iabs { |
127 | const E& a; |
128 | }; |
129 | |
130 | template<class E> |
131 | struct expr_fneg { |
132 | const E& a; |
133 | }; |
134 | |
135 | template<class E> |
136 | struct expr_ineg { |
137 | const E& a; |
138 | }; |
139 | |
140 | template<class E1, class E2> |
141 | struct expr_fmul { |
142 | const E1& a; |
143 | const E2& b; |
144 | }; |
145 | |
146 | template<class E1, class E2> |
147 | struct expr_mul_lo { |
148 | const E1& a; |
149 | const E2& b; |
150 | }; |
151 | |
152 | template<class E1, class E2> |
153 | struct expr_mul_hi { |
154 | const E1& a; |
155 | const E2& b; |
156 | }; |
157 | |
158 | template<class E1, class E2> |
159 | struct expr_mull { |
160 | const E1& a; |
161 | const E2& b; |
162 | }; |
163 | |
164 | template<class E1, class E2, class E3> |
165 | struct expr_fmadd { // a * b + c |
166 | const E1& a; |
167 | const E2& b; |
168 | const E3& c; |
169 | }; |
170 | |
171 | template<class E1, class E2, class E3> |
172 | struct expr_fmsub { // a * b - c |
173 | const E1& a; |
174 | const E2& b; |
175 | const E3& c; |
176 | }; |
177 | |
178 | template<unsigned S, class E> |
179 | struct expr_imm_shift_l { |
180 | const E& a; |
181 | static const unsigned shift = S; |
182 | }; |
183 | |
184 | template<unsigned S, class E> |
185 | struct expr_imm_shift_r { |
186 | const E& a; |
187 | static const unsigned shift = S; |
188 | }; |
189 | |
190 | |
191 | template<class E> |
192 | struct expr_vec_construct { |
193 | SIMDPP_INL E& expr() { return static_cast<E&>(*this); } |
194 | SIMDPP_INL const E& expr() const { return static_cast<const E&>(*this); } |
195 | }; |
196 | |
197 | struct expr_vec_load_splat : expr_vec_construct<expr_vec_load_splat> { |
198 | const char* a; |
199 | |
200 | expr_vec_load_splat(const char* x) : a(x) {} |
201 | }; |
202 | |
203 | template<class VE> |
204 | struct expr_vec_set_splat : expr_vec_construct<expr_vec_set_splat<VE>> { |
205 | VE a; |
206 | |
207 | expr_vec_set_splat(const VE& x) : a(x) {} |
208 | }; |
209 | |
210 | template<class VE, unsigned N> |
211 | struct expr_vec_make_const : expr_vec_construct<expr_vec_make_const<VE,N>> { |
212 | VE a[N]; |
213 | SIMDPP_INL const VE& val(unsigned n) const { return a[n%N]; } |
214 | }; |
215 | |
216 | // This expression is needed because it's not possible to use |
217 | // expr_vec_make_const to initialize floating-point vectors to ones |
218 | struct expr_vec_make_ones : expr_vec_construct<expr_vec_make_ones> {}; |
219 | |
220 | struct expr_vec_load : expr_vec_construct<expr_vec_load> { |
221 | const char* a; |
222 | }; |
223 | |
224 | struct expr_vec_load_u : expr_vec_construct<expr_vec_load_u> { |
225 | const char* a; |
226 | |
227 | expr_vec_load_u(const char* x) : a(x) {} |
228 | }; |
229 | |
230 | |
231 | } // namespace SIMDPP_ARCH_NAMESPACE |
232 | } // namespace simdpp |
233 | |
234 | #endif |
235 | |