Re: [PATCH] Handle products with exact 0 differently, etc
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
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
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
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
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
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
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
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
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
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
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