scientific 0.0.0.2 → 0.1.0.0
raw patch · 3 files changed
+15/−60 lines, 3 files
Files
- scientific.cabal +1/−1
- src/Data/Scientific.hs +12/−54
- test/test.hs +2/−5
scientific.cabal view
@@ -1,5 +1,5 @@ name: scientific-version: 0.0.0.2+version: 0.1.0.0 synopsis: Arbitrary-precision floating-point numbers represented using scientific notation description: A @Scientific@ number is an arbitrary-precision floating-point number represented using scientific notation.
src/Data/Scientific.hs view
@@ -21,8 +21,7 @@ , base10Exponent -- * Conversions- , toFractional- , fromRealFloat+ , fromFloatDigits -- * Pretty printing , FPFormat(..)@@ -44,7 +43,6 @@ import Data.Hashable (Hashable(..)) import Data.Ratio ((%), numerator, denominator) import Data.Typeable (Typeable)-import Foreign.C.Types (CDouble, CFloat) import Numeric (floatToDigits) import Text.Read (readPrec) import qualified Text.ParserCombinators.ReadPrec as ReadPrec@@ -222,20 +220,19 @@ {-# INLINE recip #-} fromRational rational- | numer < 0 = negate $ go (negate numer) 0 0- | otherwise = go numer 0 0+ | numer < 0 = negate $ longDiv (negate numer) 0 0+ | otherwise = longDiv numer 0 0 where numer = numerator rational denom = denominator rational - go :: Integer -> Integer -> Int -> Scientific- go 0 !c !e = scientific c e- go !n !c !e- | n < denom = go (n*10) (c * 10) (e-1) -- TODO: Use a logarithm here!- | otherwise = go r (c + q) e+ longDiv :: Integer -> Integer -> Int -> Scientific+ longDiv 0 !c !e = scientific c e+ longDiv !n !c !e+ | n < denom = longDiv (n*10) (c * 10) (e-1) -- TODO: Use a logarithm here!+ | otherwise = longDiv r (c + q) e where (q, r) = n `quotRem` denom- {-# INLINE fromRational #-} instance RealFrac Scientific where properFraction (Scientific c e)@@ -276,42 +273,10 @@ ---------------------------------------------------------------------- -{-# RULES-"realToFrac/Scientific->Scientific" realToFrac = id :: Scientific -> Scientific #-}---- | Efficient conversion from a 'Scientific' to a 'Fractional' number.------ Note that this module provides rewrite RULES that convert--- 'realToFrac' into 'toFractional' when going from a 'Scientific' to--- either a 'Double', 'Float', 'CDouble' or 'CFloat' to avoid going--- via 'Rational'.------ So it's recommended to use 'realToFrac' to convert to a--- 'Fractional' number. However, if you don't want to rely on these--- RULES this function can be used.-toFractional :: (Fractional a) => Scientific -> a-toFractional = whenFloating $ \c e -> fromInteger c / 10 ^ negate e-{-# INLINE toFractional #-}--{-# RULES-"realToFrac/Scientific->Double" realToFrac = toFractional :: Scientific -> Double-"realToFrac/Scientific->Float" realToFrac = toFractional :: Scientific -> Float-"realToFrac/Scientific->CDouble" realToFrac = toFractional :: Scientific -> CDouble-"realToFrac/Scientific->CFloat" realToFrac = toFractional :: Scientific -> CFloat #-}---- | Efficient conversion from a 'RealFloat' into a 'Scientific'--- number.------ Note that this module provides rewrite RULES that convert--- 'realToFrac' into 'fromRealFloat' when going from either a--- 'Double', 'Float', 'CDouble' or 'CFloat' to a 'Scientific' to avoid--- going via 'Rational'.------ So it's recommended to use 'realToFrac' to convert 'Real' numbers--- into 'Scientific'. However, if you don't want to rely on these--- RULES this function can be used.-fromRealFloat :: (RealFloat a) => a -> Scientific-fromRealFloat rf+-- | Efficient and exact conversion from a 'RealFloat' into a+-- 'Scientific' number.+fromFloatDigits :: (RealFloat a) => a -> Scientific+fromFloatDigits rf -- integers are way more efficient to convert via Rational. -- We do pay the cost of always converting to Rational first though. | denominator rat == 1 = fromInteger $ numerator rat@@ -326,13 +291,6 @@ go [] !c !n = scientific c (e - n) go (d:ds) !c !n = go ds (c * 10 + fromIntegral d) (n + 1)-{-# INLINE fromRealFloat #-}--{-# RULES-"realToFrac/Double->Scientific" realToFrac = fromRealFloat :: Double -> Scientific-"realToFrac/Float->Scientific" realToFrac = fromRealFloat :: Float -> Scientific-"realToFrac/CDouble->Scientific" realToFrac = fromRealFloat :: CDouble -> Scientific-"realToFrac/CFloat->Scientific" realToFrac = fromRealFloat :: CFloat -> Scientific #-} ----------------------------------------------------------------------
test/test.hs view
@@ -88,11 +88,8 @@ ] , testGroup "Conversions"- [ testProperty "toFractional" $ \s ->- Scientific.toFractional s == toRational s-- , testProperty "fromRealFloat" $ \(d::Double) ->- toRational (Scientific.fromRealFloat d) == toRational d+ [ testProperty "fromRealFloat" $ \s ->+ Scientific.fromFloatDigits (realToFrac s :: Double) === s ] ]