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.
41 /* Some notes on the setup of these tests:
43 * It might seem strange to mix different instructions for "setting" SIMD
44 * registers, but the difference is that the routines like setSimdIntFrom1I()
45 * only use the load/store operations that we already test separately in
46 * bootstrap_loadstore.cpp. Since these are "known good" if the bootstrap
47 * tests pass, we use them to test the normal SIMD implementation instructions
48 * that all have gmx_simd_ prefixes.
59 /*! \addtogroup module_simd */
62 #ifdef GMX_SIMD_HAVE_INT32
64 /*! \brief Test fixture for integer tests (identical to the generic \ref SimdTest) */
65 typedef SimdTest SimdIntegerTest;
67 TEST_F(SimdIntegerTest, gmxSimdSetZeroI)
69 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0), gmx_simd_setzero_i());
72 TEST_F(SimdIntegerTest, gmxSimdSet1I)
74 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(1), gmx_simd_set1_i(1));
77 #ifdef GMX_SIMD_HAVE_FINT32_ARITHMETICS
78 TEST_F(SimdIntegerTest, gmxSimdAddI)
80 GMX_EXPECT_SIMD_INT_EQ(iSimd_5_7_9, gmx_simd_add_i(iSimd_1_2_3, iSimd_4_5_6) ); // short add
81 GMX_EXPECT_SIMD_INT_EQ(iSimd_5M_7M_9M, gmx_simd_add_i(iSimd_1M_2M_3M, iSimd_4M_5M_6M)); // 32 bit add
84 TEST_F(SimdIntegerTest, gmxSimdSubI)
86 GMX_EXPECT_SIMD_INT_EQ(iSimd_1_2_3, gmx_simd_sub_i(iSimd_5_7_9, iSimd_4_5_6) ); // short sub
87 GMX_EXPECT_SIMD_INT_EQ(iSimd_1M_2M_3M, gmx_simd_sub_i(iSimd_5M_7M_9M, iSimd_4M_5M_6M)); // 32 bit sub
90 TEST_F(SimdIntegerTest, gmxSimdMulI)
92 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)
93 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)
97 #ifdef GMX_SIMD_HAVE_FINT32_LOGICAL
98 TEST_F(SimdIntegerTest, gmxSimdSlliI)
100 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4194304), gmx_simd_slli_i(gmx_simd_set1_i(2), 21)); // 2 << 21 = 4194304
103 TEST_F(SimdIntegerTest, gmxSimdSrliI)
105 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4), gmx_simd_srli_i(gmx_simd_set1_i(4194304), 20)); // 4194304 >> 20 = 4
108 TEST_F(SimdIntegerTest, gmxSimdAndI)
110 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xC0C0C0C0), gmx_simd_and_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
113 TEST_F(SimdIntegerTest, gmxSimdAndnotI)
115 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x0C0C0C0C), gmx_simd_andnot_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
118 TEST_F(SimdIntegerTest, gmxSimdOrI)
120 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xFCFCFCFC), gmx_simd_or_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
123 TEST_F(SimdIntegerTest, gmxSimdXorI)
125 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x3C3C3C3C), gmx_simd_xor_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
129 #ifdef GMX_SIMD_HAVE_INT32_EXTRACT
130 TEST_F(SimdIntegerTest, gmxSimdExtractI)
132 int idata[GMX_SIMD_INT32_WIDTH*2];
133 int * p = gmx_simd_align_i(idata);
134 gmx_simd_int32_t simd;
135 int i, extracted_int;
137 for (i = 0; i < GMX_SIMD_INT32_WIDTH; i++)
141 simd = gmx_simd_load_i(p);
143 /* We cannot do a loop here, since
144 * - C++ gets confused about signed/unsigned if SSE macros are used in EXPECT_EQ()
145 * - Extract macros can only take immediates (not variables) on some archs,
146 * and some compilers are not smart enough to expand the for loop.
148 * To solve this we use a few values manually instead of a for-loop.
150 extracted_int = gmx_simd_extract_i(simd, 0);
151 EXPECT_EQ(1, extracted_int);
152 if (GMX_SIMD_INT32_WIDTH >= 2)
154 extracted_int = gmx_simd_extract_i(simd, 1);
155 EXPECT_EQ(2, extracted_int);
157 if (GMX_SIMD_INT32_WIDTH >= 4)
159 extracted_int = gmx_simd_extract_i(simd, 3);
160 EXPECT_EQ(4, extracted_int);
162 if (GMX_SIMD_INT32_WIDTH >= 6)
164 extracted_int = gmx_simd_extract_i(simd, 5);
165 EXPECT_EQ(6, extracted_int);
167 if (GMX_SIMD_INT32_WIDTH >= 8)
169 extracted_int = gmx_simd_extract_i(simd, 7);
170 EXPECT_EQ(8, extracted_int);
175 #ifdef GMX_SIMD_HAVE_REAL
176 TEST_F(SimdIntegerTest, gmxSimdCvtR2I)
178 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4), gmx_simd_cvt_r2i(rSimd_3p75));
179 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-4), gmx_simd_cvt_r2i(rSimd_m3p75));
182 TEST_F(SimdIntegerTest, gmxSimdCvttR2I)
184 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(3), gmx_simd_cvtt_r2i(rSimd_3p75));
185 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(-3), gmx_simd_cvtt_r2i(rSimd_m3p75));
188 TEST_F(SimdIntegerTest, gmxSimdCvtI2R)
190 GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(2.0), gmx_simd_cvt_i2r(gmx_simd_set1_i(2)));
191 GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-2.0), gmx_simd_cvt_i2r(gmx_simd_set1_i(-2)));
195 #ifdef GMX_SIMD_HAVE_FINT32_ARITHMETICS
196 TEST_F(SimdIntegerTest, gmxSimdBoolCmpEqAndBlendZeroI)
198 gmx_simd_ibool_t eq = gmx_simd_cmpeq_i(iSimd_5_7_9, iSimd_7_8_9);
199 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(0, 0, 3), gmx_simd_blendzero_i(iSimd_1_2_3, eq));
202 TEST_F(SimdIntegerTest, gmxSimdBlendNotZeroI)
204 gmx_simd_ibool_t eq = gmx_simd_cmpeq_i(iSimd_5_7_9, iSimd_7_8_9);
205 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 2, 0), gmx_simd_blendnotzero_i(iSimd_1_2_3, eq));
208 TEST_F(SimdIntegerTest, gmxSimdBoolCmpLTI)
210 gmx_simd_ibool_t lt = gmx_simd_cmplt_i(iSimd_5_7_9, iSimd_7_8_9);
211 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 2, 0), gmx_simd_blendzero_i(iSimd_1_2_3, lt));
214 TEST_F(SimdIntegerTest, gmxSimdBoolAndIB)
216 gmx_simd_ibool_t eq1 = gmx_simd_cmpeq_i(iSimd_5_7_9, iSimd_7_8_9);
217 gmx_simd_ibool_t eq2 = gmx_simd_cmpeq_i(iSimd_5_7_9, iSimd_5_7_9);
218 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(0, 0, 3), gmx_simd_blendzero_i(iSimd_1_2_3, gmx_simd_and_ib(eq1, eq2)));
221 TEST_F(SimdIntegerTest, gmxSimdBoolOrIB)
223 gmx_simd_ibool_t eq1 = gmx_simd_cmpeq_i(iSimd_5_7_9, iSimd_7_8_9);
224 gmx_simd_ibool_t eq2 = gmx_simd_cmpeq_i(iSimd_5_7_9, setSimdIntFrom3I(5, 0, 0));
225 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 3), gmx_simd_blendzero_i(iSimd_1_2_3, gmx_simd_or_ib(eq1, eq2)));
228 TEST_F(SimdIntegerTest, gmxSimdAnytrueIB)
232 /* See comment in floatingpoint.cpp. We should only check the first element here,
233 * since the SIMD width could be 1 as a special case.
235 eq = gmx_simd_cmpeq_i(iSimd_5_7_9, setSimdIntFrom3I(5, 0, 0));
236 EXPECT_NE(0, gmx_simd_anytrue_ib(eq));
238 eq = gmx_simd_cmpeq_i(iSimd_1_2_3, iSimd_4_5_6);
239 EXPECT_EQ(0, gmx_simd_anytrue_ib(eq));
242 TEST_F(SimdIntegerTest, gmxSimdBlendvI)
244 gmx_simd_ibool_t lt = gmx_simd_cmplt_i(iSimd_5_7_9, iSimd_7_8_9);
245 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(4, 5, 3), gmx_simd_blendv_i(iSimd_1_2_3, iSimd_4_5_6, lt));
249 #if (defined GMX_SIMD_HAVE_REAL) && (defined GMX_SIMD_HAVE_FINT32_ARITHMETICS)
250 TEST_F(SimdIntegerTest, gmxSimdCvtB2IB)
252 gmx_simd_bool_t eq = gmx_simd_cmpeq_r(rSimd_5_7_9, setSimdRealFrom3R(5, 0, 0)); // eq should be T,F,F
253 gmx_simd_ibool_t eqi = gmx_simd_cvt_b2ib(eq);
254 GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 0), gmx_simd_blendzero_i(iSimd_1_2_3, eqi));
258 TEST_F(SimdIntegerTest, gmxSimdCvtIB2B)
260 gmx_simd_ibool_t eqi = gmx_simd_cmpeq_i(iSimd_5_7_9, setSimdIntFrom3I(5, 0, 0)); // eq should be T,F,F
261 gmx_simd_bool_t eq = gmx_simd_cvt_ib2b(eqi);
262 GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1.0, 0, 0), gmx_simd_blendzero_r(rSimd_1_2_3, eq));
266 #endif // GMX_SIMD_HAVE_INT32