2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2014,2015,2016,2017, 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.
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.
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.
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.
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.
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.
37 #include "gromacs/simd/simd.h"
38 #include "gromacs/utility/basedefinitions.h"
42 /* Some notes on the setup of these tests:
44 * It might seem strange to mix different instructions for "setting" SIMD
45 * registers, but the difference is that the routines like setSimdIntFrom1I()
46 * only use the load/store operations that we already test separately in
47 * bootstrap_loadstore.cpp. Since these are "known good" if the bootstrap
48 * tests pass, we use them to test the normal SIMD implementation instructions.
61 /*! \addtogroup module_simd */
64 /*! \brief Test fixture for integer tests (identical to the generic \ref SimdTest) */
65 typedef SimdTest SimdIntegerTest
;
67 /* Yes, Virginia. We test for real even for integers. This is because we use
68 * the floating-point type when no real integer SIMD type exists (which in turn
69 * is because the results of real-to-integer conversions end up there). This
70 * means the basic integer SIMD type is available whenever the real one is,
71 * but depending on the precision selected that might not be the case.
73 * The second we have default-precision floating-point SIMD, we also have
74 * the integer SIMD dataype and the most fundamental load/store ops.
76 #if GMX_SIMD_HAVE_REAL
78 TEST_F(SimdIntegerTest
, setZero
)
80 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0), setZero());
82 TEST_F(SimdIntegerTest
, set
)
84 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(1), SimdInt32(1));
86 #endif // GMX_SIMD_HAVE_REAL
88 #if GMX_SIMD_HAVE_INT32_ARITHMETICS
89 TEST_F(SimdIntegerTest
, add
)
91 GMX_EXPECT_SIMD_INT_EQ(iSimd_5_7_9
, iSimd_1_2_3
+ iSimd_4_5_6
); // short add
92 GMX_EXPECT_SIMD_INT_EQ(iSimd_5M_7M_9M
, iSimd_1M_2M_3M
+ iSimd_4M_5M_6M
); // 32 bit add
95 TEST_F(SimdIntegerTest
, sub
)
97 GMX_EXPECT_SIMD_INT_EQ(iSimd_1_2_3
, iSimd_5_7_9
- iSimd_4_5_6
); // short sub
98 GMX_EXPECT_SIMD_INT_EQ(iSimd_1M_2M_3M
, iSimd_5M_7M_9M
- iSimd_4M_5M_6M
); // 32 bit sub
101 TEST_F(SimdIntegerTest
, mul
)
103 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(4, 10, 18), iSimd_1_2_3
* iSimd_4_5_6
); // 2*3=6 (short mul)
104 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(268435456), SimdInt32(16384) * SimdInt32(16384) ); // 16384*16384 = 268435456 (long mul)
107 TEST_F(SimdIntegerTest
, slli
)
109 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4194304), SimdInt32(2) << 21); // 2 << 21 = 4194304
112 TEST_F(SimdIntegerTest
, srli
)
114 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4), SimdInt32(4194304) >> 20); // 4194304 >> 20 = 4
116 #endif // GMX_SIMD_HAVE_INT32_ARITHMETICS
118 #if GMX_SIMD_HAVE_INT32_LOGICAL
119 TEST_F(SimdIntegerTest
, and)
121 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xC0C0C0C0), iSimd_0xF0F0F0F0
& iSimd_0xCCCCCCCC
);
124 TEST_F(SimdIntegerTest
, andNot
)
126 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x0C0C0C0C), andNot(iSimd_0xF0F0F0F0
, iSimd_0xCCCCCCCC
));
129 TEST_F(SimdIntegerTest
, or)
131 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xFCFCFCFC), iSimd_0xF0F0F0F0
| iSimd_0xCCCCCCCC
);
134 TEST_F(SimdIntegerTest
, xor)
136 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x3C3C3C3C), iSimd_0xF0F0F0F0
^iSimd_0xCCCCCCCC
);
138 #endif // GMX_SIMD_HAVE_INT32_LOGICAL
140 #if GMX_SIMD_HAVE_INT32_EXTRACT
141 TEST_F(SimdIntegerTest
, extract
)
143 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) idata
[GMX_SIMD_REAL_WIDTH
];
146 for (int i
= 0; i
< GMX_SIMD_REAL_WIDTH
; i
++)
152 /* We cannot do a loop here, since
153 * - C++ gets confused about signed/unsigned if SSE macros are used in EXPECT_EQ()
154 * - Extract macros can only take immediates (not variables) on some archs,
155 * and some compilers are not smart enough to expand the for loop.
157 * To solve this we use a few values manually instead of a for-loop.
160 extracted_int
= extract
<0>(simd
);
161 EXPECT_EQ(1, extracted_int
);
162 #if GMX_SIMD_REAL_WIDTH >= 2
163 extracted_int
= extract
<1>(simd
);
164 EXPECT_EQ(2, extracted_int
);
166 #if GMX_SIMD_REAL_WIDTH >= 4
167 extracted_int
= extract
<3>(simd
);
168 EXPECT_EQ(4, extracted_int
);
170 #if GMX_SIMD_REAL_WIDTH >= 6
171 extracted_int
= extract
<5>(simd
);
172 EXPECT_EQ(6, extracted_int
);
174 #if GMX_SIMD_REAL_WIDTH >= 8
175 extracted_int
= extract
<7>(simd
);
176 EXPECT_EQ(8, extracted_int
);
179 #endif // GMX_SIMD_HAVE_INT32_EXTRACT
181 #if GMX_SIMD_HAVE_REAL
182 TEST_F(SimdIntegerTest
, cvtR2I
)
184 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(2), cvtR2I(rSimd_2p25
));
185 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-2), cvtR2I(rSimd_m2p25
));
186 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4), cvtR2I(rSimd_3p75
));
187 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-4), cvtR2I(rSimd_m3p75
));
188 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(3), cvtR2I(rSimd_3p25
));
189 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-3), cvtR2I(rSimd_m3p25
));
191 // Test multi-byte numbers
192 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(123457), cvtR2I(setSimdRealFrom1R(123456.7)));
193 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-123457), cvtR2I(setSimdRealFrom1R(-123456.7)));
194 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(123456), cvtR2I(setSimdRealFrom1R(123456.3)));
195 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-123456), cvtR2I(setSimdRealFrom1R(-123456.3)));
198 // Test number with more digits than we can represent in single.
199 // Note that our SIMD integers are only 32 bits, so we cannot go beyond that.
200 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(12345679), cvtR2I(setSimdRealFrom1R(12345678.6)));
201 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-12345679), cvtR2I(setSimdRealFrom1R(-12345678.6)));
202 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(12345678), cvtR2I(setSimdRealFrom1R(12345678.3)));
203 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-12345678), cvtR2I(setSimdRealFrom1R(-12345678.3)));
207 TEST_F(SimdIntegerTest
, cvttR2I
)
209 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(2), cvttR2I(rSimd_2p25
));
210 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-2), cvttR2I(rSimd_m2p25
));
211 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(3), cvttR2I(rSimd_3p75
));
212 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-3), cvttR2I(rSimd_m3p75
));
213 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(3), cvttR2I(rSimd_3p25
));
214 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-3), cvttR2I(rSimd_m3p25
));
216 // Test multi-byte numbers
217 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(123456), cvttR2I(setSimdRealFrom1R(123456.7)));
218 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-123456), cvttR2I(setSimdRealFrom1R(-123456.7)));
219 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(123456), cvttR2I(setSimdRealFrom1R(123456.3)));
220 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-123456), cvttR2I(setSimdRealFrom1R(-123456.3)));
223 // Test number with more digits than we can represent in single.
224 // Note that our SIMD integers are only 32 bits, so we cannot go beyond that.
225 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(12345678), cvttR2I(setSimdRealFrom1R(12345678.6)));
226 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-12345678), cvttR2I(setSimdRealFrom1R(-12345678.6)));
227 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(12345678), cvttR2I(setSimdRealFrom1R(12345678.3)));
228 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-12345678), cvttR2I(setSimdRealFrom1R(-12345678.3)));
232 TEST_F(SimdIntegerTest
, cvtI2R
)
234 GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(2.0), cvtI2R(SimdInt32(2)));
235 GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-2.0), cvtI2R(SimdInt32(-2)));
236 GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(102448689), cvtI2R(SimdInt32(102448689)));
237 GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-102448689), cvtI2R(SimdInt32(-102448689)));
239 #endif // GMX_SIMD_HAVE_REAL
241 #if GMX_SIMD_HAVE_INT32_ARITHMETICS
242 TEST_F(SimdIntegerTest
, cmpEqAndSelectMask
)
244 SimdIBool eq
= (iSimd_5_7_9
== iSimd_7_8_9
);
245 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(0, 0, 3), selectByMask(iSimd_1_2_3
, eq
));
248 TEST_F(SimdIntegerTest
, cmpEqAndSelectNotMask
)
250 SimdIBool eq
= (iSimd_5_7_9
== iSimd_7_8_9
);
251 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 2, 0), selectByNotMask(iSimd_1_2_3
, eq
));
254 TEST_F(SimdIntegerTest
, cmpLt
)
256 SimdIBool lt
= (iSimd_5_7_9
< iSimd_7_8_9
);
257 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 2, 0), selectByMask(iSimd_1_2_3
, lt
));
260 TEST_F(SimdIntegerTest
, testBits
)
262 SimdIBool eq
= testBits(setSimdIntFrom3I(1, 0, 2));
263 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 3), selectByMask(iSimd_1_2_3
, eq
));
265 // Test if we detect only the sign bit being set
266 eq
= testBits(setSimdIntFrom1I(0x80000000));
267 GMX_EXPECT_SIMD_INT_EQ(iSimd_1_2_3
, selectByMask(iSimd_1_2_3
, eq
));
270 TEST_F(SimdIntegerTest
, andB
)
272 SimdIBool eq1
= (iSimd_5_7_9
== iSimd_7_8_9
);
273 SimdIBool eq2
= (iSimd_5_7_9
== iSimd_5_7_9
);
274 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(0, 0, 3), selectByMask(iSimd_1_2_3
, eq1
&& eq2
));
277 TEST_F(SimdIntegerTest
, orB
)
279 SimdIBool eq1
= (iSimd_5_7_9
== iSimd_7_8_9
);
280 SimdIBool eq2
= (iSimd_5_7_9
== setSimdIntFrom3I(5, 0, 0));
281 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 3), selectByMask(iSimd_1_2_3
, eq1
|| eq2
));
284 TEST_F(SimdIntegerTest
, anyTrue
)
288 /* See comment in floatingpoint.cpp. We should only check the first element here,
289 * since the SIMD width could be 1 as a special case.
291 eq
= (iSimd_5_7_9
== setSimdIntFrom3I(5, 0, 0));
292 EXPECT_TRUE(anyTrue(eq
));
294 eq
= (iSimd_1_2_3
== iSimd_4_5_6
);
295 EXPECT_FALSE(anyTrue(eq
));
298 TEST_F(SimdIntegerTest
, blend
)
300 SimdIBool lt
= (iSimd_5_7_9
< iSimd_7_8_9
);
301 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(4, 5, 3), blend(iSimd_1_2_3
, iSimd_4_5_6
, lt
));
303 #endif // GMX_SIMD_HAVE_INT32_ARITHMETICS
305 #if GMX_SIMD_HAVE_REAL && GMX_SIMD_HAVE_INT32_ARITHMETICS
306 TEST_F(SimdIntegerTest
, cvtB2IB
)
308 SimdBool eq
= (rSimd_c3c4c5
== rSimd_c3c0c4
); // eq should be T,F,F
309 SimdIBool eqi
= cvtB2IB(eq
);
310 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 0), selectByMask(iSimd_1_2_3
, eqi
));
314 TEST_F(SimdIntegerTest
, cvtIB2B
)
316 SimdIBool eqi
= (iSimd_5_7_9
== setSimdIntFrom3I(5, 0, 0)); // eq should be T,F,F
317 SimdBool eq
= cvtIB2B(eqi
);
318 GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(c0
, 0, 0), selectByMask(rSimd_c0c1c2
, eq
));
320 #endif // GMX_SIMD_HAVE_REAL && GMX_SIMD_HAVE_INT32_ARITHMETICS