diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4fcc0adc..1acb224f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: name: Cache ~/.cabal/store with: path: ${{ steps.setup-haskell-cabal.outputs.cabal-store }} - key: ${{ runner.os }}-${{ matrix.ghc }}-CACHE_V4 + key: ${{ runner.os }}-${{ matrix.ghc }}-CACHE_V5 # ---------------- - name: "Install PAPI" run: | diff --git a/vector/src/Data/Vector.hs b/vector/src/Data/Vector.hs index 6c373bba..a653df68 100644 --- a/vector/src/Data/Vector.hs +++ b/vector/src/Data/Vector.hs @@ -4,7 +4,6 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-} - -- | -- Module : Data.Vector -- Copyright : (c) Roman Leshchinskiy 2008-2010 @@ -17,7 +16,7 @@ -- Stability : experimental -- Portability : non-portable -- --- A library for boxed vectors (that is, polymorphic arrays capable of +-- A library for lazy boxed vectors (that is, polymorphic arrays capable of -- holding any Haskell value). The vectors come in two flavours: -- -- * mutable @@ -179,275 +178,21 @@ module Data.Vector ( ) where import Control.Applicative (Applicative) -import Data.Vector.Mutable ( MVector(..) ) -import Data.Primitive.Array -import qualified Data.Vector.Fusion.Bundle as Bundle +import Data.Vector.Mutable.Unsafe ( MVector ) +import Data.Vector.Unsafe import qualified Data.Vector.Generic as G -import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf)) - -import Control.Monad ( MonadPlus(..), liftM, ap ) -import Control.Monad.ST ( ST, runST ) +import Control.Monad.ST ( ST ) import Control.Monad.Primitive -import qualified Control.Monad.Fail as Fail -import Control.Monad.Fix ( MonadFix (mfix) ) -import Control.Monad.Zip -import Data.Function ( fix ) import Prelude - ( Eq, Ord, Num, Enum, Monoid, Functor, Monad, Show, Bool, Ordering(..), Int, Maybe, Either - , compare, mempty, mappend, mconcat, return, showsPrec, fmap, otherwise, id, flip, const - , (>>=), (+), (-), (<), (<=), (>), (>=), (==), (/=), (&&), (.), ($) ) + ( Eq, Ord, Num, Enum, Monoid, Monad, Bool, Ordering(..), Int, Maybe, Either + , id, (==)) -import Data.Functor.Classes (Eq1 (..), Ord1 (..), Read1 (..), Show1 (..)) -import Data.Data ( Data(..) ) -import Text.Read ( Read(..), readListPrecDefault ) -import Data.Semigroup ( Semigroup(..) ) -import qualified Control.Applicative as Applicative -import qualified Data.Foldable as Foldable import qualified Data.Traversable as Traversable -import qualified GHC.Exts as Exts (IsList(..)) - - --- | Boxed vectors, supporting efficient slicing. -data Vector a = Vector {-# UNPACK #-} !Int - {-# UNPACK #-} !Int - {-# UNPACK #-} !(Array a) - -instance NFData a => NFData (Vector a) where - rnf = liftRnf rnf - {-# INLINEABLE rnf #-} - --- | @since 0.12.1.0 -instance NFData1 Vector where - liftRnf elemRnf = foldl' (\_ -> elemRnf) () - {-# INLINEABLE liftRnf #-} - -instance Show a => Show (Vector a) where - showsPrec = G.showsPrec - -instance Read a => Read (Vector a) where - readPrec = G.readPrec - readListPrec = readListPrecDefault - -instance Show1 Vector where - liftShowsPrec = G.liftShowsPrec - -instance Read1 Vector where - liftReadsPrec = G.liftReadsPrec - -instance Exts.IsList (Vector a) where - type Item (Vector a) = a - fromList = Data.Vector.fromList - fromListN = Data.Vector.fromListN - toList = toList - -instance Data a => Data (Vector a) where - gfoldl = G.gfoldl - toConstr _ = G.mkVecConstr "Data.Vector.Vector" - gunfold = G.gunfold - dataTypeOf _ = G.mkVecType "Data.Vector.Vector" - dataCast1 = G.dataCast - -type instance G.Mutable Vector = MVector - -instance G.Vector Vector a where - {-# INLINE basicUnsafeFreeze #-} - basicUnsafeFreeze (MVector i n marr) - = Vector i n `liftM` unsafeFreezeArray marr - - {-# INLINE basicUnsafeThaw #-} - basicUnsafeThaw (Vector i n arr) - = MVector i n `liftM` unsafeThawArray arr - - {-# INLINE basicLength #-} - basicLength (Vector _ n _) = n - - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice j n (Vector i _ arr) = Vector (i+j) n arr - - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM (Vector i _ arr) j = indexArrayM arr (i+j) - - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MVector i n dst) (Vector j _ src) - = copyArray dst i src j n - --- See http://trac.haskell.org/vector/ticket/12 -instance Eq a => Eq (Vector a) where - {-# INLINE (==) #-} - xs == ys = Bundle.eq (G.stream xs) (G.stream ys) - --- See http://trac.haskell.org/vector/ticket/12 -instance Ord a => Ord (Vector a) where - {-# INLINE compare #-} - compare xs ys = Bundle.cmp (G.stream xs) (G.stream ys) - - {-# INLINE (<) #-} - xs < ys = Bundle.cmp (G.stream xs) (G.stream ys) == LT - - {-# INLINE (<=) #-} - xs <= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= GT - - {-# INLINE (>) #-} - xs > ys = Bundle.cmp (G.stream xs) (G.stream ys) == GT - - {-# INLINE (>=) #-} - xs >= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= LT - -instance Eq1 Vector where - {-# INLINE liftEq #-} - liftEq = eqBy - -instance Ord1 Vector where - {-# INLINE liftCompare #-} - liftCompare = cmpBy - -instance Semigroup (Vector a) where - {-# INLINE (<>) #-} - (<>) = (++) - - {-# INLINE sconcat #-} - sconcat = G.concatNE - -instance Monoid (Vector a) where - {-# INLINE mempty #-} - mempty = empty - - {-# INLINE mappend #-} - mappend = (<>) - - {-# INLINE mconcat #-} - mconcat = concat - -instance Functor Vector where - {-# INLINE fmap #-} - fmap = map - - {-# INLINE (<$) #-} - (<$) = map . const - -instance Monad Vector where - {-# INLINE return #-} - return = Applicative.pure - - {-# INLINE (>>=) #-} - (>>=) = flip concatMap - --- | @since 0.12.1.0 -instance Fail.MonadFail Vector where - {-# INLINE fail #-} - fail _ = empty - -instance MonadPlus Vector where - {-# INLINE mzero #-} - mzero = empty - - {-# INLINE mplus #-} - mplus = (++) - -instance MonadZip Vector where - {-# INLINE mzip #-} - mzip = zip - - {-# INLINE mzipWith #-} - mzipWith = zipWith - {-# INLINE munzip #-} - munzip = unzip - --- | This instance has the same semantics as the one for lists. --- --- @since 0.12.2.0 -instance MonadFix Vector where - -- We take care to dispose of v0 as soon as possible (see headM docs). - -- - -- It's perfectly safe to use non-monadic indexing within generate - -- call since intermediate vector won't be created until result's - -- value is demanded. - {-# INLINE mfix #-} - mfix f - | null v0 = empty - -- We take first element of resulting vector from v0 and create - -- rest using generate. Note that cons should fuse with generate - | otherwise = runST $ do - h <- headM v0 - return $ cons h $ - generate (lv0 - 1) $ - \i -> fix (\a -> f a ! (i + 1)) - where - -- Used to calculate size of resulting vector - v0 = fix (f . head) - !lv0 = length v0 - -instance Applicative.Applicative Vector where - {-# INLINE pure #-} - pure = singleton - - {-# INLINE (<*>) #-} - (<*>) = ap - -instance Applicative.Alternative Vector where - {-# INLINE empty #-} - empty = empty - - {-# INLINE (<|>) #-} - (<|>) = (++) - -instance Foldable.Foldable Vector where - {-# INLINE foldr #-} - foldr = foldr - - {-# INLINE foldl #-} - foldl = foldl - - {-# INLINE foldr1 #-} - foldr1 = foldr1 - - {-# INLINE foldl1 #-} - foldl1 = foldl1 - - {-# INLINE foldr' #-} - foldr' = foldr' - - {-# INLINE foldl' #-} - foldl' = foldl' - - {-# INLINE toList #-} - toList = toList - - {-# INLINE length #-} - length = length - - {-# INLINE null #-} - null = null - - {-# INLINE elem #-} - elem = elem - - {-# INLINE maximum #-} - maximum = maximum - - {-# INLINE minimum #-} - minimum = minimum - - {-# INLINE sum #-} - sum = sum - - {-# INLINE product #-} - product = product - -instance Traversable.Traversable Vector where - {-# INLINE traverse #-} - traverse = traverse - - {-# INLINE mapM #-} - mapM = mapM - - {-# INLINE sequence #-} - sequence = sequence -- Length information -- ------------------ @@ -2281,52 +2026,6 @@ iforA_ :: (Applicative f) iforA_ = G.iforA_ --- Conversions - Arrays --- ----------------------------- - --- | /O(1)/ Convert an array to a vector. --- --- @since 0.12.2.0 -fromArray :: Array a -> Vector a -{-# INLINE fromArray #-} -fromArray arr = Vector 0 (sizeofArray arr) arr - --- | /O(n)/ Convert a vector to an array. --- --- @since 0.12.2.0 -toArray :: Vector a -> Array a -{-# INLINE toArray #-} -toArray (Vector offset len arr) - | offset == 0 && len == sizeofArray arr = arr - | otherwise = cloneArray arr offset len - --- | /O(1)/ Extract the underlying `Array`, offset where vector starts and the --- total number of elements in the vector. Below property always holds: --- --- > let (array, offset, len) = toArraySlice v --- > v === unsafeFromArraySlice len offset array --- --- @since 0.13.0.0 -toArraySlice :: Vector a -> (Array a, Int, Int) -{-# INLINE toArraySlice #-} -toArraySlice (Vector offset len arr) = (arr, offset, len) - - --- | /O(1)/ Convert an array slice to a vector. This function is very unsafe, --- because constructing an invalid vector can yield almost all other safe --- functions in this module unsafe. These are equivalent: --- --- > unsafeFromArraySlice len offset === unsafeTake len . unsafeDrop offset . fromArray --- --- @since 0.13.0.0 -unsafeFromArraySlice :: - Array a -- ^ Immutable boxed array. - -> Int -- ^ Offset - -> Int -- ^ Length - -> Vector a -{-# INLINE unsafeFromArraySlice #-} -unsafeFromArraySlice arr offset len = Vector offset len arr - -- Conversions - Mutable vectors -- ----------------------------- @@ -2389,4 +2088,4 @@ copy = G.copy -- $setup -- >>> :set -Wno-type-defaults --- >>> import Prelude (Char, String, Bool(True, False), min, max, fst, even, undefined, Ord(..)) +-- >>> import Prelude (Char, String, Bool(True, False), min, max, fst, even, undefined, Ord(..), ($), (<>), Num(..)) diff --git a/vector/src/Data/Vector/Mutable.hs b/vector/src/Data/Vector/Mutable.hs index 82a60c67..9ec9263b 100644 --- a/vector/src/Data/Vector/Mutable.hs +++ b/vector/src/Data/Vector/Mutable.hs @@ -4,6 +4,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE PatternSynonyms #-} -- | -- Module : Data.Vector.Mutable -- Copyright : (c) Roman Leshchinskiy 2008-2010 @@ -20,7 +21,8 @@ module Data.Vector.Mutable ( -- * Mutable boxed vectors - MVector(MVector), IOVector, STVector, + MVector, IOVector, STVector, + pattern MVector, -- * Accessors @@ -71,149 +73,21 @@ module Data.Vector.Mutable ( PrimMonad, PrimState, RealWorld ) where -import Control.Monad (when, liftM) -import Control.Monad.ST (ST) import qualified Data.Vector.Generic.Mutable as G -import Data.Vector.Internal.Check +import Data.Vector.Mutable.Unsafe (MVector,IOVector,STVector,toMutableArray,fromMutableArray) +import qualified Data.Vector.Mutable.Unsafe as U import Data.Primitive.Array import Control.Monad.Primitive -import Prelude - ( Ord, Monad, Bool, Ordering(..), Int, Maybe - , compare, return, otherwise, error - , (>>=), (+), (-), (*), (<), (>), (>=), (&&), (||), ($), (>>) ) +import Prelude( Ord, Bool, Ordering(..), Int, Maybe ) #include "vector.h" -type role MVector nominal representational - --- | Mutable boxed vectors keyed on the monad they live in ('IO' or @'ST' s@). -data MVector s a = MVector { _offset :: {-# UNPACK #-} !Int - -- ^ Offset in underlying array - , _size :: {-# UNPACK #-} !Int - -- ^ Size of slice - , _array :: {-# UNPACK #-} !(MutableArray s a) - -- ^ Underlying array - } - -type IOVector = MVector RealWorld -type STVector s = MVector s - --- NOTE: This seems unsafe, see http://trac.haskell.org/vector/ticket/54 -{- -instance NFData a => NFData (MVector s a) where - rnf (MVector i n arr) = unsafeInlineST $ force i - where - force !ix | ix < n = do x <- readArray arr ix - rnf x `seq` force (ix+1) - | otherwise = return () --} - -instance G.MVector MVector a where - {-# INLINE basicLength #-} - basicLength (MVector _ n _) = n - - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice j m (MVector i _ arr) = MVector (i+j) m arr - - {-# INLINE basicOverlaps #-} - basicOverlaps (MVector i m arr1) (MVector j n arr2) - = sameMutableArray arr1 arr2 - && (between i j (j+n) || between j i (i+m)) - where - between x y z = x >= y && x < z - - {-# INLINE basicUnsafeNew #-} - basicUnsafeNew n - = do - arr <- newArray n uninitialised - return (MVector 0 n arr) - - {-# INLINE basicInitialize #-} - -- initialization is unnecessary for boxed vectors - basicInitialize _ = return () - - {-# INLINE basicUnsafeReplicate #-} - basicUnsafeReplicate n x - = do - arr <- newArray n x - return (MVector 0 n arr) - - {-# INLINE basicUnsafeRead #-} - basicUnsafeRead (MVector i _ arr) j = readArray arr (i+j) - - {-# INLINE basicUnsafeWrite #-} - basicUnsafeWrite (MVector i _ arr) j x = writeArray arr (i+j) x - - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MVector i n dst) (MVector j _ src) - = copyMutableArray dst i src j n - - basicUnsafeMove dst@(MVector iDst n arrDst) src@(MVector iSrc _ arrSrc) - = case n of - 0 -> return () - 1 -> readArray arrSrc iSrc >>= writeArray arrDst iDst - 2 -> do - x <- readArray arrSrc iSrc - y <- readArray arrSrc (iSrc + 1) - writeArray arrDst iDst x - writeArray arrDst (iDst + 1) y - _ - | overlaps dst src - -> case compare iDst iSrc of - LT -> moveBackwards arrDst iDst iSrc n - EQ -> return () - GT | (iDst - iSrc) * 2 < n - -> moveForwardsLargeOverlap arrDst iDst iSrc n - | otherwise - -> moveForwardsSmallOverlap arrDst iDst iSrc n - | otherwise -> G.basicUnsafeCopy dst src - - {-# INLINE basicClear #-} - basicClear v = G.set v uninitialised - -{-# INLINE moveBackwards #-} -moveBackwards :: MutableArray s a -> Int -> Int -> Int -> ST s () -moveBackwards !arr !dstOff !srcOff !len = - check Internal "not a backwards move" (dstOff < srcOff) - $ loopM len $ \ i -> readArray arr (srcOff + i) >>= writeArray arr (dstOff + i) - -{-# INLINE moveForwardsSmallOverlap #-} --- Performs a move when dstOff > srcOff, optimized for when the overlap of the intervals is small. -moveForwardsSmallOverlap :: MutableArray s a -> Int -> Int -> Int -> ST s () -moveForwardsSmallOverlap !arr !dstOff !srcOff !len = - check Internal "not a forward move" (dstOff > srcOff) - $ do - tmp <- newArray overlap uninitialised - loopM overlap $ \ i -> readArray arr (dstOff + i) >>= writeArray tmp i - loopM nonOverlap $ \ i -> readArray arr (srcOff + i) >>= writeArray arr (dstOff + i) - loopM overlap $ \ i -> readArray tmp i >>= writeArray arr (dstOff + nonOverlap + i) - where nonOverlap = dstOff - srcOff; overlap = len - nonOverlap - --- Performs a move when dstOff > srcOff, optimized for when the overlap of the intervals is large. -moveForwardsLargeOverlap :: MutableArray s a -> Int -> Int -> Int -> ST s () -moveForwardsLargeOverlap !arr !dstOff !srcOff !len = - check Internal "not a forward move" (dstOff > srcOff) - $ do - queue <- newArray nonOverlap uninitialised - loopM nonOverlap $ \ i -> readArray arr (srcOff + i) >>= writeArray queue i - let mov !i !qTop = when (i < dstOff + len) $ do - x <- readArray arr i - y <- readArray queue qTop - writeArray arr i y - writeArray queue qTop x - mov (i+1) (if qTop + 1 >= nonOverlap then 0 else qTop + 1) - mov dstOff 0 - where nonOverlap = dstOff - srcOff - -{-# INLINE loopM #-} -loopM :: Monad m => Int -> (Int -> m a) -> m () -loopM !n k = let - go i = when (i < n) (k i >> go (i+1)) - in go 0 - -uninitialised :: a -uninitialised = error "Data.Vector.Mutable: uninitialised element. If you are trying to compact a vector, use the 'Data.Vector.force' function to remove uninitialised elements from the underlying array." +pattern MVector :: Int -> Int -> MutableArray s a -> MVector s a +pattern MVector i j arr = U.MVector i j arr +{-# COMPLETE MVector #-} +{-# DEPRECATED MVector "Use MVector exported from \"Data.Vector.Mutable.Unsafe\"" #-} + -- Length information -- ------------------ @@ -787,24 +661,5 @@ ifoldrM' :: (PrimMonad m) => (Int -> a -> b -> m b) -> b -> MVector (PrimState m {-# INLINE ifoldrM' #-} ifoldrM' = G.ifoldrM' --- Conversions - Arrays --- ----------------------------- - --- | /O(n)/ Make a copy of a mutable array to a new mutable vector. --- --- @since 0.12.2.0 -fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (PrimState m) a) -{-# INLINE fromMutableArray #-} -fromMutableArray marr = - let size = sizeofMutableArray marr - in MVector 0 size `liftM` cloneMutableArray marr 0 size - --- | /O(n)/ Make a copy of a mutable vector into a new mutable array. --- --- @since 0.12.2.0 -toMutableArray :: PrimMonad m => MVector (PrimState m) a -> m (MutableArray (PrimState m) a) -{-# INLINE toMutableArray #-} -toMutableArray (MVector offset size marr) = cloneMutableArray marr offset size - -- $setup --- >>> import Prelude (Integer) +-- >>> import Prelude (Integer,Num(..),($)) diff --git a/vector/src/Data/Vector/Mutable/Unsafe.hs b/vector/src/Data/Vector/Mutable/Unsafe.hs new file mode 100644 index 00000000..1e777d98 --- /dev/null +++ b/vector/src/Data/Vector/Mutable/Unsafe.hs @@ -0,0 +1,187 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE RoleAnnotations #-} +{-# LANGUAGE TypeFamilies #-} +-- | +-- This module exposes internal representation of mutable lazy boxed +-- vector and functions that work on that representation directly (as +-- opposed to using 'G.MVector' API. +-- +-- Note that working with internal representation of vector is +-- generally unsafe and may violate memory safety +module Data.Vector.Mutable.Unsafe + ( MVector(..) + , IOVector + , STVector + -- * Array conversions + , toMutableArray + , fromMutableArray + ) where + +import Control.Monad (when, liftM) +import Control.Monad.ST (ST) +import qualified Data.Vector.Generic.Mutable as G +import Data.Vector.Internal.Check +import Data.Primitive.Array +import Control.Monad.Primitive + +import Prelude + ( Monad, Ordering(..), Int + , compare, return, otherwise, error + , (>>=), (+), (-), (*), (<), (>), (>=), (&&), (||), ($), (>>) ) + +#include "vector.h" + +type role MVector nominal representational + +-- | Mutable boxed vectors keyed on the monad they live in ('IO' or @'ST' s@). +data MVector s a = MVector { _offset :: {-# UNPACK #-} !Int + -- ^ Offset in underlying array + , _size :: {-# UNPACK #-} !Int + -- ^ Size of slice + , _array :: {-# UNPACK #-} !(MutableArray s a) + -- ^ Underlying array + } + +type IOVector = MVector RealWorld +type STVector s = MVector s + + +-- NOTE: This seems unsafe, see http://trac.haskell.org/vector/ticket/54 +{- +instance NFData a => NFData (MVector s a) where + rnf (MVector i n arr) = unsafeInlineST $ force i + where + force !ix | ix < n = do x <- readArray arr ix + rnf x `seq` force (ix+1) + | otherwise = return () +-} + +instance G.MVector MVector a where + {-# INLINE basicLength #-} + basicLength (MVector _ n _) = n + + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice j m (MVector i _ arr) = MVector (i+j) m arr + + {-# INLINE basicOverlaps #-} + basicOverlaps (MVector i m arr1) (MVector j n arr2) + = sameMutableArray arr1 arr2 + && (between i j (j+n) || between j i (i+m)) + where + between x y z = x >= y && x < z + + {-# INLINE basicUnsafeNew #-} + basicUnsafeNew n + = do + arr <- newArray n uninitialised + return (MVector 0 n arr) + + {-# INLINE basicInitialize #-} + -- initialization is unnecessary for boxed vectors + basicInitialize _ = return () + + {-# INLINE basicUnsafeReplicate #-} + basicUnsafeReplicate n x + = do + arr <- newArray n x + return (MVector 0 n arr) + + {-# INLINE basicUnsafeRead #-} + basicUnsafeRead (MVector i _ arr) j = readArray arr (i+j) + + {-# INLINE basicUnsafeWrite #-} + basicUnsafeWrite (MVector i _ arr) j x = writeArray arr (i+j) x + + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MVector i n dst) (MVector j _ src) + = copyMutableArray dst i src j n + + basicUnsafeMove dst@(MVector iDst n arrDst) src@(MVector iSrc _ arrSrc) + = case n of + 0 -> return () + 1 -> readArray arrSrc iSrc >>= writeArray arrDst iDst + 2 -> do + x <- readArray arrSrc iSrc + y <- readArray arrSrc (iSrc + 1) + writeArray arrDst iDst x + writeArray arrDst (iDst + 1) y + _ + | G.overlaps dst src + -> case compare iDst iSrc of + LT -> moveBackwards arrDst iDst iSrc n + EQ -> return () + GT | (iDst - iSrc) * 2 < n + -> moveForwardsLargeOverlap arrDst iDst iSrc n + | otherwise + -> moveForwardsSmallOverlap arrDst iDst iSrc n + | otherwise -> G.basicUnsafeCopy dst src + + {-# INLINE basicClear #-} + basicClear v = G.set v uninitialised + + +{-# INLINE moveBackwards #-} +moveBackwards :: MutableArray s a -> Int -> Int -> Int -> ST s () +moveBackwards !arr !dstOff !srcOff !len = + check Internal "not a backwards move" (dstOff < srcOff) + $ loopM len $ \ i -> readArray arr (srcOff + i) >>= writeArray arr (dstOff + i) + +{-# INLINE moveForwardsSmallOverlap #-} +-- Performs a move when dstOff > srcOff, optimized for when the overlap of the intervals is small. +moveForwardsSmallOverlap :: MutableArray s a -> Int -> Int -> Int -> ST s () +moveForwardsSmallOverlap !arr !dstOff !srcOff !len = + check Internal "not a forward move" (dstOff > srcOff) + $ do + tmp <- newArray overlap uninitialised + loopM overlap $ \ i -> readArray arr (dstOff + i) >>= writeArray tmp i + loopM nonOverlap $ \ i -> readArray arr (srcOff + i) >>= writeArray arr (dstOff + i) + loopM overlap $ \ i -> readArray tmp i >>= writeArray arr (dstOff + nonOverlap + i) + where nonOverlap = dstOff - srcOff; overlap = len - nonOverlap + +-- Performs a move when dstOff > srcOff, optimized for when the overlap of the intervals is large. +moveForwardsLargeOverlap :: MutableArray s a -> Int -> Int -> Int -> ST s () +moveForwardsLargeOverlap !arr !dstOff !srcOff !len = + check Internal "not a forward move" (dstOff > srcOff) + $ do + queue <- newArray nonOverlap uninitialised + loopM nonOverlap $ \ i -> readArray arr (srcOff + i) >>= writeArray queue i + let mov !i !qTop = when (i < dstOff + len) $ do + x <- readArray arr i + y <- readArray queue qTop + writeArray arr i y + writeArray queue qTop x + mov (i+1) (if qTop + 1 >= nonOverlap then 0 else qTop + 1) + mov dstOff 0 + where nonOverlap = dstOff - srcOff + +{-# INLINE loopM #-} +loopM :: Monad m => Int -> (Int -> m a) -> m () +loopM !n k = let + go i = when (i < n) (k i >> go (i+1)) + in go 0 + +uninitialised :: a +uninitialised = error "Data.Vector.Mutable: uninitialised element. If you are trying to compact a vector, use the 'Data.Vector.force' function to remove uninitialised elements from the underlying array." + + +-- Conversions - Arrays +-- ----------------------------- + +-- | /O(n)/ Make a copy of a mutable array to a new mutable vector. +-- +-- @since 0.12.2.0 +fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (PrimState m) a) +{-# INLINE fromMutableArray #-} +fromMutableArray marr = + let size = sizeofMutableArray marr + in MVector 0 size `liftM` cloneMutableArray marr 0 size + +-- | /O(n)/ Make a copy of a mutable vector into a new mutable array. +-- +-- @since 0.12.2.0 +toMutableArray :: PrimMonad m => MVector (PrimState m) a -> m (MutableArray (PrimState m) a) +{-# INLINE toMutableArray #-} +toMutableArray (MVector offset size marr) = cloneMutableArray marr offset size diff --git a/vector/src/Data/Vector/Primitive.hs b/vector/src/Data/Vector/Primitive.hs index dade073f..2055ff6c 100644 --- a/vector/src/Data/Vector/Primitive.hs +++ b/vector/src/Data/Vector/Primitive.hs @@ -5,6 +5,7 @@ {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE PatternSynonyms #-} -- | -- Module : Data.Vector.Primitive -- Copyright : (c) Roman Leshchinskiy 2008-2010 @@ -24,7 +25,7 @@ module Data.Vector.Primitive ( -- * Primitive vectors - Vector(..), MVector(..), + Vector, MVector(MVector), pattern Vector, -- * Accessors @@ -163,145 +164,24 @@ module Data.Vector.Primitive ( import Control.Applicative (Applicative) import qualified Data.Vector.Generic as G -import Data.Vector.Primitive.Mutable ( MVector(..) ) -import Data.Vector.Internal.Check -import qualified Data.Vector.Fusion.Bundle as Bundle +import Data.Vector.Primitive.Unsafe (Vector,unsafeCoerceVector,unsafeCast) +import qualified Data.Vector.Primitive.Unsafe as U +import Data.Vector.Primitive.Mutable.Unsafe (MVector) +import Data.Vector.Primitive.Mutable (pattern MVector) +import Data.Primitive ( Prim ) import Data.Primitive.ByteArray -import Data.Primitive ( Prim, sizeOf ) -import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf)) - -import Control.Monad ( liftM ) import Control.Monad.ST ( ST ) import Control.Monad.Primitive import Prelude - ( Eq, Ord, Num, Enum, Monoid, Traversable, Monad, Read, Show, Bool, Ordering(..), Int, Maybe, Either - , compare, mempty, mappend, mconcat, showsPrec, return, otherwise, seq, error, undefined - , (+), (*), (<), (<=), (>), (>=), (==), (/=), ($!) ) - -import Data.Data ( Data(..) ) -import Text.Read ( Read(..), readListPrecDefault ) -import Data.Semigroup ( Semigroup(..) ) - -import Data.Coerce -import Unsafe.Coerce -import qualified GHC.Exts as Exts - -type role Vector nominal - --- | /O(1)/ Unsafely coerce an immutable vector from one element type to another, --- representationally equal type. The operation just changes the type of the --- underlying pointer and does not modify the elements. --- --- This is marginally safer than 'unsafeCast', since this function imposes an --- extra 'Coercible' constraint. The constraint guarantees that the element types --- are representationally equal. It however cannot guarantee --- that their respective 'Prim' instances are compatible. -unsafeCoerceVector :: Coercible a b => Vector a -> Vector b -unsafeCoerceVector = unsafeCoerce - --- | Unboxed vectors of primitive types. -data Vector a = Vector {-# UNPACK #-} !Int -- ^ offset - {-# UNPACK #-} !Int -- ^ length - {-# UNPACK #-} !ByteArray -- ^ underlying byte array - -instance NFData (Vector a) where - rnf (Vector _ _ _) = () - --- | @since 0.12.1.0 -instance NFData1 Vector where - liftRnf _ (Vector _ _ _) = () - -instance (Show a, Prim a) => Show (Vector a) where - showsPrec = G.showsPrec - -instance (Read a, Prim a) => Read (Vector a) where - readPrec = G.readPrec - readListPrec = readListPrecDefault - -instance (Data a, Prim a) => Data (Vector a) where - gfoldl = G.gfoldl - toConstr _ = G.mkVecConstr "Data.Vector.Primitive.Vector" - gunfold = G.gunfold - dataTypeOf _ = G.mkVecType "Data.Vector.Primitive.Vector" - dataCast1 = G.dataCast - - -type instance G.Mutable Vector = MVector - -instance Prim a => G.Vector Vector a where - {-# INLINE basicUnsafeFreeze #-} - basicUnsafeFreeze (MVector i n marr) - = Vector i n `liftM` unsafeFreezeByteArray marr - - {-# INLINE basicUnsafeThaw #-} - basicUnsafeThaw (Vector i n arr) - = MVector i n `liftM` unsafeThawByteArray arr - - {-# INLINE basicLength #-} - basicLength (Vector _ n _) = n - - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice j n (Vector i _ arr) = Vector (i+j) n arr - - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM (Vector i _ arr) j = return $! indexByteArray arr (i+j) - - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MVector i n dst) (Vector j _ src) - = copyByteArray dst (i*sz) src (j*sz) (n*sz) - where - sz = sizeOf (undefined :: a) - - {-# INLINE elemseq #-} - elemseq _ = seq - --- See http://trac.haskell.org/vector/ticket/12 -instance (Prim a, Eq a) => Eq (Vector a) where - {-# INLINE (==) #-} - xs == ys = Bundle.eq (G.stream xs) (G.stream ys) - --- See http://trac.haskell.org/vector/ticket/12 -instance (Prim a, Ord a) => Ord (Vector a) where - {-# INLINE compare #-} - compare xs ys = Bundle.cmp (G.stream xs) (G.stream ys) - - {-# INLINE (<) #-} - xs < ys = Bundle.cmp (G.stream xs) (G.stream ys) == LT - - {-# INLINE (<=) #-} - xs <= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= GT - - {-# INLINE (>) #-} - xs > ys = Bundle.cmp (G.stream xs) (G.stream ys) == GT - - {-# INLINE (>=) #-} - xs >= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= LT - -instance Prim a => Semigroup (Vector a) where - {-# INLINE (<>) #-} - (<>) = (++) - - {-# INLINE sconcat #-} - sconcat = G.concatNE - -instance Prim a => Monoid (Vector a) where - {-# INLINE mempty #-} - mempty = empty - - {-# INLINE mappend #-} - mappend = (<>) - - {-# INLINE mconcat #-} - mconcat = concat - -instance Prim a => Exts.IsList (Vector a) where - type Item (Vector a) = a - fromList = fromList - fromListN = fromListN - toList = toList + ( Eq, Ord, Num, Enum, Monoid, Traversable, Monad, Bool, Ordering(..), Int, Maybe, Either + , (==)) +pattern Vector :: Int -> Int -> ByteArray -> Vector a +pattern Vector i j arr = U.Vector i j arr +{-# COMPLETE Vector #-} +{-# DEPRECATED Vector "Use Vector constructor exported from \"Data.Vector.Primitive.Unsafe\"" #-} -- Length -- ------ @@ -1968,21 +1848,6 @@ iforA_ :: (Applicative f, Prim a) iforA_ = G.iforA_ --- Conversions - Unsafe casts --- -------------------------- - --- | /O(1)/ Unsafely cast a vector from one element type to another. --- This operation just changes the type of the vector and does not --- modify the elements. --- --- This function will throw an error if elements are of mismatching sizes. --- --- | @since 0.13.0.0 -unsafeCast :: forall a b. (HasCallStack, Prim a, Prim b) => Vector a -> Vector b -{-# INLINE unsafeCast #-} -unsafeCast (Vector o n ba) - | sizeOf (undefined :: a) == sizeOf (undefined :: b) = Vector o n ba - | otherwise = error "Element size mismatch" -- Conversions - Mutable vectors -- ----------------------------- @@ -2046,4 +1911,4 @@ copy :: (Prim a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m () copy = G.copy -- $setup --- >>> import Prelude (($), min, even, max, succ, id, Ord(..)) +-- >>> import Prelude (($), min, even, max, succ, id, Ord(..), Num(..), undefined) diff --git a/vector/src/Data/Vector/Primitive/Mutable.hs b/vector/src/Data/Vector/Primitive/Mutable.hs index 6c8dd884..535d41d4 100644 --- a/vector/src/Data/Vector/Primitive/Mutable.hs +++ b/vector/src/Data/Vector/Primitive/Mutable.hs @@ -3,6 +3,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE PatternSynonyms #-} -- | -- Module : Data.Vector.Primitive.Mutable -- Copyright : (c) Roman Leshchinskiy 2008-2010 @@ -19,7 +20,8 @@ module Data.Vector.Primitive.Mutable ( -- * Mutable vectors of primitive types - MVector(..), IOVector, STVector, + MVector, IOVector, STVector, + pattern MVector, -- * Accessors @@ -70,99 +72,22 @@ module Data.Vector.Primitive.Mutable ( ) where import qualified Data.Vector.Generic.Mutable as G +import Data.Primitive ( Prim ) import Data.Primitive.ByteArray -import Data.Primitive ( Prim, sizeOf ) -import Data.Vector.Internal.Check -import Data.Word ( Word8 ) +import Data.Vector.Primitive.Mutable.Unsafe + (MVector,IOVector,STVector,unsafeCoerceMVector,unsafeCast) +import qualified Data.Vector.Primitive.Mutable.Unsafe as U import Control.Monad.Primitive -import Control.Monad ( liftM ) -import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf)) - -import Prelude - ( Ord, Bool, Int, Maybe, Ordering(..) - , otherwise, error, undefined, div, show, maxBound - , (+), (*), (<), (>), (>=), (==), (&&), (||), ($), (++) ) - -import Data.Coerce -import Unsafe.Coerce +import Prelude ( Ord, Bool, Int, Maybe, Ordering(..) ) #include "vector.h" -type role MVector nominal nominal - --- | /O(1)/ Unsafely coerce a mutable vector from one element type to another, --- representationally equal type. The operation just changes the type of the --- underlying pointer and does not modify the elements. --- --- Note that this function is unsafe. The @Coercible@ constraint guarantees --- that the element types are representationally equal. It however cannot --- guarantee that their respective 'Prim' instances are compatible. -unsafeCoerceMVector :: Coercible a b => MVector s a -> MVector s b -unsafeCoerceMVector = unsafeCoerce - --- | Mutable vectors of primitive types. -data MVector s a = MVector {-# UNPACK #-} !Int -- ^ offset - {-# UNPACK #-} !Int -- ^ length - {-# UNPACK #-} !(MutableByteArray s) -- ^ underlying mutable byte array - -type IOVector = MVector RealWorld -type STVector s = MVector s - -instance NFData (MVector s a) where - rnf (MVector _ _ _) = () - -instance NFData1 (MVector s) where - liftRnf _ (MVector _ _ _) = () - -instance Prim a => G.MVector MVector a where - basicLength (MVector _ n _) = n - basicUnsafeSlice j m (MVector i _ arr) - = MVector (i+j) m arr - - {-# INLINE basicOverlaps #-} - basicOverlaps (MVector i m arr1) (MVector j n arr2) - = sameMutableByteArray arr1 arr2 - && (between i j (j+n) || between j i (i+m)) - where - between x y z = x >= y && x < z - - {-# INLINE basicUnsafeNew #-} - basicUnsafeNew n - | n < 0 = error $ "Primitive.basicUnsafeNew: negative length: " ++ show n - | n > mx = error $ "Primitive.basicUnsafeNew: length too large: " ++ show n - | otherwise = MVector 0 n `liftM` newByteArray (n * size) - where - size = sizeOf (undefined :: a) - mx = maxBound `div` size :: Int - - {-# INLINE basicInitialize #-} - basicInitialize (MVector off n v) = - setByteArray v (off * size) (n * size) (0 :: Word8) - where - size = sizeOf (undefined :: a) - - - {-# INLINE basicUnsafeRead #-} - basicUnsafeRead (MVector i _ arr) j = readByteArray arr (i+j) - - {-# INLINE basicUnsafeWrite #-} - basicUnsafeWrite (MVector i _ arr) j x = writeByteArray arr (i+j) x - - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MVector i n dst) (MVector j _ src) - = copyMutableByteArray dst (i*sz) src (j*sz) (n*sz) - where - sz = sizeOf (undefined :: a) - - {-# INLINE basicUnsafeMove #-} - basicUnsafeMove (MVector i n dst) (MVector j _ src) - = moveByteArray dst (i*sz) src (j*sz) (n * sz) - where - sz = sizeOf (undefined :: a) - - {-# INLINE basicSet #-} - basicSet (MVector i n arr) x = setByteArray arr i n x + +pattern MVector :: Int -> Int -> MutableByteArray s -> MVector s a +pattern MVector i j arr = U.MVector i j arr +{-# COMPLETE MVector #-} +{-# DEPRECATED MVector "Use MVector exported from \"Data.Vector.Primitive.Mutable.Unsafe\"" #-} -- Length information -- ------------------ @@ -745,18 +670,5 @@ ifoldrM' :: (PrimMonad m, Prim a) => (Int -> a -> b -> m b) -> b -> MVector (Pri {-# INLINE ifoldrM' #-} ifoldrM' = G.ifoldrM' --- Unsafe conversions --- ------------------ - --- | /O(1)/ Unsafely cast a vector from one element type to another. --- This operation just changes the type of the vector and does not --- modify the elements. --- --- This function will throw an error if elements are of mismatching sizes. --- --- | @since 0.13.0.0 -unsafeCast :: forall a b s. (HasCallStack, Prim a, Prim b) => MVector s a -> MVector s b -{-# INLINE unsafeCast #-} -unsafeCast (MVector o n ba) - | sizeOf (undefined :: a) == sizeOf (undefined :: b) = MVector o n ba - | otherwise = error "Element size mismatch" +-- $setup +-- >>> import Prelude (($), Num(..)) diff --git a/vector/src/Data/Vector/Primitive/Mutable/Unsafe.hs b/vector/src/Data/Vector/Primitive/Mutable/Unsafe.hs new file mode 100644 index 00000000..bf6612a0 --- /dev/null +++ b/vector/src/Data/Vector/Primitive/Mutable/Unsafe.hs @@ -0,0 +1,135 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE RoleAnnotations #-} +{-# LANGUAGE ScopedTypeVariables #-} +-- | +-- This module exposes internal representation of mutable vectors backed by +-- single 'ByteArray' and functions that work on that representation +-- directly (as opposed to using 'G.Vector' API). +-- +-- Note that working with internal representation of vector is +-- generally unsafe and may violate memory safety. +module Data.Vector.Primitive.Mutable.Unsafe + ( MVector(..) + , IOVector + , STVector + , unsafeCoerceMVector + , unsafeCast + ) where + +import qualified Data.Vector.Generic.Mutable as MG +import Data.Primitive.ByteArray +import Data.Primitive ( Prim, sizeOf ) +import Data.Word ( Word8 ) +import Control.Monad.Primitive +import Control.Monad ( liftM ) +import GHC.Stack (HasCallStack) + +import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf)) + +import Prelude + ( Int, Eq(..), Ord(..) + , otherwise, error, undefined, div, Show(..), maxBound + , (+), (*), (&&), (||), ($), (++) ) + +import Data.Coerce +import Unsafe.Coerce + + + +---------------------------------------------------------------- +-- Mutable +---------------------------------------------------------------- + +type role MVector nominal nominal + +-- | Mutable vectors of primitive types. +data MVector s a = MVector {-# UNPACK #-} !Int -- ^ offset + {-# UNPACK #-} !Int -- ^ length + {-# UNPACK #-} !(MutableByteArray s) -- ^ underlying mutable byte array + +type IOVector = MVector RealWorld +type STVector s = MVector s + +-- | /O(1)/ Unsafely coerce a mutable vector from one element type to another, +-- representationally equal type. The operation just changes the type of the +-- underlying pointer and does not modify the elements. +-- +-- Note that this function is unsafe. The @Coercible@ constraint guarantees +-- that the element types are representationally equal. It however cannot +-- guarantee that their respective 'Prim' instances are compatible. +unsafeCoerceMVector :: Coercible a b => MVector s a -> MVector s b +unsafeCoerceMVector = unsafeCoerce + +-- | /O(1)/ Unsafely cast a vector from one element type to another. +-- This operation just changes the type of the vector and does not +-- modify the elements. +-- +-- This function will throw an error if elements are of mismatching sizes. +-- +-- | @since 0.13.0.0 +unsafeCast :: forall a b s. (HasCallStack, Prim a, Prim b) => MVector s a -> MVector s b +{-# INLINE unsafeCast #-} +unsafeCast (MVector o n ba) + | sizeOf (undefined :: a) == sizeOf (undefined :: b) = MVector o n ba + | otherwise = error "Element size mismatch" + + + +instance NFData (MVector s a) where + rnf (MVector _ _ _) = () + +instance NFData1 (MVector s) where + liftRnf _ (MVector _ _ _) = () + +instance Prim a => MG.MVector MVector a where + basicLength (MVector _ n _) = n + basicUnsafeSlice j m (MVector i _ arr) + = MVector (i+j) m arr + + {-# INLINE basicOverlaps #-} + basicOverlaps (MVector i m arr1) (MVector j n arr2) + = sameMutableByteArray arr1 arr2 + && (between i j (j+n) || between j i (i+m)) + where + between x y z = x >= y && x < z + + {-# INLINE basicUnsafeNew #-} + basicUnsafeNew n + | n < 0 = error $ "Primitive.basicUnsafeNew: negative length: " ++ show n + | n > mx = error $ "Primitive.basicUnsafeNew: length too large: " ++ show n + | otherwise = MVector 0 n `liftM` newByteArray (n * size) + where + size = sizeOf (undefined :: a) + mx = maxBound `div` size :: Int + + {-# INLINE basicInitialize #-} + basicInitialize (MVector off n v) = + setByteArray v (off * size) (n * size) (0 :: Word8) + where + size = sizeOf (undefined :: a) + + + {-# INLINE basicUnsafeRead #-} + basicUnsafeRead (MVector i _ arr) j = readByteArray arr (i+j) + + {-# INLINE basicUnsafeWrite #-} + basicUnsafeWrite (MVector i _ arr) j x = writeByteArray arr (i+j) x + + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MVector i n dst) (MVector j _ src) + = copyMutableByteArray dst (i*sz) src (j*sz) (n*sz) + where + sz = sizeOf (undefined :: a) + + {-# INLINE basicUnsafeMove #-} + basicUnsafeMove (MVector i n dst) (MVector j _ src) + = moveByteArray dst (i*sz) src (j*sz) (n * sz) + where + sz = sizeOf (undefined :: a) + + {-# INLINE basicSet #-} + basicSet (MVector i n arr) x = setByteArray arr i n x + diff --git a/vector/src/Data/Vector/Primitive/Unsafe.hs b/vector/src/Data/Vector/Primitive/Unsafe.hs new file mode 100644 index 00000000..a1839417 --- /dev/null +++ b/vector/src/Data/Vector/Primitive/Unsafe.hs @@ -0,0 +1,175 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE RoleAnnotations #-} +{-# LANGUAGE ScopedTypeVariables #-} +-- | +-- This module exposes internal representation of vectors backed by +-- single 'ByteArray' and functions that work on that representation +-- directly (as opposed to using 'G.Vector' API). +-- +-- Note that working with internal representation of vector is +-- generally unsafe and may violate memory safety. +module Data.Vector.Primitive.Unsafe + ( -- * Mutable vector + Vector(..) + , unsafeCoerceVector + , unsafeCast + ) where + +import qualified Data.Vector.Generic as G +import qualified Data.Vector.Fusion.Bundle as Bundle +import Data.Data +import Data.Semigroup (Semigroup(..)) +import Data.Monoid (Monoid(..)) +import Data.Primitive.ByteArray +import Data.Primitive ( Prim, sizeOf ) +import Control.Monad ( liftM ) +import Text.Read ( Read(..), readListPrecDefault ) +import qualified GHC.Exts as Exts +import GHC.Stack (HasCallStack) + +import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf) ) + +import Prelude + ( Ord, Int, Ordering(..), Monad(..), Eq(..), Ord(..) + , undefined, Show(..), seq, otherwise, error + , (+), (*), ($!)) + +import Data.Coerce +import Unsafe.Coerce + +import Data.Vector.Primitive.Mutable.Unsafe (MVector(..)) +---------------------------------------------------------------- +-- Immutable +---------------------------------------------------------------- + +type role Vector nominal + +-- | Unboxed vectors of primitive types. +data Vector a = Vector {-# UNPACK #-} !Int -- ^ offset + {-# UNPACK #-} !Int -- ^ length + {-# UNPACK #-} !ByteArray -- ^ underlying byte array + +type instance G.Mutable Vector = MVector + +-- | /O(1)/ Unsafely coerce an immutable vector from one element type to another, +-- representationally equal type. The operation just changes the type of the +-- underlying pointer and does not modify the elements. +-- +-- This is marginally safer than 'unsafeCast', since this function imposes an +-- extra 'Coercible' constraint. The constraint guarantees that the element types +-- are representationally equal. It however cannot guarantee +-- that their respective 'Prim' instances are compatible. +unsafeCoerceVector :: Coercible a b => Vector a -> Vector b +unsafeCoerceVector = unsafeCoerce + +-- | /O(1)/ Unsafely cast a vector from one element type to another. +-- This operation just changes the type of the vector and does not +-- modify the elements. +-- +-- This function will throw an error if elements are of mismatching sizes. +-- +-- | @since 0.13.0.0 +unsafeCast :: forall a b. (HasCallStack, Prim a, Prim b) => Vector a -> Vector b +{-# INLINE unsafeCast #-} +unsafeCast (Vector o n ba) + | sizeOf (undefined :: a) == sizeOf (undefined :: b) = Vector o n ba + | otherwise = error "Element size mismatch" + + +instance Prim a => G.Vector Vector a where + {-# INLINE basicUnsafeFreeze #-} + basicUnsafeFreeze (MVector i n marr) + = Vector i n `liftM` unsafeFreezeByteArray marr + + {-# INLINE basicUnsafeThaw #-} + basicUnsafeThaw (Vector i n arr) + = MVector i n `liftM` unsafeThawByteArray arr + + {-# INLINE basicLength #-} + basicLength (Vector _ n _) = n + + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice j n (Vector i _ arr) = Vector (i+j) n arr + + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM (Vector i _ arr) j = return $! indexByteArray arr (i+j) + + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MVector i n dst) (Vector j _ src) + = copyByteArray dst (i*sz) src (j*sz) (n*sz) + where + sz = sizeOf (undefined :: a) + + {-# INLINE elemseq #-} + elemseq _ = seq + + +instance NFData (Vector a) where + rnf (Vector _ _ _) = () + +-- | @since 0.12.1.0 +instance NFData1 Vector where + liftRnf _ (Vector _ _ _) = () + +instance (Show a, Prim a) => Show (Vector a) where + showsPrec = G.showsPrec + +instance (Read a, Prim a) => Read (Vector a) where + readPrec = G.readPrec + readListPrec = readListPrecDefault + +instance (Data a, Prim a) => Data (Vector a) where + gfoldl = G.gfoldl + toConstr _ = G.mkVecConstr "Data.Vector.Primitive.Vector" + gunfold = G.gunfold + dataTypeOf _ = G.mkVecType "Data.Vector.Primitive.Vector" + dataCast1 = G.dataCast + + +-- See http://trac.haskell.org/vector/ticket/12 +instance (Prim a, Eq a) => Eq (Vector a) where + {-# INLINE (==) #-} + xs == ys = Bundle.eq (G.stream xs) (G.stream ys) + +-- See http://trac.haskell.org/vector/ticket/12 +instance (Prim a, Ord a) => Ord (Vector a) where + {-# INLINE compare #-} + compare xs ys = Bundle.cmp (G.stream xs) (G.stream ys) + + {-# INLINE (<) #-} + xs < ys = Bundle.cmp (G.stream xs) (G.stream ys) == LT + + {-# INLINE (<=) #-} + xs <= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= GT + + {-# INLINE (>) #-} + xs > ys = Bundle.cmp (G.stream xs) (G.stream ys) == GT + + {-# INLINE (>=) #-} + xs >= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= LT + +instance Prim a => Semigroup (Vector a) where + {-# INLINE (<>) #-} + (<>) = (G.++) + + {-# INLINE sconcat #-} + sconcat = G.concatNE + +instance Prim a => Monoid (Vector a) where + {-# INLINE mempty #-} + mempty = G.empty + + {-# INLINE mappend #-} + mappend = (<>) + + {-# INLINE mconcat #-} + mconcat = G.concat + +instance Prim a => Exts.IsList (Vector a) where + type Item (Vector a) = a + fromList = G.fromList + fromListN = G.fromListN + toList = G.toList diff --git a/vector/src/Data/Vector/Storable.hs b/vector/src/Data/Vector/Storable.hs index fb32941a..2cc4be36 100644 --- a/vector/src/Data/Vector/Storable.hs +++ b/vector/src/Data/Vector/Storable.hs @@ -5,6 +5,7 @@ {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE PatternSynonyms #-} -- | -- Module : Data.Vector.Storable -- Copyright : (c) Roman Leshchinskiy 2009-2010 @@ -21,7 +22,7 @@ module Data.Vector.Storable ( -- * Storable vectors - Vector, MVector(..), + Vector, MVector(MVector), -- * Accessors @@ -169,148 +170,20 @@ module Data.Vector.Storable ( import Control.Applicative (Applicative) import qualified Data.Vector.Generic as G -import Data.Vector.Storable.Mutable ( MVector(..) ) -import Data.Vector.Storable.Internal -import qualified Data.Vector.Fusion.Bundle as Bundle - -import Foreign.Storable -import Foreign.ForeignPtr -import Foreign.Ptr -import Foreign.Marshal.Array ( advancePtr, copyArray ) - -import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf)) +import Data.Vector.Storable.Mutable ( MVector, pattern MVector ) +import Data.Vector.Storable.Unsafe import Control.Monad.ST ( ST ) import Control.Monad.Primitive - +import Foreign.Storable +import Foreign.ForeignPtr import Prelude - ( Eq, Ord, Num, Enum, Monoid, Traversable, Monad, Read, Show, Bool, Ordering(..), Int, Maybe, Either, IO - , compare, mempty, mappend, mconcat, showsPrec, return, seq, undefined, div - , (*), (<), (<=), (>), (>=), (==), (/=), (&&), (.), ($) ) - -import Data.Data ( Data(..) ) -import Text.Read ( Read(..), readListPrecDefault ) -import Data.Semigroup ( Semigroup(..) ) -import Data.Coerce -import qualified GHC.Exts as Exts -import Unsafe.Coerce + ( Eq, Ord, Num, Enum, Monoid, Traversable, Monad, Bool, Ordering(..), Int, Maybe, Either + , undefined, div + , (*), (==), (&&)) #include "vector.h" -type role Vector nominal - --- | /O(1)/ Unsafely coerce a mutable vector from one element type to another, --- representationally equal type. The operation just changes the type of the --- underlying pointer and does not modify the elements. --- --- This is marginally safer than 'unsafeCast', since this function imposes an --- extra 'Coercible' constraint. This function is still not safe, however, --- since it cannot guarantee that the two types have memory-compatible --- 'Storable' instances. -unsafeCoerceVector :: Coercible a b => Vector a -> Vector b -unsafeCoerceVector = unsafeCoerce - --- | 'Storable'-based vectors. -data Vector a = Vector {-# UNPACK #-} !Int - {-# UNPACK #-} !(ForeignPtr a) - -instance NFData (Vector a) where - rnf (Vector _ _) = () - --- | @since 0.12.1.0 -instance NFData1 Vector where - liftRnf _ (Vector _ _) = () - -instance (Show a, Storable a) => Show (Vector a) where - showsPrec = G.showsPrec - -instance (Read a, Storable a) => Read (Vector a) where - readPrec = G.readPrec - readListPrec = readListPrecDefault - -instance (Data a, Storable a) => Data (Vector a) where - gfoldl = G.gfoldl - toConstr _ = G.mkVecConstr "Data.Vector.Storable.Vector" - gunfold = G.gunfold - dataTypeOf _ = G.mkVecType "Data.Vector.Storable.Vector" - dataCast1 = G.dataCast - - -type instance G.Mutable Vector = MVector - -instance Storable a => G.Vector Vector a where - {-# INLINE basicUnsafeFreeze #-} - basicUnsafeFreeze (MVector n fp) = return $ Vector n fp - - {-# INLINE basicUnsafeThaw #-} - basicUnsafeThaw (Vector n fp) = return $ MVector n fp - - {-# INLINE basicLength #-} - basicLength (Vector n _) = n - - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i n (Vector _ fp) = Vector n (updPtr (`advancePtr` i) fp) - - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM (Vector _ fp) i = return - . unsafeInlineIO - $ unsafeWithForeignPtr fp $ \p -> - peekElemOff p i - - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MVector n fp) (Vector _ fq) - = unsafePrimToPrim - $ unsafeWithForeignPtr fp $ \p -> - unsafeWithForeignPtr fq $ \q -> - copyArray p q n - - {-# INLINE elemseq #-} - elemseq _ = seq - --- See http://trac.haskell.org/vector/ticket/12 -instance (Storable a, Eq a) => Eq (Vector a) where - {-# INLINE (==) #-} - xs == ys = Bundle.eq (G.stream xs) (G.stream ys) - --- See http://trac.haskell.org/vector/ticket/12 -instance (Storable a, Ord a) => Ord (Vector a) where - {-# INLINE compare #-} - compare xs ys = Bundle.cmp (G.stream xs) (G.stream ys) - - {-# INLINE (<) #-} - xs < ys = Bundle.cmp (G.stream xs) (G.stream ys) == LT - - {-# INLINE (<=) #-} - xs <= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= GT - - {-# INLINE (>) #-} - xs > ys = Bundle.cmp (G.stream xs) (G.stream ys) == GT - - {-# INLINE (>=) #-} - xs >= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= LT - -instance Storable a => Semigroup (Vector a) where - {-# INLINE (<>) #-} - (<>) = (++) - - {-# INLINE sconcat #-} - sconcat = G.concatNE - -instance Storable a => Monoid (Vector a) where - {-# INLINE mempty #-} - mempty = empty - - {-# INLINE mappend #-} - mappend = (<>) - - {-# INLINE mconcat #-} - mconcat = concat - -instance Storable a => Exts.IsList (Vector a) where - type Item (Vector a) = a - fromList = fromList - fromListN = fromListN - toList = toList -- Length -- ------ @@ -2093,58 +1966,6 @@ copy = G.copy -- Conversions - Raw pointers -- -------------------------- --- | /O(1)/ Create a vector from a 'ForeignPtr' with an offset and a length. --- --- The data may not be modified through the pointer afterwards. --- --- If your offset is 0 it is more efficient to use 'unsafeFromForeignPtr0'. -unsafeFromForeignPtr :: Storable a - => ForeignPtr a -- ^ pointer - -> Int -- ^ offset - -> Int -- ^ length - -> Vector a -{-# INLINE_FUSED unsafeFromForeignPtr #-} -unsafeFromForeignPtr fp i n = unsafeFromForeignPtr0 fp' n - where - fp' = updPtr (`advancePtr` i) fp - -{-# RULES -"unsafeFromForeignPtr fp 0 n -> unsafeFromForeignPtr0 fp n " forall fp n. - unsafeFromForeignPtr fp 0 n = unsafeFromForeignPtr0 fp n #-} - - --- | /O(1)/ Create a vector from a 'ForeignPtr' and a length. --- --- It is assumed the pointer points directly to the data (no offset). --- Use 'unsafeFromForeignPtr' if you need to specify an offset. --- --- The data may not be modified through the pointer afterwards. -unsafeFromForeignPtr0 :: ForeignPtr a -- ^ pointer - -> Int -- ^ length - -> Vector a -{-# INLINE unsafeFromForeignPtr0 #-} -unsafeFromForeignPtr0 fp n = Vector n fp - --- | /O(1)/ Yield the underlying 'ForeignPtr' together with the offset to the --- data and its length. The data may not be modified through the 'ForeignPtr'. -unsafeToForeignPtr :: Vector a -> (ForeignPtr a, Int, Int) -{-# INLINE unsafeToForeignPtr #-} -unsafeToForeignPtr (Vector n fp) = (fp, 0, n) - --- | /O(1)/ Yield the underlying 'ForeignPtr' together with its length. --- --- You can assume that the pointer points directly to the data (no offset). --- --- The data may not be modified through the 'ForeignPtr'. -unsafeToForeignPtr0 :: Vector a -> (ForeignPtr a, Int) -{-# INLINE unsafeToForeignPtr0 #-} -unsafeToForeignPtr0 (Vector n fp) = (fp, n) - --- | Pass a pointer to the vector's data to the IO action. The data may not be --- modified through the 'Ptr. -unsafeWith :: Storable a => Vector a -> (Ptr a -> IO b) -> IO b -{-# INLINE unsafeWith #-} -unsafeWith (Vector _ fp) = withForeignPtr fp -- $setup -- >>> import Prelude (Bool(..), Double, ($), (+), (/), succ, even, min, max, id, Ord(..)) diff --git a/vector/src/Data/Vector/Storable/Mutable.hs b/vector/src/Data/Vector/Storable/Mutable.hs index 2e3c3cd2..336d769a 100644 --- a/vector/src/Data/Vector/Storable/Mutable.hs +++ b/vector/src/Data/Vector/Storable/Mutable.hs @@ -4,6 +4,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE PatternSynonyms #-} -- | -- Module : Data.Vector.Storable.Mutable -- Copyright : (c) Roman Leshchinskiy 2009-2010 @@ -20,7 +21,8 @@ module Data.Vector.Storable.Mutable( -- * Mutable vectors of 'Storable' types - MVector(..), IOVector, STVector, + MVector, IOVector, STVector, + pattern MVector, -- * Accessors @@ -76,191 +78,26 @@ module Data.Vector.Storable.Mutable( Storable, PrimMonad, PrimState, RealWorld ) where -import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf)) - import qualified Data.Vector.Generic.Mutable as G -import Data.Vector.Storable.Internal - +import Data.Vector.Storable.Mutable.Unsafe( + MVector,IOVector,STVector,unsafeCast,unsafeWith,unsafeCoerceMVector, + unsafeToForeignPtr,unsafeToForeignPtr0,unsafeFromForeignPtr,unsafeFromForeignPtr0) +import qualified Data.Vector.Storable.Mutable.Unsafe as U import Foreign.Storable -import Foreign.ForeignPtr - -import GHC.ForeignPtr (mallocPlainForeignPtrAlignedBytes) -import GHC.Base ( Int(..) ) - -import Foreign.Ptr (castPtr,plusPtr) -import Foreign.Marshal.Array ( advancePtr, copyArray, moveArray ) import Control.Monad.Primitive -import Data.Primitive.Types (Prim) -import qualified Data.Primitive.Types as DPT +import Foreign.ForeignPtr (ForeignPtr) -import GHC.Word (Word8, Word16, Word32, Word64) -import GHC.Ptr (Ptr(..)) +import Prelude (Int, Ord, Bool, Maybe, Ordering(..) ) -import Prelude - ( Ord, Bool, Maybe, IO, Ordering(..) - , return, otherwise, error, undefined, max, div, quot, maxBound, show - , (-), (*), (<), (>), (>=), (==), (&&), (||), (.), ($), (++) ) +#include "vector.h" -import Data.Coerce -import Unsafe.Coerce -#include "vector.h" +pattern MVector :: Int -> ForeignPtr a -> MVector s a +pattern MVector i ptr = U.MVector i ptr +{-# COMPLETE MVector #-} +{-# DEPRECATED MVector "Use MVector exported from Data.Vector.Strict.Mutable.Unsafe" #-} -type role MVector nominal nominal - --- | /O(1)/ Unsafely coerce a mutable vector from one element type to another, --- representationally equal type. The operation just changes the type of the --- underlying pointer and does not modify the elements. --- --- This is marginally safer than 'unsafeCast', since this function imposes an --- extra 'Coercible' constraint. This function is still not safe, however, --- since it cannot guarantee that the two types have memory-compatible --- 'Storable' instances. -unsafeCoerceMVector :: Coercible a b => MVector s a -> MVector s b -unsafeCoerceMVector = unsafeCoerce - --- | Mutable 'Storable'-based vectors. -data MVector s a = MVector {-# UNPACK #-} !Int - {-# UNPACK #-} !(ForeignPtr a) - -type IOVector = MVector RealWorld -type STVector s = MVector s - -instance NFData (MVector s a) where - rnf (MVector _ _) = () - -instance NFData1 (MVector s) where - liftRnf _ (MVector _ _) = () - -instance Storable a => G.MVector MVector a where - {-# INLINE basicLength #-} - basicLength (MVector n _) = n - - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice j m (MVector _ fp) = MVector m (updPtr (`advancePtr` j) fp) - - -- FIXME: this relies on non-portable pointer comparisons - {-# INLINE basicOverlaps #-} - basicOverlaps (MVector m fp) (MVector n fq) - = between p q (q `advancePtr` n) || between q p (p `advancePtr` m) - where - between x y z = x >= y && x < z - p = getPtr fp - q = getPtr fq - - {-# INLINE basicUnsafeNew #-} - basicUnsafeNew n - | n < 0 = error $ "Storable.basicUnsafeNew: negative length: " ++ show n - | n > mx = error $ "Storable.basicUnsafeNew: length too large: " ++ show n - | otherwise = unsafePrimToPrim $ do - fp <- mallocVector n - return $ MVector n fp - where - size = sizeOf (undefined :: a) `max` 1 - mx = maxBound `quot` size :: Int - - {-# INLINE basicInitialize #-} - basicInitialize = storableZero - - {-# INLINE basicUnsafeRead #-} - basicUnsafeRead (MVector _ fp) i - = unsafePrimToPrim - $ unsafeWithForeignPtr fp (`peekElemOff` i) - - {-# INLINE basicUnsafeWrite #-} - basicUnsafeWrite (MVector _ fp) i x - = unsafePrimToPrim - $ unsafeWithForeignPtr fp $ \p -> pokeElemOff p i x - - {-# INLINE basicSet #-} - basicSet = storableSet - - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MVector n fp) (MVector _ fq) - = unsafePrimToPrim - $ unsafeWithForeignPtr fp $ \p -> - unsafeWithForeignPtr fq $ \q -> - copyArray p q n - - {-# INLINE basicUnsafeMove #-} - basicUnsafeMove (MVector n fp) (MVector _ fq) - = unsafePrimToPrim - $ unsafeWithForeignPtr fp $ \p -> - unsafeWithForeignPtr fq $ \q -> - moveArray p q n - -storableZero :: forall a m. (Storable a, PrimMonad m) => MVector (PrimState m) a -> m () -{-# INLINE storableZero #-} -storableZero (MVector n fp) = unsafePrimToPrim . unsafeWithForeignPtr fp $ \ptr-> do - memsetPrimPtr_vector (castPtr ptr) byteSize (0 :: Word8) - where - x :: a - x = undefined - byteSize :: Int - byteSize = n * sizeOf x - -storableSet :: (Storable a, PrimMonad m) => MVector (PrimState m) a -> a -> m () -{-# INLINE storableSet #-} -storableSet (MVector n fp) x - | n == 0 = return () - | otherwise = unsafePrimToPrim $ - case sizeOf x of - 1 -> storableSetAsPrim n fp x (undefined :: Word8) - 2 -> storableSetAsPrim n fp x (undefined :: Word16) - 4 -> storableSetAsPrim n fp x (undefined :: Word32) -#if !defined(ghcjs_HOST_OS) - 8 -> storableSetAsPrim n fp x (undefined :: Word64) -#endif - _ -> unsafeWithForeignPtr fp $ \p -> do - poke p x - - let do_set i - | 2*i < n = do - copyArray (p `advancePtr` i) p i - do_set (2*i) - | otherwise = copyArray (p `advancePtr` i) p (n-i) - - do_set 1 - -storableSetAsPrim - :: forall a b . (Storable a, Prim b) => Int -> ForeignPtr a -> a -> b -> IO () -{-# INLINE [0] storableSetAsPrim #-} -storableSetAsPrim n fp x _y = unsafeWithForeignPtr fp $ \ ptr -> do - poke ptr x - -- we don't equate storable and prim reps, so we need to write to a slot - -- in storable - -- then read it back as a prim - w<- peakPrimPtr_vector (castPtr ptr :: Ptr b) 0 - memsetPrimPtr_vector (castPtr ptr `plusPtr` sizeOf x ) (n-1) w - - - -{- -AFTER primitive 0.7 is pretty old, move to using setPtr. which is really -a confusing misnomer for what's often called memset (initialize) --} --- Fill a memory block with the given value. The length is in --- elements of type @a@ rather than in bytes. -memsetPrimPtr_vector :: forall a c m. (Prim c, PrimMonad m) => Ptr a -> Int -> c -> m () -memsetPrimPtr_vector (Ptr addr#) (I# n#) x = primitive_ (DPT.setOffAddr# addr# 0# n# x) -{-# INLINE memsetPrimPtr_vector #-} - - --- Read a value from a memory position given by an address and an offset. --- The offset is in elements of type @a@ rather than in bytes. -peakPrimPtr_vector :: (Prim a, PrimMonad m) => Ptr a -> Int -> m a -peakPrimPtr_vector (Ptr addr#) (I# i#) = primitive (DPT.readOffAddr# addr# i#) -{-# INLINE peakPrimPtr_vector #-} - -{-# INLINE mallocVector #-} -mallocVector :: Storable a => Int -> IO (ForeignPtr a) -mallocVector = - doMalloc undefined - where - doMalloc :: Storable b => b -> Int -> IO (ForeignPtr b) - doMalloc dummy size = - mallocPlainForeignPtrAlignedBytes (size * sizeOf dummy) (alignment dummy) -- Length information -- ------------------ @@ -846,79 +683,5 @@ ifoldrM' :: (PrimMonad m, Storable a) => (Int -> a -> b -> m b) -> b -> MVector {-# INLINE ifoldrM' #-} ifoldrM' = G.ifoldrM' --- Unsafe conversions --- ------------------ - --- | /O(1)/ Unsafely cast a mutable vector from one element type to another. --- The operation just changes the type of the underlying pointer and does not --- modify the elements. --- --- The resulting vector contains as many elements as can fit into the --- underlying memory block. -unsafeCast :: forall a b s. - (Storable a, Storable b) => MVector s a -> MVector s b -{-# INLINE unsafeCast #-} -unsafeCast (MVector n fp) - = MVector ((n * sizeOf (undefined :: a)) `div` sizeOf (undefined :: b)) - (castForeignPtr fp) - --- Raw pointers --- ------------ - --- | /O(1)/ Create a mutable vector from a 'ForeignPtr' with an offset and a length. --- --- Modifying data through the 'ForeignPtr' afterwards is unsafe if the vector --- could have been frozen before the modification. --- --- If your offset is 0, it is more efficient to use 'unsafeFromForeignPtr0'. -unsafeFromForeignPtr :: Storable a - => ForeignPtr a -- ^ pointer - -> Int -- ^ offset - -> Int -- ^ length - -> MVector s a -{-# INLINE_FUSED unsafeFromForeignPtr #-} -unsafeFromForeignPtr fp i n = unsafeFromForeignPtr0 fp' n - where - fp' = updPtr (`advancePtr` i) fp - -{-# RULES -"unsafeFromForeignPtr fp 0 n -> unsafeFromForeignPtr0 fp n " forall fp n. - unsafeFromForeignPtr fp 0 n = unsafeFromForeignPtr0 fp n #-} - - --- | /O(1)/ Create a mutable vector from a 'ForeignPtr' and a length. --- --- It is assumed that the pointer points directly to the data (no offset). --- Use 'unsafeFromForeignPtr' if you need to specify an offset. --- --- Modifying data through the 'ForeignPtr' afterwards is unsafe if the vector --- could have been frozen before the modification. -unsafeFromForeignPtr0 :: ForeignPtr a -- ^ pointer - -> Int -- ^ length - -> MVector s a -{-# INLINE unsafeFromForeignPtr0 #-} -unsafeFromForeignPtr0 fp n = MVector n fp - --- | /O(1)/ Yield the underlying 'ForeignPtr' together with the offset to the data --- and its length. Modifying the data through the 'ForeignPtr' is --- unsafe if the vector could have been frozen before the modification. -unsafeToForeignPtr :: MVector s a -> (ForeignPtr a, Int, Int) -{-# INLINE unsafeToForeignPtr #-} -unsafeToForeignPtr (MVector n fp) = (fp, 0, n) - --- | /O(1)/ Yield the underlying 'ForeignPtr' together with its length. --- --- You can assume that the pointer points directly to the data (no offset). --- --- Modifying the data through the 'ForeignPtr' is unsafe if the vector could --- have been frozen before the modification. -unsafeToForeignPtr0 :: MVector s a -> (ForeignPtr a, Int) -{-# INLINE unsafeToForeignPtr0 #-} -unsafeToForeignPtr0 (MVector n fp) = (fp, n) - --- | Pass a pointer to the vector's data to the IO action. Modifying data --- through the pointer is unsafe if the vector could have been frozen before --- the modification. -unsafeWith :: Storable a => IOVector a -> (Ptr a -> IO b) -> IO b -{-# INLINE unsafeWith #-} -unsafeWith (MVector _ fp) = withForeignPtr fp +-- $setup +-- >>> import Prelude (($), Num(..)) diff --git a/vector/src/Data/Vector/Storable/Mutable/Unsafe.hs b/vector/src/Data/Vector/Storable/Mutable/Unsafe.hs new file mode 100644 index 00000000..4545b2f3 --- /dev/null +++ b/vector/src/Data/Vector/Storable/Mutable/Unsafe.hs @@ -0,0 +1,288 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE RoleAnnotations #-} +{-# LANGUAGE ScopedTypeVariables #-} +-- | +-- This module exposes internal representation of mutable vectors +-- based on 'Storable' and functions that work on that representation +-- directly (as opposed to using 'G.Vector' API. +-- +-- Note that working with internal representation of vector is +-- generally unsafe and may violate memory safety. +module Data.Vector.Storable.Mutable.Unsafe + ( MVector(..) + , IOVector + , STVector + -- * Unsafe conversions + , unsafeCast + , unsafeCoerceMVector + -- * Working with raw pointers + , unsafeFromForeignPtr, unsafeFromForeignPtr0 + , unsafeToForeignPtr, unsafeToForeignPtr0 + , unsafeWith + ) where + +import Control.DeepSeq (NFData(rnf), NFData1(liftRnf)) + +import qualified Data.Vector.Generic.Mutable as G +import Data.Vector.Storable.Internal + +import Foreign.Storable +import Foreign.ForeignPtr + +import GHC.ForeignPtr (mallocPlainForeignPtrAlignedBytes) +import GHC.Base ( Int(..) ) + +import Foreign.Ptr (castPtr,plusPtr) +import Foreign.Marshal.Array ( advancePtr, copyArray, moveArray ) + +import Control.Monad.Primitive +import Data.Primitive.Types (Prim) +import qualified Data.Primitive.Types as DPT + +import GHC.Word (Word8, Word16, Word32, Word64) +import GHC.Ptr (Ptr(..)) + +import Prelude + ( IO, return, otherwise, error, undefined, max, div, quot, maxBound, show + , (-), (*), (<), (>), (>=), (==), (&&), (||), (.), ($), (++) ) + +import Data.Coerce +import Unsafe.Coerce + +#include "vector.h" + + +type role MVector nominal nominal + +-- | Mutable 'Storable'-based vectors. +data MVector s a = MVector {-# UNPACK #-} !Int + {-# UNPACK #-} !(ForeignPtr a) + +type IOVector = MVector RealWorld +type STVector s = MVector s + +instance NFData (MVector s a) where + rnf (MVector _ _) = () + +instance NFData1 (MVector s) where + liftRnf _ (MVector _ _) = () + +instance Storable a => G.MVector MVector a where + {-# INLINE basicLength #-} + basicLength (MVector n _) = n + + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice j m (MVector _ fp) = MVector m (updPtr (`advancePtr` j) fp) + + -- FIXME: this relies on non-portable pointer comparisons + {-# INLINE basicOverlaps #-} + basicOverlaps (MVector m fp) (MVector n fq) + = between p q (q `advancePtr` n) || between q p (p `advancePtr` m) + where + between x y z = x >= y && x < z + p = getPtr fp + q = getPtr fq + + {-# INLINE basicUnsafeNew #-} + basicUnsafeNew n + | n < 0 = error $ "Storable.basicUnsafeNew: negative length: " ++ show n + | n > mx = error $ "Storable.basicUnsafeNew: length too large: " ++ show n + | otherwise = unsafePrimToPrim $ do + fp <- mallocVector n + return $ MVector n fp + where + size = sizeOf (undefined :: a) `max` 1 + mx = maxBound `quot` size :: Int + + {-# INLINE basicInitialize #-} + basicInitialize = storableZero + + {-# INLINE basicUnsafeRead #-} + basicUnsafeRead (MVector _ fp) i + = unsafePrimToPrim + $ unsafeWithForeignPtr fp (`peekElemOff` i) + + {-# INLINE basicUnsafeWrite #-} + basicUnsafeWrite (MVector _ fp) i x + = unsafePrimToPrim + $ unsafeWithForeignPtr fp $ \p -> pokeElemOff p i x + + {-# INLINE basicSet #-} + basicSet = storableSet + + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MVector n fp) (MVector _ fq) + = unsafePrimToPrim + $ unsafeWithForeignPtr fp $ \p -> + unsafeWithForeignPtr fq $ \q -> + copyArray p q n + + {-# INLINE basicUnsafeMove #-} + basicUnsafeMove (MVector n fp) (MVector _ fq) + = unsafePrimToPrim + $ unsafeWithForeignPtr fp $ \p -> + unsafeWithForeignPtr fq $ \q -> + moveArray p q n + + +{-# INLINE mallocVector #-} +mallocVector :: Storable a => Int -> IO (ForeignPtr a) +mallocVector = + doMalloc undefined + where + doMalloc :: Storable b => b -> Int -> IO (ForeignPtr b) + doMalloc dummy size = + mallocPlainForeignPtrAlignedBytes (size * sizeOf dummy) (alignment dummy) + +storableZero :: forall a m. (Storable a, PrimMonad m) => MVector (PrimState m) a -> m () +{-# INLINE storableZero #-} +storableZero (MVector n fp) = unsafePrimToPrim . unsafeWithForeignPtr fp $ \ptr-> do + memsetPrimPtr_vector (castPtr ptr) byteSize (0 :: Word8) + where + x :: a + x = undefined + byteSize :: Int + byteSize = n * sizeOf x + +storableSet :: (Storable a, PrimMonad m) => MVector (PrimState m) a -> a -> m () +{-# INLINE storableSet #-} +storableSet (MVector n fp) x + | n == 0 = return () + | otherwise = unsafePrimToPrim $ + case sizeOf x of + 1 -> storableSetAsPrim n fp x (undefined :: Word8) + 2 -> storableSetAsPrim n fp x (undefined :: Word16) + 4 -> storableSetAsPrim n fp x (undefined :: Word32) +#if !defined(ghcjs_HOST_OS) + 8 -> storableSetAsPrim n fp x (undefined :: Word64) +#endif + _ -> unsafeWithForeignPtr fp $ \p -> do + poke p x + + let do_set i + | 2*i < n = do + copyArray (p `advancePtr` i) p i + do_set (2*i) + | otherwise = copyArray (p `advancePtr` i) p (n-i) + + do_set 1 + +storableSetAsPrim + :: forall a b . (Storable a, Prim b) => Int -> ForeignPtr a -> a -> b -> IO () +{-# INLINE [0] storableSetAsPrim #-} +storableSetAsPrim n fp x _y = unsafeWithForeignPtr fp $ \ ptr -> do + poke ptr x + -- we don't equate storable and prim reps, so we need to write to a slot + -- in storable + -- then read it back as a prim + w<- peakPrimPtr_vector (castPtr ptr :: Ptr b) 0 + memsetPrimPtr_vector (castPtr ptr `plusPtr` sizeOf x ) (n-1) w + +{- +AFTER primitive 0.7 is pretty old, move to using setPtr. which is really +a confusing misnomer for what's often called memset (initialize) +-} +-- Fill a memory block with the given value. The length is in +-- elements of type @a@ rather than in bytes. +memsetPrimPtr_vector :: forall a c m. (Prim c, PrimMonad m) => Ptr a -> Int -> c -> m () +memsetPrimPtr_vector (Ptr addr#) (I# n#) x = primitive_ (DPT.setOffAddr# addr# 0# n# x) +{-# INLINE memsetPrimPtr_vector #-} + + +-- Read a value from a memory position given by an address and an offset. +-- The offset is in elements of type @a@ rather than in bytes. +peakPrimPtr_vector :: (Prim a, PrimMonad m) => Ptr a -> Int -> m a +peakPrimPtr_vector (Ptr addr#) (I# i#) = primitive (DPT.readOffAddr# addr# i#) +{-# INLINE peakPrimPtr_vector #-} + + +-- Unsafe conversions +-- ------------------ + +-- | /O(1)/ Unsafely cast a mutable vector from one element type to another. +-- The operation just changes the type of the underlying pointer and does not +-- modify the elements. +-- +-- The resulting vector contains as many elements as can fit into the +-- underlying memory block. +unsafeCast :: forall a b s. + (Storable a, Storable b) => MVector s a -> MVector s b +{-# INLINE unsafeCast #-} +unsafeCast (MVector n fp) + = MVector ((n * sizeOf (undefined :: a)) `div` sizeOf (undefined :: b)) + (castForeignPtr fp) + +-- | /O(1)/ Unsafely coerce a mutable vector from one element type to another, +-- representationally equal type. The operation just changes the type of the +-- underlying pointer and does not modify the elements. +-- +-- This is marginally safer than 'unsafeCast', since this function imposes an +-- extra 'Coercible' constraint. This function is still not safe, however, +-- since it cannot guarantee that the two types have memory-compatible +-- 'Storable' instances. +unsafeCoerceMVector :: Coercible a b => MVector s a -> MVector s b +unsafeCoerceMVector = unsafeCoerce + +-- Raw pointers +-- ------------ + +-- | /O(1)/ Create a mutable vector from a 'ForeignPtr' with an offset and a length. +-- +-- Modifying data through the 'ForeignPtr' afterwards is unsafe if the vector +-- could have been frozen before the modification. +-- +-- If your offset is 0, it is more efficient to use 'unsafeFromForeignPtr0'. +unsafeFromForeignPtr :: Storable a + => ForeignPtr a -- ^ pointer + -> Int -- ^ offset + -> Int -- ^ length + -> MVector s a +{-# INLINE_FUSED unsafeFromForeignPtr #-} +unsafeFromForeignPtr fp i n = unsafeFromForeignPtr0 fp' n + where + fp' = updPtr (`advancePtr` i) fp + +{-# RULES +"unsafeFromForeignPtr fp 0 n -> unsafeFromForeignPtr0 fp n " forall fp n. + unsafeFromForeignPtr fp 0 n = unsafeFromForeignPtr0 fp n #-} + + +-- | /O(1)/ Create a mutable vector from a 'ForeignPtr' and a length. +-- +-- It is assumed that the pointer points directly to the data (no offset). +-- Use 'unsafeFromForeignPtr' if you need to specify an offset. +-- +-- Modifying data through the 'ForeignPtr' afterwards is unsafe if the vector +-- could have been frozen before the modification. +unsafeFromForeignPtr0 :: ForeignPtr a -- ^ pointer + -> Int -- ^ length + -> MVector s a +{-# INLINE unsafeFromForeignPtr0 #-} +unsafeFromForeignPtr0 fp n = MVector n fp + +-- | /O(1)/ Yield the underlying 'ForeignPtr' together with the offset to the data +-- and its length. Modifying the data through the 'ForeignPtr' is +-- unsafe if the vector could have been frozen before the modification. +unsafeToForeignPtr :: MVector s a -> (ForeignPtr a, Int, Int) +{-# INLINE unsafeToForeignPtr #-} +unsafeToForeignPtr (MVector n fp) = (fp, 0, n) + +-- | /O(1)/ Yield the underlying 'ForeignPtr' together with its length. +-- +-- You can assume that the pointer points directly to the data (no offset). +-- +-- Modifying the data through the 'ForeignPtr' is unsafe if the vector could +-- have been frozen before the modification. +unsafeToForeignPtr0 :: MVector s a -> (ForeignPtr a, Int) +{-# INLINE unsafeToForeignPtr0 #-} +unsafeToForeignPtr0 (MVector n fp) = (fp, n) + +-- | Pass a pointer to the vector's data to the IO action. Modifying data +-- through the pointer is unsafe if the vector could have been frozen before +-- the modification. +unsafeWith :: Storable a => IOVector a -> (Ptr a -> IO b) -> IO b +{-# INLINE unsafeWith #-} +unsafeWith (MVector _ fp) = withForeignPtr fp diff --git a/vector/src/Data/Vector/Storable/Unsafe.hs b/vector/src/Data/Vector/Storable/Unsafe.hs new file mode 100644 index 00000000..51d6a047 --- /dev/null +++ b/vector/src/Data/Vector/Storable/Unsafe.hs @@ -0,0 +1,219 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RoleAnnotations #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeFamilies #-} +-- | +-- This module exposes internal representation of vectors based on +-- 'Storable' and functions that work on that representation directly +-- (as opposed to using 'G.Vector' API. +-- +-- Note that working with internal representation of vector is +-- generally unsafe and may violate memory safety. +module Data.Vector.Storable.Unsafe + ( Vector(..) + , unsafeCoerceVector + -- * Raw pointers + , unsafeFromForeignPtr, unsafeFromForeignPtr0 + , unsafeToForeignPtr, unsafeToForeignPtr0 + , unsafeWith + ) where + +import qualified Data.Vector.Generic as G +import Data.Vector.Storable.Mutable.Unsafe ( MVector(..) ) +import Data.Vector.Storable.Internal +import qualified Data.Vector.Fusion.Bundle as Bundle + +import Foreign.Storable +import Foreign.ForeignPtr +import Foreign.Ptr +import Foreign.Marshal.Array ( advancePtr, copyArray ) + +import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf)) + +import Control.Monad.Primitive + +import Prelude + ( Eq, Ord, Monoid, Read, Show, Ordering(..), Int, IO + , compare, mempty, mappend, mconcat, showsPrec, return, seq + , (<), (<=), (>), (>=), (==), (/=), (.), ($) ) + +import Data.Data ( Data(..) ) +import Text.Read ( Read(..), readListPrecDefault ) +import Data.Semigroup ( Semigroup(..) ) +import Data.Coerce +import qualified GHC.Exts as Exts +import Unsafe.Coerce + +#include "vector.h" + +type role Vector nominal + +-- | /O(1)/ Unsafely coerce a mutable vector from one element type to another, +-- representationally equal type. The operation just changes the type of the +-- underlying pointer and does not modify the elements. +-- +-- This is marginally safer than 'unsafeCast', since this function imposes an +-- extra 'Coercible' constraint. This function is still not safe, however, +-- since it cannot guarantee that the two types have memory-compatible +-- 'Storable' instances. +unsafeCoerceVector :: Coercible a b => Vector a -> Vector b +unsafeCoerceVector = unsafeCoerce + +-- | 'Storable'-based vectors. +data Vector a = Vector {-# UNPACK #-} !Int + {-# UNPACK #-} !(ForeignPtr a) + +instance NFData (Vector a) where + rnf (Vector _ _) = () + +-- | @since 0.12.1.0 +instance NFData1 Vector where + liftRnf _ (Vector _ _) = () + +instance (Show a, Storable a) => Show (Vector a) where + showsPrec = G.showsPrec + +instance (Read a, Storable a) => Read (Vector a) where + readPrec = G.readPrec + readListPrec = readListPrecDefault + +instance (Data a, Storable a) => Data (Vector a) where + gfoldl = G.gfoldl + toConstr _ = G.mkVecConstr "Data.Vector.Storable.Vector" + gunfold = G.gunfold + dataTypeOf _ = G.mkVecType "Data.Vector.Storable.Vector" + dataCast1 = G.dataCast + + +type instance G.Mutable Vector = MVector + +instance Storable a => G.Vector Vector a where + {-# INLINE basicUnsafeFreeze #-} + basicUnsafeFreeze (MVector n fp) = return $ Vector n fp + + {-# INLINE basicUnsafeThaw #-} + basicUnsafeThaw (Vector n fp) = return $ MVector n fp + + {-# INLINE basicLength #-} + basicLength (Vector n _) = n + + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i n (Vector _ fp) = Vector n (updPtr (`advancePtr` i) fp) + + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM (Vector _ fp) i = return + . unsafeInlineIO + $ unsafeWithForeignPtr fp $ \p -> + peekElemOff p i + + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MVector n fp) (Vector _ fq) + = unsafePrimToPrim + $ unsafeWithForeignPtr fp $ \p -> + unsafeWithForeignPtr fq $ \q -> + copyArray p q n + + {-# INLINE elemseq #-} + elemseq _ = seq + +-- See http://trac.haskell.org/vector/ticket/12 +instance (Storable a, Eq a) => Eq (Vector a) where + {-# INLINE (==) #-} + xs == ys = Bundle.eq (G.stream xs) (G.stream ys) + +-- See http://trac.haskell.org/vector/ticket/12 +instance (Storable a, Ord a) => Ord (Vector a) where + {-# INLINE compare #-} + compare xs ys = Bundle.cmp (G.stream xs) (G.stream ys) + + {-# INLINE (<) #-} + xs < ys = Bundle.cmp (G.stream xs) (G.stream ys) == LT + + {-# INLINE (<=) #-} + xs <= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= GT + + {-# INLINE (>) #-} + xs > ys = Bundle.cmp (G.stream xs) (G.stream ys) == GT + + {-# INLINE (>=) #-} + xs >= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= LT + +instance Storable a => Semigroup (Vector a) where + {-# INLINE (<>) #-} + (<>) = (G.++) + + {-# INLINE sconcat #-} + sconcat = G.concatNE + +instance Storable a => Monoid (Vector a) where + {-# INLINE mempty #-} + mempty = G.empty + + {-# INLINE mappend #-} + mappend = (<>) + + {-# INLINE mconcat #-} + mconcat = G.concat + +instance Storable a => Exts.IsList (Vector a) where + type Item (Vector a) = a + fromList = G.fromList + fromListN = G.fromListN + toList = G.toList + + +-- | /O(1)/ Create a vector from a 'ForeignPtr' with an offset and a length. +-- +-- The data may not be modified through the pointer afterwards. +-- +-- If your offset is 0 it is more efficient to use 'unsafeFromForeignPtr0'. +unsafeFromForeignPtr :: Storable a + => ForeignPtr a -- ^ pointer + -> Int -- ^ offset + -> Int -- ^ length + -> Vector a +{-# INLINE_FUSED unsafeFromForeignPtr #-} +unsafeFromForeignPtr fp i n = unsafeFromForeignPtr0 fp' n + where + fp' = updPtr (`advancePtr` i) fp + +{-# RULES +"unsafeFromForeignPtr fp 0 n -> unsafeFromForeignPtr0 fp n " forall fp n. + unsafeFromForeignPtr fp 0 n = unsafeFromForeignPtr0 fp n #-} + + +-- | /O(1)/ Create a vector from a 'ForeignPtr' and a length. +-- +-- It is assumed the pointer points directly to the data (no offset). +-- Use 'unsafeFromForeignPtr' if you need to specify an offset. +-- +-- The data may not be modified through the pointer afterwards. +unsafeFromForeignPtr0 :: ForeignPtr a -- ^ pointer + -> Int -- ^ length + -> Vector a +{-# INLINE unsafeFromForeignPtr0 #-} +unsafeFromForeignPtr0 fp n = Vector n fp + +-- | /O(1)/ Yield the underlying 'ForeignPtr' together with the offset to the +-- data and its length. The data may not be modified through the 'ForeignPtr'. +unsafeToForeignPtr :: Vector a -> (ForeignPtr a, Int, Int) +{-# INLINE unsafeToForeignPtr #-} +unsafeToForeignPtr (Vector n fp) = (fp, 0, n) + +-- | /O(1)/ Yield the underlying 'ForeignPtr' together with its length. +-- +-- You can assume that the pointer points directly to the data (no offset). +-- +-- The data may not be modified through the 'ForeignPtr'. +unsafeToForeignPtr0 :: Vector a -> (ForeignPtr a, Int) +{-# INLINE unsafeToForeignPtr0 #-} +unsafeToForeignPtr0 (Vector n fp) = (fp, n) + +-- | Pass a pointer to the vector's data to the IO action. The data may not be +-- modified through the 'Ptr. +unsafeWith :: Storable a => Vector a -> (Ptr a -> IO b) -> IO b +{-# INLINE unsafeWith #-} +unsafeWith (Vector _ fp) = withForeignPtr fp diff --git a/vector/src/Data/Vector/Strict.hs b/vector/src/Data/Vector/Strict.hs index 58db6d3f..5c5490c0 100644 --- a/vector/src/Data/Vector/Strict.hs +++ b/vector/src/Data/Vector/Strict.hs @@ -178,220 +178,17 @@ module Data.Vector.Strict ( ) where import Control.Applicative (Applicative) -import Data.Coerce -import Data.Vector.Strict.Mutable ( MVector(..) ) -import Data.Primitive.Array +import Control.Monad.Primitive +import Data.Vector.Strict.Mutable.Unsafe ( MVector(..) ) +import Data.Vector.Strict.Unsafe import qualified Data.Vector.Generic as G -import qualified Data.Vector as V - -import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf)) +import qualified Data.Traversable as Traversable -import Control.Monad ( MonadPlus(..), ap ) -import Control.Monad.ST ( ST, runST ) -import Control.Monad.Primitive -import qualified Control.Monad.Fail as Fail -import Control.Monad.Fix ( MonadFix (mfix) ) -import Control.Monad.Zip -import Data.Function ( fix ) +import Control.Monad.ST ( ST ) import Prelude - ( Eq(..), Ord(..), Num, Enum, Monoid, Functor, Monad, Show, Bool, Ordering(..), Int, Maybe, Either - , return, showsPrec, fmap, otherwise, id, flip, const - , (>>=), (+), (-), (.), ($), seq) - -import Data.Functor.Classes (Eq1 (..), Ord1 (..), Read1 (..), Show1 (..)) -import Data.Data ( Data(..) ) -import Text.Read ( Read(..), readListPrecDefault ) -import Data.Semigroup ( Semigroup(..) ) - -import qualified Control.Applicative as Applicative -import qualified Data.Foldable as Foldable -import qualified Data.Traversable as Traversable - -import qualified GHC.Exts as Exts (IsList(..)) - - --- | Strict boxed vectors, supporting efficient slicing. -newtype Vector a = Vector (V.Vector a) - deriving (Foldable.Foldable, Semigroup, Monoid) - --- NOTE: [GND for strict vector] --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- --- Strict boxed vectors (both mutable an immutable) are newtypes over --- lazy ones. This makes it possible to use GND to derive instances. --- However one must take care to preserve strictness since Vector --- instance for lazy vectors would be used. --- --- In general it's OK to derive instances where vectors are passed as --- parameters (e.g. Eq, Ord) and not OK to derive ones where new --- vector is created (e.g. Read, Functor) - -instance NFData a => NFData (Vector a) where - rnf = liftRnf rnf - {-# INLINEABLE rnf #-} - --- | @since 0.13.2.0 -instance NFData1 Vector where - liftRnf elemRnf = foldl' (\_ -> elemRnf) () - {-# INLINEABLE liftRnf #-} - -instance Show a => Show (Vector a) where - showsPrec = G.showsPrec - -instance Read a => Read (Vector a) where - readPrec = G.readPrec - readListPrec = readListPrecDefault - -instance Show1 Vector where - liftShowsPrec = G.liftShowsPrec - -instance Read1 Vector where - liftReadsPrec = G.liftReadsPrec - -instance Exts.IsList (Vector a) where - type Item (Vector a) = a - fromList = Data.Vector.Strict.fromList - fromListN = Data.Vector.Strict.fromListN - toList = toList - -instance Data a => Data (Vector a) where - gfoldl = G.gfoldl - toConstr _ = G.mkVecConstr "Data.Vector.Strict.Vector" - gunfold = G.gunfold - dataTypeOf _ = G.mkVecType "Data.Vector.Strict.Vector" - dataCast1 = G.dataCast - -type instance G.Mutable Vector = MVector - -instance G.Vector Vector a where - {-# INLINE basicUnsafeFreeze #-} - basicUnsafeFreeze = coerce (G.basicUnsafeFreeze @V.Vector @a) - {-# INLINE basicUnsafeThaw #-} - basicUnsafeThaw = coerce (G.basicUnsafeThaw @V.Vector @a) - {-# INLINE basicLength #-} - basicLength = coerce (G.basicLength @V.Vector @a) - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice = coerce (G.basicUnsafeSlice @V.Vector @a) - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM = coerce (G.basicUnsafeIndexM @V.Vector @a) - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy = coerce (G.basicUnsafeCopy @V.Vector @a) - {-# INLINE elemseq #-} - elemseq _ = seq - --- See NOTE: [GND for strict vector] --- --- Deriving strategies are only available since 8.2. So we can't use --- deriving newtype until we drop support for 8.0 -instance Eq a => Eq (Vector a) where - {-# INLINE (==) #-} - (==) = coerce ((==) @(V.Vector a)) - --- See NOTE: [GND for strict vector] -instance Ord a => Ord (Vector a) where - {-# INLINE compare #-} - compare = coerce (compare @(V.Vector a)) - {-# INLINE (<) #-} - (<) = coerce ((<) @(V.Vector a)) - {-# INLINE (<=) #-} - (<=) = coerce ((<=) @(V.Vector a)) - {-# INLINE (>) #-} - (>) = coerce ((>) @(V.Vector a)) - {-# INLINE (>=) #-} - (>=) = coerce ((>=) @(V.Vector a)) - -instance Eq1 Vector where - {-# INLINE liftEq #-} - liftEq = eqBy - -instance Ord1 Vector where - {-# INLINE liftCompare #-} - liftCompare = cmpBy - -instance Functor Vector where - {-# INLINE fmap #-} - fmap = map - - {-# INLINE (<$) #-} - (<$) = map . const - -instance Monad Vector where - {-# INLINE return #-} - return = Applicative.pure - - {-# INLINE (>>=) #-} - (>>=) = flip concatMap - --- | @since 0.13.2.0 -instance Fail.MonadFail Vector where - {-# INLINE fail #-} - fail _ = empty - -instance MonadPlus Vector where - {-# INLINE mzero #-} - mzero = empty - - {-# INLINE mplus #-} - mplus = (++) - -instance MonadZip Vector where - {-# INLINE mzip #-} - mzip = zip - - {-# INLINE mzipWith #-} - mzipWith = zipWith - - {-# INLINE munzip #-} - munzip = unzip - --- | This instance has the same semantics as the one for lists. --- --- @since 0.13.2.0 -instance MonadFix Vector where - -- We take care to dispose of v0 as soon as possible (see headM docs). - -- - -- It's perfectly safe to use non-monadic indexing within generate - -- call since intermediate vector won't be created until result's - -- value is demanded. - {-# INLINE mfix #-} - mfix f - | null v0 = empty - -- We take first element of resulting vector from v0 and create - -- rest using generate. Note that cons should fuse with generate - | otherwise = runST $ do - h <- headM v0 - return $ cons h $ - generate (lv0 - 1) $ - \i -> fix (\a -> f a ! (i + 1)) - where - -- Used to calculate size of resulting vector - v0 = fix (f . head) - !lv0 = length v0 - -instance Applicative.Applicative Vector where - {-# INLINE pure #-} - pure = singleton - - {-# INLINE (<*>) #-} - (<*>) = ap - -instance Applicative.Alternative Vector where - {-# INLINE empty #-} - empty = empty - - {-# INLINE (<|>) #-} - (<|>) = (++) - -instance Traversable.Traversable Vector where - {-# INLINE traverse #-} - traverse = traverse - - {-# INLINE mapM #-} - mapM = mapM - - {-# INLINE sequence #-} - sequence = sequence + ( Eq(..), Ord(..), Num, Enum, Monoid, Monad, Bool, Ordering(..), Int, Maybe, Either + , id) -- Length information -- ------------------ @@ -2549,67 +2346,6 @@ iforA_ :: (Applicative f) iforA_ = G.iforA_ --- Conversions - Lazy vectors --- ----------------------------- - --- | /O(1)/ Convert strict array to lazy array -toLazy :: Vector a -> V.Vector a -toLazy (Vector v) = v - --- | /O(n)/ Convert lazy array to strict array. This function reduces --- each element of vector to WHNF. -fromLazy :: V.Vector a -> Vector a -fromLazy vec = liftRnf (`seq` ()) v `seq` v where v = Vector vec - - --- Conversions - Arrays --- ----------------------------- - --- | /O(n)/ Convert an array to a vector and reduce each element to WHNF. --- --- @since 0.13.2.0 -fromArray :: Array a -> Vector a -{-# INLINE fromArray #-} -fromArray arr = liftRnf (`seq` ()) vec `seq` vec - where - vec = Vector $ V.fromArray arr - --- | /O(n)/ Convert a vector to an array. --- --- @since 0.13.2.0 -toArray :: Vector a -> Array a -{-# INLINE toArray #-} -toArray (Vector v) = V.toArray v - --- | /O(1)/ Extract the underlying `Array`, offset where vector starts and the --- total number of elements in the vector. Below property always holds: --- --- > let (array, offset, len) = toArraySlice v --- > v === unsafeFromArraySlice len offset array --- --- @since 0.13.2.0 -toArraySlice :: Vector a -> (Array a, Int, Int) -{-# INLINE toArraySlice #-} -toArraySlice (Vector v) = V.toArraySlice v - - --- | /O(n)/ Convert an array slice to a vector and reduce each element to WHNF. --- --- This function is very unsafe, because constructing an invalid --- vector can yield almost all other safe functions in this module --- unsafe. These are equivalent: --- --- > unsafeFromArraySlice len offset === unsafeTake len . unsafeDrop offset . fromArray --- --- @since 0.13.2.0 -unsafeFromArraySlice :: - Array a -- ^ Immutable boxed array. - -> Int -- ^ Offset - -> Int -- ^ Length - -> Vector a -{-# INLINE unsafeFromArraySlice #-} -unsafeFromArraySlice arr offset len = liftRnf (`seq` ()) vec `seq` vec - where vec = Vector (V.unsafeFromArraySlice arr offset len) @@ -2687,4 +2423,4 @@ copy = G.copy -- $setup -- >>> :set -Wno-type-defaults --- >>> import Prelude (Char, String, Bool(True, False), min, max, fst, even, undefined, Ord(..)) +-- >>> import Prelude (Char, String, Bool(..), min, max, fst, even, undefined, Ord(..), (<>), Num(..),($)) diff --git a/vector/src/Data/Vector/Strict/Mutable.hs b/vector/src/Data/Vector/Strict/Mutable.hs index 7af79a75..6ddc1663 100644 --- a/vector/src/Data/Vector/Strict/Mutable.hs +++ b/vector/src/Data/Vector/Strict/Mutable.hs @@ -6,6 +6,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE PatternSynonyms #-} -- | -- Module : Data.Vector.Strict.Mutable -- Copyright : (c) Roman Leshchinskiy 2008-2010 @@ -24,7 +25,8 @@ -- are set to ⊥. module Data.Vector.Strict.Mutable ( -- * Mutable boxed vectors - MVector(MVector), IOVector, STVector, + MVector, IOVector, STVector, + pattern MVector, -- * Accessors @@ -76,52 +78,21 @@ module Data.Vector.Strict.Mutable ( PrimMonad, PrimState, RealWorld ) where -import Data.Coerce import qualified Data.Vector.Generic.Mutable as G -import qualified Data.Vector.Mutable as MV -import Data.Primitive.Array +import qualified Data.Vector.Mutable as MV +import Data.Vector.Strict.Mutable.Unsafe + (MVector,IOVector,STVector,toLazy,fromLazy,toMutableArray,fromMutableArray) +import qualified Data.Vector.Strict.Mutable.Unsafe as U import Control.Monad.Primitive -import Prelude - ( Ord, Monad(..), Bool, Int, Maybe, Ordering(..) - , return, ($), (<$>) ) +import Prelude ( Ord, Bool, Int, Maybe, Ordering(..)) #include "vector.h" -type role MVector nominal representational - --- | Mutable boxed vectors keyed on the monad they live in ('IO' or @'ST' s@). -newtype MVector s a = MVector (MV.MVector s a) - -type IOVector = MVector RealWorld -type STVector s = MVector s - -instance G.MVector MVector a where - {-# INLINE basicLength #-} - basicLength = coerce (G.basicLength @MV.MVector @a) - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice = coerce (G.basicUnsafeSlice @MV.MVector @a) - {-# INLINE basicOverlaps #-} - basicOverlaps = coerce (G.basicOverlaps @MV.MVector @a) - {-# INLINE basicUnsafeNew #-} - basicUnsafeNew = coerce (G.basicUnsafeNew @MV.MVector @a) - {-# INLINE basicInitialize #-} - -- initialization is unnecessary for boxed vectors - basicInitialize _ = return () - {-# INLINE basicUnsafeReplicate #-} - basicUnsafeReplicate n !x = coerce (G.basicUnsafeReplicate @MV.MVector @a) n x - {-# INLINE basicUnsafeRead #-} - basicUnsafeRead = coerce (G.basicUnsafeRead @MV.MVector @a) - {-# INLINE basicUnsafeWrite #-} - basicUnsafeWrite vec j !x = (coerce (G.basicUnsafeWrite @MV.MVector @a)) vec j x - - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy = coerce (G.basicUnsafeCopy @MV.MVector @a) - - {-# INLINE basicUnsafeMove #-} - basicUnsafeMove = coerce (G.basicUnsafeMove @MV.MVector @a) - {-# INLINE basicClear #-} - basicClear = coerce (G.basicClear @MV.MVector @a) +pattern MVector :: MV.MVector s a -> MVector s a +pattern MVector v = U.MVector v +{-# COMPLETE MVector #-} +{-# DEPRECATED MVector "Use MVector constructor exported from \"Data.Vector.Strict.Unsafe\"" #-} -- Length information @@ -769,44 +740,6 @@ ifoldrM' :: (PrimMonad m) => (Int -> a -> b -> m b) -> b -> MVector (PrimState m {-# INLINE ifoldrM' #-} ifoldrM' = G.ifoldrM' --- Conversions - Lazy vectors --- ----------------------------- - --- | /O(1)/ Convert strict mutable vector to lazy mutable --- vector. Vectors will share mutable buffer -toLazy :: MVector s a -> MV.MVector s a -{-# INLINE toLazy #-} -toLazy (MVector vec) = vec - --- | /O(n)/ Convert lazy mutable vector to strict mutable --- vector. Vectors will share mutable buffer. This function evaluates --- vector elements to WHNF. -fromLazy :: PrimMonad m => MV.MVector (PrimState m) a -> m (MVector (PrimState m) a) -fromLazy mvec = stToPrim $ do - G.foldM' (\_ !_ -> return ()) () mvec - return $ MVector mvec - - --- Conversions - Arrays --- ----------------------------- - --- | /O(n)/ Make a copy of a mutable array to a new mutable --- vector. All elements of a vector are evaluated to WHNF --- --- @since 0.13.2.0 -fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (PrimState m) a) -{-# INLINE fromMutableArray #-} -fromMutableArray marr = stToPrim $ do - mvec <- MVector <$> MV.fromMutableArray marr - foldM' (\_ !_ -> return ()) () mvec - return mvec - --- | /O(n)/ Make a copy of a mutable vector into a new mutable array. --- --- @since 0.13.2.0 -toMutableArray :: PrimMonad m => MVector (PrimState m) a -> m (MutableArray (PrimState m) a) -{-# INLINE toMutableArray #-} -toMutableArray (MVector v) = MV.toMutableArray v -- $setup --- >>> import Prelude (Integer,Num(..)) +-- >>> import Prelude (Integer,Num(..),($)) diff --git a/vector/src/Data/Vector/Strict/Mutable/Unsafe.hs b/vector/src/Data/Vector/Strict/Mutable/Unsafe.hs new file mode 100644 index 00000000..229c524b --- /dev/null +++ b/vector/src/Data/Vector/Strict/Mutable/Unsafe.hs @@ -0,0 +1,111 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE RoleAnnotations #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE ScopedTypeVariables #-} +-- | +-- This module exposes internal representation of mutable strict boxed +-- vector and functions that work on that representation directly (as +-- opposed to using 'G.MVector' API. +-- +-- Note that working with internal representation of vector is +-- generally unsafe and may violate memory safety +module Data.Vector.Strict.Mutable.Unsafe + ( MVector(..) + , IOVector + , STVector + -- * Conversions + , toLazy + , fromLazy + , toMutableArray + , fromMutableArray + ) where + +import Data.Coerce +import qualified Data.Vector.Generic.Mutable as G +import qualified Data.Vector.Mutable as MV +import Data.Primitive.Array +import Control.Monad.Primitive + +import Prelude ( Monad(..), return, ($), (<$>) ) + +#include "vector.h" + +type role MVector nominal representational + +-- | Mutable boxed vectors keyed on the monad they live in ('IO' or @'ST' s@). +newtype MVector s a = MVector (MV.MVector s a) + +type IOVector = MVector RealWorld +type STVector s = MVector s + +instance G.MVector MVector a where + {-# INLINE basicLength #-} + basicLength = coerce (G.basicLength @MV.MVector @a) + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice = coerce (G.basicUnsafeSlice @MV.MVector @a) + {-# INLINE basicOverlaps #-} + basicOverlaps = coerce (G.basicOverlaps @MV.MVector @a) + {-# INLINE basicUnsafeNew #-} + basicUnsafeNew = coerce (G.basicUnsafeNew @MV.MVector @a) + {-# INLINE basicInitialize #-} + -- initialization is unnecessary for boxed vectors + basicInitialize _ = return () + {-# INLINE basicUnsafeReplicate #-} + basicUnsafeReplicate n !x = coerce (G.basicUnsafeReplicate @MV.MVector @a) n x + {-# INLINE basicUnsafeRead #-} + basicUnsafeRead = coerce (G.basicUnsafeRead @MV.MVector @a) + {-# INLINE basicUnsafeWrite #-} + basicUnsafeWrite vec j !x = (coerce (G.basicUnsafeWrite @MV.MVector @a)) vec j x + + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy = coerce (G.basicUnsafeCopy @MV.MVector @a) + + {-# INLINE basicUnsafeMove #-} + basicUnsafeMove = coerce (G.basicUnsafeMove @MV.MVector @a) + {-# INLINE basicClear #-} + basicClear = coerce (G.basicClear @MV.MVector @a) + + + +-- Conversions - Lazy vectors +-- ----------------------------- + +-- | /O(1)/ Convert strict mutable vector to lazy mutable +-- vector. Vectors will share mutable buffer +toLazy :: MVector s a -> MV.MVector s a +{-# INLINE toLazy #-} +toLazy (MVector vec) = vec + +-- | /O(n)/ Convert lazy mutable vector to strict mutable +-- vector. Vectors will share mutable buffer. This function evaluates +-- vector elements to WHNF. +fromLazy :: PrimMonad m => MV.MVector (PrimState m) a -> m (MVector (PrimState m) a) +fromLazy mvec = stToPrim $ do + G.foldM' (\_ !_ -> return ()) () mvec + return $ MVector mvec + + +-- Conversions - Arrays +-- ----------------------------- + +-- | /O(n)/ Make a copy of a mutable array to a new mutable +-- vector. All elements of a vector are evaluated to WHNF +-- +-- @since 0.13.2.0 +fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (PrimState m) a) +{-# INLINE fromMutableArray #-} +fromMutableArray marr = stToPrim $ do + mvec <- MVector <$> MV.fromMutableArray marr + G.foldM' (\_ !_ -> return ()) () mvec + return mvec + +-- | /O(n)/ Make a copy of a mutable vector into a new mutable array. +-- +-- @since 0.13.2.0 +toMutableArray :: PrimMonad m => MVector (PrimState m) a -> m (MutableArray (PrimState m) a) +{-# INLINE toMutableArray #-} +toMutableArray (MVector v) = MV.toMutableArray v diff --git a/vector/src/Data/Vector/Strict/Unsafe.hs b/vector/src/Data/Vector/Strict/Unsafe.hs new file mode 100644 index 00000000..1ef8b561 --- /dev/null +++ b/vector/src/Data/Vector/Strict/Unsafe.hs @@ -0,0 +1,308 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +-- | +-- This module exposes internal representation of strict boxed vector +-- and functions that work on that representation directly (as opposed +-- to using 'G.Vector' API. +-- +-- Note that working with internal representation of vector is +-- generally unsafe and may violate memory safety +module Data.Vector.Strict.Unsafe + ( Vector(..) + -- * Vector conversions + , toLazy + , fromLazy + -- * Array conversions + , toArray + , fromArray + , toArraySlice + , unsafeFromArraySlice + ) where + + +import Data.Coerce +import Data.Vector.Strict.Mutable.Unsafe ( MVector(..) ) +import Data.Primitive.Array +import qualified Data.Vector.Generic as G +import Data.Vector.Generic ((!)) +import qualified Data.Vector as V + +import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf)) + +import Control.Monad ( MonadPlus(..), ap ) +import Control.Monad.ST ( runST ) +import qualified Control.Monad.Fail as Fail +import Control.Monad.Fix ( MonadFix (mfix) ) +import Control.Monad.Zip +import Data.Function ( fix ) + +import Prelude + ( Eq(..), Ord(..), Monoid, Functor, Monad, Show, Int + , return, showsPrec, fmap, otherwise, flip, const + , (>>=), (+), (-), (.), ($), seq) + +import Data.Functor.Classes (Eq1 (..), Ord1 (..), Read1 (..), Show1 (..)) +import Data.Data ( Data(..) ) +import Text.Read ( Read(..), readListPrecDefault ) +import Data.Semigroup ( Semigroup(..) ) + +import qualified Control.Applicative as Applicative +import qualified Data.Foldable as Foldable +import qualified Data.Traversable as Traversable + +import qualified GHC.Exts as Exts (IsList(..)) + +-- | Strict boxed vectors, supporting efficient slicing. +newtype Vector a = Vector (V.Vector a) + deriving (Foldable.Foldable, Semigroup, Monoid) + +-- NOTE: [GND for strict vector] +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- +-- Strict boxed vectors (both mutable an immutable) are newtypes over +-- lazy ones. This makes it possible to use GND to derive instances. +-- However one must take care to preserve strictness since Vector +-- instance for lazy vectors would be used. +-- +-- In general it's OK to derive instances where vectors are passed as +-- parameters (e.g. Eq, Ord) and not OK to derive ones where new +-- vector is created (e.g. Read, Functor) + +liftRnfV :: (a -> ()) -> Vector a -> () +liftRnfV elemRnf = G.foldl' (\_ -> elemRnf) () + +instance NFData a => NFData (Vector a) where + rnf = liftRnfV rnf + {-# INLINEABLE rnf #-} + +-- | @since 0.13.2.0 +instance NFData1 Vector where + liftRnf = liftRnfV + {-# INLINEABLE liftRnf #-} + +instance Show a => Show (Vector a) where + showsPrec = G.showsPrec + +instance Read a => Read (Vector a) where + readPrec = G.readPrec + readListPrec = readListPrecDefault + +instance Show1 Vector where + liftShowsPrec = G.liftShowsPrec + +instance Read1 Vector where + liftReadsPrec = G.liftReadsPrec + +instance Exts.IsList (Vector a) where + type Item (Vector a) = a + fromList = G.fromList + fromListN = G.fromListN + toList = G.toList + +instance Data a => Data (Vector a) where + gfoldl = G.gfoldl + toConstr _ = G.mkVecConstr "Data.Vector.Strict.Vector" + gunfold = G.gunfold + dataTypeOf _ = G.mkVecType "Data.Vector.Strict.Vector" + dataCast1 = G.dataCast + +type instance G.Mutable Vector = MVector + +instance G.Vector Vector a where + {-# INLINE basicUnsafeFreeze #-} + basicUnsafeFreeze = coerce (G.basicUnsafeFreeze @V.Vector @a) + {-# INLINE basicUnsafeThaw #-} + basicUnsafeThaw = coerce (G.basicUnsafeThaw @V.Vector @a) + {-# INLINE basicLength #-} + basicLength = coerce (G.basicLength @V.Vector @a) + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice = coerce (G.basicUnsafeSlice @V.Vector @a) + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM = coerce (G.basicUnsafeIndexM @V.Vector @a) + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy = coerce (G.basicUnsafeCopy @V.Vector @a) + {-# INLINE elemseq #-} + elemseq _ = seq + +-- See NOTE: [GND for strict vector] +-- +-- Deriving strategies are only available since 8.2. So we can't use +-- deriving newtype until we drop support for 8.0 +instance Eq a => Eq (Vector a) where + {-# INLINE (==) #-} + (==) = coerce ((==) @(V.Vector a)) + +-- See NOTE: [GND for strict vector] +instance Ord a => Ord (Vector a) where + {-# INLINE compare #-} + compare = coerce (compare @(V.Vector a)) + {-# INLINE (<) #-} + (<) = coerce ((<) @(V.Vector a)) + {-# INLINE (<=) #-} + (<=) = coerce ((<=) @(V.Vector a)) + {-# INLINE (>) #-} + (>) = coerce ((>) @(V.Vector a)) + {-# INLINE (>=) #-} + (>=) = coerce ((>=) @(V.Vector a)) + +instance Eq1 Vector where + {-# INLINE liftEq #-} + liftEq = G.eqBy + +instance Ord1 Vector where + {-# INLINE liftCompare #-} + liftCompare = G.cmpBy + +instance Functor Vector where + {-# INLINE fmap #-} + fmap = G.map + + {-# INLINE (<$) #-} + (<$) = G.map . const + +instance Monad Vector where + {-# INLINE return #-} + return = Applicative.pure + + {-# INLINE (>>=) #-} + (>>=) = flip G.concatMap + +-- | @since 0.13.2.0 +instance Fail.MonadFail Vector where + {-# INLINE fail #-} + fail _ = G.empty + +instance MonadPlus Vector where + {-# INLINE mzero #-} + mzero = G.empty + + {-# INLINE mplus #-} + mplus = (G.++) + +instance MonadZip Vector where + {-# INLINE mzip #-} + mzip = G.zip + + {-# INLINE mzipWith #-} + mzipWith = G.zipWith + + {-# INLINE munzip #-} + munzip = G.unzip + +-- | This instance has the same semantics as the one for lists. +-- +-- @since 0.13.2.0 +instance MonadFix Vector where + -- We take care to dispose of v0 as soon as possible (see headM docs). + -- + -- It's perfectly safe to use non-monadic indexing within generate + -- call since intermediate vector won't be created until result's + -- value is demanded. + {-# INLINE mfix #-} + mfix f + | G.null v0 = G.empty + -- We take first element of resulting vector from v0 and create + -- rest using generate. Note that cons should fuse with generate + | otherwise = runST $ do + h <- G.headM v0 + return $ G.cons h $ + G.generate (lv0 - 1) $ + \i -> fix (\a -> f a ! (i + 1)) + where + -- Used to calculate size of resulting vector + v0 = fix (f . G.head) + !lv0 = G.length v0 + +instance Applicative.Applicative Vector where + {-# INLINE pure #-} + pure = G.singleton + + {-# INLINE (<*>) #-} + (<*>) = ap + +instance Applicative.Alternative Vector where + {-# INLINE empty #-} + empty = G.empty + + {-# INLINE (<|>) #-} + (<|>) = (G.++) + +instance Traversable.Traversable Vector where + {-# INLINE traverse #-} + traverse = G.traverse + + {-# INLINE mapM #-} + mapM = G.mapM + + {-# INLINE sequence #-} + sequence = G.sequence + + +-- Conversions - Lazy vectors +-- ----------------------------- + +-- | /O(1)/ Convert strict array to lazy array +toLazy :: Vector a -> V.Vector a +toLazy (Vector v) = v + +-- | /O(n)/ Convert lazy array to strict array. This function reduces +-- each element of vector to WHNF. +fromLazy :: V.Vector a -> Vector a +fromLazy vec = liftRnf (`seq` ()) v `seq` v where v = Vector vec + + +-- Conversions - Arrays +-- ----------------------------- + +-- | /O(n)/ Convert an array to a vector and reduce each element to WHNF. +-- +-- @since 0.13.2.0 +fromArray :: Array a -> Vector a +{-# INLINE fromArray #-} +fromArray arr = liftRnf (`seq` ()) vec `seq` vec + where + vec = Vector $ V.fromArray arr + +-- | /O(n)/ Convert a vector to an array. +-- +-- @since 0.13.2.0 +toArray :: Vector a -> Array a +{-# INLINE toArray #-} +toArray (Vector v) = V.toArray v + +-- | /O(1)/ Extract the underlying `Array`, offset where vector starts and the +-- total number of elements in the vector. Below property always holds: +-- +-- > let (array, offset, len) = toArraySlice v +-- > v === unsafeFromArraySlice len offset array +-- +-- @since 0.13.2.0 +toArraySlice :: Vector a -> (Array a, Int, Int) +{-# INLINE toArraySlice #-} +toArraySlice (Vector v) = V.toArraySlice v + + +-- | /O(n)/ Convert an array slice to a vector and reduce each element to WHNF. +-- +-- This function is very unsafe, because constructing an invalid +-- vector can yield almost all other safe functions in this module +-- unsafe. These are equivalent: +-- +-- > unsafeFromArraySlice len offset === unsafeTake len . unsafeDrop offset . fromArray +-- +-- @since 0.13.2.0 +unsafeFromArraySlice :: + Array a -- ^ Immutable boxed array. + -> Int -- ^ Offset + -> Int -- ^ Length + -> Vector a +{-# INLINE unsafeFromArraySlice #-} +unsafeFromArraySlice arr offset len = liftRnf (`seq` ()) vec `seq` vec + where vec = Vector (V.unsafeFromArraySlice arr offset len) diff --git a/vector/src/Data/Vector/Unboxed.hs b/vector/src/Data/Vector/Unboxed.hs index 980c5335..f413c020 100644 --- a/vector/src/Data/Vector/Unboxed.hs +++ b/vector/src/Data/Vector/Unboxed.hs @@ -68,7 +68,10 @@ -- @ module Data.Vector.Unboxed ( -- * Unboxed vectors - Vector(V_UnboxAs, V_UnboxViaPrim, V_UnboxViaStorable,V_DoNotUnboxLazy,V_DoNotUnboxStrict,V_DoNotUnboxNormalForm), + Vector(V_UnboxAs, V_UnboxViaPrim, V_UnboxViaStorable,V_DoNotUnboxLazy,V_DoNotUnboxStrict,V_DoNotUnboxNormalForm, + V_Int,V_Int8,V_Int16,V_Int32,V_Int64,V_Word,V_Word8,V_Word16,V_Word32,V_Word64,V_Float,V_Double, + V_Char,V_Bool,V_Complex,V_Identity,V_Down,V_Dual,V_Sum,V_Product,V_Min,V_Max,V_First,V_Last, + V_WrappedMonoid,V_Arg,V_Any,V_All,V_Const,V_Alt,V_Compose), MVector(..), Unbox, -- * Accessors @@ -212,21 +215,22 @@ module Data.Vector.Unboxed ( freeze, thaw, copy, unsafeFreeze, unsafeThaw, unsafeCopy, -- ** Deriving via - UnboxViaPrim(..), - As(..), - IsoUnbox(..), - UnboxViaStorable(..), + U.UnboxViaPrim(..), + U.As(..), + U.IsoUnbox(..), + U.UnboxViaStorable(..), -- *** /Lazy/ boxing - DoNotUnboxLazy(..), + U.DoNotUnboxLazy(..), -- *** /Strict/ boxing - DoNotUnboxStrict(..), - DoNotUnboxNormalForm(..) + U.DoNotUnboxStrict(..), + U.DoNotUnboxNormalForm(..) ) where import Control.Applicative (Applicative) -import Data.Vector.Unboxed.Base +import Data.Vector.Unboxed.Unsafe (Vector,MVector,Unbox) +import qualified Data.Vector.Unboxed.Unsafe as U import qualified Data.Vector.Generic as G import qualified Data.Vector.Fusion.Bundle as Bundle import Data.Vector.Fusion.Util ( delayed_min ) @@ -2175,7 +2179,7 @@ copy = G.copy -- | /O(1)/ Zip 2 vectors. zip :: (Unbox a, Unbox b) => Vector a -> Vector b -> Vector (a, b) {-# INLINE_FUSED zip #-} -zip as bs = V_2 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) +zip as bs = U.V_2 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) where len = length as `delayed_min` length bs {-# RULES "stream/zip [Vector.Unboxed]" forall as bs . G.stream (zip as bs) = Bundle.zipWith (,) (G.stream as) @@ -2185,14 +2189,14 @@ zip as bs = V_2 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) unzip :: (Unbox a, Unbox b) => Vector (a, b) -> (Vector a, Vector b) {-# INLINE unzip #-} -unzip (V_2 _ as bs) = (as, bs) +unzip (U.V_2 _ as bs) = (as, bs) -- | /O(1)/ Zip 3 vectors. zip3 :: (Unbox a, Unbox b, Unbox c) => Vector a -> Vector b -> Vector c -> Vector (a, b, c) {-# INLINE_FUSED zip3 #-} -zip3 as bs cs = V_3 len (unsafeSlice 0 len as) +zip3 as bs cs = U.V_3 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) (unsafeSlice 0 len cs) where @@ -2207,7 +2211,7 @@ unzip3 :: (Unbox a, Unbox b, Unbox c) => Vector (a, b, c) -> (Vector a, Vector b, Vector c) {-# INLINE unzip3 #-} -unzip3 (V_3 _ as bs cs) = (as, bs, cs) +unzip3 (U.V_3 _ as bs cs) = (as, bs, cs) -- | /O(1)/ Zip 4 vectors. zip4 :: (Unbox a, Unbox b, Unbox c, Unbox d) => Vector a -> @@ -2215,7 +2219,7 @@ zip4 :: (Unbox a, Unbox b, Unbox c, Unbox d) => Vector a -> Vector c -> Vector d -> Vector (a, b, c, d) {-# INLINE_FUSED zip4 #-} -zip4 as bs cs ds = V_4 len (unsafeSlice 0 len as) +zip4 as bs cs ds = U.V_4 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) (unsafeSlice 0 len cs) (unsafeSlice 0 len ds) @@ -2239,7 +2243,7 @@ unzip4 :: (Unbox a, Vector c, Vector d) {-# INLINE unzip4 #-} -unzip4 (V_4 _ as bs cs ds) = (as, bs, cs, ds) +unzip4 (U.V_4 _ as bs cs ds) = (as, bs, cs, ds) -- | /O(1)/ Zip 5 vectors. zip5 :: (Unbox a, @@ -2252,7 +2256,7 @@ zip5 :: (Unbox a, Vector d -> Vector e -> Vector (a, b, c, d, e) {-# INLINE_FUSED zip5 #-} -zip5 as bs cs ds es = V_5 len (unsafeSlice 0 len as) +zip5 as bs cs ds es = U.V_5 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) (unsafeSlice 0 len cs) (unsafeSlice 0 len ds) @@ -2285,7 +2289,7 @@ unzip5 :: (Unbox a, Vector d, Vector e) {-# INLINE unzip5 #-} -unzip5 (V_5 _ as bs cs ds es) = (as, bs, cs, ds, es) +unzip5 (U.V_5 _ as bs cs ds es) = (as, bs, cs, ds, es) -- | /O(1)/ Zip 6 vectors. zip6 :: (Unbox a, @@ -2300,7 +2304,7 @@ zip6 :: (Unbox a, Vector e -> Vector f -> Vector (a, b, c, d, e, f) {-# INLINE_FUSED zip6 #-} -zip6 as bs cs ds es fs = V_6 len (unsafeSlice 0 len as) +zip6 as bs cs ds es fs = U.V_6 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) (unsafeSlice 0 len cs) (unsafeSlice 0 len ds) @@ -2339,7 +2343,7 @@ unzip6 :: (Unbox a, Vector e, Vector f) {-# INLINE unzip6 #-} -unzip6 (V_6 _ as bs cs ds es fs) = (as, bs, cs, ds, es, fs) +unzip6 (U.V_6 _ as bs cs ds es fs) = (as, bs, cs, ds, es, fs) -- $setup diff --git a/vector/src/Data/Vector/Unboxed/Base.hs b/vector/src/Data/Vector/Unboxed/Base.hs index d962bc71..fc4cb5e3 100644 --- a/vector/src/Data/Vector/Unboxed/Base.hs +++ b/vector/src/Data/Vector/Unboxed/Base.hs @@ -1,1926 +1,6 @@ -{-# LANGUAGE BangPatterns #-} -{-# LANGUAGE CPP #-} -{-# LANGUAGE DefaultSignatures #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE GeneralizedNewtypeDeriving #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE PolyKinds #-} -{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE TypeApplications #-} -{-# LANGUAGE DerivingVia #-} {-# OPTIONS_HADDOCK hide #-} --- | --- Module : Data.Vector.Unboxed.Base --- Copyright : (c) Roman Leshchinskiy 2009-2010 --- Alexey Kuleshevich 2020-2022 --- Aleksey Khudyakov 2020-2022 --- Andrew Lelechenko 2020-2022 --- License : BSD-style --- --- Maintainer : Haskell Libraries Team --- Stability : experimental --- Portability : non-portable --- --- Adaptive unboxed vectors: basic implementation. - -module Data.Vector.Unboxed.Base ( - MVector(..), IOVector, STVector, Vector(..), Unbox, - UnboxViaPrim(..), UnboxViaStorable(..), As(..), IsoUnbox(..), - DoNotUnboxLazy(..), DoNotUnboxNormalForm(..), DoNotUnboxStrict(..) -) where - -import qualified Data.Vector.Generic as G -import qualified Data.Vector.Generic.Mutable as M -import qualified Data.Vector as B -import qualified Data.Vector.Strict as S -import qualified Data.Vector.Storable as St - -import qualified Data.Vector.Primitive as P - -import Control.Applicative (Const(..)) - -import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf), force) - -import Control.Monad.Primitive -import Control.Monad ( liftM ) - -import Data.Functor.Identity -import Data.Functor.Compose -import Data.Word ( Word8, Word16, Word32, Word64 ) -import Data.Int ( Int8, Int16, Int32, Int64 ) -import Data.Complex -import Data.Monoid (Dual(..),Sum(..),Product(..),All(..),Any(..)) -import Data.Monoid (Alt(..)) -import Data.Semigroup (Min(..),Max(..),First(..),Last(..),WrappedMonoid(..),Arg(..)) -import Data.Data ( Data(..) ) -import GHC.Exts ( Down(..) ) -import GHC.Generics -import Data.Coerce -import Data.Kind (Type) - -#include "vector.h" - -data family MVector s a -data family Vector a - -type IOVector = MVector RealWorld -type STVector s = MVector s - -type instance G.Mutable Vector = MVector - -class (G.Vector Vector a, M.MVector MVector a) => Unbox a - -instance NFData (Vector a) where rnf !_ = () -instance NFData (MVector s a) where rnf !_ = () - --- | @since 0.12.1.0 -instance NFData1 Vector where - liftRnf _ !_ = () --- | @since 0.12.1.0 -instance NFData1 (MVector s) where - liftRnf _ !_ = () - - -instance (Data a, Unbox a) => Data (Vector a) where - gfoldl = G.gfoldl - toConstr _ = G.mkVecConstr "Data.Vector.Unboxed.Vector" - gunfold = G.gunfold - dataTypeOf _ = G.mkVecType "Data.Vector.Unboxed.Vector" - dataCast1 = G.dataCast - --- ---- --- Unit --- ---- - -newtype instance MVector s () = MV_Unit Int -newtype instance Vector () = V_Unit Int - -instance Unbox () - -instance M.MVector MVector () where - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicOverlaps #-} - {-# INLINE basicUnsafeNew #-} - {-# INLINE basicInitialize #-} - {-# INLINE basicUnsafeRead #-} - {-# INLINE basicUnsafeWrite #-} - {-# INLINE basicClear #-} - {-# INLINE basicSet #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE basicUnsafeGrow #-} - - basicLength (MV_Unit n) = n - - basicUnsafeSlice _ m (MV_Unit _) = MV_Unit m - - basicOverlaps _ _ = False - - basicUnsafeNew n = return (MV_Unit n) - - -- Nothing to initialize - basicInitialize _ = return () - - basicUnsafeRead (MV_Unit _) _ = return () - - basicUnsafeWrite (MV_Unit _) _ () = return () - - basicClear _ = return () - - basicSet (MV_Unit _) () = return () - - basicUnsafeCopy (MV_Unit _) (MV_Unit _) = return () - - basicUnsafeGrow (MV_Unit n) m = return $ MV_Unit (n+m) - -instance G.Vector Vector () where - {-# INLINE basicUnsafeFreeze #-} - basicUnsafeFreeze (MV_Unit n) = return $ V_Unit n - - {-# INLINE basicUnsafeThaw #-} - basicUnsafeThaw (V_Unit n) = return $ MV_Unit n - - {-# INLINE basicLength #-} - basicLength (V_Unit n) = n - - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice _ m (V_Unit _) = V_Unit m - - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM (V_Unit _) _ = return () - - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_Unit _) (V_Unit _) = return () - - {-# INLINE elemseq #-} - elemseq _ = seq - - --- --------------- --- Primitive types --- --------------- - --- | Newtype wrapper which allows to derive unboxed vector in term of --- primitive vectors using @DerivingVia@ mechanism. This is mostly --- used as illustration of use of @DerivingVia@ for vector, see examples below. --- --- First is rather straightforward: we define newtype and use GND to --- derive 'P.Prim' instance. Newtype instances should be defined --- manually. Then we use deriving via to define necessary instances. --- --- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia -XMultiParamTypeClasses --- >>> -- Needed to derive Prim --- >>> :set -XGeneralizedNewtypeDeriving -XDataKinds -XUnboxedTuples -XPolyKinds --- >>> --- >>> import qualified Data.Vector.Generic as VG --- >>> import qualified Data.Vector.Generic.Mutable as VGM --- >>> import qualified Data.Vector.Primitive as VP --- >>> import qualified Data.Vector.Unboxed as VU --- >>> --- >>> newtype Foo = Foo Int deriving VP.Prim --- >>> --- >>> newtype instance VU.MVector s Foo = MV_Foo (VP.MVector s Foo) --- >>> newtype instance VU.Vector Foo = V_Foo (VP.Vector Foo) --- >>> deriving via (VU.UnboxViaPrim Foo) instance VGM.MVector VU.MVector Foo --- >>> deriving via (VU.UnboxViaPrim Foo) instance VG.Vector VU.Vector Foo --- >>> instance VU.Unbox Foo --- --- Second example is essentially same but with a twist. Instead of --- using 'P.Prim' instance of data type, we use underlying instance of 'Int': --- --- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia -XMultiParamTypeClasses --- >>> --- >>> import qualified Data.Vector.Generic as VG --- >>> import qualified Data.Vector.Generic.Mutable as VGM --- >>> import qualified Data.Vector.Primitive as VP --- >>> import qualified Data.Vector.Unboxed as VU --- >>> --- >>> newtype Foo = Foo Int --- >>> --- >>> newtype instance VU.MVector s Foo = MV_Foo (VP.MVector s Int) --- >>> newtype instance VU.Vector Foo = V_Foo (VP.Vector Int) --- >>> deriving via (VU.UnboxViaPrim Int) instance VGM.MVector VU.MVector Foo --- >>> deriving via (VU.UnboxViaPrim Int) instance VG.Vector VU.Vector Foo --- >>> instance VU.Unbox Foo --- --- @since 0.13.0.0 -newtype UnboxViaPrim a = UnboxViaPrim a - -newtype instance MVector s (UnboxViaPrim a) = MV_UnboxViaPrim (P.MVector s a) -newtype instance Vector (UnboxViaPrim a) = V_UnboxViaPrim (P.Vector a) - -instance P.Prim a => M.MVector MVector (UnboxViaPrim a) where - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicOverlaps #-} - {-# INLINE basicUnsafeNew #-} - {-# INLINE basicInitialize #-} - {-# INLINE basicUnsafeReplicate #-} - {-# INLINE basicUnsafeRead #-} - {-# INLINE basicUnsafeWrite #-} - {-# INLINE basicClear #-} - {-# INLINE basicSet #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE basicUnsafeGrow #-} - basicLength = coerce $ M.basicLength @P.MVector @a - basicUnsafeSlice = coerce $ M.basicUnsafeSlice @P.MVector @a - basicOverlaps = coerce $ M.basicOverlaps @P.MVector @a - basicUnsafeNew = coerce $ M.basicUnsafeNew @P.MVector @a - basicInitialize = coerce $ M.basicInitialize @P.MVector @a - basicUnsafeReplicate = coerce $ M.basicUnsafeReplicate @P.MVector @a - basicUnsafeRead = coerce $ M.basicUnsafeRead @P.MVector @a - basicUnsafeWrite = coerce $ M.basicUnsafeWrite @P.MVector @a - basicClear = coerce $ M.basicClear @P.MVector @a - basicSet = coerce $ M.basicSet @P.MVector @a - basicUnsafeCopy = coerce $ M.basicUnsafeCopy @P.MVector @a - basicUnsafeMove = coerce $ M.basicUnsafeMove @P.MVector @a - basicUnsafeGrow = coerce $ M.basicUnsafeGrow @P.MVector @a - -instance P.Prim a => G.Vector Vector (UnboxViaPrim a) where - {-# INLINE basicUnsafeFreeze #-} - {-# INLINE basicUnsafeThaw #-} - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicUnsafeIndexM #-} - {-# INLINE elemseq #-} - basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @P.Vector @a - basicUnsafeThaw = coerce $ G.basicUnsafeThaw @P.Vector @a - basicLength = coerce $ G.basicLength @P.Vector @a - basicUnsafeSlice = coerce $ G.basicUnsafeSlice @P.Vector @a - basicUnsafeIndexM = coerce $ G.basicUnsafeIndexM @P.Vector @a - basicUnsafeCopy = coerce $ G.basicUnsafeCopy @P.Vector @a - elemseq _ = seq - --- | Isomorphism between type @a@ and its representation in unboxed --- vector @b@. Default instance coerces between generic --- representations of @a@ and @b@ which means they have same shape and --- corresponding fields could be coerced to each other. Note that this --- means it's possible to have fields that have different types: --- --- >>> :set -XMultiParamTypeClasses -XDeriveGeneric -XFlexibleInstances --- >>> import GHC.Generics (Generic) --- >>> import Data.Monoid --- >>> import qualified Data.Vector.Unboxed as VU --- >>> :{ --- data Foo a = Foo Int a --- deriving (Show,Generic) --- instance VU.IsoUnbox (Foo a) (Int, a) --- instance VU.IsoUnbox (Foo a) (Sum Int, Product a) --- :} --- --- @since 0.13.0.0 -class IsoUnbox a b where - -- | Convert value into it representation in unboxed vector. - toURepr :: a -> b - default toURepr :: (Generic a, Generic b, Coercible (Rep a ()) (Rep b ())) => a -> b - toURepr = to . idU . coerce . idU . from - -- | Convert value representation in unboxed vector back to value. - fromURepr :: b -> a - default fromURepr :: (Generic a, Generic b, Coercible (Rep b ()) (Rep a ())) => b -> a - fromURepr = to . idU . coerce . idU . from - -idU :: f () -> f () -idU = id - - --- | Newtype which allows to derive unbox instances for type @a@ which --- uses @b@ as underlying representation (usually tuple). Type @a@ and --- its representation @b@ are connected by type class --- 'IsoUnbox'. Here's example which uses explicit 'IsoUnbox' instance: --- --- --- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia --- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances --- >>> import qualified Data.Vector.Unboxed as VU --- >>> import qualified Data.Vector.Unboxed.Mutable as MVU --- >>> import qualified Data.Vector.Generic as VG --- >>> import qualified Data.Vector.Generic.Mutable as VGM --- >>> :{ --- data Foo a = Foo Int a --- deriving Show --- instance VU.IsoUnbox (Foo a) (Int,a) where --- toURepr (Foo i a) = (i,a) --- fromURepr (i,a) = Foo i a --- {-# INLINE toURepr #-} --- {-# INLINE fromURepr #-} --- newtype instance VU.MVector s (Foo a) = MV_Foo (VU.MVector s (Int, a)) --- newtype instance VU.Vector (Foo a) = V_Foo (VU.Vector (Int, a)) --- deriving via (Foo a `VU.As` (Int, a)) instance VU.Unbox a => VGM.MVector MVU.MVector (Foo a) --- deriving via (Foo a `VU.As` (Int, a)) instance VU.Unbox a => VG.Vector VU.Vector (Foo a) --- instance VU.Unbox a => VU.Unbox (Foo a) --- :} --- --- --- It's also possible to use generic-based instance for 'IsoUnbox' --- which should work for all product types. --- --- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances -XDeriveGeneric --- >>> :set -XDerivingVia --- >>> import qualified Data.Vector.Unboxed as VU --- >>> import qualified Data.Vector.Generic as VG --- >>> import qualified Data.Vector.Generic.Mutable as VGM --- >>> :{ --- data Bar a = Bar Int a --- deriving (Show,Generic) --- instance VU.IsoUnbox (Bar a) (Int,a) where --- newtype instance VU.MVector s (Bar a) = MV_Bar (VU.MVector s (Int, a)) --- newtype instance VU.Vector (Bar a) = V_Bar (VU.Vector (Int, a)) --- deriving via (Bar a `VU.As` (Int, a)) instance VU.Unbox a => VGM.MVector VU.MVector (Bar a) --- deriving via (Bar a `VU.As` (Int, a)) instance VU.Unbox a => VG.Vector VU.Vector (Bar a) --- instance VU.Unbox a => VU.Unbox (Bar a) --- :} --- --- @since 0.13.0.0 -newtype As (a :: Type) (b :: Type) = As a - -newtype instance MVector s (As a b) = MV_UnboxAs (MVector s b) -newtype instance Vector (As a b) = V_UnboxAs (Vector b) - -instance (IsoUnbox a b, Unbox b) => M.MVector MVector (As a b) where - -- Methods that just use underlying vector - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicOverlaps #-} - {-# INLINE basicUnsafeNew #-} - {-# INLINE basicInitialize #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE basicUnsafeMove #-} - {-# INLINE basicUnsafeGrow #-} - {-# INLINE basicClear #-} - basicLength = coerce $ M.basicLength @MVector @b - basicUnsafeSlice = coerce $ M.basicUnsafeSlice @MVector @b - basicOverlaps = coerce $ M.basicOverlaps @MVector @b - basicUnsafeNew = coerce $ M.basicUnsafeNew @MVector @b - basicInitialize = coerce $ M.basicInitialize @MVector @b - basicUnsafeCopy = coerce $ M.basicUnsafeCopy @MVector @b - basicUnsafeMove = coerce $ M.basicUnsafeMove @MVector @b - basicUnsafeGrow = coerce $ M.basicUnsafeGrow @MVector @b - basicClear = coerce $ M.basicClear @MVector @b - -- Conversion to/from underlying representation - {-# INLINE basicUnsafeReplicate #-} - {-# INLINE basicUnsafeRead #-} - {-# INLINE basicUnsafeWrite #-} - {-# INLINE basicSet #-} - basicUnsafeReplicate n (As x) = MV_UnboxAs <$> M.basicUnsafeReplicate n (toURepr x) - basicUnsafeRead (MV_UnboxAs v) i = As . fromURepr <$> M.basicUnsafeRead v i - basicUnsafeWrite (MV_UnboxAs v) i (As x) = M.basicUnsafeWrite v i (toURepr x) - basicSet (MV_UnboxAs v) (As x) = M.basicSet v (toURepr x) - -instance (IsoUnbox a b, Unbox b) => G.Vector Vector (As a b) where - -- Method that just use underlying vector - {-# INLINE basicUnsafeFreeze #-} - {-# INLINE basicUnsafeThaw #-} - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE elemseq #-} - basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @Vector @b - basicUnsafeThaw = coerce $ G.basicUnsafeThaw @Vector @b - basicLength = coerce $ G.basicLength @Vector @b - basicUnsafeSlice = coerce $ G.basicUnsafeSlice @Vector @b - basicUnsafeCopy = coerce $ G.basicUnsafeCopy @Vector @b - elemseq _ = seq - -- Conversion to/from underlying representation - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM (V_UnboxAs v) i = As . fromURepr <$> G.basicUnsafeIndexM v i - - -newtype instance MVector s Int = MV_Int (P.MVector s Int) -newtype instance Vector Int = V_Int (P.Vector Int) -deriving via (UnboxViaPrim Int) instance M.MVector MVector Int -deriving via (UnboxViaPrim Int) instance G.Vector Vector Int -instance Unbox Int - -newtype instance MVector s Int8 = MV_Int8 (P.MVector s Int8) -newtype instance Vector Int8 = V_Int8 (P.Vector Int8) -deriving via (UnboxViaPrim Int8) instance M.MVector MVector Int8 -deriving via (UnboxViaPrim Int8) instance G.Vector Vector Int8 -instance Unbox Int8 - -newtype instance MVector s Int16 = MV_Int16 (P.MVector s Int16) -newtype instance Vector Int16 = V_Int16 (P.Vector Int16) -deriving via (UnboxViaPrim Int16) instance M.MVector MVector Int16 -deriving via (UnboxViaPrim Int16) instance G.Vector Vector Int16 -instance Unbox Int16 - -newtype instance MVector s Int32 = MV_Int32 (P.MVector s Int32) -newtype instance Vector Int32 = V_Int32 (P.Vector Int32) -deriving via (UnboxViaPrim Int32) instance M.MVector MVector Int32 -deriving via (UnboxViaPrim Int32) instance G.Vector Vector Int32 -instance Unbox Int32 - -newtype instance MVector s Int64 = MV_Int64 (P.MVector s Int64) -newtype instance Vector Int64 = V_Int64 (P.Vector Int64) -deriving via (UnboxViaPrim Int64) instance M.MVector MVector Int64 -deriving via (UnboxViaPrim Int64) instance G.Vector Vector Int64 -instance Unbox Int64 - - -newtype instance MVector s Word = MV_Word (P.MVector s Word) -newtype instance Vector Word = V_Word (P.Vector Word) -deriving via (UnboxViaPrim Word) instance M.MVector MVector Word -deriving via (UnboxViaPrim Word) instance G.Vector Vector Word -instance Unbox Word - -newtype instance MVector s Word8 = MV_Word8 (P.MVector s Word8) -newtype instance Vector Word8 = V_Word8 (P.Vector Word8) -deriving via (UnboxViaPrim Word8) instance M.MVector MVector Word8 -deriving via (UnboxViaPrim Word8) instance G.Vector Vector Word8 -instance Unbox Word8 - -newtype instance MVector s Word16 = MV_Word16 (P.MVector s Word16) -newtype instance Vector Word16 = V_Word16 (P.Vector Word16) -deriving via (UnboxViaPrim Word16) instance M.MVector MVector Word16 -deriving via (UnboxViaPrim Word16) instance G.Vector Vector Word16 -instance Unbox Word16 - -newtype instance MVector s Word32 = MV_Word32 (P.MVector s Word32) -newtype instance Vector Word32 = V_Word32 (P.Vector Word32) -deriving via (UnboxViaPrim Word32) instance M.MVector MVector Word32 -deriving via (UnboxViaPrim Word32) instance G.Vector Vector Word32 -instance Unbox Word32 - -newtype instance MVector s Word64 = MV_Word64 (P.MVector s Word64) -newtype instance Vector Word64 = V_Word64 (P.Vector Word64) -deriving via (UnboxViaPrim Word64) instance M.MVector MVector Word64 -deriving via (UnboxViaPrim Word64) instance G.Vector Vector Word64 -instance Unbox Word64 - - -newtype instance MVector s Float = MV_Float (P.MVector s Float) -newtype instance Vector Float = V_Float (P.Vector Float) -deriving via (UnboxViaPrim Float) instance M.MVector MVector Float -deriving via (UnboxViaPrim Float) instance G.Vector Vector Float -instance Unbox Float - -newtype instance MVector s Double = MV_Double (P.MVector s Double) -newtype instance Vector Double = V_Double (P.Vector Double) -deriving via (UnboxViaPrim Double) instance M.MVector MVector Double -deriving via (UnboxViaPrim Double) instance G.Vector Vector Double -instance Unbox Double - -newtype instance MVector s Char = MV_Char (P.MVector s Char) -newtype instance Vector Char = V_Char (P.Vector Char) -deriving via (UnboxViaPrim Char) instance M.MVector MVector Char -deriving via (UnboxViaPrim Char) instance G.Vector Vector Char -instance Unbox Char - --- ---- --- Bool --- ---- - -fromBool :: Bool -> Word8 -{-# INLINE fromBool #-} -fromBool True = 1 -fromBool False = 0 - -toBool :: Word8 -> Bool -{-# INLINE toBool #-} -toBool 0 = False -toBool _ = True - -newtype instance MVector s Bool = MV_Bool (P.MVector s Word8) -newtype instance Vector Bool = V_Bool (P.Vector Word8) - -instance Unbox Bool - -instance M.MVector MVector Bool where - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicOverlaps #-} - {-# INLINE basicUnsafeNew #-} - {-# INLINE basicInitialize #-} - {-# INLINE basicUnsafeReplicate #-} - {-# INLINE basicUnsafeRead #-} - {-# INLINE basicUnsafeWrite #-} - {-# INLINE basicClear #-} - {-# INLINE basicSet #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE basicUnsafeGrow #-} - basicLength (MV_Bool v) = M.basicLength v - basicUnsafeSlice i n (MV_Bool v) = MV_Bool $ M.basicUnsafeSlice i n v - basicOverlaps (MV_Bool v1) (MV_Bool v2) = M.basicOverlaps v1 v2 - basicUnsafeNew n = MV_Bool `liftM` M.basicUnsafeNew n - basicInitialize (MV_Bool v) = M.basicInitialize v - basicUnsafeReplicate n x = MV_Bool `liftM` M.basicUnsafeReplicate n (fromBool x) - basicUnsafeRead (MV_Bool v) i = toBool `liftM` M.basicUnsafeRead v i - basicUnsafeWrite (MV_Bool v) i x = M.basicUnsafeWrite v i (fromBool x) - basicClear (MV_Bool v) = M.basicClear v - basicSet (MV_Bool v) x = M.basicSet v (fromBool x) - basicUnsafeCopy (MV_Bool v1) (MV_Bool v2) = M.basicUnsafeCopy v1 v2 - basicUnsafeMove (MV_Bool v1) (MV_Bool v2) = M.basicUnsafeMove v1 v2 - basicUnsafeGrow (MV_Bool v) n = MV_Bool `liftM` M.basicUnsafeGrow v n - -instance G.Vector Vector Bool where - {-# INLINE basicUnsafeFreeze #-} - {-# INLINE basicUnsafeThaw #-} - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicUnsafeIndexM #-} - {-# INLINE elemseq #-} - basicUnsafeFreeze (MV_Bool v) = V_Bool `liftM` G.basicUnsafeFreeze v - basicUnsafeThaw (V_Bool v) = MV_Bool `liftM` G.basicUnsafeThaw v - basicLength (V_Bool v) = G.basicLength v - basicUnsafeSlice i n (V_Bool v) = V_Bool $ G.basicUnsafeSlice i n v - basicUnsafeIndexM (V_Bool v) i = toBool `liftM` G.basicUnsafeIndexM v i - basicUnsafeCopy (MV_Bool mv) (V_Bool v) = G.basicUnsafeCopy mv v - elemseq _ = seq - --- ------- --- Complex --- ------- - -newtype instance MVector s (Complex a) = MV_Complex (MVector s (a,a)) -newtype instance Vector (Complex a) = V_Complex (Vector (a,a)) - -instance (Unbox a) => Unbox (Complex a) - -instance (Unbox a) => M.MVector MVector (Complex a) where - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicOverlaps #-} - {-# INLINE basicUnsafeNew #-} - {-# INLINE basicInitialize #-} - {-# INLINE basicClear #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE basicUnsafeMove #-} - {-# INLINE basicUnsafeGrow #-} - basicLength = coerce $ M.basicLength @MVector @(a,a) - basicUnsafeSlice = coerce $ M.basicUnsafeSlice @MVector @(a,a) - basicOverlaps = coerce $ M.basicOverlaps @MVector @(a,a) - basicUnsafeNew = coerce $ M.basicUnsafeNew @MVector @(a,a) - basicInitialize = coerce $ M.basicInitialize @MVector @(a,a) - basicUnsafeCopy = coerce $ M.basicUnsafeCopy @MVector @(a,a) - basicUnsafeMove = coerce $ M.basicUnsafeMove @MVector @(a,a) - basicUnsafeGrow = coerce $ M.basicUnsafeGrow @MVector @(a,a) - basicClear = coerce $ M.basicClear @MVector @(a,a) - {-# INLINE basicUnsafeReplicate #-} - {-# INLINE basicUnsafeRead #-} - {-# INLINE basicUnsafeWrite #-} - {-# INLINE basicSet #-} - basicUnsafeReplicate n (x :+ y) = MV_Complex <$> M.basicUnsafeReplicate n (x,y) - basicUnsafeRead (MV_Complex v) i = uncurry (:+) <$> M.basicUnsafeRead v i - basicUnsafeWrite (MV_Complex v) i (x :+ y) = M.basicUnsafeWrite v i (x,y) - basicSet (MV_Complex v) (x :+ y) = M.basicSet v (x,y) - -instance (Unbox a) => G.Vector Vector (Complex a) where - {-# INLINE basicUnsafeFreeze #-} - {-# INLINE basicUnsafeThaw #-} - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicUnsafeCopy #-} - basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @Vector @(a,a) - basicUnsafeThaw = coerce $ G.basicUnsafeThaw @Vector @(a,a) - basicLength = coerce $ G.basicLength @Vector @(a,a) - basicUnsafeSlice = coerce $ G.basicUnsafeSlice @Vector @(a,a) - basicUnsafeCopy = coerce $ G.basicUnsafeCopy @Vector @(a,a) - {-# INLINE basicUnsafeIndexM #-} - {-# INLINE elemseq #-} - basicUnsafeIndexM (V_Complex v) i - = uncurry (:+) <$> G.basicUnsafeIndexM v i - elemseq _ (x :+ y) z = G.elemseq (undefined :: Vector a) x - $ G.elemseq (undefined :: Vector a) y z - --- ------- --- Identity --- ------- - -newtype instance MVector s (Identity a) = MV_Identity (MVector s a) -newtype instance Vector (Identity a) = V_Identity (Vector a) -deriving instance Unbox a => G.Vector Vector (Identity a) -deriving instance Unbox a => M.MVector MVector (Identity a) -instance Unbox a => Unbox (Identity a) - -newtype instance MVector s (Down a) = MV_Down (MVector s a) -newtype instance Vector (Down a) = V_Down (Vector a) -deriving instance Unbox a => G.Vector Vector (Down a) -deriving instance Unbox a => M.MVector MVector (Down a) -instance Unbox a => Unbox (Down a) - -newtype instance MVector s (Dual a) = MV_Dual (MVector s a) -newtype instance Vector (Dual a) = V_Dual (Vector a) -deriving instance Unbox a => G.Vector Vector (Dual a) -deriving instance Unbox a => M.MVector MVector (Dual a) -instance Unbox a => Unbox (Dual a) - -newtype instance MVector s (Sum a) = MV_Sum (MVector s a) -newtype instance Vector (Sum a) = V_Sum (Vector a) -deriving instance Unbox a => G.Vector Vector (Sum a) -deriving instance Unbox a => M.MVector MVector (Sum a) -instance Unbox a => Unbox (Sum a) - -newtype instance MVector s (Product a) = MV_Product (MVector s a) -newtype instance Vector (Product a) = V_Product (Vector a) -deriving instance Unbox a => G.Vector Vector (Product a) -deriving instance Unbox a => M.MVector MVector (Product a) -instance Unbox a => Unbox (Product a) - --- -------------- --- Data.Semigroup --- -------------- - - -newtype instance MVector s (Min a) = MV_Min (MVector s a) -newtype instance Vector (Min a) = V_Min (Vector a) -deriving instance Unbox a => G.Vector Vector (Min a) -deriving instance Unbox a => M.MVector MVector (Min a) -instance Unbox a => Unbox (Min a) - -newtype instance MVector s (Max a) = MV_Max (MVector s a) -newtype instance Vector (Max a) = V_Max (Vector a) -deriving instance Unbox a => G.Vector Vector (Max a) -deriving instance Unbox a => M.MVector MVector (Max a) -instance Unbox a => Unbox (Max a) - -newtype instance MVector s (First a) = MV_First (MVector s a) -newtype instance Vector (First a) = V_First (Vector a) -deriving instance Unbox a => G.Vector Vector (First a) -deriving instance Unbox a => M.MVector MVector (First a) -instance Unbox a => Unbox (First a) - -newtype instance MVector s (Last a) = MV_Last (MVector s a) -newtype instance Vector (Last a) = V_Last (Vector a) -deriving instance Unbox a => G.Vector Vector (Last a) -deriving instance Unbox a => M.MVector MVector (Last a) -instance Unbox a => Unbox (Last a) - -newtype instance MVector s (WrappedMonoid a) = MV_WrappedMonoid (MVector s a) -newtype instance Vector (WrappedMonoid a) = V_WrappedMonoid (Vector a) -deriving instance Unbox a => G.Vector Vector (WrappedMonoid a) -deriving instance Unbox a => M.MVector MVector (WrappedMonoid a) -instance Unbox a => Unbox (WrappedMonoid a) - --- ------------------ --- Data.Semigroup.Arg --- ------------------ - -newtype instance MVector s (Arg a b) = MV_Arg (MVector s (a,b)) -newtype instance Vector (Arg a b) = V_Arg (Vector (a,b)) - -instance (Unbox a, Unbox b) => Unbox (Arg a b) - -instance (Unbox a, Unbox b) => M.MVector MVector (Arg a b) where - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicOverlaps #-} - {-# INLINE basicUnsafeNew #-} - {-# INLINE basicInitialize #-} - {-# INLINE basicClear #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE basicUnsafeMove #-} - {-# INLINE basicUnsafeGrow #-} - basicLength = coerce $ M.basicLength @MVector @(a,b) - basicUnsafeSlice = coerce $ M.basicUnsafeSlice @MVector @(a,b) - basicOverlaps = coerce $ M.basicOverlaps @MVector @(a,b) - basicUnsafeNew = coerce $ M.basicUnsafeNew @MVector @(a,b) - basicInitialize = coerce $ M.basicInitialize @MVector @(a,b) - basicUnsafeCopy = coerce $ M.basicUnsafeCopy @MVector @(a,b) - basicUnsafeMove = coerce $ M.basicUnsafeMove @MVector @(a,b) - basicUnsafeGrow = coerce $ M.basicUnsafeGrow @MVector @(a,b) - basicClear = coerce $ M.basicClear @MVector @(a,b) - {-# INLINE basicUnsafeReplicate #-} - {-# INLINE basicUnsafeRead #-} - {-# INLINE basicUnsafeWrite #-} - {-# INLINE basicSet #-} - basicUnsafeReplicate n (Arg x y) = MV_Arg <$> M.basicUnsafeReplicate n (x,y) - basicUnsafeRead (MV_Arg v) i = uncurry Arg <$> M.basicUnsafeRead v i - basicUnsafeWrite (MV_Arg v) i (Arg x y) = M.basicUnsafeWrite v i (x,y) - basicSet (MV_Arg v) (Arg x y) = M.basicSet v (x,y) - - -instance (Unbox a, Unbox b) => G.Vector Vector (Arg a b) where - {-# INLINE basicUnsafeFreeze #-} - {-# INLINE basicUnsafeThaw #-} - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicUnsafeCopy #-} - basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @Vector @(a,b) - basicUnsafeThaw = coerce $ G.basicUnsafeThaw @Vector @(a,b) - basicLength = coerce $ G.basicLength @Vector @(a,b) - basicUnsafeSlice = coerce $ G.basicUnsafeSlice @Vector @(a,b) - basicUnsafeCopy = coerce $ G.basicUnsafeCopy @Vector @(a,b) - {-# INLINE basicUnsafeIndexM #-} - {-# INLINE elemseq #-} - basicUnsafeIndexM (V_Arg v) i = uncurry Arg `liftM` G.basicUnsafeIndexM v i - elemseq _ (Arg x y) z = G.elemseq (undefined :: Vector a) x - $ G.elemseq (undefined :: Vector b) y z - --- ------- --- Unboxing the Storable values --- ------- - --- | Newtype wrapper which allows to derive unboxed vector in term of --- storable vectors using @DerivingVia@ mechanism. This is mostly --- used as illustration of use of @DerivingVia@ for vector, see examples below. --- --- First is rather straightforward: we define newtype and use GND to --- derive 'St.Storable' instance. Newtype instances should be defined --- manually. Then we use deriving via to define necessary instances. --- --- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia -XMultiParamTypeClasses --- >>> :set -XGeneralizedNewtypeDeriving --- >>> --- >>> import qualified Data.Vector.Generic as VG --- >>> import qualified Data.Vector.Generic.Mutable as VGM --- >>> import qualified Data.Vector.Storable as VS --- >>> import qualified Data.Vector.Unboxed as VU --- >>> --- >>> newtype Foo = Foo Int deriving VS.Storable --- >>> --- >>> newtype instance VU.MVector s Foo = MV_Foo (VS.MVector s Foo) --- >>> newtype instance VU.Vector Foo = V_Foo (VS.Vector Foo) --- >>> deriving via (VU.UnboxViaStorable Foo) instance VGM.MVector VU.MVector Foo --- >>> deriving via (VU.UnboxViaStorable Foo) instance VG.Vector VU.Vector Foo --- >>> instance VU.Unbox Foo --- --- Second example is essentially same but with a twist. Instead of --- using 'St.Storable' instance of data type, we use underlying instance of 'Int': --- --- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia -XMultiParamTypeClasses --- >>> --- >>> import qualified Data.Vector.Generic as VG --- >>> import qualified Data.Vector.Generic.Mutable as VGM --- >>> import qualified Data.Vector.Storable as VS --- >>> import qualified Data.Vector.Unboxed as VU --- >>> --- >>> newtype Foo = Foo Int --- >>> --- >>> newtype instance VU.MVector s Foo = MV_Foo (VS.MVector s Int) --- >>> newtype instance VU.Vector Foo = V_Foo (VS.Vector Int) --- >>> deriving via (VU.UnboxViaStorable Int) instance VGM.MVector VU.MVector Foo --- >>> deriving via (VU.UnboxViaStorable Int) instance VG.Vector VU.Vector Foo --- >>> instance VU.Unbox Foo --- --- @since 0.13.3.0 -newtype UnboxViaStorable a = UnboxViaStorable a - -newtype instance MVector s (UnboxViaStorable a) = MV_UnboxViaStorable (St.MVector s a) -newtype instance Vector (UnboxViaStorable a) = V_UnboxViaStorable (St.Vector a) - -instance St.Storable a => M.MVector MVector (UnboxViaStorable a) where - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicOverlaps #-} - {-# INLINE basicUnsafeNew #-} - {-# INLINE basicInitialize #-} - {-# INLINE basicUnsafeReplicate #-} - {-# INLINE basicUnsafeRead #-} - {-# INLINE basicUnsafeWrite #-} - {-# INLINE basicClear #-} - {-# INLINE basicSet #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE basicUnsafeGrow #-} - basicLength = coerce $ M.basicLength @St.MVector @a - basicUnsafeSlice = coerce $ M.basicUnsafeSlice @St.MVector @a - basicOverlaps = coerce $ M.basicOverlaps @St.MVector @a - basicUnsafeNew = coerce $ M.basicUnsafeNew @St.MVector @a - basicInitialize = coerce $ M.basicInitialize @St.MVector @a - basicUnsafeReplicate = coerce $ M.basicUnsafeReplicate @St.MVector @a - basicUnsafeRead = coerce $ M.basicUnsafeRead @St.MVector @a - basicUnsafeWrite = coerce $ M.basicUnsafeWrite @St.MVector @a - basicClear = coerce $ M.basicClear @St.MVector @a - basicSet = coerce $ M.basicSet @St.MVector @a - basicUnsafeCopy = coerce $ M.basicUnsafeCopy @St.MVector @a - basicUnsafeMove = coerce $ M.basicUnsafeMove @St.MVector @a - basicUnsafeGrow = coerce $ M.basicUnsafeGrow @St.MVector @a - -instance St.Storable a => G.Vector Vector (UnboxViaStorable a) where - {-# INLINE basicUnsafeFreeze #-} - {-# INLINE basicUnsafeThaw #-} - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicUnsafeIndexM #-} - {-# INLINE elemseq #-} - basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @St.Vector @a - basicUnsafeThaw = coerce $ G.basicUnsafeThaw @St.Vector @a - basicLength = coerce $ G.basicLength @St.Vector @a - basicUnsafeSlice = coerce $ G.basicUnsafeSlice @St.Vector @a - basicUnsafeIndexM = coerce $ G.basicUnsafeIndexM @St.Vector @a - basicUnsafeCopy = coerce $ G.basicUnsafeCopy @St.Vector @a - elemseq _ = seq - -instance St.Storable a => Unbox (UnboxViaStorable a) - --- ------- --- Unboxing the boxed values --- ------- - --- | Newtype which allows to derive unbox instances for type @a@ which --- is normally a "boxed" type. The newtype does not alter the strictness --- semantics of the underlying type and inherits the laizness of said type. --- For a strict newtype wrapper, see 'DoNotUnboxStrict'. --- --- 'DoNotUnboxLazy' is intended to be unsed in conjunction with the newtype 'As' --- and the type class 'IsoUnbox'. Here's an example which uses the following --- explicit 'IsoUnbox' instance: --- --- --- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia --- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances --- >>> import qualified Data.Vector.Unboxed as VU --- >>> import qualified Data.Vector.Generic as VG --- >>> import qualified Data.Vector.Generic.Mutable as VGM --- >>> :{ --- >>> data Foo a = Foo Int a --- >>> deriving (Eq, Ord, Show) --- >>> instance VU.IsoUnbox (Foo a) (Int, VU.DoNotUnboxLazy a) where --- >>> toURepr (Foo i a) = (i, VU.DoNotUnboxLazy a) --- >>> fromURepr (i, VU.DoNotUnboxLazy a) = Foo i a --- >>> {-# INLINE toURepr #-} --- >>> {-# INLINE fromURepr #-} --- >>> newtype instance VU.MVector s (Foo a) = MV_Foo (VU.MVector s (Int, VU.DoNotUnboxLazy a)) --- >>> newtype instance VU.Vector (Foo a) = V_Foo (VU.Vector (Int, VU.DoNotUnboxLazy a)) --- >>> deriving via (Foo a `VU.As` (Int, VU.DoNotUnboxLazy a)) instance VGM.MVector VU.MVector (Foo a) --- >>> deriving via (Foo a `VU.As` (Int, VU.DoNotUnboxLazy a)) instance VG.Vector VU.Vector (Foo a) --- >>> instance VU.Unbox (Foo a) --- >>> :} --- --- >>> VU.fromListN 3 [ Foo 4 "Haskell's", Foo 8 "strong", Foo 16 "types" ] --- [Foo 4 "Haskell's",Foo 8 "strong",Foo 16 "types"] --- --- @since 0.13.2.0 -newtype DoNotUnboxLazy a = DoNotUnboxLazy a - -newtype instance MVector s (DoNotUnboxLazy a) = MV_DoNotUnboxLazy (B.MVector s a) -newtype instance Vector (DoNotUnboxLazy a) = V_DoNotUnboxLazy (B.Vector a) - -instance M.MVector MVector (DoNotUnboxLazy a) where - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicOverlaps #-} - {-# INLINE basicUnsafeNew #-} - {-# INLINE basicInitialize #-} - {-# INLINE basicUnsafeReplicate #-} - {-# INLINE basicUnsafeRead #-} - {-# INLINE basicUnsafeWrite #-} - {-# INLINE basicClear #-} - {-# INLINE basicSet #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE basicUnsafeGrow #-} - basicLength = coerce $ M.basicLength @B.MVector @a - basicUnsafeSlice = coerce $ M.basicUnsafeSlice @B.MVector @a - basicOverlaps = coerce $ M.basicOverlaps @B.MVector @a - basicUnsafeNew = coerce $ M.basicUnsafeNew @B.MVector @a - basicInitialize = coerce $ M.basicInitialize @B.MVector @a - basicUnsafeReplicate = coerce $ M.basicUnsafeReplicate @B.MVector @a - basicUnsafeRead = coerce $ M.basicUnsafeRead @B.MVector @a - basicUnsafeWrite = coerce $ M.basicUnsafeWrite @B.MVector @a - basicClear = coerce $ M.basicClear @B.MVector @a - basicSet = coerce $ M.basicSet @B.MVector @a - basicUnsafeCopy = coerce $ M.basicUnsafeCopy @B.MVector @a - basicUnsafeMove = coerce $ M.basicUnsafeMove @B.MVector @a - basicUnsafeGrow = coerce $ M.basicUnsafeGrow @B.MVector @a - -instance G.Vector Vector (DoNotUnboxLazy a) where - {-# INLINE basicUnsafeFreeze #-} - {-# INLINE basicUnsafeThaw #-} - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicUnsafeIndexM #-} - {-# INLINE elemseq #-} - basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @B.Vector @a - basicUnsafeThaw = coerce $ G.basicUnsafeThaw @B.Vector @a - basicLength = coerce $ G.basicLength @B.Vector @a - basicUnsafeSlice = coerce $ G.basicUnsafeSlice @B.Vector @a - basicUnsafeIndexM = coerce $ G.basicUnsafeIndexM @B.Vector @a - basicUnsafeCopy = coerce $ G.basicUnsafeCopy @B.Vector @a - elemseq _ = seq - -instance Unbox (DoNotUnboxLazy a) - --- | Newtype which allows to derive unbox instances for type @a@ which --- is normally a "boxed" type. The newtype stictly evaluates the wrapped values --- ensuring that the unboxed vector contains no (direct) thunks. --- For a less strict newtype wrapper, see 'DoNotUnboxLazy'. --- For a more strict newtype wrapper, see 'DoNotUnboxNormalForm'. --- --- 'DoNotUnboxStrict' is intended to be unsed in conjunction with the newtype 'As' --- and the type class 'IsoUnbox'. Here's an example which uses the following --- explicit 'IsoUnbox' instance: --- --- --- >>> :set -XBangPatterns -XTypeFamilies -XStandaloneDeriving -XDerivingVia --- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances --- >>> import qualified Data.Vector.Unboxed as VU --- >>> import qualified Data.Vector.Generic as VG --- >>> import qualified Data.Vector.Generic.Mutable as VGM --- >>> :{ --- >>> data Bar a = Bar Int a --- >>> deriving Show --- >>> instance VU.IsoUnbox (Bar a) (Int, VU.DoNotUnboxStrict a) where --- >>> toURepr (Bar i !a) = (i, VU.DoNotUnboxStrict a) --- >>> fromURepr (i, VU.DoNotUnboxStrict a) = Bar i a --- >>> {-# INLINE toURepr #-} --- >>> {-# INLINE fromURepr #-} --- >>> newtype instance VU.MVector s (Bar a) = MV_Bar (VU.MVector s (Int, VU.DoNotUnboxStrict a)) --- >>> newtype instance VU.Vector (Bar a) = V_Bar (VU.Vector (Int, VU.DoNotUnboxStrict a)) --- >>> deriving via (Bar a `VU.As` (Int, VU.DoNotUnboxStrict a)) instance VGM.MVector VU.MVector (Bar a) --- >>> deriving via (Bar a `VU.As` (Int, VU.DoNotUnboxStrict a)) instance VG.Vector VU.Vector (Bar a) --- >>> instance VU.Unbox (Bar a) --- >>> :} --- --- >>> VU.fromListN 3 [ Bar 3 "Bye", Bar 2 "for", Bar 1 "now" ] --- [Bar 3 "Bye",Bar 2 "for",Bar 1 "now"] --- --- @since 0.13.2.0 -newtype DoNotUnboxStrict a = DoNotUnboxStrict a - -newtype instance MVector s (DoNotUnboxStrict a) = MV_DoNotUnboxStrict (S.MVector s a) -newtype instance Vector (DoNotUnboxStrict a) = V_DoNotUnboxStrict (S.Vector a) - -instance M.MVector MVector (DoNotUnboxStrict a) where - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicOverlaps #-} - {-# INLINE basicUnsafeNew #-} - {-# INLINE basicInitialize #-} - {-# INLINE basicUnsafeReplicate #-} - {-# INLINE basicUnsafeRead #-} - {-# INLINE basicUnsafeWrite #-} - {-# INLINE basicClear #-} - {-# INLINE basicSet #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE basicUnsafeGrow #-} - basicLength = coerce $ M.basicLength @S.MVector @a - basicUnsafeSlice = coerce $ M.basicUnsafeSlice @S.MVector @a - basicOverlaps = coerce $ M.basicOverlaps @S.MVector @a - basicUnsafeNew = coerce $ M.basicUnsafeNew @S.MVector @a - basicInitialize = coerce $ M.basicInitialize @S.MVector @a - basicUnsafeReplicate = coerce $ M.basicUnsafeReplicate @S.MVector @a - basicUnsafeRead = coerce $ M.basicUnsafeRead @S.MVector @a - basicUnsafeWrite = coerce $ M.basicUnsafeWrite @S.MVector @a - basicClear = coerce $ M.basicClear @S.MVector @a - basicSet = coerce $ M.basicSet @S.MVector @a - basicUnsafeCopy = coerce $ M.basicUnsafeCopy @S.MVector @a - basicUnsafeMove = coerce $ M.basicUnsafeMove @S.MVector @a - basicUnsafeGrow = coerce $ M.basicUnsafeGrow @S.MVector @a - -instance G.Vector Vector (DoNotUnboxStrict a) where - {-# INLINE basicUnsafeFreeze #-} - {-# INLINE basicUnsafeThaw #-} - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicUnsafeIndexM #-} - {-# INLINE elemseq #-} - basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @S.Vector @a - basicUnsafeThaw = coerce $ G.basicUnsafeThaw @S.Vector @a - basicLength = coerce $ G.basicLength @S.Vector @a - basicUnsafeSlice = coerce $ G.basicUnsafeSlice @S.Vector @a - basicUnsafeIndexM = coerce $ G.basicUnsafeIndexM @S.Vector @a - basicUnsafeCopy = coerce $ G.basicUnsafeCopy @S.Vector @a - elemseq _ = seq - -instance Unbox (DoNotUnboxStrict a) - --- | Newtype which allows to derive unbox instances for type @a@ which --- is normally a "boxed" type. The newtype stictly evaluates the wrapped values --- via thier requisite 'NFData' instance, ensuring that the unboxed vector --- contains only values reduced to normal form. --- For a less strict newtype wrappers, see 'DoNotUnboxLazy' and 'DoNotUnboxStrict'. --- --- 'DoNotUnboxNormalForm' is intended to be unsed in conjunction with the newtype 'As' --- and the type class 'IsoUnbox'. Here's an example which uses the following --- explicit 'IsoUnbox' instance: --- --- --- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia --- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances --- >>> import qualified Data.Vector.Unboxed as VU --- >>> import qualified Data.Vector.Generic as VG --- >>> import qualified Data.Vector.Generic.Mutable as VGM --- >>> import qualified Control.DeepSeq as NF --- >>> :{ --- >>> data Baz a = Baz Int a --- >>> deriving Show --- >>> instance NF.NFData a => VU.IsoUnbox (Baz a) (Int, VU.DoNotUnboxNormalForm a) where --- >>> toURepr (Baz i a) = (i, VU.DoNotUnboxNormalForm $ NF.force a) --- >>> fromURepr (i, VU.DoNotUnboxNormalForm a) = Baz i a --- >>> {-# INLINE toURepr #-} --- >>> {-# INLINE fromURepr #-} --- >>> newtype instance VU.MVector s (Baz a) = MV_Baz (VU.MVector s (Int, VU.DoNotUnboxNormalForm a)) --- >>> newtype instance VU.Vector (Baz a) = V_Baz (VU.Vector (Int, VU.DoNotUnboxNormalForm a)) --- >>> deriving via (Baz a `VU.As` (Int, VU.DoNotUnboxNormalForm a)) instance NF.NFData a => VGM.MVector VU.MVector (Baz a) --- >>> deriving via (Baz a `VU.As` (Int, VU.DoNotUnboxNormalForm a)) instance NF.NFData a => VG.Vector VU.Vector (Baz a) --- >>> instance NF.NFData a => VU.Unbox (Baz a) --- >>> :} --- --- >>> VU.fromListN 3 [ Baz 3 "Fully", Baz 9 "evaluated", Baz 27 "data" ] --- [Baz 3 "Fully",Baz 9 "evaluated",Baz 27 "data"] --- --- @since 0.13.2.0 -newtype DoNotUnboxNormalForm a = DoNotUnboxNormalForm a - -newtype instance MVector s (DoNotUnboxNormalForm a) = MV_DoNotUnboxNormalForm (S.MVector s a) -newtype instance Vector (DoNotUnboxNormalForm a) = V_DoNotUnboxNormalForm (S.Vector a) - -instance NFData a => M.MVector MVector (DoNotUnboxNormalForm a) where - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicOverlaps #-} - {-# INLINE basicUnsafeNew #-} - {-# INLINE basicInitialize #-} - {-# INLINE basicUnsafeReplicate #-} - {-# INLINE basicUnsafeRead #-} - {-# INLINE basicUnsafeWrite #-} - {-# INLINE basicClear #-} - {-# INLINE basicSet #-} - {-# INLINE basicUnsafeCopy #-} - {-# INLINE basicUnsafeGrow #-} - basicLength = coerce $ M.basicLength @S.MVector @a - basicUnsafeSlice = coerce $ M.basicUnsafeSlice @S.MVector @a - basicOverlaps = coerce $ M.basicOverlaps @S.MVector @a - basicUnsafeNew = coerce $ M.basicUnsafeNew @S.MVector @a - basicInitialize = coerce $ M.basicInitialize @S.MVector @a - basicUnsafeReplicate = coerce (\i x -> M.basicUnsafeReplicate @S.MVector @a i (force x)) - basicUnsafeRead = coerce $ M.basicUnsafeRead @S.MVector @a - basicUnsafeWrite = coerce (\v i x -> M.basicUnsafeWrite @S.MVector @a v i (force x)) - basicClear = coerce $ M.basicClear @S.MVector @a - basicSet = coerce (\v x -> M.basicSet @S.MVector @a v (force x)) - basicUnsafeCopy = coerce $ M.basicUnsafeCopy @S.MVector @a - basicUnsafeMove = coerce $ M.basicUnsafeMove @S.MVector @a - basicUnsafeGrow = coerce $ M.basicUnsafeGrow @S.MVector @a - -instance NFData a => G.Vector Vector (DoNotUnboxNormalForm a) where - {-# INLINE basicUnsafeFreeze #-} - {-# INLINE basicUnsafeThaw #-} - {-# INLINE basicLength #-} - {-# INLINE basicUnsafeSlice #-} - {-# INLINE basicUnsafeIndexM #-} - {-# INLINE elemseq #-} - basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @S.Vector @a - basicUnsafeThaw = coerce $ G.basicUnsafeThaw @S.Vector @a - basicLength = coerce $ G.basicLength @S.Vector @a - basicUnsafeSlice = coerce $ G.basicUnsafeSlice @S.Vector @a - basicUnsafeIndexM = coerce $ G.basicUnsafeIndexM @S.Vector @a - basicUnsafeCopy = coerce $ G.basicUnsafeCopy @S.Vector @a - elemseq _ x y = rnf (coerce x :: a) `seq` y - -instance NFData a => Unbox (DoNotUnboxNormalForm a) - - -newtype instance MVector s Any = MV_Any (MVector s Bool) -newtype instance Vector Any = V_Any (Vector Bool) -deriving instance G.Vector Vector Any -deriving instance M.MVector MVector Any -instance Unbox Any - -newtype instance MVector s All = MV_All (MVector s Bool) -newtype instance Vector All = V_All (Vector Bool) -deriving instance G.Vector Vector All -deriving instance M.MVector MVector All -instance Unbox All - --- ------- --- Const --- ------- - -newtype instance MVector s (Const b a) = MV_Const (MVector s b) -newtype instance Vector (Const b a) = V_Const (Vector b) -deriving instance Unbox b => G.Vector Vector (Const b a) -deriving instance Unbox b => M.MVector MVector (Const b a) -instance Unbox b => Unbox (Const b a) - --- --- --- Alt --- --- - -newtype instance MVector s (Alt f a) = MV_Alt (MVector s (f a)) -newtype instance Vector (Alt f a) = V_Alt (Vector (f a)) -deriving instance Unbox (f a) => G.Vector Vector (Alt f a) -deriving instance Unbox (f a) => M.MVector MVector (Alt f a) -instance Unbox (f a) => Unbox (Alt f a) - --- ------- --- Compose --- ------- - -newtype instance MVector s (Compose f g a) = MV_Compose (MVector s (f (g a))) -newtype instance Vector (Compose f g a) = V_Compose (Vector (f (g a))) -deriving instance Unbox (f (g a)) => G.Vector Vector (Compose f g a) -deriving instance Unbox (f (g a)) => M.MVector MVector (Compose f g a) -instance Unbox (f (g a)) => Unbox (Compose f g a) - --- ------ --- Tuples --- ------ - -data instance MVector s (a, b) - = MV_2 {-# UNPACK #-} !Int !(MVector s a) - !(MVector s b) -data instance Vector (a, b) - = V_2 {-# UNPACK #-} !Int !(Vector a) - !(Vector b) -instance (Unbox a, Unbox b) => Unbox (a, b) -instance (Unbox a, Unbox b) => M.MVector MVector (a, b) where - {-# INLINE basicLength #-} - basicLength (MV_2 n_ _ _) = n_ - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i_ m_ (MV_2 _ as bs) - = MV_2 m_ (M.basicUnsafeSlice i_ m_ as) - (M.basicUnsafeSlice i_ m_ bs) - {-# INLINE basicOverlaps #-} - basicOverlaps (MV_2 _ as1 bs1) (MV_2 _ as2 bs2) - = M.basicOverlaps as1 as2 - || M.basicOverlaps bs1 bs2 - {-# INLINE basicUnsafeNew #-} - basicUnsafeNew n_ - = do - as <- M.basicUnsafeNew n_ - bs <- M.basicUnsafeNew n_ - return $ MV_2 n_ as bs - {-# INLINE basicInitialize #-} - basicInitialize (MV_2 _ as bs) - = do - M.basicInitialize as - M.basicInitialize bs - {-# INLINE basicUnsafeReplicate #-} - basicUnsafeReplicate n_ (a, b) - = do - as <- M.basicUnsafeReplicate n_ a - bs <- M.basicUnsafeReplicate n_ b - return $ MV_2 n_ as bs - {-# INLINE basicUnsafeRead #-} - basicUnsafeRead (MV_2 _ as bs) i_ - = do - a <- M.basicUnsafeRead as i_ - b <- M.basicUnsafeRead bs i_ - return (a, b) - {-# INLINE basicUnsafeWrite #-} - basicUnsafeWrite (MV_2 _ as bs) i_ (a, b) - = do - M.basicUnsafeWrite as i_ a - M.basicUnsafeWrite bs i_ b - {-# INLINE basicClear #-} - basicClear (MV_2 _ as bs) - = do - M.basicClear as - M.basicClear bs - {-# INLINE basicSet #-} - basicSet (MV_2 _ as bs) (a, b) - = do - M.basicSet as a - M.basicSet bs b - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_2 _ as1 bs1) (MV_2 _ as2 bs2) - = do - M.basicUnsafeCopy as1 as2 - M.basicUnsafeCopy bs1 bs2 - {-# INLINE basicUnsafeMove #-} - basicUnsafeMove (MV_2 _ as1 bs1) (MV_2 _ as2 bs2) - = do - M.basicUnsafeMove as1 as2 - M.basicUnsafeMove bs1 bs2 - {-# INLINE basicUnsafeGrow #-} - basicUnsafeGrow (MV_2 n_ as bs) m_ - = do - as' <- M.basicUnsafeGrow as m_ - bs' <- M.basicUnsafeGrow bs m_ - return $ MV_2 (m_+n_) as' bs' -instance (Unbox a, Unbox b) => G.Vector Vector (a, b) where - {-# INLINE basicUnsafeFreeze #-} - basicUnsafeFreeze (MV_2 n_ as bs) - = do - as' <- G.basicUnsafeFreeze as - bs' <- G.basicUnsafeFreeze bs - return $ V_2 n_ as' bs' - {-# INLINE basicUnsafeThaw #-} - basicUnsafeThaw (V_2 n_ as bs) - = do - as' <- G.basicUnsafeThaw as - bs' <- G.basicUnsafeThaw bs - return $ MV_2 n_ as' bs' - {-# INLINE basicLength #-} - basicLength (V_2 n_ _ _) = n_ - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i_ m_ (V_2 _ as bs) - = V_2 m_ (G.basicUnsafeSlice i_ m_ as) - (G.basicUnsafeSlice i_ m_ bs) - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM (V_2 _ as bs) i_ - = do - a <- G.basicUnsafeIndexM as i_ - b <- G.basicUnsafeIndexM bs i_ - return (a, b) - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_2 _ as1 bs1) (V_2 _ as2 bs2) - = do - G.basicUnsafeCopy as1 as2 - G.basicUnsafeCopy bs1 bs2 - {-# INLINE elemseq #-} - elemseq _ (a, b) - = G.elemseq (undefined :: Vector a) a - . G.elemseq (undefined :: Vector b) b - -data instance MVector s (a, b, c) - = MV_3 {-# UNPACK #-} !Int !(MVector s a) - !(MVector s b) - !(MVector s c) -data instance Vector (a, b, c) - = V_3 {-# UNPACK #-} !Int !(Vector a) - !(Vector b) - !(Vector c) -instance (Unbox a, Unbox b, Unbox c) => Unbox (a, b, c) -instance (Unbox a, - Unbox b, - Unbox c) => M.MVector MVector (a, b, c) where - {-# INLINE basicLength #-} - basicLength (MV_3 n_ _ _ _) = n_ - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i_ m_ (MV_3 _ as bs cs) - = MV_3 m_ (M.basicUnsafeSlice i_ m_ as) - (M.basicUnsafeSlice i_ m_ bs) - (M.basicUnsafeSlice i_ m_ cs) - {-# INLINE basicOverlaps #-} - basicOverlaps (MV_3 _ as1 bs1 cs1) (MV_3 _ as2 bs2 cs2) - = M.basicOverlaps as1 as2 - || M.basicOverlaps bs1 bs2 - || M.basicOverlaps cs1 cs2 - {-# INLINE basicUnsafeNew #-} - basicUnsafeNew n_ - = do - as <- M.basicUnsafeNew n_ - bs <- M.basicUnsafeNew n_ - cs <- M.basicUnsafeNew n_ - return $ MV_3 n_ as bs cs - {-# INLINE basicInitialize #-} - basicInitialize (MV_3 _ as bs cs) - = do - M.basicInitialize as - M.basicInitialize bs - M.basicInitialize cs - {-# INLINE basicUnsafeReplicate #-} - basicUnsafeReplicate n_ (a, b, c) - = do - as <- M.basicUnsafeReplicate n_ a - bs <- M.basicUnsafeReplicate n_ b - cs <- M.basicUnsafeReplicate n_ c - return $ MV_3 n_ as bs cs - {-# INLINE basicUnsafeRead #-} - basicUnsafeRead (MV_3 _ as bs cs) i_ - = do - a <- M.basicUnsafeRead as i_ - b <- M.basicUnsafeRead bs i_ - c <- M.basicUnsafeRead cs i_ - return (a, b, c) - {-# INLINE basicUnsafeWrite #-} - basicUnsafeWrite (MV_3 _ as bs cs) i_ (a, b, c) - = do - M.basicUnsafeWrite as i_ a - M.basicUnsafeWrite bs i_ b - M.basicUnsafeWrite cs i_ c - {-# INLINE basicClear #-} - basicClear (MV_3 _ as bs cs) - = do - M.basicClear as - M.basicClear bs - M.basicClear cs - {-# INLINE basicSet #-} - basicSet (MV_3 _ as bs cs) (a, b, c) - = do - M.basicSet as a - M.basicSet bs b - M.basicSet cs c - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_3 _ as1 bs1 cs1) (MV_3 _ as2 bs2 cs2) - = do - M.basicUnsafeCopy as1 as2 - M.basicUnsafeCopy bs1 bs2 - M.basicUnsafeCopy cs1 cs2 - {-# INLINE basicUnsafeMove #-} - basicUnsafeMove (MV_3 _ as1 bs1 cs1) (MV_3 _ as2 bs2 cs2) - = do - M.basicUnsafeMove as1 as2 - M.basicUnsafeMove bs1 bs2 - M.basicUnsafeMove cs1 cs2 - {-# INLINE basicUnsafeGrow #-} - basicUnsafeGrow (MV_3 n_ as bs cs) m_ - = do - as' <- M.basicUnsafeGrow as m_ - bs' <- M.basicUnsafeGrow bs m_ - cs' <- M.basicUnsafeGrow cs m_ - return $ MV_3 (m_+n_) as' bs' cs' -instance (Unbox a, - Unbox b, - Unbox c) => G.Vector Vector (a, b, c) where - {-# INLINE basicUnsafeFreeze #-} - basicUnsafeFreeze (MV_3 n_ as bs cs) - = do - as' <- G.basicUnsafeFreeze as - bs' <- G.basicUnsafeFreeze bs - cs' <- G.basicUnsafeFreeze cs - return $ V_3 n_ as' bs' cs' - {-# INLINE basicUnsafeThaw #-} - basicUnsafeThaw (V_3 n_ as bs cs) - = do - as' <- G.basicUnsafeThaw as - bs' <- G.basicUnsafeThaw bs - cs' <- G.basicUnsafeThaw cs - return $ MV_3 n_ as' bs' cs' - {-# INLINE basicLength #-} - basicLength (V_3 n_ _ _ _) = n_ - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i_ m_ (V_3 _ as bs cs) - = V_3 m_ (G.basicUnsafeSlice i_ m_ as) - (G.basicUnsafeSlice i_ m_ bs) - (G.basicUnsafeSlice i_ m_ cs) - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM (V_3 _ as bs cs) i_ - = do - a <- G.basicUnsafeIndexM as i_ - b <- G.basicUnsafeIndexM bs i_ - c <- G.basicUnsafeIndexM cs i_ - return (a, b, c) - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_3 _ as1 bs1 cs1) (V_3 _ as2 bs2 cs2) - = do - G.basicUnsafeCopy as1 as2 - G.basicUnsafeCopy bs1 bs2 - G.basicUnsafeCopy cs1 cs2 - {-# INLINE elemseq #-} - elemseq _ (a, b, c) - = G.elemseq (undefined :: Vector a) a - . G.elemseq (undefined :: Vector b) b - . G.elemseq (undefined :: Vector c) c - -data instance MVector s (a, b, c, d) - = MV_4 {-# UNPACK #-} !Int !(MVector s a) - !(MVector s b) - !(MVector s c) - !(MVector s d) -data instance Vector (a, b, c, d) - = V_4 {-# UNPACK #-} !Int !(Vector a) - !(Vector b) - !(Vector c) - !(Vector d) -instance (Unbox a, Unbox b, Unbox c, Unbox d) => Unbox (a, b, c, d) -instance (Unbox a, - Unbox b, - Unbox c, - Unbox d) => M.MVector MVector (a, b, c, d) where - {-# INLINE basicLength #-} - basicLength (MV_4 n_ _ _ _ _) = n_ - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i_ m_ (MV_4 _ as bs cs ds) - = MV_4 m_ (M.basicUnsafeSlice i_ m_ as) - (M.basicUnsafeSlice i_ m_ bs) - (M.basicUnsafeSlice i_ m_ cs) - (M.basicUnsafeSlice i_ m_ ds) - {-# INLINE basicOverlaps #-} - basicOverlaps (MV_4 _ as1 bs1 cs1 ds1) (MV_4 _ as2 bs2 cs2 ds2) - = M.basicOverlaps as1 as2 - || M.basicOverlaps bs1 bs2 - || M.basicOverlaps cs1 cs2 - || M.basicOverlaps ds1 ds2 - {-# INLINE basicUnsafeNew #-} - basicUnsafeNew n_ - = do - as <- M.basicUnsafeNew n_ - bs <- M.basicUnsafeNew n_ - cs <- M.basicUnsafeNew n_ - ds <- M.basicUnsafeNew n_ - return $ MV_4 n_ as bs cs ds - {-# INLINE basicInitialize #-} - basicInitialize (MV_4 _ as bs cs ds) - = do - M.basicInitialize as - M.basicInitialize bs - M.basicInitialize cs - M.basicInitialize ds - {-# INLINE basicUnsafeReplicate #-} - basicUnsafeReplicate n_ (a, b, c, d) - = do - as <- M.basicUnsafeReplicate n_ a - bs <- M.basicUnsafeReplicate n_ b - cs <- M.basicUnsafeReplicate n_ c - ds <- M.basicUnsafeReplicate n_ d - return $ MV_4 n_ as bs cs ds - {-# INLINE basicUnsafeRead #-} - basicUnsafeRead (MV_4 _ as bs cs ds) i_ - = do - a <- M.basicUnsafeRead as i_ - b <- M.basicUnsafeRead bs i_ - c <- M.basicUnsafeRead cs i_ - d <- M.basicUnsafeRead ds i_ - return (a, b, c, d) - {-# INLINE basicUnsafeWrite #-} - basicUnsafeWrite (MV_4 _ as bs cs ds) i_ (a, b, c, d) - = do - M.basicUnsafeWrite as i_ a - M.basicUnsafeWrite bs i_ b - M.basicUnsafeWrite cs i_ c - M.basicUnsafeWrite ds i_ d - {-# INLINE basicClear #-} - basicClear (MV_4 _ as bs cs ds) - = do - M.basicClear as - M.basicClear bs - M.basicClear cs - M.basicClear ds - {-# INLINE basicSet #-} - basicSet (MV_4 _ as bs cs ds) (a, b, c, d) - = do - M.basicSet as a - M.basicSet bs b - M.basicSet cs c - M.basicSet ds d - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_4 _ as1 bs1 cs1 ds1) (MV_4 _ as2 - bs2 - cs2 - ds2) - = do - M.basicUnsafeCopy as1 as2 - M.basicUnsafeCopy bs1 bs2 - M.basicUnsafeCopy cs1 cs2 - M.basicUnsafeCopy ds1 ds2 - {-# INLINE basicUnsafeMove #-} - basicUnsafeMove (MV_4 _ as1 bs1 cs1 ds1) (MV_4 _ as2 - bs2 - cs2 - ds2) - = do - M.basicUnsafeMove as1 as2 - M.basicUnsafeMove bs1 bs2 - M.basicUnsafeMove cs1 cs2 - M.basicUnsafeMove ds1 ds2 - {-# INLINE basicUnsafeGrow #-} - basicUnsafeGrow (MV_4 n_ as bs cs ds) m_ - = do - as' <- M.basicUnsafeGrow as m_ - bs' <- M.basicUnsafeGrow bs m_ - cs' <- M.basicUnsafeGrow cs m_ - ds' <- M.basicUnsafeGrow ds m_ - return $ MV_4 (m_+n_) as' bs' cs' ds' -instance (Unbox a, - Unbox b, - Unbox c, - Unbox d) => G.Vector Vector (a, b, c, d) where - {-# INLINE basicUnsafeFreeze #-} - basicUnsafeFreeze (MV_4 n_ as bs cs ds) - = do - as' <- G.basicUnsafeFreeze as - bs' <- G.basicUnsafeFreeze bs - cs' <- G.basicUnsafeFreeze cs - ds' <- G.basicUnsafeFreeze ds - return $ V_4 n_ as' bs' cs' ds' - {-# INLINE basicUnsafeThaw #-} - basicUnsafeThaw (V_4 n_ as bs cs ds) - = do - as' <- G.basicUnsafeThaw as - bs' <- G.basicUnsafeThaw bs - cs' <- G.basicUnsafeThaw cs - ds' <- G.basicUnsafeThaw ds - return $ MV_4 n_ as' bs' cs' ds' - {-# INLINE basicLength #-} - basicLength (V_4 n_ _ _ _ _) = n_ - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i_ m_ (V_4 _ as bs cs ds) - = V_4 m_ (G.basicUnsafeSlice i_ m_ as) - (G.basicUnsafeSlice i_ m_ bs) - (G.basicUnsafeSlice i_ m_ cs) - (G.basicUnsafeSlice i_ m_ ds) - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM (V_4 _ as bs cs ds) i_ - = do - a <- G.basicUnsafeIndexM as i_ - b <- G.basicUnsafeIndexM bs i_ - c <- G.basicUnsafeIndexM cs i_ - d <- G.basicUnsafeIndexM ds i_ - return (a, b, c, d) - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_4 _ as1 bs1 cs1 ds1) (V_4 _ as2 - bs2 - cs2 - ds2) - = do - G.basicUnsafeCopy as1 as2 - G.basicUnsafeCopy bs1 bs2 - G.basicUnsafeCopy cs1 cs2 - G.basicUnsafeCopy ds1 ds2 - {-# INLINE elemseq #-} - elemseq _ (a, b, c, d) - = G.elemseq (undefined :: Vector a) a - . G.elemseq (undefined :: Vector b) b - . G.elemseq (undefined :: Vector c) c - . G.elemseq (undefined :: Vector d) d - -data instance MVector s (a, b, c, d, e) - = MV_5 {-# UNPACK #-} !Int !(MVector s a) - !(MVector s b) - !(MVector s c) - !(MVector s d) - !(MVector s e) -data instance Vector (a, b, c, d, e) - = V_5 {-# UNPACK #-} !Int !(Vector a) - !(Vector b) - !(Vector c) - !(Vector d) - !(Vector e) -instance (Unbox a, - Unbox b, - Unbox c, - Unbox d, - Unbox e) => Unbox (a, b, c, d, e) -instance (Unbox a, - Unbox b, - Unbox c, - Unbox d, - Unbox e) => M.MVector MVector (a, b, c, d, e) where - {-# INLINE basicLength #-} - basicLength (MV_5 n_ _ _ _ _ _) = n_ - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i_ m_ (MV_5 _ as bs cs ds es) - = MV_5 m_ (M.basicUnsafeSlice i_ m_ as) - (M.basicUnsafeSlice i_ m_ bs) - (M.basicUnsafeSlice i_ m_ cs) - (M.basicUnsafeSlice i_ m_ ds) - (M.basicUnsafeSlice i_ m_ es) - {-# INLINE basicOverlaps #-} - basicOverlaps (MV_5 _ as1 bs1 cs1 ds1 es1) (MV_5 _ as2 - bs2 - cs2 - ds2 - es2) - = M.basicOverlaps as1 as2 - || M.basicOverlaps bs1 bs2 - || M.basicOverlaps cs1 cs2 - || M.basicOverlaps ds1 ds2 - || M.basicOverlaps es1 es2 - {-# INLINE basicUnsafeNew #-} - basicUnsafeNew n_ - = do - as <- M.basicUnsafeNew n_ - bs <- M.basicUnsafeNew n_ - cs <- M.basicUnsafeNew n_ - ds <- M.basicUnsafeNew n_ - es <- M.basicUnsafeNew n_ - return $ MV_5 n_ as bs cs ds es - {-# INLINE basicInitialize #-} - basicInitialize (MV_5 _ as bs cs ds es) - = do - M.basicInitialize as - M.basicInitialize bs - M.basicInitialize cs - M.basicInitialize ds - M.basicInitialize es - {-# INLINE basicUnsafeReplicate #-} - basicUnsafeReplicate n_ (a, b, c, d, e) - = do - as <- M.basicUnsafeReplicate n_ a - bs <- M.basicUnsafeReplicate n_ b - cs <- M.basicUnsafeReplicate n_ c - ds <- M.basicUnsafeReplicate n_ d - es <- M.basicUnsafeReplicate n_ e - return $ MV_5 n_ as bs cs ds es - {-# INLINE basicUnsafeRead #-} - basicUnsafeRead (MV_5 _ as bs cs ds es) i_ - = do - a <- M.basicUnsafeRead as i_ - b <- M.basicUnsafeRead bs i_ - c <- M.basicUnsafeRead cs i_ - d <- M.basicUnsafeRead ds i_ - e <- M.basicUnsafeRead es i_ - return (a, b, c, d, e) - {-# INLINE basicUnsafeWrite #-} - basicUnsafeWrite (MV_5 _ as bs cs ds es) i_ (a, b, c, d, e) - = do - M.basicUnsafeWrite as i_ a - M.basicUnsafeWrite bs i_ b - M.basicUnsafeWrite cs i_ c - M.basicUnsafeWrite ds i_ d - M.basicUnsafeWrite es i_ e - {-# INLINE basicClear #-} - basicClear (MV_5 _ as bs cs ds es) - = do - M.basicClear as - M.basicClear bs - M.basicClear cs - M.basicClear ds - M.basicClear es - {-# INLINE basicSet #-} - basicSet (MV_5 _ as bs cs ds es) (a, b, c, d, e) - = do - M.basicSet as a - M.basicSet bs b - M.basicSet cs c - M.basicSet ds d - M.basicSet es e - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_5 _ as1 bs1 cs1 ds1 es1) (MV_5 _ as2 - bs2 - cs2 - ds2 - es2) - = do - M.basicUnsafeCopy as1 as2 - M.basicUnsafeCopy bs1 bs2 - M.basicUnsafeCopy cs1 cs2 - M.basicUnsafeCopy ds1 ds2 - M.basicUnsafeCopy es1 es2 - {-# INLINE basicUnsafeMove #-} - basicUnsafeMove (MV_5 _ as1 bs1 cs1 ds1 es1) (MV_5 _ as2 - bs2 - cs2 - ds2 - es2) - = do - M.basicUnsafeMove as1 as2 - M.basicUnsafeMove bs1 bs2 - M.basicUnsafeMove cs1 cs2 - M.basicUnsafeMove ds1 ds2 - M.basicUnsafeMove es1 es2 - {-# INLINE basicUnsafeGrow #-} - basicUnsafeGrow (MV_5 n_ as bs cs ds es) m_ - = do - as' <- M.basicUnsafeGrow as m_ - bs' <- M.basicUnsafeGrow bs m_ - cs' <- M.basicUnsafeGrow cs m_ - ds' <- M.basicUnsafeGrow ds m_ - es' <- M.basicUnsafeGrow es m_ - return $ MV_5 (m_+n_) as' bs' cs' ds' es' -instance (Unbox a, - Unbox b, - Unbox c, - Unbox d, - Unbox e) => G.Vector Vector (a, b, c, d, e) where - {-# INLINE basicUnsafeFreeze #-} - basicUnsafeFreeze (MV_5 n_ as bs cs ds es) - = do - as' <- G.basicUnsafeFreeze as - bs' <- G.basicUnsafeFreeze bs - cs' <- G.basicUnsafeFreeze cs - ds' <- G.basicUnsafeFreeze ds - es' <- G.basicUnsafeFreeze es - return $ V_5 n_ as' bs' cs' ds' es' - {-# INLINE basicUnsafeThaw #-} - basicUnsafeThaw (V_5 n_ as bs cs ds es) - = do - as' <- G.basicUnsafeThaw as - bs' <- G.basicUnsafeThaw bs - cs' <- G.basicUnsafeThaw cs - ds' <- G.basicUnsafeThaw ds - es' <- G.basicUnsafeThaw es - return $ MV_5 n_ as' bs' cs' ds' es' - {-# INLINE basicLength #-} - basicLength (V_5 n_ _ _ _ _ _) = n_ - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i_ m_ (V_5 _ as bs cs ds es) - = V_5 m_ (G.basicUnsafeSlice i_ m_ as) - (G.basicUnsafeSlice i_ m_ bs) - (G.basicUnsafeSlice i_ m_ cs) - (G.basicUnsafeSlice i_ m_ ds) - (G.basicUnsafeSlice i_ m_ es) - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM (V_5 _ as bs cs ds es) i_ - = do - a <- G.basicUnsafeIndexM as i_ - b <- G.basicUnsafeIndexM bs i_ - c <- G.basicUnsafeIndexM cs i_ - d <- G.basicUnsafeIndexM ds i_ - e <- G.basicUnsafeIndexM es i_ - return (a, b, c, d, e) - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_5 _ as1 bs1 cs1 ds1 es1) (V_5 _ as2 - bs2 - cs2 - ds2 - es2) - = do - G.basicUnsafeCopy as1 as2 - G.basicUnsafeCopy bs1 bs2 - G.basicUnsafeCopy cs1 cs2 - G.basicUnsafeCopy ds1 ds2 - G.basicUnsafeCopy es1 es2 - {-# INLINE elemseq #-} - elemseq _ (a, b, c, d, e) - = G.elemseq (undefined :: Vector a) a - . G.elemseq (undefined :: Vector b) b - . G.elemseq (undefined :: Vector c) c - . G.elemseq (undefined :: Vector d) d - . G.elemseq (undefined :: Vector e) e - -data instance MVector s (a, b, c, d, e, f) - = MV_6 {-# UNPACK #-} !Int !(MVector s a) - !(MVector s b) - !(MVector s c) - !(MVector s d) - !(MVector s e) - !(MVector s f) -data instance Vector (a, b, c, d, e, f) - = V_6 {-# UNPACK #-} !Int !(Vector a) - !(Vector b) - !(Vector c) - !(Vector d) - !(Vector e) - !(Vector f) -instance (Unbox a, - Unbox b, - Unbox c, - Unbox d, - Unbox e, - Unbox f) => Unbox (a, b, c, d, e, f) -instance (Unbox a, - Unbox b, - Unbox c, - Unbox d, - Unbox e, - Unbox f) => M.MVector MVector (a, b, c, d, e, f) where - {-# INLINE basicLength #-} - basicLength (MV_6 n_ _ _ _ _ _ _) = n_ - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i_ m_ (MV_6 _ as bs cs ds es fs) - = MV_6 m_ (M.basicUnsafeSlice i_ m_ as) - (M.basicUnsafeSlice i_ m_ bs) - (M.basicUnsafeSlice i_ m_ cs) - (M.basicUnsafeSlice i_ m_ ds) - (M.basicUnsafeSlice i_ m_ es) - (M.basicUnsafeSlice i_ m_ fs) - {-# INLINE basicOverlaps #-} - basicOverlaps (MV_6 _ as1 bs1 cs1 ds1 es1 fs1) (MV_6 _ as2 - bs2 - cs2 - ds2 - es2 - fs2) - = M.basicOverlaps as1 as2 - || M.basicOverlaps bs1 bs2 - || M.basicOverlaps cs1 cs2 - || M.basicOverlaps ds1 ds2 - || M.basicOverlaps es1 es2 - || M.basicOverlaps fs1 fs2 - {-# INLINE basicUnsafeNew #-} - basicUnsafeNew n_ - = do - as <- M.basicUnsafeNew n_ - bs <- M.basicUnsafeNew n_ - cs <- M.basicUnsafeNew n_ - ds <- M.basicUnsafeNew n_ - es <- M.basicUnsafeNew n_ - fs <- M.basicUnsafeNew n_ - return $ MV_6 n_ as bs cs ds es fs - {-# INLINE basicInitialize #-} - basicInitialize (MV_6 _ as bs cs ds es fs) - = do - M.basicInitialize as - M.basicInitialize bs - M.basicInitialize cs - M.basicInitialize ds - M.basicInitialize es - M.basicInitialize fs - {-# INLINE basicUnsafeReplicate #-} - basicUnsafeReplicate n_ (a, b, c, d, e, f) - = do - as <- M.basicUnsafeReplicate n_ a - bs <- M.basicUnsafeReplicate n_ b - cs <- M.basicUnsafeReplicate n_ c - ds <- M.basicUnsafeReplicate n_ d - es <- M.basicUnsafeReplicate n_ e - fs <- M.basicUnsafeReplicate n_ f - return $ MV_6 n_ as bs cs ds es fs - {-# INLINE basicUnsafeRead #-} - basicUnsafeRead (MV_6 _ as bs cs ds es fs) i_ - = do - a <- M.basicUnsafeRead as i_ - b <- M.basicUnsafeRead bs i_ - c <- M.basicUnsafeRead cs i_ - d <- M.basicUnsafeRead ds i_ - e <- M.basicUnsafeRead es i_ - f <- M.basicUnsafeRead fs i_ - return (a, b, c, d, e, f) - {-# INLINE basicUnsafeWrite #-} - basicUnsafeWrite (MV_6 _ as bs cs ds es fs) i_ (a, b, c, d, e, f) - = do - M.basicUnsafeWrite as i_ a - M.basicUnsafeWrite bs i_ b - M.basicUnsafeWrite cs i_ c - M.basicUnsafeWrite ds i_ d - M.basicUnsafeWrite es i_ e - M.basicUnsafeWrite fs i_ f - {-# INLINE basicClear #-} - basicClear (MV_6 _ as bs cs ds es fs) - = do - M.basicClear as - M.basicClear bs - M.basicClear cs - M.basicClear ds - M.basicClear es - M.basicClear fs - {-# INLINE basicSet #-} - basicSet (MV_6 _ as bs cs ds es fs) (a, b, c, d, e, f) - = do - M.basicSet as a - M.basicSet bs b - M.basicSet cs c - M.basicSet ds d - M.basicSet es e - M.basicSet fs f - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_6 _ as1 bs1 cs1 ds1 es1 fs1) (MV_6 _ as2 - bs2 - cs2 - ds2 - es2 - fs2) - = do - M.basicUnsafeCopy as1 as2 - M.basicUnsafeCopy bs1 bs2 - M.basicUnsafeCopy cs1 cs2 - M.basicUnsafeCopy ds1 ds2 - M.basicUnsafeCopy es1 es2 - M.basicUnsafeCopy fs1 fs2 - {-# INLINE basicUnsafeMove #-} - basicUnsafeMove (MV_6 _ as1 bs1 cs1 ds1 es1 fs1) (MV_6 _ as2 - bs2 - cs2 - ds2 - es2 - fs2) - = do - M.basicUnsafeMove as1 as2 - M.basicUnsafeMove bs1 bs2 - M.basicUnsafeMove cs1 cs2 - M.basicUnsafeMove ds1 ds2 - M.basicUnsafeMove es1 es2 - M.basicUnsafeMove fs1 fs2 - {-# INLINE basicUnsafeGrow #-} - basicUnsafeGrow (MV_6 n_ as bs cs ds es fs) m_ - = do - as' <- M.basicUnsafeGrow as m_ - bs' <- M.basicUnsafeGrow bs m_ - cs' <- M.basicUnsafeGrow cs m_ - ds' <- M.basicUnsafeGrow ds m_ - es' <- M.basicUnsafeGrow es m_ - fs' <- M.basicUnsafeGrow fs m_ - return $ MV_6 (m_+n_) as' bs' cs' ds' es' fs' -instance (Unbox a, - Unbox b, - Unbox c, - Unbox d, - Unbox e, - Unbox f) => G.Vector Vector (a, b, c, d, e, f) where - {-# INLINE basicUnsafeFreeze #-} - basicUnsafeFreeze (MV_6 n_ as bs cs ds es fs) - = do - as' <- G.basicUnsafeFreeze as - bs' <- G.basicUnsafeFreeze bs - cs' <- G.basicUnsafeFreeze cs - ds' <- G.basicUnsafeFreeze ds - es' <- G.basicUnsafeFreeze es - fs' <- G.basicUnsafeFreeze fs - return $ V_6 n_ as' bs' cs' ds' es' fs' - {-# INLINE basicUnsafeThaw #-} - basicUnsafeThaw (V_6 n_ as bs cs ds es fs) - = do - as' <- G.basicUnsafeThaw as - bs' <- G.basicUnsafeThaw bs - cs' <- G.basicUnsafeThaw cs - ds' <- G.basicUnsafeThaw ds - es' <- G.basicUnsafeThaw es - fs' <- G.basicUnsafeThaw fs - return $ MV_6 n_ as' bs' cs' ds' es' fs' - {-# INLINE basicLength #-} - basicLength (V_6 n_ _ _ _ _ _ _) = n_ - {-# INLINE basicUnsafeSlice #-} - basicUnsafeSlice i_ m_ (V_6 _ as bs cs ds es fs) - = V_6 m_ (G.basicUnsafeSlice i_ m_ as) - (G.basicUnsafeSlice i_ m_ bs) - (G.basicUnsafeSlice i_ m_ cs) - (G.basicUnsafeSlice i_ m_ ds) - (G.basicUnsafeSlice i_ m_ es) - (G.basicUnsafeSlice i_ m_ fs) - {-# INLINE basicUnsafeIndexM #-} - basicUnsafeIndexM (V_6 _ as bs cs ds es fs) i_ - = do - a <- G.basicUnsafeIndexM as i_ - b <- G.basicUnsafeIndexM bs i_ - c <- G.basicUnsafeIndexM cs i_ - d <- G.basicUnsafeIndexM ds i_ - e <- G.basicUnsafeIndexM es i_ - f <- G.basicUnsafeIndexM fs i_ - return (a, b, c, d, e, f) - {-# INLINE basicUnsafeCopy #-} - basicUnsafeCopy (MV_6 _ as1 bs1 cs1 ds1 es1 fs1) (V_6 _ as2 - bs2 - cs2 - ds2 - es2 - fs2) - = do - G.basicUnsafeCopy as1 as2 - G.basicUnsafeCopy bs1 bs2 - G.basicUnsafeCopy cs1 cs2 - G.basicUnsafeCopy ds1 ds2 - G.basicUnsafeCopy es1 es2 - G.basicUnsafeCopy fs1 fs2 - {-# INLINE elemseq #-} - elemseq _ (a, b, c, d, e, f) - = G.elemseq (undefined :: Vector a) a - . G.elemseq (undefined :: Vector b) b - . G.elemseq (undefined :: Vector c) c - . G.elemseq (undefined :: Vector d) d - . G.elemseq (undefined :: Vector e) e - . G.elemseq (undefined :: Vector f) f +module Data.Vector.Unboxed.Base {-# DEPRECATED "Use Data.Vector.Unboxed.Unsafe instead" #-} + ( module Data.Vector.Unboxed.Unsafe + ) where +import Data.Vector.Unboxed.Unsafe diff --git a/vector/src/Data/Vector/Unboxed/Mutable.hs b/vector/src/Data/Vector/Unboxed/Mutable.hs index 3667af1f..bc5f889a 100644 --- a/vector/src/Data/Vector/Unboxed/Mutable.hs +++ b/vector/src/Data/Vector/Unboxed/Mutable.hs @@ -1,5 +1,5 @@ {-# LANGUAGE CPP #-} - +{-# LANGUAGE PatternSynonyms #-} -- | -- Module : Data.Vector.Unboxed.Mutable -- Copyright : (c) Roman Leshchinskiy 2009-2010 @@ -16,7 +16,11 @@ module Data.Vector.Unboxed.Mutable ( -- * Mutable vectors of primitive types - MVector(..), IOVector, STVector, Unbox, + MVector(MV_UnboxViaPrim, MV_UnboxViaStorable, MV_DoNotUnboxLazy, MV_DoNotUnboxStrict, MV_DoNotUnboxNormalForm, MV_UnboxAs, + MV_Int,MV_Int8,MV_Int16,MV_Int32,MV_Int64,MV_Word,MV_Word8,MV_Word16,MV_Word32,MV_Word64,MV_Float,MV_Double, + MV_Char,MV_Bool,MV_Complex,MV_Identity,MV_Down,MV_Dual,MV_Sum,MV_Product,MV_Min,MV_Max,MV_First,MV_Last, + MV_WrappedMonoid,MV_Arg,MV_Any,MV_All,MV_Const,MV_Alt,MV_Compose), + IOVector, STVector, Unbox, -- * Accessors @@ -65,10 +69,14 @@ module Data.Vector.Unboxed.Mutable ( -- ** Filling and copying set, copy, move, unsafeCopy, unsafeMove, -- * Re-exports - PrimMonad, PrimState, RealWorld + PrimMonad, PrimState, RealWorld, + -- * Deprecated + pattern MV_Unit, + pattern MV_2, pattern MV_3, pattern MV_4, pattern MV_5, pattern MV_6 ) where -import Data.Vector.Unboxed.Base +import Data.Vector.Unboxed.Unsafe (MVector, STVector,Unbox,IOVector) +import qualified Data.Vector.Unboxed.Unsafe as U import qualified Data.Vector.Generic.Mutable as G import Data.Vector.Fusion.Util ( delayed_min ) import Control.Monad.Primitive @@ -671,20 +679,20 @@ ifoldrM' = G.ifoldrM' zip :: (Unbox a, Unbox b) => MVector s a -> MVector s b -> MVector s (a, b) {-# INLINE_FUSED zip #-} -zip as bs = MV_2 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) +zip as bs = U.MV_2 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) where len = length as `delayed_min` length bs -- | /O(1)/ Unzip 2 vectors. unzip :: (Unbox a, Unbox b) => MVector s (a, b) -> (MVector s a, MVector s b) {-# INLINE unzip #-} -unzip (MV_2 _ as bs) = (as, bs) +unzip (U.MV_2 _ as bs) = (as, bs) -- | /O(1)/ Zip 3 vectors. zip3 :: (Unbox a, Unbox b, Unbox c) => MVector s a -> MVector s b -> MVector s c -> MVector s (a, b, c) {-# INLINE_FUSED zip3 #-} -zip3 as bs cs = MV_3 len (unsafeSlice 0 len as) +zip3 as bs cs = U.MV_3 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) (unsafeSlice 0 len cs) where @@ -696,7 +704,7 @@ unzip3 :: (Unbox a, MVector s b, MVector s c) {-# INLINE unzip3 #-} -unzip3 (MV_3 _ as bs cs) = (as, bs, cs) +unzip3 (U.MV_3 _ as bs cs) = (as, bs, cs) -- | /O(1)/ Zip 4 vectors. zip4 :: (Unbox a, Unbox b, Unbox c, Unbox d) => MVector s a -> @@ -704,7 +712,7 @@ zip4 :: (Unbox a, Unbox b, Unbox c, Unbox d) => MVector s a -> MVector s c -> MVector s d -> MVector s (a, b, c, d) {-# INLINE_FUSED zip4 #-} -zip4 as bs cs ds = MV_4 len (unsafeSlice 0 len as) +zip4 as bs cs ds = U.MV_4 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) (unsafeSlice 0 len cs) (unsafeSlice 0 len ds) @@ -722,7 +730,7 @@ unzip4 :: (Unbox a, MVector s c, MVector s d) {-# INLINE unzip4 #-} -unzip4 (MV_4 _ as bs cs ds) = (as, bs, cs, ds) +unzip4 (U.MV_4 _ as bs cs ds) = (as, bs, cs, ds) -- | /O(1)/ Zip 5 vectors. zip5 :: (Unbox a, @@ -735,7 +743,7 @@ zip5 :: (Unbox a, MVector s d -> MVector s e -> MVector s (a, b, c, d, e) {-# INLINE_FUSED zip5 #-} -zip5 as bs cs ds es = MV_5 len (unsafeSlice 0 len as) +zip5 as bs cs ds es = U.MV_5 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) (unsafeSlice 0 len cs) (unsafeSlice 0 len ds) @@ -757,7 +765,7 @@ unzip5 :: (Unbox a, MVector s d, MVector s e) {-# INLINE unzip5 #-} -unzip5 (MV_5 _ as bs cs ds es) = (as, bs, cs, ds, es) +unzip5 (U.MV_5 _ as bs cs ds es) = (as, bs, cs, ds, es) -- | /O(1)/ Zip 6 vectors. zip6 :: (Unbox a, @@ -772,7 +780,7 @@ zip6 :: (Unbox a, MVector s e -> MVector s f -> MVector s (a, b, c, d, e, f) {-# INLINE_FUSED zip6 #-} -zip6 as bs cs ds es fs = MV_6 len (unsafeSlice 0 len as) +zip6 as bs cs ds es fs = U.MV_6 len (unsafeSlice 0 len as) (unsafeSlice 0 len bs) (unsafeSlice 0 len cs) (unsafeSlice 0 len ds) @@ -798,7 +806,40 @@ unzip6 :: (Unbox a, MVector s e, MVector s f) {-# INLINE unzip6 #-} -unzip6 (MV_6 _ as bs cs ds es fs) = (as, bs, cs, ds, es, fs) +unzip6 (U.MV_6 _ as bs cs ds es fs) = (as, bs, cs, ds, es, fs) -- $setup -- >>> import Prelude (Char, (*), ($)) + + +pattern MV_Unit :: Int -> MVector s () +pattern MV_Unit i = U.MV_Unit i +{-# COMPLETE MV_Unit #-} +{-# DEPRECATED MV_Unit "Import constructor from \"Data.Vector.Unboxed.Unsafe\"" #-} + +pattern MV_2 :: Int -> MVector s a -> MVector s b -> MVector s (a,b) +pattern MV_2 i va vb = U.MV_2 i va vb +{-# COMPLETE MV_2 #-} +{-# DEPRECATED MV_2 "Import constructor from \"Data.Vector.Unboxed.Unsafe\"" #-} + +pattern MV_3 :: Int -> MVector s a -> MVector s b -> MVector s c -> MVector s (a,b,c) +pattern MV_3 i va vb vc = U.MV_3 i va vb vc +{-# COMPLETE MV_3 #-} +{-# DEPRECATED MV_3 "Import constructor from \"Data.Vector.Unboxed.Unsafe\"" #-} + +pattern MV_4 :: Int -> MVector s a -> MVector s b -> MVector s c -> MVector s d -> MVector s (a,b,c,d) +pattern MV_4 i va vb vc vd = U.MV_4 i va vb vc vd +{-# COMPLETE MV_4 #-} +{-# DEPRECATED MV_4 "Import constructor from \"Data.Vector.Unboxed.Unsafe\"" #-} + +pattern MV_5 :: Int -> MVector s a -> MVector s b -> MVector s c -> MVector s d + -> MVector s e -> MVector s (a,b,c,d,e) +pattern MV_5 i va vb vc vd ve = U.MV_5 i va vb vc vd ve +{-# COMPLETE MV_5 #-} +{-# DEPRECATED MV_5 "Import constructor from \"Data.Vector.Unboxed.Unsafe\"" #-} + +pattern MV_6 :: Int -> 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) +pattern MV_6 i va vb vc vd ve vf = U.MV_6 i va vb vc vd ve vf +{-# COMPLETE MV_6 #-} +{-# DEPRECATED MV_6 "Import constructor from \"Data.Vector.Unboxed.Unsafe\"" #-} diff --git a/vector/src/Data/Vector/Unboxed/Unsafe.hs b/vector/src/Data/Vector/Unboxed/Unsafe.hs new file mode 100644 index 00000000..828c6846 --- /dev/null +++ b/vector/src/Data/Vector/Unboxed/Unsafe.hs @@ -0,0 +1,1931 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE DefaultSignatures #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE PolyKinds #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE DerivingVia #-} +-- | +-- Module : Data.Vector.Unboxed.Unsafe +-- Copyright : (c) Roman Leshchinskiy 2009-2010 +-- Alexey Kuleshevich 2020-2022 +-- Aleksey Khudyakov 2020-2022 +-- Andrew Lelechenko 2020-2022 +-- License : BSD-style +-- +-- Maintainer : Haskell Libraries Team +-- Stability : experimental +-- Portability : non-portable +-- +-- Adaptive unboxed vectors. This module exposes internal +-- representation for all unboxed vectors. Both pure and mutable +-- vectors are exposed from this module. +-- +-- Note that working with internal representation is generally unsafe +-- and may violate memory safety. Data family constructors which are +-- safe exposed in "Data.Vector.Unboxed" and +-- "Data.Vector.Unboxed.Mutable" modules. +module Data.Vector.Unboxed.Unsafe ( + MVector(..), IOVector, STVector, Vector(..), Unbox, + UnboxViaPrim(..), UnboxViaStorable(..), As(..), IsoUnbox(..), + DoNotUnboxLazy(..), DoNotUnboxNormalForm(..), DoNotUnboxStrict(..) +) where + +import qualified Data.Vector.Generic as G +import qualified Data.Vector.Generic.Mutable as M +import qualified Data.Vector as B +import qualified Data.Vector.Strict as S +import qualified Data.Vector.Storable as St + +import qualified Data.Vector.Primitive as P + +import Control.Applicative (Const(..)) + +import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf), force) + +import Control.Monad.Primitive +import Control.Monad ( liftM ) + +import Data.Functor.Identity +import Data.Functor.Compose +import Data.Word ( Word8, Word16, Word32, Word64 ) +import Data.Int ( Int8, Int16, Int32, Int64 ) +import Data.Complex +import Data.Monoid (Dual(..),Sum(..),Product(..),All(..),Any(..)) +import Data.Monoid (Alt(..)) +import Data.Semigroup (Min(..),Max(..),First(..),Last(..),WrappedMonoid(..),Arg(..)) +import Data.Data ( Data(..) ) +import GHC.Exts ( Down(..) ) +import GHC.Generics +import Data.Coerce +import Data.Kind (Type) + +#include "vector.h" + +data family MVector s a +data family Vector a + +type IOVector = MVector RealWorld +type STVector s = MVector s + +type instance G.Mutable Vector = MVector + +class (G.Vector Vector a, M.MVector MVector a) => Unbox a + +instance NFData (Vector a) where rnf !_ = () +instance NFData (MVector s a) where rnf !_ = () + +-- | @since 0.12.1.0 +instance NFData1 Vector where + liftRnf _ !_ = () +-- | @since 0.12.1.0 +instance NFData1 (MVector s) where + liftRnf _ !_ = () + + +instance (Data a, Unbox a) => Data (Vector a) where + gfoldl = G.gfoldl + toConstr _ = G.mkVecConstr "Data.Vector.Unboxed.Vector" + gunfold = G.gunfold + dataTypeOf _ = G.mkVecType "Data.Vector.Unboxed.Vector" + dataCast1 = G.dataCast + +-- ---- +-- Unit +-- ---- + +newtype instance MVector s () = MV_Unit Int +newtype instance Vector () = V_Unit Int + +instance Unbox () + +instance M.MVector MVector () where + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicOverlaps #-} + {-# INLINE basicUnsafeNew #-} + {-# INLINE basicInitialize #-} + {-# INLINE basicUnsafeRead #-} + {-# INLINE basicUnsafeWrite #-} + {-# INLINE basicClear #-} + {-# INLINE basicSet #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE basicUnsafeGrow #-} + + basicLength (MV_Unit n) = n + + basicUnsafeSlice _ m (MV_Unit _) = MV_Unit m + + basicOverlaps _ _ = False + + basicUnsafeNew n = return (MV_Unit n) + + -- Nothing to initialize + basicInitialize _ = return () + + basicUnsafeRead (MV_Unit _) _ = return () + + basicUnsafeWrite (MV_Unit _) _ () = return () + + basicClear _ = return () + + basicSet (MV_Unit _) () = return () + + basicUnsafeCopy (MV_Unit _) (MV_Unit _) = return () + + basicUnsafeGrow (MV_Unit n) m = return $ MV_Unit (n+m) + +instance G.Vector Vector () where + {-# INLINE basicUnsafeFreeze #-} + basicUnsafeFreeze (MV_Unit n) = return $ V_Unit n + + {-# INLINE basicUnsafeThaw #-} + basicUnsafeThaw (V_Unit n) = return $ MV_Unit n + + {-# INLINE basicLength #-} + basicLength (V_Unit n) = n + + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice _ m (V_Unit _) = V_Unit m + + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM (V_Unit _) _ = return () + + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_Unit _) (V_Unit _) = return () + + {-# INLINE elemseq #-} + elemseq _ = seq + + +-- --------------- +-- Primitive types +-- --------------- + +-- | Newtype wrapper which allows to derive unboxed vector in term of +-- primitive vectors using @DerivingVia@ mechanism. This is mostly +-- used as illustration of use of @DerivingVia@ for vector, see examples below. +-- +-- First is rather straightforward: we define newtype and use GND to +-- derive 'P.Prim' instance. Newtype instances should be defined +-- manually. Then we use deriving via to define necessary instances. +-- +-- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia -XMultiParamTypeClasses +-- >>> -- Needed to derive Prim +-- >>> :set -XGeneralizedNewtypeDeriving -XDataKinds -XUnboxedTuples -XPolyKinds +-- >>> +-- >>> import qualified Data.Vector.Generic as VG +-- >>> import qualified Data.Vector.Generic.Mutable as VGM +-- >>> import qualified Data.Vector.Primitive as VP +-- >>> import qualified Data.Vector.Unboxed as VU +-- >>> +-- >>> newtype Foo = Foo Int deriving VP.Prim +-- >>> +-- >>> newtype instance VU.MVector s Foo = MV_Foo (VP.MVector s Foo) +-- >>> newtype instance VU.Vector Foo = V_Foo (VP.Vector Foo) +-- >>> deriving via (VU.UnboxViaPrim Foo) instance VGM.MVector VU.MVector Foo +-- >>> deriving via (VU.UnboxViaPrim Foo) instance VG.Vector VU.Vector Foo +-- >>> instance VU.Unbox Foo +-- +-- Second example is essentially same but with a twist. Instead of +-- using 'P.Prim' instance of data type, we use underlying instance of 'Int': +-- +-- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia -XMultiParamTypeClasses +-- >>> +-- >>> import qualified Data.Vector.Generic as VG +-- >>> import qualified Data.Vector.Generic.Mutable as VGM +-- >>> import qualified Data.Vector.Primitive as VP +-- >>> import qualified Data.Vector.Unboxed as VU +-- >>> +-- >>> newtype Foo = Foo Int +-- >>> +-- >>> newtype instance VU.MVector s Foo = MV_Foo (VP.MVector s Int) +-- >>> newtype instance VU.Vector Foo = V_Foo (VP.Vector Int) +-- >>> deriving via (VU.UnboxViaPrim Int) instance VGM.MVector VU.MVector Foo +-- >>> deriving via (VU.UnboxViaPrim Int) instance VG.Vector VU.Vector Foo +-- >>> instance VU.Unbox Foo +-- +-- @since 0.13.0.0 +newtype UnboxViaPrim a = UnboxViaPrim a + +newtype instance MVector s (UnboxViaPrim a) = MV_UnboxViaPrim (P.MVector s a) +newtype instance Vector (UnboxViaPrim a) = V_UnboxViaPrim (P.Vector a) + +instance P.Prim a => M.MVector MVector (UnboxViaPrim a) where + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicOverlaps #-} + {-# INLINE basicUnsafeNew #-} + {-# INLINE basicInitialize #-} + {-# INLINE basicUnsafeReplicate #-} + {-# INLINE basicUnsafeRead #-} + {-# INLINE basicUnsafeWrite #-} + {-# INLINE basicClear #-} + {-# INLINE basicSet #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE basicUnsafeGrow #-} + basicLength = coerce $ M.basicLength @P.MVector @a + basicUnsafeSlice = coerce $ M.basicUnsafeSlice @P.MVector @a + basicOverlaps = coerce $ M.basicOverlaps @P.MVector @a + basicUnsafeNew = coerce $ M.basicUnsafeNew @P.MVector @a + basicInitialize = coerce $ M.basicInitialize @P.MVector @a + basicUnsafeReplicate = coerce $ M.basicUnsafeReplicate @P.MVector @a + basicUnsafeRead = coerce $ M.basicUnsafeRead @P.MVector @a + basicUnsafeWrite = coerce $ M.basicUnsafeWrite @P.MVector @a + basicClear = coerce $ M.basicClear @P.MVector @a + basicSet = coerce $ M.basicSet @P.MVector @a + basicUnsafeCopy = coerce $ M.basicUnsafeCopy @P.MVector @a + basicUnsafeMove = coerce $ M.basicUnsafeMove @P.MVector @a + basicUnsafeGrow = coerce $ M.basicUnsafeGrow @P.MVector @a + +instance P.Prim a => G.Vector Vector (UnboxViaPrim a) where + {-# INLINE basicUnsafeFreeze #-} + {-# INLINE basicUnsafeThaw #-} + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicUnsafeIndexM #-} + {-# INLINE elemseq #-} + basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @P.Vector @a + basicUnsafeThaw = coerce $ G.basicUnsafeThaw @P.Vector @a + basicLength = coerce $ G.basicLength @P.Vector @a + basicUnsafeSlice = coerce $ G.basicUnsafeSlice @P.Vector @a + basicUnsafeIndexM = coerce $ G.basicUnsafeIndexM @P.Vector @a + basicUnsafeCopy = coerce $ G.basicUnsafeCopy @P.Vector @a + elemseq _ = seq + +-- | Isomorphism between type @a@ and its representation in unboxed +-- vector @b@. Default instance coerces between generic +-- representations of @a@ and @b@ which means they have same shape and +-- corresponding fields could be coerced to each other. Note that this +-- means it's possible to have fields that have different types: +-- +-- >>> :set -XMultiParamTypeClasses -XDeriveGeneric -XFlexibleInstances +-- >>> import GHC.Generics (Generic) +-- >>> import Data.Monoid +-- >>> import qualified Data.Vector.Unboxed as VU +-- >>> :{ +-- data Foo a = Foo Int a +-- deriving (Show,Generic) +-- instance VU.IsoUnbox (Foo a) (Int, a) +-- instance VU.IsoUnbox (Foo a) (Sum Int, Product a) +-- :} +-- +-- @since 0.13.0.0 +class IsoUnbox a b where + -- | Convert value into it representation in unboxed vector. + toURepr :: a -> b + default toURepr :: (Generic a, Generic b, Coercible (Rep a ()) (Rep b ())) => a -> b + toURepr = to . idU . coerce . idU . from + -- | Convert value representation in unboxed vector back to value. + fromURepr :: b -> a + default fromURepr :: (Generic a, Generic b, Coercible (Rep b ()) (Rep a ())) => b -> a + fromURepr = to . idU . coerce . idU . from + +idU :: f () -> f () +idU = id + + +-- | Newtype which allows to derive unbox instances for type @a@ which +-- uses @b@ as underlying representation (usually tuple). Type @a@ and +-- its representation @b@ are connected by type class +-- 'IsoUnbox'. Here's example which uses explicit 'IsoUnbox' instance: +-- +-- +-- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia +-- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances +-- >>> import qualified Data.Vector.Unboxed as VU +-- >>> import qualified Data.Vector.Unboxed.Mutable as MVU +-- >>> import qualified Data.Vector.Generic as VG +-- >>> import qualified Data.Vector.Generic.Mutable as VGM +-- >>> :{ +-- data Foo a = Foo Int a +-- deriving Show +-- instance VU.IsoUnbox (Foo a) (Int,a) where +-- toURepr (Foo i a) = (i,a) +-- fromURepr (i,a) = Foo i a +-- {-# INLINE toURepr #-} +-- {-# INLINE fromURepr #-} +-- newtype instance VU.MVector s (Foo a) = MV_Foo (VU.MVector s (Int, a)) +-- newtype instance VU.Vector (Foo a) = V_Foo (VU.Vector (Int, a)) +-- deriving via (Foo a `VU.As` (Int, a)) instance VU.Unbox a => VGM.MVector MVU.MVector (Foo a) +-- deriving via (Foo a `VU.As` (Int, a)) instance VU.Unbox a => VG.Vector VU.Vector (Foo a) +-- instance VU.Unbox a => VU.Unbox (Foo a) +-- :} +-- +-- +-- It's also possible to use generic-based instance for 'IsoUnbox' +-- which should work for all product types. +-- +-- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances -XDeriveGeneric +-- >>> :set -XDerivingVia +-- >>> import qualified Data.Vector.Unboxed as VU +-- >>> import qualified Data.Vector.Generic as VG +-- >>> import qualified Data.Vector.Generic.Mutable as VGM +-- >>> :{ +-- data Bar a = Bar Int a +-- deriving (Show,Generic) +-- instance VU.IsoUnbox (Bar a) (Int,a) where +-- newtype instance VU.MVector s (Bar a) = MV_Bar (VU.MVector s (Int, a)) +-- newtype instance VU.Vector (Bar a) = V_Bar (VU.Vector (Int, a)) +-- deriving via (Bar a `VU.As` (Int, a)) instance VU.Unbox a => VGM.MVector VU.MVector (Bar a) +-- deriving via (Bar a `VU.As` (Int, a)) instance VU.Unbox a => VG.Vector VU.Vector (Bar a) +-- instance VU.Unbox a => VU.Unbox (Bar a) +-- :} +-- +-- @since 0.13.0.0 +newtype As (a :: Type) (b :: Type) = As a + +newtype instance MVector s (As a b) = MV_UnboxAs (MVector s b) +newtype instance Vector (As a b) = V_UnboxAs (Vector b) + +instance (IsoUnbox a b, Unbox b) => M.MVector MVector (As a b) where + -- Methods that just use underlying vector + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicOverlaps #-} + {-# INLINE basicUnsafeNew #-} + {-# INLINE basicInitialize #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE basicUnsafeMove #-} + {-# INLINE basicUnsafeGrow #-} + {-# INLINE basicClear #-} + basicLength = coerce $ M.basicLength @MVector @b + basicUnsafeSlice = coerce $ M.basicUnsafeSlice @MVector @b + basicOverlaps = coerce $ M.basicOverlaps @MVector @b + basicUnsafeNew = coerce $ M.basicUnsafeNew @MVector @b + basicInitialize = coerce $ M.basicInitialize @MVector @b + basicUnsafeCopy = coerce $ M.basicUnsafeCopy @MVector @b + basicUnsafeMove = coerce $ M.basicUnsafeMove @MVector @b + basicUnsafeGrow = coerce $ M.basicUnsafeGrow @MVector @b + basicClear = coerce $ M.basicClear @MVector @b + -- Conversion to/from underlying representation + {-# INLINE basicUnsafeReplicate #-} + {-# INLINE basicUnsafeRead #-} + {-# INLINE basicUnsafeWrite #-} + {-# INLINE basicSet #-} + basicUnsafeReplicate n (As x) = MV_UnboxAs <$> M.basicUnsafeReplicate n (toURepr x) + basicUnsafeRead (MV_UnboxAs v) i = As . fromURepr <$> M.basicUnsafeRead v i + basicUnsafeWrite (MV_UnboxAs v) i (As x) = M.basicUnsafeWrite v i (toURepr x) + basicSet (MV_UnboxAs v) (As x) = M.basicSet v (toURepr x) + +instance (IsoUnbox a b, Unbox b) => G.Vector Vector (As a b) where + -- Method that just use underlying vector + {-# INLINE basicUnsafeFreeze #-} + {-# INLINE basicUnsafeThaw #-} + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE elemseq #-} + basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @Vector @b + basicUnsafeThaw = coerce $ G.basicUnsafeThaw @Vector @b + basicLength = coerce $ G.basicLength @Vector @b + basicUnsafeSlice = coerce $ G.basicUnsafeSlice @Vector @b + basicUnsafeCopy = coerce $ G.basicUnsafeCopy @Vector @b + elemseq _ = seq + -- Conversion to/from underlying representation + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM (V_UnboxAs v) i = As . fromURepr <$> G.basicUnsafeIndexM v i + + +newtype instance MVector s Int = MV_Int (P.MVector s Int) +newtype instance Vector Int = V_Int (P.Vector Int) +deriving via (UnboxViaPrim Int) instance M.MVector MVector Int +deriving via (UnboxViaPrim Int) instance G.Vector Vector Int +instance Unbox Int + +newtype instance MVector s Int8 = MV_Int8 (P.MVector s Int8) +newtype instance Vector Int8 = V_Int8 (P.Vector Int8) +deriving via (UnboxViaPrim Int8) instance M.MVector MVector Int8 +deriving via (UnboxViaPrim Int8) instance G.Vector Vector Int8 +instance Unbox Int8 + +newtype instance MVector s Int16 = MV_Int16 (P.MVector s Int16) +newtype instance Vector Int16 = V_Int16 (P.Vector Int16) +deriving via (UnboxViaPrim Int16) instance M.MVector MVector Int16 +deriving via (UnboxViaPrim Int16) instance G.Vector Vector Int16 +instance Unbox Int16 + +newtype instance MVector s Int32 = MV_Int32 (P.MVector s Int32) +newtype instance Vector Int32 = V_Int32 (P.Vector Int32) +deriving via (UnboxViaPrim Int32) instance M.MVector MVector Int32 +deriving via (UnboxViaPrim Int32) instance G.Vector Vector Int32 +instance Unbox Int32 + +newtype instance MVector s Int64 = MV_Int64 (P.MVector s Int64) +newtype instance Vector Int64 = V_Int64 (P.Vector Int64) +deriving via (UnboxViaPrim Int64) instance M.MVector MVector Int64 +deriving via (UnboxViaPrim Int64) instance G.Vector Vector Int64 +instance Unbox Int64 + + +newtype instance MVector s Word = MV_Word (P.MVector s Word) +newtype instance Vector Word = V_Word (P.Vector Word) +deriving via (UnboxViaPrim Word) instance M.MVector MVector Word +deriving via (UnboxViaPrim Word) instance G.Vector Vector Word +instance Unbox Word + +newtype instance MVector s Word8 = MV_Word8 (P.MVector s Word8) +newtype instance Vector Word8 = V_Word8 (P.Vector Word8) +deriving via (UnboxViaPrim Word8) instance M.MVector MVector Word8 +deriving via (UnboxViaPrim Word8) instance G.Vector Vector Word8 +instance Unbox Word8 + +newtype instance MVector s Word16 = MV_Word16 (P.MVector s Word16) +newtype instance Vector Word16 = V_Word16 (P.Vector Word16) +deriving via (UnboxViaPrim Word16) instance M.MVector MVector Word16 +deriving via (UnboxViaPrim Word16) instance G.Vector Vector Word16 +instance Unbox Word16 + +newtype instance MVector s Word32 = MV_Word32 (P.MVector s Word32) +newtype instance Vector Word32 = V_Word32 (P.Vector Word32) +deriving via (UnboxViaPrim Word32) instance M.MVector MVector Word32 +deriving via (UnboxViaPrim Word32) instance G.Vector Vector Word32 +instance Unbox Word32 + +newtype instance MVector s Word64 = MV_Word64 (P.MVector s Word64) +newtype instance Vector Word64 = V_Word64 (P.Vector Word64) +deriving via (UnboxViaPrim Word64) instance M.MVector MVector Word64 +deriving via (UnboxViaPrim Word64) instance G.Vector Vector Word64 +instance Unbox Word64 + + +newtype instance MVector s Float = MV_Float (P.MVector s Float) +newtype instance Vector Float = V_Float (P.Vector Float) +deriving via (UnboxViaPrim Float) instance M.MVector MVector Float +deriving via (UnboxViaPrim Float) instance G.Vector Vector Float +instance Unbox Float + +newtype instance MVector s Double = MV_Double (P.MVector s Double) +newtype instance Vector Double = V_Double (P.Vector Double) +deriving via (UnboxViaPrim Double) instance M.MVector MVector Double +deriving via (UnboxViaPrim Double) instance G.Vector Vector Double +instance Unbox Double + +newtype instance MVector s Char = MV_Char (P.MVector s Char) +newtype instance Vector Char = V_Char (P.Vector Char) +deriving via (UnboxViaPrim Char) instance M.MVector MVector Char +deriving via (UnboxViaPrim Char) instance G.Vector Vector Char +instance Unbox Char + +-- ---- +-- Bool +-- ---- + +fromBool :: Bool -> Word8 +{-# INLINE fromBool #-} +fromBool True = 1 +fromBool False = 0 + +toBool :: Word8 -> Bool +{-# INLINE toBool #-} +toBool 0 = False +toBool _ = True + +newtype instance MVector s Bool = MV_Bool (P.MVector s Word8) +newtype instance Vector Bool = V_Bool (P.Vector Word8) + +instance Unbox Bool + +instance M.MVector MVector Bool where + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicOverlaps #-} + {-# INLINE basicUnsafeNew #-} + {-# INLINE basicInitialize #-} + {-# INLINE basicUnsafeReplicate #-} + {-# INLINE basicUnsafeRead #-} + {-# INLINE basicUnsafeWrite #-} + {-# INLINE basicClear #-} + {-# INLINE basicSet #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE basicUnsafeGrow #-} + basicLength (MV_Bool v) = M.basicLength v + basicUnsafeSlice i n (MV_Bool v) = MV_Bool $ M.basicUnsafeSlice i n v + basicOverlaps (MV_Bool v1) (MV_Bool v2) = M.basicOverlaps v1 v2 + basicUnsafeNew n = MV_Bool `liftM` M.basicUnsafeNew n + basicInitialize (MV_Bool v) = M.basicInitialize v + basicUnsafeReplicate n x = MV_Bool `liftM` M.basicUnsafeReplicate n (fromBool x) + basicUnsafeRead (MV_Bool v) i = toBool `liftM` M.basicUnsafeRead v i + basicUnsafeWrite (MV_Bool v) i x = M.basicUnsafeWrite v i (fromBool x) + basicClear (MV_Bool v) = M.basicClear v + basicSet (MV_Bool v) x = M.basicSet v (fromBool x) + basicUnsafeCopy (MV_Bool v1) (MV_Bool v2) = M.basicUnsafeCopy v1 v2 + basicUnsafeMove (MV_Bool v1) (MV_Bool v2) = M.basicUnsafeMove v1 v2 + basicUnsafeGrow (MV_Bool v) n = MV_Bool `liftM` M.basicUnsafeGrow v n + +instance G.Vector Vector Bool where + {-# INLINE basicUnsafeFreeze #-} + {-# INLINE basicUnsafeThaw #-} + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicUnsafeIndexM #-} + {-# INLINE elemseq #-} + basicUnsafeFreeze (MV_Bool v) = V_Bool `liftM` G.basicUnsafeFreeze v + basicUnsafeThaw (V_Bool v) = MV_Bool `liftM` G.basicUnsafeThaw v + basicLength (V_Bool v) = G.basicLength v + basicUnsafeSlice i n (V_Bool v) = V_Bool $ G.basicUnsafeSlice i n v + basicUnsafeIndexM (V_Bool v) i = toBool `liftM` G.basicUnsafeIndexM v i + basicUnsafeCopy (MV_Bool mv) (V_Bool v) = G.basicUnsafeCopy mv v + elemseq _ = seq + +-- ------- +-- Complex +-- ------- + +newtype instance MVector s (Complex a) = MV_Complex (MVector s (a,a)) +newtype instance Vector (Complex a) = V_Complex (Vector (a,a)) + +instance (Unbox a) => Unbox (Complex a) + +instance (Unbox a) => M.MVector MVector (Complex a) where + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicOverlaps #-} + {-# INLINE basicUnsafeNew #-} + {-# INLINE basicInitialize #-} + {-# INLINE basicClear #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE basicUnsafeMove #-} + {-# INLINE basicUnsafeGrow #-} + basicLength = coerce $ M.basicLength @MVector @(a,a) + basicUnsafeSlice = coerce $ M.basicUnsafeSlice @MVector @(a,a) + basicOverlaps = coerce $ M.basicOverlaps @MVector @(a,a) + basicUnsafeNew = coerce $ M.basicUnsafeNew @MVector @(a,a) + basicInitialize = coerce $ M.basicInitialize @MVector @(a,a) + basicUnsafeCopy = coerce $ M.basicUnsafeCopy @MVector @(a,a) + basicUnsafeMove = coerce $ M.basicUnsafeMove @MVector @(a,a) + basicUnsafeGrow = coerce $ M.basicUnsafeGrow @MVector @(a,a) + basicClear = coerce $ M.basicClear @MVector @(a,a) + {-# INLINE basicUnsafeReplicate #-} + {-# INLINE basicUnsafeRead #-} + {-# INLINE basicUnsafeWrite #-} + {-# INLINE basicSet #-} + basicUnsafeReplicate n (x :+ y) = MV_Complex <$> M.basicUnsafeReplicate n (x,y) + basicUnsafeRead (MV_Complex v) i = uncurry (:+) <$> M.basicUnsafeRead v i + basicUnsafeWrite (MV_Complex v) i (x :+ y) = M.basicUnsafeWrite v i (x,y) + basicSet (MV_Complex v) (x :+ y) = M.basicSet v (x,y) + +instance (Unbox a) => G.Vector Vector (Complex a) where + {-# INLINE basicUnsafeFreeze #-} + {-# INLINE basicUnsafeThaw #-} + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicUnsafeCopy #-} + basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @Vector @(a,a) + basicUnsafeThaw = coerce $ G.basicUnsafeThaw @Vector @(a,a) + basicLength = coerce $ G.basicLength @Vector @(a,a) + basicUnsafeSlice = coerce $ G.basicUnsafeSlice @Vector @(a,a) + basicUnsafeCopy = coerce $ G.basicUnsafeCopy @Vector @(a,a) + {-# INLINE basicUnsafeIndexM #-} + {-# INLINE elemseq #-} + basicUnsafeIndexM (V_Complex v) i + = uncurry (:+) <$> G.basicUnsafeIndexM v i + elemseq _ (x :+ y) z = G.elemseq (undefined :: Vector a) x + $ G.elemseq (undefined :: Vector a) y z + +-- ------- +-- Identity +-- ------- + +newtype instance MVector s (Identity a) = MV_Identity (MVector s a) +newtype instance Vector (Identity a) = V_Identity (Vector a) +deriving instance Unbox a => G.Vector Vector (Identity a) +deriving instance Unbox a => M.MVector MVector (Identity a) +instance Unbox a => Unbox (Identity a) + +newtype instance MVector s (Down a) = MV_Down (MVector s a) +newtype instance Vector (Down a) = V_Down (Vector a) +deriving instance Unbox a => G.Vector Vector (Down a) +deriving instance Unbox a => M.MVector MVector (Down a) +instance Unbox a => Unbox (Down a) + +newtype instance MVector s (Dual a) = MV_Dual (MVector s a) +newtype instance Vector (Dual a) = V_Dual (Vector a) +deriving instance Unbox a => G.Vector Vector (Dual a) +deriving instance Unbox a => M.MVector MVector (Dual a) +instance Unbox a => Unbox (Dual a) + +newtype instance MVector s (Sum a) = MV_Sum (MVector s a) +newtype instance Vector (Sum a) = V_Sum (Vector a) +deriving instance Unbox a => G.Vector Vector (Sum a) +deriving instance Unbox a => M.MVector MVector (Sum a) +instance Unbox a => Unbox (Sum a) + +newtype instance MVector s (Product a) = MV_Product (MVector s a) +newtype instance Vector (Product a) = V_Product (Vector a) +deriving instance Unbox a => G.Vector Vector (Product a) +deriving instance Unbox a => M.MVector MVector (Product a) +instance Unbox a => Unbox (Product a) + +-- -------------- +-- Data.Semigroup +-- -------------- + + +newtype instance MVector s (Min a) = MV_Min (MVector s a) +newtype instance Vector (Min a) = V_Min (Vector a) +deriving instance Unbox a => G.Vector Vector (Min a) +deriving instance Unbox a => M.MVector MVector (Min a) +instance Unbox a => Unbox (Min a) + +newtype instance MVector s (Max a) = MV_Max (MVector s a) +newtype instance Vector (Max a) = V_Max (Vector a) +deriving instance Unbox a => G.Vector Vector (Max a) +deriving instance Unbox a => M.MVector MVector (Max a) +instance Unbox a => Unbox (Max a) + +newtype instance MVector s (First a) = MV_First (MVector s a) +newtype instance Vector (First a) = V_First (Vector a) +deriving instance Unbox a => G.Vector Vector (First a) +deriving instance Unbox a => M.MVector MVector (First a) +instance Unbox a => Unbox (First a) + +newtype instance MVector s (Last a) = MV_Last (MVector s a) +newtype instance Vector (Last a) = V_Last (Vector a) +deriving instance Unbox a => G.Vector Vector (Last a) +deriving instance Unbox a => M.MVector MVector (Last a) +instance Unbox a => Unbox (Last a) + +newtype instance MVector s (WrappedMonoid a) = MV_WrappedMonoid (MVector s a) +newtype instance Vector (WrappedMonoid a) = V_WrappedMonoid (Vector a) +deriving instance Unbox a => G.Vector Vector (WrappedMonoid a) +deriving instance Unbox a => M.MVector MVector (WrappedMonoid a) +instance Unbox a => Unbox (WrappedMonoid a) + +-- ------------------ +-- Data.Semigroup.Arg +-- ------------------ + +newtype instance MVector s (Arg a b) = MV_Arg (MVector s (a,b)) +newtype instance Vector (Arg a b) = V_Arg (Vector (a,b)) + +instance (Unbox a, Unbox b) => Unbox (Arg a b) + +instance (Unbox a, Unbox b) => M.MVector MVector (Arg a b) where + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicOverlaps #-} + {-# INLINE basicUnsafeNew #-} + {-# INLINE basicInitialize #-} + {-# INLINE basicClear #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE basicUnsafeMove #-} + {-# INLINE basicUnsafeGrow #-} + basicLength = coerce $ M.basicLength @MVector @(a,b) + basicUnsafeSlice = coerce $ M.basicUnsafeSlice @MVector @(a,b) + basicOverlaps = coerce $ M.basicOverlaps @MVector @(a,b) + basicUnsafeNew = coerce $ M.basicUnsafeNew @MVector @(a,b) + basicInitialize = coerce $ M.basicInitialize @MVector @(a,b) + basicUnsafeCopy = coerce $ M.basicUnsafeCopy @MVector @(a,b) + basicUnsafeMove = coerce $ M.basicUnsafeMove @MVector @(a,b) + basicUnsafeGrow = coerce $ M.basicUnsafeGrow @MVector @(a,b) + basicClear = coerce $ M.basicClear @MVector @(a,b) + {-# INLINE basicUnsafeReplicate #-} + {-# INLINE basicUnsafeRead #-} + {-# INLINE basicUnsafeWrite #-} + {-# INLINE basicSet #-} + basicUnsafeReplicate n (Arg x y) = MV_Arg <$> M.basicUnsafeReplicate n (x,y) + basicUnsafeRead (MV_Arg v) i = uncurry Arg <$> M.basicUnsafeRead v i + basicUnsafeWrite (MV_Arg v) i (Arg x y) = M.basicUnsafeWrite v i (x,y) + basicSet (MV_Arg v) (Arg x y) = M.basicSet v (x,y) + + +instance (Unbox a, Unbox b) => G.Vector Vector (Arg a b) where + {-# INLINE basicUnsafeFreeze #-} + {-# INLINE basicUnsafeThaw #-} + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicUnsafeCopy #-} + basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @Vector @(a,b) + basicUnsafeThaw = coerce $ G.basicUnsafeThaw @Vector @(a,b) + basicLength = coerce $ G.basicLength @Vector @(a,b) + basicUnsafeSlice = coerce $ G.basicUnsafeSlice @Vector @(a,b) + basicUnsafeCopy = coerce $ G.basicUnsafeCopy @Vector @(a,b) + {-# INLINE basicUnsafeIndexM #-} + {-# INLINE elemseq #-} + basicUnsafeIndexM (V_Arg v) i = uncurry Arg `liftM` G.basicUnsafeIndexM v i + elemseq _ (Arg x y) z = G.elemseq (undefined :: Vector a) x + $ G.elemseq (undefined :: Vector b) y z + +-- ------- +-- Unboxing the Storable values +-- ------- + +-- | Newtype wrapper which allows to derive unboxed vector in term of +-- storable vectors using @DerivingVia@ mechanism. This is mostly +-- used as illustration of use of @DerivingVia@ for vector, see examples below. +-- +-- First is rather straightforward: we define newtype and use GND to +-- derive 'St.Storable' instance. Newtype instances should be defined +-- manually. Then we use deriving via to define necessary instances. +-- +-- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia -XMultiParamTypeClasses +-- >>> :set -XGeneralizedNewtypeDeriving +-- >>> +-- >>> import qualified Data.Vector.Generic as VG +-- >>> import qualified Data.Vector.Generic.Mutable as VGM +-- >>> import qualified Data.Vector.Storable as VS +-- >>> import qualified Data.Vector.Unboxed as VU +-- >>> +-- >>> newtype Foo = Foo Int deriving VS.Storable +-- >>> +-- >>> newtype instance VU.MVector s Foo = MV_Foo (VS.MVector s Foo) +-- >>> newtype instance VU.Vector Foo = V_Foo (VS.Vector Foo) +-- >>> deriving via (VU.UnboxViaStorable Foo) instance VGM.MVector VU.MVector Foo +-- >>> deriving via (VU.UnboxViaStorable Foo) instance VG.Vector VU.Vector Foo +-- >>> instance VU.Unbox Foo +-- +-- Second example is essentially same but with a twist. Instead of +-- using 'St.Storable' instance of data type, we use underlying instance of 'Int': +-- +-- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia -XMultiParamTypeClasses +-- >>> +-- >>> import qualified Data.Vector.Generic as VG +-- >>> import qualified Data.Vector.Generic.Mutable as VGM +-- >>> import qualified Data.Vector.Storable as VS +-- >>> import qualified Data.Vector.Unboxed as VU +-- >>> +-- >>> newtype Foo = Foo Int +-- >>> +-- >>> newtype instance VU.MVector s Foo = MV_Foo (VS.MVector s Int) +-- >>> newtype instance VU.Vector Foo = V_Foo (VS.Vector Int) +-- >>> deriving via (VU.UnboxViaStorable Int) instance VGM.MVector VU.MVector Foo +-- >>> deriving via (VU.UnboxViaStorable Int) instance VG.Vector VU.Vector Foo +-- >>> instance VU.Unbox Foo +-- +-- @since 0.13.3.0 +newtype UnboxViaStorable a = UnboxViaStorable a + +newtype instance MVector s (UnboxViaStorable a) = MV_UnboxViaStorable (St.MVector s a) +newtype instance Vector (UnboxViaStorable a) = V_UnboxViaStorable (St.Vector a) + +instance St.Storable a => M.MVector MVector (UnboxViaStorable a) where + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicOverlaps #-} + {-# INLINE basicUnsafeNew #-} + {-# INLINE basicInitialize #-} + {-# INLINE basicUnsafeReplicate #-} + {-# INLINE basicUnsafeRead #-} + {-# INLINE basicUnsafeWrite #-} + {-# INLINE basicClear #-} + {-# INLINE basicSet #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE basicUnsafeGrow #-} + basicLength = coerce $ M.basicLength @St.MVector @a + basicUnsafeSlice = coerce $ M.basicUnsafeSlice @St.MVector @a + basicOverlaps = coerce $ M.basicOverlaps @St.MVector @a + basicUnsafeNew = coerce $ M.basicUnsafeNew @St.MVector @a + basicInitialize = coerce $ M.basicInitialize @St.MVector @a + basicUnsafeReplicate = coerce $ M.basicUnsafeReplicate @St.MVector @a + basicUnsafeRead = coerce $ M.basicUnsafeRead @St.MVector @a + basicUnsafeWrite = coerce $ M.basicUnsafeWrite @St.MVector @a + basicClear = coerce $ M.basicClear @St.MVector @a + basicSet = coerce $ M.basicSet @St.MVector @a + basicUnsafeCopy = coerce $ M.basicUnsafeCopy @St.MVector @a + basicUnsafeMove = coerce $ M.basicUnsafeMove @St.MVector @a + basicUnsafeGrow = coerce $ M.basicUnsafeGrow @St.MVector @a + +instance St.Storable a => G.Vector Vector (UnboxViaStorable a) where + {-# INLINE basicUnsafeFreeze #-} + {-# INLINE basicUnsafeThaw #-} + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicUnsafeIndexM #-} + {-# INLINE elemseq #-} + basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @St.Vector @a + basicUnsafeThaw = coerce $ G.basicUnsafeThaw @St.Vector @a + basicLength = coerce $ G.basicLength @St.Vector @a + basicUnsafeSlice = coerce $ G.basicUnsafeSlice @St.Vector @a + basicUnsafeIndexM = coerce $ G.basicUnsafeIndexM @St.Vector @a + basicUnsafeCopy = coerce $ G.basicUnsafeCopy @St.Vector @a + elemseq _ = seq + +instance St.Storable a => Unbox (UnboxViaStorable a) + +-- ------- +-- Unboxing the boxed values +-- ------- + +-- | Newtype which allows to derive unbox instances for type @a@ which +-- is normally a "boxed" type. The newtype does not alter the strictness +-- semantics of the underlying type and inherits the laizness of said type. +-- For a strict newtype wrapper, see 'DoNotUnboxStrict'. +-- +-- 'DoNotUnboxLazy' is intended to be unsed in conjunction with the newtype 'As' +-- and the type class 'IsoUnbox'. Here's an example which uses the following +-- explicit 'IsoUnbox' instance: +-- +-- +-- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia +-- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances +-- >>> import qualified Data.Vector.Unboxed as VU +-- >>> import qualified Data.Vector.Generic as VG +-- >>> import qualified Data.Vector.Generic.Mutable as VGM +-- >>> :{ +-- >>> data Foo a = Foo Int a +-- >>> deriving (Eq, Ord, Show) +-- >>> instance VU.IsoUnbox (Foo a) (Int, VU.DoNotUnboxLazy a) where +-- >>> toURepr (Foo i a) = (i, VU.DoNotUnboxLazy a) +-- >>> fromURepr (i, VU.DoNotUnboxLazy a) = Foo i a +-- >>> {-# INLINE toURepr #-} +-- >>> {-# INLINE fromURepr #-} +-- >>> newtype instance VU.MVector s (Foo a) = MV_Foo (VU.MVector s (Int, VU.DoNotUnboxLazy a)) +-- >>> newtype instance VU.Vector (Foo a) = V_Foo (VU.Vector (Int, VU.DoNotUnboxLazy a)) +-- >>> deriving via (Foo a `VU.As` (Int, VU.DoNotUnboxLazy a)) instance VGM.MVector VU.MVector (Foo a) +-- >>> deriving via (Foo a `VU.As` (Int, VU.DoNotUnboxLazy a)) instance VG.Vector VU.Vector (Foo a) +-- >>> instance VU.Unbox (Foo a) +-- >>> :} +-- +-- >>> VU.fromListN 3 [ Foo 4 "Haskell's", Foo 8 "strong", Foo 16 "types" ] +-- [Foo 4 "Haskell's",Foo 8 "strong",Foo 16 "types"] +-- +-- @since 0.13.2.0 +newtype DoNotUnboxLazy a = DoNotUnboxLazy a + +newtype instance MVector s (DoNotUnboxLazy a) = MV_DoNotUnboxLazy (B.MVector s a) +newtype instance Vector (DoNotUnboxLazy a) = V_DoNotUnboxLazy (B.Vector a) + +instance M.MVector MVector (DoNotUnboxLazy a) where + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicOverlaps #-} + {-# INLINE basicUnsafeNew #-} + {-# INLINE basicInitialize #-} + {-# INLINE basicUnsafeReplicate #-} + {-# INLINE basicUnsafeRead #-} + {-# INLINE basicUnsafeWrite #-} + {-# INLINE basicClear #-} + {-# INLINE basicSet #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE basicUnsafeGrow #-} + basicLength = coerce $ M.basicLength @B.MVector @a + basicUnsafeSlice = coerce $ M.basicUnsafeSlice @B.MVector @a + basicOverlaps = coerce $ M.basicOverlaps @B.MVector @a + basicUnsafeNew = coerce $ M.basicUnsafeNew @B.MVector @a + basicInitialize = coerce $ M.basicInitialize @B.MVector @a + basicUnsafeReplicate = coerce $ M.basicUnsafeReplicate @B.MVector @a + basicUnsafeRead = coerce $ M.basicUnsafeRead @B.MVector @a + basicUnsafeWrite = coerce $ M.basicUnsafeWrite @B.MVector @a + basicClear = coerce $ M.basicClear @B.MVector @a + basicSet = coerce $ M.basicSet @B.MVector @a + basicUnsafeCopy = coerce $ M.basicUnsafeCopy @B.MVector @a + basicUnsafeMove = coerce $ M.basicUnsafeMove @B.MVector @a + basicUnsafeGrow = coerce $ M.basicUnsafeGrow @B.MVector @a + +instance G.Vector Vector (DoNotUnboxLazy a) where + {-# INLINE basicUnsafeFreeze #-} + {-# INLINE basicUnsafeThaw #-} + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicUnsafeIndexM #-} + {-# INLINE elemseq #-} + basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @B.Vector @a + basicUnsafeThaw = coerce $ G.basicUnsafeThaw @B.Vector @a + basicLength = coerce $ G.basicLength @B.Vector @a + basicUnsafeSlice = coerce $ G.basicUnsafeSlice @B.Vector @a + basicUnsafeIndexM = coerce $ G.basicUnsafeIndexM @B.Vector @a + basicUnsafeCopy = coerce $ G.basicUnsafeCopy @B.Vector @a + elemseq _ = seq + +instance Unbox (DoNotUnboxLazy a) + +-- | Newtype which allows to derive unbox instances for type @a@ which +-- is normally a "boxed" type. The newtype stictly evaluates the wrapped values +-- ensuring that the unboxed vector contains no (direct) thunks. +-- For a less strict newtype wrapper, see 'DoNotUnboxLazy'. +-- For a more strict newtype wrapper, see 'DoNotUnboxNormalForm'. +-- +-- 'DoNotUnboxStrict' is intended to be unsed in conjunction with the newtype 'As' +-- and the type class 'IsoUnbox'. Here's an example which uses the following +-- explicit 'IsoUnbox' instance: +-- +-- +-- >>> :set -XBangPatterns -XTypeFamilies -XStandaloneDeriving -XDerivingVia +-- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances +-- >>> import qualified Data.Vector.Unboxed as VU +-- >>> import qualified Data.Vector.Generic as VG +-- >>> import qualified Data.Vector.Generic.Mutable as VGM +-- >>> :{ +-- >>> data Bar a = Bar Int a +-- >>> deriving Show +-- >>> instance VU.IsoUnbox (Bar a) (Int, VU.DoNotUnboxStrict a) where +-- >>> toURepr (Bar i !a) = (i, VU.DoNotUnboxStrict a) +-- >>> fromURepr (i, VU.DoNotUnboxStrict a) = Bar i a +-- >>> {-# INLINE toURepr #-} +-- >>> {-# INLINE fromURepr #-} +-- >>> newtype instance VU.MVector s (Bar a) = MV_Bar (VU.MVector s (Int, VU.DoNotUnboxStrict a)) +-- >>> newtype instance VU.Vector (Bar a) = V_Bar (VU.Vector (Int, VU.DoNotUnboxStrict a)) +-- >>> deriving via (Bar a `VU.As` (Int, VU.DoNotUnboxStrict a)) instance VGM.MVector VU.MVector (Bar a) +-- >>> deriving via (Bar a `VU.As` (Int, VU.DoNotUnboxStrict a)) instance VG.Vector VU.Vector (Bar a) +-- >>> instance VU.Unbox (Bar a) +-- >>> :} +-- +-- >>> VU.fromListN 3 [ Bar 3 "Bye", Bar 2 "for", Bar 1 "now" ] +-- [Bar 3 "Bye",Bar 2 "for",Bar 1 "now"] +-- +-- @since 0.13.2.0 +newtype DoNotUnboxStrict a = DoNotUnboxStrict a + +newtype instance MVector s (DoNotUnboxStrict a) = MV_DoNotUnboxStrict (S.MVector s a) +newtype instance Vector (DoNotUnboxStrict a) = V_DoNotUnboxStrict (S.Vector a) + +instance M.MVector MVector (DoNotUnboxStrict a) where + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicOverlaps #-} + {-# INLINE basicUnsafeNew #-} + {-# INLINE basicInitialize #-} + {-# INLINE basicUnsafeReplicate #-} + {-# INLINE basicUnsafeRead #-} + {-# INLINE basicUnsafeWrite #-} + {-# INLINE basicClear #-} + {-# INLINE basicSet #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE basicUnsafeGrow #-} + basicLength = coerce $ M.basicLength @S.MVector @a + basicUnsafeSlice = coerce $ M.basicUnsafeSlice @S.MVector @a + basicOverlaps = coerce $ M.basicOverlaps @S.MVector @a + basicUnsafeNew = coerce $ M.basicUnsafeNew @S.MVector @a + basicInitialize = coerce $ M.basicInitialize @S.MVector @a + basicUnsafeReplicate = coerce $ M.basicUnsafeReplicate @S.MVector @a + basicUnsafeRead = coerce $ M.basicUnsafeRead @S.MVector @a + basicUnsafeWrite = coerce $ M.basicUnsafeWrite @S.MVector @a + basicClear = coerce $ M.basicClear @S.MVector @a + basicSet = coerce $ M.basicSet @S.MVector @a + basicUnsafeCopy = coerce $ M.basicUnsafeCopy @S.MVector @a + basicUnsafeMove = coerce $ M.basicUnsafeMove @S.MVector @a + basicUnsafeGrow = coerce $ M.basicUnsafeGrow @S.MVector @a + +instance G.Vector Vector (DoNotUnboxStrict a) where + {-# INLINE basicUnsafeFreeze #-} + {-# INLINE basicUnsafeThaw #-} + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicUnsafeIndexM #-} + {-# INLINE elemseq #-} + basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @S.Vector @a + basicUnsafeThaw = coerce $ G.basicUnsafeThaw @S.Vector @a + basicLength = coerce $ G.basicLength @S.Vector @a + basicUnsafeSlice = coerce $ G.basicUnsafeSlice @S.Vector @a + basicUnsafeIndexM = coerce $ G.basicUnsafeIndexM @S.Vector @a + basicUnsafeCopy = coerce $ G.basicUnsafeCopy @S.Vector @a + elemseq _ = seq + +instance Unbox (DoNotUnboxStrict a) + +-- | Newtype which allows to derive unbox instances for type @a@ which +-- is normally a "boxed" type. The newtype stictly evaluates the wrapped values +-- via thier requisite 'NFData' instance, ensuring that the unboxed vector +-- contains only values reduced to normal form. +-- For a less strict newtype wrappers, see 'DoNotUnboxLazy' and 'DoNotUnboxStrict'. +-- +-- 'DoNotUnboxNormalForm' is intended to be unsed in conjunction with the newtype 'As' +-- and the type class 'IsoUnbox'. Here's an example which uses the following +-- explicit 'IsoUnbox' instance: +-- +-- +-- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia +-- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances +-- >>> import qualified Data.Vector.Unboxed as VU +-- >>> import qualified Data.Vector.Generic as VG +-- >>> import qualified Data.Vector.Generic.Mutable as VGM +-- >>> import qualified Control.DeepSeq as NF +-- >>> :{ +-- >>> data Baz a = Baz Int a +-- >>> deriving Show +-- >>> instance NF.NFData a => VU.IsoUnbox (Baz a) (Int, VU.DoNotUnboxNormalForm a) where +-- >>> toURepr (Baz i a) = (i, VU.DoNotUnboxNormalForm $ NF.force a) +-- >>> fromURepr (i, VU.DoNotUnboxNormalForm a) = Baz i a +-- >>> {-# INLINE toURepr #-} +-- >>> {-# INLINE fromURepr #-} +-- >>> newtype instance VU.MVector s (Baz a) = MV_Baz (VU.MVector s (Int, VU.DoNotUnboxNormalForm a)) +-- >>> newtype instance VU.Vector (Baz a) = V_Baz (VU.Vector (Int, VU.DoNotUnboxNormalForm a)) +-- >>> deriving via (Baz a `VU.As` (Int, VU.DoNotUnboxNormalForm a)) instance NF.NFData a => VGM.MVector VU.MVector (Baz a) +-- >>> deriving via (Baz a `VU.As` (Int, VU.DoNotUnboxNormalForm a)) instance NF.NFData a => VG.Vector VU.Vector (Baz a) +-- >>> instance NF.NFData a => VU.Unbox (Baz a) +-- >>> :} +-- +-- >>> VU.fromListN 3 [ Baz 3 "Fully", Baz 9 "evaluated", Baz 27 "data" ] +-- [Baz 3 "Fully",Baz 9 "evaluated",Baz 27 "data"] +-- +-- @since 0.13.2.0 +newtype DoNotUnboxNormalForm a = DoNotUnboxNormalForm a + +newtype instance MVector s (DoNotUnboxNormalForm a) = MV_DoNotUnboxNormalForm (S.MVector s a) +newtype instance Vector (DoNotUnboxNormalForm a) = V_DoNotUnboxNormalForm (S.Vector a) + +instance NFData a => M.MVector MVector (DoNotUnboxNormalForm a) where + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicOverlaps #-} + {-# INLINE basicUnsafeNew #-} + {-# INLINE basicInitialize #-} + {-# INLINE basicUnsafeReplicate #-} + {-# INLINE basicUnsafeRead #-} + {-# INLINE basicUnsafeWrite #-} + {-# INLINE basicClear #-} + {-# INLINE basicSet #-} + {-# INLINE basicUnsafeCopy #-} + {-# INLINE basicUnsafeGrow #-} + basicLength = coerce $ M.basicLength @S.MVector @a + basicUnsafeSlice = coerce $ M.basicUnsafeSlice @S.MVector @a + basicOverlaps = coerce $ M.basicOverlaps @S.MVector @a + basicUnsafeNew = coerce $ M.basicUnsafeNew @S.MVector @a + basicInitialize = coerce $ M.basicInitialize @S.MVector @a + basicUnsafeReplicate = coerce (\i x -> M.basicUnsafeReplicate @S.MVector @a i (force x)) + basicUnsafeRead = coerce $ M.basicUnsafeRead @S.MVector @a + basicUnsafeWrite = coerce (\v i x -> M.basicUnsafeWrite @S.MVector @a v i (force x)) + basicClear = coerce $ M.basicClear @S.MVector @a + basicSet = coerce (\v x -> M.basicSet @S.MVector @a v (force x)) + basicUnsafeCopy = coerce $ M.basicUnsafeCopy @S.MVector @a + basicUnsafeMove = coerce $ M.basicUnsafeMove @S.MVector @a + basicUnsafeGrow = coerce $ M.basicUnsafeGrow @S.MVector @a + +instance NFData a => G.Vector Vector (DoNotUnboxNormalForm a) where + {-# INLINE basicUnsafeFreeze #-} + {-# INLINE basicUnsafeThaw #-} + {-# INLINE basicLength #-} + {-# INLINE basicUnsafeSlice #-} + {-# INLINE basicUnsafeIndexM #-} + {-# INLINE elemseq #-} + basicUnsafeFreeze = coerce $ G.basicUnsafeFreeze @S.Vector @a + basicUnsafeThaw = coerce $ G.basicUnsafeThaw @S.Vector @a + basicLength = coerce $ G.basicLength @S.Vector @a + basicUnsafeSlice = coerce $ G.basicUnsafeSlice @S.Vector @a + basicUnsafeIndexM = coerce $ G.basicUnsafeIndexM @S.Vector @a + basicUnsafeCopy = coerce $ G.basicUnsafeCopy @S.Vector @a + elemseq _ x y = rnf (coerce x :: a) `seq` y + +instance NFData a => Unbox (DoNotUnboxNormalForm a) + + +newtype instance MVector s Any = MV_Any (MVector s Bool) +newtype instance Vector Any = V_Any (Vector Bool) +deriving instance G.Vector Vector Any +deriving instance M.MVector MVector Any +instance Unbox Any + +newtype instance MVector s All = MV_All (MVector s Bool) +newtype instance Vector All = V_All (Vector Bool) +deriving instance G.Vector Vector All +deriving instance M.MVector MVector All +instance Unbox All + +-- ------- +-- Const +-- ------- + +newtype instance MVector s (Const b a) = MV_Const (MVector s b) +newtype instance Vector (Const b a) = V_Const (Vector b) +deriving instance Unbox b => G.Vector Vector (Const b a) +deriving instance Unbox b => M.MVector MVector (Const b a) +instance Unbox b => Unbox (Const b a) + +-- --- +-- Alt +-- --- + +newtype instance MVector s (Alt f a) = MV_Alt (MVector s (f a)) +newtype instance Vector (Alt f a) = V_Alt (Vector (f a)) +deriving instance Unbox (f a) => G.Vector Vector (Alt f a) +deriving instance Unbox (f a) => M.MVector MVector (Alt f a) +instance Unbox (f a) => Unbox (Alt f a) + +-- ------- +-- Compose +-- ------- + +newtype instance MVector s (Compose f g a) = MV_Compose (MVector s (f (g a))) +newtype instance Vector (Compose f g a) = V_Compose (Vector (f (g a))) +deriving instance Unbox (f (g a)) => G.Vector Vector (Compose f g a) +deriving instance Unbox (f (g a)) => M.MVector MVector (Compose f g a) +instance Unbox (f (g a)) => Unbox (Compose f g a) + +-- ------ +-- Tuples +-- ------ + +data instance MVector s (a, b) + = MV_2 {-# UNPACK #-} !Int !(MVector s a) + !(MVector s b) +data instance Vector (a, b) + = V_2 {-# UNPACK #-} !Int !(Vector a) + !(Vector b) +instance (Unbox a, Unbox b) => Unbox (a, b) +instance (Unbox a, Unbox b) => M.MVector MVector (a, b) where + {-# INLINE basicLength #-} + basicLength (MV_2 n_ _ _) = n_ + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i_ m_ (MV_2 _ as bs) + = MV_2 m_ (M.basicUnsafeSlice i_ m_ as) + (M.basicUnsafeSlice i_ m_ bs) + {-# INLINE basicOverlaps #-} + basicOverlaps (MV_2 _ as1 bs1) (MV_2 _ as2 bs2) + = M.basicOverlaps as1 as2 + || M.basicOverlaps bs1 bs2 + {-# INLINE basicUnsafeNew #-} + basicUnsafeNew n_ + = do + as <- M.basicUnsafeNew n_ + bs <- M.basicUnsafeNew n_ + return $ MV_2 n_ as bs + {-# INLINE basicInitialize #-} + basicInitialize (MV_2 _ as bs) + = do + M.basicInitialize as + M.basicInitialize bs + {-# INLINE basicUnsafeReplicate #-} + basicUnsafeReplicate n_ (a, b) + = do + as <- M.basicUnsafeReplicate n_ a + bs <- M.basicUnsafeReplicate n_ b + return $ MV_2 n_ as bs + {-# INLINE basicUnsafeRead #-} + basicUnsafeRead (MV_2 _ as bs) i_ + = do + a <- M.basicUnsafeRead as i_ + b <- M.basicUnsafeRead bs i_ + return (a, b) + {-# INLINE basicUnsafeWrite #-} + basicUnsafeWrite (MV_2 _ as bs) i_ (a, b) + = do + M.basicUnsafeWrite as i_ a + M.basicUnsafeWrite bs i_ b + {-# INLINE basicClear #-} + basicClear (MV_2 _ as bs) + = do + M.basicClear as + M.basicClear bs + {-# INLINE basicSet #-} + basicSet (MV_2 _ as bs) (a, b) + = do + M.basicSet as a + M.basicSet bs b + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_2 _ as1 bs1) (MV_2 _ as2 bs2) + = do + M.basicUnsafeCopy as1 as2 + M.basicUnsafeCopy bs1 bs2 + {-# INLINE basicUnsafeMove #-} + basicUnsafeMove (MV_2 _ as1 bs1) (MV_2 _ as2 bs2) + = do + M.basicUnsafeMove as1 as2 + M.basicUnsafeMove bs1 bs2 + {-# INLINE basicUnsafeGrow #-} + basicUnsafeGrow (MV_2 n_ as bs) m_ + = do + as' <- M.basicUnsafeGrow as m_ + bs' <- M.basicUnsafeGrow bs m_ + return $ MV_2 (m_+n_) as' bs' +instance (Unbox a, Unbox b) => G.Vector Vector (a, b) where + {-# INLINE basicUnsafeFreeze #-} + basicUnsafeFreeze (MV_2 n_ as bs) + = do + as' <- G.basicUnsafeFreeze as + bs' <- G.basicUnsafeFreeze bs + return $ V_2 n_ as' bs' + {-# INLINE basicUnsafeThaw #-} + basicUnsafeThaw (V_2 n_ as bs) + = do + as' <- G.basicUnsafeThaw as + bs' <- G.basicUnsafeThaw bs + return $ MV_2 n_ as' bs' + {-# INLINE basicLength #-} + basicLength (V_2 n_ _ _) = n_ + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i_ m_ (V_2 _ as bs) + = V_2 m_ (G.basicUnsafeSlice i_ m_ as) + (G.basicUnsafeSlice i_ m_ bs) + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM (V_2 _ as bs) i_ + = do + a <- G.basicUnsafeIndexM as i_ + b <- G.basicUnsafeIndexM bs i_ + return (a, b) + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_2 _ as1 bs1) (V_2 _ as2 bs2) + = do + G.basicUnsafeCopy as1 as2 + G.basicUnsafeCopy bs1 bs2 + {-# INLINE elemseq #-} + elemseq _ (a, b) + = G.elemseq (undefined :: Vector a) a + . G.elemseq (undefined :: Vector b) b + +data instance MVector s (a, b, c) + = MV_3 {-# UNPACK #-} !Int !(MVector s a) + !(MVector s b) + !(MVector s c) +data instance Vector (a, b, c) + = V_3 {-# UNPACK #-} !Int !(Vector a) + !(Vector b) + !(Vector c) +instance (Unbox a, Unbox b, Unbox c) => Unbox (a, b, c) +instance (Unbox a, + Unbox b, + Unbox c) => M.MVector MVector (a, b, c) where + {-# INLINE basicLength #-} + basicLength (MV_3 n_ _ _ _) = n_ + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i_ m_ (MV_3 _ as bs cs) + = MV_3 m_ (M.basicUnsafeSlice i_ m_ as) + (M.basicUnsafeSlice i_ m_ bs) + (M.basicUnsafeSlice i_ m_ cs) + {-# INLINE basicOverlaps #-} + basicOverlaps (MV_3 _ as1 bs1 cs1) (MV_3 _ as2 bs2 cs2) + = M.basicOverlaps as1 as2 + || M.basicOverlaps bs1 bs2 + || M.basicOverlaps cs1 cs2 + {-# INLINE basicUnsafeNew #-} + basicUnsafeNew n_ + = do + as <- M.basicUnsafeNew n_ + bs <- M.basicUnsafeNew n_ + cs <- M.basicUnsafeNew n_ + return $ MV_3 n_ as bs cs + {-# INLINE basicInitialize #-} + basicInitialize (MV_3 _ as bs cs) + = do + M.basicInitialize as + M.basicInitialize bs + M.basicInitialize cs + {-# INLINE basicUnsafeReplicate #-} + basicUnsafeReplicate n_ (a, b, c) + = do + as <- M.basicUnsafeReplicate n_ a + bs <- M.basicUnsafeReplicate n_ b + cs <- M.basicUnsafeReplicate n_ c + return $ MV_3 n_ as bs cs + {-# INLINE basicUnsafeRead #-} + basicUnsafeRead (MV_3 _ as bs cs) i_ + = do + a <- M.basicUnsafeRead as i_ + b <- M.basicUnsafeRead bs i_ + c <- M.basicUnsafeRead cs i_ + return (a, b, c) + {-# INLINE basicUnsafeWrite #-} + basicUnsafeWrite (MV_3 _ as bs cs) i_ (a, b, c) + = do + M.basicUnsafeWrite as i_ a + M.basicUnsafeWrite bs i_ b + M.basicUnsafeWrite cs i_ c + {-# INLINE basicClear #-} + basicClear (MV_3 _ as bs cs) + = do + M.basicClear as + M.basicClear bs + M.basicClear cs + {-# INLINE basicSet #-} + basicSet (MV_3 _ as bs cs) (a, b, c) + = do + M.basicSet as a + M.basicSet bs b + M.basicSet cs c + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_3 _ as1 bs1 cs1) (MV_3 _ as2 bs2 cs2) + = do + M.basicUnsafeCopy as1 as2 + M.basicUnsafeCopy bs1 bs2 + M.basicUnsafeCopy cs1 cs2 + {-# INLINE basicUnsafeMove #-} + basicUnsafeMove (MV_3 _ as1 bs1 cs1) (MV_3 _ as2 bs2 cs2) + = do + M.basicUnsafeMove as1 as2 + M.basicUnsafeMove bs1 bs2 + M.basicUnsafeMove cs1 cs2 + {-# INLINE basicUnsafeGrow #-} + basicUnsafeGrow (MV_3 n_ as bs cs) m_ + = do + as' <- M.basicUnsafeGrow as m_ + bs' <- M.basicUnsafeGrow bs m_ + cs' <- M.basicUnsafeGrow cs m_ + return $ MV_3 (m_+n_) as' bs' cs' +instance (Unbox a, + Unbox b, + Unbox c) => G.Vector Vector (a, b, c) where + {-# INLINE basicUnsafeFreeze #-} + basicUnsafeFreeze (MV_3 n_ as bs cs) + = do + as' <- G.basicUnsafeFreeze as + bs' <- G.basicUnsafeFreeze bs + cs' <- G.basicUnsafeFreeze cs + return $ V_3 n_ as' bs' cs' + {-# INLINE basicUnsafeThaw #-} + basicUnsafeThaw (V_3 n_ as bs cs) + = do + as' <- G.basicUnsafeThaw as + bs' <- G.basicUnsafeThaw bs + cs' <- G.basicUnsafeThaw cs + return $ MV_3 n_ as' bs' cs' + {-# INLINE basicLength #-} + basicLength (V_3 n_ _ _ _) = n_ + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i_ m_ (V_3 _ as bs cs) + = V_3 m_ (G.basicUnsafeSlice i_ m_ as) + (G.basicUnsafeSlice i_ m_ bs) + (G.basicUnsafeSlice i_ m_ cs) + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM (V_3 _ as bs cs) i_ + = do + a <- G.basicUnsafeIndexM as i_ + b <- G.basicUnsafeIndexM bs i_ + c <- G.basicUnsafeIndexM cs i_ + return (a, b, c) + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_3 _ as1 bs1 cs1) (V_3 _ as2 bs2 cs2) + = do + G.basicUnsafeCopy as1 as2 + G.basicUnsafeCopy bs1 bs2 + G.basicUnsafeCopy cs1 cs2 + {-# INLINE elemseq #-} + elemseq _ (a, b, c) + = G.elemseq (undefined :: Vector a) a + . G.elemseq (undefined :: Vector b) b + . G.elemseq (undefined :: Vector c) c + +data instance MVector s (a, b, c, d) + = MV_4 {-# UNPACK #-} !Int !(MVector s a) + !(MVector s b) + !(MVector s c) + !(MVector s d) +data instance Vector (a, b, c, d) + = V_4 {-# UNPACK #-} !Int !(Vector a) + !(Vector b) + !(Vector c) + !(Vector d) +instance (Unbox a, Unbox b, Unbox c, Unbox d) => Unbox (a, b, c, d) +instance (Unbox a, + Unbox b, + Unbox c, + Unbox d) => M.MVector MVector (a, b, c, d) where + {-# INLINE basicLength #-} + basicLength (MV_4 n_ _ _ _ _) = n_ + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i_ m_ (MV_4 _ as bs cs ds) + = MV_4 m_ (M.basicUnsafeSlice i_ m_ as) + (M.basicUnsafeSlice i_ m_ bs) + (M.basicUnsafeSlice i_ m_ cs) + (M.basicUnsafeSlice i_ m_ ds) + {-# INLINE basicOverlaps #-} + basicOverlaps (MV_4 _ as1 bs1 cs1 ds1) (MV_4 _ as2 bs2 cs2 ds2) + = M.basicOverlaps as1 as2 + || M.basicOverlaps bs1 bs2 + || M.basicOverlaps cs1 cs2 + || M.basicOverlaps ds1 ds2 + {-# INLINE basicUnsafeNew #-} + basicUnsafeNew n_ + = do + as <- M.basicUnsafeNew n_ + bs <- M.basicUnsafeNew n_ + cs <- M.basicUnsafeNew n_ + ds <- M.basicUnsafeNew n_ + return $ MV_4 n_ as bs cs ds + {-# INLINE basicInitialize #-} + basicInitialize (MV_4 _ as bs cs ds) + = do + M.basicInitialize as + M.basicInitialize bs + M.basicInitialize cs + M.basicInitialize ds + {-# INLINE basicUnsafeReplicate #-} + basicUnsafeReplicate n_ (a, b, c, d) + = do + as <- M.basicUnsafeReplicate n_ a + bs <- M.basicUnsafeReplicate n_ b + cs <- M.basicUnsafeReplicate n_ c + ds <- M.basicUnsafeReplicate n_ d + return $ MV_4 n_ as bs cs ds + {-# INLINE basicUnsafeRead #-} + basicUnsafeRead (MV_4 _ as bs cs ds) i_ + = do + a <- M.basicUnsafeRead as i_ + b <- M.basicUnsafeRead bs i_ + c <- M.basicUnsafeRead cs i_ + d <- M.basicUnsafeRead ds i_ + return (a, b, c, d) + {-# INLINE basicUnsafeWrite #-} + basicUnsafeWrite (MV_4 _ as bs cs ds) i_ (a, b, c, d) + = do + M.basicUnsafeWrite as i_ a + M.basicUnsafeWrite bs i_ b + M.basicUnsafeWrite cs i_ c + M.basicUnsafeWrite ds i_ d + {-# INLINE basicClear #-} + basicClear (MV_4 _ as bs cs ds) + = do + M.basicClear as + M.basicClear bs + M.basicClear cs + M.basicClear ds + {-# INLINE basicSet #-} + basicSet (MV_4 _ as bs cs ds) (a, b, c, d) + = do + M.basicSet as a + M.basicSet bs b + M.basicSet cs c + M.basicSet ds d + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_4 _ as1 bs1 cs1 ds1) (MV_4 _ as2 + bs2 + cs2 + ds2) + = do + M.basicUnsafeCopy as1 as2 + M.basicUnsafeCopy bs1 bs2 + M.basicUnsafeCopy cs1 cs2 + M.basicUnsafeCopy ds1 ds2 + {-# INLINE basicUnsafeMove #-} + basicUnsafeMove (MV_4 _ as1 bs1 cs1 ds1) (MV_4 _ as2 + bs2 + cs2 + ds2) + = do + M.basicUnsafeMove as1 as2 + M.basicUnsafeMove bs1 bs2 + M.basicUnsafeMove cs1 cs2 + M.basicUnsafeMove ds1 ds2 + {-# INLINE basicUnsafeGrow #-} + basicUnsafeGrow (MV_4 n_ as bs cs ds) m_ + = do + as' <- M.basicUnsafeGrow as m_ + bs' <- M.basicUnsafeGrow bs m_ + cs' <- M.basicUnsafeGrow cs m_ + ds' <- M.basicUnsafeGrow ds m_ + return $ MV_4 (m_+n_) as' bs' cs' ds' +instance (Unbox a, + Unbox b, + Unbox c, + Unbox d) => G.Vector Vector (a, b, c, d) where + {-# INLINE basicUnsafeFreeze #-} + basicUnsafeFreeze (MV_4 n_ as bs cs ds) + = do + as' <- G.basicUnsafeFreeze as + bs' <- G.basicUnsafeFreeze bs + cs' <- G.basicUnsafeFreeze cs + ds' <- G.basicUnsafeFreeze ds + return $ V_4 n_ as' bs' cs' ds' + {-# INLINE basicUnsafeThaw #-} + basicUnsafeThaw (V_4 n_ as bs cs ds) + = do + as' <- G.basicUnsafeThaw as + bs' <- G.basicUnsafeThaw bs + cs' <- G.basicUnsafeThaw cs + ds' <- G.basicUnsafeThaw ds + return $ MV_4 n_ as' bs' cs' ds' + {-# INLINE basicLength #-} + basicLength (V_4 n_ _ _ _ _) = n_ + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i_ m_ (V_4 _ as bs cs ds) + = V_4 m_ (G.basicUnsafeSlice i_ m_ as) + (G.basicUnsafeSlice i_ m_ bs) + (G.basicUnsafeSlice i_ m_ cs) + (G.basicUnsafeSlice i_ m_ ds) + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM (V_4 _ as bs cs ds) i_ + = do + a <- G.basicUnsafeIndexM as i_ + b <- G.basicUnsafeIndexM bs i_ + c <- G.basicUnsafeIndexM cs i_ + d <- G.basicUnsafeIndexM ds i_ + return (a, b, c, d) + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_4 _ as1 bs1 cs1 ds1) (V_4 _ as2 + bs2 + cs2 + ds2) + = do + G.basicUnsafeCopy as1 as2 + G.basicUnsafeCopy bs1 bs2 + G.basicUnsafeCopy cs1 cs2 + G.basicUnsafeCopy ds1 ds2 + {-# INLINE elemseq #-} + elemseq _ (a, b, c, d) + = G.elemseq (undefined :: Vector a) a + . G.elemseq (undefined :: Vector b) b + . G.elemseq (undefined :: Vector c) c + . G.elemseq (undefined :: Vector d) d + +data instance MVector s (a, b, c, d, e) + = MV_5 {-# UNPACK #-} !Int !(MVector s a) + !(MVector s b) + !(MVector s c) + !(MVector s d) + !(MVector s e) +data instance Vector (a, b, c, d, e) + = V_5 {-# UNPACK #-} !Int !(Vector a) + !(Vector b) + !(Vector c) + !(Vector d) + !(Vector e) +instance (Unbox a, + Unbox b, + Unbox c, + Unbox d, + Unbox e) => Unbox (a, b, c, d, e) +instance (Unbox a, + Unbox b, + Unbox c, + Unbox d, + Unbox e) => M.MVector MVector (a, b, c, d, e) where + {-# INLINE basicLength #-} + basicLength (MV_5 n_ _ _ _ _ _) = n_ + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i_ m_ (MV_5 _ as bs cs ds es) + = MV_5 m_ (M.basicUnsafeSlice i_ m_ as) + (M.basicUnsafeSlice i_ m_ bs) + (M.basicUnsafeSlice i_ m_ cs) + (M.basicUnsafeSlice i_ m_ ds) + (M.basicUnsafeSlice i_ m_ es) + {-# INLINE basicOverlaps #-} + basicOverlaps (MV_5 _ as1 bs1 cs1 ds1 es1) (MV_5 _ as2 + bs2 + cs2 + ds2 + es2) + = M.basicOverlaps as1 as2 + || M.basicOverlaps bs1 bs2 + || M.basicOverlaps cs1 cs2 + || M.basicOverlaps ds1 ds2 + || M.basicOverlaps es1 es2 + {-# INLINE basicUnsafeNew #-} + basicUnsafeNew n_ + = do + as <- M.basicUnsafeNew n_ + bs <- M.basicUnsafeNew n_ + cs <- M.basicUnsafeNew n_ + ds <- M.basicUnsafeNew n_ + es <- M.basicUnsafeNew n_ + return $ MV_5 n_ as bs cs ds es + {-# INLINE basicInitialize #-} + basicInitialize (MV_5 _ as bs cs ds es) + = do + M.basicInitialize as + M.basicInitialize bs + M.basicInitialize cs + M.basicInitialize ds + M.basicInitialize es + {-# INLINE basicUnsafeReplicate #-} + basicUnsafeReplicate n_ (a, b, c, d, e) + = do + as <- M.basicUnsafeReplicate n_ a + bs <- M.basicUnsafeReplicate n_ b + cs <- M.basicUnsafeReplicate n_ c + ds <- M.basicUnsafeReplicate n_ d + es <- M.basicUnsafeReplicate n_ e + return $ MV_5 n_ as bs cs ds es + {-# INLINE basicUnsafeRead #-} + basicUnsafeRead (MV_5 _ as bs cs ds es) i_ + = do + a <- M.basicUnsafeRead as i_ + b <- M.basicUnsafeRead bs i_ + c <- M.basicUnsafeRead cs i_ + d <- M.basicUnsafeRead ds i_ + e <- M.basicUnsafeRead es i_ + return (a, b, c, d, e) + {-# INLINE basicUnsafeWrite #-} + basicUnsafeWrite (MV_5 _ as bs cs ds es) i_ (a, b, c, d, e) + = do + M.basicUnsafeWrite as i_ a + M.basicUnsafeWrite bs i_ b + M.basicUnsafeWrite cs i_ c + M.basicUnsafeWrite ds i_ d + M.basicUnsafeWrite es i_ e + {-# INLINE basicClear #-} + basicClear (MV_5 _ as bs cs ds es) + = do + M.basicClear as + M.basicClear bs + M.basicClear cs + M.basicClear ds + M.basicClear es + {-# INLINE basicSet #-} + basicSet (MV_5 _ as bs cs ds es) (a, b, c, d, e) + = do + M.basicSet as a + M.basicSet bs b + M.basicSet cs c + M.basicSet ds d + M.basicSet es e + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_5 _ as1 bs1 cs1 ds1 es1) (MV_5 _ as2 + bs2 + cs2 + ds2 + es2) + = do + M.basicUnsafeCopy as1 as2 + M.basicUnsafeCopy bs1 bs2 + M.basicUnsafeCopy cs1 cs2 + M.basicUnsafeCopy ds1 ds2 + M.basicUnsafeCopy es1 es2 + {-# INLINE basicUnsafeMove #-} + basicUnsafeMove (MV_5 _ as1 bs1 cs1 ds1 es1) (MV_5 _ as2 + bs2 + cs2 + ds2 + es2) + = do + M.basicUnsafeMove as1 as2 + M.basicUnsafeMove bs1 bs2 + M.basicUnsafeMove cs1 cs2 + M.basicUnsafeMove ds1 ds2 + M.basicUnsafeMove es1 es2 + {-# INLINE basicUnsafeGrow #-} + basicUnsafeGrow (MV_5 n_ as bs cs ds es) m_ + = do + as' <- M.basicUnsafeGrow as m_ + bs' <- M.basicUnsafeGrow bs m_ + cs' <- M.basicUnsafeGrow cs m_ + ds' <- M.basicUnsafeGrow ds m_ + es' <- M.basicUnsafeGrow es m_ + return $ MV_5 (m_+n_) as' bs' cs' ds' es' +instance (Unbox a, + Unbox b, + Unbox c, + Unbox d, + Unbox e) => G.Vector Vector (a, b, c, d, e) where + {-# INLINE basicUnsafeFreeze #-} + basicUnsafeFreeze (MV_5 n_ as bs cs ds es) + = do + as' <- G.basicUnsafeFreeze as + bs' <- G.basicUnsafeFreeze bs + cs' <- G.basicUnsafeFreeze cs + ds' <- G.basicUnsafeFreeze ds + es' <- G.basicUnsafeFreeze es + return $ V_5 n_ as' bs' cs' ds' es' + {-# INLINE basicUnsafeThaw #-} + basicUnsafeThaw (V_5 n_ as bs cs ds es) + = do + as' <- G.basicUnsafeThaw as + bs' <- G.basicUnsafeThaw bs + cs' <- G.basicUnsafeThaw cs + ds' <- G.basicUnsafeThaw ds + es' <- G.basicUnsafeThaw es + return $ MV_5 n_ as' bs' cs' ds' es' + {-# INLINE basicLength #-} + basicLength (V_5 n_ _ _ _ _ _) = n_ + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i_ m_ (V_5 _ as bs cs ds es) + = V_5 m_ (G.basicUnsafeSlice i_ m_ as) + (G.basicUnsafeSlice i_ m_ bs) + (G.basicUnsafeSlice i_ m_ cs) + (G.basicUnsafeSlice i_ m_ ds) + (G.basicUnsafeSlice i_ m_ es) + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM (V_5 _ as bs cs ds es) i_ + = do + a <- G.basicUnsafeIndexM as i_ + b <- G.basicUnsafeIndexM bs i_ + c <- G.basicUnsafeIndexM cs i_ + d <- G.basicUnsafeIndexM ds i_ + e <- G.basicUnsafeIndexM es i_ + return (a, b, c, d, e) + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_5 _ as1 bs1 cs1 ds1 es1) (V_5 _ as2 + bs2 + cs2 + ds2 + es2) + = do + G.basicUnsafeCopy as1 as2 + G.basicUnsafeCopy bs1 bs2 + G.basicUnsafeCopy cs1 cs2 + G.basicUnsafeCopy ds1 ds2 + G.basicUnsafeCopy es1 es2 + {-# INLINE elemseq #-} + elemseq _ (a, b, c, d, e) + = G.elemseq (undefined :: Vector a) a + . G.elemseq (undefined :: Vector b) b + . G.elemseq (undefined :: Vector c) c + . G.elemseq (undefined :: Vector d) d + . G.elemseq (undefined :: Vector e) e + +data instance MVector s (a, b, c, d, e, f) + = MV_6 {-# UNPACK #-} !Int !(MVector s a) + !(MVector s b) + !(MVector s c) + !(MVector s d) + !(MVector s e) + !(MVector s f) +data instance Vector (a, b, c, d, e, f) + = V_6 {-# UNPACK #-} !Int !(Vector a) + !(Vector b) + !(Vector c) + !(Vector d) + !(Vector e) + !(Vector f) +instance (Unbox a, + Unbox b, + Unbox c, + Unbox d, + Unbox e, + Unbox f) => Unbox (a, b, c, d, e, f) +instance (Unbox a, + Unbox b, + Unbox c, + Unbox d, + Unbox e, + Unbox f) => M.MVector MVector (a, b, c, d, e, f) where + {-# INLINE basicLength #-} + basicLength (MV_6 n_ _ _ _ _ _ _) = n_ + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i_ m_ (MV_6 _ as bs cs ds es fs) + = MV_6 m_ (M.basicUnsafeSlice i_ m_ as) + (M.basicUnsafeSlice i_ m_ bs) + (M.basicUnsafeSlice i_ m_ cs) + (M.basicUnsafeSlice i_ m_ ds) + (M.basicUnsafeSlice i_ m_ es) + (M.basicUnsafeSlice i_ m_ fs) + {-# INLINE basicOverlaps #-} + basicOverlaps (MV_6 _ as1 bs1 cs1 ds1 es1 fs1) (MV_6 _ as2 + bs2 + cs2 + ds2 + es2 + fs2) + = M.basicOverlaps as1 as2 + || M.basicOverlaps bs1 bs2 + || M.basicOverlaps cs1 cs2 + || M.basicOverlaps ds1 ds2 + || M.basicOverlaps es1 es2 + || M.basicOverlaps fs1 fs2 + {-# INLINE basicUnsafeNew #-} + basicUnsafeNew n_ + = do + as <- M.basicUnsafeNew n_ + bs <- M.basicUnsafeNew n_ + cs <- M.basicUnsafeNew n_ + ds <- M.basicUnsafeNew n_ + es <- M.basicUnsafeNew n_ + fs <- M.basicUnsafeNew n_ + return $ MV_6 n_ as bs cs ds es fs + {-# INLINE basicInitialize #-} + basicInitialize (MV_6 _ as bs cs ds es fs) + = do + M.basicInitialize as + M.basicInitialize bs + M.basicInitialize cs + M.basicInitialize ds + M.basicInitialize es + M.basicInitialize fs + {-# INLINE basicUnsafeReplicate #-} + basicUnsafeReplicate n_ (a, b, c, d, e, f) + = do + as <- M.basicUnsafeReplicate n_ a + bs <- M.basicUnsafeReplicate n_ b + cs <- M.basicUnsafeReplicate n_ c + ds <- M.basicUnsafeReplicate n_ d + es <- M.basicUnsafeReplicate n_ e + fs <- M.basicUnsafeReplicate n_ f + return $ MV_6 n_ as bs cs ds es fs + {-# INLINE basicUnsafeRead #-} + basicUnsafeRead (MV_6 _ as bs cs ds es fs) i_ + = do + a <- M.basicUnsafeRead as i_ + b <- M.basicUnsafeRead bs i_ + c <- M.basicUnsafeRead cs i_ + d <- M.basicUnsafeRead ds i_ + e <- M.basicUnsafeRead es i_ + f <- M.basicUnsafeRead fs i_ + return (a, b, c, d, e, f) + {-# INLINE basicUnsafeWrite #-} + basicUnsafeWrite (MV_6 _ as bs cs ds es fs) i_ (a, b, c, d, e, f) + = do + M.basicUnsafeWrite as i_ a + M.basicUnsafeWrite bs i_ b + M.basicUnsafeWrite cs i_ c + M.basicUnsafeWrite ds i_ d + M.basicUnsafeWrite es i_ e + M.basicUnsafeWrite fs i_ f + {-# INLINE basicClear #-} + basicClear (MV_6 _ as bs cs ds es fs) + = do + M.basicClear as + M.basicClear bs + M.basicClear cs + M.basicClear ds + M.basicClear es + M.basicClear fs + {-# INLINE basicSet #-} + basicSet (MV_6 _ as bs cs ds es fs) (a, b, c, d, e, f) + = do + M.basicSet as a + M.basicSet bs b + M.basicSet cs c + M.basicSet ds d + M.basicSet es e + M.basicSet fs f + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_6 _ as1 bs1 cs1 ds1 es1 fs1) (MV_6 _ as2 + bs2 + cs2 + ds2 + es2 + fs2) + = do + M.basicUnsafeCopy as1 as2 + M.basicUnsafeCopy bs1 bs2 + M.basicUnsafeCopy cs1 cs2 + M.basicUnsafeCopy ds1 ds2 + M.basicUnsafeCopy es1 es2 + M.basicUnsafeCopy fs1 fs2 + {-# INLINE basicUnsafeMove #-} + basicUnsafeMove (MV_6 _ as1 bs1 cs1 ds1 es1 fs1) (MV_6 _ as2 + bs2 + cs2 + ds2 + es2 + fs2) + = do + M.basicUnsafeMove as1 as2 + M.basicUnsafeMove bs1 bs2 + M.basicUnsafeMove cs1 cs2 + M.basicUnsafeMove ds1 ds2 + M.basicUnsafeMove es1 es2 + M.basicUnsafeMove fs1 fs2 + {-# INLINE basicUnsafeGrow #-} + basicUnsafeGrow (MV_6 n_ as bs cs ds es fs) m_ + = do + as' <- M.basicUnsafeGrow as m_ + bs' <- M.basicUnsafeGrow bs m_ + cs' <- M.basicUnsafeGrow cs m_ + ds' <- M.basicUnsafeGrow ds m_ + es' <- M.basicUnsafeGrow es m_ + fs' <- M.basicUnsafeGrow fs m_ + return $ MV_6 (m_+n_) as' bs' cs' ds' es' fs' +instance (Unbox a, + Unbox b, + Unbox c, + Unbox d, + Unbox e, + Unbox f) => G.Vector Vector (a, b, c, d, e, f) where + {-# INLINE basicUnsafeFreeze #-} + basicUnsafeFreeze (MV_6 n_ as bs cs ds es fs) + = do + as' <- G.basicUnsafeFreeze as + bs' <- G.basicUnsafeFreeze bs + cs' <- G.basicUnsafeFreeze cs + ds' <- G.basicUnsafeFreeze ds + es' <- G.basicUnsafeFreeze es + fs' <- G.basicUnsafeFreeze fs + return $ V_6 n_ as' bs' cs' ds' es' fs' + {-# INLINE basicUnsafeThaw #-} + basicUnsafeThaw (V_6 n_ as bs cs ds es fs) + = do + as' <- G.basicUnsafeThaw as + bs' <- G.basicUnsafeThaw bs + cs' <- G.basicUnsafeThaw cs + ds' <- G.basicUnsafeThaw ds + es' <- G.basicUnsafeThaw es + fs' <- G.basicUnsafeThaw fs + return $ MV_6 n_ as' bs' cs' ds' es' fs' + {-# INLINE basicLength #-} + basicLength (V_6 n_ _ _ _ _ _ _) = n_ + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice i_ m_ (V_6 _ as bs cs ds es fs) + = V_6 m_ (G.basicUnsafeSlice i_ m_ as) + (G.basicUnsafeSlice i_ m_ bs) + (G.basicUnsafeSlice i_ m_ cs) + (G.basicUnsafeSlice i_ m_ ds) + (G.basicUnsafeSlice i_ m_ es) + (G.basicUnsafeSlice i_ m_ fs) + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM (V_6 _ as bs cs ds es fs) i_ + = do + a <- G.basicUnsafeIndexM as i_ + b <- G.basicUnsafeIndexM bs i_ + c <- G.basicUnsafeIndexM cs i_ + d <- G.basicUnsafeIndexM ds i_ + e <- G.basicUnsafeIndexM es i_ + f <- G.basicUnsafeIndexM fs i_ + return (a, b, c, d, e, f) + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MV_6 _ as1 bs1 cs1 ds1 es1 fs1) (V_6 _ as2 + bs2 + cs2 + ds2 + es2 + fs2) + = do + G.basicUnsafeCopy as1 as2 + G.basicUnsafeCopy bs1 bs2 + G.basicUnsafeCopy cs1 cs2 + G.basicUnsafeCopy ds1 ds2 + G.basicUnsafeCopy es1 es2 + G.basicUnsafeCopy fs1 fs2 + {-# INLINE elemseq #-} + elemseq _ (a, b, c, d, e, f) + = G.elemseq (undefined :: Vector a) a + . G.elemseq (undefined :: Vector b) b + . G.elemseq (undefined :: Vector c) c + . G.elemseq (undefined :: Vector d) d + . G.elemseq (undefined :: Vector e) e + . G.elemseq (undefined :: Vector f) f + diff --git a/vector/src/Data/Vector/Unsafe.hs b/vector/src/Data/Vector/Unsafe.hs new file mode 100644 index 00000000..6b008c54 --- /dev/null +++ b/vector/src/Data/Vector/Unsafe.hs @@ -0,0 +1,340 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE TypeFamilies #-} +-- | +-- This module exposes internal representation of lazy boxed vector +-- and functions that work on that representation directly (as opposed +-- to using 'G.Vector' API. +-- +-- Note that working with internal representation of vector is +-- generally unsafe and may violate memory safety +module Data.Vector.Unsafe + ( Vector(..) + -- * Array conversions + , toArray, fromArray + , toArraySlice, unsafeFromArraySlice + ) where + +import Data.Vector.Mutable.Unsafe ( MVector(..) ) +import Data.Primitive.Array +import qualified Data.Vector.Fusion.Bundle as Bundle +import qualified Data.Vector.Generic as G +import Data.Vector.Generic ((!)) + +import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf) ) + +import Control.Monad ( MonadPlus(..), liftM, ap ) +import Control.Monad.ST ( runST ) +import qualified Control.Monad.Fail as Fail +import Control.Monad.Fix ( MonadFix (mfix) ) +import Control.Monad.Zip +import Data.Function ( fix ) + +import Prelude + ( Eq, Ord, Monoid, Functor, Monad, Show, Ordering(..), Int + , compare, mempty, mappend, mconcat, return, showsPrec, fmap, otherwise, flip, const + , (>>=), (+), (-), (<), (<=), (>), (>=), (==), (/=), (&&), (.), ($) ) + +import Data.Functor.Classes (Eq1 (..), Ord1 (..), Read1 (..), Show1 (..)) +import Data.Data ( Data(..) ) +import Text.Read ( Read(..), readListPrecDefault ) +import Data.Semigroup ( Semigroup(..) ) + +import qualified Control.Applicative as Applicative +import qualified Data.Foldable as Foldable +import qualified Data.Traversable as Traversable + +import qualified GHC.Exts as Exts (IsList(..)) + + +-- | Lazy boxed vectors, supporting efficient slicing. +data Vector a = Vector {-# UNPACK #-} !Int + {-# UNPACK #-} !Int + {-# UNPACK #-} !(Array a) + +liftRnfV :: (a -> ()) -> Vector a -> () +liftRnfV elemRnf = G.foldl' (\_ -> elemRnf) () + +instance NFData a => NFData (Vector a) where + rnf = liftRnfV rnf + {-# INLINEABLE rnf #-} + +-- | @since 0.12.1.0 +instance NFData1 Vector where + liftRnf = liftRnfV + {-# INLINEABLE liftRnf #-} + +instance Show a => Show (Vector a) where + showsPrec = G.showsPrec + +instance Read a => Read (Vector a) where + readPrec = G.readPrec + readListPrec = readListPrecDefault + +instance Show1 Vector where + liftShowsPrec = G.liftShowsPrec + +instance Read1 Vector where + liftReadsPrec = G.liftReadsPrec + +instance Exts.IsList (Vector a) where + type Item (Vector a) = a + fromList = G.fromList + fromListN = G.fromListN + toList = G.toList + +instance Data a => Data (Vector a) where + gfoldl = G.gfoldl + toConstr _ = G.mkVecConstr "Data.Vector.Vector" + gunfold = G.gunfold + dataTypeOf _ = G.mkVecType "Data.Vector.Vector" + dataCast1 = G.dataCast + +type instance G.Mutable Vector = MVector + +instance G.Vector Vector a where + {-# INLINE basicUnsafeFreeze #-} + basicUnsafeFreeze (MVector i n marr) + = Vector i n `liftM` unsafeFreezeArray marr + + {-# INLINE basicUnsafeThaw #-} + basicUnsafeThaw (Vector i n arr) + = MVector i n `liftM` unsafeThawArray arr + + {-# INLINE basicLength #-} + basicLength (Vector _ n _) = n + + {-# INLINE basicUnsafeSlice #-} + basicUnsafeSlice j n (Vector i _ arr) = Vector (i+j) n arr + + {-# INLINE basicUnsafeIndexM #-} + basicUnsafeIndexM (Vector i _ arr) j = indexArrayM arr (i+j) + + {-# INLINE basicUnsafeCopy #-} + basicUnsafeCopy (MVector i n dst) (Vector j _ src) + = copyArray dst i src j n + +-- See http://trac.haskell.org/vector/ticket/12 +instance Eq a => Eq (Vector a) where + {-# INLINE (==) #-} + xs == ys = Bundle.eq (G.stream xs) (G.stream ys) + +-- See http://trac.haskell.org/vector/ticket/12 +instance Ord a => Ord (Vector a) where + {-# INLINE compare #-} + compare xs ys = Bundle.cmp (G.stream xs) (G.stream ys) + + {-# INLINE (<) #-} + xs < ys = Bundle.cmp (G.stream xs) (G.stream ys) == LT + + {-# INLINE (<=) #-} + xs <= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= GT + + {-# INLINE (>) #-} + xs > ys = Bundle.cmp (G.stream xs) (G.stream ys) == GT + + {-# INLINE (>=) #-} + xs >= ys = Bundle.cmp (G.stream xs) (G.stream ys) /= LT + +instance Eq1 Vector where + {-# INLINE liftEq #-} + liftEq = G.eqBy + +instance Ord1 Vector where + {-# INLINE liftCompare #-} + liftCompare = G.cmpBy + +instance Semigroup (Vector a) where + {-# INLINE (<>) #-} + (<>) = (G.++) + + {-# INLINE sconcat #-} + sconcat = G.concatNE + +instance Monoid (Vector a) where + {-# INLINE mempty #-} + mempty = G.empty + + {-# INLINE mappend #-} + mappend = (<>) + + {-# INLINE mconcat #-} + mconcat = G.concat + +instance Functor Vector where + {-# INLINE fmap #-} + fmap = G.map + + {-# INLINE (<$) #-} + (<$) = G.map . const + +instance Monad Vector where + {-# INLINE return #-} + return = Applicative.pure + + {-# INLINE (>>=) #-} + (>>=) = flip G.concatMap + + +-- | @since 0.12.1.0 +instance Fail.MonadFail Vector where + {-# INLINE fail #-} + fail _ = G.empty + +instance MonadPlus Vector where + {-# INLINE mzero #-} + mzero = G.empty + + {-# INLINE mplus #-} + mplus = (G.++) + +instance MonadZip Vector where + {-# INLINE mzip #-} + mzip = G.zip + + {-# INLINE mzipWith #-} + mzipWith = G.zipWith + + {-# INLINE munzip #-} + munzip = G.unzip + +-- | This instance has the same semantics as the one for lists. +-- +-- @since 0.12.2.0 +instance MonadFix Vector where + -- We take care to dispose of v0 as soon as possible (see headM docs). + -- + -- It's perfectly safe to use non-monadic indexing within generate + -- call since intermediate vector won't be created until result's + -- value is demanded. + {-# INLINE mfix #-} + mfix f + | G.null v0 = G.empty + -- We take first element of resulting vector from v0 and create + -- rest using generate. Note that cons should fuse with generate + | otherwise = runST $ do + h <- G.headM v0 + return $ G.cons h $ + G.generate (lv0 - 1) $ + \i -> fix (\a -> f a ! (i + 1)) + where + -- Used to calculate size of resulting vector + v0 = fix (f . G.head) + !lv0 = G.length v0 + +instance Applicative.Applicative Vector where + {-# INLINE pure #-} + pure = G.singleton + + {-# INLINE (<*>) #-} + (<*>) = ap + +instance Applicative.Alternative Vector where + {-# INLINE empty #-} + empty = G.empty + + {-# INLINE (<|>) #-} + (<|>) = (G.++) + +instance Foldable.Foldable Vector where + {-# INLINE foldr #-} + foldr = G.foldr + + {-# INLINE foldl #-} + foldl = G.foldl + + {-# INLINE foldr1 #-} + foldr1 = G.foldr1 + + {-# INLINE foldl1 #-} + foldl1 = G.foldl1 + + {-# INLINE foldr' #-} + foldr' = G.foldr' + + {-# INLINE foldl' #-} + foldl' = G.foldl' + + {-# INLINE toList #-} + toList = G.toList + + {-# INLINE length #-} + length = G.length + + {-# INLINE null #-} + null = G.null + + {-# INLINE elem #-} + elem = G.elem + + {-# INLINE maximum #-} + maximum = G.maximum + + {-# INLINE minimum #-} + minimum = G.minimum + + {-# INLINE sum #-} + sum = G.sum + + {-# INLINE product #-} + product = G.product + +instance Traversable.Traversable Vector where + {-# INLINE traverse #-} + traverse = G.traverse + + {-# INLINE mapM #-} + mapM = G.mapM + + {-# INLINE sequence #-} + sequence = G.sequence + + +-- Conversions - Arrays +-- ----------------------------- + +-- | /O(1)/ Convert an array to a vector. +-- +-- @since 0.12.2.0 +fromArray :: Array a -> Vector a +{-# INLINE fromArray #-} +fromArray arr = Vector 0 (sizeofArray arr) arr + +-- | /O(n)/ Convert a vector to an array. +-- +-- @since 0.12.2.0 +toArray :: Vector a -> Array a +{-# INLINE toArray #-} +toArray (Vector offset len arr) + | offset == 0 && len == sizeofArray arr = arr + | otherwise = cloneArray arr offset len + +-- | /O(1)/ Extract the underlying `Array`, offset where vector starts and the +-- total number of elements in the vector. Below property always holds: +-- +-- > let (array, offset, len) = toArraySlice v +-- > v === unsafeFromArraySlice len offset array +-- +-- @since 0.13.0.0 +toArraySlice :: Vector a -> (Array a, Int, Int) +{-# INLINE toArraySlice #-} +toArraySlice (Vector offset len arr) = (arr, offset, len) + + +-- | /O(1)/ Convert an array slice to a vector. This function is very unsafe, +-- because constructing an invalid vector can yield almost all other safe +-- functions in this module unsafe. These are equivalent: +-- +-- > unsafeFromArraySlice len offset === unsafeTake len . unsafeDrop offset . fromArray +-- +-- @since 0.13.0.0 +unsafeFromArraySlice :: + Array a -- ^ Immutable boxed array. + -> Int -- ^ Offset + -> Int -- ^ Length + -> Vector a +{-# INLINE unsafeFromArraySlice #-} +unsafeFromArraySlice arr offset len = Vector offset len arr diff --git a/vector/tests/doctests.hs b/vector/tests/doctests.hs index 172f033d..c943beda 100644 --- a/vector/tests/doctests.hs +++ b/vector/tests/doctests.hs @@ -21,21 +21,29 @@ main = mapM_ run modGroups modGroups = [ [ "src/Data/Vector/Storable/Mutable.hs" , "src/Data/Vector/Storable.hs" + , "src/Data/Vector/Storable/Mutable/Unsafe.hs" + , "src/Data/Vector/Storable/Unsafe.hs" ] , [ "src/Data/Vector.hs" , "src/Data/Vector/Mutable.hs" + , "src/Data/Vector/Unsafe.hs" + , "src/Data/Vector/Mutable/Unsafe.hs" ] , [ "src/Data/Vector/Strict.hs" + , "src/Data/Vector/Strict/Unsafe.hs" , "src/Data/Vector/Strict/Mutable.hs" + , "src/Data/Vector/Strict/Mutable/Unsafe.hs" ] , [ "src/Data/Vector/Generic.hs" , "src/Data/Vector/Generic/Mutable.hs" ] , [ "src/Data/Vector/Primitive.hs" + , "src/Data/Vector/Primitive/Unsafe.hs" , "src/Data/Vector/Primitive/Mutable.hs" + , "src/Data/Vector/Primitive/Mutable/Unsafe.hs" ] , [ "src/Data/Vector/Unboxed.hs" , "src/Data/Vector/Unboxed/Mutable.hs" - , "src/Data/Vector/Unboxed/Base.hs" + , "src/Data/Vector/Unboxed/Unsafe.hs" ] ] diff --git a/vector/vector.cabal b/vector/vector.cabal index b16d0c1d..8dcf50d5 100644 --- a/vector/vector.cabal +++ b/vector/vector.cabal @@ -127,22 +127,31 @@ Library Data.Vector.Generic.New Data.Vector.Generic - Data.Vector.Primitive.Mutable Data.Vector.Primitive + Data.Vector.Primitive.Mutable + Data.Vector.Primitive.Mutable.Unsafe + Data.Vector.Primitive.Unsafe + Data.Vector.Storable Data.Vector.Storable.Internal Data.Vector.Storable.Mutable - Data.Vector.Storable + Data.Vector.Storable.Mutable.Unsafe + Data.Vector.Storable.Unsafe - Data.Vector.Unboxed.Base + Data.Vector.Unboxed.Unsafe Data.Vector.Unboxed.Mutable + Data.Vector.Unboxed.Base Data.Vector.Unboxed Data.Vector.Strict.Mutable Data.Vector.Strict + Data.Vector.Strict.Mutable.Unsafe + Data.Vector.Strict.Unsafe Data.Vector.Mutable Data.Vector + Data.Vector.Mutable.Unsafe + Data.Vector.Unsafe Hs-Source-Dirs: src