;;;; mandelbrot.scm - Mandelbrot set (taken from Flake's source code to his book) - felix


(declare 
  (no-winding-callcc)
  (block)
  (foreign-declare "#include \"x11cplot.h\"") )


;;; Foreign parameters:

(define-foreign-variable plot-mag int "plot_mag")
(define-foreign-variable plot-inverse int "plot_inverse")


;;; Foreign functions:

(define plot-init (foreign-lambda void "plot_init" int int int))
(define plot-set-all (foreign-lambda void "plot_set_all" int))
(define plot-point (foreign-lambda void "plot_point" double double int))
(define plot-finish (foreign-lambda void "plot_finish"))

#|
(define plot-set-range (foreign-lambda void "plot_set_range" double double double double))
(define plot-line (foreign-lambda void "plot_line" double double double double int))
(define plot-box (foreign-lambda void "plot_box" double double double double int))
|#


;;; Constants:

(define width 640)
(define height 480)
(define maxit 160)
(define invert #f)
(define levels 256)
(define rev #f)
(define idiv 1)
(define mag 1)
(define ulx -2.4)
(define uly 1.4)
(define lly -1.4)
(define bail 16.0)


;;; Set up plotting stuff:

(set! plot-mag mag)
(set! plot-inverse (if invert 1 0))
(plot-init width height levels)
(plot-set-all 0)


;;; And go...

(let ([inc (/ (- uly lly) (sub1 height))])

  (define (color k)
    (fx+ (fx/ k idiv)
	 (fx* (fxmod k idiv)
	      (fx/ levels idiv)) ) )

  (do ([j 0 (add1 j)]
       [y uly (- y inc)] )
      ((>= j height))
    (do ([i 0 (add1 i)]
	 [x ulx (+ x inc)] )
	((>= i width))
      (let ([a x]
	    [b y] )
	(call-with-current-continuation
	 (lambda (break)
	   (do ([k 1 (add1 k)])
	       ((> k maxit))
	     (let ([u (* a a)]
		   [v (* b b)]
		   [w (* 2.0 a b)] )
	       (set! a (+ (- u v) x))
	       (set! b (+ w y))
	       (when (> (+ u v) bail)
		 (if rev
		     (plot-point i j (fx+ (fxneg (fxmod (color k) levels)) (fx- levels 1)))
		     (plot-point i j (fxmod (color k) levels)) )
		 (break #f) ) ) ) ) ) ) ) ) )

(plot-finish)
