SBCL to newLISP

Q&A's, tips, howto's
Locked
kanen
Posts: 145
Joined: Thu Mar 25, 2010 6:24 pm
Contact:

SBCL to newLISP

Post by kanen »

Can someone help me translate the following SBCL (or Common Lisp) script to newLISP?

I'm presenting at a conference and interested in showing benchmarks between a bunch of different languages (including some Lisp, Scheme, Python, C, etc).

Code: Select all

; sbcl lisp version by mandeep singh

(declaim (optimize (speed 3)))

(defconstant +BAILOUT+ 16)
(defconstant +MAX-ITERATIONS+ 1000)

(defun mandelbrot (x y)
  (declare (type single-float x y))
  (let ((cr (- y 0.5))
        (ci x)
        (zi 0.0)
        (zr 0.0))
    (declare (type single-float cr ci zi zr))
    (do ((i 0 (incf i)))
        (nil)
      (let* ((temp (the single-float (* zr zi)))
             (zr2 (the single-float (* zr zr)))
             (zi2 (the single-float (* zi zi))))
        (declare (type single-float temp zr2 zi2)
                 (type fixnum i))
        (setq zr (the single-float (+ (- zr2 zi2) cr)))
        (setq zi (the single-float (+ temp temp ci)))
        (if (> (the single-float (+ zi2 zr2)) +BAILOUT+)
            (return-from mandelbrot i))
        (if (> i +MAX-ITERATIONS+)
            (return-from mandelbrot 0))))))
(defun main ()
   (let ((tstart)
   (tfinish))
     (setq tstart (get-internal-real-time))
     (do ((y -39 (incf y)))
    ((= (the fixnum y) 39))
       (format t "~%")
       (do ((x -39 (incf x)))
      ((= (the fixnum x) 39))
    (let ((i (mandelbrot (the single-float (/ x 40.0))
               (the single-float (/ y 40.0)))))
      (declare (type fixnum i x y))
        (if (zerop i)
            (format t "*")
            (format t " ")))))
     (format t "~%")
     (setq tfinish (get-internal-real-time))
     (format t "SBCL Elapsed ~,2F~%"
      (coerce (/ (- tfinish tstart) internal-time-units-per-second) 'float))))

(progn
 (main)
 (quit))
. Kanen Flowers http://kanen.me .

wandernet
Posts: 1
Joined: Tue Jun 29, 2010 9:36 am

Re: SBCL to newLISP

Post by wandernet »

Code: Select all

;newLISP v.10.0.0 
;on Win32 IPv4 UTF-8
(import "kernel32.dll" "GetTickCount")
(set 'BAILOUT 16)
(set 'MAX_ITERATIONS 1000)

(define (iterate x y)
  (let ((cr (sub y 0.5))
	    (ci x)
	    (zi 0.0)
	    (zr 0.0)
	    (i 0))
	(while 1
	  (inc i 1)
	  (set 'temp (mul zr zi))
	  (set 'zr2 (mul zr zr))
	  (set 'zi2 (mul zi zi))
	  (set 'zr  (add cr (sub zr2 zi2)))
	  (set 'zi  (add temp temp ci))
	  (if (> (add zi2 zr2) BAILOUT)
        (throw i))
	  (if (> i MAX_ITERATIONS) 
	    (throw 0)))))
		
(define (mandelbrot)
    (let ((t (GetTickCount)))
	  (for (y -39 38)
		(for (x -39 38)
			(set 'j (catch (iterate (div x 40.0) (div y 40.0))))
            (if (= j 0.0)
			  (print "*")
			  (print " ")))
		(print "\n"))
	  (println "Time Elapsed: " (- (GetTickCount) t))))

(mandelbrot)


Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: SBCL to newLISP

Post by Lutz »


kanen
Posts: 145
Joined: Thu Mar 25, 2010 6:24 pm
Contact:

Re: SBCL to newLISP

Post by kanen »

I do not use Windows.

When I look at "GetTickCount" the reference reads, "Retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days."

Seems like a simple (date-value) in newLISP can do the same thing, with a few modifications?

New code:
;(import "kernel32.dll" "GetTickCount")
(define (GetTickCount)
(date-value)
)
The problem (as Lutz says later) is that this code is SLOW compared to the same code in other languages. In fact, this example in newLISP is even slower than Python, which is impressive. :)
wandernet wrote:

Code: Select all

;newLISP v.10.0.0 
;on Win32 IPv4 UTF-8
(import "kernel32.dll" "GetTickCount")
. Kanen Flowers http://kanen.me .

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: SBCL to newLISP

Post by Lutz »

(date-value) gives only seconds of resolution, better use (time-of-day), which has at least milliseconds resolution and on modern Unix systems micro seconds of resolution.

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Re: SBCL to newLISP

Post by cormullion »

Perhaps the Python uses built-in complex numbers...

I thought Michael's complex version was more fun:

Code: Select all

(define (complex:complex
            (r 0)
            (i 0))
    (list complex r i))

(define (complex:rad)
    (set 're (self 1) 'im (self 2))
    (sqrt (add
            (mul re re)
            (mul im im))))

(define (complex:theta)
    (atan (div
            (self 1)
            (self 2))))

(define (complex:add b)
    (complex (add
                (self 1)
                (b 1))
             (add
                (self 2)
                (b 2))))

(define (complex:mul  b)
    (set 'a.re (self 1) 
         'a.im (self 2) 
         'b.re (b 1) 
         'b.im (b 2))
    (complex
         (sub
            (mul a.re b.re)
            (mul a.im b.im))
         (add
            (mul a.re b.im)
            (mul a.im b.re))))

(define (mandelbrot)
    (for (y -2 2 0.02)
        (for (x -2 2 0.02)
            (inc counter)
            (set 'z (complex x y) 'c 126 'a z)
            (while (and
                    (< (abs (:rad (set 'z (:add (:mul z z) a)))) 2)
                    (> (dec c) 32)))
            (print (char c)))
        (println)))

(mandelbrot)

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Re: SBCL to newLISP

Post by Tim Johnson »

Also, why use multiple calls to 'set when one will do?
cheers
tim
Programmer since 1987. Unix environment.

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Re: SBCL to newLISP

Post by m i c h a e l »

And a single call to set is faster, too:

Code: Select all

(define (test-once) (set 'a 1 'b 2 'c 3 'd 4 'e 5 'f 6 'g 7))

(define (test-multiple)
	(set 'a 1)
	(set 'b 2)
	(set 'c 3)
	(set 'd 4)
	(set 'e 5)
	(set 'f 6)
	(set 'g 7)
)

(time (test-once) 1000000) ;=> 447.211
(time (test-multiple) 1000000) ;=> 609.038
m i c h a e l

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Re: SBCL to newLISP

Post by Tim Johnson »

I'll buy that one. I wonder if differences would change with more complex data types?
thanks
tim
Programmer since 1987. Unix environment.

itistoday
Posts: 429
Joined: Sun Dec 02, 2007 5:10 pm
Contact:

Re: SBCL to newLISP

Post by itistoday »

Regarding the set thing... I've actually done the same benchmarks, and they've affected how I decide to use set or setf.

Basically, I've found that setf is faster for situations where only 1 variable needs to be set, but if you're setting multiple things in a row, set is faster (if called once for all of them).

It's a really insignificant difference on its own, but I figure if I make that a convention the times will eventually add up to something meaningful since set is called so much. newlisp makes it easy to microbenchmark, and so you can adjust your coding style to always use the faster version, and eventually I figure the entire program benefits from the lots-of-minor-performance-increases.
Get your Objective newLISP groove on.

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Re: SBCL to newLISP

Post by Tim Johnson »

The idea of using one call to set
with multiple symbol/value pairs
versus
multiple calls to set
with just one symbol/value pair for each call
appeals to my aversion to redundancy.
but michael makes a compelling case in the test code that he posted.

I should have some time in the next few days to run some more complex tests where
the variables are something other than integers.

thanks
tim
Programmer since 1987. Unix environment.

itistoday
Posts: 429
Joined: Sun Dec 02, 2007 5:10 pm
Contact:

Re: SBCL to newLISP

Post by itistoday »

Tim Johnson wrote:The idea of using one call to set
with multiple symbol/value pairs
versus
multiple calls to set
with just one symbol/value pair for each call
appeals to my aversion to redundancy.
but michael makes a compelling case in the test code that he posted.
I don't understand, why "but"? His test code shows it's better to use one call.
Get your Objective newLISP groove on.

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Re: SBCL to newLISP

Post by Tim Johnson »

I don't understand, why "but"? His test code shows it's better to use one call.
Oh for Pete's Sake, you're right, my brain has been AWOL these couple of days!
I misread the results.
thanks
tim
Programmer since 1987. Unix environment.

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Re: SBCL to newLISP

Post by m i c h a e l »

setf is faster than set:

Code: Select all

(define (test-setf-once) (setf a 1 b 2 c 3 d 4 e 5 f 6 g 7))

(define (test-setf-multiple)
	(setf a 1)
	(setf b 2)
	(setf c 3)
	(setf d 4)
	(setf e 5)
	(setf f 6)
	(setf g 7)
)


(println (time (test-setf-once) 1000000)) ;=> 372.934
(println (time (test-setf-multiple) 1000000)) ;=> 507.426
Curious.

m i c h a e l

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Re: SBCL to newLISP

Post by Tim Johnson »

Michael, I've never used setf like that. The docs say
setf is used when setting list or array references
but I see from my own console:

Code: Select all

> (setf a 1)
1
> a
1
Curiouser and curiouser
Programmer since 1987. Unix environment.

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Re: SBCL to newLISP

Post by m i c h a e l »

Tim wrote:Michael, I've never used setf like that.


I don't normally use setf for variable assignment either, but the comment from Greg (itistoday) sparked the new test. I was really surprised by the results. I assumed setf was slower since it's used, as you quote:
newLISP Manual & Reference wrote:when setting list or array references
I wonder if there's a good reason to not use setf in place of set and . . . wait. I forgot to test setq:

Code: Select all

(define (test-setq-once) (setq a 1 b 2 c 3 d 4 e 5 f 6 g 7))

(define (test-setq-multiple)
	(setq a 1)
	(setq b 2)
	(setq c 3)
	(setq d 4)
	(setq e 5)
	(setq f 6)
	(setq g 7)
)


(time (test-setq-once) 1000000) ;=> 381.148
(time (test-setq-multiple) 1000000) ;=> 525.763
So it looks like both setq and setf are faster than set. I ran these tests multiple times, and the q and f versions are consistently faster. Lutz, should we be using setq in place of set for the slight speed increase?

m i c h a e l

itistoday
Posts: 429
Joined: Sun Dec 02, 2007 5:10 pm
Contact:

Re: SBCL to newLISP

Post by itistoday »

m i c h a e l wrote:So it looks like both setq and setf are faster than set. I ran these tests multiple times, and the q and f versions are consistently faster. Lutz, should we be using setq in place of set for the slight speed increase?
I don't think setq should be used at all, there's no reason for it as it's just an alias for setf (which is why you're seeing those results), and included for compatibility with old code.

I originally thought set was faster than setf for multiple assignments, but it seems like I must have made a mistake in those benchmarks, so setf is faster for everything. So, I don't know about you, but for consistency and speed I'm going to use setf for everything (unless I explicitly need to set on a symbol, which happens often enough, in which case there's no choice but to use set).
Get your Objective newLISP groove on.

xytroxon
Posts: 296
Joined: Tue Nov 06, 2007 3:59 pm
Contact:

Re: SBCL to newLISP

Post by xytroxon »

setq setf !
syntax: (setq place-1 exp-1 [place-2 exp-2 ... ])

setq and setf work alike in newLISP and set the contents of a symbol, list, array or string or of a list, array or string place reference. Like set, setq and setf can take multiple argument pairs. Although both setq and setf point to the same built-in function internally, throughout this manual setq is used when setting a symbol reference and setf is used when setting list or array references.

-- xytroxon
"Many computers can print only capital letters, so we shall not use lowercase letters."
-- Let's Talk Lisp (c) 1976

itistoday
Posts: 429
Joined: Sun Dec 02, 2007 5:10 pm
Contact:

Re: SBCL to newLISP

Post by itistoday »

Yes, though the manual does use that convention for some reason, I don't see the point. I see it as adding confusion to my code and giving me one more thing to have to worry about (should I use setf or setq here?). There's no reason to burden yourself with unnecessary complexity.
Get your Objective newLISP groove on.

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Re: SBCL to newLISP

Post by m i c h a e l »

Here's one more way to set variables:

Code: Select all

> (define a 1)
1
> a
1
> _
Of course, define cannot be used to do multiple assignments. I think Lutz said this form was designed for Scheme programmers to feel more at home.

m i c h a e l

Locked