X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FFloat.lhs;h=c4003b4c6224d650cd0e6c795a0d2ea5f11daad7;hb=9ecf132d64d35e5997c12286f509b2f8d7f2a7ef;hp=ec27a1206d0018b92464f995282e82c7a36c50f7;hpb=7de50399a42ee49b0473b7b6eea2b44a2f941a12;p=ghc-base.git diff --git a/GHC/Float.lhs b/GHC/Float.lhs index ec27a12..c4003b4 100644 --- a/GHC/Float.lhs +++ b/GHC/Float.lhs @@ -1,26 +1,22 @@ -% ------------------------------------------------------------------------------ -% $Id: Float.lhs,v 1.4 2002/02/05 17:32:26 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 #-} +{-# OPTIONS_GHC -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" +-- #hide module GHC.Float( module GHC.Float, Float#, Double# ) where import Data.Maybe @@ -43,6 +39,11 @@ infixr 8 ** %********************************************************* \begin{code} +-- | Trigonometric and hyperbolic functions and related functions. +-- +-- Minimal complete definition: +-- 'pi', 'exp', 'log', 'sin', 'cos', 'sinh', 'cosh' +-- 'asin', 'acos', 'atan', 'asinh', 'acosh' and 'atanh' class (Fractional a) => Floating a where pi :: a exp, log, sqrt :: a -> a @@ -58,17 +59,58 @@ class (Fractional a) => Floating a where tan x = sin x / cos x tanh x = sinh x / cosh x +-- | Efficient, machine-independent access to the components of a +-- floating-point number. +-- +-- Minimal complete definition: +-- all except 'exponent', 'significand', 'scaleFloat' and 'atan2' class (RealFrac a, Floating a) => RealFloat a where + -- | a constant function, returning the radix of the representation + -- (often @2@) floatRadix :: a -> Integer + -- | a constant function, returning the number of digits of + -- 'floatRadix' in the significand floatDigits :: a -> Int + -- | a constant function, returning the lowest and highest values + -- the exponent may assume floatRange :: a -> (Int,Int) + -- | The function 'decodeFloat' applied to a real floating-point + -- number returns the significand expressed as an 'Integer' and an + -- appropriately scaled exponent (an 'Int'). If @'decodeFloat' x@ + -- yields @(m,n)@, then @x@ is equal in value to @m*b^^n@, where @b@ + -- is the floating-point radix, and furthermore, either @m@ and @n@ + -- are both zero or else @b^(d-1) <= m < b^d@, where @d@ is the value + -- of @'floatDigits' x@. In particular, @'decodeFloat' 0 = (0,0)@. decodeFloat :: a -> (Integer,Int) + -- | 'encodeFloat' performs the inverse of 'decodeFloat' encodeFloat :: Integer -> Int -> a + -- | the second component of 'decodeFloat'. exponent :: a -> Int + -- | the first component of 'decodeFloat', scaled to lie in the open + -- interval (@-1@,@1@) significand :: a -> a + -- | multiplies a floating-point number by an integer power of the radix scaleFloat :: Int -> a -> a - isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE - :: a -> Bool + -- | 'True' if the argument is an IEEE \"not-a-number\" (NaN) value + isNaN :: a -> Bool + -- | 'True' if the argument is an IEEE infinity or negative infinity + isInfinite :: a -> Bool + -- | 'True' if the argument is too small to be represented in + -- normalized format + isDenormalized :: a -> Bool + -- | 'True' if the argument is an IEEE negative zero + isNegativeZero :: a -> Bool + -- | 'True' if the argument is an IEEE floating point number + isIEEE :: a -> Bool + -- | a version of arctangent taking two real floating-point arguments. + -- For real floating @x@ and @y@, @'atan2' y x@ computes the angle + -- (from the positive x-axis) of the vector from the origin to the + -- point @(x,y)@. @'atan2' y x@ returns a value in the range [@-pi@, + -- @pi@]. It follows the Common Lisp semantics for the origin when + -- signed zeroes are supported. @'atan2' y 1@, with @y@ in a type + -- that is 'RealFloat', should return the same value as @'atan' y@. + -- A default definition of 'atan2' is provided, but implementors + -- can provide a more accurate implementation. atan2 :: a -> a -> a @@ -103,14 +145,15 @@ class (RealFrac a, Floating a) => RealFloat a where %********************************************************* \begin{code} +-- | Single-precision floating point numbers. +-- It is desirable that this type be at least equal in range and precision +-- to the IEEE single-precision type. data Float = F# Float# -data Double = D# Double# -instance CCallable Float -instance CReturnable Float - -instance CCallable Double -instance CReturnable Double +-- | Double-precision floating point numbers. +-- It is desirable that this type be at least equal in range and precision +-- to the IEEE double-precision type. +data Double = D# Double# \end{code} @@ -166,14 +209,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 +373,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) -> @@ -451,6 +494,9 @@ instance Enum Double where \begin{code} +-- | Show a signed 'RealFloat' value to full precision +-- using standard decimal notation for arguments whose absolute value lies +-- between @0.1@ and @9,999,999@, and scientific notation otherwise. showFloat :: (RealFloat a) => a -> ShowS showFloat x = showString (formatRealFloat FFGeneric Nothing x) @@ -542,14 +588,19 @@ roundTo base d is = -- by R.G. Burger and R.K. Dybvig in PLDI 96. -- This version uses a much slower logarithm estimator. It should be improved. --- floatToDigits takes a base and a non-negative RealFloat number, +-- | '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) +-- 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 +-- +-- (1) @n >= 1@ +-- +-- (2) @x = 0.d1d2...dn * (base**e)@ +-- +-- (3) @0 <= di <= base-1@ floatToDigits :: (RealFloat a) => Integer -> a -> ([Int], Int) floatToDigits _ 0 = ([0], 0) @@ -680,14 +731,19 @@ fromRat x = x' Now, here's Lennart's code (which works) \begin{code} -{-# SPECIALISE fromRat :: - Rational -> Double, - Rational -> Float #-} +-- | Converts a 'Rational' value into any type in class 'RealFloat'. +{-# 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 @@ -698,6 +754,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 @@ -768,18 +825,6 @@ minusFloat (F# x) (F# y) = F# (minusFloat# x y) timesFloat (F# x) (F# y) = F# (timesFloat# x y) divideFloat (F# x) (F# y) = F# (divideFloat# x y) -{-# RULES -"plusFloat x 0.0" forall x#. plusFloat# x# 0.0# = x# -"plusFloat 0.0 x" forall x#. plusFloat# 0.0# x# = x# -"minusFloat x 0.0" forall x#. minusFloat# x# 0.0# = x# -"minusFloat x x" forall x#. minusFloat# x# x# = 0.0# -"timesFloat x 0.0" forall x#. timesFloat# x# 0.0# = 0.0# -"timesFloat0.0 x" forall x#. timesFloat# 0.0# x# = 0.0# -"timesFloat x 1.0" forall x#. timesFloat# x# 1.0# = x# -"timesFloat 1.0 x" forall x#. timesFloat# 1.0# x# = x# -"divideFloat x 1.0" forall x#. divideFloat# x# 1.0# = x# - #-} - negateFloat :: Float -> Float negateFloat (F# x) = F# (negateFloat# x) @@ -826,18 +871,6 @@ minusDouble (D# x) (D# y) = D# (x -## y) timesDouble (D# x) (D# y) = D# (x *## y) divideDouble (D# x) (D# y) = D# (x /## y) -{-# RULES -"plusDouble x 0.0" forall x#. (+##) x# 0.0## = x# -"plusDouble 0.0 x" forall x#. (+##) 0.0## x# = x# -"minusDouble x 0.0" forall x#. (-##) x# 0.0## = x# -"minusDouble x x" forall x#. (-##) x# x# = 0.0## -"timesDouble x 0.0" forall x#. (*##) x# 0.0## = 0.0## -"timesDouble 0.0 x" forall x#. (*##) 0.0## x# = 0.0## -"timesDouble x 1.0" forall x#. (*##) x# 1.0## = x# -"timesDouble 1.0 x" forall x#. (*##) 1.0## x# = x# -"divideDouble x 1.0" forall x#. (/##) x# 1.0## = x# - #-} - negateDouble :: Double -> Double negateDouble (D# x) = D# (negateDouble# x)