Skip to content

floatRange gives unexpected results

Here's the signature for floatRange in base/GHC/Float.hs:

-- | a constant function, returning the lowest and highest values
-- the exponent may assume
floatRange          :: a -> (Int,Int)

And here are the results for Float and Double:

>>> floatRange (undefined :: Float)
(-125,128)

>>> floatRange (undefined :: Double)
(-1021, 1024)

This is quite surprising to me given the documentation for the function. Single-precision floating-point numbers have a maximum exponent of 127 and a minimum exponent of -126 (-149 for subnormalized floats). Double-precision floating-point numbers have a maximum exponent of 1023 and a minimum exponent of -1022 (-1074 for subnormalized doubles). This means either the documentation is faulty or the implementation is.

Tracking this down the issue seems to be the definition of the constants in base/includes/ieee-flpt.h:

   /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */
#if !defined(FLT_MIN_EXP)  
#  define FLT_MIN_EXP (-125)
#endif

And similar for the other constants, truncated:

# define FLT_MAX_EXP 128
#  define DBL_MIN_EXP (-1021)
# define DBL_MAX_EXP 1024

As the comment for FLT_MIN_EXP states, these numbers are all shifted by 1 in the direction of positive infinity. I have no idea why this is. The definitions for floatRange for Float, respectively Double are as follows:

floatRange _        =  (FLT_MIN_EXP, FLT_MAX_EXP) -- ditto [ditto refers to "from float.h", which doesn't exist and should probably be "ieee-flpt.h"]
floatRange _        =  (DBL_MIN_EXP, DBL_MAX_EXP) -- ditto

So if floatRange is supposed to do what I think it should and what its documentation says it does either these constants or the implementations of floatRange for Float and Double need to change.

Edited by toonn
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information