[Toss-devel-svn] SF.net SVN: toss:[1677] trunk/Toss
Status: Beta
Brought to you by:
lukaszkaiser
|
From: <luk...@us...> - 2012-02-18 02:07:15
|
Revision: 1677
http://toss.svn.sourceforge.net/toss/?rev=1677&view=rev
Author: lukaszkaiser
Date: 2012-02-18 02:07:02 +0000 (Sat, 18 Feb 2012)
Log Message:
-----------
Replacing Num.
Modified Paths:
--------------
trunk/Toss/Makefile
trunk/Toss/Server/Tests.ml
trunk/Toss/Solver/Num/Integers.ml
trunk/Toss/Solver/Num/Integers.mli
trunk/Toss/Solver/Num/IntegersTest.ml
trunk/Toss/Solver/Num/Naturals.ml
trunk/Toss/Solver/Num/NaturalsTest.ml
trunk/Toss/Solver/Num/NumbersTest.ml
trunk/Toss/Solver/Num/Rationals.ml
Modified: trunk/Toss/Makefile
===================================================================
--- trunk/Toss/Makefile 2012-02-17 02:36:56 UTC (rev 1676)
+++ trunk/Toss/Makefile 2012-02-18 02:07:02 UTC (rev 1677)
@@ -47,8 +47,8 @@
# TODO: Hard-coded path to js_of_ocaml.
OCB_LFLAG=-lflags -I,/usr/local/lib/ocaml/3.12.0/js_of_ocaml,-I,+oUnit,-I,+js_of_ocaml,-I,+site-lib/oUnit,-I,+site-lib/js_of_ocaml
OCB_CFLAG=-cflags -I,/usr/local/lib/ocaml/3.12.0/js_of_ocaml,-I,+oUnit,-I,+js_of_ocaml,-I,+site-lib/oUnit,-I,+site-lib/js_of_ocaml,-g
-OCB_LIB=-libs str,nums,unix,oUnit
-OCB_LIBJS=-libs str,js_of_ocaml
+OCB_LIB=-libs str,unix,oUnit
+OCB_LIBJS=-libs js_of_ocaml
OCB_PP=-pp "camlp4o -I /usr/local/lib/ocaml/3.12.0 -I /opt/local/lib/ocaml/site-lib ../caml_extensions/pa_let_try.cmo ../caml_extensions/pa_log.cmo pa_macro.cmo js_of_ocaml/pa_js.cmo"
OCB_PPJS=-pp "camlp4o -unsafe -I /usr/local/lib/ocaml/3.12.0 -I /opt/local/lib/ocaml/site-lib ../caml_extensions/pa_let_try.cmo ../caml_extensions/pa_log.cmo pa_macro.cmo -DJAVASCRIPT js_of_ocaml/pa_js.cmo"
OCAMLBUILD=ocamlbuild -log build.log -j 8 -menhir ../menhir_conf \
Modified: trunk/Toss/Server/Tests.ml
===================================================================
--- trunk/Toss/Server/Tests.ml 2012-02-17 02:36:56 UTC (rev 1676)
+++ trunk/Toss/Server/Tests.ml 2012-02-18 02:07:02 UTC (rev 1677)
@@ -14,9 +14,9 @@
let solver_tests = "Solver", [
"NaturalsTest", [NaturalsTest.tests];
- "IntegersTest", [IntegersTest.tests];
+ "IntegersTest", [IntegersTest.tests; IntegersTest.bigtests];
"RationalsTest", [RationalsTest.tests];
- "NumbersTest", [NumbersTest.tests];
+ "NumbersTest", [NumbersTest.tests; NumbersTest.bigtests];
"StructureTest", [StructureTest.tests];
"AssignmentsTest", [AssignmentsTest.tests];
"SolverTest", [SolverTest.tests; SolverTest.bigtests];
Modified: trunk/Toss/Solver/Num/Integers.ml
===================================================================
--- trunk/Toss/Solver/Num/Integers.ml 2012-02-17 02:36:56 UTC (rev 1676)
+++ trunk/Toss/Solver/Num/Integers.ml 2012-02-18 02:07:02 UTC (rev 1677)
@@ -13,7 +13,7 @@
open MiscNum
-open Naturals.N
+open Naturals
type big_int =
{ sign : int;
@@ -76,27 +76,31 @@
let max_big_int bi1 bi2 = if lt_big_int bi1 bi2 then bi2 else bi1
and min_big_int bi1 bi2 = if gt_big_int bi1 bi2 then bi2 else bi1
+let string_of_big_int bi =
+ if bi.sign = -1
+ then "-" ^ string_of_nat bi.abs_value
+ else string_of_nat bi.abs_value
+
+
(* Operations on big_int *)
let add_big_int bi1 bi2 =
- let size_bi1 = num_digits_big_int bi1
- and size_bi2 = num_digits_big_int bi2 in
- if bi1.sign = bi2.sign
- then (* Add absolute values if signs are the same *)
+ let size_bi1 = num_digits_big_int bi1
+ and size_bi2 = num_digits_big_int bi2 in
+ if bi1.sign = bi2.sign then (* Add absolute values if signs are the same *)
{ sign = bi1.sign;
abs_value =
match compare_nat (bi1.abs_value) (bi2.abs_value) with
- -1 -> let res = create_nat (succ size_bi2) in
- (blit_nat res 0 (bi2.abs_value) 0 size_bi2;
- set_digit_nat res size_bi2 0;
- add_nat res (bi1.abs_value);
- res)
- |_ -> let res = create_nat (succ size_bi1) in
- (blit_nat res 0 (bi1.abs_value) 0 size_bi1;
- set_digit_nat res size_bi1 0;
- add_nat res (bi2.abs_value);
- res)}
-
+ | -1 -> let res = create_nat (succ size_bi2) in
+ (blit_nat res 0 (bi2.abs_value) 0 size_bi2;
+ set_digit_nat res size_bi2 0;
+ add_nat res (bi1.abs_value);
+ res)
+ |_ -> let res = create_nat (succ size_bi1) in
+ (blit_nat res 0 (bi1.abs_value) 0 size_bi1;
+ set_digit_nat res size_bi1 0;
+ add_nat res (bi2.abs_value);
+ res)}
else (* Subtract absolute values if signs are different *)
match compare_nat (bi1.abs_value) (bi2.abs_value) with
| 0 -> zero_big_int
@@ -113,12 +117,12 @@
let big_int_of_int i =
{ sign = sign_int i;
abs_value =
- let res = (create_nat 1)
- in (if i = monster_int
- then (set_digit_nat res 0 biggest_int;
- incr_nat res)
- else set_digit_nat res 0 (abs i));
- res }
+ if i = monster_int then
+ let res = (create_nat 2) in
+ (set_digit_nat res 0 biggest_int;
+ incr_nat res; res)
+ else let res = (create_nat 1) in (set_digit_nat res 0 (abs i); res)
+ }
let big_int_of_nat nat =
let length = num_digits_nat nat in
@@ -146,34 +150,34 @@
abs_value = res }
let mult_big_int bi1 bi2 =
- let size_bi1 = num_digits_big_int bi1
- and size_bi2 = num_digits_big_int bi2 in
- let size_res = size_bi1 + size_bi2 in
- let res = make_nat (size_res) in
+ let size_bi1 = num_digits_big_int bi1
+ and size_bi2 = num_digits_big_int bi2 in
+ let size_res = size_bi1 + size_bi2 in
+ let res = make_nat (size_res) in
{ sign = bi1.sign * bi2.sign;
abs_value =
- if size_bi2 > size_bi1
- then (mult_nat res (bi2.abs_value) (bi1.abs_value); res)
- else (mult_nat res (bi1.abs_value) (bi2.abs_value); res)
+ if size_bi2 > size_bi1
+ then (mult_nat res (bi2.abs_value) (bi1.abs_value); res)
+ else (mult_nat res (bi1.abs_value) (bi2.abs_value); res)
}
(* (quotient, rest) of the euclidian division of 2 big_int *)
let quomod_big_int bi1 bi2 =
if bi2.sign = 0 then raise Division_by_zero
else
- let size_bi1 = num_digits_big_int bi1
- and size_bi2 = num_digits_big_int bi2 in
- match compare_nat (bi1.abs_value) (bi2.abs_value) with
- -1 -> (* 1/2 -> 0, reste 1, -1/2 -> -1, reste 1 *)
- (* 1/-2 -> 0, reste 1, -1/-2 -> 1, reste 1 *)
- if bi1.sign >= 0 then
- (big_int_of_int 0, bi1)
- else if bi2.sign >= 0 then
- (big_int_of_int(-1), add_big_int bi2 bi1)
- else
- (big_int_of_int 1, sub_big_int bi1 bi2)
+ let size_bi1 = num_digits_big_int bi1
+ and size_bi2 = num_digits_big_int bi2 in
+ match compare_nat (bi1.abs_value) (bi2.abs_value) with
+ | -1 -> (* 1/2 -> 0, reste 1, -1/2 -> -1, reste 1 *)
+ (* 1/-2 -> 0, reste 1, -1/-2 -> 1, reste 1 *)
+ if bi1.sign >= 0 then
+ (big_int_of_int 0, bi1)
+ else if bi2.sign >= 0 then
+ (big_int_of_int(-1), add_big_int bi2 bi1)
+ else
+ (big_int_of_int 1, sub_big_int bi1 bi2)
| 0 -> (big_int_of_int (bi1.sign * bi2.sign), zero_big_int)
- | _ -> let bi1_negatif = bi1.sign = -1 in
+ | _ -> let bi1_negatif = (bi1.sign = -1) in
let size_q =
if bi1_negatif
then succ (max (succ (size_bi1 - size_bi2)) 1)
@@ -236,26 +240,25 @@
let mod_big_int bi1 bi2 = snd (quomod_big_int bi1 bi2)
let gcd_big_int bi1 bi2 =
- let size_bi1 = num_digits_big_int bi1
- and size_bi2 = num_digits_big_int bi2 in
+ let size_bi1 = num_digits_big_int bi1
+ and size_bi2 = num_digits_big_int bi2 in
if is_zero_nat (bi1.abs_value) 0 size_bi1 then abs_big_int bi2
else if is_zero_nat (bi2.abs_value) 0 size_bi2 then
- { sign = 1;
- abs_value = bi1.abs_value }
+ { sign = 1; abs_value = bi1.abs_value }
else
- { sign = 1;
- abs_value =
- match compare_nat (bi1.abs_value) (bi2.abs_value) with
- | 0 -> bi1.abs_value
- | 1 ->
- let res = copy_nat (bi1.abs_value) 0 size_bi1 in
- let len = gcd_nat res (bi2.abs_value) in
- copy_nat res 0 len
- | _ ->
- let res = copy_nat (bi2.abs_value) 0 size_bi2 in
- let len = gcd_nat res (bi1.abs_value) in
- copy_nat res 0 len
- }
+ { sign = 1;
+ abs_value =
+ match compare_nat (bi1.abs_value) (bi2.abs_value) with
+ | 0 -> bi1.abs_value
+ | 1 ->
+ let res = copy_nat (bi1.abs_value) 0 size_bi1 in
+ let len = gcd_nat res (bi2.abs_value) in
+ copy_nat res 0 len
+ | _ ->
+ let res = copy_nat (bi2.abs_value) 0 size_bi2 in
+ let len = gcd_nat res (bi1.abs_value) in
+ copy_nat res 0 len
+ }
(* Coercion operators *)
@@ -264,11 +267,9 @@
let monster_nat = monster_big_int.abs_value;;
let is_int_big_int bi =
- num_digits_big_int bi == 1 &&
- match compare_nat bi.abs_value monster_nat with
- | 0 -> bi.sign == -1
- | -1 -> true
- | _ -> false;;
+ num_digits_big_int bi == 1 || (
+ num_digits_big_int bi == 2 && bi.sign == -1 &&
+ compare_nat bi.abs_value monster_nat == 0)
let int_of_big_int bi =
try let n = int_of_nat bi.abs_value in
@@ -286,12 +287,6 @@
(* Coercion with string type *)
-let string_of_big_int bi =
- if bi.sign = -1
- then "-" ^ string_of_nat bi.abs_value
- else string_of_nat bi.abs_value
-
-
let sys_big_int_of_string_aux s ofs len sgn =
if len < 1 then failwith "sys_big_int_of_string";
let n = nat_of_string s ofs len in
Modified: trunk/Toss/Solver/Num/Integers.mli
===================================================================
--- trunk/Toss/Solver/Num/Integers.mli 2012-02-17 02:36:56 UTC (rev 1676)
+++ trunk/Toss/Solver/Num/Integers.mli 2012-02-18 02:07:02 UTC (rev 1677)
@@ -98,7 +98,7 @@
val big_int_of_int : int -> big_int
(** Convert a small integer to a big integer. *)
-val big_int_of_nat : Naturals.N.nat -> big_int
+val big_int_of_nat : Naturals.nat -> big_int
(** Convert a natural to a big integer. *)
val is_int_big_int : big_int -> bool
@@ -121,7 +121,7 @@
(** {2 For internal use} *)
-val nat_of_big_int : big_int -> Naturals.N.nat
+val nat_of_big_int : big_int -> Naturals.nat
val approx_big_int: int -> big_int -> string
val base_power_big_int: int -> int -> big_int -> big_int
val round_futur_last_digit : string -> int -> int -> bool
Modified: trunk/Toss/Solver/Num/IntegersTest.ml
===================================================================
--- trunk/Toss/Solver/Num/IntegersTest.ml 2012-02-17 02:36:56 UTC (rev 1676)
+++ trunk/Toss/Solver/Num/IntegersTest.ml 2012-02-18 02:07:02 UTC (rev 1677)
@@ -1,14 +1,22 @@
open OUnit
open Integers
-let eq_bool (b1, b2) = assert_equal ~printer:string_of_bool b1 b2
+let eq_bool ?i (b1, b2) = match i with
+ | None -> assert_equal ~printer:string_of_bool b1 b2
+ | Some j -> assert_equal ~msg:(Printf.sprintf "test %i" j)
+ ~printer:string_of_bool b1 b2
let eq_int (i1, i2) = assert_equal ~printer:string_of_int i1 i2
let eq_string (s1, s2) = assert_equal ~printer:(fun x -> x) s1 s2
-let eq_big_int (bi1, bi2) = eq_bool (Integers.eq_big_int bi1 bi2, true)
+let eq_big_int ?i (bi1, bi2) =
+ let eq = Integers.eq_big_int bi1 bi2 in
+ if eq then () else
+ let is = match i with None -> "" | Some j -> Printf.sprintf "test %i: " j in
+ let msg = is ^ (string_of_big_int bi1) ^ " <> " ^ (string_of_big_int bi2) in
+ assert_equal ~msg ~printer:string_of_bool eq true
let failwith_test f x except =
try let _ = ignore (f x) in eq_string ("worked", "failed") with
- e -> eq_bool (e = except, true)
+ e -> if e = except then () else raise e
let rec gcd_int i1 i2 = if i2 = 0 then abs i1 else gcd_int i2 (i1 mod i2)
@@ -17,6 +25,19 @@
let biggest_int = monster_int - 1
let least_int = - biggest_int
+let pi_100_digits =
+"3141592653 :10
+5897932384 :20
+6264338327 :30
+9502884197 :40
+1693993751 :50
+0582097494 :60
+4592307816 :70
+4062862089 :80
+9862803482 :90
+5342117067 :100
+"
+
let pi_1000_digits =
"3141592653 :10
5897932384 :20
@@ -120,6 +141,55 @@
9216420198 :1000
"
+let pi_digits n_digits =
+ (* Pi digits computed with the streaming algorithm given on pages 4, 6
+ & 7 of "Unbounded Spigot Algorithms for the Digits of Pi", Jeremy
+ Gibbons, August 2004. *)
+ let ( !$ ) = big_int_of_int
+ and ( +$ ) = add_big_int
+ and ( *$ ) = mult_big_int in
+
+ let zero = zero_big_int
+ and one = unit_big_int
+ and three = !$ 3
+ and four = !$ 4
+ and ten = !$ 10
+ and neg_ten = !$(-10) in
+
+ (* Linear Fractional (aka Moebius) Transformations *)
+ let floor_ev (q, r, s, t) x = div_big_int (q *$ x +$ r) (s *$ x +$ t) in
+ let unit = (one, zero, zero, one) in
+ 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') in
+
+ let next z = floor_ev z three in
+ let safe z n = Integers.eq_big_int n (floor_ev z four) in
+ let prod z n = comp (ten, neg_ten *$ n, zero, one) z in
+ let cons z k = let den = 2 * k + 1 in
+ comp z (!$ k, !$(2 * den), zero, !$ den) in
+
+ let rec digit k z n row col acc =
+ if n > 0 then
+ let y = next z in
+ if safe z y then
+ if col = 10 then (
+ let row = row + 10 in
+ digit k (prod z y) (n - 1) row 1
+ ((Printf.sprintf "\t:%i\n%s" row (string_of_big_int y)) :: acc)
+ ) else (
+ digit k (prod z y) (n - 1) row (col + 1)
+ ((string_of_big_int y) :: acc)
+ )
+ else digit (k + 1) (cons z k) n row col acc
+ else
+ (Printf.sprintf "%*s\t:%i\n" (10 - col) "" (row + col)) :: acc in
+
+ let digits n = digit 1 unit n 0 0 [] in
+ String.concat "" (List.rev (digits n_digits))
+
+
+
let tests = "Integers" >::: [
"compare_big_int" >::
(fun () ->
@@ -140,76 +210,76 @@
"add_big_int" >::
(fun () ->
- eq_big_int (add_big_int zero_big_int zero_big_int, zero_big_int);
- eq_big_int (add_big_int zero_big_int (big_int_of_int 1),
- big_int_of_int 1);
- eq_big_int (add_big_int (big_int_of_int 1) zero_big_int,
- big_int_of_int 1);
- eq_big_int (add_big_int zero_big_int (big_int_of_int (-1)),
- big_int_of_int (-1));
- eq_big_int (add_big_int (big_int_of_int (-1)) zero_big_int,
- big_int_of_int (-1));
- eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int 1),
- big_int_of_int 2);
- eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int 2),
- big_int_of_int 3);
- eq_big_int (add_big_int (big_int_of_int 2) (big_int_of_int 1),
- big_int_of_int 3);
- eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int (-1)),
- big_int_of_int (-2));
- eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int (-2)),
- big_int_of_int (-3));
- eq_big_int (add_big_int (big_int_of_int (-2)) (big_int_of_int (-1)),
- big_int_of_int (-3));
- eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int (-1)),
- zero_big_int);
- eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int 1),
- zero_big_int);
- eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int (-2)),
- big_int_of_int (-1));
- eq_big_int (add_big_int (big_int_of_int (-2)) (big_int_of_int 1),
- big_int_of_int (-1));
- eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int 2),
- big_int_of_int 1);
- eq_big_int (add_big_int (big_int_of_int 2) (big_int_of_int (-1)),
- big_int_of_int 1);
+ eq_big_int ~i:1 (add_big_int zero_big_int zero_big_int, zero_big_int);
+ eq_big_int ~i:2 (add_big_int zero_big_int (big_int_of_int 1),
+ big_int_of_int 1);
+ eq_big_int ~i:3 (add_big_int (big_int_of_int 1) zero_big_int,
+ big_int_of_int 1);
+ eq_big_int ~i:4 (add_big_int zero_big_int (big_int_of_int (-1)),
+ big_int_of_int (-1));
+ eq_big_int ~i:5 (add_big_int (big_int_of_int (-1)) zero_big_int,
+ big_int_of_int (-1));
+ eq_big_int ~i:6 (add_big_int (big_int_of_int 1) (big_int_of_int 1),
+ big_int_of_int 2);
+ eq_big_int ~i:7 (add_big_int (big_int_of_int 1) (big_int_of_int 2),
+ big_int_of_int 3);
+ eq_big_int ~i:8 (add_big_int (big_int_of_int 2) (big_int_of_int 1),
+ big_int_of_int 3);
+ eq_big_int ~i:9 (add_big_int (big_int_of_int (-1)) (big_int_of_int (-1)),
+ big_int_of_int (-2));
+ eq_big_int ~i:10 (add_big_int (big_int_of_int (-1)) (big_int_of_int (-2)),
+ big_int_of_int (-3));
+ eq_big_int ~i:11 (add_big_int (big_int_of_int (-2)) (big_int_of_int (-1)),
+ big_int_of_int (-3));
+ eq_big_int ~i:12 (add_big_int (big_int_of_int 1) (big_int_of_int (-1)),
+ zero_big_int);
+ eq_big_int ~i:13 (add_big_int (big_int_of_int (-1)) (big_int_of_int 1),
+ zero_big_int);
+ eq_big_int ~i:14 (add_big_int (big_int_of_int 1) (big_int_of_int (-2)),
+ big_int_of_int (-1));
+ eq_big_int ~i:15 (add_big_int (big_int_of_int (-2)) (big_int_of_int 1),
+ big_int_of_int (-1));
+ eq_big_int ~i:16 (add_big_int (big_int_of_int (-1)) (big_int_of_int 2),
+ big_int_of_int 1);
+ eq_big_int ~i:17 (add_big_int (big_int_of_int 2) (big_int_of_int (-1)),
+ big_int_of_int 1);
);
"sub_big_int" >::
(fun () ->
- eq_big_int (sub_big_int zero_big_int zero_big_int, zero_big_int);
- eq_big_int (sub_big_int zero_big_int (big_int_of_int 1),
- big_int_of_int (-1));
- eq_big_int (sub_big_int (big_int_of_int 1) zero_big_int,
- big_int_of_int 1);
- eq_big_int (sub_big_int zero_big_int (big_int_of_int (-1)),
- big_int_of_int 1);
- eq_big_int (sub_big_int (big_int_of_int (-1)) zero_big_int,
- big_int_of_int (-1));
- eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int 1),
- zero_big_int);
- eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int 2),
- big_int_of_int (-1));
- eq_big_int (sub_big_int (big_int_of_int 2) (big_int_of_int 1),
- big_int_of_int 1);
- eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int (-1)),
- zero_big_int);
- eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int (-2)),
- big_int_of_int 1);
- eq_big_int (sub_big_int (big_int_of_int (-2)) (big_int_of_int (-1)),
- big_int_of_int (-1));
- eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int (-1)),
- big_int_of_int 2);
- eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int 1),
- big_int_of_int (-2));
- eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int (-2)),
- big_int_of_int 3);
- eq_big_int (sub_big_int (big_int_of_int (-2)) (big_int_of_int 1),
- big_int_of_int (-3));
- eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int 2),
- big_int_of_int (-3));
- eq_big_int (sub_big_int (big_int_of_int 2) (big_int_of_int (-1)),
- big_int_of_int 3);
+ eq_big_int ~i:1 (sub_big_int zero_big_int zero_big_int, zero_big_int);
+ eq_big_int ~i:2 (sub_big_int zero_big_int (big_int_of_int 1),
+ big_int_of_int (-1));
+ eq_big_int ~i:3 (sub_big_int (big_int_of_int 1) zero_big_int,
+ big_int_of_int 1);
+ eq_big_int ~i:4 (sub_big_int zero_big_int (big_int_of_int (-1)),
+ big_int_of_int 1);
+ eq_big_int ~i:5 (sub_big_int (big_int_of_int (-1)) zero_big_int,
+ big_int_of_int (-1));
+ eq_big_int ~i:6 (sub_big_int (big_int_of_int 1) (big_int_of_int 1),
+ zero_big_int);
+ eq_big_int ~i:7 (sub_big_int (big_int_of_int 1) (big_int_of_int 2),
+ big_int_of_int (-1));
+ eq_big_int ~i:8 (sub_big_int (big_int_of_int 2) (big_int_of_int 1),
+ big_int_of_int 1);
+ eq_big_int ~i:9 (sub_big_int (big_int_of_int (-1)) (big_int_of_int (-1)),
+ zero_big_int);
+ eq_big_int ~i:10 (sub_big_int (big_int_of_int (-1)) (big_int_of_int (-2)),
+ big_int_of_int 1);
+ eq_big_int ~i:11 (sub_big_int (big_int_of_int (-2)) (big_int_of_int (-1)),
+ big_int_of_int (-1));
+ eq_big_int ~i:12 (sub_big_int (big_int_of_int 1) (big_int_of_int (-1)),
+ big_int_of_int 2);
+ eq_big_int ~i:13 (sub_big_int (big_int_of_int (-1)) (big_int_of_int 1),
+ big_int_of_int (-2));
+ eq_big_int ~i:14 (sub_big_int (big_int_of_int 1) (big_int_of_int (-2)),
+ big_int_of_int 3);
+ eq_big_int ~i:15 (sub_big_int (big_int_of_int (-2)) (big_int_of_int 1),
+ big_int_of_int (-3));
+ eq_big_int ~i:16 (sub_big_int (big_int_of_int (-1)) (big_int_of_int 2),
+ big_int_of_int (-3));
+ eq_big_int ~i:17 (sub_big_int (big_int_of_int 2) (big_int_of_int (-1)),
+ big_int_of_int 3);
);
"mult_int_big_int" >::
@@ -240,43 +310,43 @@
(fun () ->
let (quotient, modulo) =
quomod_big_int (big_int_of_int 1) (big_int_of_int 1) in
- eq_big_int (quotient, big_int_of_int 1);
- eq_big_int (modulo, zero_big_int);
+ eq_big_int ~i:1 (quotient, big_int_of_int 1);
+ eq_big_int ~i:2 (modulo, zero_big_int);
let (quotient, modulo) =
quomod_big_int (big_int_of_int 1) (big_int_of_int (-1)) in
- eq_big_int (quotient, big_int_of_int (-1));
- eq_big_int (modulo, zero_big_int);
+ eq_big_int ~i:3 (quotient, big_int_of_int (-1));
+ eq_big_int ~i:4 (modulo, zero_big_int);
let (quotient, modulo) =
quomod_big_int (big_int_of_int (-1)) (big_int_of_int 1) in
- eq_big_int (quotient, big_int_of_int (-1));
- eq_big_int (modulo, zero_big_int);
+ eq_big_int ~i:5 (quotient, big_int_of_int (-1));
+ eq_big_int ~i:6 (modulo, zero_big_int);
let (quotient, modulo) =
quomod_big_int (big_int_of_int 3) (big_int_of_int 2) in
- eq_big_int (quotient, big_int_of_int 1);
- eq_big_int (modulo, big_int_of_int 1);
+ eq_big_int ~i:7 (quotient, big_int_of_int 1);
+ eq_big_int ~i:8 (modulo, big_int_of_int 1);
let (quotient, modulo) =
quomod_big_int (big_int_of_int 5) (big_int_of_int 3) in
- eq_big_int (quotient, big_int_of_int 1);
- eq_big_int (modulo, big_int_of_int 2);
+ eq_big_int ~i:9 (quotient, big_int_of_int 1);
+ eq_big_int ~i:10 (modulo, big_int_of_int 2);
let (quotient, modulo) =
quomod_big_int (big_int_of_int (-5)) (big_int_of_int 3) in
- eq_big_int (quotient, big_int_of_int (-2));
- eq_big_int (modulo, big_int_of_int 1);
+ eq_big_int ~i:11 (quotient, big_int_of_int (-2));
+ eq_big_int ~i:12 (modulo, big_int_of_int 1);
let (quotient, modulo) =
quomod_big_int (big_int_of_int 1) (big_int_of_int 2) in
- eq_big_int (quotient, zero_big_int);
- eq_big_int (modulo, big_int_of_int 1);
+ eq_big_int ~i:13 (quotient, zero_big_int);
+ eq_big_int ~i:14 (modulo, big_int_of_int 1);
let (quotient, modulo) =
quomod_big_int (big_int_of_int (-1)) (big_int_of_int 3) in
- eq_big_int (quotient, minus_big_int unit_big_int);
- eq_big_int (modulo, big_int_of_int 2);
+ eq_big_int ~i:14 (quotient, minus_big_int unit_big_int);
+ eq_big_int ~i:15 (modulo, big_int_of_int 2);
failwith_test
(quomod_big_int (big_int_of_int 1)) zero_big_int
@@ -284,23 +354,23 @@
let (quotient, modulo) =
quomod_big_int (big_int_of_int 10) (big_int_of_int 20) in
- eq_big_int (quotient, big_int_of_int 0);
- eq_big_int (modulo, big_int_of_int 10);
+ eq_big_int ~i:16 (quotient, big_int_of_int 0);
+ eq_big_int ~i:17 (modulo, big_int_of_int 10);
let (quotient, modulo) =
quomod_big_int (big_int_of_int (-10)) (big_int_of_int 20) in
- eq_big_int (quotient, big_int_of_int (-1));
- eq_big_int (modulo, big_int_of_int 10);
+ eq_big_int ~i:18 (quotient, big_int_of_int (-1));
+ eq_big_int ~i:19 (modulo, big_int_of_int 10);
let (quotient, modulo) =
quomod_big_int (big_int_of_int 10) (big_int_of_int (-20)) in
- eq_big_int (quotient, big_int_of_int 0);
- eq_big_int (modulo, big_int_of_int 10);
+ eq_big_int ~i:20 (quotient, big_int_of_int 0);
+ eq_big_int ~i:21 (modulo, big_int_of_int 10);
let (quotient, modulo) =
quomod_big_int (big_int_of_int (-10)) (big_int_of_int (-20)) in
- eq_big_int (quotient, big_int_of_int 1);
- eq_big_int (modulo, big_int_of_int 10);
+ eq_big_int ~i:22 (quotient, big_int_of_int 1);
+ eq_big_int ~i:23 (modulo, big_int_of_int 10);
);
"gcd_big_int" >::
@@ -353,27 +423,24 @@
"is_int_big_int" >::
(fun () ->
- eq_bool (is_int_big_int (big_int_of_int 1), true);
- eq_bool (is_int_big_int (big_int_of_int (-1)), true);
- eq_bool (is_int_big_int (add_big_int (big_int_of_int 1)
- (big_int_of_int biggest_int)),
- false);
+ eq_bool ~i:1 (is_int_big_int (big_int_of_int 1), true);
+ eq_bool ~i:2 (is_int_big_int (big_int_of_int (-1)), true);
+ eq_bool ~i:3 (is_int_big_int (add_big_int (big_int_of_int 1)
+ (big_int_of_int biggest_int)), false);
eq_int (int_of_big_int (big_int_of_int monster_int), monster_int);
- eq_bool (is_int_big_int (big_int_of_string (string_of_int biggest_int)),
- true);
- eq_bool (is_int_big_int (big_int_of_string (string_of_int least_int)),
- true);
- eq_bool (is_int_big_int (big_int_of_string (string_of_int monster_int)),
- true);
- eq_bool (is_int_big_int (add_big_int (big_int_of_int 1)
- (big_int_of_int (biggest_int))),
- false);
- eq_bool (is_int_big_int (add_big_int (big_int_of_int 1)
- (big_int_of_int (biggest_int))),
- false);
- eq_bool (is_int_big_int
- (minus_big_int (big_int_of_string(string_of_int monster_int))),
- false);
+ eq_bool ~i:4 (is_int_big_int (big_int_of_string
+ (string_of_int biggest_int)), true);
+ eq_bool ~i:5 (is_int_big_int (big_int_of_string
+ (string_of_int least_int)), true);
+ eq_bool ~i:6 (is_int_big_int (big_int_of_int monster_int), true);
+ eq_bool ~i:7 (is_int_big_int (big_int_of_string
+ (string_of_int monster_int)), true);
+ eq_bool ~i:8 (is_int_big_int (add_big_int (big_int_of_int 1)
+ (big_int_of_int (biggest_int))), false);
+ eq_bool ~i:9 (is_int_big_int (add_big_int (big_int_of_int 1)
+ (big_int_of_int (biggest_int))), false);
+ eq_bool ~i:10 (is_int_big_int (minus_big_int (
+ big_int_of_string(string_of_int monster_int))), false);
);
"string_of_big_int" >::
@@ -383,13 +450,13 @@
"big_int_of_string" >::
(fun () ->
- eq_big_int (big_int_of_string "1", big_int_of_int 1);
- eq_big_int (big_int_of_string "-1", big_int_of_int (-1));
- eq_big_int (big_int_of_string "0", zero_big_int);
+ eq_big_int ~i:1 (big_int_of_string "1", big_int_of_int 1);
+ eq_big_int ~i:2 (big_int_of_string "-1", big_int_of_int (-1));
+ eq_big_int ~i:3 (big_int_of_string "0", zero_big_int);
failwith_test big_int_of_string "sdjdkfighdgf" (Failure "invalid digit");
- eq_big_int (big_int_of_string "123", big_int_of_int 123);
- eq_big_int (big_int_of_string "3456", big_int_of_int 3456);
- eq_big_int (big_int_of_string "-3456", big_int_of_int (-3456));
+ eq_big_int ~i:4 (big_int_of_string "123", big_int_of_int 123);
+ eq_big_int ~i:5 (big_int_of_string "3456", big_int_of_int 3456);
+ eq_big_int ~i:6 (big_int_of_string "-3456", big_int_of_int (-3456));
let implode = List.fold_left (^) "" in
let l = List.rev [
@@ -414,18 +481,19 @@
] in
let bi1 = big_int_of_string (implode (List.rev l)) in
let bi2 = big_int_of_string (implode (List.rev ("3" :: List.tl l))) in
- eq_big_int (bi1, (add_big_int (mult_big_int bi2 (big_int_of_string "10"))
- (big_int_of_string "2")));
+ eq_big_int ~i:7 (bi1, (add_big_int (mult_big_int bi2
+ (big_int_of_string "10"))
+ (big_int_of_string "2")));
);
"power_base_int" >::
(fun () ->
- eq_big_int (big_int_of_nat (Naturals.N.power_base_int 10 0),unit_big_int);
- eq_big_int (big_int_of_nat (Naturals.N.power_base_int 10 8),
+ eq_big_int (big_int_of_nat (Naturals.power_base_int 10 0),unit_big_int);
+ eq_big_int (big_int_of_nat (Naturals.power_base_int 10 8),
big_int_of_int 100000000);
- eq_big_int (big_int_of_nat(Naturals.N.power_base_int 2 (length_of_int+2)),
- big_int_of_nat (let nat = Naturals.N.make_nat 2 in
- Naturals.N.set_digit_nat nat 1 1;
+ eq_big_int (big_int_of_nat(Naturals.power_base_int 2 (length_of_int)),
+ big_int_of_nat (let nat = Naturals.make_nat 2 in
+ Naturals.set_digit_nat nat 1 1;
nat));
);
@@ -438,53 +506,16 @@
big_int_of_int 1230);
);
- "pi digits" >::
+ "pi 100 digits" >::
(fun () ->
- (* Pi digits computed with the streaming algorithm given on pages 4, 6
- & 7 of "Unbounded Spigot Algorithms for the Digits of Pi", Jeremy
- Gibbons, August 2004. *)
- let ( !$ ) = big_int_of_int
- and ( +$ ) = add_big_int
- and ( *$ ) = mult_big_int in
+ eq_string (pi_digits 100, pi_100_digits);
+ );
+]
- let zero = zero_big_int
- and one = unit_big_int
- and three = !$ 3
- and four = !$ 4
- and ten = !$ 10
- and neg_ten = !$(-10) in
-
- (* Linear Fractional (aka Moebius) Transformations *)
- let floor_ev (q, r, s, t) x = div_big_int (q *$ x +$ r) (s *$ x +$ t) in
- let unit = (one, zero, zero, one) in
- 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') in
-
- let next z = floor_ev z three in
- let safe z n = Integers.eq_big_int n (floor_ev z four) in
- let prod z n = comp (ten, neg_ten *$ n, zero, one) z in
- let cons z k = let den = 2 * k + 1 in
- comp z (!$ k, !$(2 * den), zero, !$ den) in
-
- let rec digit k z n row col acc =
- if n > 0 then
- let y = next z in
- if safe z y then
- if col = 10 then (
- let row = row + 10 in
- digit k (prod z y) (n - 1) row 1
- ((Printf.sprintf "\t:%i\n%s" row (string_of_big_int y)) :: acc)
- ) else (
- digit k (prod z y) (n - 1) row (col + 1)
- ((string_of_big_int y) :: acc)
- )
- else digit (k + 1) (cons z k) n row col acc
- else
- (Printf.sprintf "%*s\t:%i\n" (10 - col) "" (row + col)) :: acc in
-
- let digits n = digit 1 unit n 0 0 [] in
- eq_string (String.concat "" (List.rev (digits 1000)), pi_1000_digits);
+let bigtests = "IntegersBig" >::: [
+ "pi 1000 digits" >::
+ (fun () ->
+ eq_string (pi_digits 1000, pi_1000_digits);
);
]
Modified: trunk/Toss/Solver/Num/Naturals.ml
===================================================================
--- trunk/Toss/Solver/Num/Naturals.ml 2012-02-17 02:36:56 UTC (rev 1676)
+++ trunk/Toss/Solver/Num/Naturals.ml 2012-02-18 02:07:02 UTC (rev 1677)
@@ -1,201 +1,225 @@
-IFDEF JAVASCRIPT THEN
open Array
-module N = (struct
- type nat = int array
- let max_int_length = Sys.word_size - 2 (* should be even *)
+type nat = int array
- let create_nat s = make s 0
+let max_int_length = Sys.word_size - 2 (* should be even *)
+let max_power10_int = 1000000000
+let sprint_full_length_int i = Printf.sprintf "%.9i" i
- let set_to_zero_nat s i1 i2 =
- for i = i1 to i2 do s.(i) <- 0; done
+let create_nat s = make s 0
- let make_nat len =
- if len < 0 then invalid_arg "make_nat" else create_nat len
+let set_to_zero_nat s i1 i2 =
+ for i = i1 to i2 do s.(i) <- 0; done
- let blit_nat n1 i1 n2 i2 i3 = blit n1 i1 n2 i2 i3
+let make_nat len =
+ if len < 0 then invalid_arg "make_nat" else
+ if len = 0 then create_nat 1 else create_nat len
- let copy_nat nat offset length =
- let res = create_nat length in blit nat offset res 0 length; res
+let blit_nat n1 i1 n2 i2 i3 = blit n2 i2 n1 i1 i3
- let set_digit_nat n d x = n.(d) <- x
+let copy_nat nat offset length =
+ let res = create_nat length in blit nat offset res 0 length; res
- let num_digits_nat n =
- let l = ref ((length n) - 1) in
- while (!l >= 0 && n.(!l) = 0) do l := !l - 1 done;
- !l + 1
+let set_digit_nat n d x = n.(d) <- x
- let is_zero_nat n i1 i2 = num_digits_nat (copy_nat n i1 i2) = 0
+let one_nat = make 1 1
- let shrink n =
- let m = num_digits_nat n in if m = length n then n else
- let res = make m 0 in blit n 0 res 0 m; res
+let num_digits_nat n =
+ let l = ref ((length n) - 1) in
+ while (!l >= 0 && n.(!l) = 0) do l := !l - 1 done;
+ !l + 1
- let int_of_nat n =
- if num_digits_nat n > 1 then failwith "int_of_nat" else n.(0)
- let nat_of_int i = make 1 i
+let is_zero_nat n i1 i2 = num_digits_nat (copy_nat n i1 i2) = 0
- let compare_nat n m =
- let rec compare_from i =
- let ni = if i < length n then n.(i) else 0 in
- let mi = if i < length m then m.(i) else 0 in
- if ni < mi then -1 else if ni > mi then 1 else
- if i = 0 then 0 else compare_from (i-1) in
- compare_from ((max (length n) (length m)) - 1)
+let int_of_nat n =
+ if num_digits_nat n > 1 then failwith "int_of_nat" else n.(0)
+let nat_of_int i = make 1 i
- let add_nat n x = (* n := n + x *)
- let rec add_carry i carry =
- if i >= length n then (if carry <> 0 then failwith "overflow") else
- if i >= length x then (
- let res = n.(i) + carry in
- if res >= 0 then n.(i) <- res else (
- n.(i) <- 0; add_carry (i+1) 1
- )
+let compare_nat n m =
+ let rec compare_from i =
+ let ni = if i < length n then n.(i) else 0 in
+ let mi = if i < length m then m.(i) else 0 in
+ if ni < mi then -1 else if ni > mi then 1 else
+ if i = 0 then 0 else compare_from (i-1) in
+ compare_from ((max (length n) (length m)) - 1)
+
+let add_nat_off off n x = (* n := n + (x shifted by off) *)
+ let rec add_carry i carry =
+ if i + off >= length n then (if carry <> 0 then failwith "overflow") else
+ if i >= length x then (
+ let res = n.(i+off) + carry in
+ if res >= 0 then n.(i+off) <- res else (
+ n.(i+off) <- 0; add_carry (i+1) 1
+ )
+ ) else (
+ let res = n.(i+off) + x.(i) + carry in
+ if res >= 0 then (
+ n.(i+off) <- res;
+ add_carry (i+1) 0
) else (
- let res = n.(i) + x.(i) + carry in
- if res >= 0 then (
- n.(i) <- res;
- add_carry (i+1) 0
- ) else (
- let mid = n.(i) - max_int - 1 in
- n.(i) <- mid + x.(i) + carry;
- add_carry (i+1) 1
- )
- ) in
- add_carry 0 0
+ let mid = n.(i+off) - max_int - 1 in
+ n.(i+off) <- mid + x.(i) + carry;
+ add_carry (i+1) 1
+ )
+ ) in
+ add_carry 0 0
- let incr_nat n = add_nat n (make 1 1)
+let add_nat n x = add_nat_off 0 n x
- let sub_nat n x = (* n := n - x *)
- let rec sub_carry i carry =
- if i >= length n then (if carry <> 0 then failwith "sub too big") else
- if i >= length x then (
- let res = n.(i) + carry in
- if res >= 0 then n.(i) <- res else (
- sub_carry (i+1) (-1)
- )
- ) else
- let res = n.(i) - x.(i) + carry in
- if res >= 0 then (
- n.(i) <- res;
- sub_carry (i+1) 0;
- ) else (
- n.(i) <- res + 1;
- n.(i) <- n.(i) + max_int;
- sub_carry (i+1) (-1)
- ) in
- sub_carry 0 0
+let incr_nat n = add_nat n one_nat
- let half_int = 1 lsl (max_int_length / 2)
+let sub_nat n x = (* n := n - x *)
+ let rec sub_carry i carry =
+ if i >= length n then (if carry <> 0 then failwith "sub too big") else
+ if i >= length x then (
+ let res = n.(i) + carry in
+ if res >= 0 then n.(i) <- res else (
+ sub_carry (i+1) (-1)
+ )
+ ) else
+ let res = n.(i) - x.(i) + carry in
+ if res >= 0 then (
+ n.(i) <- res;
+ sub_carry (i+1) 0;
+ ) else (
+ n.(i) <- res + 1;
+ n.(i) <- n.(i) + max_int;
+ sub_carry (i+1) (-1)
+ ) in
+ sub_carry 0 0
- let mult_digit_nat_off off n x i = (* n := x * i shift by offset *)
- let add_to_pos j x = (* n.(j) <- n.(j)+x; unsafe-add overflow to n.(j+1) *)
- if n.(j) + x >= 0 then n.(j) <- n.(j) + x else (
- let mid = x - max_int - 1 in
- n.(j) <- n.(j) + mid;
- n.(j+1) <- n.(j+1) + 1;
- ) in
- let i0, i1 = i mod half_int, i / half_int in
- let rec mult_digit j =
- if (j >= length x) then () else (
- let x0, x1 = x.(j) mod half_int, x.(j) / half_int in
- let res0, resa, resb = x0 * i0, x1 * i0, x0 * i1 in
- let res0a, res1a = (resa mod half_int) * half_int, resa / half_int in
- let res0b, res1b = (resb mod half_int) * half_int, resb / half_int in
- let next = x1 * i1 + res1a + res1b in
- if next > 0 then n.(off+j+1) <- next;
- add_to_pos (off+j) res0;
- add_to_pos (off+j) res0a;
- add_to_pos (off+j) res0b;
- mult_digit (j+1);
- ) in
- for i = 0 to off do n.(i) <- 0 done;
- mult_digit 0
+let half_int = 1 lsl (max_int_length / 2)
- let mult_digit_nat n x i = (* n := x*i *)
- fill n 0 (length n) 0;
- mult_digit_nat_off 0 n x i
+let one_arr = make 1 0
+let add_nat_off_digit off n digit =
+ one_arr.(0) <- digit;
+ add_nat_off off n one_arr
- let mult_nat n x1 x2 = (* n := x1 * x2 *)
- fill n 0 (length n) 0;
- let interim = make (length n) 0 in
- for j = 0 to (length x2) - 1 do
- mult_digit_nat_off j interim x1 x2.(j);
- add_nat n interim;
+let mult_digit_nat_off off n x i = (* n += x*i shift by offset *)
+ let i0, i1 = i mod half_int, i / half_int in
+ let rec mult_digit j =
+ if (j >= length x) then () else (
+ let x0, x1 = x.(j) mod half_int, x.(j) / half_int in
+ let res0, resa, resb = x0 * i0, x1 * i0, x0 * i1 in
+ let res0a, res1a = (resa mod half_int) * half_int, resa / half_int in
+ let res0b, res1b = (resb mod half_int) * half_int, resb / half_int in
+ let next = x1 * i1 + res1a + res1b in
+ if next > 0 then add_nat_off_digit (off+j+1) n next;
+ add_nat_off_digit (off+j) n res0;
+ add_nat_off_digit (off+j) n res0a;
+ add_nat_off_digit (off+j) n res0b;
+ mult_digit (j+1);
+ ) in
+ if i = 0 then () else if i = 1 then add_nat_off off n x else
+ mult_digit 0
+
+let mult_digit_nat n x i = (* n += x*i *)
+ mult_digit_nat_off 0 n x i
+
+let mult_nat n x1 x2 = (* n += x1 * x2 *)
+ let (nd1, nd2) = num_digits_nat x1, num_digits_nat x2 in
+ if nd1 = 0 || nd2 = 0 then () else (
+ for j = 0 to nd2 - 1 do
+ mult_digit_nat_off j n x1 x2.(j);
done
+ )
- let div_nat n xin = (* n := n / x *)
- let res, x = make_nat (length n), shrink xin in
- let lx = length x in
- let rec approx_backshift i n m =
- if m = max_int then
- let (d, b) = approx_backshift 0 n ((m / 2) + 1) in (d, b+1)
- else if m+1 > n * (1 lsl i) then
- approx_backshift (i+1) n m
- else (n * (1 lsl i)) / (m+1), i in
- let rec div_subs cur =
- match compare_nat cur x with
- | y when y < 0 -> ()
- | 0 -> add_nat res (make 1 1)
- | _->
- let l = length cur - lx in
- let (i, b) = approx_backshift 0 cur.((length cur) - 1) x.(lx - 1) in
- let xmult, resmult = make (l+1) 0, make ((length cur)+1) 0 in
- if b = 0 then (
- xmult.(l) <- i;
+let prealloc_len = 1000
+let prealloc_res, prealloc_resmult = make prealloc_len 0, make prealloc_len 0
+
+let div_nat_fn ln n x = (* put (n := n mod x) and return (n / x) *)
+ let (res, resmult) =
+ if prealloc_len > ln then (
+ fill prealloc_res 0 (ln+1) 0;
+ fill prealloc_resmult 0 (ln+1) 0;
+ prealloc_res, prealloc_resmult
+ ) else (make_nat ln, make_nat ln) in
+ let lx = num_digits_nat x in
+ let rec approx_backshift i n m add =
+ if m = max_int then
+ let (d, b) = approx_backshift 0 n ((m / 2) + 1) add in (d, b+1)
+ else
+ let shn = n * (1 lsl i) in
+ if shn > 0 && m+add > shn then
+ approx_backshift (i+1) n m add
+ else if shn > 0 then
+ shn / (m+add), i
+ else 1, i in
+ let rec div_subs cur =
+ match compare_nat cur x with
+ | y when y < 0 -> ()
+ | 0 -> add_nat res one_nat; fill cur 0 ln 0
+ | _ ->
+ let lc = num_digits_nat cur in
+ let l = lc - lx in
+ let (i, b) = approx_backshift 0 cur.(lc-1) x.(lx-1)
+ (if lx = 1 then 0 else 1) in
+ if b = 0 then (
+ add_nat_off_digit l res i;
+ mult_digit_nat_off l resmult x i;
+ ) else (
+ if l = 0 then (
+ add_nat_off_digit l res 1;
+ mult_digit_nat_off l resmult x 1;
) else (
- xmult.(l-1) <- i * (1 lsl (max_int_length - b));
- );
- add_nat res xmult;
- mult_nat resmult xmult x;
- sub_nat cur resmult;
- div_subs (shrink cur) in
- div_subs (shrink n);
- for i = 0 to (length n) - 1 do n.(i) <- res.(i) done
+ let d = i * (1 lsl (max_int_length - b)) in
+ add_nat_off_digit (l-1) res d;
+ mult_digit_nat_off (l-1) resmult x d;
+ )
+ );
+ sub_nat cur resmult;
+ fill resmult 0 ln 0;
+ div_subs cur in
+ div_subs n;
+ res
- let mod_nat a b = (* a-(b*[a/b]) *)
- let div = copy a in
- div_nat div b;
- let prod = make (length a) 0 in
- mult_nat prod div b;
- let res = copy a in
- sub_nat res prod;
- res
+(* After div, n contains
+ - in the (length x) least significant digits, the remainder
+ - in the (length n)-(length x) most significant digits, the quotient *)
+let div_nat n x =
+ let ln = num_digits_nat n in
+ let lnplus = if ln = length n then ln else ln+1 in
+ let quo, lx = div_nat_fn ln n x, length x in
+ for i = lx to lnplus - 1 do
+ n.(i) <- quo.(i - lx)
+ done
+
+let gcd_nat a b = (* set a := gcd a b, return the length *)
+ let rec gcd_n a b = if num_digits_nat b = 0 then a else (
+ ignore (div_nat_fn (num_digits_nat a) a b); gcd_n b a) in
+ let res = gcd_n a (copy b) in
+ blit res 0 a 0 (min (length res) (length a));
+ num_digits_nat a
- let rec gcd_nat_fn a b =
- if compare_nat a b < 0 then gcd_nat_fn b a else
- if num_digits_nat b = 0 then a else gcd_nat_fn b (mod_nat a b)
+let shrink ?max n =
+ let nd = num_digits_nat n in
+ let m = match max with None -> nd | Some m -> min m nd in
+ if m = length n then n else
+ if m = 0 then make 1 0 else let res = make m 0 in blit n 0 res 0 m; res
- let gcd_nat a b = (* set a := gcd a b, return length of a *)
- let res = shrink (gcd_nat_fn a b) in
- fill a 0 (length a) 0;
- blit res 0 a 0 (length res);
- length res
+let rec power_base_int n i = (* n ^ i *)
+ if i < 0 then invalid_arg "negative power" else
+ if i = 0 then make 1 1 else if i = 1 then make 1 n else
+ let r = power_base_int n (i / 2) in
+ let rsq = make (2 * (length r)) 0 in
+ mult_nat rsq r r;
+ if i mod 2 = 0 then shrink rsq else
+ let m = make (2 * (length r) + 1) 0 in
+ (mult_nat m rsq (make 1 n); shrink m)
+
+let string_of_nat n =
+ let rec string_rec m =
+ let lm = length m in
+ if lm = 1 then string_of_int m.(0) else (
+ let quo = div_nat_fn (num_digits_nat m) m (make 1 max_power10_int) in
+ let s = string_rec (shrink ~max:lm quo) in
+ s ^ (sprint_full_length_int m.(0))
+ ) in
+ if num_digits_nat n = 0 then "0" else string_rec (copy (shrink n))
- let rec power_base_int n i = (* n ^ i *)
- if i < 0 then invalid_arg "negative power" else
- if i = 0 then make 1 1 else if i = 1 then make 1 n else
- let r = power_base_int n (i / 2) in
- let rsq = make (2 * (length r)) 0 in
- mult_nat rsq r r;
- if i mod 2 = 0 then shrink rsq else
- let m = make (2 * (length r) + 1) 0 in
- (mult_nat m rsq (make 1 n); shrink m)
-
- let string_of_nat n =
- let rec string_rec m =
- if length m = 1 then string_of_int m.(0) else (
- let mcp, mdiv = copy m, make (length m) 0 in
- div_nat m (make 1 1000000);
- mult_nat mdiv m (make 1 1000000);
- sub_nat mcp mdiv;
- let s = string_rec (shrink m) in
- s ^ (Printf.sprintf "%.6i" mcp.(0))
- ) in
- if num_digits_nat n = 0 then "0" else string_rec (copy (shrink n))
-
- let max_int_str_len = String.length (string_of_int max_int)
- let rec nat_of_string s ofs len =
+let max_int_str_len = String.length (string_of_int max_int)
+let rec nat_of_string s ofs len =
+ try
if len < max_int_str_len then
make 1 (int_of_string (String.sub s ofs len))
else (
@@ -208,54 +232,4 @@
add_nat res n;
res
)
-end)
-ELSE
-module N = (struct
- type nat = Nat.nat * int (* store number size *)
-
- let create_nat s = (Nat.create_nat s, s)
- let set_to_zero_nat (s, l) i1 i2 = Nat.set_to_zero_nat s i1 i2
- let make_nat len =
- if len < 0 then invalid_arg "make_nat" else
- let res = create_nat len in set_to_zero_nat res 0 len; res
-
- let blit_nat (n1, l1) i1 (n2, l2) i2 i3 = Nat.blit_nat n1 i1 n2 i2 i3
- let copy_nat nat offset length =
- let res = create_nat (length) in
- blit_nat res 0 nat offset length;
- res
-
- let set_digit_nat (n, l) d x = Nat.set_digit_nat n d x
- let num_digits_nat (n, l) =
- Nat.num_digits_nat n 0 (Nat.length_nat n)
-
- let is_zero_nat (n, _) i1 i2 = Nat.is_zero_nat n i1 i2
- let int_of_nat (n, l) = Nat.int_of_nat n
- let nat_of_int i = (Nat.nat_of_int i, 1)
- let incr_nat (n, l) = ignore (Nat.incr_nat n 0 l 1)
-
- let add_nat (n, ln) (x, lx) =
- ignore (Nat.add_nat n 0 ln x 0 lx 0)
-
- let sub_nat (n, ln) (x, lx) = ignore (Nat.sub_nat n 0 ln x 0 lx 1)
-
- let mult_digit_nat (n, ln) (x, lx) i =
- ignore (Nat.mult_digit_nat n 0 ln x 0 lx (Nat.nat_of_int i) 0)
-
- let mult_nat (n, ln) (x1, l1) (x2, l2) =
- ignore (Nat.mult_nat n 0 ln x1 0 l1 x2 0 l2)
-
- let div_nat (n, ln) (x, lx) = Nat.div_nat n 0 ln x 0 lx
-
- let compare_nat (n, ln) (m, lm) = Nat.compare_nat n 0 ln m 0 lm
- let gcd_nat (n, ln) (m, lm) = Nat.gcd_nat n 0 ln m 0 lm
- let string_of_nat (n, _) = Nat.string_of_nat n
- let nat_of_string s ofs len =
- let n = Nat.sys_nat_of_string 10 s ofs len in
- (n, Nat.num_digits_nat n 0 (Nat.length_nat n))
-
- let power_base_int i j =
- let n = Nat.power_base_int i j in
- (n, Nat.num_digits_nat n 0 (Nat.length_nat n))
-end)
-ENDIF
+ with Failure s -> failwith "invalid digit"
Modified: trunk/Toss/Solver/Num/NaturalsTest.ml
===================================================================
--- trunk/Toss/Solver/Num/NaturalsTest.ml 2012-02-17 02:36:56 UTC (rev 1676)
+++ trunk/Toss/Solver/Num/NaturalsTest.ml 2012-02-18 02:07:02 UTC (rev 1677)
@@ -1,5 +1,5 @@
open OUnit
-open Naturals.N
+open Naturals
let eq_bool (b1, b2) = assert_equal ~printer:string_of_bool b2 b1
let eq_int (i1, i2) = assert_equal ~printer:string_of_int i2 i1
@@ -42,11 +42,12 @@
incr_nat n;
equal_nat (n, nat_of_int 2);
- (*let n = create_nat 2 in
+ let n = create_nat 2 in
set_digit_nat n 0 max_int;
+ set_digit_nat n 1 0;
incr_nat n;
sub_nat n (nat_of_int 2);
- equal_nat (n, nat_of_int (max_int - 1));*)
+ equal_nat (n, nat_of_int (max_int - 1));
);
"is_zero_nat" >::
Modified: trunk/Toss/Solver/Num/NumbersTest.ml
===================================================================
--- trunk/Toss/Solver/Num/NumbersTest.ml 2012-02-17 02:36:56 UTC (rev 1676)
+++ trunk/Toss/Solver/Num/NumbersTest.ml 2012-02-18 02:07:02 UTC (rev 1677)
@@ -17,7 +17,51 @@
let biggest_int = monster_int - 1
let least_int = - biggest_int
+let pi_digits n_digits =
+ (* Pi digits computed with the streaming algorithm given on pages 4, 6
+ & 7 of "Unbounded Spigot Algorithms for the Digits of Pi", Jeremy
+ Gibbons, August 2004. *)
+ let zero = num_of_int 0
+ and one = num_of_int 1
+ and three = num_of_int 3
+ and four = num_of_int 4
+ and ten = num_of_int 10
+ and neg_ten = num_of_int (-10) in
+ (* Linear Fractional (aka Moebius) Transformations *)
+ let floor_ev (q, r, s, t) x = quo_num (q */ x +/ r) (s */ x +/ t) in
+ let unit = (one, zero, zero, one) in
+ 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') in
+
+ let next z = floor_ev z three in
+ let safe z n = (n =/ (floor_ev z four)) in
+ let prod z n = comp (ten, neg_ten */ n, zero, one) z in
+ let cons z k =
+ let den = 2 * k + 1 in
+ comp z (num_of_int k, num_of_int (2 * den), zero, num_of_int den) in
+
+ let rec digit k z n row col acc =
+ if n > 0 then
+ let y = next z in
+ if safe z y then
+ if col = 10 then (
+ let row = row + 10 in
+ digit k (prod z y) (n - 1) row 1
+ ((Printf.sprintf "\t:%i\n%s" row (string_of_num y)) :: acc)
+ ) else (
+ digit k (prod z y) (n - 1) row (col + 1)
+ ((string_of_num y) :: acc)
+ )
+ else digit (k + 1) (cons z k) n row col acc
+ else
+ (Printf.sprintf "%*s\t:%i\n" (10 - col) "" (row + col)) :: acc in
+
+ let digits n = digit 1 unit n 0 0 [] in
+ String.concat "" (List.rev (digits n_digits))
+
+
let tests = "Numbers" >::: [
"add_num" >::
(fun () ->
@@ -134,51 +178,16 @@
failwith_test num_of_string ("frlshjkurty") (Failure "num_of_string");
);
- "pi digits" >::
+ "pi 100 digits" >::
(fun () ->
- (* Pi digits computed with the streaming algorithm given on pages 4, 6
- & 7 of "Unbounded Spigot Algorithms for the Digits of Pi", Jeremy
- Gibbons, August 2004. *)
- let zero = num_of_int 0
- and one = num_of_int 1
- and three = num_of_int 3
- and four = num_of_int 4
- and ten = num_of_int 10
- and neg_ten = num_of_int (-10) in
+ eq_string (pi_digits 100, IntegersTest.pi_100_digits);
+ );
+]
- (* Linear Fractional (aka Moebius) Transformations *)
- let floor_ev (q, r, s, t) x = quo_num (q */ x +/ r) (s */ x +/ t) in
- let unit = (one, zero, zero, one) in
- 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') in
-
- let next z = floor_ev z three in
- let safe z n = (n =/ (floor_ev z four)) in
- let prod z n = comp (ten, neg_ten */ n, zero, one) z in
- let cons z k =
- let den = 2 * k + 1 in
- comp z (num_of_int k, num_of_int (2 * den), zero, num_of_int den) in
-
- let rec digit k z n row col acc =
- if n > 0 then
- let y = next z in
- if safe z y then
- if col = 10 then (
- let row = row + 10 in
- digit k (prod z y) (n - 1) row 1
- ((Printf.sprintf "\t:%i\n%s" row (string_of_num y)) :: acc)
- ) else (
- digit k (prod z y) (n - 1) row (col + 1)
- ((string_of_num y) :: acc)
- )
- else digit (k + 1) (cons z k) n row col acc
- else
- (Printf.sprintf "%*s\t:%i\n" (10 - col) "" (row + col)) :: acc in
-
- let digits n = digit 1 unit n 0 0 [] in
- eq_string (String.concat "" (List.rev (digits 1000)),
- IntegersTest.pi_1000_digits);
+let bigtests = "NumbersBig" >::: [
+ "pi 1000 digits" >::
+ (fun () ->
+ eq_string (pi_digits 1000, IntegersTest.pi_1000_digits);
);
]
Modified: trunk/Toss/Solver/Num/Rationals.ml
===================================================================
--- trunk/Toss/Solver/Num/Rationals.ml 2012-02-17 02:36:56 UTC (rev 1676)
+++ trunk/Toss/Solver/Num/Rationals.ml 2012-02-18 02:07:02 UTC (rev 1677)
@@ -401,7 +401,7 @@
s1 contains one more digit than desired for the round off operation *)
if n >= 0 then begin
let s1 =
- Naturals.N.string_of_nat
+ Naturals.string_of_nat
(nat_of_big_int
(div_big_int
(base_power_big_int
@@ -478,7 +478,7 @@
div_big_int (base_power_big_int
10 k (abs_big_int r.numerator))
r.denominator) in
- Naturals.N.string_of_nat nat) in
+ Naturals.string_of_nat nat) in
if (round_futur_last_digit s 0 (String.length s))
then
let m = num_decimal_digits_int (succ msd) in
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|