(ns de.linuxmagazin.cpu-heizung (:import (java.awt Color Dimension) (java.awt.image BufferedImage) (javax.swing JPanel JFrame))) (def param {:size 500 :max-abs-val 2 :max-iter 2000 :xmin -1.5 :ymin -1.0 :xmax 0.5 :ymax 1.0}) (defn scale-range [x min max steps] (+ min (* x (/ (- max min) steps)))) (defn size-range [] (range 0 (param :size))) (defn color-log-scale "Skalierung des Iterations-Wertes." [n max-n] (max (* 255 (/ (Math/log (* n (/ 255.0 max-n))) (Math/log 255))) 0.0)) (defn color-value "Berechnung des Farbwertes." [iter] (int (- 255 (color-log-scale iter (param :max-iter))))) (defn mandelbrot-iterations-no-type "Naive Implementation der Mandelbrot-Iteration. Kann durch Typ-Hinweise an den Compiler optimiert werden." [x0 y0 max-abs max-iter] (loop [x x0 y y0 iter 0] (if (== iter max-iter) 0 (let [x1 (+ x0 (- (* x x) (* y y))) y1 (+ y0 (* 2.0 (* x y))) abs (+ (* x1 x1) (* y1 y1))] (if (< abs max-abs) (recur x1 y1 (inc iter)) iter))))) (defn mandelbrot-iterations "Naive Implementation der Mandelbrot-Iteration. Enthält Typ-Hinweise für den Compiler." [x0 y0 max-abs max-iterations] (let [x0 (float x0) y0 (float y0) max-iter (int max-iterations)] (loop [x (float x0) y (float y0) iter (int 0)] (if (== iter max-iter) 0 (let [x1 (+ x0 (- (* x x) (* y y))) y1 (+ y0 (* (float 2) (* x y))) abs (+ (* x1 x1) (* y1 y1))] (if (< abs max-abs) (recur x1 y1 (+ iter (int 1))) iter)))))) (defn mandelbrot-line "Berechne eine Zeile der Mandelbrot-Menge. Achtung das Resultat ist lazy." [x] (map (fn [pxy] (let [y (scale-range pxy (param :ymin) (param :ymax) (param :size))] (mandelbrot-iterations x y (param :max-abs-val) (param :max-iter)))) (size-range))) (def world (ref (vec (repeat (param :size) [])))) (defn make-world-image [] (let [img (new BufferedImage (inc (param :size)) (inc (param :size)) BufferedImage/TYPE_INT_ARGB)] (doseq [pxy (size-range)] (let [line (world pxy)] (when (not (empty? line)) (doseq [pxx (size-range)] (.setRGB img pxx pxy (.getRGB (Color. (color-value (line pxx)) (color-value (line pxx)) 255))))))) img)) (defn repaint-world-img [g] (.drawImage g (make-world-image) 0 0 nil)) (def world-agent (agent {})) (defn mandelbrot-parallel [] (let [frame (JFrame. "Fractal Multi-Threaded") panel (proxy [JPanel] [] (paintComponent [g] (proxy-super paintComponent g) (repaint-world-img g) ))] (dosync (ref-set world (vec (repeat (param :size) [])))) (.setPreferredSize panel (Dimension. (param :size) (param :size))) (doto frame (.add panel) (.pack) (.setVisible true)) ;; The Meat (dorun (pmap (fn [pxx] (let [x (scale-range pxx (param :xmin) (param :xmax) (param :size)) newline (vec (mandelbrot-line x))] (dosync (alter world (fn [state] (assoc state pxx newline)))) (send-off world-agent (fn [_] (.repaint panel))))) (size-range))) panel))