scubature-1.0.0.0: src/Numeric/Integration/SphericalSimplexCubature/Internal.hs
module Numeric.Integration.SphericalSimplexCubature.Internal
(orthants, SphericalSimplex, transformedIntegrand)
where
import Data.List.Index (imap)
import Data.Matrix (detLU, diagonalList, fromLists,
minorMatrix, toLists, zero, (<->))
import Data.Vector.Unboxed (Vector)
import qualified Data.Vector.Unboxed as V
type SphericalSimplex = [[Double]] -- square [v1, v2, v3, v4]
orthants :: Int -> [SphericalSimplex]
orthants n = reverse $ map (toLists . diagonalList n 0) (pm n)
where pm 2 = [[i, j] | i <- [-1, 1], j <- [-1, 1]]
pm k = [i : l | i <- [-1, 1], l <- pm (k-1)]
norm2 :: [Double] -> Double
norm2 v = sqrt $ sum $ zipWith (*) v v
dotproduct :: [Double] -> [Double] -> Double
dotproduct a b = sum $ zipWith (*) a b
scalarTimesList :: Double -> [Double] -> [Double]
scalarTimesList lambda = map (* lambda)
f :: SphericalSimplex -> [Double] -> [Double]
f vertices stu = foldr (zipWith (+)) (vertices!!0) terms
where
w = map (zipWith subtract (vertices!!0)) (tail vertices)
terms = zipWith scalarTimesList stu w
g :: SphericalSimplex -> [Double] -> [Double]
g vertices stu = scalarTimesList (1 / norm2 fstu) fstu
where fstu = f vertices stu
dg :: SphericalSimplex -> [Double] -> [[Double]]
dg vertices stu = zipWith (zipWith subtract) fviv1 nviv1
where
fstu = f vertices stu
invn = 1 / norm2 fstu
invn3 = invn*invn*invn
viv1 = map (zipWith subtract (head vertices)) (tail vertices)
nviv1 = map (scalarTimesList invn) viv1
dpi = map ((*invn3) . dotproduct fstu) viv1
fviv1 = map (`scalarTimesList` fstu) dpi
extProduct :: [[Double]] -> [Double]
extProduct vectors =
imap (\i mat -> (if even i then 1 else -1) * detLU mat) minorMatrices
where
dim = length vectors + 1
matrix = zero 1 dim <-> fromLists vectors
minorMatrices = map (\j -> minorMatrix 1 j matrix) [1 .. dim]
sigma :: SphericalSimplex -> [Double] -> Double
sigma ssimplex stu = norm2 $ extProduct (dg ssimplex stu)
transformedIntegrand :: SphericalSimplex -> ([Double] -> Double)
-> (Vector Double -> Double)
transformedIntegrand ssimplex integrand stu =
let stul = V.toList stu in
sigma ssimplex stul * integrand (g ssimplex stul)