Vec 0.9.2 → 0.9.3
raw patch · 5 files changed
+105/−176 lines, 5 filesdep ~QuickCheck
Dependency ranges changed: QuickCheck
Files
- Data/Vec/Base.hs +47/−29
- Data/Vec/Instances.hs +0/−132
- Data/Vec/LinAlg.hs +35/−6
- Data/Vec/Packed.hs +18/−2
- Vec.cabal +5/−7
Data/Vec/Base.hs view
@@ -1,8 +1,6 @@ {- Copyright (c) 2008, Scott E. Dillard. All rights reserved. -} -{-# LANGUAGE BangPatterns #-} {-# LANGUAGE EmptyDataDecls #-}-{-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FunctionalDependencies #-}@@ -13,7 +11,7 @@ {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE UndecidableInstances #-} -{-# HADDOCK_OPTIONS prune #-}+-- {-# HADDOCK_OPTIONS prune #-} module Data.Vec.Base where @@ -85,57 +83,77 @@ -- Use `vec` when the length can be inferred. mkVec :: n -> a -> v - -- | turn a list into a vector of inferred length++instance Vec N1 a ( a :. () ) where+ mkVec _ a = a :. ()+ {-# INLINE mkVec #-}++instance Vec (Succ n) a (a':.v) => Vec (Succ (Succ n)) a (a:.a':.v) where+ mkVec _ a = a :. (mkVec undefined a)+ {-# INLINE mkVec #-}+++-- | Make a uniform vector. The length is inferred.+vec :: (Vec n a v) => a -> v+vec = mkVec undefined+{-# INLINE vec #-}+++-- | Build a vector from a list, or access vector elements using run-time+-- indicies, numbered from 0.++class VecList a v | v -> a where+ -- | Turn a list into a vector of inferred length. The list must be at least+ -- as long as the vector, but may be longer. Make a mental note of the+ -- distinction between this and 'matFromList', as you might accidentally use+ -- this when you mean that. Because number literals can be converted to+ -- vectors, and matrices are vectors of vectors, the following works+ -- + -- > fromList [1,2,3,4] :: 'Mat22' Int + -- > > ((1):.(1):.()):.((2):.(2):.()):.()+ --+ -- even though we meant to do this+ --+ -- > 'matFromList' [1,2,3,4] :: 'Mat22' Int + -- > > ((1):.(2):.()):.((3):.(4):.()):.() fromList :: [a] -> v - -- | get a vector element, which one is determined at runtime+ -- | Get a vector element, which one determined at runtime. getElem :: Int -> v -> a - -- | set a vector element, which one is determined at runtime+ -- | Set a vector element, which one determined at runtime setElem :: Int -> a -> v -> v -instance Vec N1 a ( a :. () ) where- mkVec _ a = a :. ()+instance VecList a (a:.()) where fromList (a:_) = a :. () fromList [] = error "fromList: list too short"- getElem !i (a :. _) + getElem i (a :. _) | i == 0 = a | otherwise = error "getElem: index out of bounds"- setElem !i a _ + setElem i a _ | i == 0 = a :. () | otherwise = error "setElem: index out of bounds" {-# INLINE setElem #-} {-# INLINE getElem #-}- {-# INLINE mkVec #-} {-# INLINE fromList #-} -instance Vec (Succ n) a (a':.v) => Vec (Succ (Succ n)) a (a:.a':.v) where- mkVec _ a = a :. (mkVec undefined a)- fromList (a:as) = a :. (fromList as)+instance VecList a (a':.v) => VecList a (a:.(a':.v)) where+ fromList (a:as) = a :. fromList as fromList [] = error "fromList: list too short"- getElem !i (a :. v)+ getElem i (a :. v) | i == 0 = a | otherwise = getElem (i-1) v- setElem !i a (x :. v)- | i == 0 = a :. v- | otherwise = x :. (setElem (i-1) a v)+ setElem i a' (a :. v)+ | i == 0 = a' :. v+ | otherwise = a :. (setElem (i-1) a' v) {-# INLINE setElem #-} {-# INLINE getElem #-}- {-# INLINE mkVec #-} {-# INLINE fromList #-} ---- | Make a uniform vector. The length is inferred.-vec :: (Vec n a v) => a -> v-vec = mkVec undefined-{-# INLINE vec #-}-- -- | get or set a vector element, known at compile --time. Use the Nat types to access vector components. For instance, @get n0@ --gets the x component, @set n2 44@ sets the z component to 44. - class Access n a v | v -> a where get :: n -> v -> a set :: n -> a -> v -> v@@ -418,12 +436,12 @@ {-# INLINE matToList #-} -- | convert a list-of-lists into a matrix-matFromLists :: (Vec j a v, Vec i v m) => [[a]] -> m+matFromLists :: (Vec j a v, Vec i v m, VecList a v, VecList v m) => [[a]] -> m matFromLists = fromList . (P.map fromList) {-# INLINE matFromLists #-} -- | convert a list into a matrix. (row-major order)-matFromList :: forall i j v m a. (Vec i v m, Vec j a v, Nat i) => [a] -> m+matFromList :: forall i j v m a. (Vec i v m, Vec j a v, Nat i, VecList a v, VecList v m) => [a] -> m matFromList = matFromLists . groupsOf (nat(undefined::i)) where groupsOf n xs = let (a,b) = splitAt n xs in a:(groupsOf n b) {-# INLINE matFromList #-}
− Data/Vec/Instances.hs
@@ -1,132 +0,0 @@-{- Copyright (c) 2008, Scott E. Dillard. All rights reserved. -}-{-# OPTIONS -cpp #-}--{-# LANGUAGE EmptyDataDecls #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE UndecidableInstances #-}--module Data.Vec.Instances where--import Prelude hiding (map,foldl,foldr,zipWith)-import Data.Vec.Base as V-import Data.Vec.Nat-import Foreign.Storable-import Foreign.Ptr-import Test.QuickCheck---- Storable instances. --instance Storable a => Storable (a:.()) where- sizeOf _ = sizeOf (undefined::a)- alignment _ = alignment (undefined::a)- peek p = peek (castPtr p) >>= \a -> return (a:.())- peekByteOff p o = peek (p`plusPtr`o)- peekElemOff p i = peek (p`plusPtr`(i*sizeOf(undefined::a)))- poke p (a:._) = poke (castPtr p) a- pokeByteOff p o x = poke (p`plusPtr`o) x- pokeElemOff p i x = poke (p`plusPtr`(i*sizeOf(undefined::a))) x- {-# INLINE sizeOf #-}- {-# INLINE alignment #-}- {-# INLINE peek #-}- {-# INLINE peekByteOff #-}- {-# INLINE peekElemOff #-}- {-# INLINE poke #-}- {-# INLINE pokeByteOff #-}- {-# INLINE pokeElemOff #-}--instance (Vec (Succ (Succ n)) a (a:.a:.v), Storable a, Storable (a:.v)) - => Storable (a:.a:.v) - where- sizeOf _ = sizeOf (undefined::a) + sizeOf (undefined::(a:.v))- alignment _ = alignment (undefined::a)- peek p = - peek (castPtr p) >>= \a -> - peek (castPtr (p`plusPtr`sizeOf(undefined::a))) >>= \v -> - return (a:.v)- peekByteOff p o = peek (p`plusPtr`o)- peekElemOff p i = peek (p`plusPtr`(i*sizeOf(undefined::(a:.a:.v))))- poke p (a:.v) = - poke (castPtr p) a >> - poke (castPtr (p`plusPtr`sizeOf(undefined::a))) v- pokeByteOff p o x = poke (p`plusPtr`o) x- pokeElemOff p i x = poke (p`plusPtr`(i*sizeOf(undefined::(a:.a:.v)))) x- {-# INLINE sizeOf #-}- {-# INLINE alignment #-}- {-# INLINE peek #-}- {-# INLINE peekByteOff #-}- {-# INLINE peekElemOff #-}- {-# INLINE poke #-}- {-# INLINE pokeByteOff #-}- {-# INLINE pokeElemOff #-}----- Num and Fractional instances : All arithmetic is done component-wise and--- literals construct uniform vectors and matrices. ------ The rule is : --- If the method is unary, it's a map. --- If it's binary, it's a zipWith.--instance- (Eq (a:.u)- ,Show (a:.u)- ,Num a- ,Map a a (a:.u) (a:.u) - ,ZipWith a a a (a:.u) (a:.u) (a:.u)- ,Vec (Succ l) a (a:.u)- )- => Num (a:.u) - where- (+) u v = V.zipWith (+) u v - (-) u v = V.zipWith (-) u v- (*) u v = V.zipWith (*) u v- abs u = V.map abs u- signum u = V.map signum u- fromInteger i = vec (fromInteger i)- {-# INLINE (+) #-}- {-# INLINE (-) #-}- {-# INLINE (*) #-}- {-# INLINE abs #-}- {-# INLINE signum #-}- {-# INLINE fromInteger #-}---instance - (Fractional a- ,Ord (a:.u)- ,ZipWith a a a (a:.u) (a:.u) (a:.u)- ,Map a a (a:.u) (a:.u)- ,Vec (Succ l) a (a:.u)- ,Show (a:.u)- ) - => Fractional (a:.u) - where- (/) u v = V.zipWith (/) u v- recip u = V.map recip u- fromRational r = vec (fromRational r)- {-# INLINE (/) #-}- {-# INLINE recip #-}- {-# INLINE fromRational #-}------ Arbitrary instances--instance Arbitrary a => Arbitrary (a:.()) where- arbitrary = arbitrary >>= return . (:.())- coarbitrary (a:._) = variant 0 . coarbitrary a--instance (Length (a:.v) (Succ n), Arbitrary a', Arbitrary (a:.v)) => Arbitrary (a':.a:.v) where- arbitrary = arbitrary >>= \a -> - arbitrary >>= \v -> return (a:.v);- coarbitrary (a:.v) = variant (V.length v) . coarbitrary a . coarbitrary v--
Data/Vec/LinAlg.hs view
@@ -1,17 +1,15 @@ {- Copyright (c) 2008, Scott E. Dillard. All rights reserved. -} -{-# LANGUAGE BangPatterns #-} {-# LANGUAGE EmptyDataDecls #-}-{-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE PatternSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE OverlappingInstances #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_HADDOCK ignore-exports,prune #-}@@ -58,7 +56,9 @@ import Control.Monad import Data.Maybe +import Unsafe.Coerce + -- | dot / inner / scalar product dot :: (Num a, Num v, Fold a v) => v -> v -> a dot u v = sum (u*v)@@ -351,11 +351,11 @@ alternating :: n -> a -> v instance Alternating N1 a (a:.()) where- alternating _ !a = a:.()+ alternating _ a = a:.() {-# INLINE alternating #-} instance (Num a, Alternating n a (a:.v)) => Alternating (Succ n) a (a:.a:.v) where- alternating _ !a = a:.(alternating (undefined::n) (negate $! a))+ alternating _ a = a:.(alternating (undefined::n) (negate a)) {-# INLINE alternating #-} @@ -367,9 +367,36 @@ det' ( (a:.b:.()) :. (c:.d:.()) :. () ) = a*d-b*c {-# INLINE det' #-} ---this instance is particularly ugly in order to avoid overlapping with the one above++--This is the only overlapping instance in the whole library (goddamnit) instance (Num a+ ,Fold a v+ ,Num v+ ,Head m v+ ,Vec n a v+ ,Map m__ a vm v+ ,Transpose vmt vm+ ,DropConsec v vv+ ,Map v vv m_ vmt+ ,Tail m m_+ ,Alternating n a v+ ,Det' a m__+ )+ => Det' a m+ where+ det' m =+ sum ((alternating undefined 1) * (head m) *+ (map det' (transpose(map(dropConsec)(tail m)))))+ {-# INLINE det' #-}++--For reference, here is the non-overlapping instance that worked in 6.8. When+--I figure out what happened between 6.8 and 6.10, hopefully we can go back to+--a non-overlapping instance.++{-+instance+ (Num a ,Num (a:.a:.a:.v) ,Fold a (a:.a:.a:.v) ,Alternating (Succ (Succ (Succ n))) a (a:.a:.a:.v)@@ -388,6 +415,8 @@ sum ((alternating undefined 1) * mh * (map det' (transpose (map dropConsec mt :: vmt)))) {-# INLINE det' #-}+-}+ -- For now, use wrapper class to allow type inference. I think maybe the
Data/Vec/Packed.hs view
@@ -39,8 +39,8 @@ -- arguments to be unpacked, but the result is a polymorphic vector @(:.)@, so -- you will need to pack it again. I admit that this is awkward. ----- There are also instances for 'Take', 'Drop', 'Last', 'Head', 'Tail' and--- 'Snoc'. These come in handy for thinks like quaternions and homogenous+-- There are also instances for 'Access', 'Take', 'Drop', 'Last', 'Head', 'Tail' and+-- 'Snoc'. These come in handy for things like quaternions and homogenous -- coordinates. module Data.Vec.Packed where@@ -301,3 +301,19 @@ where drop n v = pack (drop n (unpack v)) {-# INLINE drop #-}++instance (Access n a v, PackedVec v) => Access n a (Packed v)+ where+ get n v = get n (unpack v)+ set n a v = pack (set n a (unpack v))+ {-# INLINE get #-}+ {-# INLINE set #-}++instance (VecList a v, PackedVec v) => VecList a (Packed v)+ where+ fromList = pack . fromList+ getElem i = getElem i . unpack+ setElem i a = pack . setElem i a . unpack+ {-# INLINE setElem #-}+ {-# INLINE getElem #-}+ {-# INLINE fromList #-}
Vec.cabal view
@@ -1,5 +1,5 @@ Name: Vec-Version: 0.9.2+Version: 0.9.3 License: BSD3 License-file: LICENSE Author: Scott E. Dillard@@ -19,25 +19,23 @@ Category: Data,Math library- Build-Depends: base,QuickCheck+ Build-Depends: base,QuickCheck<2 Exposed-modules: Data.Vec Data.Vec.Base, Data.Vec.LinAlg, Data.Vec.Nat,- Data.Vec.Instances Data.Vec.Packed Extensions: - BangPatterns, EmptyDataDecls,- ExistentialQuantification,- FlexibleInstances, FlexibleContexts,+ FlexibleInstances, FunctionalDependencies, MultiParamTypeClasses, NoMonomorphismRestriction,+ OverlappingInstances, ScopedTypeVariables,+ TypeFamilies, TypeOperators, TypeSynonymInstances,- TypeFamilies, UndecidableInstances