{- |
3-dimensional vectors with vector arithmetic.
-}
module Data.Vector.V3 where
import Data.Vector.Class
data Vector3 = Vector3 {v3x, v3y, v3z :: {-# UNPACK #-} !Scalar} deriving (Eq, Show)
instance BasicVector Vector3 where
vmap f (Vector3 x y z ) = Vector3 (f x) (f y) (f z)
vzip f (Vector3 x1 y1 z1) (Vector3 x2 y2 z2) = Vector3 (f x1 x2) (f y1 y2) (f z1 z2)
vfold f (Vector3 x y z ) = f x (f y z)
vpack (x:y:z:_) = Just $ Vector3 x y z
vpack _ = Nothing
vunpack (Vector3 x y z) = [x,y,z]
vpromote x = Vector3 x x x
instance Num Vector3 where
(+) = vzip (+)
(-) = vzip (-)
(*) = vzip (*)
abs = vmap abs
signum = vmap signum
fromInteger = vpromote . fromInteger
instance Fractional Vector3 where
(/) = vzip (/)
recip = vmap recip
fromRational = vpromote . 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 x1 y1 z1) (Vector3 x2 y2 z2) =
Vector3
{
v3x = y1 * z2 - y2 * z1,
v3y = z1 * x2 - z2 * x1,
v3z = x1 * y2 - x2 * y1
}