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
-~----------~----~----~----~------~----~------~--~---