Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unsafeToArray function for getting the underlying boxed Array #434

Merged
merged 2 commits into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions vector/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
37 changes: 32 additions & 5 deletions vector/src/Data/Vector.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
-- -----------------------------
Expand Down
18 changes: 18 additions & 0 deletions vector/tests/Tests/Vector/UnitTests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ tests =
, testGroup "Data.Vector"
[ testCase "MonadFix" checkMonadFix
, testCase "toFromArray" toFromArray
, testCase "toFromArraySlice" toFromArraySlice
, testCase "toFromArraySliceUnsafe" toFromArraySliceUnsafe
, testCase "toFromMutableArray" toFromMutableArray
]
]
Expand Down Expand Up @@ -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
Expand Down