{-# LANGUAGE MultiParamTypeClasses, TypeOperators
, TypeFamilies, UndecidableInstances, CPP
, FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wall #-}
module Data.VectorSpace
( module Data.AdditiveGroup
, VectorSpace(..), (^/), (^*)
, InnerSpace(..)
, lerp, linearCombo, magnitudeSq, magnitude, normalized, project
) where
import Control.Applicative (liftA2)
import Data.Complex hiding (magnitude)
import Foreign.C.Types (CSChar, CInt, CShort, CLong, CLLong, CIntMax, CFloat, CDouble)
import Data.Ratio
import Data.AdditiveGroup
import Data.MemoTrie
import Data.VectorSpace.Generic
import qualified GHC.Generics as Gnrx
import GHC.Generics (Generic, (:*:)(..))
infixr 7 *^
class AdditiveGroup v => VectorSpace v where
type Scalar v :: *
type Scalar v = Scalar (VRep v)
(*^) :: Scalar v -> v -> v
default (*^) :: (Generic v, VectorSpace (VRep v), Scalar (VRep v) ~ Scalar v)
=> Scalar v -> v -> v
μ *^ v = Gnrx.to (μ *^ Gnrx.from v :: VRep v)
{-# INLINE (*^) #-}
infixr 7 <.>
class (VectorSpace v, AdditiveGroup (Scalar v)) => InnerSpace v where
(<.>) :: v -> v -> Scalar v
default (<.>) :: (Generic v, InnerSpace (VRep v), Scalar (VRep v) ~ Scalar v)
=> v -> v -> Scalar v
v<.>w = (Gnrx.from v :: VRep v) <.> Gnrx.from w
{-# INLINE (<.>) #-}
infixr 7 ^/
infixl 7 ^*
(^/) :: (VectorSpace v, s ~ Scalar v, Fractional s) => v -> s -> v
v ^/ s = recip s *^ v
{-# INLINE (^/) #-}
(^*) :: (VectorSpace v, s ~ Scalar v) => v -> s -> v
(^*) = flip (*^)
{-# INLINE (^*) #-}
lerp :: VectorSpace v => v -> v -> Scalar v -> v
lerp a b t = a ^+^ t *^ (b ^-^ a)
{-# INLINE lerp #-}
linearCombo :: VectorSpace v => [(v,Scalar v)] -> v
linearCombo ps = sumV [v ^* s | (v,s) <- ps]
{-# INLINE linearCombo #-}
magnitudeSq :: (InnerSpace v, s ~ Scalar v) => v -> s
magnitudeSq v = v <.> v
{-# INLINE magnitudeSq #-}
magnitude :: (InnerSpace v, s ~ Scalar v, Floating s) => v -> s
magnitude = sqrt . magnitudeSq
{-# INLINE magnitude #-}
normalized :: (InnerSpace v, s ~ Scalar v, Floating s) => v -> v
normalized v = v ^/ magnitude v
{-# INLINE normalized #-}
project :: (InnerSpace v, s ~ Scalar v, Fractional s) => v -> v -> v
project u v = ((v <.> u) / magnitudeSq u) *^ u
{-# INLINE project #-}
#define ScalarType(t) \
instance VectorSpace (t) where \
{ type Scalar (t) = (t) \
; (*^) = (*) } ; \
instance InnerSpace (t) where (<.>) = (*)
ScalarType(Int)
ScalarType(Integer)
ScalarType(Double)
ScalarType(Float)
ScalarType(CSChar)
ScalarType(CInt)
ScalarType(CShort)
ScalarType(CLong)
ScalarType(CLLong)
ScalarType(CIntMax)
ScalarType(CDouble)
ScalarType(CFloat)
instance Integral a => VectorSpace (Ratio a) where
type Scalar (Ratio a) = Ratio a
(*^) = (*)
instance Integral a => InnerSpace (Ratio a) where (<.>) = (*)
instance (RealFloat v, VectorSpace v) => VectorSpace (Complex v) where
type Scalar (Complex v) = Scalar v
s*^(u :+ v) = s*^u :+ s*^v
instance (RealFloat v, InnerSpace v)
=> InnerSpace (Complex v) where
(u :+ v) <.> (u' :+ v') = (u <.> u') ^+^ (v <.> v')
instance ( VectorSpace u, s ~ Scalar u
, VectorSpace v, s ~ Scalar v )
=> VectorSpace (u,v) where
type Scalar (u,v) = Scalar u
s *^ (u,v) = (s*^u,s*^v)
instance ( InnerSpace u, s ~ Scalar u
, InnerSpace v, s ~ Scalar v )
=> InnerSpace (u,v) where
(u,v) <.> (u',v') = (u <.> u') ^+^ (v <.> v')
instance ( VectorSpace u, s ~ Scalar u
, VectorSpace v, s ~ Scalar v
, VectorSpace w, s ~ Scalar w )
=> VectorSpace (u,v,w) where
type Scalar (u,v,w) = Scalar u
s *^ (u,v,w) = (s*^u,s*^v,s*^w)
instance ( InnerSpace u, s ~ Scalar u
, InnerSpace v, s ~ Scalar v
, InnerSpace w, s ~ Scalar w )
=> InnerSpace (u,v,w) where
(u,v,w) <.> (u',v',w') = u<.>u' ^+^ v<.>v' ^+^ w<.>w'
instance ( VectorSpace u, s ~ Scalar u
, VectorSpace v, s ~ Scalar v
, VectorSpace w, s ~ Scalar w
, VectorSpace x, s ~ Scalar x )
=> VectorSpace (u,v,w,x) where
type Scalar (u,v,w,x) = Scalar u
s *^ (u,v,w,x) = (s*^u,s*^v,s*^w,s*^x)
instance ( InnerSpace u, s ~ Scalar u
, InnerSpace v, s ~ Scalar v
, InnerSpace w, s ~ Scalar w
, InnerSpace x, s ~ Scalar x )
=> InnerSpace (u,v,w,x) where
(u,v,w,x) <.> (u',v',w',x') = u<.>u' ^+^ v<.>v' ^+^ w<.>w' ^+^ x<.>x'
instance VectorSpace v => VectorSpace (Maybe v) where
type Scalar (Maybe v) = Scalar v
(*^) s = fmap (s *^)
instance VectorSpace v => VectorSpace (a -> v) where
type Scalar (a -> v) = a -> Scalar v
(*^) = liftA2 (*^)
instance InnerSpace v => InnerSpace (a -> v) where
(<.>) = liftA2 (<.>)
instance (HasTrie a, VectorSpace v) => VectorSpace (a :->: v) where
type Scalar (a :->: v) = Scalar v
(*^) s = fmap (s *^)
instance InnerSpace a => InnerSpace (Maybe a) where
Nothing <.> _ = zeroV
_ <.> Nothing = zeroV
Just u <.> Just v = u <.> v
instance VectorSpace a => VectorSpace (Gnrx.Rec0 a s) where
type Scalar (Gnrx.Rec0 a s) = Scalar a
μ *^ Gnrx.K1 v = Gnrx.K1 $ μ*^v
{-# INLINE (*^) #-}
instance VectorSpace (f p) => VectorSpace (Gnrx.M1 i c f p) where
type Scalar (Gnrx.M1 i c f p) = Scalar (f p)
μ *^ Gnrx.M1 v = Gnrx.M1 $ μ*^v
{-# INLINE (*^) #-}
instance (VectorSpace (f p), VectorSpace (g p), Scalar (f p) ~ Scalar (g p))
=> VectorSpace ((f :*: g) p) where
type Scalar ((f:*:g) p) = Scalar (f p)
μ *^ (x:*:y) = μ*^x :*: μ*^y
{-# INLINE (*^) #-}
instance InnerSpace a => InnerSpace (Gnrx.Rec0 a s) where
Gnrx.K1 v <.> Gnrx.K1 w = v<.>w
{-# INLINE (<.>) #-}
instance InnerSpace (f p) => InnerSpace (Gnrx.M1 i c f p) where
Gnrx.M1 v <.> Gnrx.M1 w = v<.>w
{-# INLINE (<.>) #-}
instance ( InnerSpace (f p), InnerSpace (g p)
, Scalar (f p) ~ Scalar (g p), Num (Scalar (f p)) )
=> InnerSpace ((f :*: g) p) where
(x:*:y) <.> (ξ:*:υ) = x<.>ξ + y<.>υ
{-# INLINE (<.>) #-}