Can Chapel catch division by zero?

Hi! I am trying to catch a division by zero error:

var zf: real;
try {
   zf = zminop  - Aminop/dAlop(zminop);
}
catch {
   zf = zminop;
}

where dAlop(zminop) returns 0.0, but it does not seem to work. I wonder if it is possible at present to catch floating point exceptions? Any suggestions welcome! Thanks,

Nelson

Hi Nelson,

For me the computation zf = zminop - Aminop/dAlop(zminop); completes successfully, producing -inf. Would this work for you if you checked for it using isinf and/or isnan ?

We currently do not have exceptions for arithmetic operations, and even if we did, exceptions might add noticeable performance overhead.

Vass

Hi Vass: thanks for the answer. I imagined that performance could be an issue. My program runs and gives -inf for zf. Of course, an old-fashioned if (or isinf, or isnan) solves the issue, so I will use it.

regards

Nelson

You do not need to be that extreme, nor sacrifice too much performance. If what you describe is all you are trying to do, there are alternatives. Note that the invocation of isinf() or isnan() as they are currently implemented in many libraries include a mandatory memory access.

The code to test whether x is +INFINITY or -INFINITY is

if abs(x) == INFINITY then // pretty obvious

The code to test whether some number is a Not-A-Number or NaN is

if x != x then // only happens with x is actually an NaN

The above on the other hand, will only incur the penalty of a floating point comparison.

Try this

type Real = real(32);
const zero = 0:Real;
const inf = INFINITY:Real;
const one = 1:Real;
const t = one / zero;
const z = (zero - zero) / (zero - zero);

writeln("comparing against INFINITY ", if t == inf then "works" else "fails");
writeln("verifying real(w) is a NAN ", if z != z then "works" else "fails");

If you really want to be extravagant, you can start looking for IEEE 754 exceptions which are very different animals to a Chapel (or C++) exception. And they may have all sorts of optimization issues because Chapel does not honour statement sequence when producing code.

I compile with --fast and follow that by --ieee-float to make sure the compiler does think that the comparison of a number against itself will ever fail (which some dumb optimizer might assume).

None of the above codes introduces superfluous IEEE754 exceptions.

Looking at your code, if the term

Aminop/dAlop(zminop)

blows up, i.e. goes to INFINITY, you want to throw it away. Would

zf = zminop - let t = Aminop/dAlop(zminop) in if abs(t) != INFINITY then t else 0:t.type;

achieve the same result?

Hi Damian: thanks for the suggestion.

I had settled with the rather orthodox
if dAlop(zminop) == 0.0 then {
zf = zminop;
}
else {
zf = zminop - Aminop/dAlop(zminop);
}

The alternative you proposed
zf = zminop - let
t = Aminop/dAlop(zminop) in
if abs(t) != INFINITY then t else 0.0;

seems to produce the same results. Apart from the fact that I am calling a function twice in the first alternative, and that this could of course be avoided, an if is still needed in both options, so I wonder if the second has an advantage in performance.

Regards

Nelson

Your solution does not catch the case where the function is much much smaller than Aminop and the division still yields INFINITY. Unless of course you want zf to really be set to -INFINITY

In answer to your question after performance, I would always avoid two function calls when I can do the same calculation with one. Period!