interval sqrt and pow exceptions
David G Hough at validgh
validgh
Thu Jan 15 20:49:04 PST 1998
The discussion in December about algorithms that depend on particular
exception handling led to several responses about the case of real
sqrt([-1.0,d]) for 0 < d << 1
The three folks who responded to this specifically favored ignoring the
negative part of the argument and returning the numerical result
[0,sqrt(d)]
along with some kind of exception-occurred status information,
but I haven't gotten comfortable with that approach yet. It seems to
me uncomfortably like the arguments made during IEEE 754 development that
sqrt(x) for x < 0 should return 0, because in a correct program, x
would only be negative because of roundoff and so it could just as well
be zero with no harm done. IEEE 754 specifies returning NaN, however,
because
1) it was deemed more important to avoid misleading results where
they could be easily prevented, and
2) while programmers capable of proving
that negative sqrt arguments could be treated as zero were equally capable
of inserting appropriate tests to convert negative arguments to zero,
3) programmers who hadn't thought about the possibility of program
errors leading to negative arguments to sqrt,
would not be likely to insert tests
for negative arguments, to detect the errors that they hadn't thought about.
The inconvenience to expert programmers was considered less serious than
the inconvenience to inexpert programmers in this instance.
Reasonings about interval exceptions might lead one to define
sqrt([-1,-1]) to be
empty, because the arguments are outside the
domain of real sqrt, or
C*, a special pattern representing all the
real and complex numbers, which surely includes the correct imaginary result, or
NaI, a special pattern representing Not-an-Interval, corresponding
to IEEE 754 Not-a-Number.
Then sqrt([-1,d]) = sqrt([-1,0)] U sqrt([0,d]), leading to the possibilities
[0,sqrt(d)]
C*
NaI
usually with some kind of exception-occurred status as well. Interestingly,
the empty set, C*, and NaI all propagate in similar ways with respect to
arithmetic with ordinary intervals containing numbers; the interesting
differences occur when these symbols interact with each other, and more
particularly in set operations like intersection and union: empty disappears
in union, C* in intersection, while NaI is hard to get rid of, though like
NaN it has to disappear in logical operations whose only possible results are
True or False, with only some kind of exception-occurred status to mark
its passing.
Many interval methods depend on dividing a larger interval into subintervals,
evaluating a function over each subinterval, and taking the union of these
subresults, and work just as well if all out-of-domain invalid results are
simply ignored. Such results are viewed as uninteresting rather than
programming errors to be caught.
Even more interesting are cases like
[-2.0,-2.0] ** [0.3,2.7]
that really bring the exception issues in point x**y into sharp focus. Is it
really right to evaluate that interval expression as the convex hull of
([-2.0,-2.0]) ** 1 U ([-2.0,-2.0]) ** 2 ?
I'm beginning to think that floating-point x**y with negative x should just
be an invalid exception, regardless of the integralness of y,
and that programs that intend to raise negative numbers to
integer powers should do so explicitly, as is easily
expressible in Fortran x**n though more problematic in C.
More information about the Numeric-interest
mailing list