+
+-- | Takes a 'FunctionValues' and a function that transforms one
+-- 'Cardinal' to another (called a rotation). Then it applies the
+-- rotation to each element of the 'FunctionValues' object, and
+-- returns the result.
+rotate :: (Cardinal -> Cardinal) -> FunctionValues -> FunctionValues
+rotate rotation fv =
+ FunctionValues { front = eval fv (rotation F),
+ back = eval fv (rotation B),
+ left = eval fv (rotation L),
+ right = eval fv (rotation R),
+ down = eval fv (rotation D),
+ top = eval fv (rotation T),
+ front_left = eval fv (rotation FL),
+ front_right = eval fv (rotation FR),
+ front_down = eval fv (rotation FD),
+ front_top = eval fv (rotation FT),
+ back_left = eval fv (rotation BL),
+ back_right = eval fv (rotation BR),
+ back_down = eval fv (rotation BD),
+ back_top = eval fv (rotation BT),
+ left_down = eval fv (rotation LD),
+ left_top = eval fv (rotation LT),
+ right_down = eval fv (rotation RD),
+ right_top = eval fv (rotation RT),
+ front_left_down = eval fv (rotation FLD),
+ front_left_top = eval fv (rotation FLT),
+ front_right_down = eval fv (rotation FRD),
+ front_right_top = eval fv (rotation FRT),
+ back_left_down = eval fv (rotation BLD),
+ back_left_top = eval fv (rotation BLT),
+ back_right_down = eval fv (rotation BRD),
+ back_right_top = eval fv (rotation BRT),
+ interior = interior fv }
+
+
+
+-- | Ensure that the trilinear values wind up where we think they
+-- should.
+test_directions :: Assertion
+test_directions =
+ assertTrue "all direction functions work" (and equalities)
+ where
+ fvs = make_values trilinear 1 1 1
+ equalities = [ interior fvs == 4,
+ front fvs == 1,
+ back fvs == 7,
+ left fvs == 2,
+ right fvs == 6,
+ down fvs == 3,
+ top fvs == 5,
+ front_left fvs == 1,
+ front_right fvs == 1,
+ front_down fvs == 1,
+ front_top fvs == 1,
+ back_left fvs == 3,
+ back_right fvs == 11,
+ back_down fvs == 5,
+ back_top fvs == 9,
+ left_down fvs == 2,
+ left_top fvs == 2,
+ right_down fvs == 4,
+ right_top fvs == 8,
+ front_left_down fvs == 1,
+ front_left_top fvs == 1,
+ front_right_down fvs == 1,
+ front_right_top fvs == 1,
+ back_left_down fvs == 3,
+ back_left_top fvs == 3,
+ back_right_down fvs == 7,
+ back_right_top fvs == 15]
+
+
+function_values_tests :: TestTree
+function_values_tests =
+ testGroup "FunctionValues tests"
+ [ testCase "test directions" test_directions ]
+
+
+prop_x_rotation_doesnt_affect_front :: FunctionValues -> Bool
+prop_x_rotation_doesnt_affect_front fv0 =
+ expr1 == expr2
+ where
+ fv1 = rotate cwx fv0
+ expr1 = front fv0
+ expr2 = front fv1
+
+prop_x_rotation_doesnt_affect_back :: FunctionValues -> Bool
+prop_x_rotation_doesnt_affect_back fv0 =
+ expr1 == expr2
+ where
+ fv1 = rotate cwx fv0
+ expr1 = back fv0
+ expr2 = back fv1
+
+
+prop_y_rotation_doesnt_affect_left :: FunctionValues -> Bool
+prop_y_rotation_doesnt_affect_left fv0 =
+ expr1 == expr2
+ where
+ fv1 = rotate cwy fv0
+ expr1 = left fv0
+ expr2 = left fv1
+
+prop_y_rotation_doesnt_affect_right :: FunctionValues -> Bool
+prop_y_rotation_doesnt_affect_right fv0 =
+ expr1 == expr2
+ where
+ fv1 = rotate cwy fv0
+ expr1 = right fv0
+ expr2 = right fv1
+
+
+prop_z_rotation_doesnt_affect_down :: FunctionValues -> Bool
+prop_z_rotation_doesnt_affect_down fv0 =
+ expr1 == expr2
+ where
+ fv1 = rotate cwz fv0
+ expr1 = down fv0
+ expr2 = down fv1
+
+
+prop_z_rotation_doesnt_affect_top :: FunctionValues -> Bool
+prop_z_rotation_doesnt_affect_top fv0 =
+ expr1 == expr2
+ where
+ fv1 = rotate cwz fv0
+ expr1 = top fv0
+ expr2 = top fv1
+
+
+function_values_properties :: TestTree
+function_values_properties =
+ let tp = testProperty
+ in
+ testGroup "FunctionValues properties" [
+ tp "x rotation doesn't affect front" prop_x_rotation_doesnt_affect_front,
+ tp "x rotation doesn't affect back" prop_x_rotation_doesnt_affect_back,
+ tp "y rotation doesn't affect left" prop_y_rotation_doesnt_affect_left,
+ tp "y rotation doesn't affect right" prop_y_rotation_doesnt_affect_right,
+ tp "z rotation doesn't affect top" prop_z_rotation_doesnt_affect_top,
+ tp "z rotation doesn't affect down" prop_z_rotation_doesnt_affect_down ]