3f3df63154698ded482748208a90e904df7d3efd
[alexxy/gromacs.git] / src / gromacs / simd / tests / simd4.h
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 #ifndef GMX_SIMD_TESTS_SIMD4_H
36 #define GMX_SIMD_TESTS_SIMD4_H
37
38 /*! \internal \file
39  * \brief
40  * Declares fixture for testing of SIMD4 functionality.
41  *
42  * This files specializes the common base test utilities to be used
43  * for SIMD4 variables. For detailed documentation, check out the normal
44  * SIMD test classes and files.
45  *
46  * \author Erik Lindahl <erik.lindahl@scilifelab.se>
47  * \ingroup module_simd
48  */
49
50 #include <vector>
51 #include <gtest/gtest.h>
52 #include "gromacs/simd/simd.h"
53 #include "gromacs/simd/tests/base.h"
54
55 namespace gmx
56 {
57 namespace test
58 {
59
60 /*! \cond internal */
61 /*! \addtogroup module_simd */
62 /*! \{ */
63
64 #ifdef GMX_SIMD4_HAVE_REAL
65 extern const gmx_simd4_real_t rSimd4_1_2_3;     //!< Generic (different) fp values.
66 extern const gmx_simd4_real_t rSimd4_4_5_6;     //!< Generic (different) fp values.
67 extern const gmx_simd4_real_t rSimd4_7_8_9;     //!< Generic (different) fp values.
68 extern const gmx_simd4_real_t rSimd4_5_7_9;     //!< rSimd_1_2_3 + rSimd_4_5_6.
69 extern const gmx_simd4_real_t rSimd4_m1_m2_m3;  //!< Generic negative fp values.
70 extern const gmx_simd4_real_t rSimd4_3_1_4;     //!< Used to test min/max.
71 extern const gmx_simd4_real_t rSimd4_m3_m1_m4;  //!< negative rSimd_3_1_4.
72 extern const gmx_simd4_real_t rSimd4_2p25;      //!< Value that rounds down.
73 extern const gmx_simd4_real_t rSimd4_3p75;      //!< Value that rounds up.
74 extern const gmx_simd4_real_t rSimd4_m2p25;     //!< Negative value that rounds up.
75 extern const gmx_simd4_real_t rSimd4_m3p75;     //!< Negative value that rounds down.
76 //! Three large floating-point values whose exponents are >32.
77 extern const gmx_simd4_real_t rSimd4_Exp;
78 #    if (defined GMX_SIMD_HAVE_DOUBLE) && (defined GMX_DOUBLE)
79 // Make sure we also test exponents outside single precision when we use double
80 extern const gmx_simd4_real_t rSimd4_ExpDouble;
81 #    endif
82 extern const gmx_simd4_real_t rSimd4_Bits1; //!< Pattern F0 repeated to fill single/double.
83 extern const gmx_simd4_real_t rSimd4_Bits2; //!< Pattern CC repeated to fill single/double.
84 extern const gmx_simd4_real_t rSimd4_Bits3; //!< Pattern C0 repeated to fill single/double.
85 extern const gmx_simd4_real_t rSimd4_Bits4; //!< Pattern 0C repeated to fill single/double.
86 extern const gmx_simd4_real_t rSimd4_Bits5; //!< Pattern FC repeated to fill single/double.
87 extern const gmx_simd4_real_t rSimd4_Bits6; //!< Pattern 3C repeated to fill single/double.
88
89 /*! \internal
90  * \brief
91  * Test fixture for SIMD4 tests - contains test settings.
92  *
93  * This is a very simple test fixture that basically just takes the common
94  * SIMD/SIMD4 functionality from SimdBaseTest and creates wrapper routines
95  * specific for SIMD4 functionality.
96  */
97 class Simd4Test : public SimdBaseTest
98 {
99     public:
100         /*! \brief Compare two real SIMD4 variables for approximate equality.
101          *
102          * This is an internal implementation routine. YOu should always use
103          * GMX_EXPECT_SIMD4_REAL_NEAR() instead.
104          *
105          * This routine is designed according to the Google test specs, so the char
106          * strings will describe the arguments to the macro.
107          *
108          * The comparison is applied to each element, and it returns true if each element
109          * in the SIMD4 test variable is within the class tolerances of the corresponding
110          * reference element.
111          */
112         ::testing::AssertionResult
113         compareSimd4RealUlp(const char * refExpr, const char * tstExpr,
114                             const gmx_simd4_real_t ref, const gmx_simd4_real_t tst);
115
116         /*! \brief Compare two real SIMD4 variables for exact equality.
117          *
118          * This is an internal implementation routine. YOu should always use
119          * GMX_EXPECT_SIMD4_REAL_NEAR() instead.
120          *
121          * This routine is designed according to the Google test specs, so the char
122          * strings will describe the arguments to the macro.
123          *
124          * The comparison is applied to each element, and it returns true if each element
125          * in the SIMD4 test variable is within the class tolerances of the corresponding
126          * reference element.
127          */
128         ::testing::AssertionResult
129         compareSimd4RealEq(const char * refExpr, const char * tstExpr,
130                            const gmx_simd4_real_t ref, const gmx_simd4_real_t tst);
131 };
132
133 /*! \brief Convert SIMD4 real to std::vector<real>.
134  *
135  * The returned vector will have the same length as the SIMD4 width.
136  */
137 std::vector<real> simd4Real2Vector(const gmx_simd4_real_t simd4);
138
139 /*! \brief Return floating-point SIMD4 value from std::vector<real>.
140  *
141  * If the vector is longer than SIMD4 width, only the first elements will be used.
142  * If it is shorter, the contents will be repeated to fill the SIMD4 register.
143  */
144 gmx_simd4_real_t   vector2Simd4Real(const std::vector<real> &v);
145
146 /*! \brief Set SIMD4 register contents from three real values.
147  *
148  * It might seem stupid to use three values when we know that the SIMD4 width
149  * is 4, but it simplifies the test organization when the SIMD and SIMD4 tests
150  * are completely symmetric.
151  */
152 gmx_simd4_real_t   setSimd4RealFrom3R(real r0, real r1, real r2);
153
154 /*! \brief Set SIMD4 register contents from single real value.
155  *
156  * All elements is set from the given value. This is effectively the same
157  * operation as gmx_simd4_set1_r(), but is implemented using only load/store
158  * operations that have been tested separately in the bootstrapping tests.
159  */
160 gmx_simd4_real_t   setSimd4RealFrom1R(real value);
161
162 /*! \brief Test if a SIMD4 real is bitwise identical to reference SIMD4 value. */
163 #define GMX_EXPECT_SIMD4_REAL_EQ(ref, tst)   EXPECT_PRED_FORMAT2(compareSimd4RealEq, ref, tst)
164
165 /*! \brief Test if a SIMD4 real is within tolerance of reference SIMD4 value. */
166 #define GMX_EXPECT_SIMD4_REAL_NEAR(ref, tst) EXPECT_PRED_FORMAT2(compareSimd4RealUlp, ref, tst)
167
168 #endif  // GMX_SIMD4_HAVE_REAL
169
170 /*! \} */
171 /*! \endcond */
172
173 }      // namespace
174 }      // namespace
175
176 #endif // GMX_SIMD_TESTS_SIMD4_H