{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- |
-- Module      : Data.Prim.Memory.Fold
-- Copyright   : (c) Alexey Kuleshevich 2020
-- License     : BSD3
-- Maintainer  : Alexey Kuleshevich <alexey@kuleshevi.ch>
-- Stability   : experimental
-- Portability : non-portable
--
module Data.Prim.Memory.Fold where

import Data.Prim
import Data.Prim.Memory.Internal


foldlMem ::
     forall e a mr. (Prim e, MemRead mr)
  => (a -> e -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
foldlMem :: (a -> e -> a) -> a -> mr -> a
foldlMem a -> e -> a
f = (a -> Off e -> e -> a) -> a -> mr -> a
forall e a mr.
(Prim e, MemRead mr) =>
(a -> Off e -> e -> a) -> a -> mr -> a
ifoldlMem (\a
a Off e
_ -> a -> e -> a
f a
a)
{-# INLINE foldlMem #-}


ifoldlMem ::
     forall e a mr. (Prim e, MemRead mr)
  => (a -> Off e -> e -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
ifoldlMem :: (a -> Off e -> e -> a) -> a -> mr -> a
ifoldlMem a -> Off e -> e -> a
f a
initAcc mr
mem = Off e -> Count e -> (a -> Off e -> e -> a) -> a -> mr -> a
forall e a mr.
(Prim e, MemRead mr) =>
Off e -> Count e -> (a -> Off e -> e -> a) -> a -> mr -> a
ifoldlOffMem Off e
0 (mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
mem :: Count e) a -> Off e -> e -> a
f a
initAcc mr
mem
{-# INLINE ifoldlMem #-}

ifoldlOffMem ::
     forall e a mr. (Prim e, MemRead mr)
  => Off e
  -- ^ Initial offset to start at
  -> Count e
  -- ^ Total number of elements to iterate through
  -> (a -> Off e -> e -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
ifoldlOffMem :: Off e -> Count e -> (a -> Off e -> e -> a) -> a -> mr -> a
ifoldlOffMem Off e
off Count e
count a -> Off e -> e -> a
f a
initAcc mr
mem = a -> Off e -> a
loop a
initAcc Off e
off
  where
    k :: Off e
k = Count e -> Off e
forall e. Count e -> Off e
countToOff Count e
count Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
off
    loop :: a -> Off e -> a
loop !a
acc Off e
i
      | Off e
i Off e -> Off e -> Bool
forall a. Ord a => a -> a -> Bool
>= Off e
k = a
acc
      | Bool
otherwise = a -> Off e -> a
loop (a -> Off e -> e -> a
f a
acc Off e
i (mr -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr
mem Off e
i)) (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
1)
{-# INLINE ifoldlOffMem #-}




foldlLazyMem ::
     forall e a mr. (Prim e, MemRead mr)
  => (a -> e -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
foldlLazyMem :: (a -> e -> a) -> a -> mr -> a
foldlLazyMem a -> e -> a
f = (a -> Off e -> e -> a) -> a -> mr -> a
forall e a mr.
(Prim e, MemRead mr) =>
(a -> Off e -> e -> a) -> a -> mr -> a
ifoldlLazyMem (\a
a Off e
_ -> a -> e -> a
f a
a)
{-# INLINE foldlLazyMem #-}

ifoldlLazyMem ::
     forall e a mr. (Prim e, MemRead mr)
  => (a -> Off e -> e -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
ifoldlLazyMem :: (a -> Off e -> e -> a) -> a -> mr -> a
ifoldlLazyMem a -> Off e -> e -> a
f a
initAcc mr
mem = Off e -> Count e -> (a -> Off e -> e -> a) -> a -> mr -> a
forall e a mr.
(Prim e, MemRead mr) =>
Off e -> Count e -> (a -> Off e -> e -> a) -> a -> mr -> a
ifoldlLazyOffMem Off e
0 (mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
mem :: Count e) a -> Off e -> e -> a
f a
initAcc mr
mem
{-# INLINE ifoldlLazyMem #-}

ifoldlLazyOffMem ::
     forall e a mr. (Prim e, MemRead mr)
  => Off e
  -- ^ Initial offset to start at
  -> Count e
  -- ^ Total number of elements to iterate through
  -> (a -> Off e -> e -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
ifoldlLazyOffMem :: Off e -> Count e -> (a -> Off e -> e -> a) -> a -> mr -> a
ifoldlLazyOffMem Off e
off Count e
count a -> Off e -> e -> a
f a
initAcc mr
mem = a -> Off e -> a
loop a
initAcc Off e
off
  where
    k :: Off e
k = Count e -> Off e
forall e. Count e -> Off e
countToOff Count e
count Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
off
    loop :: a -> Off e -> a
loop a
acc Off e
i
      | Off e
i Off e -> Off e -> Bool
forall a. Ord a => a -> a -> Bool
>= Off e
k = a
acc
      | Bool
otherwise = a -> Off e -> a
loop (a -> Off e -> e -> a
f a
acc Off e
i (mr -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr
mem Off e
i)) (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
1)
{-# INLINE ifoldlLazyOffMem #-}




foldrMem ::
     forall e a mr. (Prim e, MemRead mr)
  => (e -> a -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
foldrMem :: (e -> a -> a) -> a -> mr -> a
foldrMem e -> a -> a
f = (Off e -> e -> a -> a) -> a -> mr -> a
forall e a mr.
(Prim e, MemRead mr) =>
(Off e -> e -> a -> a) -> a -> mr -> a
ifoldrMem ((e -> a -> a) -> Off e -> e -> a -> a
forall a b. a -> b -> a
const e -> a -> a
f)
{-# INLINE foldrMem #-}

ifoldrMem ::
     forall e a mr. (Prim e, MemRead mr)
  => (Off e -> e -> a -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
ifoldrMem :: (Off e -> e -> a -> a) -> a -> mr -> a
ifoldrMem Off e -> e -> a -> a
f a
initAcc mr
mem = Off e -> Count e -> (Off e -> e -> a -> a) -> a -> mr -> a
forall e a mr.
(Prim e, MemRead mr) =>
Off e -> Count e -> (Off e -> e -> a -> a) -> a -> mr -> a
ifoldrOffMem Off e
0 (mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
mem :: Count e) Off e -> e -> a -> a
f a
initAcc mr
mem
{-# INLINE ifoldrMem #-}

ifoldrOffMem ::
     forall e a mr. (Prim e, MemRead mr)
  => Off e
  -- ^ Initial offset to start at
  -> Count e
  -- ^ Total number of elements to iterate through
  -> (Off e -> e -> a -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
ifoldrOffMem :: Off e -> Count e -> (Off e -> e -> a -> a) -> a -> mr -> a
ifoldrOffMem Off e
off Count e
count Off e -> e -> a -> a
f a
initAcc mr
mem = a -> Off e -> a
loop a
initAcc Off e
off
  where
    k :: Off e
k = Count e -> Off e
forall e. Count e -> Off e
countToOff Count e
count Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
off
    loop :: a -> Off e -> a
loop !a
acc Off e
i
      | Off e
i Off e -> Off e -> Bool
forall a. Ord a => a -> a -> Bool
>= Off e
k = a
acc
      | Bool
otherwise = Off e -> e -> a -> a
f Off e
i (mr -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr
mem Off e
i) (a -> Off e -> a
loop a
acc (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
1))
{-# INLINE ifoldrOffMem #-}


-- | Right fold with a lazy accumulator
--
-- @since 0.3.0
foldrLazyMem ::
     forall e a mr. (Prim e, MemRead mr)
  => (e -> a -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
foldrLazyMem :: (e -> a -> a) -> a -> mr -> a
foldrLazyMem e -> a -> a
f = (Off e -> e -> a -> a) -> a -> mr -> a
forall e a mr.
(Prim e, MemRead mr) =>
(Off e -> e -> a -> a) -> a -> mr -> a
ifoldrLazyMem ((e -> a -> a) -> Off e -> e -> a -> a
forall a b. a -> b -> a
const e -> a -> a
f)
{-# INLINE foldrLazyMem #-}

-- | Right fold with a lazy accumulator using an offset aware function
--
-- @since 0.3.0
ifoldrLazyMem ::
     forall e a mr. (Prim e, MemRead mr)
  => (Off e -> e -> a -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
ifoldrLazyMem :: (Off e -> e -> a -> a) -> a -> mr -> a
ifoldrLazyMem Off e -> e -> a -> a
f a
initAcc mr
mem =
  Off e -> Count e -> (Off e -> e -> a -> a) -> a -> mr -> a
forall e a mr.
(Prim e, MemRead mr) =>
Off e -> Count e -> (Off e -> e -> a -> a) -> a -> mr -> a
ifoldrLazyOffMem Off e
0 (mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
mem :: Count e) Off e -> e -> a -> a
f a
initAcc mr
mem
{-# INLINE ifoldrLazyMem #-}


ifoldrLazyOffMem ::
     forall e a mr. (Prim e, MemRead mr)
  => Off e
  -- ^ Initial offset to start at
  -> Count e
  -- ^ Total number of elements to iterate through
  -> (Off e -> e -> a -> a)
  -- ^ Folding function
  -> a
  -- ^ Initial accumulator
  -> mr
  -- ^ Memory region to iterate over
  -> a
ifoldrLazyOffMem :: Off e -> Count e -> (Off e -> e -> a -> a) -> a -> mr -> a
ifoldrLazyOffMem Off e
off Count e
count Off e -> e -> a -> a
f a
initAcc mr
mem = a -> Off e -> a
loop a
initAcc Off e
off
  where
    k :: Off e
k = Count e -> Off e
forall e. Count e -> Off e
countToOff Count e
count Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
off
    loop :: a -> Off e -> a
loop a
acc Off e
i
      | Off e
i Off e -> Off e -> Bool
forall a. Ord a => a -> a -> Bool
>= Off e
k = a
acc
      | Bool
otherwise = Off e -> e -> a -> a
f Off e
i (mr -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr
mem Off e
i) (a -> Off e -> a
loop a
acc (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
1))
{-# INLINE ifoldrLazyOffMem #-}




foldMapOffMem ::
     forall e m mr. (Prim e, MemRead mr, Monoid m)
  => Off e
  -> Count e
  -> (e -> m)
  -> mr
  -> m
foldMapOffMem :: Off e -> Count e -> (e -> m) -> mr -> m
foldMapOffMem Off e
off Count e
count e -> m
f = Off e -> Count e -> (Off e -> e -> m -> m) -> m -> mr -> m
forall e a mr.
(Prim e, MemRead mr) =>
Off e -> Count e -> (Off e -> e -> a -> a) -> a -> mr -> a
ifoldrLazyOffMem Off e
off Count e
count (\Off e
_ e
e m
acc -> e -> m
f e
e m -> m -> m
forall a. Monoid a => a -> a -> a
`mappend` m
acc) m
forall a. Monoid a => a
mempty
{-# INLINE foldMapOffMem #-}

ifoldMapOffMem ::
     forall e m mr. (Prim e, MemRead mr, Monoid m)
  => Off e
  -> Count e
  -> (Off e -> e -> m)
  -> mr
  -> m
ifoldMapOffMem :: Off e -> Count e -> (Off e -> e -> m) -> mr -> m
ifoldMapOffMem Off e
off Count e
count Off e -> e -> m
f =
  Off e -> Count e -> (Off e -> e -> m -> m) -> m -> mr -> m
forall e a mr.
(Prim e, MemRead mr) =>
Off e -> Count e -> (Off e -> e -> a -> a) -> a -> mr -> a
ifoldrLazyOffMem Off e
off Count e
count (\Off e
i e
e m
acc -> Off e -> e -> m
f Off e
i e
e m -> m -> m
forall a. Monoid a => a -> a -> a
`mappend` m
acc) m
forall a. Monoid a => a
mempty
{-# INLINE ifoldMapOffMem #-}



anyOffMem ::
     forall e mr. (Prim e, MemRead mr)
  => Off e
  -> Count e
  -> (e -> Bool)
  -> mr
  -> Bool
anyOffMem :: Off e -> Count e -> (e -> Bool) -> mr -> Bool
anyOffMem Off e
off Count e
count e -> Bool
p = Any -> Bool
getAny (Any -> Bool) -> (mr -> Any) -> mr -> Bool
forall a b c (proxy :: * -> * -> *).
Coercible b c =>
proxy b c -> (a -> b) -> a -> c
#. Off e -> Count e -> (e -> Any) -> mr -> Any
forall e m mr.
(Prim e, MemRead mr, Monoid m) =>
Off e -> Count e -> (e -> m) -> mr -> m
foldMapOffMem Off e
off Count e
count (Bool -> Any
Any (Bool -> Any) -> (e -> Bool) -> e -> Any
forall a b c (proxy :: * -> * -> *).
Coercible b c =>
proxy b c -> (a -> b) -> a -> c
#. e -> Bool
p)
{-# INLINE anyOffMem #-}

ianyOffMem ::
     forall e mr. (Prim e, MemRead mr)
  => Off e
  -> Count e
  -> (Off e -> e -> Bool)
  -> mr
  -> Bool
ianyOffMem :: Off e -> Count e -> (Off e -> e -> Bool) -> mr -> Bool
ianyOffMem Off e
off Count e
count Off e -> e -> Bool
p = Any -> Bool
getAny (Any -> Bool) -> (mr -> Any) -> mr -> Bool
forall a b c (proxy :: * -> * -> *).
Coercible b c =>
proxy b c -> (a -> b) -> a -> c
#. Off e -> Count e -> (Off e -> e -> Any) -> mr -> Any
forall e m mr.
(Prim e, MemRead mr, Monoid m) =>
Off e -> Count e -> (Off e -> e -> m) -> mr -> m
ifoldMapOffMem Off e
off Count e
count (\Off e
i -> Bool -> Any
Any (Bool -> Any) -> (e -> Bool) -> e -> Any
forall a b c (proxy :: * -> * -> *).
Coercible b c =>
proxy b c -> (a -> b) -> a -> c
#. Off e -> e -> Bool
p Off e
i)
{-# INLINE ianyOffMem #-}


anyMem :: forall e mr . (Prim e, MemRead mr) => (e -> Bool) -> mr -> Bool
anyMem :: (e -> Bool) -> mr -> Bool
anyMem e -> Bool
p mr
xs = Off e -> Count e -> (e -> Bool) -> mr -> Bool
forall e mr.
(Prim e, MemRead mr) =>
Off e -> Count e -> (e -> Bool) -> mr -> Bool
anyOffMem Off e
0 (mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
xs :: Count e) e -> Bool
p mr
xs
{-# INLINE anyMem #-}

ianyMem :: forall e mr . (Prim e, MemRead mr) => (Off e -> e -> Bool) -> mr -> Bool
ianyMem :: (Off e -> e -> Bool) -> mr -> Bool
ianyMem Off e -> e -> Bool
p mr
xs = Off e -> Count e -> (Off e -> e -> Bool) -> mr -> Bool
forall e mr.
(Prim e, MemRead mr) =>
Off e -> Count e -> (Off e -> e -> Bool) -> mr -> Bool
ianyOffMem Off e
0 (mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
xs :: Count e) Off e -> e -> Bool
p mr
xs
{-# INLINE ianyMem #-}

allOffMem ::
     forall e mr. (Prim e, MemRead mr)
  => Off e
  -> Count e
  -> (e -> Bool)
  -> mr
  -> Bool
allOffMem :: Off e -> Count e -> (e -> Bool) -> mr -> Bool
allOffMem Off e
off Count e
count e -> Bool
p = All -> Bool
getAll (All -> Bool) -> (mr -> All) -> mr -> Bool
forall a b c (proxy :: * -> * -> *).
Coercible b c =>
proxy b c -> (a -> b) -> a -> c
#. Off e -> Count e -> (e -> All) -> mr -> All
forall e m mr.
(Prim e, MemRead mr, Monoid m) =>
Off e -> Count e -> (e -> m) -> mr -> m
foldMapOffMem Off e
off Count e
count (Bool -> All
All (Bool -> All) -> (e -> Bool) -> e -> All
forall a b c (proxy :: * -> * -> *).
Coercible b c =>
proxy b c -> (a -> b) -> a -> c
#. e -> Bool
p)
{-# INLINE allOffMem #-}

iallOffMem ::
     forall e mr. (Prim e, MemRead mr)
  => Off e
  -> Count e
  -> (Off e -> e -> Bool)
  -> mr
  -> Bool
iallOffMem :: Off e -> Count e -> (Off e -> e -> Bool) -> mr -> Bool
iallOffMem Off e
off Count e
count Off e -> e -> Bool
p = All -> Bool
getAll (All -> Bool) -> (mr -> All) -> mr -> Bool
forall a b c (proxy :: * -> * -> *).
Coercible b c =>
proxy b c -> (a -> b) -> a -> c
#. Off e -> Count e -> (Off e -> e -> All) -> mr -> All
forall e m mr.
(Prim e, MemRead mr, Monoid m) =>
Off e -> Count e -> (Off e -> e -> m) -> mr -> m
ifoldMapOffMem Off e
off Count e
count (\Off e
i -> Bool -> All
All (Bool -> All) -> (e -> Bool) -> e -> All
forall a b c (proxy :: * -> * -> *).
Coercible b c =>
proxy b c -> (a -> b) -> a -> c
#. Off e -> e -> Bool
p Off e
i)
{-# INLINE iallOffMem #-}


allMem :: forall e mr . (Prim e, MemRead mr) => (e -> Bool) -> mr -> Bool
allMem :: (e -> Bool) -> mr -> Bool
allMem e -> Bool
p mr
xs = Off e -> Count e -> (e -> Bool) -> mr -> Bool
forall e mr.
(Prim e, MemRead mr) =>
Off e -> Count e -> (e -> Bool) -> mr -> Bool
allOffMem Off e
0 (mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
xs :: Count e) e -> Bool
p mr
xs
{-# INLINE allMem #-}

iallMem :: forall e mr . (Prim e, MemRead mr) => (Off e -> e -> Bool) -> mr -> Bool
iallMem :: (Off e -> e -> Bool) -> mr -> Bool
iallMem Off e -> e -> Bool
p mr
xs = Off e -> Count e -> (Off e -> e -> Bool) -> mr -> Bool
forall e mr.
(Prim e, MemRead mr) =>
Off e -> Count e -> (Off e -> e -> Bool) -> mr -> Bool
iallOffMem Off e
0 (mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
xs :: Count e) Off e -> e -> Bool
p mr
xs
{-# INLINE iallMem #-}



---------




-- Dangerous: ignores the slack
eqMem :: forall e mr . (Prim e, Eq e, MemRead mr) => mr -> mr -> Bool
eqMem :: mr -> mr -> Bool
eqMem mr
m1 mr
m2
  | mr -> mr -> Bool
forall mr. MemRead mr => mr -> mr -> Bool
isSameMem mr
m1 mr
m2 = Bool
True
  | Bool
otherwise = Count e
n Count e -> Count e -> Bool
forall a. Eq a => a -> a -> Bool
== mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
m2 Bool -> Bool -> Bool
&& mr -> Off e -> mr -> Off e -> Count e -> Bool
forall e mr1 mr2.
(Prim e, Eq e, MemRead mr1, MemRead mr2) =>
mr1 -> Off e -> mr2 -> Off e -> Count e -> Bool
eqOffMem mr
m1 Off e
0 mr
m2 Off e
0 Count e
n
  where
    n :: Count e
n = mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
m1 :: Count e
{-# INLINE eqMem #-}



-- | Check two regions of memory for equality using the `Eq` instance. It will return
-- `True` whenever both regions hold exactly the same elements and `False` as soon as the
-- first pair of mismatched elements is discovered in the two regions. It is safe for both
-- regions to refer to the same part of memory.
--
-- [Unsafe] When any precondition for either of the offsets @memOff1@, @memOff2@ or the
-- element count @memCount@ is violated the result is either unpredictable output or
-- failure with a segfault.
--
-- @since 0.3.0
eqOffMem ::
     (Prim e, Eq e, MemRead mr1, MemRead mr2)
  => mr1 -- ^ /memRead1/ - First region of memory
  -> Off e
  -- ^ /memOff1/ - Offset for @memRead1@ in number of elements
  --
  -- /__Precondition:__/
  --
  -- > 0 <= memOff1
  -> mr2 -- ^ /memRead2/ - Second region of memory
  -> Off e
  -- ^ /memOff2/ - Offset for @memRead1@ in number of elements
  --
  -- /__Precondition:__/
  --
  -- > 0 <= memOff2
  -> Count e
  -- ^ /memCount/ - Number of elements of type __@e@__ to compare
  --
  -- /__Preconditions:__/
  --
  -- > 0 <= memCount
  --
  -- > offToCount memOff1 + memCount < countMem memRead1
  --
  -- > offToCount memOff2 + memCount < countMem memRead2
  -> Bool
eqOffMem :: mr1 -> Off e -> mr2 -> Off e -> Count e -> Bool
eqOffMem mr1
m1 Off e
off1 mr2
m2 Off e
off2 Count e
count = Off e -> Bool
loop Off e
off1
  where
    doff :: Off e
doff = Off e
off2 Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
- Off e
off1
    k :: Off e
k = Count e -> Off e
forall e. Count e -> Off e
countToOff Count e
count Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
off1
    loop :: Off e -> Bool
loop !Off e
i
      | Off e
i Off e -> Off e -> Bool
forall a. Ord a => a -> a -> Bool
< Off e
k = mr1 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr1
m1 Off e
i e -> e -> Bool
forall a. Eq a => a -> a -> Bool
== mr2 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr2
m2 (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
doff) Bool -> Bool -> Bool
&& Off e -> Bool
loop (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
1)
      | Bool
otherwise = Bool
True
{-# INLINE[1] eqOffMem #-}

eqOffMemBinary ::
     forall e mr1 mr2. (Prim e, MemRead mr1, MemRead mr2)
  => mr1
  -> Off e
  -> mr2
  -> Off e
  -> Count e
  -> Bool
eqOffMemBinary :: mr1 -> Off e -> mr2 -> Off e -> Count e -> Bool
eqOffMemBinary mr1
m1 Off e
off1 mr2
m2 Off e
off2 Count e
count =
  mr1 -> Off Word8 -> mr2 -> Off Word8 -> Count Word8 -> Bool
forall mr1 mr2.
(MemRead mr1, MemRead mr2) =>
mr1 -> Off Word8 -> mr2 -> Off Word8 -> Count Word8 -> Bool
eqByteOffMem mr1
m1 (Off e -> Off Word8
forall e. Prim e => Off e -> Off Word8
toByteOff Off e
off1) mr2
m2 (Off e -> Off Word8
forall e. Prim e => Off e -> Off Word8
toByteOff Off e
off2) (Count e -> Count Word8
forall e. Prim e => Count e -> Count Word8
toByteCount Count e
count)
{-# INLINE eqOffMemBinary #-}

{-# RULES
"eqOffMem/Char" forall mr1 (off1 :: Off Char) . eqOffMem mr1 off1 = eqOffMemBinary mr1 off1
"eqOffMem/Word" forall mr1 (off1 :: Off Word) . eqOffMem mr1 off1 = eqOffMemBinary mr1 off1
"eqOffMem/Word8" eqOffMem = eqByteOffMem
"eqOffMem/Word16" forall mr1 (off1 :: Off Word16) . eqOffMem mr1 off1 = eqOffMemBinary mr1 off1
"eqOffMem/Word32" forall mr1 (off1 :: Off Word32) . eqOffMem mr1 off1 = eqOffMemBinary mr1 off1
"eqOffMem/Word64" forall mr1 (off1 :: Off Word64) . eqOffMem mr1 off1 = eqOffMemBinary mr1 off1
"eqOffMem/Int" forall mr1 (off1 :: Off Int) . eqOffMem mr1 off1 = eqOffMemBinary mr1 off1
"eqOffMem/Int8" forall mr1 (off1 :: Off Int8) . eqOffMem mr1 off1 = eqOffMemBinary mr1 off1
"eqOffMem/Int16" forall mr1 (off1 :: Off Int16) . eqOffMem mr1 off1 = eqOffMemBinary mr1 off1
"eqOffMem/Int32" forall mr1 (off1 :: Off Int32) . eqOffMem mr1 off1 = eqOffMemBinary mr1 off1
"eqOffMem/Int64" forall mr1 (off1 :: Off Int64) . eqOffMem mr1 off1 = eqOffMemBinary mr1 off1
#-}

eqOffMutMem ::
     forall e ma1 ma2 m s. (Prim e, Eq e, MonadPrim s m, MemWrite ma1, MemWrite ma2)
  => ma1 s
  -> Off e
  -> ma2 s
  -> Off e
  -> Count e
  -> m Bool
eqOffMutMem :: ma1 s -> Off e -> ma2 s -> Off e -> Count e -> m Bool
eqOffMutMem ma1 s
mm1 Off e
off1 ma2 s
mm2 Off e
off2 Count e
count = Off e -> m Bool
forall (m :: * -> *). MonadPrim s m => Off e -> m Bool
loop Off e
off1
  where
    doff :: Off e
doff = Off e
off2 Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
- Off e
off1
    k :: Off e
k = Count e -> Off e
forall e. Count e -> Off e
countToOff Count e
count Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
off1
    loop :: Off e -> m Bool
loop !Off e
i
      | Off e
i Off e -> Off e -> Bool
forall a. Ord a => a -> a -> Bool
< Off e
k = do
        e
e1 <- ma1 s -> Off e -> m e
forall (mw :: * -> *) s (m :: * -> *) e.
(MemWrite mw, MonadPrim s m, Prim e) =>
mw s -> Off e -> m e
readOffMutMem ma1 s
mm1 Off e
i
        e
e2 <- ma2 s -> Off e -> m e
forall (mw :: * -> *) s (m :: * -> *) e.
(MemWrite mw, MonadPrim s m, Prim e) =>
mw s -> Off e -> m e
readOffMutMem ma2 s
mm2 (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
doff)
        if e
e1 e -> e -> Bool
forall a. Eq a => a -> a -> Bool
== e
e2
          then Off e -> m Bool
loop (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
1)
          else Bool -> m Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
      | Bool
otherwise = Bool -> m Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
{-# INLINE eqOffMutMem #-}


-- | Compare two mutable memory regions for element equality. Regions themselves are not
-- modified, as such it is semantically similar to `eqMem` which works on immutable
-- regions.
eqMutMem ::
     forall e ma m s. (Prim e, Eq e, MonadPrim s m, MemAlloc ma)
  => ma s
  -> ma s
  -> m Bool
eqMutMem :: ma s -> ma s -> m Bool
eqMutMem ma s
mm1 ma s
mm2
  | ma s -> ma s -> Bool
forall (mw :: * -> *) s. MemWrite mw => mw s -> mw s -> Bool
isSameMutMem ma s
mm1 ma s
mm2 = Bool -> m Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
  | Bool
otherwise = do
    Count e
n1 <- ma s -> m (Count e)
forall e (ma :: * -> *) (m :: * -> *) s.
(MemAlloc ma, MonadPrim s m, Prim e) =>
ma s -> m (Count e)
getCountMutMem ma s
mm1
    Count e
n2 <- ma s -> m (Count e)
forall e (ma :: * -> *) (m :: * -> *) s.
(MemAlloc ma, MonadPrim s m, Prim e) =>
ma s -> m (Count e)
getCountMutMem ma s
mm2
    if Count e
n1 Count e -> Count e -> Bool
forall a. Eq a => a -> a -> Bool
/= Count e
n2
      then Bool -> m Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
      else ma s -> Off e -> ma s -> Off e -> Count e -> m Bool
forall e (ma1 :: * -> *) (ma2 :: * -> *) (m :: * -> *) s.
(Prim e, Eq e, MonadPrim s m, MemWrite ma1, MemWrite ma2) =>
ma1 s -> Off e -> ma2 s -> Off e -> Count e -> m Bool
eqOffMutMem ma s
mm1 Off e
0 ma s
mm2 Off e
0 (Count e
n1 :: Count e)
{-# INLINE eqMutMem #-}



-- | Compare two regions using the `Ord` instance. It will return `EQ` whenever both
-- regions hold exactly the same elements and `LT` or `GT` as soon as the first discovered
-- element that is less than or greater than respectfully in the first region when
-- compared to the second one. It is safe for both regions to refer to the same part of
-- memory.
--
-- @since 0.3.0
compareMem ::
     forall e mr. (Prim e, Ord e, MemRead mr)
  => mr -- ^ /memRead1/ - First region of memory
  -> mr -- ^ /memRead2/ - Second region of memory
  -> Ordering
compareMem :: mr -> mr -> Ordering
compareMem mr
m1 mr
m2
  | mr -> mr -> Bool
forall mr. MemRead mr => mr -> mr -> Bool
isSameMem mr
m1 mr
m2 = Ordering
EQ
  | Bool
otherwise = mr -> Off e -> mr -> Off e -> Count e -> Ordering
forall e mr1 mr2.
(Prim e, Ord e, MemRead mr1, MemRead mr2) =>
mr1 -> Off e -> mr2 -> Off e -> Count e -> Ordering
compareOffMem mr
m1 Off e
0 mr
m2 Off e
0 (Count e -> Count e -> Count e
forall a. Ord a => a -> a -> a
min Count e
n1 Count e
n2) Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Count e -> Count e -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Count e
n1 Count e
n2
  where
    n1 :: Count e
n1 = mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
m1 :: Count e
    n2 :: Count e
n2 = mr -> Count e
forall e mr. (MemRead mr, Prim e) => mr -> Count e
countMem mr
m2 :: Count e
{-# INLINE compareMem #-}

-- | Compare two regions using the `Ord` instance. It will return `EQ` whenever both
-- regions hold exactly the same elements and `LT` or `GT` as soon as the first discovered
-- element that is less than or greater than respectfully in the first region when
-- compared to the second one. It is safe for both regions to refer to the same part of
-- memory.
--
-- [Unsafe] When any precondition for either of the offsets @memOff1@, @memOff2@ or the
-- element count @memCount@ is violated the result is either unpredictable output or
-- failure with a segfault.
--
-- @since 0.3.0
compareOffMem ::
     (Prim e, Ord e, MemRead mr1, MemRead mr2)
  => mr1 -- ^ /memRead1/ - First region of memory
  -> Off e
  -- ^ /memOff1/ - Offset for @memRead1@ in number of elements
  --
  -- /__Precondition:__/
  --
  -- > 0 <= memOff1
  -> mr2 -- ^ /memRead2/ - Second region of memory
  -> Off e
  -- ^ /memOff2/ - Offset for @memRead1@ in number of elements
  --
  -- /__Precondition:__/
  --
  -- > 0 <= memOff2
  -> Count e
  -- ^ /memCount/ - Number of elements of type __@e@__ to compare
  --
  -- /__Preconditions:__/
  --
  -- > 0 <= memCount
  --
  -- > offToCount memOff1 + memCount < countMem memRead1
  --
  -- > offToCount memOff2 + memCount < countMem memRead2
  -> Ordering
compareOffMem :: mr1 -> Off e -> mr2 -> Off e -> Count e -> Ordering
compareOffMem mr1
m1 Off e
off1 mr2
m2 Off e
off2 Count e
count = Off e -> Ordering
loop Off e
off1
  where
    doff :: Off e
doff = Off e
off2 Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
- Off e
off1
    k :: Off e
k = Count e -> Off e
forall e. Count e -> Off e
countToOff Count e
count Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
off1
    kRem :: Off e
kRem = Count e -> Off e
forall e. Count e -> Off e
countToOff Count e
count Off e -> Off e -> Off e
forall a. Integral a => a -> a -> a
`rem` Off e
4
    k4 :: Off e
k4 = Off e
k Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
- Off e
kRem
    -- Some loop unrolling to get an extra 25% kick for smaller types
    loop :: Off e -> Ordering
loop !Off e
i
      | Off e
i Off e -> Off e -> Bool
forall a. Ord a => a -> a -> Bool
< Off e
k4 =
        let !i' :: Off e
i' = Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
1
            !i'' :: Off e
i'' = Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
2
            !i''' :: Off e
i''' = Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
3
         in e -> e -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (mr1 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr1
m1 Off e
i) (mr2 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr2
m2 (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
doff)) Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<>
            e -> e -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (mr1 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr1
m1 Off e
i') (mr2 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr2
m2 (Off e
i' Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
doff)) Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<>
            e -> e -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (mr1 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr1
m1 Off e
i'') (mr2 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr2
m2 (Off e
i'' Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
doff)) Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<>
            e -> e -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (mr1 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr1
m1 Off e
i''') (mr2 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr2
m2 (Off e
i''' Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
doff)) Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<>
            Off e -> Ordering
loop (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
4)
      | Off e
i Off e -> Off e -> Bool
forall a. Ord a => a -> a -> Bool
< Off e
k = e -> e -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (mr1 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr1
m1 Off e
i) (mr2 -> Off e -> e
forall mr e. (MemRead mr, Prim e) => mr -> Off e -> e
indexOffMem mr2
m2 (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
doff)) Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Off e -> Ordering
loop (Off e
i Off e -> Off e -> Off e
forall a. Num a => a -> a -> a
+ Off e
1)
      | Bool
otherwise = Ordering
EQ
{-# INLINE [1] compareOffMem #-}

{-# RULES
"compareOffMem/Word8" compareOffMem = compareByteOffMem
#-}