1 #include <fstream>
2 #include <sstream>
3 #include <cstdio>
4 #include <cxxtest/TestSuite.h>
5 #include <libgeodecomp/geometry/streak.h>
6 #include <libgeodecomp/misc/apitraits.h>
7 #include <libgeodecomp/storage/grid.h>
8 #include <libgeodecomp/storage/displacedgrid.h>
9 #include <libgeodecomp/misc/testcell.h>
10 
11 #define GRIDWIDTH 4
12 #define GRIDHEIGHT 5
13 
14 double edge = 0;
15 
16 class MyDummyCell
17 {
18 public:
19     class API :
20         public LibGeoDecomp::APITraits::HasSoA
21     {};
22 
23     explicit MyDummyCell(const int x = 0, const double y = 0, const char z = 0) :
x(x)24         x(x),
25         y(y),
26         z(z)
27     {}
28 
29     inline bool operator==(const MyDummyCell& other)
30     {
31         return
32             (x == other.x) &&
33             (y == other.y) &&
34             (z == other.z);
35     }
36 
37     int x;
38     double y;
39     char z;
40 };
41 
42 LIBFLATARRAY_REGISTER_SOA(MyDummyCell, ((int)(x))((double)(y))((char)(z)) )
43 
44 using namespace LibGeoDecomp;
45 
46 namespace LibGeoDecomp {
47 
48 /*
49  * testGrid is
50  *     x=0         x=3
51  * y=0 200 201 202 203
52  *     204 205 206 207
53  *     208 209 210 211
54  *     212 213 214 215
55  * y=4 216 217 218 219
56  */
57 class GridTest : public CxxTest::TestSuite
58 {
59     Grid<TestCell<2> > *testGrid;
60 
61 public:
62 
setUp()63     void setUp()
64     {
65         testGrid = new Grid<TestCell<2> >(Coord<2>(GRIDWIDTH, GRIDHEIGHT));
66 
67         int num = 200;
68         for (int y = 0; y < testGrid->getDimensions().y(); y++) {
69             for (int x = 0; x < testGrid->getDimensions().x(); x++) {
70                 (*testGrid)[Coord<2>(x, y)] =
71                     TestCell<2>(Coord<2>(x, y), testGrid->getDimensions());
72                 (*testGrid)[Coord<2>(x, y)].testValue =  num++;
73             }
74         }
75     }
76 
tearDown()77     void tearDown()
78     {
79         delete testGrid;
80     }
81 
testDefaultConstructor()82     void testDefaultConstructor()
83     {
84         Grid<TestCell<2> > g;
85         TS_ASSERT_EQUALS(0, (int)g.getDimensions().x());
86         TS_ASSERT_EQUALS(0, (int)g.getDimensions().y());
87     }
88 
testCopyConstructorFromGridBase()89     void testCopyConstructorFromGridBase()
90     {
91         Grid<int> a;
92         Grid<int> b(Coord<2>(10, 5), 5);
93         GridBase<int, 2>& base = b;
94         a = Grid<int>(base);
95         TS_ASSERT_EQUALS(a, b);
96     }
97 
testConstructorDefaultInit()98     void testConstructorDefaultInit()
99     {
100         Grid<double> g(Coord<2>(10, 12), 14.16, 47.11);
101         TS_ASSERT_EQUALS(Coord<2>(10, 12), g.getDimensions());
102         TS_ASSERT_EQUALS(14.16, g[5][6]);
103         TS_ASSERT_EQUALS(47.11, g[Coord<2>(-1, -1)]);
104     }
105 
testMultiDimensionalConstructor()106     void testMultiDimensionalConstructor()
107     {
108         Coord<3> dim(3, 4, 5);
109         Grid<double, Topologies::Torus<3>::Topology > g(dim);
110         g.getEdgeCell() = -1;
111         g[Coord<3>(2, 1, 1)] = 1;
112         g[Coord<3>(-1, 27, -2)] = 5;
113 
114         TS_ASSERT_EQUALS(dim, g.getDimensions());
115         TS_ASSERT_EQUALS(-1, g.getEdgeCell());
116         TS_ASSERT_EQUALS(1, g[Coord<3>(-1, 1, 1)]);
117         TS_ASSERT_EQUALS(5, g[Coord<3>(2, 3, 3)]);
118     }
119 
testOperatorEqual1()120     void testOperatorEqual1()
121     {
122         int width = testGrid->getDimensions().x();
123         int height = testGrid->getDimensions().y();
124         double deltaTemp = 42.0;
125         Coord<2> changedCoord(0, 4);
126 
127         Grid<TestCell<2> > other(Coord<2>(width, height));
128         TS_ASSERT(!other[4][2].isValid);
129         for(int x = 0; x < width; x++)
130             for(int y = 0; y < height; y++)
131                 other.cellMatrix[y][x] = testGrid->cellMatrix[y][x];
132 
133         TS_ASSERT(*testGrid == other);
134 
135         other[changedCoord].testValue += deltaTemp;
136         TS_ASSERT_EQUALS(
137             other[changedCoord].testValue,
138             (*testGrid)[changedCoord].testValue + deltaTemp);
139         TS_ASSERT(*testGrid != other);
140     }
141 
testOperatorEqual2()142     void testOperatorEqual2()
143     {
144         Grid<TestCell<2> > a(Coord<2>(0, 0));
145         Grid<TestCell<2> > b(Coord<2>(0, 0));
146         TS_ASSERT_EQUALS(a, b);
147     }
148 
testCopyConstructor()149     void testCopyConstructor()
150     {
151         Grid<int> a1(Coord<2>(200, 100));
152         for (int i = 0; i < 100; i++) {
153             for (int j = 0; j < 200; j++) {
154                 a1[Coord<2>(j, i)] = i * 200 + j;
155             }
156         }
157 
158         Grid<int> a2;
159         a2 = a1;
160         TS_ASSERT_EQUALS(a1, a1);
161         TS_ASSERT_EQUALS(a1, a2);
162 
163         a2[Coord<2>(0, 0)] = 4711;
164         TS_ASSERT_DIFFERS(a1, a2);
165     }
166 
testOperatorSquareBracketsOfCoord()167     void testOperatorSquareBracketsOfCoord()
168     {
169         (*testGrid)[Coord<2>(2, 3)].testValue = 47;
170         TS_ASSERT_EQUALS((*testGrid)[Coord<2>(2, 3)].testValue, 47);
171         (*testGrid)[Coord<2>(2, 3)].testValue = 11;
172         TS_ASSERT_EQUALS((*testGrid)[Coord<2>(2, 3)].testValue, 11);
173     }
174 
testResize()175     void testResize()
176     {
177         Grid<int> g(Coord<2>(64, 20));
178         TS_ASSERT_EQUALS(Coord<2>(64, 20), g.getDimensions());
179         g.resize(Coord<2>(12, 34));
180         TS_ASSERT_EQUALS(Coord<2>(12, 34), g.getDimensions());
181     }
182 
testGetNeighborhood()183     void testGetNeighborhood()
184     {
185         CoordMap<TestCell<2> > hood = testGrid->getNeighborhood(Coord<2>(1,2));
186 
187         TS_ASSERT_EQUALS(hood[Coord<2>( 0, -1)].testValue, 205);
188 
189         TS_ASSERT_EQUALS(hood[Coord<2>(-1,  0)].testValue, 208);
190         TS_ASSERT_EQUALS(hood[Coord<2>( 0,  0)].testValue, 209);
191         TS_ASSERT_EQUALS(hood[Coord<2>( 1,  0)].testValue, 210);
192 
193         TS_ASSERT_EQUALS(hood[Coord<2>( 0,  1)].testValue, 213);
194     }
195 
testGetNeighborhoodReferenceReturn()196     void testGetNeighborhoodReferenceReturn()
197     {
198         CoordMap<TestCell<2> > hood = testGrid->getNeighborhood(Coord<2>(1,2));
199         /* We need to use absolute coordinates for testGrid, but relative
200          * coordinates for the neighbourhood map "hood"
201          */
202 
203         TS_ASSERT_EQUALS((*testGrid)[Coord<2>(1,1)], hood[Coord<2>( 0,-1)])
204 
205         TS_ASSERT_EQUALS((*testGrid)[Coord<2>(0,2)], hood[Coord<2>(-1, 0)])
206         TS_ASSERT_EQUALS((*testGrid)[Coord<2>(1,2)], hood[Coord<2>( 0, 0)])
207         TS_ASSERT_EQUALS((*testGrid)[Coord<2>(2,2)], hood[Coord<2>( 1, 0)])
208 
209         TS_ASSERT_EQUALS((*testGrid)[Coord<2>(1,3)], hood[Coord<2>( 0, 1)])
210     }
211 
testGetNeighborhoodInUpperRightCorner()212     void testGetNeighborhoodInUpperRightCorner()
213     {
214         CoordMap<TestCell<2> > hood = testGrid->getNeighborhood(Coord<2>(GRIDWIDTH-1, 0));
215 
216         TS_ASSERT_EQUALS(hood[Coord<2>( 0, -1)].testValue,
217                          TestCell<2>::defaultValue());
218 
219         TS_ASSERT_EQUALS(hood[Coord<2>(-1,  0)].testValue, 202);
220         TS_ASSERT_EQUALS(hood[Coord<2>( 0,  0)].testValue, 203);
221         TS_ASSERT_EQUALS(hood[Coord<2>( 1,  0)].testValue,
222                          TestCell<2>::defaultValue());
223 
224         TS_ASSERT_EQUALS(hood[Coord<2>( 0,  1)].testValue, 207);
225     }
226 
testGetSetManyCells()227     void testGetSetManyCells()
228     {
229 	TestCell<2> cells[2];
230 	testGrid->get(Streak<2>(Coord<2>(1, 3), 3), cells);
231 
232 	for (int i = 0; i < 2; ++i) {
233 	    TS_ASSERT_EQUALS(cells[i], testGrid->get(Coord<2>(i + 1, 3)));
234 	}
235 
236 	for (int i = 0; i < 2; ++i) {
237             cells[i].testValue = i + 1234;
238         }
239         testGrid->set(Streak<2>(Coord<2>(1, 3), 3), cells);
240 
241 	for (int i = 0; i < 2; ++i) {
242 	    TS_ASSERT_EQUALS(cells[i], testGrid->get(Coord<2>(i + 1, 3)));
243 	}
244     }
245 
testToString()246     void testToString()
247     {
248         Grid<int> fooBar(Coord<2>(3, 2), 4711);
249         // set edge cell...
250         fooBar[Coord<2>(-1, -1)] = 2701;
251         // ...and two others
252         fooBar[Coord<2>( 1,  0)] = 19;
253         fooBar[Coord<2>( 2,  1)] = 81;
254         std::string expected =
255             "Grid<2>(\n"
256             "boundingBox: CoordBox<2>(origin: (0, 0), dimensions: (3, 2))\n"
257             "edgeCell:\n"
258             "2701\n"
259             "Coord(0, 0):\n"
260             "4711\n"
261             "Coord(1, 0):\n"
262             "19\n"
263             "Coord(2, 0):\n"
264             "4711\n"
265             "Coord(0, 1):\n"
266             "4711\n"
267             "Coord(1, 1):\n"
268             "4711\n"
269             "Coord(2, 1):\n"
270             "81\n"
271             ")";
272         TS_ASSERT_EQUALS(fooBar.toString(), expected);
273     }
274 
testEdgeCell()275     void testEdgeCell()
276     {
277         Grid<int> fooBar(Coord<2>(12, 34), 56, 78);
278         TS_ASSERT_EQUALS(fooBar.edgeCell, 78);
279         TS_ASSERT_EQUALS(fooBar[Coord<2>(-1, -1)], 78);
280 
281         fooBar[Coord<2>(-1, -1)] = 90;
282         TS_ASSERT_EQUALS(fooBar.edgeCell, 90);
283         TS_ASSERT_EQUALS(fooBar[Coord<2>(-1, -1)], 90);
284 
285         fooBar.edgeCell = 10;
286         TS_ASSERT_EQUALS(fooBar.edgeCell, 10);
287         TS_ASSERT_EQUALS(fooBar[Coord<2>(-1, -1)], 10);
288     }
289 
testFill2D()290     void testFill2D()
291     {
292         CoordBox<2> insert(Coord<2>(10, 20), Coord<2>(4, 7));
293         Coord<2> dim(40, 70);
294 
295         Grid<int> g(dim, -1);
296         g.fill(insert, 2);
297 
298 
299         for (int y = 0; y < dim.y(); ++y) {
300             for (int x = 0; x < dim.x(); ++x) {
301                 Coord<2> c = Coord<2>(x, y);
302                 int expected = -1;
303                 if (insert.inBounds(c)) {
304                     expected = 2;
305                 }
306 
307                 TS_ASSERT_EQUALS(expected, g[c]);
308             }
309         }
310     }
311 
testFill3D()312     void testFill3D()
313     {
314         CoordBox<3> insert(Coord<3>(10, 20, 15), Coord<3>(4, 7, 5));
315         Coord<3> dim(40, 70, 30);
316 
317         Grid<int, Topologies::Cube<3>::Topology> g(dim, -1);
318         g.fill(insert, 2);
319 
320 
321         for (int z = 0; z < dim.z(); ++z) {
322             for (int y = 0; y < dim.y(); ++y) {
323                 for (int x = 0; x < dim.x(); ++x) {
324                     Coord<3> c = Coord<3>(x, y, z);
325                     int expected = -1;
326                     if (insert.inBounds(c)) {
327                         expected = 2;
328                     }
329 
330                     TS_ASSERT_EQUALS(expected, g[c]);
331                 }
332             }
333         }
334     }
335 
testDefaultTopology()336     void testDefaultTopology()
337     {
338         Grid<int> g(Coord<2>(3, 4), 10, 11);
339         // in-bounds accesses
340         TS_ASSERT_EQUALS(g[Coord<2>( 0,  0)], 10);
341         TS_ASSERT_EQUALS(g[Coord<2>( 2,  0)], 10);
342         TS_ASSERT_EQUALS(g[Coord<2>( 0,  3)], 10);
343         TS_ASSERT_EQUALS(g[Coord<2>( 2,  3)], 10);
344 
345         // out-of-bounds accesses should yield edge cell
346         TS_ASSERT_EQUALS(g[Coord<2>( 0,  4)], 11);
347         TS_ASSERT_EQUALS(g[Coord<2>( 0, -1)], 11);
348         TS_ASSERT_EQUALS(g[Coord<2>( 3,  0)], 11);
349         TS_ASSERT_EQUALS(g[Coord<2>(-1,  0)], 11);
350     }
351 
trans(const int & x,const int & dimension)352     inline int trans(const int& x, const int& dimension)
353     {
354         return (x + dimension) % dimension;
355     }
356 
testTorusTopology()357     void testTorusTopology()
358     {
359         Grid<int, Topologies::Torus<2>::Topology> g(Coord<2>(3, 4), 0, -1);
360         for (int y = 0; y < 4; ++y) {
361             for (int x = 0; x < 3; ++x) {
362                 g[Coord<2>(x, y)] = y * 10 + x;
363             }
364         }
365 
366         // in-bounds accesses
367         TS_ASSERT_EQUALS(g[Coord<2>( 0,  0)],  0);
368         TS_ASSERT_EQUALS(g[Coord<2>( 2,  0)],  2);
369         TS_ASSERT_EQUALS(g[Coord<2>( 0,  3)], 30);
370         TS_ASSERT_EQUALS(g[Coord<2>( 2,  3)], 32);
371 
372         // out-of-bounds accesses should not yield edge cell
373         TS_ASSERT_EQUALS(g[Coord<2>( 0,  4)],  0);
374         TS_ASSERT_EQUALS(g[Coord<2>( 0, -1)], 30);
375         TS_ASSERT_EQUALS(g[Coord<2>( 3,  0)],  0);
376         TS_ASSERT_EQUALS(g[Coord<2>(-1,  0)],  2);
377         TS_ASSERT_EQUALS(g[Coord<2>(47, 69)], 12);
378     }
379 
testFill3d()380     void testFill3d()
381     {
382         Coord<3> dim(3, 4, 5);
383         Grid<int, Topologies::Cube<3>::Topology> g(dim, 47, 11);
384         TS_ASSERT_EQUALS(g[Coord<3>(-1, 0, 0)],  11);
385 
386         for (int z=0; z < dim.z(); ++z) {
387             for (int y=0; y < dim.y(); ++y) {
388                 for (int x=0; x < dim.x(); ++x)  {
389                     TS_ASSERT_EQUALS(g[Coord<3>(x, y, z)], 47);
390                 }
391             }
392         }
393     }
394 
testCompare()395     void testCompare()
396     {
397         Coord<2> dim(5, 4);
398         Grid<int> g1(dim, 4);
399         Grid<int> g2(dim, 9);
400         DisplacedGrid<int> g3(CoordBox<2>(Coord<2>(), dim), 4);
401         DisplacedGrid<int> g4(CoordBox<2>(Coord<2>(), dim), 9);
402         DisplacedGrid<int> g5(CoordBox<2>(Coord<2>(), Coord<2>(5, 5)), 9);
403 
404         TS_ASSERT(g1 != g2);
405         TS_ASSERT(g1 == g3);
406         TS_ASSERT(g1 != g4);
407         TS_ASSERT(g1 != g5);
408 
409         TS_ASSERT(g2 != g3);
410         TS_ASSERT(g2 == g4);
411         TS_ASSERT(g2 != g5);
412     }
413 
testLoadSaveMember()414     void testLoadSaveMember()
415     {
416         // basic setup:
417         Selector<MyDummyCell> xSelector(&MyDummyCell::x, "x");
418         Selector<MyDummyCell> ySelector(&MyDummyCell::y, "y");
419         Selector<MyDummyCell> zSelector(&MyDummyCell::z, "z");
420 
421         Coord<2> dim(40, 20);
422         Grid<MyDummyCell, Topologies::Cube<2>::Topology> grid(dim);
423         for (int y = 0; y < dim.y(); ++y) {
424             for (int x = 0; x < dim.x(); ++x) {
425                 grid[Coord<2>(x, y)] = MyDummyCell(x, y, 13);
426             }
427         }
428 
429         Region<2> region;
430         region << Streak<2>(Coord<2>( 0,  0), 10)
431                << Streak<2>(Coord<2>(10, 10), 20)
432                << Streak<2>(Coord<2>(30, 19), 40);
433 
434         std::vector<int   > xVector(region.size(), -1);
435         std::vector<double> yVector(region.size(), -1);
436         std::vector<char  > zVector(region.size(), -1);
437 
438         grid.saveMember(&xVector[0], xSelector, region);
439         grid.saveMember(&yVector[0], ySelector, region);
440         grid.saveMember(&zVector[0], zSelector, region);
441 
442         Region<2>::Iterator cursor = region.begin();
443 
444         // test whether grid data is accurately copied back:
445         for (std::size_t i = 0; i < region.size(); ++i) {
446             TS_ASSERT_EQUALS(xVector[i], cursor->x());
447             TS_ASSERT_EQUALS(yVector[i], cursor->y());
448             TS_ASSERT_EQUALS(zVector[i], 13);
449             ++cursor;
450         }
451 
452         // modify vectors and copy back to grid:
453         for (std::size_t i = 0; i < region.size(); ++i) {
454             xVector[i] = 1000 + i;
455             yVector[i] = 2000 + i;
456             zVector[i] = i;
457         }
458 
459         grid.loadMember(&xVector[0], xSelector, region);
460         grid.loadMember(&yVector[0], ySelector, region);
461         grid.loadMember(&zVector[0], zSelector, region);
462 
463         int counter = 0;
464         for (Region<2>::Iterator i = region.begin(); i != region.end(); ++i) {
465             TS_ASSERT_EQUALS(grid[*i], MyDummyCell(1000 + counter, 2000 + counter, counter));
466             ++counter;
467         }
468     }
469 };
470 
471 }
472