[std-interval] Out-of-domain behavior

Guillaume Melquiond guillaume.melquiond at ens-lyon.fr
Mon Oct 9 15:46:39 PDT 2006

Le dimanche 08 octobre 2006 à 08:55 -0700, Steve Clamage a écrit :

> I'm sorry, I didn't mean to introduce any confusion by talking about a
> hypothetical "iNaN".
>
> There is no real number corresponding to sqrt(-1), but if sqrt returns,
> it must return some value.
>
> I only wanted to distinguish the case of returning a result when there

[ This mail is meant to state anew, what the problem is precisely, so
that we don't get sidetracked too much. ]

The NaI was only discussed as a way to return something when one of the
inputs has no interpretation as an interval, for example a NaN
floating-point value. This is just an implementation detail due to some
functions/constructors having floating-point arguments. Let's focus on
interval arithmetic; the important point is: With interval functions,
there _always_ is an interval answer. This is a consequence of the
mathematical model we chose in the proposal: intervals are sets and
functions are set extensions. Example: sqrt([-1,2]) returns a superset
of [0,sqrt(2)] while sqrt([-1,-1]) returns the empty set.

Unfortunately, when solving equations (differential or not), this
resulting set does not contain enough information. You also want to know
if some values of the input interval were out of the domain of the real
function. This information should not replace the previous interval, it
has to be an _extra_ information. This is why neither an exception nor a
NaI are good solutions, as you will lose the "set" part of the answer.
Moreover, the out-of-domain information has to propagate till the end of
the computations: it has not much sense locally, it is only useful when
looking at the global computation.

So, if we want to use the most interesting interval algorithms, we
should systematically use something like a pair<interval, bool> instead
of just an interval, both at input and at output of interval functions.
This is neither usable nor efficient.

So the two solutions we are left with are:

1. Using an explicit parameter:

interval my_function(interval x, interval y, bool &f)
{ return divide(sqrt(x, f), 1. + sqrt(asin(x) + y, f), f); }

2. Using an implicit (global) parameter:

interval my_function(interval x, interval y)
{ return sqrt(x) / (1. + sqrt(asin(x) + y)); }

The first solution has a clean semantic and it is vendor-friendly, as
there is no side effect. The second solution is user-friendly, as it is
more readable, less error-prone (have you noticed the mistake in the
first version of my_function?), and probably more efficient. I don't
think any of these two solutions is clearly superior, and unfortunately
I don't have anything better to suggest.

Best regards,

Guillaume