{-# LANGUAGE BangPatterns, CPP #-} ----------------------------------------------------------------------------- -- | -- Module : Data.PseudoBoolean.Internal.TextUtil -- Copyright : (c) Masahiro Sakai 2012-2014 -- License : BSD-style -- -- Maintainer : masahiro.sakai@gmail.com -- Stability : provisional -- Portability : non-portable (BangPatterns) -- ----------------------------------------------------------------------------- module Data.PseudoBoolean.Internal.TextUtil ( readUnsignedInteger ) where #include "MachDeps.h" import Control.Exception import Data.Word -- | 'read' allocate too many intermediate 'Integer'. -- Therefore we use this optimized implementation instead. -- Many intermediate values in this implementation will be optimized -- away by worker-wrapper transformation and unboxing. {-# INLINABLE readUnsignedInteger #-} readUnsignedInteger :: String -> Integer readUnsignedInteger str = assert (result == read str) $ result where result :: Integer result = go 0 str lim :: Word #if !MIN_VERSION_base(4,6,1) && WORD_SIZE_IN_BITS == 32 {- To avoid a bug of maxBound -} lim = 0xFFFFFFFF `div` 10 #else lim = maxBound `div` 10 #endif go :: Integer -> [Char] -> Integer go !r [] = r go !r ds = case go2 0 1 ds of (r2,b,ds2) -> go (r * fromIntegral b + fromIntegral r2) ds2 go2 :: Word -> Word -> [Char] -> (Word, Word, [Char]) go2 !r !b dds | assert (b > r) (b > lim) = (r,b,dds) go2 !r !b [] = (r, b, []) go2 !r !b (d:ds) = go2 (r*10 + charToWord d) (b*10) ds charToWord :: Char -> Word charToWord '0' = 0 charToWord '1' = 1 charToWord '2' = 2 charToWord '3' = 3 charToWord '4' = 4 charToWord '5' = 5 charToWord '6' = 6 charToWord '7' = 7 charToWord '8' = 8 charToWord '9' = 9