module Data.LinearMap.HerMetric (
HerMetric, HerMetric'
, metricSq, metricSq', metric, metric', metrics, metrics'
, projector, projector'
, adjoint
, transformMetric, transformMetric'
, dualiseMetric, dualiseMetric'
, HasMetric(..)
, (^<.>)
, metriScale, metriScale'
) where
import Prelude hiding ((^))
import Data.VectorSpace
import Data.LinearMap
import Data.Basis
import Data.MemoTrie
import Control.Applicative
import Data.Manifold.Types
infixr 7 <.>^, ^<.>
newtype HerMetric v = HerMetric { getHerMetric :: v :-* DualSpace v }
instance HasMetric v => AdditiveGroup (HerMetric v) where
zeroV = HerMetric zeroV
negateV (HerMetric m) = HerMetric $ negateV m
HerMetric m ^+^ HerMetric n = HerMetric $ m ^+^ n
instance HasMetric v => VectorSpace (HerMetric v) where
type Scalar (HerMetric v) = Scalar v
s *^ (HerMetric m) = HerMetric $ s *^ m
newtype HerMetric' v = HerMetric' { dualMetric :: DualSpace v :-* v }
instance (HasMetric v) => AdditiveGroup (HerMetric' v) where
zeroV = HerMetric' zeroV
negateV (HerMetric' m) = HerMetric' $ negateV m
HerMetric' m ^+^ HerMetric' n = HerMetric' $ m ^+^ n
instance (HasMetric v) => VectorSpace (HerMetric' v) where
type Scalar (HerMetric' v) = Scalar v
s *^ (HerMetric' m) = HerMetric' $ s *^ m
projector :: HasMetric v => DualSpace v -> HerMetric v
projector u = HerMetric (linear $ \v -> u ^* (u<.>^v))
projector' :: HasMetric v => v -> HerMetric' v
projector' v = HerMetric' . linear $ \u -> v ^* (v^<.>u)
metricSq :: HasMetric v => HerMetric v -> v -> Scalar v
metricSq (HerMetric m) v = lapply m v <.>^ v
metricSq' :: HasMetric v => HerMetric' v -> DualSpace v -> Scalar v
metricSq' (HerMetric' m) u = lapply m u ^<.> u
metric :: (HasMetric v, Floating (Scalar v)) => HerMetric v -> v -> Scalar v
metric (HerMetric m) v = sqrt $ lapply m v <.>^ v
metric' :: (HasMetric v, Floating (Scalar v)) => HerMetric' v -> DualSpace v -> Scalar v
metric' (HerMetric' m) u = sqrt $ lapply m u ^<.> u
metriScale :: (HasMetric v, Floating (Scalar v)) => HerMetric v -> v -> v
metriScale m v = metric m v *^ v
metriScale' :: (HasMetric v, Floating (Scalar v))
=> HerMetric' v -> DualSpace v -> DualSpace v
metriScale' m v = metric' m v *^ v
metrics :: (HasMetric v, Floating (Scalar v)) => HerMetric v -> [v] -> Scalar v
metrics m vs = sqrt . sum $ metricSq m <$> vs
metrics' :: (HasMetric v, Floating (Scalar v)) => HerMetric' v -> [DualSpace v] -> Scalar v
metrics' m vs = sqrt . sum $ metricSq' m <$> vs
transformMetric :: (HasMetric v, HasMetric w, Scalar v ~ Scalar w)
=> (w :-* v) -> HerMetric v -> HerMetric w
transformMetric t (HerMetric m) = HerMetric $ adjoint t *.* m *.* t
transformMetric' :: ( HasMetric v, HasMetric w, Scalar v ~ Scalar w )
=> (v :-* w) -> HerMetric' v -> HerMetric' w
transformMetric' t (HerMetric' m)
= HerMetric' $ t *.* m *.* adjoint t
dualiseMetric :: (HasMetric v, HasMetric (DualSpace v))
=> HerMetric (DualSpace v) -> HerMetric' v
dualiseMetric (HerMetric m) = HerMetric' $ linear doubleDual' *.* m
dualiseMetric' :: (HasMetric v, HasMetric (DualSpace v))
=> HerMetric' v -> HerMetric (DualSpace v)
dualiseMetric' (HerMetric' m) = HerMetric $ linear doubleDual *.* m
class ( HasBasis v, VectorSpace (Scalar v), HasTrie (Basis v)
, VectorSpace (DualSpace v), HasBasis (DualSpace v)
, Scalar v ~ Scalar (DualSpace v), Basis v ~ Basis (DualSpace v) )
=> HasMetric v where
type DualSpace v :: *
type DualSpace v = v
(<.>^) :: DualSpace v -> v -> Scalar v
functional :: (v -> Scalar v) -> DualSpace v
doubleDual :: HasMetric (DualSpace v) => v -> DualSpace (DualSpace v)
doubleDual' :: HasMetric (DualSpace v) => DualSpace (DualSpace v) -> v
(^<.>) :: HasMetric v => v -> DualSpace v -> Scalar v
ket ^<.> bra = bra <.>^ ket
instance (VectorSpace k) => HasMetric (ZeroDim k) where
Origin<.>^Origin = zeroV
functional _ = Origin
doubleDual = id; doubleDual'= id
instance HasMetric Double where
(<.>^) = (<.>)
functional f = f 1
doubleDual = id; doubleDual'= id
instance ( HasMetric v, HasMetric w, Scalar v ~ Scalar w
, HasMetric (DualSpace v), DualSpace (DualSpace v) ~ v
, HasMetric (DualSpace w), DualSpace (DualSpace w) ~ w
) => HasMetric (v,w) where
type DualSpace (v,w) = (DualSpace v, DualSpace w)
(v,w)<.>^(v',w') = v<.>^v' ^+^ w<.>^w'
functional f = (functional $ f . (,zeroV), functional $ f . (zeroV,))
doubleDual = id; doubleDual'= id
adjoint :: (HasMetric v, HasMetric w, Scalar w ~ Scalar v)
=> (v :-* w) -> DualSpace w :-* DualSpace v
adjoint m = linear $ \w -> functional $ \v
-> w <.>^lapply m v
metrConst :: (HasMetric v, v ~ DualSpace v, Num (Scalar v)) => Scalar v -> HerMetric v
metrConst = HerMetric . linear . (*^)
instance (HasMetric v, v ~ DualSpace v, Num (Scalar v)) => Num (HerMetric v) where
fromInteger = metrConst . fromInteger
(+) = (^+^)
negate = negateV
HerMetric m * HerMetric n = HerMetric $ m *.* n
abs = error "abs undefined for HerMetric"
signum = error "signum undefined for HerMetric"
metrNumFun :: (HasMetric v, v ~ Scalar v, v ~ DualSpace v, Num v)
=> (v -> v) -> HerMetric v -> HerMetric v
metrNumFun f (HerMetric m) = HerMetric . linear . (*^) . f $ lapply m 1
instance (HasMetric v, v ~ Scalar v, v ~ DualSpace v, Fractional v)
=> Fractional (HerMetric v) where
fromRational = metrConst . fromRational
recip = metrNumFun recip
instance (HasMetric v, v ~ Scalar v, v ~ DualSpace v, Floating v)
=> Floating (HerMetric v) where
pi = metrConst pi
sqrt = metrNumFun sqrt
exp = metrNumFun exp
log = metrNumFun log
sin = metrNumFun sin
cos = metrNumFun cos
tan = metrNumFun tan
asin = metrNumFun asin
acos = metrNumFun acos
atan = metrNumFun atan
sinh = metrNumFun sinh
cosh = metrNumFun cosh
asinh = metrNumFun asinh
atanh = metrNumFun atanh
acosh = metrNumFun acosh