snoc,
unsafeIndex
)
+
import Prelude hiding (LT)
import Test.Framework (Test, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Cardinal
import Comparisons ((~=), (~~=))
-import qualified Face (Face(Face, v0, v1, v2, v3))
-import FunctionValues
+import qualified Face (Face(..), center)
+import FunctionValues (FunctionValues, eval, rotate)
import Misc (all_equal, disjoint)
-import Point
-import Tetrahedron (
- Tetrahedron(..),
- c,
- b0,
- b1,
- b2,
- b3,
- volume
- )
-import ThreeDimensional
-
-data Cube = Cube { h :: Double,
- i :: Int,
- j :: Int,
- k :: Int,
- fv :: FunctionValues,
- tetrahedra_volume :: Double }
+import Point (Point(..), dot)
+import Tetrahedron (Tetrahedron(..), barycenter, c, volume)
+
+data Cube = Cube { i :: !Int,
+ j :: !Int,
+ k :: !Int,
+ fv :: !FunctionValues,
+ tetrahedra_volume :: !Double }
deriving (Eq)
instance Arbitrary Cube where
arbitrary = do
- (Positive h') <- arbitrary :: Gen (Positive Double)
i' <- choose (coordmin, coordmax)
j' <- choose (coordmin, coordmax)
k' <- choose (coordmin, coordmax)
fv' <- arbitrary :: Gen FunctionValues
(Positive tet_vol) <- arbitrary :: Gen (Positive Double)
- return (Cube h' i' j' k' fv' tet_vol)
- where
- coordmin = -268435456 -- -(2^29 / 2)
- coordmax = 268435456 -- +(2^29 / 2)
+ return (Cube i' j' k' fv' tet_vol)
+ where
+ -- The idea here is that, when cubed in the volume formula,
+ -- these numbers don't overflow 64 bits. This number is not
+ -- magic in any other sense than that it does not cause test
+ -- failures, while 2^23 does.
+ coordmax = 4194304 -- 2^22
+ coordmin = -coordmax
instance Show Cube where
show cube =
"Cube_" ++ subscript ++ "\n" ++
- " h: " ++ (show (h cube)) ++ "\n" ++
" Center: " ++ (show (center cube)) ++ "\n" ++
" xmin: " ++ (show (xmin cube)) ++ "\n" ++
" xmax: " ++ (show (xmax cube)) ++ "\n" ++
" ymin: " ++ (show (ymin cube)) ++ "\n" ++
" ymax: " ++ (show (ymax cube)) ++ "\n" ++
" zmin: " ++ (show (zmin cube)) ++ "\n" ++
- " zmax: " ++ (show (zmax cube)) ++ "\n" ++
- " fv: " ++ (show (Cube.fv cube)) ++ "\n"
+ " zmax: " ++ (show (zmax cube)) ++ "\n"
where
subscript =
(show (i cube)) ++ "," ++ (show (j cube)) ++ "," ++ (show (k cube))
-- | The left-side boundary of the cube. See Sorokina and Zeilfelder,
-- p. 76.
xmin :: Cube -> Double
-xmin cube = (2*i' - 1)*delta / 2
+xmin cube = (i' - 1/2)
where
i' = fromIntegral (i cube) :: Double
- delta = h cube
-- | The right-side boundary of the cube. See Sorokina and Zeilfelder,
-- p. 76.
xmax :: Cube -> Double
-xmax cube = (2*i' + 1)*delta / 2
+xmax cube = (i' + 1/2)
where
i' = fromIntegral (i cube) :: Double
- delta = h cube
-- | The front boundary of the cube. See Sorokina and Zeilfelder,
-- p. 76.
ymin :: Cube -> Double
-ymin cube = (2*j' - 1)*delta / 2
+ymin cube = (j' - 1/2)
where
j' = fromIntegral (j cube) :: Double
- delta = h cube
-- | The back boundary of the cube. See Sorokina and Zeilfelder,
-- p. 76.
ymax :: Cube -> Double
-ymax cube = (2*j' + 1)*delta / 2
+ymax cube = (j' + 1/2)
where
j' = fromIntegral (j cube) :: Double
- delta = h cube
-- | The bottom boundary of the cube. See Sorokina and Zeilfelder,
-- p. 76.
zmin :: Cube -> Double
-zmin cube = (2*k' - 1)*delta / 2
+zmin cube = (k' - 1/2)
where
k' = fromIntegral (k cube) :: Double
- delta = h cube
-- | The top boundary of the cube. See Sorokina and Zeilfelder,
-- p. 76.
zmax :: Cube -> Double
-zmax cube = (2*k' + 1)*delta / 2
+zmax cube = (k' + 1/2)
where
k' = fromIntegral (k cube) :: Double
- delta = h cube
-
-instance ThreeDimensional Cube where
- -- | The center of Cube_ijk coincides with v_ijk at
- -- (ih, jh, kh). See Sorokina and Zeilfelder, p. 76.
- center cube = (x, y, z)
- where
- delta = h cube
- i' = fromIntegral (i cube) :: Double
- j' = fromIntegral (j cube) :: Double
- k' = fromIntegral (k cube) :: Double
- x = delta * i'
- y = delta * j'
- z = delta * k'
-
- -- | It's easy to tell if a point is within a cube; just make sure
- -- that it falls on the proper side of each of the cube's faces.
- contains_point cube (x, y, z)
- | x < (xmin cube) = False
- | x > (xmax cube) = False
- | y < (ymin cube) = False
- | y > (ymax cube) = False
- | z < (zmin cube) = False
- | z > (zmax cube) = False
- | otherwise = True
+-- | The center of Cube_ijk coincides with v_ijk at
+-- (i, j, k). See Sorokina and Zeilfelder, p. 76.
+center :: Cube -> Point
+center cube =
+ Point x y z
+ where
+ x = fromIntegral (i cube) :: Double
+ y = fromIntegral (j cube) :: Double
+ z = fromIntegral (k cube) :: Double
+
-- Face stuff.
top_face :: Cube -> Face.Face
top_face cube = Face.Face v0' v1' v2' v3'
where
- delta = (1/2)*(h cube)
- v0' = (center cube) + (delta, -delta, delta)
- v1' = (center cube) + (delta, delta, delta)
- v2' = (center cube) + (-delta, delta, delta)
- v3' = (center cube) + (-delta, -delta, delta)
+ delta = 1/2
+ cc = center cube
+ v0' = cc + ( Point delta (-delta) delta )
+ v1' = cc + ( Point delta delta delta )
+ v2' = cc + ( Point (-delta) delta delta )
+ v3' = cc + ( Point (-delta) (-delta) delta )
back_face :: Cube -> Face.Face
back_face cube = Face.Face v0' v1' v2' v3'
where
- delta = (1/2)*(h cube)
- v0' = (center cube) + (delta, -delta, -delta)
- v1' = (center cube) + (delta, delta, -delta)
- v2' = (center cube) + (delta, delta, delta)
- v3' = (center cube) + (delta, -delta, delta)
+ delta = 1/2
+ cc = center cube
+ v0' = cc + ( Point delta (-delta) (-delta) )
+ v1' = cc + ( Point delta delta (-delta) )
+ v2' = cc + ( Point delta delta delta )
+ v3' = cc + ( Point delta (-delta) delta )
-- The bottom face (in the direction of -z) of the cube.
down_face :: Cube -> Face.Face
down_face cube = Face.Face v0' v1' v2' v3'
where
- delta = (1/2)*(h cube)
- v0' = (center cube) + (-delta, -delta, -delta)
- v1' = (center cube) + (-delta, delta, -delta)
- v2' = (center cube) + (delta, delta, -delta)
- v3' = (center cube) + (delta, -delta, -delta)
+ delta = 1/2
+ cc = center cube
+ v0' = cc + ( Point (-delta) (-delta) (-delta) )
+ v1' = cc + ( Point (-delta) delta (-delta) )
+ v2' = cc + ( Point delta delta (-delta) )
+ v3' = cc + ( Point delta (-delta) (-delta) )
front_face :: Cube -> Face.Face
front_face cube = Face.Face v0' v1' v2' v3'
where
- delta = (1/2)*(h cube)
- v0' = (center cube) + (-delta, -delta, delta)
- v1' = (center cube) + (-delta, delta, delta)
- v2' = (center cube) + (-delta, delta, -delta)
- v3' = (center cube) + (-delta, -delta, -delta)
+ delta = 1/2
+ cc = center cube
+ v0' = cc + ( Point (-delta) (-delta) delta )
+ v1' = cc + ( Point (-delta) delta delta )
+ v2' = cc + ( Point (-delta) delta (-delta) )
+ v3' = cc + ( Point (-delta) (-delta) (-delta) )
-- | The left (in the direction of -y) face of the cube.
left_face :: Cube -> Face.Face
left_face cube = Face.Face v0' v1' v2' v3'
where
- delta = (1/2)*(h cube)
- v0' = (center cube) + (delta, -delta, delta)
- v1' = (center cube) + (-delta, -delta, delta)
- v2' = (center cube) + (-delta, -delta, -delta)
- v3' = (center cube) + (delta, -delta, -delta)
+ delta = 1/2
+ cc = center cube
+ v0' = cc + ( Point delta (-delta) delta )
+ v1' = cc + ( Point (-delta) (-delta) delta )
+ v2' = cc + ( Point (-delta) (-delta) (-delta) )
+ v3' = cc + ( Point delta (-delta) (-delta) )
-- | The right (in the direction of y) face of the cube.
right_face :: Cube -> Face.Face
right_face cube = Face.Face v0' v1' v2' v3'
where
- delta = (1/2)*(h cube)
- v0' = (center cube) + (-delta, delta, delta)
- v1' = (center cube) + (delta, delta, delta)
- v2' = (center cube) + (delta, delta, -delta)
- v3' = (center cube) + (-delta, delta, -delta)
+ delta = 1/2
+ cc = center cube
+ v0' = cc + ( Point (-delta) delta delta)
+ v1' = cc + ( Point delta delta delta )
+ v2' = cc + ( Point delta delta (-delta) )
+ v3' = cc + ( Point (-delta) delta (-delta) )
tetrahedron :: Cube -> Int -> Tetrahedron
Tetrahedron (fv cube) v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (front_face cube)
- v2' = Face.v0 (front_face cube)
- v3' = Face.v1 (front_face cube)
+ ff = front_face cube
+ v1' = Face.center ff
+ v2' = Face.v0 ff
+ v3' = Face.v1 ff
vol = tetrahedra_volume cube
tetrahedron cube 1 =
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (front_face cube)
- v2' = Face.v1 (front_face cube)
- v3' = Face.v2 (front_face cube)
+ ff = front_face cube
+ v1' = Face.center ff
+ v2' = Face.v1 ff
+ v3' = Face.v2 ff
fv' = rotate ccwx (fv cube)
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (front_face cube)
- v2' = Face.v2 (front_face cube)
- v3' = Face.v3 (front_face cube)
+ ff = front_face cube
+ v1' = Face.center ff
+ v2' = Face.v2 ff
+ v3' = Face.v3 ff
fv' = rotate ccwx $ rotate ccwx $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (front_face cube)
- v2' = Face.v3 (front_face cube)
- v3' = Face.v0 (front_face cube)
+ ff = front_face cube
+ v1' = Face.center ff
+ v2' = Face.v3 ff
+ v3' = Face.v0 ff
fv' = rotate cwx (fv cube)
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (top_face cube)
- v2' = Face.v0 (top_face cube)
- v3' = Face.v1 (top_face cube)
+ tf = top_face cube
+ v1' = Face.center tf
+ v2' = Face.v0 tf
+ v3' = Face.v1 tf
fv' = rotate cwy (fv cube)
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (top_face cube)
- v2' = Face.v1 (top_face cube)
- v3' = Face.v2 (top_face cube)
+ tf = top_face cube
+ v1' = Face.center tf
+ v2' = Face.v1 tf
+ v3' = Face.v2 tf
fv' = rotate cwy $ rotate cwz $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (top_face cube)
- v2' = Face.v2 (top_face cube)
- v3' = Face.v3 (top_face cube)
+ tf = top_face cube
+ v1' = Face.center tf
+ v2' = Face.v2 tf
+ v3' = Face.v3 tf
fv' = rotate cwy $ rotate cwz
$ rotate cwz
$ fv cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (top_face cube)
- v2' = Face.v3 (top_face cube)
- v3' = Face.v0 (top_face cube)
+ tf = top_face cube
+ v1' = Face.center tf
+ v2' = Face.v3 tf
+ v3' = Face.v0 tf
fv' = rotate cwy $ rotate ccwz $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (back_face cube)
- v2' = Face.v0 (back_face cube)
- v3' = Face.v1 (back_face cube)
+ bf = back_face cube
+ v1' = Face.center bf
+ v2' = Face.v0 bf
+ v3' = Face.v1 bf
fv' = rotate cwy $ rotate cwy $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (back_face cube)
- v2' = Face.v1 (back_face cube)
- v3' = Face.v2 (back_face cube)
+ bf = back_face cube
+ v1' = Face.center bf
+ v2' = Face.v1 bf
+ v3' = Face.v2 bf
fv' = rotate cwy $ rotate cwy
$ rotate cwx
$ fv cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (back_face cube)
- v2' = Face.v2 (back_face cube)
- v3' = Face.v3 (back_face cube)
+ bf = back_face cube
+ v1' = Face.center bf
+ v2' = Face.v2 bf
+ v3' = Face.v3 bf
fv' = rotate cwy $ rotate cwy
$ rotate cwx
$ rotate cwx
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (back_face cube)
- v2' = Face.v3 (back_face cube)
- v3' = Face.v0 (back_face cube)
+ bf = back_face cube
+ v1' = Face.center bf
+ v2' = Face.v3 bf
+ v3' = Face.v0 bf
fv' = rotate cwy $ rotate cwy
$ rotate ccwx
$ fv cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (down_face cube)
- v2' = Face.v0 (down_face cube)
- v3' = Face.v1 (down_face cube)
+ df = down_face cube
+ v1' = Face.center df
+ v2' = Face.v0 df
+ v3' = Face.v1 df
fv' = rotate ccwy $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (down_face cube)
- v2' = Face.v1 (down_face cube)
- v3' = Face.v2 (down_face cube)
+ df = down_face cube
+ v1' = Face.center df
+ v2' = Face.v1 df
+ v3' = Face.v2 df
fv' = rotate ccwy $ rotate ccwz $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (down_face cube)
- v2' = Face.v2 (down_face cube)
- v3' = Face.v3 (down_face cube)
+ df = down_face cube
+ v1' = Face.center df
+ v2' = Face.v2 df
+ v3' = Face.v3 df
fv' = rotate ccwy $ rotate ccwz
$ rotate ccwz
$ fv cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (down_face cube)
- v2' = Face.v3 (down_face cube)
- v3' = Face.v0 (down_face cube)
+ df = down_face cube
+ v1' = Face.center df
+ v2' = Face.v3 df
+ v3' = Face.v0 df
fv' = rotate ccwy $ rotate cwz $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (right_face cube)
- v2' = Face.v0 (right_face cube)
- v3' = Face.v1 (right_face cube)
+ rf = right_face cube
+ v1' = Face.center rf
+ v2' = Face.v0 rf
+ v3' = Face.v1 rf
fv' = rotate ccwz $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (right_face cube)
- v2' = Face.v1 (right_face cube)
- v3' = Face.v2 (right_face cube)
+ rf = right_face cube
+ v1' = Face.center rf
+ v2' = Face.v1 rf
+ v3' = Face.v2 rf
fv' = rotate ccwz $ rotate cwy $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (right_face cube)
- v2' = Face.v2 (right_face cube)
- v3' = Face.v3 (right_face cube)
+ rf = right_face cube
+ v1' = Face.center rf
+ v2' = Face.v2 rf
+ v3' = Face.v3 rf
fv' = rotate ccwz $ rotate cwy
$ rotate cwy
$ fv cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (right_face cube)
- v2' = Face.v3 (right_face cube)
- v3' = Face.v0 (right_face cube)
+ rf = right_face cube
+ v1' = Face.center rf
+ v2' = Face.v3 rf
+ v3' = Face.v0 rf
fv' = rotate ccwz $ rotate ccwy
$ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (left_face cube)
- v2' = Face.v0 (left_face cube)
- v3' = Face.v1 (left_face cube)
+ lf = left_face cube
+ v1' = Face.center lf
+ v2' = Face.v0 lf
+ v3' = Face.v1 lf
fv' = rotate cwz $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (left_face cube)
- v2' = Face.v1 (left_face cube)
- v3' = Face.v2 (left_face cube)
+ lf = left_face cube
+ v1' = Face.center lf
+ v2' = Face.v1 lf
+ v3' = Face.v2 lf
fv' = rotate cwz $ rotate ccwy $ fv cube
vol = tetrahedra_volume cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (left_face cube)
- v2' = Face.v2 (left_face cube)
- v3' = Face.v3 (left_face cube)
+ lf = left_face cube
+ v1' = Face.center lf
+ v2' = Face.v2 lf
+ v3' = Face.v3 lf
fv' = rotate cwz $ rotate ccwy
$ rotate ccwy
$ fv cube
Tetrahedron fv' v0' v1' v2' v3' vol
where
v0' = center cube
- v1' = center (left_face cube)
- v2' = Face.v3 (left_face cube)
- v3' = Face.v0 (left_face cube)
+ lf = left_face cube
+ v1' = Face.center lf
+ v2' = Face.v3 lf
+ v3' = Face.v0 lf
fv' = rotate cwz $ rotate cwy
$ fv cube
vol = tetrahedra_volume cube
--- Feels dirty, but whatever.
-tetrahedron _ _ = error "asked for a nonexistent tetrahedron"
-
-- Only used in tests, so we don't need the added speed
-- of Data.Vector.
(tetrahedron cube 18)
in_top_half :: Cube -> Point -> Bool
-in_top_half cube (_,_,z) =
+in_top_half cube (Point _ _ z) =
distance_from_top <= distance_from_bottom
where
distance_from_top = abs $ (zmax cube) - z
distance_from_bottom = abs $ (zmin cube) - z
in_front_half :: Cube -> Point -> Bool
-in_front_half cube (x,_,_) =
+in_front_half cube (Point x _ _) =
distance_from_front <= distance_from_back
where
distance_from_front = abs $ (xmin cube) - x
in_left_half :: Cube -> Point -> Bool
-in_left_half cube (_,y,_) =
+in_left_half cube (Point _ y _) =
distance_from_left <= distance_from_right
where
distance_from_left = abs $ (ymin cube) - y
-- This can throw an exception, but the use of 'head' might
-- save us some unnecessary computations.
--
+{-# INLINE find_containing_tetrahedron #-}
find_containing_tetrahedron :: Cube -> Point -> Tetrahedron
find_containing_tetrahedron cube p =
candidates `V.unsafeIndex` (fromJust lucky_idx)
top_half = in_top_half cube p
left_half = in_left_half cube p
+ candidates :: V.Vector Tetrahedron
candidates =
if front_half then
else
back_right_down_tetrahedra cube
- -- Use the dot product instead of 'distance' here to save a
- -- sqrt(). So, "distances" below really means "distances squared."
- distances = V.map ((dot p) . center) candidates
+ -- Use the dot product instead of Euclidean distance here to save
+ -- a sqrt(). So, "distances" below really means "distances
+ -- squared."
+ distances :: V.Vector Double
+ distances = V.map ((dot p) . barycenter) candidates
+
+ shortest_distance :: Double
shortest_distance = V.minimum distances
+
+ -- Compute the index of the tetrahedron with the center closest to
+ -- p. This is a bad algorithm, but don't change it! If you make it
+ -- smarter by finding the index of shortest_distance in distances
+ -- (this should give the same answer and avoids recomputing the
+ -- dot product), the program gets slower. Seriously!
+ lucky_idx :: Maybe Int
lucky_idx = V.findIndex
- (\t -> (center t) `dot` p == shortest_distance)
+ (\t -> (barycenter t) `dot` p == shortest_distance)
candidates
-- | Since the grid size is necessarily positive, all tetrahedra
--- (which comprise cubes of positive volume) must have positive volume
--- as well.
+-- (which comprise cubes of positive volume) must have positive
+-- volume as well.
prop_all_volumes_positive :: Cube -> Bool
prop_all_volumes_positive cube =
- null nonpositive_volumes
+ all (>= 0) volumes
where
ts = tetrahedra cube
volumes = map volume ts
- nonpositive_volumes = filter (<= 0) volumes
+
-- | In fact, since all of the tetrahedra are identical, we should
-- already know their volumes. There's 24 tetrahedra to a cube, so
--- we'd expect the volume of each one to be (1/24)*h^3.
+-- we'd expect the volume of each one to be 1/24.
prop_all_volumes_exact :: Cube -> Bool
prop_all_volumes_exact cube =
- and [volume t ~~= (1/24)*(delta^(3::Int)) | t <- tetrahedra cube]
- where
- delta = h cube
+ and [volume t ~~= 1/24 | t <- tetrahedra cube]
--- | All tetrahedron should have their v0 located at the center of the cube.
+-- | All tetrahedron should have their v0 located at the center of the
+-- cube.
prop_v0_all_equal :: Cube -> Bool
prop_v0_all_equal cube = (v0 t0) == (v0 t1)
where
-- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Note that the
--- third and fourth indices of c-t1 have been switched. This is
+-- third and fourth indices of c-t3 have been switched. This is
-- because we store the triangles oriented such that their volume is
-- positive. If T and T-tilde share \<v0,v1,v2\> and v3,v3-tilde point
-- in opposite directions, one of them has to have negative volume!
t4 = tetrahedron cube 4
t5 = tetrahedron cube 5
--- -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Repeats
--- -- 'prop_c0120_identity1' with tetrahedrons 5 and 6.
+-- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Repeats
+-- 'prop_c0120_identity1' with tetrahedrons 5 and 6.
prop_c0120_identity6 :: Cube -> Bool
prop_c0120_identity6 cube =
c t6 0 1 2 0 ~= (c t6 0 0 2 1 + c t5 0 0 1 2) / 2
t6 = tetrahedron cube 6
--- -- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Repeats
--- -- 'prop_c0120_identity1' with tetrahedrons 6 and 7.
+-- | Given in Sorokina and Zeilfelder, p. 79, (2.6). Repeats
+-- 'prop_c0120_identity1' with tetrahedrons 6 and 7.
prop_c0120_identity7 :: Cube -> Bool
prop_c0120_identity7 cube =
c t7 0 1 2 0 ~= (c t7 0 0 2 1 + c t6 0 0 1 2) / 2
t6 = tetrahedron cube 6
-
--- | Given in Sorokina and Zeilfelder, p. 78.
-prop_cijk1_identity :: Cube -> Bool
-prop_cijk1_identity cube =
- and [ c t0 i j k 1 ~=
- (c t1 (i+1) j k 0) * ((b0 t0) (v3 t1)) +
- (c t1 i (j+1) k 0) * ((b1 t0) (v3 t1)) +
- (c t1 i j (k+1) 0) * ((b2 t0) (v3 t1)) +
- (c t1 i j k 1) * ((b3 t0) (v3 t1)) | i <- [0..2],
- j <- [0..2],
- k <- [0..2],
- i + j + k == 2]
- where
- t0 = tetrahedron cube 0
- t1 = tetrahedron cube 1
-
-
-- | The function values at the interior should be the same for all
-- tetrahedra.
prop_interior_values_all_identical :: Cube -> Bool
-- This test checks the rotation works as expected.
prop_c_tilde_2100_rotation_correct :: Cube -> Bool
prop_c_tilde_2100_rotation_correct cube =
- expr1 == expr2
+ expr1 ~= expr2
where
t0 = tetrahedron cube 0
t6 = tetrahedron cube 6
-- even meaningful!
prop_c_tilde_2100_correct :: Cube -> Bool
prop_c_tilde_2100_correct cube =
- c t6 2 1 0 0 == expected
+ c t6 2 1 0 0 ~= expected
where
t0 = tetrahedron cube 0
t6 = tetrahedron cube 6
t20 = tetrahedron cube 20
-
-
-
-p78_25_properties :: Test.Framework.Test
-p78_25_properties =
- testGroup "p. 78, Section (2.5) Properties" [
- testProperty "c_ijk1 identity" prop_cijk1_identity ]
-
p79_26_properties :: Test.Framework.Test
p79_26_properties =
testGroup "p. 79, Section (2.6) Properties" [
cube_properties :: Test.Framework.Test
cube_properties =
testGroup "Cube Properties" [
- p78_25_properties,
p79_26_properties,
p79_27_properties,
p79_28_properties,