ISO/ IEC JTC1/SC22/WG14 N943

Document WG14 N943
Date: Friday, November 24, 2000 8:12 PM

I was asked by the Austin Common Standards Revision Group
(http://www.opengroup.org/austin/) to clean up their man pages for the
math library functions taking into account C99.  After spending several
days and making multiple passes thru C99 7.12 and Annex F and
considering the comments from the other reviewers, I noticed a few items
that I believe need to be fixed in C99. 

Possible Defect Reports related to the C99 math library. 

1.  fma():  Needs to mention possible overflow and underflow errors.

7.12.13.1 fma: Add to Description: 
 A range error may occur. 

2.  nexttoward():  To make it clearer (required by 7.12.11.4), 

F.9.8.4 nexttoward:
should be changed to: 
 No additional requirements beyond nextafter.
Also, that paragraph should be numbered.

3.  lrint, llrint, lround, llround, ilogb: Need to be consistent (and
explicit) when results are too big to represent in an integer type. 
Also, that case should be treated as a domain error. 

7.12.6.5 ilogb: 
Change: 
 A range error may occur if x is 0.
to 
 A domain error occurs if x is 0, infinite, or NaN.
Add: 
 If the correct value is outside the range of the return type, the
 numeric result is unspecifed, and a domain error occurs. 

7.12.9.5 lrint/llrint: 
Change 
 If the rounded value is outside the range of the return type, the
 numeric result is unspecifed.  A range error may occur if the magnitude
 of x is too large.
to 
 If the rounded value is outside the range of the return type, the
 numeric result is unspecifed, and a domain error occurs. 

7.12.9.7 lround/llround: 
Change 
 If the rounded value is outside the range of the return type, the
 numeric result is unspecifed.  A range error may occur if the magnitude
 of x is too large'
to 
 If the rounded value is outside the range of the return type, the
 numeric result is unspecifed, and a domain error occurs.

4.  pow(0,<0) should be considered a pole error (result is an exact
infinity) in the base standard (it already is in Annex F). 

7.12.7.4 pow: 
Split:
 A domain error may occur if x is zero and y is less than or equal to
 zero.
into
 A domain error may occur if x is zero and y is zero.
and
 A range error may occur if x is zero and y is less than zero.

5.  logb(0) should be considered a pole error in the base standard (it
already is in Annex F).

7.12.6.11 logb: 
Change:  
 A domain error may occur if the argument is zero.
to 
 A range error may occur if the argument is zero.

6.  fmod(), remainder(), and remquo(): As one takes the limit as y
approaches zero, the remainder approaches zero (0 <= |result| < |y|) and
the quotient is unspecified.  This series of changes may also require
that IEEE-754 be changed.  Assuming that fmod, remainder, and remquo
should be consistent with each other, the following needs to be done. 
An alternative is to do some of these changes. 

7.12.10.1 fmod: 
No change needed.

7.12.10.2 remainder: 
Add: 
 If y is zero, whether a domain error occurs or the remainder functions
 return zero is implementation defined. 

7.12.10.3 remquo: 
Add: 
 If y is zero, the quotient stored is unspecified.

F.9.7.1 fmod: 
Change 
 fmod(x,y) returns a NaN and raises the "invalid" floating-point
 exception for x infinite or y zero.
to two items:
 fmod(x,y) returns a NaN and raises the "invalid" floating-point
 exception for x infinite.
and 
 fmod(x,y) returns a zero (with sign of x) for y zero.

F.9.7.2 remainder: 
Add: 
 remainder(x,y) returns a zero (with sign of x) for y zero.

F.9.7.3 remquo: 
Add: 
 remquo(x,y) returns a zero (with sign of x) for y zero and has an
 unspecified quotient stored.
Also add, 
 When remquo returns a NaN, the quotient stored is unspecified.

7.  tgamma(zero or negative integer) should be considered a pole error
since the correct mathematical result is an exact infinity (whose
sign depends upon the direction that the limit is taken from).  Annex F
already does this for the zero argument case.

7.12.8.4 tgamma:
Change:
 A domain error occurs if x is a negative integer or if the result
 cannot be represented when x is zero.
to
 A range error may occur if x is a negative integer or zero.

F.9.5.4 tgamma:
Change:
 tgamma(x) returns a NaN and raises the "invalid" floating-point
 exception for x a negative integer.
to
 tgamma(x) returns +INF and raises the "divide-by-zero"
 floating-point exception for x a negative integer. 
Change:
 tgamma(-INF) returns a NaN and raises the "invalid" floating-point
 exception.
to
 tgamma(-INF) returns +INF and raises the "divide-by-zero"
 floating-point exception.

================================================================

The following is a brief summary of the error cases in the math libarary
functions.  It covers both the base standard (section 7.12) and the
IEEE-754 annex F.  Look for '@@' in the following to find the existing
inconsistent error cases. 

The format of these lines is:  function(arguments) base-error; Annex-F-error 

Domain error
  These should be a required domain error and raise invalid for Annex F.
acos(not in [-1,+1]); invalid if Annex F
asin(not in [-1,+1]); invalid if Annex F
atan2(0,0) = may domain; no invalid if Annex F
cos(INF) invalid if Annex F
sin(INF) invalid if Annex F
tan(INF) invalid if Annex F
acosh(<1); invalid if Annex F
atanh(not in [-1,+1]); invalid if Annex F
log(<0); invalid if Annex F
log10(<0); invalid if Annex F
log1p(<-1); invalid if Annex F
log2(<0); invalid if Annex F
pow(finite negative,finite non-integer); invalid if Annex F
pow(0,0) = may domain; no invalid if Annex F
sqrt(<0); invalid if Annex F
@@ fmod(x,0) = 0 or may domain; invalid if Annex F
fmod(INF,y); invalid if Annex F
@@ remainder(x,0); invalid if Annex F
remainder(INF,y); invalid if Annex F
@@ remquo(x,0); invalid if Annex F
remquo(INF,y); invalid if Annex F
@@ ilogb(0) = may range
@@ lrint, llrint(for large args) = may range; invalid if Annex F
@@ lrint, llrint(NaN or INF); invalid if Annex F
@@ lround, llround(for large args) = may range; invalid if Annex F
@@ lround, llround(NaN or INF); invalid if Annex F
fma(x*y is invalid, z is NaN); optional invalid if Annex F
fma(x*y+z is invalid); invalid if Annex F

Pole (or singularity) error - one kind of range error
  These should be an optional range error and raise div-by-0 for Annex F.
atanh(+/-1) = may range; div-by-0 if Annex F
log(0) = may range; div-by-0 if Annex F
log10(0) = may range; div-by-0 if Annex F
log1p(-1) = may range; div-by-0 if Annex F
log2(0) = may range; div-by-0 if Annex F
@@ logb(0) = may domain; div-by-0 if Annex F
@@ pow(0,<0) = may domain; div-by-0 if Annex F
lgamma(0 or negative int) = may range; div-by-0 if Annex F
@@ tgamma(0) = domain if result is not inf; div-by-0 if Annex F
@@ tgamma(negative int) = domain; invalid if Annex F
@@ tgamma(-INF) = domain; invalid if Annex F

Overflow error - one kind of range error
  These should be a range error and raise overflow for Annex F.
cosh(large args)
sinh(large args)
exp(large args)
exp2(large args)
expm1(large args)
ldexp() = may
scalbn, scalbln() = may
hypot() = may
pow() = may
lgamma(large args)
tgamma(large & small args)
nextafter() result too large = may; overflow if Annex F
nexttoward() result too large = may; overflow if Annex F
fdim() = may
@@ fma() = no errors mentioned

Underflow error - one kind of range error
  These should be a range error and optional raise underflow for Annex F.
exp(large args)
exp2(large args)
ldexp() = may
scalbn, scalbln() = may
hypot() = may
pow() = may
erfc(large args)
fdim() = may
nextafter() result too small; underflow if Annex F
nexttoward() result too small; underflow if Annex F
@@ fma() = no errors mentioned