Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-06 Thread Neil Jerram
Noah Lavine noah.b.lav...@gmail.com writes:

 Hello Mark,

 I haven't read through all of the discussion yet, but it's obvious
 that you have good reasons for wanting (* 0 X) to be NaN when X is

NB (and for the record), NaN here should be inexact.




Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-06 Thread Neil Jerram
Mark H Weaver m...@netris.org writes:

 Neil Jerram n...@ossau.uklinux.net writes:

 In other words, the argument is that any inexact number might actually
 be infinite.  (Right?)

 Yes.

 That strikes me as stretching the idea of inexactness too far; and also
 as not useful, because I'm sure there are many practical ways of
 producing inexact numbers that are provably finite (e.g. sqrt(5)).

 There are some cases where it can be proven, but anytime you divide by
 an inexact number (or apply any other function with singularities), you
 must assume that the finiteness of the result is unknown.

Again, that seems impractical to me.  Just as many inexact number
calculations are provably finite, there are many inexact number
calculations that are provably non-zero.  This approach seems like
letting the tail wag the dog.

However, as you've indicated by your question below, what matters for
our purposes is whether it makes a difference to programming.  So I'll
put my intuition aside and focus on that.

 My guess is that for the majority of programming situations where I
 have an inexact number X, that number is provably finite, and so I'd
 want (* 0 X) to be an exact 0.

 Can you give a practical example where it is important for (* 0 X) for
 inexact X to produce an exact 0?  If I understood why this was important
 (besides the aesthetics of an exact result), I might be more motivated
 to try to produce an exact 0 when possible.

No, I can't.

If a program knew for sure that a multiplication included an exact 0,
and that the other arguments were all finite, there would be no point
having the multiplication there.  In other cases, if a program needed to
rely on the result of a multiplication being exact, it would either have
to know that all the arguments were exact, or use inexact-exact.

I think that leaves no cases where it makes a practical difference
whether (* 0 X) is exact or inexact.  So on that basis I'm happy to
concede this point.

Many thanks for your patient explanations, and for all your work on
these numeric patches.

Regards,
Neil



Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-01 Thread Andy Wingo
Hi Mark,

On Tue 01 Feb 2011 13:09, Mark H Weaver m...@netris.org writes:

 Subject: [PATCH] Trigonometric functions return exact numbers in some
 cases

Why would you want this?

Just wondering.

Andy
-- 
http://wingolog.org/



Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-01 Thread Andy Wingo
On Tue 01 Feb 2011 13:09, Mark H Weaver m...@netris.org writes:

 Here's another batch of numerics patches.

Thanks, applied all but the trigonometric functions one, pending further
discussion.

Andy
-- 
http://wingolog.org/



Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-01 Thread Neil Jerram
Mark H Weaver m...@netris.org writes:

 Here's another batch of numerics patches.  The most important one
 changes the way products involving exact 0 are handled:

 * libguile/numbers.c (scm_product): Handle exact 0 differently.  A
   product containing an exact 0 now returns an exact 0 if and only if
   the other arguments are all exact.

I don't get this one.  I would expect ... are all finite.  Why would
an exact 0 times a finite number be inexact?

  If an
   infinite or NaN value is present, a NaN value is returned.

No problem here - this one makes sense.

   A note on the rationale for (* 0 0.0) returning 0.0 and not exact 0:
   The exactness propagation rules allow us to return an exact result in
   the presence of inexact arguments only if the values of the inexact
   arguments do not affect the result.

OK.  And in the case where all the inexact arguments are finite, I would
say that the values of the inexact arguments do not affect the result
is true.

  In this case, the value of the
   inexact argument _does_ affect the result, because an infinite or NaN
   value causes the result to be a NaN.

But in the (* 0 0.0) case, the inexact argument is not an infinite or
NaN value.  So I don't understand the logic here.

Regards,
Neil



Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-01 Thread Mark H Weaver
 Subject: [PATCH] Trigonometric functions return exact numbers in some
 cases

 Why would you want this?

I'm a developer of Maxima, a free CAS (computer algebra system).  I'm
interested in building a free CAS on top of Guile, probably with large
chunks of functionality adapted from Maxima.  As part of this, I would
like it to return exact results whenever feasible.  If the argument
passed to a trig function is a symbolic expression, that will
automatically be handled by GOOPS methods for the various operators.
However, there are a few exceptions where trig functions applied to
simple numbers will never reach GOOPS.  I'd like to do the right thing
in those cases.

Note that this is also the motivation behind my interest in bigfloats,
and in making sure that the numeric code is fully extensible.

 Best,
  Mark



Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-01 Thread Mark H Weaver
Neil Jerram n...@ossau.uklinux.net writes:
 * libguile/numbers.c (scm_product): Handle exact 0 differently.  A
   product containing an exact 0 now returns an exact 0 if and only if
   the other arguments are all exact.

 I don't get this one.  I would expect ... are all finite.

I almost wrote ... are all finite and exact, but exact implies finite,
so I simplified it.

 Why would an exact 0 times a finite number be inexact?

The point of the exact/inexact distinction is to ensure that if you see
an exact number, you can trust that it is provably the correct answer,
and that no inaccuracies associated with inexact arithmetic along the
way could possibly have corrupted that answer.

In this case, the inaccuracies associated with inexact arithmetic could
result in an infinity being misrepresented as a finite number, or vice
versa.  For example, if X is inexact, then we cannot claim that the
result of (* 0 (/ X)) is an exact 0, because a small change in X could
affect the final answer.

 Best,
  Mark



Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-01 Thread Neil Jerram
Mark H Weaver m...@netris.org writes:

 The point of the exact/inexact distinction is to ensure that if you see
 an exact number, you can trust that it is provably the correct answer,
 and that no inaccuracies associated with inexact arithmetic along the
 way could possibly have corrupted that answer.

Yes, I think I understand that.

 In this case, the inaccuracies associated with inexact arithmetic could
 result in an infinity being misrepresented as a finite number, or vice
 versa.  For example, if X is inexact, then we cannot claim that the
 result of (* 0 (/ X)) is an exact 0, because a small change in X could
 affect the final answer.

In other words, the argument is that any inexact number might actually
be infinite.  (Right?)

That strikes me as stretching the idea of inexactness too far; and also
as not useful, because I'm sure there are many practical ways of
producing inexact numbers that are provably finite (e.g. sqrt(5)).  My
guess is that for the majority of programming situations where I have an
inexact number X, that number is provably finite, and so I'd want (* 0
X) to be an exact 0.

But I'm not an expert, and I'm not actually writing those programs
now...

Are you following specific references here?  FWIW, for cases like this,
the last para of R6RS 11.7.1 allows either 0 (exact) or 0.0 (inexact).

Neil



Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-01 Thread Mark H Weaver
Neil Jerram n...@ossau.uklinux.net writes:
 In this case, the inaccuracies associated with inexact arithmetic could
 result in an infinity being misrepresented as a finite number, or vice
 versa.  For example, if X is inexact, then we cannot claim that the
 result of (* 0 (/ X)) is an exact 0, because a small change in X could
 affect the final answer.

 In other words, the argument is that any inexact number might actually
 be infinite.  (Right?)

Yes.

 That strikes me as stretching the idea of inexactness too far; and also
 as not useful, because I'm sure there are many practical ways of
 producing inexact numbers that are provably finite (e.g. sqrt(5)).

There are some cases where it can be proven, but anytime you divide by
an inexact number (or apply any other function with singularities), you
must assume that the finiteness of the result is unknown.  Unless you
keep track of the necessary information about how an inexact number was
computed, you cannot know its finiteness, therefore you must assume the
worst.

One approach to proving finiteness in simple cases might be as follows:
Every inexact number could include an additional flag indicating whether
it's provably finite.  Division by an inexact number would have to
return an inexact number with that flag cleared.  Similarly for other
functions with singularities.  Most other operations would AND the
operand flags together to determine the result flag.

However, I don't currently see that the benefits of this would outweigh
the additional implementation complexity and overhead.

 My guess is that for the majority of programming situations where I
 have an inexact number X, that number is provably finite, and so I'd
 want (* 0 X) to be an exact 0.

Can you give a practical example where it is important for (* 0 X) for
inexact X to produce an exact 0?  If I understood why this was important
(besides the aesthetics of an exact result), I might be more motivated
to try to produce an exact 0 when possible.

 Are you following specific references here?  FWIW, for cases like this,
 the last para of R6RS 11.7.1 allows either 0 (exact) or 0.0 (inexact).

Yes, the R6RS does allow (* 1.0 0) to be an exact 0, but that's because
it also allows (* 0 +inf.0) and (* 0 +nan.0) to be an exact 0.  Section
11.7.4.3 provides the following examples:

  (* 0 +inf.0)  ==  0 or +nan.0
  (* 0 +nan.0)  ==  0 or +nan.0
  (* 1.0 0) ==  0 or 0.0

It follows from the rules of exactness propagation that (* 1.0 0) may be
an exact 0 only if (* 0 X) is an exact 0 for _any_ inexact X.  We
_could_ do this, if we made (* 0 +inf.0) and (* 0 +nan.0) return exact 0
as well.  However, doing this would necessarily destroy the equivalence
of (/ X Y) and (* X (/ Y)), as explained in my first message of this
thread.

The following note in section 11.7.4.3, regarding `min' and `max', gives
a hint of how strictly these exactness rules should be enforced:

  Note: If any argument is inexact, then the result is also inexact
  (unless the procedure can prove that the inaccuracy is not large
  enough to affect the result, which is possible only in unusual
  implementations).  If min or max is used to compare number objects of
  mixed exactness, and the numerical value of the result cannot be
  represented as an inexact number object without loss of accuracy, then
  the procedure may raise an exception with condition type
  implementation-restriction.

 Best,
  Mark



Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-01 Thread Noah Lavine
Hello Mark,

I haven't read through all of the discussion yet, but it's obvious
that you have good reasons for wanting (* 0 X) to be NaN when X is
inexact. And yet for compatibility reasons it is nice if Guile agrees
with Scheme standards. Therefore I think it would be great if you
would send an email with exactly what you said here to
scheme-repo...@scheme-reports.org, which is the public discussion
forum for R7RS.

Of course Guile could just implement this itself, and maybe it will,
but our lives would be much easier if our behavior could be both
useful and standard, and it seems that the best way to do that might
be to change the standard.

Noah

On Tue, Feb 1, 2011 at 11:22 PM, Mark H Weaver m...@netris.org wrote:
 I wrote:
 Are you following specific references here?  FWIW, for cases like this,
 the last para of R6RS 11.7.1 allows either 0 (exact) or 0.0 (inexact).

 Yes, the R6RS does allow (* 1.0 0) to be an exact 0, but that's because
 it also allows (* 0 +inf.0) and (* 0 +nan.0) to be an exact 0.  Section
 11.7.4.3 provides the following examples:

   (* 0 +inf.0)  ==  0 or +nan.0
   (* 0 +nan.0)  ==  0 or +nan.0
   (* 1.0 0)     ==  0 or 0.0

 It follows from the rules of exactness propagation that (* 1.0 0) may be
 an exact 0 only if (* 0 X) is an exact 0 for _any_ inexact X.

 I apologize, I should have admitted that I am going a bit further than
 the R6RS strictly requires, based on my understanding of the rationale
 behind exactness in Scheme.

 It is true that both the R5RS and the R6RS specifically give (* 0 X),
 for inexact X, as an example where it is permissible to return an exact
 0, without mentioning any associated caveats, e.g. that one must also
 make (* 0 +inf.0) and (* 0 +nan.0) be an exact 0 as well.

 I suspect the reason that the R5RS did not mention these caveats is that
 it does not specify anything about infinities or NaNs.  For example,
 MIT/GNU Scheme evaluates (* 0 X) to exact 0 for inexact X, but that is
 justified because its arithmetic operations do not produce infinities or
 NaNs; they throw exceptions instead.

 As for the R6RS, I confess that a strict reading of the exactness
 propagation rule does allow (* 0 X) to be 0 for inexact 0, even
 (* 0 +inf.0) yields something else.  That's because their rule requires
 only that the same result is returned for all possible substitutions of
 _exact_ arguments for the inexact ones.  Since the infinities and NaNs
 are not exact, they are not considered as possible substitutions.

  One general exception to the rule above is that an implementation may
  return an exact result despite inexact arguments if that exact result
  would be the correct result for all possible substitutions of exact
  arguments for the inexact ones.

 I think that the R6RS is wrong here.  As I understand it, the rationale
 for the exactness system is to allow the construction of provably
 correct programs, despite the existence of inexact arithmetic.  One
 should be able to trust that any exact number is provably correct,
 presuming that inexact-exact was not used of course.

 Is there a compelling reason why (* 0 X) should yield an exact 0 for
 inexact X?  Is there a reason more important than being able to trust
 that exact values are provably correct?

    Best,
     Mark





Re: [PATCH] Handle products with exact 0 differently, etc

2011-02-01 Thread Mark H Weaver
Noah Lavine noah.b.lav...@gmail.com writes:
 I haven't read through all of the discussion yet, but it's obvious
 that you have good reasons for wanting (* 0 X) to be NaN when X is
 inexact. And yet for compatibility reasons it is nice if Guile agrees
 with Scheme standards.

In case there is any doubt, the behavior of (* 0 X) that I am advocating
(that it should yield an inexact result when X is inexact) is clearly
permitted by both the R5RS and the R6RS.  That much is beyond any doubt.

My disagreement with the R6RS is that it _permits_ an exact 0 result in
this case, even when infinities and NaNs are supported as numeric
objects.

 Therefore I think it would be great if you would send an email with
 exactly what you said here to scheme-repo...@scheme-reports.org, which
 is the public discussion forum for R7RS.

Yes, thank you for suggesting that, I should write something up.

  Mark