{- |
  3-dimensional vectors with vector arithmetic.
-}

module Data.Vector.V3 where

import Data.Vector.Class

data Vector3 = Vector3 {Vector3 -> Scalar
v3x, Vector3 -> Scalar
v3y, Vector3 -> Scalar
v3z :: {-# UNPACK #-} !Scalar} deriving (Vector3 -> Vector3 -> Bool
(Vector3 -> Vector3 -> Bool)
-> (Vector3 -> Vector3 -> Bool) -> Eq Vector3
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Vector3 -> Vector3 -> Bool
== :: Vector3 -> Vector3 -> Bool
$c/= :: Vector3 -> Vector3 -> Bool
/= :: Vector3 -> Vector3 -> Bool
Eq, Int -> Vector3 -> ShowS
[Vector3] -> ShowS
Vector3 -> String
(Int -> Vector3 -> ShowS)
-> (Vector3 -> String) -> ([Vector3] -> ShowS) -> Show Vector3
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Vector3 -> ShowS
showsPrec :: Int -> Vector3 -> ShowS
$cshow :: Vector3 -> String
show :: Vector3 -> String
$cshowList :: [Vector3] -> ShowS
showList :: [Vector3] -> ShowS
Show)

instance BasicVector Vector3 where
  vmap :: (Scalar -> Scalar) -> Vector3 -> Vector3
vmap  Scalar -> Scalar
f (Vector3 Scalar
x  Scalar
y  Scalar
z )                    = Scalar -> Scalar -> Scalar -> Vector3
Vector3 (Scalar -> Scalar
f Scalar
x)     (Scalar -> Scalar
f Scalar
y)     (Scalar -> Scalar
f Scalar
z)
  vzip :: (Scalar -> Scalar -> Scalar) -> Vector3 -> Vector3 -> Vector3
vzip  Scalar -> Scalar -> Scalar
f (Vector3 Scalar
x1 Scalar
y1 Scalar
z1) (Vector3 Scalar
x2 Scalar
y2 Scalar
z2) = Scalar -> Scalar -> Scalar -> Vector3
Vector3 (Scalar -> Scalar -> Scalar
f Scalar
x1 Scalar
x2) (Scalar -> Scalar -> Scalar
f Scalar
y1 Scalar
y2) (Scalar -> Scalar -> Scalar
f Scalar
z1 Scalar
z2)
  vfold :: (Scalar -> Scalar -> Scalar) -> Vector3 -> Scalar
vfold Scalar -> Scalar -> Scalar
f (Vector3 Scalar
x  Scalar
y  Scalar
z )                    = Scalar -> Scalar -> Scalar
f Scalar
x (Scalar -> Scalar -> Scalar
f Scalar
y Scalar
z)

  vpack :: [Scalar] -> Maybe Vector3
vpack (Scalar
x:Scalar
y:Scalar
z:[Scalar]
_) = Vector3 -> Maybe Vector3
forall a. a -> Maybe a
Just (Vector3 -> Maybe Vector3) -> Vector3 -> Maybe Vector3
forall a b. (a -> b) -> a -> b
$ Scalar -> Scalar -> Scalar -> Vector3
Vector3 Scalar
x Scalar
y Scalar
z
  vpack [Scalar]
_         = Maybe Vector3
forall a. Maybe a
Nothing

  vunpack :: Vector3 -> [Scalar]
vunpack (Vector3 Scalar
x Scalar
y Scalar
z) = [Scalar
x,Scalar
y,Scalar
z]

  vpromote :: Scalar -> Vector3
vpromote Scalar
x = Scalar -> Scalar -> Scalar -> Vector3
Vector3 Scalar
x Scalar
x Scalar
x

instance Num Vector3 where
  + :: Vector3 -> Vector3 -> Vector3
(+) = (Scalar -> Scalar -> Scalar) -> Vector3 -> Vector3 -> Vector3
forall v.
BasicVector v =>
(Scalar -> Scalar -> Scalar) -> v -> v -> v
vzip Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
(+)
  (-) = (Scalar -> Scalar -> Scalar) -> Vector3 -> Vector3 -> Vector3
forall v.
BasicVector v =>
(Scalar -> Scalar -> Scalar) -> v -> v -> v
vzip (-)
  * :: Vector3 -> Vector3 -> Vector3
(*) = (Scalar -> Scalar -> Scalar) -> Vector3 -> Vector3 -> Vector3
forall v.
BasicVector v =>
(Scalar -> Scalar -> Scalar) -> v -> v -> v
vzip Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
(*)
  abs :: Vector3 -> Vector3
abs = (Scalar -> Scalar) -> Vector3 -> Vector3
forall v. BasicVector v => (Scalar -> Scalar) -> v -> v
vmap Scalar -> Scalar
forall a. Num a => a -> a
abs
  signum :: Vector3 -> Vector3
signum = (Scalar -> Scalar) -> Vector3 -> Vector3
forall v. BasicVector v => (Scalar -> Scalar) -> v -> v
vmap Scalar -> Scalar
forall a. Num a => a -> a
signum
  fromInteger :: Integer -> Vector3
fromInteger = Scalar -> Vector3
forall v. BasicVector v => Scalar -> v
vpromote (Scalar -> Vector3) -> (Integer -> Scalar) -> Integer -> Vector3
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Scalar
forall a. Num a => Integer -> a
fromInteger

instance Fractional Vector3 where
  / :: Vector3 -> Vector3 -> Vector3
(/) = (Scalar -> Scalar -> Scalar) -> Vector3 -> Vector3 -> Vector3
forall v.
BasicVector v =>
(Scalar -> Scalar -> Scalar) -> v -> v -> v
vzip Scalar -> Scalar -> Scalar
forall a. Fractional a => a -> a -> a
(/)
  recip :: Vector3 -> Vector3
recip = (Scalar -> Scalar) -> Vector3 -> Vector3
forall v. BasicVector v => (Scalar -> Scalar) -> v -> v
vmap Scalar -> Scalar
forall a. Fractional a => a -> a
recip
  fromRational :: Rational -> Vector3
fromRational = Scalar -> Vector3
forall v. BasicVector v => Scalar -> v
vpromote (Scalar -> Vector3) -> (Rational -> Scalar) -> Rational -> Vector3
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Scalar
forall a. Fractional a => Rational -> a
fromRational

instance Vector Vector3 where

{- |
  Take the /cross product/ of two 3D vectors. This produces a new 3D vector that is perpendicular to the plane of the first two vectors, and who's length is equal to the sine of the angle between those vectors multiplied by their lengths.

  Note that @a \`vcross\` b = negate (b \`vcross\` a)@.
-}
vcross :: Vector3 -> Vector3 -> Vector3
vcross :: Vector3 -> Vector3 -> Vector3
vcross (Vector3 Scalar
x1 Scalar
y1 Scalar
z1) (Vector3 Scalar
x2 Scalar
y2 Scalar
z2) =
  Vector3
  {
    v3x :: Scalar
v3x = Scalar
y1 Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Scalar
z2   Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
-   Scalar
y2 Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Scalar
z1,
    v3y :: Scalar
v3y = Scalar
z1 Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Scalar
x2   Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
-   Scalar
z2 Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Scalar
x1,
    v3z :: Scalar
v3z = Scalar
x1 Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Scalar
y2   Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
-   Scalar
x2 Scalar -> Scalar -> Scalar
forall a. Num a => a -> a -> a
* Scalar
y1
  }