packages feed

unboxing-vector (empty) → 0.1.0.0

raw patch · 14 files changed

+2376/−0 lines, 14 filesdep +HUnitdep +basedep +deepseqsetup-changed

Dependencies added: HUnit, base, deepseq, mono-traversable, primitive, should-not-typecheck, unboxing-vector, vector

Files

+ ChangeLog.md view
@@ -0,0 +1,8 @@+# Changelog for unboxing-vector++## Version 0.1.0.0 (2019-06-17)++Initial release with++- Data.Vector.Unboxing+- Data.Vector.Unboxing.Mutable
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright ARATA Mizuki (c) 2019++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of ARATA Mizuki nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,80 @@+# unboxing-vector++This package provides newtype-friendly wrappers for `Data.Vector.Unboxed` in [`vector` package](http://hackage.haskell.org/package/vector).++## Description++Suppose you define a newtype for `Int` and want to store them in an unboxed vector.++```haskell+newtype Foo = Foo Int++generate 10 (\i -> Foo i) :: Data.Vector.Unboxed.Vector Foo+```++With plain `Data.Vector.Unboxed`, you either write two dozen of lines of code to get it work (the exact code is [here](https://github.com/minoki/unboxing-vector/blob/3a152014b9660ef1e2885d6b9c66423064223f63/test/Foo.hs#L36-L63)), or resort to Template Haskell ([`vector-th-unbox` package](http://hackage.haskell.org/package/vector-th-unbox)) to generate it.++But with `Data.Vector.Unboxing`, the code you write is just two lines:++```haskell+instance Data.Vector.Unboxing.Unboxable Foo where+  type Rep Foo = Int++generate 10 (\i -> Foo i) :: Data.Vector.Unboxing.Vector Foo+```++...and if you want to be even more concise, you can derive `Unboxable` instance with `GeneralizedNewtypeDeriving`.++Note that the vector type provided by this package (`Data.Vector.Unboxing.Vector`) is *different* from `Data.Vector.Unboxed.Vector`.++The module defining the type `Foo` does not need to export its constructor to enable use of `Vector Foo`.++## For non-newtypes++Suppose you define a datatype isomorphic to a tuple of primitive types, like:++```haskell+data ComplexDouble = MkComplexDouble {-# UNPACK #-} !Double {-# UNPACK #-} !Double+```++In this example, `ComplexDouble` is isomorphic to `(Double, Double)`, but has a different representation. Thus, you cannot derive `Data.Vector.Unboxing.Unboxable` from `(Double, Double)`.++For such cases, unboxing-vector provides a feature to derive `Unboxable` using `Generic`.++```haskell+{-# LANGUAGE DeriveGeneric, DerivingVia, UndecidableInstances #-}++data ComplexDouble = ..+  deriving Generic+  deriving Data.Vector.Unboxing.Unboxable via Data.Vector.Unboxing.Generics ComplexDouble+```++## Conversion++### Conversion from/to Unboxed vector++You can use `fromUnboxedVector` and `toUnboxedVector` to convert one vector type to another.++```haskell+import qualified Data.Vector.Unboxed as Unboxed+import qualified Data.Vector.Unboxing as Unboxing++convert :: Unboxed.Vector Int -> Unboxing.Vector Int+convert vec = Unboxing.fromUnboxedVector vec+```++### Coercion between Unboxing vectors++You can use `coerceVector` to convert vector types of different element types, if they have the same representation and have appropriate data constructors in scope.++```haskell+import qualified Data.Vector.Unboxing as Unboxing+import Data.MonoTraversable (ofold)+import Data.Monoid (Sum(..), All, getAll)++sum :: Unboxing.Vector Int -> Int+sum vec = getSum $ ofold (Unboxing.coerceVector vec :: Unboxing.Vector (Sum Int)) -- OK++and :: Unboxing.Vector Bool -> Bool+and vec = getAll $ ofold (Unboxing.coerceVector vec :: Unboxing.Vector All) -- fails because the data constructor is not in scope+```
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ benchmark/Bench.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveGeneric #-}+{-# OPTIONS_GHC -Wno-type-defaults -Wno-name-shadowing #-}+import qualified Data.Vector.Unboxed as U+import qualified Data.Vector.Unboxed.Mutable as UM+import qualified Data.Vector.Unboxing as V+import qualified Data.Vector as B+import qualified Data.Vector.Generic as G+import System.Environment (getArgs, getProgName)+import Control.Monad+import Data.List+import qualified Poly as P++modulo :: Int+modulo = 17++newtype IntMod = IntMod Int deriving (Eq)++instance Show IntMod where+  show (IntMod n) = show n++instance V.Unboxable IntMod where+  type Rep IntMod = Int++instance Num IntMod where+  IntMod x + IntMod y = IntMod ((x + y) `rem` modulo)+  IntMod x - IntMod y = IntMod ((x - y) `mod` modulo)+  IntMod x * IntMod y = IntMod ((x * y) `rem` modulo)+  negate (IntMod x) = IntMod (negate x `mod` modulo)+  fromInteger n = IntMod (fromInteger (n `mod` fromIntegral modulo))+  abs = undefined; signum = undefined++instance Fractional IntMod where+  recip x = let x2 = x * x+                x5 = x2 * x2 * x+                x15 = x5 * x5 * x5+            in x15 -- x^15+  fromRational = undefined++trim :: U.Vector Int -> U.Vector Int+trim xs+  | U.null xs = U.empty+  | U.last xs == 0 = trim (U.init xs)+  | otherwise = xs++addMod, subMod, mulMod :: Int -> Int -> Int+addMod x y = (x + y) `rem` modulo+subMod x y = (x - y) `mod` modulo+mulMod x y = (x * y) `rem` modulo++sumMod :: [Int] -> Int+sumMod = foldl' addMod 0++negateMod :: Int -> Int+negateMod x = (negate x) `mod` modulo++recipMod :: Int -> Int+recipMod x = let x2 = x `mulMod` x+                 x5 = (x2 `mulMod` x2) `mulMod` x+                 x15 = (x5 `mulMod` x5) `mulMod` x5+             in x15++polyAdd :: U.Vector Int -> U.Vector Int -> U.Vector Int+polyAdd xs ys+  | n < m = U.create $ do+      v <- UM.new m+      forM_ [0..n-1] $ \i -> UM.write v i ((xs U.! i) `addMod` (ys U.! i))+      forM_ [n..m-1] $ \i -> UM.write v i (ys U.! i)+      return v+  | m < n = U.create $ do+      v <- UM.new n+      forM_ [0..m-1] $ \i -> UM.write v i ((xs U.! i) `addMod` (ys U.! i))+      forM_ [m..n-1] $ \i -> UM.write v i (xs U.! i)+      return v+  | otherwise = trim $ U.zipWith addMod xs ys+  where n = U.length xs+        m = U.length ys++polySub :: U.Vector Int -> U.Vector Int -> U.Vector Int+polySub xs ys+  | n < m = U.create $ do+      v <- UM.new m+      forM_ [0..n-1] $ \i -> UM.write v i ((xs U.! i) `subMod` (ys U.! i))+      forM_ [n..m-1] $ \i -> UM.write v i (negateMod (ys U.! i))+      return v+  | m < n = U.create $ do+      v <- UM.new n+      forM_ [0..m-1] $ \i -> UM.write v i ((xs U.! i) `subMod` (ys U.! i))+      forM_ [m..n-1] $ \i -> UM.write v i (xs U.! i)+      return v+  | otherwise = trim $ U.zipWith subMod xs ys+  where n = U.length xs+        m = U.length ys++polyMul :: U.Vector Int -> U.Vector Int -> U.Vector Int+polyMul xs ys+    | n == 0 || m == 0 = U.empty+    | otherwise = U.generate (n + m - 1) (\i -> sumMod [(xs U.! j) `mulMod` (ys U.! (i - j)) | j <- [max 0 (i - m + 1)..min i (n-1)]])+    where n = U.length xs+          m = U.length ys++scalePoly :: Int -> U.Vector Int -> U.Vector Int+scalePoly a xs+  | a == 0 = U.empty+  | otherwise = U.map (`mulMod` a) xs++toMonicPoly :: U.Vector Int -> U.Vector Int+toMonicPoly xs | U.null xs = U.empty+               | otherwise = U.map (`mulMod` recipMod (U.last xs)) xs++divModPoly :: U.Vector Int -> U.Vector Int -> (U.Vector Int, U.Vector Int)+divModPoly f g+  | U.null g = error "divMod: divide by zero"+  | U.length f < U.length g = (U.empty, f)+  | otherwise = loop U.empty (scalePoly (recipMod b) f)+  where+    g' = toMonicPoly g+    b = U.last g+    -- invariant: f == q * g + scale b p+    loop q !p | U.length p < U.length g = (q, scalePoly b p)+              | otherwise = let !q' = U.drop (U.length g - 1) p+                            in loop (q `polyAdd` q') (p `polySub` (q' `polyMul` g'))++modPoly :: U.Vector Int -> U.Vector Int -> U.Vector Int+modPoly f g = snd (divModPoly f g)++powModPoly :: U.Vector Int -> Int -> U.Vector Int -> U.Vector Int+powModPoly _ 0 _modulo = U.singleton 1+powModPoly f n modulo = loop (n-1) f f+  where loop 0 !_ !acc = acc+        loop 1 !m !acc = (m `polyMul` acc) `modPoly` modulo+        loop i !m !acc+          | even i = loop (i `quot` 2) ((m `polyMul` m) `modPoly` modulo) acc+          | otherwise = loop (i `quot` 2) ((m `polyMul` m) `modPoly` modulo) ((m `polyMul` acc) `modPoly` modulo)++powPoly :: U.Vector Int -> Int -> U.Vector Int+powPoly _ 0 = U.singleton 1+powPoly f n = loop (n-1) f f+  where loop 0 !_ !acc = acc+        loop 1 !m !acc = m `polyMul` acc+        loop i !m !acc+          | even i = loop (i `quot` 2) (m `polyMul` m) acc+          | otherwise = loop (i `quot` 2) (m `polyMul` m) (m `polyMul` acc)++-- Specialization for unboxing vectors + IntMod:+{-# SPECIALIZE P.addPoly :: P.Poly V.Vector IntMod -> P.Poly V.Vector IntMod -> P.Poly V.Vector IntMod #-}+{-# SPECIALIZE P.subPoly :: P.Poly V.Vector IntMod -> P.Poly V.Vector IntMod -> P.Poly V.Vector IntMod #-}+{-# SPECIALIZE P.mulPoly :: P.Poly V.Vector IntMod -> P.Poly V.Vector IntMod -> P.Poly V.Vector IntMod #-}+{-# SPECIALIZE P.divMod :: P.Poly V.Vector IntMod -> P.Poly V.Vector IntMod -> (P.Poly V.Vector IntMod, P.Poly V.Vector IntMod) #-}+{-# SPECIALIZE P.powMod :: P.Poly V.Vector IntMod -> Int -> P.Poly V.Vector IntMod -> P.Poly V.Vector IntMod #-}++-- Specialization for boxed vectors + IntMod:+{-# SPECIALIZE P.addPoly :: P.Poly B.Vector IntMod -> P.Poly B.Vector IntMod -> P.Poly B.Vector IntMod #-}+{-# SPECIALIZE P.subPoly :: P.Poly B.Vector IntMod -> P.Poly B.Vector IntMod -> P.Poly B.Vector IntMod #-}+{-# SPECIALIZE P.mulPoly :: P.Poly B.Vector IntMod -> P.Poly B.Vector IntMod -> P.Poly B.Vector IntMod #-}+{-# SPECIALIZE P.divMod :: P.Poly B.Vector IntMod -> P.Poly B.Vector IntMod -> (P.Poly B.Vector IntMod, P.Poly B.Vector IntMod) #-}+{-# SPECIALIZE P.powMod :: P.Poly B.Vector IntMod -> Int -> P.Poly B.Vector IntMod -> P.Poly B.Vector IntMod #-}++main :: IO ()+main = do+  args <- getArgs+  case args of+    "unboxed":_ -> do+      let f = U.fromList [modulo-1,modulo-1,modulo-1] `polyAdd` (powPoly (U.fromList [0,1]) 2000) {- U.fromList [if k==2000 then 1 else 0 | k<-[0..2000]] -}+      let g = powModPoly (U.fromList [0,1]) 1000000000 f+      print $ sumMod $ U.toList g -- should print '1'+    "unboxing":_ -> do+      let f = P.x^2000 - (P.x^2 + P.x + 1) :: P.Poly V.Vector IntMod+      let g = P.powMod P.x 1000000000 f+      print $ G.sum $ P.coeffAsc g -- should print '1'+    "boxed":_ -> do+      let f = P.x^2000 - (P.x^2 + P.x + 1) :: P.Poly B.Vector IntMod+      let g = P.powMod P.x 1000000000 f+      print $ G.sum $ P.coeffAsc g -- should print '1'+    _ -> do+      progName <- getProgName+      putStrLn $ progName ++ " (unboxed|unboxing|boxed)"+      putStr $ unlines ["This program computes the polynomial x^1000000000 mod (x^2000 - x^2 - x - 1)"+                       ,"and prints its value at x=1 in the finite field F_17 (or GF(17))."+                       ,"Run with '+RTS -t' to show memory usage."+                       ]
+ benchmark/Poly.hs view
@@ -0,0 +1,172 @@+{-# LANGUAGE BangPatterns #-}+module Poly where+import Prelude hiding (gcd, div, mod, divMod, const)+import Control.Monad+import qualified Data.Vector.Generic as G+import qualified Data.Vector.Generic.Mutable as GM+import qualified Data.Vector.Unboxing -- for writing SPECIALIZE instance pragma+import qualified Data.Vector -- for writing SPECIALIZE instance pragma++infixl 7 `div`, `mod`++-- univariate polynomial, coefficients in ascending order+newtype Poly vect a = Poly (vect a) deriving (Eq,Show)++zero :: (G.Vector vect a) => Poly vect a+zero = Poly G.empty+{-# INLINE zero #-}++isZero :: (G.Vector vect a) => Poly vect a -> Bool+isZero (Poly xs) = G.null xs+{-# INLINE isZero #-}++const :: (Eq a, Num a, G.Vector vect a) => a -> Poly vect a+const 0 = zero+const a = Poly (G.singleton a)+{-# INLINE const #-}++x :: (Num a, Eq a, G.Vector vect a) => Poly vect a+x = Poly (G.fromList [0, 1])+{-# INLINE x #-}++fromCoeffAsc :: (Eq a, Num a, G.Vector vect a) => vect a -> Poly vect a+fromCoeffAsc xs+  | G.null xs = Poly G.empty+  | G.last xs == 0 = fromCoeffAsc (G.init xs)+  | otherwise = Poly xs+{-# INLINE fromCoeffAsc #-}++coeffAsc :: Poly vect a -> vect a+coeffAsc (Poly xs) = xs+{-# INLINE coeffAsc #-}++addPoly :: (Eq a, Num a, G.Vector vect a) => Poly vect a -> Poly vect a -> Poly vect a+addPoly (Poly xs) (Poly ys)+  | n < m = Poly $ G.create $ do+      v <- GM.new m+      forM_ [0..n-1] $ \i -> GM.write v i ((xs G.! i) + (ys G.! i))+      forM_ [n..m-1] $ \i -> GM.write v i (ys G.! i)+      return v+  | m < n = Poly $ G.create $ do+      v <- GM.new n+      forM_ [0..m-1] $ \i -> GM.write v i ((xs G.! i) + (ys G.! i))+      forM_ [m..n-1] $ \i -> GM.write v i (xs G.! i)+      return v+  | otherwise = fromCoeffAsc $ G.zipWith (+) xs ys+  where n = G.length xs+        m = G.length ys+{-# INLINABLE addPoly #-}++subPoly :: (Eq a, Num a, G.Vector vect a) => Poly vect a -> Poly vect a -> Poly vect a+subPoly (Poly xs) (Poly ys)+  | n < m = Poly $ G.create $ do+      v <- GM.new m+      forM_ [0..n-1] $ \i -> GM.write v i ((xs G.! i) - (ys G.! i))+      forM_ [n..m-1] $ \i -> GM.write v i (negate (ys G.! i))+      return v+  | m < n = Poly $ G.create $ do+      v <- GM.new n+      forM_ [0..m-1] $ \i -> GM.write v i ((xs G.! i) - (ys G.! i))+      forM_ [m..n-1] $ \i -> GM.write v i (xs G.! i)+      return v+  | otherwise = fromCoeffAsc $ G.zipWith (-) xs ys+  where n = G.length xs+        m = G.length ys+{-# INLINABLE subPoly #-}++-- multiplication: naive method+mulPoly :: (Eq a, Num a, G.Vector vect a) => Poly vect a -> Poly vect a -> Poly vect a+mulPoly (Poly xs) (Poly ys)+  | n == 0 || m == 0 = zero+  | otherwise = Poly $ G.generate (n + m - 1) (\i -> sum [(xs G.! j) * (ys G.! (i - j)) | j <- [max 0 (i - m + 1)..min i (n-1)]])+  where n = G.length xs+        m = G.length ys+{-# INLINABLE mulPoly #-}++instance (Eq a, Num a, G.Vector vect a) => Num (Poly vect a) where+  negate (Poly xs) = Poly $ G.map negate xs+  {-# INLINE negate #-}++  (+) = addPoly+  {-# INLINE (+) #-}++  (-) = subPoly+  {-# INLINE (-) #-}++  (*) = mulPoly+  {-# INLINE (*) #-}++  fromInteger n = const $ fromInteger n+  {-# INLINE fromInteger #-}++  abs = undefined+  signum = undefined++  {-# SPECIALIZE instance (Eq a, Num a) => Num (Poly Data.Vector.Vector a) #-}+  {-# SPECIALIZE instance (Eq a, Num a, Data.Vector.Unboxing.Unboxable a) => Num (Poly Data.Vector.Unboxing.Vector a) #-}++degree :: (G.Vector vect a) => Poly vect a -> Maybe Int+degree (Poly xs) = case G.length xs - 1 of+  -1 -> Nothing+  n -> Just n+{-# INLINE degree #-}++degree' :: (G.Vector vect a) => Poly vect a -> Int+degree' (Poly xs) = case G.length xs of+  0 -> error "degree': zero polynomial"+  n -> n - 1+{-# INLINE degree' #-}++leadingCoefficient :: (Num a, G.Vector vect a) => Poly vect a -> a+leadingCoefficient (Poly xs)+  | G.null xs = 0+  | otherwise = G.last xs+{-# INLINE leadingCoefficient #-}++toMonic :: (Fractional a, G.Vector vect a) => Poly vect a -> Poly vect a+toMonic f@(Poly xs)+  | G.null xs = zero+  | otherwise = Poly $ G.map (* recip (leadingCoefficient f)) xs+{-# INLINE toMonic #-}++scale :: (Eq a, Num a, G.Vector vect a) => a -> Poly vect a -> Poly vect a+scale a (Poly xs)+  | a == 0 = zero+  | otherwise = Poly $ G.map (* a) xs+{-# INLINE scale #-}++divMod :: (Eq a, Fractional a, G.Vector vect a) => Poly vect a -> Poly vect a -> (Poly vect a, Poly vect a)+divMod f g+  | isZero g = error "divMod: divide by zero"+  | degree f < degree g = (zero, f)+  | otherwise = loop zero (scale (recip b) f)+  where+    g' = toMonic g+    b = leadingCoefficient g+    -- invariant: f == q * g + scale b p+    loop q !p | degree p < degree g = (q, scale b p)+              | otherwise = let !q' = Poly (G.drop (degree' g) (coeffAsc p))+                            in loop (q + q') (p - q' * g')+{-# INLINABLE divMod #-}++div, mod :: (Eq a, Fractional a, G.Vector vect a) => Poly vect a -> Poly vect a -> Poly vect a+div f g = fst (divMod f g)+mod f g = snd (divMod f g)+{-# INLINE div #-}+{-# INLINE mod #-}++-- | GCD with naive Euclidean algorithm+gcd :: (Eq a, Fractional a, G.Vector vect a) => Poly vect a -> Poly vect a -> Poly vect a+gcd f g | isZero g = f+        | otherwise = gcd g (f `mod` g)+{-# INLINE gcd #-}++powMod :: (Eq a, Fractional a, G.Vector vect a) => Poly vect a -> Int -> Poly vect a -> Poly vect a+powMod _a 0 _modulo = 1+powMod a n modulo = loop (n-1) a a+  where loop 0 !_ !acc = acc+        loop 1 !m !acc = m * acc `mod` modulo+        loop i !m !acc+          | even i = loop (i `quot` 2) (m * m `mod` modulo) acc+          | otherwise = loop (i `quot` 2) (m * m `mod` modulo) (m * acc `mod` modulo)+{-# INLINABLE powMod #-}
+ src/Data/Vector/Unboxing.hs view
@@ -0,0 +1,839 @@+{-# LANGUAGE RankNTypes #-}+module Data.Vector.Unboxing+  (Vector+  ,Unboxable(Rep)+  ,Generics(..)+  -- * Accessors+  -- ** Length information+  ,length,null+  -- ** Indexing+  ,(!),(!?),head,last,unsafeIndex,unsafeHead,unsafeLast+  -- ** Monadic indexing+  ,indexM,headM,lastM,unsafeIndexM,unsafeHeadM,unsafeLastM+  -- ** Extracting subvectors (slicing)+  ,slice,init,tail,take,drop,splitAt,unsafeSlice,unsafeInit,unsafeTail+  ,unsafeTake,unsafeDrop+  -- * Construction+  -- ** Initialisation+  ,empty,singleton,replicate,generate,iterateN+  -- ** Monadic initialisation+  ,replicateM,generateM,iterateNM,create,createT+  -- ** Unfolding+  ,unfoldr,unfoldrN,unfoldrM,unfoldrNM,constructN,constructrN+  -- ** Enumeration+  ,enumFromN,enumFromStepN,enumFromTo,enumFromThenTo+  -- ** Concatenation+  ,cons,snoc,(++),concat+  -- ** Restricting memory usage+  ,force+  -- * Modifying vectors+  -- ** Bulk updates+  ,(//),update,update_,unsafeUpd,unsafeUpdate,unsafeUpdate_+  -- ** Accumulations+  ,accum,accumulate,accumulate_,unsafeAccum,unsafeAccumulate,unsafeAccumulate_+  -- ** Permutations+  ,reverse,backpermute,unsafeBackpermute+  -- ** Safe destructive updates+  ,modify+  -- * Elementwise operations+  -- ** Indexing+  ,indexed+  -- ** Mapping+  ,map,imap,concatMap+  -- ** Monadic mapping+  ,mapM,imapM,mapM_,imapM_,forM,forM_+  -- ** Zipping+  ,zipWith,zipWith3,zipWith4,zipWith5,zipWith6,izipWith,izipWith3,izipWith4+  ,izipWith5,izipWith6,zip,zip3,zip4,zip5,zip6+  -- ** Monadic zipping+  ,zipWithM,izipWithM,zipWithM_,izipWithM_+  -- ** Unzipping+  ,unzip,unzip3,unzip4,unzip5,unzip6+  -- * Working with predicates+  -- ** Filtering+  ,filter,ifilter,uniq,mapMaybe,imapMaybe,filterM,takeWhile,dropWhile+  -- ** Partitioning+  ,partition,unstablePartition,span,break+  -- ** Searching+  ,elem,notElem,find,findIndex,findIndices,elemIndex,elemIndices+  -- * Folding+  ,foldl,foldl1,foldl',foldl1',foldr,foldr1,foldr',foldr1',ifoldl,ifoldl'+  ,ifoldr,ifoldr'+  -- ** Specialised folds+  ,all,any,and,or,sum,product,maximum,maximumBy,minimum,minimumBy,minIndex+  ,minIndexBy,maxIndex,maxIndexBy+  -- ** Monadic folds+  ,foldM,ifoldM,foldM',ifoldM',fold1M,fold1M',foldM_,ifoldM_,foldM'_,ifoldM'_+  ,fold1M_,fold1M'_+  -- * Prefix sums (scans)+  ,prescanl,prescanl',postscanl,postscanl',scanl,scanl',scanl1,scanl1',iscanl+  ,iscanl',prescanr,prescanr',postscanr,postscanr',scanr,scanr',scanr1,scanr1'+  ,iscanr,iscanr'+  -- * Conversions+  -- ** Lists+  ,toList,fromList,fromListN+  -- ** Other vector types+  ,convert -- from Data.Vector.Generic+  ,toUnboxedVector+  ,fromUnboxedVector+  ,coerceVector+  ,liftCoercion+  ,vectorCoercion+  -- ** Mutable vectors+  ,freeze,thaw,copy,unsafeFreeze,unsafeThaw,unsafeCopy+  ) where++import Prelude (Monad,Int,Bool,Maybe,Traversable,Eq,Num,Enum,Ord,Ordering)+import qualified Data.Vector.Generic as G+import Data.Vector.Generic (convert)+import Data.Vector.Unboxing.Internal+import Control.Monad.ST+import Control.Monad.Primitive (PrimMonad,PrimState)++length :: (Unboxable a) => Vector a -> Int+length = G.length+{-# INLINE length #-}++null :: (Unboxable a) => Vector a -> Bool+null = G.null+{-# INLINE null #-}++(!) :: (Unboxable a) => Vector a -> Int -> a+(!) = (G.!)+{-# INLINE (!) #-}++(!?) :: (Unboxable a) => Vector a -> Int -> Maybe a+(!?) = (G.!?)+{-# INLINE (!?) #-}++head :: (Unboxable a) => Vector a -> a+head = G.head+{-# INLINE head #-}++last :: (Unboxable a) => Vector a -> a+last = G.last+{-# INLINE last #-}++unsafeIndex :: (Unboxable a) => Vector a -> Int -> a+unsafeIndex = G.unsafeIndex+{-# INLINE unsafeIndex #-}++unsafeHead :: (Unboxable a) => Vector a -> a+unsafeHead = G.unsafeHead+{-# INLINE unsafeHead #-}++unsafeLast :: (Unboxable a) => Vector a -> a+unsafeLast = G.unsafeLast+{-# INLINE unsafeLast #-}++indexM :: (Monad m, Unboxable a) => Vector a -> Int -> m a+indexM = G.indexM+{-# INLINE indexM #-}++headM :: (Monad m, Unboxable a) => Vector a -> m a+headM = G.headM+{-# INLINE headM #-}++lastM :: (Monad m, Unboxable a) => Vector a -> m a+lastM = G.lastM+{-# INLINE lastM #-}++unsafeIndexM :: (Monad m, Unboxable a) => Vector a -> Int -> m a+unsafeIndexM = G.unsafeIndexM+{-# INLINE unsafeIndexM #-}++unsafeHeadM :: (Monad m, Unboxable a) => Vector a -> m a+unsafeHeadM = G.unsafeHeadM+{-# INLINE unsafeHeadM #-}++unsafeLastM :: (Monad m, Unboxable a) => Vector a -> m a+unsafeLastM = G.unsafeLastM+{-# INLINE unsafeLastM #-}++slice :: (Unboxable a) => Int -> Int -> Vector a -> Vector a+slice = G.slice+{-# INLINE slice #-}++init :: (Unboxable a) => Vector a -> Vector a+init = G.init+{-# INLINE init #-}++tail :: (Unboxable a) => Vector a -> Vector a+tail = G.tail+{-# INLINE tail #-}++take :: (Unboxable a) => Int -> Vector a -> Vector a+take = G.take+{-# INLINE take #-}++drop :: (Unboxable a) => Int -> Vector a -> Vector a+drop = G.drop+{-# INLINE drop #-}++splitAt :: (Unboxable a) => Int -> Vector a -> (Vector a, Vector a)+splitAt = G.splitAt+{-# INLINE splitAt #-}++unsafeSlice :: (Unboxable a) => Int -> Int -> Vector a -> Vector a+unsafeSlice = G.unsafeSlice+{-# INLINE unsafeSlice #-}++unsafeInit :: (Unboxable a) => Vector a -> Vector a+unsafeInit = G.unsafeInit+{-# INLINE unsafeInit #-}++unsafeTail :: (Unboxable a) => Vector a -> Vector a+unsafeTail = G.unsafeTail+{-# INLINE unsafeTail #-}++unsafeTake :: (Unboxable a) => Int -> Vector a -> Vector a+unsafeTake = G.unsafeTake+{-# INLINE unsafeTake #-}++unsafeDrop :: (Unboxable a) => Int -> Vector a -> Vector a+unsafeDrop = G.unsafeDrop+{-# INLINE unsafeDrop #-}++empty :: (Unboxable a) => Vector a+empty = G.empty+{-# INLINE empty #-}++singleton :: (Unboxable a) => a -> Vector a+singleton = G.singleton+{-# INLINE singleton #-}++replicate :: (Unboxable a) => Int -> a -> Vector a+replicate = G.replicate+{-# INLINE replicate #-}++generate :: (Unboxable a) => Int -> (Int -> a) -> Vector a+generate = G.generate+{-# INLINE generate #-}++iterateN :: (Unboxable a) => Int -> (a -> a) -> a -> Vector a+iterateN = G.iterateN+{-# INLINE iterateN #-}++replicateM :: (Monad m, Unboxable a) => Int -> m a -> m (Vector a)+replicateM = G.replicateM+{-# INLINE replicateM #-}++generateM :: (Monad m, Unboxable a) => Int -> (Int -> m a) -> m (Vector a)+generateM = G.generateM+{-# INLINE generateM #-}++iterateNM :: (Monad m, Unboxable a) => Int -> (a -> m a) -> a -> m (Vector a)+iterateNM = G.iterateNM+{-# INLINE iterateNM #-}++create :: (Unboxable a) => (forall s. ST s (MVector s a)) -> Vector a+create = G.create+{-# INLINE create #-}++createT :: (Traversable f, Unboxable a) => (forall s. ST s (f (MVector s a))) -> f (Vector a)+createT = G.createT+{-# INLINE createT #-}++unfoldr :: (Unboxable a) => (b -> Maybe (a, b)) -> b -> Vector a+unfoldr = G.unfoldr+{-# INLINE unfoldr #-}++unfoldrN :: (Unboxable a) => Int -> (b -> Maybe (a, b)) -> b -> Vector a+unfoldrN = G.unfoldrN+{-# INLINE unfoldrN #-}++unfoldrM :: (Monad m, Unboxable a) => (b -> m (Maybe (a, b))) -> b -> m (Vector a)+unfoldrM = G.unfoldrM+{-# INLINE unfoldrM #-}++unfoldrNM :: (Monad m, Unboxable a) => Int -> (b -> m (Maybe (a, b))) -> b -> m (Vector a)+unfoldrNM = G.unfoldrNM+{-# INLINE unfoldrNM #-}++constructN :: (Unboxable a) => Int -> (Vector a -> a) -> Vector a+constructN = G.constructN+{-# INLINE constructN #-}++constructrN :: (Unboxable a) => Int -> (Vector a -> a) -> Vector a+constructrN = G.constructrN+{-# INLINE constructrN #-}++enumFromN :: (Num a, Unboxable a) => a -> Int -> Vector a+enumFromN = G.enumFromN+{-# INLINE enumFromN #-}++enumFromStepN :: (Num a, Unboxable a) => a -> a -> Int -> Vector a+enumFromStepN = G.enumFromStepN+{-# INLINE enumFromStepN #-}++enumFromTo :: (Enum a, Unboxable a) => a -> a -> Vector a+enumFromTo = G.enumFromTo+{-# INLINE enumFromTo #-}++enumFromThenTo :: (Enum a, Unboxable a) => a -> a -> a -> Vector a+enumFromThenTo = G.enumFromThenTo+{-# INLINE enumFromThenTo #-}++cons :: (Unboxable a) => a -> Vector a -> Vector a+cons = G.cons+{-# INLINE cons #-}++snoc :: (Unboxable a) => Vector a -> a -> Vector a+snoc = G.snoc+{-# INLINE snoc #-}++(++) :: (Unboxable a) => Vector a -> Vector a -> Vector a+(++) = (G.++)+{-# INLINE (++) #-}++concat :: (Unboxable a) => [Vector a] -> Vector a+concat = G.concat+{-# INLINE concat #-}++force :: (Unboxable a) => Vector a -> Vector a+force = G.force+{-# INLINE force #-}++(//) :: (Unboxable a) => Vector a -> [(Int, a)] -> Vector a+(//) = (G.//)+{-# INLINE (//) #-}++update :: (Unboxable a) => Vector a -> Vector (Int, a) -> Vector a+update = G.update+{-# INLINE update #-}++update_ :: (Unboxable a) => Vector a -> Vector Int -> Vector a -> Vector a+update_ = G.update_+{-# INLINE update_ #-}++unsafeUpd :: (Unboxable a) => Vector a -> [(Int, a)] -> Vector a+unsafeUpd = G.unsafeUpd+{-# INLINE unsafeUpd #-}++unsafeUpdate :: (Unboxable a) => Vector a -> Vector (Int, a) -> Vector a+unsafeUpdate = G.unsafeUpdate+{-# INLINE unsafeUpdate #-}++unsafeUpdate_ :: (Unboxable a) => Vector a -> Vector Int -> Vector a -> Vector a+unsafeUpdate_ = G.unsafeUpdate_+{-# INLINE unsafeUpdate_ #-}++accum :: (Unboxable a) => (a -> b -> a) -> Vector a -> [(Int, b)] -> Vector a+accum = G.accum+{-# INLINE accum #-}++accumulate :: (Unboxable a, Unboxable b) => (a -> b -> a) -> Vector a -> Vector (Int, b) -> Vector a+accumulate = G.accumulate+{-# INLINE accumulate #-}++accumulate_ :: (Unboxable a, Unboxable b) => (a -> b -> a) -> Vector a -> Vector Int -> Vector b -> Vector a+accumulate_ = G.accumulate_+{-# INLINE accumulate_ #-}++unsafeAccum :: (Unboxable a) => (a -> b -> a) -> Vector a -> [(Int, b)] -> Vector a+unsafeAccum = G.unsafeAccum+{-# INLINE unsafeAccum #-}++unsafeAccumulate :: (Unboxable a, Unboxable b) => (a -> b -> a) -> Vector a -> Vector (Int, b) -> Vector a+unsafeAccumulate = G.unsafeAccumulate+{-# INLINE unsafeAccumulate #-}++unsafeAccumulate_ :: (Unboxable a, Unboxable b) => (a -> b -> a) -> Vector a -> Vector Int -> Vector b -> Vector a+unsafeAccumulate_ = G.unsafeAccumulate_+{-# INLINE unsafeAccumulate_ #-}++reverse :: (Unboxable a) => Vector a -> Vector a+reverse = G.reverse+{-# INLINE reverse #-}++backpermute :: (Unboxable a) => Vector a -> Vector Int -> Vector a+backpermute = G.backpermute+{-# INLINE backpermute #-}++unsafeBackpermute :: (Unboxable a) => Vector a -> Vector Int -> Vector a+unsafeBackpermute = G.unsafeBackpermute+{-# INLINE unsafeBackpermute #-}++modify :: (Unboxable a) => (forall s. MVector s a -> ST s ()) -> Vector a -> Vector a+modify = G.modify+{-# INLINE modify #-}++indexed :: (Unboxable a) => Vector a -> Vector (Int, a)+indexed = G.indexed+{-# INLINE indexed #-}++map :: (Unboxable a, Unboxable b) => (a -> b) -> Vector a -> Vector b+map = G.map+{-# INLINE map #-}++imap :: (Unboxable a, Unboxable b) => (Int -> a -> b) -> Vector a -> Vector b+imap = G.imap+{-# INLINE imap #-}++concatMap :: (Unboxable a, Unboxable b) => (a -> Vector b) -> Vector a -> Vector b+concatMap = G.concatMap+{-# INLINE concatMap #-}++mapM :: (Monad m, Unboxable a, Unboxable b) => (a -> m b) -> Vector a -> m (Vector b)+mapM = G.mapM+{-# INLINE mapM #-}++imapM :: (Monad m, Unboxable a, Unboxable b) => (Int -> a -> m b) -> Vector a -> m (Vector b)+imapM = G.imapM+{-# INLINE imapM #-}++mapM_ :: (Monad m, Unboxable a) => (a -> m b) -> Vector a -> m ()+mapM_ = G.mapM_+{-# INLINE mapM_ #-}++imapM_ :: (Monad m, Unboxable a) => (Int -> a -> m b) -> Vector a -> m ()+imapM_ = G.imapM_+{-# INLINE imapM_ #-}++forM :: (Monad m, Unboxable a, Unboxable b) => Vector a -> (a -> m b) -> m (Vector b)+forM = G.forM+{-# INLINE forM #-}++forM_ :: (Monad m, Unboxable a) => Vector a -> (a -> m b) -> m ()+forM_ = G.forM_+{-# INLINE forM_ #-}++zipWith :: (Unboxable a, Unboxable b, Unboxable c) => (a -> b -> c) -> Vector a -> Vector b -> Vector c+zipWith = G.zipWith+{-# INLINE zipWith #-}++zipWith3 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d) => (a -> b -> c -> d) -> Vector a -> Vector b -> Vector c -> Vector d+zipWith3 = G.zipWith3+{-# INLINE zipWith3 #-}++zipWith4 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e) => (a -> b -> c -> d -> e) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e+zipWith4 = G.zipWith4+{-# INLINE zipWith4 #-}++zipWith5 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e, Unboxable f) => (a -> b -> c -> d -> e -> f) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector f+zipWith5 = G.zipWith5+{-# INLINE zipWith5 #-}++zipWith6 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e, Unboxable f, Unboxable g) => (a -> b -> c -> d -> e -> f -> g) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector f -> Vector g+zipWith6 = G.zipWith6+{-# INLINE zipWith6 #-}++izipWith :: (Unboxable a, Unboxable b, Unboxable c) => (Int -> a -> b -> c) -> Vector a -> Vector b -> Vector c+izipWith = G.izipWith+{-# INLINE izipWith #-}++izipWith3 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d) => (Int -> a -> b -> c -> d) -> Vector a -> Vector b -> Vector c -> Vector d+izipWith3 = G.izipWith3+{-# INLINE izipWith3 #-}++izipWith4 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e) => (Int -> a -> b -> c -> d -> e) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e+izipWith4 = G.izipWith4+{-# INLINE izipWith4 #-}++izipWith5 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e, Unboxable f) => (Int -> a -> b -> c -> d -> e -> f) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector f+izipWith5 = G.izipWith5+{-# INLINE izipWith5 #-}++izipWith6 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e, Unboxable f, Unboxable g) => (Int -> a -> b -> c -> d -> e -> f -> g) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector f -> Vector g+izipWith6 = G.izipWith6+{-# INLINE izipWith6 #-}++zip :: (Unboxable a, Unboxable b) => Vector a -> Vector b -> Vector (a, b)+zip = G.zip+{-# INLINE zip #-}++zip3 :: (Unboxable a, Unboxable b, Unboxable c) => Vector a -> Vector b -> Vector c -> Vector (a, b, c)+zip3 = G.zip3+{-# INLINE zip3 #-}++zip4 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d) => Vector a -> Vector b -> Vector c -> Vector d -> Vector (a, b, c, d)+zip4 = G.zip4+{-# INLINE zip4 #-}++zip5 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e) => Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector (a, b, c, d, e)+zip5 = G.zip5+{-# INLINE zip5 #-}++zip6 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e, Unboxable f) => Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector f -> Vector (a, b, c, d, e, f)+zip6 = G.zip6+{-# INLINE zip6 #-}++zipWithM :: (Monad m, Unboxable a, Unboxable b, Unboxable c) => (a -> b -> m c) -> Vector a -> Vector b -> m (Vector c)+zipWithM = G.zipWithM+{-# INLINE zipWithM #-}++izipWithM :: (Monad m, Unboxable a, Unboxable b, Unboxable c) => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m (Vector c)+izipWithM = G.izipWithM+{-# INLINE izipWithM #-}++zipWithM_ :: (Monad m, Unboxable a, Unboxable b) => (a -> b -> m c) -> Vector a -> Vector b -> m ()+zipWithM_ = G.zipWithM_+{-# INLINE zipWithM_ #-}++izipWithM_ :: (Monad m, Unboxable a, Unboxable b) => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m ()+izipWithM_ = G.izipWithM_+{-# INLINE izipWithM_ #-}++unzip :: (Unboxable a, Unboxable b) => Vector (a, b) -> (Vector a, Vector b)+unzip = G.unzip+{-# INLINE unzip #-}++unzip3 :: (Unboxable a, Unboxable b, Unboxable c) => Vector (a, b, c) -> (Vector a, Vector b, Vector c)+unzip3 = G.unzip3+{-# INLINE unzip3 #-}++unzip4 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d) => Vector (a, b, c, d) -> (Vector a, Vector b, Vector c, Vector d)+unzip4 = G.unzip4+{-# INLINE unzip4 #-}++unzip5 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e) => Vector (a, b, c, d, e) -> (Vector a, Vector b, Vector c, Vector d, Vector e)+unzip5 = G.unzip5+{-# INLINE unzip5 #-}++unzip6 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e, Unboxable f) => Vector (a, b, c, d, e, f) -> (Vector a, Vector b, Vector c, Vector d, Vector e, Vector f)+unzip6 = G.unzip6+{-# INLINE unzip6 #-}++filter :: (Unboxable a) => (a -> Bool) -> Vector a -> Vector a+filter = G.filter+{-# INLINE filter #-}++ifilter :: (Unboxable a) => (Int -> a -> Bool) -> Vector a -> Vector a+ifilter = G.ifilter+{-# INLINE ifilter #-}++uniq :: (Eq a, Unboxable a) => Vector a -> Vector a+uniq = G.uniq+{-# INLINE uniq #-}++mapMaybe :: (Unboxable a, Unboxable b) => (a -> Maybe b) -> Vector a -> Vector b+mapMaybe = G.mapMaybe+{-# INLINE mapMaybe #-}++imapMaybe :: (Unboxable a, Unboxable b) => (Int -> a -> Maybe b) -> Vector a -> Vector b+imapMaybe = G.imapMaybe+{-# INLINE imapMaybe #-}++filterM :: (Monad m, Unboxable a) => (a -> m Bool) -> Vector a -> m (Vector a)+filterM = G.filterM+{-# INLINE filterM #-}++takeWhile :: (Unboxable a) => (a -> Bool) -> Vector a -> Vector a+takeWhile = G.takeWhile+{-# INLINE takeWhile #-}++dropWhile :: (Unboxable a) => (a -> Bool) -> Vector a -> Vector a+dropWhile = G.dropWhile+{-# INLINE dropWhile #-}++partition :: (Unboxable a) => (a -> Bool) -> Vector a -> (Vector a, Vector a)+partition = G.partition+{-# INLINE partition #-}++unstablePartition :: (Unboxable a) => (a -> Bool) -> Vector a -> (Vector a, Vector a)+unstablePartition = G.unstablePartition+{-# INLINE unstablePartition #-}++span :: (Unboxable a) => (a -> Bool) -> Vector a -> (Vector a, Vector a)+span = G.span+{-# INLINE span #-}++break :: (Unboxable a) => (a -> Bool) -> Vector a -> (Vector a, Vector a)+break = G.break+{-# INLINE break #-}++elem :: (Eq a, Unboxable a) => a -> Vector a -> Bool+elem = G.elem+{-# INLINE elem #-}++notElem :: (Eq a, Unboxable a) => a -> Vector a -> Bool+notElem = G.notElem+{-# INLINE notElem #-}++find :: (Unboxable a) => (a -> Bool) -> Vector a -> Maybe a+find = G.find+{-# INLINE find #-}++findIndex :: (Unboxable a) => (a -> Bool) -> Vector a -> Maybe Int+findIndex = G.findIndex+{-# INLINE findIndex #-}++findIndices :: (Unboxable a) => (a -> Bool) -> Vector a -> Vector Int+findIndices = G.findIndices+{-# INLINE findIndices #-}++elemIndex :: (Eq a, Unboxable a) => a -> Vector a -> Maybe Int+elemIndex = G.elemIndex+{-# INLINE elemIndex #-}++elemIndices :: (Eq a, Unboxable a) => a -> Vector a -> Vector Int+elemIndices = G.elemIndices+{-# INLINE elemIndices #-}++foldl :: (Unboxable b) => (a -> b -> a) -> a -> Vector b -> a+foldl = G.foldl+{-# INLINE foldl #-}++foldl1 :: (Unboxable a) => (a -> a -> a) -> Vector a -> a+foldl1 = G.foldl1+{-# INLINE foldl1 #-}++foldl' :: (Unboxable b) => (a -> b -> a) -> a -> Vector b -> a+foldl' = G.foldl'+{-# INLINE foldl' #-}++foldl1' :: (Unboxable a) => (a -> a -> a) -> Vector a -> a+foldl1' = G.foldl1'+{-# INLINE foldl1' #-}++foldr :: (Unboxable a) => (a -> b -> b) -> b -> Vector a -> b+foldr = G.foldr+{-# INLINE foldr #-}++foldr1 :: (Unboxable a) => (a -> a -> a) -> Vector a -> a+foldr1 = G.foldr1+{-# INLINE foldr1 #-}++foldr' :: (Unboxable a) => (a -> b -> b) -> b -> Vector a -> b+foldr' = G.foldr'+{-# INLINE foldr' #-}++foldr1' :: (Unboxable a) => (a -> a -> a) -> Vector a -> a+foldr1' = G.foldr1'+{-# INLINE foldr1' #-}++ifoldl :: (Unboxable b) => (a -> Int -> b -> a) -> a -> Vector b -> a+ifoldl = G.ifoldl+{-# INLINE ifoldl #-}++ifoldl' :: (Unboxable b) => (a -> Int -> b -> a) -> a -> Vector b -> a+ifoldl' = G.ifoldl'+{-# INLINE ifoldl' #-}++ifoldr :: (Unboxable a) => (Int -> a -> b -> b) -> b -> Vector a -> b+ifoldr = G.ifoldr+{-# INLINE ifoldr #-}++ifoldr' :: (Unboxable a) => (Int -> a -> b -> b) -> b -> Vector a -> b+ifoldr' = G.ifoldr'+{-# INLINE ifoldr' #-}++all :: (Unboxable a) => (a -> Bool) -> Vector a -> Bool+all = G.all+{-# INLINE all #-}++any :: (Unboxable a) => (a -> Bool) -> Vector a -> Bool+any = G.any+{-# INLINE any #-}++and :: Vector Bool -> Bool+and = G.and+{-# INLINE and #-}++or :: Vector Bool -> Bool+or = G.or+{-# INLINE or #-}++sum :: (Num a, Unboxable a) => Vector a -> a+sum = G.sum+{-# INLINE sum #-}++product :: (Num a, Unboxable a) => Vector a -> a+product = G.product+{-# INLINE product #-}++maximum :: (Ord a, Unboxable a) => Vector a -> a+maximum = G.maximum+{-# INLINE maximum #-}++maximumBy :: (Unboxable a) => (a -> a -> Ordering) -> Vector a -> a+maximumBy = G.maximumBy+{-# INLINE maximumBy #-}++minimum :: (Ord a, Unboxable a) => Vector a -> a+minimum = G.minimum+{-# INLINE minimum #-}++minimumBy :: (Unboxable a) => (a -> a -> Ordering) -> Vector a -> a+minimumBy = G.minimumBy+{-# INLINE minimumBy #-}++minIndex :: (Ord a, Unboxable a) => Vector a -> Int+minIndex = G.minIndex+{-# INLINE minIndex #-}++minIndexBy :: (Unboxable a) => (a -> a -> Ordering) -> Vector a -> Int+minIndexBy = G.minIndexBy+{-# INLINE minIndexBy #-}++maxIndex :: (Ord a, Unboxable a) => Vector a -> Int+maxIndex = G.maxIndex+{-# INLINE maxIndex #-}++maxIndexBy :: (Unboxable a) => (a -> a -> Ordering) -> Vector a -> Int+maxIndexBy = G.maxIndexBy+{-# INLINE maxIndexBy #-}++foldM :: (Monad m, Unboxable b) => (a -> b -> m a) -> a -> Vector b -> m a+foldM = G.foldM+{-# INLINE foldM #-}++ifoldM :: (Monad m, Unboxable b) => (a -> Int -> b -> m a) -> a -> Vector b -> m a+ifoldM = G.ifoldM+{-# INLINE ifoldM #-}++foldM' :: (Monad m, Unboxable b) => (a -> b -> m a) -> a -> Vector b -> m a+foldM' = G.foldM'+{-# INLINE foldM' #-}++ifoldM' :: (Monad m, Unboxable b) => (a -> Int -> b -> m a) -> a -> Vector b -> m a+ifoldM' = G.ifoldM'+{-# INLINE ifoldM' #-}++fold1M :: (Monad m, Unboxable a) => (a -> a -> m a) -> Vector a -> m a+fold1M = G.fold1M+{-# INLINE fold1M #-}++fold1M' :: (Monad m, Unboxable a) => (a -> a -> m a) -> Vector a -> m a+fold1M' = G.fold1M'+{-# INLINE fold1M' #-}++foldM_ :: (Monad m, Unboxable b) => (a -> b -> m a) -> a -> Vector b -> m ()+foldM_ = G.foldM_+{-# INLINE foldM_ #-}++ifoldM_ :: (Monad m, Unboxable b) => (a -> Int -> b -> m a) -> a -> Vector b -> m ()+ifoldM_ = G.ifoldM_+{-# INLINE ifoldM_ #-}++foldM'_ :: (Monad m, Unboxable b) => (a -> b -> m a) -> a -> Vector b -> m ()+foldM'_ = G.foldM'_+{-# INLINE foldM'_ #-}++ifoldM'_ :: (Monad m, Unboxable b) => (a -> Int -> b -> m a) -> a -> Vector b -> m ()+ifoldM'_ = G.ifoldM'_+{-# INLINE ifoldM'_ #-}++fold1M_ :: (Monad m, Unboxable a) => (a -> a -> m a) -> Vector a -> m ()+fold1M_ = G.fold1M_+{-# INLINE fold1M_ #-}++fold1M'_ :: (Monad m, Unboxable a) => (a -> a -> m a) -> Vector a -> m ()+fold1M'_ = G.fold1M'_+{-# INLINE fold1M'_ #-}++prescanl :: (Unboxable a, Unboxable b) => (a -> b -> a) -> a -> Vector b -> Vector a+prescanl = G.prescanl+{-# INLINE prescanl #-}++prescanl' :: (Unboxable a, Unboxable b) => (a -> b -> a) -> a -> Vector b -> Vector a+prescanl' = G.prescanl'+{-# INLINE prescanl' #-}++postscanl :: (Unboxable a, Unboxable b) => (a -> b -> a) -> a -> Vector b -> Vector a+postscanl = G.postscanl+{-# INLINE postscanl #-}++postscanl' :: (Unboxable a, Unboxable b) => (a -> b -> a) -> a -> Vector b -> Vector a+postscanl' = G.postscanl'+{-# INLINE postscanl' #-}++scanl :: (Unboxable a, Unboxable b) => (a -> b -> a) -> a -> Vector b -> Vector a+scanl = G.scanl+{-# INLINE scanl #-}++scanl' :: (Unboxable a, Unboxable b) => (a -> b -> a) -> a -> Vector b -> Vector a+scanl' = G.scanl'+{-# INLINE scanl' #-}++scanl1 :: (Unboxable a) => (a -> a -> a) -> Vector a -> Vector a+scanl1 = G.scanl1+{-# INLINE scanl1 #-}++scanl1' :: (Unboxable a) => (a -> a -> a) -> Vector a -> Vector a+scanl1' = G.scanl1'+{-# INLINE scanl1' #-}++iscanl :: (Unboxable a, Unboxable b) => (Int -> a -> b -> a) -> a -> Vector b -> Vector a+iscanl = G.iscanl+{-# INLINE iscanl #-}++iscanl' :: (Unboxable a, Unboxable b) => (Int -> a -> b -> a) -> a -> Vector b -> Vector a+iscanl' = G.iscanl'+{-# INLINE iscanl' #-}++prescanr :: (Unboxable a, Unboxable b) => (a -> b -> b) -> b -> Vector a -> Vector b+prescanr = G.prescanr+{-# INLINE prescanr #-}++prescanr' :: (Unboxable a, Unboxable b) => (a -> b -> b) -> b -> Vector a -> Vector b+prescanr' = G.prescanr'+{-# INLINE prescanr' #-}++postscanr :: (Unboxable a, Unboxable b) => (a -> b -> b) -> b -> Vector a -> Vector b+postscanr = G.postscanr+{-# INLINE postscanr #-}++postscanr' :: (Unboxable a, Unboxable b) => (a -> b -> b) -> b -> Vector a -> Vector b+postscanr' = G.postscanr'+{-# INLINE postscanr' #-}++scanr :: (Unboxable a, Unboxable b) => (a -> b -> b) -> b -> Vector a -> Vector b+scanr = G.scanr+{-# INLINE scanr #-}++scanr' :: (Unboxable a, Unboxable b) => (a -> b -> b) -> b -> Vector a -> Vector b+scanr' = G.scanr'+{-# INLINE scanr' #-}++scanr1 :: (Unboxable a) => (a -> a -> a) -> Vector a -> Vector a+scanr1 = G.scanr1+{-# INLINE scanr1 #-}++scanr1' :: (Unboxable a) => (a -> a -> a) -> Vector a -> Vector a+scanr1' = G.scanr1'+{-# INLINE scanr1' #-}++iscanr :: (Unboxable a, Unboxable b) => (Int -> a -> b -> b) -> b -> Vector a -> Vector b+iscanr = G.iscanr+{-# INLINE iscanr #-}++iscanr' :: (Unboxable a, Unboxable b) => (Int -> a -> b -> b) -> b -> Vector a -> Vector b+iscanr' = G.iscanr'+{-# INLINE iscanr' #-}++toList :: (Unboxable a) => Vector a -> [a]+toList = G.toList+{-# INLINE toList #-}++fromList :: (Unboxable a) => [a] -> Vector a+fromList = G.fromList+{-# INLINE fromList #-}++fromListN :: (Unboxable a) => Int -> [a] -> Vector a+fromListN = G.fromListN+{-# INLINE fromListN #-}++freeze :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> m (Vector a)+freeze = G.freeze+{-# INLINE freeze #-}++thaw :: (PrimMonad m, Unboxable a) => Vector a -> m (MVector (PrimState m) a)+thaw = G.thaw+{-# INLINE thaw #-}++copy :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> Vector a -> m ()+copy = G.copy+{-# INLINE copy #-}++unsafeFreeze :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> m (Vector a)+unsafeFreeze = G.unsafeFreeze+{-# INLINE unsafeFreeze #-}++unsafeThaw :: (PrimMonad m, Unboxable a) => Vector a -> m (MVector (PrimState m) a)+unsafeThaw = G.unsafeThaw+{-# INLINE unsafeThaw #-}++unsafeCopy :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> Vector a -> m ()+unsafeCopy = G.unsafeCopy+{-# INLINE unsafeCopy #-}
+ src/Data/Vector/Unboxing/Internal.hs view
@@ -0,0 +1,521 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_HADDOCK hide #-}+module Data.Vector.Unboxing.Internal+  (Unboxable(Rep)+  ,Vector(UnboxingVector)+  ,MVector(UnboxingMVector)+  ,Generics(..)+  ,coerceVector+  ,liftCoercion+  ,vectorCoercion+  ,toUnboxedVector+  ,fromUnboxedVector+  ,coercionWithUnboxedVector+  ,toUnboxedMVector+  ,fromUnboxedMVector+  ,coercionWithUnboxedMVector+  ) where+import qualified Data.Vector.Generic as G+import qualified Data.Vector.Generic.Mutable as GM+import qualified Data.Vector.Unboxed as U+import qualified Data.Vector.Unboxed.Mutable as UM+import qualified Data.Vector.Fusion.Bundle as Bundle+import Data.Coerce+import Data.Type.Coercion+import Data.Int+import Data.Word+import qualified GHC.Generics+import Data.Type.Bool+import qualified Data.Complex+import qualified Data.Functor.Identity+import qualified Data.Functor.Const+import qualified Data.Ord+import qualified Data.Semigroup+import qualified Data.Monoid+import qualified Data.MonoTraversable -- from mono-traversable+import qualified Data.Sequences       -- from mono-traversable+import GHC.Exts (IsList(..))+import Control.DeepSeq (NFData(..))+import Text.Read (Read(..),readListPrecDefault)+import GHC.TypeLits (TypeError,ErrorMessage(Text))++newtype Vector a = UnboxingVector (U.Vector (Rep a))+newtype MVector s a = UnboxingMVector (UM.MVector s (Rep a))++type instance G.Mutable Vector = MVector++-- | Types that can be stored in unboxed vectors ('Vector' and 'MVector').+--+-- You can define instances of this class like:+--+-- > newtype Foo = Foo Int+-- > instance Unboxable Foo where+-- >   type Rep Foo = Int+--+-- The type specified by 'Rep' needs to be an instance of 'U.Unbox',+-- and coercion must be possible between the two types.+--+-- Instances can also be derived with @GeneralizedNewtypeDeriving@.+-- GND always works if the base type is an instance of 'Unboxable'.+--+-- If you want to have non-trivial correspondence between the type and the representation,+-- use 'Generics' wrapper with @DerivingVia@.+--+-- Note that @UndecidableInstances@ is needed if you use GND or @DerivingVia@ to derive instances.+class U.Unbox (Rep a) => Unboxable a where+  -- | The underlying type of @a@.  Must be an instance of 'U.Unbox'.+  type Rep a++  -- Hidden members:++  -- Used by 'coerceVector'+  type CoercibleRep a+  type CoercibleRep a = Rep a++  -- True if both 'unboxingFrom and 'unboxingTo' are just 'coerce'+  type IsTrivial a :: Bool+  type IsTrivial a = 'True+  -- TODO: Use ConstraintKinds?++  unboxingFrom :: a -> Rep a+  default unboxingFrom :: Coercible a (Rep a) => a -> Rep a+  unboxingFrom = coerce+  {-# INLINE unboxingFrom #-}++  unboxingTo :: Rep a -> a+  default unboxingTo :: Coercible a (Rep a) => Rep a -> a+  unboxingTo = coerce+  {-# INLINE unboxingTo #-}++coerceVector :: (Coercible a b, Unboxable a, Unboxable b, CoercibleRep a ~ CoercibleRep b, Rep a ~ Rep b) => Vector a -> Vector b+coerceVector = coerce+{-# INLINE coerceVector #-}++liftCoercion :: (Unboxable a, Unboxable b, CoercibleRep a ~ CoercibleRep b, Rep a ~ Rep b) => Coercion a b -> Coercion (Vector a) (Vector b)+liftCoercion Coercion = Coercion+{-# INLINE liftCoercion #-}++vectorCoercion :: (Coercible a b, Unboxable a, Unboxable b, CoercibleRep a ~ CoercibleRep b, Rep a ~ Rep b) => Coercion (Vector a) (Vector b)+vectorCoercion = Coercion+{-# INLINE vectorCoercion #-}++toUnboxedVector :: (Unboxable a, Rep a ~ a, IsTrivial a ~ 'True) => Vector a -> U.Vector a+toUnboxedVector = coerce+{-# INLINE toUnboxedVector #-}++fromUnboxedVector :: (Unboxable a, Rep a ~ a, IsTrivial a ~ 'True) => U.Vector a -> Vector a+fromUnboxedVector = coerce+{-# INLINE fromUnboxedVector #-}++toUnboxedMVector :: (Unboxable a, Rep a ~ a, IsTrivial a ~ 'True) => MVector s a -> UM.MVector s a+toUnboxedMVector = coerce+{-# INLINE toUnboxedMVector #-}++fromUnboxedMVector :: (Unboxable a, Rep a ~ a, IsTrivial a ~ 'True) => UM.MVector s a -> MVector s a+fromUnboxedMVector = coerce+{-# INLINE fromUnboxedMVector #-}++coercionWithUnboxedVector :: (Unboxable a, Rep a ~ a, IsTrivial a ~ 'True) => Coercion (Vector a) (U.Vector a)+coercionWithUnboxedVector = Coercion+{-# INLINE coercionWithUnboxedVector #-}++coercionWithUnboxedMVector :: (Unboxable a, Rep a ~ a, IsTrivial a ~ 'True) => Coercion (MVector s a) (U.MVector s a)+coercionWithUnboxedMVector = Coercion+{-# INLINE coercionWithUnboxedMVector #-}++-----++-- Generics++-- | A newtype wrapper to be used with @DerivingVia@.+--+-- Usage:+--+-- > data Bar = Bar !Int !Int+-- >   deriving Generic+-- >   deriving Unboxable via Generics Bar+newtype Generics a = Generics a++instance (GHC.Generics.Generic a, Unboxable (Rep' (GHC.Generics.Rep a)), Unboxable' (GHC.Generics.Rep a)) => Unboxable (Generics a) where+  type Rep (Generics a) = Rep (Rep' (GHC.Generics.Rep a))+  type CoercibleRep (Generics a) = a+  type IsTrivial (Generics a) = 'False+  unboxingFrom (Generics x) = unboxingFrom (from' (GHC.Generics.from x))+  {-# INLINE unboxingFrom #-}+  unboxingTo y = Generics (GHC.Generics.to (to' (unboxingTo y)))+  {-# INLINE unboxingTo #-}++class Unboxable' f where+  type Rep' f+  from' :: f x -> Rep' f+  to' :: Rep' f -> f x+instance Unboxable' GHC.Generics.U1 where+  type Rep' GHC.Generics.U1 = ()+  from' _ = ()+  to' _ = GHC.Generics.U1+  {-# INLINE from' #-}+  {-# INLINE to' #-}+instance Unboxable c => Unboxable' (GHC.Generics.K1 i c) where+  type Rep' (GHC.Generics.K1 i c) = Rep c+  from' = {- from . GHC.Generics.unK1 -} coerce (unboxingFrom :: c -> Rep c)+  to' = {- GHC.Generics.K1 . to -} coerce (unboxingTo :: Rep c -> c)+  {-# INLINE from' #-}+  {-# INLINE to' #-}+instance Unboxable' f => Unboxable' (GHC.Generics.M1 i c f) where+  type Rep' (GHC.Generics.M1 i c f) = Rep' f+  from' = from' . GHC.Generics.unM1+  to' = GHC.Generics.M1 . to'+  {-# INLINE from' #-}+  {-# INLINE to' #-}+instance (Unboxable' f, Unboxable' g) => Unboxable' (f GHC.Generics.:*: g) where+  type Rep' (f GHC.Generics.:*: g) = (Rep' f, Rep' g)+  from' (x GHC.Generics.:*: y) = (from' x, from' y)+  to' (x, y) = (to' x GHC.Generics.:*: to' y)+  {-# INLINE from' #-}+  {-# INLINE to' #-}+instance Unboxable' (f GHC.Generics.:+: g) where+  type Rep' (f GHC.Generics.:+: g) = TypeError ('Text "Cannot derive Unboxable instance for a sum type.")+  from' = undefined+  to' = undefined++-----++-- Instances++instance (Unboxable a) => IsList (Vector a) where+  type Item (Vector a) = a+  fromList = G.fromList+  fromListN = G.fromListN+  toList = G.toList+  {-# INLINE fromList #-}+  {-# INLINE fromListN #-}+  {-# INLINE toList #-}++instance (Eq a, Unboxable a) => Eq (Vector a) where+  xs == ys = Bundle.eq (G.stream xs) (G.stream ys)+  xs /= ys = not (Bundle.eq (G.stream xs) (G.stream ys))+  {-# INLINE (==) #-}+  {-# INLINE (/=) #-}++instance (Ord a, Unboxable a) => Ord (Vector a) where+  compare xs ys = Bundle.cmp (G.stream xs) (G.stream ys)+  {-# INLINE compare #-}++instance (Show a, Unboxable a) => Show (Vector a) where+  showsPrec = G.showsPrec+  {-# INLINE showsPrec #-}++instance (Read a, Unboxable a) => Read (Vector a) where+  readPrec = G.readPrec+  readListPrec = readListPrecDefault+  {-# INLINE readPrec #-}+  {-# INLINE readListPrec #-}++instance (Unboxable a) => Semigroup (Vector a) where+  (<>) = (G.++)+  sconcat = G.concatNE+  {-# INLINE (<>) #-}+  {-# INLINE sconcat #-}++instance (Unboxable a) => Monoid (Vector a) where+  mempty = G.empty+  mappend = (<>)+  mconcat = G.concat+  {-# INLINE mempty #-}+  {-# INLINE mappend #-}+  {-# INLINE mconcat #-}++instance NFData (Vector a) where+  rnf !_ = () -- the content is unboxed++instance (Unboxable a) => GM.MVector MVector a where+  basicLength (UnboxingMVector mv)                           = GM.basicLength mv+  basicUnsafeSlice i l (UnboxingMVector mv)                  = UnboxingMVector (GM.basicUnsafeSlice i l mv)+  basicOverlaps (UnboxingMVector mv) (UnboxingMVector mv')   = GM.basicOverlaps mv mv'+  basicUnsafeNew l                                           = UnboxingMVector <$> GM.basicUnsafeNew l+  basicInitialize (UnboxingMVector mv)                       = GM.basicInitialize mv+  basicUnsafeReplicate i x                                   = UnboxingMVector <$> GM.basicUnsafeReplicate i (unboxingFrom x)+  basicUnsafeRead (UnboxingMVector mv) i                     = unboxingTo <$> GM.basicUnsafeRead mv i+  basicUnsafeWrite (UnboxingMVector mv) i x                  = GM.basicUnsafeWrite mv i (unboxingFrom x)+  basicClear (UnboxingMVector mv)                            = GM.basicClear mv+  basicSet (UnboxingMVector mv) x                            = GM.basicSet mv (unboxingFrom x)+  basicUnsafeCopy (UnboxingMVector mv) (UnboxingMVector mv') = GM.basicUnsafeCopy mv mv'+  basicUnsafeMove (UnboxingMVector mv) (UnboxingMVector mv') = GM.basicUnsafeMove mv mv'+  basicUnsafeGrow (UnboxingMVector mv) n                     = UnboxingMVector <$> GM.basicUnsafeGrow mv n+  {-# INLINE basicLength #-}+  {-# INLINE basicUnsafeSlice #-}+  {-# INLINE basicOverlaps #-}+  {-# INLINE basicUnsafeNew #-}+  {-# INLINE basicInitialize #-}+  {-# INLINE basicUnsafeRead #-}+  {-# INLINE basicUnsafeWrite #-}+  {-# INLINE basicClear #-}+  {-# INLINE basicSet #-}+  {-# INLINE basicUnsafeCopy #-}+  {-# INLINE basicUnsafeMove #-}+  {-# INLINE basicUnsafeGrow #-}++instance (Unboxable a) => G.Vector Vector a where+  basicUnsafeFreeze (UnboxingMVector mv)                  = UnboxingVector <$> G.basicUnsafeFreeze mv+  basicUnsafeThaw (UnboxingVector v)                      = UnboxingMVector <$> G.basicUnsafeThaw v+  basicLength (UnboxingVector v)                          = G.basicLength v+  basicUnsafeSlice i l (UnboxingVector v)                 = UnboxingVector (G.basicUnsafeSlice i l v)+  basicUnsafeIndexM (UnboxingVector v) i                  = unboxingTo <$> G.basicUnsafeIndexM v i+  basicUnsafeCopy (UnboxingMVector mv) (UnboxingVector v) = G.basicUnsafeCopy mv v+  elemseq (UnboxingVector v) x y                          = G.elemseq v (unboxingFrom x) y -- ?+  {-# INLINE basicUnsafeFreeze #-}+  {-# INLINE basicUnsafeThaw #-}+  {-# INLINE basicLength #-}+  {-# INLINE basicUnsafeSlice #-}+  {-# INLINE basicUnsafeIndexM #-}+  {-# INLINE basicUnsafeCopy #-}+  {-# INLINE elemseq #-}++-----++-- Classes from mono-traversable++type instance Data.MonoTraversable.Element (Vector a) = a++instance (Unboxable a) => Data.MonoTraversable.MonoFunctor (Vector a) where+  omap = G.map+  {-# INLINE omap #-}++instance (Unboxable a) => Data.MonoTraversable.MonoFoldable (Vector a) where+  ofoldMap f = G.foldr (mappend . f) mempty+  ofoldr = G.foldr+  ofoldl' = G.foldl'+  otoList = G.toList+  oall = G.all+  oany = G.any+  onull = G.null+  olength = G.length+  olength64 = fromIntegral . G.length+  -- ocompareLength : use default+  -- otraverse_ : use default+  -- ofor_ : use default+  -- omapM_ : use default (G.mapM_ requires a Monad, unfortunately)+  -- oforM_ : use default (G.forM_ requires a Monad, unfortunately)+  ofoldlM = G.foldM+  -- ofoldMap1Ex : use default+  ofoldr1Ex = G.foldr1+  ofoldl1Ex' = G.foldl1'+  headEx = G.head+  lastEx = G.last+  unsafeHead = G.unsafeHead+  unsafeLast = G.unsafeLast+  maximumByEx = G.maximumBy+  minimumByEx = G.minimumBy+  oelem = G.elem+  onotElem = G.notElem+  {-# INLINE ofoldMap #-}+  {-# INLINE ofoldr #-}+  {-# INLINE ofoldl' #-}+  {-# INLINE otoList #-}+  {-# INLINE oall #-}+  {-# INLINE oany #-}+  {-# INLINE onull #-}+  {-# INLINE olength #-}+  {-# INLINE olength64 #-}+  {-# INLINE ofoldlM #-}+  {-# INLINE ofoldr1Ex #-}+  {-# INLINE ofoldl1Ex' #-}+  {-# INLINE headEx #-}+  {-# INLINE lastEx #-}+  {-# INLINE unsafeHead #-}+  {-# INLINE unsafeLast #-}+  {-# INLINE maximumByEx #-}+  {-# INLINE minimumByEx #-}+  {-# INLINE oelem #-}+  {-# INLINE onotElem #-}++instance (Unboxable a) => Data.MonoTraversable.MonoTraversable (Vector a) where+  otraverse f v = let !n = G.length v+                  in G.fromListN n <$> traverse f (G.toList v)+  omapM = Data.MonoTraversable.otraverse+  {-# INLINE otraverse #-}+  {-# INLINE omapM #-}++instance (Unboxable a) => Data.MonoTraversable.MonoPointed (Vector a) where+  opoint = G.singleton+  {-# INLINE opoint #-}++instance (Unboxable a) => Data.MonoTraversable.GrowingAppend (Vector a)++instance (Unboxable a) => Data.Sequences.SemiSequence (Vector a) where+  type Index (Vector a) = Int+  intersperse = Data.Sequences.defaultIntersperse+  reverse = G.reverse+  find = G.find+  sortBy = Data.Sequences.vectorSortBy+  cons = G.cons+  snoc = G.snoc+  {-# INLINE intersperse #-}+  {-# INLINE reverse #-}+  {-# INLINE find #-}+  {-# INLINE sortBy #-}+  {-# INLINE cons #-}+  {-# INLINE snoc #-}++instance (Unboxable a) => Data.Sequences.IsSequence (Vector a) where+  fromList = G.fromList+  lengthIndex = G.length+  break = G.break+  span = G.span+  dropWhile = G.dropWhile+  takeWhile = G.takeWhile+  splitAt = G.splitAt+  -- unsafeSplitAt : use default+  take = G.take+  unsafeTake = G.unsafeTake+  drop = G.drop+  unsafeDrop = G.unsafeDrop+  -- dropEnd : use default+  partition = G.partition+  uncons v | G.null v = Nothing+           | otherwise = Just (G.head v, G.tail v)+  unsnoc v | G.null v = Nothing+           | otherwise = Just (G.init v, G.last v)+  filter = G.filter+  filterM = G.filterM+  replicate = G.replicate+  replicateM = G.replicateM+  -- groupBy : use default+  -- groupAllOn : use default+  -- subsequences : use default+  -- permutations : use default+  tailEx = G.tail+  -- tailMay : use default+  initEx = G.init+  -- initMay : use default+  unsafeTail = G.unsafeTail+  unsafeInit = G.unsafeInit+  index = (G.!?)+  indexEx = (G.!)+  unsafeIndex = G.unsafeIndex+  -- splitWhen : use default+  {-# INLINE fromList #-}+  {-# INLINE lengthIndex #-}+  {-# INLINE break #-}+  {-# INLINE span #-}+  {-# INLINE dropWhile #-}+  {-# INLINE takeWhile #-}+  {-# INLINE splitAt #-}+  {-# INLINE take #-}+  {-# INLINE unsafeTake #-}+  {-# INLINE drop #-}+  {-# INLINE unsafeDrop #-}+  {-# INLINE partition #-}+  {-# INLINE uncons #-}+  {-# INLINE unsnoc #-}+  {-# INLINE filter #-}+  {-# INLINE filterM #-}+  {-# INLINE replicate #-}+  {-# INLINE replicateM #-}+  {-# INLINE tailEx #-}+  {-# INLINE initEx #-}+  {-# INLINE unsafeTail #-}+  {-# INLINE unsafeInit #-}+  {-# INLINE index #-}+  {-# INLINE indexEx #-}+  {-# INLINE unsafeIndex #-}++-----++-- Unboxable instances++instance Unboxable Bool where   type Rep Bool = Bool+instance Unboxable Char where   type Rep Char = Char+instance Unboxable Double where type Rep Double = Double+instance Unboxable Float where  type Rep Float = Float+instance Unboxable Int where    type Rep Int = Int+instance Unboxable Int8 where   type Rep Int8 = Int8+instance Unboxable Int16 where  type Rep Int16 = Int16+instance Unboxable Int32 where  type Rep Int32 = Int32+instance Unboxable Int64 where  type Rep Int64 = Int64+instance Unboxable Word where   type Rep Word = Word+instance Unboxable Word8 where  type Rep Word8 = Word8+instance Unboxable Word16 where type Rep Word16 = Word16+instance Unboxable Word32 where type Rep Word32 = Word32+instance Unboxable Word64 where type Rep Word64 = Word64+instance Unboxable () where     type Rep () = ()++instance (Unboxable a) => Unboxable (Data.Complex.Complex a) where+  type Rep (Data.Complex.Complex a) = Data.Complex.Complex (Rep a)+  type CoercibleRep (Data.Complex.Complex a) = Data.Complex.Complex (CoercibleRep a)+  type IsTrivial (Data.Complex.Complex a) = IsTrivial a+  unboxingFrom = fmap unboxingFrom+  unboxingTo = fmap unboxingTo+  {-# INLINE unboxingFrom #-}+  {-# INLINE unboxingTo #-}++instance (Unboxable a, Unboxable b) => Unboxable (a, b) where+  type Rep (a, b) = (Rep a, Rep b)+  type CoercibleRep (a, b) = (CoercibleRep a, CoercibleRep b)+  type IsTrivial (a, b) = IsTrivial a && IsTrivial b+  unboxingFrom (a, b) = (unboxingFrom a, unboxingFrom b)+  unboxingTo (a, b) = (unboxingTo a, unboxingTo b)+  {-# INLINE unboxingFrom #-}+  {-# INLINE unboxingTo #-}++instance (Unboxable a, Unboxable b, Unboxable c) => Unboxable (a, b, c) where+  type Rep (a, b, c) = (Rep a, Rep b, Rep c)+  type CoercibleRep (a, b, c) = (CoercibleRep a, CoercibleRep b, CoercibleRep c)+  type IsTrivial (a, b, c) = IsTrivial a && IsTrivial b && IsTrivial c+  unboxingFrom (a, b, c) = (unboxingFrom a, unboxingFrom b, unboxingFrom c)+  unboxingTo (a, b, c) = (unboxingTo a, unboxingTo b, unboxingTo c)+  {-# INLINE unboxingFrom #-}+  {-# INLINE unboxingTo #-}++instance (Unboxable a, Unboxable b, Unboxable c, Unboxable d) => Unboxable (a, b, c, d) where+  type Rep (a, b, c, d) = (Rep a, Rep b, Rep c, Rep d)+  type CoercibleRep (a, b, c, d) = (CoercibleRep a, CoercibleRep b, CoercibleRep c, CoercibleRep d)+  type IsTrivial (a, b, c, d) = IsTrivial a && IsTrivial b && IsTrivial c && IsTrivial d+  unboxingFrom (a, b, c, d) = (unboxingFrom a, unboxingFrom b, unboxingFrom c, unboxingFrom d)+  unboxingTo (a, b, c, d) = (unboxingTo a, unboxingTo b, unboxingTo c, unboxingTo d)+  {-# INLINE unboxingFrom #-}+  {-# INLINE unboxingTo #-}++instance (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e) => Unboxable (a, b, c, d, e) where+  type Rep (a, b, c, d, e) = (Rep a, Rep b, Rep c, Rep d, Rep e)+  type CoercibleRep (a, b, c, d, e) = (CoercibleRep a, CoercibleRep b, CoercibleRep c, CoercibleRep d, CoercibleRep e)+  type IsTrivial (a, b, c, d, e) = IsTrivial a && IsTrivial b && IsTrivial c && IsTrivial d && IsTrivial e+  unboxingFrom (a, b, c, d, e) = (unboxingFrom a, unboxingFrom b, unboxingFrom c, unboxingFrom d, unboxingFrom e)+  unboxingTo (a, b, c, d, e) = (unboxingTo a, unboxingTo b, unboxingTo c, unboxingTo d, unboxingTo e)+  {-# INLINE unboxingFrom #-}+  {-# INLINE unboxingTo #-}++instance (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e, Unboxable f) => Unboxable (a, b, c, d, e, f) where+  type Rep (a, b, c, d, e, f) = (Rep a, Rep b, Rep c, Rep d, Rep e, Rep f)+  type CoercibleRep (a, b, c, d, e, f) = (CoercibleRep a, CoercibleRep b, CoercibleRep c, CoercibleRep d, CoercibleRep e, CoercibleRep f)+  type IsTrivial (a, b, c, d, e, f) = IsTrivial a && IsTrivial b && IsTrivial c && IsTrivial d && IsTrivial e && IsTrivial f+  unboxingFrom (a, b, c, d, e, f) = (unboxingFrom a, unboxingFrom b, unboxingFrom c, unboxingFrom d, unboxingFrom e, unboxingFrom f)+  unboxingTo (a, b, c, d, e, f) = (unboxingTo a, unboxingTo b, unboxingTo c, unboxingTo d, unboxingTo e, unboxingTo f)+  {-# INLINE unboxingFrom #-}+  {-# INLINE unboxingTo #-}++deriving instance Unboxable a => Unboxable (Data.Functor.Identity.Identity a)+deriving instance Unboxable a => Unboxable (Data.Functor.Const.Const a b)+deriving instance Unboxable a => Unboxable (Data.Semigroup.Min a)+deriving instance Unboxable a => Unboxable (Data.Semigroup.Max a)+deriving instance Unboxable a => Unboxable (Data.Semigroup.First a)+deriving instance Unboxable a => Unboxable (Data.Semigroup.Last a)+deriving instance Unboxable a => Unboxable (Data.Semigroup.WrappedMonoid a)+deriving instance Unboxable a => Unboxable (Data.Monoid.Dual a)+deriving instance Unboxable Data.Monoid.All+deriving instance Unboxable Data.Monoid.Any+deriving instance Unboxable a => Unboxable (Data.Monoid.Sum a)+deriving instance Unboxable a => Unboxable (Data.Monoid.Product a)+deriving instance Unboxable a => Unboxable (Data.Ord.Down a)
+ src/Data/Vector/Unboxing/Mutable.hs view
@@ -0,0 +1,240 @@+module Data.Vector.Unboxing.Mutable+  (MVector+  ,IOVector+  ,STVector+  ,Unboxable(Rep)+  ,Generics(..)+  -- * Accessors+  -- ** Length information+  ,length,null+  -- ** Extracting subvectors (slicing)+  ,slice,init,tail,take,drop,splitAt,unsafeSlice,unsafeInit,unsafeTail+  ,unsafeTake,unsafeDrop+  -- ** Overlapping+  ,overlaps+  -- * Construction+  -- ** Initialisation+  ,new,unsafeNew,replicate,replicateM,clone+  -- ** Growing+  ,grow,unsafeGrow+  -- ** Restricting memory usage+  ,clear+  -- * Zipping and unzipping+  ,zip,zip3,zip4,zip5,zip6,unzip,unzip3,unzip4,unzip5,unzip6+  -- * Accessing individual elements+  ,read,write,modify,swap,unsafeRead,unsafeWrite,unsafeModify,unsafeSwap+  -- * Modifying vectors+  ,nextPermutation+  -- ** Filling and copying+  ,set,copy,move,unsafeCopy,unsafeMove+  -- * Conversions from/to other vector types+  ,toUnboxedMVector+  ,fromUnboxedMVector+  ) where++import Prelude (Int,Bool,Ord)+import qualified Data.Vector.Generic.Mutable as G+import qualified Data.Vector.Unboxed.Mutable as UM+import Data.Vector.Unboxing.Internal+import Control.Monad.ST+import Control.Monad.Primitive (PrimMonad,PrimState)+import Data.Coerce++type IOVector = MVector RealWorld+type STVector s = MVector s++length :: (Unboxable a) => MVector s a -> Int+length = G.length+{-# INLINE length #-}++null :: (Unboxable a) => MVector s a -> Bool+null = G.null+{-# INLINE null #-}++slice :: (Unboxable a) => Int -> Int -> MVector s a -> MVector s a+slice = G.slice+{-# INLINE slice #-}++init :: (Unboxable a) => MVector s a -> MVector s a+init = G.init+{-# INLINE init #-}++tail :: (Unboxable a) => MVector s a -> MVector s a+tail = G.tail+{-# INLINE tail #-}++take :: (Unboxable a) => Int -> MVector s a -> MVector s a+take = G.take+{-# INLINE take #-}++drop :: (Unboxable a) => Int -> MVector s a -> MVector s a+drop = G.drop+{-# INLINE drop #-}++splitAt :: (Unboxable a) => Int -> MVector s a -> (MVector s a, MVector s a)+splitAt = G.splitAt+{-# INLINE splitAt #-}++unsafeSlice :: (Unboxable a) => Int -> Int -> MVector s a -> MVector s a+unsafeSlice = G.unsafeSlice+{-# INLINE unsafeSlice #-}++unsafeInit :: (Unboxable a) => MVector s a -> MVector s a+unsafeInit = G.unsafeInit+{-# INLINE unsafeInit #-}++unsafeTail :: (Unboxable a) => MVector s a -> MVector s a+unsafeTail = G.unsafeTail+{-# INLINE unsafeTail #-}++unsafeTake :: (Unboxable a) => Int -> MVector s a -> MVector s a+unsafeTake = G.unsafeTake+{-# INLINE unsafeTake #-}++unsafeDrop :: (Unboxable a) => Int -> MVector s a -> MVector s a+unsafeDrop = G.unsafeDrop+{-# INLINE unsafeDrop #-}++overlaps :: (Unboxable a) => MVector s a -> MVector s a -> Bool+overlaps = G.overlaps+{-# INLINE overlaps #-}++new :: (PrimMonad m, Unboxable a) => Int -> m (MVector (PrimState m) a)+new = G.new+{-# INLINE new #-}++unsafeNew :: (PrimMonad m, Unboxable a) => Int -> m (MVector (PrimState m) a)+unsafeNew = G.unsafeNew+{-# INLINE unsafeNew #-}++replicate :: (PrimMonad m, Unboxable a) => Int -> a -> m (MVector (PrimState m) a)+replicate = G.replicate+{-# INLINE replicate #-}++replicateM :: (PrimMonad m, Unboxable a) => Int -> m a -> m (MVector (PrimState m) a)+replicateM = G.replicateM+{-# INLINE replicateM #-}++clone :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> m (MVector (PrimState m) a)+clone = G.clone+{-# INLINE clone #-}++grow :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)+grow = G.grow+{-# INLINE grow #-}++unsafeGrow :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)+unsafeGrow = G.unsafeGrow+{-# INLINE unsafeGrow #-}++clear :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> m ()+clear = G.clear+{-# INLINE clear #-}++read :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> Int -> m a+read = G.read+{-# INLINE read #-}++write :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> Int -> a -> m ()+write = G.write+{-# INLINE write #-}++modify :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> (a -> a) -> Int -> m ()+modify = G.modify+{-# INLINE modify #-}++swap :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> Int -> Int -> m ()+swap = G.swap+{-# INLINE swap #-}++unsafeRead :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> Int -> m a+unsafeRead = G.unsafeRead+{-# INLINE unsafeRead #-}++unsafeWrite :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> Int -> a -> m ()+unsafeWrite = G.unsafeWrite+{-# INLINE unsafeWrite #-}++unsafeModify :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> (a -> a) -> Int -> m ()+unsafeModify = G.unsafeModify+{-# INLINE unsafeModify #-}++unsafeSwap :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> Int -> Int -> m ()+unsafeSwap = G.unsafeSwap+{-# INLINE unsafeSwap #-}++nextPermutation :: (PrimMonad m, Ord e, Unboxable e) => MVector (PrimState m) e -> m Bool+nextPermutation = G.nextPermutation+{-# INLINE nextPermutation #-}++set :: (PrimMonad m, Unboxable a) => MVector (PrimState m) a -> a -> m ()+set = G.set+{-# INLINE set #-}++copy :: (PrimMonad m, Unboxable a)+     => MVector (PrimState m) a   -- ^ target+     -> MVector (PrimState m) a   -- ^ source+     -> m ()+copy = G.copy+{-# INLINE copy #-}++move :: (PrimMonad m, Unboxable a)+     => MVector (PrimState m) a   -- ^ target+     -> MVector (PrimState m) a   -- ^ source+     -> m ()+move = G.move+{-# INLINE move #-}++unsafeCopy :: (PrimMonad m, Unboxable a)+           => MVector (PrimState m) a   -- ^ target+           -> MVector (PrimState m) a   -- ^ source+           -> m ()+unsafeCopy = G.unsafeCopy+{-# INLINE unsafeCopy #-}++unsafeMove :: (PrimMonad m, Unboxable a)+           => MVector (PrimState m) a   -- ^ target+           -> MVector (PrimState m) a   -- ^ source+           -> m ()+unsafeMove = G.unsafeMove+{-# INLINE unsafeMove #-}++zip :: (Unboxable a, Unboxable b) => MVector s a -> MVector s b -> MVector s (a, b)+zip = coerce UM.zip+{-# INLINE zip #-}++zip3 :: (Unboxable a, Unboxable b, Unboxable c) => MVector s a -> MVector s b -> MVector s c -> MVector s (a, b, c)+zip3 = coerce UM.zip3+{-# INLINE zip3 #-}++zip4 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d) => MVector s a -> MVector s b -> MVector s c -> MVector s d -> MVector s (a, b, c, d)+zip4 = coerce UM.zip4+{-# INLINE zip4 #-}++zip5 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e) => MVector s a -> MVector s b -> MVector s c -> MVector s d -> MVector s e -> MVector s (a, b, c, d, e)+zip5 = coerce UM.zip5+{-# INLINE zip5 #-}++zip6 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e, Unboxable f) => MVector s a -> MVector s b -> MVector s c -> MVector s d -> MVector s e -> MVector s f -> MVector s (a, b, c, d, e, f)+zip6 = coerce UM.zip6+{-# INLINE zip6 #-}++unzip :: (Unboxable a, Unboxable b) => MVector s (a, b) -> (MVector s a, MVector s b)+unzip = coerce UM.unzip+{-# INLINE unzip #-}++unzip3 :: (Unboxable a, Unboxable b, Unboxable c) => MVector s (a, b, c) -> (MVector s a, MVector s b, MVector s c)+unzip3 = coerce UM.unzip3+{-# INLINE unzip3 #-}++unzip4 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d) => MVector s (a, b, c, d) -> (MVector s a, MVector s b, MVector s c, MVector s d)+unzip4 = coerce UM.unzip4+{-# INLINE unzip4 #-}++unzip5 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e) => MVector s (a, b, c, d, e) -> (MVector s a, MVector s b, MVector s c, MVector s d, MVector s e)+unzip5 = coerce UM.unzip5+{-# INLINE unzip5 #-}++unzip6 :: (Unboxable a, Unboxable b, Unboxable c, Unboxable d, Unboxable e, Unboxable f) => MVector s (a, b, c, d, e, f) -> (MVector s a, MVector s b, MVector s c, MVector s d, MVector s e, MVector s f)+unzip6 = coerce UM.unzip6+{-# INLINE unzip6 #-}
+ test/Foo.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module Foo+  (Foo -- the constructor is not exported!+  ,mkFoo+  ) where+import Data.Vector.Unboxing (Unboxable(..))+import qualified Data.Vector.Unboxed as U+import qualified Data.Vector.Unboxed.Mutable as UM+import qualified Data.Vector.Generic as G+import qualified Data.Vector.Generic.Mutable as GM+import Control.DeepSeq (NFData)+import GHC.Generics+import Data.Coerce++newtype Foo = Foo Int deriving (Eq,Show,Generic)++instance NFData Foo++mkFoo :: Foo+mkFoo = Foo 42++-- Comparison of Data.Vector.Unboxing and Data.Vector.Unboxed:++-- The number of lines needed to enable 'Data.Vector.Unboxing.Vector Foo' is ...++instance Unboxable Foo where+  type Rep Foo = Int -- needs TypeFamilies here++-- ... only 2 lines!+-- Also, you can use GeneralizedNewtypeDeriving + UndecidableInstances if you want to write less.++-- On the other hand, the number of lines needed to enable 'Data.Vector.Unboxed.Vector Foo' is ...++newtype instance UM.MVector s Foo = MV_Foo (UM.MVector s Int)+newtype instance U.Vector Foo = V_Foo (U.Vector Int)++instance GM.MVector UM.MVector Foo where -- needs MultiParamTypeClasses here+  basicLength (MV_Foo mv) = GM.basicLength mv+  basicUnsafeSlice i l (MV_Foo mv) = MV_Foo (GM.basicUnsafeSlice i l mv)+  basicOverlaps (MV_Foo mv) (MV_Foo mv') = GM.basicOverlaps mv mv'+  basicUnsafeNew l = MV_Foo <$> GM.basicUnsafeNew l+  basicInitialize (MV_Foo mv) = GM.basicInitialize mv+  basicUnsafeReplicate i x = MV_Foo <$> GM.basicUnsafeReplicate i (coerce x)+  basicUnsafeRead (MV_Foo mv) i = coerce <$> GM.basicUnsafeRead mv i+  basicUnsafeWrite (MV_Foo mv) i x = GM.basicUnsafeWrite mv i (coerce x)+  basicClear (MV_Foo mv) = GM.basicClear mv+  basicSet (MV_Foo mv) x = GM.basicSet mv (coerce x)+  basicUnsafeCopy (MV_Foo mv) (MV_Foo mv') = GM.basicUnsafeCopy mv mv'+  basicUnsafeMove (MV_Foo mv) (MV_Foo mv') = GM.basicUnsafeMove mv mv'+  basicUnsafeGrow (MV_Foo mv) n = MV_Foo <$> GM.basicUnsafeGrow mv n++instance G.Vector U.Vector Foo where -- needs MultiParamTypeClasses here+  basicUnsafeFreeze (MV_Foo mv) = V_Foo <$> G.basicUnsafeFreeze mv+  basicUnsafeThaw (V_Foo v) = MV_Foo <$> G.basicUnsafeThaw v+  basicLength (V_Foo v) = G.basicLength v+  basicUnsafeSlice i l (V_Foo v) = V_Foo (G.basicUnsafeSlice i l v)+  basicUnsafeIndexM (V_Foo v) i = coerce <$> G.basicUnsafeIndexM v i+  basicUnsafeCopy (MV_Foo mv) (V_Foo v) = G.basicUnsafeCopy mv v+  elemseq (V_Foo v) x y = G.elemseq v (coerce x) y++instance U.Unbox Foo++-- ... enormous!+-- Unfortunately, you cannot use GeneralizedNewtypeDeriving to MVector/Vector classes.
+ test/Generic.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE UndecidableInstances #-}+module Generic where+import Test.HUnit+import qualified Data.Vector.Unboxing as V+import GHC.Generics+import Foo (Foo,mkFoo)++-- Deriving using Generic+data ComplexDouble = ComplexDouble { realPartD :: {-# UNPACK #-} !Double+                                   , imagPartD :: {-# UNPACK #-} !Double+                                   }+  deriving (Eq,Show,Generic)+  deriving V.Unboxable via V.Generics ComplexDouble++testComplexDouble = TestCase $ do+  let v :: V.Vector ComplexDouble+      v = V.singleton (ComplexDouble 1.0 2.0)+      x :: V.Vector Double+      x = V.map realPartD v+  assertEqual "construction" (ComplexDouble 1.0 2.0) (V.head v)+  assertEqual "map" (V.singleton 1.0) x++data Bar = Bar {-# UNPACK #-} !Foo {-# UNPACK #-} !Double+  deriving (Eq,Show,Generic)+  deriving V.Unboxable via V.Generics Bar++testBar = TestCase $ do+  let v :: V.Vector Bar+      v = V.singleton (Bar mkFoo 3.14)+  assertEqual "construction" (Bar mkFoo 3.14) (V.head v)+  assertEqual "map" (V.singleton mkFoo) (V.map (\(Bar foo _) -> foo) v)
+ test/Spec.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE UndecidableInstances #-}+import Prelude+import Test.HUnit+import qualified Data.Vector.Unboxing as V+import qualified Data.Vector.Unboxed+import Data.Monoid (Sum(..))+import Data.MonoTraversable (ofold)+---+import TestTypeErrors+import Foo (Foo,mkFoo)+import Generic++testInt = TestCase $ do+  let v = V.fromList [2,-5,42] :: V.Vector Int+      w = Data.Vector.Unboxed.fromList [2,-5,42] :: Data.Vector.Unboxed.Vector Int+  assertEqual "to unboxed" w (V.toUnboxedVector v)+  assertEqual "from unboxed" v (V.fromUnboxedVector w)++newtype IntMod17 = IntMod17 Int+  deriving (Eq,Show)+--  deriving newtype VF.Unboxable++instance V.Unboxable IntMod17 where+  type Rep IntMod17 = Int++instance Num IntMod17 where+  IntMod17 x + IntMod17 y = IntMod17 ((x + y) `rem` 17)+  IntMod17 x - IntMod17 y = IntMod17 ((x - y) `mod` 17)+  IntMod17 x * IntMod17 y = IntMod17 ((x * y) `rem` 17)+  negate (IntMod17 x) = IntMod17 (negate x `mod` 17)+  fromInteger x = IntMod17 (fromIntegral (x `mod` 17))+  abs = undefined; signum = undefined++testIntMod17 = TestCase $ do+  let v = V.fromList [-3,-2,-1,0,1,2,3,4,5] :: V.Vector IntMod17+  assertEqual "construction" (V.fromList [14,15,16,0,1,2,3,4,5]) v+  assertEqual "sum" 9 (V.sum v) -- not 60+  assertEqual "coercion" (V.fromList [14,15,16,0,1,2,3,4,5] :: V.Vector Int) (V.coerceVector v) -- this is possible because the constructor of IntMod17 is visible here+  let vSum = V.coerceVector v :: V.Vector (Sum IntMod17)+  assertEqual "coercion and sum" (Sum 9) (ofold vSum)++newtype Baz = Baz Foo+  deriving (Eq,Show,V.Unboxable)++testBaz = TestCase $ do+  let foo :: V.Vector Foo+      foo = V.singleton mkFoo+      baz :: V.Vector Baz+      baz = V.singleton (Baz mkFoo)+  assertEqual "construction" (Baz mkFoo) (V.head baz)+  assertEqual "map 1" baz (V.map Baz foo)+  assertEqual "map 2" foo (V.map (\(Baz x) -> x) baz)+  assertEqual "coercion" baz (V.coerceVector foo)++-- We can make an unboxed vector of Foo, even though we don't have 'Coercible Int Foo' in scope.+testAbstractType = TestCase $ do+  let v = V.singleton mkFoo :: V.Vector Foo+  assertEqual "Foo" mkFoo (V.head v)+  assertEqual "coercion" mkFoo (getSum $ V.head (V.coerceVector v :: V.Vector (Sum Foo)))++tests = TestList [TestLabel "Basic features" testIntMod17+                 ,TestLabel "Conversion with Data.Vector.Unboxed" testInt+                 ,TestLabel "Test with abstract type" testAbstractType+                 ,TestLabel "Check for type errors" testTypeErrors+                 ,TestLabel "Test with generic 1" testComplexDouble+                 ,TestLabel "Test with generic 2" testBar+                 ,TestLabel "Test with GND" testBaz+                 ]++main = runTestTT tests+
+ test/TestTypeErrors.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fdefer-type-errors -Wno-deferred-type-errors #-}+module TestTypeErrors where+import Test.HUnit+import Test.ShouldNotTypecheck+import Data.Coerce+import qualified Data.Vector.Unboxing as V+import Foo (Foo)+import GHC.Generics++-- Since the module Foo does not export Foo's constructor,+-- it should be impossible to create a value of Foo in this module.++-- 'intToFoo1' should not compile because the constructor of 'Foo' is not visible.+intToFoo1 :: Int -> Foo+intToFoo1 x = coerce x++-- 'intToFoo2' should not compile because 'coerceVector' requires the constructor to be visible.+-- This one does compile if 'coerceVector' is defined as+-- > coerceVector :: ({- Coercible a b, -} Rep a ~ Rep b) => Vector a -> Vector b+intToFoo2 :: Int -> Foo+intToFoo2 x = V.head (V.coerceVector (V.singleton x))++-- 'intToFoo3' should not compile because the constructor of Foo is not visible.+-- This one does compile if 'Unboxable' is defined as+-- > class (U.Unbox (Rep a), Coercible a (Rep a)) => Unboxable a+intToFoo3 :: (V.Unboxable a, a ~ Foo) => Int -> a+intToFoo3 x = coerce x++data Animal = Dog | Cat+  deriving (Eq,Show,Generic)+  deriving V.Unboxable via V.Generics Animal++testTypeErrors :: Test+testTypeErrors = TestList [TestLabel "Basic test for coerce" $ TestCase $ shouldNotTypecheck (intToFoo1 0xDEAD)+                          ,TestLabel "Test for coerceVector" $ TestCase $ shouldNotTypecheck (intToFoo2 0xDEAD)+                          ,TestLabel "Test for Unboxable" $ TestCase $ shouldNotTypecheck (intToFoo3 0xDEAD)+                          ,TestLabel "Test generic deriving for a sum type" $ TestCase $ shouldNotTypecheck (V.singleton Dog)+                          ]+
+ unboxing-vector.cabal view
@@ -0,0 +1,85 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.31.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: 6f43e3e12c9aa312cf1e18e1bc60132a5cb9878c463bd2b9863a20ea6c7125cf++name:           unboxing-vector+version:        0.1.0.0+synopsis:       Newtype-friendly Unboxed Vectors+description:    Please see the README on GitHub at <https://github.com/minoki/unboxing-vector#readme>+category:       Data, Data Structures+homepage:       https://github.com/minoki/unboxing-vector#readme+bug-reports:    https://github.com/minoki/unboxing-vector/issues+author:         ARATA Mizuki <minorinoki@gmail.com>+maintainer:     ARATA Mizuki <minorinoki@gmail.com>+copyright:      2019 ARATA Mizuki+license:        BSD3+license-file:   LICENSE+build-type:     Simple+extra-source-files:+    README.md+    ChangeLog.md++source-repository head+  type: git+  location: https://github.com/minoki/unboxing-vector++library+  exposed-modules:+      Data.Vector.Unboxing+      Data.Vector.Unboxing.Mutable+  other-modules:+      Data.Vector.Unboxing.Internal+  hs-source-dirs:+      src+  ghc-options: -Wall+  build-depends:+      base >=4.9 && <5+    , deepseq+    , mono-traversable+    , primitive+    , vector+  default-language: Haskell2010++test-suite unboxing-vector-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Foo+      Generic+      TestTypeErrors+      Paths_unboxing_vector+  hs-source-dirs:+      test+  ghc-options: -Wall -Wno-missing-signatures+  build-depends:+      HUnit+    , base >=4.9 && <5+    , deepseq+    , mono-traversable+    , primitive+    , should-not-typecheck+    , unboxing-vector+    , vector+  default-language: Haskell2010++benchmark unboxing-vector-benchmark+  type: exitcode-stdio-1.0+  main-is: Bench.hs+  other-modules:+      Poly+      Paths_unboxing_vector+  hs-source-dirs:+      benchmark+  ghc-options: -Wall -rtsopts+  build-depends:+      base >=4.9 && <5+    , deepseq+    , mono-traversable+    , primitive+    , unboxing-vector+    , vector+  default-language: Haskell2010