I've been playing around with rendering a mandelbrot set, and using
pure java it renders about 2 seconds on my machine, however it runs
about 10 times as slow in clojure, I was curious if I'm doing anything
obviously wrong, or if it's just life :) I do run it with the -server
flag, which does improve it a bit. I've got the java and clojure
source below:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.ImageObserver;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Mandelbrot extends Canvas implements ImageObserver {
public static final int WIDTH = 640;
public static final int HEIGHT = 640;
private static int BAILOUT = 4;
private static int MAX_ITERATIONS = 32;
public BufferStrategy strategy;
public Mandelbrot () {
setBounds(0,0,WIDTH,HEIGHT);
setBackground(Color.BLACK);
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(WIDTH, HEIGHT));
panel.setLayout(null);
panel.add(this);
JFrame frame = new JFrame("Mandelbrot");
frame.add(panel);
frame.setBounds(0,0,WIDTH, HEIGHT);
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create a double buffer
createBufferStrategy(2);
strategy = getBufferStrategy();
requestFocus();
}
private int checkBounds(float x, float y) {
float cr = x;
float ci = y;
float zi = 0.0f;
float zr = 0.0f;
int i = 0;
while (true) {
i++;
float temp = zr * zi;
float zr2 = zr * zr;
float zi2 = zi * zi;
zr = zr2 - zi2 + cr;
zi = temp + temp + ci;
if (zi2 + zr2 > BAILOUT)
return i;
if (i > MAX_ITERATIONS)
return 0;
}
}
private void draw() {
float x = -2.1f, y = -1.5f, z = 3.0f;
int i, j;
Graphics g = strategy.getDrawGraphics();
g.clearRect(0, 0, getWidth(), getHeight());
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
int value = checkBounds((x +
z*(i/(float)WIDTH)), (y + z*(j/(float)
HEIGHT)));
if (value > 0) {
g.setColor(new
Color(value*255/MAX_ITERATIONS));
g.drawRect(i, j, 0, 0);
}
}
strategy.show();
}
strategy.show();
}
public static void main(String args[]) {
Mandelbrot m = new Mandelbrot();
long startTime = System.currentTimeMillis();
m.draw();
System.out.println((System.currentTimeMillis() -
startTime)/1000);
}
}
Clojure:
(ns main
(:import (java.awt Color Container Graphics Canvas Dimension)
(javax.swing JPanel JFrame)
(java.awt.image BufferedImage BufferStrategy)))
(def *width* 640)
(def *height* 640)
(def *max-steps* 32)
(defn on-thread [f] (doto (new Thread f) (.start)))
(defn check-bounds [x y]
(loop [px x
py y
zx 0.0
zy 0.0
zx2 0.0
zy2 0.0
value 0]
(if (and (< value *max-steps*) (< (+ zx2 zy2)
4.0))
(let [new-zy (+ (* 2.0 zx zy) py)
new-zx (+ (- zx2 zy2) px)
new-zx2 (* new-zx new-zx)
new-zy2 (* 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 [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*))
([buffer g y]
(doseq [y (range 0 y)]
(draw-line g y)
;(on-thread (draw-line g y))
(. buffer show))))
(defn draw [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))
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
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
-~----------~----~----~----~------~----~------~--~---