{-# LANGUAGE DefaultSignatures      #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}
-- |
-- Module      :  Data.VectorSpace
-- Copyright   :  (c) Antony Courtney and Henrik Nilsson, Yale University, 2003
-- License     :  BSD-style (see the LICENSE file in the distribution)
--
-- Maintainer  :  ivan.perez@keera.co.uk
-- Stability   :  provisional
-- Portability :  non-portable (GHC extensions)
--
-- Vector space type relation and basic instances.
--
-- There can be other implementations of VectorSpace, for example you could
-- implement it with linear like this:
--
-- @
-- {-# LANGUAGE FlexibleInstances     #-}
-- {-# LANGUAGE MultiParamTypeClasses #-}
--
-- import FRP.Yampa
-- import Linear    as L
--
-- instance (Eq a, Floating a) => VectorSpace (V2 a) a where
--   zeroVector = L.zero
--   (*^) = (L.*^)
--   (^/) = (L.^/)
--   negateVector = L.negated
--   (^+^) = (L.^+^)
--   (^-^) = (L.^-^)
--   dot = L.dot
-- @
--
-- Using this you could benefit from more advanced vector operators and the
-- improved performance linear brings while keeping a simple type class
-- interface with few dependencies.
module Data.VectorSpace where

infixr *^
infixl ^/
infix 7 `dot`
infixl 6 ^+^, ^-^

-- | Vector space type relation.
--
--   A vector space is a set (type) closed under addition and multiplication by
--   a scalar. The type of the scalar is the /field/ of the vector space, and
--   it is said that @v@ is a vector space over @a@.
--
--   The encoding uses a type class |VectorSpace| @v a@, where @v@ represents
--   the type of the vectors and @a@ represents the types of the scalars.
class VectorSpace v a | v -> a where

  -- | Vector with no magnitude (unit for addition).
  zeroVector :: v

  -- | Multiplication by a scalar.
  (*^) :: a -> v -> v

  -- | Division by a scalar.
  (^/) :: v -> a -> v
  default (^/) :: Fractional a => v -> a -> v
  v
v ^/ a
a = (a
1 forall a. Fractional a => a -> a -> a
/ a
a) forall v a. VectorSpace v a => a -> v -> v
*^ v
v

  -- | Vector addition
  (^+^) :: v -> v -> v

  -- | Vector subtraction
  (^-^) :: v -> v -> v
  v
v1 ^-^ v
v2 = v
v1 forall v a. VectorSpace v a => v -> v -> v
^+^ forall v a. VectorSpace v a => v -> v
negateVector v
v2

  -- | Vector negation. Addition with a negated vector should be
  --   same as subtraction.
  negateVector :: v -> v
  default negateVector :: Num a => v -> v
  negateVector v
v = (-a
1) forall v a. VectorSpace v a => a -> v -> v
*^ v
v

  -- | Dot product (also known as scalar or inner product).
  --
  -- For two vectors, mathematically represented as @a = a1,a2,...,an@ and @b
  -- = b1,b2,...,bn@, the dot product is @a . b = a1*b1 + a2*b2 + ... +
  -- an*bn@.
  --
  -- Some properties are derived from this. The dot product of a vector with
  -- itself is the square of its magnitude ('norm'), and the dot product of
  -- two orthogonal vectors is zero.
  dot :: v -> v -> a

  -- | Vector's norm (also known as magnitude).
  --
  -- For a vector represented mathematically as @a = a1,a2,...,an@, the norm
  -- is the square root of @a1^2 + a2^2 + ... + an^2@.
  norm :: v -> a
  default norm :: Floating a => v -> a
  norm v
v = forall a. Floating a => a -> a
sqrt (v
v forall v a. VectorSpace v a => v -> v -> a
`dot` v
v)

  -- | Return a vector with the same origin and orientation (angle), but such
  -- that the norm is one (the unit for multiplication by a scalar).
  normalize :: v -> v
  default normalize :: (Eq a, Floating a) => v -> v
  normalize v
v = if a
nv forall a. Eq a => a -> a -> Bool
/= a
0 then v
v forall v a. VectorSpace v a => v -> a -> v
^/ a
nv else forall a. HasCallStack => [Char] -> a
error [Char]
"normalize: zero vector"
    where
      nv :: a
nv = forall v a. VectorSpace v a => v -> a
norm v
v

-- | Vector space instance for 'Float's, with 'Float' scalars.
instance VectorSpace Float Float where
  zeroVector :: Float
zeroVector = Float
0

  Float
a *^ :: Float -> Float -> Float
*^ Float
x = Float
a forall a. Num a => a -> a -> a
* Float
x

  Float
x ^/ :: Float -> Float -> Float
^/ Float
a = Float
x forall a. Fractional a => a -> a -> a
/ Float
a

  negateVector :: Float -> Float
negateVector Float
x = -Float
x

  Float
x1 ^+^ :: Float -> Float -> Float
^+^ Float
x2 = Float
x1 forall a. Num a => a -> a -> a
+ Float
x2

  Float
x1 ^-^ :: Float -> Float -> Float
^-^ Float
x2 = Float
x1 forall a. Num a => a -> a -> a
- Float
x2

  Float
x1 dot :: Float -> Float -> Float
`dot` Float
x2 = Float
x1 forall a. Num a => a -> a -> a
* Float
x2

-- | Vector space instance for 'Double's, with 'Double' scalars.
instance VectorSpace Double Double where
  zeroVector :: Double
zeroVector = Double
0

  Double
a *^ :: Double -> Double -> Double
*^ Double
x = Double
a forall a. Num a => a -> a -> a
* Double
x

  Double
x ^/ :: Double -> Double -> Double
^/ Double
a = Double
x forall a. Fractional a => a -> a -> a
/ Double
a

  negateVector :: Double -> Double
negateVector Double
x = -Double
x

  Double
x1 ^+^ :: Double -> Double -> Double
^+^ Double
x2 = Double
x1 forall a. Num a => a -> a -> a
+ Double
x2

  Double
x1 ^-^ :: Double -> Double -> Double
^-^ Double
x2 = Double
x1 forall a. Num a => a -> a -> a
- Double
x2

  Double
x1 dot :: Double -> Double -> Double
`dot` Double
x2 = Double
x1 forall a. Num a => a -> a -> a
* Double
x2

-- | Vector space instance for pairs of 'Floating' point numbers.
instance (Eq a, Floating a) => VectorSpace (a, a) a where
  zeroVector :: (a, a)
zeroVector = (a
0, a
0)

  a
a *^ :: a -> (a, a) -> (a, a)
*^ (a
x, a
y) = (a
a forall a. Num a => a -> a -> a
* a
x, a
a forall a. Num a => a -> a -> a
* a
y)

  (a
x, a
y) ^/ :: (a, a) -> a -> (a, a)
^/ a
a = (a
x forall a. Fractional a => a -> a -> a
/ a
a, a
y forall a. Fractional a => a -> a -> a
/ a
a)

  negateVector :: (a, a) -> (a, a)
negateVector (a
x, a
y) = (-a
x, -a
y)

  (a
x1, a
y1) ^+^ :: (a, a) -> (a, a) -> (a, a)
^+^ (a
x2, a
y2) = (a
x1 forall a. Num a => a -> a -> a
+ a
x2, a
y1 forall a. Num a => a -> a -> a
+ a
y2)

  (a
x1, a
y1) ^-^ :: (a, a) -> (a, a) -> (a, a)
^-^ (a
x2, a
y2) = (a
x1 forall a. Num a => a -> a -> a
- a
x2, a
y1 forall a. Num a => a -> a -> a
- a
y2)

  (a
x1, a
y1) dot :: (a, a) -> (a, a) -> a
`dot` (a
x2, a
y2) = a
x1 forall a. Num a => a -> a -> a
* a
x2 forall a. Num a => a -> a -> a
+ a
y1 forall a. Num a => a -> a -> a
* a
y2

-- | Vector space instance for triplets of 'Floating' point numbers.
instance (Eq a, Floating a) => VectorSpace (a, a, a) a where
  zeroVector :: (a, a, a)
zeroVector = (a
0, a
0, a
0)

  a
a *^ :: a -> (a, a, a) -> (a, a, a)
*^ (a
x, a
y, a
z) = (a
a forall a. Num a => a -> a -> a
* a
x, a
a forall a. Num a => a -> a -> a
* a
y, a
a forall a. Num a => a -> a -> a
* a
z)

  (a
x, a
y, a
z) ^/ :: (a, a, a) -> a -> (a, a, a)
^/ a
a = (a
x forall a. Fractional a => a -> a -> a
/ a
a, a
y forall a. Fractional a => a -> a -> a
/ a
a, a
z forall a. Fractional a => a -> a -> a
/ a
a)

  negateVector :: (a, a, a) -> (a, a, a)
negateVector (a
x, a
y, a
z) = (-a
x, -a
y, -a
z)

  (a
x1, a
y1, a
z1) ^+^ :: (a, a, a) -> (a, a, a) -> (a, a, a)
^+^ (a
x2, a
y2, a
z2) = (a
x1 forall a. Num a => a -> a -> a
+ a
x2, a
y1 forall a. Num a => a -> a -> a
+ a
y2, a
z1 forall a. Num a => a -> a -> a
+ a
z2)

  (a
x1, a
y1, a
z1) ^-^ :: (a, a, a) -> (a, a, a) -> (a, a, a)
^-^ (a
x2, a
y2, a
z2) = (a
x1 forall a. Num a => a -> a -> a
- a
x2, a
y1 forall a. Num a => a -> a -> a
- a
y2, a
z1 forall a. Num a => a -> a -> a
- a
z2)

  (a
x1, a
y1, a
z1) dot :: (a, a, a) -> (a, a, a) -> a
`dot` (a
x2, a
y2, a
z2) = a
x1 forall a. Num a => a -> a -> a
* a
x2 forall a. Num a => a -> a -> a
+ a
y1 forall a. Num a => a -> a -> a
* a
y2 forall a. Num a => a -> a -> a
+ a
z1 forall a. Num a => a -> a -> a
* a
z2

-- | Vector space instance for tuples with four 'Floating' point numbers.
instance (Eq a, Floating a) => VectorSpace (a, a, a, a) a where
  zeroVector :: (a, a, a, a)
zeroVector = (a
0, a
0, a
0, a
0)

  a
a *^ :: a -> (a, a, a, a) -> (a, a, a, a)
*^ (a
x, a
y, a
z, a
u) = (a
a forall a. Num a => a -> a -> a
* a
x, a
a forall a. Num a => a -> a -> a
* a
y, a
a forall a. Num a => a -> a -> a
* a
z, a
a forall a. Num a => a -> a -> a
* a
u)

  (a
x, a
y, a
z, a
u) ^/ :: (a, a, a, a) -> a -> (a, a, a, a)
^/ a
a = (a
x forall a. Fractional a => a -> a -> a
/ a
a, a
y forall a. Fractional a => a -> a -> a
/ a
a, a
z forall a. Fractional a => a -> a -> a
/ a
a, a
u forall a. Fractional a => a -> a -> a
/ a
a)

  negateVector :: (a, a, a, a) -> (a, a, a, a)
negateVector (a
x, a
y, a
z, a
u) = (-a
x, -a
y, -a
z, -a
u)

  (a
x1, a
y1, a
z1, a
u1) ^+^ :: (a, a, a, a) -> (a, a, a, a) -> (a, a, a, a)
^+^ (a
x2, a
y2, a
z2, a
u2) = (a
x1 forall a. Num a => a -> a -> a
+ a
x2, a
y1 forall a. Num a => a -> a -> a
+ a
y2, a
z1 forall a. Num a => a -> a -> a
+ a
z2, a
u1 forall a. Num a => a -> a -> a
+ a
u2)

  (a
x1, a
y1, a
z1, a
u1) ^-^ :: (a, a, a, a) -> (a, a, a, a) -> (a, a, a, a)
^-^ (a
x2, a
y2, a
z2, a
u2) = (a
x1 forall a. Num a => a -> a -> a
- a
x2, a
y1 forall a. Num a => a -> a -> a
- a
y2, a
z1 forall a. Num a => a -> a -> a
- a
z2, a
u1 forall a. Num a => a -> a -> a
- a
u2)

  (a
x1, a
y1, a
z1, a
u1) dot :: (a, a, a, a) -> (a, a, a, a) -> a
`dot` (a
x2, a
y2, a
z2, a
u2) =
    a
x1 forall a. Num a => a -> a -> a
* a
x2 forall a. Num a => a -> a -> a
+ a
y1 forall a. Num a => a -> a -> a
* a
y2 forall a. Num a => a -> a -> a
+ a
z1 forall a. Num a => a -> a -> a
* a
z2 forall a. Num a => a -> a -> a
+ a
u1 forall a. Num a => a -> a -> a
* a
u2

-- | Vector space instance for tuples with five 'Floating' point numbers.
instance (Eq a, Floating a) => VectorSpace (a, a, a, a, a) a where
  zeroVector :: (a, a, a, a, a)
zeroVector = (a
0, a
0, a
0, a
0, a
0)

  a
a *^ :: a -> (a, a, a, a, a) -> (a, a, a, a, a)
*^ (a
x, a
y, a
z, a
u, a
v) = (a
a forall a. Num a => a -> a -> a
* a
x, a
a forall a. Num a => a -> a -> a
* a
y, a
a forall a. Num a => a -> a -> a
* a
z, a
a forall a. Num a => a -> a -> a
* a
u, a
a forall a. Num a => a -> a -> a
* a
v)

  (a
x, a
y, a
z, a
u, a
v) ^/ :: (a, a, a, a, a) -> a -> (a, a, a, a, a)
^/ a
a = (a
x forall a. Fractional a => a -> a -> a
/ a
a, a
y forall a. Fractional a => a -> a -> a
/ a
a, a
z forall a. Fractional a => a -> a -> a
/ a
a, a
u forall a. Fractional a => a -> a -> a
/ a
a, a
v forall a. Fractional a => a -> a -> a
/ a
a)

  negateVector :: (a, a, a, a, a) -> (a, a, a, a, a)
negateVector (a
x, a
y, a
z, a
u, a
v) = (-a
x, -a
y, -a
z, -a
u, -a
v)

  (a
x1, a
y1, a
z1, a
u1, a
v1) ^+^ :: (a, a, a, a, a) -> (a, a, a, a, a) -> (a, a, a, a, a)
^+^ (a
x2, a
y2, a
z2, a
u2, a
v2) =
    (a
x1 forall a. Num a => a -> a -> a
+ a
x2, a
y1 forall a. Num a => a -> a -> a
+ a
y2, a
z1 forall a. Num a => a -> a -> a
+ a
z2, a
u1 forall a. Num a => a -> a -> a
+ a
u2, a
v1 forall a. Num a => a -> a -> a
+ a
v2)

  (a
x1, a
y1, a
z1, a
u1, a
v1) ^-^ :: (a, a, a, a, a) -> (a, a, a, a, a) -> (a, a, a, a, a)
^-^ (a
x2, a
y2, a
z2, a
u2, a
v2) =
    (a
x1 forall a. Num a => a -> a -> a
- a
x2, a
y1 forall a. Num a => a -> a -> a
- a
y2, a
z1 forall a. Num a => a -> a -> a
- a
z2, a
u1 forall a. Num a => a -> a -> a
- a
u2, a
v1 forall a. Num a => a -> a -> a
- a
v2)

  (a
x1, a
y1, a
z1, a
u1, a
v1) dot :: (a, a, a, a, a) -> (a, a, a, a, a) -> a
`dot` (a
x2, a
y2, a
z2, a
u2, a
v2) =
    a
x1 forall a. Num a => a -> a -> a
* a
x2 forall a. Num a => a -> a -> a
+ a
y1 forall a. Num a => a -> a -> a
* a
y2 forall a. Num a => a -> a -> a
+ a
z1 forall a. Num a => a -> a -> a
* a
z2 forall a. Num a => a -> a -> a
+ a
u1 forall a. Num a => a -> a -> a
* a
u2 forall a. Num a => a -> a -> a
+ a
v1 forall a. Num a => a -> a -> a
* a
v2