{-# LANGUAGE NoImplicitPrelude #-}
module Data.NumberLength.Integer
(
lengthInteger
, lengthIntegerHex
)
where
import Prelude
( Bounded(maxBound)
, Integer
, Integral(quot)
, Num((+), fromInteger, negate)
, (^)
, fromIntegral
)
import Data.Bool (otherwise)
import Data.Eq (Eq((==)))
import Data.Int (Int)
import Data.Ord (Ord((<)))
import Data.NumberLength.Int (lengthInt, lengthIntHex)
import Data.NumberLength.Internal (either32or64)
lengthInteger :: Integer -> Int
lengthInteger n
| n < 0 = go (negate (fromIntegral n))
| otherwise = go (fromIntegral n)
where
go :: Integer -> Int
go m
| m < maxInt = lengthInt (fromInteger m)
| otherwise =
let r = m `quot` (10 ^ maxIntDigits)
in maxIntDigits + if r == 0 then 0 else lengthInteger r
maxIntDigits :: Int
maxIntDigits = 10 `either32or64` 19
{-# INLINE lengthInteger #-}
lengthIntegerHex :: Integer -> Int
lengthIntegerHex n
| n < 0 = go (negate n)
| otherwise = go n
where
go :: Integer -> Int
go m
| m < maxInt = lengthIntHex (fromInteger m)
| otherwise =
let r = m `quot` (16 ^ maxIntDigits)
in maxIntDigits + if r == 0 then 0 else lengthIntegerHex r
maxIntDigits :: Int
maxIntDigits = 8 `either32or64` 16
{-# INLINE lengthIntegerHex #-}
maxInt :: Integer
maxInt = fromIntegral (maxBound :: Int)