module Algebra.VectorSpace (
      VectorSpace(..)
    , vsum
) where



import Data.Foldable (foldl')



-- | A generic vector space. Not only classic vectors like 'Vec2' form a vector
-- space, but also concepts like 'Angle's – anything that can be added, inverted,
-- and multiplied with a scalar.
--
-- Vector spaces come with a number of laws that you can look up on Wikipedia. The
-- short version is: each operation behaves like addition/multiplication on normal
-- numbers.
class VectorSpace v where
    {-# MINIMAL (+.), (*.), ((-.) | negateV), zero #-}
    -- | Vector addition
    (+.) :: v -> v -> v

    -- | Vector subtraction
    (-.) :: v -> v -> v
    v
a -. v
b = v
a v -> v -> v
forall v. VectorSpace v => v -> v -> v
+. v -> v
forall v. VectorSpace v => v -> v
negateV v
b

    -- | Multiplication with a scalar
    (*.) :: Double -> v -> v

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

    -- | Neutral element
    zero :: v

    -- | Inverse element
    negateV :: v -> v
    negateV v
a = (-Double
1) Double -> v -> v
forall v. VectorSpace v => Double -> v -> v
*. v
a

infixl 6 +., -.
infixl 7 *., /.

instance (VectorSpace v1, VectorSpace v2) => VectorSpace (v1, v2) where
    (v1
u1, v2
v1) +. :: (v1, v2) -> (v1, v2) -> (v1, v2)
+. (v1
u2, v2
v2) = (v1
u1v1 -> v1 -> v1
forall v. VectorSpace v => v -> v -> v
+.v1
u2, v2
v1v2 -> v2 -> v2
forall v. VectorSpace v => v -> v -> v
+.v2
v2)
    (v1
u1, v2
v1) -. :: (v1, v2) -> (v1, v2) -> (v1, v2)
-. (v1
u2, v2
v2) = (v1
u1v1 -> v1 -> v1
forall v. VectorSpace v => v -> v -> v
-.v1
u2, v2
v1v2 -> v2 -> v2
forall v. VectorSpace v => v -> v -> v
-.v2
v2)
    Double
a *. :: Double -> (v1, v2) -> (v1, v2)
*. (v1
u1, v2
v1) = (Double
aDouble -> v1 -> v1
forall v. VectorSpace v => Double -> v -> v
*.v1
u1, Double
aDouble -> v2 -> v2
forall v. VectorSpace v => Double -> v -> v
*.v2
v1)
    zero :: (v1, v2)
zero = (v1
forall v. VectorSpace v => v
zero, v2
forall v. VectorSpace v => v
zero)

instance (VectorSpace v1, VectorSpace v2, VectorSpace v3) => VectorSpace (v1, v2, v3) where
    (v1
u1, v2
v1, v3
w1) +. :: (v1, v2, v3) -> (v1, v2, v3) -> (v1, v2, v3)
+. (v1
u2, v2
v2, v3
w2) = (v1
u1v1 -> v1 -> v1
forall v. VectorSpace v => v -> v -> v
+.v1
u2, v2
v1v2 -> v2 -> v2
forall v. VectorSpace v => v -> v -> v
+.v2
v2, v3
w1v3 -> v3 -> v3
forall v. VectorSpace v => v -> v -> v
+.v3
w2)
    (v1
u1, v2
v1, v3
w1) -. :: (v1, v2, v3) -> (v1, v2, v3) -> (v1, v2, v3)
-. (v1
u2, v2
v2, v3
w2) = (v1
u1v1 -> v1 -> v1
forall v. VectorSpace v => v -> v -> v
-.v1
u2, v2
v1v2 -> v2 -> v2
forall v. VectorSpace v => v -> v -> v
-.v2
v2, v3
w1v3 -> v3 -> v3
forall v. VectorSpace v => v -> v -> v
-.v3
w2)
    Double
a *. :: Double -> (v1, v2, v3) -> (v1, v2, v3)
*. (v1
u1, v2
v1, v3
w1) = (Double
aDouble -> v1 -> v1
forall v. VectorSpace v => Double -> v -> v
*.v1
u1, Double
aDouble -> v2 -> v2
forall v. VectorSpace v => Double -> v -> v
*.v2
v1, Double
aDouble -> v3 -> v3
forall v. VectorSpace v => Double -> v -> v
*.v3
w1)
    zero :: (v1, v2, v3)
zero = (v1
forall v. VectorSpace v => v
zero, v2
forall v. VectorSpace v => v
zero, v3
forall v. VectorSpace v => v
zero)

instance (VectorSpace v1, VectorSpace v2, VectorSpace v3, VectorSpace v4) => VectorSpace (v1, v2, v3, v4) where
    (v1
u1, v2
v1, v3
w1, v4
x1) +. :: (v1, v2, v3, v4) -> (v1, v2, v3, v4) -> (v1, v2, v3, v4)
+. (v1
u2, v2
v2, v3
w2, v4
x2) = (v1
u1v1 -> v1 -> v1
forall v. VectorSpace v => v -> v -> v
+.v1
u2, v2
v1v2 -> v2 -> v2
forall v. VectorSpace v => v -> v -> v
+.v2
v2, v3
w1v3 -> v3 -> v3
forall v. VectorSpace v => v -> v -> v
+.v3
w2, v4
x1v4 -> v4 -> v4
forall v. VectorSpace v => v -> v -> v
+.v4
x2)
    (v1
u1, v2
v1, v3
w1, v4
x1) -. :: (v1, v2, v3, v4) -> (v1, v2, v3, v4) -> (v1, v2, v3, v4)
-. (v1
u2, v2
v2, v3
w2, v4
x2) = (v1
u1v1 -> v1 -> v1
forall v. VectorSpace v => v -> v -> v
-.v1
u2, v2
v1v2 -> v2 -> v2
forall v. VectorSpace v => v -> v -> v
-.v2
v2, v3
w1v3 -> v3 -> v3
forall v. VectorSpace v => v -> v -> v
-.v3
w2, v4
x1v4 -> v4 -> v4
forall v. VectorSpace v => v -> v -> v
-.v4
x2)
    Double
a *. :: Double -> (v1, v2, v3, v4) -> (v1, v2, v3, v4)
*. (v1
u1, v2
v1, v3
w1, v4
x1) = (Double
aDouble -> v1 -> v1
forall v. VectorSpace v => Double -> v -> v
*.v1
u1, Double
aDouble -> v2 -> v2
forall v. VectorSpace v => Double -> v -> v
*.v2
v1, Double
aDouble -> v3 -> v3
forall v. VectorSpace v => Double -> v -> v
*.v3
w1, Double
aDouble -> v4 -> v4
forall v. VectorSpace v => Double -> v -> v
*.v4
x1)
    zero :: (v1, v2, v3, v4)
zero = (v1
forall v. VectorSpace v => v
zero, v2
forall v. VectorSpace v => v
zero, v3
forall v. VectorSpace v => v
zero, v4
forall v. VectorSpace v => v
zero)

instance (VectorSpace v1, VectorSpace v2, VectorSpace v3, VectorSpace v4, VectorSpace v5) => VectorSpace (v1, v2, v3, v4, v5) where
    (v1
u1, v2
v1, v3
w1, v4
x1, v5
y1) +. :: (v1, v2, v3, v4, v5)
-> (v1, v2, v3, v4, v5) -> (v1, v2, v3, v4, v5)
+. (v1
u2, v2
v2, v3
w2, v4
x2, v5
y2) = (v1
u1v1 -> v1 -> v1
forall v. VectorSpace v => v -> v -> v
+.v1
u2, v2
v1v2 -> v2 -> v2
forall v. VectorSpace v => v -> v -> v
+.v2
v2, v3
w1v3 -> v3 -> v3
forall v. VectorSpace v => v -> v -> v
+.v3
w2, v4
x1v4 -> v4 -> v4
forall v. VectorSpace v => v -> v -> v
+.v4
x2, v5
y1v5 -> v5 -> v5
forall v. VectorSpace v => v -> v -> v
+.v5
y2)
    (v1
u1, v2
v1, v3
w1, v4
x1, v5
y1) -. :: (v1, v2, v3, v4, v5)
-> (v1, v2, v3, v4, v5) -> (v1, v2, v3, v4, v5)
-. (v1
u2, v2
v2, v3
w2, v4
x2, v5
y2) = (v1
u1v1 -> v1 -> v1
forall v. VectorSpace v => v -> v -> v
-.v1
u2, v2
v1v2 -> v2 -> v2
forall v. VectorSpace v => v -> v -> v
-.v2
v2, v3
w1v3 -> v3 -> v3
forall v. VectorSpace v => v -> v -> v
-.v3
w2, v4
x1v4 -> v4 -> v4
forall v. VectorSpace v => v -> v -> v
-.v4
x2, v5
y1v5 -> v5 -> v5
forall v. VectorSpace v => v -> v -> v
-.v5
y2)
    Double
a *. :: Double -> (v1, v2, v3, v4, v5) -> (v1, v2, v3, v4, v5)
*. (v1
u1, v2
v1, v3
w1, v4
x1, v5
y1) = (Double
aDouble -> v1 -> v1
forall v. VectorSpace v => Double -> v -> v
*.v1
u1, Double
aDouble -> v2 -> v2
forall v. VectorSpace v => Double -> v -> v
*.v2
v1, Double
aDouble -> v3 -> v3
forall v. VectorSpace v => Double -> v -> v
*.v3
w1, Double
aDouble -> v4 -> v4
forall v. VectorSpace v => Double -> v -> v
*.v4
x1, Double
aDouble -> v5 -> v5
forall v. VectorSpace v => Double -> v -> v
*.v5
y1)
    zero :: (v1, v2, v3, v4, v5)
zero = (v1
forall v. VectorSpace v => v
zero, v2
forall v. VectorSpace v => v
zero, v3
forall v. VectorSpace v => v
zero, v4
forall v. VectorSpace v => v
zero, v5
forall v. VectorSpace v => v
zero)

instance VectorSpace Double where
    Double
a +. :: Double -> Double -> Double
+. Double
b = Double
aDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
b
    Double
a *. :: Double -> Double -> Double
*. Double
b = Double
aDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
b
    Double
a -. :: Double -> Double -> Double
-. Double
b = Double
aDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
b
    zero :: Double
zero = Double
0

instance VectorSpace b => VectorSpace (a -> b) where
    (a -> b
f +. :: (a -> b) -> (a -> b) -> a -> b
+. a -> b
g) a
a = a -> b
f a
a b -> b -> b
forall v. VectorSpace v => v -> v -> v
+. a -> b
g a
a
    (Double
c *. :: Double -> (a -> b) -> a -> b
*. a -> b
f) a
a = Double
c Double -> b -> b
forall v. VectorSpace v => Double -> v -> v
*. a -> b
f a
a
    (a -> b
f -. :: (a -> b) -> (a -> b) -> a -> b
-. a -> b
g) a
a = a -> b
f a
a b -> b -> b
forall v. VectorSpace v => v -> v -> v
-. a -> b
g a
a
    zero :: a -> b
zero = b -> a -> b
forall a b. a -> b -> a
const b
forall v. VectorSpace v => v
zero

vsum :: VectorSpace a => [a] -> a
vsum :: forall a. VectorSpace a => [a] -> a
vsum = (a -> a -> a) -> a -> [a] -> a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' a -> a -> a
forall v. VectorSpace v => v -> v -> v
(+.) a
forall v. VectorSpace v => v
zero