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

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

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 Data.Foldable (toList)
import qualified Data.IntMap.Strict as IntMap
import qualified Data.IntSet as IntSet
import Data.Ix
import qualified Data.Map.Strict as Map
import Data.Sequence (Seq)
import qualified Data.Set as Set
import Data.Text as Text
import Data.Time (Day, UTCTime)
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as V.U
import Data.Word (Word32, Word64, Word8)
import GHC.Natural (Natural (NatJ#, NatS#))
import GHC.Prim (ByteArray#, sizeofByteArray#)
import GHC.Types (Int (I#))

#if __GLASGOW_HASKELL__ >= 900
-- Use the GHC version here because this is compiler dependent, and only indirectly lib dependent.
import GHC.Num.BigNat (BigNat (BN#))
import GHC.Num.Integer (Integer (IS, IP, IN))
#else
import GHC.Integer.GMP.Internals (BigNat(BN#), Integer(S#, Jn#, Jp#))
#endif

--------------------------------------------------------------------------------

-- Module copied from Cardano.Prelude

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

-- | These functions assume a 64-bit architecture
heapSizeMb, heapSizeKb :: Int -> Int
heapSizeMb :: Int -> Int
heapSizeMb Int
w = Int
wordSize forall a. Num a => a -> a -> a
* Int
w forall a. Integral a => a -> a -> a
`div` (Int
1024 forall a. Num a => a -> a -> a
* Int
1024)
heapSizeKb :: Int -> Int
heapSizeKb Int
w = Int
wordSize forall a. Num a => a -> a -> a
* Int
w 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 :: forall a. HeapWords a => a -> Int
heapWords1 a
a = Int
2 forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a
heapWords2 :: forall a1 a. (HeapWords a1, HeapWords a) => a -> a1 -> Int
heapWords2 a
a a1
b = Int
3 forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b
heapWords3 :: forall a2 a1 a.
(HeapWords a2, HeapWords a1, HeapWords a) =>
a -> a1 -> a2 -> Int
heapWords3 a
a a1
b a2
c = Int
4 forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c
heapWords4 :: forall a3 a2 a1 a.
(HeapWords a3, HeapWords a2, HeapWords a1, HeapWords a) =>
a -> a1 -> a2 -> a3 -> Int
heapWords4 a
a a1
b a2
c a3
d = Int
5 forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a3
d
heapWords5 :: forall a4 a3 a2 a1 a.
(HeapWords a4, HeapWords a3, HeapWords a2, HeapWords a1,
 HeapWords a) =>
a -> a1 -> a2 -> a3 -> a4 -> Int
heapWords5 a
a a1
b a2
c a3
d a4
e =
  Int
6 forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a3
d forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a4
e
heapWords6 :: forall a5 a4 a3 a2 a1 a.
(HeapWords a5, HeapWords a4, HeapWords a3, HeapWords a2,
 HeapWords a1, HeapWords a) =>
a -> a1 -> a2 -> a3 -> a4 -> a5 -> Int
heapWords6 a
a a1
b a2
c a3
d a4
e a5
f =
  Int
7
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a3
d
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a4
e
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a5
f
heapWords7 :: forall a6 a5 a4 a3 a2 a1 a.
(HeapWords a6, HeapWords a5, HeapWords a4, HeapWords a3,
 HeapWords a2, HeapWords a1, HeapWords a) =>
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
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a3
d
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a4
e
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a5
f
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a6
g
heapWords8 :: forall a7 a6 a5 a4 a3 a2 a1 a.
(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
heapWords8 a
a a1
b a2
c a3
d a4
e a5
f a6
g a7
h =
  Int
9
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a3
d
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a4
e
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a5
f
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a6
g
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a7
h
heapWords9 :: forall a8 a7 a6 a5 a4 a3 a2 a1 a.
(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
heapWords9 a
a a1
b a2
c a3
d a4
e a5
f a6
g a7
h a8
i =
  Int
10
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a3
d
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a4
e
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a5
f
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a6
g
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a7
h
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a8
i
heapWords10 :: forall a9 a8 a7 a6 a5 a4 a3 a2 a1 a.
(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
heapWords10 a
a a1
b a2
c a3
d a4
e a5
f a6
g a7
h a8
i a9
j =
  Int
11
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a3
d
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a4
e
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a5
f
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a6
g
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a7
h
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a8
i
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a9
j
heapWords11 :: forall a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a.
(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
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
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a3
d
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a4
e
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a5
f
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a6
g
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a7
h
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a8
i
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a9
j
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a10
k
heapWords12 :: forall a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a.
(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
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
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a3
d
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a4
e
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a5
f
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a6
g
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a7
h
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a8
i
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a9
j
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a10
k
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a11
l
heapWords13 :: forall a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a.
(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
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
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a
a
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a1
b
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a2
c
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a3
d
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a4
e
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a5
f
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a6
g
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a7
h
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a8
i
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a9
j
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a10
k
    forall a. Num a => a -> a -> a
+ forall a. HeapWords a => a -> Int
heapWords a11
l
    forall a. Num a => a -> a -> a
+ 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

{- FOURMOLU_DISABLE -}
instance HeapWords Integer where
#if __GLASGOW_HASKELL__ >= 900
  heapWords :: Integer -> Int
heapWords (IS Int#
_) = Int
2
    -- We have
    --
    -- > IS !Int#
    --
    -- so @(IS !Int)@ requires:
    --
    -- - 1 word for the 'IS' object header
    -- - 1 word for the single 'IS' unboxed field, of type 'Int#'
    --
    -- ┌──┬──────┐
    -- │IS│ Int# │
    -- └──┴──────┘
    --
#else
  heapWords (S# _) = 2
    -- 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# │
    -- └──┴──────┘
    --
#endif
{- FOURMOLU_ENABLE -}

#if __GLASGOW_HASKELL__ >= 900
  heapWords (IP ByteArray#
bigNat) = Int
4 forall a. Num a => a -> a -> a
+ Int# -> Int
I# (ByteArray# -> Int#
sizeofByteArray# ByteArray#
bigNat)
    -- We have
    --
    -- > IP !BigNat#
    -- > type BigNat# = WordArray#
    -- > type WordArray# = ByteArray#
    --
    -- so @IP !BigNat#@ requires:
    --
    -- - 1 word for the 'IP' 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.
    --
    -- ┌──┬───┐
    -- │IP│ ◉ │
    -- └──┴─╂─┘
    --      ▼
    --     ┌───┬───┬───┬─┈   ┈─┬───┐
    --     │BA#│ sz│   │       │   │   2 + n Words
    --     └───┴───┴───┴─┈   ┈─┴───┘
    --
#else
  heapWords (Jp# bigNat) = 2 + heapWordsUnpacked 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
    --      └───┴───┴───┴─┈   ┈─┴───┘
    --
#endif

#if __GLASGOW_HASKELL__ >= 900
  heapWords (IN ByteArray#
bigNat) = Int
4 forall a. Num a => a -> a -> a
+ Int# -> Int
I# (ByteArray# -> Int#
sizeofByteArray# ByteArray#
bigNat)
    -- We have
    --
    -- > IN !BigNat#
    -- > type BigNat# = WordArray#
    -- > type WordArray# = ByteArray#
    --
    -- so @IN !BigNat#@ requires:
    --
    -- - 1 word for the 'IN' 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
    --
    -- ┌──┬───┐
    -- │IN│ ◉ │
    -- └──┴─╂─┘
    --      ▼
    --     ┌───┬───┬───┬─┈   ┈─┬───┐
    --     │BA#│ sz│   │       │   │   2 + n Words
    --     └───┴───┴───┴─┈   ┈─┴───┘
    --
#else
  heapWords (Jn# bigNat) = 2 + heapWordsUnpacked 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
    --      └───┴───┴───┴─┈   ┈─┴───┘
    --
#endif

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) = 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) = 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) = 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) = 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) = 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) = forall a. HeapWords a => a -> Int
heapWords1 a
a
  heapWords (Right b
b) = forall a. HeapWords a => a -> Int
heapWords1 b
b

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

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

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

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

instance HeapWords BS.ByteString where
  heapWords :: ByteString -> Int
heapWords ByteString
s =
    let (Int
w, Int
t) = forall a. Integral a => a -> a -> (a, a)
divMod (ByteString -> Int
BS.length ByteString
s) Int
wordSize
     in Int
5 forall a. Num a => a -> a -> a
+ Int
w forall a. Num a => a -> a -> a
+ 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) = forall a. Integral a => a -> a -> (a, a)
divMod (ShortByteString -> Int
BSS.length ShortByteString
s) Int
wordSize
     in Int
4 forall a. Num a => a -> a -> a
+ Int
w forall a. Num a => a -> a -> a
+ forall a. Num a => a -> a
signum Int
t

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

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

heapWordsUArray :: (Ix i, A.IArray a e) => Int -> a i e -> Int
heapWordsUArray :: forall i (a :: * -> * -> *) e.
(Ix i, IArray a e) =>
Int -> a i e -> Int
heapWordsUArray Int
sz a i e
a = Int
13 forall a. Num a => a -> a -> a
+ (forall a. Ix a => (a, a) -> Int
rangeSize (forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> (i, i)
A.bounds a i e
a) forall a. Num a => a -> a -> a
* Int
sz) 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 forall a. Num a => a -> a -> a
+ forall a. Vector a -> Int
V.length Vector e
a forall a. Num a => a -> a -> a
+ forall a b. (a -> b -> a) -> a -> Vector b -> a
V.foldl' (\Int
s e
e -> Int
s forall a. Num a => a -> a -> a
+ 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 :: forall e. Unbox e => Int -> Vector e -> Int
heapWordsUVector Int
sz Vector e
a = Int
5 forall a. Num a => a -> a -> a
+ (forall a. Unbox a => Vector a -> Int
V.U.length Vector e
a forall a. Num a => a -> a -> a
* Int
sz) forall a. Integral a => a -> a -> a
`div` Int
wordSize

instance HeapWords Natural where
  heapWords :: Natural -> Int
heapWords (NatS# Word#
_) =
    -- 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 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 forall a. Num a => a -> a -> a
+ Int
1 forall a. Num a => a -> a -> a
+ 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 forall a. Num a => a -> a -> a
+ Int
1 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 forall a. Num a => a -> a -> a
+ Int
n
  where
    -- 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
    -- └───┴───┴───┴─┈   ┈─┴───┘

    n :: Int
n = Int
1 forall a. Num a => a -> a -> a
+ ((Int
nbytes forall a. Num a => a -> a -> a
- Int
1) 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 :: forall a. HeapWords a => a -> Int
heapWordsUnpacked a
x = forall a. HeapWords a => a -> Int
heapWords a
x forall a. Num a => a -> a -> a
- Int
2