X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FFloat.lhs;h=71a0e2ea83bf2abf14f5849dc51d9f72f961ed9a;hb=b5a2f82b561cc5398756c2498a54bb506567ce77;hp=08fa67ca747a89345e44808e83e267b5a71fd1bc;hpb=d9e5fa673b75cdffbcd0e85cdcc98d706acbb29a;p=haskell-directory.git diff --git a/GHC/Float.lhs b/GHC/Float.lhs index 08fa67c..71a0e2e 100644 --- a/GHC/Float.lhs +++ b/GHC/Float.lhs @@ -1,23 +1,18 @@ -% ------------------------------------------------------------------------------ -% $Id: Float.lhs,v 1.2 2001/07/03 14:13:32 simonmar Exp $ -% -% (c) The University of Glasgow, 1994-2000 -% - -\section[GHC.Num]{Module @GHC.Num@} - -The types - - Float - Double - -and the classes - - Floating - RealFloat - \begin{code} {-# OPTIONS -fno-implicit-prelude #-} +----------------------------------------------------------------------------- +-- | +-- Module : GHC.Float +-- Copyright : (c) The University of Glasgow 1994-2002 +-- License : see libraries/base/LICENSE +-- +-- Maintainer : cvs-ghc@haskell.org +-- Stability : internal +-- Portability : non-portable (GHC Extensions) +-- +-- The types 'Float' and 'Double', and the classes 'Floating' and 'RealFloat'. +-- +----------------------------------------------------------------------------- #include "ieee-flpt.h" @@ -103,7 +98,10 @@ class (RealFrac a, Floating a) => RealFloat a where %********************************************************* \begin{code} +-- | Single-precision floating point numbers. data Float = F# Float# + +-- | Double-precision floating point numbers. data Double = D# Double# instance CCallable Float @@ -166,14 +164,14 @@ instance RealFrac Float where {-# SPECIALIZE properFraction :: Float -> (Int, Float) #-} {-# SPECIALIZE round :: Float -> Int #-} - {-# SPECIALIZE ceiling :: Float -> Int #-} - {-# SPECIALIZE floor :: Float -> Int #-} - {-# SPECIALIZE properFraction :: Float -> (Integer, Float) #-} - {-# SPECIALIZE truncate :: Float -> Integer #-} + {-# SPECIALIZE properFraction :: Float -> (Integer, Float) #-} {-# SPECIALIZE round :: Float -> Integer #-} - {-# SPECIALIZE ceiling :: Float -> Integer #-} - {-# SPECIALIZE floor :: Float -> Integer #-} + + -- ceiling, floor, and truncate are all small + {-# INLINE ceiling #-} + {-# INLINE floor #-} + {-# INLINE truncate #-} properFraction x = case (decodeFloat x) of { (m,n) -> @@ -330,14 +328,14 @@ instance RealFrac Double where {-# SPECIALIZE properFraction :: Double -> (Int, Double) #-} {-# SPECIALIZE round :: Double -> Int #-} - {-# SPECIALIZE ceiling :: Double -> Int #-} - {-# SPECIALIZE floor :: Double -> Int #-} {-# SPECIALIZE properFraction :: Double -> (Integer, Double) #-} - {-# SPECIALIZE truncate :: Double -> Integer #-} {-# SPECIALIZE round :: Double -> Integer #-} - {-# SPECIALIZE ceiling :: Double -> Integer #-} - {-# SPECIALIZE floor :: Double -> Integer #-} + + -- ceiling, floor, and truncate are all small + {-# INLINE ceiling #-} + {-# INLINE floor #-} + {-# INLINE truncate #-} properFraction x = case (decodeFloat x) of { (m,n) -> @@ -496,13 +494,15 @@ formatRealFloat fmt decs x mk0 ls = case ls of { "" -> "0" ; _ -> ls} in case decs of - Nothing -> - let - f 0 s rs = mk0 (reverse s) ++ '.':mk0 rs - f n s "" = f (n-1) ('0':s) "" - f n s (r:rs) = f (n-1) (r:s) rs - in - f e "" ds + Nothing + | e <= 0 -> "0." ++ replicate (-e) '0' ++ ds + | otherwise -> + let + f 0 s rs = mk0 (reverse s) ++ '.':mk0 rs + f n s "" = f (n-1) ('0':s) "" + f n s (r:rs) = f (n-1) (r:s) rs + in + f e "" ds Just dec -> let dec' = max dec 0 in if e >= 0 then @@ -516,8 +516,8 @@ formatRealFloat fmt decs x (ei,is') = roundTo base dec' (replicate (-e) 0 ++ is) d:ds' = map intToDigit (if ei > 0 then is' else 0:is') in - d : '.' : ds' - + d : (if null ds' then "" else '.':ds') + roundTo :: Int -> Int -> [Int] -> (Int,[Int]) roundTo base d is = @@ -536,13 +536,18 @@ roundTo base d is = (c,ds) = f (n-1) xs i' = c + i --- -- Based on "Printing Floating-Point Numbers Quickly and Accurately" -- by R.G. Burger and R.K. Dybvig in PLDI 96. -- This version uses a much slower logarithm estimator. It should be improved. --- This function returns a list of digits (Ints in [0..base-1]) and an --- exponent. +-- floatToDigits takes a base and a non-negative RealFloat number, +-- and returns a list of digits and an exponent. +-- In particular, if x>=0, and +-- floatToDigits base x = ([d1,d2,...,dn], e) +-- then +-- (a) n >= 1 +-- (b) x = 0.d1d2...dn * (base**e) +-- (c) 0 <= di <= base-1 floatToDigits :: (RealFloat a) => Integer -> a -> ([Int], Int) floatToDigits _ 0 = ([0], 0) @@ -673,14 +678,18 @@ fromRat x = x' Now, here's Lennart's code (which works) \begin{code} -{-# SPECIALISE fromRat :: - Rational -> Double, - Rational -> Float #-} +{-# SPECIALISE fromRat :: Rational -> Double, + Rational -> Float #-} fromRat :: (RealFloat a) => Rational -> a -fromRat x - | x == 0 = encodeFloat 0 0 -- Handle exceptional cases - | x < 0 = - fromRat' (-x) -- first. - | otherwise = fromRat' x + +-- Deal with special cases first, delegating the real work to fromRat' +fromRat (n :% 0) | n > 0 = 1/0 -- +Infinity + | n == 0 = 0/0 -- NaN + | n < 0 = -1/0 -- -Infinity + +fromRat (n :% d) | n > 0 = fromRat' (n :% d) + | n == 0 = encodeFloat 0 0 -- Zero + | n < 0 = - fromRat' ((-n) :% d) -- Conversion process: -- Scale the rational number by the RealFloat base until @@ -691,6 +700,7 @@ fromRat x -- a first guess of the exponent. fromRat' :: (RealFloat a) => Rational -> a +-- Invariant: argument is strictly positive fromRat' x = r where b = floatRadix r p = floatDigits r @@ -852,27 +862,27 @@ powerDouble (D# x) (D# y) = D# (x **## y) \end{code} \begin{code} -foreign import ccall "__encodeFloat" unsafe +foreign import ccall unsafe "__encodeFloat" encodeFloat# :: Int# -> ByteArray# -> Int -> Float -foreign import ccall "__int_encodeFloat" unsafe +foreign import ccall unsafe "__int_encodeFloat" int_encodeFloat# :: Int# -> Int -> Float -foreign import ccall "isFloatNaN" unsafe isFloatNaN :: Float -> Int -foreign import ccall "isFloatInfinite" unsafe isFloatInfinite :: Float -> Int -foreign import ccall "isFloatDenormalized" unsafe isFloatDenormalized :: Float -> Int -foreign import ccall "isFloatNegativeZero" unsafe isFloatNegativeZero :: Float -> Int +foreign import ccall unsafe "isFloatNaN" isFloatNaN :: Float -> Int +foreign import ccall unsafe "isFloatInfinite" isFloatInfinite :: Float -> Int +foreign import ccall unsafe "isFloatDenormalized" isFloatDenormalized :: Float -> Int +foreign import ccall unsafe "isFloatNegativeZero" isFloatNegativeZero :: Float -> Int -foreign import ccall "__encodeDouble" unsafe +foreign import ccall unsafe "__encodeDouble" encodeDouble# :: Int# -> ByteArray# -> Int -> Double -foreign import ccall "__int_encodeDouble" unsafe +foreign import ccall unsafe "__int_encodeDouble" int_encodeDouble# :: Int# -> Int -> Double -foreign import ccall "isDoubleNaN" unsafe isDoubleNaN :: Double -> Int -foreign import ccall "isDoubleInfinite" unsafe isDoubleInfinite :: Double -> Int -foreign import ccall "isDoubleDenormalized" unsafe isDoubleDenormalized :: Double -> Int -foreign import ccall "isDoubleNegativeZero" unsafe isDoubleNegativeZero :: Double -> Int +foreign import ccall unsafe "isDoubleNaN" isDoubleNaN :: Double -> Int +foreign import ccall unsafe "isDoubleInfinite" isDoubleInfinite :: Double -> Int +foreign import ccall unsafe "isDoubleDenormalized" isDoubleDenormalized :: Double -> Int +foreign import ccall unsafe "isDoubleNegativeZero" isDoubleNegativeZero :: Double -> Int \end{code} %*********************************************************