content: \begin{code}
  {-# LANGUAGE BangPatterns, CPP, MagicHash, NoImplicitPrelude #-}
  {-# OPTIONS_HADDOCK hide #-}
  
  #define INT_MINBOUND (-2147483648#)
  #define NEG_INT_MINBOUND (S# 2147483647# `plusInteger` S# 1#)
  
  module GHC.Integer.Type where
  
  import GHC.Prim
  
  import GHC.Integer.GMP.Prim (
      -- GMP-related primitives
      cmpInteger#, cmpIntegerInt#,
      plusInteger#, minusInteger#, timesInteger#,
      quotRemInteger#, quotInteger#, remInteger#,
      divModInteger#, divInteger#, modInteger#,
      decodeDouble#,
      int2Integer#, integer2Int#, word2Integer#, integer2Word#,
      andInteger#, orInteger#, xorInteger#, complementInteger#,
      int64ToInteger#,  integerToInt64#,
      word64ToInteger#, integerToWord64#,
      shiftLInteger#, shiftRInteger#, toFloat#, toDouble#,
      negateInteger#, integerToJSString#, fromRat#
   )
  
  import GHC.IntWord64 (
              Int64#, Word64#,
              int64ToWord64#, intToInt64#,
              int64ToInt#, word64ToInt64#,
              geInt64#, leInt64#, leWord64#,
         )
  
  import GHC.Classes
  import GHC.Types
  
  default ()
  \end{code}
  
  %*********************************************************
  %*                                                      *
  \subsection{The @Integer@ type}
  %*                                                      *
  %*********************************************************
  
  Convenient boxed Integer PrimOps.
  
  \begin{code}
  -- | Arbitrary-precision integers.
  data Integer
     = S# Int#                       -- small integers
     | J# ByteArray#                 -- large integers
  
  mkInteger :: Bool   -- non-negative?
            -> [Int]  -- absolute value in 31 bit chunks, least significant first
                      -- ideally these would be Words rather than Ints, but
                      -- we don't have Word available at the moment.
            -> Integer
  mkInteger nonNegative is = let abs = f is
                             in if nonNegative then abs else negateInteger abs
      where f [] = S# 0#
            f (I# i : is') = S# i `orInteger` shiftLInteger (f is') 31#
  
  {-# NOINLINE smallInteger #-}
  smallInteger :: Int# -> Integer
  smallInteger i = S# i
  
  {-# NOINLINE wordToInteger #-}
  wordToInteger :: Word# -> Integer
  wordToInteger w = J# (word2Integer# w)
  
  {-# RULES
  "integerToInt/smallInteger"   forall x . integerToInt  (smallInteger  x) = x
  "integerToWord/wordToInteger" forall x . integerToWord (wordToInteger x) = x
   #-}
  
  {-# NOINLINE integerToWord #-}
  integerToWord :: Integer -> Word#
  integerToWord (S# i) = int2Word# i
  integerToWord (J# n) = integer2Word# n
  
  {-# NOINLINE integerToWord64 #-}
  integerToWord64 :: Integer -> Word64#
  integerToWord64 (S# i) = int64ToWord64# (intToInt64# i)
  integerToWord64 (J# n) = integerToWord64# n
  
  {-# NOINLINE word64ToInteger #-}
  word64ToInteger :: Word64# -> Integer
  word64ToInteger w = if isTrue# (w `leWord64#` int64ToWord64# (intToInt64# 0x7FFFFFFF#))
                      then S# (int64ToInt# (word64ToInt64# w))
                      else J# (word64ToInteger# w)
  
  {-# NOINLINE integerToInt64 #-}
  integerToInt64 :: Integer -> Int64#
  integerToInt64 (S# i) = intToInt64# i
  integerToInt64 (J# n) = integerToInt64# n
  
  {-# NOINLINE int64ToInteger #-}
  int64ToInteger :: Int64# -> Integer
  int64ToInteger i = if (isTrue# (i `leInt64#` intToInt64# 0x7FFFFFFF#) &&
                         isTrue# (i `geInt64#` intToInt64# -0x80000000#))
                     then smallInteger (int64ToInt# i)
                     else J# (int64ToInteger# i)
  
  {-# RULES
  "integerToInt64/int64ToInteger"   forall x . integerToInt64  (int64ToInteger  x) = x
  "integerToWord64/word64ToInteger" forall x . integerToWord64 (word64ToInteger x) = x
   #-}
  
  integerToInt :: Integer -> Int#
  {-# NOINLINE integerToInt #-}
  integerToInt (S# i)   = i
  integerToInt (J# n) = integer2Int# n
  
  toBig :: Integer -> Integer
  toBig (S# i)   = J# (int2Integer# i)
  toBig i@(J# _) = i
  
  testBitInteger :: Integer -> Int# -> Bool
  testBitInteger (S# i) b = isTrue# (i `andI#` (1# `uncheckedIShiftL#` b))
  testBitInteger (J# i) b =
      isTrue# (cmpIntegerInt# ((i `shiftRInteger#` b) `andInteger#` one) 0#)
    where
      one = int2Integer# 1#
  \end{code}
  
  
  %*********************************************************
  %*                                                      *
  \subsection{Dividing @Integers@}
  %*                                                      *
  %*********************************************************
  
  \begin{code}
  -- XXX There's no good reason for us using unboxed tuples for the
  -- results, but we don't have Data.Tuple available.
  
  -- Note that we don't check for divide-by-zero here. That needs
  -- to be done where it's used.
  -- (we don't have error)
  
  {-# NOINLINE quotRemInteger #-}
  quotRemInteger :: Integer -> Integer -> (# Integer, Integer #)
  quotRemInteger a@(S# INT_MINBOUND) b = quotRemInteger (toBig a) b
  quotRemInteger (S# i) (S# j) = (# S# q, S# r #)
      where
        -- NB. don't inline these.  (# S# (i `quotInt#` j), ... #) means
        -- (# let q = i `quotInt#` j in S# q, ... #) which builds a
        -- useless thunk.  Placing the bindings here means they'll be
        -- evaluated strictly.
        !q = i `quotInt#` j
        !r = i `remInt#`  j
  quotRemInteger i1@(J# _) i2@(S# _) = quotRemInteger i1 (toBig i2)
  quotRemInteger i1@(S# _) i2@(J# _) = quotRemInteger (toBig i1) i2
  quotRemInteger (J# n1) (J# n2)
    = case (quotRemInteger# n1 n2) of
            (# n3, n4 #)
              -> (# J# n3, J# n4 #)
  
  {-# NOINLINE divModInteger #-}
  divModInteger :: Integer -> Integer -> (# Integer, Integer #)
  divModInteger a@(S# INT_MINBOUND) b = divModInteger (toBig a) b
  divModInteger (S# i) (S# j) = (# S# d, S# m #)
      where
        -- NB. don't inline these.  See quotRemInteger above.
        !d = i `divInt#` j
        !m = i `modInt#` j
  
  divModInteger i1@(J# _) i2@(S# _) = divModInteger i1 (toBig i2)
  divModInteger i1@(S# _) i2@(J# _) = divModInteger (toBig i1) i2
  divModInteger (J# n1) (J# n2)
    = case (divModInteger# n1 n2) of
            (# n3, n4 #)
              -> (# J# n3, J# n4 #)
  
  {-# NOINLINE remInteger #-}
  remInteger :: Integer -> Integer -> Integer
  remInteger a@(S# INT_MINBOUND) b = remInteger (toBig a) b
  remInteger (S# a) (S# b) = S# (remInt# a b)
  {- Special case doesn't work, because a 1-element J# has the range
     -(2^32-1) -- 2^32-1, whereas S# has the range -2^31 -- (2^31-1)
  remInteger ia@(S# a) (J# sb b)
    | sb ==# 1#  = S# (remInt# a (word2Int# (integer2Word# sb b)))
    | sb ==# -1# = S# (remInt# a (0# -# (word2Int# (integer2Word# sb b))))
    | 0# <# sb   = ia
    | otherwise  = S# (0# -# a)
  -}
  remInteger ia@(S# _) ib@(J# _) = remInteger (toBig ia) ib
  remInteger (J# a) (S# b)
    = J# (remInteger# a (int2Integer# b))
  remInteger (J# a) (J# b)
    = J# (remInteger# a b)
  
  {-# NOINLINE quotInteger #-}
  quotInteger :: Integer -> Integer -> Integer
  quotInteger a@(S# INT_MINBOUND) b = quotInteger (toBig a) b
  quotInteger (S# a) (S# b) = S# (quotInt# a b)
  {- Special case disabled, see remInteger above
  quotInteger (S# a) (J# sb b)
    | sb ==# 1#  = S# (quotInt# a (word2Int# (integer2Word# sb b)))
    | sb ==# -1# = S# (quotInt# a (0# -# (word2Int# (integer2Word# sb b))))
    | otherwise  = S# 0
  -}
  quotInteger ia@(S# _) ib@(J# _) = quotInteger (toBig ia) ib
  quotInteger (J# a) (S# b)
    = S# (integer2Int# (quotInteger# a (int2Integer# b)))
  quotInteger (J# a) (J# b)
    = J# (quotInteger# a b)
  
  {-# NOINLINE modInteger #-}
  modInteger :: Integer -> Integer -> Integer
  modInteger a@(S# INT_MINBOUND) b = modInteger (toBig a) b
  modInteger (S# a) (S# b) = S# (modInt# a b)
  modInteger ia@(S# _) ib@(J# _) = modInteger (toBig ia) ib
  modInteger (J# a) (S# b)
    = J# (modInteger# a (int2Integer# b))
  modInteger (J# a) (J# b)
    = J# (modInteger# a b)
  
  {-# NOINLINE divInteger #-}
  divInteger :: Integer -> Integer -> Integer
  divInteger a@(S# INT_MINBOUND) b = divInteger (toBig a) b
  divInteger (S# a) (S# b) = S# (divInt# a b)
  divInteger ia@(S# _) ib@(J# _) = divInteger (toBig ia) ib
  divInteger (J# a) (S# b)
    = J# (divInteger# a (int2Integer# b))
  divInteger (J# a) (J# b)
    = J# (divInteger# a b)
  \end{code}
  
  
  
  \begin{code}
  -- We can't throw an error here, so it is up to our caller to
  -- not call us with both arguments being 0.
  {-# NOINLINE gcdInteger #-}
  gcdInteger :: Integer -> Integer -> Integer
  gcdInteger a b =
      gcdI (absInteger a) (absInteger b)
    where
      gcdI a b = if b `eqInteger` S# 0#
                   then a
                   else gcdI b (a `remInteger` b)
  
  {-# NOINLINE lcmInteger #-}
  lcmInteger :: Integer -> Integer -> Integer
  lcmInteger a b =      if a `eqInteger` S# 0# then S# 0#
                   else if b `eqInteger` S# 0# then S# 0#
                   else absInteger ((a `quotInteger` (gcdInteger a b))
                                    `timesInteger` b)
  \end{code}
  
  
  
  %*********************************************************
  %*                                                      *
  \subsection{The @Integer@ instances for @Eq@, @Ord@}
  %*                                                      *
  %*********************************************************
  
  \begin{code}
  {-# NOINLINE eqInteger #-}
  eqInteger :: Integer -> Integer -> Bool
  eqInteger (S# i)     (S# j) = isTrue# (i ==# j)
  eqInteger (S# i)     (J# d) = isTrue# (cmpIntegerInt# d i ==# 0#)
  eqInteger (J# d)   (S# i)   = isTrue# (cmpIntegerInt# d i ==# 0#)
  eqInteger (J# a) (J# b)     = isTrue# (cmpInteger# a b ==# 0#)
  
  {-# NOINLINE neqInteger #-}
  neqInteger :: Integer -> Integer -> Bool
  neqInteger (S# i)     (S# j) = isTrue# (i /=# j)
  neqInteger (S# i)     (J# d) = isTrue# (cmpIntegerInt# d i /=# 0#)
  neqInteger (J# d)     (S# i) = isTrue# (cmpIntegerInt# d i /=# 0#)
  neqInteger (J# a) (J# b)     = isTrue# (cmpInteger# a b /=# 0#)
  
  instance  Eq Integer  where
      (==) = eqInteger
      (/=) = neqInteger
  
  ------------------------------------------------------------------------
  
  {-# NOINLINE leInteger #-}
  leInteger :: Integer -> Integer -> Bool
  leInteger (S# i)     (S# j) = isTrue# (i <=# j)
  leInteger (J# d)   (S# i)   = isTrue# (cmpIntegerInt# d i <=# 0#)
  leInteger (S# i)     (J# d) = isTrue# (cmpIntegerInt# d i >=# 0#)
  leInteger (J# a) (J# b)     = isTrue# (cmpInteger# a b <=# 0#)
  
  {-# NOINLINE gtInteger #-}
  gtInteger :: Integer -> Integer -> Bool
  gtInteger (S# i)     (S# j) = isTrue# (i ># j)
  gtInteger (J# d)   (S# i)   = isTrue# (cmpIntegerInt# d i ># 0#)
  gtInteger (S# i)     (J# d) = isTrue# (cmpIntegerInt# d i <# 0#)
  gtInteger (J# a) (J# b)     = isTrue# (cmpInteger# a b ># 0#)
  
  {-# NOINLINE ltInteger #-}
  ltInteger :: Integer -> Integer -> Bool
  ltInteger (S# i)     (S# j) = isTrue# (i <# j)
  ltInteger (J# d)   (S# i)   = isTrue# (cmpIntegerInt# d i <# 0#)
  ltInteger (S# i)     (J# d) = isTrue# (cmpIntegerInt# d i ># 0#)
  ltInteger (J# a) (J# b)     = isTrue# (cmpInteger# a b <# 0#)
  
  {-# NOINLINE geInteger #-}
  geInteger :: Integer -> Integer -> Bool
  geInteger (S# i)     (S# j) = isTrue# (i >=# j)
  geInteger (J# d)   (S# i)   = isTrue# (cmpIntegerInt# d i >=# 0#)
  geInteger (S# i)     (J# d) = isTrue# (cmpIntegerInt# d i <=# 0#)
  geInteger (J# a) (J# b)     = isTrue# (cmpInteger# a b >=# 0#)
  
  {-# NOINLINE compareInteger #-}
  compareInteger :: Integer -> Integer -> Ordering
  compareInteger (S# i)  (S# j)
     =      if isTrue# (i ==# j) then EQ
       else if isTrue# (i <=# j) then LT
       else                 GT
  compareInteger (J# d) (S# i)
     = case cmpIntegerInt# d i of { res# ->
       if isTrue# (res# <# 0#) then LT else
       if isTrue# (res# ># 0#) then GT else EQ
       }
  compareInteger (S# i) (J# d)
     = case cmpIntegerInt# d i of { res# ->
       if isTrue# (res# ># 0#) then LT else
       if isTrue# (res# <# 0#) then GT else EQ
       }
  compareInteger (J# a) (J# b)
     = case cmpInteger# a b of { res# ->
       if isTrue# (res# <# 0#) then LT else
       if isTrue# (res# ># 0#) then GT else EQ
       }
  
  instance Ord Integer where
      (<=) = leInteger
      (>)  = gtInteger
      (<)  = ltInteger
      (>=) = geInteger
      compare = compareInteger
  \end{code}
  
  
  %*********************************************************
  %*                                                      *
  \subsection{The @Integer@ instances for @Num@}
  %*                                                      *
  %*********************************************************
  
  \begin{code}
  {-# NOINLINE absInteger #-}
  absInteger :: Integer -> Integer
  absInteger (S# INT_MINBOUND) = NEG_INT_MINBOUND
  absInteger n@(S# i) = if isTrue# (i >=# 0#) then n else S# (negateInt# i)
  absInteger n@(J# d) = if isTrue# (cmpIntegerInt# d 0# <# 0#)
                          then J# (negateInteger# d)
                          else n
  
  {-# NOINLINE signumInteger #-}
  signumInteger :: Integer -> Integer
  signumInteger (S# i) = if isTrue# (i <# 0#) then S# -1#
                         else if isTrue# (i ==# 0#) then S# 0#
                         else S# 1#
  signumInteger (J# d)
    = let
          !cmp = cmpIntegerInt# d 0#
      in
      if      isTrue# (cmp >#  0#) then S# 1#
      else if isTrue# (cmp ==# 0#) then S# 0#
      else                    S# (negateInt# 1#)
  
  {-# NOINLINE plusInteger #-}
  plusInteger :: Integer -> Integer -> Integer
  plusInteger i1@(S# i) i2@(S# j)  = case addIntC# i j of
                                     (# r, c #) ->
                                         if isTrue# (c ==# 0#)
                                         then S# r
                                         else plusInteger (toBig i1) (toBig i2)
  plusInteger i1@(J# _) i2@(S# _) = plusInteger i1 (toBig i2)
  plusInteger i1@(S# _) i2@(J# _) = plusInteger (toBig i1) i2
  plusInteger (J# a) (J# b)       = J# (plusInteger# a b)
  
  {-# NOINLINE minusInteger #-}
  minusInteger :: Integer -> Integer -> Integer
  minusInteger i1@(S# i) i2@(S# j)   = case subIntC# i j of
                                       (# r, c #) ->
                                           if isTrue# (c ==# 0#) then S# r
                                           else minusInteger (toBig i1)
                                                             (toBig i2)
  minusInteger i1@(J# _) i2@(S# _) = minusInteger i1 (toBig i2)
  minusInteger i1@(S# _) i2@(J# _) = minusInteger (toBig i1) i2
  minusInteger (J# a) (J# b)       = J# (minusInteger# a b)
  
  {-# NOINLINE timesInteger #-}
  timesInteger :: Integer -> Integer -> Integer
  timesInteger i1@(S# i) i2@(S# j)   = if isTrue# (mulIntMayOflo# i j ==# 0#)
                                       then S# (i *# j)
                                       else timesInteger (toBig i1) (toBig i2)
  timesInteger i1@(J# _) i2@(S# _) = timesInteger i1 (toBig i2)
  timesInteger i1@(S# _) i2@(J# _) = timesInteger (toBig i1) i2
  timesInteger (J# a) (J# b)       = J# (timesInteger# a b)
  
  {-# NOINLINE negateInteger #-}
  negateInteger :: Integer -> Integer
  negateInteger (S# INT_MINBOUND) = NEG_INT_MINBOUND
  negateInteger (S# i)            = S# (negateInt# i)
  negateInteger (J# i)            = J# (negateInteger# i)
  \end{code}
  
  
  %*********************************************************
  %*                                                      *
  \subsection{The @Integer@ stuff for Double@}
  %*                                                      *
  %*********************************************************
  
  \begin{code}
  {-# NOINLINE encodeFloatInteger #-}
  encodeFloatInteger :: Integer -> Int# -> Float#
  encodeFloatInteger (S# m) e =
    int2Float# m `timesFloat#` (2.0# `powerFloat#` (int2Float# e))
  encodeFloatInteger (J# m) e =
    toFloat# m `timesFloat#` (2.0# `powerFloat#` (int2Float# e))
  
  {-# NOINLINE encodeDoubleInteger #-}
  encodeDoubleInteger :: Integer -> Int# -> Double#
  encodeDoubleInteger (S# m) e =
    int2Double# m *## (2.0## **## (int2Double# e))
  encodeDoubleInteger (J# m) e =
    toDouble# m *## (2.0## **## (int2Double# e))
  
  {-# NOINLINE decodeDoubleInteger #-}
  decodeDoubleInteger :: Double# -> (# Integer, Int# #)
  decodeDoubleInteger d = case decodeDouble# d of
                          (# exp#, d# #) -> (# J# d#, exp# #)
  
  -- previous code: doubleFromInteger n = fromInteger n = encodeFloat n 0
  -- doesn't work too well, because encodeFloat is defined in
  -- terms of ccalls which can never be simplified away.  We
  -- want simple literals like (fromInteger 3 :: Float) to turn
  -- into (F# 3.0), hence the special case for S# here.
  
  {-# NOINLINE doubleFromInteger #-}
  doubleFromInteger :: Integer -> Double#
  doubleFromInteger (S# i#) = int2Double# i#
  doubleFromInteger (J# i#) = toDouble# i#
  
  {-# NOINLINE floatFromInteger #-}
  floatFromInteger :: Integer -> Float#
  floatFromInteger (S# i#) = int2Float# i#
  floatFromInteger (J# i#) = toFloat# i#
  
  \end{code}
  
  %*********************************************************
  %*                                                      *
  \subsection{The @Integer@ Bit definitions@}
  %*                                                      *
  %*********************************************************
  
  We explicitly pattern match against J# and S# in order to produce
  Core that doesn't have pattern matching errors, as that would
  introduce a spurious dependency to base.
  
  \begin{code}
  {-# NOINLINE andInteger #-}
  andInteger :: Integer -> Integer -> Integer
  (S# x) `andInteger` (S# y) = S# (word2Int# (int2Word# x `and#` int2Word# y))
  x@(S# _) `andInteger` y@(J# _) = toBig x `andInteger` y
  x@(J# _) `andInteger` y@(S# _) = x `andInteger` toBig y
  (J# a) `andInteger` (J# b)     = J# (andInteger# a b)
  
  {-# NOINLINE orInteger #-}
  orInteger :: Integer -> Integer -> Integer
  (S# x) `orInteger` (S# y) = S# (word2Int# (int2Word# x `or#` int2Word# y))
  x@(S# _) `orInteger` y@(J# _) = toBig x `orInteger` y
  x@(J# _) `orInteger` y@(S# _) = x `orInteger` toBig y
  (J# a) `orInteger` (J# b)     = J# (orInteger# a b)
  
  {-# NOINLINE xorInteger #-}
  xorInteger :: Integer -> Integer -> Integer
  (S# x) `xorInteger` (S# y) = S# (word2Int# (int2Word# x `xor#` int2Word# y))
  x@(S# _) `xorInteger` y@(J# _) = toBig x `xorInteger` y
  x@(J# _) `xorInteger` y@(S# _) = x `xorInteger` toBig y
  (J# a) `xorInteger` (J# b)     = J# (xorInteger# a b)
  
  {-# NOINLINE complementInteger #-}
  complementInteger :: Integer -> Integer
  complementInteger (S# x)
      = S# (word2Int# (int2Word# x `xor#` 0xffffffff##))
  complementInteger (J# d)
      = J# (complementInteger# d)
  
  {-# NOINLINE shiftLInteger #-}
  shiftLInteger :: Integer -> Int# -> Integer
  shiftLInteger j@(S# _) i = shiftLInteger (toBig j) i
  shiftLInteger (J# d) i   = J# (shiftLInteger# d i)
  
  {-# NOINLINE shiftRInteger #-}
  shiftRInteger :: Integer -> Int# -> Integer
  shiftRInteger j@(S# _) i = shiftRInteger (toBig j) i
  shiftRInteger (J# d) i   = J# (shiftRInteger# d i)
  
  {-# NOINLINE integerToJSString #-}
  integerToJSString :: Integer -> ByteArray#
  integerToJSString i@(S# _) = integerToJSString (toBig i)
  integerToJSString (J# i)   = integerToJSString# i
  
  \end{code}
  
  %*********************************************************
  %*                                                      *
  \subsection{The @Integer@ hashing@}
  %*                                                      *
  %*********************************************************
  
  \begin{code}
  -- This is used by hashUnique
  
  -- | hashInteger returns the same value as 'fromIntegral', although in
  -- unboxed form.  It might be a reasonable hash function for 'Integer', 
  -- given a suitable distribution of 'Integer' values.
  
  hashInteger :: Integer -> Int#
  hashInteger = integerToInt
  \end{code}
  
  %*********************************************************
  %*                                                      *
  \subsection{Integer logarithms@}
  %*                                                      *
  %*********************************************************
  
  \begin{code}
  
  -- Moved here because of build problems in GHC.Integer.Logarithms.Internals.
  
  -- TODO: fix roundingMode!
  
  #define WSHIFT 5
  #define MMASK 31
  
  -- Assumption: Integer is strictly positive
  -- For small integers, use wordLog#,
  -- in the general case, check words from the most
  -- significant down, once a nonzero word is found,
  -- calculate its log2 and add the number of following bits.
  integerLog2# :: Integer -> Int#
  integerLog2# (S# i)   = wordLog2# (int2Word# i)
  integerLog2# i@(J# _) = log2I i
  
  log2I :: Integer -> Int#
  log2I i =
      l2 (S# 1#) 0#
    where
      l2 x l | x `ltInteger` i = l2 (shiftLInteger x 1#) (l +# 1#)
             | x `gtInteger` i = l -# 1#
             | x `eqInteger` i = l
  
  -- Assumption: Integer is strictly positive
  -- First component is log2 n, second is 0# iff n is a power of two
  integerLog2IsPowerOf2# :: Integer -> (# Int#, Int# #)
  -- The power of 2 test is n&(n-1) == 0, thus powers of 2
  -- are indicated bythe second component being zero.
  integerLog2IsPowerOf2# (S# i) =
      case int2Word# i of
        w -> (# wordLog2# w, word2Int# (w `and#` (w `minusWord#` 1##)) #)
  -- Find the log2 as above, test whether that word is a power
  -- of 2, if so, check whether only zero bits follow.
  integerLog2IsPowerOf2# n@(J# x) =
      case integerLog2# n of
        l -> (# l, is2pow #)
    where
      one = int2Integer# 1#
      is2pow = cmpIntegerInt# (andInteger# x (minusInteger# x one)) 0#
  
  -- Assumption: Integer and Int# are strictly positive, Int# is less
  -- than logBase 2 of Integer, otherwise havoc ensues.
  -- Used only for the numerator in fromRational when the denominator
  -- is a power of 2.
  -- The Int# argument is log2 n minus the number of bits in the mantissa
  -- of the target type, i.e. the index of the first non-integral bit in
  -- the quotient.
  --
  -- 0# means round down (towards zero)
  -- 1# means we have a half-integer, round to even
  -- 2# means round up (away from zero)
  roundingMode# :: Integer -> Int# -> Int#
  roundingMode# (S# i) t =
      case int2Word# i `and#` ((uncheckedShiftL# 2## t) `minusWord#` 1##) of
        k -> case uncheckedShiftL# 1## t of
              c -> if isTrue# (c `gtWord#` k)
                      then 0#
                      else if isTrue# (c `ltWord#` k)
                              then 2#
                              else 1#
  roundingMode# i@(J# _) t =
      case i `andInteger` ((shiftLInteger (S# 2#) t) `minusInteger` S# 1#) of
        k -> case shiftLInteger (S# 1#) t of
              c -> if c `gtInteger` k
                      then 0#
                      else if c `ltInteger` k
                              then 2#
                              else 1#
  
  -- wordLog2# 0## = -1#
  {-# INLINE wordLog2# #-}
  wordLog2# :: Word# -> Int#
  wordLog2# i =
      if isTrue# (i `eqWord#` 0##) then -1# else l2 1## 0#
    where
      l2 x l | isTrue# (x `ltWord#` i) = l2 (x `timesWord#` 2##) (l +# 1#)
             | isTrue# (x `gtWord#` i) = l -# 1#
             | isTrue# (x `eqWord#` i) = l
  
  \end{code}
  