Line data Source code
1 : #include "doctest/doctest.h"
2 :
3 : #include "CartesianIndices.h"
4 :
5 : #include <iostream>
6 : #include <sstream>
7 : #include <vector>
8 : #include "spdlog/fmt/fmt.h"
9 : #include "spdlog/fmt/bundled/ranges.h"
10 :
11 : TEST_SUITE_BEGIN("CartesianIndices");
12 :
13 : using namespace elsa;
14 :
15 : namespace doctest
16 : {
17 : template <>
18 : struct StringMaker<CartesianIndices> {
19 : static String convert(const CartesianIndices& value)
20 0 : {
21 0 : return fmt::format("{}", value).c_str();
22 0 : }
23 : };
24 : template <typename T>
25 : struct StringMaker<std::vector<T>> {
26 : static String convert(const std::vector<T>& value)
27 : {
28 : return fmt::format("{}", value).c_str();
29 : }
30 : };
31 : template <>
32 : struct StringMaker<IndexVector_t> {
33 : static String convert(const IndexVector_t& value)
34 0 : {
35 0 : Eigen::IOFormat format(4, 0, ", ", "", "", "", "[", "]");
36 0 : std::stringstream stream;
37 0 : stream << value.format(format);
38 0 : return stream.str().c_str();
39 0 : }
40 : };
41 : } // namespace doctest
42 :
43 : TEST_CASE("Begin and End iterator comparison")
44 2 : {
45 2 : GIVEN("a 1D grid")
46 2 : {
47 1 : const CartesianIndices grid(std::vector<int>{5});
48 :
49 1 : CAPTURE(grid);
50 :
51 1 : auto begin = grid.begin();
52 1 : auto end = grid.end();
53 :
54 1 : CHECK_NE(begin, end);
55 1 : CHECK_EQ(end, end);
56 1 : CHECK_EQ(begin, begin);
57 :
58 1 : begin += 5;
59 :
60 1 : CAPTURE(*begin);
61 1 : CAPTURE(*end);
62 1 : CHECK_EQ(begin, end);
63 1 : }
64 :
65 2 : GIVEN("a 2D grid")
66 2 : {
67 1 : const CartesianIndices grid(std::vector<int>{5, 5});
68 :
69 1 : CAPTURE(grid);
70 :
71 1 : auto begin = grid.begin();
72 1 : auto end = grid.end();
73 :
74 1 : CHECK_NE(begin, end);
75 1 : CHECK_EQ(end, end);
76 1 : CHECK_EQ(begin, begin);
77 :
78 1 : begin += 25;
79 :
80 1 : CAPTURE(*begin);
81 1 : CAPTURE(*end);
82 1 : CHECK_EQ(begin, end);
83 1 : }
84 2 : }
85 :
86 : TEST_CASE("Construct 1D")
87 7 : {
88 7 : const CartesianIndices grid(std::vector<int>{5});
89 :
90 7 : CAPTURE(grid);
91 :
92 7 : THEN("The sizes are correct")
93 7 : {
94 1 : CHECK_EQ(grid.dims(), 1);
95 1 : CHECK_EQ(grid.size(), 5);
96 1 : }
97 :
98 7 : THEN("The first and last coordinate are correct")
99 7 : {
100 1 : CHECK_EQ(grid.first(), IndexVector_t({{0}}));
101 1 : CHECK_EQ(grid.last(), IndexVector_t({{5}}));
102 1 : }
103 :
104 7 : WHEN("iterating over the grid using an indces")
105 7 : {
106 1 : auto begin = grid.begin();
107 6 : for (int i = 0; i < grid.size(); ++i) {
108 5 : CHECK_EQ(begin[i], IndexVector_t({{i}}));
109 5 : }
110 1 : }
111 :
112 7 : WHEN("iterating over the grid")
113 7 : {
114 1 : auto begin = grid.begin();
115 1 : auto end = grid.end();
116 :
117 1 : CHECK_NE(begin, end);
118 :
119 1 : auto pos = 0;
120 6 : for (; begin != end; ++begin) {
121 5 : CHECK_EQ(*begin, IndexVector_t({{pos++}}));
122 5 : }
123 :
124 1 : CHECK_EQ(pos, 5);
125 1 : CHECK_EQ(begin, end);
126 1 : }
127 :
128 7 : WHEN("increment and decrement iterator")
129 7 : {
130 1 : auto begin = grid.begin();
131 :
132 1 : CHECK_EQ(*begin, IndexVector_t({{0}}));
133 :
134 : // Prefix increment
135 1 : ++begin;
136 1 : CHECK_EQ(*begin, IndexVector_t({{1}}));
137 :
138 : // Postfix increment
139 1 : begin++;
140 1 : CHECK_EQ(*begin, IndexVector_t({{2}}));
141 :
142 : // Prefix decrement
143 1 : --begin;
144 1 : CHECK_EQ(*begin, IndexVector_t({{1}}));
145 :
146 : // Postfix decrement
147 1 : begin--;
148 1 : CHECK_EQ(*begin, IndexVector_t({{0}}));
149 1 : CHECK_EQ(*begin, *grid.begin());
150 1 : }
151 :
152 7 : WHEN("advance by n")
153 7 : {
154 1 : auto begin = grid.begin();
155 :
156 1 : begin += 0;
157 1 : CHECK_EQ(*begin, IndexVector_t({{0}}));
158 :
159 1 : begin += 2;
160 1 : CHECK_EQ(*begin, IndexVector_t({{2}}));
161 :
162 1 : begin -= 0;
163 1 : CHECK_EQ(*begin, IndexVector_t({{2}}));
164 :
165 1 : begin -= 2;
166 1 : CHECK_EQ(*begin, *grid.begin());
167 1 : }
168 :
169 7 : WHEN("Calculating distance")
170 7 : {
171 1 : auto begin = grid.begin();
172 :
173 1 : CHECK_EQ(begin - begin, 0);
174 1 : CHECK_EQ(std::distance(begin, begin), 0);
175 :
176 1 : auto iter = begin;
177 1 : ++iter;
178 :
179 1 : CHECK_EQ(begin - iter, -1);
180 1 : CHECK_EQ(std::distance(iter, begin), -1);
181 :
182 1 : CHECK_EQ(iter - begin, 1);
183 1 : CHECK_EQ(std::distance(begin, iter), 1);
184 :
185 1 : iter += grid.size() - 1;
186 1 : CHECK_EQ(iter - begin, grid.size());
187 1 : }
188 7 : }
189 :
190 : TEST_CASE("Construct 1D given start and end")
191 4 : {
192 4 : CartesianIndices grid(std::vector<int>{5}, std::vector<int>{10});
193 :
194 4 : CAPTURE(grid);
195 4 : THEN("The sizes are correct")
196 4 : {
197 1 : CHECK_EQ(grid.dims(), 1);
198 1 : CHECK_EQ(grid.size(), 5);
199 1 : }
200 :
201 4 : THEN("The first and last coordinate are correct")
202 4 : {
203 1 : CHECK_EQ(grid.first(), IndexVector_t({{5}}));
204 1 : CHECK_EQ(grid.last(), IndexVector_t({{10}}));
205 1 : }
206 :
207 4 : WHEN("iterating over the grid")
208 4 : {
209 1 : auto begin = grid.begin();
210 1 : auto end = grid.end();
211 :
212 1 : CHECK_NE(begin, end);
213 :
214 1 : auto pos = 5;
215 6 : for (; begin != end; ++begin) {
216 5 : CHECK_EQ(*begin, IndexVector_t({{pos++}}));
217 5 : }
218 :
219 1 : CHECK_EQ(pos, 10);
220 1 : CHECK_EQ(begin, end);
221 1 : }
222 :
223 4 : WHEN("Calculating distance")
224 4 : {
225 1 : auto begin = grid.begin();
226 :
227 1 : CHECK_EQ(begin - begin, 0);
228 1 : CHECK_EQ(std::distance(begin, begin), 0);
229 :
230 1 : auto iter = begin;
231 1 : ++iter;
232 :
233 1 : CHECK_EQ(begin - iter, -1);
234 1 : CHECK_EQ(std::distance(iter, begin), -1);
235 :
236 1 : CHECK_EQ(iter - begin, 1);
237 1 : CHECK_EQ(std::distance(begin, iter), 1);
238 :
239 1 : iter += grid.size() - 1;
240 1 : CHECK_EQ(iter - begin, grid.size());
241 1 : }
242 4 : }
243 :
244 : TEST_CASE("Construct 2D")
245 7 : {
246 7 : const CartesianIndices grid(std::vector<int>{5, 7});
247 :
248 7 : CAPTURE(grid);
249 7 : THEN("The sizes are correct")
250 7 : {
251 1 : CHECK_EQ(grid.dims(), 2);
252 1 : CHECK_EQ(grid.size(), 5 * 7);
253 1 : }
254 :
255 7 : THEN("The first and last coordinate are correct")
256 7 : {
257 1 : CHECK_EQ(grid.first(), IndexVector_t({{0, 0}}));
258 1 : CHECK_EQ(grid.last(), IndexVector_t({{5, 7}}));
259 1 : }
260 :
261 7 : WHEN("iterating over the grid")
262 7 : {
263 1 : auto begin = grid.begin();
264 1 : auto end = grid.end();
265 :
266 1 : CHECK_NE(begin, end);
267 :
268 1 : auto pos = 0;
269 36 : for (; begin != end; ++begin) {
270 : // I don't really want to repeat the logic completely again, but as
271 : // long as we in total traverse the same amount as size() of the
272 : // grid, it should be fine
273 35 : ++pos;
274 35 : }
275 :
276 1 : CHECK_EQ(pos, grid.size());
277 1 : CHECK_EQ(begin, end);
278 1 : }
279 :
280 7 : WHEN("increment iterator")
281 7 : {
282 1 : auto begin = grid.begin();
283 1 : CHECK_EQ(*begin, IndexVector_t({{0, 0}}));
284 :
285 1 : THEN("Last dimension is incremented")
286 1 : {
287 1 : ++begin;
288 1 : CHECK_EQ(*begin, IndexVector_t({{0, 1}}));
289 :
290 1 : ++begin;
291 1 : CHECK_EQ(*begin, IndexVector_t({{0, 2}}));
292 1 : }
293 1 : }
294 :
295 7 : THEN("Iterating over all indices")
296 7 : {
297 1 : auto begin = grid.begin();
298 :
299 1 : auto x1 = 0;
300 1 : auto x2 = 0;
301 :
302 6 : for (int i = 0; i < 5; ++i) {
303 40 : for (int j = 0; j < 7; ++j) {
304 35 : CHECK_EQ(*begin, IndexVector_t({{x1, x2}}));
305 35 : ++begin;
306 35 : ++x2;
307 35 : }
308 5 : x2 = 0;
309 5 : ++x1;
310 5 : }
311 1 : }
312 :
313 7 : WHEN("advance by n")
314 7 : {
315 1 : auto begin = grid.begin();
316 :
317 1 : begin += 0;
318 1 : CHECK_EQ(*begin, IndexVector_t({{0, 0}}));
319 :
320 1 : begin += 2;
321 1 : CHECK_EQ(*begin, IndexVector_t({{0, 2}}));
322 :
323 1 : begin -= 0;
324 1 : CHECK_EQ(*begin, IndexVector_t({{0, 2}}));
325 :
326 1 : begin -= 2;
327 1 : CHECK_EQ(*begin, *grid.begin());
328 :
329 1 : begin += 7;
330 1 : CHECK_EQ(*begin, IndexVector_t({{1, 0}}));
331 :
332 1 : begin += 9;
333 1 : CHECK_EQ(*begin, IndexVector_t({{2, 2}}));
334 :
335 1 : begin -= 16;
336 1 : CHECK_EQ(*begin, IndexVector_t({{0, 0}}));
337 1 : }
338 :
339 7 : WHEN("Calculating distance")
340 7 : {
341 1 : auto begin = grid.begin();
342 :
343 1 : CHECK_EQ(begin - begin, 0);
344 1 : CHECK_EQ(std::distance(begin, begin), 0);
345 :
346 1 : auto iter = begin;
347 1 : ++iter;
348 :
349 1 : CHECK_EQ(begin - iter, -1);
350 1 : CHECK_EQ(std::distance(iter, begin), -1);
351 :
352 1 : CHECK_EQ(iter - begin, 1);
353 1 : CHECK_EQ(std::distance(begin, iter), 1);
354 :
355 1 : iter += grid.size() - 1;
356 1 : CHECK_EQ(iter - begin, grid.size());
357 1 : }
358 7 : }
359 :
360 : TEST_CASE("Construct 2D given start and end")
361 3 : {
362 3 : CartesianIndices grid(std::vector<int>{5, 7}, std::vector<int>{10, 12});
363 :
364 3 : CAPTURE(grid);
365 3 : THEN("The sizes are correct")
366 3 : {
367 1 : CHECK_EQ(grid.dims(), 2);
368 1 : CHECK_EQ(grid.size(), 5 * 5);
369 1 : }
370 :
371 3 : THEN("The first and last coordinate are correct")
372 3 : {
373 1 : CHECK_EQ(grid.first(), IndexVector_t({{5, 7}}));
374 1 : CHECK_EQ(grid.last(), IndexVector_t({{10, 12}}));
375 1 : }
376 :
377 3 : WHEN("iterating over the grid")
378 3 : {
379 1 : auto begin = grid.begin();
380 1 : auto end = grid.end();
381 :
382 1 : CHECK_NE(begin, end);
383 :
384 1 : auto pos = 0;
385 26 : for (; begin != end; ++begin) {
386 : // I don't really want to repeat the logic completely again, but as
387 : // long as we in total traverse the same amount as size() of the
388 : // grid, it should be fine
389 25 : ++pos;
390 25 : CAPTURE(*begin);
391 25 : CAPTURE(*end);
392 :
393 : // Protect against endless loops
394 25 : REQUIRE(pos < grid.size() + 1);
395 25 : }
396 :
397 1 : CHECK_EQ(pos, grid.size());
398 1 : CHECK_EQ(begin, end);
399 1 : }
400 3 : }
401 :
402 : TEST_CASE("Construct 3D")
403 6 : {
404 6 : const CartesianIndices grid(std::vector<int>{5, 7, 9});
405 :
406 6 : CAPTURE(grid);
407 6 : THEN("The sizes are correct")
408 6 : {
409 1 : CHECK_EQ(grid.dims(), 3);
410 1 : CHECK_EQ(grid.size(), 5 * 7 * 9);
411 1 : }
412 :
413 6 : THEN("The first and last coordinate are correct")
414 6 : {
415 1 : CHECK_EQ(grid.first(), IndexVector_t({{0, 0, 0}}));
416 1 : CHECK_EQ(grid.last(), IndexVector_t({{5, 7, 9}}));
417 1 : }
418 :
419 6 : WHEN("iterating over the grid")
420 6 : {
421 1 : auto begin = grid.begin();
422 1 : auto end = grid.end();
423 :
424 1 : CHECK_NE(begin, end);
425 :
426 1 : auto pos = 0;
427 316 : for (; begin != end; ++begin) {
428 : // I don't really want to repeat the logic completely again, but as
429 : // long as we in total traverse the same amount as size() of the
430 : // grid, it should be fine
431 315 : ++pos;
432 :
433 315 : CAPTURE(*begin);
434 315 : CAPTURE(*end);
435 :
436 : // Protect against endless loops
437 315 : REQUIRE(pos < grid.size() + 1);
438 315 : }
439 :
440 1 : CHECK_EQ(pos, grid.size());
441 1 : CHECK_EQ(begin, end);
442 1 : }
443 :
444 6 : THEN("Iterating over all indices")
445 6 : {
446 1 : auto begin = grid.begin();
447 :
448 1 : auto x1 = 0;
449 1 : auto x2 = 0;
450 1 : auto x3 = 0;
451 :
452 6 : for (int i = 0; i < 5; ++i) {
453 40 : for (int j = 0; j < 7; ++j) {
454 350 : for (int k = 0; k < 9; ++k) {
455 315 : CHECK_EQ(*begin, IndexVector_t({{x1, x2, x3}}));
456 315 : ++begin;
457 315 : ++x3;
458 315 : }
459 35 : x3 = 0;
460 35 : ++x2;
461 35 : }
462 5 : x2 = 0;
463 5 : ++x1;
464 5 : }
465 1 : }
466 :
467 6 : WHEN("advance by n")
468 6 : {
469 1 : auto begin = grid.begin();
470 :
471 1 : begin += 0;
472 1 : CHECK_EQ(*begin, IndexVector_t({{0, 0, 0}}));
473 :
474 1 : begin += 2;
475 1 : CHECK_EQ(*begin, IndexVector_t({{0, 0, 2}}));
476 :
477 1 : begin -= 0;
478 1 : CHECK_EQ(*begin, IndexVector_t({{0, 0, 2}}));
479 :
480 1 : begin -= 2;
481 1 : CHECK_EQ(*begin, *grid.begin());
482 :
483 1 : begin += 9;
484 1 : CHECK_EQ(*begin, IndexVector_t({{0, 1, 0}}));
485 :
486 1 : begin += 11;
487 1 : CHECK_EQ(*begin, IndexVector_t({{0, 2, 2}}));
488 :
489 1 : begin -= 20;
490 1 : CHECK_EQ(*begin, IndexVector_t({{0, 0, 0}}));
491 1 : }
492 :
493 6 : WHEN("Calculating distance")
494 6 : {
495 1 : auto begin = grid.begin();
496 :
497 1 : CHECK_EQ(begin - begin, 0);
498 1 : CHECK_EQ(std::distance(begin, begin), 0);
499 :
500 1 : auto iter = begin;
501 1 : ++iter;
502 :
503 1 : CHECK_EQ(begin - iter, -1);
504 1 : CHECK_EQ(std::distance(iter, begin), -1);
505 :
506 1 : CHECK_EQ(iter - begin, 1);
507 1 : CHECK_EQ(std::distance(begin, iter), 1);
508 :
509 1 : iter += grid.size() - 1;
510 1 : CHECK_EQ(iter - begin, grid.size());
511 1 : }
512 6 : }
513 :
514 : TEST_CASE("Construct 3D given start and end")
515 4 : {
516 4 : CartesianIndices grid(std::vector<int>{5, 7, 9}, std::vector<int>{10, 12, 14});
517 :
518 4 : CAPTURE(grid);
519 4 : THEN("The sizes are correct")
520 4 : {
521 1 : CHECK_EQ(grid.dims(), 3);
522 1 : CHECK_EQ(grid.size(), 5 * 5 * 5);
523 1 : }
524 :
525 4 : THEN("The first and last coordinate are correct")
526 4 : {
527 1 : CHECK_EQ(grid.first(), IndexVector_t({{5, 7, 9}}));
528 1 : CHECK_EQ(grid.last(), IndexVector_t({{10, 12, 14}}));
529 1 : }
530 :
531 4 : WHEN("iterating over the grid")
532 4 : {
533 1 : auto begin = grid.begin();
534 1 : auto end = grid.end();
535 :
536 1 : CHECK_NE(begin, end);
537 :
538 1 : auto pos = 0;
539 126 : for (; begin != end; ++begin) {
540 : // I don't really want to repeat the logic completely again, but as long as we
541 : // in total traverse the same amount as size() of the grid, it should be fine
542 125 : ++pos;
543 :
544 125 : CAPTURE(*begin);
545 125 : CAPTURE(*end);
546 :
547 : // Protect against endless loops
548 125 : REQUIRE(pos < grid.size() + 1);
549 125 : }
550 :
551 1 : CHECK_EQ(pos, grid.size());
552 1 : CHECK_EQ(begin, end);
553 1 : }
554 :
555 4 : WHEN("Calculating distance")
556 4 : {
557 1 : auto begin = grid.begin();
558 :
559 1 : CHECK_EQ(begin - begin, 0);
560 1 : CHECK_EQ(std::distance(begin, begin), 0);
561 :
562 1 : auto iter = begin;
563 1 : ++iter;
564 :
565 1 : CHECK_EQ(begin - iter, -1);
566 1 : CHECK_EQ(std::distance(iter, begin), -1);
567 :
568 1 : CHECK_EQ(iter - begin, 1);
569 1 : CHECK_EQ(std::distance(begin, iter), 1);
570 :
571 1 : iter += grid.size() - 1;
572 1 : CHECK_EQ(iter - begin, grid.size());
573 1 : }
574 4 : }
575 :
576 : TEST_CASE("Visit neighbours in 2D")
577 1 : {
578 1 : Eigen::IOFormat format(4, 0, ", ", "", "", "", "[", "]");
579 :
580 1 : auto cur = IndexVector_t({{2, 5}});
581 1 : auto lower = IndexVector_t({{2, 4}});
582 1 : auto upper = IndexVector_t({{3, 7}});
583 : // auto grid = CartesianIndices(lower, upper);
584 1 : auto grid = neighbours_in_slice(cur, 1);
585 :
586 1 : CHECK_EQ(lower, grid.first());
587 1 : CHECK_EQ(upper, grid.last());
588 :
589 1 : auto begin = grid.begin();
590 1 : auto end = grid.end();
591 :
592 1 : auto ypos = lower[1];
593 4 : for (; begin != end; ++begin) {
594 3 : CHECK_EQ(*begin, IndexVector_t({{cur[0], ypos}}));
595 3 : ++ypos;
596 3 : }
597 1 : }
598 :
599 : TEST_CASE("Visit neighbours in 2D")
600 1 : {
601 1 : Eigen::IOFormat format(4, 0, ", ", "", "", "", "[", "]");
602 :
603 1 : auto cur = IndexVector_t({{2, 5}});
604 1 : auto lower = IndexVector_t({{2, 4}});
605 1 : auto upper = IndexVector_t({{3, 7}});
606 : // auto grid = CartesianIndices(lower, upper);
607 1 : auto grid = neighbours_in_slice(cur, 1);
608 :
609 1 : CHECK_EQ(lower, grid.first());
610 1 : CHECK_EQ(upper, grid.last());
611 :
612 1 : auto begin = grid.begin();
613 1 : auto end = grid.end();
614 :
615 1 : auto ypos = lower[1];
616 4 : for (; begin != end; ++begin) {
617 3 : CHECK_EQ(*begin, IndexVector_t({{cur[0], ypos}}));
618 3 : ++ypos;
619 3 : }
620 1 : }
621 :
622 : TEST_CASE("Visit neighbours in 2D with bounds")
623 2 : {
624 2 : Eigen::IOFormat format(4, 0, ", ", "", "", "", "[", "]");
625 2 : WHEN("Having a start position at the lower border")
626 2 : {
627 1 : auto cur = IndexVector_t({{2, 1}});
628 1 : auto lower = IndexVector_t({{0, 0}});
629 1 : auto upper = IndexVector_t({{5, 5}});
630 :
631 1 : auto grid = neighbours_in_slice(cur, 2, 0, lower, upper);
632 :
633 1 : CHECK_EQ(grid.first(), IndexVector_t({{2, 0}}));
634 1 : CHECK_EQ(grid.last(), IndexVector_t({{3, 4}}));
635 :
636 1 : auto begin = grid.begin();
637 1 : auto end = grid.end();
638 :
639 1 : auto ypos = 0;
640 5 : for (; begin != end; ++begin) {
641 4 : CHECK_EQ(*begin, IndexVector_t({{cur[0], ypos}}));
642 4 : ++ypos;
643 4 : }
644 1 : }
645 :
646 2 : WHEN("Having a start position at the upper border")
647 2 : {
648 1 : auto cur = IndexVector_t({{2, 4}});
649 1 : auto lower = IndexVector_t({{0, 0}});
650 1 : auto upper = IndexVector_t({{5, 5}});
651 : // auto grid = CartesianIndices(lower, upper);
652 1 : auto grid = neighbours_in_slice(cur, 2, 0, lower, upper);
653 :
654 1 : CHECK_EQ(grid.first(), IndexVector_t({{2, 2}}));
655 1 : CHECK_EQ(grid.last(), IndexVector_t({{3, 5}}));
656 :
657 1 : auto begin = grid.begin();
658 1 : auto end = grid.end();
659 :
660 1 : auto ypos = 2;
661 4 : for (; begin != end; ++begin) {
662 3 : CHECK_EQ(*begin, IndexVector_t({{cur[0], ypos}}));
663 3 : ++ypos;
664 3 : }
665 1 : }
666 2 : }
667 :
668 : TEST_CASE("Test formatting")
669 5 : {
670 5 : WHEN("Creating a 1D CartesianIndices")
671 5 : {
672 1 : const CartesianIndices grid(std::vector<int>{5});
673 :
674 1 : CHECK_EQ(fmt::format("{}", grid), "(0:5)");
675 1 : }
676 :
677 5 : WHEN("Creating a 1D CartesianIndices, not starting at 0")
678 5 : {
679 1 : const CartesianIndices grid(std::vector<int>{3}, std::vector<int>{5});
680 :
681 1 : CHECK_EQ(fmt::format("{}", grid), "(3:5)");
682 1 : }
683 :
684 5 : WHEN("Creating a 2D CartesianIndices")
685 5 : {
686 1 : const CartesianIndices grid(std::vector<int>{5, 3});
687 :
688 1 : CHECK_EQ(fmt::format("{}", grid), "(0:5, 0:3)");
689 1 : }
690 :
691 5 : WHEN("Creating a 1D CartesianIndices, not starting at 0")
692 5 : {
693 1 : const CartesianIndices grid(std::vector<int>{3, 1}, std::vector<int>{5, 5});
694 :
695 1 : CHECK_EQ(fmt::format("{}", grid), "(3:5, 1:5)");
696 1 : }
697 :
698 5 : WHEN("Creating a 3D CartesianIndices")
699 5 : {
700 1 : const CartesianIndices grid(std::vector<int>{5, 3, 9});
701 :
702 1 : CHECK_EQ(fmt::format("{}", grid), "(0:5, 0:3, 0:9)");
703 1 : }
704 5 : }
705 :
706 : TEST_CASE("Relational operators")
707 6 : {
708 6 : GIVEN("a 1D grid")
709 6 : {
710 3 : const CartesianIndices grid(std::vector<int>{50});
711 :
712 3 : CAPTURE(grid);
713 :
714 3 : auto begin = grid.begin();
715 3 : auto end = grid.end();
716 :
717 3 : CAPTURE(*begin);
718 3 : CAPTURE(*end);
719 :
720 3 : WHEN("Taking some element in the middle of the grid")
721 3 : {
722 3 : auto mid = begin + 25;
723 :
724 3 : CAPTURE(*mid);
725 :
726 3 : THEN("It compare equal to begin + pos")
727 3 : {
728 1 : CHECK_EQ(mid, 25 + begin);
729 1 : CHECK_EQ(begin, mid - 25);
730 1 : }
731 :
732 3 : THEN("It behaves correctly for less then (equal)")
733 3 : {
734 1 : CHECK_LT(begin, mid);
735 1 : CHECK_LT(mid - 1, mid);
736 1 : CHECK_LE(mid - 1, mid);
737 1 : CHECK_LE(mid, mid);
738 1 : }
739 :
740 3 : THEN("It behaves correctly for less then (equal)")
741 3 : {
742 1 : CHECK_GT(mid, begin);
743 1 : CHECK_GT(1 + mid, mid);
744 1 : CHECK_GE(1 + mid, mid);
745 1 : CHECK_GE(mid, mid);
746 1 : }
747 3 : }
748 3 : }
749 :
750 6 : GIVEN("a 2D grid")
751 6 : {
752 3 : const CartesianIndices grid(std::vector<int>{10, 10});
753 :
754 3 : CAPTURE(grid);
755 :
756 3 : auto begin = grid.begin();
757 3 : auto end = grid.end();
758 :
759 3 : CAPTURE(*begin);
760 3 : CAPTURE(*end);
761 :
762 3 : WHEN("Taking some element in the middle of the grid")
763 3 : {
764 3 : auto mid = begin + 25;
765 :
766 3 : CAPTURE(*mid);
767 :
768 3 : THEN("It compare equal to begin + pos")
769 3 : {
770 1 : CHECK_EQ(mid, 25 + begin);
771 1 : CHECK_EQ(begin, mid - 25);
772 1 : }
773 :
774 3 : THEN("It behaves correctly for less then (equal)")
775 3 : {
776 1 : CHECK_LT(begin, mid);
777 1 : CHECK_LT(mid - 1, mid);
778 1 : CHECK_LE(mid - 1, mid);
779 1 : CHECK_LE(mid, mid);
780 1 : }
781 :
782 3 : THEN("It behaves correctly for less then (equal)")
783 3 : {
784 1 : CHECK_GT(mid, begin);
785 1 : CHECK_GT(1 + mid, mid);
786 1 : CHECK_GE(1 + mid, mid);
787 1 : CHECK_GE(mid, mid);
788 1 : }
789 3 : }
790 3 : }
791 6 : }
792 :
793 : TEST_SUITE_END();
|