cvs commit: src/lib/msun/src s_round.c s_roundf.c s_roundl.c

Bruce Evans bde at FreeBSD.org
Fri Dec 2 13:45:07 GMT 2005


bde         2005-12-02 13:45:06 UTC

  FreeBSD src repository

  Modified files:
    lib/msun/src         s_round.c s_roundf.c s_roundl.c 
  Log:
  Fixed roundf().  The following cases never worked in FreeBSD:
  - in round-towards-minus-infinity mode, on all machines, roundf(x) never
    worked for 0 < |x| < 0.5 (2*0x3effffff cases in all, or almost half of
    float space).  It was -0 for 0 < x < 0.5 and 0 for -0.5 < x < 0, but
    should be 0 and -0, respectively.  This is because t = ceilf(|x|) = 1
    for these args, and when we adjust t from 1 to 0 by subtracting 1, we
    get -0 in this rounding mode, but we want and expected to get 0.
  - in round-towards-minus-infinity, round towards zero and round-to-nearest
    modes, on machines that evaluate float expressions in float precision
    (most machines except i386's), roundf(x) never worked for |x| =
    <float value immediately below 0.5> (2 cases in all).  It was +-1 but
    should have been +-0.  This is because t = ceilf(|x|) = 1 for these
    args, and when we try to classify |x| by subtracting it from 1 we
    get an unexpected rounding error -- the result is 0.5 after rounding
    to float in all 3 rounding modes, so we we have forgotten the
    difference between |x| and 0.5 and end up returning the same value
    as for +-0.5.
  
  The fix is to use floorf() instead of ceilf() and to add 1 instead of
  -1 in the adjustment.  With floorf() all the expressions used are
  always evaluated exactly so there are no rounding problems, and with
  adjustments of +1 we don't go near -0 when adjusting.
  
  Attempted to fix round() and roundl() by cloning the fix for roundf().
  This has only been tested for round(), only on args representable as
  floats.  Double expressions are evaluated in double precision even on
  i386's, so round(0.5-epsilon) was broken even on i386's.  roundl()
  must be completely broken on i386's since long double precision is not
  really supported.  There seem to be no other dependencies on the
  precision.
  
  Revision  Changes    Path
  1.4       +6 -6      src/lib/msun/src/s_round.c
  1.4       +6 -6      src/lib/msun/src/s_roundf.c
  1.2       +6 -6      src/lib/msun/src/s_roundl.c


More information about the cvs-all mailing list