OCaml pidigits update
CONTRIBUTE SOURCE CODE
(*
* The Computer Language Benchmarks Game
* https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
*
* prepared by Gabriel Scherer
* inspired by Zarith version (OCaml#5) by Christophe Troestler and Matías Giovannini
*)
let init = (Mpz.of_int 1, Mpz.of_int 1, Mpz.of_int 0)
let extract =
let res : Mpz.m Mpz.tt = Mpz.init () in
fun (num,den,acc) nth ->
(* (nth * num + acc) / den |> to_int *)
Mpz.mul_si res num nth;
Mpz.add res res acc;
Mpz.tdiv_q res res den;
Mpz.get_int res
let next z = extract z 3
let safe z n = extract z 4 = n
let prod =
let tmp : Mpz.m Mpz.tt = Mpz.init () in
fun (res_num, res_den, res_acc) (num,den,acc) d ->
(* (10 * num, den, 10 * (acc - den * of_int d)) *)
Mpz.mul_si res_num num 10;
Mpz.set res_den den;
Mpz.mul_si tmp den d;
Mpz.sub res_acc acc tmp;
Mpz.mul_si res_acc res_acc 10;
()
let cons =
fun (res_num, res_den, res_acc) (num,den,acc) k ->
let k2 = k * 2 + 1 in
(* (k * num, k2 * den, k2 * (acc + num + num)) *)
Mpz.mul_si res_den den k2;
Mpz.add res_acc acc num;
Mpz.add res_acc res_acc num;
Mpz.mul_si res_acc res_acc k2;
(* must go below the computation of res_acc,
to avoid trashing the 'num' value it uses *)
Mpz.mul_si res_num num k;
()
let columns = 10
let rec digit k z n row col =
if n = 0 then Printf.printf "%*s\t:%i\n" (columns-col) "" (row+col) else
let d = next z in
if safe z d then
if col = columns then begin
let row = row + col in
Printf.printf "\t:%i\n%i" row d;
prod z z d;
digit k z (n-1) row 1
end else begin
print_int d;
prod z z d;
digit k z (n-1) row (col+1)
end
else begin
cons z z k;
digit (k+1) z n row col
end
let digits n = digit 1 init n 0 0
let () = digits (try int_of_string (Array.get Sys.argv 1) with _ -> 27)
Provide a helpful Title
OCaml pidigits Gabriel Scherer
Attach your source code file
Provide an example build command-line
The command-line that I used to build and test my program is:
opam install mlgmpidl (* to get the Mpz module *)
ocamlfind ocamlopt -package gmp -linkpkg pidigits.ocaml-6.ml -o pidigits.ocaml-6.ocaml_run
time ./pidigits.ocaml-6.ocaml_run 10_000
However, I am not sure whether opam
is available on your test environment. I suppose that you prefer to use Debian packages to install the dependencies. The packaging of mlgmpidl on Debian is a bit funky, it is included in the larger package libapron-ocaml-dev. I think that the following should work, but I have not tested it (no Debian machine at hand). Please let me know if you don't want external dependencies, or if the command does not work.
apt-get install libapron-ocaml-dev
ocamlopt -I /usr/lib/ocaml/apron gmp.cmxa pidigits.ocaml-6.ml -o pidigits.ocaml-6.ocaml_run
Thanks!