Personal tools

Library for vectors

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
(Small thing for playing with vectors.)
 
m (Added vmag_sqr)
 
Line 15: Line 15:
 
vdot :: Vector v => v -> v -> Scalar
 
vdot :: Vector v => v -> v -> Scalar
 
vdot v0 v1 = vfold (+) 0 $ vzip (*) v0 v1
 
vdot v0 v1 = vfold (+) 0 $ vzip (*) v0 v1
  +
  +
vmag_sqr :: Vector v => v -> Scalar
  +
vmag_sqr v = v `vdot` v
   
 
vmag :: Vector v => v -> Scalar
 
vmag :: Vector v => v -> Scalar
vmag v = sqrt $ vdot v v
+
vmag = sqrt . vmag_sqr
   
 
vscale :: Vector v => Scalar -> v -> v
 
vscale :: Vector v => Scalar -> v -> v

Latest revision as of 14:10, 18 April 2007


Most people just use
(Int,Int)
or similar for a 2-vector. However, if you find yourself wanting to do lots of vector arithmetic, that becomes annoying quite quickly. Below is what I use; feel free to adapt it to your needs.
module Vector where
 
type Scalar = Double
 
class Vector v where
  vmap  :: (Scalar -> Scalar) -> v -> v
  vzip  :: (Scalar -> Scalar -> Scalar) -> v -> v -> v
  vfold :: (x -> Scalar -> x) -> x -> v -> x
 
vdot :: Vector v => v -> v -> Scalar
vdot v0 v1 = vfold (+) 0 $ vzip (*) v0 v1
 
vmag_sqr :: Vector v => v -> Scalar
vmag_sqr v = v `vdot` v
 
vmag :: Vector v => v -> Scalar
vmag = sqrt . vmag_sqr
 
vscale :: Vector v => Scalar -> v -> v
vscale s = vmap (s*)
 
vunit :: Vector v => v -> v
vunit v =
  if vmag v == 0
    then v
    else vscale (1 / vmag v) v
 
 
data Vector2 = Vector2 {v2x, v2y :: Scalar} deriving (Eq)
 
instance Show Vector2 where
  show (Vector2 x y) = "<" ++ (show x) ++ ", " ++ (show y) ++ ">"
 
instance Vector Vector2 where
  vmap  f   (Vector2 x y) = Vector2 (f x) (f y)
  vfold f i (Vector2 x y) = (i `f` x) `f` y
  vzip  f   (Vector2 x0 y0) (Vector2 x1 y1) = Vector2 (f x0 x1) (f y0 y1)
 
instance Num Vector2 where
  (+) = vzip (+)
  (-) = vzip (-)
  (*) = vzip (*)
  negate = vmap negate
  fromInteger s = Vector2 (fromInteger s) (fromInteger s)
 
instance Fractional Vector2 where
  (/) = vzip (/)
  fromDouble s = Vector2 s s
 
 
data Vector3 = Vector3 {v3x, v3y, v3z :: Scalar} deriving (Eq)
 
instance Show Vector3 where
  show (Vector3 x y z) = "<" ++ (show x) ++ ", " ++ (show y) ++ ", " ++ (show z) ++ ">"
 
instance Vector Vector3 where
  vmap  f   (Vector3 x y z) = Vector3 (f x) (f y) (f z)
  vfold f i (Vector3 x y z) = ((i `f` x) `f` y) `f` z
  vzip  f   (Vector3 x0 y0 z0) (Vector3 x1 y1 z1) = Vector3 (f x0 x1) (f y0 y1) (f z0 z1)
 
instance Num Vector3 where
  (+) = vzip (+)
  (-) = vzip (-)
  (*) = vzip (*)
  negate = vmap negate
  fromInteger s = Vector3 (fromInteger s) (fromInteger s) (fromInteger s)
 
instance Fractional Vector3 where
  (/) = vzip (/)
  fromDouble s = Vector3 s s s
 
v3cross (Vector3 x0 y0 z0) (Vector3 x1 y1 z1) = Vector3 (y0*z1 - y1*z0) (x0*z1 - x1*z0) (x0*y1 - x1*y0)
PS. If anybody knows a way to make every instance of
Vector
automatically become an instance of
Num
, etc., let me know!