diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 913eab61..bbb86d25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,28 +18,28 @@ jobs: matrix: include: # Linux - - { cabal: "3.4", os: ubuntu-latest, ghc: "8.0.2" } - - { cabal: "3.4", os: ubuntu-latest, ghc: "8.2.2" } - - { cabal: "3.4", os: ubuntu-latest, ghc: "8.4.4" } - - { cabal: "3.4", os: ubuntu-latest, ghc: "8.6.5" } - - { cabal: "3.4", os: ubuntu-latest, ghc: "8.8.4" } - - { cabal: "3.4", os: ubuntu-latest, ghc: "8.10.7" } - - { cabal: "3.4", os: ubuntu-latest, ghc: "9.0.1" } - - { cabal: "3.4", os: ubuntu-latest, ghc: "9.2.1" } + - { cabal: "3.6", os: ubuntu-latest, ghc: "8.0.2" } + - { cabal: "3.6", os: ubuntu-latest, ghc: "8.2.2" } + - { cabal: "3.6", os: ubuntu-latest, ghc: "8.4.4" } + - { cabal: "3.6", os: ubuntu-latest, ghc: "8.6.5" } + - { cabal: "3.6", os: ubuntu-latest, ghc: "8.8.4" } + - { cabal: "3.6", os: ubuntu-latest, ghc: "8.10.7" } + - { cabal: "3.6", os: ubuntu-latest, ghc: "9.0.1" } + - { cabal: "3.6", os: ubuntu-latest, ghc: "9.2.1" } # Win - - { cabal: "3.2", os: windows-latest, ghc: "8.4.4" } - - { cabal: "3.2", os: windows-latest, ghc: "8.6.5" } + - { cabal: "3.6", os: windows-latest, ghc: "8.4.4" } # OOM when building tests - # - { cabal: "3.4", os: windows-latest, ghc: "8.8.4" } - # - { cabal: "3.4", os: windows-latest, ghc: "8.10.4" } + # - { cabal: "3.6", os: windows-latest, ghc: "8.6.5" } + # - { cabal: "3.6", os: windows-latest, ghc: "8.8.4" } + # - { cabal: "3.6", os: windows-latest, ghc: "8.10.4" } # Too flaky: - # - { cabal: "3.4", os: windows-latest, ghc: "9.0.1" } + # - { cabal: "3.6", os: windows-latest, ghc: "9.0.1" } # MacOS - - { cabal: "3.2", os: macOS-latest, ghc: "8.4.4" } - - { cabal: "3.2", os: macOS-latest, ghc: "8.6.5" } - - { cabal: "3.2", os: macOS-latest, ghc: "8.8.4" } - - { cabal: "3.2", os: macOS-latest, ghc: "8.10.7" } - - { cabal: "3.4", os: macOS-latest, ghc: "9.0.1" } + - { cabal: "3.6", os: macOS-latest, ghc: "8.4.4" } + - { cabal: "3.6", os: macOS-latest, ghc: "8.6.5" } + - { cabal: "3.6", os: macOS-latest, ghc: "8.8.4" } + - { cabal: "3.6", os: macOS-latest, ghc: "8.10.7" } + - { cabal: "3.6", os: macOS-latest, ghc: "9.0.1" } fail-fast: false steps: diff --git a/vector/changelog.md b/vector/changelog.md index 6308aa13..84553f1f 100644 --- a/vector/changelog.md +++ b/vector/changelog.md @@ -47,6 +47,8 @@ * Add `groupBy` and `group` for `Data.Vector.Generic` and the specialized version in `Data.Vector`, `Data.Vector.Unboxed`, `Data.Vector.Storable` and `Data.Vector.Primitive`. +* Add `toArraySlice` and `unsafeFromArraySlice` functions for conversion to and + from the underlying boxed `Array`. # Changes in version 0.12.3.1 diff --git a/vector/src/Data/Vector.hs b/vector/src/Data/Vector.hs index 731494a3..be48d4d3 100644 --- a/vector/src/Data/Vector.hs +++ b/vector/src/Data/Vector.hs @@ -163,7 +163,7 @@ module Data.Vector ( toList, Data.Vector.fromList, Data.Vector.fromListN, -- ** Arrays - fromArray, toArray, + toArray, fromArray, toArraySlice, unsafeFromArraySlice, -- ** Other vector types G.convert, @@ -2136,16 +2136,43 @@ fromListN = G.fromListN -- @since 0.12.2.0 fromArray :: Array a -> Vector a {-# INLINE fromArray #-} -fromArray x = Vector 0 (sizeofArray x) x +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 size arr) - | offset == 0 && size == sizeofArray arr = arr - | otherwise = cloneArray arr offset size +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 -- ----------------------------- diff --git a/vector/tests/Tests/Vector/UnitTests.hs b/vector/tests/Tests/Vector/UnitTests.hs index 4946b3b9..0eb3cea5 100644 --- a/vector/tests/Tests/Vector/UnitTests.hs +++ b/vector/tests/Tests/Vector/UnitTests.hs @@ -91,6 +91,8 @@ tests = , testGroup "Data.Vector" [ testCase "MonadFix" checkMonadFix , testCase "toFromArray" toFromArray + , testCase "toFromArraySlice" toFromArraySlice + , testCase "toFromArraySliceUnsafe" toFromArraySliceUnsafe , testCase "toFromMutableArray" toFromMutableArray ] ] @@ -202,6 +204,22 @@ toFromArray = mkArrayRoundtrip $ \name v -> assertEqual name v $ Boxed.fromArray (Boxed.toArray v) +toFromArraySlice :: Assertion +toFromArraySlice = + mkArrayRoundtrip $ \name v -> + case Boxed.toArraySlice v of + (arr, off, n) -> + assertEqual name v $ + Boxed.take n (Boxed.drop off (Boxed.fromArray arr)) + +toFromArraySliceUnsafe :: Assertion +toFromArraySliceUnsafe = + mkArrayRoundtrip $ \name v -> + case Boxed.toArraySlice v of + (arr, off, n) -> + assertEqual name v $ + Boxed.unsafeFromArraySlice arr off n + toFromMutableArray :: Assertion toFromMutableArray = mkArrayRoundtrip assetRoundtrip where