floatRange gives unexpected results
Here's the signature for
-- | a constant function, returning the lowest and highest values -- the exponent may assume floatRange :: a -> (Int,Int)
And here are the results for
>>> 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
-149 for subnormalized floats). Double-precision floating-point numbers have a maximum exponent of
1023 and a minimum exponent of
-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
/* 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
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
floatRange is supposed to do what I think it should and what its documentation says it does either these constants or the implementations of
Double need to change.