Created
May 22, 2012 14:36
-
-
Save quoll/2769463 to your computer and use it in GitHub Desktop.
Simple complex number code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns test.complex | |
"A simple complex number library") | |
(defprotocol ComplexOp | |
(abs [this] "The absolute value of the number") | |
(abs2 [this] "The absolute value squared of the number") | |
(plus [this ^Complex that] "Adds another number") | |
(times [this ^Complex that] "Multiplies by another number") | |
(minus [this ^Complex that] "Subtracts another number") | |
(divide [this ^Complex that] "Divides by another number") | |
(plus-dbl [this ^double that] "Adds a real number") | |
(times-dbl [this ^double that] "Multiplies by a real number") | |
(minus-dbl [this ^double that] "Subtracts a real number") | |
(divide-dbl [this ^double that] "Divides by a real number")) | |
(defrecord Complex [re im] | |
ComplexOp | |
(abs [this] (Math/sqrt (+ (* re re) (* im im)))) | |
(abs2 [this] (+ (* re re) (* im im))) | |
(plus [this {tr :re, ti :im}] (Complex. (+ re tr) (+ im ti))) | |
(times [this {tr :re, ti :im}] (Complex. (- (* re tr) (* im ti)) (+ (* re ti) (* im tr)))) | |
(minus [this {tr :re, ti :im}] (Complex. (- re tr) (- im ti))) | |
(divide [this {tr :re, ti :im}] | |
(let [denom (+ (* tr tr) (* ti ti))] | |
(Complex. (/ (+ (* re tr) (* im ti)) denom) (/ (- (* im tr) (* re ti)) denom)))) | |
(plus-dbl [this that] (Complex. (+ re that) im)) | |
(times-dbl [this that] (Complex. (* re that) (* im that))) | |
(minus-dbl [this that] (Complex. (- re that) im)) | |
(divide-dbl [this that] | |
(Complex. (/ re that) (/ im that)))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns test.mand | |
"Mandelbrot generator. Test 2. | |
This version does not use any Java." | |
(:gen-class) | |
(:use [test.complex :only (abs2 times plus)]) | |
(:import [test.complex Complex] | |
[java.awt Graphics Color Dimension] | |
[java.awt.event KeyListener KeyEvent] | |
[java.awt.image BufferedImage] | |
[javax.swing JPanel JFrame SwingUtilities])) | |
(def min-x -2.0) | |
(def max-x 1.0) | |
(def min-y -1.0) | |
(def max-y 1.0) | |
(def limit 1000) | |
(def window-name "Mandelbrot") | |
(def default-width 300) | |
(def default-height 200) | |
(defn ^long scaled-color [^long count] (long (* (Math/log (inc count)) 37))) | |
(defn mandelbrotColor [c] | |
(loop [z (Complex. 0 0) count 0] | |
(if (>= count limit) | |
Color/BLUE | |
(let [z (plus (times z z) c)] | |
(if (>= (abs2 z) 4) | |
(Color. (scaled-color count) 0 0) | |
(recur z (inc count))))))) | |
(defn plot [^Graphics g [x y c]] | |
(.setColor g c) | |
(.fillRect g x y 1 1) | |
g) | |
(defn render [^Graphics g ^long width ^long height] | |
(let [math-width (- max-x min-x) | |
math-height (- max-y min-y) | |
t (System/currentTimeMillis)] | |
(letfn [(coord-2-math [^long x ^long y] | |
(Complex. (+ (/ (* math-width x) width) min-x) | |
(- max-y (/ (* y math-height) height))))] | |
(reduce plot g | |
(map (fn [[a b]] [a b (mandelbrotColor (coord-2-math a b))]) (for [x (range width) y (range height)] [x y])))) | |
(println "Render: " (- (System/currentTimeMillis) t) "ms"))) | |
(defn get-image- [^long width ^long height] | |
(let [image (BufferedImage. width height BufferedImage/TYPE_INT_RGB)] | |
(render (.createGraphics image) width height) | |
image)) | |
(def get-image (memoize get-image-)) | |
(defn new-drawer [] | |
(proxy [JPanel] [] | |
(paint [^Graphics graphics-context] | |
(let [width (proxy-super getWidth) | |
height (proxy-super getHeight)] | |
(.drawImage graphics-context (get-image width height) 0 0 nil))))) | |
(defn show-window [] | |
(let [^JPanel drawing-obj (new-drawer) | |
frame (JFrame. window-name) | |
closer (proxy [KeyListener] [] | |
(keyPressed [^KeyEvent e] (when (= (.getKeyChar e) \q) (.dispose frame))) | |
(keyReleased [e]) | |
(keyTyped [e]))] | |
(.setPreferredSize drawing-obj (Dimension. default-width default-height)) | |
(.add (.getContentPane frame) drawing-obj) | |
(doto frame | |
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) | |
(.pack) | |
(.setBackground Color/WHITE) | |
(.addKeyListener closer) | |
(.setVisible true)))) | |
(defn start-window [] | |
(SwingUtilities/invokeLater #(show-window))) | |
(defn -main [& args] (start-window)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment