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