{- | 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 }