Module

Linear

Package
purescript-linear
Repository
afcondon/purescript-linear

Linear algebra for graphics programming.

This module re-exports the core functionality from the linear package. It provides fixed-size vectors (V2, V3, V4), quaternions for 3D rotations, and matrix operations commonly used in graphics and game development.

Quick Start

import Linear

-- 2D vector operations
v1 = V2 3.0 4.0
v2 = V2 1.0 0.0
sum = v1 ^+^ v2         -- V2 4.0 4.0
length = norm v1        -- 5.0
unit = signorm v1       -- V2 0.6 0.8

-- 3D cross product
x = V3 1.0 0.0 0.0
y = V3 0.0 1.0 0.0
z = cross x y           -- V3 0.0 0.0 1.0

-- Quaternion rotation
q = axisAngle (V3 0.0 1.0 0.0) (pi / 2.0)  -- 90° around Y
rotated = rotate q (V3 1.0 0.0 0.0)         -- ≈ V3 0.0 0.0 (-1.0)

Re-exports from Linear.Affine

#Point Source

newtype Point :: forall k. (k -> Type) -> k -> Typenewtype Point f a

A point in an affine space.

The Point newtype distinguishes points from vectors at the type level. This prevents nonsensical operations like adding two points together.

origin = P (V2 0.0 0.0)
position = P (V2 3.0 4.0)

Constructors

  • P (f a)

Instances

#Affine Source

class Affine :: (Type -> Type) -> (Type -> Type) -> Constraintclass (Additive d) <= Affine p d | p -> d where

An affine space is a set of points with associated difference vectors.

Laws:

  • p .+^ (q .-. p) = q
  • (p .+^ u) .+^ v = p .+^ (u ^+^ v)
  • p .-. p = zero

Members

  • diff :: forall a. Ring a => p a -> p a -> d a

    The vector from the first point to the second.

  • moveBy :: forall a. Semiring a => p a -> d a -> p a

    Add a vector to a point.

  • moveByNeg :: forall a. Ring a => p a -> d a -> p a

    Subtract a vector from a point.

Instances

#unP Source

unP :: forall f a. Point f a -> f a

Unwrap a point to get the underlying vector.

#qdA Source

qdA :: forall p d. Affine p d => Metric d => p Number -> p Number -> Number

The squared distance between two points.

More efficient than distanceA when you only need to compare distances.

qdA (P (V2 0.0 0.0)) (P (V2 3.0 4.0)) = 25.0

#origin Source

origin :: forall f a. Applicative f => Semiring a => Point f a

The origin point (all coordinates zero).

origin :: Point V3 Number
origin = P (V3 0.0 0.0 0.0)

#lerpP Source

lerpP :: forall p d. Affine p d => Functor d => Number -> p Number -> p Number -> p Number

Linear interpolation between two points.

lerpP 0.0 p1 p2 = p1
lerpP 1.0 p1 p2 = p2
lerpP 0.5 p1 p2 -- midpoint

#distanceA Source

distanceA :: forall p d. Affine p d => Metric d => p Number -> p Number -> Number

The distance between two points.

distanceA (P (V2 0.0 0.0)) (P (V2 3.0 4.0)) = 5.0

#(.-^) Source

Operator alias for Linear.Affine.moveByNeg (left-associative / precedence 6)

#(.-.) Source

Operator alias for Linear.Affine.diff (left-associative / precedence 6)

#(.+^) Source

Operator alias for Linear.Affine.moveBy (left-associative / precedence 6)

Re-exports from Linear.Epsilon

#Epsilon Source

class Epsilon a  where

A typeclass for types that support approximate zero testing.

The nearZero function provides a "fairly subjective test to see if a quantity is near zero" (as Ed Kmett puts it).

Members

Instances

Re-exports from Linear.Matrix

#M44 Source

type M44 a = V4 (V4 a)

4x4 matrix (commonly used for 3D transformations)

#M43 Source

type M43 a = V4 (V3 a)

4x3 matrix

#M42 Source

type M42 a = V4 (V2 a)

4x2 matrix

#M34 Source

type M34 a = V3 (V4 a)

3x4 matrix

#M33 Source

type M33 a = V3 (V3 a)

3x3 matrix

#M32 Source

type M32 a = V3 (V2 a)

3x2 matrix

#M24 Source

type M24 a = V2 (V4 a)

2x4 matrix

#M23 Source

type M23 a = V2 (V3 a)

2x3 matrix

#M22 Source

type M22 a = V2 (V2 a)

2x2 matrix (2 rows, 2 columns)

#transpose44 Source

transpose44 :: forall a. M44 a -> M44 a

Transpose a 4x4 matrix.

#transpose33 Source

transpose33 :: forall a. M33 a -> M33 a

Transpose a 3x3 matrix.

#transpose22 Source

transpose22 :: forall a. M22 a -> M22 a

Transpose a 2x2 matrix.

#trace33 Source

trace33 :: forall a. Semiring a => M33 a -> a

Compute the trace (sum of diagonal) of a 3x3 matrix.

#mkTransformationMat Source

mkTransformationMat :: M33 Number -> V3 Number -> M44 Number

Build a 4x4 transformation matrix from a 3x3 rotation matrix and translation.

#mkTransformation Source

mkTransformation :: Quaternion Number -> V3 Number -> M44 Number

Build a 4x4 transformation matrix from a quaternion rotation and translation.

The resulting matrix applies rotation first, then translation.

mkTransformation identity (V3 1.0 2.0 3.0) -- pure translation
mkTransformation rotation (V3 0.0 0.0 0.0) -- pure rotation

#inv44 Source

inv44 :: M44 Number -> Maybe (M44 Number)

Inverse of a 4x4 matrix, if it exists.

#inv33 Source

inv33 :: M33 Number -> Maybe (M33 Number)

Inverse of a 3x3 matrix, if it exists.

#inv22 Source

inv22 :: M22 Number -> Maybe (M22 Number)

Inverse of a 2x2 matrix, if it exists.

#identity44 Source

identity44 :: forall a. Semiring a => M44 a

4x4 identity matrix.

#identity33 Source

identity33 :: forall a. Semiring a => M33 a

3x3 identity matrix.

#identity22 Source

identity22 :: forall a. Semiring a => M22 a

2x2 identity matrix.

#fromQuaternion Source

fromQuaternion :: Quaternion Number -> M33 Number

Convert a unit quaternion to a 3x3 rotation matrix.

fromQuaternion (Quaternion 1.0 (V3 0.0 0.0 0.0)) = identity33

#diagonal33 Source

diagonal33 :: forall a. M33 a -> V3 a

Extract the diagonal of a 3x3 matrix.

#det44 Source

det44 :: forall a. Ring a => M44 a -> a

Determinant of a 4x4 matrix.

#det33 Source

det33 :: forall a. Ring a => M33 a -> a

Determinant of a 3x3 matrix.

#det22 Source

det22 :: forall a. Ring a => M22 a -> a

Determinant of a 2x2 matrix.

#(*!) Source

Operator alias for Linear.Matrix.mulVM (left-associative / precedence 7)

#(!*!) Source

Operator alias for Linear.Matrix.mulMM (left-associative / precedence 7)

#(!*) Source

Operator alias for Linear.Matrix.mulMV (left-associative / precedence 7)

Re-exports from Linear.Metric

#Metric Source

class Metric :: (Type -> Type) -> Constraintclass (Additive f) <= Metric f  where

A metric space with an inner product.

Laws:

  • dot v v >= 0 (positive semi-definite)
  • dot v v = 0 implies v = zero
  • dot u v = dot v u (symmetry)
  • dot (a *^ u) v = a * dot u v (linearity)

Members

  • dot :: forall a. Semiring a => f a -> f a -> a

    The inner (dot) product of two vectors.

    dot (V2 1.0 2.0) (V2 3.0 4.0) = 11.0  -- 1*3 + 2*4
    
  • quadrance :: forall a. Semiring a => f a -> a

    The squared norm of a vector (quadrance from rational trigonometry).

    This is more efficient than norm when you only need to compare magnitudes.

    quadrance (V2 3.0 4.0) = 25.0  -- 3² + 4²
    
  • qd :: forall a. Ring a => f a -> f a -> a

    The squared distance between two vectors.

    qd (V2 0.0 0.0) (V2 3.0 4.0) = 25.0
    
  • distance :: f Number -> f Number -> Number

    The Euclidean distance between two vectors.

    distance (V2 0.0 0.0) (V2 3.0 4.0) = 5.0
    
  • norm :: f Number -> Number

    The Euclidean norm (magnitude) of a vector.

    norm (V2 3.0 4.0) = 5.0
    
  • signorm :: f Number -> f Number

    Convert a non-zero vector to a unit vector (signorm = "sign of norm").

    Returns the zero vector when given the zero vector.

    signorm (V2 3.0 4.0) = V2 0.6 0.8
    signorm (V2 0.0 0.0) = V2 0.0 0.0
    

#project Source

project :: forall f. Metric f => f Number -> f Number -> f Number

Project the first vector onto the second.

project (V2 1.0 0.0) (V2 1.0 1.0) = V2 0.5 0.5

#normalize Source

normalize :: forall f. Metric f => Epsilon Number => f Number -> f Number

Normalize a vector to unit length.

Unlike signorm, this function handles the zero vector by returning zero rather than NaN.

normalize (V2 3.0 4.0) = V2 0.6 0.8
normalize (V2 0.0 0.0) = V2 0.0 0.0

Re-exports from Linear.Quaternion

#Quaternion Source

data Quaternion a

A quaternion representing a rotation in 3D space.

A quaternion q = w + xi + yj + zk is stored as Quaternion w (V3 x y z). Unit quaternions (where |q| = 1) represent rotations.

identity = Quaternion 1.0 (V3 0.0 0.0 0.0)

Constructors

Instances

#slerp Source

slerp :: Number -> Quaternion Number -> Quaternion Number -> Quaternion Number

Spherical linear interpolation between two quaternions.

This produces smooth rotation interpolation along the shortest path.

slerp 0.0 q1 q2 = q1
slerp 1.0 q1 q2 = q2
slerp 0.5 q1 q2 -- halfway rotation

#rotate Source

rotate :: Quaternion Number -> V3 Number -> V3 Number

Rotate a 3D vector by a quaternion.

The quaternion should be a unit quaternion for proper rotation.

let q = axisAngle (V3 0.0 1.0 0.0) (pi / 2.0)  -- 90° around Y
rotate q (V3 1.0 0.0 0.0) ≈ V3 0.0 0.0 (-1.0)

#qmul Source

qmul :: forall a. Ring a => Quaternion a -> Quaternion a -> Quaternion a

Quaternion multiplication (Hamilton product).

This is NOT commutative: qmul q1 q2 /= qmul q2 q1 in general. Composing rotations: to apply rotation q1 then q2, use qmul q2 q1.

qmul identity q = q
qmul q identity = q

#inverse Source

inverse :: Quaternion Number -> Quaternion Number

The multiplicative inverse of a quaternion.

For unit quaternions, this equals the conjugate.

qmul q (inverse q) ≈ identity

#fromEuler Source

fromEuler :: Number -> Number -> Number -> Quaternion Number

Construct a rotation from Euler angles (in radians).

Order is ZYX (yaw, pitch, roll).

fromEuler 0.0 0.0 0.0 = identity

#conjugate Source

conjugate :: forall a. Ring a => Quaternion a -> Quaternion a

The conjugate of a quaternion.

For unit quaternions, the conjugate equals the inverse and represents the opposite rotation.

conjugate (Quaternion w (V3 x y z)) = Quaternion w (V3 (-x) (-y) (-z))

#axisAngle Source

axisAngle :: V3 Number -> Number -> Quaternion Number

Construct a rotation quaternion from an axis and angle.

The axis should be a unit vector. The angle is in radians.

-- 90 degree rotation around the Y axis
axisAngle (V3 0.0 1.0 0.0) (pi / 2.0)

Re-exports from Linear.V2

#V2 Source

data V2 a

A 2-dimensional vector.

origin = V2 0.0 0.0
direction = V2 1.0 0.0

Constructors

Instances

#unangle Source

unangle :: V2 Number -> Number

Extract the angle (in radians) from a vector, measured from the positive x-axis.

unangle (V2 1.0 0.0) = 0.0
unangle (V2 0.0 1.0) = pi / 2.0

#perp Source

perp :: forall a. Ring a => V2 a -> V2 a

The counter-clockwise perpendicular vector.

perp (V2 1.0 0.0) = V2 0.0 1.0
perp (V2 0.0 1.0) = V2 (-1.0) 0.0

#crossZ Source

crossZ :: forall a. Ring a => V2 a -> V2 a -> a

The z-component of the cross product of two 2D vectors.

This is useful for determining the orientation of two vectors:

  • Positive: v2 is counter-clockwise from v1
  • Negative: v2 is clockwise from v1
  • Zero: vectors are parallel
crossZ (V2 1.0 0.0) (V2 0.0 1.0) = 1.0  -- counter-clockwise
crossZ (V2 0.0 1.0) (V2 1.0 0.0) = -1.0 -- clockwise

#angle Source

angle :: Number -> V2 Number

Construct a unit vector at the given angle (in radians) from the positive x-axis.

angle 0.0 = V2 1.0 0.0
angle (pi / 2.0) ≈ V2 0.0 1.0

Re-exports from Linear.V3

#V3 Source

data V3 a

A 3-dimensional vector.

origin = V3 0.0 0.0 0.0
up = V3 0.0 1.0 0.0

Constructors

Instances

#triple Source

triple :: forall a. Ring a => V3 a -> V3 a -> V3 a -> a

The scalar triple product of three vectors.

This equals the signed volume of the parallelepiped formed by the vectors.

triple (V3 1.0 0.0 0.0) (V3 0.0 1.0 0.0) (V3 0.0 0.0 1.0) = 1.0

#cross Source

cross :: forall a. Ring a => V3 a -> V3 a -> V3 a

The cross product of two 3D vectors.

The result is perpendicular to both input vectors, with magnitude equal to the area of the parallelogram they span.

cross (V3 1.0 0.0 0.0) (V3 0.0 1.0 0.0) = V3 0.0 0.0 1.0

Re-exports from Linear.V4

#V4 Source

data V4 a

A 4-dimensional vector.

Often used for homogeneous coordinates where (x, y, z, w) represents the 3D point (x/w, y/w, z/w).

origin = V4 0.0 0.0 0.0 1.0
direction = V4 1.0 0.0 0.0 0.0

Constructors

  • V4 a a a a

Instances

#vector Source

vector :: forall a. Semiring a => V3 a -> V4 a

Convert a 3D vector to homogeneous coordinates with w=0.

This represents a direction (not a point) in homogeneous coordinates.

vector (V3 1.0 0.0 0.0) = V4 1.0 0.0 0.0 0.0

#point Source

point :: forall a. Semiring a => V3 a -> V4 a

Convert a 3D point to homogeneous coordinates with w=1.

This represents a point (not a direction) in homogeneous coordinates.

point (V3 1.0 2.0 3.0) = V4 1.0 2.0 3.0 1.0

#normalizePoint Source

normalizePoint :: V4 Number -> V3 Number

Convert homogeneous coordinates back to 3D by dividing by w.

normalizePoint (V4 2.0 4.0 6.0 2.0) = V3 1.0 2.0 3.0

Re-exports from Linear.Vector

#Additive Source

class Additive :: (Type -> Type) -> Constraintclass (Functor f) <= Additive f  where

A vector space with addition and scalar multiplication.

Laws:

  • add zero v = v (left identity)
  • add v zero = v (right identity)
  • add (add u v) w = add u (add v w) (associativity)
  • add u v = add v u (commutativity)
  • sub v v = zero

Members

  • zero :: forall a. Semiring a => f a

    The zero vector

  • add :: forall a. Semiring a => f a -> f a -> f a

    Vector addition

  • sub :: forall a. Ring a => f a -> f a -> f a

    Vector subtraction

  • lerp :: forall a. Ring a => a -> f a -> f a -> f a

    Linear interpolation: lerp t a b = a + t * (b - a)

    • lerp 0.0 a b = a
    • lerp 1.0 a b = b
  • liftU2 :: forall a. (a -> a -> a) -> f a -> f a -> f a

    Apply a function to non-zero values (union semantics)

  • liftI2 :: forall a b c. (a -> b -> c) -> f a -> f b -> f c

    Apply a function component-wise (intersection semantics)

#sumV Source

sumV :: forall f g a. Foldable f => Additive g => Semiring a => f (g a) -> g a

Sum a collection of vectors

#negated Source

negated :: forall f a. Functor f => Ring a => f a -> f a

Negate a vector

negated (V2 1.0 (-2.0)) = V2 (-1.0) 2.0

#(^/) Source

Operator alias for Linear.Vector.scalarDiv (left-associative / precedence 7)

#(^-^) Source

Operator alias for Linear.Vector.sub (left-associative / precedence 6)

#(^+^) Source

Operator alias for Linear.Vector.add (left-associative / precedence 6)

#(^*) Source

Operator alias for Linear.Vector.scalarR (left-associative / precedence 7)

#(*^) Source

Operator alias for Linear.Vector.scalarL (left-associative / precedence 7)