Took a shot at implementing PI in Clojure using a reasonably fast
algorithm.
So why is it so slow ? Is BigDecimal just that bad ? Would fixed point
arithmetic be better using BigInteger ?
(MacBook Pro - Intel Core 2 Duo 2.26 GHz - 4GB RAM)
(set! *warn-on-reflection* true)
(import 'java.lang.Math)
(import 'java.math.MathContext)
(import 'java.math.RoundingMode)
(import 'java.math.BigInteger)
(import 'java.math.BigDecimal)
(defn sb-pi [digits]
"Calculates PI digits using the Salamin-Brent algorithm
and Java's BigDecimal class."
(let [mcdigits (new MathContext (+ 10 digits)) ; add 10 guard digits
zero (new BigDecimal 0)
one (new BigDecimal 1)
two (new BigDecimal 2)
four (new BigDecimal 4)]
(defn big-sqrt[#^BigDecimal num digits]
"Calculates square root using Newton's method."
(defn big-sqrt-int
[#^BigDecimal num
#^BigDecimal x0
#^BigDecimal x1
digits]
(if (not (. x0 equals x1))
(big-sqrt-int
num x1
(. (. x1 add (. num divide x1 digits RoundingMode/
HALF_DOWN))
divide two digits RoundingMode/HALF_DOWN)
digits)
x1))
(big-sqrt-int
num zero (. BigDecimal valueOf (Math/sqrt (. num doubleValue)))
(+ 1 digits)))
(defn sb-pi-int
[#^BigDecimal a #^BigDecimal b #^BigDecimal x #^BigDecimal p n]
(let
[#^BigDecimal a1 (. (. a add b) divide two mcdigits)
#^BigDecimal b1 (big-sqrt (. a multiply b mcdigits) digits)
#^BigDecimal x1 (. x subtract
(. p multiply
(. (. a subtract a1) multiply (. a
subtract a1)
mcdigits) mcdigits))
#^BigDecimal p1 (. two multiply p mcdigits)]
(if (> n digits)
(. (. (. (. a1 add b1) multiply (. a1 add b1) mcdigits)
divide (. four multiply x1) mcdigits) setScale digits
RoundingMode/HALF_UP)
(recur a1 b1 x1 p1 (* 2 n)))))
(let
[#^BigDecimal sa one
#^BigDecimal sb (. one divide (big-sqrt two digits) mcdigits)
#^BigDecimal sx (. one divide four)
#^BigDecimal sp one]
(sb-pi-int sa sb sx sp 1)
)))
(time (println (sb-pi 1))) ;; 4.058 ms
(time (println (sb-pi 10))) ;; 6.611 ms
(time (println (sb-pi 100))) ;; 21.615 ms
(time (println (sb-pi 1000))) ;; 211.314 ms
(time (println (sb-pi 10000))) ;; 22090.236 ms
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---