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

Reply via email to