pidigits.scm 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. (module-compile-options warn-undefined-variable: #t
  2. warn-invoke-unknown-method: #t)
  3. ;; Based on this Java version:
  4. ;; http://shootout.alioth.debian.org/u32q/benchmark.php?test=pidigits&lang=javaxint&id=1
  5. ;; contributed by Isaac Gouy
  6. (define-class Transformation ()
  7. (q :: integer)
  8. (r :: integer)
  9. (s :: integer)
  10. (t :: integer)
  11. (k :: int init: 0)
  12. ((next) :: void
  13. (set! k (+ k 1))
  14. (set! q k)
  15. (set! r (+ (* 4 k) 2))
  16. (set! s 0)
  17. (set! t (+ (* 2 k) 1)))
  18. ((extract (j :: int)) :: int
  19. (let ((numerator :: integer (+ (* q j) r))
  20. (denominator :: integer (+ (* s j) t)))
  21. ((integer:quotient numerator denominator):intValue)))
  22. ((qrst (qn :: int) (rn :: int) (sn :: int) (tn :: int)) :: void
  23. (set! q qn)
  24. (set! r rn)
  25. (set! s sn)
  26. (set! t tn)
  27. (set! k 0))
  28. ((compose (a :: Transformation)) :: Transformation
  29. (Transformation q: (* q a:q)
  30. r: (+ (* q a:r) (* r a:t))
  31. s: (+ (* s a:q) (* t a:s))
  32. t: (+ (* s a:r) (* t a:t)))))
  33. (define-class PiDigitSpigot ()
  34. (z :: Transformation init: (Transformation q: 1 r: 0 s: 0 t: 1))
  35. (x :: Transformation init: (Transformation q: 0 r: 0 s: 0 t: 0))
  36. (inverse :: Transformation init: (Transformation q: 0 r: 0 s: 0 t: 0))
  37. ((next) :: int
  38. (let ((y (digit)))
  39. (if (isSafe y)
  40. (begin (set! z (produce y)) y)
  41. (begin (x:next) (set! z (consume x)) (next)))))
  42. ((digit) :: int (z:extract 3))
  43. ((isSafe (digit :: int)) :: boolean
  44. (= digit (z:extract 4)))
  45. ((produce (i :: int)) :: Transformation
  46. (inverse:qrst 10 (* i -10) 0 1)
  47. (inverse:compose z))
  48. ((consume (a :: Transformation)) :: Transformation
  49. (z:compose a)))
  50. (define-constant L :: int 10)
  51. (define (pidigits (n :: int) (out :: java.io.PrintStream)) :: void
  52. (let ((j :: int 0)
  53. (digits (PiDigitSpigot)))
  54. (do ((n :: int n (- n L)))
  55. ((<= n 0))
  56. (if (>= n L)
  57. (do ((i :: int 0 (+ i 1)))
  58. ((>= i L) (set! j (+ j L)))
  59. (out:print (digits:next)))
  60. (begin
  61. (do ((i :: int 0 (+ i 1)))
  62. ((= i n))
  63. (out:print (digits:next)))
  64. (do ((i :: int n (+ i 1)))
  65. ((>= i L))
  66. (out:print " "))
  67. (set! j (+ j n))))
  68. (out:print "\t:")
  69. (out:println j))))
  70. (pidigits (string->number (cadr (command-line))) java.lang.System:out)