diff --git a/vector/changelog.md b/vector/changelog.md index faabc117..60063f04 100644 --- a/vector/changelog.md +++ b/vector/changelog.md @@ -43,6 +43,7 @@ resulted in an error. This change was introduced in: [#382](https://github.com/haskell/vector/pull/382) * Remove redundant `Storable` constraints on to/from `ForeignPtr` conversions +* Add `unsafeCast` to `Primitive` vectors # Changes in version 0.12.3.0 diff --git a/vector/src/Data/Vector/Primitive.hs b/vector/src/Data/Vector/Primitive.hs index bc18ed8e..cc45cd43 100644 --- a/vector/src/Data/Vector/Primitive.hs +++ b/vector/src/Data/Vector/Primitive.hs @@ -145,7 +145,7 @@ module Data.Vector.Primitive ( toList, fromList, fromListN, -- ** Other vector types - G.convert, + G.convert, unsafeCast, unsafeCoerceVector, -- ** Mutable vectors @@ -157,6 +157,7 @@ module Data.Vector.Primitive ( 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.Primitive.ByteArray import Data.Primitive ( Prim, sizeOf ) @@ -203,7 +204,7 @@ type role Vector nominal -- 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. +-- 'Prim' instances. -- -- Note that this function is unsafe. The @Coercible@ constraint guarantees -- that the element types are representationally equal. It however cannot @@ -1769,6 +1770,22 @@ fromListN :: Prim a => Int -> [a] -> Vector a {-# INLINE fromListN #-} fromListN = G.fromListN +-- 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 -- ----------------------------- diff --git a/vector/src/Data/Vector/Primitive/Mutable.hs b/vector/src/Data/Vector/Primitive/Mutable.hs index 25ccf964..b8587b9e 100644 --- a/vector/src/Data/Vector/Primitive/Mutable.hs +++ b/vector/src/Data/Vector/Primitive/Mutable.hs @@ -61,7 +61,7 @@ module Data.Vector.Primitive.Mutable ( set, copy, move, unsafeCopy, unsafeMove, -- * Unsafe conversions - unsafeCoerceMVector, + unsafeCoerceMVector, unsafeCast, -- * Re-exports Prim, PrimMonad, PrimState, RealWorld ) where @@ -69,6 +69,7 @@ module Data.Vector.Primitive.Mutable ( import qualified Data.Vector.Generic.Mutable as G import Data.Primitive.ByteArray import Data.Primitive ( Prim, sizeOf ) +import Data.Vector.Internal.Check import Data.Word ( Word8 ) import Control.Monad.Primitive import Control.Monad ( liftM ) @@ -656,3 +657,20 @@ ifoldrM = G.ifoldrM ifoldrM' :: (PrimMonad m, Prim a) => (Int -> a -> b -> m b) -> b -> MVector (PrimState m) a -> m b {-# 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"