2 * This file is part of the GROMACS molecular simulation package.
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.
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.
39 /* Some notes on the setup of these tests:
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.
57 /*! \addtogroup module_simd */
60 #ifdef GMX_SIMD_HAVE_INT32
62 /*! \brief Test fixture for integer tests (identical to the generic \ref SimdTest) */
63 typedef SimdTest SimdIntegerTest;
65 TEST_F(SimdIntegerTest, gmxSimdSetZeroI)
67 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0), gmx_simd_setzero_i());
70 TEST_F(SimdIntegerTest, gmxSimdSet1I)
72 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(1), gmx_simd_set1_i(1));
75 #ifdef GMX_SIMD_HAVE_FINT32_ARITHMETICS
76 TEST_F(SimdIntegerTest, gmxSimdAddI)
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
82 TEST_F(SimdIntegerTest, gmxSimdSubI)
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
88 TEST_F(SimdIntegerTest, gmxSimdMulI)
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)
95 #ifdef GMX_SIMD_HAVE_FINT32_LOGICAL
96 TEST_F(SimdIntegerTest, gmxSimdSlliI)
98 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4194304), gmx_simd_slli_i(gmx_simd_set1_i(2), 21)); // 2 << 21 = 4194304
101 TEST_F(SimdIntegerTest, gmxSimdSrliI)
103 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4), gmx_simd_srli_i(gmx_simd_set1_i(4194304), 20)); // 4194304 >> 20 = 4
106 TEST_F(SimdIntegerTest, gmxSimdAndI)
108 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xC0C0C0C0), gmx_simd_and_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
111 TEST_F(SimdIntegerTest, gmxSimdAndnotI)
113 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x0C0C0C0C), gmx_simd_andnot_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
116 TEST_F(SimdIntegerTest, gmxSimdOrI)
118 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xFCFCFCFC), gmx_simd_or_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
121 TEST_F(SimdIntegerTest, gmxSimdXorI)
123 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x3C3C3C3C), gmx_simd_xor_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
127 #ifdef GMX_SIMD_HAVE_INT32_EXTRACT
128 TEST_F(SimdIntegerTest, gmxSimdExtractI)
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;
135 for (i = 0; i < GMX_SIMD_INT32_WIDTH; i++)
139 simd = gmx_simd_load_i(p);
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.
146 * To solve this we use a few values manually instead of a for-loop.
148 extracted_int = gmx_simd_extract_i(simd, 0);
149 EXPECT_EQ(1, extracted_int);
150 if (GMX_SIMD_INT32_WIDTH >= 2)
152 extracted_int = gmx_simd_extract_i(simd, 1);
153 EXPECT_EQ(2, extracted_int);
155 if (GMX_SIMD_INT32_WIDTH >= 4)
157 extracted_int = gmx_simd_extract_i(simd, 3);
158 EXPECT_EQ(4, extracted_int);
160 if (GMX_SIMD_INT32_WIDTH >= 6)
162 extracted_int = gmx_simd_extract_i(simd, 5);
163 EXPECT_EQ(6, extracted_int);
165 if (GMX_SIMD_INT32_WIDTH >= 8)
167 extracted_int = gmx_simd_extract_i(simd, 7);
168 EXPECT_EQ(8, extracted_int);
173 #ifdef GMX_SIMD_HAVE_REAL
174 TEST_F(SimdIntegerTest, gmxSimdCvtR2I)
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));
180 TEST_F(SimdIntegerTest, gmxSimdCvttR2I)
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));
186 TEST_F(SimdIntegerTest, gmxSimdCvtI2R)
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)));
193 #ifdef GMX_SIMD_HAVE_FINT32_ARITHMETICS
194 TEST_F(SimdIntegerTest, gmxSimdBoolCmpEqAndBlendZeroI)
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));
200 TEST_F(SimdIntegerTest, gmxSimdBlendNotZeroI)
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));
206 TEST_F(SimdIntegerTest, gmxSimdBoolCmpLTI)
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));
212 TEST_F(SimdIntegerTest, gmxSimdBoolAndIB)
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)));
219 TEST_F(SimdIntegerTest, gmxSimdBoolOrIB)
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)));
226 TEST_F(SimdIntegerTest, gmxSimdAnytrueIB)
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.
233 eq = gmx_simd_cmpeq_i(iSimd_5_7_9, setSimdIntFrom3I(5, 0, 0));
234 EXPECT_NE(0, gmx_simd_anytrue_ib(eq));
236 eq = gmx_simd_cmpeq_i(iSimd_1_2_3, iSimd_4_5_6);
237 EXPECT_EQ(0, gmx_simd_anytrue_ib(eq));
240 TEST_F(SimdIntegerTest, gmxSimdBlendvI)
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));
247 #if (defined GMX_SIMD_HAVE_REAL) && (defined GMX_SIMD_HAVE_FINT32_ARITHMETICS)
248 TEST_F(SimdIntegerTest, gmxSimdCvtB2IB)
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));
256 TEST_F(SimdIntegerTest, gmxSimdCvtIB2B)
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));
264 #endif // GMX_SIMD_HAVE_INT32