From: ·········@gmail.com
Subject: Should this cons so much?
Date: 
Message-ID: <1156021734.782651.149750@p79g2000cwp.googlegroups.com>
So, I'm something of a hobbyist, and I've discovered that Common Lisp
is, well, lots of fun.

One of those hobbyist projects that everyone seems to try at one point
in their life that I'm just getting around to is a Mandelbrot set
generator. What I've come up with is this:

(defun mandelbrot-cycles (c)
  (do ((z c (+ (* z z) c))
       (i 0 (1+ i)))
      ((or (> i 20) (>= (abs z) 2.0)) i)))

(defun make-dat (n)
  (setf *dat*
	(make-array (list n n) :element-type 'fixnum))
  (let ((scale (/ 2.0 (1- n)))
	(shift-x (- (* 0.75 (1- n))))
	(shift-y (- (* 0.5 (1- n)))))
    (flet ((subs->complex (ix iy)
	     (complex (* scale (+ ix shift-x))
		      (* scale (+ iy shift-y)))))
      (do ((ix 0 (1+ ix)))
	  ((>= ix n))
	(do ((iy 0 (1+ iy)))
	     ((>= iy n))
	  (setf (aref *dat* ix iy)
		(mandelbrot-cycles (subs->complex ix iy))))))))

which works OK, but it seems to cons an awful lot. Specifically,

CL-USER> (time (progn (setf *dat* (make-array '(401 401)
					      :element-type 'fixnum))
		      nil))
Evaluation took:
  0.001 seconds of real time
  6.89e-4 seconds of user run time
  7.4e-5 seconds of system run time
  0 page faults and
  643,216 bytes consed.
NIL

CL-USER> (time (make-dat 401))
Evaluation took:
  7.896 seconds of real time
  3.841309 seconds of user run time
  0.973084 seconds of system run time
  0 page faults and
  396,162,944 bytes consed.
NIL

It seems to cons an awful lot---about 600 bytes per iteration. Is that
sort of behavior normal, or am I doing something silly?

Also, on a quasi-related note, it there a FORMAT directive for
iterating over an array the way ~{ and ~} iterate over lists? I looked
in the HyperSpec and didn't see anything....

Thanks in advance!
Matt Pillsbury

From: Barry Margolin
Subject: Re: Should this cons so much?
Date: 
Message-ID: <barmar-A07D7F.17343219082006@comcast.dca.giganews.com>
In article <························@p79g2000cwp.googlegroups.com>,
 ·········@gmail.com wrote:

> (defun mandelbrot-cycles (c)
>   (do ((z c (+ (* z z) c))
>        (i 0 (1+ i)))
>       ((or (> i 20) (>= (abs z) 2.0)) i)))
> 
> (defun make-dat (n)
>   (setf *dat*
> 	(make-array (list n n) :element-type 'fixnum))
>   (let ((scale (/ 2.0 (1- n)))
> 	(shift-x (- (* 0.75 (1- n))))
> 	(shift-y (- (* 0.5 (1- n)))))
>     (flet ((subs->complex (ix iy)
> 	     (complex (* scale (+ ix shift-x))
> 		      (* scale (+ iy shift-y)))))
>       (do ((ix 0 (1+ ix)))
> 	  ((>= ix n))
> 	(do ((iy 0 (1+ iy)))
> 	     ((>= iy n))
> 	  (setf (aref *dat* ix iy)
> 		(mandelbrot-cycles (subs->complex ix iy))))))))
> 
> which works OK, but it seems to cons an awful lot. Specifically,
...
> It seems to cons an awful lot---about 600 bytes per iteration. Is that
> sort of behavior normal, or am I doing something silly?

It's all the boxing and unboxing of floats.  If you declare the types of 
all the float temporaries and parameters it will probably improve things.

> Also, on a quasi-related note, it there a FORMAT directive for
> iterating over an array the way ~{ and ~} iterate over lists? I looked
> in the HyperSpec and didn't see anything....

Nope.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: ·········@gmail.com
Subject: Re: Should this cons so much?
Date: 
Message-ID: <1156041249.245395.146940@p79g2000cwp.googlegroups.com>
Barry Margolin wrote:

> In article <························@p79g2000cwp.googlegroups.com>,
>  ·········@gmail.com wrote:

> > It seems to cons an awful lot---about 600 bytes per iteration. Is that
> > sort of behavior normal, or am I doing something silly?

> It's all the boxing and unboxing of floats.  If you declare the types of
> all the float temporaries and parameters it will probably improve things.

That did it; declaring everything as doubles got things down to about 8
bytes/iteration.

> > Also, on a quasi-related note, it there a FORMAT directive for
> > iterating over an array the way ~{ and ~} iterate over lists? I looked
> > in the HyperSpec and didn't see anything....

> Nope.

There doesn't seem to be a LOOP keyword for it either (although that's
not so hard to work around). Oh well.

Thanks again for the help,
Matt Pillsbury
From: Bill Atkins
Subject: Re: Should this cons so much?
Date: 
Message-ID: <1156041391.204766.326530@m73g2000cwd.googlegroups.com>
·········@gmail.com wrote:
> There doesn't seem to be a LOOP keyword for it either (although that's
> not so hard to work around). Oh well.

ACROSS:

(loop for x across #(1 2 3) collect x) => (1 2 3)
From: ·········@gmail.com
Subject: Re: Should this cons so much?
Date: 
Message-ID: <1156046109.874554.107100@i42g2000cwa.googlegroups.com>
Bill Atkins wrote:
> ·········@gmail.com wrote:
> > There doesn't seem to be a LOOP keyword for it either (although that's
> > not so hard to work around). Oh well.

> ACROSS:

> (loop for x across #(1 2 3) collect x) => (1 2 3)

Works for vectors but not for multi-dimensional arrays.

Cheers,
Matt Pillsbury
From: Pascal Bourguignon
Subject: Re: Should this cons so much?
Date: 
Message-ID: <871wrcf0y0.fsf@thalassa.informatimago.com>
·········@gmail.com writes:

> Bill Atkins wrote:
>> ·········@gmail.com wrote:
>> > There doesn't seem to be a LOOP keyword for it either (although that's
>> > not so hard to work around). Oh well.
>
>> ACROSS:
>
>> (loop for x across #(1 2 3) collect x) => (1 2 3)
>
> Works for vectors but not for multi-dimensional arrays.

(loop :for i :from  0 :below (array-total-size)
      :collect (row-major-aref array i))

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

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.