...
Many math errors can be prevented by carefully bounds checking the arguments before calling functions, and taking alternative action if the bounds are violated. In particular, the following functions should be bounds checked as follows:
However, for some functions it is not practical to use bounds checking to prevent all errors. In the above pow
example, the bounds check does not prevent the pow(10., 1e6)
range error. In these cases detection must be used, either in addition to bounds checking or instead of bounds checking.
...
lgammma(x) | (x == 0) || (x < 0 && x is an integer) || (x is too large) |
tgammma(x) | (x == 0) || (x < 0 && x is an integer) || (x is too large) || (x is too small) |
However, for some functions it is not practical to use bounds checking to prevent all errors. In the above pow
example, the bounds check does not prevent the pow(10., 1e6)
range error. In these cases detection must be used, either in addition to bounds checking or instead of bounds checking.
acos(x), asin(x)
Noncompliant Code Example
The following noncompliant code computes the arc cosine of the variable x
...
acos(x), asin(x)
Noncompliant Code Example
The following noncompliant code computes the arc cosine of the variable x
Code Block |
---|
|
double x;
double result;
/* Set the value for x */
result = acos(x);
|
Wiki Markup |
---|
However, this code may produce a _domain error_ if {{x}} is not in the range \[-1, \+1\]. |
Compliant Solution
The following compliant solution uses bounds checking to ensure that there is not a domain error.
Code Block |
---|
|
double x;
double result;
/* Set the value for x */
ifresult (= isnanacos(x) || isless(x,-1) || isgreater(x, 1) ){
/* handle domain error */
}
result = acos(x);
|
...
Wiki Markup |
---|
However, this code may produce a _domain error_ if {{x}} is not in the range \[-1, \+1\]. |
Compliant Solution
The following compliant solution uses bounds checking to ensure that there is not a domain error
...
atan2(y, x)
Noncompliant Code Example
The following noncompliant code computes the arc tangent of the two variables x
and y
.
Code Block |
---|
|
double x;
double y;
double result;
/* Set the value for x and y */
resultif =( atan2(y, x);
|
However, this code may produce a domain error if both x
and y
are zero.
Compliant Solution
isnan(x) || isless(x,-1) || isgreater(x, 1) ){
/* handle domain error */
}
result = acos(x);
|
atan2(y, x)
Noncompliant Code Example
The following noncompliant code computes the arc tangent of the two variables x
and y
The following compliant solution tests the arguments to ensure that there is not a domain error.
Code Block |
---|
|
double x;
double y;
double result;
/* Set the value for x and y */
ifresult = atan2(y, (x == 0.f) && (y == 0.f) ) {
/* handle domain error */
}
result = atan2(y, x);
|
...
However, this code may produce a domain error if both x
and y
are zero.
Compliant Solution
The following compliant solution tests the arguments to ensure that there is not a domain error
...
log(x), log10(x)
Noncompliant Code Example
The following noncompliant code determines the natural logarithm of x
.
Code Block |
---|
|
double x;
double y;
double result;
/* Set the value for x and y */
resultif ( (x = log(x);
|
However, this code may produce a domain error if x
is negative and a range error if x
is zero.
Compliant Solution
= 0.f) && (y == 0.f) ) {
/* handle domain error */
}
result = atan2(y, x);
|
log(x), log10(x)
Noncompliant Code Example
The following noncompliant code determines the natural logarithm of x
The following compliant solution tests the suspect arguments to ensure that no domain errors or range errors are raised.
Code Block |
---|
|
double x;
double result;
/* Set the value for x */
if (isnan(x) || islessequal(x, 0)) {
/* handle domain and range errors */
}
result = log(x);
|
...
However, this code may produce a domain error if x
is negative and a range error if x
is zero.
Compliant Solution
The following compliant solution tests the suspect arguments to ensure that no domain errors or range errors are raised
...
pow(x, y)
Noncompliant Code Example
The following noncompliant code raises x
to the power of y
.
Code Block |
---|
|
double x;
double yresult;
double result;
result = pow
/* Set the value for x */
if (isnan(x) || islessequal(x, y0));
|
...
{
/* handle domain and range errors */
}
result = log(x);
|
pow(x, y)
Noncompliant Code Example
This code only performs bounds checking on x
and y
. It prevents domain errors and some range errors, but does not prevent range errors where the result cannot be represented as a double
(see the Error Checking and Detection section below regarding ways to mitigate the effects of a range error)The following noncompliant code raises x
to the power of y
.
Code Block |
---|
|
double x;
double y;
double result;
ifresult = pow(((x == 0.f) && islessequal(y, 0)) ||
(isless(x, 0))) {
/* handle domain and range errors */
}
result = pow(x, y);
|
...
However, this code may produce a domain error if x
is negative and y
is not an integer, or if x
is zero and y
is zero. A domain error or range error may occur if x
is zero and y
is negative, and a range error may occur if the result cannot be represented as a double
.
Noncompliant Code Example
This code only performs bounds checking on x
and y
. It prevents domain errors and some range errors, but does not prevent range errors where the result cannot be represented as a double
(see the Error Checking and Detection section below regarding ways to mitigate the effects of a range error).
...
sqrt(x)
Noncompliant Code Example
The following noncompliant code determines the square root of x
Code Block |
---|
|
double x;
double y;
double result;
result = sqrt(x);
|
However, this code may produce a domain error if x
is negative.
Compliant Solution
if (((x == 0.f) && islessequal(y, 0)) ||
(isless(x, 0))) {
/* handle domain and range errors */
}
result = pow(x, y);
|
sqrt(x)
Noncompliant Code Example
The following noncompliant code determines the square root of x
The following compliant solution tests the suspect argument to ensure that no domain error is raised.
Code Block |
---|
|
double x;
double result;
result = sqrt(x);
|
However, this code may produce a domain error if x
is negative.
Compliant Solution
The following compliant solution tests the suspect argument to ensure that no domain error is raised.
Code Block |
---|
|
double x;
double result;
if (isless(x, 0)){
/* handle domain error */
}
result = sqrt(x);
|
lgamma(x), tgamma(x)
The "too large" and "too small" conditions for a range error in the gamma functions are vague enough to make it very difficult to catch all possible range errors simply by looking at the input.
Noncompliant Code Example
The following noncompliant code example attempts to prevent domain and range errors, but a range error occurs nonetheless.
Code Block |
---|
|
float x = -90.5;
if ((x == 0) || (x < 0 && x == nearbyint(x))) {
/* Handle Error */
}
float f = tgamma(x);
|
Compliant Solution
This compliant solution detects the underflow by using the methods described below in the Error Checking and Detection section.
Code Block |
---|
|
float x = -90.5;
if ((x == 0) || (x < 0 && x == nearbyint(x))) {
/* Handle Error */
}
feclearexcept(FE_ALL_EXCEPT);
float f = tgamma(x)
double x;
double result;
if (isless(x,fetestexcept(FE_UNDERFLOW) != 0)) {
/* handle domain error */
}
result = sqrt(x);printf("Underflow detected\n");
}
|
Anchor |
---|
| Error Checking and Detection |
---|
| Error Checking and Detection |
---|
|
Error Checking and Detection
Wiki Markup |
---|
The exact treatment of error conditions from math functions is quite complicated. C99 Section 7.12.1 defines the following behavior for floating point overflow \[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] |
...