Apply clang-format to source tree
[alexxy/gromacs.git] / src / gromacs / math / tests / multidimarray.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 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.
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 multidimensional arrays
38  *
39  * \author Christian Blau <cblau@gwdg.de>
40  * \ingroup module_math
41  */
42 #include "gmxpre.h"
43
44 #include "gromacs/math/multidimarray.h"
45
46 #include <string>
47 #include <vector>
48
49 #include <gmock/gmock.h>
50 #include <gtest/gtest.h>
51
52 #include "gromacs/mdspan/extensions.h"
53
54 #include "testutils/testasserts.h"
55
56 namespace gmx
57 {
58
59 namespace test
60 {
61
62 namespace
63 {
64
65 class MultiDimArrayTest : public ::testing::Test
66 {
67 public:
68     MultiDimArrayTest()
69     {
70         std::fill(begin(staticArray_), end(staticArray_), testNumber_ - 1);
71         std::fill(begin(dynamicArray_), end(dynamicArray_), testNumber_ - 1);
72     }
73
74 protected:
75     using static_container_type = std::array<float, 3 * 3>;
76     using static_extents_type   = extents<3, 3>;
77     using static_array_type     = MultiDimArray<static_container_type, static_extents_type>;
78
79     using dynamic_container_type = std::vector<float>;
80     using dynamic_extents_type   = extents<dynamic_extent, dynamic_extent>;
81     using dynamic_array_type     = MultiDimArray<dynamic_container_type, dynamic_extents_type>;
82
83     static_array_type  staticArray_;
84     dynamic_array_type dynamicArray_{ 2, 2 };
85
86     float testNumber_ = 42;
87 };
88
89
90 TEST_F(MultiDimArrayTest, canConstructAndFillStatic)
91 {
92     for (const auto& x : staticArray_)
93     {
94         EXPECT_EQ(testNumber_ - 1, x);
95     }
96 }
97
98 TEST_F(MultiDimArrayTest, canConstructAndFillDynamic)
99 {
100     for (const auto& x : dynamicArray_)
101     {
102         EXPECT_EQ(testNumber_ - 1, x);
103     }
104 }
105
106 TEST_F(MultiDimArrayTest, canSetValuesInStatic)
107 {
108     staticArray_(1, 1) = testNumber_;
109     EXPECT_EQ(testNumber_, staticArray_(1, 1));
110 }
111
112 TEST_F(MultiDimArrayTest, canSetValuesInDynamic)
113 {
114     dynamicArray_(1, 1) = testNumber_;
115     EXPECT_EQ(testNumber_, dynamicArray_(1, 1));
116 }
117
118 TEST_F(MultiDimArrayTest, canMoveConstructStatic)
119 {
120     auto other(std::move(staticArray_));
121     for (const auto& x : other)
122     {
123         EXPECT_EQ(testNumber_ - 1, x);
124     }
125 }
126
127 TEST_F(MultiDimArrayTest, canMoveConstructDynamic)
128 {
129     auto other(std::move(dynamicArray_));
130     for (const auto& x : other)
131     {
132         EXPECT_EQ(testNumber_ - 1, x);
133     }
134 }
135
136 TEST_F(MultiDimArrayTest, canMoveAssignStatic)
137 {
138     static_array_type other;
139     other = std::move(staticArray_);
140     for (const auto& x : other)
141     {
142         EXPECT_EQ(testNumber_ - 1, x);
143     }
144 }
145
146 TEST_F(MultiDimArrayTest, canMoveAssignDynamic)
147 {
148     dynamic_array_type other;
149     other = std::move(dynamicArray_);
150     for (const auto& x : other)
151     {
152         EXPECT_EQ(testNumber_ - 1, x);
153     }
154 }
155
156 TEST_F(MultiDimArrayTest, canCopyConstructStatic)
157 {
158     auto other       = staticArray_;
159     auto twoDArrayIt = begin(staticArray_);
160     for (const auto& x : other)
161     {
162         EXPECT_EQ(*twoDArrayIt, x);
163         ++twoDArrayIt;
164     }
165 }
166
167 TEST_F(MultiDimArrayTest, canCopyConstructDynamic)
168 {
169     auto other       = dynamicArray_;
170     auto twoDArrayIt = begin(dynamicArray_);
171     for (const auto& x : other)
172     {
173         EXPECT_EQ(*twoDArrayIt, x);
174         ++twoDArrayIt;
175     }
176 }
177
178 TEST_F(MultiDimArrayTest, canCopyAssignStatic)
179 {
180     static_array_type other;
181     other            = staticArray_;
182     auto twoDArrayIt = begin(staticArray_);
183     for (const auto& x : other)
184     {
185         EXPECT_EQ(*twoDArrayIt, x);
186         ++twoDArrayIt;
187     }
188 }
189
190 TEST_F(MultiDimArrayTest, canCopyAssignDynamic)
191 {
192     dynamic_array_type other;
193     other            = dynamicArray_;
194     auto twoDArrayIt = begin(dynamicArray_);
195     for (const auto& x : other)
196     {
197         EXPECT_EQ(*twoDArrayIt, x);
198         ++twoDArrayIt;
199     }
200 }
201
202 TEST_F(MultiDimArrayTest, canSwapStatic)
203 {
204     static_array_type other;
205     staticArray_(0, 0) = testNumber_;
206     other.swap(staticArray_);
207     EXPECT_EQ(testNumber_, other(0, 0));
208     for (auto x = begin(other) + 1; x != end(other); ++x)
209     {
210         EXPECT_EQ(testNumber_ - 1, *x);
211     }
212 }
213
214 TEST_F(MultiDimArrayTest, canSwapDynamic)
215 {
216     dynamic_array_type other;
217     dynamicArray_(0, 0) = testNumber_;
218     other.swap(dynamicArray_);
219     EXPECT_EQ(testNumber_, other(0, 0));
220     for (auto x = begin(other) + 1; x != end(other); ++x)
221     {
222         EXPECT_EQ(testNumber_ - 1, *x);
223     }
224 }
225
226 TEST_F(MultiDimArrayTest, staticMultiDimArrayExtent)
227 {
228     EXPECT_EQ(staticArray_.extent(0), 3);
229     EXPECT_EQ(staticArray_.extent(1), 3);
230 }
231
232 TEST_F(MultiDimArrayTest, dynamicMultiDimArrayExtent)
233 {
234     EXPECT_EQ(dynamicArray_.extent(0), 2);
235     EXPECT_EQ(dynamicArray_.extent(1), 2);
236 }
237
238 TEST_F(MultiDimArrayTest, dynamicMultiDimArrayResizesToCorrectExtent)
239 {
240     dynamicArray_.resize(5, 4);
241     EXPECT_EQ(dynamicArray_.extent(0), 5);
242     EXPECT_EQ(dynamicArray_.extent(1), 4);
243 }
244
245 TEST_F(MultiDimArrayTest, dynamicMultiDimArrayResizeAndSetValue)
246 {
247     dynamicArray_.resize(5, 4);
248     dynamicArray_(4, 3) = testNumber_;
249     EXPECT_EQ(dynamicArray_(4, 3), testNumber_);
250 }
251
252 TEST_F(MultiDimArrayTest, staticMultiDimArrayFromArray)
253 {
254     static_array_type arr = { { 1, 2, 3, 4, 5, 6, 7, 8, 9 } };
255     EXPECT_EQ(arr(0, 0), 1);
256     EXPECT_EQ(arr(0, 1), 2);
257     EXPECT_EQ(arr(0, 2), 3);
258     EXPECT_EQ(arr(1, 0), 4);
259     EXPECT_EQ(arr(1, 1), 5);
260     EXPECT_EQ(arr(1, 2), 6);
261     EXPECT_EQ(arr(2, 0), 7);
262     EXPECT_EQ(arr(2, 1), 8);
263     EXPECT_EQ(arr(2, 2), 9);
264 }
265
266 TEST_F(MultiDimArrayTest, conversionToView)
267 {
268     static_array_type::view_type view = staticArray_.asView();
269     view(2, 2)                        = testNumber_;
270     EXPECT_EQ(testNumber_, view(2, 2));
271 }
272
273 TEST_F(MultiDimArrayTest, conversionToConstView)
274 {
275     static_array_type::const_view_type view = staticArray_.asConstView();
276     // the following must not compile:
277     // view(2, 2) = testNumber_;
278     for (const auto& x : view)
279     {
280         EXPECT_EQ(testNumber_ - 1, x);
281     }
282 }
283
284 TEST_F(MultiDimArrayTest, viewBegin)
285 {
286     static_array_type::view_type view = staticArray_.asView();
287     *begin(view)                      = testNumber_;
288     EXPECT_EQ(*begin(view), testNumber_);
289 }
290
291 TEST_F(MultiDimArrayTest, viewEnd)
292 {
293     static_array_type::view_type view = staticArray_.asView();
294     auto                         x    = end(view);
295     --x;
296     view(2, 2) = testNumber_;
297     EXPECT_EQ(*x, testNumber_);
298 }
299
300 TEST_F(MultiDimArrayTest, constViewConstBegin)
301 {
302     staticArray_(0, 0) = testNumber_;
303     const auto view    = staticArray_.asConstView();
304     // must not compile: *begin(view) = testNumber_;
305     EXPECT_EQ(*begin(view), testNumber_);
306 }
307
308 TEST_F(MultiDimArrayTest, constViewConstEnd)
309 {
310     staticArray_(2, 2) = testNumber_;
311     const auto view    = staticArray_.asConstView();
312     auto       x       = end(view);
313     --x;
314     EXPECT_EQ(*x, testNumber_);
315 }
316
317 TEST(MultiDimArrayToMdSpanTest, convertsToMdSpan)
318 {
319     MultiDimArray<std::array<int, 4>, extents<2, 2>> arr = { { 0, 1, 2, 3 } };
320     basic_mdspan<int, extents<2, 2>>                 span(arr);
321
322     // test copy correctness
323     EXPECT_EQ(span(1, 1), 3);
324
325     // test that span operates on same data as array
326     span(0, 1) = -5;
327     EXPECT_EQ(arr(0, 1), -5);
328 }
329
330 TEST(MultiDimArrayToMdSpanTest, constArrayToMdSpan)
331 {
332     const MultiDimArray<std::array<int, 4>, extents<2, 2>> constArr = { { 0, 1, 2, 3 } };
333     basic_mdspan<const int, extents<2, 2>>                 span(constArr);
334     EXPECT_EQ(span(0, 1), 1);
335 }
336
337 TEST(MultiDimArrayToMdSpanTest, nonConstArrayToConstMdSpan)
338 {
339     MultiDimArray<std::array<int, 4>, extents<2, 2>> arr = { { 0, 1, 2, 3 } };
340     basic_mdspan<const int, extents<2, 2>>           span(arr);
341     EXPECT_EQ(span(0, 1), 1);
342 }
343
344 TEST(MultiDimArrayToMdSpanTest, implicitConversionToMdSpan)
345 {
346     auto testFunc = [](basic_mdspan<const int, extents<2, 2>> a) { return a(0, 0); };
347     MultiDimArray<std::array<int, 4>, extents<2, 2>> arr = { { 0, 1, 2, 3 } };
348     EXPECT_EQ(testFunc(arr), 0);
349 }
350
351 } // namespace
352 } // namespace test
353
354 } // namespace gmx