packages feed

simple-vec3 0.1.0.1 → 0.2

raw patch · 9 files changed

+419/−317 lines, 9 filesdep +QuickCheckdep +tastydep +tasty-quickcheckdep ~basedep ~criteriondep ~simple-vec3PVP ok

version bump matches the API change (PVP)

Dependencies added: QuickCheck, tasty, tasty-quickcheck, tasty-th, vector-th-unbox

Dependency ranges changed: base, criterion, simple-vec3, vector

API changes (from Hackage documentation)

- Data.Vec3: TUVec3 :: (Double, Double, Double) -> TUVec3
- Data.Vec3: data UVec3
- Data.Vec3: newtype TUVec3
- Data.Vec3.Storable: SVec3 :: !CDouble -> !CDouble -> !CDouble -> SVec3
- Data.Vec3.Storable: data SVec3
- Data.Vec3.Storable: instance Eq SVec3
- Data.Vec3.Storable: instance Show SVec3
- Data.Vec3.Storable: instance Storable SVec3
- Data.Vec3.Storable: instance Vec3 SVec3
- Data.Vec3.TUnboxed: TUVec3 :: (Double, Double, Double) -> TUVec3
- Data.Vec3.TUnboxed: instance Eq (Matrix TUVec3)
- Data.Vec3.TUnboxed: instance Eq TUVec3
- Data.Vec3.TUnboxed: instance MVector MVector (Matrix TUVec3)
- Data.Vec3.TUnboxed: instance MVector MVector TUVec3
- Data.Vec3.TUnboxed: instance Show (Matrix TUVec3)
- Data.Vec3.TUnboxed: instance Show TUVec3
- Data.Vec3.TUnboxed: instance Unbox (Matrix TUVec3)
- Data.Vec3.TUnboxed: instance Unbox TUVec3
- Data.Vec3.TUnboxed: instance Vec3 TUVec3
- Data.Vec3.TUnboxed: instance Vector Vector (Matrix TUVec3)
- Data.Vec3.TUnboxed: instance Vector Vector TUVec3
- Data.Vec3.TUnboxed: newtype TUVec3
- Data.Vec3.Unboxed: data UVec3
- Data.Vec3.Unboxed: instance Eq UVec3
- Data.Vec3.Unboxed: instance MVector MVector UVec3
- Data.Vec3.Unboxed: instance Show UVec3
- Data.Vec3.Unboxed: instance Unbox UVec3
- Data.Vec3.Unboxed: instance Vec3 UVec3
- Data.Vec3.Unboxed: instance Vector Vector UVec3
+ Data.Vec3: data family Matrix v;
+ Data.Vec3: instance Data.Vec3.Class.Vec3 Data.Vec3.SVec3
+ Data.Vec3: instance Foreign.Storable.Storable Data.Vec3.SVec3
+ Data.Vec3: instance GHC.Classes.Eq (Data.Vec3.Class.Matrix Data.Vec3.SVec3)
+ Data.Vec3: instance GHC.Classes.Eq Data.Vec3.SVec3
+ Data.Vec3: instance GHC.Show.Show (Data.Vec3.Class.Matrix Data.Vec3.SVec3)
+ Data.Vec3: instance GHC.Show.Show Data.Vec3.SVec3
+ Data.Vec3: instance Test.QuickCheck.Arbitrary.Arbitrary Data.Vec3.SVec3
+ Data.Vec3: newtype UVec3
+ Data.Vec3: }
+ Data.Vec3.Class: data family Matrix v;
+ Data.Vec3.Class: }
+ Data.Vec3.Unboxed: instance Data.Vec3.Class.Vec3 Data.Vec3.Unboxed.UVec3
+ Data.Vec3.Unboxed: instance Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector (Data.Vec3.Class.Matrix Data.Vec3.Unboxed.UVec3)
+ Data.Vec3.Unboxed: instance Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector Data.Vec3.Unboxed.UVec3
+ Data.Vec3.Unboxed: instance Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector (Data.Vec3.Class.Matrix Data.Vec3.Unboxed.UVec3)
+ Data.Vec3.Unboxed: instance Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector Data.Vec3.Unboxed.UVec3
+ Data.Vec3.Unboxed: instance Data.Vector.Unboxed.Base.Unbox (Data.Vec3.Class.Matrix Data.Vec3.Unboxed.UVec3)
+ Data.Vec3.Unboxed: instance Data.Vector.Unboxed.Base.Unbox Data.Vec3.Unboxed.UVec3
+ Data.Vec3.Unboxed: instance GHC.Classes.Eq (Data.Vec3.Class.Matrix Data.Vec3.Unboxed.UVec3)
+ Data.Vec3.Unboxed: instance GHC.Classes.Eq Data.Vec3.Unboxed.UVec3
+ Data.Vec3.Unboxed: instance GHC.Show.Show (Data.Vec3.Class.Matrix Data.Vec3.Unboxed.UVec3)
+ Data.Vec3.Unboxed: instance GHC.Show.Show Data.Vec3.Unboxed.UVec3
+ Data.Vec3.Unboxed: newtype UVec3
+ Data.Vec3.Unboxed.Contiguous: UVec3 :: !Double -> !Double -> !Double -> UVec3
+ Data.Vec3.Unboxed.Contiguous: data UVec3
+ Data.Vec3.Unboxed.Contiguous: instance Data.Vec3.Class.Vec3 Data.Vec3.Unboxed.Contiguous.UVec3
+ Data.Vec3.Unboxed.Contiguous: instance Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector Data.Vec3.Unboxed.Contiguous.UVec3
+ Data.Vec3.Unboxed.Contiguous: instance Data.Vector.Generic.Mutable.Base.MVector Data.Vector.Unboxed.Base.MVector Data.Vec3.Unboxed.Contiguous.UVec3
+ Data.Vec3.Unboxed.Contiguous: instance Data.Vector.Unboxed.Base.Unbox Data.Vec3.Unboxed.Contiguous.UVec3
+ Data.Vec3.Unboxed.Contiguous: instance GHC.Classes.Eq Data.Vec3.Unboxed.Contiguous.UVec3
+ Data.Vec3.Unboxed.Contiguous: instance GHC.Show.Show Data.Vec3.Unboxed.Contiguous.UVec3
- Data.Vec3: UVec3 :: !Double -> !Double -> !Double -> UVec3
+ Data.Vec3: UVec3 :: (Double, Double, Double) -> UVec3
- Data.Vec3: class Vec3 v where data family Matrix v origin = fromXYZ (0, 0, 0) zipWith f v1 v2 = fromXYZ (f x1 x2, f y1 y2, f z1 z2) where (x1, y1, z1) = toXYZ v1 (x2, y2, z2) = toXYZ v2 <+> v1 v2 = zipWith (+) v1 v2 <-> v1 v2 = zipWith (-) v1 v2 >< v1 v2 = fromXYZ (y1 * z2 - y2 * z1, x2 * z1 - x1 * z2, x1 * y2 - x2 * y1) where (x1, y1, z1) = toXYZ v1 (x2, y2, z2) = toXYZ v2 .^ v s = fromXYZ (x * s, y * s, z * s) where (x, y, z) = toXYZ v .* v1 v2 = x + y + z where (x, y, z) = toXYZ $ zipWith (*) v1 v2 norm v = sqrt (v .* v) normalize v = v .^ (1 / norm v) distance v1 v2 = norm (v1 <-> v2) invert v = origin <-> v dotM v1 v2 m = v1 .* (m `mxv` v2) mxv m v = fromXYZ (r1 .* v, r2 .* v, r3 .* v) where (r1, r2, r3) = toRows m diag d = fromRows (fromXYZ (d, 0, 0), fromXYZ (0, d, 0), fromXYZ (0, 0, d)) vxv v1 v2 = fromRows (v2 .^ v11, v2 .^ v12, v2 .^ v13) where (v11, v12, v13) = toXYZ v1 addM m1 m2 = fromRows (r11 <+> r21, r12 <+> r22, r13 <+> r23) where (r11, r12, r13) = toRows m1 (r21, r22, r23) = toRows m2
+ Data.Vec3: class Vec3 v where data Matrix v origin = fromXYZ (0, 0, 0) zipWith f v1 v2 = fromXYZ (f x1 x2, f y1 y2, f z1 z2) where (x1, y1, z1) = toXYZ v1 (x2, y2, z2) = toXYZ v2 (<+>) = zipWith (+) (<->) = zipWith (-) (><) v1 v2 = fromXYZ (y1 * z2 - y2 * z1, x2 * z1 - x1 * z2, x1 * y2 - x2 * y1) where (x1, y1, z1) = toXYZ v1 (x2, y2, z2) = toXYZ v2 (.^) v s = fromXYZ (x * s, y * s, z * s) where (x, y, z) = toXYZ v (.*) v1 v2 = x + y + z where (x, y, z) = toXYZ $ zipWith (*) v1 v2 norm v = sqrt (v .* v) normalize v = v .^ (1 / norm v) distance v1 v2 = norm (v1 <-> v2) invert v = origin <-> v dotM v1 v2 m = v1 .* (m `mxv` v2) mxv m v = fromXYZ (r1 .* v, r2 .* v, r3 .* v) where (r1, r2, r3) = toRows m diag d = fromRows (fromXYZ (d, 0, 0), fromXYZ (0, d, 0), fromXYZ (0, 0, d)) vxv v1 v2 = fromRows (v2 .^ v11, v2 .^ v12, v2 .^ v13) where (v11, v12, v13) = toXYZ v1 addM m1 m2 = fromRows (r11 <+> r21, r12 <+> r22, r13 <+> r23) where (r11, r12, r13) = toRows m1 (r21, r22, r23) = toRows m2 where {
- Data.Vec3.Class: class Vec3 v where data family Matrix v origin = fromXYZ (0, 0, 0) zipWith f v1 v2 = fromXYZ (f x1 x2, f y1 y2, f z1 z2) where (x1, y1, z1) = toXYZ v1 (x2, y2, z2) = toXYZ v2 <+> v1 v2 = zipWith (+) v1 v2 <-> v1 v2 = zipWith (-) v1 v2 >< v1 v2 = fromXYZ (y1 * z2 - y2 * z1, x2 * z1 - x1 * z2, x1 * y2 - x2 * y1) where (x1, y1, z1) = toXYZ v1 (x2, y2, z2) = toXYZ v2 .^ v s = fromXYZ (x * s, y * s, z * s) where (x, y, z) = toXYZ v .* v1 v2 = x + y + z where (x, y, z) = toXYZ $ zipWith (*) v1 v2 norm v = sqrt (v .* v) normalize v = v .^ (1 / norm v) distance v1 v2 = norm (v1 <-> v2) invert v = origin <-> v dotM v1 v2 m = v1 .* (m `mxv` v2) mxv m v = fromXYZ (r1 .* v, r2 .* v, r3 .* v) where (r1, r2, r3) = toRows m diag d = fromRows (fromXYZ (d, 0, 0), fromXYZ (0, d, 0), fromXYZ (0, 0, d)) vxv v1 v2 = fromRows (v2 .^ v11, v2 .^ v12, v2 .^ v13) where (v11, v12, v13) = toXYZ v1 addM m1 m2 = fromRows (r11 <+> r21, r12 <+> r22, r13 <+> r23) where (r11, r12, r13) = toRows m1 (r21, r22, r23) = toRows m2
+ Data.Vec3.Class: class Vec3 v where data Matrix v origin = fromXYZ (0, 0, 0) zipWith f v1 v2 = fromXYZ (f x1 x2, f y1 y2, f z1 z2) where (x1, y1, z1) = toXYZ v1 (x2, y2, z2) = toXYZ v2 (<+>) = zipWith (+) (<->) = zipWith (-) (><) v1 v2 = fromXYZ (y1 * z2 - y2 * z1, x2 * z1 - x1 * z2, x1 * y2 - x2 * y1) where (x1, y1, z1) = toXYZ v1 (x2, y2, z2) = toXYZ v2 (.^) v s = fromXYZ (x * s, y * s, z * s) where (x, y, z) = toXYZ v (.*) v1 v2 = x + y + z where (x, y, z) = toXYZ $ zipWith (*) v1 v2 norm v = sqrt (v .* v) normalize v = v .^ (1 / norm v) distance v1 v2 = norm (v1 <-> v2) invert v = origin <-> v dotM v1 v2 m = v1 .* (m `mxv` v2) mxv m v = fromXYZ (r1 .* v, r2 .* v, r3 .* v) where (r1, r2, r3) = toRows m diag d = fromRows (fromXYZ (d, 0, 0), fromXYZ (0, d, 0), fromXYZ (0, 0, d)) vxv v1 v2 = fromRows (v2 .^ v11, v2 .^ v12, v2 .^ v13) where (v11, v12, v13) = toXYZ v1 addM m1 m2 = fromRows (r11 <+> r21, r12 <+> r22, r13 <+> r23) where (r11, r12, r13) = toRows m1 (r21, r22, r23) = toRows m2 where {
- Data.Vec3.Unboxed: UVec3 :: !Double -> !Double -> !Double -> UVec3
+ Data.Vec3.Unboxed: UVec3 :: (Double, Double, Double) -> UVec3

Files

benchmark/Benchmark.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleContexts #-}+ import Criterion.Main  import Data.Vector.Generic as VG@@ -7,6 +7,7 @@ import Data.Vector.Unboxed as VU  import Data.Vec3+import qualified Data.Vec3.Unboxed.Contiguous as C   oXYZ :: (Double, Double, Double)@@ -20,64 +21,55 @@ n :: Int n = 1000000 + bigN :: Int bigN = n * 10 -foo :: Vec3 v => v -> v -> Double-foo v1 v2 = x1 + x2-    where-      (x1, _, _) = toXYZ v1-      (x2, _, _) = toXYZ v2-{-# INLINE foo #-} - -- Access to whole elements-test :: (Show a, Vec3 a, VG.Vector v a) => v a -> v a -> IO ()-test v v2 = do-  let !vr = VG.zipWith (<+>) v v-  return ()-{-# INLINE test #-}+testWhole :: (Vec3 a, VG.Vector v a) => v a -> v a -> Benchmarkable+testWhole v v2 = whnf (uncurry $ VG.zipWith (<+>)) (v, v2)   -- Access to x components of elements-testComp :: (Show a, Vec3 a, VG.Vector v a, VG.Vector v Double) => v a -> v a -> IO ()-testComp v v2 = do-  let !vr = VG.zipWith (foo) v v-  return ()-{-# INLINE testComp #-}+testComp :: (Vec3 a, VG.Vector v a, VG.Vector v Double) => v a -> v a -> Benchmarkable+testComp v v' = whnf (uncurry $ VG.zipWith foo) (v, v')+  where+    foo v1 v2 = x1 + x2+      where+        (x1, _, _) = toXYZ v1+        (x2, _, _) = toXYZ v2   -- zipWith using generic dot product-testDotM :: (Show a, Vec3 a, VG.Vector v a, VG.Vector v Double) => v a -> v a -> IO ()-testDotM v v2 = do-  let o = fromXYZ oXYZ-      m = fromRows (o, o, o)-      dotM' e1 e2 = dotM e1 e2 m-      !vr = VG.zipWith dotM' v v2-  return ()-{-# INLINE testDotM #-}+testDotM :: (Vec3 a, VG.Vector v a, VG.Vector v Double) => v a -> v a -> Benchmarkable+testDotM v v2 = whnf (uncurry $ VG.zipWith dotM') (v, v2)+  where+    o = fromXYZ oXYZ+    m = fromRows (o, o, o)+    dotM' e1 e2 = dotM e1 e2 m   -- Note that source arrays are not forced in test functions. -tv :: VU.Vector TUVec3+tv :: VU.Vector UVec3 tv = VG.replicate n $ fromXYZ oXYZ  -uv :: VU.Vector UVec3-uv = VG.replicate n $ fromXYZ oXYZ+cv :: VU.Vector C.UVec3+cv = VG.replicate n $ fromXYZ oXYZ   sv :: VS.Vector SVec3 sv = VG.replicate n $ fromXYZ oXYZ  -tv' :: VU.Vector TUVec3+tv' :: VU.Vector UVec3 tv' = VG.replicate n $ fromXYZ oXYZ'  -uv' :: VU.Vector UVec3-uv' = VG.replicate n $ fromXYZ oXYZ'+cv' :: VU.Vector C.UVec3+cv' = VG.replicate n $ fromXYZ oXYZ'   sv' :: VS.Vector SVec3@@ -88,11 +80,11 @@ bsv = VG.replicate bigN $ fromXYZ oXYZ  -buv :: VU.Vector UVec3-buv = VG.replicate bigN $ fromXYZ oXYZ+bcv :: VU.Vector C.UVec3+bcv = VG.replicate bigN $ fromXYZ oXYZ  -btv :: VU.Vector TUVec3+btv :: VU.Vector UVec3 btv = VG.replicate bigN $ fromXYZ oXYZ  @@ -100,43 +92,44 @@ bsv' = VG.replicate bigN $ fromXYZ oXYZ'  -buv' :: VU.Vector UVec3-buv' = VG.replicate bigN $ fromXYZ oXYZ'+bcv' :: VU.Vector C.UVec3+bcv' = VG.replicate bigN $ fromXYZ oXYZ'  -btv' :: VU.Vector TUVec3+btv' :: VU.Vector UVec3 btv' = VG.replicate bigN $ fromXYZ oXYZ'  +main :: IO () main = defaultMain        [ bgroup "zipWith"-                    [ bench "Storable"             $ test sv sv'-                    , bench "Unboxed (contiguous)" $ test uv uv'-                    , bench "Unboxed (tuples)"     $ test tv tv'+                    [ bench "SVec/Storable"           $ testWhole sv sv'+                    , bench "UVec/Unboxed"            $ testWhole tv tv'+                    , bench "UVec/Unboxed/Contiguous" $ testWhole cv cv'                     ]        , bgroup "zipWith-by-x"-                    [ bench "Storable"             $ testComp sv sv'-                    , bench "Unboxed (contiguous)" $ testComp uv uv'-                    , bench "Unboxed (tuples)"     $ testComp tv tv'+                    [ bench "SVec/Storable"           $ testComp sv sv'+                    , bench "UVec/Unboxed"            $ testComp tv tv'+                    , bench "UVec/Unboxed/Contiguous" $ testComp cv cv'                     ]        , bgroup "zipWith-dotM"-                    [ bench "Storable"             $ testDotM sv sv'-                    , bench "Unboxed (contiguous)" $ testDotM uv uv'-                    , bench "Unboxed (tuples)"     $ testDotM tv tv'+                    [ bench "SVec/Storable"           $ testDotM sv sv'+                    , bench "UVec/Unboxed"            $ testDotM tv tv'+                    , bench "UVec/Unboxed/Contiguous" $ testDotM cv cv'                     ]        , bgroup "zipWith 10M"-                    [ bench "Storable"             $ test bsv bsv'-                    , bench "Unboxed (contiguous)" $ test buv buv'-                    , bench "Unboxed (tuples)"     $ test btv btv'+                    [ bench "SVec/Storable"           $ testWhole bsv bsv'+                    , bench "UVec/Unboxed"            $ testWhole btv btv'+                    , bench "UVec/Unboxed/Contiguous" $ testWhole bcv bcv'                     ]        , bgroup "zipWith-by-x 10M"-                    [ bench "Storable"             $ testComp bsv bsv'-                    , bench "Unboxed (contiguous)" $ testComp buv buv'-                    , bench "Unboxed (tuples)"     $ testComp btv btv'+                    [ bench "SVec/Storable"           $ testComp bsv bsv'+                    , bench "UVec/Unboxed"            $ testComp btv btv'+                    , bench "UVec/Unboxed/Contiguous" $ testComp bcv bcv'                     ]        , bgroup "zipWith-dotM 10M"-                    [ bench "Storable"             $ testDotM bsv bsv'-                    , bench "Unboxed (contiguous)" $ testDotM buv buv'-                    , bench "Unboxed (tuples)"     $ testDotM btv btv'+                    [ bench "SVec/Storable"           $ testDotM bsv bsv'+                    , bench "UVec/Unboxed"            $ testDotM btv btv'+                    , bench "UVec/Unboxed/Contiguous" $ testDotM bcv bcv'                     ]        ]
simple-vec3.cabal view
@@ -1,53 +1,63 @@-name:                simple-vec3-version:             0.1.0.1--synopsis:            Three-dimensional vectors of doubles with basic operations--description:         A class of 3-vectors with a set of basic methods for-                     geometry operations on vectors and an associated-                     matrix type. Several instances are provided for-                     use with "Data.Vector.Unboxed" and-                     "Data.Vector.Storable" as container types.--homepage:            http://github.com/dzhus/simple-vec3/-license:             BSD3-license-file:        LICENSE-author:              Dmitry Dzhus-maintainer:          <dima@dzhus.org>-category:            Math, Numerical--build-type:          Simple-cabal-version:       >=1.8-tested-with:         GHC == 7.6.1+name: simple-vec3+version: 0.2+cabal-version: >=1.10+build-type: Simple+license: BSD3+license-file: LICENSE+maintainer: <dima@dzhus.org>+homepage: https://github.com/dzhus/simple-vec3#readme+bug-reports: https://github.com/dzhus/simple-vec3/issues+synopsis: Three-dimensional vectors of doubles with basic operations+description:+    A class of 3-vectors with a set of basic methods for geometry operations on vectors and an associated matrix type. Instances are provided for use with "Data.Vector.Unboxed" and "Data.Vector.Storable" as container types.+category: Math, Numerical+author: Dmitry Dzhus  source-repository head-  type:     git-  location: http://github.com/dzhus/simple-vec3/+    type: git+    location: https://github.com/dzhus/simple-vec3  library-  hs-source-dirs: src--  ghc-options: -Wall -O2 -fllvm--  exposed-modules:-    Data.Vec3-    Data.Vec3.Class-    Data.Vec3.Storable-    Data.Vec3.TUnboxed-    Data.Vec3.Unboxed+    exposed-modules:+        Data.Vec3+        Data.Vec3.Class+        Data.Vec3.Unboxed+        Data.Vec3.Unboxed.Contiguous+    build-depends:+        base >=4.9.0.0 && <5,+        QuickCheck >=2.8.2,+        vector >=0.11.0.0,+        vector-th-unbox >=0.2.1.6+    default-language: Haskell2010+    hs-source-dirs: src+    ghc-options: -Wall -  build-depends:-    base        == 4.6.*,-    vector      == 0.10.*+test-suite pythia-recommender-test+    type: exitcode-stdio-1.0+    main-is: Tests.hs+    build-depends:+        base >=4.9.0.0 && <5,+        QuickCheck >=2.8.2,+        vector >=0.11.0.0,+        vector-th-unbox >=0.2.1.6,+        simple-vec3 >=0.2,+        tasty >=0.11.0.4,+        tasty-quickcheck >=0.8.4,+        tasty-th >=0.1.4+    default-language: Haskell2010+    hs-source-dirs: tests+    ghc-options: -Wall  benchmark simple-vec3-benchmark-   type:    exitcode-stdio-1.0-   main-is: benchmark/Benchmark.hs--   ghc-options: -Wall -O2 -fllvm -rtsopts--   build-depends:-     base       == 4.6.*,-     criterion  == 0.6.*,-     simple-vec3,-     vector     == 0.10.*+    type: exitcode-stdio-1.0+    main-is: Benchmark.hs+    build-depends:+        base >=4.9.0.0 && <5,+        QuickCheck >=2.8.2,+        vector >=0.11.0.0,+        vector-th-unbox >=0.2.1.6,+        criterion >=1.1.1.0,+        simple-vec3 >=0.2+    default-language: Haskell2010+    hs-source-dirs: benchmark+    ghc-options: -Wall
src/Data/Vec3.hs view
@@ -1,13 +1,91 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}++{-|++'Vec3' class and implementations.++-}+ module Data.Vec3     ( Vec3(..)-    , UVec3(..)     , SVec3(..)-    , TUVec3(..)+    , UVec3(..)     )  where +import Prelude hiding (reverse)++import Foreign+import Foreign.C.Types+ import Data.Vec3.Class-import Data.Vec3.Storable-import Data.Vec3.TUnboxed import Data.Vec3.Unboxed++import Test.QuickCheck+++-- | 'Vec3' implementation with 'Foreign.Storable.Storable' instance+-- based on a single contiguous array storage scheme, suitable for use+-- with "Data.Vector.Storable".+--+-- 'Unbox' instance provides the required index transformations.+--+-- @+-- interface: [d1 x   y   z  ; d2 x   y   z  ...], length = N = M / 3+--                |   |   |       |   |   |+-- storage:   [  d1x d2y d2z ;   d2x d2y d2z ...], length = M+-- @+data SVec3 = SVec3 !CDouble !CDouble !CDouble+             deriving (Eq, Show)+++instance Storable SVec3 where+  sizeOf _    = sizeOf (undefined :: CDouble) * 3+  alignment _ = alignment (undefined :: CDouble)++  peek p = do+      x <- peekElemOff q 0+      y <- peekElemOff q 1+      z <- peekElemOff q 2+      return $ SVec3 x y z+    where+      q = castPtr p+  {-# INLINE peek #-}++  poke p (SVec3 x y z) = do+      pokeElemOff q 0 x+      pokeElemOff q 1 y+      pokeElemOff q 2 z+    where+      q = castPtr p+  {-# INLINE poke #-}+++instance Vec3 SVec3 where+    newtype Matrix SVec3 = SMatrix (SVec3, SVec3, SVec3)+                           deriving (Eq, Show)++    fromXYZ (x, y, z) = SVec3 (CDouble x) (CDouble y) (CDouble z)+    {-# INLINE fromXYZ #-}++    toXYZ (SVec3 (CDouble x) (CDouble y) (CDouble z)) = (x, y, z)+    {-# INLINE toXYZ #-}++    fromRows (r1, r2, r3) = SMatrix (r1, r2, r3)+    {-# INLINE fromRows #-}++    toRows (SMatrix (r1, r2, r3)) = (r1, r2, r3)+    {-# INLINE toRows #-}+++instance Arbitrary SVec3 where+  arbitrary = do+    x <- arbitrary+    y <- arbitrary+    z <- arbitrary+    return $ fromXYZ (x, y, z)++  shrink (SVec3 (CDouble x) (CDouble y) (CDouble z)) =+    map fromXYZ $ shrink (x, y, z)
src/Data/Vec3/Class.hs view
@@ -34,12 +34,12 @@      -- | Add two vectors.     (<+>)          :: v -> v -> v-    (<+>) v1 v2     = zipWith (+) v1 v2+    (<+>)          = zipWith (+)     {-# INLINE (<+>) #-}      -- | Subtract two vectors.     (<->)          :: v -> v -> v-    (<->) v1 v2     = zipWith (-) v1 v2+    (<->)          = zipWith (-)     {-# INLINE (<->) #-}      -- | Cross product.@@ -140,7 +140,7 @@      -- | Transpose a vector and multiply it by another vector,     -- producing a matrix.-    -- +    --     -- @     -- [ v1x ]                       [ r11  r12  r13 ]     -- [     ]                       [               ]
− src/Data/Vec3/Storable.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeFamilies #-}--module Data.Vec3.Storable-    ( SVec3(..)-    )--where--import Prelude hiding (reverse)--import Foreign-import Foreign.C.Types----import Data.Vector.Storable as VS--import Data.Vec3.Class----- | 'Vec3' implementation with 'Foreign.Storable.Storable' instance,--- suitable for use with "Data.Vector.Storable".-data SVec3 = SVec3 !CDouble !CDouble !CDouble-             deriving (Eq, Show)---instance Storable SVec3 where-  sizeOf _    = sizeOf (undefined :: CDouble) * 3-  alignment _ = alignment (undefined :: CDouble)--  peek p = do-      x <- peekElemOff q 0-      y <- peekElemOff q 1-      z <- peekElemOff q 2-      return $ SVec3 x y z-    where-      q = castPtr p-  {-# INLINE peek #-}--  poke p (SVec3 x y z) = do-      pokeElemOff q 0 x-      pokeElemOff q 1 y-      pokeElemOff q 2 z-    where-      q = castPtr p-  {-# INLINE poke #-}---instance Vec3 SVec3 where-    newtype Matrix SVec3 = SMatrix (SVec3, SVec3, SVec3)--    fromXYZ (x, y, z) = SVec3 (CDouble x) (CDouble y) (CDouble z)-    {-# INLINE fromXYZ #-}--    toXYZ (SVec3 (CDouble x) (CDouble y) (CDouble z)) = (x, y, z)-    {-# INLINE toXYZ #-}--    fromRows (r1, r2, r3) = SMatrix (r1, r2, r3)-    {-# INLINE fromRows #-}--    toRows (SMatrix (r1, r2, r3)) = (r1, r2, r3)-    {-# INLINE toRows #-}
− src/Data/Vec3/TUnboxed.hs
@@ -1,58 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE TypeFamilies #-}--module Data.Vec3.TUnboxed-    ( TUVec3(..)-    )--where--import Prelude hiding (reverse)--import Data.Vector.Unboxed as VU-import Data.Vector.Generic as VG-import Data.Vector.Generic.Mutable as VG--import Data.Vec3.Class----- | 'Vec3' implementation with 'Data.Vector.Unboxed.Unbox' instance--- based on tuples, suitable for use with "Data.Vector.Unboxed".------ This represents 3-vector as a triple of doubles, using the default--- Unbox instance for tuples as provided by "Data.Vector.Unboxed",--- which wraps a vector of tuples as a tuple of vectors.------ @--- interface:  [d1 (x, y, z); d2 (x, y, z) ...], length = N---                  |  |  |       |  |  |--- storage(x): [d1x-+  |  | ; d2x-+  |  |  ...], length = N--- storage(y): [d1y----+  | ; d2y----+  |  ...], length = N--- storage(z): [d1z-------+ ; d2z-------+  ...], length = N--- @-newtype TUVec3 = TUVec3 (Double, Double, Double)-                deriving (Eq, Show,-                          VG.Vector VU.Vector,-                          VG.MVector VU.MVector,-                          VU.Unbox)---instance Vec3 TUVec3 where-    newtype Matrix TUVec3 = TUMatrix (TUVec3, TUVec3, TUVec3)-                            deriving (Eq, Show,-                                      VG.Vector VU.Vector,-                                      VG.MVector VU.MVector,-                                      VU.Unbox)---    fromXYZ v = TUVec3 v-    {-# INLINE fromXYZ #-}--    toXYZ (TUVec3 v) = v-    {-# INLINE toXYZ #-}--    fromRows (r1, r2, r3) = TUMatrix (r1, r2, r3)-    {-# INLINE fromRows #-}--    toRows (TUMatrix (r1, r2, r3)) = (r1, r2, r3)-    {-# INLINE toRows #-}
src/Data/Vec3/Unboxed.hs view
@@ -1,5 +1,6 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}  module Data.Vec3.Unboxed@@ -10,41 +11,44 @@  import Prelude hiding (reverse) -import Control.Monad--import Data.Vector.Unboxed as VU-import Data.Vector.Generic as VG-import Data.Vector.Generic.Mutable as VGM+import Data.Vector.Unboxed.Deriving  import Data.Vec3.Class   -- | 'Vec3' implementation with 'Data.Vector.Unboxed.Unbox' instance--- based on a single contiguous array storage scheme, suitable for use--- with "Data.Vector.Unboxed".+-- based on tuples, suitable for use with "Data.Vector.Unboxed". ----- 'Unbox' instance provides the required index transformations.+-- This represents 3-vector as a triple of doubles, using the default+-- Unbox instance for tuples as provided by "Data.Vector.Unboxed",+-- which wraps a vector of tuples as a tuple of vectors. -- -- @--- interface: [d1 x   y   z  ; d2 x   y   z  ...], length = N = M / 3---                |   |   |       |   |   |--- storage:   [  d1x d2y d2z ;   d2x d2y d2z ...], length = M+-- interface:  [d1 (x, y, z); d2 (x, y, z) ...], length = N+--                  |  |  |       |  |  |+-- storage(x): [d1x-+  |  | ; d2x-+  |  |  ...], length = N+-- storage(y): [d1y----+  | ; d2y----+  |  ...], length = N+-- storage(z): [d1z-------+ ; d2z-------+  ...], length = N -- @------ Thanks to dense packing scheme the performance of this--- implementation should generally be on par with 'Storable'-based--- 'Data.Vec3.SVec3'.-data UVec3 = UVec3 !Double !Double !Double-              deriving (Eq, Show)+newtype UVec3 = UVec3 (Double, Double, Double)+                deriving (Eq, Show)  +derivingUnbox "UVec3"+  [t|UVec3 -> (Double, Double, Double)|]+  [|\(UVec3 v) -> v|]+  [|UVec3|]++ instance Vec3 UVec3 where     newtype Matrix UVec3 = UMatrix (UVec3, UVec3, UVec3)+                           deriving (Eq, Show) -    fromXYZ (x, y, z) = UVec3 x y z++    fromXYZ = UVec3     {-# INLINE fromXYZ #-} -    toXYZ (UVec3 x y z) = (x, y, z)+    toXYZ (UVec3 v) = v     {-# INLINE toXYZ #-}      fromRows (r1, r2, r3) = UMatrix (r1, r2, r3)@@ -54,72 +58,7 @@     {-# INLINE toRows #-}  -newtype instance VU.MVector s UVec3 = MV_UVec3 (VU.MVector s Double)-newtype instance VU.Vector    UVec3 = V_UVec3  (VU.Vector    Double)---instance VGM.MVector VU.MVector UVec3 where-    basicLength (MV_UVec3 v) =-        VGM.basicLength v `quot` 3-    {-# INLINE basicLength #-}--    basicUnsafeSlice s l (MV_UVec3 v) =-        MV_UVec3 $ VGM.basicUnsafeSlice (s * 3) (l * 3) v-    {-# INLINE basicUnsafeSlice #-}--    basicOverlaps (MV_UVec3 v1) (MV_UVec3 v2) =-        VGM.basicOverlaps v1 v2-    {-# INLINE basicOverlaps #-}--    basicUnsafeNew n =-        MV_UVec3 `liftM` VGM.basicUnsafeNew (n * 3)-    {-# INLINE basicUnsafeNew #-}--    basicUnsafeRead (MV_UVec3 v) i = do-        x <- VGM.basicUnsafeRead v  j-        y <- VGM.basicUnsafeRead v (j + 1)-        z <- VGM.basicUnsafeRead v (j + 2)-        return $ UVec3 x y z-        where-          j = i * 3-    {-# INLINE basicUnsafeRead #-}--    basicUnsafeWrite (MV_UVec3 v) i (UVec3 x y z) =-        VGM.basicUnsafeWrite v  j      x >>-        VGM.basicUnsafeWrite v (j + 1) y >>-        VGM.basicUnsafeWrite v (j + 2) z-        where-          j = i * 3-    {-# INLINE basicUnsafeWrite #-}---instance VG.Vector VU.Vector UVec3 where-    basicUnsafeFreeze (MV_UVec3 v) =-        V_UVec3 `liftM` VG.basicUnsafeFreeze v-    {-# INLINE basicUnsafeFreeze #-}--    basicUnsafeThaw (V_UVec3 v) =-        MV_UVec3 `liftM` VG.basicUnsafeThaw v-    {-# INLINE basicUnsafeThaw #-}--    basicLength (V_UVec3 v) = VG.basicLength v `quot` 3-    {-# INLINE basicLength #-}--    basicUnsafeSlice s l (V_UVec3 v) =-        V_UVec3 $ VG.basicUnsafeSlice (s * 3) (l * 3) v-    {-# INLINE basicUnsafeSlice #-}--    basicUnsafeIndexM (V_UVec3 v) i = do-        x <- VG.basicUnsafeIndexM v  j-        y <- VG.basicUnsafeIndexM v (j + 1)-        z <- VG.basicUnsafeIndexM v (j + 2)-        return $ UVec3 x y z-        where-          j = i * 3-    {-# INLINE basicUnsafeIndexM #-}--    basicUnsafeCopy (MV_UVec3 mv) (V_UVec3 v)-        = VG.basicUnsafeCopy mv v-    {-# INLINE basicUnsafeCopy #-}--instance Unbox UVec3+derivingUnbox "UMatrix"+  [t|Matrix UVec3 -> (UVec3, UVec3, UVec3)|]+  [|\(UMatrix v) -> v|]+  [|UMatrix|]
+ src/Data/Vec3/Unboxed/Contiguous.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}++{-|++'Vec3' implementation with 'Data.Vector.Unboxed.Unbox' instance based+on single array storage scheme, suitable for use with+"Data.Vector.Unboxed".++-}++module Data.Vec3.Unboxed.Contiguous+    ( UVec3(..)+    )+++where++import Prelude hiding (reverse)++import Control.Monad++import Data.Vector.Unboxed as VU+import Data.Vector.Generic as VG+import Data.Vector.Generic.Mutable as VGM++import Data.Vec3.Class+++-- | 'Vec3' implementation with 'Data.Vector.Unboxed.Unbox' instance+-- based on a single contiguous array storage scheme, suitable for use+-- with "Data.Vector.Unboxed".+--+-- 'Unbox' instance provides the required index transformations.+--+-- @+-- interface: [d1 x   y   z  ; d2 x   y   z  ...], length = N = M / 3+--                |   |   |       |   |   |+-- storage:   [  d1x d2y d2z ;   d2x d2y d2z ...], length = M+-- @+data UVec3 = UVec3 !Double !Double !Double+              deriving (Eq, Show)+++instance Vec3 UVec3 where+    newtype Matrix UVec3 = UMatrix (UVec3, UVec3, UVec3)++    fromXYZ (x, y, z) = UVec3 x y z+    {-# INLINE fromXYZ #-}++    toXYZ (UVec3 x y z) = (x, y, z)+    {-# INLINE toXYZ #-}++    fromRows (r1, r2, r3) = UMatrix (r1, r2, r3)+    {-# INLINE fromRows #-}++    toRows (UMatrix (r1, r2, r3)) = (r1, r2, r3)+    {-# INLINE toRows #-}+++newtype instance VU.MVector s UVec3 = MV_UVec3 (VU.MVector s Double)+newtype instance VU.Vector    UVec3 = V_UVec3  (VU.Vector    Double)+++instance VGM.MVector VU.MVector UVec3 where+    basicInitialize (MV_UVec3 v) =+        VGM.basicInitialize v+    {-# INLINE basicInitialize #-}++    basicLength (MV_UVec3 v) =+        VGM.basicLength v `quot` 3+    {-# INLINE basicLength #-}++    basicUnsafeSlice s l (MV_UVec3 v) =+        MV_UVec3 $ VGM.basicUnsafeSlice (s * 3) (l * 3) v+    {-# INLINE basicUnsafeSlice #-}++    basicOverlaps (MV_UVec3 v1) (MV_UVec3 v2) =+        VGM.basicOverlaps v1 v2+    {-# INLINE basicOverlaps #-}++    basicUnsafeNew n =+        MV_UVec3 `liftM` VGM.basicUnsafeNew (n * 3)+    {-# INLINE basicUnsafeNew #-}++    basicUnsafeRead (MV_UVec3 v) i = do+        x <- VGM.basicUnsafeRead v  j+        y <- VGM.basicUnsafeRead v (j + 1)+        z <- VGM.basicUnsafeRead v (j + 2)+        return $ UVec3 x y z+        where+          j = i * 3+    {-# INLINE basicUnsafeRead #-}++    basicUnsafeWrite (MV_UVec3 v) i (UVec3 x y z) =+        VGM.basicUnsafeWrite v  j      x >>+        VGM.basicUnsafeWrite v (j + 1) y >>+        VGM.basicUnsafeWrite v (j + 2) z+        where+          j = i * 3+    {-# INLINE basicUnsafeWrite #-}+++instance VG.Vector VU.Vector UVec3 where+    basicUnsafeFreeze (MV_UVec3 v) =+        V_UVec3 `liftM` VG.basicUnsafeFreeze v+    {-# INLINE basicUnsafeFreeze #-}++    basicUnsafeThaw (V_UVec3 v) =+        MV_UVec3 `liftM` VG.basicUnsafeThaw v+    {-# INLINE basicUnsafeThaw #-}++    basicLength (V_UVec3 v) = VG.basicLength v `quot` 3+    {-# INLINE basicLength #-}++    basicUnsafeSlice s l (V_UVec3 v) =+        V_UVec3 $ VG.basicUnsafeSlice (s * 3) (l * 3) v+    {-# INLINE basicUnsafeSlice #-}++    basicUnsafeIndexM (V_UVec3 v) i = do+        x <- VG.basicUnsafeIndexM v  j+        y <- VG.basicUnsafeIndexM v (j + 1)+        z <- VG.basicUnsafeIndexM v (j + 2)+        return $ UVec3 x y z+        where+          j = i * 3+    {-# INLINE basicUnsafeIndexM #-}++    basicUnsafeCopy (MV_UVec3 mv) (V_UVec3 v)+        = VG.basicUnsafeCopy mv v+    {-# INLINE basicUnsafeCopy #-}++instance Unbox UVec3
+ tests/Tests.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE ScopedTypeVariables #-}++import Test.Tasty+import Test.Tasty.QuickCheck++import Data.Vec3+++infix 4 <~=>+(<~=>) :: SVec3 -> SVec3 -> Bool+(<~=>) a b = ax ~= bx &&+             ay ~= by &&+             az ~= bz+  where+    (ax, ay, az) = toXYZ (a :: SVec3)+    (bx, by, bz) = toXYZ (b :: SVec3)+++infix 4 ~=+(~=) :: Double -> Double -> Bool+(~=) a b | a == b = True+         | a == 0 || b == 0 || isDenormalized absDiff = absDiff < maxError+         | otherwise = absDiff / (abs a + abs b) < maxError+  where+    absDiff = abs $ a - b+    maxError = 1e-13+++tests :: [TestTree]+tests =+  [ testProperty+    "Commutativity of addition: a + b = b + a"+    (\(a :: SVec3) b -> a <+> b <~=> b <+> a)+  , testProperty+    "Associativity of addition: (a + b) + c = a + (b + c)"+    (\(a :: SVec3) b c -> (a <+> b) <+> c <~=> a <+> (b <+> c))+  , testProperty+    "Identity element of addition (zero): v + 0 = v"+    (\(v :: SVec3) -> (v <+> origin <~=> v))+  , testProperty+    "Inverse elements of addition: v + (-v) = 0"+    (\(v :: SVec3) -> (v <+> invert v <~=> origin))+  , testProperty+    "Compatibility of scalar and field multiplication"+    (\(v :: SVec3) p q -> (v .^ p .^ q <~=> v .^ (p * q)))+  , testProperty+    "Identity of scalar multiplication"+    (\(v :: SVec3) -> (v .^ 1 <~=> v))+  , testProperty+    "Distributivity wrt vector addition"+    (\(a :: SVec3) b p -> ((a <+> b) .^ p) <~=> (a .^ p) <+> (b .^ p))+  , testProperty+    "Distributivity wrt scalar addition"+    (\(a :: SVec3) p q -> (a .^ (p + q) <~=> (a .^ p) <+> (a .^ q)))+  , testProperty+    "Subtraction definition"+    (\(a :: SVec3) b -> (a <+> invert b <~=> a <-> b))+  , testProperty+    "Normalization"+    (\(v :: SVec3) -> (v <~=> origin || norm (normalize v) ~= 1))+  , testProperty+    "Triangle inequality"+    (\(a :: SVec3) b c -> (distance a b + distance b c >= distance a c))+  ]+++main :: IO ()+main = defaultMain $ testGroup "Tests" tests