Search code examples
arrayshaskellmemmove

Is there a memmove/memcpy wrapper for STUArray?


I'm switching a program from using MVector Word32 to STUArray Word Word32. In my vector code, I used unsafeMove to move vector slices around; thinking it was probably wrapping memmove for efficiency.

case dst ⊕ 3 of
  src | n < src + w -> do
    let w0 = n - src
    let w' = w - w0
    unsafeMove (slice dst w0 v) (slice src w0 v)
    if w' <= 3
      then do
        unsafeMove (slice (n - 3) w' v) (slice 0 w' v)
      else do
        let w'' = w' - 3
        unsafeMove (slice (n - 3) 3 v) (slice 0 3 v)
        unsafeMove (slice 0 w'' v) (slice 3 w'' v)
  src | n < dst + w -> do
    let w1 = n - dst
    let w'' = w - w1
    unsafeMove (slice dst w1 v) (slice src w1 v)
    unsafeMove (slice 0 w'' v) (slice 3 w'' v)
  src -> do
    unsafeMove (slice dst w v) (slice src w v)

The MArray typeclass doesn't seem to expose a way to move multiple elements in a single call, only one-by-one. Is there a wrapper for moving multiple STUArray elements (or maybe ByteArray#) at once?


Solution

  • thinking it was probably wrapping memmove for efficiency

    First I decided to check for you whether this is actually true, and it is.

    • unsafeMove eventually boils down to the basicUnsafeCopy operation defined for MVector, which delegates to copyMutableArray.
    • copyMutableArray's implementation varies by GHC version. For old versions, it was just an IO loop in ordinary Haskell, but since 7.8 it has delegated to a primop copyMutableArray#.
    • copyMutableArray# is a wrapper around memmove and memcopy, depending whether the arrays overlap.

    I grepped through the source of Data.Array, and found no references to copyMutableArray. Another possibility would be that Data.Array exposes some way for you to view your STUArray as a MutableArray, and thereby call copyMutableArray yourself. But I also find no mention of MutableArray in Data.Array.

    My tentative conclusion is that there is no memmove/memcopy wrapper in Data.Array.