aboutsummaryrefslogtreecommitdiff
path: root/bbp.scm
blob: 9865a355e29746471ac0e811439ae18a332bb5c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
;; Copyright (C) 2026 Thomas Guillermo Albers Raviola
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

(import (rnrs)
	(srfi srfi-1)
	(srfi srfi-43))

(define (digits-of-pi n)
  ;; k=0 -> 3.2222222222 ...
  ;; k=1 -> 0.0212212212 ...
  ;; start vector with 3.243443443 ...
  (define digits (let ((v (make-vector n 4)))
		   (vector-set! v 0 2)
		   (do ((i 2 (+ i 3)))
		       ((>= i (vector-length v)) v)
		     (vector-set! v i 3))))
  (define (partial-term k)
    (let ([8k (* 8 k)])
      (- (/ 4 (+ 8k 1)) (/ 2 (+ 8k 4)) (/ 1 (+ 8k 5)) (/ 1 (+ 8k 6)))))
  (define (do-carry! v)
    (do ([i (- (vector-length v) 1) (- i 1)])
	((= i 0))
      (when (>= (vector-ref v i) 16)
	(vector-set! v (- i 1) (+ (vector-ref v (- i 1))
				  (fxdiv (vector-ref v i) 16)))
	(vector-set! v i (fxmod (vector-ref v i) 16)))))
  ;; k=2 -> 0.000acef6dc ...
  ;; k=3 -> 0.000055038c ...
  ;; k=4 -> 0.00000326fe ...
  (do ([k 2 (+ k 1)])
      ((= k n))
    (let* ([a (partial-term k)]
	   [den (denominator a)])
      (do ([i (+ k 1) (+ i 1)]
	   [num (fx* 16 (numerator a)) (fxmod (fx* 16 num) den)])
	  ((>= i n))
	(let ([v (vector-ref digits i)])
	  (vector-set! digits i (+ v (fxdiv (fx* 16 num) den)))))))
  (do-carry! digits)
  digits)

(define (display-digits-of-pi n)
  (let ([digits (digits-of-pi (+ n 4))])
    (display "3.")
    (do ([i 0 (+ i 1)])
	((= i n))
      (display (vector-ref digits i)))
    (newline)))

(display-digits-of-pi 100)

(define (digits-of-pi* n)
  (define digits (make-vector n 0))
  (define (term k)
    (let ([8k (* 8 k)])
      (/ (- (/ 4 (+ 8k 1)) (/ 2 (+ 8k 4)) (/ 1 (+ 8k 5)) (/ 1 (+ 8k 6)))
	 (expt 16 k))))
  ;; sum n+1 terms
  (define sum (let loop ([k 0] [s 0])
		(if (> k n) s (loop (+ k 1) (+ s (term k))))))
  (let ([den (denominator sum)])
    (do ([i 0 (+ i 1)]
	 [num (numerator sum) (* 16 (mod num den))])
	((>= i n) digits)
      (vector-set! digits i (div num den)))))