cvs commit: src/lib/msun/src e_pow.c e_powf.c

Bruce Evans bde at FreeBSD.org
Thu Feb 14 01:42:24 PST 2008


bde         2008-02-14 09:42:24 UTC

  FreeBSD src repository

  Modified files:
    lib/msun/src         e_pow.c e_powf.c 
  Log:
  Use the expression (x+0.0)-(y+0.0) instead of x+y when mixing NaN arg(s).
  This uses 2 tricks to improve consistency so that more serious problems
  aren't hidden in simple regression tests by noise for the NaNs:
  
  - for a signaling NaN, adding 0.0 generates the invalid exception and
    converts to a quiet NaN, and doesn't have too many effects for other
    types of args (it converts -0 to +0 in some rounding modes, but that
    hopefully doesn't change the result after adding the NaN arg).  This
    avoids some inconsistencies on i386 and ia64.  On these arches, the
    result of an operation on 2 NaNs is apparently the largest or the
    smallest of the NaNs as bits (consistently largest or smallest for
    each arch, but the opposite).  I forget which way the comparison
    goes and if the sign bit affects it.  The quiet bit is is handled
    poorly by not always setting it before the comparision or ignoring
    it.  Thus if one of the args was originally a signaling NaN and the
    other was originally a quiet NaN, then the result depends too much
    on whether the signaling NaN has been quieted at this point, which
    in turn depends on optimizations and promotions.  E.g., passing float
    signaling NaNs to double functions must quiet them on conversion;
    on i387, loading a signaling NaN of type float or double (but not
    long double) into a register involves a conversion, so it quiets
    signaling NaNs, so if the addition has 2 register operands than it
    only sees quiet NaNs, but if the addition has a memory operand then
    it sees a signaling NaN iff it is in the memory operand.
  
  - subtraction instead of addition is used to avoid a dubious optimization
    in old versions of gcc.  For SSE operations, mixing of NaNs apparently
    always gives the target operand.  This is not as good as the i387
    and ia64 behaviour.  It doesn't mix NaNs at all, and makes addition
    not quite commutative.  Old versions of gcc sometimes rewrite x+y
    to y+x and thus give different results (in bits) for NaNs.  gcc-3.3.3
    rewrites x+y to y+x for one of pow() and powf() but not the other,
    so starting from float NaN args x and y, powf(x, y) was almost always
    different from pow(x, y).
  
  These tricks won't give consistency of 2-arg float and double functions
  with long double ones on amd64, since long double ones use the i387
  which has different semantics from SSE.
  
  Convert to __FBSDID().
  
  Revision  Changes    Path
  1.12      +4 -5      src/lib/msun/src/e_pow.c
  1.13      +4 -5      src/lib/msun/src/e_powf.c


More information about the cvs-src mailing list