SYCL: Avoid using no_init read accessor in rocFFT
[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,2015,2016,2017,2018 by the GROMACS development team.
5  * Copyright (c) 2019,2020, by the GROMACS development team, led by
6  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7  * and including many others, as listed in the AUTHORS file in the
8  * top-level source directory and at http://www.gromacs.org.
9  *
10  * GROMACS is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * GROMACS is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GROMACS; if not, see
22  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24  *
25  * If you want to redistribute modifications to GROMACS, please
26  * consider that scientific software is very special. Version
27  * control is crucial - bugs must be traceable. We will be happy to
28  * consider code for inclusion in the official distribution, but
29  * derived work must not be called official GROMACS. Details are found
30  * in the README & COPYING files - if they are missing, get the
31  * official version at http://www.gromacs.org.
32  *
33  * To help us fund GROMACS development, we humbly ask that you cite
34  * the research papers on the package. Check out http://www.gromacs.org.
35  */
36 #include "gmxpre.h"
37
38 #include <array>
39
40 #include "gromacs/simd/simd.h"
41 #include "gromacs/utility/basedefinitions.h"
42
43 #include "simd.h"
44
45 /* Some notes on the setup of these tests:
46  *
47  * It might seem strange to mix different instructions for "setting" SIMD
48  * registers, but the difference is that the routines like setSimdIntFrom1I()
49  * only use the load/store operations that we already test separately in
50  * bootstrap_loadstore.cpp. Since these are "known good" if the bootstrap
51  * tests pass, we use them to test the normal SIMD implementation instructions.
52  */
53
54 #if GMX_SIMD
55
56 namespace gmx
57 {
58 namespace test
59 {
60 namespace
61 {
62
63 /*! \cond internal */
64 /*! \addtogroup module_simd */
65 /*! \{ */
66
67 /*! \brief Test fixture for integer tests (identical to the generic \ref SimdTest) */
68 typedef SimdTest SimdIntegerTest;
69
70 /* Yes, Virginia. We test for real even for integers. This is because we use
71  * the floating-point type when no real integer SIMD type exists (which in turn
72  * is because the results of real-to-integer conversions end up there). This
73  * means the basic integer SIMD type is available whenever the real one is,
74  * but depending on the precision selected that might not be the case.
75  *
76  * The second we have default-precision floating-point SIMD, we also have
77  * the integer SIMD dataype and the most fundamental load/store ops.
78  */
79 #    if GMX_SIMD_HAVE_REAL
80
81 TEST_F(SimdIntegerTest, setZero)
82 {
83     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0), setZero());
84 }
85 TEST_F(SimdIntegerTest, set)
86 {
87     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(1), SimdInt32(1));
88 }
89 #    endif // GMX_SIMD_HAVE_REAL
90
91 #    if GMX_SIMD_HAVE_INT32_ARITHMETICS
92 TEST_F(SimdIntegerTest, add)
93 {
94     GMX_EXPECT_SIMD_INT_EQ(iSimd_5_7_9, iSimd_1_2_3 + iSimd_4_5_6);          // short add
95     GMX_EXPECT_SIMD_INT_EQ(iSimd_5M_7M_9M, iSimd_1M_2M_3M + iSimd_4M_5M_6M); // 32 bit add
96 }
97
98 TEST_F(SimdIntegerTest, sub)
99 {
100     GMX_EXPECT_SIMD_INT_EQ(iSimd_1_2_3, iSimd_5_7_9 - iSimd_4_5_6);          // short sub
101     GMX_EXPECT_SIMD_INT_EQ(iSimd_1M_2M_3M, iSimd_5M_7M_9M - iSimd_4M_5M_6M); // 32 bit sub
102 }
103
104 TEST_F(SimdIntegerTest, mul)
105 {
106     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(4, 10, 18), iSimd_1_2_3 * iSimd_4_5_6); // 2*3=6 (short mul)
107     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(268435456),
108                            SimdInt32(16384) * SimdInt32(16384)); // 16384*16384 = 268435456 (long mul)
109 }
110
111 #    endif // GMX_SIMD_HAVE_INT32_ARITHMETICS
112
113 #    if GMX_SIMD_HAVE_INT32_LOGICAL
114 TEST_F(SimdIntegerTest, and)
115 {
116     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xC0C0C0C0), iSimd_0xF0F0F0F0 & iSimd_0xCCCCCCCC);
117 }
118
119 TEST_F(SimdIntegerTest, andNot)
120 {
121     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x0C0C0C0C), andNot(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
122 }
123
124 TEST_F(SimdIntegerTest, or)
125 {
126     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xFCFCFCFC), iSimd_0xF0F0F0F0 | iSimd_0xCCCCCCCC);
127 }
128
129 TEST_F(SimdIntegerTest, xor)
130 {
131     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x3C3C3C3C), iSimd_0xF0F0F0F0 ^ iSimd_0xCCCCCCCC);
132 }
133 #    endif // GMX_SIMD_HAVE_INT32_LOGICAL
134
135 #    if GMX_SIMD_HAVE_INT32_EXTRACT
136 TEST_F(SimdIntegerTest, extract)
137 {
138     alignas(GMX_SIMD_ALIGNMENT) std::int32_t idata[GMX_SIMD_REAL_WIDTH];
139     SimdInt32                                simd;
140
141     for (int i = 0; i < GMX_SIMD_REAL_WIDTH; i++)
142     {
143         idata[i] = i + 1;
144     }
145     simd = load<SimdInt32>(idata);
146
147     /* We cannot do a loop here, since
148      * - C++ gets confused about signed/unsigned if SSE macros are used in EXPECT_EQ()
149      * - Extract macros can only take immediates (not variables) on some archs,
150      *   and some compilers are not smart enough to expand the for loop.
151      *
152      * To solve this we use a few values manually instead of a for-loop.
153      */
154     int extracted_int;
155     extracted_int = extract<0>(simd);
156     EXPECT_EQ(1, extracted_int);
157 #        if GMX_SIMD_REAL_WIDTH >= 2
158     extracted_int = extract<1>(simd);
159     EXPECT_EQ(2, extracted_int);
160 #        endif
161 #        if GMX_SIMD_REAL_WIDTH >= 4
162     extracted_int = extract<3>(simd);
163     EXPECT_EQ(4, extracted_int);
164 #        endif
165 #        if GMX_SIMD_REAL_WIDTH >= 6
166     extracted_int = extract<5>(simd);
167     EXPECT_EQ(6, extracted_int);
168 #        endif
169 #        if GMX_SIMD_REAL_WIDTH >= 8
170     extracted_int = extract<7>(simd);
171     EXPECT_EQ(8, extracted_int);
172 #        endif
173 }
174 #    endif // GMX_SIMD_HAVE_INT32_EXTRACT
175
176 #    if GMX_SIMD_HAVE_REAL
177 TEST_F(SimdIntegerTest, cvtR2I)
178 {
179     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(2), cvtR2I(rSimd_2p25));
180     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-2), cvtR2I(rSimd_m2p25));
181     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4), cvtR2I(rSimd_3p75));
182     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-4), cvtR2I(rSimd_m3p75));
183     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(3), cvtR2I(rSimd_3p25));
184     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-3), cvtR2I(rSimd_m3p25));
185
186     // Test multi-byte numbers
187     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(123457), cvtR2I(setSimdRealFrom1R(123456.7)));
188     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-123457), cvtR2I(setSimdRealFrom1R(-123456.7)));
189     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(123456), cvtR2I(setSimdRealFrom1R(123456.3)));
190     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-123456), cvtR2I(setSimdRealFrom1R(-123456.3)));
191
192 #        if GMX_DOUBLE
193     // Test number with more digits than we can represent in single.
194     // Note that our SIMD integers are only 32 bits, so we cannot go beyond that.
195     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(12345679), cvtR2I(setSimdRealFrom1R(12345678.6)));
196     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-12345679), cvtR2I(setSimdRealFrom1R(-12345678.6)));
197     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(12345678), cvtR2I(setSimdRealFrom1R(12345678.3)));
198     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-12345678), cvtR2I(setSimdRealFrom1R(-12345678.3)));
199 #        endif
200 }
201
202 TEST_F(SimdIntegerTest, cvttR2I)
203 {
204     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(2), cvttR2I(rSimd_2p25));
205     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-2), cvttR2I(rSimd_m2p25));
206     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(3), cvttR2I(rSimd_3p75));
207     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-3), cvttR2I(rSimd_m3p75));
208     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(3), cvttR2I(rSimd_3p25));
209     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-3), cvttR2I(rSimd_m3p25));
210
211     // Test multi-byte numbers
212     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(123456), cvttR2I(setSimdRealFrom1R(123456.7)));
213     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-123456), cvttR2I(setSimdRealFrom1R(-123456.7)));
214     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(123456), cvttR2I(setSimdRealFrom1R(123456.3)));
215     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-123456), cvttR2I(setSimdRealFrom1R(-123456.3)));
216
217 #        if GMX_DOUBLE
218     // Test number with more digits than we can represent in single.
219     // Note that our SIMD integers are only 32 bits, so we cannot go beyond that.
220     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(12345678), cvttR2I(setSimdRealFrom1R(12345678.6)));
221     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-12345678), cvttR2I(setSimdRealFrom1R(-12345678.6)));
222     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(12345678), cvttR2I(setSimdRealFrom1R(12345678.3)));
223     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-12345678), cvttR2I(setSimdRealFrom1R(-12345678.3)));
224 #        endif
225 }
226
227 TEST_F(SimdIntegerTest, cvtI2R)
228 {
229     GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(2.0), cvtI2R(SimdInt32(2)));
230     GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-2.0), cvtI2R(SimdInt32(-2)));
231     GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(102448689._real), cvtI2R(SimdInt32(102448689)));
232     GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-102448689._real), cvtI2R(SimdInt32(-102448689)));
233 }
234 #    endif // GMX_SIMD_HAVE_REAL
235
236 #    if GMX_SIMD_HAVE_INT32_ARITHMETICS
237 TEST_F(SimdIntegerTest, cmpEqAndSelectMask)
238 {
239     SimdIBool eq = (iSimd_5_7_9 == iSimd_7_8_9);
240     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(0, 0, 3), selectByMask(iSimd_1_2_3, eq));
241 }
242
243 TEST_F(SimdIntegerTest, cmpEqAndSelectNotMask)
244 {
245     SimdIBool eq = (iSimd_5_7_9 == iSimd_7_8_9);
246     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 2, 0), selectByNotMask(iSimd_1_2_3, eq));
247 }
248
249 TEST_F(SimdIntegerTest, cmpLt)
250 {
251     SimdIBool lt = (iSimd_5_7_9 < iSimd_7_8_9);
252     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 2, 0), selectByMask(iSimd_1_2_3, lt));
253 }
254
255 TEST_F(SimdIntegerTest, testBits)
256 {
257     SimdIBool eq = testBits(setSimdIntFrom3I(1, 0, 2));
258     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 3), selectByMask(iSimd_1_2_3, eq));
259
260     // Test if we detect only the sign bit being set
261     eq = testBits(setSimdIntFrom1I(0x80000000));
262     GMX_EXPECT_SIMD_INT_EQ(iSimd_1_2_3, selectByMask(iSimd_1_2_3, eq));
263 }
264
265 TEST_F(SimdIntegerTest, andB)
266 {
267     SimdIBool eq1 = (iSimd_5_7_9 == iSimd_7_8_9);
268     SimdIBool eq2 = (iSimd_5_7_9 == iSimd_5_7_9);
269     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(0, 0, 3), selectByMask(iSimd_1_2_3, eq1 && eq2));
270 }
271
272 TEST_F(SimdIntegerTest, orB)
273 {
274     SimdIBool eq1 = (iSimd_5_7_9 == iSimd_7_8_9);
275     SimdIBool eq2 = (iSimd_5_7_9 == setSimdIntFrom3I(5, 0, 0));
276     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 3), selectByMask(iSimd_1_2_3, eq1 || eq2));
277 }
278
279 TEST_F(SimdIntegerTest, anyTrue)
280 {
281     alignas(GMX_SIMD_ALIGNMENT) std::array<std::int32_t, GMX_SIMD_REAL_WIDTH> mem{};
282
283     // Test the false case
284     EXPECT_FALSE(anyTrue(setZero() < load<SimdInt32>(mem.data())));
285
286     // Test each bit (these should all be true)
287     for (int i = 0; i < GMX_SIMD_REAL_WIDTH; i++)
288     {
289         mem.fill(0);
290         mem[i] = 1;
291         EXPECT_TRUE(anyTrue(setZero() < load<SimdInt32>(mem.data())))
292                 << "Not detecting true in element " << i;
293     }
294 }
295
296 TEST_F(SimdIntegerTest, blend)
297 {
298     SimdIBool lt = (iSimd_5_7_9 < iSimd_7_8_9);
299     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(4, 5, 3), blend(iSimd_1_2_3, iSimd_4_5_6, lt));
300 }
301 #    endif // GMX_SIMD_HAVE_INT32_ARITHMETICS
302
303 #    if GMX_SIMD_HAVE_REAL && GMX_SIMD_HAVE_INT32_ARITHMETICS
304 TEST_F(SimdIntegerTest, cvtB2IB)
305 {
306     SimdBool  eq  = (rSimd_c3c4c5 == rSimd_c3c0c4); // eq should be T,F,F
307     SimdIBool eqi = cvtB2IB(eq);
308     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 0), selectByMask(iSimd_1_2_3, eqi));
309 }
310
311 TEST_F(SimdIntegerTest, cvtIB2B)
312 {
313     SimdIBool eqi = (iSimd_5_7_9 == setSimdIntFrom3I(5, 0, 0)); // eq should be T,F,F
314     SimdBool  eq  = cvtIB2B(eqi);
315     GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(c0, 0, 0), selectByMask(rSimd_c0c1c2, eq));
316 }
317 #    endif // GMX_SIMD_HAVE_REAL && GMX_SIMD_HAVE_INT32_ARITHMETICS
318
319 /*! \} */
320 /*! \endcond */
321
322 } // namespace
323 } // namespace test
324 } // namespace gmx
325
326 #endif // GMX_SIMD