{-# LANGUAGE MagicHash, UnboxedTuples, NoImplicitPrelude #-}
module GHC.Integer.Logarithms
    ( integerLogBase#
    , integerLog2#
    , wordLog2#
    ) where

import GHC.Prim
import GHC.Integer
import qualified GHC.Integer.Logarithms.Internals as I

-- | Calculate the integer logarithm for an arbitrary base.
--   The base must be greater than 1, the second argument, the number
--   whose logarithm is sought, should be positive, otherwise the
--   result is meaningless.
--
-- > base ^ integerLogBase# base m <= m < base ^ (integerLogBase# base m + 1)
--
-- for @base > 1@ and @m > 0@.
integerLogBase# :: Integer -> Integer -> Int#
integerLogBase# :: Integer -> Integer -> Int#
integerLogBase# Integer
b Integer
m = case Integer -> (# Integer, Int# #)
step Integer
b of
                        (# Integer
_, Int#
e #) -> Int#
e
  where
    step :: Integer -> (# Integer, Int# #)
step Integer
pw =
      if Integer
m Integer -> Integer -> Bool
`ltInteger` Integer
pw
        then (# Integer
m, Int#
0# #)
        else case Integer -> (# Integer, Int# #)
step (Integer
pw Integer -> Integer -> Integer
`timesInteger` Integer
pw) of
               (# Integer
q, Int#
e #) ->
                 if Integer
q Integer -> Integer -> Bool
`ltInteger` Integer
pw
                   then (# Integer
q, Int#
2# Int# -> Int# -> Int#
*# Int#
e #)
                   else (# Integer
q Integer -> Integer -> Integer
`quotInteger` Integer
pw, Int#
2# Int# -> Int# -> Int#
*# Int#
e Int# -> Int# -> Int#
+# Int#
1# #)

-- | Calculate the integer base 2 logarithm of an 'Integer'.
--   The calculation is more efficient than for the general case,
--   on platforms with 32- or 64-bit words much more efficient.
--
--  The argument must be strictly positive, that condition is /not/ checked.
integerLog2# :: Integer -> Int#
integerLog2# :: Integer -> Int#
integerLog2# = Integer -> Int#
I.integerLog2#

-- | This function calculates the integer base 2 logarithm of a 'Word#'.
wordLog2# :: Word# -> Int#
wordLog2# :: Word# -> Int#
wordLog2# = Word# -> Int#
I.wordLog2#