Prev: Still learning to think in Lisp...
Next: NYC LOCAL: Tuesday 11 May 2010 Lisp NYC Meet and NYLUG Hack Meet
From: Barry Margolin on 11 May 2010 07:57 In article <m18w7qfz65.fsf(a)earthlink.net>, Raymond Toy <rtoy(a)earthlink.net> wrote: > How do you know there is a performance tradeoff? Did you check to see > if sbcl does something different? AFAICT, sbcl does nothing special > in this case and punts to the generic expt routine which checks the > types of both arguments to figure out what needs to be done. The cost > of returning the accurate answer is very small. But what's the benefit? How often do you use LOG with floating point parameters where the number is an exact power of the base? -- Barry Margolin, barmar(a)alum.mit.edu Arlington, MA *** PLEASE post questions in newsgroups, not directly to me *** *** PLEASE don't copy me on replies, I'll read them in the group ***
From: Raymond Toy on 11 May 2010 08:15 >>>>> "Barry" == Barry Margolin <barmar(a)alum.mit.edu> writes: Barry> In article <m18w7qfz65.fsf(a)earthlink.net>, Barry> Raymond Toy <rtoy(a)earthlink.net> wrote: >> How do you know there is a performance tradeoff? Did you check >> to see if sbcl does something different? AFAICT, sbcl does >> nothing special in this case and punts to the generic expt >> routine which checks the types of both arguments to figure out >> what needs to be done. The cost of returning the accurate >> answer is very small. Barry> But what's the benefit? How often do you use LOG with Barry> floating point parameters where the number is an exact Barry> power of the base? What? The benefit is a more accurate answer. What about this then: (expt 5 #c(3d0 0d0)) -> #C(125.00001127654393D0 0.0D0) Would people rather get #c(125d0 0d0) instead? It's not about the base, it's about implementing (expt x y) as (exp (* y (log x))). CMUCL does this, but makes x and y have the same precision before doing the computation. SBCL just uses the formula as is, with the types as given. Ray
From: Raymond Toy on 11 May 2010 08:23 >>>>> "Raymond" == Raymond Toy <rtoy(a)earthlink.net> writes: >>>>> "Barry" == Barry Margolin <barmar(a)alum.mit.edu> writes: Barry> In article <m1mxw7fi6p.fsf(a)earthlink.net>, Barry> Raymond Toy <rtoy(a)earthlink.net> wrote: >>> >>> What is the expected answer? >>> >>> The same issue applies to (log 10 10d0). Ccl and sbcl return >>> 1.0000000138867557D0. Cmucl and clisp return 1d0. Barry> Floating point is an approximation, and errors can creep Barry> in. It looks like the latter implementations have some Barry> special checks for when the number is an exact power of the Barry> base, while the former use the same algorithm for Barry> everything. Raymond> Well, the difference is way bigger than I would have Raymond> expected. In fact, I know that sbcl computes (expt 2 Raymond> #c(2d0 0d0)) as (exp (* #c(2d0 0d0) (log 2))). That (log Raymond> 2) returns a single-float as expected and required. This Raymond> is what causes the loss of accuracy. There's also a kind of inconsistency (with ccl, perhaps others): (expt 5 #c(3d0 0d0)) -> #c(125.0001127654393d0 0d0) (expt 5 3d0) -> 125d0 I would have expected the results to be much closer. Ray
From: Captain Obvious on 11 May 2010 09:21 Captain>> Well, if you want to work at double accuracy, why don't Captain>> you explicitly specify 2 as double-float? RT> Yes, I am well aware of how to get the answer I want. My question is RT> what is the correct answer? When you're working with floating point numbers, there is no such thing as "the correct answer". You should NEVER compare floating point numbers directly, but only with some precision threshold which is relevant to your application and calculations you're doing. RT> How do you know there is a performance tradeoff? Let's say I guess so. Count all possible types for base and power. Mutiply them. That's a number of cases it has to deal with. If you deal with parameters one by one, number of cases is a lot smaller -- you still need to handle calculations which are supposed to be precise by standard in a special way, but for the rest, one common code path will do. RT> The cost of returning the accurate answer is very small. If you think that SBCL can be improved, why don't you speak with SBCL developers? RT> And who said it was only sbcl that does it this way? I guess other have same rationale. But CLISP is high-overhead anyway, so it can spend some time doing dispatch. RT> The rule of float and rational contagion says the rational is RT> converted to a float of the same format. This hints that 2 should be RT> converted to 2d0. The very last sentence says RT> In the case of complex numbers, the real and imaginary parts RT> are effectively handled individually. How about a full quote: "When rationals and floats are compared by a numerical function, the function rational is effectively called to convert the float to a rational and then an exact comparison is performed. In the case of complex numbers, the real and imaginary parts are effectively handled individually." They are handled individually only for comparison! As I understand, complex numbers are considered to be different from floating numbers and rules of contagion are relaxed for them. 12.1.5.2 Rule of Complex Contagion "When a real and a complex are both part of a computation, the real is first converted to a complex by providing an imaginary part of 0." That's all. Formats are not mentioned at all.
From: Tamas K Papp on 11 May 2010 09:47
On Tue, 11 May 2010 08:15:05 -0400, Raymond Toy wrote: >>>>>> "Barry" == Barry Margolin <barmar(a)alum.mit.edu> writes: > > Barry> In article <m18w7qfz65.fsf(a)earthlink.net>, Barry> Raymond > Toy <rtoy(a)earthlink.net> wrote: > > >> How do you know there is a performance tradeoff? Did you check > >> to see if sbcl does something different? AFAICT, sbcl does > >> nothing special in this case and punts to the generic expt > >> routine which checks the types of both arguments to figure out > >> what needs to be done. The cost of returning the accurate answer > >> is very small. > > Barry> But what's the benefit? How often do you use LOG with Barry> > floating point parameters where the number is an exact Barry> power > of the base? > > What? The benefit is a more accurate answer. What about this then: > > (expt 5 #c(3d0 0d0)) -> #C(125.00001127654393D0 0.0D0) > > Would people rather get #c(125d0 0d0) instead? > > It's not about the base, it's about implementing (expt x y) as (exp (* y > (log x))). CMUCL does this, but makes x and y have the same precision > before doing the computation. SBCL just uses the formula as is, with > the types as given. I prefer CMUCL's approach. I think that the extra cost, if any, should be trivial, especially on todays CPU's. I suggest that report it as a bug in SBCL. Now the other, completely orthogonal question is whether a numerical routine should calculate "exact" values for cases when it is possible. The only case when I don't like that to happen is when it causes a discontinuity: eg if a routine uses an approximation for non-integers but an "exact" method for integers, a discontinuity might arise in the neighborhood of integers. So I prefer if the user can signal which method to use: eg have (expt 5 3) calculate it the "exact" way, and (exp 5 3d0) or (exp #C(3d0 0)) using an approximation (which, in the case of EXP, is so good that it is hard to distinguish from the exact result). But this might matter for certain implementations of the gamma function, etc. In the particular problem, I would prefer if (expt x (complex y 0)) always gave the same result as (expt x y), even if there is some extra cost/overhead. I care much more about correctness than speed. Tamas |