module Data.AffineSpace
(
AffineSpace(..), (.-^), distanceSq, distance, alerp, affineCombo
) where
import Control.Applicative (liftA2)
import Data.Ratio
import Foreign.C.Types (CSChar, CInt, CShort, CLong, CLLong, CIntMax, CFloat, CDouble)
import Control.Arrow(first)
import Data.VectorSpace
infixl 6 .+^, .-^
infix 6 .-.
class AdditiveGroup (Diff p) => AffineSpace p where
type Diff p
(.-.) :: p -> p -> Diff p
(.+^) :: p -> Diff p -> p
(.-^) :: AffineSpace p => p -> Diff p -> p
p .-^ v = p .+^ negateV v
distanceSq :: (AffineSpace p, v ~ Diff p, InnerSpace v) =>
p -> p -> Scalar v
distanceSq = (fmap.fmap) magnitudeSq (.-.)
distance :: (AffineSpace p, v ~ Diff p, InnerSpace v
, s ~ Scalar v, Floating (Scalar v))
=> p -> p -> s
distance = (fmap.fmap) sqrt distanceSq
alerp :: (AffineSpace p, VectorSpace (Diff p)) =>
p -> p -> Scalar (Diff p) -> p
alerp p p' s = p .+^ (s *^ (p' .-. p))
affineCombo :: (AffineSpace p, v ~ Diff p, VectorSpace v) => p -> [(p,Scalar v)] -> p
affineCombo z l = z .+^ linearCombo (map (first (.-. z)) l)
#define ScalarTypeCon(con,t) \
instance con => AffineSpace (t) where \
{ type Diff (t) = t \
; (.-.) = () \
; (.+^) = (+) }
#define ScalarType(t) ScalarTypeCon((),t)
ScalarType(Int)
ScalarType(Integer)
ScalarType(Double)
ScalarType(Float)
ScalarType(CSChar)
ScalarType(CInt)
ScalarType(CShort)
ScalarType(CLong)
ScalarType(CLLong)
ScalarType(CIntMax)
ScalarType(CDouble)
ScalarType(CFloat)
ScalarTypeCon(Integral a,Ratio a)
instance (AffineSpace p, AffineSpace q) => AffineSpace (p,q) where
type Diff (p,q) = (Diff p, Diff q)
(p,q) .-. (p',q') = (p .-. p', q .-. q')
(p,q) .+^ (u,v) = (p .+^ u, q .+^ v)
instance (AffineSpace p, AffineSpace q, AffineSpace r) => AffineSpace (p,q,r) where
type Diff (p,q,r) = (Diff p, Diff q, Diff r)
(p,q,r) .-. (p',q',r') = (p .-. p', q .-. q', r .-. r')
(p,q,r) .+^ (u,v,w) = (p .+^ u, q .+^ v, r .+^ w)
instance (AffineSpace p) => AffineSpace (a -> p) where
type Diff (a -> p) = a -> Diff p
(.-.) = liftA2 (.-.)
(.+^) = liftA2 (.+^)