On Aug 22, 1:51 pm, jng27 <jgran...@gmail.com> wrote:
> This updated version is 2x as fast as the previous version :
>
> (import 'java.lang.Math)
> (import 'java.math.MathContext)
> (import 'java.math.BigDecimal)
>
> (defn sb-pi [places]
>   "Calculates PI digits using the Salamin-Brent algorithm
>    and Java's BigDecimal class."
>
>   (let [digits (+ 10 places) ;; add some guard digits
>         round-mode BigDecimal/ROUND_DOWN]
>
>     (defn big-sqrt[#^BigDecimal num]
>       "Calculates square root using Newton's method."

You *really* shouldn't do nested defns. They're misleading, as defns
*always* cause a global change.
Just use separate functions.

>
>       (defn big-sqrt-int
>         [#^BigDecimal num
>          #^BigDecimal x0
>          #^BigDecimal x1]
>         (let [x0new x1
>               x1new (. num divide x0new digits round-mode)

Hm, I wonder if there's a way to avoid calling java. But if you do, I
think you should use the form
(.divide num x0new digits round-mode) instead of . directly. It's
lispier and easier to read.

>               x1tot (. (+ x1new x0new)
>                        divide 2M digits round-mode)]
>           (if (= x0 x1)
>             x1tot
>             (recur num x1 x1tot))))
>
>       (big-sqrt-int
>        num 0M (. BigDecimal valueOf (Math/sqrt (. num doubleValue)))))
>
>     (defn sb-pi-int
>       [#^BigDecimal a #^BigDecimal b #^BigDecimal
>        t #^BigDecimal x #^BigDecimal y]
>
>       (let
>           [#^BigDecimal y1 a
>            #^BigDecimal a1 (. (+ a b) divide 2M digits round-mode)
>            #^BigDecimal b1 (big-sqrt (* b y1))
>            #^BigDecimal t1 (- t
>                               (* x
>                                  (* (- y1 a1)
>                                     (- y1 a1))))
>            #^BigDecimal x1 (* x 2M)]
>
>         (if (. a equals b)
Clojure = calls equals, so just use (= a b)

>           (. (. (* (+ a1 b1) (+ a1 b1))
>              divide (* t1 4M) digits round-mode)
>              setScale places round-mode)
This is why I dislike . -- it's almost impossible to tell what
operation you're applying, and to which operands because the operation
name is not at the head of the list. :/
If you really need to use the .divide methods directly, maybe you
could use the -> macro like this:

(-> (* (+ a1 b1) (+ a1 b1)) ; would be faster to (let [tmp (+ a1
b1)]  ...) first though.
     (.divide (* t1 4M) digits round-mode)
     (.setScale places round-mode)

Though I think setting the math context would be a better solution.
eg.
(binding
  [*math-context* (java.math.MathContext. 5 java.math.RoundingMode/
HALF_UP)]
  (* 5M 1.1111105M))
gives 5.5556M

--
Jarkko
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to