Re: Tail call optimization

2025-02-13 Thread Alexander Burger
On Thu, Feb 13, 2025 at 07:38:10AM +0100, Alexander Burger wrote:
> When I built the tco version yesterday, I experimended with both
> versions, and somehow the 'M' code was lost :(

OK, I will settle with this version:

   # Print next digit of PI
   (de digit (Env)
  (job Env
 (tco (Q R S K N L)
(if (>= (- (+ R (* 4 Q)) S) (* N S))
   (tc
  (* Q K)
  (* L (+ R (* 2 Q)))
  (* S L)
  (inc K)
  (/ (+ (* Q (+ 2 (* 7 K))) (* R L)) (* S L))
  (+ 2 L) ) )
(prog1 N
   (let M (- (/ (* 10 (+ R (* 3 Q))) S) (* 10 N))
  (setq Q (* 10 Q)  R (* 10 (- R (* N S)))  N M) ) ) ) ) )

   # Print 'N' or all digits of PI
   (de pi (N)
  (let E (env 'Q 1  'R 0  'S 1  'K 1  'N 3  'L 3)
 (prin (digit E) ".")
 (do (or N T)
(prin (digit E))
(flush) ) )
  (prinl) )

The 'job' environment is factored out of 'digit' so that 'pi' can be
restarted like:

   $ ./pil misc/pi.l +
   : (pi 7)
   3.1415926
   -> NIL

   : (pi 30)
   3.141592653589793238462643383279
   -> NIL

   : (pi)
   
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669...

☺/ A!ex

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


Re: Tail call optimization

2025-02-13 Thread Alexander Burger
On Thu, Feb 13, 2025 at 08:50:16AM -0800, Lindsay Lawrence wrote:
> I think it is also a good a test/example of picolisp's support for bignums.

Indeed. The numbers in the 'E' environment get quite big. After ten
thousand digits of PI, 'S' and 'Q' have 145746 digits and 'R' has 145748
digits.

I verified that the first hundred thousand ouput digits are correct.

☺/ A!ex

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


Re: Tail call optimization

2025-02-13 Thread Lindsay Lawrence
On Thu, Feb 13, 2025 at 9:37 AM Alexander Burger 
wrote:

> On Thu, Feb 13, 2025 at 08:50:16AM -0800, Lindsay Lawrence wrote:
> > I think it is also a good a test/example of picolisp's support for
> bignums.
>
> Indeed. The numbers in the 'E' environment get quite big. After ten
> thousand digits of PI, 'S' and 'Q' have 145746 digits and 'R' has 145748
> digits.
>
> I verified that the first hundred thousand ouput digits are correct.
>
> Super.

I learned a new (to me) picolisp function from the updated code in your
other email, 'env', as well as the utility of 'prog1'.

It takes a while to get to 100K on my machine!

Thanks!
 /Lindsay


Re: Tail call optimization

2025-02-13 Thread Lindsay Lawrence
>
>
>
> Sorry again for the confusion!
>
> 👍

I think it is also a good a test/example of picolisp's support for bignums.

It could be a fun exercise to implement a version of this with one of the
other Pi algorithms that discards already computed digits
so it could essentially just churn out digits of pi as long as it existed
without any loss of performance.

/Lindsay


Re: Tail call optimization

2025-02-13 Thread Lindsay Lawrence
On Thu, Feb 13, 2025 at 9:37 AM Alexander Burger 
wrote:

> On Thu, Feb 13, 2025 at 08:50:16AM -0800, Lindsay Lawrence wrote:
> > I think it is also a good a test/example of picolisp's support for
> bignums.
>
> Indeed. The numbers in the 'E' environment get quite big. After ten
> thousand digits of PI, 'S' and 'Q' have 145746 digits and 'R' has 145748
> digits.
>
> I verified that the first hundred thousand ouput digits are correct.
>

A bit of searching came up with the paper with the haskell version

https://www.cs.ox.ac.uk/people/jeremy.gibbons/publications/spigot.pdf

Interestingly enough there is another version of PI in there, recursive,
based on the Gosper series,
that a faster... although it is based on a conjecture they haven't proven
in that paper.

The picolisp version of that one is below ('tco' is a nice fit for it as
well!)

(de piDigits (N)
   (default Q 1 R 180 S 60 I 2)
   (tco
  (Q R S I N)
  (let
 (U
(*
   3
   (+ (* 3 I) 1)
   (+ (* 3 I) 2) )
Y
(/
   (+
  (* Q (- (* 27 I) 12))
  (* 5 R) )
   (* 5 S) ) )
 (prin Y)
 (if (or (not N) (gt0 N))
(tc
   (* 10 Q I (- (* 2 I) 1))
   (*
  10
  U
  (-
 (+ (* Q (- (* 5 I) 2)) R)
 (* Y S) ) )
   (* S U)
   (+ I 1)
   (dec N) ) ) ) ) )

On my machine that outputs digits of PI like below

: (bench (out "pi-digits.1.txt" (piDigits 1)))
8.751 sec
-> NIL
: (bench (out "pi-digits.1.txt" (piDigits 5)))
117.745 sec
-> NIL
: (bench (out "pi-digits.1.txt" (piDigits 10)))
613.212 sec
-> NIL

/Lindsay