astrotypes  0.0
MultiArrayTest.cpp
Go to the documentation of this file.
1 /*
2  * MIT License
3  *
4  * Copyright (c) 2018 PulsarSearchSoft
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "../MultiArrayTest.h"
25 #include "../TestMultiArray.h"
27 #include <algorithm>
28 
29 
30 namespace pss {
31 namespace astrotypes {
32 namespace test {
33 
34 
36  : ::testing::Test()
37 {
38 }
39 
41 {
42 }
43 
45 {
46 }
47 
49 {
50 }
51 
52 TEST_F(MultiArrayTest, test_single_dimension_size)
53 {
56  ASSERT_EQ(ma.dimension<DimensionA>(), size);
57  ASSERT_EQ(ma.dimension<DimensionB>(), DimensionSize<DimensionB>(0U));
58  ASSERT_EQ(ma.dimension<DimensionC>(), DimensionSize<DimensionC>(0U));
59  ASSERT_EQ(std::distance(ma.begin(), ma.end()), size);
60 }
61 
62 TEST_F(MultiArrayTest, test_single_dimension_const_iterator)
63 {
66  auto it = ma.cbegin();
67  auto end = ma.cend();
68  ASSERT_EQ(std::distance(it, end), (std::size_t)size);
69  unsigned n=0;
70  std::for_each(it, end, [&](int const& val)
71  {
72  ASSERT_EQ(val, n);
73  ++n;
74  });
75  ASSERT_EQ(n, (unsigned)size);
76 }
77 
78 TEST_F(MultiArrayTest, test_two_dimension_1_slice_operator_DimensionB_const_iterator)
79 {
80  DimensionSize<DimensionA> size_a(30);
81  DimensionSize<DimensionB> size_b(20);
83 
84  // slice 0 - sanity checks for first slice
86  ASSERT_EQ(&*slice0.begin(), &*ma.begin());
87  int* end0=&*ma.begin() + (size_b * (size_a - 1) +1 );
88  ASSERT_EQ(&*slice0.end(), end0) << "delta=" << end0 - &*slice0.end();
89 
90  ASSERT_EQ(slice0.dimension<DimensionA>(), size_a);
91  ASSERT_EQ(slice0.dimension<DimensionB>(), DimensionSize<DimensionB>(1));
92  auto it = slice0.cbegin();
93  auto end = slice0.cend();
94  ASSERT_EQ(std::distance(it, end), (std::size_t)size_a);
95  unsigned n=0;
96  std::for_each(it, end, [&](int const& val)
97  {
98  ASSERT_EQ(val, n);
99  n += (std::size_t)size_b;
100  });
101  ASSERT_EQ(n, (unsigned)size_b * size_a);
102 
103  // slice q - sanity checks for first slice
105  ASSERT_EQ(&*slice1.begin(), (&*ma.begin()) + 1);
106  int* end1=&*slice1.begin() + (size_b * (size_a - 1) +1 );
107  ASSERT_EQ(&*slice1.end(), end1) << "delta=" << end1 - &*slice1.end();
108 
109 }
110 
111 TEST_F(MultiArrayTest, test_two_dimension_1_slice_DimensionA_const_iterator)
112 {
113  DimensionSize<DimensionA> size_a(30);
114  DimensionSize<DimensionB> size_b(20);
116  auto slice = ma[DimensionIndex<DimensionA>(1)];
117  ASSERT_EQ(slice.dimension<DimensionB>(), size_b);
118  auto it = slice.cbegin();
119  auto end = slice.cend();
120  ASSERT_EQ(std::distance(it, end), (std::size_t)size_b);
121  unsigned n=(unsigned)size_b;
122  std::for_each(it, end, [&](int const& val)
123  {
124  ASSERT_EQ(val, n);
125  ++n;
126  });
127  ASSERT_EQ(n-(unsigned)size_b, (unsigned)size_b);
128 }
129 
130 TEST_F(MultiArrayTest, test_two_dimension_1_slice_operator_DimensionA_const_iterator)
131 {
132  DimensionSize<DimensionA> size_a(30);
133  DimensionSize<DimensionB> size_b(20);
136  ASSERT_EQ(slice.dimension<DimensionB>(), size_b);
137  auto it = slice.cbegin();
138  auto end = slice.cend();
139  ASSERT_EQ(std::distance(it, end), (std::size_t)size_b);
140  unsigned n=(unsigned)size_b;
141  std::for_each(it, end, [&](int const& val)
142  {
143  ASSERT_EQ(val, n);
144  ++n;
145  });
146  ASSERT_EQ(n-(unsigned)size_b, (unsigned)size_b);
147 }
148 
149 /*
150 TEST_F(MultiArrayTest, test_two_dimension_slice_range_outside_of_array_DimensionA)
151 {
152  DimensionSize<DimensionA> size_a(30);
153  DimensionSize<DimensionB> size_b(20);
154  TestMultiArray<int, DimensionA, DimensionB> ab(size_a, size_b);
155 
156  auto slice = ab.slice(DimensionSpan<DimensionA>(DimensionIndex<DimensionA>(31), DimensionSize<DimensionA>(2)));
157  ASSERT_EQ(slice.dimension<DimensionA>(), DimensionSize<DimensionA>(0));
158  ASSERT_EQ(slice.begin(), slice.end());
159 }
160 
161 TEST_F(MultiArrayTest, test_two_dimension_slice_range_outside_of_array_DimensionB)
162 {
163  DimensionSize<DimensionA> size_a(6);
164  DimensionSize<DimensionB> size_b(5);
165  TestMultiArray<int, DimensionA, DimensionB> ab(size_a, size_b);
166 
167  auto slice = ab.slice(DimensionSpan<DimensionB>(DimensionIndex<DimensionB>(8), DimensionSize<DimensionB>(2)));
168  ASSERT_EQ(slice.dimension<DimensionB>(), DimensionSize<DimensionB>(0));
169  ASSERT_EQ(slice.dimension<DimensionA>(), size_a);
170  ASSERT_EQ(&*slice.begin(), &*ab.end()) << "begin=" << (void*) &*slice.begin() << " ab.begin=" << &*ab.begin() << " ab.end=" << (void*)&*ab.end();
171  ASSERT_EQ(slice.begin(), slice.end()) << "begin=" << (void*) &*slice.begin() << " end=" << (void*)&*slice.end();
172 }
173 
174 TEST_F(MultiArrayTest, test_two_dimension_slice_range_extends_beyond_array)
175 {
176  DimensionSize<DimensionA> size_a(20);
177  DimensionSize<DimensionB> size_b(20);
178  TestMultiArray<int, DimensionA, DimensionB> ab(size_a, size_b);
179 
180  auto slice = ab.slice(DimensionSpan<DimensionA>(DimensionIndex<DimensionA>(10), DimensionSize<DimensionA>(30)));
181  ASSERT_EQ(slice.dimension<DimensionA>(), DimensionSize<DimensionA>(10));
182  ASSERT_NE(slice.begin(), slice.end());
183  ASSERT_EQ(&*ab.end(), &*slice.end());
184 }
185 */
186 
187 
188 TEST_F(MultiArrayTest, test_two_dimension_transpose_constructor)
189 {
190  DimensionSize<DimensionA> size_a(30);
191  DimensionSize<DimensionB> size_b(20);
193 
195  ASSERT_EQ(ba.dimension<DimensionA>(), size_a);
196  ASSERT_EQ(ba.dimension<DimensionB>(), size_b);
197 
198  for(DimensionIndex<DimensionA> i(0); i < ab.dimension<DimensionA>(); ++i) {
199  for(DimensionIndex<DimensionB> j(0); j < ab.dimension<DimensionB>(); ++j) {
200  ASSERT_EQ(ba[j][i], ab[i][j]) << " i=" << i << " j=" << j << " " << &ba[j][i];
201  }
202  }
203 }
204 
205 TEST_F(MultiArrayTest, test_three_dimension_size)
206 {
207  DimensionSize<DimensionA> size_a(10);
208  DimensionSize<DimensionB> size_b(20);
209  DimensionSize<DimensionC> size_c(30);
211  ASSERT_EQ(ma.dimension<DimensionA>(), size_a);
212  ASSERT_EQ(ma.dimension<DimensionB>(), size_b);
213  ASSERT_EQ(ma.dimension<DimensionC>(), size_c);
214 }
215 
216 TEST_F(MultiArrayTest, test_three_dimension_square_bracket_operator)
217 {
218  DimensionSize<DimensionA> size_a(10);
219  DimensionSize<DimensionB> size_b(20);
220  DimensionSize<DimensionC> size_c(30);
222  for(DimensionIndex<DimensionA> index(0); index < size_a; ++index)
223  {
224  auto slice = ma[index];
225  //ASSERT_EQ(slice.dimension<DimensionA>(), DimensionIndex<DimensionA>(9) - index);
226  //ASSERT_EQ(slice.dimension<DimensionA>(), DimensionSize<DimensionA>(0));
227  ASSERT_EQ(slice.dimension<DimensionB>(), size_b);
228  ASSERT_EQ(slice.dimension<DimensionC>(), size_c);
229  }
230 }
231 
232 TEST_F(MultiArrayTest, test_const_three_dimension_square_bracket_operator)
233 {
234  DimensionSize<DimensionA> size_a(10);
235  DimensionSize<DimensionB> size_b(20);
236  DimensionSize<DimensionC> size_c(30);
237  TestMultiArray<unsigned, DimensionA, DimensionB, DimensionC> const ma( size_a, size_b, size_c);
238  for(DimensionIndex<DimensionA> index(0); index < size_a; ++index)
239  {
240  auto slice = ma[index];
241  //ASSERT_EQ(slice.dimension<DimensionA>(), DimensionIndex<DimensionA>(9) - index);
242  //ASSERT_EQ(slice.dimension<DimensionA>(), DimensionSize<DimensionA>(0));
243  ASSERT_EQ(slice.dimension<DimensionB>(), size_b);
244  ASSERT_EQ(slice.dimension<DimensionC>(), size_c);
245  }
246 }
247 
248 TEST_F(MultiArrayTest, test_three_dimension_slice_operator)
249 {
250  DimensionSize<DimensionA> size_a(10);
251  DimensionSize<DimensionB> size_b(20);
252  DimensionSize<DimensionC> size_c(30);
254  for(DimensionIndex<DimensionA> index(0); index < size_a; ++index)
255  {
256  SCOPED_TRACE(index);
257  for(DimensionIndex<DimensionA> index_2(index + DimensionSize<DimensionA>(1)); index_2 < size_a; ++index_2)
258  {
259  SCOPED_TRACE(index_2);
260  auto slice = ma.slice(DimensionSpan<DimensionA>(index, index_2 ));
261  ASSERT_EQ(static_cast<std::size_t>(slice.dimension<DimensionA>()), (index_2 - index) + 1 );
262  ASSERT_EQ(slice.dimension<DimensionB>(), size_b);
263  ASSERT_EQ(slice.dimension<DimensionC>(), size_c);
264  }
265  }
266 }
267 
268 TEST_F(MultiArrayTest, test_const_three_dimension_slice_operator)
269 {
270  DimensionSize<DimensionA> size_a(10);
271  DimensionSize<DimensionB> size_b(20);
272  DimensionSize<DimensionC> size_c(30);
273  TestMultiArray<unsigned, DimensionA, DimensionB, DimensionC> const ma( size_a, size_b, size_c);
274  for(DimensionIndex<DimensionA> index(0); index < size_a; ++index)
275  {
276  for(DimensionIndex<DimensionA> index_2(index + DimensionSize<DimensionA>(1)); index_2 < size_a; ++index_2)
277  {
278  auto slice = ma.slice(DimensionSpan<DimensionA>(index, index_2 ));
279  ASSERT_EQ(static_cast<std::size_t>(slice.dimension<DimensionA>()), (index_2 - index) + 1 );
280  ASSERT_EQ(slice.dimension<DimensionB>(), size_b);
281  ASSERT_EQ(slice.dimension<DimensionC>(), size_c);
282  }
283  }
284 }
285 
286 TEST_F(MultiArrayTest, test_three_dimension_std_copy)
287 {
288  DimensionSize<DimensionA> size_a(10);
289  DimensionSize<DimensionB> size_b(20);
290  DimensionSize<DimensionC> size_c(30);
291  // fill some data
292  std::vector<unsigned> data(size_a * size_b * size_c);
293  unsigned val=0;
294  std::generate(data.begin(), data.end(), [&]() { return val++; } );
295 
297  std::copy(data.begin(), data.end(), ma.begin()); // copy in
298 
299  // ensure the [] operators return the correct values
300  for(DimensionIndex<DimensionA> i(0); i < ma.dimension<DimensionA>(); ++i) {
301  for(DimensionIndex<DimensionB> j(0); j < ma.dimension<DimensionB>(); ++j) {
302  ASSERT_EQ( i * size_b * size_c + j * size_c + 20, ma[i][j][DimensionIndex<DimensionC>(20)]) << "i=" << i
303  << " j=" << j;
304  }
305  }
306 
307  std::vector<unsigned> dst;
308  dst.reserve(size_a * size_b * size_c);
309  std::copy(ma.begin(), ma.end(), std::back_inserter(dst)); //copy our
310  ASSERT_EQ(data.size(), dst.size());
311  ASSERT_EQ(data, dst);
312 
313  // test cbegin/cend
314  dst.clear();
315  std::copy(ma.cbegin(), ma.cend(), std::back_inserter(dst)); //copy our
316  ASSERT_EQ(data, dst);
317 }
318 
319 TEST_F(MultiArrayTest, test_one_dimension_resize)
320 {
321  DimensionSize<DimensionA> size_a(10);
322 
324 
325  size_a = DimensionSize<DimensionA>(5);
326  ma.resize(size_a);
327  ASSERT_EQ(ma.dimension<DimensionA>(), size_a);
328  ASSERT_EQ(std::distance(ma.begin(), ma.end()), size_a);
329 }
330 
331 TEST_F(MultiArrayTest, test_one_dimension_resize_with_value)
332 {
333  DimensionSize<DimensionA> size_a(2);
334 
336 
337  size_a = DimensionSize<DimensionA>(5);
338  ma.resize(size_a, 99);
339  ASSERT_EQ(ma.dimension<DimensionA>(), size_a);
340  ASSERT_EQ(std::distance(ma.begin(), ma.end()), size_a);
341  for(DimensionIndex<DimensionA> i = DimensionIndex<DimensionA>(2); i < size_a; ++i ) {
342  ASSERT_EQ(ma[i], 99U);
343  }
344 }
345 
346 TEST_F(MultiArrayTest, test_two_dimension_resize_with_value)
347 {
348  DimensionSize<DimensionA> size_a(1);
349  DimensionSize<DimensionB> size_b(2);
350  DimensionSize<DimensionA> new_size_a(10);
351  DimensionSize<DimensionB> new_size_b(20);
353  ma.resize<DimensionA, DimensionB>(new_size_a, new_size_b, 199U);
354  for(DimensionIndex<DimensionA> i = DimensionIndex<DimensionA>(1); i < new_size_a; ++i ) {
355  for(DimensionIndex<DimensionB> j = DimensionIndex<DimensionB>(2); j < new_size_b; ++j ) {
356  ASSERT_EQ(ma[i][j], 199U);
357  }
358  }
359 }
360 
361 TEST_F(MultiArrayTest, test_three_dimension_resize)
362 {
363  DimensionSize<DimensionA> size_a(10);
364  DimensionSize<DimensionB> size_b(20);
365  DimensionSize<DimensionC> size_c(30);
366 
368 
369  size_a = DimensionSize<DimensionA>(5);
370  ma.resize(size_a);
371  ASSERT_EQ(ma.dimension<DimensionA>(), size_a);
372  ASSERT_EQ(ma.dimension<DimensionB>(), size_b);
373  ASSERT_EQ(ma.dimension<DimensionC>(), size_c);
374  ASSERT_EQ(std::distance(ma.begin(), ma.end()), size_a * size_b * size_c);
375 
376  size_b = DimensionSize<DimensionB>(15);
377  ma.resize(size_b);
378  ASSERT_EQ(ma.dimension<DimensionA>(), size_a);
379  ASSERT_EQ(ma.dimension<DimensionB>(), size_b);
380  ASSERT_EQ(ma.dimension<DimensionC>(), size_c);
381  ASSERT_EQ(std::distance(ma.begin(), ma.end()), size_a * size_b * size_c);
382 
383  size_c = DimensionSize<DimensionC>(25);
384  ma.resize(size_c);
385  ASSERT_EQ(ma.dimension<DimensionA>(), size_a);
386  ASSERT_EQ(ma.dimension<DimensionB>(), size_b);
387  ASSERT_EQ(ma.dimension<DimensionC>(), size_c);
388  ASSERT_EQ(std::distance(ma.begin(), ma.end()), size_a * size_b * size_c);
389 }
390 
391 TEST_F(MultiArrayTest, test_three_dimension_resize_multiple_args)
392 {
393  DimensionSize<DimensionA> size_a(10);
394  DimensionSize<DimensionB> size_b(20);
395  DimensionSize<DimensionC> size_c(30);
396 
398  size_a = DimensionSize<DimensionA>(5);
399  size_b = DimensionSize<DimensionB>(15);
400  ma.resize(size_a, size_b);
401  ASSERT_EQ(std::distance(ma.begin(), ma.end()), size_a * size_b * size_c);
402 
403  size_b = DimensionSize<DimensionB>(20);
404  size_c = DimensionSize<DimensionC>(5);
405  ma.resize(size_b, size_c);
406  ASSERT_EQ(std::distance(ma.begin(), ma.end()), size_a * size_b * size_c);
407 }
408 
409 TEST_F(MultiArrayTest, test_three_dimension_data_size)
410 {
411  DimensionSize<DimensionA> size_a(10);
412  DimensionSize<DimensionB> size_b(20);
413  DimensionSize<DimensionC> size_c(30);
414 
416  ASSERT_EQ(ma.data_size(), size_a * size_b * size_c);
417 }
418 
419 TEST_F(MultiArrayTest, test_three_dimension_equal_operator)
420 {
421  DimensionSize<DimensionA> size_a(10);
422  DimensionSize<DimensionB> size_b(20);
423  DimensionSize<DimensionB> size_b_2(30);
424  DimensionSize<DimensionC> size_c(30);
425  DimensionSize<DimensionC> size_c_2(20);
426 
429  TestMultiArray<unsigned, DimensionA, DimensionB, DimensionC> ma_3( size_a, size_b_2, size_c_2);
430  ASSERT_EQ(ma_1, ma_2);
431 
432  // check dirrefent dimensions (but same overall size)
433  ASSERT_EQ(ma_1.data_size(), ma_3.data_size());
434  ASSERT_FALSE(ma_1 == ma_3);
435 
436  // change the data
438  ASSERT_FALSE(ma_1 == ma_2);
439 }
440 
441 TEST_F(MultiArrayTest, test_has_dimension)
442 {
444  static_assert(std::is_same<typename has_dimension<TestType1d, DimensionA>::type, std::true_type>::value, "expecting true");
445  static_assert(std::is_same<typename has_dimension<TestType1d, DimensionB>::type, std::false_type>::value, "expecting false");
446  typedef MultiArray<std::allocator<unsigned>, unsigned, TestMultiArrayMixin, DimensionA, DimensionB> TestType2d;
447  static_assert(std::is_same<typename has_dimension<TestType2d, DimensionA>::type, std::true_type>::value, "expecting true");
448  static_assert(std::is_same<typename has_dimension<TestType2d, DimensionB>::type, std::true_type>::value, "expecting true");
449  static_assert(std::is_same<typename has_dimension<TestType2d, DimensionC>::type, std::false_type>::value, "expecting false");
450 }
451 
452 TEST_F(MultiArrayTest, test_has_exact_dimensions)
453 {
455  typedef MultiArray<std::allocator<unsigned>, unsigned, TestMultiArrayMixin, DimensionA, DimensionB> TestType2d;
456 
457  // 1D
458  static_assert(std::is_same<typename has_exact_dimensions<TestType1d, DimensionA, DimensionB>::type, std::false_type>::value, "expecting false");
459  static_assert(std::is_same<typename has_exact_dimensions<TestType1d, DimensionB>::type, std::false_type>::value, "expecting false");
460  static_assert(std::is_same<typename has_exact_dimensions<TestType1d, DimensionA>::type, std::true_type>::value, "expecting true");
461 
462  // 2d
464  ASSERT_TRUE(r);
465  static_assert(std::is_same<typename has_exact_dimensions<TestType2d, DimensionB, DimensionA>::type, std::false_type>::value, "expecting false");
466  static_assert(std::is_same<typename has_exact_dimensions<TestType2d, DimensionB>::type, std::false_type>::value, "expecting false");
467  static_assert(std::is_same<typename has_exact_dimensions<TestType2d, DimensionA, DimensionB, DimensionC>::type, std::false_type>::value, "expecting false");
468  static_assert(std::is_same<typename has_exact_dimensions<TestType2d, DimensionA, DimensionB>::type, std::true_type>::value, "expecting true");
469 }
470 
471 } // namespace test
472 } // namespace astrotypes
473 } // namespace pss
A tagged dimensionIndex variable.
Defines a contiguous range over dimension in index.
Definition: DimensionSpan.h:41
std::size_t data_size() const
the total size of data in all dimensions
TEST_F(MultiArrayTest, test_single_dimension_size)
An instantiation of the MutliArray template for unit tests.
return true if the Dimensions provided match exactly those of the structure T (including order) ...
Definition: TypeTraits.h:107
A compile time dimesion tagging of size_t.
Definition: DimensionSize.h:39
return true if the Dimension is represented in the structure
Definition: TypeTraits.h:71
template classes to specify multiple dimension arrays with explicit dimension types ...
Definition: MultiArray.h:42
std::enable_if< std::is_same< Dim, Dimensions... >::value, DimensionSize< Dimensions... > >::type dimension() const