module Data.VectorSpace
( module Data.AdditiveGroup
, VectorSpace(..), (^/), (^*)
, InnerSpace(..)
, lerp, 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
infixr 7 *^
class AdditiveGroup v => VectorSpace v where
type Scalar v :: *
(*^) :: Scalar v -> v -> v
infixr 7 <.>
class (VectorSpace v, AdditiveGroup (Scalar v)) => InnerSpace v where
(<.>) :: v -> v -> Scalar v
infixr 7 ^/
infixl 7 ^*
(^/) :: (VectorSpace v, s ~ Scalar v, Fractional s) => v -> s -> v
v ^/ s = (1/s) *^ v
(^*) :: (VectorSpace v, s ~ Scalar v) => v -> s -> v
(^*) = flip (*^)
lerp :: VectorSpace v => v -> v -> Scalar v -> v
lerp a b t = a ^+^ t *^ (b ^-^ a)
magnitudeSq :: (InnerSpace v, s ~ Scalar v) => v -> s
magnitudeSq v = v <.> v
magnitude :: (InnerSpace v, s ~ Scalar v, Floating s) => v -> s
magnitude = sqrt . magnitudeSq
normalized :: (InnerSpace v, s ~ Scalar v, Floating s) => v -> v
normalized v = v ^/ magnitude v
project :: (InnerSpace v, s ~ Scalar v, Fractional s) => v -> v -> v
project u v = ((v <.> u) / magnitudeSq u) *^ u
#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