{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MagicHash #-}

module Cardano.Prelude.HeapWords
  ( HeapWords(..)
  , heapSizeMb
  , heapSizeKb
  , heapWords0
  , heapWords1
  , heapWords2
  , heapWords3
  , heapWords4
  , heapWords5
  , heapWords6
  , heapWords7
  , heapWords8
  , heapWords9
  , heapWords10
  , heapWords11
  , heapWords12
  , heapWords13
  , heapWordsUArray
  , heapWordsUVector
  , heapWordsUnpacked
  )
where

import Cardano.Prelude.Base

import qualified Data.Array.Unboxed as A
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Short as BSS
import qualified Data.IntMap.Strict as IntMap
import qualified Data.IntSet as IntSet
import Data.Ix
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import Data.Time (Day, UTCTime)
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as V.U
import GHC.Integer.GMP.Internals (BigNat(BN#), Integer(S#, Jn#, Jp#))
import GHC.Natural (Natural(NatS#, NatJ#))
import GHC.Prim (ByteArray#, sizeofByteArray#)
import GHC.Types (Int(I#))

--------------------------------------------------------------------------------
-- HeapWords class and instances
--------------------------------------------------------------------------------

-- | These functions assume a 64-bit architecture
heapSizeMb, heapSizeKb :: Int -> Int
heapSizeMb :: Int -> Int
heapSizeMb Int
w = Int
wordSize Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
w Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` (Int
1024 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
1024)
heapSizeKb :: Int -> Int
heapSizeKb Int
w = Int
wordSize Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
w Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
1024

wordSize :: Int
wordSize :: Int
wordSize = Int
8

-- | Size in the heap of values, in words (to get the size in bytes multiply by
--   4 on a 32-bit machine or 8 on a 64-bit machine)
class HeapWords a where
  heapWords :: a -> Int

heapWords0 :: Int
heapWords1 :: HeapWords a => a -> Int
heapWords2 :: (HeapWords a1, HeapWords a) => a -> a1 -> Int
heapWords3 :: (HeapWords a2, HeapWords a1, HeapWords a) => a -> a1 -> a2 -> Int
heapWords4
  :: (HeapWords a3, HeapWords a2, HeapWords a1, HeapWords a)
  => a
  -> a1
  -> a2
  -> a3
  -> Int
heapWords5
  :: (HeapWords a4, HeapWords a3, HeapWords a2, HeapWords a1, HeapWords a)
  => a
  -> a1
  -> a2
  -> a3
  -> a4
  -> Int
heapWords6
  :: ( HeapWords a5
     , HeapWords a4
     , HeapWords a3
     , HeapWords a2
     , HeapWords a1
     , HeapWords a
     )
  => a
  -> a1
  -> a2
  -> a3
  -> a4
  -> a5
  -> Int
heapWords7
  :: ( HeapWords a6
     , HeapWords a5
     , HeapWords a4
     , HeapWords a3
     , HeapWords a2
     , HeapWords a1
     , HeapWords a
     )
  => a
  -> a1
  -> a2
  -> a3
  -> a4
  -> a5
  -> a6
  -> Int
heapWords8
  :: ( HeapWords a7
     , HeapWords a6
     , HeapWords a5
     , HeapWords a4
     , HeapWords a3
     , HeapWords a2
     , HeapWords a1
     , HeapWords a
     )
  => a
  -> a1
  -> a2
  -> a3
  -> a4
  -> a5
  -> a6
  -> a7
  -> Int
heapWords9
  :: ( HeapWords a8
     , HeapWords a7
     , HeapWords a6
     , HeapWords a5
     , HeapWords a4
     , HeapWords a3
     , HeapWords a2
     , HeapWords a1
     , HeapWords a
     )
  => a
  -> a1
  -> a2
  -> a3
  -> a4
  -> a5
  -> a6
  -> a7
  -> a8
  -> Int
heapWords10
  :: ( HeapWords a9
     , HeapWords a8
     , HeapWords a7
     , HeapWords a6
     , HeapWords a5
     , HeapWords a4
     , HeapWords a3
     , HeapWords a2
     , HeapWords a1
     , HeapWords a
     )
  => a
  -> a1
  -> a2
  -> a3
  -> a4
  -> a5
  -> a6
  -> a7
  -> a8
  -> a9
  -> Int
heapWords11
  :: ( HeapWords a10
     , HeapWords a9
     , HeapWords a8
     , HeapWords a7
     , HeapWords a6
     , HeapWords a5
     , HeapWords a4
     , HeapWords a3
     , HeapWords a2
     , HeapWords a1
     , HeapWords a
     )
  => a
  -> a1
  -> a2
  -> a3
  -> a4
  -> a5
  -> a6
  -> a7
  -> a8
  -> a9
  -> a10
  -> Int
heapWords12
  :: ( HeapWords a11
     , HeapWords a10
     , HeapWords a9
     , HeapWords a8
     , HeapWords a7
     , HeapWords a6
     , HeapWords a5
     , HeapWords a4
     , HeapWords a3
     , HeapWords a2
     , HeapWords a1
     , HeapWords a
     )
  => a
  -> a1
  -> a2
  -> a3
  -> a4
  -> a5
  -> a6
  -> a7
  -> a8
  -> a9
  -> a10
  -> a11
  -> Int
heapWords13
  :: ( HeapWords a12
     , HeapWords a11
     , HeapWords a10
     , HeapWords a9
     , HeapWords a8
     , HeapWords a7
     , HeapWords a6
     , HeapWords a5
     , HeapWords a4
     , HeapWords a3
     , HeapWords a2
     , HeapWords a1
     , HeapWords a
     )
  => a
  -> a1
  -> a2
  -> a3
  -> a4
  -> a5
  -> a6
  -> a7
  -> a8
  -> a9
  -> a10
  -> a11
  -> a12
  -> Int


heapWords0 :: Int
heapWords0 = Int
0
heapWords1 :: a -> Int
heapWords1 a
a = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a
heapWords2 :: a -> a1 -> Int
heapWords2 a
a a1
b = Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b
heapWords3 :: a -> a1 -> a2 -> Int
heapWords3 a
a a1
b a2
c = Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c
heapWords4 :: a -> a1 -> a2 -> a3 -> Int
heapWords4 a
a a1
b a2
c a3
d = Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a3 -> Int
forall a. HeapWords a => a -> Int
heapWords a3
d
heapWords5 :: a -> a1 -> a2 -> a3 -> a4 -> Int
heapWords5 a
a a1
b a2
c a3
d a4
e =
  Int
6 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a3 -> Int
forall a. HeapWords a => a -> Int
heapWords a3
d Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a4 -> Int
forall a. HeapWords a => a -> Int
heapWords a4
e
heapWords6 :: a -> a1 -> a2 -> a3 -> a4 -> a5 -> Int
heapWords6 a
a a1
b a2
c a3
d a4
e a5
f =
  Int
7
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a3 -> Int
forall a. HeapWords a => a -> Int
heapWords a3
d
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a4 -> Int
forall a. HeapWords a => a -> Int
heapWords a4
e
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a5 -> Int
forall a. HeapWords a => a -> Int
heapWords a5
f
heapWords7 :: a -> a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> Int
heapWords7 a
a a1
b a2
c a3
d a4
e a5
f a6
g =
  Int
8
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a3 -> Int
forall a. HeapWords a => a -> Int
heapWords a3
d
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a4 -> Int
forall a. HeapWords a => a -> Int
heapWords a4
e
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a5 -> Int
forall a. HeapWords a => a -> Int
heapWords a5
f
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a6 -> Int
forall a. HeapWords a => a -> Int
heapWords a6
g
heapWords8 :: a -> a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> Int
heapWords8 a
a a1
b a2
c a3
d a4
e a5
f a6
g a7
h =
  Int
9
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a3 -> Int
forall a. HeapWords a => a -> Int
heapWords a3
d
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a4 -> Int
forall a. HeapWords a => a -> Int
heapWords a4
e
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a5 -> Int
forall a. HeapWords a => a -> Int
heapWords a5
f
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a6 -> Int
forall a. HeapWords a => a -> Int
heapWords a6
g
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a7 -> Int
forall a. HeapWords a => a -> Int
heapWords a7
h
heapWords9 :: a -> a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> Int
heapWords9 a
a a1
b a2
c a3
d a4
e a5
f a6
g a7
h a8
i =
  Int
10
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a3 -> Int
forall a. HeapWords a => a -> Int
heapWords a3
d
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a4 -> Int
forall a. HeapWords a => a -> Int
heapWords a4
e
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a5 -> Int
forall a. HeapWords a => a -> Int
heapWords a5
f
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a6 -> Int
forall a. HeapWords a => a -> Int
heapWords a6
g
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a7 -> Int
forall a. HeapWords a => a -> Int
heapWords a7
h
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a8 -> Int
forall a. HeapWords a => a -> Int
heapWords a8
i
heapWords10 :: a -> a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> a9 -> Int
heapWords10 a
a a1
b a2
c a3
d a4
e a5
f a6
g a7
h a8
i a9
j =
  Int
11
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a3 -> Int
forall a. HeapWords a => a -> Int
heapWords a3
d
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a4 -> Int
forall a. HeapWords a => a -> Int
heapWords a4
e
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a5 -> Int
forall a. HeapWords a => a -> Int
heapWords a5
f
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a6 -> Int
forall a. HeapWords a => a -> Int
heapWords a6
g
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a7 -> Int
forall a. HeapWords a => a -> Int
heapWords a7
h
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a8 -> Int
forall a. HeapWords a => a -> Int
heapWords a8
i
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a9 -> Int
forall a. HeapWords a => a -> Int
heapWords a9
j
heapWords11 :: a
-> a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> a9 -> a10 -> Int
heapWords11 a
a a1
b a2
c a3
d a4
e a5
f a6
g a7
h a8
i a9
j a10
k =
  Int
12
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a3 -> Int
forall a. HeapWords a => a -> Int
heapWords a3
d
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a4 -> Int
forall a. HeapWords a => a -> Int
heapWords a4
e
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a5 -> Int
forall a. HeapWords a => a -> Int
heapWords a5
f
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a6 -> Int
forall a. HeapWords a => a -> Int
heapWords a6
g
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a7 -> Int
forall a. HeapWords a => a -> Int
heapWords a7
h
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a8 -> Int
forall a. HeapWords a => a -> Int
heapWords a8
i
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a9 -> Int
forall a. HeapWords a => a -> Int
heapWords a9
j
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a10 -> Int
forall a. HeapWords a => a -> Int
heapWords a10
k
heapWords12 :: a
-> a1
-> a2
-> a3
-> a4
-> a5
-> a6
-> a7
-> a8
-> a9
-> a10
-> a11
-> Int
heapWords12 a
a a1
b a2
c a3
d a4
e a5
f a6
g a7
h a8
i a9
j a10
k a11
l =
  Int
13
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a3 -> Int
forall a. HeapWords a => a -> Int
heapWords a3
d
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a4 -> Int
forall a. HeapWords a => a -> Int
heapWords a4
e
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a5 -> Int
forall a. HeapWords a => a -> Int
heapWords a5
f
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a6 -> Int
forall a. HeapWords a => a -> Int
heapWords a6
g
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a7 -> Int
forall a. HeapWords a => a -> Int
heapWords a7
h
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a8 -> Int
forall a. HeapWords a => a -> Int
heapWords a8
i
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a9 -> Int
forall a. HeapWords a => a -> Int
heapWords a9
j
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a10 -> Int
forall a. HeapWords a => a -> Int
heapWords a10
k
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a11 -> Int
forall a. HeapWords a => a -> Int
heapWords a11
l
heapWords13 :: a
-> a1
-> a2
-> a3
-> a4
-> a5
-> a6
-> a7
-> a8
-> a9
-> a10
-> a11
-> a12
-> Int
heapWords13 a
a a1
b a2
c a3
d a4
e a5
f a6
g a7
h a8
i a9
j a10
k a11
l a12
m =
  Int
14
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
a
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a1 -> Int
forall a. HeapWords a => a -> Int
heapWords a1
b
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a2 -> Int
forall a. HeapWords a => a -> Int
heapWords a2
c
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a3 -> Int
forall a. HeapWords a => a -> Int
heapWords a3
d
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a4 -> Int
forall a. HeapWords a => a -> Int
heapWords a4
e
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a5 -> Int
forall a. HeapWords a => a -> Int
heapWords a5
f
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a6 -> Int
forall a. HeapWords a => a -> Int
heapWords a6
g
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a7 -> Int
forall a. HeapWords a => a -> Int
heapWords a7
h
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a8 -> Int
forall a. HeapWords a => a -> Int
heapWords a8
i
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a9 -> Int
forall a. HeapWords a => a -> Int
heapWords a9
j
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a10 -> Int
forall a. HeapWords a => a -> Int
heapWords a10
k
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a11 -> Int
forall a. HeapWords a => a -> Int
heapWords a11
l
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a12 -> Int
forall a. HeapWords a => a -> Int
heapWords a12
m


instance HeapWords (a -> b) where
  heapWords :: (a -> b) -> Int
heapWords a -> b
_ = Int
0

instance HeapWords Int where
  heapWords :: Int -> Int
heapWords Int
_ = Int
2

instance HeapWords Word where
  heapWords :: Word -> Int
heapWords Word
_ = Int
2

instance HeapWords Word8 where
  heapWords :: Word8 -> Int
heapWords Word8
_ = Int
2

instance HeapWords Word32 where
  heapWords :: Word32 -> Int
heapWords Word32
_ = Int
2

instance HeapWords Word64 where
  heapWords :: Word64 -> Int
heapWords Word64
_ = Int
2

instance HeapWords Char where
  -- For 'Char' there is a special case, where for chars <= 255 the garbage
  -- collector will replace them with pointers to statically allocated ones.
  -- Bigger 'Char's remain as a 2-word heap object. However, if we assume that
  -- 'Char's are mainly ASCII, then these pointers will be in the pointers
  -- section of the containing object, and therefore the storage required by
  -- this will be accounted for elsewhere.
  heapWords :: Char -> Int
heapWords Char
_ = Int
0

instance HeapWords Bool where
  -- There's a special optimization in GHC for nullary constructors, such that
  -- they get allocated once and shared. So if we consider the amortized size
  -- over all occurrences in a program, @heapWords@ for these constructors
  -- tends to 0.
  heapWords :: Bool -> Int
heapWords Bool
_ = Int
0

instance HeapWords Integer where
  heapWords :: Integer -> Int
heapWords (S# Int#
_)
    -- We have
    --
    -- > S# !Int#
    --
    -- so @(S# !Int)@ requires:
    --
    -- - 1 word for the 'S#' object header
    -- - 1 word for the single 'S#' unboxed field, of type 'Int#'
    --
    -- ┌──┬──────┐
    -- │S#│ Int# │
    -- └──┴──────┘
    --
    = Int
2
  heapWords (Jp# BigNat
bigNat)
    -- We have
    --
    -- > Jp# {-# UNPACK #-} !BigNat
    -- > data BigNat = BN# ByteArray#
    --
    -- so @Jp# {-# UNPACK #-} !BigNat@ requires:
    --
    -- - 1 word for the 'Jp#' object header
    -- - 1 word for the pointer to the byte array object
    -- - 1 word for the byte array object header
    -- - 1 word for the size of the byte array payload in bytes
    -- - the heap words required for the byte array payload
    --
    -- Note that for the sake of uniformity, we use 'heapWordsUnpacked' to
    -- account for the level of indirection removed by the @UNPACK@ pragma.
    --
    -- ┌───┬───┐
    -- │Jp#│ ◉ │
    -- └───┴─╂─┘
    --       ▼
    --      ┌───┬───┬───┬─┈   ┈─┬───┐
    --      │BA#│ sz│   │       │   │   2 + n Words
    --      └───┴───┴───┴─┈   ┈─┴───┘
    --
    = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ BigNat -> Int
forall a. HeapWords a => a -> Int
heapWordsUnpacked BigNat
bigNat
  heapWords (Jn# BigNat
bigNat)
    -- We have
    --
    -- > Jn# {-# UNPACK #-} !BigNat
    -- > data BigNat = BN# ByteArray#
    --
    -- so @Jn# {-# UNPACK #-} !BigNat@ requires:
    --
    -- - 1 word for the 'Jn#' object header
    -- - 1 word for the pointer to the byte array object
    -- - 1 word for the byte array object header
    -- - 1 word for the size of the byte array payload in bytes
    -- - the heap words required for the byte array payload
    --
    -- Note that for the sake of uniformity, we use 'heapWordsUnpacked' to
    -- account for the level of indirection removed by the @UNPACK@ pragma.
    --
    -- ┌───┬───┐
    -- │Jn#│ ◉ │
    -- └───┴─╂─┘
    --       ▼
    --      ┌───┬───┬───┬─┈   ┈─┬───┐
    --      │BA#│ sz│   │       │   │   2 + n Words
    --      └───┴───┴───┴─┈   ┈─┴───┘
    --
    = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ BigNat -> Int
forall a. HeapWords a => a -> Int
heapWordsUnpacked BigNat
bigNat

instance HeapWords Float where
  heapWords :: Float -> Int
heapWords Float
_ = Int
2

instance HeapWords UTCTime where
  heapWords :: UTCTime -> Int
heapWords UTCTime
_ = Int
7

instance HeapWords Day where
  heapWords :: Day -> Int
heapWords Day
_ = Int
2

instance HeapWords a => HeapWords [a] where
  heapWords :: [a] -> Int
heapWords []     = Int
heapWords0
  heapWords (a
x:[a]
xs) = a -> [a] -> Int
forall a1 a. (HeapWords a1, HeapWords a) => a -> a1 -> Int
heapWords2 a
x [a]
xs

instance (HeapWords a, HeapWords b) => HeapWords (a,b) where
  heapWords :: (a, b) -> Int
heapWords (a
a,b
b) = a -> b -> Int
forall a1 a. (HeapWords a1, HeapWords a) => a -> a1 -> Int
heapWords2 a
a b
b

instance (HeapWords a, HeapWords b, HeapWords c) => HeapWords (a,b,c) where
  heapWords :: (a, b, c) -> Int
heapWords (a
a,b
b,c
c) = a -> b -> c -> Int
forall a2 a1 a.
(HeapWords a2, HeapWords a1, HeapWords a) =>
a -> a1 -> a2 -> Int
heapWords3 a
a b
b c
c

instance (HeapWords a, HeapWords b, HeapWords c, HeapWords d) => HeapWords (a,b,c,d) where
  heapWords :: (a, b, c, d) -> Int
heapWords (a
a,b
b,c
c,d
d) = a -> b -> c -> d -> Int
forall a3 a2 a1 a.
(HeapWords a3, HeapWords a2, HeapWords a1, HeapWords a) =>
a -> a1 -> a2 -> a3 -> Int
heapWords4 a
a b
b c
c d
d

instance HeapWords a => HeapWords (Maybe a) where
  heapWords :: Maybe a -> Int
heapWords Maybe a
Nothing  = Int
heapWords0
  heapWords (Just a
a) = a -> Int
forall a. HeapWords a => a -> Int
heapWords1 a
a

instance (HeapWords a, HeapWords b) => HeapWords (Either a b) where
  heapWords :: Either a b -> Int
heapWords (Left  a
a) = a -> Int
forall a. HeapWords a => a -> Int
heapWords1 a
a
  heapWords (Right b
b) = b -> Int
forall a. HeapWords a => a -> Int
heapWords1 b
b

instance (HeapWords a, HeapWords b) => HeapWords (Map a b) where
  heapWords :: Map a b -> Int
heapWords Map a b
m = [Int] -> Int
forall (f :: * -> *) a. (Foldable f, Num a) => f a -> a
sum [ Int
6 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ b -> Int
forall a. HeapWords a => a -> Int
heapWords b
v | (a
k,b
v) <- Map a b -> [(a, b)]
forall k a. Map k a -> [(k, a)]
Map.toList Map a b
m ]

instance HeapWords a => HeapWords (IntMap a) where
  heapWords :: IntMap a -> Int
heapWords IntMap a
m = [Int] -> Int
forall (f :: * -> *) a. (Foldable f, Num a) => f a -> a
sum [ Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
v | a
v <- IntMap a -> [a]
forall a. IntMap a -> [a]
IntMap.elems IntMap a
m ]

instance HeapWords a => HeapWords (Set a) where
  heapWords :: Set a -> Int
heapWords Set a
m = [Int] -> Int
forall (f :: * -> *) a. (Foldable f, Num a) => f a -> a
sum [ Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
v | a
v <- Set a -> [a]
forall a. Set a -> [a]
Set.elems Set a
m ]

instance HeapWords IntSet where
  heapWords :: IntSet -> Int
heapWords IntSet
s = Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
* IntSet -> Int
IntSet.size IntSet
s --estimate

instance HeapWords a => HeapWords (Seq a) where
  heapWords :: Seq a -> Int
heapWords Seq a
s = [Int] -> Int
forall (f :: * -> *) a. (Foldable f, Num a) => f a -> a
sum [ Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. HeapWords a => a -> Int
heapWords a
v | a
v <- Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq a
s ] --estimate

instance HeapWords ByteString where
  heapWords :: ByteString -> Int
heapWords ByteString
s = let (Int
w,Int
t) = Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
divMod (ByteString -> Int
BS.length ByteString
s) Int
wordSize
               in Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int
forall a. Num a => a -> a
signum Int
t

instance HeapWords BSS.ShortByteString where
  heapWords :: ShortByteString -> Int
heapWords ShortByteString
s
    -- We have
    --
    -- > data ShortByteString = SBS ByteArray#
    --
    -- so @SBS ByteArray#@ requires:
    --
    -- - 1 word for the 'SBS' object header
    -- - 1 word for the pointer to the byte array object
    -- - 1 word for the byte array object header
    -- - 1 word for the size of the byte array payload in bytes
    -- - the heap words required for the byte array payload
    --
    -- ┌───┬───┐
    -- │SBS│ ◉ │
    -- └───┴─╂─┘
    --       ▼
    --      ┌───┬───┬───┬─┈   ┈─┬───┐
    --      │BA#│ sz│   │       │   │   2 + n Words
    --      └───┴───┴───┴─┈   ┈─┴───┘
    --
    = let (Int
w,Int
t) = Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
divMod (ShortByteString -> Int
BSS.length ShortByteString
s) Int
wordSize
      in Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int
forall a. Num a => a -> a
signum Int
t

instance HeapWords LByteString where
  heapWords :: LByteString -> Int
heapWords LByteString
s = [Int] -> Int
forall (f :: * -> *) a. (Foldable f, Num a) => f a -> a
sum [ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ByteString -> Int
forall a. HeapWords a => a -> Int
heapWords ByteString
c | ByteString
c <- LByteString -> [ByteString]
LBS.toChunks LByteString
s ]

instance HeapWords Text where
  heapWords :: Text -> Int
heapWords Text
s = let (Int
w,Int
t) = Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
divMod (Text -> Int
forall a. HasLength a => a -> Int
length Text
s) (Int
wordSize Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2)
               in Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int
forall a. Num a => a -> a
signum Int
t

heapWordsUArray :: (Ix i, A.IArray a e) => Int -> a i e -> Int
heapWordsUArray :: Int -> a i e -> Int
heapWordsUArray Int
sz a i e
a = Int
13 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ((i, i) -> Int
forall a. Ix a => (a, a) -> Int
rangeSize (a i e -> (i, i)
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> (i, i)
A.bounds a i e
a) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
sz) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
wordSize

instance HeapWords e => HeapWords (V.Vector e) where
  heapWords :: Vector e -> Int
heapWords Vector e
a = Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Vector e -> Int
forall a. Vector a -> Int
V.length Vector e
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int -> e -> Int) -> Int -> Vector e -> Int
forall a b. (a -> b -> a) -> a -> Vector b -> a
V.foldl' (\Int
s e
e -> Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ e -> Int
forall a. HeapWords a => a -> Int
heapWords e
e) Int
0 Vector e
a

heapWordsUVector :: V.U.Unbox e => Int -> V.U.Vector e -> Int
heapWordsUVector :: Int -> Vector e -> Int
heapWordsUVector Int
sz Vector e
a = Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Vector e -> Int
forall a. Unbox a => Vector a -> Int
V.U.length Vector e
a Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
sz) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
wordSize

instance HeapWords Natural where
  heapWords :: Natural -> Int
heapWords (NatS# GmpLimb#
_)
    -- We have
    --
    -- > NatS# GmpLimb#
    -- > type GmpLimb# = Word#
    --
    -- so @(NatS# n)@ requires:
    --
    -- - 1 word for the header 'NatS#' object header
    -- - 1 word for the single 'NatS#' unboxed field, of type 'Word#'
    --
    -- ┌─────┬───────┐
    -- │NatS#│ Word#'│
    -- └─────┴───────┘
    --
    = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
  heapWords (NatJ# BigNat
bn)
    -- We have
    --
    -- > NatJ# {-# UNPACK #-} !BigNat
    --
    -- so @NatJ# bn@ requires:
    --
    -- - 1 word for the 'NatJ#' object header
    -- - 1 word for the pointer to the byte array object
    -- - the heap words required by the byte array object
    --
    -- Note that for the sake of uniformity, we use 'heapWordsUnpacked' to
    -- account for the level of indirection removed by the @UNPACK@ pragma.
    --
    -- ┌─────┬───┐
    -- │NatJ#│ ◉ │
    -- └─────┴─╂─┘
    --         ▼
    --        ┌───┬───┬───┬─┈   ┈─┬───┐
    --        │BA#│ sz│   │       │   │   2 + n Words
    --        └───┴───┴───┴─┈   ┈─┴───┘
    --
    = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ BigNat -> Int
forall a. HeapWords a => a -> Int
heapWordsUnpacked BigNat
bn

instance HeapWords BigNat where
  heapWords :: BigNat -> Int
heapWords (BN# ByteArray#
arr) =
    -- We have
    --
    -- > data BigNat = BN# ByteArray#
    --
    -- so @BN# ByteArray#@ requires:
    --
    -- - 1 word for the @BN#@ object header
    -- - 1 word for the pointer to the byte array
    -- - the words used by the byte array (see 'heapWordsByteArray#').
    --
    -- ┌──────┬───┐
    -- │BigNat│ ◉ │
    -- └──────┴─╂─┘
    --          ▼
    --        ┌───┬───┬───┬─┈   ┈─┬───┐
    --        │BA#│ sz│   │       │   │   2 + n Words
    --        └───┴───┴───┴─┈   ┈─┴───┘
    Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ByteArray# -> Int
heapWordsByteArray# ByteArray#
arr

-- | Calculate the heap words required to store a 'ByteArray#' object.
--
heapWordsByteArray# :: ByteArray# -> Int
heapWordsByteArray# :: ByteArray# -> Int
heapWordsByteArray# ByteArray#
ba# = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n
  -- We require:
  --
  -- - 2 for the 'ByteArray#' heap object (1 for header, and 1 for storing its
  --   size)
  -- - @n@ for the variable sized part
  --
  -- ┌───┬───┬───┬─┈   ┈─┬───┐
  -- │BA#│ sz│   │       │   │   2 + n Words
  -- └───┴───┴───┴─┈   ┈─┴───┘
 where
  n :: Int
n      = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ((Int
nbytes Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
wordSize)
  nbytes :: Int
nbytes = Int# -> Int
I# (ByteArray# -> Int#
sizeofByteArray# ByteArray#
ba#)

-- | Calculate the number of heap words used by a field unpacked within another
-- constructor.
--
-- This function simply subtracts 2 from the 'heapWords' result of its
-- parameter, since in the case of an unpacked field we _do not_ have to use:
--
-- - a word for the pointer to the inner structure.
-- - a word for the constructor that is being unpacked.
--
heapWordsUnpacked :: HeapWords a => a -> Int
heapWordsUnpacked :: a -> Int
heapWordsUnpacked a
x = a -> Int
forall a. HeapWords a => a -> Int
heapWords a
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2