Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 Nov 1995 13:32:49 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        bde@zeta.org.au, markd@grizzly.com
Cc:        freebsd-hackers@freebsd.org, jkh@time.cdrom.com, julian@ref.tfs.com
Subject:   Re: NPX still broken in 2.1.0-951104-SNAP...
Message-ID:  <199511070232.NAA07332@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>>I tried masking overflow and division by 0, leaving only invalid operand
>>exceptions unmasked.  This works quite well for detecting bugs without
>>breaking things that IEEE arithmetic can do well:
>>
>>	pow(0.0, -1.0) = Inf;
>>	int i = pow(0.0, -1.0) => SIGFPE
>>...

>Isn't pow (0.0, -1.0) return an error instead of SIGFPEing?  Here is 

pow() returns OK (see the previous line of the test).  Then the assignment
to the int traps.  It should trap because infinity can't be represented by
an int.  (For the same reason, 1/0 should trap although 1.0/0.0 doesn't.)

>what the SCO manual page says:
>  The pow function returns 0 and sets errno to [EDOM] when x is 0 and y is
>  non-positive, or when x is negative and y is not an integer. In these
>  cases, a message indicating DOMAIN error is printed on the standard error.
>  When the correct value for pow would overflow or underflow, pow returns +/-
>  HUGE or 0 respectively, and sets errno to [ERANGE].

>Seems like its pretty straight forwarded to change __kernel_standard() to
>return NaN instead of zero.  Am I missing something?

The 18 other cases handled by e_pow.c :-).  pow(0.0, -1.0) isn't even a
domain error for a version of pow() as careful as the one in e_pow.c
(NaN would be returned for a domain error).

>If there is not going to be another SNAP, it would obviously be foolish
>to make this change beform the final.  If there is going to be SNAP or too,
>editing the 50 w_*.c files to save the old mask, zero it and then
>restore it on exit would be pretty straight forward.  I could probably

The following works for acos(2.0):
-----
*** w_acos.c~	Wed May 31 19:13:32 1995
--- w_acos.c	Tue Nov  7 10:51:03 1995
***************
*** 33,39 ****
--- 33,46 ----
  	return __ieee754_acos(x);
  #else
  	double z;
+ 	int s = fpgetmask();
+ 	if (s != 0)
+ 		fpsetmask(0);
  	z = __ieee754_acos(x);
+ 	if (s != 0) {
+ 		fpresetsticky(FP_STKY_FLD);
+ 		fpsetmask(s);
+ 	}
  	if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
  	if(fabs(x)>1.0) {
  	        return __kernel_standard(x,x,1); /* acos(|x|>1) */
----
(also #include <floatingpoint.h> in math_private.h).  The fp functions
generate poor code (`fnstcw; fnstenv; fldenv; ... fnstenv; fldenv;
fnstenv; fldenv' plus bitfield fiddling where `fnstcw; fldcw; ...
fnclex; fldcw' plus less bitfield fiddling would be sufficient).
The (s != 0) test reduces the cost if all exceptions are already
masked.

I'm not sure whether isnan(), fabs() or __kernel_standard() can trap.
If the can the the mask would have to be restored before each return.
I wouldn't want to edit the files that much for a temporary change
and would use another layer of wrapping.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199511070232.NAA07332>