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
13namespace simdpp {
14namespace SIMDPP_ARCH_NAMESPACE {
15namespace 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*/
20template<class R, class E> struct expr_eval_wrapper;
21template<class R, class E> struct expr_eval;
22
23} // namespace detail
24
25// -----------------------------------------------------------------------------
26struct expr_empty {};
27
28template<class E1, class E2>
29struct expr_bit_and {
30 const E1& a;
31 const E2& b;
32};
33
34template<class E1, class E2>
35struct expr_bit_andnot {
36 const E1& a;
37 const E2& b;
38};
39
40template<class E>
41struct expr_bit_not {
42 const E& a;
43};
44
45template<class E1, class E2>
46struct expr_bit_or {
47 const E1& a;
48 const E2& b;
49};
50
51template<class E1, class E2>
52struct expr_bit_xor {
53 const E1& a;
54 const E2& b;
55};
56
57template<class E1, class E2, class E3>
58struct expr_blend {
59 const E1& on;
60 const E2& off;
61 const E3& mask;
62};
63
64template<unsigned S, class E>
65struct expr_splat2 {
66 const E& a;
67};
68
69template<unsigned S, class E>
70struct expr_splat4 {
71 const E& a;
72};
73
74template<unsigned S, class E>
75struct expr_splat8 {
76 const E& a;
77};
78
79template<unsigned S, class E>
80struct expr_splat16 {
81 const E& a;
82};
83
84template<class E1, class E2>
85struct expr_iadd {
86 const E1& a;
87 const E2& b;
88};
89
90template<class E1, class E2>
91struct expr_fadd {
92 const E1& a;
93 const E2& b;
94};
95
96template<class E1, class E2>
97struct expr_iadd_sat {
98 const E1& a;
99 const E2& b;
100};
101
102template<class E1, class E2>
103struct expr_fsub {
104 const E1& a;
105 const E2& b;
106};
107
108template<class E1, class E2>
109struct expr_isub {
110 const E1& a;
111 const E2& b;
112};
113
114template<class E1, class E2>
115struct expr_isub_sat {
116 const E1& a;
117 const E2& b;
118};
119
120template<class E>
121struct expr_fabs {
122 const E& a;
123};
124
125template<class E>
126struct expr_iabs {
127 const E& a;
128};
129
130template<class E>
131struct expr_fneg {
132 const E& a;
133};
134
135template<class E>
136struct expr_ineg {
137 const E& a;
138};
139
140template<class E1, class E2>
141struct expr_fmul {
142 const E1& a;
143 const E2& b;
144};
145
146template<class E1, class E2>
147struct expr_mul_lo {
148 const E1& a;
149 const E2& b;
150};
151
152template<class E1, class E2>
153struct expr_mul_hi {
154 const E1& a;
155 const E2& b;
156};
157
158template<class E1, class E2>
159struct expr_mull {
160 const E1& a;
161 const E2& b;
162};
163
164template<class E1, class E2, class E3>
165struct expr_fmadd { // a * b + c
166 const E1& a;
167 const E2& b;
168 const E3& c;
169};
170
171template<class E1, class E2, class E3>
172struct expr_fmsub { // a * b - c
173 const E1& a;
174 const E2& b;
175 const E3& c;
176};
177
178template<unsigned S, class E>
179struct expr_imm_shift_l {
180 const E& a;
181 static const unsigned shift = S;
182};
183
184template<unsigned S, class E>
185struct expr_imm_shift_r {
186 const E& a;
187 static const unsigned shift = S;
188};
189
190
191template<class E>
192struct 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
197struct 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
203template<class VE>
204struct 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
210template<class VE, unsigned N>
211struct 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
218struct expr_vec_make_ones : expr_vec_construct<expr_vec_make_ones> {};
219
220struct expr_vec_load : expr_vec_construct<expr_vec_load> {
221 const char* a;
222};
223
224struct 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