thanks a lot, that's really helpful.
On Apr 2, 7:25 am, Paul Stadig <p...@stadig.name> wrote:
> I got it down to about 3 seconds. I did what William said, but the biggest
> improvement was from changing the way *width*, *height*, and *max-steps*
> were defined. I noticed that in the Java version they are constants, but in
> the Clojure version they are Vars which means that inside your tight inner
> loops you are dereferencing the vars multiple times. Vars are for thread
> local values, but these values are not expected to change. I'm not sure the
> best way to make these vars into constants, but I changed them into macros:
>
> (defmacro *width* [] (float 640))
>
> Then replaced instances of *width* with (*width*). The macros will get
> compiled down to floats instead of resulting in multiple Var.deref calls
> (and probably Number.floatValue calls) per loop iteration.
>
> Here is the code:
>
> (ns main
> (:import (java.awt Color Container Graphics Canvas Dimension)
> (javax.swing JPanel JFrame)
> (java.awt.image BufferedImage BufferStrategy)))
>
> (set! *warn-on-reflection* true)
>
> (defmacro *width* [] (float 640))
> (defmacro *height* [] (float 640))
> (defmacro *max-steps* [] (float 32))
>
> (defn on-thread [#^Runnable f] (doto (new Thread f) (.start)))
>
> (defn check-bounds [x y]
> (loop [px (float x)
> py (float y)
> zx (float 0.0)
> zy (float 0.0)
> zx2 (float 0.0)
> zy2 (float 0.0)
> value (float 0)]
> (if (and (< value (*max-steps*)) (< (+ zx2 zy2) (float 4.0)))
> (let [new-zy (float (+ (* (float 2.0) zx zy) py))
> new-zx (float (+ (- zx2 zy2) px))
> new-zx2 (float (* new-zx new-zx))
> new-zy2 (float (* new-zy new-zy))]
> (recur px py new-zx new-zy new-zx2 new-zy2 (inc value)))
> (if (== value (*max-steps*)) 0 value))))
>
> (defn draw-line [#^Graphics g y]
> (let [dy (- 1.25 (* 2.5 (/ y (*height*))))]
> (doseq [x (range 0 (*width*))]
> (let [dx (- (* 2.5 (/ x (*width*))) 2.0)]
> (let [value (check-bounds dx dy)]
> (if (> value 0)
> (doto g
> (. setColor (Color. (* value (/ 255
> (*max-steps*)))))
> (. drawRect x y 0 0))))))))
>
> (defn draw-lines
> ([buffer g] (draw-lines buffer g (*height*)))
> ([#^BufferStrategy buffer g y]
> (doseq [y (range 0 y)]
> (draw-line g y)
> ;(on-thread (draw-line g y))
> (. buffer show))))
>
> (defn draw [#^Canvas canvas]
> (let [buffer (. canvas getBufferStrategy)
> g (. buffer getDrawGraphics)]
> (draw-lines buffer g)))
>
> (defn main []
>
> (let [panel (JPanel.)
> canvas (Canvas.)
> frame (JFrame. "Mandelbrot")]
>
> (doto panel
> (.setPreferredSize (Dimension. (*width*) (*height*)))
> (.setLayout nil)
> (.add canvas))
>
> (doto frame
> (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
> (.setBounds 0,0,(*width*) (*height*))
> (.setResizable false)
> (.add panel)
> (.setVisible true))
>
> (doto canvas
> (.setBounds 0,0,(*width*) (*height*))
> (.setBackground (Color/BLACK))
> (.createBufferStrategy 2)
> (.requestFocus))
>
> (draw canvas)))
>
> (time (main))
>
> ~$ clojure /tmp/mandelbrot.clj
> "Elapsed time: 3577.128587 msecs"
>
> Paul
--~--~---------~--~----~------------~-------~--~----~
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
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
-~----------~----~----~----~------~----~------~--~---