Hi Jimmie,

thanks for your long feedback and sharing your experiences!

> I have spent a fair amount of the last 4 days playing with PicoLisp. I

Yess. From your code I see that you master PicoLisp already quite well! I
suspect that you gave up just a little bit too early.

> : (scl 12)
> -> 12
> : (*Scl)
> Segmentation fault (core dumped)

Haha, right. Calling (*Scl) is a prefect way to segfault. Think about what it
means: It calls a *function* starting in memory at address 12!

HOWEVER! The segfaults you observed in your program are NOT your fault! You
indeed found a bug in the bignum functions of PicoLisp, causing a crash upon a
certain combination of numeric arguments.

Strange that this was not detected earlier, I used a lot of test routines with
random numbers.

I cound not locate the exact location of the bug yet. It is a Heisenbug, because
it only occurs if the garbage collector runs in the right moment. I know this
because it all runs well if you call 'gc' *before* the test, e.g.

   (gc 700)

I will dig into it now, to find and fix it, and release a new PicoLisp version.
Thanks for finding it!

As you spent already so much time on it, I feel that I should try it myself.

I rewrote parts of it to be more PicoLisp-like, as you violate some of the
PicoLisp programming rules and styles. I won't comment on the details, but paste
my own version below.

The new version is about 150 times faster. The main reason is that you used
'nth' to index into long lists again and again. Here on my notebook it
finishes the 100 reps in one and a half minutes:

   $ time ./pil x.l +
   *Scl: 12
   87.144 sec
   nsum: 11257.349310772499
   navg: 0.390880184402
   4.093 sec
   91.250 sec
   nsum: 11228.585386471924
   navg: 0.389881437030

   real    1m31.628s
   user    1m31.308s
   sys     0m0.400s

> A successful 100 rep run should give an
> nsum: 11322.307098752284    and
> navg: 0.393135663151121    within acceptable floating point differences.

Note that I get slightly different results, because I use '*/' instead of '/' in
the 'average' function. I believe that this is more correct, as '*/' rounds the

Now let me start the bug hunt.

♪♫ Alex

PS: Here is my code:

(scl 12)

(de average (L)
   (*/ (sum prog L) (length L)) )

(de normalize (N)
   (let NN (if (=0 N) 0.000123456789 N)
      (while (<= NN 0.0001)
         (setq NN (* 10 NN)) )
      (while (>= NN 1.0)
         (setq NN (*/ NN 10)) )
      NN ) )

(de createlist (Lsize)
      (let I 0
         (do Lsize
            (link (normalize (inc 'I 1.0))) ) ) ) )

(de loop1calc (I J N)
   (let V (*/ N (+ I N) (- J N) 0.1234567 `(* 1.0 1.0 1.0))
      (normalize (*/ V V V `(* 1.0 1.0)) ) ) )

(de loop2calc (I J N)
      (*/ N
         (+ J 1.0)
         (+ N N N)
         `(* 1.0 1.0 1.0) ) ) )

(de loopN (Fun Lst Reps)
   (let I 1.0
      (do Reps
         (let J 0
                  (set L
                     (Fun I (inc 'J 1.0) (car L)) ) )
               Lst ) )
         (inc 'I 1.0) ) )
      *Nsum (sum prog Lst)
      *Navg (average Lst) ) )

(de loop1 (Lst Reps)
   (loopN loop1calc Lst Reps) )

(de loop2 (Lst Reps)
   (loopN loop2calc Lst Reps) )

(de doit ()
   (prinl "*Scl: " *Scl)
      (let Reps 100
         (prinl "createlist")
         (let L (createlist (* 60 24 5 4))
            (println "loop1")
            (bench (loop1 L Reps))
            (prinl "loop2")
            (prinl "nsum: " (format *Nsum *Scl))
            (prinl "navg: " (format *Navg *Scl))
            (bench (loop2 L Reps)) ) ) )
   (prinl "nsum: " (format *Nsum *Scl))
   (prinl "navg: " (format *Navg *Scl)) )

(gc 700)

UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

Reply via email to