number-length-0.2.0.0: src/Data/NumberLength/Integer.hs
{-# LANGUAGE NoImplicitPrelude #-}
-- |
-- Module: $HEADER$
-- Description: Get number of digits of an Integer.
-- Copyright: (c) 2016, Peter Trško
-- License: BSD3
--
-- Stability: experimental
-- Portability: NoImplicitPrelude
--
-- Get number of digits of an 'Integer'.
--
-- /Since 0.2.0.0/
module Data.NumberLength.Integer
(
-- * Decimal (base 10)
lengthInteger
-- * Hexadecimal (base 16)
, 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)
-- | Number of digits in a @number :: 'Integer'@ in base 10.
--
-- /Since 0.2.0.0/
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 #-}
-- | Number of digits in a @number :: 'Integer'@ in base 16.
--
-- /Since 0.2.0.0/
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 #-}
-- | Maximum value of type 'Int' cast in to 'Integral'.
--
-- /Do not export this function!/
maxInt :: Integer
maxInt = fromIntegral (maxBound :: Int)