Merge release-5-0 into master
[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 "config.h"
38
39 #include "simd.h"
40
41 /* Some notes on the setup of these tests:
42  *
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.
49  */
50
51 namespace gmx
52 {
53 namespace test
54 {
55 namespace
56 {
57
58 /*! \cond internal */
59 /*! \addtogroup module_simd */
60 /*! \{ */
61
62 #ifdef GMX_SIMD_HAVE_INT32
63
64 /*! \brief Test fixture for integer tests (identical to the generic \ref SimdTest) */
65 typedef SimdTest SimdIntegerTest;
66
67 TEST_F(SimdIntegerTest, gmxSimdSetZeroI)
68 {
69     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0), gmx_simd_setzero_i());
70 }
71
72 TEST_F(SimdIntegerTest, gmxSimdSet1I)
73 {
74     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(1), gmx_simd_set1_i(1));
75 }
76
77 #ifdef GMX_SIMD_HAVE_FINT32_ARITHMETICS
78 TEST_F(SimdIntegerTest, gmxSimdAddI)
79 {
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
82 }
83
84 TEST_F(SimdIntegerTest, gmxSimdSubI)
85 {
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
88 }
89
90 TEST_F(SimdIntegerTest, gmxSimdMulI)
91 {
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)
94 }
95 #endif
96
97 #ifdef GMX_SIMD_HAVE_FINT32_LOGICAL
98 TEST_F(SimdIntegerTest, gmxSimdSlliI)
99 {
100     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4194304), gmx_simd_slli_i(gmx_simd_set1_i(2), 21)); // 2 << 21 = 4194304
101 }
102
103 TEST_F(SimdIntegerTest, gmxSimdSrliI)
104 {
105     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(4), gmx_simd_srli_i(gmx_simd_set1_i(4194304), 20)); // 4194304 >> 20 = 4
106 }
107
108 TEST_F(SimdIntegerTest, gmxSimdAndI)
109 {
110     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xC0C0C0C0), gmx_simd_and_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
111 }
112
113 TEST_F(SimdIntegerTest, gmxSimdAndnotI)
114 {
115     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x0C0C0C0C), gmx_simd_andnot_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
116 }
117
118 TEST_F(SimdIntegerTest, gmxSimdOrI)
119 {
120     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0xFCFCFCFC), gmx_simd_or_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
121 }
122
123 TEST_F(SimdIntegerTest, gmxSimdXorI)
124 {
125     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom1I(0x3C3C3C3C), gmx_simd_xor_i(iSimd_0xF0F0F0F0, iSimd_0xCCCCCCCC));
126 }
127 #endif
128
129 #ifdef GMX_SIMD_HAVE_INT32_EXTRACT
130 TEST_F(SimdIntegerTest, gmxSimdExtractI)
131 {
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;
136
137     for (i = 0; i < GMX_SIMD_INT32_WIDTH; i++)
138     {
139         p[i] = i+1;
140     }
141     simd = gmx_simd_load_i(p);
142
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.
147      *
148      * To solve this we use a few values manually instead of a for-loop.
149      */
150     extracted_int = gmx_simd_extract_i(simd, 0);
151     EXPECT_EQ(1, extracted_int);
152     if (GMX_SIMD_INT32_WIDTH >= 2)
153     {
154         extracted_int = gmx_simd_extract_i(simd, 1);
155         EXPECT_EQ(2, extracted_int);
156     }
157     if (GMX_SIMD_INT32_WIDTH >= 4)
158     {
159         extracted_int = gmx_simd_extract_i(simd, 3);
160         EXPECT_EQ(4, extracted_int);
161     }
162     if (GMX_SIMD_INT32_WIDTH >= 6)
163     {
164         extracted_int = gmx_simd_extract_i(simd, 5);
165         EXPECT_EQ(6, extracted_int);
166     }
167     if (GMX_SIMD_INT32_WIDTH >= 8)
168     {
169         extracted_int = gmx_simd_extract_i(simd, 7);
170         EXPECT_EQ(8, extracted_int);
171     }
172 }
173 #endif
174
175 #ifdef GMX_SIMD_HAVE_REAL
176 TEST_F(SimdIntegerTest, gmxSimdCvtR2I)
177 {
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));
180 }
181
182 TEST_F(SimdIntegerTest, gmxSimdCvttR2I)
183 {
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));
186 }
187
188 TEST_F(SimdIntegerTest, gmxSimdCvtI2R)
189 {
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)));
192 }
193 #endif
194
195 #ifdef GMX_SIMD_HAVE_FINT32_ARITHMETICS
196 TEST_F(SimdIntegerTest, gmxSimdBoolCmpEqAndBlendZeroI)
197 {
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));
200 }
201
202 TEST_F(SimdIntegerTest, gmxSimdBlendNotZeroI)
203 {
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));
206 }
207
208 TEST_F(SimdIntegerTest, gmxSimdBoolCmpLTI)
209 {
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));
212 }
213
214 TEST_F(SimdIntegerTest, gmxSimdBoolAndIB)
215 {
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)));
219 }
220
221 TEST_F(SimdIntegerTest, gmxSimdBoolOrIB)
222 {
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)));
226 }
227
228 TEST_F(SimdIntegerTest, gmxSimdAnytrueIB)
229 {
230     gmx_simd_ibool_t eq;
231
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.
234      */
235     eq = gmx_simd_cmpeq_i(iSimd_5_7_9, setSimdIntFrom3I(5, 0, 0));
236     EXPECT_NE(0, gmx_simd_anytrue_ib(eq));
237
238     eq = gmx_simd_cmpeq_i(iSimd_1_2_3, iSimd_4_5_6);
239     EXPECT_EQ(0, gmx_simd_anytrue_ib(eq));
240 }
241
242 TEST_F(SimdIntegerTest, gmxSimdBlendvI)
243 {
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));
246 }
247 #endif
248
249 #if (defined GMX_SIMD_HAVE_REAL) && (defined GMX_SIMD_HAVE_FINT32_ARITHMETICS)
250 TEST_F(SimdIntegerTest, gmxSimdCvtB2IB)
251 {
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));
255
256 }
257
258 TEST_F(SimdIntegerTest, gmxSimdCvtIB2B)
259 {
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));
263 }
264 #endif
265
266 #endif      // GMX_SIMD_HAVE_INT32
267
268 /*! \} */
269 /*! \endcond */
270
271 }      // namespace
272 }      // namespace
273 }      // namespace