On May 10, 2011, at 3:40 PM, Matthew Flatt wrote: > At Tue, 10 May 2011 10:05:35 -0400, Matthias Felleisen wrote: >> 2. The addition in lieu of the multiplication is consistently the fastest >> version of the three I mentioned last night: >> >> (: the-sqrt : Real -> Real) >> (define (the-sqrt y) >> (let loop [(x (/ y 2.0))] >> (let [(error (- y (* x x)))] >> (if (< (abs error) epsilon) >> x >> (loop (+ x (/ error (+ x x)))))))) >> >> Our compiler should probably implement reduction of strength optimizations >> based on this one experiment alone. The savings here are over 10%. > > In the variant where you divide by 2, are you using `2' or `2.0'? > > I'd expect `(/ error 2.0 x)' to be faster than `(/ error (+ x x))' in > the case that `x' and `error' are flonums, because it avoids a boxing > step. But `(/ error 2 x)' would be slower, because it mixes a fixnum > with floats. > > Of course, if you want the code to go fast, either use flonum > operations or make the type `Float': > > (: my-sqrt : Natural -> Float) > (define (my-sqrt y) > (let loop [(x (/ (exact->inexact y) 2.0))] > (let [(error (- y (* x x)))] > (if (< (abs error) epsilon) > x > (loop (+ x (/ error (+ x x)))))))) > > Then it's unlikely to matter whether you use `(/ error (+ x x))' or `(/ > error 2 x)' because there's no representation mixing and flonums are > unboxed.
I typed everything as Float (which is what I had last night). I tried (+ x x), 2.0 x, and 2 x on 5 x 1000 iterations over 1000 element lists. The differences are noise (except for one freaky, large exception). -- Matthias _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users