]> gitweb.michael.orlitzky.com - spline3.git/blob - src/Tests/Cube.hs
Fix the Cube tests re: the 'tetrahedron' change.
[spline3.git] / src / Tests / Cube.hs
1 module Tests.Cube
2 where
3
4 import Prelude hiding (LT)
5
6 import Cardinal
7 import Comparisons
8 import Cube hiding (i, j, k)
9 import FunctionValues
10 import Misc (all_equal, disjoint)
11 import Tetrahedron (b0, b1, b2, b3, c, fv,
12 v0, v1, v2, v3, volume)
13
14
15 -- Quickcheck tests.
16
17 -- | The 'front_half_tetrahedra' and 'back_half_tetrahedra' should
18 -- have no tetrahedra in common.
19 prop_front_back_tetrahedra_disjoint :: Cube -> Bool
20 prop_front_back_tetrahedra_disjoint c =
21 disjoint (front_half_tetrahedra c) (back_half_tetrahedra c)
22
23
24 -- | The 'top_half_tetrahedra' and 'down_half_tetrahedra' should
25 -- have no tetrahedra in common.
26 prop_top_down_tetrahedra_disjoint :: Cube -> Bool
27 prop_top_down_tetrahedra_disjoint c =
28 disjoint (top_half_tetrahedra c) (down_half_tetrahedra c)
29
30
31 -- | The 'left_half_tetrahedra' and 'right_half_tetrahedra' should
32 -- have no tetrahedra in common.
33 prop_left_right_tetrahedra_disjoint :: Cube -> Bool
34 prop_left_right_tetrahedra_disjoint c =
35 disjoint (left_half_tetrahedra c) (right_half_tetrahedra c)
36
37
38 -- | Since the grid size is necessarily positive, all tetrahedra
39 -- (which comprise cubes of positive volume) must have positive volume
40 -- as well.
41 prop_all_volumes_positive :: Cube -> Bool
42 prop_all_volumes_positive cube =
43 null nonpositive_volumes
44 where
45 ts = tetrahedra cube
46 volumes = map volume ts
47 nonpositive_volumes = filter (<= 0) volumes
48
49 -- | In fact, since all of the tetrahedra are identical, we should
50 -- already know their volumes. There's 24 tetrahedra to a cube, so
51 -- we'd expect the volume of each one to be (1/24)*h^3.
52 prop_all_volumes_exact :: Cube -> Bool
53 prop_all_volumes_exact cube =
54 and [volume t ~~= (1/24)*(delta^(3::Int)) | t <- tetrahedra cube]
55 where
56 delta = h cube
57
58 -- | All tetrahedron should have their v0 located at the center of the cube.
59 prop_v0_all_equal :: Cube -> Bool
60 prop_v0_all_equal cube = (v0 t0) == (v0 t1)
61 where
62 t0 = head (tetrahedra cube) -- Doesn't matter which two we choose.
63 t1 = head $ tail (tetrahedra cube)
64
65
66 -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Note that the
67 -- third and fourth indices of c-t1 have been switched. This is
68 -- because we store the triangles oriented such that their volume is
69 -- positive. If T and T-tilde share \<v0,v1,v2\> and v3,v3-tilde point
70 -- in opposite directions, one of them has to have negative volume!
71 prop_c0120_identity1 :: Cube -> Bool
72 prop_c0120_identity1 cube =
73 c t0 0 1 2 0 ~= (c t0 0 0 2 1 + c t3 0 0 1 2) / 2
74 where
75 t0 = tetrahedron cube 0
76 t3 = tetrahedron cube 3
77
78
79 -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Repeats
80 -- 'prop_c0120_identity1' with tetrahedrons 1 and 2.
81 prop_c0120_identity2 :: Cube -> Bool
82 prop_c0120_identity2 cube =
83 c t1 0 1 2 0 ~= (c t1 0 0 2 1 + c t0 0 0 1 2) / 2
84 where
85 t0 = tetrahedron cube 0
86 t1 = tetrahedron cube 1
87
88 -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Repeats
89 -- 'prop_c0120_identity1' with tetrahedrons 1 and 2.
90 prop_c0120_identity3 :: Cube -> Bool
91 prop_c0120_identity3 cube =
92 c t2 0 1 2 0 ~= (c t2 0 0 2 1 + c t1 0 0 1 2) / 2
93 where
94 t1 = tetrahedron cube 1
95 t2 = tetrahedron cube 2
96
97 -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Repeats
98 -- 'prop_c0120_identity1' with tetrahedrons 2 and 3.
99 prop_c0120_identity4 :: Cube -> Bool
100 prop_c0120_identity4 cube =
101 c t3 0 1 2 0 ~= (c t3 0 0 2 1 + c t2 0 0 1 2) / 2
102 where
103 t2 = tetrahedron cube 2
104 t3 = tetrahedron cube 3
105
106
107 -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Repeats
108 -- 'prop_c0120_identity1' with tetrahedrons 4 and 5.
109 prop_c0120_identity5 :: Cube -> Bool
110 prop_c0120_identity5 cube =
111 c t5 0 1 2 0 ~= (c t5 0 0 2 1 + c t4 0 0 1 2) / 2
112 where
113 t4 = tetrahedron cube 4
114 t5 = tetrahedron cube 5
115
116 -- -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Repeats
117 -- -- 'prop_c0120_identity1' with tetrahedrons 5 and 6.
118 prop_c0120_identity6 :: Cube -> Bool
119 prop_c0120_identity6 cube =
120 c t6 0 1 2 0 ~= (c t6 0 0 2 1 + c t5 0 0 1 2) / 2
121 where
122 t5 = tetrahedron cube 5
123 t6 = tetrahedron cube 6
124
125
126 -- -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Repeats
127 -- -- 'prop_c0120_identity1' with tetrahedrons 6 and 7.
128 prop_c0120_identity7 :: Cube -> Bool
129 prop_c0120_identity7 cube =
130 c t7 0 1 2 0 ~= (c t7 0 0 2 1 + c t6 0 0 1 2) / 2
131 where
132 t6 = tetrahedron cube 6
133 t7 = tetrahedron cube 7
134
135
136 -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). See
137 -- 'prop_c0120_identity1'.
138 prop_c0210_identity1 :: Cube -> Bool
139 prop_c0210_identity1 cube =
140 c t0 0 2 1 0 ~= (c t0 0 1 1 1 + c t3 0 1 1 1) / 2
141 where
142 t0 = tetrahedron cube 0
143 t3 = tetrahedron cube 3
144
145
146 -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). See
147 -- 'prop_c0120_identity1'.
148 prop_c0300_identity1 :: Cube -> Bool
149 prop_c0300_identity1 cube =
150 c t0 0 3 0 0 ~= (c t0 0 2 0 1 + c t3 0 2 1 0) / 2
151 where
152 t0 = tetrahedron cube 0
153 t3 = tetrahedron cube 3
154
155
156 -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). See
157 -- 'prop_c0120_identity1'.
158 prop_c1110_identity :: Cube -> Bool
159 prop_c1110_identity cube =
160 c t0 1 1 1 0 ~= (c t0 1 0 1 1 + c t3 1 0 1 1) / 2
161 where
162 t0 = tetrahedron cube 0
163 t3 = tetrahedron cube 3
164
165
166 -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). See
167 -- 'prop_c0120_identity1'.
168 prop_c1200_identity1 :: Cube -> Bool
169 prop_c1200_identity1 cube =
170 c t0 1 2 0 0 ~= (c t0 1 1 0 1 + c t3 1 1 1 0) / 2
171 where
172 t0 = tetrahedron cube 0
173 t3 = tetrahedron cube 3
174
175
176 -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). See
177 -- 'prop_c0120_identity1'.
178 prop_c2100_identity1 :: Cube -> Bool
179 prop_c2100_identity1 cube =
180 c t0 2 1 0 0 ~= (c t0 2 0 0 1 + c t3 2 0 1 0) / 2
181 where
182 t0 = tetrahedron cube 0
183 t3 = tetrahedron cube 3
184
185
186
187 -- | Given in Sorokina and Zeilfelder, p. 79, (2.7). Note that the
188 -- third and fourth indices of c-t3 have been switched. This is
189 -- because we store the triangles oriented such that their volume is
190 -- positive. If T and T-tilde share \<v0,v1,v2\> and v3,v3-tilde
191 -- point in opposite directions, one of them has to have negative
192 -- volume!
193 prop_c0102_identity1 :: Cube -> Bool
194 prop_c0102_identity1 cube =
195 c t0 0 1 0 2 ~= (c t0 0 0 1 2 + c t1 0 0 2 1) / 2
196 where
197 t0 = tetrahedron cube 0
198 t1 = tetrahedron cube 1
199
200
201 -- | Given in Sorokina and Zeilfelder, p. 79, (2.7). See
202 -- 'prop_c0102_identity1'.
203 prop_c0201_identity1 :: Cube -> Bool
204 prop_c0201_identity1 cube =
205 c t0 0 2 0 1 ~= (c t0 0 1 1 1 + c t1 0 1 1 1) / 2
206 where
207 t0 = tetrahedron cube 0
208 t1 = tetrahedron cube 1
209
210
211 -- | Given in Sorokina and Zeilfelder, p. 79, (2.7). See
212 -- 'prop_c0102_identity1'.
213 prop_c0300_identity2 :: Cube -> Bool
214 prop_c0300_identity2 cube =
215 c t0 0 3 0 0 ~= (c t0 0 2 1 0 + c t1 0 2 0 1) / 2
216 where
217 t0 = tetrahedron cube 0
218 t1 = tetrahedron cube 1
219
220
221 -- | Given in Sorokina and Zeilfelder, p. 79, (2.7). See
222 -- 'prop_c0102_identity1'.
223 prop_c1101_identity :: Cube -> Bool
224 prop_c1101_identity cube =
225 c t0 1 1 0 1 ~= (c t0 1 0 1 1 + c t1 1 0 1 1) / 2
226 where
227 t0 = tetrahedron cube 0
228 t1 = tetrahedron cube 1
229
230
231 -- | Given in Sorokina and Zeilfelder, p. 79, (2.7). See
232 -- 'prop_c0102_identity1'.
233 prop_c1200_identity2 :: Cube -> Bool
234 prop_c1200_identity2 cube =
235 c t0 1 2 0 0 ~= (c t0 1 1 1 0 + c t1 1 1 0 1) / 2
236 where
237 t0 = tetrahedron cube 0
238 t1 = tetrahedron cube 1
239
240
241 -- | Given in Sorokina and Zeilfelder, p. 79, (2.7). See
242 -- 'prop_c0102_identity1'.
243 prop_c2100_identity2 :: Cube -> Bool
244 prop_c2100_identity2 cube =
245 c t0 2 1 0 0 ~= (c t0 2 0 1 0 + c t1 2 0 0 1) / 2
246 where
247 t0 = tetrahedron cube 0
248 t1 = tetrahedron cube 1
249
250
251 -- | Given in Sorokina and Zeilfelder, p. 79, (2.8). The third and
252 -- fourth indices of c-t6 have been switched. This is because we
253 -- store the triangles oriented such that their volume is
254 -- positive. If T and T-tilde share \<v0,v1,v2\> and v3,v3-tilde
255 -- point in opposite directions, one of them has to have negative
256 -- volume!
257 prop_c3000_identity :: Cube -> Bool
258 prop_c3000_identity cube =
259 c t0 3 0 0 0 ~= c t0 2 1 0 0 + c t6 2 1 0 0
260 - ((c t0 2 0 1 0 + c t0 2 0 0 1)/ 2)
261 where
262 t0 = tetrahedron cube 0
263 t6 = tetrahedron cube 6
264
265
266 -- | Given in Sorokina and Zeilfelder, p. 79, (2.8). See
267 -- 'prop_c3000_identity'.
268 prop_c2010_identity :: Cube -> Bool
269 prop_c2010_identity cube =
270 c t0 2 0 1 0 ~= c t0 1 1 1 0 + c t6 1 1 0 1
271 - ((c t0 1 0 2 0 + c t0 1 0 1 1)/ 2)
272 where
273 t0 = tetrahedron cube 0
274 t6 = tetrahedron cube 6
275
276
277 -- | Given in Sorokina and Zeilfelder, p. 79, (2.8). See
278 -- 'prop_c3000_identity'.
279 prop_c2001_identity :: Cube -> Bool
280 prop_c2001_identity cube =
281 c t0 2 0 0 1 ~= c t0 1 1 0 1 + c t6 1 1 1 0
282 - ((c t0 1 0 0 2 + c t0 1 0 1 1)/ 2)
283 where
284 t0 = tetrahedron cube 0
285 t6 = tetrahedron cube 6
286
287
288 -- | Given in Sorokina and Zeilfelder, p. 79, (2.8). See
289 -- 'prop_c3000_identity'.
290 prop_c1020_identity :: Cube -> Bool
291 prop_c1020_identity cube =
292 c t0 1 0 2 0 ~= c t0 0 1 2 0 + c t6 0 1 0 2
293 - ((c t0 0 0 3 0 + c t0 0 0 2 1)/ 2)
294 where
295 t0 = tetrahedron cube 0
296 t6 = tetrahedron cube 6
297
298
299 -- | Given in Sorokina and Zeilfelder, p. 79, (2.8). See
300 -- 'prop_c3000_identity'.
301 prop_c1002_identity :: Cube -> Bool
302 prop_c1002_identity cube =
303 c t0 1 0 0 2 ~= c t0 0 1 0 2 + c t6 0 1 2 0
304 - ((c t0 0 0 0 3 + c t0 0 0 1 2)/ 2)
305 where
306 t0 = tetrahedron cube 0
307 t6 = tetrahedron cube 6
308
309
310 -- | Given in Sorokina and Zeilfelder, p. 79, (2.8). See
311 -- 'prop_c3000_identity'.
312 prop_c1011_identity :: Cube -> Bool
313 prop_c1011_identity cube =
314 c t0 1 0 1 1 ~= c t0 0 1 1 1 + c t6 0 1 1 1 -
315 ((c t0 0 0 1 2 + c t0 0 0 2 1)/ 2)
316 where
317 t0 = tetrahedron cube 0
318 t6 = tetrahedron cube 6
319
320
321
322 -- | Given in Sorokina and Zeilfelder, p. 78.
323 prop_cijk1_identity :: Cube -> Bool
324 prop_cijk1_identity cube =
325 and [ c t0 i j k 1 ~=
326 (c t1 (i+1) j k 0) * ((b0 t0) (v3 t1)) +
327 (c t1 i (j+1) k 0) * ((b1 t0) (v3 t1)) +
328 (c t1 i j (k+1) 0) * ((b2 t0) (v3 t1)) +
329 (c t1 i j k 1) * ((b3 t0) (v3 t1)) | i <- [0..2],
330 j <- [0..2],
331 k <- [0..2],
332 i + j + k == 2]
333 where
334 t0 = tetrahedron cube 0
335 t1 = tetrahedron cube 1
336
337
338 -- | The function values at the interior should be the same for all
339 -- tetrahedra.
340 prop_interior_values_all_identical :: Cube -> Bool
341 prop_interior_values_all_identical cube =
342 all_equal [ eval (Tetrahedron.fv tet) I | tet <- tetrahedra cube ]
343
344
345 -- | We know what (c t6 2 1 0 0) should be from Sorokina and Zeilfelder, p. 87.
346 -- This test checks the rotation works as expected.
347 prop_c_tilde_2100_rotation_correct :: Cube -> Bool
348 prop_c_tilde_2100_rotation_correct cube =
349 expr1 == expr2
350 where
351 t0 = tetrahedron cube 0
352 t6 = tetrahedron cube 6
353
354 -- What gets computed for c2100 of t6.
355 expr1 = eval (Tetrahedron.fv t6) $
356 (3/8)*I +
357 (1/12)*(T + R + L + D) +
358 (1/64)*(FT + FR + FL + FD) +
359 (7/48)*F +
360 (1/48)*B +
361 (1/96)*(RT + LD + LT + RD) +
362 (1/192)*(BT + BR + BL + BD)
363
364 -- What should be computed for c2100 of t6.
365 expr2 = eval (Tetrahedron.fv t0) $
366 (3/8)*I +
367 (1/12)*(F + R + L + B) +
368 (1/64)*(FT + RT + LT + BT) +
369 (7/48)*T +
370 (1/48)*D +
371 (1/96)*(FR + FL + BR + BL) +
372 (1/192)*(FD + RD + LD + BD)
373
374
375 -- | We know what (c t6 2 1 0 0) should be from Sorokina and
376 -- Zeilfelder, p. 87. This test checks the actual value based on
377 -- the FunctionValues of the cube.
378 --
379 -- If 'prop_c_tilde_2100_rotation_correct' passes, then this test is
380 -- even meaningful!
381 prop_c_tilde_2100_correct :: Cube -> Bool
382 prop_c_tilde_2100_correct cube =
383 c t6 2 1 0 0 == expected
384 where
385 t0 = tetrahedron cube 0
386 t6 = tetrahedron cube 6
387 fvs = Tetrahedron.fv t0
388 expected = eval fvs $
389 (3/8)*I +
390 (1/12)*(F + R + L + B) +
391 (1/64)*(FT + RT + LT + BT) +
392 (7/48)*T +
393 (1/48)*D +
394 (1/96)*(FR + FL + BR + BL) +
395 (1/192)*(FD + RD + LD + BD)
396
397
398 -- Tests to check that the correct edges are incidental.
399 prop_t0_shares_edge_with_t1 :: Cube -> Bool
400 prop_t0_shares_edge_with_t1 cube =
401 (v1 t0) == (v1 t1) && (v3 t0) == (v2 t1)
402 where
403 t0 = tetrahedron cube 0
404 t1 = tetrahedron cube 1
405
406 prop_t0_shares_edge_with_t3 :: Cube -> Bool
407 prop_t0_shares_edge_with_t3 cube =
408 (v1 t0) == (v1 t3) && (v2 t0) == (v3 t3)
409 where
410 t0 = tetrahedron cube 0
411 t3 = tetrahedron cube 3
412
413 prop_t0_shares_edge_with_t6 :: Cube -> Bool
414 prop_t0_shares_edge_with_t6 cube =
415 (v2 t0) == (v3 t6) && (v3 t0) == (v2 t6)
416 where
417 t0 = tetrahedron cube 0
418 t6 = tetrahedron cube 6
419
420 prop_t1_shares_edge_with_t2 :: Cube -> Bool
421 prop_t1_shares_edge_with_t2 cube =
422 (v1 t1) == (v1 t2) && (v3 t1) == (v2 t2)
423 where
424 t1 = tetrahedron cube 1
425 t2 = tetrahedron cube 2
426
427 prop_t1_shares_edge_with_t19 :: Cube -> Bool
428 prop_t1_shares_edge_with_t19 cube =
429 (v2 t1) == (v3 t19) && (v3 t1) == (v2 t19)
430 where
431 t1 = tetrahedron cube 1
432 t19 = tetrahedron cube 19
433
434 prop_t2_shares_edge_with_t3 :: Cube -> Bool
435 prop_t2_shares_edge_with_t3 cube =
436 (v1 t1) == (v1 t2) && (v3 t1) == (v2 t2)
437 where
438 t1 = tetrahedron cube 1
439 t2 = tetrahedron cube 2
440
441 prop_t2_shares_edge_with_t12 :: Cube -> Bool
442 prop_t2_shares_edge_with_t12 cube =
443 (v2 t2) == (v3 t12) && (v3 t2) == (v2 t12)
444 where
445 t2 = tetrahedron cube 2
446 t12 = tetrahedron cube 12
447
448 prop_t3_shares_edge_with_t21 :: Cube -> Bool
449 prop_t3_shares_edge_with_t21 cube =
450 (v2 t3) == (v3 t21) && (v3 t3) == (v2 t21)
451 where
452 t3 = tetrahedron cube 3
453 t21 = tetrahedron cube 21
454
455 prop_t4_shares_edge_with_t5 :: Cube -> Bool
456 prop_t4_shares_edge_with_t5 cube =
457 (v1 t4) == (v1 t5) && (v3 t4) == (v2 t5)
458 where
459 t4 = tetrahedron cube 4
460 t5 = tetrahedron cube 5
461
462 prop_t4_shares_edge_with_t7 :: Cube -> Bool
463 prop_t4_shares_edge_with_t7 cube =
464 (v1 t4) == (v1 t7) && (v2 t4) == (v3 t7)
465 where
466 t4 = tetrahedron cube 4
467 t7 = tetrahedron cube 7
468
469 prop_t4_shares_edge_with_t10 :: Cube -> Bool
470 prop_t4_shares_edge_with_t10 cube =
471 (v2 t4) == (v3 t10) && (v3 t4) == (v2 t10)
472 where
473 t4 = tetrahedron cube 4
474 t10 = tetrahedron cube 10
475
476 prop_t5_shares_edge_with_t6 :: Cube -> Bool
477 prop_t5_shares_edge_with_t6 cube =
478 (v1 t5) == (v1 t6) && (v3 t5) == (v2 t6)
479 where
480 t5 = tetrahedron cube 5
481 t6 = tetrahedron cube 6
482
483 prop_t5_shares_edge_with_t16 :: Cube -> Bool
484 prop_t5_shares_edge_with_t16 cube =
485 (v2 t5) == (v3 t16) && (v3 t5) == (v2 t16)
486 where
487 t5 = tetrahedron cube 5
488 t16 = tetrahedron cube 16
489
490 prop_t6_shares_edge_with_t7 :: Cube -> Bool
491 prop_t6_shares_edge_with_t7 cube =
492 (v1 t6) == (v1 t7) && (v3 t6) == (v2 t7)
493 where
494 t6 = tetrahedron cube 6
495 t7 = tetrahedron cube 7
496
497 prop_t7_shares_edge_with_t20 :: Cube -> Bool
498 prop_t7_shares_edge_with_t20 cube =
499 (v2 t7) == (v3 t20) && (v2 t7) == (v3 t20)
500 where
501 t7 = tetrahedron cube 7
502 t20 = tetrahedron cube 20