;;; -*- lexical-binding: t -*- ;; samples that hit 256 wrap in the graphic to display as zero ;; exponential 0.8 enhances contrast a bit (let ((a (make-vector 257 0))) (dotimes (v 256) (aset a v (floor (* 256 (expt (/ v 256.0) 0.8))))) (define-inline contrast (v) (aref a v))) (defconst +1fx+ (expt 2 12)) (define-inline fx (x) (* x +1fx+)) (define-inline fx2 (n d) (/ (* n +1fx+) d)) (defconst +4fx+ (fx 4)) (define-inline fx* (l r) (/ (* l r) +1fx+)) (define-inline fx^2 (x) (fx* x x)) (define-inline mandelbrot1 (cx cy) (let ((zr 0) (zi 0) (v 0) zr^2 zi^2) (while (and (< v 256) (<= (+ (setq zr^2 (fx^2 zr)) (setq zi^2 (fx^2 zi))) +4fx+)) (setq v (1+ v)) (let ((tmp (+ zr^2 (- zi^2) cx))) (setq zi (+ (* (fx* zr zi) 2) cy)) (setq zr tmp))) v)) (defun mandelbrot (&optional w h) (declare (speed 3)) (interactive) (let ((output (make-vector (* w h) 0.0)) (idx 0)) (let ((w (or w 1600)) (h (or h 1200)) (x0 (fx2 -25 10)) (y0 (fx2 -15 10))) (let ((dxp (/ (fx 4) w)) (dyp (/ (fx 3) h))) (dotimes (y h) (let ((cy (+ y0 (* dyp y)))) (dotimes (x w) (let ((v (contrast (mandelbrot1 (+ x0 (* dxp x)) cy)))) (aset output idx v) (setq idx (1+ idx)))))))) output)) (defun mandelbrot-bench () (interactive) (let (output) (profiler-start 'cpu+mem) (setq output (mandelbrot 320 200)) (profiler-stop) (profiler-report) (message "%S" output))) ;;(mandelbrot 320 200) ;;(mandelbrot 640 480) ;;(mandelbrot 1024 768) ;;(mandelbrot) ;; (profiler-start 'mem) ;; (mandelbrot 320 200) ;; (profiler-stop) ;; (profiler-report) ;;(profiler-start 'cpu) ;;(mandelbrot 320 200) ;;(profiler-stop) ;;(profiler-report) ;;(profiler-start 'cpu+mem) ;;(mandelbrot) ;;(profiler-stop) ;;(profiler-report) ;; (benchmark-run 1 (mandelbrot 320 200)) ;;(32.898215598 2 0.09366582000001245) ;;(51.629763289 2 0.09165389300000015)