+ testGroup "p. 78, Section (2.4) Properties" [
+ testProperty "c3000 identity" prop_c3000_identity,
+ testProperty "c2100 identity" prop_c2100_identity,
+ testProperty "c1110 identity" prop_c1110_identity]
+ where
+ -- | Returns the domain point of t with indices i,j,k,l.
+ domain_point :: Tetrahedron -> Int -> Int -> Int -> Int -> Point
+ domain_point t i j k l
+ | i + j + k + l == 3 = weighted_sum `scale` (1/3)
+ | otherwise = error "domain point index out of bounds"
+ where
+ v0' = (v0 t) `scale` (fromIntegral i)
+ v1' = (v1 t) `scale` (fromIntegral j)
+ v2' = (v2 t) `scale` (fromIntegral k)
+ v3' = (v3 t) `scale` (fromIntegral l)
+ weighted_sum = v0' + v1' + v2' + v3'
+
+
+ -- | Used for convenience in the next few tests.
+ p :: Tetrahedron -> Int -> Int -> Int -> Int -> Double
+ p t i j k l = (polynomial t) (domain_point t i j k l)
+
+
+ -- | Given in Sorokina and Zeilfelder, p. 78.
+ prop_c3000_identity :: Tetrahedron -> Property
+ prop_c3000_identity t =
+ (volume t) > 0 ==>
+ c t 3 0 0 0 ~= p t 3 0 0 0
+
+ -- | Given in Sorokina and Zeilfelder, p. 78.
+ prop_c2100_identity :: Tetrahedron -> Property
+ prop_c2100_identity t =
+ (volume t) > 0 ==>
+ c t 2 1 0 0 ~= (term1 - term2 + term3 - term4)
+ where
+ term1 = (1/3)*(p t 0 3 0 0)
+ term2 = (5/6)*(p t 3 0 0 0)
+ term3 = 3*(p t 2 1 0 0)
+ term4 = (3/2)*(p t 1 2 0 0)
+
+ -- | Given in Sorokina and Zeilfelder, p. 78.
+ prop_c1110_identity :: Tetrahedron -> Property
+ prop_c1110_identity t =
+ (volume t) > 0 ==>
+ c t 1 1 1 0 ~= (term1 + term2 - term3 - term4)
+ where
+ term1 = (1/3)*((p t 3 0 0 0) + (p t 0 3 0 0) + (p t 0 0 3 0))
+ term2 = (9/2)*(p t 1 1 1 0)
+ term3 = (3/4)*((p t 2 1 0 0) + (p t 1 2 0 0) + (p t 2 0 1 0))
+ term4 = (3/4)*((p t 1 0 2 0) + (p t 0 2 1 0) + (p t 0 1 2 0))
+