Remove unnecessary config.h includes
[alexxy/gromacs.git] / src / gromacs / simd / tests / simd_integer.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2014, 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 #include "gmxpre.h"
36
37 #include "simd.h"
38
39 /* Some notes on the setup of these tests:
40  *
41  * It might seem strange to mix different instructions for "setting" SIMD
42  * registers, but the difference is that the routines like setSimdIntFrom1I()
43  * only use the load/store operations that we already test separately in
44  * bootstrap_loadstore.cpp. Since these are "known good" if the bootstrap
45  * tests pass, we use them to test the normal SIMD implementation instructions
46  * that all have gmx_simd_ prefixes.
47  */
48
49 namespace gmx
50 {
51 namespace test
52 {
53 namespace
54 {
55
56 /*! \cond internal */
57 /*! \addtogroup module_simd */
58 /*! \{ */
59
60 #ifdef GMX_SIMD_HAVE_INT32
61
62 /*! \brief Test fixture for integer tests (identical to the generic \ref SimdTest) */
63 typedef SimdTest SimdIntegerTest;
64
65 TEST_F(SimdIntegerTest, gmxSimdSetZeroI)
66 {
67     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0), gmx_simd_setzero_i());
68 }
69
70 TEST_F(SimdIntegerTest, gmxSimdSet1I)
71 {
72     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(1), gmx_simd_set1_i(1));
73 }
74
75 #ifdef GMX_SIMD_HAVE_FINT32_ARITHMETICS
76 TEST_F(SimdIntegerTest, gmxSimdAddI)
77 {
78     GMX_EXPECT_SIMD_INT_EQ(iSimd_5_7_9,   gmx_simd_add_i(iSimd_1_2_3, iSimd_4_5_6)    );    // short add
79     GMX_EXPECT_SIMD_INT_EQ(iSimd_5M_7M_9M, gmx_simd_add_i(iSimd_1M_2M_3M, iSimd_4M_5M_6M)); // 32 bit add
80 }
81
82 TEST_F(SimdIntegerTest, gmxSimdSubI)
83 {
84     GMX_EXPECT_SIMD_INT_EQ(iSimd_1_2_3,   gmx_simd_sub_i(iSimd_5_7_9, iSimd_4_5_6)    );    // short sub
85     GMX_EXPECT_SIMD_INT_EQ(iSimd_1M_2M_3M, gmx_simd_sub_i(iSimd_5M_7M_9M, iSimd_4M_5M_6M)); // 32 bit sub
86 }
87
88 TEST_F(SimdIntegerTest, gmxSimdMulI)
89 {
90     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(4, 10, 18), gmx_simd_mul_i(iSimd_1_2_3, iSimd_4_5_6));                       // 2*3=6 (short mul)
91     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(268435456), gmx_simd_mul_i(gmx_simd_set1_i(16384), gmx_simd_set1_i(16384))); // 16384*16384 = 268435456 (long mul)
92 }
93 #endif
94
95 #ifdef GMX_SIMD_HAVE_FINT32_LOGICAL
96 TEST_F(SimdIntegerTest, gmxSimdSlliI)
97 {
98     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4194304), gmx_simd_slli_i(gmx_simd_set1_i(2), 21)); // 2 << 21 = 4194304
99 }
100
101 TEST_F(SimdIntegerTest, gmxSimdSrliI)
102 {
103     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4), gmx_simd_srli_i(gmx_simd_set1_i(4194304), 20)); // 4194304 >> 20 = 4
104 }
105
106 TEST_F(SimdIntegerTest, gmxSimdAndI)
107 {
108     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xC0C0C0C0), gmx_simd_and_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
109 }
110
111 TEST_F(SimdIntegerTest, gmxSimdAndnotI)
112 {
113     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x0C0C0C0C), gmx_simd_andnot_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
114 }
115
116 TEST_F(SimdIntegerTest, gmxSimdOrI)
117 {
118     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xFCFCFCFC), gmx_simd_or_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
119 }
120
121 TEST_F(SimdIntegerTest, gmxSimdXorI)
122 {
123     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x3C3C3C3C), gmx_simd_xor_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
124 }
125 #endif
126
127 #ifdef GMX_SIMD_HAVE_INT32_EXTRACT
128 TEST_F(SimdIntegerTest, gmxSimdExtractI)
129 {
130     int              idata[GMX_SIMD_INT32_WIDTH*2];
131     int *            p = gmx_simd_align_i(idata);
132     gmx_simd_int32_t simd;
133     int              i, extracted_int;
134
135     for (i = 0; i < GMX_SIMD_INT32_WIDTH; i++)
136     {
137         p[i] = i+1;
138     }
139     simd = gmx_simd_load_i(p);
140
141     /* We cannot do a loop here, since
142      * - C++ gets confused about signed/unsigned if SSE macros are used in EXPECT_EQ()
143      * - Extract macros can only take immediates (not variables) on some archs,
144      *   and some compilers are not smart enough to expand the for loop.
145      *
146      * To solve this we use a few values manually instead of a for-loop.
147      */
148     extracted_int = gmx_simd_extract_i(simd, 0);
149     EXPECT_EQ(1, extracted_int);
150     if (GMX_SIMD_INT32_WIDTH >= 2)
151     {
152         extracted_int = gmx_simd_extract_i(simd, 1);
153         EXPECT_EQ(2, extracted_int);
154     }
155     if (GMX_SIMD_INT32_WIDTH >= 4)
156     {
157         extracted_int = gmx_simd_extract_i(simd, 3);
158         EXPECT_EQ(4, extracted_int);
159     }
160     if (GMX_SIMD_INT32_WIDTH >= 6)
161     {
162         extracted_int = gmx_simd_extract_i(simd, 5);
163         EXPECT_EQ(6, extracted_int);
164     }
165     if (GMX_SIMD_INT32_WIDTH >= 8)
166     {
167         extracted_int = gmx_simd_extract_i(simd, 7);
168         EXPECT_EQ(8, extracted_int);
169     }
170 }
171 #endif
172
173 #ifdef GMX_SIMD_HAVE_REAL
174 TEST_F(SimdIntegerTest, gmxSimdCvtR2I)
175 {
176     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4), gmx_simd_cvt_r2i(rSimd_3p75));
177     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-4), gmx_simd_cvt_r2i(rSimd_m3p75));
178 }
179
180 TEST_F(SimdIntegerTest, gmxSimdCvttR2I)
181 {
182     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(3), gmx_simd_cvtt_r2i(rSimd_3p75));
183     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-3), gmx_simd_cvtt_r2i(rSimd_m3p75));
184 }
185
186 TEST_F(SimdIntegerTest, gmxSimdCvtI2R)
187 {
188     GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(2.0), gmx_simd_cvt_i2r(gmx_simd_set1_i(2)));
189     GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-2.0), gmx_simd_cvt_i2r(gmx_simd_set1_i(-2)));
190 }
191 #endif
192
193 #ifdef GMX_SIMD_HAVE_FINT32_ARITHMETICS
194 TEST_F(SimdIntegerTest, gmxSimdBoolCmpEqAndBlendZeroI)
195 {
196     gmx_simd_ibool_t eq   = gmx_simd_cmpeq_i(iSimd_5_7_9, iSimd_7_8_9);
197     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(0, 0, 3), gmx_simd_blendzero_i(iSimd_1_2_3, eq));
198 }
199
200 TEST_F(SimdIntegerTest, gmxSimdBlendNotZeroI)
201 {
202     gmx_simd_ibool_t eq   = gmx_simd_cmpeq_i(iSimd_5_7_9, iSimd_7_8_9);
203     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 2, 0), gmx_simd_blendnotzero_i(iSimd_1_2_3, eq));
204 }
205
206 TEST_F(SimdIntegerTest, gmxSimdBoolCmpLTI)
207 {
208     gmx_simd_ibool_t lt   = gmx_simd_cmplt_i(iSimd_5_7_9, iSimd_7_8_9);
209     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 2, 0), gmx_simd_blendzero_i(iSimd_1_2_3, lt));
210 }
211
212 TEST_F(SimdIntegerTest, gmxSimdBoolAndIB)
213 {
214     gmx_simd_ibool_t eq1  = gmx_simd_cmpeq_i(iSimd_5_7_9, iSimd_7_8_9);
215     gmx_simd_ibool_t eq2  = gmx_simd_cmpeq_i(iSimd_5_7_9, iSimd_5_7_9);
216     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(0, 0, 3), gmx_simd_blendzero_i(iSimd_1_2_3, gmx_simd_and_ib(eq1, eq2)));
217 }
218
219 TEST_F(SimdIntegerTest, gmxSimdBoolOrIB)
220 {
221     gmx_simd_ibool_t eq1  = gmx_simd_cmpeq_i(iSimd_5_7_9, iSimd_7_8_9);
222     gmx_simd_ibool_t eq2  = gmx_simd_cmpeq_i(iSimd_5_7_9, setSimdIntFrom3I(5, 0, 0));
223     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 3), gmx_simd_blendzero_i(iSimd_1_2_3, gmx_simd_or_ib(eq1, eq2)));
224 }
225
226 TEST_F(SimdIntegerTest, gmxSimdAnytrueIB)
227 {
228     gmx_simd_ibool_t eq;
229
230     /* See comment in floatingpoint.cpp. We should only check the first element here,
231      * since the SIMD width could be 1 as a special case.
232      */
233     eq = gmx_simd_cmpeq_i(iSimd_5_7_9, setSimdIntFrom3I(5, 0, 0));
234     EXPECT_NE(0, gmx_simd_anytrue_ib(eq));
235
236     eq = gmx_simd_cmpeq_i(iSimd_1_2_3, iSimd_4_5_6);
237     EXPECT_EQ(0, gmx_simd_anytrue_ib(eq));
238 }
239
240 TEST_F(SimdIntegerTest, gmxSimdBlendvI)
241 {
242     gmx_simd_ibool_t lt   = gmx_simd_cmplt_i(iSimd_5_7_9, iSimd_7_8_9);
243     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(4, 5, 3), gmx_simd_blendv_i(iSimd_1_2_3, iSimd_4_5_6, lt));
244 }
245 #endif
246
247 #if (defined GMX_SIMD_HAVE_REAL) && (defined GMX_SIMD_HAVE_FINT32_ARITHMETICS)
248 TEST_F(SimdIntegerTest, gmxSimdCvtB2IB)
249 {
250     gmx_simd_bool_t  eq   = gmx_simd_cmpeq_r(rSimd_5_7_9, setSimdRealFrom3R(5, 0, 0));  // eq should be T,F,F
251     gmx_simd_ibool_t eqi  = gmx_simd_cvt_b2ib(eq);
252     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 0), gmx_simd_blendzero_i(iSimd_1_2_3, eqi));
253
254 }
255
256 TEST_F(SimdIntegerTest, gmxSimdCvtIB2B)
257 {
258     gmx_simd_ibool_t eqi  = gmx_simd_cmpeq_i(iSimd_5_7_9, setSimdIntFrom3I(5, 0, 0));  // eq should be T,F,F
259     gmx_simd_bool_t  eq   = gmx_simd_cvt_ib2b(eqi);
260     GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1.0, 0, 0), gmx_simd_blendzero_r(rSimd_1_2_3, eq));
261 }
262 #endif
263
264 #endif      // GMX_SIMD_HAVE_INT32
265
266 /*! \} */
267 /*! \endcond */
268
269 }      // namespace
270 }      // namespace
271 }      // namespace