(* Pi digits computed with the sreaming algorithm given on pages 4, 6 & 7 of "Unbounded Spigot Algorithms for the Digits of Pi", Jeremy Gibbons, August 2004. *) open Printf open Big_int let ( !$ ) = Big_int.big_int_of_int let ( +$ ) = Big_int.add_big_int let ( *$ ) = Big_int.mult_big_int let ( =$ ) = Big_int.eq_big_int let zero = Big_int.zero_big_int and one = Big_int.unit_big_int and three = !$ 3 and four = !$ 4 and ten = !$ 10 and neg_ten = !$(-10) (* Linear Fractional (aka Möbius) Transformations *) module LFT = struct let floor_ev (q,r,s,t) x = div_big_int (q *$ x +$ r) (s *$ x +$ t) let unit = (one, zero, zero, one) let comp (q,r,s,t) (q',r',s',t') = (q *$ q' +$ r *$ s', q *$ r' +$ r *$ t', s *$ q' +$ t *$ s', s *$ r' +$ t *$ t') end let next z = LFT.floor_ev z three and safe z n = (n =$ LFT.floor_ev z four) and prod z n = LFT.comp (ten, neg_ten *$ n, zero, one) z and cons z k = let den = 2*k+1 in LFT.comp z (!$ k, !$(2*den), zero, !$ den) let rec digit k z n row col = if n > 0 then let y = next z in if safe z y then if col = 10 then ( let row = row + 10 in printf "\t:%i\n%s" row (string_of_big_int y); digit k (prod z y) (n-1) row 1 ) else ( print_string(string_of_big_int y); digit k (prod z y) (n-1) row (col+1) ) else digit (k+1) (cons z k) n row col else printf "%*s\t:%i\n" (10 - col) "" (row + col) let digits n = digit 1 LFT.unit n 0 0 let () = digits(int_of_string Sys.argv.(1))