1 {-# LANGUAGE RebindableSyntax #-}
2 {-# LANGUAGE ScopedTypeVariables #-}
3 {-# LANGUAGE TypeFamilies #-}
8 import Data.Vector.Fixed (Arity, N1)
12 import NumericPrelude hiding ((*), abs)
13 import qualified NumericPrelude as NP ((*))
14 import qualified Algebra.Field as Field
17 -- | Solve the system m' * x = b', where m' is upper-triangular. Will
18 -- probably crash if m' is non-singular. The result is the vector x.
22 -- >>> let identity = fromList [[1,0,0],[0,1,0],[0,0,1]] :: Mat3 Double
23 -- >>> let b = vec3d (1, 2, 3::Double)
24 -- >>> forward_substitute identity b
25 -- ((1.0),(2.0),(3.0))
26 -- >>> (forward_substitute identity b) == b
29 -- >>> let m = fromList [[1,0],[1,1]] :: Mat2 Double
30 -- >>> let b = vec2d (1, 1::Double)
31 -- >>> forward_substitute m b
34 forward_substitute :: forall a m. (Field.C a, Arity m)
38 forward_substitute m' b' = x'
42 -- Convenient accessor for the elements of b'.
46 -- Convenient accessor for the elements of m'.
50 -- Convenient accessor for the elements of x'.
54 -- The second argument to lambda should always be zero here, so we
56 lambda :: Int -> Int -> a
57 lambda 0 _ = (b 0) / (m 0 0)
58 lambda k _ = ((b k) - sum [ (m k j) NP.* (x j) |
59 j <- [0..k-1] ]) / (m k k)
62 -- | Solve the system m*x = b, where m is lower-triangular. Will
63 -- probably crash if m is non-singular. The result is the vector x.
67 -- >>> let identity = fromList [[1,0,0],[0,1,0],[0,0,1]] :: Mat3 Double
68 -- >>> let b = vec3d (1, 2, 3::Double)
69 -- >>> backward_substitute identity b
70 -- ((1.0),(2.0),(3.0))
71 -- >>> (backward_substitute identity b) == b
74 backward_substitute :: (Field.C a, Arity m)
78 backward_substitute m b =
79 forward_substitute (transpose m) b
82 -- | Solve the linear system m*x = b where m is positive definite.
84 solve_positive_definite :: Mat v w a -> Mat w z a
85 solve_positive_definite m b = x
88 -- First we solve r^T * y == b for y. Then let y=r*x
89 rx = forward_substitute (transpose r) b
90 -- Now solve r*x == b.