    {-# LANGUAGE Trustworthy #-}
    {-# LANGUAGE CPP, MagicHash, UnboxedTuples, NoImplicitPrelude #-}
    {-# OPTIONS_GHC -O2 #-}
    {-# OPTIONS_HADDOCK not-home #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  GHC.Float.ConversionUtils
    -- Copyright   :  (c) Daniel Fischer 2010
    -- License     :  see libraries/base/LICENSE
    --
    -- Maintainer  :  cvs-ghc@haskell.org
    -- Stability   :  internal
    -- Portability :  non-portable (GHC Extensions)
    --
    -- Utilities for conversion between Double/Float and Rational
    --
    -----------------------------------------------------------------------------

    #include "MachDeps.h"

    module GHC.Float.ConversionUtils ( elimZerosInteger, elimZerosInt# ) where

    import GHC.Base
    import GHC.Num.Integer
    #if WORD_SIZE_IN_BITS < 64
    import GHC.IntWord64
    #endif

    default ()

    #if WORD_SIZE_IN_BITS < 64

    #define TO64    integerToInt64#

    toByte64# :: Int64# -> Int#
    toByte64# i = word2Int# (and# 255## (int2Word# (int64ToInt# i)))

    -- Double mantissae have 53 bits, too much for Int#
    elim64# :: Int64# -> Int# -> (# Integer, Int# #)
    elim64# n e =
        case zeroCount (toByte64# n) of
          t | isTrue# (e <=# t) -> (# integerFromInt64# (uncheckedIShiftRA64# n e), 0# #)
            | isTrue# (t <# 8#) -> (# integerFromInt64# (uncheckedIShiftRA64# n t), e -# t #)
            | otherwise         -> elim64# (uncheckedIShiftRA64# n 8#) (e -# 8#)

    #else

    #define TO64    integerToInt#

    -- Double mantissae fit it Int#
    elim64# :: Int# -> Int# -> (# Integer, Int# #)
    elim64# :: Int# -> Int# -> (# Integer, Int# #)
    elim64# = Int# -> Int# -> (# Integer, Int# #)
    elimZerosInt#

    #endif

    {-# INLINE elimZerosInteger #-}
    elimZerosInteger :: Integer -> Int# -> (# Integer, Int# #)
    elimZerosInteger :: Integer -> Int# -> (# Integer, Int# #)
    elimZerosInteger Integer
    m Int#
    e = Int# -> Int# -> (# Integer, Int# #)
    elim64# (TO64 m) e

    elimZerosInt# :: Int# -> Int# -> (# Integer, Int# #)
    elimZerosInt# :: Int# -> Int# -> (# Integer, Int# #)
    elimZerosInt# Int#
    n Int#
    e =
        case Int# -> Int#
    zeroCount (Int# -> Int#
    toByte# Int#
    n) of
          Int#
    t | Int# -> Bool
    isTrue# (Int#
    e Int# -> Int# -> Int#
    <=# Int#
    t) -> (# Int# -> Integer
    IS (Int# -> Int# -> Int#
    uncheckedIShiftRA# Int#
    n Int#
    e), Int#
    0# #)
            | Int# -> Bool
    isTrue# (Int#
    t Int# -> Int# -> Int#
    <# Int#
    8#) -> (# Int# -> Integer
    IS (Int# -> Int# -> Int#
    uncheckedIShiftRA# Int#
    n Int#
    t), Int#
    e Int# -> Int# -> Int#
    -# Int#
    t #)
            | Bool
    otherwise         -> Int# -> Int# -> (# Integer, Int# #)
    elimZerosInt# (Int# -> Int# -> Int#
    uncheckedIShiftRA# Int#
    n Int#
    8#) (Int#
    e Int# -> Int# -> Int#
    -# Int#
    8#)

    {-# INLINE zeroCount #-}
    zeroCount :: Int# -> Int#
    zeroCount :: Int# -> Int#
    zeroCount Int#
    i =
        case BA
    zeroCountArr of
          BA ByteArray#
    ba -> ByteArray# -> Int# -> Int#
    indexInt8Array# ByteArray#
    ba Int#
    i

    toByte# :: Int# -> Int#
    toByte# :: Int# -> Int#
    toByte# Int#
    i = Word# -> Int#
    word2Int# (Word# -> Word# -> Word#
    and# Word#
    255## (Int# -> Word#
    int2Word# Int#
    i))

    data BA = BA ByteArray#

    -- Number of trailing zero bits in a byte
    zeroCountArr :: BA
    zeroCountArr :: BA
    zeroCountArr =
        let mkArr :: State# d -> ByteArray#
    mkArr State# d
    s =
              case Int# -> State# d -> (# State# d, MutableByteArray# d #)
    forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
    newByteArray# Int#
    256# State# d
    s of
                (# State# d
    s1, MutableByteArray# d
    mba #) ->
                  case MutableByteArray# d -> Int# -> Int# -> State# d -> State# d
    forall d.
    MutableByteArray# d -> Int# -> Int# -> State# d -> State# d
    writeInt8Array# MutableByteArray# d
    mba Int#
    0# Int#
    8# State# d
    s1 of
                    State# d
    s2 ->
                      let fillA :: Int# -> Int# -> Int# -> State# d -> State# d
    fillA Int#
    step Int#
    val Int#
    idx State# d
    st
                            | Int# -> Bool
    isTrue# (Int#
    idx Int# -> Int# -> Int#
    <# Int#
    256#) =
                                            case MutableByteArray# d -> Int# -> Int# -> State# d -> State# d
    forall d.
    MutableByteArray# d -> Int# -> Int# -> State# d -> State# d
    writeInt8Array# MutableByteArray# d
    mba Int#
    idx Int#
    val State# d
    st of
                                              State# d
    nx -> Int# -> Int# -> Int# -> State# d -> State# d
    fillA Int#
    step Int#
    val (Int#
    idx Int# -> Int# -> Int#
    +# Int#
    step) State# d
    nx
                            | Int# -> Bool
    isTrue# (Int#
    step Int# -> Int# -> Int#
    <# Int#
    256#) =
                                            Int# -> Int# -> Int# -> State# d -> State# d
    fillA (Int#
    2# Int# -> Int# -> Int#
    *# Int#
    step) (Int#
    val Int# -> Int# -> Int#
    +# Int#
    1#) Int#
    step  State# d
    st
                            | Bool
    otherwise   = State# d
    st
                      in case Int# -> Int# -> Int# -> State# d -> State# d
    fillA Int#
    2# Int#
    0# Int#
    1# State# d
    s2 of
                           State# d
    s3 -> case MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
    unsafeFreezeByteArray# MutableByteArray# d
    mba State# d
    s3 of
                                    (# State# d
    _, ByteArray#
    ba #) -> ByteArray#
    ba
        in case State# RealWorld -> ByteArray#
    forall {d}. State# d -> ByteArray#
    mkArr State# RealWorld
    realWorld# of
            ByteArray#
    b -> ByteArray# -> BA
    BA ByteArray#
    b