From: Frank Buss
Subject: Mandelbrot for the terminal
Date: 
Message-ID: <ceef5p$cch$1@newsreader2.netcologne.de>
Based on a Java program ( http://tinyurl.com/57smz ) I've implemented a 
Lisp program for showing the Mandelbrot set:

  (loop for y from -1 to 1.1 by 0.1 do
        (loop for x from -2 to 1 by 0.04 do
              (let* ((c 126)
                     (z (complex x y))
                     (a z))
                (loop while (< (abs
                                (setq z (+ (* z z) a)))
                               2)
                  while (> (decf c) 32)) 
                (princ (code-char c))))
        (format t "~%"))

I tried to make it as short as possible and it is some chars shorter than 
the Java program, if written in one line without much spaces. With CLISP, 
the program is only 4 times slower than the Java program. Nice result, I 
didn't expect this with my unoptimized program and using complex variables.

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de

From: Abdulaziz Ghuloum
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <cef8bj$jhv$1@hood.uits.indiana.edu>
Frank Buss wrote:

> Based on a Java program ( http://tinyurl.com/57smz ) I've implemented a 
> Lisp program for showing the Mandelbrot set:
> 
>   (loop for y from -1 to 1.1 by 0.1 do
>         (loop for x from -2 to 1 by 0.04 do
>               (let* ((c 126)
>                      (z (complex x y))
>                      (a z))
>                 (loop while (< (abs
>                                 (setq z (+ (* z z) a)))
>                                2)
>                   while (> (decf c) 32)) 
>                 (princ (code-char c))))
>         (format t "~%"))
> ...

And a scheme version:

(define (mandel)
   (do ((y -1 (+ y 0.1))) ((> y 1))
     (do ((x -2 (+ x 0.04))) ((> x 1))
       (let ((a (make-rectangular x y)))
         (let loop ((z a) (c 126))
           (let ((q (+ a (* z z))))
             (if (and (< (magnitude q) 2) (> c 32))
                 (loop q (sub1 c))
                 (display (integer->char c)))))))
     (newline)))


Aziz,,,
From: David Steuber
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <4ddd570c.0407310523.33b58367@posting.google.com>
Abdulaziz Ghuloum <········@c-s-remove-dashes.indiana.edu> wrote in message news:<············@hood.uits.indiana.edu>...
> And a scheme version:
> 
> (define (mandel)
>    (do ((y -1 (+ y 0.1))) ((> y 1))
>      (do ((x -2 (+ x 0.04))) ((> x 1))
>        (let ((a (make-rectangular x y)))
>          (let loop ((z a) (c 126))
>            (let ((q (+ a (* z z))))
>              (if (and (< (magnitude q) 2) (> c 32))
>                  (loop q (sub1 c))
>                  (display (integer->char c)))))))
>      (newline)))

I really should get back to my CL version that does images.  My movie
is still on my website.  But that was done with a combination of Perl
and C.

http://www.david-steuber.com/~david/fractal-movie/
From: Edi Weitz
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <874qnp87wp.fsf@bird.agharta.de>
On Fri, 30 Jul 2004 21:39:05 +0000 (UTC), Frank Buss <··@frank-buss.de> wrote:

> Based on a Java program ( http://tinyurl.com/57smz ) I've
> implemented a Lisp program for showing the Mandelbrot set:
>
>   (loop for y from -1 to 1.1 by 0.1 do
>         (loop for x from -2 to 1 by 0.04 do
>               (let* ((c 126)
>                      (z (complex x y))
>                      (a z))
>                 (loop while (< (abs
>                                 (setq z (+ (* z z) a)))
>                                2)
>                   while (> (decf c) 32)) 
>                 (princ (code-char c))))
>         (format t "~%"))
>
> I tried to make it as short as possible and it is some chars shorter
> than the Java program, if written in one line without much
> spaces. With CLISP, the program is only 4 times slower than the Java
> program. Nice result, I didn't expect this with my unoptimized
> program and using complex variables.

If I change it a little bit

  (defun mandel ()
    (loop for y from -1 to 1.1 by 0.1 do
      (loop for x from -2 to 1 by 0.04 do
        (let* ((c 126)
               (z (complex x y))
               (a z))
          (loop while (and (< (abs
                               (setq z (+ (* z z) a)))
                              2)
                           (> (decf c) 32)))
          (princ (code-char c))))
      (princ #\Newline)))

and compile it with CMUCL (19a-pre3) then it's actually faster by a
factor of 1.3 than the Java (1.5.0-beta2) version on my
laptop. Cool... :)

-- 

"Lisp doesn't look any deader than usual to me."
(David Thornley, reply to a question older than most languages)

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Peter Seibel
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <m3hdrpb0ot.fsf@javamonkey.com>
Edi Weitz <········@agharta.de> writes:

> On Fri, 30 Jul 2004 21:39:05 +0000 (UTC), Frank Buss <··@frank-buss.de> wrote:
>
>> Based on a Java program ( http://tinyurl.com/57smz ) I've
>> implemented a Lisp program for showing the Mandelbrot set:
>>
>>   (loop for y from -1 to 1.1 by 0.1 do
>>         (loop for x from -2 to 1 by 0.04 do
>>               (let* ((c 126)
>>                      (z (complex x y))
>>                      (a z))
>>                 (loop while (< (abs
>>                                 (setq z (+ (* z z) a)))
>>                                2)
>>                   while (> (decf c) 32)) 
>>                 (princ (code-char c))))
>>         (format t "~%"))
>>
>> I tried to make it as short as possible and it is some chars shorter
>> than the Java program, if written in one line without much
>> spaces. With CLISP, the program is only 4 times slower than the Java
>> program. Nice result, I didn't expect this with my unoptimized
>> program and using complex variables.
>
> If I change it a little bit
>
>   (defun mandel ()
>     (loop for y from -1 to 1.1 by 0.1 do
>       (loop for x from -2 to 1 by 0.04 do
>         (let* ((c 126)
>                (z (complex x y))
>                (a z))
>           (loop while (and (< (abs
>                                (setq z (+ (* z z) a)))
>                               2)
>                            (> (decf c) 32)))
>           (princ (code-char c))))
>       (princ #\Newline)))
>
> and compile it with CMUCL (19a-pre3) then it's actually faster by a
> factor of 1.3 than the Java (1.5.0-beta2) version on my
> laptop. Cool... :)

Man, that's rad! Just pasted that puppy in my REPL and boom! ASCII art
Mandlebrot. Nice.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: neo88
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <6a73bb68.0407301840.2ee9335f@posting.google.com>
Peter Seibel <·····@javamonkey.com> wrote in message news:<··············@javamonkey.com>...
> Edi Weitz <········@agharta.de> writes:
> 
> > On Fri, 30 Jul 2004 21:39:05 +0000 (UTC), Frank Buss <··@frank-buss.de> wrote:
> >
> >> Based on a Java program ( http://tinyurl.com/57smz ) I've
> >> implemented a Lisp program for showing the Mandelbrot set:
> >>
> >>   (loop for y from -1 to 1.1 by 0.1 do
> >>         (loop for x from -2 to 1 by 0.04 do
> >>               (let* ((c 126)
> >>                      (z (complex x y))
> >>                      (a z))
> >>                 (loop while (< (abs
> >>                                 (setq z (+ (* z z) a)))
> >>                                2)
> >>                   while (> (decf c) 32)) 
> >>                 (princ (code-char c))))
> >>         (format t "~%"))
> >>
> >> I tried to make it as short as possible and it is some chars shorter
> >> than the Java program, if written in one line without much
> >> spaces. With CLISP, the program is only 4 times slower than the Java
> >> program. Nice result, I didn't expect this with my unoptimized
> >> program and using complex variables.
> >
> > If I change it a little bit
> >
> >   (defun mandel ()
> >     (loop for y from -1 to 1.1 by 0.1 do
> >       (loop for x from -2 to 1 by 0.04 do
> >         (let* ((c 126)
> >                (z (complex x y))
> >                (a z))
> >           (loop while (and (< (abs
> >                                (setq z (+ (* z z) a)))
> >                               2)
> >                            (> (decf c) 32)))
> >           (princ (code-char c))))
> >       (princ #\Newline)))
> >
> > and compile it with CMUCL (19a-pre3) then it's actually faster by a
> > factor of 1.3 than the Java (1.5.0-beta2) version on my
> > laptop. Cool... :)
> 
> Man, that's rad! Just pasted that puppy in my REPL and boom! ASCII art
> Mandlebrot. Nice.
> 
> -Peter

Very cool. How did you get the ascii characters though? I don't see
them anywhere in the code. All I see that might even have something to
do with it is
(princ (code-char c))))

-- 
May the Source be with you.
neo88 (Philip Haddad)
From: pkhuong
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <51184814.0407302246.5d4f360a@posting.google.com>
······@truevine.net (neo88) wrote in message news:<····························@posting.google.com>...
> Peter Seibel <·····@javamonkey.com> wrote in message news:<··············@javamonkey.com>...
> > Edi Weitz <········@agharta.de> writes:
[...]
> > > If I change it a little bit
> > >
> > >   (defun mandel ()
> > >     (loop for y from -1 to 1.1 by 0.1 do
> > >       (loop for x from -2 to 1 by 0.04 do
> > >         (let* ((c 126)
> > >                (z (complex x y))
> > >                (a z))
> > >           (loop while (and (< (abs
> > >                                (setq z (+ (* z z) a)))
> > >                               2)
> > >                            (> (decf c) 32)))
> > >           (princ (code-char c))))
> > >       (princ #\Newline)))
> > >
> > > and compile it with CMUCL (19a-pre3) then it's actually faster by a
> > > factor of 1.3 than the Java (1.5.0-beta2) version on my
> > > laptop. Cool... :)
> > 
> > Man, that's rad! Just pasted that puppy in my REPL and boom! ASCII art
> > Mandlebrot. Nice.
> > 
> > -Peter
> 
> Very cool. How did you get the ascii characters though? I don't see
> them anywhere in the code. All I see that might even have something to
> do with it is
> (princ (code-char c))))
Yes. code-char/char-code is not specified to have anything to do with
ASCII, but i guess you can assume it does in most non-brain-damaged
implementations.
From: Pascal Bourguignon
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <8765844207.fsf@thalassa.informatimago.com>
··········@pvk.ca (pkhuong) writes:
> > Very cool. How did you get the ascii characters though? I don't see
> > them anywhere in the code. All I see that might even have something to
> > do with it is
> > (princ (code-char c))))
> Yes. code-char/char-code is not specified to have anything to do with
> ASCII, but i guess you can assume it does in most non-brain-damaged
> implementations.

The first ASCII art were done in EBCDIC!


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Alan Crowe
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <86isc4wtvw.fsf@cawtech.freeserve.co.uk>
neo88 asked:

> Very cool. How did you get the ascii characters though? I
> don't see them anywhere in the code. All I see that might
> even have something to do with it is 
>
> (princ (code-char c))

Spot the magic numbers 32 and 126

(char-code #\space) => 32
(char-code #\~) => 126

the code commits itself to the ASCII character set.

--
Alan Crowe
Edinburgh
Scotland
From: Jim Newton
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <2n3qn3Fsg5v7U1@uni-berlin.de>
i'm not sure how the algorithm is supposed to be
selecting the character to display, but it does not
seem very adapatable if i try to zoom in on the
boundary of the mandelbrot set.

Here is my attempt to allow the user to zoom
in on various parts of the picture.

After each drawing you can select a quadrant to
zoom into

       |
   2   |   1
       |
------+------
       |
   3   |   4
       |

However, as you zoom it does not seem to show
any extra detail.  Is there something wrong with
my function?

(defun mandel ()
   (let (( x0 -2.0)
	( y0 -1.0)
	( x1 1.0)
	( y1 1.1)
	midx
	midy
	)
     (loop while t do
	  (window x0 y0 x1 y1)
	  (setf midx (/ (+ x1 x0) 2.0)
		midy (/ (+ y1 y0) 2.0))
	  (format t "quadrant: ")
	  (multiple-value-setq ( x0 y0 x1 y1 )
	    (case (read)
	      ( 1 (values midx midy x1   y1))
	      ( 2 (values x0   midy midx y1))
	      ( 3 (values x0   y0   midx midy))
	      ( 4 (values midx y0   x1   midy))
	      ( t (values x0   y0   x1   y1)))))))
			
(defun window ( x0 y0 x1 y1)
   (let (( dx (/ (- x1 x0) 30.0))
	( dy (/ (- y1 y0) 30.0)))
     (format t "x0=~A y0=~A x1=~A y1=~A dx=~A dy=~A~%"
	    x0 y0 x1 y1 dx dy)

     (loop for y from y0 to y1 by dy do
	  (loop for x from x0 to x1 by dx do
		(let* ((c 126)
		       (z (complex x y))
		       (a z))
		  (loop while (and (< (abs
				       (setq z (+ (* z z) a)))
				      2)
				   (> (decf c) 32)))
		  (princ (code-char c))))
	  (princ #\Newline))))
From: Frank Buss
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <ceieu0$f6o$1@newsreader2.netcologne.de>
Jim Newton <·····@rdrop.com> wrote:

> i'm not sure how the algorithm is supposed to be
> selecting the character to display, but it does not
> seem very adapatable if i try to zoom in on the
> boundary of the mandelbrot set.
> 
> Here is my attempt to allow the user to zoom
> in on various parts of the picture.
> 
> After each drawing you can select a quadrant to
> zoom into
> 
>        |
>    2   |   1
>        |
> ------+------
>        |
>    3   |   4
>        |
> 
> However, as you zoom it does not seem to show
> any extra detail.  Is there something wrong with
> my function?

works well on my computer. But the quadrants are mirrored at the y-axis, 
because you test at negative y coordinates first. Try this:

4322321221121243141341

This zooms 1 : 4,000,000, but after the last '1' the program ended in an 
endless loop, because looks like my floating point precision is limited 
to 8 significant digits with your program.

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Jim Newton
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <2n3uhmFro5j7U1@uni-berlin.de>
you can now call (mandel...) with the zoom
quadrants

e.g., (mandel 2 4 1 1)

after the zooming, it goes into interactive mode.
Yes there seems to be a limitation around dx=1e-8...
curious.

-jim



(defun mandel ( &rest quadrants)
   (let (( x0 -2.0)
	( y0 -2.0)
	( x1  2.0)
	( y1  2.0))
	

     (dolist ( q quadrants)
       (multiple-value-setq ( x0 y0 x1 y1 )
	(select-quadrant  q x0 y0 x1 y1  )))

     (loop while t do
	  (draw-quadrant x0 y0 x1 y1)
	  (format t "quadrant: ")
	  (multiple-value-setq ( x0 y0 x1 y1 )
	    (select-quadrant (read) x0 y0 x1 y1)))))

(defun select-quadrant ( q x0 y0 x1 y1)
   (let (( midx (/ (+ x1 x0) 2.0))
	( midy (/ (+ y1 y0) 2.0)))
     (case q
       ( 1 (values midx midy x1   y1))
       ( 2 (values x0   midy midx y1))
       ( 3 (values x0   y0   midx midy))
       ( 4 (values midx y0   x1   midy))
       ( t (values x0   y0   x1   y1)))))

(defun draw-quadrant ( x0 y0 x1 y1)
   (let (( dx (/ (- x1 x0) 30.0))
	( dy (/ (- y1 y0) 30.0)))
     (format t "x0=~A y0=~A x1=~A y1=~A dx=~A dy=~A~%"
	    x0 y0 x1 y1 dx dy)

     (princ "2")
     (loop for x from x0 to x1 by dx do
	  (princ "-"))
     (princ "1")
     (princ #\Newline)
     (loop for y from y1 downto y0 by dy do
	  (princ "|")
	  (loop for x from x0 to x1 by dx do
		(let* ((c 126)
		       (z (complex x y))
		       (a z))
		  (loop while (and (< (abs
				       (setq z (+ (* z z) a)))
				      2)
				   (> (decf c) 32)))
		  (princ (code-char c))))
	  (princ "|")
	  (princ #\Newline))
     (princ "3")
     (loop for x from x0 to x1 by dx do
	  (princ "-"))
     (princ "4")
     (princ #\Newline)))

(compile 'mandel)
(compile 'select-quadrant)
(compile 'draw-quadrant)
(mandel)



Frank Buss wrote:
> Jim Newton <·····@rdrop.com> wrote:
> 
> 
>>i'm not sure how the algorithm is supposed to be
>>selecting the character to display, but it does not
>>seem very adapatable if i try to zoom in on the
>>boundary of the mandelbrot set.
>>
>>Here is my attempt to allow the user to zoom
>>in on various parts of the picture.
>>
>>After each drawing you can select a quadrant to
>>zoom into
>>
>>       |
>>   2   |   1
>>       |
>>------+------
>>       |
>>   3   |   4
>>       |
>>
>>However, as you zoom it does not seem to show
>>any extra detail.  Is there something wrong with
>>my function?
> 
> 
> works well on my computer. But the quadrants are mirrored at the y-axis, 
> because you test at negative y coordinates first. Try this:
> 
> 4322321221121243141341
> 
> This zooms 1 : 4,000,000, but after the last '1' the program ended in an 
> endless loop, because looks like my floating point precision is limited 
> to 8 significant digits with your program.
> 
From: Frank Buss
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <ceila9$slh$1@newsreader2.netcologne.de>
Jim Newton <·····@rdrop.com> wrote:

> you can now call (mandel...) with the zoom
> quadrants
> 
> e.g., (mandel 2 4 1 1)
> 
> after the zooming, it goes into interactive mode.
> Yes there seems to be a limitation around dx=1e-8...
> curious.

you can replace all numbers with double-floats, then you can go until
dx= double-float-epsilon (something around 1d-16 on my computer) and then 
this works:

(mandel 1 3 2 3 2 3 3 4 1 1 4 4 1 3 3 1 3 3 3 1 4 4 4 1 3 4 4 4 3 3 3 4 3 
4 2 3 4 4 1 1 2 4 3)

Zooming 1:8796093022208. That's like zooming from the earth fullscreen to 
a flake of one hair of a person fullscreen :-)

(defun mandel ( &rest quadrants)
  (let (( x0 -2d0)
	( y0 -2d0)
	( x1  2d0)
	( y1  2d0))
	

    (dolist ( q quadrants)
      (multiple-value-setq ( x0 y0 x1 y1 )
	(select-quadrant  q x0 y0 x1 y1  )))

    (loop while t do
	  (draw-quadrant x0 y0 x1 y1)
	  (format t "quadrant: ")
	  (multiple-value-setq ( x0 y0 x1 y1 )
	    (select-quadrant (read) x0 y0 x1 y1)))))

(defun select-quadrant ( q x0 y0 x1 y1)
  (let (( midx (/ (+ x1 x0) 2d0))
	( midy (/ (+ y1 y0) 2d0)))
    (case q
      ( 1 (values midx midy x1   y1))
      ( 2 (values x0   midy midx y1))
      ( 3 (values x0   y0   midx midy))
      ( 4 (values midx y0   x1   midy))
      ( t (values x0   y0   x1   y1)))))

(defun draw-quadrant ( x0 y0 x1 y1)
  (let (( dx (/ (- x1 x0) 30d0))
	( dy (/ (- y1 y0) 30d0)))
    (format t "x0=~A y0=~A x1=~A y1=~A dx=~A dy=~A~%"
	    x0 y0 x1 y1 dx dy)

    (princ "2")
    (loop for x from x0 to x1 by dx do
	  (princ "-"))
    (princ "1")
    (princ #\Newline)
    (loop for y from y1 downto y0 by dy do
	  (princ "|")
	  (loop for x from x0 to x1 by dx do
		(let* ((c 126)
		       (z (complex x y))
		       (a z))
		  (loop while (and (< (abs
				       (setq z (+ (* z z) a)))
				      2)
				   (> (decf c) 32)))
		  (princ (code-char c))))
	  (princ "|")
	  (princ #\Newline))
    (princ "3")
    (loop for x from x0 to x1 by dx do
	  (princ "-"))
    (princ "4")
    (princ #\Newline)))

(compile 'mandel)
(compile 'select-quadrant)
(compile 'draw-quadrant)
(mandel)

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Jim Newton
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <2n43qpFs6iv1U1@uni-berlin.de>
does complex do something different if you
give it two double floats?  i.e., is there a
difference between (complex 1.0 1.0) and (complex 1d0 1d0)
-jim

Frank Buss wrote:
> Jim Newton <·····@rdrop.com> wrote:
> 
> 
>>you can now call (mandel...) with the zoom
>>quadrants
>>
>>e.g., (mandel 2 4 1 1)
>>
>>after the zooming, it goes into interactive mode.
>>Yes there seems to be a limitation around dx=1e-8...
>>curious.
> 
> 
> you can replace all numbers with double-floats, then you can go until
> dx= double-float-epsilon (something around 1d-16 on my computer) and then 
> this works:
> 
> (mandel 1 3 2 3 2 3 3 4 1 1 4 4 1 3 3 1 3 3 3 1 4 4 4 1 3 4 4 4 3 3 3 4 3 
> 4 2 3 4 4 1 1 2 4 3)
> 
> Zooming 1:8796093022208. That's like zooming from the earth fullscreen to 
> a flake of one hair of a person fullscreen :-)
> 
> (defun mandel ( &rest quadrants)
>   (let (( x0 -2d0)
> 	( y0 -2d0)
> 	( x1  2d0)
> 	( y1  2d0))
> 	
> 
>     (dolist ( q quadrants)
>       (multiple-value-setq ( x0 y0 x1 y1 )
> 	(select-quadrant  q x0 y0 x1 y1  )))
> 
>     (loop while t do
> 	  (draw-quadrant x0 y0 x1 y1)
> 	  (format t "quadrant: ")
> 	  (multiple-value-setq ( x0 y0 x1 y1 )
> 	    (select-quadrant (read) x0 y0 x1 y1)))))
> 
> (defun select-quadrant ( q x0 y0 x1 y1)
>   (let (( midx (/ (+ x1 x0) 2d0))
> 	( midy (/ (+ y1 y0) 2d0)))
>     (case q
>       ( 1 (values midx midy x1   y1))
>       ( 2 (values x0   midy midx y1))
>       ( 3 (values x0   y0   midx midy))
>       ( 4 (values midx y0   x1   midy))
>       ( t (values x0   y0   x1   y1)))))
> 
> (defun draw-quadrant ( x0 y0 x1 y1)
>   (let (( dx (/ (- x1 x0) 30d0))
> 	( dy (/ (- y1 y0) 30d0)))
>     (format t "x0=~A y0=~A x1=~A y1=~A dx=~A dy=~A~%"
> 	    x0 y0 x1 y1 dx dy)
> 
>     (princ "2")
>     (loop for x from x0 to x1 by dx do
> 	  (princ "-"))
>     (princ "1")
>     (princ #\Newline)
>     (loop for y from y1 downto y0 by dy do
> 	  (princ "|")
> 	  (loop for x from x0 to x1 by dx do
> 		(let* ((c 126)
> 		       (z (complex x y))
> 		       (a z))
> 		  (loop while (and (< (abs
> 				       (setq z (+ (* z z) a)))
> 				      2)
> 				   (> (decf c) 32)))
> 		  (princ (code-char c))))
> 	  (princ "|")
> 	  (princ #\Newline))
>     (princ "3")
>     (loop for x from x0 to x1 by dx do
> 	  (princ "-"))
>     (princ "4")
>     (princ #\Newline)))
> 
> (compile 'mandel)
> (compile 'select-quadrant)
> (compile 'draw-quadrant)
> (mandel)
> 
From: Frank Buss
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <2p6gi0FhfteeU1@uni-berlin.de>
Jim Newton <·····@rdrop.com> wrote:

> does complex do something different if you
> give it two double floats?  i.e., is there a
> difference between (complex 1.0 1.0) and (complex 1d0 1d0)

yes. If I'm doing this in CLISP:

(expt (/ (complex 1 1) 1e30) 2)

I got a SIMPLE-FLOATING-POINT-UNDERFLOW error, but if I do this:

(expt (/ (complex 1d0 1d0) 1e30) 2)

I got #C(0.0d0 1.9999999398101364d-60) (and a warning, which is not 
generated if I use 1d30 instead of 1e30).

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Jim Newton
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <2n3s91Fsnpg9U1@uni-berlin.de>
ahh i see the problem... the current implementation
draws the quadrants with the y axis inverted.

        |
    3   |   4
        |
  ------+------
        |
    2   |   1
        |



i've modified the code to decrement y instead of increment.
and it seems to work well... except that
when dx or dy becomes in the range of dx=1.5894572e-8 dy=1.5894572e-8
very strange things happen... i wonder is this a problem with
percision on the x86?

x0=-0.04844904 y0=0.80464506 x1=-0.048448563 y1=0.80464554 
dx=1.5894572e-8 dy=1.5894572e-8


give it a try...

(defun mandel ()
   (let (( x0 -2.0) ;;( x0 -2.0)
	( y0 -2.0) ;;( y0 -1.0)
	( x1  2.0) ;;( x1 1.0)
	( y1  2.0) ;;( y1 1.1)
	midx
	midy
	)
     (loop while t do
	  (window x0 y0 x1 y1)
	  (setf midx (/ (+ x1 x0) 2.0)
		midy (/ (+ y1 y0) 2.0))
	  (format t "quadrant: ")
	  (multiple-value-setq ( x0 y0 x1 y1 )
	    (case (read)
	      ( 1 (values midx midy x1   y1))
	      ( 2 (values x0   midy midx y1))
	      ( 3 (values x0   y0   midx midy))
	      ( 4 (values midx y0   x1   midy))
	      ( t (values x0   y0   x1   y1)))))))
			
(defun window ( x0 y0 x1 y1)
   (let (( dx (/ (- x1 x0) 30.0))
	( dy (/ (- y1 y0) 30.0)))
     (format t "x0=~A y0=~A x1=~A y1=~A dx=~A dy=~A~%"
	    x0 y0 x1 y1 dx dy)

     (princ "2")
     (loop for x from x0 to x1 by dx do
	  (princ "-"))
     (princ "1")
     (princ #\Newline)
     (loop for y from y1 downto y0 by dy do
	  (princ "|")
	  (loop for x from x0 to x1 by dx do
		(let* ((c 126)
		       (z (complex x y))
		       (a z))
		  (loop while (and (< (abs
				       (setq z (+ (* z z) a)))
				      2)
				   (> (decf c) 32)))
		  (princ (code-char c))))
	  (princ "|")
	  (princ #\Newline))
     (princ "3")
     (loop for x from x0 to x1 by dx do
	  (princ "-"))
     (princ "4")
     (princ #\Newline)))

(compile 'mandel)
(compile 'window)
(mandel)

-jim


Jim Newton wrote:
> i'm not sure how the algorithm is supposed to be
> selecting the character to display, but it does not
> seem very adapatable if i try to zoom in on the
> boundary of the mandelbrot set.
> 
> Here is my attempt to allow the user to zoom
> in on various parts of the picture.
> 
> After each drawing you can select a quadrant to
> zoom into
> 
>       |
>   2   |   1
>       |
> ------+------
>       |
>   3   |   4
>       |
> 
> However, as you zoom it does not seem to show
> any extra detail.  Is there something wrong with
> my function?
> 
> (defun mandel ()
>   (let (( x0 -2.0)
>     ( y0 -1.0)
>     ( x1 1.0)
>     ( y1 1.1)
>     midx
>     midy
>     )
>     (loop while t do
>       (window x0 y0 x1 y1)
>       (setf midx (/ (+ x1 x0) 2.0)
>         midy (/ (+ y1 y0) 2.0))
>       (format t "quadrant: ")
>       (multiple-value-setq ( x0 y0 x1 y1 )
>         (case (read)
>           ( 1 (values midx midy x1   y1))
>           ( 2 (values x0   midy midx y1))
>           ( 3 (values x0   y0   midx midy))
>           ( 4 (values midx y0   x1   midy))
>           ( t (values x0   y0   x1   y1)))))))
>            
> (defun window ( x0 y0 x1 y1)
>   (let (( dx (/ (- x1 x0) 30.0))
>     ( dy (/ (- y1 y0) 30.0)))
>     (format t "x0=~A y0=~A x1=~A y1=~A dx=~A dy=~A~%"
>         x0 y0 x1 y1 dx dy)
> 
>     (loop for y from y0 to y1 by dy do
>       (loop for x from x0 to x1 by dx do
>         (let* ((c 126)
>                (z (complex x y))
>                (a z))
>           (loop while (and (< (abs
>                        (setq z (+ (* z z) a)))
>                       2)
>                    (> (decf c) 32)))
>           (princ (code-char c))))
>       (princ #\Newline))))
> 
From: Edi Weitz
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <877jsl6sum.fsf@bird.agharta.de>
On Sat, 31 Jul 2004 00:08:54 +0200, Edi Weitz <········@agharta.de> wrote:

> If I change it a little bit
>
>   (defun mandel ()
>     (loop for y from -1 to 1.1 by 0.1 do
>       (loop for x from -2 to 1 by 0.04 do
>         (let* ((c 126)
>                (z (complex x y))
>                (a z))
>           (loop while (and (< (abs
>                                (setq z (+ (* z z) a)))
>                               2)
>                            (> (decf c) 32)))
>           (princ (code-char c))))
>       (princ #\Newline)))
>
> and compile it with CMUCL (19a-pre3) then it's actually faster by a
> factor of 1.3 than the Java (1.5.0-beta2) version on my
> laptop. Cool... :)

Faster even if you start cheating a little:

  (defun mandel ()
    (loop for y from -1 to 1.1 by 0.1 do
      (loop for x from -2 to 1 by 0.04 do
        (let* ((z (complex x y))
               (a z))
          (loop for c in '#.(loop for c downfrom 126 above 32
                                  collect (code-char c))
                while (< (abs
                           (setq z (+ (* z z) a)))
                         2)
                finally (princ c))))
      (princ #\Newline)))

But I'll stop now... :)

-- 

"Lisp doesn't look any deader than usual to me."
(David Thornley, reply to a question older than most languages)

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Frank Buss
Subject: Re: Mandelbrot with TGA output
Date: 
Message-ID: <cefmln$5dq$1@newsreader2.netcologne.de>
Edi Weitz <········@agharta.de> wrote:

>           (loop for c in '#.(loop for c downfrom 126 above 32
>                                   collect (code-char c))

this is really nice, I didn't know the reader macros before.

Ok, and now with TGA output, in the size of my screen for a new wallpaper 
(see http://www.frank-buss.de/tmp/mandelbrot.jpg for a quality reduced 
version). The program finished in 346 seconds run time, but that's mainly 
because the algorithm is not optimized. There is a recursive algorithm 
which calculates only 4 border points of a rectangle and fills it, if it 
has the same color, which should reduce the running time to less than 10 
seconds, I think, because most time the algorithm is spending in the 
black area.

(defun mandelbrot ()
  (let* ((width 1600)
         (height 1024)
         (x0 0.25)
         (y0 0.5)
         (x1 0.43)
         (y1 0.71)
         (image
          (make-array (list width height 3)
                      :element-type '(unsigned-byte 8)
                      :initial-element 0)))
    (loop for y from 0 to (1- height) do
          (loop for x from 0 to (1- width) do
                (let* ((c 60)
                       (z (complex
                           (float (+ (* (- x1 x0) (/ x width)) x0))
                           (float (+ (* (- y1 y0) (/ y height)) y0))))
                       (a z))
                  (loop while (and (< (square
                                       (setq z (+ (* z z) a)))
                                      4)
                                   (> (decf c) 0)))
                  (if (> c 0) (progn
                                (setf (aref image x y 0)
                                      (mod (* 4 c) 256))
                                (setf (aref image x y 1)
                                      (mod (* 8 c) 256))
                                (setf (aref image x y 2)
                                      (mod (* 13 c) 256)))))))
    (write-tga image "mandelbrot.tga")))

(defun square (z)
  (+ (* (realpart z) (realpart z)) (* (imagpart z) (imagpart z))))

(defun write-tga (image filename)
  (let* ((dimension (array-dimensions image))
         (width (nth 0 dimension))
         (height (nth 1 dimension)))
    (with-open-file
        (tga filename
             :direction :output
             :if-exists :supersede
             :element-type 'unsigned-byte)
      (dolist (byte (list 0 0 2 0 0 0 0 0 0 0 0 0
                          (mod width 256) (floor width 256)
                          (mod height 256) (floor height 256) 24 0))
        (write-byte byte tga))
      (loop for y from 0 to (1- height) do
            (loop for x from 0 to (1- width) do
                  (write-byte (aref image x y 0) tga)
                  (write-byte (aref image x y 1) tga)
                  (write-byte (aref image x y 2) tga))))))


-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: neo88
Subject: Re: Mandelbrot with TGA output
Date: 
Message-ID: <6a73bb68.0408010515.546921d8@posting.google.com>
Frank Buss <··@frank-buss.de> wrote in message news:<············@newsreader2.netcologne.de>...
> Edi Weitz <········@agharta.de> wrote:
> 
> >           (loop for c in '#.(loop for c downfrom 126 above 32
> >                                   collect (code-char c))
> 
> this is really nice, I didn't know the reader macros before.
> 
> Ok, and now with TGA output, in the size of my screen for a new wallpaper 
> (see http://www.frank-buss.de/tmp/mandelbrot.jpg for a quality reduced 
> version). The program finished in 346 seconds run time, but that's mainly 
> because the algorithm is not optimized. 

346 seconds = 5 min 46 seconds. I ran this program for about seven
minutes I'd say, on CMUCL 18e, and all it did was call the GC
endlessly until I intruppted it from Emacs. I also tried it in Allegro
CL Trial, and it instantly overflowed the allowed GC allocation.

There is a recursive algorithm 
> which calculates only 4 border points of a rectangle and fills it, if it 
> has the same color, which should reduce the running time to less than 10 
> seconds, I think, because most time the algorithm is spending in the 
> black area.
> 
> (defun mandelbrot ()
>   (let* ((width 1600)
>          (height 1024)
>          (x0 0.25)
>          (y0 0.5)
>          (x1 0.43)
>          (y1 0.71)
>          (image
>           (make-array (list width height 3)
>                       :element-type '(unsigned-byte 8)
>                       :initial-element 0)))
>     (loop for y from 0 to (1- height) do
>           (loop for x from 0 to (1- width) do
>                 (let* ((c 60)
>                        (z (complex
>                            (float (+ (* (- x1 x0) (/ x width)) x0))
>                            (float (+ (* (- y1 y0) (/ y height)) y0))))
>                        (a z))
>                   (loop while (and (< (square
>                                        (setq z (+ (* z z) a)))
>                                       4)
>                                    (> (decf c) 0)))
>                   (if (> c 0) (progn
>                                 (setf (aref image x y 0)
>                                       (mod (* 4 c) 256))
>                                 (setf (aref image x y 1)
>                                       (mod (* 8 c) 256))
>                                 (setf (aref image x y 2)
>                                       (mod (* 13 c) 256)))))))
>     (write-tga image "mandelbrot.tga")))
> 
> (defun square (z)
>   (+ (* (realpart z) (realpart z)) (* (imagpart z) (imagpart z))))
> 
> (defun write-tga (image filename)
>   (let* ((dimension (array-dimensions image))
>          (width (nth 0 dimension))
>          (height (nth 1 dimension)))
>     (with-open-file
>         (tga filename
>              :direction :output
>              :if-exists :supersede
>              :element-type 'unsigned-byte)
>       (dolist (byte (list 0 0 2 0 0 0 0 0 0 0 0 0
>                           (mod width 256) (floor width 256)
>                           (mod height 256) (floor height 256) 24 0))
>         (write-byte byte tga))
>       (loop for y from 0 to (1- height) do
>             (loop for x from 0 to (1- width) do
>                   (write-byte (aref image x y 0) tga)
>                   (write-byte (aref image x y 1) tga)
>                   (write-byte (aref image x y 2) tga))))))

So does this write a tga file to the directory that the program is in,
so that you can open it later, or does it write the file directly to
the screen?

-- 
May the Source be with you.
neo88 (Philip Haddad)
From: Frank Buss
Subject: Re: Mandelbrot with TGA output
Date: 
Message-ID: <ceiqlk$ajp$1@newsreader2.netcologne.de>
······@truevine.net (neo88) wrote:

> 346 seconds = 5 min 46 seconds. I ran this program for about seven
> minutes I'd say, on CMUCL 18e, and all it did was call the GC
> endlessly until I intruppted it from Emacs. I also tried it in Allegro
> CL Trial, and it instantly overflowed the allowed GC allocation.

in CMUCL you should try (compile 'mandelbrot) and (compile 'square) first, 
it greatly enhances the speed. And you can reduce the output size by 
reducing the 1600x1024 size.

> So does this write a tga file to the directory that the program is in,
> so that you can open it later, or does it write the file directly to
> the screen?

it writes it in the current working directory. Perhaps you should write 
somthing like "/tmp/mandelbrot.tga" to write it to a place you know where 
it is.

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Edi Weitz
Subject: Re: Mandelbrot with TGA output
Date: 
Message-ID: <87hdrnnexh.fsf@bird.agharta.de>
On 1 Aug 2004 06:15:10 -0700, ······@truevine.net (neo88) wrote:

> 346 seconds = 5 min 46 seconds. I ran this program for about seven
> minutes I'd say, on CMUCL 18e, and all it did was call the GC
> endlessly until I intruppted it from Emacs.

Did you compile it?

-- 

"Lisp doesn't look any deader than usual to me."
(David Thornley, reply to a question older than most languages)

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Frank Buss
Subject: Re: Mandelbrot with TGA output
Date: 
Message-ID: <cej9kk$d92$1@newsreader2.netcologne.de>
Frank Buss <··@frank-buss.de> wrote:

> Ok, and now with TGA output

and finally: ASCII output in an MPEG animation :-)

http://www.mynetcologne.de/~nc-buszfr/mandelbrot.mpg (4.9 MB)

This was easy: first I screen captured the output of char 33 to 126, 
saved it to TGA and created a Lisp vector with this Lisp program from it:

(defun charset ()
  (with-open-file (chars "/tmp/chars.tga" :element-type 'unsigned-byte)
    (loop for c from 0 to 93 do
          (princ "(")
          (princ #\Newline)
          (loop for y from 11 downto 0 do
                (file-position chars (+ 18 (* y 752) (* c 8)))
                (princ "\"")
                (loop for x from 0 to 7 do
                      (if (= 255 (read-byte chars))
                          (princ "*")
                          (princ " ")))
                (princ "\" ")
                (princ #\Newline))
          (princ ")")
          (princ #\Newline))))

Which looked like this:

(defconstant *charset*
  (make-array
   '(94 12)
   :initial-contents
   '((
      "        "
      "  **    "
      " ****   "
      " ****   "
      " ****   "
      "  **    "
      "  **    "
      "        "
      "  **    "
      "  **    "
      "        "
      "        "
      )
     (
      "        "
      " **  ** "
      " **  ** "
      " **  ** "
      "  *  *  "
      "        "
      "        "
      "        "
      "        "
      "        "
      "        "
      "        "
      )
...

Then I wrote a litte class, which simulates a terminal output with TGA 
and interpolates between a zooming step (see below, full program: 
http://www.frank-buss.de/tmp/mandelbrot.lisp.txt ). The 344 TGAs were 
converted with http://dmr.ath.cx/gfx/tga2avi/ to a 107 MB AVI file and 
then with http://www.winload.de/download.php?programm_id=23273 to MPG.

(defun mandel (&rest quadrants)
  (let ((x0 -2d0)
	(y0 -2d0)
	(x1  2d0)
	(y1  2d0)
        (i 0)
        (steps 8))
    (dolist (q quadrants)
      (let ((x0-old x0)
            (y0-old y0)
            (x1-old x1)
            (y1-old y1))
        (multiple-value-setq (x0 y0 x1 y1)
          (select-quadrant q x0 y0 x1 y1))
        (loop for j from 0 to (1- steps) do
              (format t "calculating image ~S of ~S~%" (1+ i) (* steps 
(length quadrants)))
              (draw-quadrant i 
                             (+ (* (/ (- x0 x0-old) steps) j) x0-old)
                             (+ (* (/ (- y0 y0-old) steps) j) y0-old)
                             (+ (* (/ (- x1 x1-old) steps) j) x1-old)
                             (+ (* (/ (- y1 y1-old) steps) j) y1-old))
              (incf i))))))

(defun select-quadrant (q x0 y0 x1 y1)
  (let ((midx (/ (+ x1 x0) 2d0))
        (midy (/ (+ y1 y0) 2d0)))
    (case q
      (1 (values midx midy x1   y1))
      (2 (values x0   midy midx y1))
      (3 (values x0   y0   midx midy))
      (4 (values midx y0   x1   midy))
      (t (values x0   y0   x1   y1)))))

(defun draw-quadrant (i x0 y0 x1 y1)
  (let ((steps 30)
        (ti (make-instance 'terminal-image)))
    (char-out ti #\2)
    (loop for x from 0 to steps do
          (char-out ti #\-))
    (char-out ti #\1)
    (newline ti)
    (loop for y from 0 to steps do
          (char-out ti #\|)
          (loop for x from 0 to steps do
                (let* ((c 126)
                       (z (complex
                           (+ (* (/ (- x1 x0) steps) x) x0)
                           (+ (* (/ (- y1 y0) steps) y) y0)))
                       (a z))
                  (loop while (and (< (abs
                                       (setq z (+ (* z z) a)))
                                      2)
                                   (> (decf c) 32)))
                  (char-out ti (code-char c))
                  ))
          (char-out ti #\|)
          (newline ti))
    (char-out ti #\3)
    (loop for x from 0 to steps do
          (char-out ti #\-))
    (char-out ti #\4)
    (newline ti)
    (write-tga ti (format nil "/tmp/t~S.tga" i))))

(defclass terminal-image ()
  ((cols :initarg cols :initform 33)
   (rows :initarg rows :initform 33)
   (cursor-x :initform 0)
   (cursor-y :initform 0)
   width height image))

(defmethod char-out ((ti terminal-image) c)
  (let ((index (- (char-code c) 33))
        (x0 (* 8 (slot-value ti 'cursor-x)))
        (y0 (* 12 (slot-value ti 'cursor-y))))
    (if (and (<= 0 index) (< index 94))
        (loop for y from 0 to 11 do
              (let ((char-line (aref *charset* index y)))
                (loop for x from 0 to 7 do
                      (if (not (eq #\Space (elt char-line x)))
                          (setf
                           (aref (slot-value ti 'image)
                                 (+ y y0) (+ x x0))
                           1)))))))
  (incf (slot-value ti 'cursor-x)))

(defmethod newline ((ti terminal-image))
  (setf (slot-value ti 'cursor-x) 0)
  (incf (slot-value ti 'cursor-y)))

(defmethod initialize-instance :after ((ti terminal-image) &key)
  (let ((width (* (slot-value ti 'cols) 8))
        (height (* (slot-value ti 'rows) 12)))
    (setf (slot-value ti 'width) width)
    (setf (slot-value ti 'height) height)
    (setf (slot-value ti 'image) (make-array
                                  (list height width)
                                  :element-type '(unsigned-byte 1)
                                  :initial-element 0))))

(defmethod write-tga ((ti terminal-image) filename)
  (let ((width (slot-value ti 'width))
        (height (slot-value ti 'height)))
    (with-open-file
        (tga filename
             :direction :output
             :if-exists :supersede
             :element-type 'unsigned-byte)
      (dolist (byte (list 0 0 2 0 0 0 0 0 0 0 0 0
                          (mod width 256) (floor width 256)
                          (mod height 256) (floor height 256) 24 0))
        (write-byte byte tga))
      (loop for y from (1- height) downto 0 do
            (loop for x from 0 to (1- width) do
                  (let ((color
                         (if (= (aref (slot-value ti 'image) y x) 1)
                             255
                             0)))
                    (write-byte color tga)
                    (write-byte color tga)
                    (write-byte color tga)))))))

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Wolfhard Buß
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <m3d62ccqu7.fsf@buss-14250.user.cis.dfn.de>
Edi Weitz:

>   (defun mandel ()
>     (loop for y from -1 to 1.1 by 0.1 do
>       (loop for x from -2 to 1 by 0.04 do
>         (let* ((z (complex x y))
>                (a z))
>           (loop for c in '#.(loop for c downfrom 126 above 32
>                                   collect (code-char c))
>                 while (< (abs
>                            (setq z (+ (* z z) a)))
>                          2)
>                 finally (princ c))))
>       (princ #\Newline)))
>

Not the final iteration:

 (loop for y from -1 to 1.1 by 0.1 do
       (loop for x from -2 to 1 by 0.04 do
             (loop with a = (complex x y)
                   for z = a then (+ (* z z) a)
                   for c in '#.(loop for c downfrom 126 downto 32
                                     collect (code-char c))
                       while (< (* z (conjugate z) 4)
                       finally (princ c)))
       (princ #\Newline))

> But I'll stop now... :)

-- 
"Brown the leaves, gray the sky, the horizont - white."
                                            -- Unknown
From: Eivind L. Rygge
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <874qni25bk.fsf@arnt.fjomegata.no>
Frank Buss <··@frank-buss.de> writes:

> Based on a Java program ( http://tinyurl.com/57smz ) I've implemented a 
> Lisp program for showing the Mandelbrot set:
> 
>   (loop for y from -1 to 1.1 by 0.1 do
>         (loop for x from -2 to 1 by 0.04 do
>               (let* ((c 126)
>                      (z (complex x y))
>                      (a z))
>                 (loop while (< (abs
>                                 (setq z (+ (* z z) a)))
>                                2)
>                   while (> (decf c) 32)) 
>                 (princ (code-char c))))
>         (format t "~%"))
(...)

... and an Emacs Lisp version:

(require 'cl)

(defun comp-mult (a b) ; a and b are lists (x y) corresponding to x + yi
  (list (- (* (car a) (car b)) 
	   (* (cadr a) (cadr b)))
	(+ (* (car a) (cadr b)) 
	   (* (cadr a) (car b))))) 

(defun comp-add (z1 z2)
  (list (+ (car z1) (car z2))
	(+ (cadr z1) (cadr z2))))

(defun comp-abs (z)
  (sqrt (+ (* (car z) (car z))  
	   (* (cadr z) (cadr z)))))
	

(let* ((buffer-name (get-buffer-create "*Mandelbrot*")))
  (switch-to-buffer buffer-name)
  (erase-buffer)
  (loop for y from -1 to 1.1 by 0.1 do
	(loop for x from -2 to 1 by 0.04 do
	      (let* ((c 126)
		     (z (list x y))
		     (a z))
                (loop while (< (comp-abs
                                (setq z (comp-add (comp-mult z z) a)))
                               2)
		      while (> (decf c) 32)) 
                (insert (princ (make-char 'ascii c)))))
	(newline)))


I had to create some helper functions for handling the complex
values.  I guess I could've used the calc package's functions
concerning complex numbers, but they looked awkward to use without
running the calculator as far as I could see.  Besides, not all use
the calc package anyway.  

Eivind L. Rygge
Oslo, Norway

PS! First post in comp.lang.lisp :-)
Hello to all who attended the Lisp & Scheme Workshop here in Oslo this summer.
From: Pascal Bourguignon
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <87y8kux0cm.fsf@thalassa.informatimago.com>
······@hotmail.com (Eivind L. Rygge) writes:
> ... and an Emacs Lisp version:
> 
> (require 'cl)
> 
>  ; a and b are lists (x y) corresponding to x + yi

Why not mere cons cells?

(defun realpart (c) (car c))
(defun imagpart (c) (cdr c))
(defun complex  (r &optional (i 0)) (cons r i))

Or, slightly less COMMON-LISP, but slightly more efficient:

(defmacro realpart (c) `(car ,c))
(defmacro imagpart (c) `(cdr ,c))
(defmacro complex  (r &optional (i 0)) `(cons ,r ,i))


> (defun comp-mult (a b)
>   (list (- (* (car a) (car b)) 
> 	   (* (cadr a) (cadr b)))
> 	(+ (* (car a) (cadr b)) 
> 	   (* (cadr a) (car b))))) 


(defun c* (&rest args)
     (reduce (lambda (a b)
                (complex (- (* (realpart a)(realpart b))
                            (* (imagpart a)(imagpart b)))
                         (+ (* (realpart a)(imagpart b))
                            (* (imagpart a)(realpart b)))))
              args
              :inital-value (complex 1 0)))

 
> (defun comp-add (z1 z2)
>   (list (+ (car z1) (car z2))
> 	(+ (cadr z1) (cadr z2))))

(defun c+ (&rest args)
     (reduce (lambda (a b)
                (complex (+ (realpart a)(realpart b))
                         (+ (imagpart a)(imagpart b))))
              args
              :inital-value (complex 0 0)))
 
> (defun comp-abs (z)
>   (sqrt (+ (* (car z) (car z))  
> 	   (* (cadr z) (cadr z)))))

(defun cabs (c)
     (sqrt (+ (* (realpart c)(realpart c))
              (* (imagpart c)(imagpart c)))))
 	
 
> (let* ((buffer-name (get-buffer-create "*Mandelbrot*")))
>   (switch-to-buffer buffer-name)
>   (erase-buffer)
>   (loop for y from -1 to 1.1 by 0.1 do
> 	(loop for x from -2 to 1 by 0.04 do
> 	      (let* ((c 126)
> 		     (z (list x y))
> 		     (a z))
>                 (loop while (< (comp-abs
>                                 (setq z (comp-add (comp-mult z z) a)))
>                                2)
> 		      while (> (decf c) 32)) 
>                 (insert (princ (make-char 'ascii c)))))
> 	(newline)))
> 
> 
> I had to create some helper functions for handling the complex
> values.  I guess I could've used the calc package's functions
> concerning complex numbers, but they looked awkward to use without
> running the calculator as far as I could see.  Besides, not all use
> the calc package anyway.  
> 
> Eivind L. Rygge
> Oslo, Norway
> 
> PS! First post in comp.lang.lisp :-)
> Hello to all who attended the Lisp & Scheme Workshop here in Oslo this summer.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: Dave Pearson
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <slrnch3s5n.dm9.davep.news@hagbard.davep.org>
* Eivind L. Rygge <······@hotmail.com>:

> ... and an Emacs Lisp version:

<URL:http://www.gnusoftware.com/Emacs/Lisp/mandel.el> might be of interest.

-- 
Dave Pearson
http://www.davep.org/lisp/
From: Pascal Costanza
Subject: Re: Mandelbrot for the terminal
Date: 
Message-ID: <cesv0d$ih0$2@newsreader2.netcologne.de>
Eivind L. Rygge wrote:

> PS! First post in comp.lang.lisp :-)
> Hello to all who attended the Lisp & Scheme Workshop here in Oslo this summer.

Hi. ;)

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."