packages feed

fast-digits-0.3.2.0: src-internal/Data/FastDigits/Internal.hs

{-|
Module      : Data.FastDigits.Internal
Copyright   : (c) Andrew Lelechenko, 2015-2016
License     : GPL-3
Maintainer  : andrew.lelechenko@gmail.com

-}

{-# LANGUAGE BangPatterns  #-}
{-# LANGUAGE CPP           #-}
{-# LANGUAGE MagicHash     #-}
{-# LANGUAGE UnboxedTuples #-}

module Data.FastDigits.Internal
  ( selectPower
  , selectPower'
  ) where

import Data.Bits (finiteBitSize)
import GHC.Exts (Word#, Word(..), timesWord2#, plusWord#, timesWord#)

-- | Take an integer base and return (pow, base^pow),
--   where base^pow <= maxBound and pow is as large as possible.
selectPower :: Word# -> (# Word#, Word# #)
selectPower 2##
  | finiteBitSize (0 :: Word) == 64
  = (# 63##, 9223372036854775808## #)
selectPower 10##
  | finiteBitSize (0 :: Word) == 64
  = (# 19##, 10000000000000000000## #)

selectPower base = go base
  where
    go pw = case timesWord2# pw pw of
        (# 0##, pw2 #)
          -> let !(# n, pw2n #) = go pw2 in
            case timesWord2# pw pw2n of
              (# 0##, pw2n1 #) -> (#n `timesWord#` 2## `plusWord#` 1##, pw2n1 #)
              _ -> (# n `timesWord#` 2##, pw2n #)
        _           -> (# 1##, pw #)

-- | Take an integer base and return (pow, base^pow),
--   where base^pow <= maxBound and pow is as large as possible.
selectPower' :: Word -> (Word, Word)
selectPower' (W# base) = (W# power, W# poweredBase)
  where
    !(# power, poweredBase #) = selectPower base