2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2015,2016,2017,2018,2019, 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 * Tests for simple math functions.
39 * \author Erik Lindahl <erik.lindahl@gmail.com>
40 * \ingroup module_math
44 #include "gromacs/math/functions.h"
49 #include <gtest/gtest.h>
51 #include "testutils/refdata.h"
52 #include "testutils/testasserts.h"
57 TEST(FunctionTest
, StaticLog2
)
59 gmx::test::TestReferenceData data
;
60 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
61 std::vector
<int> result(11);
63 // This needs to be expanded manually since it is evaluated at compile time,
64 // and the compiler chokes if we put it as formal arguments to push_back
65 result
[0] = gmx::StaticLog2
<1>::value
;
66 result
[1] = gmx::StaticLog2
<2>::value
;
67 result
[2] = gmx::StaticLog2
<3>::value
;
68 result
[3] = gmx::StaticLog2
<4>::value
;
69 result
[4] = gmx::StaticLog2
<5>::value
;
70 result
[5] = gmx::StaticLog2
<6>::value
;
71 result
[6] = gmx::StaticLog2
<7>::value
;
72 result
[7] = gmx::StaticLog2
<8>::value
;
73 result
[8] = gmx::StaticLog2
<0xFFFFFFFF>::value
;
74 result
[9] = gmx::StaticLog2
<9876543210>::value
; // > 32 bits
75 result
[10] = gmx::StaticLog2
<0xFFFFFFFFFFFFFFFFULL
>::value
;
77 checker
.checkSequence(result
.begin(), result
.end(), "StaticLog2");
80 TEST(FunctionTest
, Log2I32Bit
)
82 gmx::test::TestReferenceData data
;
83 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
84 std::vector
<int> result
;
86 for (std::uint32_t i
= 1; i
<= 0xF; i
++)
88 result
.push_back(gmx::log2I(i
));
91 for (std::uint32_t i
= 0; i
<= 0xF; i
++)
93 result
.push_back(gmx::log2I(static_cast<std::uint32_t>(0xFFFFFFF0 + i
)));
95 checker
.checkSequence(result
.begin(), result
.end(), "Log2I32Bit");
98 TEST(FunctionTest
, Log2I64Bit
)
100 gmx::test::TestReferenceData data
;
101 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
102 std::vector
<int> result
;
104 for (std::uint64_t i
= 1; i
<= 0xF; i
++)
106 result
.push_back(gmx::log2I(i
));
109 for (std::uint64_t i
= 0; i
<= 0x1F; i
++)
111 result
.push_back(gmx::log2I(static_cast<std::uint64_t>(0xFFFFFFF0ULL
+ i
)));
114 for (std::uint64_t i
= 0; i
<= 0xF; i
++)
116 result
.push_back(gmx::log2I(static_cast<std::uint64_t>(0xFFFFFFFFFFFFFFF0ULL
+ i
)));
118 checker
.checkSequence(result
.begin(), result
.end(), "Log2I64Bit");
121 TEST(FunctionTest
, GreatestCommonDivisor
)
123 EXPECT_EQ(8, gmx::greatestCommonDivisor(24, 64));
124 EXPECT_EQ(8, gmx::greatestCommonDivisor(64, 24));
125 EXPECT_EQ(1, gmx::greatestCommonDivisor(169, 289));
128 TEST(FunctionTest
, InvsqrtFloat
)
130 gmx::test::TestReferenceData data
;
131 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
132 std::vector
<float> result
;
134 for (float f
= 1.0; f
< 10.0; f
+= 1.0)
136 result
.push_back(gmx::invsqrt(f
));
138 checker
.checkSequence(result
.begin(), result
.end(), "InvsqrtFloat");
141 TEST(FunctionTest
, InvsqrtDouble
)
143 gmx::test::TestReferenceData data
;
144 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
145 std::vector
<double> result
;
147 for (double f
= 1.0; f
< 10.0; f
+= 1.0) // NOLINT(clang-analyzer-security.FloatLoopCounter)
149 result
.push_back(gmx::invsqrt(f
));
151 checker
.checkSequence(result
.begin(), result
.end(), "InvsqrtDouble");
154 TEST(FunctionTest
, InvsqrtInteger
)
156 gmx::test::TestReferenceData data
;
157 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
158 std::vector
<double> result
;
160 for (int i
= 1; i
< 10; i
++)
162 result
.push_back(gmx::invsqrt(i
));
164 checker
.checkSequence(result
.begin(), result
.end(), "InvsqrtInteger");
167 TEST(FunctionTest
, InvcbrtFloat
)
169 gmx::test::TestReferenceData data
;
170 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
171 std::vector
<float> result
;
173 for (int f
: { -5, -4, -3, -2, -1, 1, 2, 3, 4 })
175 result
.push_back(gmx::invcbrt(f
));
177 checker
.checkSequence(result
.begin(), result
.end(), "InvcbrtFloat");
180 TEST(FunctionTest
, InvcbrtDouble
)
182 gmx::test::TestReferenceData data
;
183 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
184 std::vector
<double> result
;
186 for (double d
: { -5, -4, -3, -2, -1, 1, 2, 3, 4 })
188 result
.push_back(gmx::invcbrt(d
));
190 checker
.checkSequence(result
.begin(), result
.end(), "InvcbrtDouble");
193 TEST(FunctionTest
, InvcbrtInteger
)
195 gmx::test::TestReferenceData data
;
196 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
197 std::vector
<double> result
;
199 for (int i
: { -5, -4, -3, -2, -1, 1, 2, 3, 4 })
201 result
.push_back(gmx::invcbrt(i
));
203 checker
.checkSequence(result
.begin(), result
.end(), "InvcbrtInteger");
207 TEST(FunctionTest
, SixthrootFloat
)
209 gmx::test::TestReferenceData data
;
210 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
211 std::vector
<float> result
;
213 for (float f
= 0; f
< 10.0; f
+= 1.0)
215 result
.push_back(gmx::sixthroot(f
));
217 checker
.checkSequence(result
.begin(), result
.end(), "SixthrootFloat");
220 TEST(FunctionTest
, SixthrootDouble
)
222 gmx::test::TestReferenceData data
;
223 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
224 std::vector
<double> result
;
226 for (double d
= 0; d
< 10.0; d
+= 1.0) // NOLINT(clang-analyzer-security.FloatLoopCounter)
228 result
.push_back(gmx::sixthroot(d
));
230 checker
.checkSequence(result
.begin(), result
.end(), "SixthrootDouble");
233 TEST(FunctionTest
, SixthrootInteger
)
235 gmx::test::TestReferenceData data
;
236 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
237 std::vector
<double> result
;
240 for (int i
= 0; i
< 10; i
++)
242 result
.push_back(gmx::sixthroot(i
));
244 checker
.checkSequence(result
.begin(), result
.end(), "SixthrootInteger");
247 TEST(FunctionTest
, InvsixthrootFloat
)
249 gmx::test::TestReferenceData data
;
250 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
251 std::vector
<float> result
;
253 for (float f
= 1.0; f
< 10.0; f
+= 1.0)
255 result
.push_back(gmx::invsixthroot(f
));
257 checker
.checkSequence(result
.begin(), result
.end(), "InvsixthrootFloat");
260 TEST(FunctionTest
, InvsixthrootDouble
)
262 gmx::test::TestReferenceData data
;
263 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
264 std::vector
<double> result
;
266 for (double d
= 1.0; d
< 10.0; d
+= 1.0) // NOLINT(clang-analyzer-security.FloatLoopCounter)
268 result
.push_back(gmx::invsixthroot(d
));
270 checker
.checkSequence(result
.begin(), result
.end(), "InvsixthrootDouble");
273 TEST(FunctionTest
, InvsixthrootInteger
)
275 gmx::test::TestReferenceData data
;
276 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
277 std::vector
<double> result
;
279 for (int i
= 1; i
< 10; i
++)
281 result
.push_back(gmx::invsixthroot(i
));
283 checker
.checkSequence(result
.begin(), result
.end(), "InvsixthrootInteger");
286 TEST(FunctionTest
, Powers
)
288 // These should be remarkably difficult to screw up, but test each
289 // of them once anyway with integer and fp arguments to catch typos.
290 EXPECT_EQ(4, gmx::square(2));
291 EXPECT_EQ(8, gmx::power3(2));
292 EXPECT_EQ(16, gmx::power4(2));
293 EXPECT_EQ(32, gmx::power5(2));
294 EXPECT_EQ(64, gmx::power6(2));
295 EXPECT_EQ(4096, gmx::power12(2));
297 EXPECT_EQ(6.25, gmx::square(2.5));
298 EXPECT_EQ(15.625, gmx::power3(2.5));
299 EXPECT_EQ(39.0625, gmx::power4(2.5));
300 EXPECT_EQ(97.65625, gmx::power5(2.5));
301 EXPECT_EQ(244.140625, gmx::power6(2.5));
302 EXPECT_EQ(59604.644775390625, gmx::power12(2.5));
305 TEST(FunctionTest
, ErfInvFloat
)
307 gmx::test::TestReferenceData data
;
308 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
309 std::vector
<float> result
;
312 for (int i
= 0; i
< npoints
; i
++)
314 float r
= float(2 * i
- npoints
+ 1) / float(npoints
);
316 result
.push_back(gmx::erfinv(r
));
318 checker
.checkSequence(result
.begin(), result
.end(), "ErfInvFloat");
321 TEST(FunctionTest
, ErfInvDouble
)
323 gmx::test::TestReferenceData data
;
324 gmx::test::TestReferenceChecker
checker(data
.rootChecker());
325 std::vector
<double> result
;
328 for (int i
= 0; i
< npoints
; i
++)
330 double r
= double(2 * i
- npoints
+ 1) / npoints
;
332 result
.push_back(gmx::erfinv(r
));
334 checker
.checkSequence(result
.begin(), result
.end(), "ErfInvDouble");
337 TEST(FunctionTest
, ErfAndErfInvAreInversesFloat
)
341 for (int i
= 0; i
< npoints
; i
++)
343 float r
= float(2 * i
- npoints
+ 1) / float(npoints
);
344 EXPECT_FLOAT_EQ_TOL(r
, std::erf(gmx::erfinv(r
)), gmx::test::ulpTolerance(10));
348 TEST(FunctionTest
, ErfAndErfInvAreInversesDouble
)
352 for (int i
= 0; i
< npoints
; i
++)
354 double r
= double(2 * i
- npoints
+ 1) / npoints
;
355 EXPECT_DOUBLE_EQ_TOL(r
, std::erf(gmx::erfinv(r
)), gmx::test::ulpTolerance(10));