Subject: bug#30426: division inconsistency?

From: Mark H Weaver <[email-masked]>
Date: Wed, 14 Feb 2018 15:54:28 -0500

[email-masked] writes:

> Thanks very much for the informative answer!  I am not sure what
> (* 0 +nan.0) should return.  I lean toward +nan.0 mainly because
> I assume NaNs exist to indicate an error somewhere, and you want
> that to be returned.

It's a sensible position.  FWIW, my rationale is that for all exact
integers k, (* k x) => (+ x ...) with k copies of x in the arguments.
By that rule, (* 0 x) => (+).

It's certainly true that NaNs exist to indicate errors, but they might
not be propagated to the final result due to control flow, and for a
typical formal specification of multiplication-by-exact-integer
equivalent to the rule above, the NaN would not be propagated.

More generally, if the result would be the same for _any_ exact real
substituted in place of the NaN, then I believe it's justifiable to drop
the NaN.  R7RS-small states a similar rule in section 6.2.4:

  An arithmetic operation where one operand is NaN returns NaN, unless
  the implementation can prove that the result would be the same if the
  NaN were replaced by any rational number.

> For (* 0 +inf.0) I have no druthers.

> For (/ 0.0 0) and (/ +nan.0 0) s7 throws a divide-by-zero error,
> but I have no good reason for doing this.

For lack of a more comprehensive framework to decide corner cases
involving a mixture of exact and inexact arguments, I've found it useful
to use limits to decide the results of numerical operations involving
inexact zeroes or infinities.  Based on my reading of IEEE 754 and
related articles by Kahan, this is the approach that I've found is most
justifiable and consistent with IEEE 754.

For example, for (<op> 0.0 y ...), I take the limit of (<op> x y ...) as
x approaches zero from above, and similarly for 'x' in other argument
positions.  For -0.0, I take the limit as x approaches zero from below.
Similarly for the infinities.  This rule does not cover cases where more
than one argument is an inexact zero or infinity.

If one accepts this approach, then (/ 0.0 0) is undefined and
(* 0 +inf.0) is 0.

> In s7, I'd prefer to say (/ x y ...) is equal to (/ x (* y ...)) in
> all cases.

FWIW, I believe this is in violation of all RnRS at least as far back as
R3RS, which all specify that '/' returns the quotient of its arguments,
associating to the left.  On the other hand, I've not been shy to
deviate from RnRS when I thought it made sense to do so, so I can't
complain :)

     Regards,
       Mark