Created SIMD module
[alexxy/gromacs.git] / src / gromacs / simd / four_wide_macros_ref.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2013, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35
36 #ifndef GMX_SIMD_FOUR_WIDE_MACROS_REF_H
37 #define GMX_SIMD_FOUR_WIDE_MACROS_REF_H
38
39 /* This file contains a reference plain-C implementation of 4-wide SIMD.
40  * This code is only useful for testing and documentation.
41  * Either float or double precision is supported through gmx_simd4_real,
42  * which is set in gmx_simd4_macros.h
43  */
44
45
46 #include <math.h>
47
48 /* float/double SIMD register type */
49 typedef struct {
50     gmx_simd4_real r[GMX_SIMD4_WIDTH];
51 } gmx_simd4_ref_pr;
52
53 /* boolean SIMD register type */
54 typedef struct {
55     char r[GMX_SIMD4_WIDTH];
56 } gmx_simd4_ref_pb;
57
58
59 /* Load GMX_SIMD4_WIDTH reals for memory starting at r */
60 static gmx_inline gmx_simd4_ref_pr
61 gmx_simd4_ref_load_pr(const gmx_simd4_real *r)
62 {
63     gmx_simd4_ref_pr a;
64     int              i;
65
66     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
67     {
68         a.r[i] = r[i];
69     }
70
71     return a;
72 }
73
74 /* Set all SIMD register elements to r */
75 static gmx_inline gmx_simd4_ref_pr
76 gmx_simd4_ref_set1_pr(gmx_simd4_real r)
77 {
78     gmx_simd4_ref_pr a;
79     int              i;
80
81     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
82     {
83         a.r[i] = r;
84     }
85
86     return a;
87 }
88
89 /* Set all SIMD register elements to 0 */
90 static gmx_inline gmx_simd4_ref_pr
91 gmx_simd4_ref_setzero_pr()
92 {
93     gmx_simd4_ref_pr a;
94     int              i;
95
96     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
97     {
98         a.r[i] = 0.0;
99     }
100
101     return a;
102 }
103
104 static gmx_inline void
105 gmx_simd4_ref_store_pr(gmx_simd4_real *dest, gmx_simd4_ref_pr src)
106 {
107     int i;
108
109     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
110     {
111         dest[i] = src.r[i];
112     }
113 }
114
115 static gmx_inline gmx_simd4_ref_pr
116 gmx_simd4_ref_add_pr(gmx_simd4_ref_pr a, gmx_simd4_ref_pr b)
117 {
118     gmx_simd4_ref_pr c;
119     int              i;
120
121     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
122     {
123         c.r[i] = a.r[i] + b.r[i];
124     }
125
126     return c;
127 }
128
129 static gmx_inline gmx_simd4_ref_pr
130 gmx_simd4_ref_sub_pr(gmx_simd4_ref_pr a, gmx_simd4_ref_pr b)
131 {
132     gmx_simd4_ref_pr c;
133     int              i;
134
135     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
136     {
137         c.r[i] = a.r[i] - b.r[i];
138     }
139
140     return c;
141 }
142
143 static gmx_inline gmx_simd4_ref_pr
144 gmx_simd4_ref_mul_pr(gmx_simd4_ref_pr a, gmx_simd4_ref_pr b)
145 {
146     gmx_simd4_ref_pr c;
147     int              i;
148
149     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
150     {
151         c.r[i] = a.r[i]*b.r[i];
152     }
153
154     return c;
155 }
156
157 static gmx_inline gmx_simd4_ref_pr
158 gmx_simd4_ref_madd_pr(gmx_simd4_ref_pr a, gmx_simd4_ref_pr b, gmx_simd4_ref_pr c)
159 {
160     gmx_simd4_ref_pr d;
161     int              i;
162
163     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
164     {
165         d.r[i] = a.r[i]*b.r[i] + c.r[i];
166     }
167
168     return d;
169 }
170
171 static gmx_inline gmx_simd4_ref_pr
172 gmx_simd4_ref_nmsub_pr(gmx_simd4_ref_pr a, gmx_simd4_ref_pr b, gmx_simd4_ref_pr c)
173 {
174     gmx_simd4_ref_pr d;
175     int              i;
176
177     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
178     {
179         d.r[i] = -a.r[i]*b.r[i] + c.r[i];
180     }
181
182     return d;
183 }
184
185 static gmx_inline gmx_simd4_real
186 gmx_simd4_ref_dotproduct3(gmx_simd4_ref_pr a, gmx_simd4_ref_pr b)
187 {
188     gmx_simd4_real dp;
189     int            i;
190
191     dp = 0.0;
192     for (i = 0; i < 3; i++)
193     {
194         dp += a.r[i]*b.r[i];
195     }
196
197     return dp;
198 }
199
200 static gmx_inline gmx_simd4_ref_pr
201 gmx_simd4_ref_min_pr(gmx_simd4_ref_pr a, gmx_simd4_ref_pr b)
202 {
203     gmx_simd4_ref_pr c;
204     int              i;
205
206     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
207     {
208         c.r[i] = (a.r[i] <= b.r[i] ? a.r[i] : b.r[i]);
209     }
210
211     return c;
212 }
213
214 static gmx_inline gmx_simd4_ref_pr
215 gmx_simd4_ref_max_pr(gmx_simd4_ref_pr a, gmx_simd4_ref_pr b)
216 {
217     gmx_simd4_ref_pr c;
218     int              i;
219
220     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
221     {
222         c.r[i] = (a.r[i] >= b.r[i] ? a.r[i] : b.r[i]);
223     }
224
225     return c;
226 }
227
228 static gmx_inline gmx_simd4_ref_pr
229 gmx_simd4_ref_blendzero_pr(gmx_simd4_ref_pr a, gmx_simd4_ref_pb b)
230 {
231     gmx_simd4_ref_pr c;
232     int              i;
233
234     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
235     {
236         c.r[i] = (b.r[i] ? a.r[i] : 0.0);
237     }
238
239     return c;
240 }
241
242 /* Comparison */
243 static gmx_inline gmx_simd4_ref_pb
244 gmx_simd4_ref_cmplt_pr(gmx_simd4_ref_pr a, gmx_simd4_ref_pr b)
245 {
246     gmx_simd4_ref_pb c;
247     int              i;
248
249     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
250     {
251         c.r[i] = (a.r[i] < b.r[i]);
252     }
253
254     return c;
255 }
256
257 /* Logical AND on SIMD booleans */
258 static gmx_inline gmx_simd4_ref_pb
259 gmx_simd4_ref_and_pb(gmx_simd4_ref_pb a, gmx_simd4_ref_pb b)
260 {
261     gmx_simd4_ref_pb c;
262     int              i;
263
264     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
265     {
266         c.r[i] = (a.r[i] && b.r[i]);
267     }
268
269     return c;
270 }
271
272 /* Logical OR on SIMD booleans */
273 static gmx_inline gmx_simd4_ref_pb
274 gmx_simd4_ref_or_pb(gmx_simd4_ref_pb a, gmx_simd4_ref_pb b)
275 {
276     gmx_simd4_ref_pb c;
277     int              i;
278
279     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
280     {
281         c.r[i] = (a.r[i] || b.r[i]);
282     }
283
284     return c;
285 }
286
287 /* gmx_anytrue_pb(x) returns if any of the boolean is x is True */
288 static gmx_inline int
289 gmx_simd4_ref_anytrue_pb(gmx_simd4_ref_pb a)
290 {
291     int anytrue;
292     int i;
293
294     anytrue = 0;
295     for (i = 0; i < GMX_SIMD4_WIDTH; i++)
296     {
297         if (a.r[i])
298         {
299             anytrue = 1;
300         }
301     }
302
303     return anytrue;
304 }
305
306 #endif