Patch to rework IEEE floating point checks

Brad Lucier lucier@math.purdue.edu
Fri Mar 1 13:54:00 GMT 2002


I think rth has already (enthusiastically) approved this.

I should have mentioned that I don't like the name 
MODE_HAS_SIGN_DEPENDENT_ROUNDING.  The problem is that I don't know
what it means.  (I mean, I understand the definition you give, but it
doesn't make sense to me in English.) Round down (to minus infinity)
doesn't seem to be sign dependent, since the direction of rounding does
*not* depend on the sign, but "round to zero" does.  Yet the first counts as
MODE_HAS_SIGN_DEPENDENT_ROUNDING, and the second does not.

Ah, so what.

> > Ths issue here is not just whether EDOM is set for NaN results, but whether
> > the hardware sin/cos have similar accuracy to the library routines.
> > Someone might not care about errno or NaNs but still want full accuracy
> > for sin/cos.
> 
> I think I'm missing your point here, but the "if" statement does just
> add a NaN check.  The code before it emits something like:
> 
>         x = internal_sin (y);
> 
> and the if statement simply adds:
> 
>         if (x != x)
>           errno = EDOM;
> 
> or:
> 
>         if (x != x)
>           x = external_sin (y)
> 
> depending on whether errno is directly accessible.  It should be
> completely redundant for modes without NaNs.

OK, I don't know precisely what the code does now, and I don't want to
spend the time to find out (sorry).  What I'm saying is that the last time
I looked at this code and changed it a bit, I was reminded that one should
use the library sin/cos routines rather than the assembler builtins even
if one didn't care about +0, -0 issues or Nans, but if one does care about
accuracy.  If the code doesn't currently do that, then I think it's
currently wrong.

> *************** fold (expr)
> *** 7151,7158 ****
>   		abort ();
>   	      }
>   
> ! 	  /* If this is A != 0 ? A : 0, this is simply A.  For ==, it is
> ! 	     always zero.  */
>   
>   	  if (integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (arg2))
>   	    {
> --- 7204,7213 ----
>   		abort ();
>   	      }
>   
> ! 	  /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
> ! 	     A == 0 ? A : 0 is always 0 unless A is -0.  Note that
> ! 	     both transformations are correct when A is NaN: A != 0
> ! 	     is then true, and A == 0 is false.  */
>   
>   	  if (integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (arg2))
>   	    {
> *************** fold (expr)
> *** 7162,7170 ****
>   		return pedantic_non_lvalue (convert (type, integer_zero_node));
>   	    }
>   
> ! 	  /* If this is A op B ? A : B, this is either A, B, min (A, B),
> ! 	     or max (A, B), depending on the operation.  */
>   
>   	  if (operand_equal_for_comparison_p (TREE_OPERAND (arg0, 1),
>   					      arg2, TREE_OPERAND (arg0, 0)))
>   	    {
> --- 7217,7248 ----
>   		return pedantic_non_lvalue (convert (type, integer_zero_node));
>   	    }
>   
> ! 	  /* Try some transformations of A op B ? A : B.
> ! 
> ! 	     A == B? A : B    same as B
> ! 	     A != B? A : B    same as A
> ! 	     A >= B? A : B    same as max (A, B)
> ! 	     A > B?  A : B    same as max (B, A)
> ! 	     A <= B? A : B    same as min (A, B)
> ! 	     A < B?  A : B    same as min (B, A)
>   
> + 	     As above, these transformations don't work in the presence
> + 	     of signed zeros.  For example, if A and B are zeros of
> + 	     opposite sign, the first two transformations will change
> + 	     the sign of the result.  In the last four, the original
> + 	     expressions give different results for (A=+0, B=-0) and
> + 	     (A=-0, B=+0), but the transformed expressions do not.
> + 
> + 	     The first two transformations are correct if either A or B
> + 	     is a NaN.  In the first transformation, the condition will
> + 	     be false, and B will indeed be chosen.  In the case of the
> + 	     second transformation, the condition A != B will be true,
> + 	     and A will be chosen.
> + 
> + 	     The conversions to max() and min() are not correct if B is
> + 	     a number and A is not.  The conditions in the original
> + 	     expressions will be false, so all four give B.  The min()
> + 	     and max() versions would give a NaN instead.  */
>   	  if (operand_equal_for_comparison_p (TREE_OPERAND (arg0, 1),
>   					      arg2, TREE_OPERAND (arg0, 0)))
>   	    {

Don't you have to change more than the comments in these two places?
Or is this taken care of later?  (I'm losing track here.)



More information about the Gcc-patches mailing list