module DataSketches.Quantiles.RelativeErrorQuantile.Internal.Compactor
  ( ReqCompactor
  , mkReqCompactor
  , CompactorReturn (..)
  , compact
  , getBuffer
  , getCoin
  , getLgWeight
  , getNominalCapacity
  , getNumSections
  , merge
  , nearestEven
  ) where

import GHC.TypeLits
import Data.Bits ((.&.), (.|.), complement, countTrailingZeros, shiftL, shiftR)
import Data.Primitive.MutVar
import Data.Proxy
import Data.Semigroup (Semigroup)
import Data.Word
import DataSketches.Quantiles.RelativeErrorQuantile.Types
import System.Random.MWC (create, Variate(uniform), Gen)
import Control.Exception (assert)
import Control.Monad (when)
import Control.Monad.Primitive
import DataSketches.Quantiles.RelativeErrorQuantile.Internal.Constants
import DataSketches.Quantiles.RelativeErrorQuantile.Internal.DoubleBuffer
import DataSketches.Core.Internal.URef
import DataSketches.Core.Snapshot

data CompactorReturn s = CompactorReturn
  { CompactorReturn s -> Int
crDeltaRetItems :: {-# UNPACK #-} !Int
  , CompactorReturn s -> Int
crDeltaNominalSize :: {-# UNPACK #-} !Int
  , CompactorReturn s -> DoubleBuffer s
crDoubleBuffer :: {-# UNPACK #-} !(DoubleBuffer s)
  }

data ReqCompactor s = ReqCompactor
  -- Configuration constants
  { ReqCompactor s -> RankAccuracy
rcRankAccuracy :: !RankAccuracy
  , ReqCompactor s -> Word8
rcLgWeight :: {-# UNPACK #-} !Word8
  , ReqCompactor s -> Gen s
rcRng :: {-# UNPACK #-} !(Gen s)
  -- State
  , ReqCompactor s -> URef s Word64
rcState :: {-# UNPACK #-} !(URef s Word64)
  , ReqCompactor s -> URef s Bool
rcLastFlip :: {-# UNPACK #-} !(URef s Bool)
  , ReqCompactor s -> URef s Double
rcSectionSizeFlt :: {-# UNPACK #-} !(URef s Double)
  , ReqCompactor s -> URef s Word32
rcSectionSize :: {-# UNPACK #-} !(URef s Word32)
  , ReqCompactor s -> URef s Word8
rcNumSections :: {-# UNPACK #-} !(URef s Word8)
  , ReqCompactor s -> MutVar s (DoubleBuffer s)
rcBuffer :: {-# UNPACK #-} !(MutVar s (DoubleBuffer s))
  }

data ReqCompactorSnapshot = ReqCompactorSnapshot
    { ReqCompactorSnapshot -> RankAccuracy
snapshotCompactorRankAccuracy :: !RankAccuracy
    , ReqCompactorSnapshot -> Word64
snapshotCompactorRankAccuracyState :: !Word64
    , ReqCompactorSnapshot -> Bool
snapshotCompactorLastFlip :: !Bool
    , ReqCompactorSnapshot -> Double
snapshotCompactorSectionSizeFlt :: !Double
    , ReqCompactorSnapshot -> Word32
snapshotCompactorSectionSize :: !Word32
    , ReqCompactorSnapshot -> Word8
snapshotCompactorNumSections :: !Word8
    , ReqCompactorSnapshot -> Snapshot DoubleBuffer
snapshotCompactorBuffer :: !(Snapshot DoubleBuffer)
    } deriving (Int -> ReqCompactorSnapshot -> ShowS
[ReqCompactorSnapshot] -> ShowS
ReqCompactorSnapshot -> String
(Int -> ReqCompactorSnapshot -> ShowS)
-> (ReqCompactorSnapshot -> String)
-> ([ReqCompactorSnapshot] -> ShowS)
-> Show ReqCompactorSnapshot
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ReqCompactorSnapshot] -> ShowS
$cshowList :: [ReqCompactorSnapshot] -> ShowS
show :: ReqCompactorSnapshot -> String
$cshow :: ReqCompactorSnapshot -> String
showsPrec :: Int -> ReqCompactorSnapshot -> ShowS
$cshowsPrec :: Int -> ReqCompactorSnapshot -> ShowS
Show)

instance TakeSnapshot ReqCompactor where
  type Snapshot ReqCompactor = ReqCompactorSnapshot
  takeSnapshot :: ReqCompactor (PrimState m) -> m (Snapshot ReqCompactor)
takeSnapshot ReqCompactor{Word8
Gen (PrimState m)
MutVar (PrimState m) (DoubleBuffer (PrimState m))
URef (PrimState m) Bool
URef (PrimState m) Double
URef (PrimState m) Word8
URef (PrimState m) Word32
URef (PrimState m) Word64
RankAccuracy
rcBuffer :: MutVar (PrimState m) (DoubleBuffer (PrimState m))
rcNumSections :: URef (PrimState m) Word8
rcSectionSize :: URef (PrimState m) Word32
rcSectionSizeFlt :: URef (PrimState m) Double
rcLastFlip :: URef (PrimState m) Bool
rcState :: URef (PrimState m) Word64
rcRng :: Gen (PrimState m)
rcLgWeight :: Word8
rcRankAccuracy :: RankAccuracy
rcBuffer :: forall s. ReqCompactor s -> MutVar s (DoubleBuffer s)
rcNumSections :: forall s. ReqCompactor s -> URef s Word8
rcSectionSize :: forall s. ReqCompactor s -> URef s Word32
rcSectionSizeFlt :: forall s. ReqCompactor s -> URef s Double
rcLastFlip :: forall s. ReqCompactor s -> URef s Bool
rcState :: forall s. ReqCompactor s -> URef s Word64
rcRng :: forall s. ReqCompactor s -> Gen s
rcLgWeight :: forall s. ReqCompactor s -> Word8
rcRankAccuracy :: forall s. ReqCompactor s -> RankAccuracy
..} = RankAccuracy
-> Word64
-> Bool
-> Double
-> Word32
-> Word8
-> Snapshot DoubleBuffer
-> ReqCompactorSnapshot
ReqCompactorSnapshot RankAccuracy
rcRankAccuracy
    (Word64
 -> Bool
 -> Double
 -> Word32
 -> Word8
 -> DoubleBufferSnapshot
 -> ReqCompactorSnapshot)
-> m Word64
-> m (Bool
      -> Double
      -> Word32
      -> Word8
      -> DoubleBufferSnapshot
      -> ReqCompactorSnapshot)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> URef (PrimState m) Word64 -> m Word64
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef URef (PrimState m) Word64
rcState
    m (Bool
   -> Double
   -> Word32
   -> Word8
   -> DoubleBufferSnapshot
   -> ReqCompactorSnapshot)
-> m Bool
-> m (Double
      -> Word32 -> Word8 -> DoubleBufferSnapshot -> ReqCompactorSnapshot)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> URef (PrimState m) Bool -> m Bool
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef URef (PrimState m) Bool
rcLastFlip
    m (Double
   -> Word32 -> Word8 -> DoubleBufferSnapshot -> ReqCompactorSnapshot)
-> m Double
-> m (Word32
      -> Word8 -> DoubleBufferSnapshot -> ReqCompactorSnapshot)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> URef (PrimState m) Double -> m Double
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef URef (PrimState m) Double
rcSectionSizeFlt
    m (Word32 -> Word8 -> DoubleBufferSnapshot -> ReqCompactorSnapshot)
-> m Word32
-> m (Word8 -> DoubleBufferSnapshot -> ReqCompactorSnapshot)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> URef (PrimState m) Word32 -> m Word32
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef URef (PrimState m) Word32
rcSectionSize
    m (Word8 -> DoubleBufferSnapshot -> ReqCompactorSnapshot)
-> m Word8 -> m (DoubleBufferSnapshot -> ReqCompactorSnapshot)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> URef (PrimState m) Word8 -> m Word8
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef URef (PrimState m) Word8
rcNumSections
    m (DoubleBufferSnapshot -> ReqCompactorSnapshot)
-> m DoubleBufferSnapshot -> m ReqCompactorSnapshot
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (MutVar (PrimState m) (DoubleBuffer (PrimState m))
-> m (DoubleBuffer (PrimState m))
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar MutVar (PrimState m) (DoubleBuffer (PrimState m))
rcBuffer m (DoubleBuffer (PrimState m))
-> (DoubleBuffer (PrimState m) -> m DoubleBufferSnapshot)
-> m DoubleBufferSnapshot
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DoubleBuffer (PrimState m) -> m DoubleBufferSnapshot
forall (a :: * -> *) (m :: * -> *).
(TakeSnapshot a, PrimMonad m) =>
a (PrimState m) -> m (Snapshot a)
takeSnapshot)


mkReqCompactor
  :: PrimMonad m
  => Gen (PrimState m)
  -> Word8
  -> RankAccuracy
  -> Word32
  -> m (ReqCompactor (PrimState m))
mkReqCompactor :: Gen (PrimState m)
-> Word8
-> RankAccuracy
-> Word32
-> m (ReqCompactor (PrimState m))
mkReqCompactor Gen (PrimState m)
g Word8
lgWeight RankAccuracy
rankAccuracy Word32
sectionSize = do
  let nominalCapacity :: Int
nominalCapacity = Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Int) -> Word32 -> Int
forall a b. (a -> b) -> a -> b
$ Word32
forall a. Num a => a
nomCapMulti Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
forall a. Num a => a
initNumberOfSections Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
sectionSize
  DoubleBuffer (PrimState m)
buff <- Int -> Int -> Bool -> m (DoubleBuffer (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
Int -> Int -> Bool -> m (DoubleBuffer (PrimState m))
mkBuffer (Int
nominalCapacity Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2) Int
nominalCapacity (RankAccuracy
rankAccuracy RankAccuracy -> RankAccuracy -> Bool
forall a. Eq a => a -> a -> Bool
== RankAccuracy
HighRanksAreAccurate)
  RankAccuracy
-> Word8
-> Gen (PrimState m)
-> URef (PrimState m) Word64
-> URef (PrimState m) Bool
-> URef (PrimState m) Double
-> URef (PrimState m) Word32
-> URef (PrimState m) Word8
-> MutVar (PrimState m) (DoubleBuffer (PrimState m))
-> ReqCompactor (PrimState m)
forall s.
RankAccuracy
-> Word8
-> Gen s
-> URef s Word64
-> URef s Bool
-> URef s Double
-> URef s Word32
-> URef s Word8
-> MutVar s (DoubleBuffer s)
-> ReqCompactor s
ReqCompactor RankAccuracy
rankAccuracy Word8
lgWeight Gen (PrimState m)
g
    (URef (PrimState m) Word64
 -> URef (PrimState m) Bool
 -> URef (PrimState m) Double
 -> URef (PrimState m) Word32
 -> URef (PrimState m) Word8
 -> MutVar (PrimState m) (DoubleBuffer (PrimState m))
 -> ReqCompactor (PrimState m))
-> m (URef (PrimState m) Word64)
-> m (URef (PrimState m) Bool
      -> URef (PrimState m) Double
      -> URef (PrimState m) Word32
      -> URef (PrimState m) Word8
      -> MutVar (PrimState m) (DoubleBuffer (PrimState m))
      -> ReqCompactor (PrimState m))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word64 -> m (URef (PrimState m) Word64)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
a -> m (URef (PrimState m) a)
newURef Word64
0
    m (URef (PrimState m) Bool
   -> URef (PrimState m) Double
   -> URef (PrimState m) Word32
   -> URef (PrimState m) Word8
   -> MutVar (PrimState m) (DoubleBuffer (PrimState m))
   -> ReqCompactor (PrimState m))
-> m (URef (PrimState m) Bool)
-> m (URef (PrimState m) Double
      -> URef (PrimState m) Word32
      -> URef (PrimState m) Word8
      -> MutVar (PrimState m) (DoubleBuffer (PrimState m))
      -> ReqCompactor (PrimState m))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Bool -> m (URef (PrimState m) Bool)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
a -> m (URef (PrimState m) a)
newURef Bool
False
    m (URef (PrimState m) Double
   -> URef (PrimState m) Word32
   -> URef (PrimState m) Word8
   -> MutVar (PrimState m) (DoubleBuffer (PrimState m))
   -> ReqCompactor (PrimState m))
-> m (URef (PrimState m) Double)
-> m (URef (PrimState m) Word32
      -> URef (PrimState m) Word8
      -> MutVar (PrimState m) (DoubleBuffer (PrimState m))
      -> ReqCompactor (PrimState m))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Double -> m (URef (PrimState m) Double)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
a -> m (URef (PrimState m) a)
newURef (Word32 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
sectionSize)
    m (URef (PrimState m) Word32
   -> URef (PrimState m) Word8
   -> MutVar (PrimState m) (DoubleBuffer (PrimState m))
   -> ReqCompactor (PrimState m))
-> m (URef (PrimState m) Word32)
-> m (URef (PrimState m) Word8
      -> MutVar (PrimState m) (DoubleBuffer (PrimState m))
      -> ReqCompactor (PrimState m))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Word32 -> m (URef (PrimState m) Word32)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
a -> m (URef (PrimState m) a)
newURef Word32
sectionSize
    m (URef (PrimState m) Word8
   -> MutVar (PrimState m) (DoubleBuffer (PrimState m))
   -> ReqCompactor (PrimState m))
-> m (URef (PrimState m) Word8)
-> m (MutVar (PrimState m) (DoubleBuffer (PrimState m))
      -> ReqCompactor (PrimState m))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Word8 -> m (URef (PrimState m) Word8)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
a -> m (URef (PrimState m) a)
newURef Word8
forall a. Num a => a
initNumberOfSections
    m (MutVar (PrimState m) (DoubleBuffer (PrimState m))
   -> ReqCompactor (PrimState m))
-> m (MutVar (PrimState m) (DoubleBuffer (PrimState m)))
-> m (ReqCompactor (PrimState m))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> DoubleBuffer (PrimState m)
-> m (MutVar (PrimState m) (DoubleBuffer (PrimState m)))
forall (m :: * -> *) a.
PrimMonad m =>
a -> m (MutVar (PrimState m) a)
newMutVar DoubleBuffer (PrimState m)
buff

nomCapMult :: Num a => a
nomCapMult :: a
nomCapMult = a
2

toInt :: Integral a => a -> Int
toInt :: a -> Int
toInt = a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral

compact :: (PrimMonad m) => ReqCompactor (PrimState m) -> m (CompactorReturn (PrimState m))
compact :: ReqCompactor (PrimState m) -> m (CompactorReturn (PrimState m))
compact ReqCompactor (PrimState m)
this = do
  Int
startBuffSize <- DoubleBuffer (PrimState m) -> m Int
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> m Int
getCount (DoubleBuffer (PrimState m) -> m Int)
-> m (DoubleBuffer (PrimState m)) -> m Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
getBuffer ReqCompactor (PrimState m)
this
  Int
startNominalCapacity <- ReqCompactor (PrimState m) -> m Int
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m Int
getNominalCapacity ReqCompactor (PrimState m)
this
  Word8
numSections <- URef (PrimState m) Word8 -> m Word8
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word8 -> m Word8)
-> URef (PrimState m) Word8 -> m Word8
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Word8
forall s. ReqCompactor s -> URef s Word8
rcNumSections ReqCompactor (PrimState m)
this
  Word32
sectionSize <- URef (PrimState m) Word32 -> m Word32
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word32 -> m Word32)
-> URef (PrimState m) Word32 -> m Word32
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Word32
forall s. ReqCompactor s -> URef s Word32
rcSectionSize ReqCompactor (PrimState m)
this
  Word64
state <- URef (PrimState m) Word64 -> m Word64
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word64 -> m Word64)
-> URef (PrimState m) Word64 -> m Word64
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Word64
forall s. ReqCompactor s -> URef s Word64
rcState ReqCompactor (PrimState m)
this
  let trailingOnes :: Int
trailingOnes = Int -> Int
forall a. Enum a => a -> a
succ (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Word64 -> Int
forall b. FiniteBits b => b -> Int
countTrailingZeros (Word64 -> Int) -> Word64 -> Int
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64
forall a. Bits a => a -> a
complement Word64
state
      sectionsToCompact :: Int
sectionsToCompact = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
trailingOnes (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
numSections
  (Int
compactionStart, Int
compactionEnd) <- ReqCompactor (PrimState m) -> Int -> m (Int, Int)
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> Int -> m (Int, Int)
computeCompactionRange ReqCompactor (PrimState m)
this Int
sectionsToCompact
  -- TODO, this fails in GHCi but not in tests?
  Bool
-> m (CompactorReturn (PrimState m))
-> m (CompactorReturn (PrimState m))
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
compactionEnd Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
compactionStart Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2) (m (CompactorReturn (PrimState m))
 -> m (CompactorReturn (PrimState m)))
-> m (CompactorReturn (PrimState m))
-> m (CompactorReturn (PrimState m))
forall a b. (a -> b) -> a -> b
$ do
    Bool
coin <- if Word64
state Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
1 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
1
      then (Bool -> Bool) -> m Bool -> m Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Bool -> Bool
not (m Bool -> m Bool) -> m Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ URef (PrimState m) Bool -> m Bool
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Bool -> m Bool)
-> URef (PrimState m) Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Bool
forall s. ReqCompactor s -> URef s Bool
rcLastFlip ReqCompactor (PrimState m)
this
      else ReqCompactor (PrimState m) -> m Bool
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m Bool
flipCoin ReqCompactor (PrimState m)
this
    URef (PrimState m) Bool -> Bool -> m ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> a -> m ()
writeURef (ReqCompactor (PrimState m) -> URef (PrimState m) Bool
forall s. ReqCompactor s -> URef s Bool
rcLastFlip ReqCompactor (PrimState m)
this) Bool
coin
    DoubleBuffer (PrimState m)
buff <- ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
getBuffer ReqCompactor (PrimState m)
this
    DoubleBuffer (PrimState m)
promote <- DoubleBuffer (PrimState m)
-> Int -> Int -> Bool -> m (DoubleBuffer (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m)
-> Int -> Int -> Bool -> m (DoubleBuffer (PrimState m))
getEvensOrOdds DoubleBuffer (PrimState m)
buff Int
compactionStart Int
compactionEnd Bool
coin
    DoubleBuffer (PrimState m) -> Int -> m ()
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> Int -> m ()
trimCount DoubleBuffer (PrimState m)
buff (Int -> m ()) -> Int -> m ()
forall a b. (a -> b) -> a -> b
$ Int
startBuffSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int
compactionEnd Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
compactionStart)
    URef (PrimState m) Word64 -> (Word64 -> Word64) -> m ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> (a -> a) -> m ()
modifyURef (ReqCompactor (PrimState m) -> URef (PrimState m) Word64
forall s. ReqCompactor s -> URef s Word64
rcState ReqCompactor (PrimState m)
this) (Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1)
    ReqCompactor (PrimState m) -> m Bool
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m Bool
ensureEnoughSections ReqCompactor (PrimState m)
this
    Int
endBuffSize <- DoubleBuffer (PrimState m) -> m Int
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> m Int
getCount DoubleBuffer (PrimState m)
buff
    Int
promoteBuffSize <- DoubleBuffer (PrimState m) -> m Int
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> m Int
getCount DoubleBuffer (PrimState m)
promote
    Int
endNominalCapacity <- ReqCompactor (PrimState m) -> m Int
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m Int
getNominalCapacity ReqCompactor (PrimState m)
this
    CompactorReturn (PrimState m) -> m (CompactorReturn (PrimState m))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CompactorReturn (PrimState m)
 -> m (CompactorReturn (PrimState m)))
-> CompactorReturn (PrimState m)
-> m (CompactorReturn (PrimState m))
forall a b. (a -> b) -> a -> b
$ CompactorReturn :: forall s. Int -> Int -> DoubleBuffer s -> CompactorReturn s
CompactorReturn
      { crDeltaRetItems :: Int
crDeltaRetItems = Int
endBuffSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
startBuffSize Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
promoteBuffSize
      , crDeltaNominalSize :: Int
crDeltaNominalSize = Int
endNominalCapacity Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
startNominalCapacity
      , crDoubleBuffer :: DoubleBuffer (PrimState m)
crDoubleBuffer = DoubleBuffer (PrimState m)
promote
      }

getLgWeight :: ReqCompactor s -> Word8
getLgWeight :: ReqCompactor s -> Word8
getLgWeight = ReqCompactor s -> Word8
forall s. ReqCompactor s -> Word8
rcLgWeight

getBuffer :: PrimMonad m => ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
getBuffer :: ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
getBuffer = MutVar (PrimState m) (DoubleBuffer (PrimState m))
-> m (DoubleBuffer (PrimState m))
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar (MutVar (PrimState m) (DoubleBuffer (PrimState m))
 -> m (DoubleBuffer (PrimState m)))
-> (ReqCompactor (PrimState m)
    -> MutVar (PrimState m) (DoubleBuffer (PrimState m)))
-> ReqCompactor (PrimState m)
-> m (DoubleBuffer (PrimState m))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReqCompactor (PrimState m)
-> MutVar (PrimState m) (DoubleBuffer (PrimState m))
forall s. ReqCompactor s -> MutVar s (DoubleBuffer s)
rcBuffer

flipCoin :: (PrimMonad m) => ReqCompactor (PrimState m) -> m Bool
flipCoin :: ReqCompactor (PrimState m) -> m Bool
flipCoin = Gen (PrimState m) -> m Bool
forall a (m :: * -> *).
(Variate a, PrimMonad m) =>
Gen (PrimState m) -> m a
uniform (Gen (PrimState m) -> m Bool)
-> (ReqCompactor (PrimState m) -> Gen (PrimState m))
-> ReqCompactor (PrimState m)
-> m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReqCompactor (PrimState m) -> Gen (PrimState m)
forall s. ReqCompactor s -> Gen s
rcRng

getCoin :: PrimMonad m => ReqCompactor (PrimState m) -> m Bool
getCoin :: ReqCompactor (PrimState m) -> m Bool
getCoin = URef (PrimState m) Bool -> m Bool
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Bool -> m Bool)
-> (ReqCompactor (PrimState m) -> URef (PrimState m) Bool)
-> ReqCompactor (PrimState m)
-> m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReqCompactor (PrimState m) -> URef (PrimState m) Bool
forall s. ReqCompactor s -> URef s Bool
rcLastFlip

getNominalCapacity :: PrimMonad m => ReqCompactor (PrimState m) -> m Int
getNominalCapacity :: ReqCompactor (PrimState m) -> m Int
getNominalCapacity ReqCompactor (PrimState m)
compactor = do
  Word8
numSections <- URef (PrimState m) Word8 -> m Word8
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word8 -> m Word8)
-> URef (PrimState m) Word8 -> m Word8
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Word8
forall s. ReqCompactor s -> URef s Word8
rcNumSections ReqCompactor (PrimState m)
compactor
  Word32
sectionSize <- URef (PrimState m) Word32 -> m Word32
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word32 -> m Word32)
-> URef (PrimState m) Word32 -> m Word32
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Word32
forall s. ReqCompactor s -> URef s Word32
rcSectionSize ReqCompactor (PrimState m)
compactor
  Int -> m Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int -> m Int) -> Int -> m Int
forall a b. (a -> b) -> a -> b
$ Int
forall a. Num a => a
nomCapMult Int -> Int -> Int
forall a. Num a => a -> a -> a
* Word8 -> Int
forall a. Integral a => a -> Int
toInt Word8
numSections Int -> Int -> Int
forall a. Num a => a -> a -> a
* Word32 -> Int
forall a. Integral a => a -> Int
toInt Word32
sectionSize

getNumSections :: PrimMonad m => ReqCompactor (PrimState m) -> m Word8
getNumSections :: ReqCompactor (PrimState m) -> m Word8
getNumSections = URef (PrimState m) Word8 -> m Word8
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word8 -> m Word8)
-> (ReqCompactor (PrimState m) -> URef (PrimState m) Word8)
-> ReqCompactor (PrimState m)
-> m Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReqCompactor (PrimState m) -> URef (PrimState m) Word8
forall s. ReqCompactor s -> URef s Word8
rcNumSections

getSectionSizeFlt :: PrimMonad m => ReqCompactor (PrimState m) -> m Double
getSectionSizeFlt :: ReqCompactor (PrimState m) -> m Double
getSectionSizeFlt = URef (PrimState m) Double -> m Double
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Double -> m Double)
-> (ReqCompactor (PrimState m) -> URef (PrimState m) Double)
-> ReqCompactor (PrimState m)
-> m Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReqCompactor (PrimState m) -> URef (PrimState m) Double
forall s. ReqCompactor s -> URef s Double
rcSectionSizeFlt

getState :: PrimMonad m => ReqCompactor (PrimState m) -> m Word64
getState :: ReqCompactor (PrimState m) -> m Word64
getState = URef (PrimState m) Word64 -> m Word64
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word64 -> m Word64)
-> (ReqCompactor (PrimState m) -> URef (PrimState m) Word64)
-> ReqCompactor (PrimState m)
-> m Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReqCompactor (PrimState m) -> URef (PrimState m) Word64
forall s. ReqCompactor s -> URef s Word64
rcState

-- | Merge the other given compactor into this one. They both must have the
-- same @lgWeight@
merge
  :: (PrimMonad m, s ~ PrimState m)
  => ReqCompactor (PrimState m)
  -- ^ The compactor to merge into
  -> ReqCompactor (PrimState m)
  -- ^ The compactor to merge from 
  -> m (ReqCompactor s)
merge :: ReqCompactor (PrimState m)
-> ReqCompactor (PrimState m) -> m (ReqCompactor s)
merge ReqCompactor (PrimState m)
this ReqCompactor (PrimState m)
otherCompactor = Bool -> m (ReqCompactor s) -> m (ReqCompactor s)
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (ReqCompactor s -> Word8
forall s. ReqCompactor s -> Word8
rcLgWeight ReqCompactor s
ReqCompactor (PrimState m)
this Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== ReqCompactor s -> Word8
forall s. ReqCompactor s -> Word8
rcLgWeight ReqCompactor s
ReqCompactor (PrimState m)
otherCompactor) (m (ReqCompactor s) -> m (ReqCompactor s))
-> m (ReqCompactor s) -> m (ReqCompactor s)
forall a b. (a -> b) -> a -> b
$ do
  Word64
otherState <- URef (PrimState m) Word64 -> m Word64
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word64 -> m Word64)
-> URef (PrimState m) Word64 -> m Word64
forall a b. (a -> b) -> a -> b
$ ReqCompactor s -> URef s Word64
forall s. ReqCompactor s -> URef s Word64
rcState ReqCompactor s
ReqCompactor (PrimState m)
otherCompactor
  URef (PrimState m) Word64 -> (Word64 -> Word64) -> m ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> (a -> a) -> m ()
modifyURef (ReqCompactor s -> URef s Word64
forall s. ReqCompactor s -> URef s Word64
rcState ReqCompactor s
ReqCompactor (PrimState m)
this) (Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64
otherState)
  m ()
ensureMaxSections

  DoubleBuffer s
buff <- ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
getBuffer ReqCompactor (PrimState m)
this
  DoubleBuffer (PrimState m) -> m ()
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> m ()
sort DoubleBuffer s
DoubleBuffer (PrimState m)
buff

  DoubleBuffer s
otherBuff <- ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
getBuffer ReqCompactor (PrimState m)
otherCompactor
  DoubleBuffer (PrimState m) -> m ()
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> m ()
sort DoubleBuffer s
DoubleBuffer (PrimState m)
otherBuff

  Bool
otherBuffIsBigger <- Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
(>) (Int -> Int -> Bool) -> m Int -> m (Int -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DoubleBuffer (PrimState m) -> m Int
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> m Int
getCount DoubleBuffer s
DoubleBuffer (PrimState m)
otherBuff m (Int -> Bool) -> m Int -> m Bool
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> DoubleBuffer (PrimState m) -> m Int
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> m Int
getCount DoubleBuffer s
DoubleBuffer (PrimState m)
buff
  ()
finalBuff <- if Bool
otherBuffIsBigger
     then do
        DoubleBuffer s
otherBuff' <- DoubleBuffer (PrimState m) -> m (DoubleBuffer (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> m (DoubleBuffer (PrimState m))
copyBuffer DoubleBuffer s
DoubleBuffer (PrimState m)
otherBuff
        DoubleBuffer (PrimState m) -> DoubleBuffer (PrimState m) -> m ()
forall (m :: * -> *).
(PrimMonad m, ?callStack::CallStack) =>
DoubleBuffer (PrimState m) -> DoubleBuffer (PrimState m) -> m ()
mergeSortIn DoubleBuffer s
DoubleBuffer (PrimState m)
otherBuff' DoubleBuffer s
DoubleBuffer (PrimState m)
buff
        MutVar (PrimState m) (DoubleBuffer s) -> DoubleBuffer s -> m ()
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> a -> m ()
writeMutVar (ReqCompactor s -> MutVar s (DoubleBuffer s)
forall s. ReqCompactor s -> MutVar s (DoubleBuffer s)
rcBuffer ReqCompactor s
ReqCompactor (PrimState m)
this) DoubleBuffer s
otherBuff'
     else DoubleBuffer (PrimState m) -> DoubleBuffer (PrimState m) -> m ()
forall (m :: * -> *).
(PrimMonad m, ?callStack::CallStack) =>
DoubleBuffer (PrimState m) -> DoubleBuffer (PrimState m) -> m ()
mergeSortIn DoubleBuffer s
DoubleBuffer (PrimState m)
buff DoubleBuffer s
DoubleBuffer (PrimState m)
otherBuff
  ReqCompactor s -> m (ReqCompactor s)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ReqCompactor s
ReqCompactor (PrimState m)
this
  where
    ensureMaxSections :: m ()
ensureMaxSections = do
      Bool
adjusted <- ReqCompactor (PrimState m) -> m Bool
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m Bool
ensureEnoughSections ReqCompactor (PrimState m)
this
      -- loop until no adjustments can be made
      Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
adjusted m ()
ensureMaxSections

-- | Adjust the sectionSize and numSections if possible.
ensureEnoughSections
  :: PrimMonad m
  => ReqCompactor (PrimState m)
  -> m Bool
  -- ^ 'True' if the SectionSize and NumSections were adjusted.
ensureEnoughSections :: ReqCompactor (PrimState m) -> m Bool
ensureEnoughSections ReqCompactor (PrimState m)
compactor = do
  Double
sectionSizeFlt <- URef (PrimState m) Double -> m Double
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Double -> m Double)
-> URef (PrimState m) Double -> m Double
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Double
forall s. ReqCompactor s -> URef s Double
rcSectionSizeFlt ReqCompactor (PrimState m)
compactor
  let szf :: Double
szf = Double
sectionSizeFlt Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
sqrt2
      ne :: Int
ne = Double -> Int
nearestEven Double
szf
  Word64
state <- URef (PrimState m) Word64 -> m Word64
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word64 -> m Word64)
-> URef (PrimState m) Word64 -> m Word64
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Word64
forall s. ReqCompactor s -> URef s Word64
rcState ReqCompactor (PrimState m)
compactor
  Word8
numSections <- URef (PrimState m) Word8 -> m Word8
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word8 -> m Word8)
-> URef (PrimState m) Word8 -> m Word8
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Word8
forall s. ReqCompactor s -> URef s Word8
rcNumSections ReqCompactor (PrimState m)
compactor
  Word32
sectionSize <- URef (PrimState m) Word32 -> m Word32
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word32 -> m Word32)
-> URef (PrimState m) Word32 -> m Word32
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Word32
forall s. ReqCompactor s -> URef s Word32
rcSectionSize ReqCompactor (PrimState m)
compactor
  if Word64
state Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
>= (Word64
1 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftL` Word8 -> Int
forall a. Integral a => a -> Int
toInt (Word8
numSections Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
1))
     Bool -> Bool -> Bool
&& Word32
sectionSize Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32
forall a. Num a => a
minK
     Bool -> Bool -> Bool
&& Int
ne Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
forall a. Num a => a
minK
     then do
       URef (PrimState m) Double -> Double -> m ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> a -> m ()
writeURef (ReqCompactor (PrimState m) -> URef (PrimState m) Double
forall s. ReqCompactor s -> URef s Double
rcSectionSizeFlt ReqCompactor (PrimState m)
compactor) Double
szf
       URef (PrimState m) Word32 -> Word32 -> m ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> a -> m ()
writeURef (ReqCompactor (PrimState m) -> URef (PrimState m) Word32
forall s. ReqCompactor s -> URef s Word32
rcSectionSize ReqCompactor (PrimState m)
compactor) (Word32 -> m ()) -> Word32 -> m ()
forall a b. (a -> b) -> a -> b
$ Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ne
       URef (PrimState m) Word8 -> (Word8 -> Word8) -> m ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> (a -> a) -> m ()
modifyURef (ReqCompactor (PrimState m) -> URef (PrimState m) Word8
forall s. ReqCompactor s -> URef s Word8
rcNumSections ReqCompactor (PrimState m)
compactor) (Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftL` Int
1)
       DoubleBuffer (PrimState m)
buf <- ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
getBuffer ReqCompactor (PrimState m)
compactor
       Int
nomCapacity <- ReqCompactor (PrimState m) -> m Int
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m Int
getNominalCapacity ReqCompactor (PrimState m)
compactor
       DoubleBuffer (PrimState m) -> Int -> m ()
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> Int -> m ()
ensureCapacity DoubleBuffer (PrimState m)
buf (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
nomCapacity)
       Bool -> m Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
     else Bool -> m Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False

-- | Computes the start and end indices of the compacted region
computeCompactionRange
  :: PrimMonad m
  => ReqCompactor (PrimState m)
  -> Int
  -- ^ secsToCompact the number of contiguous sections to compact
  -> m (Int, Int)
-- ^ the start and end indices of the compacted region in compact form
computeCompactionRange :: ReqCompactor (PrimState m) -> Int -> m (Int, Int)
computeCompactionRange ReqCompactor (PrimState m)
this Int
secsToCompact = do
  Int
buffSize <- DoubleBuffer (PrimState m) -> m Int
forall (m :: * -> *).
PrimMonad m =>
DoubleBuffer (PrimState m) -> m Int
getCount (DoubleBuffer (PrimState m) -> m Int)
-> m (DoubleBuffer (PrimState m)) -> m Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m (DoubleBuffer (PrimState m))
getBuffer ReqCompactor (PrimState m)
this
  Int
nominalCapacity <- ReqCompactor (PrimState m) -> m Int
forall (m :: * -> *).
PrimMonad m =>
ReqCompactor (PrimState m) -> m Int
getNominalCapacity ReqCompactor (PrimState m)
this
  Word8
numSections <- URef (PrimState m) Word8 -> m Word8
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word8 -> m Word8)
-> URef (PrimState m) Word8 -> m Word8
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Word8
forall s. ReqCompactor s -> URef s Word8
rcNumSections ReqCompactor (PrimState m)
this
  Word32
sectionSize <- URef (PrimState m) Word32 -> m Word32
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
URef (PrimState m) a -> m a
readURef (URef (PrimState m) Word32 -> m Word32)
-> URef (PrimState m) Word32 -> m Word32
forall a b. (a -> b) -> a -> b
$ ReqCompactor (PrimState m) -> URef (PrimState m) Word32
forall s. ReqCompactor s -> URef s Word32
rcSectionSize ReqCompactor (PrimState m)
this
  let nonCompact :: Int
nonCompact = (Int
nominalCapacity Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
numSections Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
secsToCompact) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
sectionSize
      nonCompact' :: Int
nonCompact' = if (Int
buffSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
nonCompact) Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 then Int
nonCompact Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 else Int
nonCompact
  (Int, Int) -> m (Int, Int)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Int, Int) -> m (Int, Int)) -> (Int, Int) -> m (Int, Int)
forall a b. (a -> b) -> a -> b
$ case ReqCompactor (PrimState m) -> RankAccuracy
forall s. ReqCompactor s -> RankAccuracy
rcRankAccuracy ReqCompactor (PrimState m)
this of
    RankAccuracy
HighRanksAreAccurate -> (Int
0, Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int
buffSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
nonCompact')
    RankAccuracy
LowRanksAreAccurate -> (Int
nonCompact', Int
buffSize)

-- | Returns the nearest even integer to the given value. Also used by test.
nearestEven
  :: Double
  -- ^ the given value
  -> Int
  -- ^ the nearest even integer to the given value.
nearestEven :: Double -> Int
nearestEven Double
x = Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round (Double
x Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2) Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftL` Int
1