AC-Vector 1.2.2 → 2.0.0
raw patch · 13 files changed
+462/−173 lines, 13 filesdep ~basesetup-changedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Data.Vector: (*|) :: (Vector v) => v -> Scalar -> v
- Data.Vector: (|*) :: (Vector v) => Scalar -> v -> v
- Data.Vector: Vector2 :: !!Scalar -> !!Scalar -> Vector2
- Data.Vector: Vector3 :: !!Scalar -> !!Scalar -> !!Scalar -> Vector3
- Data.Vector: class Vector v
- Data.Vector: data Vector2
- Data.Vector: data Vector3
- Data.Vector: fromScalar :: (Vector v) => Scalar -> v
- Data.Vector: instance Eq Vector2
- Data.Vector: instance Eq Vector3
- Data.Vector: instance Fractional Vector2
- Data.Vector: instance Fractional Vector3
- Data.Vector: instance Num Vector2
- Data.Vector: instance Num Vector3
- Data.Vector: instance Ord Vector2
- Data.Vector: instance Ord Vector3
- Data.Vector: instance Show Vector2
- Data.Vector: instance Show Vector3
- Data.Vector: instance Vector Vector2
- Data.Vector: instance Vector Vector3
- Data.Vector: type Scalar = Double
- Data.Vector: v2x :: Vector2 -> !!Scalar
- Data.Vector: v2y :: Vector2 -> !!Scalar
- Data.Vector: v3x :: Vector3 -> !!Scalar
- Data.Vector: v3y :: Vector3 -> !!Scalar
- Data.Vector: v3z :: Vector3 -> !!Scalar
- Data.Vector: vcross :: Vector3 -> Vector3 -> Vector3
- Data.Vector: vdot :: (Vector v) => v -> v -> Scalar
- Data.Vector: vector2X :: Vector2
- Data.Vector: vector2Y :: Vector2
- Data.Vector: vector3X :: Vector3
- Data.Vector: vector3Y :: Vector3
- Data.Vector: vector3Z :: Vector3
- Data.Vector: vfold :: (Vector v) => (Scalar -> Scalar -> Scalar) -> v -> Scalar
- Data.Vector: vmag :: (Vector v) => v -> Scalar
- Data.Vector: vmap :: (Vector v) => (Scalar -> Scalar) -> v -> v
- Data.Vector: vnormalise :: (Vector v) => v -> v
- Data.Vector: vzip :: (Vector v) => (Scalar -> Scalar -> Scalar) -> v -> v -> v
+ Data.Vector.Class: (*|) :: (Vector v) => Scalar -> v -> v
+ Data.Vector.Class: (|*) :: (Vector v) => v -> Scalar -> v
+ Data.Vector.Class: class Vector v
+ Data.Vector.Class: type Scalar = Double
+ Data.Vector.Class: vdot :: (Vector v) => v -> v -> Scalar
+ Data.Vector.Class: vfold :: (Vector v) => (Scalar -> Scalar -> Scalar) -> (v -> Scalar)
+ Data.Vector.Class: vlinear :: (Num v, Vector v) => Scalar -> v -> v -> v
+ Data.Vector.Class: vmag :: (Vector v) => v -> Scalar
+ Data.Vector.Class: vmap :: (Vector v) => (Scalar -> Scalar) -> (v -> v)
+ Data.Vector.Class: vnormalise :: (Vector v) => v -> v
+ Data.Vector.Class: vpack :: (Vector v) => [Scalar] -> Maybe v
+ Data.Vector.Class: vunpack :: (Vector v) => v -> [Scalar]
+ Data.Vector.Class: vzip :: (Vector v) => (Scalar -> Scalar -> Scalar) -> (v -> v -> v)
+ Data.Vector.Transform: data Transform1
+ Data.Vector.Transform: data Transform2
+ Data.Vector.Transform: data Transform3
+ Data.Vector.Transform: data Transform4
+ Data.Vector.Transform: transformP1 :: Transform1 -> Vector1 -> Vector1
+ Data.Vector.Transform: transformP2 :: Transform2 -> Vector2 -> Vector2
+ Data.Vector.Transform: transformP3 :: Transform3 -> Vector3 -> Vector3
+ Data.Vector.Transform: transformP4 :: Transform4 -> Vector4 -> Vector4
+ Data.Vector.Transform.T1: Transform1 :: !!Scalar -> !!Scalar -> Transform1
+ Data.Vector.Transform.T1: data Transform1
+ Data.Vector.Transform.T1: instance Eq Transform1
+ Data.Vector.Transform.T1: instance Monoid Transform1
+ Data.Vector.Transform.T1: instance Show Transform1
+ Data.Vector.Transform.T1: t1_1X :: Transform1 -> !!Scalar
+ Data.Vector.Transform.T1: t1_XX :: Transform1 -> !!Scalar
+ Data.Vector.Transform.T1: transformP1 :: Transform1 -> Vector1 -> Vector1
+ Data.Vector.Transform.T2: Transform2 :: !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> Transform2
+ Data.Vector.Transform.T2: data Transform2
+ Data.Vector.Transform.T2: instance Eq Transform2
+ Data.Vector.Transform.T2: instance Monoid Transform2
+ Data.Vector.Transform.T2: instance Show Transform2
+ Data.Vector.Transform.T2: t2_1X :: Transform2 -> !!Scalar
+ Data.Vector.Transform.T2: t2_1Y :: Transform2 -> !!Scalar
+ Data.Vector.Transform.T2: t2_XX :: Transform2 -> !!Scalar
+ Data.Vector.Transform.T2: t2_XY :: Transform2 -> !!Scalar
+ Data.Vector.Transform.T2: t2_YX :: Transform2 -> !!Scalar
+ Data.Vector.Transform.T2: t2_YY :: Transform2 -> !!Scalar
+ Data.Vector.Transform.T2: transformP2 :: Transform2 -> Vector2 -> Vector2
+ Data.Vector.Transform.T3: Transform3 :: !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> Transform3
+ Data.Vector.Transform.T3: data Transform3
+ Data.Vector.Transform.T3: instance Eq Transform3
+ Data.Vector.Transform.T3: instance Monoid Transform3
+ Data.Vector.Transform.T3: instance Show Transform3
+ Data.Vector.Transform.T3: t3_1X :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_1Y :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_1Z :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_XX :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_XY :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_XZ :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_YX :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_YY :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_YZ :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_ZX :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_ZY :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: t3_ZZ :: Transform3 -> !!Scalar
+ Data.Vector.Transform.T3: transformP3 :: Transform3 -> Vector3 -> Vector3
+ Data.Vector.Transform.T4: Transform4 :: !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> Transform4
+ Data.Vector.Transform.T4: data Transform4
+ Data.Vector.Transform.T4: instance Eq Transform4
+ Data.Vector.Transform.T4: instance Monoid Transform4
+ Data.Vector.Transform.T4: instance Show Transform4
+ Data.Vector.Transform.T4: t4_1W :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_1X :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_1Y :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_1Z :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_WW :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_WX :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_WY :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_WZ :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_XW :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_XX :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_XY :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_XZ :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_YW :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_YX :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_YY :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_YZ :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_ZW :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_ZX :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_ZY :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: t4_ZZ :: Transform4 -> !!Scalar
+ Data.Vector.Transform.T4: transformP4 :: Transform4 -> Vector4 -> Vector4
+ Data.Vector.V1: Vector1 :: Scalar -> Vector1
+ Data.Vector.V1: instance Enum Vector1
+ Data.Vector.V1: instance Eq Vector1
+ Data.Vector.V1: instance Fractional Vector1
+ Data.Vector.V1: instance Num Vector1
+ Data.Vector.V1: instance Ord Vector1
+ Data.Vector.V1: instance Show Vector1
+ Data.Vector.V1: instance Vector Vector1
+ Data.Vector.V1: newtype Vector1
+ Data.Vector.V1: v1x :: Vector1 -> Scalar
+ Data.Vector.V2: Vector2 :: !!Scalar -> !!Scalar -> Vector2
+ Data.Vector.V2: data Vector2
+ Data.Vector.V2: instance Eq Vector2
+ Data.Vector.V2: instance Fractional Vector2
+ Data.Vector.V2: instance Num Vector2
+ Data.Vector.V2: instance Show Vector2
+ Data.Vector.V2: instance Vector Vector2
+ Data.Vector.V2: v2x :: Vector2 -> !!Scalar
+ Data.Vector.V2: v2y :: Vector2 -> !!Scalar
+ Data.Vector.V3: Vector3 :: !!Scalar -> !!Scalar -> !!Scalar -> Vector3
+ Data.Vector.V3: data Vector3
+ Data.Vector.V3: instance Eq Vector3
+ Data.Vector.V3: instance Fractional Vector3
+ Data.Vector.V3: instance Num Vector3
+ Data.Vector.V3: instance Show Vector3
+ Data.Vector.V3: instance Vector Vector3
+ Data.Vector.V3: v3x :: Vector3 -> !!Scalar
+ Data.Vector.V3: v3y :: Vector3 -> !!Scalar
+ Data.Vector.V3: v3z :: Vector3 -> !!Scalar
+ Data.Vector.V3: vcross :: Vector3 -> Vector3 -> Vector3
+ Data.Vector.V4: Vector4 :: !!Scalar -> !!Scalar -> !!Scalar -> !!Scalar -> Vector4
+ Data.Vector.V4: data Vector4
+ Data.Vector.V4: instance Eq Vector4
+ Data.Vector.V4: instance Fractional Vector4
+ Data.Vector.V4: instance Num Vector4
+ Data.Vector.V4: instance Show Vector4
+ Data.Vector.V4: instance Vector Vector4
+ Data.Vector.V4: v4w :: Vector4 -> !!Scalar
+ Data.Vector.V4: v4x :: Vector4 -> !!Scalar
+ Data.Vector.V4: v4y :: Vector4 -> !!Scalar
+ Data.Vector.V4: v4z :: Vector4 -> !!Scalar
Files
- AC-Vector.cabal +16/−8
- Data/Vector.hs +17/−164
- Data/Vector/Class.hs +72/−0
- Data/Vector/Transform.hs +17/−0
- Data/Vector/Transform/T1.hs +35/−0
- Data/Vector/Transform/T2.hs +46/−0
- Data/Vector/Transform/T3.hs +55/−0
- Data/Vector/Transform/T4.hs +66/−0
- Data/Vector/V1.hs +28/−0
- Data/Vector/V2.hs +32/−0
- Data/Vector/V3.hs +46/−0
- Data/Vector/V4.hs +32/−0
- Setup.hs +0/−1
AC-Vector.cabal view
@@ -1,8 +1,8 @@ Cabal-Version: >= 1.6 Name: AC-Vector -Version: 1.2.2 +Version: 2.0.0 Stability: Experimental -Synopsis: Efficient geometric vectors. +Synopsis: Efficient geometric vectors and transformations. Description: @@ -10,11 +10,8 @@ with @Double@ fields, with seperate types for each size of vector, and a type class for handling vectors generally. - Changes: - - * /All prior versions/ of this library have a faulty - implementation of 'vcross'. Specifically, the sign of - the Y-coordinate is inverted. Oops! + Existing API has been rearranged. Now supports 4D vectors + and linear transformations. Category: Data, Math, Numerical License: BSD3 @@ -25,6 +22,17 @@ Tested-With: GHC == 6.10.3 Library - Exposed-modules: Data.Vector + Exposed-modules: + Data.Vector, + Data.Vector.Class, + Data.Vector.V1, + Data.Vector.V2, + Data.Vector.V3, + Data.Vector.V4, + Data.Vector.Transform, + Data.Vector.Transform.T1, + Data.Vector.Transform.T2, + Data.Vector.Transform.T3, + Data.Vector.Transform.T4 Build-Depends: base >= 4 && < 5 HS-Source-Dirs: .
Data/Vector.hs view
@@ -1,166 +1,19 @@-{- | - This module provides several small vectors over @Double@ values. - All fields are strict and unpacked, so using these should be - fairly efficient. Each size of vector is a seperate type. It also - provides a few vector constants to save you some typing now and - then. --} - -module Data.Vector where - -{- | The type of @Vector@ fields. -} -type Scalar = Double - -{- | - The @Vector@ class. All vectors are members of this class, - and it provides ways to apply functions over vectors. - Typically this methods aren't used directly; rather, the - other class instances for each vector are implemented - in terms of these. --} -class Vector v where - fromScalar :: Scalar -> v - vmap :: (Scalar -> Scalar) -> v -> v - vzip :: (Scalar -> Scalar -> Scalar) -> v -> v -> v - vfold :: (Scalar -> Scalar -> Scalar) -> v -> Scalar - -{- | - Takes the /dot product/ of two vectors [of the same dimension]. - If you remember your highschool linear algebra, the dot product - of two vectors V and W is equal to |V| * |W| * cos k, where - |V| is the length of vector V, and k is the minimum angle - between the two vectors. --} -vdot :: Vector v => v -> v -> Scalar -vdot v w = vfold (+) $ vzip (*) v w - -{- | - Returns the /magnitude/ of a vector (that is, it's length). - Note that this is always positive or zero (never negative). --} -vmag :: Vector v => v -> Scalar -vmag v = sqrt $ v `vdot` v - -{- | - Multiply a vector by a scalar. This scales the magnitude - (length) of the vector, but leaves its length unchanged. - (Except in the case of a negative scalar, in which case - the vector's direction is reversed.) - - The operators '|*' and '*|' are identical, just with their - arguments flipped. --} -(|*) :: Vector v => Scalar -> v -> v -s |* v = vmap (*s) v - -{- | - Multiply a vector by a scalar. This scales the magnitude - (length) of the vector, but leaves its length unchanged. - (Except in the case of a negative scalar, in which case - the vector's direction is reversed.) - - The operators '*|' and '|*' are identical, just with their - arguments flipped. --} -(*|) :: Vector v => v -> Scalar -> v -v *| s = vmap (*s) v - -{- | - Adjust a vector so that its length is exactly one. (Or, - if the vector's length was zero, it stays zero.) --} -vnormalise :: Vector v => v -> v -vnormalise v = - let m = vmag v - in if m < 1e-10 then v else v *| (1/m) - -{- | - The type of 2-dimensional vectors. It provides various - class instances such as 'Eq', 'Num', 'Show', etc. --} -data Vector2 = Vector2 {v2x, v2y :: {-# UNPACK #-} !Scalar} - deriving (Eq, Ord, Show) - -instance Vector Vector2 where - fromScalar x = Vector2 x x - vmap f (Vector2 x1 y1) = Vector2 (f x1) (f y1) - vzip f (Vector2 x1 y1) (Vector2 x2 y2) = Vector2 (f x1 x2) (f y1 y2) - vfold f (Vector2 x1 y1) = f x1 y1 - -instance Num Vector2 where - (+) = vzip (+) - (-) = vzip (-) - (*) = vzip (*) - negate = vmap negate - abs = vmap abs - signum = vmap signum - fromInteger n = let s = fromInteger n in fromScalar s - -instance Fractional Vector2 where - (/) = vzip (/) - recip = vmap recip - fromRational r = let s = fromRational r in fromScalar s - --- | Constant: The unit-length X vector, (1, 0). -vector2X :: Vector2 -vector2X = Vector2 1 0 - --- | Constant: The unit-length Y vector, (0, 1). -vector2Y :: Vector2 -vector2Y = Vector2 0 1 - - - -{- | - The type of 3-dimensional vectors. Similar to 'Vector2'. --} -data Vector3 = Vector3 {v3x, v3y, v3z :: {-# UNPACK #-} !Scalar} - deriving (Eq, Ord, Show) - -instance Vector Vector3 where - fromScalar x = Vector3 x x x - vmap f (Vector3 x1 y1 z1) = Vector3 (f x1) (f y1) (f z1) - vzip f (Vector3 x1 y1 z1) (Vector3 x2 y2 z2) = Vector3 (f x1 x2) (f y1 y2) (f z1 z2) - vfold f (Vector3 x1 y1 z1) = f x1 (f y1 z1) - -instance Num Vector3 where - (+) = vzip (+) - (-) = vzip (-) - (*) = vzip (*) - negate = vmap negate - abs = vmap abs - signum = vmap signum - fromInteger n = let s = fromInteger n in fromScalar s - -instance Fractional Vector3 where - (/) = vzip (/) - recip = vmap recip - fromRational r = let s = fromRational r in fromScalar s - -{- | - Takes the /cross product/ of two [3D] vectors. Again, from highschool - linear algebra, the cross product of vector V and W is a new vector - P such that |P| = |V| * |W| * sin k (where k is the minimum angle - between V and W), and the direction of P is perpendicular to both - V and W. For example, @vcross 'vector3X' 'vector3Y' = 'vector3Z'@. - Note also that @vcross w v = negate (vcross v w)@. --} -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 - } - --- | Constant: The unit-length X vector, (1, 0, 0). -vector3X :: Vector3 -vector3X = Vector3 1 0 0 +-- | Convenience module providing easy access to everything in this package. (See individual modules for fuller details.) --- | Constant: The unit-length Y vector, (0, 1, 0). -vector3Y :: Vector3 -vector3Y = Vector3 0 1 0 +module Data.Vector + ( + module Data.Vector.Class, + module Data.Vector.V1, + module Data.Vector.V2, + module Data.Vector.V3, + module Data.Vector.V4, + module Data.Vector.Transform, + ) + where --- | Constant: The unit-length Z vector, (0, 0, 1). -vector3Z :: Vector3 -vector3Z = Vector3 0 0 1 +import Data.Vector.Class +import Data.Vector.V1 +import Data.Vector.V2 +import Data.Vector.V3 +import Data.Vector.V4 +import Data.Vector.Transform
+ Data/Vector/Class.hs view
@@ -0,0 +1,72 @@+{- | + General function applicable to all vector types. +-} + +module Data.Vector.Class where + +-- | The type of vector field values. +type Scalar = Double + +{- | + All vector types belong to this class. Aside from 'vpack' and 'vunpack', these methods aren't especially useful to end-users; they're used internally by the vector arithmetic implementations. +-} +class Vector v where + -- | Apply a function to all vector fields. + vmap :: (Scalar -> Scalar) -> (v -> v) + + -- | Zip two vectors together field-by-field using the supplied function (in the style of @Data.List.zipWith@). + vzip :: (Scalar -> Scalar -> Scalar) -> (v -> v -> v) + + -- | Reduce a vector down to a single value using the supplied binary operator. The ordering in which this happens isn't guaranteed, so the operator should probably be associative and commutative. + vfold :: (Scalar -> Scalar -> Scalar) -> (v -> Scalar) + + -- | Pack a list of values into a vector. Extra values are ignored, too few values yields @Nothing@. + vpack :: [Scalar] -> Maybe v + + -- | Unpack a vector into a list of values. (Always succeeds.) + vunpack :: v -> [Scalar] + +{- | + Scale a vector (i.e., change its length but not its direction). This operator has the same precedence as the usual @(*)@ operator. + + The @(*|)@ and @(|*)@ operators are identical, but with their argument flipped. Just remember that the \'@|@\' denotes the scalar part. +-} +(*|) :: Vector v => Scalar -> v -> v +k *| v = vmap (k*) v + +{- | + Scale a vector (i.e., change its length but not its direction). This operator has the same precedence as the usual @(*)@ operator. + + The @(*|)@ and @(|*)@ operators are identical, but with their argument flipped. Just remember that the \'@|@\' denotes the scalar part. +-} +(|*) :: Vector v => v -> Scalar -> v +v |* k = vmap (k*) v + +infixl 7 *| +infixl 7 |* + +-- | Take the /dot product/ of two vectors. This is a scalar equal to the cosine of the angle between the two vectors multiplied by the length of each vectors. +vdot :: Vector v => v -> v -> Scalar +v1 `vdot` v2 = vfold (+) $ vzip (*) v1 v2 + +-- | Return the length or /magnitude/ of a vector. (Note that this involves a slow square root operation.) +vmag :: Vector v => v -> Scalar +vmag v = sqrt (v `vdot` v) + +-- | Normalise a vector. In order words, return a new vector with the same direction, but a length of exactly one. (If the vector's length is zero or very near to zero, the vector is returned unchanged.) +vnormalise :: Vector v => v -> v +vnormalise v = + let m = vmag v + in if m < 1e-16 then v else v |* (1/m) + +{- | + Linearly interpolate between two points in space. + + * @vlinear 0 a b = a@ + + * @vlinear 1 a b = b@ + + * @vlinear 0.5 a b@ would give a point exactly half way between @a@ and @b@ in a straight line. +-} +vlinear :: (Num v, Vector v) => Scalar -> v -> v -> v +vlinear t a b = (1-t) *| a + t *| b
+ Data/Vector/Transform.hs view
@@ -0,0 +1,17 @@+{- | + Convenience module to import all sizes of transform. (This doesn't include all the field names though, just the transform types and their application functions.) +-} + +module Data.Vector.Transform + ( + Transform1 (), transformP1, + Transform2 (), transformP2, + Transform3 (), transformP3, + Transform4 (), transformP4, + ) + where + +import Data.Vector.Transform.T1 +import Data.Vector.Transform.T2 +import Data.Vector.Transform.T3 +import Data.Vector.Transform.T4
+ Data/Vector/Transform/T1.hs view
@@ -0,0 +1,35 @@+{- | + 1-dimensional linear transformations. +-} + +module Data.Vector.Transform.T1 where + +import Data.Monoid + +import Data.Vector.Class +import Data.Vector.V1 + +{- | + The type of 1D linear transformations. Essentially, this is applying a linear function to a number. + + Note the @Monoid@ instance, which gives you access to the identity transform (@mempty@) and the ability to combine a series of transforms into a single transform (@mappend@). +-} +data Transform1 = + Transform1 + { + t1_XX, t1_1X :: {-# UNPACK #-} !Scalar + } + deriving (Eq, Show) + +instance Monoid Transform1 where + mempty = Transform1 1 0 + mappend a b = + Transform1 + { + t1_XX = t1_XX a * t1_XX b, + t1_1X = t1_1X a * t1_XX b + t1_1X b + } + +-- | Apply a 1D transformation to a 1D point, yielding a new 1D point. +transformP1 :: Transform1 -> Vector1 -> Vector1 +transformP1 a (Vector1 x) = Vector1 (t1_XX a * x + t1_1X a)
+ Data/Vector/Transform/T2.hs view
@@ -0,0 +1,46 @@+{- | + 2-dimensional linear transformations. +-} + +module Data.Vector.Transform.T2 where + +import Data.Monoid + +import Data.Vector.Class +import Data.Vector.V2 + +{- | + The type of 2D linear transformations. + + Note the @Monoid@ instance, which gives you access to the identity transform (@mempty@) and the ability to combine a series of transforms into a single transform (@mappend@). +-} +data Transform2 = + Transform2 + { + t2_XX, t2_YX, t2_1X, + t2_XY, t2_YY, t2_1Y :: {-# UNPACK #-} !Scalar + } + deriving (Eq, Show) + +instance Monoid Transform2 where + mempty = Transform2 1 0 0 0 1 0 + mappend a b = + Transform2 + { + t2_XX = t2_XX a * t2_XX b + t2_XY a * t2_YX b, + t2_YX = t2_YX a * t2_XX b + t2_YY a * t2_YX b, + t2_1X = t2_1X a * t2_XX b + t2_1Y a * t2_YX b + t2_1X b, + + t2_XY = t2_XX a * t2_XY b + t2_XY a * t2_YY b, + t2_YY = t2_YX a * t2_XY b + t2_YY a * t2_YY b, + t2_1Y = t2_1X a * t2_XY b + t2_1Y a * t2_YY b + t2_1Y b + } + +-- | Apply a 2D transformation to a 2D point, yielding a new 2D point. +transformP2 :: Transform2 -> Vector2 -> Vector2 +transformP2 a (Vector2 x y) = + Vector2 + { + v2x = t2_XX a * x + t2_YX a * y + t2_1X a, + v2y = t2_XY a * x + t2_YY a * y + t2_1Y a + }
+ Data/Vector/Transform/T3.hs view
@@ -0,0 +1,55 @@+{- | + 3-dimensional linear transformations. +-} + +module Data.Vector.Transform.T3 where + +import Data.Monoid + +import Data.Vector.Class +import Data.Vector.V3 + +{- | + The type of 3D linear transformations. + + Note the @Monoid@ instance, which gives you access to the identity transform (@mempty@) and the ability to combine a series of transforms into a single transform (@mappend@). +-} +data Transform3 = + Transform3 + { + t3_XX, t3_YX, t3_ZX, t3_1X, + t3_XY, t3_YY, t3_ZY, t3_1Y, + t3_XZ, t3_YZ, t3_ZZ, t3_1Z :: {-# UNPACK #-} !Scalar + } + deriving (Eq, Show) + +instance Monoid Transform3 where + mempty = Transform3 1 0 0 0 0 1 0 0 0 0 1 0 + mappend a b = + Transform3 + { + t3_XX = t3_XX a * t3_XX b + t3_XY a * t3_YX b + t3_XZ a * t3_ZX b, + t3_YX = t3_YX a * t3_XX b + t3_YY a * t3_YX b + t3_YZ a * t3_ZX b, + t3_ZX = t3_ZX a * t3_XX b + t3_ZY a * t3_YX b + t3_ZZ a * t3_ZX b, + t3_1X = t3_1X a * t3_XX b + t3_1Y a * t3_YX b + t3_1Z a * t3_ZX b + t3_1X b, + + t3_XY = t3_XX a * t3_XY b + t3_XY a * t3_YY b + t3_XZ a * t3_ZY b, + t3_YY = t3_YX a * t3_XY b + t3_YY a * t3_YY b + t3_YZ a * t3_ZY b, + t3_ZY = t3_ZX a * t3_XY b + t3_ZY a * t3_YY b + t3_ZZ a * t3_ZY b, + t3_1Y = t3_1X a * t3_XY b + t3_1Y a * t3_YY b + t3_1Z a * t3_ZY b + t3_1Y b, + + t3_XZ = t3_XX a * t3_XZ b + t3_XY a * t3_YZ b + t3_XZ a * t3_ZZ b, + t3_YZ = t3_YX a * t3_XZ b + t3_YY a * t3_YZ b + t3_YZ a * t3_ZZ b, + t3_ZZ = t3_ZX a * t3_XZ b + t3_ZY a * t3_YZ b + t3_ZZ a * t3_ZZ b, + t3_1Z = t3_1X a * t3_XZ b + t3_1Y a * t3_YZ b + t3_1Z a * t3_ZZ b + t3_1Z b + } + +-- | Apply a 3D transformation to a 3D point, yielding a new 3D point. +transformP3 :: Transform3 -> Vector3 -> Vector3 +transformP3 a (Vector3 x y z) = + Vector3 + { + v3x = t3_XX a * x + t3_YX a * y + t3_ZX a * z + t3_1X a, + v3y = t3_XY a * x + t3_YY a * y + t3_ZY a * z + t3_1Y a, + v3z = t3_XZ a * x + t3_YZ a * y + t3_ZZ a * z + t3_1Z a + }
+ Data/Vector/Transform/T4.hs view
@@ -0,0 +1,66 @@+{- | + 4-dimensional linear transformations. +-} + +module Data.Vector.Transform.T4 where + +import Data.Monoid + +import Data.Vector.Class +import Data.Vector.V4 + +{- | + The type of 4D linear transformations. + + Note the @Monoid@ instance, which gives you access to the identity transform (@mempty@) and the ability to combine a series of transforms into a single transform (@mappend@). +-} +data Transform4 = + Transform4 + { + t4_XX, t4_YX, t4_ZX, t4_WX, t4_1X, + t4_XY, t4_YY, t4_ZY, t4_WY, t4_1Y, + t4_XZ, t4_YZ, t4_ZZ, t4_WZ, t4_1Z, + t4_XW, t4_YW, t4_ZW, t4_WW, t4_1W :: {-# UNPACK #-} !Scalar + } + deriving (Eq, Show) + +instance Monoid Transform4 where + mempty = Transform4 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 + mappend a b = + Transform4 + { + t4_XX = t4_XX a * t4_XX b + t4_XY a * t4_YX b + t4_XZ a * t4_ZX b + t4_XW a * t4_WX b, + t4_YX = t4_YX a * t4_XX b + t4_YY a * t4_YX b + t4_YZ a * t4_ZX b + t4_YW a * t4_WX b, + t4_ZX = t4_ZX a * t4_XX b + t4_ZY a * t4_YX b + t4_ZZ a * t4_ZX b + t4_ZW a * t4_WX b, + t4_WX = t4_WX a * t4_XX b + t4_WY a * t4_YX b + t4_WZ a * t4_ZX b + t4_WW a * t4_WX b, + t4_1X = t4_1X a * t4_XX b + t4_1Y a * t4_YX b + t4_1Z a * t4_ZX b + t4_1W a * t4_WX b + t4_1X b, + + t4_XY = t4_XX a * t4_XY b + t4_XY a * t4_YY b + t4_XZ a * t4_ZY b + t4_XW a * t4_WY b, + t4_YY = t4_YX a * t4_XY b + t4_YY a * t4_YY b + t4_YZ a * t4_ZY b + t4_YW a * t4_WY b, + t4_ZY = t4_ZX a * t4_XY b + t4_ZY a * t4_YY b + t4_ZZ a * t4_ZY b + t4_ZW a * t4_WY b, + t4_WY = t4_WX a * t4_XY b + t4_WY a * t4_YY b + t4_WZ a * t4_ZY b + t4_WW a * t4_WY b, + t4_1Y = t4_1X a * t4_XY b + t4_1Y a * t4_YY b + t4_1Z a * t4_ZY b + t4_1W a * t4_WY b + t4_1Y b, + + t4_XZ = t4_XX a * t4_XZ b + t4_XY a * t4_YZ b + t4_XZ a * t4_ZZ b + t4_XW a * t4_WZ b, + t4_YZ = t4_YX a * t4_XZ b + t4_YY a * t4_YZ b + t4_YZ a * t4_ZZ b + t4_YW a * t4_WZ b, + t4_ZZ = t4_ZX a * t4_XZ b + t4_ZY a * t4_YZ b + t4_ZZ a * t4_ZZ b + t4_ZW a * t4_WZ b, + t4_WZ = t4_WX a * t4_XZ b + t4_WY a * t4_YZ b + t4_WZ a * t4_ZZ b + t4_WW a * t4_WZ b, + t4_1Z = t4_1X a * t4_XZ b + t4_1Y a * t4_YZ b + t4_1Z a * t4_ZZ b + t4_1W a * t4_WZ b + t4_1Z b, + + t4_XW = t4_XX a * t4_XW b + t4_XY a * t4_YW b + t4_XZ a * t4_ZW b + t4_XW a * t4_WW b, + t4_YW = t4_YX a * t4_XW b + t4_YY a * t4_YW b + t4_YZ a * t4_ZW b + t4_YW a * t4_WW b, + t4_ZW = t4_ZX a * t4_XW b + t4_ZY a * t4_YW b + t4_ZZ a * t4_ZW b + t4_ZW a * t4_WW b, + t4_WW = t4_WX a * t4_XW b + t4_WY a * t4_YW b + t4_WZ a * t4_ZW b + t4_WW a * t4_WW b, + t4_1W = t4_1X a * t4_XW b + t4_1Y a * t4_YW b + t4_1Z a * t4_ZW b + t4_1W a * t4_WW b + t4_1W b + } + +-- | Apply a 4D transformation to a 4D point, yielding a new 4D point. +transformP4 :: Transform4 -> Vector4 -> Vector4 +transformP4 a (Vector4 x y z w) = + Vector4 + { + v4x = t4_XX a * x + t4_YX a * y + t4_ZX a * z + t4_WX a * w + t4_1X a, + v4y = t4_XY a * x + t4_YY a * y + t4_ZY a * z + t4_WY a * w + t4_1Y a, + v4z = t4_XZ a * x + t4_YZ a * y + t4_ZZ a * z + t4_WZ a * w + t4_1Z a, + v4w = t4_XW a * x + t4_YW a * y + t4_ZW a * z + t4_WW a * w + t4_1W a + }
+ Data/Vector/V1.hs view
@@ -0,0 +1,28 @@+{- | + 1-dimensional vectors with vector arithmetic. + + This isn't especially useful. Usually if you want to calculate with scalars, you can just use the 'Scalar' type directly. However, this module provides a 'Vector1' newtype over 'Scalar' that allows a scalar to be treated as a sort of vector, which is very occasionally useful. +-} + +{-# LANGUAGE GeneralizedNewtypeDeriving #-} + +module Data.Vector.V1 where + +import Data.Vector.Class + +{- | + The type of 1D vectors. + + Owing to its particularly simple structure, this type has more class instances than \'propper\' vectors have. Still, for the most part you'll probably want to just use 'Scalar' itself directly. +-} +newtype Vector1 = Vector1 {v1x :: Scalar} deriving (Eq, Ord, Enum, Show, Num, Fractional) + +instance Vector Vector1 where + vmap f (Vector1 x ) = Vector1 (f x) + vzip f (Vector1 x1) (Vector1 x2) = Vector1 (f x1 x2) + vfold _ (Vector1 x ) = x + + vpack (x:_) = Just $ Vector1 x + vpack _ = Nothing + + vunpack (Vector1 x) = [x]
+ Data/Vector/V2.hs view
@@ -0,0 +1,32 @@+{- | + 2-dimensional vectors with vector arithmetic. +-} + +module Data.Vector.V2 where + +import Data.Vector.Class + +data Vector2 = Vector2 {v2x, v2y :: {-# UNPACK #-} !Scalar} deriving (Eq, Show) + +instance Vector Vector2 where + vmap f (Vector2 x y ) = Vector2 (f x) (f y) + vzip f (Vector2 x1 y1) (Vector2 x2 y2) = Vector2 (f x1 x2) (f y1 y2) + vfold f (Vector2 x y ) = f x y + + vpack (x:y:_) = Just $ Vector2 x y + vpack _ = Nothing + + vunpack (Vector2 x y) = [x,y] + +instance Num Vector2 where + (+) = vzip (+) + (-) = vzip (-) + (*) = vzip (*) + abs = vmap abs + signum = vmap signum + fromInteger x = let x' = fromInteger x in Vector2 x' x' + +instance Fractional Vector2 where + (/) = vzip (/) + recip = vmap recip + fromRational x = let x' = fromRational x in Vector2 x' x'
+ Data/Vector/V3.hs view
@@ -0,0 +1,46 @@+{- | + 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 Vector 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] + +instance Num Vector3 where + (+) = vzip (+) + (-) = vzip (-) + (*) = vzip (*) + abs = vmap abs + signum = vmap signum + fromInteger x = let x' = fromInteger x in Vector3 x' x' x' + +instance Fractional Vector3 where + (/) = vzip (/) + recip = vmap recip + fromRational x = let x' = fromRational x in Vector3 x' x' x' + +{- | + 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 + }
+ Data/Vector/V4.hs view
@@ -0,0 +1,32 @@+{- | + 4-dimensional vectors with vector arithmetic. +-} + +module Data.Vector.V4 where + +import Data.Vector.Class + +data Vector4 = Vector4 {v4x, v4y, v4z, v4w :: {-# UNPACK #-} !Scalar} deriving (Eq, Show) + +instance Vector Vector4 where + vmap f (Vector4 x y z w ) = Vector4 (f x) (f y) (f z) (f w) + vzip f (Vector4 x1 y1 z1 w1) (Vector4 x2 y2 z2 w2) = Vector4 (f x1 x2) (f y1 y2) (f z1 z2) (f w1 w2) + vfold f (Vector4 x y z w ) = f (f x y) (f z w) + + vpack (x:y:z:w:_) = Just $ Vector4 x y z w + vpack _ = Nothing + + vunpack (Vector4 x y z w) = [x,y,z,w] + +instance Num Vector4 where + (+) = vzip (+) + (-) = vzip (-) + (*) = vzip (*) + abs = vmap abs + signum = vmap signum + fromInteger x = let x' = fromInteger x in Vector4 x' x' x' x' + +instance Fractional Vector4 where + (/) = vzip (/) + recip = vmap recip + fromRational x = let x' = fromRational x in Vector4 x' x' x' x'
Setup.hs view
@@ -1,3 +1,2 @@ import Distribution.Simple - main = defaultMain