-- 1.0
--
-- >>> value_at Examples.trilinear 1 3 0
--- 4.0
+-- 5.0
--
value_at :: Values3D -> Int -> Int -> Int -> Double
value_at v3d i j k
-- Put the most common case first!
- | (i >= 0) && (j >= 0) && (k >= 0) =
+ | (valid_i i) && (valid_j j) && (valid_k k) =
idx v3d i j k
- -- The next three are from the first line in (7.3).
- | (i == -1) && (j >= 0) && (k >= 0) =
- 2*(value_at v3d 0 j k) - (value_at v3d 1 j k)
-
- | (i >= 0) && (j == -1) && (k >= 0) =
- 2*(value_at v3d i 0 k) - (value_at v3d i 1 k)
-
- | (i >= 0) && (j >= 0) && (k == -1) =
- 2*(value_at v3d i j 0) - (value_at v3d i j 1)
-
- -- The next two are from the second line in (7.3).
- | (i == -1) && (j == -1) && (k >= 0) =
- 2*(value_at v3d i 0 k) - (value_at v3d i 1 k)
-
- | (i == -1) && (j == ysize) && (k >= 0) =
- 2*(value_at v3d i (ysize - 1) k) - (value_at v3d i (ysize - 2) k)
-
- -- The next two are from the third line in (7.3).
- | (i == -1) && (j >= 0) && (k == -1) =
- 2*(value_at v3d i j 0) - (value_at v3d i j 1)
-
- | (i == -1) && (j >= 0) && (k == zsize) =
- 2*(value_at v3d i j (zsize - 1)) - (value_at v3d i j (zsize - 2))
-
- -- Repeat the above (j and k) cases for i >= 0.
- | (i >= 0) && (j == -1) && (k == -1) =
- 2*(value_at v3d i j 0) - (value_at v3d i j 1)
-
- | (i == xsize) && (j == -1) && (k >= 0) =
- 2*(value_at v3d (xsize - 1) j k) - (value_at v3d (xsize - 2) j k)
-
- -- These two cases I made up.
- | (i == -1) && (j == -1) && (k == -1) =
- 2*(value_at v3d i j 0) - (value_at v3d i j 1)
-
- | (i == xsize) && (j == ysize) && (k == zsize) =
- 2*(value_at v3d i j (zsize - 1)) - (value_at v3d i j (zsize - 2))
+ -- The next three are from the first line in (7.3). Analogous cases
+ -- have been added where the indices are one-too-big. These are the
+ -- "one index is bad" cases.
+ | not (valid_i i) =
+ if (i == -1)
+ then
+ 2*(value_at v3d 0 j k) - (value_at v3d 1 j k)
+ else
+ 2*(value_at v3d (i-1) j k) - (value_at v3d (i-2) j k)
+
+ | not (valid_j j) =
+ if (j == -1)
+ then
+ 2*(value_at v3d i 0 k) - (value_at v3d i 1 k)
+ else
+ 2*(value_at v3d i (j-1) k) - (value_at v3d i (j-2) k)
+
+ | not (valid_k k) =
+ if (k == -1)
+ then
+ 2*(value_at v3d i j 0) - (value_at v3d i j 1)
+ else
+ 2*(value_at v3d i j (k-1)) - (value_at v3d i j (k-2))
| otherwise =
let istr = show i
where
(xsize, ysize, zsize) = dims v3d
+ valid_i :: Int -> Bool
+ valid_i i' = (i' >= 0) && (i' < xsize)
+
+ valid_j :: Int -> Bool
+ valid_j j' = (j' >= 0) && (j' < ysize)
+
+ valid_k :: Int -> Bool
+ valid_k k' = (k' >= 0) && (k' < zsize)
+
+
-- | Given a three-dimensional list of 'Double' and a set of 3D
-- coordinates (i,j,k), constructs and returns the 'FunctionValues'
| i <- [0..2],
j <- [0..2],
k <- [0..2],
+ c0 <- cs,
t <- tetrahedra c0,
let p = polynomial t,
let i' = fromIntegral i,
let k' = fromIntegral k]
where
g = make_grid 1 trilinear
- c0 = cube_at g 1 1 1
+ cs = [ cube_at g ci cj ck | ci <- [0..2], cj <- [0..2], ck <- [0..2] ]
test_zeros_reproduced :: Assertion
k <- [0..2],
let i' = fromIntegral i,
let j' = fromIntegral j,
- let k' = fromIntegral k]
+ let k' = fromIntegral k,
+ c0 <- cs,
+ t0 <- tetrahedra c0,
+ let p = polynomial t0 ]
where
g = make_grid 1 zeros
- c0 = cube_at g 1 1 1
- t0 = tetrahedron c0 0
- p = polynomial t0
+ cs = [ cube_at g ci cj ck | ci <- [0..2], cj <- [0..2], ck <- [0..2] ]
-- | Make sure we can reproduce a 9x9x9 trilinear from the 3x3x3 one.