{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE BinaryLiterals #-}
{-# OPTIONS_GHC -Wno-name-shadowing #-}

-- | Multi-precision natural
module GHC.Num.BigNat where

#include "MachDeps.h"
#include "WordSize.h"

import GHC.Prim
import GHC.Types
import GHC.Classes
import GHC.Magic
import GHC.Num.Primitives
import GHC.Num.WordArray
import GHC.Num.Backend

default ()

-- | A BigNat
--
-- Represented as an array of limbs (Word#) stored in little-endian order (Word#
-- themselves use machine order).
--
-- Invariant (canonical representation): higher Word# is non-zero.
--
-- As a consequence, zero is represented with a WordArray# whose size is 0.
type BigNat# = WordArray#
   -- we use a type-alias instead of an unlifted newtype to make Integer/Natural
   -- types easier to wire in the compiler

-- | A lifted BigNat
--
-- Represented as an array of limbs (Word#) stored in little-endian order (Word#
-- themselves use machine order).
--
-- Invariant (canonical representation): higher Word# is non-zero.
--
-- As a consequence, zero is represented with a WordArray# whose size is 0.
data BigNat = BN# { BigNat -> BigNat#
unBigNat :: BigNat# }

-- Note [Why (# #)?]
-- ~~~~~~~~~~~~~~~~~
--
-- We can't have top-level BigNat# for now because they are unlifted ByteArray#
-- (see #17521). So we use functions that take an empty argument (# #) that
-- will be discarded at compile time.


-- | Check that the BigNat is valid
bigNatCheck# :: BigNat# -> Bool#
bigNatCheck# :: BigNat# -> Bool#
bigNatCheck# BigNat#
bn
   | Bool#
0#  <- BigNat# -> Bool#
bigNatSize# BigNat#
bn                         = Bool#
1#
   -- check that size is a multiple of Word size
   | Bool#
r <- Bool# -> Bool# -> Bool#
remInt# (BigNat# -> Bool#
sizeofByteArray# BigNat#
bn) WORD_SIZE_IN_BYTES#
   , Bool# -> Bool
isTrue# (Bool#
r Bool# -> Bool# -> Bool#
/=# Bool#
0#)                            = Bool#
0#
   -- check that most-significant limb isn't zero
   | Word#
0## <- BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
bn (BigNat# -> Bool#
bigNatSize# BigNat#
bn Bool# -> Bool# -> Bool#
-# Bool#
1#) = Bool#
0#
   | Bool
True                                          = Bool#
1#

-- | Check that the BigNat is valid
bigNatCheck :: BigNat# -> Bool
bigNatCheck :: BigNat# -> Bool
bigNatCheck BigNat#
bn = Bool# -> Bool
isTrue# (BigNat# -> Bool#
bigNatCheck# BigNat#
bn)

-- | Number of words in the BigNat
bigNatSize :: BigNat# -> Word
bigNatSize :: BigNat# -> Word
bigNatSize BigNat#
bn = Word# -> Word
W# (Bool# -> Word#
int2Word# (BigNat# -> Bool#
bigNatSize# BigNat#
bn))

-- | Number of words in the BigNat
bigNatSize# :: BigNat# -> Int#
bigNatSize# :: BigNat# -> Bool#
bigNatSize# BigNat#
ba = BigNat# -> Bool#
wordArraySize# BigNat#
ba

{-# NOINLINE bigNatZero #-}
bigNatZero :: BigNat
bigNatZero :: BigNat
bigNatZero = BigNat# -> BigNat
BN# (Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
0# (\MutableWordArray# RealWorld
_ State# RealWorld
s -> State# RealWorld
s))

{-# NOINLINE bigNatOne #-}
bigNatOne :: BigNat
bigNatOne :: BigNat
bigNatOne = BigNat# -> BigNat
BN# (Word# -> BigNat#
bigNatFromWord# Word#
1##)

-- | BigNat Zero
bigNatZero# :: (# #) -> BigNat# -- cf Note [Why (# #)?]
bigNatZero# :: (# #) -> BigNat#
bigNatZero# (# #)
_ = case BigNat
bigNatZero of
   BN# BigNat#
w -> BigNat#
w

-- | BigNat one
bigNatOne# :: (# #) -> BigNat# -- cf Note [Why (# #)?]
bigNatOne# :: (# #) -> BigNat#
bigNatOne# (# #)
_ = case BigNat
bigNatOne of
   BN# BigNat#
w -> BigNat#
w

raiseDivZero_BigNat :: (# #) -> BigNat#
raiseDivZero_BigNat :: (# #) -> BigNat#
raiseDivZero_BigNat (# #)
_ = case Any
forall a. a
raiseDivZero of
   !Any
_ -> (# #) -> BigNat#
bigNatZero# (# #)
   -- see Note [ghc-bignum exceptions] in GHC.Num.Primitives

-- | Indicate if a bigNat is zero
bigNatIsZero :: BigNat# -> Bool
bigNatIsZero :: BigNat# -> Bool
bigNatIsZero BigNat#
bn = Bool# -> Bool
isTrue# (BigNat# -> Bool#
bigNatIsZero# BigNat#
bn)

-- | Indicate if a bigNat is zero
bigNatIsZero# :: BigNat# -> Bool#
bigNatIsZero# :: BigNat# -> Bool#
bigNatIsZero# BigNat#
ba = BigNat# -> Bool#
wordArraySize# BigNat#
ba Bool# -> Bool# -> Bool#
==# Bool#
0#

-- | Indicate if a bigNat is one
bigNatIsOne :: BigNat# -> Bool
bigNatIsOne :: BigNat# -> Bool
bigNatIsOne BigNat#
bn = Bool# -> Bool
isTrue# (BigNat# -> Bool#
bigNatIsOne# BigNat#
bn)

-- | Indicate if a bigNat is one
bigNatIsOne# :: BigNat# -> Bool#
bigNatIsOne# :: BigNat# -> Bool#
bigNatIsOne# BigNat#
ba =
   BigNat# -> Bool#
wordArraySize# BigNat#
ba Bool# -> Bool# -> Bool#
==# Bool#
1#
   Bool# -> Bool# -> Bool#
&&# BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
ba Bool#
0# Word# -> Word# -> Bool#
`eqWord#` Word#
1##

-- | Indicate if a bigNat is two
bigNatIsTwo :: BigNat# -> Bool
bigNatIsTwo :: BigNat# -> Bool
bigNatIsTwo BigNat#
bn = Bool# -> Bool
isTrue# (BigNat# -> Bool#
bigNatIsTwo# BigNat#
bn)

-- | Indicate if a bigNat is two
bigNatIsTwo# :: BigNat# -> Bool#
bigNatIsTwo# :: BigNat# -> Bool#
bigNatIsTwo# BigNat#
ba =
   BigNat# -> Bool#
wordArraySize# BigNat#
ba Bool# -> Bool# -> Bool#
==# Bool#
1#
   Bool# -> Bool# -> Bool#
&&# BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
ba Bool#
0# Word# -> Word# -> Bool#
`eqWord#` Word#
2##

-- | Indicate if the value is a power of two and which one
bigNatIsPowerOf2# :: BigNat# -> (# (# #) | Word# #)
bigNatIsPowerOf2# :: BigNat# -> (# (# #) | Word# #)
bigNatIsPowerOf2# BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
a                      = (# (# #) | #)
   | Bool
True = case Word# -> (# (# #) | Word# #)
wordIsPowerOf2# Word#
msw of
               (# (# #) | #) -> (# (# #) | #)
               (# | Word#
c  #) -> case Bool# -> Bool#
checkAllZeroes (Bool#
imax Bool# -> Bool# -> Bool#
-# Bool#
1#) of
                  Bool#
0# -> (# (# #) | #)
                  Bool#
_  -> (# | Word#
c Word# -> Word# -> Word#
`plusWord#`
                              (Bool# -> Word#
int2Word# Bool#
imax Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BITS_SHIFT#) #)
   where
      msw :: Word#
msw  = BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
imax
      sz :: Bool#
sz   = BigNat# -> Bool#
bigNatSize# BigNat#
a
      imax :: Bool#
imax = Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#
      checkAllZeroes :: Bool# -> Bool#
checkAllZeroes Bool#
i
         | Bool# -> Bool
isTrue# (Bool#
i Bool# -> Bool# -> Bool#
<# Bool#
0#) = Bool#
1#
         | Bool
True = case BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
i of
                     Word#
0## -> Bool# -> Bool#
checkAllZeroes (Bool#
i Bool# -> Bool# -> Bool#
-# Bool#
1#)
                     Word#
_   -> Bool#
0#

-- | Return the Word# at the given index
bigNatIndex# :: BigNat# -> Int# -> Word#
bigNatIndex# :: BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
x Bool#
i = BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
x Bool#
i

-- | Return the Word# at the given index
bigNatIndex :: BigNat# -> Int# -> Word
bigNatIndex :: BigNat# -> Bool# -> Word
bigNatIndex BigNat#
bn Bool#
i = Word# -> Word
W# (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
bn Bool#
i)

-------------------------------------------------
-- Conversion
-------------------------------------------------

-- | Create a BigNat from a Word
bigNatFromWord :: Word -> BigNat#
bigNatFromWord :: Word -> BigNat#
bigNatFromWord (W# Word#
w) = Word# -> BigNat#
bigNatFromWord# Word#
w

-- | Create a BigNat from a Word
bigNatFromWord# :: Word# -> BigNat#
bigNatFromWord# :: Word# -> BigNat#
bigNatFromWord# Word#
0## = (# #) -> BigNat#
bigNatZero# (# #)
bigNatFromWord# Word#
w   = Word# -> BigNat#
wordArrayFromWord# Word#
w

-- | Convert a list of non-zero Words (most-significant first) into a BigNat
bigNatFromWordList :: [Word] -> BigNat#
bigNatFromWordList :: [Word] -> BigNat#
bigNatFromWordList (W# Word#
0##:[Word]
xs) = [Word] -> BigNat#
bigNatFromWordList [Word]
xs
bigNatFromWordList [Word]
xs          = [Word] -> BigNat#
bigNatFromWordListUnsafe [Word]
xs

-- | Convert a list of non-zero Words (most-significant first) into a BigNat
bigNatFromWordList# :: [Word] -> WordArray#
{-# NOINLINE bigNatFromWordList# #-}
bigNatFromWordList# :: [Word] -> BigNat#
bigNatFromWordList# [Word]
xs = [Word] -> BigNat#
bigNatFromWordList [Word]
xs

-- | Return the absolute value of the Int# in a BigNat
bigNatFromAbsInt# :: Int# -> BigNat#
bigNatFromAbsInt# :: Bool# -> BigNat#
bigNatFromAbsInt# Bool#
i = Word# -> BigNat#
bigNatFromWord# (Bool# -> Word#
wordFromAbsInt# Bool#
i)

-- | Convert a list of non-zero Words (most-significant first) into a BigNat.
-- Don't remove most-significant zero words
bigNatFromWordListUnsafe :: [Word] -> BigNat#
bigNatFromWordListUnsafe :: [Word] -> BigNat#
bigNatFromWordListUnsafe [] = (# #) -> BigNat#
bigNatZero# (# #)
bigNatFromWordListUnsafe [Word]
xs =
   let
      length :: Bool# -> [a] -> Bool#
length Bool#
i []     = Bool#
i
      length Bool#
i (a
_:[a]
ys) = Bool# -> [a] -> Bool#
length (Bool#
i Bool# -> Bool# -> Bool#
+# Bool#
1#) [a]
ys
      !lxs :: Bool#
lxs = Bool# -> [Word] -> Bool#
forall {a}. Bool# -> [a] -> Bool#
length Bool#
0# [Word]
xs
      writeWordList :: MutableWordArray# s -> Bool# -> [Word] -> State# s -> State# s
writeWordList MutableWordArray# s
_mwa Bool#
_i []        State# s
s = State# s
s
      writeWordList MutableWordArray# s
mwa   Bool#
i (W# Word#
w:[Word]
ws) State# s
s =
         case MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# s
mwa Bool#
i Word#
w State# s
s of
            State# s
s1 -> MutableWordArray# s -> Bool# -> [Word] -> State# s -> State# s
writeWordList MutableWordArray# s
mwa (Bool#
i Bool# -> Bool# -> Bool#
-# Bool#
1#) [Word]
ws State# s
s1
   in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
lxs \MutableWordArray# RealWorld
mwa ->
            MutableWordArray# RealWorld
-> Bool# -> [Word] -> State# RealWorld -> State# RealWorld
forall {s}.
MutableWordArray# s -> Bool# -> [Word] -> State# s -> State# s
writeWordList MutableWordArray# RealWorld
mwa (Bool#
lxs Bool# -> Bool# -> Bool#
-# Bool#
1#) [Word]
xs

-- | Convert a BigNat into a list of non-zero Words (most-significant first)
bigNatToWordList :: BigNat# -> [Word]
bigNatToWordList :: BigNat# -> [Word]
bigNatToWordList BigNat#
bn = Bool# -> [Word]
go (BigNat# -> Bool#
bigNatSize# BigNat#
bn)
   where
      go :: Bool# -> [Word]
go Bool#
0# = []
      go Bool#
n  = BigNat# -> Bool# -> Word
bigNatIndex BigNat#
bn (Bool#
n Bool# -> Bool# -> Bool#
-# Bool#
1#) Word -> [Word] -> [Word]
forall a. a -> [a] -> [a]
: Bool# -> [Word]
go (Bool#
n Bool# -> Bool# -> Bool#
-# Bool#
1#)


-- | Convert two Word# (most-significant first) into a BigNat
bigNatFromWord2# :: Word# -> Word# -> BigNat#
bigNatFromWord2# :: Word# -> Word# -> BigNat#
bigNatFromWord2# Word#
0## Word#
0## = (# #) -> BigNat#
bigNatZero# (# #)
bigNatFromWord2# Word#
0## Word#
l   = Word# -> BigNat#
bigNatFromWord# Word#
l
bigNatFromWord2# Word#
h   Word#
l   = Word# -> Word# -> BigNat#
wordArrayFromWord2# Word#
h Word#
l

-- | Convert a BigNat into a Word#
bigNatToWord# :: BigNat# -> Word#
bigNatToWord# :: BigNat# -> Word#
bigNatToWord# BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = Word#
0##
   | Bool
True           = BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
0#

-- | Convert a BigNat into a Word# if it fits
bigNatToWordMaybe# :: BigNat# -> (# (# #) | Word# #)
bigNatToWordMaybe# :: BigNat# -> (# (# #) | Word# #)
bigNatToWordMaybe# BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
a                = (#       | Word#
0## #)
   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
bigNatSize# BigNat#
a Bool# -> Bool# -> Bool#
># Bool#
1#) = (# (# #) |     #)
   | Bool
True                          = (#       | BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
0# #)

-- | Convert a BigNat into a Word
bigNatToWord :: BigNat# -> Word
bigNatToWord :: BigNat# -> Word
bigNatToWord BigNat#
bn = Word# -> Word
W# (BigNat# -> Word#
bigNatToWord# BigNat#
bn)

-- | Convert a BigNat into a Int#
bigNatToInt# :: BigNat# -> Int#
bigNatToInt# :: BigNat# -> Bool#
bigNatToInt# BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = Bool#
0#
   | Bool
True           = BigNat# -> Bool# -> Bool#
indexIntArray# BigNat#
a Bool#
0#

-- | Convert a BigNat into a Int
bigNatToInt :: BigNat# -> Int
bigNatToInt :: BigNat# -> Int
bigNatToInt BigNat#
bn = Bool# -> Int
I# (BigNat# -> Bool#
bigNatToInt# BigNat#
bn)

#if WORD_SIZE_IN_BITS == 32

-- | Convert a Word64# into a BigNat on 32-bit architectures
bigNatFromWord64# :: Word64# -> BigNat#
bigNatFromWord64# w64 = bigNatFromWord2# wh# wl#
  where
    wh# = word64ToWord# (uncheckedShiftRL64# w64 32#)
    wl# = word64ToWord# w64

-- | Convert a BigNat into a Word64# on 32-bit architectures
bigNatToWord64# :: BigNat# -> Word64#
bigNatToWord64# b
  | bigNatIsZero b = wordToWord64# 0##
  | wl <- wordToWord64# (bigNatToWord# b)
  = if isTrue# (bigNatSize# b ># 1#)
      then
         let wh = wordToWord64# (bigNatIndex# b 1#)
         in uncheckedShiftL64# wh 32# `or64#` wl
      else wl

#else

-- | Convert a Word64# into a BigNat on 64-bit architectures
bigNatFromWord64# :: Word64# -> BigNat#
bigNatFromWord64# :: Word64# -> BigNat#
bigNatFromWord64# Word64#
w64 = Word# -> BigNat#
bigNatFromWord# (Word64# -> Word#
word64ToWord# Word64#
w64)

-- | Convert a BigNat into a Word64# on 64-bit architectures
bigNatToWord64# :: BigNat# -> Word64#
bigNatToWord64# :: BigNat# -> Word64#
bigNatToWord64# BigNat#
b = Word# -> Word64#
wordToWord64# (BigNat# -> Word#
bigNatToWord# BigNat#
b)

#endif

-- | Encode (# BigNat mantissa, Int# exponent #) into a Double#
bigNatEncodeDouble# :: BigNat# -> Int# -> Double#
bigNatEncodeDouble# :: BigNat# -> Bool# -> Double#
bigNatEncodeDouble# BigNat#
a Bool#
e
   | BigNat# -> Bool
bigNatIsZero BigNat#
a
   = Word# -> Double#
word2Double# Word#
0## -- FIXME: isn't it NaN on 0# exponent?

   | Bool
True
   = (BigNat# -> Bool# -> Double#) -> BigNat# -> Bool# -> Double#
forall a. a -> a
inline BigNat# -> Bool# -> Double#
bignat_encode_double BigNat#
a Bool#
e

-------------------------------------------------
-- Predicates
-------------------------------------------------

-- | Test if a BigNat is greater than a Word
bigNatGtWord# :: BigNat# -> Word# -> Bool#
bigNatGtWord# :: BigNat# -> Word# -> Bool#
bigNatGtWord# BigNat#
bn Word#
w =
   Bool# -> Bool#
notB# (BigNat# -> Bool#
bigNatIsZero# BigNat#
bn)
   Bool# -> Bool# -> Bool#
&&# (   BigNat# -> Bool#
bigNatSize# BigNat#
bn Bool# -> Bool# -> Bool#
># Bool#
1#
       Bool# -> Bool# -> Bool#
||# BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
bn Bool#
0# Word# -> Word# -> Bool#
`gtWord#` Word#
w
       )

-- | Test if a BigNat is equal to a Word
bigNatEqWord# :: BigNat# -> Word# -> Bool#
bigNatEqWord# :: BigNat# -> Word# -> Bool#
bigNatEqWord# BigNat#
bn Word#
w
   | Word#
0## <- Word#
w
   = BigNat# -> Bool#
bigNatIsZero# BigNat#
bn

   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
bigNatSize# BigNat#
bn Bool# -> Bool# -> Bool#
==# Bool#
1#)
   = BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
bn Bool#
0# Word# -> Word# -> Bool#
`eqWord#` Word#
w

   | Bool
True
   = Bool#
0#

-- | Test if a BigNat is greater than a Word
bigNatGtWord :: BigNat# -> Word -> Bool
bigNatGtWord :: BigNat# -> Word -> Bool
bigNatGtWord BigNat#
bn (W# Word#
w) = Bool# -> Bool
isTrue# (BigNat# -> Word# -> Bool#
bigNatGtWord# BigNat#
bn Word#
w)

-- | Test if a BigNat is lower than or equal to a Word
bigNatLeWord# :: BigNat# -> Word# -> Bool#
bigNatLeWord# :: BigNat# -> Word# -> Bool#
bigNatLeWord# BigNat#
bn Word#
w = Bool# -> Bool#
notB# (BigNat# -> Word# -> Bool#
bigNatGtWord# BigNat#
bn Word#
w)

-- | Test if a BigNat is lower than or equal to a Word
bigNatLeWord :: BigNat# -> Word -> Bool
bigNatLeWord :: BigNat# -> Word -> Bool
bigNatLeWord BigNat#
bn (W# Word#
w) = Bool# -> Bool
isTrue# (BigNat# -> Word# -> Bool#
bigNatLeWord# BigNat#
bn Word#
w)

-- | Equality test for BigNat
bigNatEq# :: BigNat# -> BigNat# -> Bool#
{-# NOINLINE bigNatEq# #-}
bigNatEq# :: BigNat# -> BigNat# -> Bool#
bigNatEq# BigNat#
wa BigNat#
wb
   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
wordArraySize# BigNat#
wa Bool# -> Bool# -> Bool#
/=# BigNat# -> Bool#
wordArraySize# BigNat#
wb) = Bool#
0#
   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
wordArraySize# BigNat#
wa Bool# -> Bool# -> Bool#
==# Bool#
0#)                = Bool#
1#
   | Bool
True = (BigNat# -> BigNat# -> Bool#) -> BigNat# -> BigNat# -> Bool#
forall a. a -> a
inline BigNat# -> BigNat# -> Bool#
bignat_compare BigNat#
wa BigNat#
wb Bool# -> Bool# -> Bool#
==# Bool#
0#

-- | Equality test for BigNat
bigNatEq :: BigNat# -> BigNat# -> Bool
bigNatEq :: BigNat# -> BigNat# -> Bool
bigNatEq BigNat#
a BigNat#
b = Bool# -> Bool
isTrue# (BigNat# -> BigNat# -> Bool#
bigNatEq# BigNat#
a BigNat#
b)

-- | Inequality test for BigNat
bigNatNe# :: BigNat# -> BigNat# -> Bool#
bigNatNe# :: BigNat# -> BigNat# -> Bool#
bigNatNe# BigNat#
a BigNat#
b = Bool# -> Bool#
notB# (BigNat# -> BigNat# -> Bool#
bigNatEq# BigNat#
a BigNat#
b)

-- | Equality test for BigNat
bigNatNe :: BigNat# -> BigNat# -> Bool
bigNatNe :: BigNat# -> BigNat# -> Bool
bigNatNe BigNat#
a BigNat#
b = Bool# -> Bool
isTrue# (BigNat# -> BigNat# -> Bool#
bigNatNe# BigNat#
a BigNat#
b)

-- | Compare a BigNat and a Word#
bigNatCompareWord# :: BigNat# -> Word# -> Ordering
{-# NOINLINE bigNatCompareWord# #-}
bigNatCompareWord# :: BigNat# -> Word# -> Ordering
bigNatCompareWord# BigNat#
a Word#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a                   = Word# -> Word# -> Ordering
cmpW# Word#
0## Word#
b
   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
wordArraySize# BigNat#
a Bool# -> Bool# -> Bool#
># Bool#
1#) = Ordering
GT
   | Bool
True
   = Word# -> Word# -> Ordering
cmpW# (BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
0#) Word#
b

-- | Compare a BigNat and a Word
bigNatCompareWord :: BigNat# -> Word -> Ordering
bigNatCompareWord :: BigNat# -> Word -> Ordering
bigNatCompareWord BigNat#
a (W# Word#
b) = BigNat# -> Word# -> Ordering
bigNatCompareWord# BigNat#
a Word#
b

-- | Compare two BigNat
bigNatCompare :: BigNat# -> BigNat# -> Ordering
{-# NOINLINE bigNatCompare #-}
bigNatCompare :: BigNat# -> BigNat# -> Ordering
bigNatCompare BigNat#
a BigNat#
b =
   let
      szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
      szB :: Bool#
szB = BigNat# -> Bool#
wordArraySize# BigNat#
b
   in if
   | Bool# -> Bool
isTrue# (Bool#
szA Bool# -> Bool# -> Bool#
># Bool#
szB) -> Ordering
GT
   | Bool# -> Bool
isTrue# (Bool#
szA Bool# -> Bool# -> Bool#
<# Bool#
szB) -> Ordering
LT
   | Bool# -> Bool
isTrue# (Bool#
szA Bool# -> Bool# -> Bool#
==# Bool#
0#) -> Ordering
EQ
   | Bool
True                 -> Bool# -> Bool# -> Ordering
compareInt# ((BigNat# -> BigNat# -> Bool#) -> BigNat# -> BigNat# -> Bool#
forall a. a -> a
inline BigNat# -> BigNat# -> Bool#
bignat_compare BigNat#
a BigNat#
b) Bool#
0#


-- | Predicate: a < b
bigNatLt# :: BigNat# -> BigNat# -> Bool#
bigNatLt# :: BigNat# -> BigNat# -> Bool#
bigNatLt# BigNat#
a BigNat#
b
  | Ordering
LT <- BigNat# -> BigNat# -> Ordering
bigNatCompare BigNat#
a BigNat#
b = Bool#
1#
  | Bool
True                    = Bool#
0#

-- | Predicate: a < b
bigNatLt :: BigNat# -> BigNat# -> Bool
bigNatLt :: BigNat# -> BigNat# -> Bool
bigNatLt BigNat#
a BigNat#
b = Bool# -> Bool
isTrue# (BigNat# -> BigNat# -> Bool#
bigNatLt# BigNat#
a BigNat#
b)

-- | Predicate: a <= b
bigNatLe# :: BigNat# -> BigNat# -> Bool#
bigNatLe# :: BigNat# -> BigNat# -> Bool#
bigNatLe# BigNat#
a BigNat#
b
  | Ordering
GT <- BigNat# -> BigNat# -> Ordering
bigNatCompare BigNat#
a BigNat#
b = Bool#
0#
  | Bool
True                    = Bool#
1#

-- | Predicate: a <= b
bigNatLe :: BigNat# -> BigNat# -> Bool
bigNatLe :: BigNat# -> BigNat# -> Bool
bigNatLe BigNat#
a BigNat#
b = Bool# -> Bool
isTrue# (BigNat# -> BigNat# -> Bool#
bigNatLe# BigNat#
a BigNat#
b)

-- | Predicate: a > b
bigNatGt# :: BigNat# -> BigNat# -> Bool#
bigNatGt# :: BigNat# -> BigNat# -> Bool#
bigNatGt# BigNat#
a BigNat#
b
  | Ordering
GT <- BigNat# -> BigNat# -> Ordering
bigNatCompare BigNat#
a BigNat#
b = Bool#
1#
  | Bool
True                    = Bool#
0#

-- | Predicate: a > b
bigNatGt :: BigNat# -> BigNat# -> Bool
bigNatGt :: BigNat# -> BigNat# -> Bool
bigNatGt BigNat#
a BigNat#
b = Bool# -> Bool
isTrue# (BigNat# -> BigNat# -> Bool#
bigNatGt# BigNat#
a BigNat#
b)

-- | Predicate: a >= b
bigNatGe# :: BigNat# -> BigNat# -> Bool#
bigNatGe# :: BigNat# -> BigNat# -> Bool#
bigNatGe# BigNat#
a BigNat#
b
  | Ordering
LT <- BigNat# -> BigNat# -> Ordering
bigNatCompare BigNat#
a BigNat#
b = Bool#
0#
  | Bool
True                    = Bool#
1#

-- | Predicate: a >= b
bigNatGe :: BigNat# -> BigNat# -> Bool
bigNatGe :: BigNat# -> BigNat# -> Bool
bigNatGe BigNat#
a BigNat#
b = Bool# -> Bool
isTrue# (BigNat# -> BigNat# -> Bool#
bigNatGe# BigNat#
a BigNat#
b)

-------------------------------------------------
-- Addition
-------------------------------------------------

-- | Add a bigNat and a Word#
bigNatAddWord# :: BigNat# -> Word# -> BigNat#
bigNatAddWord# :: BigNat# -> Word# -> BigNat#
bigNatAddWord# BigNat#
a Word#
b
   | Word#
0## <- Word#
b
   = BigNat#
a

   | BigNat# -> Bool
bigNatIsZero BigNat#
a
   = Word# -> BigNat#
bigNatFromWord# Word#
b

   | Bool
True
   = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# (BigNat# -> Bool#
wordArraySize# BigNat#
a Bool# -> Bool# -> Bool#
+# Bool#
1#) \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
         (MutableWordArray# RealWorld
 -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> Word#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
bignat_add_word MutableWordArray# RealWorld
mwa BigNat#
a Word#
b State# RealWorld
s

-- | Add a bigNat and a Word
bigNatAddWord :: BigNat# -> Word -> BigNat#
bigNatAddWord :: BigNat# -> Word -> BigNat#
bigNatAddWord BigNat#
a (W# Word#
b) = BigNat# -> Word# -> BigNat#
bigNatAddWord# BigNat#
a Word#
b

-- | Add two bigNats
bigNatAdd :: BigNat# -> BigNat# -> BigNat#
bigNatAdd :: BigNat# -> BigNat# -> BigNat#
bigNatAdd BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = BigNat#
a
   | Bool
True =
   let
      !szA :: Bool#
szA     = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !szB :: Bool#
szB     = BigNat# -> Bool#
wordArraySize# BigNat#
b
      !szMax :: Bool#
szMax   = Bool# -> Bool# -> Bool#
maxI# Bool#
szA Bool#
szB
      !sz :: Bool#
sz      = Bool#
szMax Bool# -> Bool# -> Bool#
+# Bool#
1# -- for the potential carry
   in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
         (MutableWordArray# RealWorld
 -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
bignat_add MutableWordArray# RealWorld
mwa BigNat#
a BigNat#
b State# RealWorld
s

-------------------------------------------------
-- Multiplication
-------------------------------------------------

-- | Multiply a BigNat by a Word#
bigNatMulWord# :: BigNat# -> Word# -> BigNat#
bigNatMulWord# :: BigNat# -> Word# -> BigNat#
bigNatMulWord# BigNat#
a Word#
w
   | Word#
0## <- Word#
w       = (# #) -> BigNat#
bigNatZero# (# #)
   | Word#
1## <- Word#
w       = BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = (# #) -> BigNat#
bigNatZero# (# #)
   | BigNat# -> Bool
bigNatIsOne  BigNat#
a = Word# -> BigNat#
bigNatFromWord# Word#
w
   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
bigNatSize# BigNat#
a Bool# -> Bool# -> Bool#
==# Bool#
1#)
   = case Word# -> Word# -> (# Word#, Word# #)
timesWord2# (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
0#) Word#
w of
      (# Word#
h, Word#
l #) -> Word# -> Word# -> BigNat#
bigNatFromWord2# Word#
h Word#
l
   | Bool
True = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# (BigNat# -> Bool#
bigNatSize# BigNat#
a Bool# -> Bool# -> Bool#
+# Bool#
1#) \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
               (MutableWordArray# RealWorld
 -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> Word#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
bignat_mul_word MutableWordArray# RealWorld
mwa BigNat#
a Word#
w State# RealWorld
s

-- | Multiply a BigNAt by a Word
bigNatMulWord :: BigNat# -> Word -> BigNat#
bigNatMulWord :: BigNat# -> Word -> BigNat#
bigNatMulWord BigNat#
a (W# Word#
w) = BigNat# -> Word# -> BigNat#
bigNatMulWord# BigNat#
a Word#
w

-- | Square a BigNat
bigNatSqr :: BigNat# -> BigNat#
bigNatSqr :: BigNat# -> BigNat#
bigNatSqr BigNat#
a = BigNat# -> BigNat# -> BigNat#
bigNatMul BigNat#
a BigNat#
a
   -- This can be replaced by a backend primitive in the future (e.g. to use
   -- GMP's mpn_sqr)

-- | Multiplication (classical algorithm)
bigNatMul :: BigNat# -> BigNat# -> BigNat#
bigNatMul :: BigNat# -> BigNat# -> BigNat#
bigNatMul BigNat#
a BigNat#
b
   | BigNat# -> Word
bigNatSize BigNat#
b Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
> BigNat# -> Word
bigNatSize BigNat#
a = BigNat# -> BigNat# -> BigNat#
bigNatMul BigNat#
b BigNat#
a -- optimize loops
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = BigNat#
b
   | BigNat# -> Bool
bigNatIsOne  BigNat#
a = BigNat#
b
   | BigNat# -> Bool
bigNatIsOne  BigNat#
b = BigNat#
a
   | Bool
True =
      let
         !szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
         !szB :: Bool#
szB = BigNat# -> Bool#
wordArraySize# BigNat#
b
         !sz :: Bool#
sz  = Bool#
szA Bool# -> Bool# -> Bool#
+# Bool#
szB
      in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s->
            (MutableWordArray# RealWorld
 -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
bignat_mul MutableWordArray# RealWorld
mwa BigNat#
a BigNat#
b State# RealWorld
s


-------------------------------------------------
-- Subtraction
-------------------------------------------------

-- | Subtract a Word# from a BigNat
--
-- The BigNat must be bigger than the Word#.
bigNatSubWordUnsafe# :: BigNat# -> Word# -> BigNat#
bigNatSubWordUnsafe# :: BigNat# -> Word# -> BigNat#
bigNatSubWordUnsafe# BigNat#
x Word#
y
   | Word#
0## <- Word#
y = BigNat#
x
   | Bool
True     = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
sz \MutableWordArray# RealWorld
mwa -> MutableWordArray# RealWorld
-> Word# -> Bool# -> State# RealWorld -> State# RealWorld
forall {s}.
MutableByteArray# s -> Word# -> Bool# -> State# s -> State# s
go MutableWordArray# RealWorld
mwa Word#
y Bool#
0#
   where
      !sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
x

      go :: MutableByteArray# s -> Word# -> Bool# -> State# s -> State# s
go MutableByteArray# s
mwa Word#
carry Bool#
i State# s
s
         | Bool# -> Bool
isTrue# (Bool#
i Bool# -> Bool# -> Bool#
>=# Bool#
sz)
         = State# s
s

         | Word#
0## <- Word#
carry
         = MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableByteArray# s
mwa Bool#
i BigNat#
x Bool#
i (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
i) State# s
s

         | Bool
True
         = case Word# -> Word# -> (# Word#, Bool# #)
subWordC# (BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
x Bool#
i) Word#
carry of
            (# Word#
l, Bool#
c #) -> case MutableByteArray# s -> Bool# -> Word# -> State# s -> State# s
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableByteArray# s
mwa Bool#
i Word#
l State# s
s of
                              State# s
s1 -> MutableByteArray# s -> Word# -> Bool# -> State# s -> State# s
go MutableByteArray# s
mwa (Bool# -> Word#
int2Word# Bool#
c) (Bool#
i Bool# -> Bool# -> Bool#
+# Bool#
1#) State# s
s1

-- | Subtract a Word# from a BigNat
--
-- The BigNat must be bigger than the Word#.
bigNatSubWordUnsafe :: BigNat# -> Word -> BigNat#
bigNatSubWordUnsafe :: BigNat# -> Word -> BigNat#
bigNatSubWordUnsafe BigNat#
x (W# Word#
y) = BigNat# -> Word# -> BigNat#
bigNatSubWordUnsafe# BigNat#
x Word#
y

-- | Subtract a Word# from a BigNat
bigNatSubWord# :: BigNat# -> Word# -> (# (# #) | BigNat# #)
bigNatSubWord# :: BigNat# -> Word# -> (# (# #) | BigNat# #)
bigNatSubWord# BigNat#
a Word#
b
   | Word#
0## <- Word#
b          = (# | BigNat#
a #)
   | BigNat# -> Bool
bigNatIsZero BigNat#
a    = (# (# #) | #)
   | Bool
True
   = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, Bool# #))
-> (# (# #) | BigNat# #)
withNewWordArrayTrimmedMaybe# (BigNat# -> Bool#
bigNatSize# BigNat#
a) \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
            (MutableWordArray# RealWorld
 -> BigNat#
 -> Word#
 -> State# RealWorld
 -> (# State# RealWorld, Bool# #))
-> MutableWordArray# RealWorld
-> BigNat#
-> Word#
-> State# RealWorld
-> (# State# RealWorld, Bool# #)
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat#
-> Word#
-> State# RealWorld
-> (# State# RealWorld, Bool# #)
bignat_sub_word MutableWordArray# RealWorld
mwa BigNat#
a Word#
b State# RealWorld
s


-- | Subtract two BigNat (don't check if a >= b)
bigNatSubUnsafe :: BigNat# -> BigNat# -> BigNat#
bigNatSubUnsafe :: BigNat# -> BigNat# -> BigNat#
bigNatSubUnsafe BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = BigNat#
a
   | Bool
True =
      let szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
      in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
szA \MutableWordArray# RealWorld
mwa State# RealWorld
s->
            case (MutableWordArray# RealWorld
 -> BigNat#
 -> BigNat#
 -> State# RealWorld
 -> (# State# RealWorld, Bool# #))
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> (# State# RealWorld, Bool# #)
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> (# State# RealWorld, Bool# #)
bignat_sub MutableWordArray# RealWorld
mwa BigNat#
a BigNat#
b State# RealWorld
s of
               (# State# RealWorld
s', Bool#
1# #) -> State# RealWorld
s'
               (# State# RealWorld
s', Bool#
_  #) -> case Any
forall a. a
raiseUnderflow of
                                 !Any
_ -> State# RealWorld
s'
                                 -- see Note [ghc-bignum exceptions] in
                                 -- GHC.Num.Primitives

-- | Subtract two BigNat
bigNatSub :: BigNat# -> BigNat# -> (# (# #) | BigNat# #)
bigNatSub :: BigNat# -> BigNat# -> (# (# #) | BigNat# #)
bigNatSub BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = (# | BigNat#
a #)
   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
bigNatSize# BigNat#
a Bool# -> Bool# -> Bool#
<# BigNat# -> Bool#
bigNatSize# BigNat#
b)
   = (# (# #) | #)

   | Bool
True
   = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> (# State# RealWorld, Bool# #))
-> (# (# #) | BigNat# #)
withNewWordArrayTrimmedMaybe# (BigNat# -> Bool#
bigNatSize# BigNat#
a) \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
            (MutableWordArray# RealWorld
 -> BigNat#
 -> BigNat#
 -> State# RealWorld
 -> (# State# RealWorld, Bool# #))
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> (# State# RealWorld, Bool# #)
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> (# State# RealWorld, Bool# #)
bignat_sub MutableWordArray# RealWorld
mwa BigNat#
a BigNat#
b State# RealWorld
s


-------------------------------------------------
-- Division
-------------------------------------------------

-- | Divide a BigNat by a Word, return the quotient
--
-- Require:
--    b /= 0
bigNatQuotWord# :: BigNat# -> Word# -> BigNat#
bigNatQuotWord# :: BigNat# -> Word# -> BigNat#
bigNatQuotWord# BigNat#
a Word#
b
   | Word#
1## <- Word#
b = BigNat#
a
   | Word#
0## <- Word#
b = (# #) -> BigNat#
raiseDivZero_BigNat (# #)
   | Bool
True =
   let
      sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
a
   in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
sz \MutableWordArray# RealWorld
mwq State# RealWorld
s ->
         (MutableWordArray# RealWorld
 -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> Word#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
bignat_quot_word MutableWordArray# RealWorld
mwq BigNat#
a Word#
b State# RealWorld
s

-- | Divide a BigNat by a Word, return the quotient
--
-- Require:
--    b /= 0
bigNatQuotWord :: BigNat# -> Word -> BigNat#
bigNatQuotWord :: BigNat# -> Word -> BigNat#
bigNatQuotWord BigNat#
a (W# Word#
b) = BigNat# -> Word# -> BigNat#
bigNatQuotWord# BigNat#
a Word#
b

-- | Divide a BigNat by a Word, return the remainder
--
-- Require:
--    b /= 0
bigNatRemWord# :: BigNat# -> Word# -> Word#
bigNatRemWord# :: BigNat# -> Word# -> Word#
bigNatRemWord# BigNat#
a Word#
b
   | Word#
0## <- Word#
b       = (# #) -> Word#
raiseDivZero_Word# (# #)
   | Word#
1## <- Word#
b       = Word#
0##
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = Word#
0##
   | Bool
True           = (BigNat# -> Word# -> Word#) -> BigNat# -> Word# -> Word#
forall a. a -> a
inline BigNat# -> Word# -> Word#
bignat_rem_word BigNat#
a Word#
b

-- | Divide a BigNat by a Word, return the remainder
--
-- Require:
--    b /= 0
bigNatRemWord :: BigNat# -> Word -> Word
bigNatRemWord :: BigNat# -> Word -> Word
bigNatRemWord BigNat#
a (W# Word#
b) = Word# -> Word
W# (BigNat# -> Word# -> Word#
bigNatRemWord# BigNat#
a Word#
b)

-- | QuotRem a BigNat by a Word
--
-- Require:
--    b /= 0
bigNatQuotRemWord# :: BigNat# -> Word# -> (# BigNat#, Word# #)
bigNatQuotRemWord# :: BigNat# -> Word# -> (# BigNat#, Word# #)
bigNatQuotRemWord# BigNat#
a Word#
b
   | Word#
0## <- Word#
b = case Any
forall a. a
raiseDivZero of
                  !Any
_ -> (# (# #) -> BigNat#
bigNatZero# (# #), Word#
0## #)
                  -- see Note [ghc-bignum exceptions] in GHC.Num.Primitives
   | Word#
1## <- Word#
b = (# BigNat#
a, Word#
0## #)
   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
bigNatSize# BigNat#
a Bool# -> Bool# -> Bool#
==# Bool#
1#)
   , Word#
a0 <- BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
0#
   = case Word# -> Word# -> Ordering
compareWord# Word#
a0 Word#
b of
      Ordering
LT -> (# (# #) -> BigNat#
bigNatZero# (# #), Word#
a0  #)
      Ordering
EQ -> (# (# #) -> BigNat#
bigNatOne#  (# #), Word#
0## #)
      Ordering
GT -> case Word# -> Word# -> (# Word#, Word# #)
quotRemWord# Word#
a0 Word#
b of
               (# Word#
q, Word#
r #) -> (# Word# -> BigNat#
bigNatFromWord# Word#
q, Word#
r #)
   | Bool
True =
   let
      sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
a
      io :: State# RealWorld -> (# State# RealWorld, (# BigNat#, Word# #) #)
io State# RealWorld
s =
         case Bool#
-> State# RealWorld
-> (# State# RealWorld, MutableWordArray# RealWorld #)
forall s. Bool# -> State# s -> (# State# s, MutableWordArray# s #)
newWordArray# Bool#
sz State# RealWorld
s of { (# State# RealWorld
s1, MutableWordArray# RealWorld
mwq #) ->
         case (MutableWordArray# RealWorld
 -> BigNat#
 -> Word#
 -> State# RealWorld
 -> (# State# RealWorld, Word# #))
-> MutableWordArray# RealWorld
-> BigNat#
-> Word#
-> State# RealWorld
-> (# State# RealWorld, Word# #)
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat#
-> Word#
-> State# RealWorld
-> (# State# RealWorld, Word# #)
bignat_quotrem_word MutableWordArray# RealWorld
mwq BigNat#
a Word#
b State# RealWorld
s1 of { (# State# RealWorld
s2, Word#
r #)  ->
         case MutableWordArray# RealWorld -> State# RealWorld -> State# RealWorld
forall s. MutableByteArray# s -> State# s -> State# s
mwaTrimZeroes# MutableWordArray# RealWorld
mwq State# RealWorld
s2 of { State# RealWorld
s3 ->
         case MutableWordArray# RealWorld
-> State# RealWorld -> (# State# RealWorld, BigNat# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, BigNat# #)
unsafeFreezeByteArray# MutableWordArray# RealWorld
mwq State# RealWorld
s3 of { (# State# RealWorld
s4, BigNat#
wq #) ->
         (# State# RealWorld
s4, (# BigNat#
wq, Word#
r #) #)
         }}}}
   in case (State# RealWorld -> (# State# RealWorld, (# BigNat#, Word# #) #))
-> (# State# RealWorld, (# BigNat#, Word# #) #)
forall o. (State# RealWorld -> o) -> o
runRW# State# RealWorld -> (# State# RealWorld, (# BigNat#, Word# #) #)
io of
         (# State# RealWorld
_, (# BigNat#
wq,Word#
r #) #) -> (# BigNat#
wq, Word#
r #)


-- | BigNat division returning (quotient,remainder)
bigNatQuotRem# :: BigNat# -> BigNat# -> (# BigNat#, BigNat# #)
bigNatQuotRem# :: BigNat# -> BigNat# -> (# BigNat#, BigNat# #)
bigNatQuotRem# BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
b          = case Any
forall a. a
raiseDivZero of
                                 !Any
_ -> (# (# #) -> BigNat#
bigNatZero# (# #), (# #) -> BigNat#
bigNatZero# (# #) #)
                                 -- see Note [ghc-bignum exceptions] in GHC.Num.Primitives
   | BigNat# -> Bool
bigNatIsZero BigNat#
a          = (# (# #) -> BigNat#
bigNatZero# (# #), (# #) -> BigNat#
bigNatZero# (# #) #)
   | BigNat# -> Bool
bigNatIsOne BigNat#
b           = (# BigNat#
a                , (# #) -> BigNat#
bigNatZero# (# #) #)
   | Ordering
LT <- Ordering
cmp               = (# (# #) -> BigNat#
bigNatZero# (# #), BigNat#
a #)
   | Ordering
EQ <- Ordering
cmp               = (# (# #) -> BigNat#
bigNatOne#  (# #), (# #) -> BigNat#
bigNatZero# (# #) #)
   | Bool# -> Bool
isTrue# (Bool#
szB Bool# -> Bool# -> Bool#
==# Bool#
1#)    = case BigNat# -> Word# -> (# BigNat#, Word# #)
bigNatQuotRemWord# BigNat#
a (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
b Bool#
0#) of
                                 (# BigNat#
q, Word#
r #) -> (# BigNat#
q, Word# -> BigNat#
bigNatFromWord# Word#
r #)

   | Bool
True = Bool#
-> Bool#
-> (MutableWordArray# RealWorld
    -> MutableWordArray# RealWorld
    -> State# RealWorld
    -> State# RealWorld)
-> (# BigNat#, BigNat# #)
withNewWordArray2Trimmed# Bool#
szQ Bool#
szR \MutableWordArray# RealWorld
mwq MutableWordArray# RealWorld
mwr State# RealWorld
s ->
                     (MutableWordArray# RealWorld
 -> MutableWordArray# RealWorld
 -> BigNat#
 -> BigNat#
 -> State# RealWorld
 -> State# RealWorld)
-> MutableWordArray# RealWorld
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
bignat_quotrem MutableWordArray# RealWorld
mwq MutableWordArray# RealWorld
mwr BigNat#
a BigNat#
b State# RealWorld
s
   where
   cmp :: Ordering
cmp = BigNat# -> BigNat# -> Ordering
bigNatCompare BigNat#
a BigNat#
b
   szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
   szB :: Bool#
szB = BigNat# -> Bool#
wordArraySize# BigNat#
b
   szQ :: Bool#
szQ = Bool#
1# Bool# -> Bool# -> Bool#
+# Bool#
szA Bool# -> Bool# -> Bool#
-# Bool#
szB
   szR :: Bool#
szR = Bool#
szB


-- | BigNat division returning quotient
bigNatQuot :: BigNat# -> BigNat# -> BigNat#
bigNatQuot :: BigNat# -> BigNat# -> BigNat#
bigNatQuot BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
b          = (# #) -> BigNat#
raiseDivZero_BigNat (# #)
   | BigNat# -> Bool
bigNatIsZero BigNat#
a          = (# #) -> BigNat#
bigNatZero# (# #)
   | BigNat# -> Bool
bigNatIsOne BigNat#
b           = BigNat#
a
   | Ordering
LT <- Ordering
cmp               = (# #) -> BigNat#
bigNatZero# (# #)
   | Ordering
EQ <- Ordering
cmp               = (# #) -> BigNat#
bigNatOne# (# #)
   | Bool# -> Bool
isTrue# (Bool#
szB Bool# -> Bool# -> Bool#
==# Bool#
1#)    = BigNat# -> Word# -> BigNat#
bigNatQuotWord# BigNat#
a (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
b Bool#
0#)
   | Bool
True                    = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
szQ \MutableWordArray# RealWorld
mwq State# RealWorld
s ->
                                 (MutableWordArray# RealWorld
 -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
bignat_quot MutableWordArray# RealWorld
mwq BigNat#
a BigNat#
b State# RealWorld
s
   where
   cmp :: Ordering
cmp = BigNat# -> BigNat# -> Ordering
bigNatCompare BigNat#
a BigNat#
b
   szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
   szB :: Bool#
szB = BigNat# -> Bool#
wordArraySize# BigNat#
b
   szQ :: Bool#
szQ = Bool#
1# Bool# -> Bool# -> Bool#
+# Bool#
szA Bool# -> Bool# -> Bool#
-# Bool#
szB

-- | BigNat division returning remainder
bigNatRem :: BigNat# -> BigNat# -> BigNat#
bigNatRem :: BigNat# -> BigNat# -> BigNat#
bigNatRem BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
b          = (# #) -> BigNat#
raiseDivZero_BigNat (# #)
   | BigNat# -> Bool
bigNatIsZero BigNat#
a          = (# #) -> BigNat#
bigNatZero# (# #)
   | BigNat# -> Bool
bigNatIsOne BigNat#
b           = (# #) -> BigNat#
bigNatZero# (# #)
   | Ordering
LT <- Ordering
cmp               = BigNat#
a
   | Ordering
EQ <- Ordering
cmp               = (# #) -> BigNat#
bigNatZero# (# #)
   | Bool# -> Bool
isTrue# (Bool#
szB Bool# -> Bool# -> Bool#
==# Bool#
1#)    = case BigNat# -> Word# -> Word#
bigNatRemWord# BigNat#
a (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
b Bool#
0#) of
                                 Word#
r -> Word# -> BigNat#
bigNatFromWord# Word#
r
   | Bool
True                    = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
szR \MutableWordArray# RealWorld
mwr State# RealWorld
s ->
                                 (MutableWordArray# RealWorld
 -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
bignat_rem MutableWordArray# RealWorld
mwr BigNat#
a BigNat#
b State# RealWorld
s
   where
   cmp :: Ordering
cmp = BigNat# -> BigNat# -> Ordering
bigNatCompare BigNat#
a BigNat#
b
   szB :: Bool#
szB = BigNat# -> Bool#
wordArraySize# BigNat#
b
   szR :: Bool#
szR = Bool#
szB

-------------------------------------------------
-- GCD / LCM
-------------------------------------------------

-- Word#/Int# GCDs shouldn't be here in BigNat. However GMP provides a very fast
-- implementation so we keep this here at least until we get a native Haskell
-- implementation as fast as GMP's one. Note that these functions are used in
-- `base` (e.g. in GHC.Real)

-- | Greatest common divisor between two Word#
gcdWord# :: Word# -> Word# -> Word#
gcdWord# :: Word# -> Word# -> Word#
gcdWord# = Word# -> Word# -> Word#
bignat_gcd_word_word

-- | Greatest common divisor between two Word
gcdWord :: Word -> Word -> Word
gcdWord :: Word -> Word -> Word
gcdWord (W# Word#
x) (W# Word#
y) = Word# -> Word
W# (Word# -> Word# -> Word#
gcdWord# Word#
x Word#
y)

-- | Greatest common divisor between two Int#
--
-- __Warning__: result may become negative if (at least) one argument
-- is 'minBound'
gcdInt# :: Int# -> Int# -> Int#
gcdInt# :: Bool# -> Bool# -> Bool#
gcdInt# Bool#
x Bool#
y = Word# -> Bool#
word2Int# (Word# -> Word# -> Word#
gcdWord# (Bool# -> Word#
wordFromAbsInt# Bool#
x) (Bool# -> Word#
wordFromAbsInt# Bool#
y))

-- | Greatest common divisor between two Int
--
-- __Warning__: result may become negative if (at least) one argument
-- is 'minBound'
gcdInt :: Int -> Int -> Int
gcdInt :: Int -> Int -> Int
gcdInt (I# Bool#
x) (I# Bool#
y) = Bool# -> Int
I# (Bool# -> Bool# -> Bool#
gcdInt# Bool#
x Bool#
y)

-- | Greatest common divisor
bigNatGcd :: BigNat# -> BigNat# -> BigNat#
bigNatGcd :: BigNat# -> BigNat# -> BigNat#
bigNatGcd BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = BigNat#
a
   | BigNat# -> Bool
bigNatIsOne BigNat#
a  = BigNat#
a
   | BigNat# -> Bool
bigNatIsOne BigNat#
b  = BigNat#
b
   | Bool
True
   = case (# BigNat# -> Bool#
bigNatSize# BigNat#
a, BigNat# -> Bool#
bigNatSize# BigNat#
b #) of
      (# Bool#
1#, Bool#
1# #) -> Word# -> BigNat#
bigNatFromWord# (Word# -> Word# -> Word#
gcdWord# (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
0#)
                                                (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
b Bool#
0#))
      (# Bool#
1#, Bool#
_  #) -> Word# -> BigNat#
bigNatFromWord# (BigNat# -> Word# -> Word#
bigNatGcdWord# BigNat#
b (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
0#))
      (# Bool#
_ , Bool#
1# #) -> Word# -> BigNat#
bigNatFromWord# (BigNat# -> Word# -> Word#
bigNatGcdWord# BigNat#
a (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
b Bool#
0#))
      (# Bool#, Bool# #)
_            ->
         let
            go :: BigNat# -> BigNat# -> BigNat#
go BigNat#
wx BigNat#
wy = -- wx > wy
               Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# (BigNat# -> Bool#
wordArraySize# BigNat#
wy) \MutableWordArray# RealWorld
mwr State# RealWorld
s ->
                  MutableWordArray# RealWorld
-> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
bignat_gcd MutableWordArray# RealWorld
mwr BigNat#
wx BigNat#
wy State# RealWorld
s
         in case BigNat# -> BigNat# -> Ordering
bigNatCompare BigNat#
a BigNat#
b of
               Ordering
EQ -> BigNat#
a
               Ordering
LT -> BigNat# -> BigNat# -> BigNat#
go BigNat#
b BigNat#
a
               Ordering
GT -> BigNat# -> BigNat# -> BigNat#
go BigNat#
a BigNat#
b

-- | Greatest common divisor
bigNatGcdWord# :: BigNat# -> Word# -> Word#
bigNatGcdWord# :: BigNat# -> Word# -> Word#
bigNatGcdWord# BigNat#
a Word#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = Word#
0##
   | Word#
0## <- Word#
b       = Word#
0##
   | BigNat# -> Bool
bigNatIsOne BigNat#
a  = Word#
1##
   | Word#
1## <- Word#
b       = Word#
1##
   | Bool
True           = case BigNat# -> Word# -> Ordering
bigNatCompareWord# BigNat#
a Word#
b of
      Ordering
EQ -> Word#
b
      Ordering
_  -> BigNat# -> Word# -> Word#
bignat_gcd_word BigNat#
a Word#
b

-- | Least common multiple
bigNatLcm :: BigNat# -> BigNat# -> BigNat#
bigNatLcm :: BigNat# -> BigNat# -> BigNat#
bigNatLcm BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = (# #) -> BigNat#
bigNatZero# (# #)
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = (# #) -> BigNat#
bigNatZero# (# #)
   | BigNat# -> Bool
bigNatIsOne  BigNat#
a = BigNat#
b
   | BigNat# -> Bool
bigNatIsOne  BigNat#
b = BigNat#
a
   | Bool
True
   = case (# BigNat# -> Bool#
bigNatSize# BigNat#
a, BigNat# -> Bool#
bigNatSize# BigNat#
b #) of
      (# Bool#
1#, Bool#
1# #) -> Word# -> Word# -> BigNat#
bigNatLcmWordWord# (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
0#) (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
b Bool#
0#)
      (# Bool#
1#, Bool#
_  #) -> BigNat# -> Word# -> BigNat#
bigNatLcmWord# BigNat#
b (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
0#)
      (# Bool#
_ , Bool#
1# #) -> BigNat# -> Word# -> BigNat#
bigNatLcmWord# BigNat#
a (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
b Bool#
0#)
      (# Bool#, Bool# #)
_            -> (BigNat#
a BigNat# -> BigNat# -> BigNat#
`bigNatQuot` (BigNat#
a BigNat# -> BigNat# -> BigNat#
`bigNatGcd` BigNat#
b)) BigNat# -> BigNat# -> BigNat#
`bigNatMul` BigNat#
b
                       -- TODO: use extended GCD to get a's factor directly

-- | Least common multiple with a Word#
bigNatLcmWord# :: BigNat# -> Word# -> BigNat#
bigNatLcmWord# :: BigNat# -> Word# -> BigNat#
bigNatLcmWord# BigNat#
a Word#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a      = (# #) -> BigNat#
bigNatZero# (# #)
   | Word#
0## <- Word#
b            = (# #) -> BigNat#
bigNatZero# (# #)
   | BigNat# -> Bool
bigNatIsOne  BigNat#
a      = Word# -> BigNat#
bigNatFromWord# Word#
b
   | Word#
1## <- Word#
b            = BigNat#
a
   | Bool#
1# <- BigNat# -> Bool#
bigNatSize# BigNat#
a = Word# -> Word# -> BigNat#
bigNatLcmWordWord# (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
0#) Word#
b
   | Bool
True
   = (BigNat#
a BigNat# -> Word# -> BigNat#
`bigNatQuotWord#` (BigNat#
a BigNat# -> Word# -> Word#
`bigNatGcdWord#` Word#
b)) BigNat# -> Word# -> BigNat#
`bigNatMulWord#` Word#
b
      -- TODO: use extended GCD to get a's factor directly

-- | Least common multiple between two Word#
bigNatLcmWordWord# :: Word# -> Word# -> BigNat#
bigNatLcmWordWord# :: Word# -> Word# -> BigNat#
bigNatLcmWordWord# Word#
a Word#
b
   | Word#
0## <- Word#
a = (# #) -> BigNat#
bigNatZero# (# #)
   | Word#
0## <- Word#
b = (# #) -> BigNat#
bigNatZero# (# #)
   | Word#
1## <- Word#
a = Word# -> BigNat#
bigNatFromWord# Word#
b
   | Word#
1## <- Word#
b = Word# -> BigNat#
bigNatFromWord# Word#
a
   | Bool
True     = case (Word#
a Word# -> Word# -> Word#
`quotWord#` (Word#
a Word# -> Word# -> Word#
`gcdWord#` Word#
b)) Word# -> Word# -> (# Word#, Word# #)
`timesWord2#` Word#
b of
                     -- TODO: use extended GCD to get a's factor directly
      (# Word#
h, Word#
l #) -> Word# -> Word# -> BigNat#
bigNatFromWord2# Word#
h Word#
l


-------------------------------------------------
-- Bitwise operations
-------------------------------------------------

-- | Bitwise OR
bigNatOr :: BigNat# -> BigNat# -> BigNat#
bigNatOr :: BigNat# -> BigNat# -> BigNat#
bigNatOr BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = BigNat#
a
   | Bool
True           = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
                        (MutableWordArray# RealWorld
 -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
bignat_or MutableWordArray# RealWorld
mwa BigNat#
a BigNat#
b State# RealWorld
s
   where
      !szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !szB :: Bool#
szB = BigNat# -> Bool#
wordArraySize# BigNat#
b
      !sz :: Bool#
sz  = Bool# -> Bool# -> Bool#
maxI# Bool#
szA Bool#
szB

-- | Bitwise OR with Word#
bigNatOrWord# :: BigNat# -> Word# -> BigNat#
bigNatOrWord# :: BigNat# -> Word# -> BigNat#
bigNatOrWord# BigNat#
a Word#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = Word# -> BigNat#
bigNatFromWord# Word#
b
   | Word#
0## <- Word#
b       = BigNat#
a
   | Bool
True           =
      let sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
a
      in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
            case MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
1# BigNat#
a Bool#
1# (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#) State# RealWorld
s of
               State# RealWorld
s' -> MutableWordArray# RealWorld
-> Bool# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# RealWorld
mwa Bool#
0# (BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
0# Word# -> Word# -> Word#
`or#` Word#
b) State# RealWorld
s'

-- | Bitwise AND
bigNatAnd :: BigNat# -> BigNat# -> BigNat#
bigNatAnd :: BigNat# -> BigNat# -> BigNat#
bigNatAnd BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = BigNat#
b
   | Bool
True           = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
                        (MutableWordArray# RealWorld
 -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
bignat_and MutableWordArray# RealWorld
mwa BigNat#
a BigNat#
b State# RealWorld
s
   where
      !szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !szB :: Bool#
szB = BigNat# -> Bool#
wordArraySize# BigNat#
b
      !sz :: Bool#
sz  = Bool# -> Bool# -> Bool#
minI# Bool#
szA Bool#
szB

-- | Bitwise ANDNOT
bigNatAndNot :: BigNat# -> BigNat# -> BigNat#
bigNatAndNot :: BigNat# -> BigNat# -> BigNat#
bigNatAndNot BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = BigNat#
a
   | Bool
True           = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
szA \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
                        (MutableWordArray# RealWorld
 -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
bignat_and_not MutableWordArray# RealWorld
mwa BigNat#
a BigNat#
b State# RealWorld
s
   where
      !szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a

-- | Bitwise AND with Word#
bigNatAndWord# :: BigNat# -> Word# -> BigNat#
bigNatAndWord# :: BigNat# -> Word# -> BigNat#
bigNatAndWord# BigNat#
a Word#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = BigNat#
a
   | Bool
True           = Word# -> BigNat#
bigNatFromWord# (BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
0# Word# -> Word# -> Word#
`and#` Word#
b)

-- | Bitwise ANDNOT with Word#
bigNatAndNotWord# :: BigNat# -> Word# -> BigNat#
bigNatAndNotWord# :: BigNat# -> Word# -> BigNat#
bigNatAndNotWord# BigNat#
a Word#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a     = BigNat#
a
   | Bool#
szA <- BigNat# -> Bool#
bigNatSize# BigNat#
a
   = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
szA \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
      -- duplicate higher limbs
      case MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
1# BigNat#
a Bool#
1# (Bool#
szA Bool# -> Bool# -> Bool#
-# Bool#
1#) State# RealWorld
s of
         State# RealWorld
s' -> MutableWordArray# RealWorld
-> Bool# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
writeWordArray# MutableWordArray# RealWorld
mwa Bool#
0#
               (BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
0# Word# -> Word# -> Word#
`and#` Word# -> Word#
not# Word#
b) State# RealWorld
s'

-- | Bitwise AND with Int#
bigNatAndInt# :: BigNat# -> Int# -> BigNat#
bigNatAndInt# :: BigNat# -> Bool# -> BigNat#
bigNatAndInt# BigNat#
a Bool#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a     = BigNat#
a
   | Bool# -> Bool
isTrue# (Bool#
b Bool# -> Bool# -> Bool#
>=# Bool#
0#) = BigNat# -> Word# -> BigNat#
bigNatAndWord# BigNat#
a (Bool# -> Word#
int2Word# Bool#
b)
   | Bool#
szA <- BigNat# -> Bool#
bigNatSize# BigNat#
a
   = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
szA \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
      -- duplicate higher limbs (because of sign-extension of b)
      case MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
1# BigNat#
a Bool#
1# (Bool#
szA Bool# -> Bool# -> Bool#
-# Bool#
1#) State# RealWorld
s of
         State# RealWorld
s' -> MutableWordArray# RealWorld
-> Bool# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
writeWordArray# MutableWordArray# RealWorld
mwa Bool#
0#
               (BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
0# Word# -> Word# -> Word#
`and#` Bool# -> Word#
int2Word# Bool#
b) State# RealWorld
s'


-- | Bitwise XOR
bigNatXor :: BigNat# -> BigNat# -> BigNat#
bigNatXor :: BigNat# -> BigNat# -> BigNat#
bigNatXor BigNat#
a BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = BigNat#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = BigNat#
a
   | Bool
True           = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
                        (MutableWordArray# RealWorld
 -> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> BigNat# -> State# RealWorld -> State# RealWorld
bignat_xor MutableWordArray# RealWorld
mwa BigNat#
a BigNat#
b State# RealWorld
s
   where
      !szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !szB :: Bool#
szB = BigNat# -> Bool#
wordArraySize# BigNat#
b
      !sz :: Bool#
sz  = Bool# -> Bool# -> Bool#
maxI# Bool#
szA Bool#
szB

-- | Bitwise XOR with Word#
bigNatXorWord# :: BigNat# -> Word# -> BigNat#
bigNatXorWord# :: BigNat# -> Word# -> BigNat#
bigNatXorWord# BigNat#
a Word#
b
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = Word# -> BigNat#
bigNatFromWord# Word#
b
   | Word#
0## <- Word#
b       = BigNat#
a
   | Bool
True           =
      let
         sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
a
      in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
            case MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
1# BigNat#
a Bool#
1# (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#) State# RealWorld
s of
               State# RealWorld
s' -> MutableWordArray# RealWorld
-> Bool# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# RealWorld
mwa Bool#
0# (BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
0# Word# -> Word# -> Word#
`xor#` Word#
b) State# RealWorld
s'

-- | PopCount for BigNat
bigNatPopCount :: BigNat# -> Word
bigNatPopCount :: BigNat# -> Word
bigNatPopCount BigNat#
a = Word# -> Word
W# (BigNat# -> Word#
bigNatPopCount# BigNat#
a)

-- | PopCount for BigNat
bigNatPopCount# :: BigNat# -> Word#
bigNatPopCount# :: BigNat# -> Word#
bigNatPopCount# BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = Word#
0##
   | Bool
True           = (BigNat# -> Word#) -> BigNat# -> Word#
forall a. a -> a
inline BigNat# -> Word#
bignat_popcount BigNat#
a

-- | Bit shift right
bigNatShiftR# :: BigNat# -> Word# -> BigNat#
bigNatShiftR# :: BigNat# -> Word# -> BigNat#
bigNatShiftR# BigNat#
a Word#
n
   | Word#
0## <- Word#
n
   = BigNat#
a

   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
wordArraySize# BigNat#
a Bool# -> Bool# -> Bool#
==# Bool#
0#)
   = BigNat#
a

   | Bool#
nw <- Word# -> Bool#
word2Int# (Word#
n Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
   , Bool# -> Bool
isTrue# (Bool#
nw Bool# -> Bool# -> Bool#
>=# BigNat# -> Bool#
wordArraySize# BigNat#
a)
   = (# #) -> BigNat#
bigNatZero# (# #)

   | Bool
True
   = let
      !szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !nw :: Bool#
nw  = Word# -> Bool#
word2Int# (Word#
n Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
      !sz :: Bool#
sz  = Bool#
szA Bool# -> Bool# -> Bool#
-# Bool#
nw
     in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
         (MutableWordArray# RealWorld
 -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> Word#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
bignat_shiftr MutableWordArray# RealWorld
mwa BigNat#
a Word#
n State# RealWorld
s

-- | Bit shift right (two's complement)
bigNatShiftRNeg# :: BigNat# -> Word# -> BigNat#
bigNatShiftRNeg# :: BigNat# -> Word# -> BigNat#
bigNatShiftRNeg# BigNat#
a Word#
n
   | Word#
0## <- Word#
n
   = BigNat#
a

   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
wordArraySize# BigNat#
a Bool# -> Bool# -> Bool#
==# Bool#
0#)
   = BigNat#
a

   | Bool#
nw <- Word# -> Bool#
word2Int# (Word#
n Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
   , Bool# -> Bool
isTrue# (Bool#
nw Bool# -> Bool# -> Bool#
>=# BigNat# -> Bool#
wordArraySize# BigNat#
a)
   = (# #) -> BigNat#
bigNatZero# (# #)

   | Bool
True
   = let
      !szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !nw :: Bool#
nw  = (Word# -> Bool#
word2Int# Word#
n Bool# -> Bool# -> Bool#
-# Bool#
1#) Bool# -> Bool# -> Bool#
`uncheckedIShiftRL#` WORD_SIZE_BITS_SHIFT#
      !sz :: Bool#
sz  = Bool#
szA Bool# -> Bool# -> Bool#
-# Bool#
nw
     in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
         (MutableWordArray# RealWorld
 -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> Word#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
bignat_shiftr_neg MutableWordArray# RealWorld
mwa BigNat#
a Word#
n State# RealWorld
s


-- | Bit shift right
bigNatShiftR :: BigNat# -> Word -> BigNat#
bigNatShiftR :: BigNat# -> Word -> BigNat#
bigNatShiftR BigNat#
a (W# Word#
n) = BigNat# -> Word# -> BigNat#
bigNatShiftR# BigNat#
a Word#
n

-- | Bit shift left
bigNatShiftL :: BigNat# -> Word -> BigNat#
bigNatShiftL :: BigNat# -> Word -> BigNat#
bigNatShiftL BigNat#
a (W# Word#
n) = BigNat# -> Word# -> BigNat#
bigNatShiftL# BigNat#
a Word#
n

-- | Bit shift left
bigNatShiftL# :: BigNat# -> Word# -> BigNat#
bigNatShiftL# :: BigNat# -> Word# -> BigNat#
bigNatShiftL# BigNat#
a Word#
n
   | Word#
0## <- Word#
n
   = BigNat#
a

   | Bool# -> Bool
isTrue# (BigNat# -> Bool#
wordArraySize# BigNat#
a Bool# -> Bool# -> Bool#
==# Bool#
0#)
   = BigNat#
a

   | Bool
True
   = let
      !szA :: Bool#
szA = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !nw :: Bool#
nw  = Word# -> Bool#
word2Int# (Word#
n Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
      !nb :: Bool#
nb  = Word# -> Bool#
word2Int# (Word#
n Word# -> Word# -> Word#
`and#` WORD_SIZE_BITS_MASK##)
      !sz :: Bool#
sz   = Bool#
szA Bool# -> Bool# -> Bool#
+# Bool#
nw Bool# -> Bool# -> Bool#
+# (Bool#
nb Bool# -> Bool# -> Bool#
/=# Bool#
0#)

     in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
         (MutableWordArray# RealWorld
 -> BigNat# -> Word# -> State# RealWorld -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> Word#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat# -> Word# -> State# RealWorld -> State# RealWorld
bignat_shiftl MutableWordArray# RealWorld
mwa BigNat#
a Word#
n State# RealWorld
s


-- | BigNat bit test
bigNatTestBit# :: BigNat# -> Word# -> Bool#
bigNatTestBit# :: BigNat# -> Word# -> Bool#
bigNatTestBit# BigNat#
a Word#
n =
   let
      !sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !nw :: Bool#
nw = Word# -> Bool#
word2Int# (Word#
n Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
      !nb :: Word#
nb = Word#
n Word# -> Word# -> Word#
`and#` WORD_SIZE_BITS_MASK##
   in if
      | Bool# -> Bool
isTrue# (Bool#
nw Bool# -> Bool# -> Bool#
>=# Bool#
sz) -> Bool#
0#
      | Bool
True                -> Word# -> Word# -> Bool#
testBitW# (BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
nw) Word#
nb

-- | BigNat bit test
bigNatTestBit :: BigNat# -> Word -> Bool
bigNatTestBit :: BigNat# -> Word -> Bool
bigNatTestBit BigNat#
a (W# Word#
n) = Bool# -> Bool
isTrue# (BigNat# -> Word# -> Bool#
bigNatTestBit# BigNat#
a Word#
n)


-- | Return a BigNat whose bit `i` is the only one set.
--
-- Specialized version of `bigNatShiftL (bigNatFromWord# 1##)`
--
bigNatBit# :: Word# -> BigNat#
bigNatBit# :: Word# -> BigNat#
bigNatBit# Word#
i
   | Word#
0## <- Word#
i = (# #) -> BigNat#
bigNatOne# (# #)
   | Bool
True =
   let
      !nw :: Bool#
nw = Word# -> Bool#
word2Int# (Word#
i Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
      !nb :: Bool#
nb = Word# -> Bool#
word2Int# (Word#
i Word# -> Word# -> Word#
`and#` WORD_SIZE_BITS_MASK##)
      !sz :: Bool#
sz = Bool#
nw Bool# -> Bool# -> Bool#
+# Bool#
1#
      !v :: Word#
v  = Word#
1## Word# -> Bool# -> Word#
`uncheckedShiftL#` Bool#
nb
   in Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
         -- clear the array
         case MutableWordArray# RealWorld
-> Word# -> Word# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s
-> Word# -> Word# -> Word# -> State# s -> State# s
mwaFill# MutableWordArray# RealWorld
mwa Word#
0## Word#
0## (Bool# -> Word#
int2Word# Bool#
sz) State# RealWorld
s of
            -- set the bit in the most-significant word
            State# RealWorld
s2 -> MutableWordArray# RealWorld
-> Bool# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# RealWorld
mwa (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#) Word#
v State# RealWorld
s2

-- | Return a BigNat whose bit `i` is the only one set.
--
-- Specialized version of `bigNatShiftL (bigNatFromWord# 1##)`
--
bigNatBit :: Word -> BigNat#
bigNatBit :: Word -> BigNat#
bigNatBit (W# Word#
i) = Word# -> BigNat#
bigNatBit# Word#
i

-- | BigNat clear bit
bigNatClearBit# :: BigNat# -> Word# -> BigNat#
bigNatClearBit# :: BigNat# -> Word# -> BigNat#
bigNatClearBit# BigNat#
a Word#
n
   -- check the range validity and the current bit value
   | Bool# -> Bool
isTrue# (BigNat# -> Word# -> Bool#
bigNatTestBit# BigNat#
a Word#
n Bool# -> Bool# -> Bool#
==# Bool#
0#) = BigNat#
a
   | Bool
True
   = let
      !sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !nw :: Bool#
nw = Word# -> Bool#
word2Int# (Word#
n Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
      !nb :: Bool#
nb = Word# -> Bool#
word2Int# (Word#
n Word# -> Word# -> Word#
`and#` WORD_SIZE_BITS_MASK##)
      !nv :: Word#
nv = BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
nw Word# -> Word# -> Word#
`xor#` Bool# -> Word#
bitW# Bool#
nb
   in if
      | Bool# -> Bool
isTrue# (Bool#
sz Bool# -> Bool# -> Bool#
==# Bool#
1#)
      -> Word# -> BigNat#
bigNatFromWord# Word#
nv

      -- special case, operating on most-significant Word
      | Word#
0## <- Word#
nv
      , Bool# -> Bool
isTrue# (Bool#
nw Bool# -> Bool# -> Bool#
+# Bool#
1# Bool# -> Bool# -> Bool#
==# Bool#
sz)
      -> case Bool#
sz Bool# -> Bool# -> Bool#
-# (BigNat# -> Bool# -> Bool#
waClzAt BigNat#
a (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
2#) Bool# -> Bool# -> Bool#
+# Bool#
1#) of
            Bool#
0#  -> (# #) -> BigNat#
bigNatZero# (# #)
            Bool#
nsz -> Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
nsz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
                     MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
0# BigNat#
a Bool#
0# Bool#
nsz State# RealWorld
s

      | Bool
True ->
         Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
            case MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
0# BigNat#
a Bool#
0# Bool#
sz State# RealWorld
s of
               State# RealWorld
s' -> MutableWordArray# RealWorld
-> Bool# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
writeWordArray# MutableWordArray# RealWorld
mwa Bool#
nw Word#
nv State# RealWorld
s'

-- | BigNat set bit
bigNatSetBit# :: BigNat# -> Word# -> BigNat#
{-# NOINLINE bigNatSetBit# #-}
bigNatSetBit# :: BigNat# -> Word# -> BigNat#
bigNatSetBit# BigNat#
a Word#
n
   -- check the current bit value
   | Bool# -> Bool
isTrue# (BigNat# -> Word# -> Bool#
bigNatTestBit# BigNat#
a Word#
n) = BigNat#
a
   | Bool
True
   = let
      !sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !nw :: Bool#
nw = Word# -> Bool#
word2Int# (Word#
n Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
      !nb :: Bool#
nb = Word# -> Bool#
word2Int# (Word#
n Word# -> Word# -> Word#
`and#` WORD_SIZE_BITS_MASK##)
      d :: Bool#
d   = Bool#
nw Bool# -> Bool# -> Bool#
+# Bool#
1# Bool# -> Bool# -> Bool#
-# Bool#
sz
   in if
      -- result BigNat will have more limbs
      | Bool# -> Bool
isTrue# (Bool#
d Bool# -> Bool# -> Bool#
># Bool#
0#)
      -> Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# (Bool#
nw Bool# -> Bool# -> Bool#
+# Bool#
1#) \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
            case MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
0# BigNat#
a Bool#
0# Bool#
sz State# RealWorld
s of
               State# RealWorld
s' -> case MutableWordArray# RealWorld
-> Word# -> Word# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s
-> Word# -> Word# -> Word# -> State# s -> State# s
mwaFill# MutableWordArray# RealWorld
mwa Word#
0## (Bool# -> Word#
int2Word# Bool#
sz) (Bool# -> Word#
int2Word# (Bool#
d Bool# -> Bool# -> Bool#
-# Bool#
1#)) State# RealWorld
s' of
                  State# RealWorld
s'' -> MutableWordArray# RealWorld
-> Bool# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
writeWordArray# MutableWordArray# RealWorld
mwa Bool#
nw (Bool# -> Word#
bitW# Bool#
nb) State# RealWorld
s''

      | Word#
nv <- BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
nw Word# -> Word# -> Word#
`or#` Bool# -> Word#
bitW# Bool#
nb
      -> Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
            case MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
0# BigNat#
a Bool#
0# Bool#
sz State# RealWorld
s of
               State# RealWorld
s' -> MutableWordArray# RealWorld
-> Bool# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
writeWordArray# MutableWordArray# RealWorld
mwa Bool#
nw Word#
nv State# RealWorld
s'

-- | Reverse the given bit
bigNatComplementBit# :: BigNat# -> Word# -> BigNat#
bigNatComplementBit# :: BigNat# -> Word# -> BigNat#
bigNatComplementBit# BigNat#
a Word#
n =
   let
      !sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
a
      !nw :: Bool#
nw = Word# -> Bool#
word2Int# (Word#
n Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BITS_SHIFT#)
      !nb :: Bool#
nb = Word# -> Bool#
word2Int# (Word#
n Word# -> Word# -> Word#
`and#` WORD_SIZE_BITS_MASK##)
      d :: Bool#
d   = Bool#
nw Bool# -> Bool# -> Bool#
+# Bool#
1# Bool# -> Bool# -> Bool#
-# Bool#
sz
   in if
      -- result BigNat will have more limbs
      | Bool# -> Bool
isTrue# (Bool#
d Bool# -> Bool# -> Bool#
># Bool#
0#)
      -> Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# (Bool#
nw Bool# -> Bool# -> Bool#
+# Bool#
1#) \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
            case MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
0# BigNat#
a Bool#
0# Bool#
sz State# RealWorld
s of
               State# RealWorld
s' -> case MutableWordArray# RealWorld
-> Word# -> Word# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s
-> Word# -> Word# -> Word# -> State# s -> State# s
mwaFill# MutableWordArray# RealWorld
mwa Word#
0## (Bool# -> Word#
int2Word# Bool#
sz) (Bool# -> Word#
int2Word# (Bool#
d Bool# -> Bool# -> Bool#
-# Bool#
1#)) State# RealWorld
s' of
                  State# RealWorld
s'' -> MutableWordArray# RealWorld
-> Bool# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
writeWordArray# MutableWordArray# RealWorld
mwa Bool#
nw (Bool# -> Word#
bitW# Bool#
nb) State# RealWorld
s''

      | Word#
nv <- BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a Bool#
nw Word# -> Word# -> Word#
`xor#` Bool# -> Word#
bitW# Bool#
nb
      -> Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# Bool#
sz \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
            case MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
0# BigNat#
a Bool#
0# Bool#
sz State# RealWorld
s of
               State# RealWorld
s' -> MutableWordArray# RealWorld
-> Bool# -> Word# -> State# RealWorld -> State# RealWorld
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
writeWordArray# MutableWordArray# RealWorld
mwa Bool#
nw Word#
nv State# RealWorld
s'

-------------------------------------------------
-- Log operations
-------------------------------------------------

-- | Base 2 logarithm
bigNatLog2# :: BigNat# -> Word#
bigNatLog2# :: BigNat# -> Word#
bigNatLog2# BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = Word#
0##
   | Bool
True           =
      let i :: Word#
i = Bool# -> Word#
int2Word# (BigNat# -> Bool#
bigNatSize# BigNat#
a) Word# -> Word# -> Word#
`minusWord#` Word#
1##
      in Word# -> Word#
wordLog2# (BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
a (Word# -> Bool#
word2Int# Word#
i))
         Word# -> Word# -> Word#
`plusWord#` (Word#
i Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BITS_SHIFT#)

-- | Base 2 logarithm
bigNatLog2 :: BigNat# -> Word
bigNatLog2 :: BigNat# -> Word
bigNatLog2 BigNat#
a = Word# -> Word
W# (BigNat# -> Word#
bigNatLog2# BigNat#
a)

-- | Logarithm for an arbitrary base
bigNatLogBase# :: BigNat# -> BigNat# -> Word#
bigNatLogBase# :: BigNat# -> BigNat# -> Word#
bigNatLogBase# BigNat#
base BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
base Bool -> Bool -> Bool
|| BigNat# -> Bool
bigNatIsOne BigNat#
base
   = (# #) -> Word#
unexpectedValue_Word# (# #)

   | Bool#
1# <- BigNat# -> Bool#
bigNatSize# BigNat#
base
   , Word#
2## <- BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
base Bool#
0#
   = BigNat# -> Word#
bigNatLog2# BigNat#
a

   -- TODO: optimize log base power of 2 (256, etc.)

   | Bool
True
   = case BigNat# -> (# BigNat#, Word# #)
go BigNat#
base of (# BigNat#
_, Word#
e' #) -> Word#
e'
   where
      go :: BigNat# -> (# BigNat#, Word# #)
go BigNat#
pw = if BigNat#
a BigNat# -> BigNat# -> Bool
`bigNatLt` BigNat#
pw
         then (# BigNat#
a, Word#
0## #)
         else case BigNat# -> (# BigNat#, Word# #)
go (BigNat# -> BigNat#
bigNatSqr BigNat#
pw) of
          (# BigNat#
q, Word#
e #) -> if BigNat#
q BigNat# -> BigNat# -> Bool
`bigNatLt` BigNat#
pw
            then (# BigNat#
q, Word#
2## Word# -> Word# -> Word#
`timesWord#` Word#
e #)
            else (# BigNat#
q BigNat# -> BigNat# -> BigNat#
`bigNatQuot` BigNat#
pw
                 , (Word#
2## Word# -> Word# -> Word#
`timesWord#` Word#
e) Word# -> Word# -> Word#
`plusWord#` Word#
1## #)

-- | Logarithm for an arbitrary base
bigNatLogBase :: BigNat# -> BigNat# -> Word
bigNatLogBase :: BigNat# -> BigNat# -> Word
bigNatLogBase BigNat#
base BigNat#
a = Word# -> Word
W# (BigNat# -> BigNat# -> Word#
bigNatLogBase# BigNat#
base BigNat#
a)

-- | Logarithm for an arbitrary base
bigNatLogBaseWord# :: Word# -> BigNat# -> Word#
bigNatLogBaseWord# :: Word# -> BigNat# -> Word#
bigNatLogBaseWord# Word#
base BigNat#
a
   | Word#
0## <- Word#
base = (# #) -> Word#
unexpectedValue_Word# (# #)
   | Word#
1## <- Word#
base = (# #) -> Word#
unexpectedValue_Word# (# #)
   | Word#
2## <- Word#
base = BigNat# -> Word#
bigNatLog2# BigNat#
a
   -- TODO: optimize log base power of 2 (256, etc.)
   | Bool
True = BigNat# -> BigNat# -> Word#
bigNatLogBase# (Word# -> BigNat#
bigNatFromWord# Word#
base) BigNat#
a

-- | Logarithm for an arbitrary base
bigNatLogBaseWord :: Word -> BigNat# -> Word
bigNatLogBaseWord :: Word -> BigNat# -> Word
bigNatLogBaseWord (W# Word#
base) BigNat#
a = Word# -> Word
W# (Word# -> BigNat# -> Word#
bigNatLogBaseWord# Word#
base BigNat#
a)

-------------------------------------------------
-- Various
-------------------------------------------------

-- | Compute the number of digits of the BigNat in the given base.
--
-- `base` must be > 1
bigNatSizeInBase# :: Word# -> BigNat# -> Word#
bigNatSizeInBase# :: Word# -> BigNat# -> Word#
bigNatSizeInBase# Word#
base BigNat#
a
   | Bool# -> Bool
isTrue# (Word#
base Word# -> Word# -> Bool#
`leWord#` Word#
1##)
   = (# #) -> Word#
unexpectedValue_Word# (# #)

   | BigNat# -> Bool
bigNatIsZero BigNat#
a
   = Word#
0##

   | Bool
True
   = Word# -> BigNat# -> Word#
bigNatLogBaseWord# Word#
base BigNat#
a Word# -> Word# -> Word#
`plusWord#` Word#
1##

-- | Compute the number of digits of the BigNat in the given base.
--
-- `base` must be > 1
bigNatSizeInBase :: Word -> BigNat# -> Word
bigNatSizeInBase :: Word -> BigNat# -> Word
bigNatSizeInBase (W# Word#
w) BigNat#
a = Word# -> Word
W# (Word# -> BigNat# -> Word#
bigNatSizeInBase# Word#
w BigNat#
a)

-------------------------------------------------
-- PowMod
-------------------------------------------------

-- Word# powMod shouldn't be here in BigNat. However GMP provides a very fast
-- implementation so we keep this here at least until we get a native Haskell
-- implementation as fast as GMP's one.

powModWord# :: Word# -> Word# -> Word# -> Word#
powModWord# :: Word# -> Word# -> Word# -> Word#
powModWord# = Word# -> Word# -> Word# -> Word#
bignat_powmod_words


-- | \"@'bigNatPowModWord#' /b/ /e/ /m/@\" computes base @/b/@ raised to
-- exponent @/e/@ modulo @/m/@.
bigNatPowModWord# :: BigNat# -> BigNat# -> Word# -> Word#
bigNatPowModWord# :: BigNat# -> BigNat# -> Word# -> Word#
bigNatPowModWord# !BigNat#
_ !BigNat#
_ Word#
0## = (# #) -> Word#
raiseDivZero_Word# (# #)
bigNatPowModWord# BigNat#
_  BigNat#
_  Word#
1## = Word#
0##
bigNatPowModWord# BigNat#
b  BigNat#
e  Word#
m
   | BigNat# -> Bool
bigNatIsZero BigNat#
e         = Word#
1##
   | BigNat# -> Bool
bigNatIsZero BigNat#
b         = Word#
0##
   | BigNat# -> Bool
bigNatIsOne  BigNat#
b         = Word#
1##
   | Bool
True                   = BigNat# -> BigNat# -> Word# -> Word#
bignat_powmod_word BigNat#
b BigNat#
e Word#
m

-- | \"@'bigNatPowMod' /b/ /e/ /m/@\" computes base @/b/@ raised to
-- exponent @/e/@ modulo @/m/@.
bigNatPowMod :: BigNat# -> BigNat# -> BigNat# -> BigNat#
bigNatPowMod :: BigNat# -> BigNat# -> BigNat# -> BigNat#
bigNatPowMod !BigNat#
b !BigNat#
e !BigNat#
m
   | (# | Word#
m' #) <- BigNat# -> (# (# #) | Word# #)
bigNatToWordMaybe# BigNat#
m
   = Word# -> BigNat#
bigNatFromWord# (BigNat# -> BigNat# -> Word# -> Word#
bigNatPowModWord# BigNat#
b BigNat#
e Word#
m')
   | BigNat# -> Bool
bigNatIsZero BigNat#
m = (# #) -> BigNat#
raiseDivZero_BigNat (# #)
   | BigNat# -> Bool
bigNatIsOne  BigNat#
m = Word# -> BigNat#
bigNatFromWord# Word#
0##
   | BigNat# -> Bool
bigNatIsZero BigNat#
e = Word# -> BigNat#
bigNatFromWord# Word#
1##
   | BigNat# -> Bool
bigNatIsZero BigNat#
b = Word# -> BigNat#
bigNatFromWord# Word#
0##
   | BigNat# -> Bool
bigNatIsOne  BigNat#
b = Word# -> BigNat#
bigNatFromWord# Word#
1##
   | Bool
True           = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArrayTrimmed# (BigNat# -> Bool#
bigNatSize# BigNat#
m) \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
                         (MutableWordArray# RealWorld
 -> BigNat#
 -> BigNat#
 -> BigNat#
 -> State# RealWorld
 -> State# RealWorld)
-> MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
forall a. a -> a
inline MutableWordArray# RealWorld
-> BigNat#
-> BigNat#
-> BigNat#
-> State# RealWorld
-> State# RealWorld
bignat_powmod MutableWordArray# RealWorld
mwa BigNat#
b BigNat#
e BigNat#
m State# RealWorld
s

-- | Return count of trailing zero bits
--
-- Return 0 for zero BigNat
bigNatCtz# :: BigNat# -> Word#
bigNatCtz# :: BigNat# -> Word#
bigNatCtz# BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = Word#
0##
   | Bool
True           = Bool# -> Word# -> Word#
go Bool#
0# Word#
0##
      where
         go :: Bool# -> Word# -> Word#
go Bool#
i Word#
c = case BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
i of
            Word#
0## -> Bool# -> Word# -> Word#
go (Bool#
i Bool# -> Bool# -> Bool#
+# Bool#
1#) (Word#
c Word# -> Word# -> Word#
`plusWord#` WORD_SIZE_IN_BITS##)
            Word#
w   -> Word# -> Word#
ctz# Word#
w Word# -> Word# -> Word#
`plusWord#` Word#
c

-- | Return count of trailing zero bits
--
-- Return 0 for zero BigNat
bigNatCtz :: BigNat# -> Word
bigNatCtz :: BigNat# -> Word
bigNatCtz BigNat#
a = Word# -> Word
W# (BigNat# -> Word#
bigNatCtz# BigNat#
a)


-- | Return count of trailing zero words
--
-- Return 0 for zero BigNat
bigNatCtzWord# :: BigNat# -> Word#
bigNatCtzWord# :: BigNat# -> Word#
bigNatCtzWord# BigNat#
a
   | BigNat# -> Bool
bigNatIsZero BigNat#
a = Word#
0##
   | Bool
True           = Bool# -> Word# -> Word#
go Bool#
0# Word#
0##
      where
         go :: Bool# -> Word# -> Word#
go Bool#
i Word#
c = case BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
i of
            Word#
0## -> Bool# -> Word# -> Word#
go (Bool#
i Bool# -> Bool# -> Bool#
+# Bool#
1#) (Word#
c Word# -> Word# -> Word#
`plusWord#` Word#
1##)
            Word#
_   -> Word#
c

-- | Return count of trailing zero words
--
-- Return 0 for zero BigNat
bigNatCtzWord :: BigNat# -> Word
bigNatCtzWord :: BigNat# -> Word
bigNatCtzWord BigNat#
a = Word# -> Word
W# (BigNat# -> Word#
bigNatCtzWord# BigNat#
a)

-------------------------------------------------
-- Export to memory
-------------------------------------------------

-- | Write a BigNat in base-256 little-endian representation and return the
-- number of bytes written.
--
-- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
-- written in advance. In case of @/i/ == 0@, the function will write and report
-- zero bytes written.
bigNatToAddrLE# :: BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
{-# NOINLINE bigNatToAddrLE# #-}
bigNatToAddrLE# :: forall s. BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
bigNatToAddrLE# BigNat#
a Addr#
addr State# s
s0
   | Bool# -> Bool
isTrue# (Bool#
sz Bool# -> Bool# -> Bool#
==# Bool#
0#) = (# State# s
s0, Word#
0## #)
   | Bool
True = case State# s -> (# State# s, Word# #)
forall {s}. State# s -> (# State# s, Word# #)
writeMSB State# s
s0 of
      (# State# s
s1, Word#
k #) -> case Bool# -> State# s -> State# s
forall {s}. Bool# -> State# s -> State# s
go Bool#
0# State# s
s1 of
         State# s
s2 -> (# State# s
s2, Word#
k Word# -> Word# -> Word#
`plusWord#` (Bool# -> Word#
int2Word# Bool#
li Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#) #)
   where
     !sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
a
     !li :: Bool#
li = Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#

     writeMSB :: State# s -> (# State# s, Word# #)
writeMSB = Word# -> Addr# -> State# s -> (# State# s, Word# #)
forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
wordToAddrLE# (BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
li)
                  (Addr#
addr Addr# -> Bool# -> Addr#
`plusAddr#` (Bool#
li Bool# -> Bool# -> Bool#
`uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#))

     go :: Bool# -> State# s -> State# s
go Bool#
i State# s
s
      | Bool# -> Bool
isTrue# (Bool#
i Bool# -> Bool# -> Bool#
<# Bool#
li)
      , Bool#
off <- Bool#
i Bool# -> Bool# -> Bool#
`uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#
      , Word#
w <- BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
i
      = case Word# -> Addr# -> State# s -> State# s
forall s. Word# -> Addr# -> State# s -> State# s
wordWriteAddrLE# Word#
w (Addr#
addr Addr# -> Bool# -> Addr#
`plusAddr#` Bool#
off) State# s
s of
         State# s
s -> Bool# -> State# s -> State# s
go (Bool#
i Bool# -> Bool# -> Bool#
+# Bool#
1#) State# s
s

      | Bool
True
      = State# s
s

-- | Write a BigNat in base-256 big-endian representation and return the
-- number of bytes written.
--
-- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
-- written in advance. In case of @/i/ == 0@, the function will write and report
-- zero bytes written.
bigNatToAddrBE# :: BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
{-# NOINLINE bigNatToAddrBE# #-}
bigNatToAddrBE# :: forall s. BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
bigNatToAddrBE# BigNat#
a Addr#
addr State# s
s0
   | Bool# -> Bool
isTrue# (Bool#
sz Bool# -> Bool# -> Bool#
==# Bool#
0#) = (# State# s
s0, Word#
0## #)
   | Word#
msw <- BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#)
   = case Word# -> Addr# -> State# s -> (# State# s, Word# #)
forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
wordToAddrBE# Word#
msw Addr#
addr State# s
s0 of
      (# State# s
s1, Word#
k #) -> case Bool# -> Addr# -> State# s -> State# s
forall {s}. Bool# -> Addr# -> State# s -> State# s
go (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#) (Addr#
addr Addr# -> Bool# -> Addr#
`plusAddr#` Word# -> Bool#
word2Int# Word#
k) State# s
s1 of
         State# s
s2 -> (# State# s
s2, Word#
k Word# -> Word# -> Word#
`plusWord#` (Bool# -> Word#
int2Word# (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#) Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#) #)
   where
     sz :: Bool#
sz   = BigNat# -> Bool#
wordArraySize# BigNat#
a

     go :: Bool# -> Addr# -> State# s -> State# s
go Bool#
i Addr#
adr State# s
s
      | Bool#
0# <- Bool#
i
      = State# s
s

      | Word#
w <- BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a (Bool#
i Bool# -> Bool# -> Bool#
-# Bool#
1#)
      = case Word# -> Addr# -> State# s -> State# s
forall s. Word# -> Addr# -> State# s -> State# s
wordWriteAddrBE# Word#
w Addr#
adr State# s
s of
         State# s
s' -> Bool# -> Addr# -> State# s -> State# s
go (Bool#
i Bool# -> Bool# -> Bool#
-# Bool#
1#)
                  (Addr#
adr Addr# -> Bool# -> Addr#
`plusAddr#` WORD_SIZE_IN_BYTES# ) s'


-- | Write a BigNat in base-256 representation and return the
-- number of bytes written.
--
-- The endianness is selected with the Bool# parameter: most significant
-- byte first (big-endian) if @1#@ or least significant byte first
-- (little-endian) if @0#@.
--
-- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
-- written in advance. In case of @/i/ == 0@, the function will write and report
-- zero bytes written.
bigNatToAddr# :: BigNat# -> Addr# -> Bool# -> State# s -> (# State# s, Word# #)
bigNatToAddr# :: forall s.
BigNat# -> Addr# -> Bool# -> State# s -> (# State# s, Word# #)
bigNatToAddr# BigNat#
a Addr#
addr Bool#
0# State# s
s = BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
forall s. BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
bigNatToAddrLE# BigNat#
a Addr#
addr State# s
s
bigNatToAddr# BigNat#
a Addr#
addr Bool#
_  State# s
s = BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
forall s. BigNat# -> Addr# -> State# s -> (# State# s, Word# #)
bigNatToAddrBE# BigNat#
a Addr#
addr State# s
s

-- | Write a BigNat in base-256 representation and return the
-- number of bytes written.
--
-- The endianness is selected with the Bool# parameter: most significant
-- byte first (big-endian) if @1#@ or least significant byte first
-- (little-endian) if @0#@.
--
-- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
-- written in advance. In case of @/i/ == 0@, the function will write and report
-- zero bytes written.
bigNatToAddr :: BigNat# -> Addr# -> Bool# -> IO Word
bigNatToAddr :: BigNat# -> Addr# -> Bool# -> IO Word
bigNatToAddr BigNat#
a Addr#
addr Bool#
e = (State# RealWorld -> (# State# RealWorld, Word #)) -> IO Word
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO \State# RealWorld
s -> case BigNat#
-> Addr#
-> Bool#
-> State# RealWorld
-> (# State# RealWorld, Word# #)
forall s.
BigNat# -> Addr# -> Bool# -> State# s -> (# State# s, Word# #)
bigNatToAddr# BigNat#
a Addr#
addr Bool#
e State# RealWorld
s of
   (# State# RealWorld
s', Word#
w #) -> (# State# RealWorld
s', Word# -> Word
W# Word#
w #)



-------------------------------------------------
-- Import from memory
-------------------------------------------------

-- | Read a BigNat in base-256 little-endian representation from an Addr#.
--
-- The size is given in bytes.
--
-- Higher limbs equal to 0 are automatically trimmed.
bigNatFromAddrLE# :: Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
{-# NOINLINE bigNatFromAddrLE# #-}
bigNatFromAddrLE# :: forall s. Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
bigNatFromAddrLE# Word#
0## Addr#
_    State# s
s = (# State# s
s, (# #) -> BigNat#
bigNatZero# (# #) #)
bigNatFromAddrLE# Word#
sz  Addr#
addr State# s
s =
   let
      !nw :: Word#
nw = Word#
sz Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BYTES_SHIFT#
      !nb :: Word#
nb = Word#
sz Word# -> Word# -> Word#
`and#` WORD_SIZE_BYTES_MASK##

      readMSB :: MutableWordArray# s -> State# s -> State# s
readMSB MutableWordArray# s
mwa State# s
s
         | Word#
0## <- Word#
nb
         = State# s
s

         | Bool#
off <- Word# -> Bool#
word2Int# (Word#
nw Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#)
         = case Word# -> Addr# -> State# s -> (# State# s, Word# #)
forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
wordFromAddrLE# Word#
nb (Addr#
addr Addr# -> Bool# -> Addr#
`plusAddr#` Bool#
off) State# s
s of
            (# State# s
s, Word#
w #) -> MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# s
mwa (Word# -> Bool#
word2Int# Word#
nw) Word#
w State# s
s

      go :: MutableWordArray# s -> Bool# -> State# s -> State# s
go MutableWordArray# s
mwa Bool#
i State# s
s
         | Bool# -> Bool
isTrue# (Bool#
i Bool# -> Bool# -> Bool#
==# Word# -> Bool#
word2Int# Word#
nw)
         = State# s
s

         | Bool#
off <- Bool#
i Bool# -> Bool# -> Bool#
`uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#
         = case Word# -> Addr# -> State# s -> (# State# s, Word# #)
forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
wordFromAddrLE# WORD_SIZE_IN_BYTES## (addr State# s
`plusAddr#` off) s of
            (# State# s
s, Word#
w #) -> case MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# s
mwa Bool#
i Word#
w State# s
s of
               State# s
s -> MutableWordArray# s -> Bool# -> State# s -> State# s
go MutableWordArray# s
mwa (Bool#
i Bool# -> Bool# -> Bool#
+# Bool#
1#) State# s
s

   in case Bool# -> State# s -> (# State# s, MutableWordArray# s #)
forall s. Bool# -> State# s -> (# State# s, MutableWordArray# s #)
newWordArray# (Word# -> Bool#
word2Int# Word#
nw Bool# -> Bool# -> Bool#
+# (Word# -> Bool#
word2Int# Word#
nb Bool# -> Bool# -> Bool#
/=# Bool#
0#)) State# s
s of
         (# State# s
s, MutableWordArray# s
mwa #) -> case MutableWordArray# s -> State# s -> State# s
forall s. MutableByteArray# s -> State# s -> State# s
readMSB MutableWordArray# s
mwa State# s
s of
            State# s
s -> case MutableWordArray# s -> Bool# -> State# s -> State# s
forall {s}. MutableWordArray# s -> Bool# -> State# s -> State# s
go MutableWordArray# s
mwa Bool#
0# State# s
s of
               State# s
s -> case MutableWordArray# s -> State# s -> State# s
forall s. MutableByteArray# s -> State# s -> State# s
mwaTrimZeroes# MutableWordArray# s
mwa State# s
s of
                  State# s
s -> MutableWordArray# s -> State# s -> (# State# s, BigNat# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, BigNat# #)
unsafeFreezeByteArray# MutableWordArray# s
mwa State# s
s

-- | Read a BigNat in base-256 big-endian representation from an Addr#.
--
-- The size is given in bytes.
--
-- Null higher limbs are automatically trimmed.
bigNatFromAddrBE# :: Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
{-# NOINLINE bigNatFromAddrBE# #-}
bigNatFromAddrBE# :: forall s. Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
bigNatFromAddrBE# Word#
0## Addr#
_    State# s
s = (# State# s
s, (# #) -> BigNat#
bigNatZero# (# #) #)
bigNatFromAddrBE# Word#
sz  Addr#
addr State# s
s =
   let
      !nw :: Bool#
nw = Word# -> Bool#
word2Int# (Word#
sz Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BYTES_SHIFT#)
      !nb :: Word#
nb = Word#
sz Word# -> Word# -> Word#
`and#` WORD_SIZE_BYTES_MASK##

      goMSB :: MutableWordArray# s -> State# s -> State# s
goMSB MutableWordArray# s
mwa State# s
s
         | Word#
0## <- Word#
nb
         = State# s
s

         | Bool
True
         = case Word# -> Addr# -> State# s -> (# State# s, Word# #)
forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
wordFromAddrBE# Word#
nb Addr#
addr State# s
s of
            (# State# s
s, Word#
w #) -> MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# s
mwa Bool#
nw Word#
w State# s
s

      go :: MutableWordArray# s -> Bool# -> State# s -> State# s
go MutableWordArray# s
mwa Bool#
i State# s
s
         | Bool# -> Bool
isTrue# (Bool#
i Bool# -> Bool# -> Bool#
==# Bool#
nw)
         = State# s
s

         | Bool#
k <- Bool#
nw Bool# -> Bool# -> Bool#
-# Bool#
1# Bool# -> Bool# -> Bool#
-# Bool#
i
         , Bool#
off <- (Bool#
k Bool# -> Bool# -> Bool#
`uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#) +# word2Int# nb
         = case Word# -> Addr# -> State# s -> (# State# s, Word# #)
forall s. Word# -> Addr# -> State# s -> (# State# s, Word# #)
wordFromAddrBE# WORD_SIZE_IN_BYTES## (addr State# s
`plusAddr#` off) s of
            (# State# s
s, Word#
w #) -> case MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# s
mwa Bool#
i Word#
w State# s
s of
               State# s
s -> MutableWordArray# s -> Bool# -> State# s -> State# s
go MutableWordArray# s
mwa (Bool#
i Bool# -> Bool# -> Bool#
+# Bool#
1#) State# s
s

   in case Bool# -> State# s -> (# State# s, MutableWordArray# s #)
forall s. Bool# -> State# s -> (# State# s, MutableWordArray# s #)
newWordArray# (Bool#
nw Bool# -> Bool# -> Bool#
+# (Word# -> Bool#
word2Int# Word#
nb Bool# -> Bool# -> Bool#
/=# Bool#
0#)) State# s
s of
         (# State# s
s, MutableWordArray# s
mwa #) -> case MutableWordArray# s -> State# s -> State# s
forall s. MutableByteArray# s -> State# s -> State# s
goMSB MutableWordArray# s
mwa State# s
s of
            State# s
s -> case MutableWordArray# s -> Bool# -> State# s -> State# s
forall {s}. MutableWordArray# s -> Bool# -> State# s -> State# s
go MutableWordArray# s
mwa Bool#
0# State# s
s of
               State# s
s -> case MutableWordArray# s -> State# s -> State# s
forall s. MutableByteArray# s -> State# s -> State# s
mwaTrimZeroes# MutableWordArray# s
mwa State# s
s of
                  State# s
s -> MutableWordArray# s -> State# s -> (# State# s, BigNat# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, BigNat# #)
unsafeFreezeByteArray# MutableWordArray# s
mwa State# s
s

-- | Read a BigNat in base-256 representation from an Addr#.
--
-- The size is given in bytes.
--
-- The endianness is selected with the Bool# parameter: most significant
-- byte first (big-endian) if @1#@ or least significant byte first
-- (little-endian) if @0#@.
--
-- Null higher limbs are automatically trimmed.
bigNatFromAddr# :: Word# -> Addr# -> Bool# -> State# s -> (# State# s, BigNat# #)
bigNatFromAddr# :: forall s.
Word# -> Addr# -> Bool# -> State# s -> (# State# s, BigNat# #)
bigNatFromAddr# Word#
sz Addr#
addr Bool#
0# State# s
s = Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
forall s. Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
bigNatFromAddrLE# Word#
sz Addr#
addr State# s
s
bigNatFromAddr# Word#
sz Addr#
addr Bool#
_  State# s
s = Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
forall s. Word# -> Addr# -> State# s -> (# State# s, BigNat# #)
bigNatFromAddrBE# Word#
sz Addr#
addr State# s
s

-------------------------------------------------
-- Export to ByteArray
-------------------------------------------------

-- | Write a BigNat in base-256 little-endian representation and return the
-- number of bytes written.
--
-- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
-- written in advance. In case of @/i/ == 0@, the function will write and report
-- zero bytes written.
bigNatToMutableByteArrayLE# :: BigNat# -> MutableByteArray# s -> Word# -> State# s -> (# State# s, Word# #)
{-# NOINLINE bigNatToMutableByteArrayLE# #-}
bigNatToMutableByteArrayLE# :: forall s.
BigNat#
-> MutableByteArray# s
-> Word#
-> State# s
-> (# State# s, Word# #)
bigNatToMutableByteArrayLE# BigNat#
a MutableByteArray# s
mba Word#
moff State# s
s0
   | Bool# -> Bool
isTrue# (Bool#
sz Bool# -> Bool# -> Bool#
==# Bool#
0#) = (# State# s
s0, Word#
0## #)
   | Bool
True = case State# s -> (# State# s, Word# #)
writeMSB State# s
s0 of
      (# State# s
s1, Word#
k #) -> case Bool# -> State# s -> State# s
go Bool#
0# State# s
s1 of
         State# s
s2 -> (# State# s
s2, Word#
k Word# -> Word# -> Word#
`plusWord#` (Bool# -> Word#
int2Word# Bool#
li Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#) #)
   where
     !sz :: Bool#
sz = BigNat# -> Bool#
wordArraySize# BigNat#
a
     !li :: Bool#
li = Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#

     writeMSB :: State# s -> (# State# s, Word# #)
writeMSB = Word#
-> MutableByteArray# s
-> Word#
-> State# s
-> (# State# s, Word# #)
forall s.
Word#
-> MutableByteArray# s
-> Word#
-> State# s
-> (# State# s, Word# #)
wordToMutableByteArrayLE# (BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
li)
                  MutableByteArray# s
mba (Word#
moff Word# -> Word# -> Word#
`plusWord#` Bool# -> Word#
int2Word# (Bool#
li Bool# -> Bool# -> Bool#
`uncheckedIShiftL#` WORD_SIZE_BYTES_SHIFT#))

     go :: Bool# -> State# s -> State# s
go Bool#
i State# s
s
      | Bool# -> Bool
isTrue# (Bool#
i Bool# -> Bool# -> Bool#
<# Bool#
li)
      , Word#
off <- Bool# -> Word#
int2Word# Bool#
i Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#
      , Word#
w <- BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a Bool#
i
      = case Word# -> MutableByteArray# s -> Word# -> State# s -> State# s
forall s.
Word# -> MutableByteArray# s -> Word# -> State# s -> State# s
wordWriteMutableByteArrayLE# Word#
w MutableByteArray# s
mba (Word#
moff Word# -> Word# -> Word#
`plusWord#` Word#
off) State# s
s of
         State# s
s -> Bool# -> State# s -> State# s
go (Bool#
i Bool# -> Bool# -> Bool#
+# Bool#
1#) State# s
s

      | Bool
True
      = State# s
s

-- | Write a BigNat in base-256 big-endian representation and return the
-- number of bytes written.
--
-- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
-- written in advance. In case of @/i/ == 0@, the function will write and report
-- zero bytes written.
bigNatToMutableByteArrayBE# :: BigNat# -> MutableByteArray# s -> Word# -> State# s -> (# State# s, Word# #)
{-# NOINLINE bigNatToMutableByteArrayBE# #-}
bigNatToMutableByteArrayBE# :: forall s.
BigNat#
-> MutableByteArray# s
-> Word#
-> State# s
-> (# State# s, Word# #)
bigNatToMutableByteArrayBE# BigNat#
a MutableByteArray# s
mba Word#
moff State# s
s0
   | Bool# -> Bool
isTrue# (Bool#
sz Bool# -> Bool# -> Bool#
==# Bool#
0#) = (# State# s
s0, Word#
0## #)
   | Word#
msw <- BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#)
   = case Word#
-> MutableByteArray# s
-> Word#
-> State# s
-> (# State# s, Word# #)
forall s.
Word#
-> MutableByteArray# s
-> Word#
-> State# s
-> (# State# s, Word# #)
wordToMutableByteArrayBE# Word#
msw MutableByteArray# s
mba Word#
moff State# s
s0 of
      (# State# s
s1, Word#
k #) -> case Bool# -> Word# -> State# s -> State# s
go (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#) Word#
k State# s
s1 of
         State# s
s2 -> (# State# s
s2, Word#
k Word# -> Word# -> Word#
`plusWord#` (Bool# -> Word#
int2Word# (Bool#
sz Bool# -> Bool# -> Bool#
-# Bool#
1#) Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#) #)
   where
     sz :: Bool#
sz   = BigNat# -> Bool#
wordArraySize# BigNat#
a

     go :: Bool# -> Word# -> State# s -> State# s
go Bool#
i Word#
c State# s
s
      | Bool#
0# <- Bool#
i
      = State# s
s

      | Word#
w <- BigNat# -> Bool# -> Word#
indexWordArray# BigNat#
a (Bool#
i Bool# -> Bool# -> Bool#
-# Bool#
1#)
      = case Word# -> MutableByteArray# s -> Word# -> State# s -> State# s
forall s.
Word# -> MutableByteArray# s -> Word# -> State# s -> State# s
wordWriteMutableByteArrayBE# Word#
w MutableByteArray# s
mba (Word#
moff Word# -> Word# -> Word#
`plusWord#` Word#
c) State# s
s of
         State# s
s' -> Bool# -> Word# -> State# s -> State# s
go (Bool#
i Bool# -> Bool# -> Bool#
-# Bool#
1#)
                  (Word#
c Word# -> Word# -> Word#
`plusWord#` WORD_SIZE_IN_BYTES## ) s'


-- | Write a BigNat in base-256 representation and return the
-- number of bytes written.
--
-- The endianness is selected with the Bool# parameter: most significant
-- byte first (big-endian) if @1#@ or least significant byte first
-- (little-endian) if @0#@.
--
-- Use \"@'bigNatSizeInBase' 256# /i/@\" to compute the exact number of bytes
-- written in advance. In case of @/i/ == 0@, the function will write and report
-- zero bytes written.
bigNatToMutableByteArray# :: BigNat# -> MutableByteArray# s -> Word# -> Bool# -> State# s -> (# State# s, Word# #)
bigNatToMutableByteArray# :: forall s.
BigNat#
-> MutableByteArray# s
-> Word#
-> Bool#
-> State# s
-> (# State# s, Word# #)
bigNatToMutableByteArray# BigNat#
a MutableByteArray# s
mba Word#
off Bool#
0# State# s
s = BigNat#
-> MutableByteArray# s
-> Word#
-> State# s
-> (# State# s, Word# #)
forall s.
BigNat#
-> MutableByteArray# s
-> Word#
-> State# s
-> (# State# s, Word# #)
bigNatToMutableByteArrayLE# BigNat#
a MutableByteArray# s
mba Word#
off State# s
s
bigNatToMutableByteArray# BigNat#
a MutableByteArray# s
mba Word#
off Bool#
_  State# s
s = BigNat#
-> MutableByteArray# s
-> Word#
-> State# s
-> (# State# s, Word# #)
forall s.
BigNat#
-> MutableByteArray# s
-> Word#
-> State# s
-> (# State# s, Word# #)
bigNatToMutableByteArrayBE# BigNat#
a MutableByteArray# s
mba Word#
off State# s
s

-------------------------------------------------
-- Import from ByteArray
-------------------------------------------------

-- | Read a BigNat in base-256 little-endian representation from a ByteArray#.
--
-- The size is given in bytes.
--
-- Null higher limbs are automatically trimmed.
bigNatFromByteArrayLE# :: Word# -> ByteArray# -> Word# -> State# s -> (# State# s, BigNat# #)
{-# NOINLINE bigNatFromByteArrayLE# #-}
bigNatFromByteArrayLE# :: forall s.
Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
bigNatFromByteArrayLE# Word#
0## BigNat#
_  Word#
_    State# s
s = (# State# s
s, (# #) -> BigNat#
bigNatZero# (# #) #)
bigNatFromByteArrayLE# Word#
sz  BigNat#
ba Word#
moff State# s
s =
   let
      !nw :: Word#
nw = Word#
sz Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BYTES_SHIFT#
      !nb :: Word#
nb = Word#
sz Word# -> Word# -> Word#
`and#` WORD_SIZE_BYTES_MASK##

      readMSB :: MutableWordArray# s -> State# s -> State# s
readMSB MutableWordArray# s
mwa State# s
s
         | Word#
0## <- Word#
nb
         = State# s
s

         | Word#
off <- Word#
nw Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#
         = case Word# -> BigNat# -> Word# -> Word#
wordFromByteArrayLE# Word#
nb BigNat#
ba (Word#
moff Word# -> Word# -> Word#
`plusWord#` Word#
off) of
               Word#
w -> MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# s
mwa (Word# -> Bool#
word2Int# Word#
nw) Word#
w State# s
s

      go :: MutableWordArray# s -> Word# -> State# s -> State# s
go MutableWordArray# s
mwa Word#
i State# s
s
         | Bool# -> Bool
isTrue# (Word#
i Word# -> Word# -> Bool#
`eqWord#` Word#
nw)
         = State# s
s

         | Word#
off <- Word#
i Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#
         = case Word# -> BigNat# -> Word# -> Word#
wordFromByteArrayLE# WORD_SIZE_IN_BYTES## ba (moff `plusWord#` off) of
               Word#
w -> case MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# s
mwa (Word# -> Bool#
word2Int# Word#
i) Word#
w State# s
s of
                  State# s
s -> MutableWordArray# s -> Word# -> State# s -> State# s
go MutableWordArray# s
mwa (Word#
i Word# -> Word# -> Word#
`plusWord#` Word#
1##) State# s
s

   in case Bool# -> State# s -> (# State# s, MutableWordArray# s #)
forall s. Bool# -> State# s -> (# State# s, MutableWordArray# s #)
newWordArray# (Word# -> Bool#
word2Int# Word#
nw Bool# -> Bool# -> Bool#
+# (Word# -> Bool#
word2Int# Word#
nb Bool# -> Bool# -> Bool#
/=# Bool#
0#)) State# s
s of
         (# State# s
s, MutableWordArray# s
mwa #) -> case MutableWordArray# s -> State# s -> State# s
forall s. MutableByteArray# s -> State# s -> State# s
readMSB MutableWordArray# s
mwa State# s
s of
            State# s
s -> case MutableWordArray# s -> Word# -> State# s -> State# s
forall {s}. MutableWordArray# s -> Word# -> State# s -> State# s
go MutableWordArray# s
mwa Word#
0## State# s
s of
               State# s
s -> case MutableWordArray# s -> State# s -> State# s
forall s. MutableByteArray# s -> State# s -> State# s
mwaTrimZeroes# MutableWordArray# s
mwa State# s
s of
                  State# s
s -> MutableWordArray# s -> State# s -> (# State# s, BigNat# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, BigNat# #)
unsafeFreezeByteArray# MutableWordArray# s
mwa State# s
s

-- | Read a BigNat in base-256 big-endian representation from a ByteArray#.
--
-- The size is given in bytes.
--
-- Null higher limbs are automatically trimmed.
bigNatFromByteArrayBE# :: Word# -> ByteArray# -> Word# -> State# s -> (# State# s, BigNat# #)
{-# NOINLINE bigNatFromByteArrayBE# #-}
bigNatFromByteArrayBE# :: forall s.
Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
bigNatFromByteArrayBE# Word#
0## BigNat#
_  Word#
_    State# s
s = (# State# s
s, (# #) -> BigNat#
bigNatZero# (# #) #)
bigNatFromByteArrayBE# Word#
sz  BigNat#
ba Word#
moff State# s
s =
   let
      !nw :: Word#
nw = Word#
sz Word# -> Bool# -> Word#
`uncheckedShiftRL#` WORD_SIZE_BYTES_SHIFT#
      !nb :: Word#
nb = Word#
sz Word# -> Word# -> Word#
`and#` WORD_SIZE_BYTES_MASK##

      goMSB :: MutableWordArray# s -> State# s -> State# s
goMSB MutableWordArray# s
mwa State# s
s
         | Word#
0## <- Word#
nb
         = State# s
s

         | Bool
True
         = case Word# -> BigNat# -> Word# -> Word#
wordFromByteArrayBE# Word#
nb BigNat#
ba Word#
moff of
            Word#
w -> MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# s
mwa (Word# -> Bool#
word2Int# Word#
nw) Word#
w State# s
s

      go :: MutableWordArray# s -> Word# -> State# s -> State# s
go MutableWordArray# s
mwa Word#
i State# s
s
         | Bool# -> Bool
isTrue# (Word#
i Word# -> Word# -> Bool#
`eqWord#` Word#
nw)
         = State# s
s

         | Word#
k <- Word#
nw Word# -> Word# -> Word#
`minusWord#` Word#
1## Word# -> Word# -> Word#
`minusWord#` Word#
i
         , Word#
off <- (Word#
k Word# -> Bool# -> Word#
`uncheckedShiftL#` WORD_SIZE_BYTES_SHIFT#) `plusWord#` nb
         = case Word# -> BigNat# -> Word# -> Word#
wordFromByteArrayBE# WORD_SIZE_IN_BYTES## ba (moff `plusWord#` off) of
            Word#
w -> case MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
forall s.
MutableWordArray# s -> Bool# -> Word# -> State# s -> State# s
mwaWrite# MutableWordArray# s
mwa (Word# -> Bool#
word2Int# Word#
i) Word#
w State# s
s of
               State# s
s -> MutableWordArray# s -> Word# -> State# s -> State# s
go MutableWordArray# s
mwa (Word#
i Word# -> Word# -> Word#
`plusWord#` Word#
1##) State# s
s

   in case Bool# -> State# s -> (# State# s, MutableWordArray# s #)
forall s. Bool# -> State# s -> (# State# s, MutableWordArray# s #)
newWordArray# (Word# -> Bool#
word2Int# Word#
nw Bool# -> Bool# -> Bool#
+# (Word# -> Bool#
word2Int# Word#
nb Bool# -> Bool# -> Bool#
/=# Bool#
0#)) State# s
s of
         (# State# s
s, MutableWordArray# s
mwa #) -> case MutableWordArray# s -> State# s -> State# s
forall s. MutableByteArray# s -> State# s -> State# s
goMSB MutableWordArray# s
mwa State# s
s of
            State# s
s -> case MutableWordArray# s -> Word# -> State# s -> State# s
forall {s}. MutableWordArray# s -> Word# -> State# s -> State# s
go MutableWordArray# s
mwa Word#
0## State# s
s of
               State# s
s -> case MutableWordArray# s -> State# s -> State# s
forall s. MutableByteArray# s -> State# s -> State# s
mwaTrimZeroes# MutableWordArray# s
mwa State# s
s of
                  State# s
s -> MutableWordArray# s -> State# s -> (# State# s, BigNat# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, BigNat# #)
unsafeFreezeByteArray# MutableWordArray# s
mwa State# s
s

-- | Read a BigNat in base-256 representation from a ByteArray#.
--
-- The size is given in bytes.
--
-- The endianness is selected with the Bool# parameter: most significant
-- byte first (big-endian) if @1#@ or least significant byte first
-- (little-endian) if @0#@.
--
-- Null higher limbs are automatically trimmed.
bigNatFromByteArray# :: Word# -> ByteArray# -> Word# -> Bool# -> State# s -> (# State# s, BigNat# #)
bigNatFromByteArray# :: forall s.
Word#
-> BigNat# -> Word# -> Bool# -> State# s -> (# State# s, BigNat# #)
bigNatFromByteArray# Word#
sz BigNat#
ba Word#
off Bool#
0# State# s
s = Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
forall s.
Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
bigNatFromByteArrayLE# Word#
sz BigNat#
ba Word#
off State# s
s
bigNatFromByteArray# Word#
sz BigNat#
ba Word#
off Bool#
_  State# s
s = Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
forall s.
Word# -> BigNat# -> Word# -> State# s -> (# State# s, BigNat# #)
bigNatFromByteArrayBE# Word#
sz BigNat#
ba Word#
off State# s
s




-- | Create a BigNat# from a WordArray# containing /n/ limbs in
-- least-significant-first order.
--
-- If possible 'WordArray#', will be used directly (i.e. shared
-- /without/ cloning the 'WordArray#' into a newly allocated one)
bigNatFromWordArray# :: WordArray# -> Word# -> BigNat#
{-# NOINLINE bigNatFromWordArray# #-}
bigNatFromWordArray# :: BigNat# -> Word# -> BigNat#
bigNatFromWordArray# BigNat#
wa Word#
n0
   | Bool# -> Bool
isTrue# (Word#
n Word# -> Word# -> Bool#
`eqWord#` Word#
0##)
   = (# #) -> BigNat#
bigNatZero# (# #)

   | Bool# -> Bool
isTrue# (Word#
r Word# -> Word# -> Bool#
`eqWord#` Word#
0##) -- i.e. wa is multiple of limb-size
   , Bool# -> Bool
isTrue# (Word#
q Word# -> Word# -> Bool#
`eqWord#` Word#
n)
   = BigNat#
wa

   | Bool
True = Bool#
-> (MutableWordArray# RealWorld
    -> State# RealWorld -> State# RealWorld)
-> BigNat#
withNewWordArray# (Word# -> Bool#
word2Int# Word#
n) \MutableWordArray# RealWorld
mwa State# RealWorld
s ->
               MutableWordArray# RealWorld
-> Bool#
-> BigNat#
-> Bool#
-> Bool#
-> State# RealWorld
-> State# RealWorld
forall s.
MutableByteArray# s
-> Bool# -> BigNat# -> Bool# -> Bool# -> State# s -> State# s
mwaArrayCopy# MutableWordArray# RealWorld
mwa Bool#
0# BigNat#
wa Bool#
0# (Word# -> Bool#
word2Int# Word#
n) State# RealWorld
s
   where
      !(# Word#
q, Word#
r #) = Word# -> Word# -> (# Word#, Word# #)
quotRemWord# (Bool# -> Word#
int2Word# (BigNat# -> Bool#
sizeofByteArray# BigNat#
wa))
                                 WORD_SIZE_IN_BYTES##
      -- find real size in Words by removing trailing null limbs
      !n :: Word#
n = Word# -> Word#
real_size Word#
n0
      real_size :: Word# -> Word#
real_size Word#
0## = Word#
0##
      real_size Word#
i
           | Word#
0## <- BigNat# -> Bool# -> Word#
bigNatIndex# BigNat#
wa (Word# -> Bool#
word2Int# (Word#
i Word# -> Word# -> Word#
`minusWord#` Word#
1##))
           = Word# -> Word#
real_size (Word#
i Word# -> Word# -> Word#
`minusWord#` Word#
1##)
      real_size Word#
i = Word#
i


-- | Create a BigNat from a WordArray# containing /n/ limbs in
-- least-significant-first order.
--
-- If possible 'WordArray#', will be used directly (i.e. shared
-- /without/ cloning the 'WordArray#' into a newly allocated one)
bigNatFromWordArray :: WordArray# -> Word# -> BigNat
bigNatFromWordArray :: BigNat# -> Word# -> BigNat
bigNatFromWordArray BigNat#
wa Word#
n = BigNat# -> BigNat
BN# (BigNat# -> Word# -> BigNat#
bigNatFromWordArray# BigNat#
wa Word#
n)

-------------------------------------------------
-- Instances
-------------------------------------------------

instance Eq BigNat where
   BN# BigNat#
a == :: BigNat -> BigNat -> Bool
== BN# BigNat#
b = BigNat# -> BigNat# -> Bool
bigNatEq BigNat#
a BigNat#
b
   BN# BigNat#
a /= :: BigNat -> BigNat -> Bool
/= BN# BigNat#
b = BigNat# -> BigNat# -> Bool
bigNatNe BigNat#
a BigNat#
b

instance Ord BigNat where
   (BN# BigNat#
a) compare :: BigNat -> BigNat -> Ordering
`compare` (BN# BigNat#
b) = BigNat# -> BigNat# -> Ordering
bigNatCompare BigNat#
a BigNat#
b
   BN# BigNat#
a < :: BigNat -> BigNat -> Bool
<  BN# BigNat#
b = BigNat# -> BigNat# -> Bool
bigNatLt BigNat#
a BigNat#
b
   BN# BigNat#
a <= :: BigNat -> BigNat -> Bool
<= BN# BigNat#
b = BigNat# -> BigNat# -> Bool
bigNatLe BigNat#
a BigNat#
b
   BN# BigNat#
a > :: BigNat -> BigNat -> Bool
>  BN# BigNat#
b = BigNat# -> BigNat# -> Bool
bigNatGt BigNat#
a BigNat#
b
   BN# BigNat#
a >= :: BigNat -> BigNat -> Bool
>= BN# BigNat#
b = BigNat# -> BigNat# -> Bool
bigNatGe BigNat#
a BigNat#
b