Add comparison operator to BasicVector
[alexxy/gromacs.git] / src / gromacs / math / tests / vectypes.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2014,2015,2016,2018,2019,2021, 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 /*! \internal \file
36  * \brief
37  * Tests various corners of gmx::RVec implementation.
38  *
39  * The main point of these tests is to check that all different constructs
40  * using gmx::RVec compile, and that some of the non-trivial conversions
41  * to/from rvec work as intended.
42  *
43  * \author Teemu Murtola <teemu.murtola@gmail.com>
44  * \ingroup module_math
45  */
46 #include "gmxpre.h"
47
48 #include "gromacs/math/vectypes.h"
49
50 #include <vector>
51
52 #include <gtest/gtest.h>
53
54 #include "gromacs/math/vec.h"
55
56 #include "testutils/testasserts.h"
57
58 namespace
59 {
60
61 using gmx::DVec;
62 using gmx::IVec;
63 using gmx::RVec;
64
65 TEST(RVecTest, CanBeStoredInVector)
66 {
67     std::vector<RVec> v;
68     v.emplace_back(1, 2, 3);
69     v.resize(2);
70     EXPECT_EQ(1, v[0][XX]);
71     EXPECT_EQ(2, v[0][YY]);
72     EXPECT_EQ(3, v[0][ZZ]);
73 }
74
75 TEST(RVecTest, ConvertsImplicitlyFrom_rvec)
76 {
77     std::vector<RVec> v;
78     rvec              x = { 1, 2, 3 };
79     v.emplace_back(x);
80     EXPECT_EQ(1, v[0][XX]);
81     EXPECT_EQ(2, v[0][YY]);
82     EXPECT_EQ(3, v[0][ZZ]);
83 }
84
85 TEST(RVecTest, ConvertsImplicitlyTo_rvec)
86 {
87     std::vector<RVec> v;
88     v.emplace_back(1, 2, 3);
89     rvec x;
90     copy_rvec(v[0], x);
91     EXPECT_EQ(1, x[XX]);
92     EXPECT_EQ(2, x[YY]);
93     EXPECT_EQ(3, x[ZZ]);
94 }
95
96 TEST(RVecTest, WorksAsMutable_rvec)
97 {
98     std::vector<RVec> v;
99     v.emplace_back(1, 2, 3);
100     rvec x = { 2, 3, 4 };
101     copy_rvec(x, v[0]);
102     EXPECT_EQ(2, v[0][XX]);
103     EXPECT_EQ(3, v[0][YY]);
104     EXPECT_EQ(4, v[0][ZZ]);
105 }
106
107 TEST(RVecTest, WorksAs_rvec_Array)
108 {
109     std::vector<RVec> v;
110     v.emplace_back(1, 2, 3);
111     v.emplace_back(2, 3, 4);
112     const rvec* r = as_rvec_array(v.data());
113     EXPECT_EQ(1, r[0][XX]);
114     EXPECT_EQ(2, r[0][YY]);
115     EXPECT_EQ(3, r[0][ZZ]);
116     EXPECT_EQ(2, r[1][XX]);
117     EXPECT_EQ(3, r[1][YY]);
118     EXPECT_EQ(4, r[1][ZZ]);
119 }
120
121 TEST(RVecTest, ComparesEqual)
122 {
123     RVec a(1, 2, 3);
124     RVec b(1, 2, 3);
125     RVec c(1, 2, 2);
126     EXPECT_EQ(a == b, true);
127     EXPECT_EQ(a == c, false);
128 }
129
130 TEST(RVecTest, ComparesUnequal)
131 {
132     RVec a(1, 2, 3);
133     RVec b(1, 2, 3);
134     RVec c(1, 2, 2);
135     EXPECT_EQ(a != b, false);
136     EXPECT_EQ(a != c, true);
137 }
138
139 /*! \brief
140  * Test overloaded math operations
141  */
142
143 TEST(RVecTest, CanAddRVecToRvec)
144 {
145     RVec a(1, 2, 3);
146     RVec b(3, 2, 1);
147     RVec c;
148     c = a + b;
149     EXPECT_EQ(4, c[XX]);
150     EXPECT_EQ(4, c[YY]);
151     EXPECT_EQ(4, c[ZZ]);
152 }
153
154 TEST(RVecTest, CanAddAssignRVecToRvec)
155 {
156     RVec a(1, 2, 3);
157     RVec b(3, 2, 1);
158     a += b;
159     EXPECT_EQ(4, a[XX]);
160     EXPECT_EQ(4, a[YY]);
161     EXPECT_EQ(4, a[ZZ]);
162 }
163
164
165 TEST(RVecTest, CanSubtractRVecFromRvec)
166 {
167     RVec a(1, 2, 3);
168     RVec b(3, 2, 1);
169     RVec c;
170     c = b - a;
171     EXPECT_EQ(2, c[XX]);
172     EXPECT_EQ(0, c[YY]);
173     EXPECT_EQ(-2, c[ZZ]);
174 }
175
176 TEST(RVecTest, CanSubtractAssignRVecFromRvec)
177 {
178     RVec a(1, 2, 3);
179     RVec b(3, 2, 1);
180     RVec c;
181     b -= a;
182     EXPECT_EQ(2, b[XX]);
183     EXPECT_EQ(0, b[YY]);
184     EXPECT_EQ(-2, b[ZZ]);
185 }
186
187 TEST(RVecTest, CanDotProductRVecByRvec)
188 {
189     RVec  a(1, 2, 3);
190     RVec  b(3, 2, 1);
191     float c;
192     c = a.dot(b);
193     EXPECT_EQ(10, c);
194 }
195
196 TEST(RVecTest, CanCrossProductRVecByRvec)
197 {
198     RVec a(1, 2, 3);
199     RVec b(3, 2, 1);
200     RVec c;
201     c = a.cross(b);
202     EXPECT_EQ(-4, c[XX]);
203     EXPECT_EQ(8, c[YY]);
204     EXPECT_EQ(-4, c[ZZ]);
205 }
206
207 /*! \brief
208  * Test for inplace operations imported from vec.h
209  */
210
211 TEST(RVecTest, CanDivideRVecInplace)
212 {
213     RVec a(1, 2, 3);
214     real b = 0.5;
215     RVec c;
216     c = a / b;
217     EXPECT_EQ(2, c[XX]);
218     EXPECT_EQ(4, c[YY]);
219     EXPECT_EQ(6, c[ZZ]);
220 }
221
222 TEST(RVecTest, CanScaleRVec)
223 {
224     RVec a(1, 2, 3);
225     real b = 2.0;
226     a *= b;
227     EXPECT_EQ(2, a[XX]);
228     EXPECT_EQ(4, a[YY]);
229     EXPECT_EQ(6, a[ZZ]);
230 }
231
232 TEST(RVecTest, CanDivideRVec)
233 {
234     RVec a(1, 2, 3);
235     real b = 0.5;
236     a /= b;
237     EXPECT_EQ(2, a[XX]);
238     EXPECT_EQ(4, a[YY]);
239     EXPECT_EQ(6, a[ZZ]);
240 }
241
242 TEST(RVecTest, CanDoUnitvFromRVec)
243 {
244     RVec a(3, 0, 0);
245     RVec b;
246     b = a.unitVector();
247     EXPECT_REAL_EQ(1, b[XX]);
248     EXPECT_REAL_EQ(0, b[YY]);
249     EXPECT_REAL_EQ(0, b[ZZ]);
250 }
251
252 TEST(RVecTest, CanSqLengthOfRVec)
253 {
254     RVec a(1, 2, 2);
255     real b;
256     b = a.norm2();
257     EXPECT_REAL_EQ(9, b);
258 }
259
260 TEST(RVecTest, CanLengthOfRVec)
261 {
262     RVec a(1, 2, 2);
263     real b;
264     b = a.norm();
265     EXPECT_REAL_EQ(3, b);
266 }
267
268 TEST(RVecTest, CanCastToRVec)
269 {
270     DVec a(1, 2, 2);
271     RVec b;
272     b = a.toRVec();
273     EXPECT_EQ(1, b[XX]);
274     EXPECT_EQ(2, b[YY]);
275     EXPECT_EQ(2, b[ZZ]);
276 }
277
278 TEST(RVecTest, CanCastToDVec)
279 {
280     RVec a(1, 2, 2);
281     DVec b;
282     b = a.toDVec();
283     EXPECT_EQ(1, b[XX]);
284     EXPECT_EQ(2, b[YY]);
285     EXPECT_EQ(2, b[ZZ]);
286 }
287
288
289 /*! \brief
290  * Tests for out of class functions
291  */
292 TEST(RVecTest, CanLeftScalarMultiply)
293 {
294     RVec a(1, 2, 3);
295     real b = 2.0;
296     RVec c;
297     c = b * a;
298     EXPECT_EQ(2, c[XX]);
299     EXPECT_EQ(4, c[YY]);
300     EXPECT_EQ(6, c[ZZ]);
301 }
302
303 TEST(RVecTest, CanRightScalarMultiply)
304 {
305     RVec a(1, 2, 3);
306     real b = 2.0;
307     RVec c;
308     c = a * b;
309     EXPECT_EQ(2, c[XX]);
310     EXPECT_EQ(4, c[YY]);
311     EXPECT_EQ(6, c[ZZ]);
312 }
313
314 TEST(RVecTest, CanGetUnitvFromRVec)
315 {
316     RVec a(3, 0, 0);
317     RVec b;
318     b = gmx::unitVector(a);
319     EXPECT_REAL_EQ(1, b[XX]);
320     EXPECT_REAL_EQ(0, b[YY]);
321     EXPECT_REAL_EQ(0, b[ZZ]);
322 }
323
324 TEST(RVecTest, CanGetSqLengthOfRVec)
325 {
326     RVec a(1, 2, 2);
327     real b;
328     b = gmx::norm2(a);
329     EXPECT_REAL_EQ(9, b);
330 }
331
332 TEST(RVecTest, CanGetLengthOfRVec)
333 {
334     RVec a(1, 2, 2);
335     real b;
336     b = gmx::norm(a);
337     EXPECT_REAL_EQ(3, b);
338 }
339
340 TEST(RVecTest, CanDoCrossProductOfRVec)
341 {
342     RVec a(1, 2, 3);
343     RVec b(3, 2, 1);
344     RVec c;
345     c = gmx::cross(a, b);
346     EXPECT_EQ(-4, c[XX]);
347     EXPECT_EQ(8, c[YY]);
348     EXPECT_EQ(-4, c[ZZ]);
349 }
350
351 TEST(RVecTest, CanDoDotProductOfRVec)
352 {
353     RVec  a(1, 2, 3);
354     RVec  b(3, 2, 1);
355     float c;
356     c = gmx::dot(a, b);
357     EXPECT_EQ(10, c);
358 }
359
360 TEST(RVecTest, CanScaleByVector)
361 {
362     RVec a(1, 2, 3);
363     RVec b(3, 2, 1);
364     RVec scaled = scaleByVector(a, b);
365     EXPECT_REAL_EQ(3, scaled[XX]);
366     EXPECT_REAL_EQ(4, scaled[YY]);
367     EXPECT_REAL_EQ(3, scaled[ZZ]);
368 }
369
370 TEST(RVecTest, asIVec)
371 {
372     RVec a(1.2, 2.7, -3e3);
373     auto asIvec = a.toIVec();
374
375     EXPECT_REAL_EQ(1, asIvec[XX]);
376     EXPECT_REAL_EQ(2, asIvec[YY]);
377     EXPECT_REAL_EQ(-3000, asIvec[ZZ]);
378 }
379
380 TEST(RVecTest, elementWiseMin)
381 {
382     RVec a(1, 2, 3);
383     RVec b(3, 2, 1);
384     auto minAB = elementWiseMin(a, b);
385
386     EXPECT_REAL_EQ(1, minAB[XX]);
387     EXPECT_REAL_EQ(2, minAB[YY]);
388     EXPECT_REAL_EQ(1, minAB[ZZ]);
389 }
390
391 TEST(RVecTest, elementWiseMax)
392 {
393     RVec a(1, 2, 3);
394     RVec b(3, 2, 1);
395     auto maxAB = elementWiseMax(a, b);
396
397     EXPECT_REAL_EQ(3, maxAB[XX]);
398     EXPECT_REAL_EQ(2, maxAB[YY]);
399     EXPECT_REAL_EQ(3, maxAB[ZZ]);
400 }
401
402 /*! \brief
403  * Helper function for testing DVec to dvec conversions.
404  */
405 const dvec* testFunction(const dvec& x)
406 {
407     return &x;
408 }
409
410 TEST(RVecTest, WorksAs_dvec_Reference)
411 {
412     DVec        v(1, 2, 3);
413     const dvec* r = testFunction(v.as_vec());
414     EXPECT_EQ(1, r[0][XX]);
415     EXPECT_EQ(2, r[0][YY]);
416     EXPECT_EQ(3, r[0][ZZ]);
417 }
418
419 /*! \brief
420  * Helper function for testing IVec to ivec conversions.
421  */
422 const ivec* testFunction(const ivec& x)
423 {
424     return &x;
425 }
426
427 TEST(RVecTest, WorksAs_ivec_Reference)
428 {
429     IVec        v(1, 2, 3);
430     const ivec* r = testFunction(v.as_vec());
431     EXPECT_EQ(1, r[0][XX]);
432     EXPECT_EQ(2, r[0][YY]);
433     EXPECT_EQ(3, r[0][ZZ]);
434 }
435
436 /*! \brief
437  * Helper function for testing RVec to rvec conversions.
438  */
439 #if !GMX_DOUBLE // otherwise rvec==dvec
440 const rvec* testFunction(const rvec& x)
441 {
442     return &x;
443 }
444 #endif
445
446 TEST(RVecTest, WorksAs_rvec_Reference)
447 {
448     RVec        v(1, 2, 3);
449     const rvec* r = testFunction(v);
450     EXPECT_EQ(1, r[0][XX]);
451     EXPECT_EQ(2, r[0][YY]);
452     EXPECT_EQ(3, r[0][ZZ]);
453 }
454
455 TEST(RVecTest, CopyConstructorWorks)
456 {
457     RVec v(1, 2, 3);
458     RVec copy(v);
459     EXPECT_EQ(1, copy[XX]);
460     EXPECT_EQ(2, copy[YY]);
461     EXPECT_EQ(3, copy[ZZ]);
462 }
463
464 TEST(RVecTest, CopyAssignmentWorks)
465 {
466     RVec v(1, 2, 3);
467     RVec copy;
468     copy = v;
469     EXPECT_EQ(1, copy[XX]);
470     EXPECT_EQ(2, copy[YY]);
471     EXPECT_EQ(3, copy[ZZ]);
472 }
473
474 TEST(RVecTest, MoveConstructorWorks)
475 {
476     RVec v(1, 2, 3);
477     RVec copy(v);
478     EXPECT_EQ(1, copy[XX]);
479     EXPECT_EQ(2, copy[YY]);
480     EXPECT_EQ(3, copy[ZZ]);
481 }
482
483 TEST(RVecTest, MoveAssignmentWorks)
484 {
485     RVec v(1, 2, 3);
486     RVec copy;
487     copy = v;
488     EXPECT_EQ(1, copy[XX]);
489     EXPECT_EQ(2, copy[YY]);
490     EXPECT_EQ(3, copy[ZZ]);
491 }
492
493 } // namespace