summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--otherlibs/num/Makefile75
-rw-r--r--otherlibs/num/README64
-rw-r--r--otherlibs/num/arith_flags.ml23
-rw-r--r--otherlibs/num/arith_flags.mli18
-rw-r--r--otherlibs/num/arith_status.ml98
-rw-r--r--otherlibs/num/arith_status.mli49
-rw-r--r--otherlibs/num/big_int.ml594
-rw-r--r--otherlibs/num/big_int.mli64
-rw-r--r--otherlibs/num/bignum/Makefile335
-rw-r--r--otherlibs/num/bignum/README97
-rw-r--r--otherlibs/num/bignum/c/KerN.c932
-rw-r--r--otherlibs/num/bignum/c/bn/bnCmp.c77
-rw-r--r--otherlibs/num/bignum/c/bn/bnDivide.c156
-rw-r--r--otherlibs/num/bignum/c/bn/bnInit.c74
-rw-r--r--otherlibs/num/bignum/c/bn/bnMult.c84
-rw-r--r--otherlibs/num/bignum/c/bz.c833
-rw-r--r--otherlibs/num/bignum/c/bzf.c50
-rw-r--r--otherlibs/num/bignum/c/bztest.c167
-rw-r--r--otherlibs/num/bignum/c/testKerN.c1085
-rw-r--r--otherlibs/num/bignum/h/BigNum.h144
-rw-r--r--otherlibs/num/bignum/h/BigZ.h97
-rw-r--r--otherlibs/num/bignum/h/BntoBnn.h111
-rw-r--r--otherlibs/num/bignum/s/68KerN.s403
-rw-r--r--otherlibs/num/bignum/s/68KerN_mot.s410
-rw-r--r--otherlibs/num/bignum/s/68KerN_sony.s426
-rw-r--r--otherlibs/num/bignum/s/RS6000KerN.s468
-rw-r--r--otherlibs/num/bignum/s/alphaKerN.s2511
-rw-r--r--otherlibs/num/bignum/s/hpKerN.s814
-rw-r--r--otherlibs/num/bignum/s/i960KerN.s928
-rw-r--r--otherlibs/num/bignum/s/mipsKerN.s1382
-rw-r--r--otherlibs/num/bignum/s/nsKerN.s427
-rw-r--r--otherlibs/num/bignum/s/pyramidKerN.s454
-rw-r--r--otherlibs/num/bignum/s/sparcKerN.s643
-rw-r--r--otherlibs/num/bignum/s/sparcfpuKerN.s741
-rw-r--r--otherlibs/num/bignum/s/supersparcKerN.s469
-rw-r--r--otherlibs/num/bignum/s/unix2vms.sed28
-rw-r--r--otherlibs/num/bignum/s/vaxKerN.mar701
-rw-r--r--otherlibs/num/bignum/s/vaxKerN.s700
-rw-r--r--otherlibs/num/int_misc.mli23
-rw-r--r--otherlibs/num/int_misc.mlp41
-rw-r--r--otherlibs/num/nat.mli70
-rw-r--r--otherlibs/num/nat.mlp527
-rw-r--r--otherlibs/num/num.ml398
-rw-r--r--otherlibs/num/num.mli120
-rw-r--r--otherlibs/num/ratio.ml567
-rw-r--r--otherlibs/num/ratio.mli86
-rw-r--r--otherlibs/num/string_misc.ml18
-rw-r--r--otherlibs/num/string_misc.mli14
-rw-r--r--otherlibs/num/test/Makefile36
-rw-r--r--otherlibs/num/test/end_test.ml8
-rw-r--r--otherlibs/num/test/test.ml60
-rw-r--r--otherlibs/num/test/test_big_ints.ml365
-rw-r--r--otherlibs/num/test/test_nats.ml127
-rw-r--r--otherlibs/num/test/test_nums.ml220
-rw-r--r--otherlibs/num/test/test_ratios.ml928
55 files changed, 20340 insertions, 0 deletions
diff --git a/otherlibs/num/Makefile b/otherlibs/num/Makefile
new file mode 100644
index 000000000..eaa3270cc
--- /dev/null
+++ b/otherlibs/num/Makefile
@@ -0,0 +1,75 @@
+# Makefile for the "num" (exact rational arithmetic) library
+
+include ../../Makefile.config
+
+# Compilation options
+CC=$(BYTECC)
+CFLAGS=-O -I./bignum/h -I../../byterun $(BYTECCCOMPOPTS)
+CAMLC=../../boot/cslrun ../../boot/cslc -I ../../boot
+CAMLOPT=../../boot/cslrun ../../cslopt -I ../../stdlib
+
+CAMLOBJS=int_misc.cmo string_misc.cmo nat.cmo big_int.cmo arith_flags.cmo \
+ ratio.cmo num.cmo arith_status.cmo
+
+CAMLINTF=big_int.cmi nat.cmi num.cmi ratio.cmi arith_status.cmi
+
+COBJS=nat_stubs.o
+
+all: libnums.a nums.cma $(CMIFILES)
+
+allopt: libnums.a nums.cmxa $(CMIFILES)
+
+nums.cma: $(CAMLOBJS)
+ $(CAMLC) -a -o nums.cma $(CAMLOBJS)
+
+nums.cmxa: $(CAMLOBJS:.cmo=.cmx)
+ $(CAMLOPT) -a -o nums.cmxa $(CAMLOBJS:.cmo=.cmx)
+
+libnums.a: bignum/libbignum.a $(COBJS)
+ cp bignum/libbignum.a libnums.a
+ ar r libnums.a $(COBJS)
+ $(RANLIB) libnums.a
+
+bignum/libbignum.a:
+ cd bignum; make $(BIGNUM_ARCH) CC="$(CC)"
+
+install:
+ cp libnums.a $(LIBDIR)/libnums.a
+ cd $(LIBDIR); $(RANLIB) libnums.a
+ cp nums.cma $(CMIFILES) $(LIBDIR)
+
+installopt:
+ cp nums.cmxa nums.a $(LIBDIR)
+ cd $(LIBDIR); $(RANLIB) nums.a
+
+clean:
+ rm -f *.a *.o *.cm*
+ rm -f nat.ml int_misc.ml
+ cd bignum; make scratch
+ cd test; make clean
+
+.SUFFIXES: .ml .mli .mlp .cmi .cmo .cmx
+
+.mli.cmi:
+ $(CAMLC) -c $(COMPFLAGS) $<
+
+.ml.cmo:
+ $(CAMLC) -c $(COMPFLAGS) $<
+
+.ml.cmx:
+ $(CAMLOPT) -c $(COMPFLAGS) $<
+
+.mlp.ml:
+ @rm -f $@
+ $(CPP) $< > $@
+ @chmod a-w $@
+
+int_misc.ml: int_misc.mlp
+nat.ml: nat.mlp
+nat_stubs.o: nat.h
+
+depend: nat.ml int_misc.ml
+ gcc -MM $(CFLAGS) *.c > .depend
+ ../../tools/csldep *.mli *.ml >> .depend
+
+include .depend
diff --git a/otherlibs/num/README b/otherlibs/num/README
new file mode 100644
index 000000000..e7f432591
--- /dev/null
+++ b/otherlibs/num/README
@@ -0,0 +1,64 @@
+The "libnum" library implements exact-precision rational arithmetic.
+It is built upon the state-of-the-art BigNum arbitrary-precision
+integer arithmetic package, and therefore achieves very high
+performance (it's faster than Maple, for instance).
+
+This library is derived from Valerie Menissie-Morain's implementation
+of rational arithmetic for Caml V3.1 (INRIA), and builds on the BigNum
+package developed by Bernard Serpette, Jean Vuillemin and Jean-Claude
+Herve (INRIA and Digital PRL). Xavier Leroy (INRIA) did the Caml Light
+port. Victor Manuel Gulias Fernandez did the Caml Special Light port.
+
+This library is documented in "The CAML Numbers Reference Manual" by
+Valerie Menissier-Morain, technical report 141, INRIA, july 1992,
+available by anonymous FTP from ftp.inria.fr, directory
+INRIA/publications/RT, file RT-0141.ps.Z.
+
+USAGE:
+
+To use the bignum library from your programs, just do
+
+ cslc -custom <other options> nums.cma <other .cmo and .ml files> -lnums
+
+for the linking phase.
+
+If you'd like to have the bignum functions available at toplevel, do
+
+ cslmktop -o csltopnum -custom <other options> nums.cma <other .cmo and .ml files> -lnums
+ ./csltopnum
+
+As an example, try:
+
+ open Num;;
+ let rec fact n =
+ if n = 0 then Int 1 else mult_num (num_of_int n) (fact(n-1));;
+ string_of_num(fact 1000);;
+
+KNOWN TARGET ARCHITECTURES:
+
+ C portable C version (default)
+ sparc Sparc V8 assembly code, SunOS 4.1
+ sparc-solaris Sparc V8 assembly code, Solaris 2
+ supersparc Sparc V9 assembly code, SunOS 4.1
+ supersparc-solaris Sparc V9 assembly code, Solaris 2
+ mips MIPS R2000, R3000, R4000 assembly code
+ alpha DEC Alpha (21064) assembly code
+ 68K Motorola 68020 assembly code
+ vax DEC VAX assembly code
+ i960 Intel 80960A assembly code
+ ns National Semiconductors 32032 assembly code
+ pyramid Pyramid minicomputers assembly code
+
+LEGAL NOTICE:
+
+This work uses the BigNum package developed jointly by INRIA and Digital PRL.
+
+The code in the bignum/ subdirectory is copyright INRIA and Digital,
+and may be reproduced and distributed freely to non commercial usage
+according to the conditions stated in the documentation of this package
+(directory bignum/doc).
+
+KNOWN PROBLEMS:
+
+64-bit architectures are not yet fully supported. The test suite passes on
+a Dec Alpha, but some bugs remain.
diff --git a/otherlibs/num/arith_flags.ml b/otherlibs/num/arith_flags.ml
new file mode 100644
index 000000000..e9d9fb035
--- /dev/null
+++ b/otherlibs/num/arith_flags.ml
@@ -0,0 +1,23 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+let error_when_null_denominator_flag = ref true;;
+
+let normalize_ratio_flag = ref false;;
+
+let normalize_ratio_when_printing_flag = ref true;;
+
+let floating_precision = ref 12;;
+
+let approx_printing_flag = ref false;;
+
diff --git a/otherlibs/num/arith_flags.mli b/otherlibs/num/arith_flags.mli
new file mode 100644
index 000000000..948a8438e
--- /dev/null
+++ b/otherlibs/num/arith_flags.mli
@@ -0,0 +1,18 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+val error_when_null_denominator_flag : bool ref
+val normalize_ratio_flag : bool ref
+val normalize_ratio_when_printing_flag : bool ref
+val floating_precision : int ref
+val approx_printing_flag : bool ref;;
diff --git a/otherlibs/num/arith_status.ml b/otherlibs/num/arith_status.ml
new file mode 100644
index 000000000..e98e3f82c
--- /dev/null
+++ b/otherlibs/num/arith_status.ml
@@ -0,0 +1,98 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Arith_flags;;
+
+let get_error_when_null_denominator () =
+ !error_when_null_denominator_flag
+and set_error_when_null_denominator choice =
+ error_when_null_denominator_flag := choice;;
+
+let get_normalize_ratio () = !normalize_ratio_flag
+and set_normalize_ratio choice = normalize_ratio_flag := choice;;
+
+let get_normalize_ratio_when_printing () =
+ !normalize_ratio_when_printing_flag
+and set_normalize_ratio_when_printing choice =
+ normalize_ratio_when_printing_flag := choice;;
+
+let get_floating_precision () = !floating_precision
+and set_floating_precision i = floating_precision := i;;
+
+let get_approx_printing () = !approx_printing_flag
+and set_approx_printing b = approx_printing_flag := b;;
+
+let arith_print_string s = print_string s; print_string " --> ";;
+
+let arith_print_bool = function
+ true -> print_string "ON"
+| _ -> print_string "OFF"
+;;
+
+let arith_status () =
+ print_newline ();
+
+ arith_print_string
+ "Normalization during computation";
+ arith_print_bool (get_normalize_ratio ());
+ print_newline ();
+ print_string " (returned by get_normalize_ratio ())";
+ print_newline ();
+ print_string " (modifiable with set_normalize_ratio <your choice>)";
+ print_newline ();
+ print_newline ();
+
+ arith_print_string
+ "Normalization when printing";
+ arith_print_bool (get_normalize_ratio_when_printing ());
+ print_newline ();
+ print_string
+ " (returned by get_normalize_ratio_when_printing ())";
+ print_newline ();
+ print_string
+ " (modifiable with set_normalize_ratio_when_printing <your choice>)";
+ print_newline ();
+ print_newline ();
+
+ arith_print_string
+ "Floating point approximation when printing rational numbers";
+ arith_print_bool (get_approx_printing ());
+ print_newline ();
+ print_string
+ " (returned by get_approx_printing ())";
+ print_newline ();
+ print_string
+ " (modifiable with set_approx_printing <your choice>)";
+ print_newline ();
+ (if (get_approx_printing ())
+ then (print_string " Default precision = ";
+ print_int (get_floating_precision ());
+ print_newline ();
+ print_string " (returned by get_floating_precision ())";
+ print_newline ();
+ print_string
+ " (modifiable with set_floating_precision <your choice>)";
+ print_newline ();
+ print_newline ())
+ else print_newline());
+
+ arith_print_string
+ "Error when a rational denominator is null";
+ arith_print_bool (get_error_when_null_denominator ());
+ print_newline ();
+ print_string " (returned by get_error_when_null_denominator ())";
+ print_newline ();
+ print_string
+ " (modifiable with set_error_when_null_denominator <your choice>)";
+ print_newline ()
+;;
diff --git a/otherlibs/num/arith_status.mli b/otherlibs/num/arith_status.mli
new file mode 100644
index 000000000..c0b7f878f
--- /dev/null
+++ b/otherlibs/num/arith_status.mli
@@ -0,0 +1,49 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Module [Arith_status]: flags that control rational arithmetic *)
+
+val arith_status: unit -> unit;;
+ (* Print the current status of the arithmetic flags. *)
+
+val get_error_when_null_denominator : unit -> bool
+val set_error_when_null_denominator : bool -> unit
+ (* Get or set the flag [null_denominator]. When on, attempting to
+ create a rational with a null denominator raises an exception.
+ When off, rationals with null denominators are accepted.
+ Initially: on. *)
+val get_normalize_ratio : unit -> bool
+val set_normalize_ratio : bool -> unit
+ (* Get or set the flag [normalize_ratio]. When on, rational
+ numbers are normalized after each operation. When off,
+ rational numbers are not normalized until printed.
+ Initially: off. *)
+val get_normalize_ratio_when_printing : unit -> bool
+val set_normalize_ratio_when_printing : bool -> unit
+ (* Get or set the flag [normalize_ratio_when_printing].
+ When on, rational numbers are normalized before being printed.
+ When off, rational numbers are printed as is, without normalization.
+ Initially: on. *)
+val get_approx_printing : unit -> bool
+val set_approx_printing : bool -> unit
+ (* Get or set the flag [approx_printing].
+ When on, rational numbers are printed as a decimal approximation.
+ When off, rational numbers are printed as a fraction.
+ Initially: off. *)
+val get_floating_precision : unit -> int
+val set_floating_precision : int -> unit
+ (* Get or set the parameter [floating_precision].
+ This parameter is the number of digits displayed when
+ [approx_printing] is on.
+ Initially: 12. *)
+;;
diff --git a/otherlibs/num/big_int.ml b/otherlibs/num/big_int.ml
new file mode 100644
index 000000000..81ff44278
--- /dev/null
+++ b/otherlibs/num/big_int.ml
@@ -0,0 +1,594 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Int_misc
+open Nat
+
+type big_int =
+ { sign : int;
+ abs_value : nat }
+
+let create_big_int sign nat =
+ if sign = 1 or sign = -1 or
+ (sign = 0 &
+ is_zero_nat nat 0 (num_digits_nat nat 0 (length_nat nat)))
+ then { sign = sign;
+ abs_value = nat }
+ else invalid_arg "create_big_int"
+
+(* Sign of a big_int *)
+let sign_big_int bi = bi.sign
+
+let zero_big_int =
+ { sign = 0;
+ abs_value = make_nat 1 }
+
+let unit_big_int =
+ { sign = 1;
+ abs_value = nat_of_int 1 }
+
+(* Number of digits in a big_int *)
+let num_digits_big_int bi =
+ num_digits_nat (bi.abs_value) 0 (length_nat bi.abs_value)
+
+(* Opposite of a big_int *)
+let minus_big_int bi =
+ { sign = - bi.sign;
+ abs_value = copy_nat (bi.abs_value) 0 (num_digits_big_int bi)}
+
+(* Absolute value of a big_int *)
+let abs_big_int bi =
+ { sign = if bi.sign = 0 then 0 else 1;
+ abs_value = copy_nat (bi.abs_value) 0 (num_digits_big_int bi)}
+
+(* Comparison operators on big_int *)
+
+(*
+ compare_big_int (bi, bi2) = sign of (bi-bi2)
+ i.e. 1 if bi > bi2
+ 0 if bi = bi2
+ -1 if bi < bi2
+*)
+let compare_big_int bi1 bi2 =
+ if bi1.sign = 0 & bi2.sign = 0 then 0
+ else if bi1.sign < bi2.sign then -1
+ else if bi1.sign > bi2.sign then 1
+ else if bi1.sign = 1 then
+ compare_nat (bi1.abs_value) 0 (num_digits_big_int bi1)
+ (bi2.abs_value) 0 (num_digits_big_int bi2)
+ else
+ compare_nat (bi2.abs_value) 0 (num_digits_big_int bi2)
+ (bi1.abs_value) 0 (num_digits_big_int bi1)
+
+let eq_big_int bi1 bi2 = compare_big_int bi1 bi2 = 0
+and le_big_int bi1 bi2 = compare_big_int bi1 bi2 <= 0
+and ge_big_int bi1 bi2 = compare_big_int bi1 bi2 >= 0
+and lt_big_int bi1 bi2 = compare_big_int bi1 bi2 < 0
+and gt_big_int bi1 bi2 = compare_big_int bi1 bi2 > 0
+
+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
+
+(* Operations on big_int *)
+
+let pred_big_int bi =
+ match bi.sign with
+ 0 -> { sign = -1; abs_value = nat_of_int 1}
+ | 1 -> let size_bi = num_digits_big_int bi in
+ let copy_bi = copy_nat (bi.abs_value) 0 size_bi in
+ decr_nat copy_bi 0 size_bi 0;
+ { sign = if is_zero_nat copy_bi 0 size_bi then 0 else 1;
+ abs_value = copy_bi }
+ | _ -> let size_bi = num_digits_big_int bi in
+ let size_res = succ (size_bi) in
+ let copy_bi = create_nat (size_res) in
+ blit_nat copy_bi 0 (bi.abs_value) 0 size_bi;
+ set_digit_nat copy_bi size_bi 0;
+ incr_nat copy_bi 0 size_res 1;
+ { sign = -1;
+ abs_value = copy_bi }
+
+let succ_big_int bi =
+ match bi.sign with
+ 0 -> {sign = 1; abs_value = nat_of_int 1}
+ | -1 -> let size_bi = num_digits_big_int bi in
+ let copy_bi = copy_nat (bi.abs_value) 0 size_bi in
+ decr_nat copy_bi 0 size_bi 0;
+ { sign = if is_zero_nat copy_bi 0 size_bi then 0 else -1;
+ abs_value = copy_bi }
+ | _ -> let size_bi = num_digits_big_int bi in
+ let size_res = succ (size_bi) in
+ let copy_bi = create_nat (size_res) in
+ blit_nat copy_bi 0 (bi.abs_value) 0 size_bi;
+ set_digit_nat copy_bi size_bi 0;
+ incr_nat copy_bi 0 size_res 1;
+ { sign = 1;
+ abs_value = copy_bi }
+
+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 *)
+ { sign = bi1.sign;
+ abs_value =
+ match compare_nat (bi1.abs_value) 0 size_bi1
+ (bi2.abs_value) 0 size_bi2 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 0 (succ size_bi2)
+ (bi1.abs_value) 0 size_bi1 0;
+ 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 0 (succ size_bi1)
+ (bi2.abs_value) 0 size_bi2 0;
+ res)}
+
+ else (* Subtract absolute values if signs are different *)
+ match compare_nat (bi1.abs_value) 0 size_bi1
+ (bi2.abs_value) 0 size_bi2 with
+ 0 -> zero_big_int
+ | 1 -> { sign = bi1.sign;
+ abs_value =
+ let res = copy_nat (bi1.abs_value) 0 size_bi1 in
+ (sub_nat res 0 size_bi1
+ (bi2.abs_value) 0 size_bi2 1;
+ res) }
+ | _ -> { sign = bi2.sign;
+ abs_value =
+ let res = copy_nat (bi2.abs_value) 0 size_bi2 in
+ (sub_nat res 0 size_bi2
+ (bi1.abs_value) 0 size_bi1 1;
+ res) }
+
+(* Coercion with int type *)
+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 0 1 1; ())
+ else set_digit_nat res 0 (abs i));
+ res }
+
+let add_int_big_int i bi = add_big_int (big_int_of_int i) bi
+
+let sub_big_int bi1 bi2 = add_big_int bi1 (minus_big_int bi2)
+
+(* Returns i * bi *)
+let mult_int_big_int i bi =
+ let size_bi = num_digits_big_int bi in
+ let size_res = succ size_bi in
+ if i = monster_int
+ then let res = create_nat size_res in
+ blit_nat res 0 (bi.abs_value) 0 size_bi;
+ mult_digit_nat res 0 size_res (bi.abs_value) 0 size_bi
+ (nat_of_int biggest_int) 0;
+ { sign = - (sign_big_int bi);
+ abs_value = res }
+ else let res = make_nat (size_res) in
+ mult_digit_nat res 0 size_res (bi.abs_value) 0 size_bi
+ (nat_of_int (abs i)) 0;
+ { sign = (sign_int i) * (sign_big_int bi);
+ 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
+ { sign = bi1.sign * bi2.sign;
+ abs_value =
+ if size_bi2 > size_bi1
+ then (mult_nat res 0 size_res (bi2.abs_value) 0 size_bi2
+ (bi1.abs_value) 0 size_bi1;res)
+ else (mult_nat res 0 size_res (bi1.abs_value) 0 size_bi1
+ (bi2.abs_value) 0 size_bi2;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) 0 size_bi1
+ (bi2.abs_value) 0 size_bi2 with
+ -1 -> (* 1/2 -> 0, reste 1, -1/2 -> -1, reste 1 *)
+ if bi1.sign = -1
+ then (big_int_of_int(-1), add_big_int bi2 bi1)
+ else (big_int_of_int 0, bi1)
+ | 0 -> (big_int_of_int (bi1.sign * bi2.sign), zero_big_int)
+ | _ -> let bi1_negatif = bi1.sign = -1 in
+ let size_q =
+ if bi1_negatif
+ then succ (max (succ (size_bi1 - size_bi2)) 1)
+ else max (succ (size_bi1 - size_bi2)) 1
+ and size_r = succ (max size_bi1 size_bi2)
+ (* r is long enough to contain both quotient and remainder *)
+ (* of the euclidian division *)
+ in
+ (* set up quotient, remainder *)
+ let q = create_nat size_q
+ and r = create_nat size_r in
+ blit_nat r 0 (bi1.abs_value) 0 size_bi1;
+ set_to_zero_nat r size_bi1 (size_r - size_bi1);
+
+ (* do the division of |bi1| by |bi2|
+ - at the beginning, r contains |bi1|
+ - at the end, r contains
+ * in the size_bi2 least significant digits, the remainder
+ * in the size_r-size_bi2 most significant digits, the quotient
+ note the conditions for application of div_nat are verified here
+ *)
+ div_nat r 0 size_r (bi2.abs_value) 0 size_bi2;
+
+ (* separate quotient and remainder *)
+ blit_nat q 0 r size_bi2 (size_r - size_bi2);
+ let not_null_mod = not (is_zero_nat r 0 size_bi2) in
+
+ (* correct the signs, adjusting the quotient and remainder *)
+ if bi1_negatif & not_null_mod
+ then
+ (* bi1<0, r>0, noting r for (r, size_bi2) the remainder, *)
+ (* we have |bi1|=q * |bi2| + r with 0 < r < |bi2|, *)
+ (* thus -bi1 = q * |bi2| + r *)
+ (* and bi1 = (-q) * |bi2| + (-r) with -|bi2| < (-r) < 0 *)
+ (* thus bi1 = -(q+1) * |bi2| + (|bi2|-r) *)
+ (* with 0 < (|bi2|-r) < |bi2| *)
+ (* so the quotient has for sign the opposite of the bi2'one *)
+ (* and for value q+1 *)
+ (* and the remainder is strictly positive *)
+ (* has for value |bi2|-r *)
+ (let new_r = copy_nat (bi2.abs_value) 0 size_bi2 in
+ (* new_r contains (r, size_bi2) the remainder *)
+ { sign = - bi2.sign;
+ abs_value = (set_digit_nat q (pred size_q) 0;
+ incr_nat q 0 size_q 1; q) },
+ { sign = 1;
+ abs_value =
+ (sub_nat new_r 0 size_bi2 r 0 size_bi2 1;
+ new_r) })
+ else
+ (if bi1_negatif then set_digit_nat q (pred size_q) 0;
+ { sign = if is_zero_nat q 0 size_q
+ then 0
+ else bi1.sign * bi2.sign;
+ abs_value = q },
+ { sign = if not_null_mod then 1 else 0;
+ abs_value = copy_nat r 0 size_bi2 })
+
+let div_big_int bi1 bi2 = fst (quomod_big_int bi1 bi2)
+and 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
+ 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 }
+ else
+ { sign = 1;
+ abs_value =
+ match compare_nat (bi1.abs_value) 0 size_bi1
+ (bi2.abs_value) 0 size_bi2 with
+ 0 -> bi1.abs_value
+ | 1 ->
+ let res = copy_nat (bi1.abs_value) 0 size_bi1 in
+ let len =
+ gcd_nat res 0 size_bi1 (bi2.abs_value) 0 size_bi2 in
+ copy_nat res 0 len
+ | _ ->
+ let res = copy_nat (bi2.abs_value) 0 size_bi2 in
+ let len =
+ gcd_nat res 0 size_bi2 (bi1.abs_value) 0 size_bi1 in
+ copy_nat res 0 len
+ }
+
+(* Coercion operators *)
+
+let int_of_big_int bi =
+ try bi.sign * int_of_nat bi.abs_value
+ with Failure _ ->
+ if eq_big_int bi (big_int_of_int monster_int)
+ then monster_int
+ else failwith "int_of_big_int"
+
+let is_int_big_int bi =
+ is_nat_int (bi.abs_value) 0 (num_digits_big_int bi)
+or (bi.sign = -1 & num_digits_big_int bi = 1 &
+ num_leading_zero_bits_in_digit (bi.abs_value) 0 >= 1)
+
+(* XL: le "1" provient de "pred (length_of_digit - length_of_int))" *)
+
+(* Coercion with nat type *)
+let nat_of_big_int bi =
+ if bi.sign = -1
+ then failwith "nat_of_big_int"
+ else copy_nat (bi.abs_value) 0 (num_digits_big_int bi)
+
+let sys_big_int_of_nat nat off len =
+ let length = num_digits_nat nat off len in
+ { sign = if is_zero_nat nat off length then 0 else 1;
+ abs_value = copy_nat nat off length }
+
+let big_int_of_nat nat =
+ sys_big_int_of_nat nat 0 (length_nat nat)
+
+(* 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
+
+(* XL: j'ai puissamment simplifie "big_int_of_string", en virant
+ la notation scientifique (123e6 ou 123.456e12). *)
+
+let sys_big_int_of_string s ofs len =
+ let (sign, nat) =
+ if String.get s ofs = '-'
+ then (-1, sys_nat_of_string 10 s (ofs+1) (len-1))
+ else ( 1, sys_nat_of_string 10 s ofs len) in
+ { sign = if is_zero_nat nat 0 (length_nat nat) then 0 else sign;
+ abs_value = nat }
+
+let big_int_of_string s =
+ sys_big_int_of_string s 0 (String.length s)
+
+let power_base_nat base nat off len =
+ if is_zero_nat nat off len then nat_of_int 1 else
+ let power_base = make_nat (succ length_of_digit) in
+ let (pmax, pint) = make_power_base base power_base in
+ let (n, rem) =
+ let (x, y) = quomod_big_int (sys_big_int_of_nat nat off len)
+ (big_int_of_int (succ pmax)) in
+ (int_of_big_int x, int_of_big_int y) in
+ if n = 0 then copy_nat power_base (pred rem) 1 else
+ begin
+ let res = make_nat n
+ and res2 = make_nat n
+ and l = num_bits_int n - 2 in
+ let p = ref (1 lsl l) in
+ blit_nat res 0 power_base pmax 1;
+ for i = l downto 0 do
+ let len = num_digits_nat res 0 n in
+ let len2 = min n (2 * len) in
+ let succ_len2 = succ len2 in
+ square_nat res2 0 len2 res 0 len;
+ begin
+ if n land !p > 0
+ then (set_to_zero_nat res 0 len;
+ mult_digit_nat res 0 succ_len2
+ res2 0 len2
+ power_base pmax; ())
+ else blit_nat res 0 res2 0 len2
+ end;
+ set_to_zero_nat res2 0 len2;
+ p := !p lsr 1
+ done;
+ if rem > 0
+ then (mult_digit_nat res2 0 n
+ res 0 n power_base (pred rem);
+ res2)
+ else res
+ end
+
+let power_int_positive_int i n =
+ match sign_int n with
+ 0 -> unit_big_int
+ | -1 -> invalid_arg "power_int_positive_int"
+ | _ -> let nat = power_base_int (abs i) n in
+ { sign = if i >= 0
+ then sign_int i
+ else if n land 1 = 0
+ then 1
+ else -1;
+ abs_value = nat}
+
+let power_big_int_positive_int bi n =
+ match sign_int n with
+ 0 -> unit_big_int
+ | -1 -> invalid_arg "power_big_int_positive_int"
+ | _ -> let bi_len = num_digits_big_int bi in
+ let res_len = bi_len * n in
+ let res = make_nat res_len
+ and res2 = make_nat res_len
+ and l = num_bits_int n - 2 in
+ let p = ref (1 lsl l) in
+ blit_nat res 0 (bi.abs_value) 0 bi_len;
+ for i = l downto 0 do
+ let len = num_digits_nat res 0 res_len in
+ let len2 = min res_len (2 * len) in
+ let succ_len2 = succ len2 in
+ square_nat res2 0 len2 res 0 len;
+ (if n land !p > 0
+ then (set_to_zero_nat res 0 len;
+ mult_nat res 0 succ_len2
+ res2 0 len2 (bi.abs_value) 0 bi_len;
+ set_to_zero_nat res2 0 len2)
+ else blit_nat res 0 res2 0 len2;
+ set_to_zero_nat res2 0 len2);
+ p := !p lsr 1
+ done;
+ {sign = if bi.sign >= 0
+ then bi.sign
+ else if n land 1 = 0
+ then 1
+ else -1;
+ abs_value = res}
+
+let power_int_positive_big_int i bi =
+ match sign_big_int bi with
+ 0 -> unit_big_int
+ | -1 -> invalid_arg "power_int_positive_big_int"
+ | _ -> let nat = power_base_nat
+ (abs i) (bi.abs_value) 0 (num_digits_big_int bi) in
+ { sign = if i >= 0
+ then sign_int i
+ else if is_digit_odd (bi.abs_value) 0
+ then -1
+ else 1;
+ abs_value = nat }
+
+let power_big_int_positive_big_int bi1 bi2 =
+ match sign_big_int bi2 with
+ 0 -> unit_big_int
+ | -1 -> invalid_arg "power_big_int_positive_big_int"
+ | _ -> let nat = bi2.abs_value
+ and off = 0
+ and len_bi2 = num_digits_big_int bi2 in
+ let bi1_len = num_digits_big_int bi1 in
+ let res_len = int_of_big_int (mult_int_big_int bi1_len bi2) in
+ let res = make_nat res_len
+ and res2 = make_nat res_len
+ and l = (len_bi2 * length_of_digit
+ - num_leading_zero_bits_in_digit nat (pred len_bi2)) - 2 in
+ let p = ref (1 lsl l) in
+ blit_nat res 0 (bi1.abs_value) 0 bi1_len;
+ for i = l downto 0 do
+ let nat = bi2.abs_value in
+ let len = num_digits_nat res 0 res_len in
+ let len2 = min res_len (2 * len) in
+ let succ_len2 = succ len2 in
+ square_nat res2 0 len2 res 0 len;
+ land_digit_nat nat 0 (nat_of_int !p) 0;
+ if is_zero_nat nat 0 len_bi2
+ then (blit_nat res 0 res2 0 len2;
+ set_to_zero_nat res2 0 len2)
+ else (set_to_zero_nat res 0 len;
+ mult_nat res 0 succ_len2
+ res2 0 len2 (bi1.abs_value) 0 bi1_len;
+ set_to_zero_nat res2 0 len2);
+ p := !p lsr 1
+ done;
+ {sign = if bi1.sign >= 0
+ then bi1.sign
+ else if is_digit_odd (bi2.abs_value) 0
+ then -1
+ else 1;
+ abs_value = res}
+
+(* base_power_big_int compute bi*base^n *)
+let base_power_big_int base n bi =
+ match sign_int n with
+ 0 -> bi
+ | -1 -> let nat = power_base_int base (-n) in
+ let len_nat = num_digits_nat nat 0 (length_nat nat)
+ and len_bi = num_digits_big_int bi in
+ if len_bi < len_nat then
+ invalid_arg "base_power_big_int"
+ else if len_bi = len_nat &
+ compare_digits_nat (bi.abs_value) len_bi nat len_nat = -1
+ then invalid_arg "base_power_big_int"
+ else
+ let copy = create_nat (succ len_bi) in
+ blit_nat copy 0 (bi.abs_value) 0 len_bi;
+ set_digit_nat copy len_bi 0;
+ div_nat copy 0 (succ len_bi)
+ nat 0 len_nat;
+ if not (is_zero_nat copy 0 len_nat)
+ then invalid_arg "base_power_big_int"
+ else { sign = bi.sign;
+ abs_value = copy_nat copy len_nat 1 }
+ | _ -> let nat = power_base_int base n in
+ let len_nat = num_digits_nat nat 0 (length_nat nat)
+ and len_bi = num_digits_big_int bi in
+ let new_len = len_bi + len_nat in
+ let res = make_nat new_len in
+ (if len_bi > len_nat
+ then mult_nat res 0 new_len
+ (bi.abs_value) 0 len_bi
+ nat 0 len_nat
+ else mult_nat res 0 new_len
+ nat 0 len_nat
+ (bi.abs_value) 0 len_bi)
+ ; if is_zero_nat res 0 new_len
+ then zero_big_int
+ else create_big_int (bi.sign) res
+
+(* Coercion with float type *)
+
+let float_of_big_int bi =
+ float_of_string (string_of_big_int bi)
+
+(* XL: suppression de big_int_of_float et nat_of_float. *)
+
+(* Other functions needed *)
+
+(* Integer part of the square root of a big_int *)
+let sqrt_big_int bi =
+ match bi.sign with
+ -1 -> invalid_arg "sqrt_big_int"
+ | 0 -> {sign = 0;
+ abs_value = make_nat (1)}
+ | _ -> {sign = 1;
+ abs_value = sqrt_nat (bi.abs_value) 0 (num_digits_big_int bi)}
+
+let square_big_int bi =
+ let len_bi = num_digits_big_int bi in
+ let len_res = 2 * len_bi in
+ let res = make_nat len_res in
+ square_nat res 0 len_res (bi.abs_value) 0 len_bi;
+ { sign = bi.sign;
+ abs_value = res }
+
+(* round off of the futur last digit (of the integer represented by the string
+ argument of the function) that is now the previous one.
+ if s contains an integer of the form (10^n)-1
+ then s <- only 0 digits and the result_int is true
+ else s <- the round number and the result_int is false *)
+let round_futur_last_digit s off_set length =
+ let l = pred (length + off_set) in
+ if Char.code(String.get s l) >= Char.code '5'
+ then
+ let rec round_rec l =
+ let current_char = String.get s l in
+ if current_char = '9'
+ then
+ (String.set s l '0';
+ if l = off_set then true else round_rec (pred l))
+ else
+ (String.set s l (Char.chr (succ (Char.code current_char)));
+ false)
+ in round_rec (pred l)
+ else false
+
+
+(* Approximation with floating decimal point a` la approx_ratio_exp *)
+let approx_big_int prec bi =
+ let len_bi = num_digits_big_int bi in
+ let n =
+ max 0
+ (int_of_big_int (
+ add_int_big_int
+ (-prec)
+ (div_big_int (mult_big_int (big_int_of_int (pred len_bi))
+ (big_int_of_string "963295986"))
+ (big_int_of_string "100000000")))) in
+ let s =
+ string_of_big_int (div_big_int bi (power_int_positive_int 10 n)) in
+ let (sign, off, len) =
+ if String.get s 0 = '-'
+ then ("-", 1, succ prec)
+ else ("", 0, prec) in
+ if (round_futur_last_digit s off (succ prec))
+ then (sign^"1."^(String.make prec '0')^"e"^
+ (string_of_int (n + 1 - off + String.length s)))
+ else (sign^(String.sub s off 1)^"."^
+ (String.sub s (succ off) (pred prec))
+ ^"e"^(string_of_int (n - succ off + String.length s)))
diff --git a/otherlibs/num/big_int.mli b/otherlibs/num/big_int.mli
new file mode 100644
index 000000000..42c26f1b3
--- /dev/null
+++ b/otherlibs/num/big_int.mli
@@ -0,0 +1,64 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Module [Big_int]: operations on big integers *)
+
+(* Big integers (type [big_int]) are signed integers of arbitrary size. *)
+
+open Nat
+
+type big_int
+
+val sign_big_int : big_int -> int
+val zero_big_int : big_int
+val unit_big_int : big_int
+val num_digits_big_int : big_int -> int
+val minus_big_int : big_int -> big_int
+val abs_big_int : big_int -> big_int
+val compare_big_int : big_int -> big_int -> int
+val eq_big_int : big_int -> big_int -> bool
+val le_big_int : big_int -> big_int -> bool
+val ge_big_int : big_int -> big_int -> bool
+val lt_big_int : big_int -> big_int -> bool
+val gt_big_int : big_int -> big_int -> bool
+val max_big_int : big_int -> big_int -> big_int
+val min_big_int : big_int -> big_int -> big_int
+val pred_big_int : big_int -> big_int
+val succ_big_int : big_int -> big_int
+val add_big_int : big_int -> big_int -> big_int
+val big_int_of_int : int -> big_int
+val add_int_big_int : int -> big_int -> big_int
+val sub_big_int : big_int -> big_int -> big_int
+val mult_int_big_int : int -> big_int -> big_int
+val mult_big_int : big_int -> big_int -> big_int
+val quomod_big_int : big_int -> big_int -> big_int * big_int
+val div_big_int : big_int -> big_int -> big_int
+val mod_big_int : big_int -> big_int -> big_int
+val gcd_big_int : big_int -> big_int -> big_int
+val int_of_big_int : big_int -> int
+val is_int_big_int : big_int -> bool
+val nat_of_big_int : big_int -> nat
+val big_int_of_nat : nat -> big_int
+val string_of_big_int : big_int -> string
+val big_int_of_string : string -> big_int
+val float_of_big_int : big_int -> float
+val square_big_int: big_int -> big_int
+val sqrt_big_int: big_int -> big_int
+val base_power_big_int: int -> int -> big_int -> big_int
+val sys_big_int_of_string: string -> int -> int -> big_int
+val power_int_positive_int: int -> int -> big_int
+val power_big_int_positive_int: big_int -> int -> big_int
+val power_int_positive_big_int: int -> big_int -> big_int
+val power_big_int_positive_big_int: big_int -> big_int -> big_int
+val round_futur_last_digit : string -> int -> int -> bool
+val approx_big_int: int -> big_int -> string
diff --git a/otherlibs/num/bignum/Makefile b/otherlibs/num/bignum/Makefile
new file mode 100644
index 000000000..89be3bda7
--- /dev/null
+++ b/otherlibs/num/bignum/Makefile
@@ -0,0 +1,335 @@
+# Copyright Digital Equipment Corporation & INRIA 1988, 1989, 1992
+# Last modified_on Tue Nov 3 13:44:57 1992 by shand
+# modified_on Fri May 31 18:26:52 GMT+2:00 1991 by herve
+# modified_on Thu Nov 2 14:23:14 GMT+1:00 1989 by gangnet
+# modified_on Wed Jul 5 10:23:54 GMT+2:00 1989 by bertin
+
+CC = cc
+AR = ar
+RANLIB = ranlib
+RANLIBTEST=test -f /usr/bin/ranlib -o -f /bin/ranlib
+LIB = libbignum.a
+OBJECT = o/KerN.o o/bnInit.o o/bnMult.o o/bnDivide.o o/bnCmp.o o/bzf.o o/bz.o
+KERNH = h/BigNum.h
+CFLAGS = -c -I./h -O -DCAML_LIGHT
+LDFLAGS =
+
+# extra entries:
+# all - make all the stuff
+# tidy - cleanup directories
+# scratch - start from scratch
+
+default:
+ @echo "Usage: make <version>"
+ @echo "see README for valid versions."
+ @sh -c 'exit 1'
+
+#all: testKerN bztest
+# @echo All is done
+
+all: $(LIB)
+ @echo All is done
+
+tidy:
+ -rm -f ,* .,* *~ #*# .emacs_[0-9]* *.BAK *.CKP core a.out
+ -rm -f */,* */.,* */*~ */#*# */.emacs_[0-9]* */*.BAK */*.CKP
+
+scratch:tidy
+ rm -f o/*.o libbignum.a bztest testKerN
+
+# build the BigNum library
+$(LIB): $(OBJECT)
+ -rm -f $(LIB)
+ $(AR) cr $(LIB) $(OBJECT)
+ if $(RANLIBTEST); then $(RANLIB) $(LIB); else true; fi
+
+# How to choose the machine dependent version. All produce KerN.o
+o/KerN.o: c/KerN.c
+ @echo "The Default is KerN written in C with digits on long"
+ make C CC="$(CC)" CFLAGS="$(CFLAGS)"
+
+C: scratch
+ $(CC) $(CFLAGS) c/KerN.c
+ mv KerN.o o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+68K: scratch
+ as s/68KerN.s -o o/KerN.o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+vax: scratch
+ as s/vaxKerN.s -o o/KerN.o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" all
+
+ns: scratch
+ as s/nsKerN.s -o o/KerN.o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+mips: scratch
+ as -w s/mipsKerN.s -o o/KerN.o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" all
+
+alpha: scratch
+ as -O s/alphaKerN.s -o o/KerN.o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" all
+
+pyramid: scratch
+ as s/pyramidKerN.s -o o/KerN.o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+i960: scratch
+ as s/i960KerN.s -o o/KerN.o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+sparc: scratch
+ as s/sparcKerN.s -o o/KerN.o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+sparcfpu: scratch
+ as s/sparcfpuKerN.s -o o/KerN.o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+supersparc: scratch
+ as s/supersparcKerN.s -o o/KerN.o
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+sparc-solaris: scratch
+ sed -e 's/_Bnn/Bnn/g' s/sparcKerN.s > s/KerN.s
+ as s/KerN.s -o o/KerN.o
+ rm -f s/KerN.s
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+sparcfpu-solaris: scratch
+ sed -e 's/_Bnn/Bnn/g' s/sparcfpuKerN.s > s/KerN.s
+ as s/KerN.s -o o/KerN.o
+ rm -f s/KerN.s
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+supersparc-solaris: scratch
+ sed -e 's/_Bnn/Bnn/g' s/supersparcKerN.s > s/KerN.s
+ as s/KerN.s -o o/KerN.o
+ rm -f s/KerN.s
+ make CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ OBJECT="$(OBJECT)" all
+
+# Construct VMS assembler from UNIX version
+
+s/vaxKerN.mar: s/vaxKerN.s
+ sed -f s/unix2vms.sed < s/vaxKerN.s > $@
+
+# Level N
+o/bnInit.o: c/bn/bnInit.c $(KERNH)
+ $(CC) $(CFLAGS) c/bn/bnInit.c
+ mv bnInit.o o
+
+o/bnMult.o: c/bn/bnMult.c $(KERNH)
+ $(CC) $(CFLAGS) c/bn/bnMult.c
+ mv bnMult.o o
+
+o/bnDivide.o: c/bn/bnDivide.c $(KERNH)
+ $(CC) $(CFLAGS) c/bn/bnDivide.c
+ mv bnDivide.o o
+
+o/bnCmp.o: c/bn/bnCmp.c $(KERNH)
+ $(CC) $(CFLAGS) c/bn/bnCmp.c
+ mv bnCmp.o o
+
+# Level Z
+o/bz.o: c/bz.c h/BigZ.h $(KERNH)
+ $(CC) $(CFLAGS) c/bz.c
+ mv bz.o o
+
+# level R
+o/br.o: c/br.c h/BigR.h h/BigZ.h $(KERNH)
+ $(CC) $(CFLAGS) c/br.c
+ mv br.o o
+
+# Some functions build with BigZ
+o/bzf.o: c/bzf.c h/BigZ.h $(KERNH)
+ $(CC) $(CFLAGS) c/bzf.c
+ mv bzf.o o
+
+# Tests Of KerN
+testKerN: o/testKerN.o $(LIB)
+ $(CC) o/testKerN.o $(LIB) $(LDFLAGS) -o testKerN
+
+o/testKerN.o: c/testKerN.c $(KERNH)
+ $(CC) $(CFLAGS) c/testKerN.c
+ mv testKerN.o o
+
+# Tests Of BigZ
+bztest: o/bztest.o $(LIB)
+ $(CC) o/bztest.o $(LIB) $(LDFLAGS) -o bztest
+
+o/bztest.o: c/bztest.c h/BigZ.h $(KERNH)
+ $(CC) $(CFLAGS) c/bztest.c
+ mv bztest.o o
+
+# Tests Of BigR
+brtest: o/brtest.o $(LIB)
+ $(CC) o/brtest.o $(LIB) $(LDFLAGS) -o brtest
+
+o/brtest.o: c/brtest.c h/BigR.h h/BigZ.h $(KERNH)
+ $(CC) $(CFLAGS) c/brtest.c
+ mv brtest.o o
+
+# documentation
+doc: doc/bn.ps doc/bnf.ps
+docprl: doc/bnprl.ps
+
+doc/bn.dvi: doc/bn.tex doc/bnbody.tex
+ cd doc;\
+ latex bn;\
+ makeindex bn;\
+ sed -e "s/\\item Bz/\\newpage \\Bz/g" < bn.ind > bn.index;\
+ mv bn.index bn.ind;\
+ latex bn;\
+ cd ..
+
+doc/bn.ps: doc/bn.dvi
+ cd doc;\
+ dvips -o bn.ps bn;\
+ cd ..
+
+doc/bnf.dvi: doc/bnf.tex
+ cd doc;\
+ latex bnf;\
+ cd ..
+
+doc/bnf.ps: doc/bnf.dvi
+ cd doc;\
+ dvips -o bnf.ps bnf;\
+ cd ..
+
+doc/bnprl.dvi: doc/bnprl.tex doc/bnbody.tex
+ cd doc;\
+ latex bnprl;\
+ makeindex bnprl;\
+ sed -e "s/\\item Bz/\\newpage \\Bz/g" < bnprl.ind > bnprl.index;\
+ mv bnprl.index bnprl.ind;\
+ latex bnprl;\
+ cd ..
+
+doc/bnprl.ps: doc/bnprl.dvi
+ cd doc;\
+ dvips -o bnprl.ps bnprl;\
+ cd ..
+
+
+# build shell archives
+PACKET_SIZE = 90
+PREFIX = bignum.
+DIRS = c c/bn h s o doc
+
+# If you modify the list of files in the package kit, don't forget
+# to update README.
+
+KIT= README Makefile VMSmakefile MSDOSmakefile\
+ doc/bn.tex doc/bnbody.tex doc/bnf.tex doc/intro\
+ c/KerN.c c/bn/bnInit.c c/bn/bnMult.c c/bn/bnDivide.c\
+ c/bn/bnCmp.c c/bz.c c/bzf.c \
+ c/bztest.c c/testKerN.c \
+ h/BigNum.h h/BigZ.h \
+ s/vaxKerN.s s/68KerN.s s/nsKerN.s s/68KerN_mot.s \
+ s/mipsKerN.s s/pyramidKerN.s s/vaxKerN.mar s/unix2vms.sed \
+ s/i960KerN.s s/sparcKerN.s s/sparcfpuKerN.s \
+ s/alphaKerN.s \
+ o/EMPTY
+
+bignum.01.shar: $(KIT)
+ makekit -s$(PACKET_SIZE)k -n$(PREFIX) -t"Now do 'make'" $(DIRS) $(KIT)
+ for f in `ls bignum.[0-9][0-9]`; \
+ do mv $$f $$f.shar; \
+ done
+
+bignum.00.shar: README doc/intro bignum.01.shar
+ ls bignum.[0-9][0-9].shar | sed -e "s/^bignum0*/ BigNum - Part /" > _flist1
+ ls bignum.[0-9][0-9].shar | sed -e "s/^/ /" > _flist2
+ ls bignum.[0-9][0-9].shar | sed -e "s/^/ \/bin\/sh /" > _flist3
+ ls bignum.[0-9][0-9].shar | sed -e "s/^/ shar -u /" > _flist4
+ cc -E -Uvax -I. doc/intro >introtobn
+ sed \
+ -e "s/modified_on/modified_on/g" \
+ -e "/doc\/$(VERSION)intro/d" \
+ -e "/.\/$(VERSION)README/d" \
+ -e "s/NN/"`ls bignum.??.shar | wc -l | sed -e "s/ //g"`"/g" \
+ -e "/^INCLUDE1/r _flist1" \
+ -e "/^INCLUDE2/r _flist2" \
+ -e "/^INCLUDE3/r _flist3" \
+ -e "/^INCLUDE4/r _flist4" \
+ -e "/^INCLUDE./d" \
+ <introtobn > bignum.00.shar
+ rm -f introtobn _flist[1-9]
+
+# build shell archives of the beta version
+
+# If you modify the list of files in the package betakit, don't forget
+# to update betaREADME.
+
+BETAKIT= $(KIT) c/br.c c/brtest.c h/BigR.h
+
+# note we replace README by betaREADME and doc/intro by doc/betaintro
+# such that the filename will be README and doc/intro in the archive,
+betabignum01: $(BETAKIT) betaREADME doc/betaintro
+ mv README README.cur
+ cp betaREADME README
+ mv doc/intro doc/intro.cur
+ cp doc/betaintro doc/intro
+ makekit -s$(PACKET_SIZE)k -n$(PREFIX) -t"Now do 'make'" $(DIRS) $(BETAKIT)
+ mv README.cur README
+ mv doc/intro.cur doc/intro
+
+
+# send shell archives
+SENDMAIL=/usr/lib/sendmail
+SENDMAILFLAGS=
+USER=nil
+FULLNAME=nil
+COPY=librarian@prl.dec.com
+VERSION= # the version you want to mail, could be empty (current release) or "beta"
+
+
+mail: $(VERSION)bignum.01.shar bignum.00.shar # do bignum00 AFTER !!
+ @sh -c "if [ x$(USER) = xnil -o 'x$(FULLNAME)' = xnil ]; \
+ then echo must specify USER and FULLNAME; \
+ echo EG make USER=herve@prl FULLNAME="'\"'"J-C Herve, Digital PRL"'\"'" mail; exit 1; \
+ else :; fi"
+ @touch Recipients
+ @echo '' >> Recipients
+ @date >> Recipients
+ @echo "$(FULLNAME)" >> Recipients
+ @echo '<'"$(USER)"'>' >> Recipients
+ @echo "To: $(COPY)" >tosend
+ @echo "Subject: BIGNUM DAEMON" >>tosend
+ @echo "Jean-Christophe, I have sent the package bignum to:" >>tosend
+ @echo >>tosend
+ @echo " $(FULLNAME)" >>tosend
+ @echo " $(USER)" >>tosend
+ @echo >>tosend
+ @echo "Thanks to register this address in your distribution list." >>tosend
+ @$(SENDMAIL) $(SENDMAILFLAGS) $(COPY) <tosend
+ echo To: $(USER) > sendmail_header
+ cp sendmail_header tosend
+ echo "Subject: BigNum package from Digital PRL" >>tosend
+ cat bignum.00.shar >>tosend
+ rm -f bignum.00.shar
+ $(SENDMAIL) $(SENDMAILFLAGS) $(USER) <tosend
+ for i in `ls bignum.[0-9][0-9].shar`; \
+ do cp sendmail_header tosend; \
+ echo $$i | sed -e "s/^bignum0*/Subject: BigNum - Part /" >>tosend; \
+ echo "# Remove all text above and including this line." >>tosend; \
+ sed -e "s/modified_on/modified_on/g" <$$i >>tosend; \
+ $(SENDMAIL) $(SENDMAILFLAGS) $(USER) <tosend; \
+ done
+ rm -f sendmail_header tosend bignum.[0-9][0-9].shar
+
diff --git a/otherlibs/num/bignum/README b/otherlibs/num/bignum/README
new file mode 100644
index 000000000..a2fb5ef54
--- /dev/null
+++ b/otherlibs/num/bignum/README
@@ -0,0 +1,97 @@
+
+This directory contains the C and assembler source code for BigNum.
+
+ The subdirectory doc contains the documentation files:
+ bn.tex - Document BigNum in LaTeX format
+ bnf.tex - Document BigNum in French and LaTeX format
+ makeidx.sty - macro used in BigNum document
+
+ The subdirectory h contains the C include files:
+ BigZ.h - Types and structures for clients of BigZ
+ BigNum.h - Types and structures for clients of BigNum
+
+ The subdirectory c contains the C source files:
+ KerN.c - BigNum implementation ("kernel" routines)
+ bn/bn*.c - BigNum implementation ("non-kernel" routines),
+ that is bnInit.c, bnMult.c, bnDivide.c and bnCmp.c
+ bz.c - BigZ implementation
+ bzf.c - Miscellaneous functions built on top of BigZ
+ bztest.c - Test program for verifying a BigNum implementation
+ testKerN.c - Test program for verifying KerN implementation
+
+ The subdirectory s contains the assembler source files:
+ vaxKerN.s - Vax/U*ix implementation of KerN
+ vaxKerN.mar - Vax/VMS implementation of KerN
+ 68KerN.s - 68020 implementation of KerN (MIT syntax)
+ 68KerN_mot.s - 68020 implementation of KerN (Motorola syntax)
+ nsKerN.s - NS implementation of KerN
+ mipsKerN.s - MIPS implementation of KerN
+ pyramidKerN.s - Pyramid implementation of KerN
+ i960KerN.s - Intel 80960 implementation of KerN
+ sparcKerN.s - SPARC implementation of KerN
+ sparcfpuKerN.s - SPARC implementation of KerN using FPU, may
+ give faster multiplication on SPARC
+ implementations with fast floating point
+ supersparcKerN.s - SPARC V8 implementation of KerN
+ (with hardware integer multiplication)
+
+ Other Files:
+ Makefile - U*ix makefile
+ VMSmakefile - VMS makefile
+ MSDOSmakefile - MSDOS makefile
+
+
+Now, to build or modify the current version of the package, type one of:
+
+ on U*ix system:
+ make vax - to use vax assembly code
+ make 68K - to use 68020 assembly code
+ make ns - to use NS assembly code
+ make mips - to use mips assembly code
+ make pyramid - to use pyramid assembly code
+ make i960 - to use intel 80960 assembly code
+ make sparc - to use sparc assembly code (SunOS 4)
+ make sparcfpu - to use sparc assembly code (with multiply in FPU)
+ make supersparc - to use sparc V8 assembly code (Sun OS 4)
+ make sparc-solaris
+ make sparcfpu-solaris same as above, for Solaris 2 instead of SunOS 4
+ make supersparc-solaris
+ make C16 - to use C code with 16 bits digits
+ make C32 - to use C code with 32 bits digits (default version)
+
+ on VMS system: (copy VMSmakefile to Makefile, before)
+ mms vax - to use vax assembly code (default version)
+ mms C32 - to use C code with 32 bits digits
+ we suppose you have defined the standard libraries of C-VMS with:
+ define lnk$library sys$library:vaxccurse
+ define lnk$library_1 sys$library:vaxcrtlg
+ define lnk$library_2 sys$library:vaxcrtl
+
+ on MSDOS system: (copy MSDOSmakefile to Makefile, before)
+ make makefile - to use C code (16 bits digits)
+
+Each of these commands products the following files:
+
+ on U*ix system:
+ BigNum.a - BigNum library
+ testKerN - Test program executable for KerN
+ bztest - Test program executable for BigZ
+
+ on VMS system:
+ BigNum.olb - BigNum library
+ testKerN.exe - Test program executable for KerN
+ bztest.exe - Test program executable for BigZ
+
+ on MSDOS system:
+ BigNum.lib - BigNum library
+ testKerN.exe - Test program executable for KerN
+ bztest.exe - Test program executable for BigZ
+
+
+On U*ix system, if you have the tools LaTeX (L. Lamport's special version of Knuth's
+famous TeX, as described in the Addison-Wesley book), makeindex and
+dvips, type:
+ make doc - to build the Postscript files of the documents,
+
+If you do not have dvips, use your local equivalent tool to print
+the dvi file produced by the LaTeX command.
diff --git a/otherlibs/num/bignum/c/KerN.c b/otherlibs/num/bignum/c/KerN.c
new file mode 100644
index 000000000..7b9ef1ce1
--- /dev/null
+++ b/otherlibs/num/bignum/c/KerN.c
@@ -0,0 +1,932 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Thu Feb 20 18:18:12 GMT+1:00 1992 by shand */
+/* modified_on Tue Jan 15 19:32:53 GMT+1:00 1991 by herve */
+
+
+/* KerN.c: the kernel written in C */
+
+/*
+ * Description of types and constants.
+ *
+ * Several conventions are used in the commentary:
+ * A "BigNum" is the name for an infinite-precision number.
+ * Capital letters (e.g., "N") are used to refer to the value of BigNums.
+ * The word "digit" refers to a single BigNum digit.
+ * The notation "Size(N)" refers to the number of digits in N,
+ * which is typically passed to the subroutine as "nl".
+ * The notation "Length(N)" refers to the number of digits in N,
+ * not including any leading zeros.
+ * The word "Base" is used for the number 2 ** BN_DIGIT_SIZE, where
+ * BN_DIGIT_SIZE is the number of bits in a single BigNum digit.
+ * The expression "BBase(N)" is used for Base ** NumDigits(N).
+ * The term "leading zeros" refers to any zeros before the most
+ * significant digit of a number.
+ *
+ *
+ * In the code, we have:
+ *
+ * "nn" is a pointer to a big number,
+ * "nl" is the number of digits from nn,
+ * "d" is a digit.
+ *
+ */
+
+
+/* */
+
+#define BNNMACROS_OFF
+#include "BigNum.h"
+#define NOMEM
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)KerN.c: copyright Digital Equipment Corporation & INRIA 1988, 1989\n";
+
+
+ /******* non arithmetic access to digits ********/
+
+
+#ifndef _NO_PROTO
+void BnnSetToZero (BigNum nn, BigNumLength nl)
+#else
+void BnnSetToZero (nn, nl)
+BigNum nn; BigNumLength nl;
+#endif
+
+/*
+ * Sets all the specified digits of the BigNum to 0
+ */
+
+{
+ BigNum nnlim;
+ if (nl <= 0)
+ return;
+ nnlim = nn+nl-1;
+ do *nn = 0; while(nn++ < nnlim);
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+void BnnAssign (BigNum mm, BigNum nn, BigNumLength nl)
+#else /* _NO_PROTO */
+void BnnAssign ( mm, nn, nl)
+BigNum mm; BigNum nn; BigNumLength nl;
+#endif /* _NO_PROTO */
+
+/*
+ * Copies N => M
+ */
+
+{
+ BigNum nnlim;
+ if (nl <= 0)
+ return;
+ nnlim = nn+nl;
+#ifdef MSDOS
+ if (realaddr(mm) < realaddr(nn) || realaddr(mm) > realaddr(nnlim))
+#else
+ if ((mm < nn) || ( mm > nnlim))
+#endif
+ do *mm++ = *nn++; while(nn < nnlim);
+ else
+#ifdef MSDOS
+ if (realaddr(mm) > realaddr(nn))
+#else
+ if (mm > nn)
+#endif
+ {
+ mm += nl;
+ do *--mm = *--nnlim; while(nn < nnlim);
+ }
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+void BnnSetDigit (BigNum nn, BigNumDigit d)
+#else /* _NO_PROTO */
+void BnnSetDigit ( nn, d)
+BigNum nn; BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/*
+ * Sets a single digit of N to the passed value
+ */
+
+{
+ *nn = d;
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+BigNumDigit BnnGetDigit (BigNum nn)
+#else /* _NO_PROTO */
+BigNumDigit BnnGetDigit ( nn)
+BigNum nn;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns the single digit pointed by N
+ */
+
+{
+ return (*nn);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigNumLength BnnNumDigits (BigNum nn, BigNumLength nl)
+#else /* _NO_PROTO */
+BigNumLength BnnNumDigits ( nn, nl)
+BigNum nn; BigNumLength nl;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns the number of digits of N, not counting leading zeros
+ */
+
+{
+ nn += nl;
+
+ while (nl != 0 && *--nn == 0)
+ nl--;
+
+ return (nl == 0 ? 1 : nl);
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+BigNumDigit BnnNumLeadingZeroBitsInDigit (BigNumDigit d)
+#else /* _NO_PROTO */
+BigNumDigit BnnNumLeadingZeroBitsInDigit ( d)
+BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns the number of leading zero bits in a digit
+ */
+
+{
+ register int p = 0;
+ if (BN_DIGIT_SIZE == 16 || BN_DIGIT_SIZE == 32 || BN_DIGIT_SIZE == 64)
+ {
+ register BigNumDigit mask = (~(BigNumDigit)0) << (BN_DIGIT_SIZE/2);
+ register BigNumLength maskl = BN_DIGIT_SIZE/2;
+
+ if (d == 0)
+ return (BN_DIGIT_SIZE);
+ while (maskl)
+ {
+ if ((d & mask) == 0)
+ {
+ p += maskl;
+ d <<= maskl;
+ }
+ maskl >>= 1;
+ mask <<= maskl;
+ }
+ }
+ else
+ {
+ register BigNumDigit mask = ((BigNumDigit)1) << (BN_DIGIT_SIZE-1);
+
+ while ((d & mask) == 0)
+ {
+ p++;
+ mask >>= 1;
+ }
+ }
+
+ return (p);
+}
+
+ /***************************************/
+/* */
+
+ /************** Predicates on one digit ***************/
+
+
+#ifndef _NO_PROTO
+Boolean BnnDoesDigitFitInWord (BigNumDigit d)
+#else /* _NO_PROTO */
+Boolean BnnDoesDigitFitInWord ( d)
+BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns TRUE iff the digit can be represented in just BN_WORD_SIZE bits
+ */
+{
+ /* The C compiler must evaluate the predicate at compile time */
+ if (BN_DIGIT_SIZE > BN_WORD_SIZE)
+ return (d >= ((BigNumDigit)1) << BN_WORD_SIZE ? FALSE : TRUE);
+ else
+ return (TRUE);
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+Boolean BnnIsDigitZero (BigNumDigit d)
+#else /* _NO_PROTO */
+Boolean BnnIsDigitZero ( d)
+BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/* Returns TRUE iff digit = 0 */
+
+{
+ return (d == 0);
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+Boolean BnnIsDigitNormalized (BigNumDigit d)
+#else /* _NO_PROTO */
+Boolean BnnIsDigitNormalized ( d)
+BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns TRUE iff Base/2 <= digit < Base
+ * i.e., if digit's leading bit is 1
+ */
+
+{
+ return (d & (((BigNumDigit)1) << (BN_DIGIT_SIZE - 1)) ? TRUE : FALSE);
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+Boolean BnnIsDigitOdd (BigNumDigit d)
+#else /* _NO_PROTO */
+Boolean BnnIsDigitOdd ( d)
+BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns TRUE iff digit is odd
+ */
+
+{
+ return (d & 1 ? TRUE : FALSE);
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+BigNumCmp BnnCompareDigits (BigNumDigit d1, BigNumDigit d2)
+#else /* _NO_PROTO */
+BigNumCmp BnnCompareDigits ( d1, d2)
+BigNumDigit d1; BigNumDigit d2;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns BN_GREATER if digit1 > digit2
+ * BN_EQUAL if digit1 = digit2
+ * BN_LESS if digit1 < digit2
+ */
+
+{
+ return (d1 > d2 ? BN_GT : (d1 == d2 ? BN_EQ : BN_LT));
+}
+
+ /***************** Logical operations ********************/
+
+
+#ifndef _NO_PROTO
+void BnnComplement (BigNum nn, BigNumLength nl)
+#else /* _NO_PROTO */
+void BnnComplement ( nn, nl)
+BigNum nn; BigNumLength nl;
+#endif /* _NO_PROTO */
+
+/*
+ * Performs the computation BBase(N) - N - 1 => N
+ */
+
+{
+ BigNum nnlim;
+
+ if (nl <= 0)
+ return;
+ nnlim = nn+nl;
+ do
+ {
+ nn++;
+ nn[-1] = ~nn[-1];
+ }
+ while (nn < nnlim);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+void BnnAndDigits (BigNum n, BigNumDigit d)
+#else /* _NO_PROTO */
+void BnnAndDigits ( n, d)
+BigNum n; BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns the logical computation n[0] AND d in n[0]
+ */
+
+{
+ *n &= d;
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+void BnnOrDigits (BigNum n, BigNumDigit d)
+#else /* _NO_PROTO */
+void BnnOrDigits ( n, d)
+BigNum n; BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns the logical computation n[0] OR d2 in n[0].
+ */
+
+{
+ *n |= d;
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+void BnnXorDigits (BigNum n, BigNumDigit d)
+#else /* _NO_PROTO */
+void BnnXorDigits ( n, d)
+BigNum n; BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns the logical computation n[0] XOR d in n[0].
+ */
+
+{
+ *n ^= d;
+}
+
+ /***************************************/
+/* */
+
+ /****************** Shift operations *******************/
+
+
+#ifndef _NO_PROTO
+BigNumDigit BnnShiftLeft (BigNum mm, BigNumLength ml, int nbits)
+#else /* _NO_PROTO */
+BigNumDigit BnnShiftLeft ( mm, ml, nbits)
+BigNum mm; BigNumLength ml; int nbits;
+#endif /* _NO_PROTO */
+
+/*
+ * Shifts M left by "nbits", filling with 0s.
+ * Returns the leftmost "nbits" of M in a digit.
+ * Assumes 0 <= nbits < BN_DIGIT_SIZE.
+ */
+
+{
+ register BigNumDigit res = 0, save;
+ int rnbits;
+
+
+ if (nbits != 0)
+ {
+ rnbits = BN_DIGIT_SIZE - nbits;
+
+ while (ml-- > 0)
+ {
+ save = *mm;
+ *mm++ = (save << nbits) | res;
+ res = save >> rnbits;
+ }
+ }
+
+ return (res);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigNumDigit BnnShiftRight (BigNum mm, BigNumLength ml, int nbits)
+#else /* _NO_PROTO */
+BigNumDigit BnnShiftRight ( mm, ml, nbits)
+BigNum mm; BigNumLength ml; int nbits;
+#endif /* _NO_PROTO */
+
+/*
+ * Shifts M right by "nbits", filling with 0s.
+ * Returns the rightmost "nbits" of M in a digit.
+ * Assumes 0 <= nbits < BN_DIGIT_SIZE.
+ */
+
+{
+ register BigNumDigit res = 0, save;
+ int lnbits;
+
+
+ if (nbits != 0)
+ {
+ mm += ml;
+ lnbits = BN_DIGIT_SIZE - nbits;
+
+ while (ml-- > 0)
+ {
+ save = *(--mm);
+ *mm = (save >> nbits) | res;
+ res = save << lnbits;
+ }
+ }
+
+ return (res);
+}
+
+ /***************************************/
+/* */
+
+
+ /******************* Additions **************************/
+
+
+#ifndef _NO_PROTO
+BigNumCarry BnnAddCarry (BigNum nn, BigNumLength nl, BigNumCarry carryin)
+#else /* _NO_PROTO */
+BigNumCarry BnnAddCarry ( nn, nl, carryin)
+BigNum nn; BigNumLength nl; BigNumCarry carryin;
+#endif /* _NO_PROTO */
+
+/*
+ * Performs the sum N + CarryIn => N.
+ * Returns the CarryOut.
+ */
+
+{
+ if (carryin == 0)
+ return (0);
+
+ if (nl == 0)
+ return (1);
+
+ while (nl > 0 && !(++(*nn++)))
+ nl--;
+
+ return (nl > 0 ? 0 : 1);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigNumCarry BnnAdd (BigNum mm, BigNumLength ml, BigNum nn, BigNumLength nl, BigNumCarry carryin)
+#else /* _NO_PROTO */
+BigNumCarry BnnAdd ( mm, ml, nn, nl, carryin)
+BigNum mm; BigNumLength ml; BigNum nn; BigNumLength nl; BigNumCarry carryin;
+#endif /* _NO_PROTO */
+
+/*
+ * Performs the sum M + N + CarryIn => M.
+ * Returns the CarryOut.
+ * Assumes Size(M) >= Size(N).
+ */
+
+{
+ register BigNumProduct c = carryin;
+
+
+ ml -= nl;
+ /* test computed at compile time */
+ if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ {
+ while (nl > 0)
+ {
+ c += ((BigNumProduct)*mm) + *(nn++);
+ *(mm++) = c;
+ c >>= BN_DIGIT_SIZE;
+ nl--;
+ }
+ }
+ else
+ {
+ register BigNumProduct save;
+
+ while (nl > 0)
+ {
+ save = *mm;
+ c += save;
+ if (c < save)
+ {
+ *(mm++) = *(nn++);
+ c = 1;
+ }
+ else
+ {
+ save = *(nn++);
+ c += save;
+ *(mm++) = c;
+ c = (c < save) ? 1 : 0;
+ }
+ nl--;
+ }
+ }
+
+ return (BnnAddCarry (mm, ml, (BigNumCarry) c));
+}
+
+ /***************************************/
+/* */
+
+ /****************** Subtraction *************************/
+
+
+
+#ifndef _NO_PROTO
+BigNumCarry BnnSubtractBorrow (BigNum nn, BigNumLength nl, BigNumCarry carryin)
+#else /* _NO_PROTO */
+BigNumCarry BnnSubtractBorrow ( nn, nl, carryin)
+BigNum nn; BigNumLength nl; BigNumCarry carryin;
+#endif /* _NO_PROTO */
+
+/*
+ * Performs the difference N + CarryIn - 1 => N.
+ * Returns the CarryOut.
+ */
+
+{
+ if (carryin == 1)
+ return (1);
+ if (nl == 0)
+ return (0);
+
+ while (nl > 0 && !((*nn++)--))
+ nl--;
+
+ return (nl > 0 ? 1 : 0);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigNumCarry BnnSubtract (BigNum mm, BigNumLength ml, BigNum nn, BigNumLength nl, BigNumCarry carryin)
+#else /* _NO_PROTO */
+BigNumCarry BnnSubtract ( mm, ml, nn, nl, carryin)
+BigNum mm; BigNumLength ml; BigNum nn; BigNumLength nl; BigNumCarry carryin;
+#endif /* _NO_PROTO */
+
+/*
+ * Performs the difference M - N + CarryIn - 1 => M.
+ * Returns the CarryOut.
+ * Assumes Size(M) >= Size(N).
+ */
+
+{
+ register BigNumProduct c = carryin;
+ register BigNumDigit invn;
+
+
+ ml -= nl;
+ /* test computed at compile time */
+ if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ {
+ while (nl > 0)
+ {
+ invn = *(nn++) ^ -1;
+ c += ((BigNumProduct)*mm) + invn;
+ *(mm++) = c;
+ c >>= BN_DIGIT_SIZE;
+ nl--;
+ }
+ }
+ else
+ {
+ register BigNumProduct save;
+
+ while (nl > 0)
+ {
+ save = *mm;
+ invn = *(nn++) ^ -1;
+ c += save;
+
+ if (c < save)
+ {
+ *(mm++) = invn;
+ c = 1;
+ }
+ else
+ {
+ c += invn;
+ *(mm++) = c;
+ c = (c < invn) ? 1 : 0;
+ }
+ nl--;
+ }
+ }
+
+ return (BnnSubtractBorrow (mm, ml, (BigNumCarry) c)); }
+
+
+ /***************************************/
+/* */
+
+ /***************** Multiplication ************************/
+
+#ifndef _NO_PROTO
+BigNumCarry BnnMultiplyDigit (BigNum pp, BigNumLength pl, BigNum mm, BigNumLength ml, BigNumDigit d)
+#else /* _NO_PROTO */
+BigNumCarry BnnMultiplyDigit ( pp, pl, mm, ml, d)
+BigNum pp; BigNumLength pl; BigNum mm; BigNumLength ml; BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/*
+ * Performs the product:
+ * Q = P + M * d
+ * BB = BBase(P)
+ * Q mod BB => P
+ * Q div BB => CarryOut
+ * Returns the CarryOut.
+ * Assumes Size(P) >= Size(M) + 1.
+ */
+
+{
+ register BigNumProduct c = 0;
+
+
+ if (d == 0)
+ return (0);
+
+ if (d == 1)
+ return (BnnAdd (pp, pl, mm, ml, (BigNumCarry) 0));
+
+ pl -= ml;
+ /* test computed at compile time */
+ if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ {
+ while (ml != 0)
+ {
+ ml--;
+ c += *pp + (((BigNumProduct)d) * (*(mm++)));
+ *(pp++) = c;
+ c >>= BN_DIGIT_SIZE;
+ }
+
+ while (pl != 0)
+ {
+ pl--;
+ c += *pp;
+ *(pp++) = c;
+ c >>= BN_DIGIT_SIZE;
+ }
+
+ return (c);
+ }
+ else
+ {
+/* help for stupid compilers--may actually be counter
+ productive on pipelined machines with decent register allocation!! */
+#define m_digit X0
+#define X3 Lm
+#define X1 Hm
+ register BigNumDigit Lm, Hm, Ld, Hd, X0, X2 /*, X1, X3 */;
+
+ Ld = d & ((((BigNumDigit)1) << (BN_DIGIT_SIZE / 2)) -1);
+ Hd = d >> (BN_DIGIT_SIZE / 2);
+ while (ml != 0)
+ {
+ ml--;
+ m_digit = *mm++;
+ Lm = m_digit & ((((BigNumDigit)1) << (BN_DIGIT_SIZE / 2)) -1);
+ Hm = m_digit >> (BN_DIGIT_SIZE / 2);
+ X0 = Ld * Lm;
+ X2 = Hd * Lm;
+ X3 = Hd * Hm;
+ X1 = Ld * Hm;
+
+ if ((c += X0) < X0) X3++;
+ if ((X1 += X2) < X2) X3 += (((BigNumDigit)1)<<(BN_DIGIT_SIZE / 2));
+ X3 += (X1 >> (BN_DIGIT_SIZE / 2));
+ X1 <<= (BN_DIGIT_SIZE / 2);
+ if ((c += X1) < X1) X3++;
+ if ((*pp += c) < c) X3++;
+ pp++;
+
+ c = X3;
+#undef m_digit
+#undef X1
+#undef X3
+ }
+
+ X0 = *pp;
+ c += X0;
+ *(pp++) = c;
+
+ if (c >= X0)
+ return (0);
+
+ pl--;
+ while (pl != 0 && !(++(*pp++)))
+ pl--;
+
+ return (pl != 0 ? 0 : 1);
+ }
+}
+
+#ifdef mips
+#ifndef _NO_PROTO
+BigNumCarry BnnMultiply2Digit (BigNum pp, BigNumLength pl, BigNum mm, BigNumLength ml, BigNumDigit d0, BigNumDigit d1)
+#else /* _NO_PROTO */
+BigNumCarry BnnMultiply2Digit ( pp, pl, mm, ml, d0, d1)
+BigNum pp; BigNumLength pl; BigNum mm; BigNumLength ml; BigNumDigit d0; BigNumDigit d1;
+#endif /* _NO_PROTO */
+
+/*
+ * Provided for compatibility with mips assembler implementation.
+ * Performs the product:
+ * Q = P + M * d0_d1
+ * BB = BBase(P)
+ * Q mod BB => P
+ * Q div BB => CarryOut
+ * Returns the CarryOut.
+ * Assumes Size(P) >= Size(M) + 1.
+ */
+
+{
+ return
+ BnnMultiplyDigit (pp, pl, mm, ml, d0)
+ + BnnMultiplyDigit (pp+1, pl-1, mm, ml, d1);
+}
+#endif /* mips */
+
+
+ /***************************************/
+/* */
+
+ /********************** Division *************************/
+
+
+ /* xh:xl -= yh:yl */
+#define SUB(xh,xl,yh,yl) if (yl > xl) {xl -= yl; xh -= yh + 1;}\
+ else {xl -= yl; xh -= yh;}
+
+#define LOW(x) (x & ((((BigNumDigit)1) << (BN_DIGIT_SIZE / 2)) -1))
+#define HIGH(x) (x >> (BN_DIGIT_SIZE / 2))
+#define L2H(x) (x << (BN_DIGIT_SIZE / 2))
+
+
+#ifndef _NO_PROTO
+BigNumDigit BnnDivideDigit (BigNum qq, BigNum nn, BigNumLength nl, BigNumDigit d)
+#else /* _NO_PROTO */
+BigNumDigit BnnDivideDigit ( qq, nn, nl, d)
+BigNum qq; BigNum nn; BigNumLength nl; BigNumDigit d;
+#endif /* _NO_PROTO */
+
+/* Performs the quotient: N div d => Q
+ * Returns R = N mod d
+ * Assumes leading digit of N < d, and d > 0.
+ */
+
+{
+ /* test computed at compile time */
+ if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ {
+ register BigNumProduct quad;
+
+
+ nn += nl;
+ nl--;
+ qq += nl;
+ quad = *(--nn);
+
+ while (nl != 0)
+ {
+ nl--;
+ quad = (quad << BN_DIGIT_SIZE) | *(--nn);
+ *(--qq) = quad / d;
+ quad = quad % d;
+ }
+
+ return (quad);
+ }
+ else
+ {
+ int k;
+ BigNumLength orig_nl;
+ BigNumDigit rh; /* Two halves of current remainder */
+ BigNumDigit rl; /* Correspond to quad above */
+ register BigNumDigit qa; /* Current appr. to quotient */
+ register BigNumDigit ph, pl; /* product of c and qa */
+ BigNumDigit ch, cl, prev_qq;
+
+
+ /* Normalize divisor */
+ k = BnnNumLeadingZeroBitsInDigit (d);
+ if (k != 0)
+ {
+ prev_qq = qq[-1];
+ orig_nl = nl;
+ d <<= k;
+ BnnShiftLeft (nn, nl, k);
+ }
+
+ nn += nl;
+ nl--;
+ qq += nl;
+
+ ch = HIGH (d);
+ cl = LOW (d);
+
+ rl = *(--nn);
+
+ while (nl != 0)
+ {
+ nl--;
+ rh = rl;
+ rl = *(--nn);
+ qa = rh / ch; /* appr. quotient */
+
+ /* Compute ph, pl */
+ pl = cl * qa;
+ ph = ch * qa;
+ ph += HIGH (pl);
+ pl = L2H (pl);
+
+ /* While ph:pl > rh:rl, decrement qa, adjust qh:ql */
+ while (ph > rh || ph == rh && pl > rl)
+ {
+ qa--;
+ SUB (ph, pl, ch, L2H (cl));
+ }
+
+ SUB (rh, rl, ph, pl);
+
+ /* Top half of quotient is correct; save it */
+ *(--qq) = L2H (qa);
+ qa = (L2H (rh) | HIGH (rl)) / ch;
+
+ /* Approx low half of q */
+ /* Compute ph, pl, again */
+ pl = cl * qa;
+ ph = ch * qa;
+ ph += HIGH (pl);
+ pl = LOW (pl) | L2H (LOW (ph));
+ ph = HIGH (ph);
+
+ /* While ph:pl > rh:rl, decrement qa, adjust qh:ql */
+ while (ph > rh || ph == rh && pl > rl)
+ {
+ qa--;
+ SUB (ph, pl, 0, d);
+ }
+
+ /* Subtract ph:pl from rh:rl; we know rh will be 0 */
+ rl -= pl;
+ *qq |= qa;
+ }
+
+ /* Denormalize dividend */
+ if (k != 0) {
+ if((qq > nn) && (qq < &nn[orig_nl])) {
+ /* Overlap between qq and nn. Care of *qq! */
+ orig_nl = (qq - nn);
+ BnnShiftRight (nn, orig_nl, k);
+ nn[orig_nl - 1] = prev_qq;
+ } else if(qq == nn) {
+ BnnShiftRight(&nn[orig_nl - 1], 1, k);
+ } else {
+ BnnShiftRight (nn, orig_nl, k);
+ } }
+ return (rl >> k);
+ }
+}
+
+ /***************************************/
+
+
diff --git a/otherlibs/num/bignum/c/bn/bnCmp.c b/otherlibs/num/bignum/c/bn/bnCmp.c
new file mode 100644
index 000000000..b678124d1
--- /dev/null
+++ b/otherlibs/num/bignum/c/bn/bnCmp.c
@@ -0,0 +1,77 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Fri Oct 5 16:13:31 GMT+1:00 1990 by herve */
+/* modified_on Fri Aug 10 17:21:47 GMT+2:00 1990 by shand */
+
+
+/* bnCmp.c: a piece of the bignum kernel written in C */
+
+
+ /***************************************/
+
+#define BNNMACROS_OFF
+#include "BigNum.h"
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)bnCmp.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n";
+
+
+#ifndef _NO_PROTO
+Boolean BnnIsZero (BigNum nn, BigNumLength nl)
+#else /* _NO_PROTO */
+Boolean BnnIsZero (nn, nl)
+BigNum nn; BigNumLength nl;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns TRUE iff N = 0
+ */
+
+{
+ return (BnnNumDigits (nn, nl) == 1 && (nl == 0 || BnnIsDigitZero (*nn)));
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigNumCmp BnnCompare (BigNum mm, BigNumLength ml, BigNum nn, BigNumLength nl)
+#else /* _NO_PROTO */
+BigNumCmp BnnCompare (mm, ml, nn, nl)
+BigNum mm; BigNumLength ml; BigNum nn; BigNumLength nl;
+#endif /* _NO_PROTO */
+
+/*
+ * return
+ * BN_GT iff M > N
+ * BN_EQ iff N = N
+ * BN_LT iff N < N
+*/
+
+{
+ register BigNumCmp result = BN_EQ;
+
+
+ ml = BnnNumDigits (mm, ml);
+ nl = BnnNumDigits (nn, nl);
+
+ if (ml != nl)
+ return (ml > nl ? BN_GT : BN_LT);
+
+ while (result == BN_EQ && ml-- > 0)
+ result = BnnCompareDigits (*(mm+ml), *(nn+ml));
+
+ return (result);
+
+/**** USE memcmp() instead: extern int memcmp ();
+
+ if (ml == nl)
+ {
+ lex = memcmp (mm, nn, nl*BN_DIGIT_SIZE/BN_BYTE_SIZE);
+ return (lex > 0 ? BN_GT: (lex == 0 ? BN_EQ: BN_LT));
+ }
+ else
+ return (ml > nl ? BN_GT : BN_LT);
+******/
+}
diff --git a/otherlibs/num/bignum/c/bn/bnDivide.c b/otherlibs/num/bignum/c/bn/bnDivide.c
new file mode 100644
index 000000000..e25938bb8
--- /dev/null
+++ b/otherlibs/num/bignum/c/bn/bnDivide.c
@@ -0,0 +1,156 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Mon Apr 15 18:51:35 GMT+2:00 1991 by herve */
+/* modified_on Fri Mar 30 3:29:17 GMT+2:00 1990 by shand */
+
+
+/* bnDivide.c: a piece of the bignum kernel written in C */
+
+
+ /***************************************/
+
+#define BNNMACROS_OFF
+#include "BigNum.h"
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)bnDivide.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n";
+
+
+static divide (nn, nl, dd, dl)
+
+ BigNum nn, dd;
+register BigNumLength nl, dl;
+
+/*
+ * In-place division.
+ *
+ * Input (N has been EXTENDED by 1 PLACE; D is normalized):
+ * +-----------------------------------------------+----+
+ * | N EXT|
+ * +-----------------------------------------------+----+
+ *
+ * +-------------------------------+
+ * | D 1|
+ * +-------------------------------+
+ *
+ * Output (in place of N):
+ * +-------------------------------+---------------+----+
+ * | R | Q |
+ * +-------------------------------+---------------+----+
+ *
+ * Assumes:
+ * N > D
+ * Size(N) > Size(D)
+ * last digit of N < last digit of D
+ * D is normalized (Base/2 <= last digit of D < Base)
+ */
+
+{
+ register int ni;
+ BigNumDigit DDigit, BaseMinus1, QApp, RApp;
+
+
+ /* Initialize constants */
+ BnnSetDigit (&BaseMinus1, 0);
+ BnnComplement(&BaseMinus1, 1);
+
+ /* Save the most significant digit of D */
+ BnnAssign (&DDigit, dd+dl-1, 1);
+
+ /* Replace D by Base - D */
+ BnnComplement (dd, dl);
+ BnnAddCarry (dd, dl, 1);
+
+ /* For each digit of the divisor, from most significant to least: */
+ nl += 1;
+ ni = nl-dl;
+ while (--ni >= 0)
+ {
+ /* Compute the approximate quotient */
+ nl--;
+
+ /* If first digits of numerator and denominator are the same, */
+ if (BnnCompareDigits (*(nn+nl), DDigit) == BN_EQ)
+ /* Use "Base - 1" for the approximate quotient */
+ BnnAssign (&QApp, &BaseMinus1, 1);
+ else
+ /* Divide the first 2 digits of N by the first digit of D */
+ RApp = BnnDivideDigit (&QApp, nn+nl-1, 2, DDigit);
+
+ /* Compute the remainder */
+ BnnMultiplyDigit (nn+ni, dl+1, dd, dl, QApp);
+
+ /* Correct the approximate quotient, in case it was too large */
+ while (BnnCompareDigits (*(nn+nl), QApp) != BN_EQ)
+ {
+ BnnSubtract (nn+ni, dl+1, dd, dl, 1); /* Subtract D from N */
+ BnnSubtractBorrow (&QApp, 1, 0); /* Q -= 1 */
+ }
+ }
+
+ /* Restore original D */
+ BnnComplement (dd, dl);
+ BnnAddCarry (dd, dl, 1);
+}
+
+
+ /***************************************/
+/* */
+
+
+void BnnDivide (nn, nl, dd, dl)
+
+ BigNum nn, dd;
+register BigNumLength nl, dl;
+
+/*
+ * Performs the quotient:
+ * N div D => high-order bits of N, starting at N[dl]
+ * N mod D => low-order dl bits of N
+ *
+ * Assumes
+ * Size(N) > Size(D),
+ * last digit of N < last digit of D (if N > D).
+ */
+
+{
+ BigNumDigit nshift;
+
+
+ /* Take care of easy cases first */
+ switch (BnnCompare (nn, nl, dd, dl))
+ {
+ case BN_LT: /* n < d */
+ ; /* N => R */
+ BnnSetToZero (nn+dl, nl-dl); /* 0 => Q */
+ return;
+ case BN_EQ: /* n == d */
+ BnnSetToZero (nn, nl); /* 0 => R */
+ BnnSetDigit (nn+dl, 1); /* 1 => Q */
+ /* bug fixed Mon Apr 15 18:36:50 GMT+2:00 1991 by jch,
+ was BnnSetDigit (nn+nl-1, 1); */
+ return;
+ }
+
+ /* here: n > d */
+
+ /* If divisor is just 1 digit, use a special divide */
+ if (dl == 1)
+ *nn = BnnDivideDigit (nn+1, nn, nl, *dd); /* note: nn+1 = nn+dl */
+ /* Otherwise, divide one digit at a time */
+ else
+ {
+ /* Normalize */
+ nshift = BnnNumLeadingZeroBitsInDigit (*(dd+dl-1));
+ BnnShiftLeft (dd, dl, nshift);
+ BnnShiftLeft (nn, nl, nshift);
+
+ /* Divide */
+ divide (nn, nl-1, dd, dl);
+
+ /* Unnormalize */
+ BnnShiftRight (dd, dl, nshift);
+ BnnShiftRight (nn, dl, nshift);
+ /* note: unnormalize N <=> unnormalize R (with R < D) */
+ }
+}
diff --git a/otherlibs/num/bignum/c/bn/bnInit.c b/otherlibs/num/bignum/c/bn/bnInit.c
new file mode 100644
index 000000000..d02301508
--- /dev/null
+++ b/otherlibs/num/bignum/c/bn/bnInit.c
@@ -0,0 +1,74 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Fri Oct 5 16:28:39 GMT+1:00 1990 by herve */
+/* modified_on Fri Mar 30 3:28:56 GMT+2:00 1990 by shand */
+
+
+/* bnInit.c: a piece of the bignum kernel written in C */
+
+
+ /***************************************/
+
+#define BNNMACROS_OFF
+#include "BigNum.h"
+
+static int Initialized = FALSE;
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)bnInit.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n";
+
+
+ /***************************************/
+
+void BnnInit ()
+{
+ if (!Initialized)
+ {
+
+
+ Initialized = TRUE;
+ }
+}
+
+ /***************************************/
+
+void BnnClose ()
+{
+ if (Initialized)
+ {
+
+
+ Initialized = FALSE;
+ }
+}
+
+ /***************************************/
+
+ /* some U*ix standard functions do not exist on VMS */
+ /* neither on MSDOS */
+
+#ifdef NOMEM
+
+/* Copies LENGTH bytes from string SRC to string DST */
+void bcopy(src, dst, length)
+char *src, *dst;
+register int length;
+{
+ for (; length > 0; length--)
+ *dst++ = *src++;
+}
+
+/* Places LENGTH 0 bytes in the string B */
+void bzero(buffer, length)
+char *buffer;
+register int length;
+{
+ for (; length>0; length--)
+ *buffer++ = 0;
+}
+
+#endif
+
+
+
+ /***************************************/
diff --git a/otherlibs/num/bignum/c/bn/bnMult.c b/otherlibs/num/bignum/c/bn/bnMult.c
new file mode 100644
index 000000000..f4ecf8337
--- /dev/null
+++ b/otherlibs/num/bignum/c/bn/bnMult.c
@@ -0,0 +1,84 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Tue Oct 9 10:43:48 GMT+1:00 1990 by herve */
+/* modified_on Fri Mar 30 4:13:47 GMT+2:00 1990 by shand */
+
+
+/* bnMult.c: a piece of the bignum kernel written in C */
+
+
+ /***************************************/
+
+#define BNNMACROS_OFF
+#include "BigNum.h"
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)bnMult.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n";
+
+
+BigNumCarry BnnMultiply (pp, pl, mm, ml, nn, nl)
+
+register BigNum pp, nn;
+ BigNum mm;
+register BigNumLength pl, nl;
+ BigNumLength ml;
+
+/*
+ * Performs the product:
+ * Q = P + M * N
+ * BB = BBase(P)
+ * Q mod BB => P
+ * Q div BB => CarryOut
+ *
+ * Returns the CarryOut.
+ *
+ * Assumes:
+ * Size(P) >= Size(M) + Size(N),
+ * Size(M) >= Size(N).
+ */
+
+{
+ BigNumCarry c;
+
+ /* Multiply one digit at a time */
+
+ /* the following code give higher performance squaring.
+ ** Unfortunately for small nl, procedure call overheads kills it
+ */
+#ifndef mips_v131
+#ifndef MSDOS
+ /* Squaring code provoke a mips optimizer bug in V1.31 */
+ /* It also doesn't work using MSDOS */
+ if (mm == nn && ml == nl && nl > 6)
+ {
+ register BigNumDigit n_prev = 0;
+ /* special case of squaring */
+ for (c = 0; nl > 0; )
+ {
+ register BigNumDigit n = *nn;
+ c += BnnMultiplyDigit(pp, pl, nn, 1, n);
+ if (n_prev)
+ c += BnnAdd(pp, pl, nn, 1, (BigNumCarry) 0);
+ nl--, nn++;
+ pp += 2, pl -= 2;
+ c += BnnMultiplyDigit(pp-1, pl+1, nn, nl, n+n+n_prev);
+ /* note following if statements are resolved at compile time */
+ if (sizeof(BigNumDigit) == sizeof(short))
+ n_prev = ((short) n) < 0;
+ else if (sizeof(BigNumDigit) == sizeof(int))
+ n_prev = ((int) n) < 0;
+ else if (sizeof(BigNumDigit) == sizeof(long))
+ n_prev = ((long) n) < 0;
+ else
+ n_prev = ((n<<1)>>1) == n;
+ }
+ }
+ else
+#endif
+#endif
+ for (c = 0; nl-- > 0; pp++, nn++, pl--)
+ c += BnnMultiplyDigit (pp, pl, mm, ml, *nn);
+
+ return c;
+}
+
diff --git a/otherlibs/num/bignum/c/bz.c b/otherlibs/num/bignum/c/bz.c
new file mode 100644
index 000000000..10d0c224f
--- /dev/null
+++ b/otherlibs/num/bignum/c/bz.c
@@ -0,0 +1,833 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Thu Apr 4 20:01:18 GMT+2:00 1991 by herve */
+/* modified_on Thu Mar 22 20:45:38 GMT+1:00 1990 by shand */
+
+
+/* bz.c: provides an implementation of "unlimited-precision"
+ * arithmetic for signed integers.
+ *
+ * Several conventions are used in the commentary:
+ * A "BigZ" is the name for an arbitrary-precision signed integer.
+ * Capital letters (e.g., "Z") are used to refer to the value of BigZs.
+ */
+
+
+#include "BigZ.h"
+
+
+ /***************************************/
+/*
+#include <stdio.h>
+#include <macros.h>
+#include <math.h>
+#include <malloc.h>
+#include <values.h>
+*/
+
+#define NULL 0
+#define max(a,b) (a<b ? b : a)
+#define abs(x) (x>=0 ? x : -(x))
+#define M_LN2 0.69314718055994530942
+#define M_LN10 2.30258509299404568402
+#define BITSPERBYTE 8
+#define BITS(type) (BITSPERBYTE * (int)sizeof(type))
+#define HIBITI (1 << BITS(int) - 1)
+#define MAXINT (~HIBITI)
+
+ /***************************************/
+
+#define BzToBn(z) ((z)->Digits)
+#define CTOI(c) (c >= '0' && c <= '9' ? c - '0' :\
+ c >= 'a' && c <= 'f' ? c - 'a' + 10:\
+ c >= 'A' && c <= 'F' ? c - 'A' + 10:\
+ 0)
+
+extern char *malloc();
+
+ /*** copyright ***/
+
+static char copyright[]="@(#)bz.c: copyright Digital Equipment Corporation & INRIA 1988, 1989\n";
+
+
+ /***************************************/
+
+static int Initialized = FALSE;
+
+/* constants used by BzToString() and BzFromString() */
+static double BzLog [] =
+{
+ 0,
+ 0, /* log (1) */
+ M_LN2, /* log (2) */
+ 1.098612, /* log (3) */
+ 1.386294, /* log (4) */
+ 1.609438, /* log (5) */
+ 1.791759, /* log (6) */
+ 1.945910, /* log (7) */
+ 2.079442, /* log (8) */
+ 2.197225, /* log (9) */
+ M_LN10, /* log (10) */
+ 2.397895, /* log (11) */
+ 2.484907, /* log (12) */
+ 2.564949, /* log (13) */
+ 2.639057, /* log (14) */
+ 2.708050, /* log (15) */
+ 2.772588, /* log (16) */
+};
+
+/* */
+
+
+#ifndef _NO_PROTO
+void BzInit (void)
+#else /* _NO_PROTO */
+void BzInit ()
+#endif /* _NO_PROTO */
+{
+ if (!Initialized)
+ {
+ BnnInit ();
+ Initialized = TRUE;
+ }
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+BigZ BzCreate (BigNumLength Size)
+#else /* _NO_PROTO */
+BigZ BzCreate (Size)
+BigNumLength Size;
+#endif /* _NO_PROTO */
+
+/*
+ * Allocates a BigZ of the desired size.
+ * Sets it to 0.
+ */
+
+{
+ BigZ z;
+
+
+ if ((z = (BigZ) (malloc (sizeof (struct BigZHeader) + Size * sizeof (BigNumDigit)))) != NULL)
+ {
+ /* reset digits */
+ BnnSetToZero (BzToBn (z), Size);
+
+ /* init header */
+ BzSetSize (z, Size);
+ BzSetSign (z, BZ_ZERO);
+ }
+
+ return (z);
+}
+
+
+
+#ifndef _NO_PROTO
+void BzFree (BigZ z)
+#else /* _NO_PROTO */
+void BzFree (z)
+BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Frees an existing BigZ.
+ */
+
+{
+ free (z);
+}
+
+ /***************************************/
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+void BzFreeString (char *s)
+#else /* _NO_PROTO */
+void BzFreeString (s)
+char *s;
+#endif /* _NO_PROTO */
+
+/*
+ * Frees an existing BigZ allocated string.
+ */
+
+{
+ free (s);
+}
+
+ /***************************************/
+/* */
+
+#ifndef _NO_PROTO
+BigNumLength BzNumDigits (BigZ z)
+#else /* _NO_PROTO */
+BigNumLength BzNumDigits (z)
+BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns the number of digits used by z.
+ */
+
+{
+ return (BnnNumDigits (BzToBn (z), BzGetSize (z)));
+}
+
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+BigZ BzCopy (BigZ z)
+#else /* _NO_PROTO */
+BigZ BzCopy (z)
+BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Creates a copy of the passed BigZ.
+ */
+
+{
+ BigZ y;
+ int zl;
+
+
+ zl = BzNumDigits (z);
+ if ((y = BzCreate (zl)) != NULL)
+ {
+ /* copy the digits */
+ BnnAssign (BzToBn (y), BzToBn (z), zl);
+
+ /* copy the header WITHOUT the size !! */
+ BzSetSign (y, BzGetSign (z));
+ }
+
+ return (y);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigZ BzNegate (BigZ z)
+#else /* _NO_PROTO */
+BigZ BzNegate (z)
+BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Negates the passed BigZ.
+ */
+
+{
+ BigZ y;
+
+ y = BzCopy (z);
+ BzSetSign (y, BzGetOppositeSign (z));
+
+ return (y);
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+BigZ BzAbs (BigZ z)
+#else /* _NO_PROTO */
+BigZ BzAbs (z)
+BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Takes the absolute value of the passed BigZ.
+ */
+
+{
+ BigZ y;
+
+ y = BzCopy (z);
+ BzSetSign (y, abs (BzGetSign (z)));
+
+ return (y);
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+BzCmp BzCompare (BigZ y, BigZ z)
+#else /* _NO_PROTO */
+BzCmp BzCompare (y, z)
+BigZ y; BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns BZ_GT if Y > Z,
+ * BZ_LT if Y < Z,
+ * BZ_EQ otherwise.
+ */
+
+{
+ return (BzGetSign (y) > BzGetSign (z) ? BZ_GT :
+ BzGetSign (y) < BzGetSign (z) ? BZ_LT :
+ BzGetSign (y) > 0 ? BnnCompare (BzToBn (y), BzGetSize (y),
+ BzToBn (z), BzGetSize (z)) :
+ BzGetSign (y) < 0 ? BnnCompare (BzToBn (z), BzGetSize (z),
+ BzToBn (y), BzGetSize (y)) :
+ BZ_EQ);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigZ BzAdd (BigZ y, BigZ z)
+#else /* _NO_PROTO */
+BigZ BzAdd (y, z)
+BigZ y; BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns Y + Z.
+ */
+
+{
+ BigZ n;
+ int yl;
+ int zl;
+
+
+ yl = BzNumDigits (y);
+ zl = BzNumDigits (z);
+
+ if (BzGetSign (y) == BzGetSign (z))
+ {
+ /* Add magnitudes if signs are the same */
+ switch (BnnCompare (BzToBn (y), yl, BzToBn (z), zl))
+ {
+ case BZ_EQ:
+ case BZ_GT: /* |Y| >= |Z| */
+
+ if ((n = BzCreate (yl+1)) != NULL)
+ {
+ BnnAssign (BzToBn (n), BzToBn (y), yl);
+ BnnAdd (BzToBn (n), yl+1, BzToBn (z), zl, (BigNumCarry) 0);
+ BzSetSign (n, BzGetSign (y));
+ }
+ break;
+
+ default: /* BZ_LT: |Y| < |Z| */
+
+ if ((n = BzCreate (zl+1)) != NULL)
+ {
+ BnnAssign (BzToBn (n), BzToBn (z), zl);
+ BnnAdd (BzToBn (n), zl+1, BzToBn (y), yl, (BigNumCarry) 0);
+ BzSetSign (n, BzGetSign (z));
+ }
+ break;
+ }
+ }
+/* */
+
+
+ else
+ {
+ /* Subtract magnitudes if signs are different */
+ switch (BnnCompare (BzToBn (y), yl, BzToBn (z), zl))
+ {
+ case BZ_EQ: /* Y = -Z */
+
+ n = BzCreate (1);
+ break;
+
+ case BZ_GT: /* |Y| > |Z| */
+
+ if ((n = BzCreate (yl)) != NULL)
+ {
+ BnnAssign (BzToBn (n), BzToBn (y), yl);
+ BnnSubtract (BzToBn (n), yl, BzToBn (z), zl, (BigNumCarry) 1);
+ BzSetSign (n, BzGetSign (y));
+ }
+ break;
+
+ default: /* BZ_LT: |Y| < |Z| */
+
+ if ((n = BzCreate (zl)) != NULL)
+ {
+ BnnAssign (BzToBn (n), BzToBn (z), zl);
+ BnnSubtract (BzToBn (n), zl, BzToBn (y), yl, (BigNumCarry) 1);
+ BzSetSign (n, BzGetSign (z));
+ }
+ break;
+ }
+ }
+
+ return (n);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigZ BzSubtract (BigZ y, BigZ z)
+#else /* _NO_PROTO */
+BigZ BzSubtract (y, z)
+BigZ y; BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns Y - Z.
+ */
+
+{
+ if (y == z)
+ return (BzCreate (1));
+ else
+ {
+ BigZ diff;
+
+ BzSetSign (z, BzGetOppositeSign (z));
+ diff = BzAdd (y, z);
+ BzSetSign (z, BzGetOppositeSign (z));
+
+ return diff;
+ }
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigZ BzMultiply (BigZ y, BigZ z)
+#else /* _NO_PROTO */
+BigZ BzMultiply (y, z)
+BigZ y; BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns Y * Z.
+ */
+
+{
+ BigZ n;
+ int yl, zl;
+
+
+ yl = BzNumDigits (y);
+ zl = BzNumDigits (z);
+
+ if ((n = BzCreate (yl+zl)) != NULL)
+ {
+ BnnMultiply (BzToBn (n), yl+zl, BzToBn (y), yl, BzToBn (z), zl);
+ BzSetSign (n, BzGetSign (y) * BzGetSign (z));
+ }
+
+ return (n);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigZ BzDivide (BigZ y, BigZ z, BigZ *r)
+#else /* _NO_PROTO */
+BigZ BzDivide (y, z, r)
+BigZ y; BigZ z; BigZ *r;
+#endif /* _NO_PROTO */
+
+/*
+ * Sets Y mod Z => R,
+ * Returns Y div Z => Q
+ *
+ * such that Y = ZQ + R
+ * and 0 <= R < |Z|.
+ *
+ * Return NULL if Z = 0
+ *
+ * Return floor(Y/Z) if Z > 0
+ * otherwise return ceil(Y/Z)
+ * where / is the real numbers division.
+ */
+
+{
+ BigZ q;
+ int yl, zl, ql, rl;
+ Boolean rnotnul;
+
+
+ if (BzGetSign (z) == BZ_ZERO)
+ return (NULL);
+
+ yl = BzNumDigits (y);
+ zl = BzNumDigits (z);
+
+ /* max +1 since BnnAddCarry can overflow */
+ ql = max (yl-zl+1, 1) +1;
+ rl = max (zl,yl) + 1;
+
+ /* Set up quotient, remainder */
+ q = BzCreate (ql);
+ *r = BzCreate (rl);
+
+ if (!*r || !q)
+ return (NULL);
+
+ BnnAssign (BzToBn (*r), BzToBn (y), yl);
+
+ /* Do the division */
+ BnnDivide (BzToBn (*r), rl, BzToBn (z), zl);
+ BnnAssign (BzToBn (q), BzToBn (*r) + zl, rl-zl);
+ BnnSetToZero (BzToBn (*r) + zl, rl-zl);
+ rl = zl;
+
+ /* Correct the signs, adjusting the quotient and remainder */
+ rnotnul = !BnnIsZero (BzToBn (*r), rl);
+ if (BzGetSign (y) == BZ_MINUS && rnotnul)
+ {
+ /* Y < 0, R > 0: (Q+1)=>Q, Z-R=>R */
+ BnnAddCarry (BzToBn (q), ql, (BigNumCarry) 1);
+
+ BzSetSign (q, BzGetOppositeSign (z));
+ BnnComplement (BzToBn (*r), rl);
+ BnnAdd (BzToBn (*r), rl, BzToBn (z), zl, (BigNumCarry) 1);
+ }
+ else
+ BzSetSign (q, BzGetSign (y) * BzGetSign (z));
+
+ if (BnnIsZero (BzToBn(q),ql))
+ BzSetSign (q,BZ_ZERO);
+
+ /* Correct the sign of the remainder */
+ if (rnotnul)
+ BzSetSign (*r, BZ_PLUS);
+
+ return (q);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigZ BzDiv (BigZ y, BigZ z)
+#else /* _NO_PROTO */
+BigZ BzDiv (y, z)
+BigZ y; BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns Y div Z.
+ *
+ * Return NULL if Z = 0
+ *
+ * Return floor(Y/Z) if Z > 0
+ * otherwise return ceil(Y/Z)
+ * where / is the real numbers division
+ */
+
+{
+ BigZ q, r;
+
+
+ q = BzDivide (y, z, &r);
+ BzFree (r);
+
+ return (q);
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+BigZ BzMod (BigZ y, BigZ z)
+#else /* _NO_PROTO */
+BigZ BzMod (y, z)
+BigZ y; BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns Y mod Z.
+ */
+
+{
+ BigZ r;
+
+
+ BzFree (BzDivide (y, z, &r));
+
+ return (r);
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+char * BzToString (BigZ z, BigNumDigit base)
+#else /* _NO_PROTO */
+char * BzToString (z, base)
+BigZ z; BigNumDigit base;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns a pointer to a string that represents Z in the specified base.
+ * Assumes 2 <= base <= 16.
+ */
+
+{
+ char * string;
+ BigZ y, q, t;
+ BigNumDigit r;
+
+ static char Digit[] = "0123456789ABCDEF";
+ char * s;
+ int sd;
+ int zl, sl;
+
+
+ if (base < 2 || base > 16)
+ return (NULL);
+
+ /* Allocate BigNums and set up string */
+ zl = BzNumDigits (z) + 1;
+ sl = BzLog[2] * BN_DIGIT_SIZE * zl / BzLog[base] + 3;
+
+ y = BzCreate (zl);
+ q = BzCreate (zl);
+
+ string = malloc (sl * sizeof (char));
+
+ if (!y || !q || !string)
+ return (NULL);
+
+ BnnAssign (BzToBn (y), BzToBn (z), zl-1);
+ s = string + sl;
+
+ /* Divide Z by base repeatedly; successive digits given by remainders */
+ *--s = '\0';
+ if (BzGetSign (z) == BZ_ZERO)
+ *--s = '0';
+ else
+ do
+ {
+ r = BnnDivideDigit (BzToBn (q), BzToBn (y), zl, base);
+ *--s = Digit[r];
+
+ /* exchange y and q (to avoid BzMove (y, q) */
+ t = q, q = y, y = t;
+ } while (!BnnIsZero (BzToBn (y), zl));
+
+ /* Set sign if negative */
+ if (BzGetSign (z) < 0)
+ *--s = '-';
+
+ /* and move string into position */
+ if ((sd = s-string) > 0)
+ while (s < string + sl)
+ {
+ *(s-sd) = *s;
+ s++;
+ }
+
+ /* Free temporary BigNums and return the string */
+ BzFree(y);
+ BzFree(q);
+
+ return string;
+}
+
+ /***************************************/
+/* */
+
+
+#ifndef _NO_PROTO
+BigZ BzFromString (char *s, BigNumDigit base)
+#else /* _NO_PROTO */
+BigZ BzFromString (s, base)
+char *s; BigNumDigit base;
+#endif /* _NO_PROTO */
+
+/*
+ * Creates a BigZ whose value is represented by "string" in the
+ * specified base. The "string" may contain leading spaces,
+ * followed by an optional sign, followed by a series of digits.
+ * Assumes 2 <= base <= 16.
+ * When called from C, only the first 2 arguments are passed.
+ */
+
+{
+ BigZ z, p, t;
+ BzSign sign;
+ int zl;
+
+
+ /* Throw away any initial space */
+ while (*s == ' ')
+ s++;
+
+ /* Allocate BigNums */
+ zl = strlen (s) * BzLog[base] / (BzLog[2] * BN_DIGIT_SIZE) + 1;
+
+ z = BzCreate (zl);
+ p = BzCreate (zl);
+
+ if (!z || !p)
+ return (NULL);
+
+ /* Set up sign, base, initialize result */
+ sign = (*s == '-' ? (s++, BZ_MINUS) : *s == '+' ? (s++, BZ_PLUS) : BZ_PLUS);
+
+ /* Multiply in the digits of the string, one at a time */
+ for (; *s != '\0'; s++)
+ {
+ BnnSetToZero (BzToBn (p), zl);
+ BnnSetDigit (BzToBn (p), CTOI (*s));
+ BnnMultiplyDigit (BzToBn (p), zl, BzToBn (z), zl, base);
+
+ /* exchange z and p (to avoid BzMove (z, p) */
+ t = p, p = z, z = t;
+ }
+
+ /* Set sign of result */
+ BzSetSign (z, BnnIsZero (BzToBn (z), zl) ? BZ_ZERO : sign);
+
+ /* Free temporary BigNums */
+ BzFree (p);
+
+ return (z);
+}
+
+ /***************************************/
+
+#ifndef _NO_PROTO
+BigZ BzFromInteger (int i)
+#else /* _NO_PROTO */
+BigZ BzFromInteger (i)
+int i;
+#endif /* _NO_PROTO */
+
+{
+ BigZ z;
+
+
+ z = BzCreate (1);
+
+ z->Digits[0] = abs (i);
+
+ if (i > 0)
+ BzSetSign (z, BZ_PLUS);
+ else
+ if (i < 0)
+ BzSetSign (z, BZ_MINUS);
+ else
+ BzSetSign (z, BZ_ZERO);
+
+ return z;
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+int BzToInteger (BigZ z)
+#else /* _NO_PROTO */
+int BzToInteger (z)
+BigZ z;
+#endif /* _NO_PROTO */
+
+{
+ if (BzNumDigits (z) > 1)
+ return (MAXINT);
+
+ if (BzGetSign (z) == BZ_MINUS)
+ return (- z->Digits[0]);
+ else
+ return (z->Digits[0]);
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+BigZ BzFromBigNum (BigNum n, BigNumLength nl)
+#else /* _NO_PROTO */
+BigZ BzFromBigNum (n, nl)
+BigNum n; BigNumLength nl;
+#endif /* _NO_PROTO */
+
+{
+ BigZ z;
+ int i;
+
+
+ z = BzCreate (nl);
+
+ /* set the sign of z such that the pointer n is unchanged yet */
+ if (BnnIsZero (n, nl))
+ BzSetSign (z, BZ_ZERO);
+ else
+ BzSetSign (z, BZ_PLUS);
+
+ for (i = 0; i < nl; i++, n++)
+ z->Digits[i] = *n;
+
+ return z;
+}
+
+ /***************************************/
+
+#ifndef _NO_PROTO
+BigNum BzToBigNum (BigZ z, BigNumLength *nl)
+#else /* _NO_PROTO */
+BigNum BzToBigNum (z, nl)
+BigZ z; BigNumLength *nl;
+#endif /* _NO_PROTO */
+
+{
+ BigNum n, m;
+ int i;
+
+
+ if (BzGetSign (z) == BZ_MINUS)
+ return NULL;
+
+ *nl = BzNumDigits (z);
+
+ if ((n = (BigNum) (malloc (((*nl+1) * sizeof (BigNumDigit))))) != NULL)
+ {
+ *n = *nl; /* set size */
+
+ for (i = 0, m = ++n; i < *nl; i++, m++)
+ *m = z->Digits[i];
+ }
+
+ return n;
+}
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+void BzClose (void)
+#else /* _NO_PROTO */
+void BzClose ()
+#endif /* _NO_PROTO */
+{
+ if (Initialized)
+ {
+ BnnClose ();
+ Initialized = FALSE;
+ }
+}
+
+ /***************************************/
diff --git a/otherlibs/num/bignum/c/bzf.c b/otherlibs/num/bignum/c/bzf.c
new file mode 100644
index 000000000..7186452aa
--- /dev/null
+++ b/otherlibs/num/bignum/c/bzf.c
@@ -0,0 +1,50 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Mon Jan 23 16:05:27 GMT+1:00 1989 by herve */
+
+/*
+ * bzf.c: Miscellaneous functions built on top of BigZ.
+ *
+ */
+
+
+#include "BigZ.h"
+
+ /***************************************/
+
+#define BzToBn(z) ((z)->Digits)
+
+ /***************************************/
+
+
+#ifndef _NO_PROTO
+BigZ BzFactorial (BigZ z)
+#else /* _NO_PROTO */
+BigZ BzFactorial (z)
+BigZ z;
+#endif /* _NO_PROTO */
+
+/*
+ * Returns Z!
+ * Assumes Z < Base.
+ */
+
+{
+ BigZ f;
+ BigNumDigit zval;
+ int fl = 1;
+
+
+ zval = BnnGetDigit (BzToBn (z));
+ f = BzCreate (zval+1);
+ BnnSetDigit (BzToBn (f), 1);
+ BzSetSign (f, BzGetSign (z));
+
+ while (zval-- > 1)
+ {
+ BnnMultiplyDigit (BzToBn (f), fl+1, BzToBn (f), fl, zval);
+ fl = BnnNumDigits (BzToBn (f), fl+1);
+ }
+
+ return (f);
+}
+
diff --git a/otherlibs/num/bignum/c/bztest.c b/otherlibs/num/bignum/c/bztest.c
new file mode 100644
index 000000000..2d06b184e
--- /dev/null
+++ b/otherlibs/num/bignum/c/bztest.c
@@ -0,0 +1,167 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Tue Feb 25 1:27:57 GMT+1:00 1992 by shand */
+/* modified_on Mon Apr 15 18:44:14 GMT+2:00 1991 by herve */
+
+#include <stdio.h>
+#include "BigZ.h"
+
+#ifndef MSDOS
+#define S(A,B) strcmp(A,B)
+#define P(A) fprintf(stderr,"%d...",A)
+#define E(A,B,C) fprintf(stderr,"\nError in test #%d:\nComputed: %s\nCorrect: %s\n",A,C,B)
+#define T(A,B,C) S(B,C)?E(A,B,C):P(A)
+#else
+void T(A,B,C)
+int A;
+char *B, *C;
+{
+ if (strcmp (B, C))
+ fprintf (stderr, "\nError in test #%d:\nComputed: %s\nCorrect: %s\n",A,C,B);
+ else
+ fprintf (stderr,"%2d...",A);
+}
+#endif
+#define NEWLINE fprintf(stderr,"\n")
+#define To(A) BzToString(A,10)
+#define From(A) BzFromString(A,10)
+#define Abs(A) BzAbs(A)
+#define Neg(A) BzNegate(A)
+#define Add(A,B) BzAdd(A,B)
+#define Sub(A,B) BzSubtract(A,B)
+#define Mul(A,B) BzMultiply(A,B)
+#define Div(A,B) BzDiv(A,B)
+#define Mod(A,B) BzMod(A,B)
+#define Fac(A) BzFactorial(A)
+#define FromI(I) BzFromInteger(I)
+#define Cmp(A,B) BzCompare(A,B)
+#define Sqa(A) Mul(A,A)
+
+#define zero FromI(0)
+#define one FromI(1)
+#define two FromI(2)
+#define minusone FromI(-1)
+
+#ifdef DIGITonUSHORT
+#define two31m1 Sub(Mul(From("65536"),From("32768")),one)
+#else
+#define two31m1 FromI(0x7FFFFFFF)
+#endif
+
+main()
+{
+ BigZ a,b;
+
+ T(1,"12", To(From("12"))) ;
+ T(2,"12345678910", To(From("12345678910"))) ;
+ T(3,"123", To(From("00000123"))) ;
+ T(4,"-123", To(From("-123"))) ;
+ T(5,"-32768", To(From("-32768"))) ;
+ T(6,"-32768", To(Neg(From("32768")))) ;
+ T(7,"-32768", To(Add(From("-16384"),From("-16384")))) ;
+ T(8,"-32768", To(Add(From("-16383"),From("-16385")))) ;
+ T(9,"-32768", To(Mul(From("2"),From("-16384")))) ;
+ T(10,"-16384", To(Div(From("-32768"),From("2")))) ;
+ NEWLINE;
+ T(11,"100000", To(Add(From("1"),From("99999")))) ;
+ T(12,"12343994",To(Add(From("-1684"),From("12345678"))));
+ T(13,"-12329294",To(Sub(From("16384"),From("12345678"))));
+ T(14,"135801",To(Add(From("12345"),From("123456"))));
+ T(15,"123456135801",To(Add(From("12345"),From("123456123456"))));
+ T(16,"135801",To(Add(From("123456"),From("12345"))));
+ T(17,"123456135801",To(Add(From("123456123456"),From("12345"))));
+ T(18,"135801",To(Sub(From("12345"),From("-123456"))));
+ T(19,"123456135801",To(Sub(From("12345"),From("-123456123456"))));
+ T(20,"135801",To(Sub(From("123456"),From("-12345"))));
+ NEWLINE;
+ T(21,"123456135801",To(Sub(From("123456123456"),From("-12345"))));
+ T(22,"-111111",To(Sub(From("12345"),From("123456"))));
+ T(23,"111111",To(Sub(From("123456"),From("12345"))));
+ T(24,"-123456111111",To(Sub(From("12345"),From("123456123456"))));
+ T(25,"123456111111",To(Sub(From("123456123456"),From("12345"))));
+ T(26,"-111111",To(Add(From("12345"),From("-123456"))));
+ T(27,"111111",To(Add(From("123456"),From("-12345"))));
+ T(28,"-123456111111",To(Add(From("12345"),From("-123456123456"))));
+ T(29,"123456111111",To(Add(From("123456123456"),From("-12345"))));
+ T(30,"2", To(Div(From("264195"),From("97200")))) ;
+ NEWLINE;
+ T(31,"27405", To(Mod(From("97200"),From("69795")))) ;
+ T(32,"4294967295", To(Div(From("22685491128062564230891640495451214097"),From("5281877500950955845296219748")))) ;
+ T(33,"99997",To(Add(From("-3"),From("100000"))));
+ T(34,"-100003",To(Add(From("-3"),From("-100000"))));
+ T(35,"999999",To(Sub(From("1000000"),From("1"))));
+ T(36,"999999999",To(Mul(From("12345679"),From("81"))));
+ a = From("1234567");
+ b = From("123456");
+ T(37,"1234567",To(Add(Mul(Div(a,b),b),Mod(a,b))));
+ T(38,"-1234567",To(Add(Mul(Div(Neg(a),Neg(b)),Neg(b)),Mod(Neg(a),Neg(b)))));
+ T(39,"1234567",To(Add(Mul(Div(a,Neg(b)),Neg(b)),Mod(a,Neg(b)))));
+ T(40,"10000000000000000000000",To(Mul(From("-100000000000"),From("-100000000000"))));
+ NEWLINE;
+ T(41,"-10000000000000000000000",To(Mul(From("-100000000000"),From("100000000000"))));
+ T(42,"-10000000000000000000000",To(Mul(From("100000000000"),From("-100000000000"))));
+ T(43,"10000000000000000000000",To(Mul(From("100000000000"),From("100000000000"))));
+ a = Sub(From("10000000000000"),From("10000000000000"));
+ T(44,"0",To(Mod(a,From("1000000000000"))));
+ T(45,"0",To(Div(a,From("1000000000000"))));
+ T(46,"0",To(Mod(Neg(a),From("10000000000000"))));
+ T(47,"0",To(Div(Neg(a),From("10000000000000"))));
+ T(48,"2",To(Div(From("3000"),Sub(From("1234567891234"),From("1234567890000")))));
+ T(49,"532",To(Mod(From("3000"),Sub(From("1234567891234"),From("1234567890000")))));
+ T(50,"9",To(Mod(From("-1234567890"),From("1234567899"))));
+ NEWLINE;
+ T(51,"2",To(Mod(Sub(From("12345678900000"),From("12345678926887")),From("3"))));
+ T(52,"40830949904677684825316369628906250000000000000",To(Mul(From("48270948888581289062500000000"),From("845870049062500000"))));
+ T(53,"22666179639240748063923391983020279316955515",To(Mul(From("6956883693"),From("3258093801689886619170103176686855"))));
+ T(54,"1405006117752879898543142606244511569936384000000000",To(Fac(From("42"))));
+ T(55,"0",To(Mod(Fac(From("13")),Fac(From("9")))));
+ T(56,"0",To(Mod(Fac(From("34")),Fac(From("13")))));
+ T(57,"0",To(Mod(Fac(From("57")),Fac(From("21")))));
+ T(58,"0",To(Mod(Fac(From("40")),Fac(From("39")))));
+ T(59,"59",To(Div(Fac(From("59")),Fac(From("58")))));
+ T(60,"2",To(Div(From("5"),From("2"))));
+ NEWLINE;
+ T(61,"1",To(Mod(From("5"),From("2"))));
+ T(62,"-3",To(Div(From("-5"),From("2"))));
+ T(63,"1",To(Mod(From("-5"),From("2"))));
+ T(64,"3",To(Div(From("-5"),From("-2"))));
+ T(65,"1",To(Mod(From("-5"),From("-2"))));
+ T(66,"-2",To(Div(From("5"),From("-2"))));
+ T(67,"1",To(Mod(From("5"),From("-2"))));
+ T(68,"3",To(Div(From("6"),From("2"))));
+ T(69,"0",To(Mod(From("6"),From("2"))));
+ T(70,"-3",To(Div(From("-6"),From("2"))));
+ NEWLINE;
+ T(71,"0",To(Mod(From("-6"),From("2"))));
+ T(72,"3",To(Div(From("-6"),From("-2"))));
+ T(73,"0",To(Mod(From("-6"),From("-2"))));
+ T(74,"-3",To(Div(From("6"),From("-2"))));
+ T(75,"0",To(Mod(From("6"),From("-2"))));
+ T(76,"0",To(Abs(From("0"))));
+ T(77,"1234567890",To(Abs(From("1234567890"))));
+ T(78,"1234567890",To(Abs(From("-1234567890"))));
+ T(79,"1",BzCompare(From("-1234567890"),From("12345"))<0?"1":"0");
+ T(80,"1",BzGetSign(From("-1234567890"))<0?"1":"0");
+ NEWLINE;
+ T(81,"0", To(Add(From("-1"),Mul(From("-1"),From("-1")))));
+ T(82,"-1",To(Add(From("-1"),Mul(From("0"), From("-1")))));
+ T(83,"-3",To(Add(From("-1"),Mul(From("-2"),From("1" )))));
+ T(84,"1", To(Add(From("-1"),Mul(From("-2"),From("-1")))));
+ T(85,"-1",To(Add(From("1"), Mul(From("-2"),From("1" )))));
+ T(86,"18446744065119617025",To(Mul(From("4294967295"),From("4294967295"))));
+ /* (-2^64 + 2^32 - 1) / 2^32 */
+ T(87,"-4294967296",To(Div(
+ Sub(Mul(Mul(Add(Mul(two31m1,two),one),Mul(Add(two31m1,one), two)),minusone),one),
+ Mul(Add (two31m1,one),two))));
+ T(88,"Equal",(Cmp(Mod(FromI(10),FromI(5)),zero) == BZ_EQ)?"Equal":"Not equal");
+ T(89,"Equal",(Cmp(Div(FromI(4),FromI(5)),zero) == BZ_EQ)?"Equal":"Not equal");
+ a = From ("100000000000000000000000000000000000000");
+ T(90,To (a),To(Div (Sqa (a),a)));
+ /* 90: tests the MIPS & turbo C optimizer bugs. If the special */
+ /* purpose squaring code is enabled and the optimizer */
+ /* messes up, this test will fail */
+ NEWLINE;
+ b = Sqa (a);
+ T(91,To (b),To(Div (Sqa (b),b)));
+ T(92,"-1",To(Div(From("13"),From("-13"))));
+ NEWLINE;
+}
diff --git a/otherlibs/num/bignum/c/testKerN.c b/otherlibs/num/bignum/c/testKerN.c
new file mode 100644
index 000000000..22faa3224
--- /dev/null
+++ b/otherlibs/num/bignum/c/testKerN.c
@@ -0,0 +1,1085 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* testKerN.c: tests des primitives de KerN */
+/* Last modified_on Thu Feb 20 17:26:13 GMT+1:00 1992 by shand */
+/* modified_on Wed Feb 14 16:14:04 GMT+1:00 1990 by herve */
+/* modified_on 17-OCT-1989 20:35:55.91 by Jim Lawton */
+
+/* You can comment the line below if you want to test the C macro Package
+ instead of C or Assembly functions. */
+
+#define BNNMACROS_OFF 1
+
+
+#include "BigNum.h"
+ /* old types of Bn */
+
+typedef BigNumDigit BigNumType; /* A BigNum's type */
+
+struct BigNumHeader /* The header of a BigNum */
+{
+ BigNumType type;
+ BigNumLength length;
+};
+
+ /* old functions of Bn */
+
+/*
+ * Creation and access to type and length fields.
+ */
+extern char *malloc();
+/* Allocates a BigNum structure and returns a pointer to it */
+BigNum BnAlloc(size) int size; {
+ register BigNum n;
+
+ n = (BigNum) (malloc(sizeof(struct BigNumHeader) +
+ size * sizeof(BigNumDigit))
+ + sizeof(struct BigNumHeader));
+ (((struct BigNumHeader *) n) - 1)->length = size;
+ return(n);
+}
+
+/* Allocates a BigNum, inserts its Type, and returns a pointer to it */
+BigNum BnCreate(type, size) BigNumType type; int size; {
+ register BigNum n;
+
+ n = BnAlloc(size);
+ (((struct BigNumHeader *) n) - 1)->type = type;
+ BnnSetToZero ((n+ 0), size);
+ return(n);
+}
+
+/* Frees a BigNum structure */
+BnFree(n) BigNum n; {
+ free(((struct BigNumHeader *) n) - 1);
+ return 1;
+}
+
+/* Returns the BigNum's Type */
+BigNumType BnGetType(n) BigNum n; {
+ return((((struct BigNumHeader *) n) - 1)->type);
+}
+
+/* Sets the BigNum's Type */
+BnSetType(n, type) BigNum n; BigNumType type; {
+ (((struct BigNumHeader *) n) - 1)->type = type;
+}
+
+/* Returns the number of digits allocated for the BigNum */
+BnGetSize(n) BigNum n; {
+ return((((struct BigNumHeader *) n) - 1)->length);
+}
+
+
+
+ /* structure d'un test */
+
+struct testenv {
+ char *name; /* Le nom de la fonction teste'e. */
+ int flag; /* Pour savoir si l'on continue le Test. */
+ char hist[2048]; /* L'expression qui provoque l'erreur. */
+ char *depend; /* De quoi depend le Test. */
+};
+
+
+ /* Les nombres pre'de'finies. */
+
+static BigNum NumbVect[5][2];
+static BigNum NumbProto, Ntmp2, NtmpBig;
+
+#define RN(n) NumbVect[n][0]
+#define SN(n) NumbVect[n][1]
+
+ /* Taille des nombres utilise's. */
+ /* de la forme 4(n + 1) */
+#define TESTLENGTH 16
+#define DTL TESTLENGTH/2
+#define QTL TESTLENGTH/4
+
+/* Nombre de test. */
+int TestCount, CallDummy = 0;
+
+int dummy()
+{
+ /* a simple way to get control after <n> steps in the debugger */
+ printf("TestCount = %d\n", TestCount);
+}
+
+int TestCountInc()
+{
+ TestCount++;
+ if (TestCount == CallDummy)
+ dummy();
+}
+
+ResetTest(n) int n; {
+ /* Remet le nieme nombre a` la valeur prototype. */
+ BnnAssign ((RN(n)+ 0), ( NumbProto+ 0), TESTLENGTH);
+ BnnAssign ((SN(n)+ 0), ( NumbProto+ 0), TESTLENGTH);
+}
+
+Check(n) int n; {
+ int i;
+ /* Verifie que les n nombres calcules correspondent aux simule's. */
+ for(i = 0; i < n; i++)
+ if(CheckSubRange(i, 0, TESTLENGTH)) return(1);
+ return(FALSE);
+}
+
+CheckSubRange(x, nd, nl) int x, nd, nl; {
+ /* Verifie l'e'galite' des sous-nombres
+ (RN(x), nd, nl) et (SN(x), nd, nl) */
+ while(nl) {
+ nl--;
+ if(BnnCompareDigits (*(RN(x)+ nd), *( SN(x)+ nd))) return(nd + 1);
+ nd++;
+ }
+ return(FALSE);
+}
+
+ShowDiff0(e, r1, r2) struct testenv *e; int r1,r2; {
+ ErrorPrint(e);
+ if(r1 != r2)
+ printf("---- Result is %d and should be %d----\n", r1, r2);
+ return(e->flag);
+}
+
+ShowDiff1(e, r1, r2, n, nd, nl)
+ struct testenv *e; char *n; int r1, r2, nd, nl; {
+ ErrorPrint(e);
+ if(r1 != r2)
+ printf("---- Result is %d and should be %d----\n", r1, r2);
+ ShowOutRange(0, n, nd, nl);
+ ShowSubNumber(0, n, nd, nl);
+ return(e->flag);
+}
+
+ShowDiff2(e, r1, r2, n, nd, nl, m, md, ml)
+ struct testenv *e; char *n, *m; int r1, r2, nd, nl, md, ml; {
+ ErrorPrint(e);
+ if(r1 != r2)
+ printf("---- Result is %d and should be %d----\n", r1, r2);
+ ShowOutRange(0, n, nd, nl);
+ ShowOutRange(1, m, md, ml);
+ ShowSubNumber(0, n, nd, nl);
+ ShowSubNumber(1, m, md, ml);
+ return(e->flag);
+}
+
+ShowDiff3(e, r1, r2, n, nd, nl, m, md, ml, o, od, ol)
+ struct testenv *e; char *n, *m, *o;
+ int r1, r2, nd, nl, md, ml, od, ol; {
+ ErrorPrint(e);
+ if(r1 != r2)
+ printf("---- Result is %d and should be %d----\n", r1, r2);
+ ShowOutRange(0, n, nd, nl);
+ ShowOutRange(1, m, md, ml);
+ ShowOutRange(2, o, od, ol);
+ ShowSubNumber(0, n, nd, nl);
+ ShowSubNumber(1, m, md, ml);
+ ShowSubNumber(2, o, od, ol);
+ return(e->flag);
+}
+
+ShowDiff4(e, r1, r2, n, nd, nl, m, md, ml, o, od, ol, p, pd, pl)
+ struct testenv *e; char *n, *m, *o, *p;
+ int r1, r2, nd, nl, md, ml, od, ol, pd, pl; {
+ ErrorPrint(e);
+ if(r1 != r2)
+ printf("---- Result is %d and should be %d----\n", r1, r2);
+ ShowOutRange(0, n, nd, nl);
+ ShowOutRange(1, m, md, ml);
+ ShowOutRange(2, o, od, ol);
+ ShowOutRange(3, p, pd, pl);
+ ShowSubNumber(0, n, nd, nl);
+ ShowSubNumber(1, m, md, ml);
+ ShowSubNumber(2, o, od, ol);
+ ShowSubNumber(3, p, pd, pl);
+ return(e->flag);
+}
+
+ShowSubNumber(x, n, nd, nl) char *n; int x, nd, nl; {
+ printf("[%s, %d, %d] = ", n, nd, nl);
+ RangeNumberPrint("", RN(x), nd, nl);
+ if(CheckSubRange(x, nd, nl)) {
+ RangeNumberPrint(" Before: ", NumbProto, nd, nl);
+ RangeNumberPrint(" Simulated: ", SN(x), nd, nl);
+} }
+
+RangeNumberPrint(s, n, nd, nl) char *s; BigNum n; int nd, nl; {
+ int first = 1;
+
+ /* Ne marche que si BnGetDigit est garanti!!! */
+ printf("%s {", s);
+ while(nl) {
+ nl--;
+ if(!first) printf(", "); else first = 0;
+ if(BN_DIGIT_SIZE <= 16)
+ printf("%.4X", BnnGetDigit ((n+ nd + nl)));
+ else if(BN_DIGIT_SIZE <= 32)
+ printf("%.8X", BnnGetDigit ((n+ nd + nl)));
+ else printf("%.16lX", BnnGetDigit ((n+ nd + nl)));
+ }
+ printf("}\n");
+}
+
+char *msg = "---- Modification Out of Range of number ";
+ShowOutRange(x, n, nd, nl) char *n; int x, nd, nl; {
+ int i = 0, bol = 0;
+
+ while(i = CheckSubRange(x, i, TESTLENGTH - i)) {
+ if((i <= nd) || (i > nd + nl)) {
+ if(!bol) {
+ bol = 1;
+ printf("%s %s at index: (%d", msg, n, i - 1);
+ } else {
+ printf(" %d", i - 1);
+ } } }
+ if(bol) printf(").\n");
+}
+
+ErrorPrint(e) struct testenv *e; {
+ printf("*** Error in compute : %s\n", e->hist);
+ printf(" Depends on %s\n", e->depend);
+}
+
+/*
+ * Tests des fonctions non redefinisables
+ */
+
+int genlengthvec[] = {9, 8, 1, 0, 2000, 32000,};
+BigNumType gentypevec[] = {0, 1, 2, 3, 4, 5,};
+
+Generique(e) struct testenv *e; {
+ int i;
+ int length, length2;
+ BigNumType type, type2;
+ int fix;
+ BigNum n;
+
+
+ for(i=0; i < 6; i++) {
+ type = gentypevec[i];
+ length = genlengthvec[i];
+ n = BnCreate(type, length);
+ if((type2 = BnGetType(n)) != type) {
+ sprintf(e->hist,"BnGetType(BnCreate(%d, %d));", type, length);
+ if(ShowDiff0(e, type, type2)) return(TRUE);
+ }
+ if((length2 = BnGetSize(n)) != length) {
+ sprintf(e->hist,"BnGetSize(BnCreate(%d, %d));", type, length);
+ if(ShowDiff0(e, length, length2)) return(TRUE);
+ }
+ if(BnFree(n) == 0) {
+ sprintf(e->hist, "BnFree(BnCreate(%d, %d));", type, length);
+ if(ShowDiff0(e, 1, 0)) return(TRUE);
+ }
+ BnSetType((n = BnAlloc(length)), type);
+ if((type2 = BnGetType(n)) != type) {
+ sprintf(e->hist,"BnGetType(BnAlloc(%d, %d));", type, length);
+ if(ShowDiff0(e, type, type2)) return(TRUE);
+ }
+ if((length2 = BnGetSize(n)) != length) {
+ sprintf(e->hist,"BnGetSize(BnAlloc(%d, %d));", type, length);
+ if(ShowDiff0(e, length, length2)) return(TRUE);
+ }
+ if(BnFree(n) == 0) {
+ sprintf(e->hist, "BnFree(BnAlloc(%d, %d));", type, length);
+ if(ShowDiff0(e, 1, 0)) return(TRUE);
+ }
+ }
+ return(FALSE);
+}
+
+/*
+ * BnSetToZero
+ */
+___BnSetToZero___(n, nd, nl) register BigNum n; register int nd, nl; {
+ register int i;
+ for(i=0; i<nl; i++)
+ BnnSetDigit ((n+ nd + i), 0);
+}
+
+TestBnSetToZero(e) struct testenv *e; {
+ int nd, nl;
+
+ e->depend = "(BnSetDigit)";
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++) {
+ TestCountInc();
+ ResetTest(0);
+ BnnSetToZero ((RN(0)+ nd), nl);
+ ___BnSetToZero___(SN(0), nd, nl);
+ if(Check(1)) {
+ sprintf(e->hist, "%s(n, %d, %d)", e->name, nd, nl);
+ if(ShowDiff1(e, 0, 0, "n", nd, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnAssign
+ */
+___BnAssign___(m, md, n, nd, nl) BigNum m, n; int md, nd, nl; {
+ register int i;
+ for(i=0; i<nl; i++)
+ BnnSetDigit ((NtmpBig+ i), BnnGetDigit ((n+ nd + i)));
+ for(i=0; i<nl; i++)
+ BnnSetDigit ((m+ md + i), BnnGetDigit ((NtmpBig+ i)));
+}
+
+TestBnAssign(e) struct testenv *e; {
+ int md, nd, nl;
+
+ e->depend = "(BnGetDigit, BnSetDigit)";
+ for(md = 0; md <= TESTLENGTH; md++)
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl=0; ((nl<=TESTLENGTH-nd) && (nl<=TESTLENGTH-md)); nl++) {
+ TestCountInc();
+ ResetTest(0);
+ BnnAssign ((RN(0)+ md), ( RN(0)+ nd), nl);
+ ___BnAssign___(SN(0), md, SN(0), nd, nl);
+ if(Check(1)) {
+ sprintf(e->hist, "%s(m, %d, n, %d, %d)", e->name,
+ md, nd, nl);
+ if(ShowDiff1(e, 0, 0, "n", md, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+
+/*
+ * BnNumDigits
+ */
+___BnNumDigits___(n, nd, nl) register BigNum n; register int nd, nl; {
+
+ while(nl != 0) {
+ nl--;
+ if(!BnnIsDigitZero (*(n+ nd + nl))) break;
+ }
+ return(nl + 1);
+}
+
+TestBnNumDigits(e) struct testenv *e; {
+ int nd0, nl0, nd, nl, l1, l2;
+
+ e->depend = "(BnIsDigitZero)";
+ for(nd0 = 0; nd0 <= TESTLENGTH; nd0++)
+ for(nl0 = 0; nl0 <= TESTLENGTH - nd0; nl0++)
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++) {
+ TestCountInc();
+ ResetTest(0);
+ BnnSetToZero ((RN(0)+ nd0), nl0);
+ BnnSetToZero ((SN(0)+ nd0), nl0);
+ l1 = BnnNumDigits ((RN(0)+ nd), nl);
+ l2 = ___BnNumDigits___(SN(0), nd, nl);
+ if(Check(1) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, %d)", e->name, nd, nl);
+ if(ShowDiff1(e, l1, l2, "n", nd, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnNumLeadingZeroBitsInDigit
+ */
+__BnNumLeadingZeroBitsInDigit__(n, nd) BigNum n; int nd; {
+ int p = 0;
+
+ if(BnnIsDigitZero (*(n+ nd))) return(BN_DIGIT_SIZE);
+ BnnAssign ((Ntmp2+ 0), ( n+ nd), 1);
+ *( Ntmp2+ 1) = BnnShiftLeft ((Ntmp2+ 0), 1, 1);
+ while(BnnIsDigitZero (*(Ntmp2+ 1))) {
+ *( Ntmp2+ 1) = BnnShiftLeft ((Ntmp2+ 0), 1, 1);
+ p++;
+ }
+ return(p);
+}
+
+TestBnNumLeadingZeroBitsInDigit(e) struct testenv *e; {
+ int nd; int l1, l2;
+
+
+ e->depend = "(BnShiftLeft, BnIsDigitZero)";
+ ResetTest(0);
+ for(nd = 0; nd < TESTLENGTH; nd++) {
+ TestCountInc();
+ l1 = BnnNumLeadingZeroBitsInDigit (*(RN(0)+ nd));
+ l2 = __BnNumLeadingZeroBitsInDigit__(SN(0), nd);
+ if(Check(1) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d)", e->name, nd);
+ if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnIsDigitZero
+ */
+___BnIsDigitZero___(n, nd) BigNum n; int nd; {
+ if(BnnGetDigit ((n+ nd)) == 0) return(1);
+ return(0);
+}
+
+TestBnIsDigitZero(e) struct testenv *e; {
+ int nd; int l1, l2;
+
+ e->depend = "()";
+ ResetTest(0);
+ for(nd = 0; nd < TESTLENGTH; nd++) {
+ TestCountInc();
+ l1 = BnnIsDigitZero (*(RN(0)+ nd));
+ l2 = ___BnIsDigitZero___(SN(0), nd);
+ if(Check(1) || ((l1 == 0) && (l2 != 0)) ||
+ ((l1 != 0) && (l2 == 0))) {
+ sprintf(e->hist, "%s(n, %d)", e->name, nd);
+ if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnIsDigitNormalized
+ */
+___BnIsDigitNormalized___(n, nd) BigNum n; int nd; {
+ BnnAssign ((Ntmp2+ 0), ( n+ nd), 1);
+ *( Ntmp2+ 1) = BnnShiftLeft ((Ntmp2+ 0), 1, 1);
+ if(BnnIsDigitZero (*(Ntmp2+ 1))) return(0);
+ return(1);
+}
+
+TestBnIsDigitNormalized(e) struct testenv *e; {
+ int nd; int l1, l2;
+
+ e->depend = "(BnShiftLeft, BnIsDigitZero)";
+ ResetTest(0);
+ for(nd = 0; nd < TESTLENGTH; nd++) {
+ TestCountInc();
+ l1 = BnnIsDigitNormalized (*(RN(0)+ nd));
+ l2 = ___BnIsDigitNormalized___(SN(0), nd);
+ if(Check(1) || ((l1 == 0) && (l2 != 0)) ||
+ ((l1 != 0) && (l2 == 0))) {
+ sprintf(e->hist, "%s(n, %d)", e->name, nd);
+ if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnIsDigitOdd
+ */
+___BnIsDigitOdd___(n, nd) BigNum n; int nd; {
+ BnnAssign ((Ntmp2+ 0), ( n+ nd), 1);
+ *( Ntmp2+ 1) = BnnShiftRight ((Ntmp2+ 0), 1, 1);
+ if(BnnIsDigitZero (*(Ntmp2+ 1))) return(0);
+ return(1);
+}
+
+TestBnIsDigitOdd(e) struct testenv *e; {
+ int nd; int l1, l2;
+
+ e->depend = "(BnShiftRight, BnIsDigitZero)";
+ ResetTest(0);
+ for(nd = 0; nd < TESTLENGTH; nd++) {
+ TestCountInc();
+ l1 = BnnIsDigitOdd (*(RN(0)+ nd));
+ l2 = ___BnIsDigitOdd___(SN(0), nd);
+ if(Check(1) || ((l1 == 0) && (l2 != 0)) ||
+ ((l1 != 0) && (l2 == 0))) {
+ sprintf(e->hist, "%s(n, %d)", e->name, nd);
+ if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnCompareDigits
+ */
+___BnCompareDigits___(n, nd, m, md) BigNum n, m; int nd, md; {
+ BnnAssign ((Ntmp2+ 0), ( n+ nd), 1);
+ BnnComplement ((Ntmp2+ 0), 1);
+ if(BnnAdd ((Ntmp2+ 0), 1, ( m+ md), 1, (BigNumCarry) 0)) return(-1);
+ BnnComplement ((Ntmp2+ 0), 1);
+ if(BnnIsDigitZero (*(Ntmp2+ 0))) return(0);
+ return(1);
+}
+
+TestBnCompareDigits(e) struct testenv *e; {
+ int nd, md; int l1, l2;
+
+ e->depend = "(BnComplement, BnAdd, BnIsDigitZero)";
+ ResetTest(0);
+ ResetTest(1);
+ for(nd = 0; nd < TESTLENGTH; nd++)
+ for(md = 0; md < TESTLENGTH; md++) {
+ TestCountInc();
+ l1 = BnnCompareDigits (*(RN(0)+ nd), *( RN(1)+ md));
+ l2 = ___BnCompareDigits___(SN(0), nd, SN(1), md);
+ if(Check(2) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md);
+ if(ShowDiff2(e, l1, l2, "n", nd, 1, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnComplement
+ */
+___BnComplement___(n, nd, nl) BigNum n; int nd, nl; {
+ int i;
+
+ BnnSetDigit ((Ntmp2+ 0), 0);
+ BnnSubtractBorrow ((Ntmp2+ 0), 1, 0);
+ for(i = 0; i < nl; i++)
+ BnnXorDigits ((n+ nd + i), *( Ntmp2+ 0));
+}
+
+TestBnComplement(e) struct testenv *e; {
+ int nd, nl;
+
+ e->depend = "(BnSubtractBorrow, BnXorDigits)";
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++) {
+ TestCountInc();
+ ResetTest(0);
+ BnnComplement ((RN(0)+ nd), nl);
+ ___BnComplement___(SN(0), nd, nl);
+ if(Check(1)) {
+ sprintf(e->hist, "%s(n, %d, %d)", e->name, nd, nl);
+ if(ShowDiff1(e, 0, 0, "n", nd, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnAndDigits
+ */
+___BnAndDigits___(n, nd, m, md) BigNum n, m; int nd, md; {
+ BnnAssign ((Ntmp2+ 0), ( n+ nd), 1);
+ BnnOrDigits ((Ntmp2+ 0), *( m+ md));
+ BnnXorDigits ((Ntmp2+ 0), *( m+ md));
+ BnnXorDigits ((n+ nd), *( Ntmp2+ 0));
+}
+
+TestBnAndDigits(e) struct testenv *e; {
+ int nd, md;
+
+ e->depend = "(BnOrDigits, BnXorDigits)";
+ ResetTest(1);
+ for(nd = 0; nd < TESTLENGTH; nd++)
+ for(md = 0; md < TESTLENGTH; md++) {
+ TestCountInc();
+ ResetTest(0);
+ BnnAndDigits ((RN(0)+ nd), *( RN(1)+ md));
+ ___BnAndDigits___(SN(0), nd, SN(1), md);
+ if(Check(2)) {
+ sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md);
+ if(ShowDiff2(e, 0, 0, "n", nd, 1, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnOrDigits
+ */
+___BnOrDigits___(n, nd, m, md) BigNum n, m; int nd, md; {
+ BnnAssign ((Ntmp2+ 0), ( n+ nd), 1);
+ BnnAndDigits ((Ntmp2+ 0), *( m+ md));
+ BnnXorDigits ((Ntmp2+ 0), *( m+ md));
+ BnnXorDigits ((n+ nd), *( Ntmp2+ 0));
+}
+
+TestBnOrDigits(e) struct testenv *e; {
+ int nd, md;
+
+ e->depend = "(BnAndDigits, BnXorDigits)";
+ ResetTest(1);
+ for(nd = 0; nd < TESTLENGTH; nd++)
+ for(md = 0; md < TESTLENGTH; md++) {
+ TestCountInc();
+ ResetTest(0);
+ BnnOrDigits ((RN(0)+ nd), *( RN(1)+ md));
+ ___BnOrDigits___(SN(0), nd, SN(1), md);
+ if(Check(2)) {
+ sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md);
+ if(ShowDiff2(e, 0, 0, "n", nd, 1, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnXorDigits
+ */
+___BnXorDigits___(n, nd, m, md) BigNum n, m; int nd, md; {
+ BnnAssign ((Ntmp2+ 0), ( n+ nd), 1);
+ BnnAndDigits ((Ntmp2+ 0), *( m+ md));
+ BnnComplement ((Ntmp2+ 0), 1);
+ BnnOrDigits ((n+ nd), *( m+ md));
+ BnnAndDigits ((n+ nd), *( Ntmp2+ 0));
+}
+
+TestBnXorDigits(e) struct testenv *e; {
+ int nd, md;
+
+ e->depend = "(BnAndDigits, BnComplement, BnOrDigits)";
+ ResetTest(1);
+ for(nd = 0; nd < TESTLENGTH; nd++)
+ for(md = 0; md < TESTLENGTH; md++) {
+ TestCountInc();
+ ResetTest(0);
+ BnnXorDigits ((RN(0)+ nd), *( RN(1)+ md));
+ ___BnXorDigits___(SN(0), nd, SN(1), md);
+ if(Check(2)) {
+ sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md);
+ if(ShowDiff2(e, 0, 0, "n", nd, 1, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnShiftLeft
+ */
+___BnShiftLeft___(n, nd, nl, m, md, s) BigNum n, m; int nd, nl, md; int s; {
+ BnnSetDigit ((m+ md), 2);
+ BnnSetDigit ((Ntmp2+ 0), 1);
+ while(s--) {
+ BnnSetToZero ((NtmpBig+ 0), 2);
+ BnnMultiplyDigit ((NtmpBig+ 0), 2, ( Ntmp2+ 0), 1, *( m+ md));
+ BnnAssign ((Ntmp2+ 0), ( NtmpBig+ 0), 1);
+ }
+ BnnSetToZero ((NtmpBig+ 0), nl + 1);
+ BnnMultiplyDigit ((NtmpBig+ 0), nl + 1, ( n+ nd), nl, *( Ntmp2+ 0));
+ BnnAssign ((n+ nd), ( NtmpBig+ 0), nl);
+ BnnAssign ((m+ md), ( NtmpBig+ nl), 1);
+}
+
+TestBnShiftLeft(e) struct testenv *e; {
+ int nd, nl, md; int s;
+
+ e->depend = "(BnSetToZero, BnMultiplyDigit)";
+ ResetTest(1);
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(md = 0; md < 2; md++)
+ for(s = 0; s < BN_DIGIT_SIZE; s++) {
+ TestCountInc();
+ ResetTest(0);
+ *( RN(1)+ md) = BnnShiftLeft ((RN(0)+ nd), nl, s);
+ ___BnShiftLeft___(SN(0), nd, nl, SN(1), md, s);
+ if(Check(2)) {
+ sprintf(e->hist, "%s(n, %d, %d, m, %d, %d)",
+ e->name, nd, nl, md, s);
+ if(ShowDiff2(e, 0, 0, "n", nd, nl, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnShiftRight
+ */
+___BnShiftRight___(n, nd, nl, m, md, s) BigNum n, m; int nd, nl, md; int s; {
+ if((nl == 0) || (s == 0)) {
+ BnnSetDigit ((m+ md), 0);
+ return;
+ }
+ BnnAssign ((NtmpBig+ 0), ( n+ nd), nl);
+ *( NtmpBig+ nl) = BnnShiftLeft ((NtmpBig+ 0), nl, BN_DIGIT_SIZE - s);
+ BnnAssign ((n+ nd), ( NtmpBig+ 1), nl);
+ BnnAssign ((m+ md), ( NtmpBig+ 0), 1);
+}
+
+TestBnShiftRight(e) struct testenv *e; {
+ int nd, nl, md; int s;
+
+ e->depend = "(BnShiftLeft)";
+ ResetTest(1);
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(md = 0; md < 2; md++)
+ for(s = 0; s < BN_DIGIT_SIZE; s++) {
+ TestCountInc();
+ ResetTest(0);
+ *( RN(1)+ md) = BnnShiftRight ((RN(0)+ nd), nl, s);
+ ___BnShiftRight___(SN(0), nd, nl, SN(1), md, s);
+ if(Check(2)) {
+ sprintf(e->hist, "%s(n, %d, %d, m, %d, %d)",
+ e->name, nd, nl, md, s);
+ if(ShowDiff2(e, 0, 0, "n", nd, nl, "m", md, 1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnAddCarry
+ */
+BigNumCarry
+___BnAddCarry___(n, nd, nl, r) BigNum n; int nd, nl; int r;{
+ if(r == 0) return(0);
+ BnnComplement ((n+ nd), nl);
+ r = BnnSubtractBorrow ((n+ nd), nl, 0);
+ BnnComplement ((n+ nd), nl);
+ if(r == 0) return(1);
+ return(0);
+}
+
+TestBnAddCarry(e) struct testenv *e; {
+ int nd, nl; int r, l1, l2;
+
+ e->depend = "(BnComplement, BnSubtractBorrow)";
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(r = 0; r < 2; r++) {
+ TestCountInc();
+ ResetTest(0);
+ l1 = BnnAddCarry ((RN(0)+ nd), nl, r);
+ l2 = ___BnAddCarry___(SN(0), nd, nl, r);
+ if(Check(1) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, %d, %d)",
+ e->name, nd, nl, r);
+ if(ShowDiff1(e, l1, l2, "n", nd, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnAdd
+ */
+BigNumCarry
+___BnAdd___(n, nd, nl, m, md, ml, r) BigNum n, m; int nd, nl, md, ml; BigNumCarry r;{
+ BnnComplement ((m+ md), ml);
+ r = BnnSubtract ((n+ nd), ml, ( m+ md), ml, r);
+ BnnComplement ((m+ md), ml);
+ return(BnnAddCarry ((n+ nd + ml), nl - ml, r));
+}
+
+TestBnAdd(e) struct testenv *e; {
+ int nd, nl, md, ml; int l1, l2; BigNumCarry r;
+
+ e->depend = "(BnComplement, BnSubtract, BnAddCarry)";
+ ResetTest(1);
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(md = 0; md <= TESTLENGTH - nl; md++)
+ for(ml = 0; ml <= nl ; ml++)
+ for(r = 0; r < 2; r++) {
+ TestCountInc();
+ ResetTest(0);
+ l1 = BnnAdd ((RN(0)+ nd), nl, ( RN(1)+ md), ml, r);
+ l2 = ___BnAdd___(SN(0), nd, nl, SN(1), md, ml, r);
+ if(Check(2) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, %d, m, %d, %d, %d)",
+ e->name, nd, nl, md, ml, r);
+ if(ShowDiff2(e, l1, l2, "n", nd, nl, "m", md, ml))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnSubtractBorrow
+ */
+BigNumCarry
+___BnSubtractBorrow___(n, nd, nl, r) BigNum n; int nd, nl; BigNumCarry r;{
+ if(r == 1) return(1);
+ BnnComplement ((n+ nd), nl);
+ r = BnnAddCarry ((n+ nd), nl, (BigNumCarry) 1);
+ BnnComplement ((n+ nd), nl);
+ if(r == 0) return(1);
+ return(0);
+}
+
+TestBnSubtractBorrow(e) struct testenv *e; {
+ int nd, nl; int l1, l2; BigNumCarry r;
+
+ e->depend = "(BnComplement, BnAddCarry)";
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(r = 0; r < 2; r++) {
+ TestCountInc();
+ ResetTest(0);
+ l1 = BnnSubtractBorrow ((RN(0)+ nd), nl, r);
+ l2 = ___BnSubtractBorrow___(SN(0), nd, nl, r);
+ if(Check(1) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, %d, %d)",
+ e->name, nd, nl, r);
+ if(ShowDiff1(e, l1, l2, "n", nd, nl)) return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnSubtract
+ */
+BigNumCarry
+___BnSubtract___(n, nd, nl, m, md, ml, r) BigNum n, m; int nd, nl, md, ml; BigNumCarry r;{
+ BnnComplement ((m+ md), ml);
+ r = BnnAdd ((n+ nd), ml, ( m+ md), ml, r);
+ BnnComplement ((m+ md), ml);
+ return(BnnSubtractBorrow ((n+ nd + ml), nl - ml, r));
+}
+
+TestBnSubtract(e) struct testenv *e; {
+ int nd, nl, md, ml; int l1, l2; BigNumCarry r;
+
+ e->depend = "(BnComplement, BnAdd, BnSubtractBorrow)";
+ ResetTest(1);
+ for(nd = 0; nd <= TESTLENGTH; nd++)
+ for(nl = 0; nl <= TESTLENGTH - nd; nl++)
+ for(md = 0; md <= TESTLENGTH - nl; md++)
+ for(ml = 0; ml <= nl ; ml++)
+ for(r = 0; r < 2; r++) {
+ TestCountInc();
+ ResetTest(0);
+ l1 = BnnSubtract ((RN(0)+ nd), nl, ( RN(1)+ md), ml, r);
+ l2 = ___BnSubtract___(SN(0), nd, nl, SN(1), md, ml, r);
+ if(Check(2) || l1 != l2) {
+ sprintf(e->hist, "%s(n, %d, %d, m, %d, %d, %d)",
+ e->name, nd, nl, md, ml, r);
+ if(ShowDiff2(e, l1, l2, "n", nd, nl, "m", md, ml))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnMultiplyDigit
+ */
+BigNumCarry
+___BnMultiplyDigit___(p, pd, pl, n, nd, nl, m, md) BigNum p, n, m; int pd, pl, nd, nl, md; {
+ BigNumCarry r = 0, ret = 0;
+
+ BnnAssign ((Ntmp2+ 0), ( m+ md), 1);
+ BnnAssign ((NtmpBig+ 0), ( n+ nd), nl);
+ BnnSetToZero ((NtmpBig+ nl), 1);
+ while(!BnnIsDigitZero (*(Ntmp2+ 0))) {
+ if(BnnIsDigitOdd (*(Ntmp2+ 0))) {
+ r = BnnAdd ((p+ pd), pl, ( NtmpBig+ 0), nl + 1, (BigNumCarry) 0);
+ if((ret == 0) && (r == 1)) ret = 1;
+ else if((ret == 1) && (r == 1)) ret = 2;
+ }
+ *( Ntmp2+ 1) = BnnShiftRight ((Ntmp2+ 0), 1, 1);
+ *( Ntmp2+ 1) = BnnShiftLeft ((NtmpBig+ 0), nl + 1, 1);
+ if(!BnnIsDigitZero (*(Ntmp2+ 1))) ret = 3;
+ }
+ return(ret);
+}
+
+TestBnMultiplyDigit(e) struct testenv *e; {
+ int pd, pl, nd, nl, md; int l1, l2;
+
+ e->depend = "(BnSetToZero, BnIsDigitZero, BnIsDigitOdd, BnAdd, BnShiftRight, BnShiftLeft)";
+ ResetTest(1);
+ ResetTest(2);
+ for(pd = 0; pd <= TESTLENGTH; pd++)
+ for(pl = 0; pl <= TESTLENGTH - pd; pl++)
+ for(nd = 0; nd <= TESTLENGTH - pl; nd++)
+ for(nl = 0; nl < pl ; nl++)
+ for(md = 0; md < TESTLENGTH; md++) {
+ TestCountInc();
+ ResetTest(0);
+ l1 = BnnMultiplyDigit ((RN(0)+pd), pl, (RN(1)+nd), nl, *(RN(2)+md));
+ l2 = ___BnMultiplyDigit___(SN(0),pd,pl,SN(1),nd,nl,SN(2),md);
+ if(Check(3) || l1 != l2) {
+ sprintf(e->hist,
+ "BnMultiplyDigit(p, %d, %d, n, %d, %d, m, %d)",
+ pd, pl, nd, nl, md);
+ if(ShowDiff3(e,l1,l2,"p",pd,pl,"n",nd,nl,"m",md,1))
+ return(1);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnDivideDigit
+ */
+TestBnDivideDigit(e) struct testenv *e; {
+ int nd, nl, md, qd, rd, l2;
+
+ e->depend = "(BnSetToZero, BnMultiplyDigit, BnCompareDigits)";
+ ResetTest(2);
+ ResetTest(3);
+ for(nd = 0; nd <= TESTLENGTH - 2; nd++)
+ for(nl = 2; nl <= TESTLENGTH - nd; nl++)
+ for(md = 0; md < TESTLENGTH; md++)
+ for(qd = 0; qd < TESTLENGTH - nl + 1 ; qd++)
+ for(rd = 0; rd < 2; rd++)
+ if((!BnnIsDigitZero (*(RN(3)+ md))) &&
+ (BnnCompareDigits (*(RN(2)+ nd+nl-1), *( RN(3)+ md)) == -1)) {
+ TestCountInc();
+ ResetTest(0);
+ ResetTest(1);
+ *( RN(1)+ rd) = BnnDivideDigit ((RN(0)+ qd), ( RN(2)+ nd), nl, *( RN(3)+ md));
+ BnnAssign ((SN(0)+ qd), ( RN(0)+ qd), nl - 1);
+ BnnAssign ((SN(1)+ rd), ( RN(1)+ rd), 1);
+ BnnSetToZero ((SN(2)+ nd), nl);
+ BnnAssign ((SN(2)+ nd), ( SN(1)+ rd), 1);
+ l2 = BnnMultiplyDigit ((SN(2)+nd), nl, ( SN(0)+qd), nl - 1, *( SN(3)+ md));
+ if(Check(4) || l2 != 0) {
+ sprintf(e->hist,
+ "BnDivideDigit(q, %d, r, %d, n, %d, %d, m, %d)",
+ qd, rd, nd, nl, md);
+ if(ShowDiff4(e, 0, l2, "q", qd, nl - 1, "r", rd, 1,
+ "n", nd, nl, "m", md, 1))
+ return(TRUE);
+ } }
+ return(FALSE);
+}
+
+/*
+ * BnMultiply
+ */
+___BnMultiply___(p, pd, pl, m, md, ml, n, nd, nl) BigNum p, m, n; int pd, pl, md, ml, nd, nl; {
+ int ret;
+
+ for (ret = 0; nl-- > 0; pd++, nd++, pl--)
+ ret += BnnMultiplyDigit ((p+ pd), pl, ( m+ md), ml, *( n+ nd));
+ return(ret);
+}
+
+TestBnMultiply(e) struct testenv *e; {
+ BigNumLength pd, pl, nd, nl, md, ml; int l1, l2;
+
+ e->depend = "(BnSetToZero, BnMultiplyDigit)";
+ ResetTest(1);
+ ResetTest(2);
+ for(pd = 0; pd <= TESTLENGTH; pd++)
+ for(pl = 0; pl <= TESTLENGTH - pd && pl <= TESTLENGTH/2; pl++)
+ for(nd = 0; nd <= TESTLENGTH - pl; nd++)
+ for(nl = 0; nl < pl && nl <= TESTLENGTH/3; nl++)
+ {
+ if (nl <= pl-nl)
+ {
+ /* Test squaring */
+ TestCountInc();
+ ResetTest(0);
+ l1 = BnnMultiply ((RN(0)+pd), pl, (RN(1)+nd), nl, (RN(1)+nd), nl);
+ l2 = ___BnMultiply___(SN(0),pd,pl,SN(1),nd,nl,SN(1),nd,nl);
+ if(Check(3) || l1 != l2) {
+ sprintf(e->hist,
+ "BnMultiply(p, %d, %d, n, %d, %d, n, %d, %d)",
+ pd, pl, nd, nl, nd, nl);
+ if(ShowDiff3(e,l1,l2,"p",pd,pl,"n",nd,nl,"n",nd,nl))
+ return(1);
+ }
+
+ }
+ for(md = 0; md <= TESTLENGTH; md++)
+ for (ml = 0; ml <= pl-nl && ml <= TESTLENGTH/3 && md+ml <= TESTLENGTH; ml++) {
+ TestCountInc();
+ ResetTest(0);
+ l1 = BnnMultiply ((RN(0)+pd), pl, (RN(1)+nd), nl, (RN(2)+md), ml);
+ l2 = ___BnMultiply___(SN(0),pd,pl,SN(1),nd,nl,SN(2),md,ml);
+ if(Check(3) || l1 != l2) {
+ sprintf(e->hist,
+ "BnMultiply(p, %d, %d, n, %d, %d, m, %d, %d)",
+ pd, pl, nd, nl, md, ml);
+ if(ShowDiff3(e,l1,l2,"p",pd,pl,"n",nd,nl,"m",md,ml))
+ return(1);
+ } } }
+ return(FALSE);
+}
+
+/*
+ * Main
+ */
+typedef struct {
+ int (*TestFnt)();
+ char *NameFnt;
+} TESTONE;
+TESTONE AllTest[] = {
+ Generique, "Generic Functions",
+ TestBnSetToZero, "BnSetToZero",
+ TestBnAssign, "BnAssign",
+ TestBnNumDigits, "BnNumDigits",
+ TestBnNumLeadingZeroBitsInDigit, "BnNumLeadingZeroBitsInDigit",
+ TestBnIsDigitZero, "BnIsDigitZero",
+ TestBnIsDigitNormalized, "BnIsDigitNormalized",
+ TestBnIsDigitOdd, "BnIsDigitOdd",
+ TestBnCompareDigits, "BnCompareDigits",
+ TestBnComplement, "BnComplement",
+ TestBnAndDigits, "BnAndDigits",
+ TestBnOrDigits, "BnOrDigits",
+ TestBnXorDigits, "BnXorDigits",
+ TestBnShiftLeft, "BnShiftLeft",
+ TestBnShiftRight, "BnShiftRight",
+ TestBnAddCarry, "BnAddCarry",
+ TestBnAdd, "BnAdd",
+ TestBnSubtractBorrow, "BnSubtractBorrow",
+ TestBnSubtract, "BnSubtract",
+ TestBnMultiplyDigit, "BnMultiplyDigit",
+ TestBnDivideDigit, "BnDivideDigit",
+ TestBnMultiply, "BnMultiply",
+};
+
+main(n, s) int n; char **s; {
+ struct testenv realenv, *e = &realenv;
+ int i, j, nbtest, SizeAllTest;
+
+ /* Initialisations de l'environnement de test. */
+ e->flag = 1;
+ e->depend = "()";
+ /* Allocation des 2 nombres globaux. */
+ Ntmp2 = BnAlloc(2);
+ NtmpBig = BnAlloc(2 * TESTLENGTH);
+ NumbProto = BnAlloc(TESTLENGTH);
+ /* Creation du nombre prototype. */
+ BnnSetDigit ((NumbProto+ 0), 0); /* Les 2 premiers a` ze'ro. */
+ BnnSetDigit ((NumbProto+ 1), 0);
+ for(i=0; i < TESTLENGTH/4 - 1; i++) /* Le premier quart est la */
+ BnnSetDigit ((NumbProto+ i + 2), i + 1); /* suite 1, 2, 3, ... */
+ /* Le 2nd quart est le 1er shifte de BN_DIGIT_SIZE - 2. 0x4000 0x8000 ...*/
+ BnnAssign ((NumbProto+ QTL + 1), ( NumbProto+ 2), QTL - 1);
+ *( NumbProto+ 0) = BnnShiftLeft ((NumbProto+ QTL + 1), QTL - 1, BN_DIGIT_SIZE - 2);
+ /* La 2nd moitie est l'inverse logique de la 1ere */
+ BnnAssign ((NumbProto+ DTL), ( NumbProto+ 0), DTL);
+ BnnComplement ((NumbProto+ DTL), DTL);
+ /* Allocation des nombres utilise's */
+ for(i=0; i < 5; i++) {
+ RN(i) = BnAlloc(TESTLENGTH);
+ SN(i) = BnAlloc(TESTLENGTH);
+ }
+ if(n > 1 && s[1][0] == '-') {
+ CallDummy = atoi(s[1]+1);
+ n--;
+ s++;
+ }
+ if(n == 1) {
+ printf("%s [-CallDummy#] v|a|TestNum\n", s[0]);
+ }
+ /* On y va */
+ SizeAllTest = (sizeof(AllTest)/sizeof(AllTest[0]));
+ for(i = 1; i < n; i++) {
+ if(s[i][0] == 'm') {
+ /* 0 = No skip; 1 = skip to next; else STOP */
+ e->flag = atoi(&s[i][1]);
+ } else if(s[i][0] == 'a') {
+ for(i = 0; i < SizeAllTest; i++)
+ dotest(e, i);
+ } else if(s[i][0] == 'v') {
+ for(j = 0; j < SizeAllTest; j++)
+ seetest(j);
+ } else {
+ nbtest = atoi(s[i]);
+ if((nbtest < 0) || (nbtest >= SizeAllTest))
+ printf("Test %d is invalid\n", nbtest);
+ else dotest(e, nbtest);
+} } }
+
+dotest(e, n) struct testenv *e; int n; {
+ seetest(n);
+ TestCount = 0;
+ e->name = AllTest[n].NameFnt;
+ if(((*(AllTest[n].TestFnt)) (e)) && e->flag > 1) exit(0);
+ printf("%d tests were performed\n", TestCount);
+}
+
+seetest(n) int n; {
+ printf("%d. Testing %s\n", n, AllTest[n].NameFnt);
+}
+
diff --git a/otherlibs/num/bignum/h/BigNum.h b/otherlibs/num/bignum/h/BigNum.h
new file mode 100644
index 000000000..604a9c0a9
--- /dev/null
+++ b/otherlibs/num/bignum/h/BigNum.h
@@ -0,0 +1,144 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Thu Feb 20 18:41:41 GMT+1:00 1992 by shand */
+/* modified_on Thu Oct 31 16:41:47 1991 by herve */
+/* modified_on Wed Jul 5 10:19:33 GMT+2:00 1989 by bertin */
+/* Adapted to Caml Light by Xavier Leroy, Mon May 9. */
+
+/* BigN.h - Types and structures for clients of BigNum */
+
+#if !defined(_stdc_)
+#define _NO_PROTO
+#endif
+
+
+ /******** representation of a bignum ******/
+/*
+** <--------------------------- nl ---------------------------->
+** | Least Most |
+** |Significant| | | |Significant|
+** |BigNumDigit| | | |BigNumDigit|
+** |___________|___________|___________|___________|___________|
+** ^ (sometimes
+** | is zero)
+** nn
+*/
+
+/* signals BigNum.h already included */
+#define BIGNUM
+
+ /*************** sizes ********************/
+
+#define BN_BYTE_SIZE 8
+#ifdef CAML_LIGHT
+#define BN_WORD_SIZE (sizeof (long) * BN_BYTE_SIZE - 2)
+#else
+#define BN_WORD_SIZE (sizeof (int) * BN_BYTE_SIZE)
+#endif
+#define BN_DIGIT_SIZE (sizeof (BigNumDigit) * BN_BYTE_SIZE)
+
+/* notes: */
+/* BN_BYTE_SIZE: number of bits in a byte */
+/* BN_WORD_SIZE: number of bits in an "int" in the target language */
+/* BN_DIGIT_SIZE: number of bits in a digit of a BigNum */
+
+
+ /****** results of compare functions ******/
+
+ /* Note: we don't use "enum" to interface with Modula2+, Lisp, ... */
+#define BN_LT -1
+#define BN_EQ 0
+#define BN_GT 1
+
+ /*************** boolean ******************/
+
+#define TRUE 1
+#define FALSE 0
+
+typedef unsigned long BigNumDigit;
+
+#ifndef BigZBoolean
+typedef int Boolean;
+#define BigZBoolean
+#endif
+
+#ifndef __
+#if defined(_NO_PROTO)
+#define __(args) ()
+#else
+#define __(args) args
+#endif
+#endif
+
+ /* bignum types: digits, big numbers, carries ... */
+
+typedef BigNumDigit * BigNum; /* A big number is a digit pointer */
+typedef BigNumDigit BigNumCarry; /* Either 0 or 1 */
+typedef unsigned long BigNumProduct; /* The product of two digits */
+/* BigNumLength must be int as nl is in the code, remember int is 16 bits on MSDOS - jch */
+typedef unsigned long BigNumLength; /* The length of a bignum */
+typedef int BigNumCmp; /* result of comparison */
+
+/* */
+
+
+ /************ functions of bn.c ***********/
+
+extern void BnnInit __((void));
+extern void BnnClose __((void));
+
+extern Boolean BnnIsZero __((BigNum nn, BigNumLength nl));
+extern BigNumCarry BnnMultiply __((BigNum pp,BigNumLength pl, BigNum nn, BigNumLength nl, BigNum mm, BigNumLength ml));
+extern void BnnDivide __((BigNum nn, BigNumLength nl, BigNum dd, BigNumLength dl));
+extern BigNumCmp BnnCompare __((BigNum mm, BigNumLength ml, BigNum nn, BigNumLength nl));
+
+ /*********** functions of KerN.c **********/
+extern void BnnSetToZero __((BigNum nn, BigNumLength nl));
+extern void BnnAssign __((BigNum mm, BigNum nn, BigNumLength nl));
+extern void BnnSetDigit __((BigNum nn, BigNumDigit d));
+extern BigNumDigit BnnGetDigit __((BigNum nn));
+extern BigNumLength BnnNumDigits __((BigNum nn, BigNumLength nl));
+extern BigNumDigit BnnNumLeadingZeroBitsInDigit __((BigNumDigit d));
+extern Boolean BnnDoesDigitFitInWord __((BigNumDigit d));
+extern Boolean BnnIsDigitZero __((BigNumDigit d));
+extern Boolean BnnIsDigitNormalized __((BigNumDigit d));
+extern Boolean BnnIsDigitOdd __((BigNumDigit d));
+extern BigNumCmp BnnCompareDigits __((BigNumDigit d1, BigNumDigit d2));
+extern void BnnComplement __((BigNum nn, BigNumLength nl));
+extern void BnnAndDigits __((BigNum n, BigNumDigit d));
+extern void BnnOrDigits __((BigNum n, BigNumDigit d));
+extern void BnnXorDigits __((BigNum n, BigNumDigit d));
+extern BigNumDigit BnnShiftLeft __((BigNum mm, BigNumLength ml, int nbits));
+extern BigNumDigit BnnShiftRight __((BigNum mm, BigNumLength ml, int nbits));
+extern BigNumCarry BnnAddCarry __((BigNum nn, BigNumLength nl, BigNumCarry carryin));
+extern BigNumCarry BnnAdd __((BigNum mm, BigNumLength ml, BigNum nn, BigNumLength nl, BigNumCarry carryin));
+extern BigNumCarry BnnSubtractBorrow __((BigNum nn, BigNumLength nl, BigNumCarry carryin));
+extern BigNumCarry BnnSubtract __((BigNum mm, BigNumLength ml, BigNum nn, BigNumLength nl, BigNumCarry carryin));
+extern BigNumCarry BnnMultiplyDigit __((BigNum mm, BigNumLength ml, BigNum nn, BigNumLength nl, BigNumDigit d));
+extern BigNumDigit BnnDivideDigit __((BigNum qq, BigNum nn, BigNumLength nl, BigNumDigit d));
+
+/* */
+
+ /* some functions can be written with macro-procedures */
+
+
+#ifndef BNNMACROS_OFF
+/* the functions BnnIsZero and BnnCompareDigits are not macro procedures
+ since they use parameters twice, and that can produce bugs if
+ you pass a parameter like x++
+ */
+#define BnnSetDigit(nn,d) (*(nn) = (d))
+#define BnnGetDigit(nn) (*(nn))
+#define BnnDoesDigitFitInWord(d) (BN_DIGIT_SIZE > BN_WORD_SIZE ? ((d) >= (BigNumDigit)1 << BN_WORD_SIZE ? FALSE : TRUE) : TRUE)
+#define BnnIsDigitZero(d) ((d) == 0)
+#define BnnIsDigitNormalized(d) ((d) & (((BigNumDigit) 1) << (BN_DIGIT_SIZE - 1)) ? TRUE : FALSE)
+#define BnnIsDigitOdd(d) ((d) & ((BigNumDigit) 1) ? TRUE : FALSE)
+#define BnnAndDigits(nn, d) (*(nn) &= (d))
+#define BnnOrDigits(nn, d) (*(nn) |= (d))
+#define BnnXorDigits(nn, d) (*(nn) ^= (d))
+
+#endif
+
+
+#ifdef MSDOS
+#define realaddr(p) ((((long)(p) & (65535 << 16)) >> 12)+((long)(p) & 65535))
+#endif
diff --git a/otherlibs/num/bignum/h/BigZ.h b/otherlibs/num/bignum/h/BigZ.h
new file mode 100644
index 000000000..aaab0a2b7
--- /dev/null
+++ b/otherlibs/num/bignum/h/BigZ.h
@@ -0,0 +1,97 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* Last modified_on Fri Oct 5 16:45:46 GMT+1:00 1990 by herve */
+/* modified_on Thu Mar 22 21:29:09 GMT+1:00 1990 by shand */
+
+/* BigZ.h: Types and structures for clients of BigZ */
+
+
+ /* BigZ sign */
+
+
+#define BZ_PLUS 1
+#define BZ_ZERO 0
+#define BZ_MINUS -1
+#define BzSign BigNumCmp
+
+
+ /* BigZ compare result */
+
+
+#define BZ_LT BN_LT
+#define BZ_EQ BN_EQ
+#define BZ_GT BN_GT
+#define BzCmp BigNumCmp
+
+
+ /* BigZ number */
+
+#ifndef BIGNUM
+#include "BigNum.h"
+#endif
+
+struct BigZHeader
+{
+ BigNumLength Size;
+ BzSign Sign;
+};
+
+
+struct BigZStruct
+{
+ struct BigZHeader Header;
+ BigNumDigit Digits [16];
+};
+
+
+typedef struct BigZStruct * BigZ;
+
+/* */
+
+
+ /*********** macros of bz.c **********/
+
+
+#define BzGetSize(z) ((BigNumLength)(z)->Header.Size)
+#define BzGetSign(z) ((z)->Header.Sign)
+
+#define BzSetSize(z,s) (z)->Header.Size = s
+#define BzSetSign(z,s) (z)->Header.Sign = s
+
+#define BzGetOppositeSign(z) (-(z)->Header.Sign)
+
+
+ /*********** functions of bz.c **********/
+
+extern void BzInit __((void));
+extern void BzClose __((void));
+
+extern BigZ BzCreate __((BigNumLength));
+extern void BzFree __((BigZ));
+extern void BzFreeString __((char *));
+
+extern BigNumLength BzNumDigits __((BigZ));
+
+extern BigZ BzCopy __((BigZ));
+extern BigZ BzNegate __((BigZ));
+extern BigZ BzAbs __((BigZ));
+extern BigNumCmp BzCompare __((BigZ, BigZ));
+
+extern BigZ BzAdd __((BigZ, BigZ));
+extern BigZ BzSubtract __((BigZ, BigZ));
+extern BigZ BzMultiply __((BigZ, BigZ));
+extern BigZ BzDivide __((BigZ, BigZ, BigZ *));
+extern BigZ BzDiv __((BigZ, BigZ));
+extern BigZ BzMod __((BigZ, BigZ));
+
+extern BigZ BzFromString __((char *, BigNumDigit));
+extern char * BzToString __((BigZ, BigNumDigit));
+
+extern BigZ BzFromInteger __((int));
+extern int BzToInteger __((BigZ));
+
+extern BigZ BzFromBigNum __((BigNum, BigNumLength));
+extern BigNum BzToBigNum __((BigZ, BigNumLength *));
+
+ /*********** functions of bzf.c **********/
+
+extern BigZ BzFactorial __((BigZ));
diff --git a/otherlibs/num/bignum/h/BntoBnn.h b/otherlibs/num/bignum/h/BntoBnn.h
new file mode 100644
index 000000000..a01679a0f
--- /dev/null
+++ b/otherlibs/num/bignum/h/BntoBnn.h
@@ -0,0 +1,111 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988 */
+/* Last modified on Wed Feb 14 16:20:34 GMT+1:00 1990 by herve */
+/* modified on 17-OCT-1989 20:23:23.17 by Jim Lawton SDE/Galway */
+
+/* BntoBnn.h: allowing to use the new interfaces of KerN */
+
+
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#ifndef VMS
+extern char *malloc();
+#endif
+#endif
+
+ /* old types of Bn */
+
+typedef unsigned int BigNumType; /* A BigNum's type */
+
+struct BigNumHeader /* The header of a BigNum */
+{
+ BigNumType type;
+ int length;
+};
+
+
+ /* macros of old types of Bn */
+
+#define BN_TYPE(n) (((struct BigNumHeader *) n) - 1)->type
+#define BN_LENGTH(n) (((struct BigNumHeader *) n) - 1)->length
+
+
+ /* macros of functions of Bn to functions Bnn */
+
+#define BnIsZero(n, nd, nl) BnnIsZero ((n+nd), nl)
+#define BnMultiply(p, pd, pl, m, md, ml, n, nd, nl) BnnMultiply ((p+pd), pl, (m+md), ml, (n+nd), nl)
+#define BnDivide(n, nd, nl, d, dd, dl) BnnDivide ((n+nd), nl, (d+dd), dl)
+#define BnCompare(m, md, ml, n, nd, nl) BnnCompare ((m+md), ml, (n+nd), nl)
+#define BnSetToZero(n, nd, nl) BnnSetToZero ((n+nd), nl)
+#define BnAssign(m, md, n, nd, nl) BnnAssign ((m+md), (n+nd), nl)
+#define BnSetDigit(n, nd, d) BnnSetDigit ((n+nd), d)
+#define BnGetDigit(n, nd) BnnGetDigit ((n+nd))
+#define BnNumDigits(n, nd, nl) BnnNumDigits ((n+nd), nl)
+#define BnNumLeadingZeroBitsInDigit(n, nd) BnnNumLeadingZeroBitsInDigit (*(n+nd))
+#define BnDoesDigitFitInWord(n, nd) BnnDoesDigitFitInWord (*(n+nd))
+#define BnIsDigitZero(n, nd) BnnIsDigitZero (*(n+nd))
+#define BnIsDigitNormalized(n, nd) BnnIsDigitNormalized (*(n+nd))
+#define BnIsDigitOdd(n, nd) BnnIsDigitOdd (*(n+nd))
+#define BnCompareDigits(m, md, n, nd) BnnCompareDigits (*(m+md), *(n+nd))
+#define BnComplement(n, nd, nl) BnnComplement ((n+nd), nl)
+#define BnAndDigits(m, md, n, nd) BnnAndDigits ((m+md), *(n+nd))
+#define BnOrDigits(m, md, n, nd) BnnOrDigits ((m+md), *(n+nd))
+#define BnXorDigits(m, md, n, nd) BnnXorDigits ((m+md), *(n+nd))
+#define BnShiftLeft(m, md, ml, n, nd, nbits) *(n+nd) = BnnShiftLeft ((m+md), ml, nbits)
+#define BnShiftRight(m, md, ml, n, nd, nbits) *(n+nd) = BnnShiftRight ((m+md), ml, nbits)
+#define BnAddCarry(n, nd, nl, carryin) BnnAddCarry ((n+nd), nl, carryin)
+#define BnAdd(m, md, ml, n, nd, nl, carryin) BnnAdd ((m+md), ml, (n+nd), nl, carryin)
+#define BnSubtractBorrow(n, nd, nl, carryin) BnnSubtractBorrow ((n+nd), nl, carryin)
+#define BnSubtract(m, md, ml, n, nd, nl, carryin) BnnSubtract ((m+md), ml, (n+nd), nl, carryin)
+#define BnMultiplyDigit(p, pd, pl, m, md, ml, n, nd) BnnMultiplyDigit ((p+pd), pl, (m+md), ml, *(n+nd))
+#define BnDivideDigit(q, qd, r, rd, n, nd, nl, d, dd) *(r+rd) = BnnDivideDigit ((q+qd), (n+nd), nl, *(d+dd))
+
+
+ /* old functions of Bn */
+
+/*
+ * Creation and access to type and length fields.
+ */
+
+/* Allocates a BigNum structure and returns a pointer to it */
+BigNum BnAlloc(size) int size; {
+ register BigNum n;
+
+ n = (BigNum) ((char *) malloc(sizeof(struct BigNumHeader) +
+ size * sizeof(BigNumDigit))
+ + sizeof(struct BigNumHeader));
+ BN_LENGTH(n) = size;
+ return(n);
+}
+
+/* Allocates a BigNum, inserts its Type, and returns a pointer to it */
+BigNum BnCreate(type, size) BigNumType type; int size; {
+ register BigNum n;
+
+ n = BnAlloc(size);
+ BN_TYPE(n) = type;
+ BnSetToZero(n, 0, size);
+ return(n);
+}
+
+/* Frees a BigNum structure */
+int BnFree(n) BigNum n; {
+ free(((struct BigNumHeader *) n) - 1);
+ return 1;
+}
+
+/* Returns the BigNum's Type */
+BigNumType BnGetType(n) BigNum n; {
+ return(BN_TYPE(n));
+}
+
+/* Sets the BigNum's Type */
+void BnSetType(n, type) BigNum n; BigNumType type; {
+ BN_TYPE(n) = type;
+}
+
+/* Returns the number of digits allocated for the BigNum */
+int BnGetSize(n) BigNum n; {
+ return(BN_LENGTH(n));
+}
+
diff --git a/otherlibs/num/bignum/s/68KerN.s b/otherlibs/num/bignum/s/68KerN.s
new file mode 100644
index 000000000..1b84ae0fb
--- /dev/null
+++ b/otherlibs/num/bignum/s/68KerN.s
@@ -0,0 +1,403 @@
+| Copyright Digital Equipment Corporation & INRIA 1988, 1989
+|
+| KerN for the 68020 : MIT syntax
+| [Bepaul]
+|
+ .text
+
+ .globl _BnnSetToZero
+_BnnSetToZero: BSTZnn = 4
+ BSTZnl = 8
+ movl sp@(BSTZnn),a0
+ movl sp@(BSTZnl),d0
+ dbf d0,BSTZ1 | if(nl--) goto BSTZ1;
+ rts | return;
+BSTZ1: clrl a0@+ | *(nn++) = 0;
+ dbf d0,BSTZ1 | if(nl--) goto BSTZ1;
+ rts | return;
+
+ .globl _BnnAssign
+_BnnAssign: BAGmm = 4
+ BAGnn = 8
+ BAGnl = 12
+ movl sp@(BAGmm),a0
+ movl sp@(BAGnn),a1
+ movl sp@(BAGnl),d0
+ cmpl a1,a0
+ jcc BAG2 | if(mm >= nn) goto BAG2;
+ dbf d0,BAG1 | if(nl--) goto BAG1;
+ rts | return;
+BAG1: movl a1@+,a0@+ | *(mm++) = *(nn++);
+ dbf d0,BAG1 | if(nl--) goto BAG1;
+ rts | return;
+BAG2: jls BAG4 | if(mm <= nn) goto BAG4;
+ lea a0@(0,d0:l:4),a0 | mm = &mm[nl];
+ lea a1@(0,d0:l:4),a1 | nn = &nn[nl];
+ dbf d0,BAG3 | if(nl--) goto BAG3;
+ rts | return;
+BAG3: movl a1@-,a0@- | *(--mm) = *(--nn);
+ dbf d0,BAG3 | if(nl--) goto BAG3;
+BAG4: rts | return;
+
+ .globl _BnnSetDigit
+_BnnSetDigit: BSDnn = 4
+ BSDd = 8
+ movl sp@(BSDnn),a0
+ movl sp@(BSDd),a0@ | *nn = d;
+ rts | return;
+
+ .globl _BnnGetDigit
+_BnnGetDigit: BGDnn = 4
+ movl sp@(BGDnn),a0
+ movl a0@,d0 | return(*nn);
+ rts
+
+ .globl _BnnNumDigits
+_BnnNumDigits: BNDnn = 4
+ BNDnl = 8
+ movl sp@(BNDnn),a0
+ movl sp@(BNDnl),d0
+ lea a0@(0,d0:l:4),a0 | nn = &nn[nl];
+ dbf d0,BND1 | if(nl--) goto BND1;
+ moveq #1,d0
+ rts | return(1);
+BND1: tstl a0@-
+ jne BND3 | if(*(--nn) != 0) goto BND3;
+ dbf d0,BND1 | if(nl--) goto BND1;
+ moveq #1,d0
+ rts | return(1);
+BND3: addql #1,d0
+ rts | return(nl + 1);
+
+ .globl _BnnNumLeadingZeroBitsInDigit
+_BnnNumLeadingZeroBitsInDigit: BLZd = 4
+ bfffo sp@(BLZd){#0:#32},d0
+ rts
+
+ .globl _BnnDoesDigitFitInWord
+_BnnDoesDigitFitInWord: BDFd = 4
+ moveq #1,d0 | C_VERSION
+ rts
+
+ .globl _BnnIsDigitZero
+_BnnIsDigitZero: BDZd = 4
+ clrl d0
+ tstl sp@(BDZd)
+ seq d0
+ rts | return(d == 0);
+
+ .globl _BnnIsDigitNormalized
+_BnnIsDigitNormalized: BDNd = 4
+ clrl d0
+ tstw sp@(BDNd)
+ smi d0
+ rts | return(d < 0);
+
+ .globl _BnnIsDigitOdd
+_BnnIsDigitOdd: BDOd = 4
+ clrl d0
+ movw sp@(BDOd+2),cc
+ scs d0
+ rts | return(d & 1);
+
+ .globl _BnnCompareDigits
+_BnnCompareDigits: BCDd1 = 4
+ BCDd2 = 8
+ movl sp@(BCDd1),d1
+ cmpl sp@(BCDd2),d1
+ bhi BCDsup | if(d1 > d2) goto BCDsup;
+ sne d0
+ extbl d0
+ rts | return(-(d1 < d2));
+BCDsup: moveq #1,d0
+ rts | return(1);
+
+ .globl _BnnComplement
+_BnnComplement: BCMnn = 4
+ BCMnl = 8
+ movl sp@(BCMnn),a0
+ movl sp@(BCMnl),d0
+ dbf d0,BCM1 | if(nl--) goto BCM1;
+ rts | return;
+BCM1: notl a0@+ | *(nn++) ^= -1;
+ dbf d0,BCM1 | if(nl--) goto BCM1;
+ rts | return;
+
+ .globl _BnnAndDigits
+_BnnAndDigits: BADnn = 4
+ BADd = 8
+ movl sp@(BADnn),a0
+ movl sp@(BADd),d0
+ andl d0,a0@ | *n &= d;
+ rts | return;
+
+ .globl _BnnOrDigits
+_BnnOrDigits: BODnn = 4
+ BODd = 8
+ movl sp@(BODnn),a0
+ movl sp@(BODd),d0
+ orl d0,a0@ | *n |= d;
+ rts | return;
+
+ .globl _BnnXorDigits
+_BnnXorDigits: BXDnn = 4
+ BXDd = 8
+ movl sp@(BXDnn),a0
+ movl sp@(BXDd),d0
+ eorl d0,a0@ | *n ^= d;
+ rts | return;
+
+ .globl _BnnShiftLeft
+_BnnShiftLeft: BSLmm = 4
+ BSLml = 8
+ BSLnbi = 12
+ clrl d0 | res = 0;
+ movl sp@(BSLnbi),d1
+ jne BSL0 | if(nbi) goto BSL0;
+ rts | return(res);
+BSL0: movl sp@(BSLmm),a0
+ moveml #0x3C00,sp@- | Save 4 registers
+ movl sp@(BSLml + 16),d2
+ moveq #32,d3 | rnbi = BN_DIGIT_SIZE;
+ subl d1,d3 | rnbi -= nbi;
+ dbf d2,BSL1 | if(ml--) goto BSL1;
+ moveml a7@+,#0x003C | Restore 4 registers
+ rts | return(res);
+BSL1: movl a0@,d4 | save = *mm;
+ movl d4,d5 | X = save;
+ lsll d1,d5 | X <<= nbi;
+ orl d0,d5 | X |= res;
+ movl d5,a0@+ | *(mm++) = X;
+ movl d4,d0 | res = save;
+ lsrl d3,d0 | res >>= rnbi;
+ dbf d2,BSL1 | if(ml--) goto BSL1;
+ moveml a7@+,#0x003C | Restore 4 registers
+ rts | return(res);
+
+ .globl _BnnShiftRight
+_BnnShiftRight: BSRmm = 4
+ BSRml = 8
+ BSRnbi = 12
+ clrl d0 | res = 0;
+ movl sp@(BSRnbi),d1
+ jne BSR0 | if(nbi) goto BSR0;
+ rts | return(res);
+BSR0: movl sp@(BSRmm),a0
+ moveml #0x3C00,sp@- | Save 4 registers
+ movl sp@(BSRml + 16),d2
+ lea a0@(0,d2:l:4),a0 | mm = &mm[ml];
+ moveq #32,d3 | lnbi = BN_DIGIT_SIZE;
+ subl d1,d3 | lnbi -= nbi;
+ dbf d2,BSR1 | if(ml--) goto BSR1;
+ moveml a7@+,#0x003C | Restore 4 registers
+ rts | return(res);
+BSR1: movl a0@-,d4 | save = *(--mm);
+ movl d4,d5 | X = save;
+ lsrl d1,d5 | X >>= nbi;
+ orl d0,d5 | X |= res;
+ movl d5,a0@ | *mm = X;
+ movl d4,d0 | res = save;
+ lsll d3,d0 | res <<= lnbi;
+BSR2: dbf d2,BSR1 | if(ml--) goto BSR1;
+ moveml a7@+,#0x003C | Restore 4 registers
+ rts | return(res);
+
+ .globl _BnnAddCarry
+_BnnAddCarry: BACnn = 4
+ BACnl = 8
+ BACcar = 12
+ movl sp@(BACcar),d0 |
+ jeq BAC2 | if(car == 0) return(car);
+ movl sp@(BACnl),d0 |
+ jeq BAC3 | if(nl == 0) return(1);
+ movl sp@(BACnn),a0
+ subql #1,d0 | nl--;
+BAC1: addql #1,a0@+ | ++(*nn++);
+ dbcc d0,BAC1 | if(Carry || nl--) goto BAC1
+ scs d0
+ negb d0
+ extbl d0
+BAC2: rts | return(Carry)
+BAC3: moveq #1,d0
+ rts | return(1);
+
+ .globl _BnnAdd
+_BnnAdd: BADDmm = 4
+ BADDml = 8
+ BADDnn = 12
+ BADDnl = 16
+ BADDcar = 20
+ movl sp@(BADDmm),a0
+ movl sp@(BADDnn),a1
+ movl sp@(BADDnl),d1
+ subl d1,sp@(BADDml) | ml -= nl;
+ tstl d1
+ jne BADD1 | if(nl) goto BADD1
+ tstl sp@(BADDcar) ||
+ jne BADD7 | if(car) goto BADD7
+ clrl d0
+ rts | return(0);
+BADD1: subql #1,d1 | nl--;
+ movl sp@(BADDcar),d0
+ negb d0 | /* Bit No 4 */
+ movw d0,cc | X = car;
+ movl d2,sp@- ||| Save register.
+BADDX: movl a1@+,d0
+ movl a0@,d2
+ addxl d0,d2 | N = *mm + *(nn++) + X
+ movl d2,a0@+ | X = N >> 32; *(mn++) = N;
+ dbf d1,BADDX | if(nl--) goto BADDX
+ movl sp@+,d2 ||| Restore register.
+ movw cc,d0
+ andw #0x10,d0
+ jne BADD7 | if(X) goto BADD7;
+ clrl d0 | return(0);
+ rts
+BADD7: movl sp@(BADDml),d0
+ jeq BADD9 | if(ml == 0) return(1);
+ subql #1,d0 | ml--;
+BADD8: addql #1,a0@+ | ++(*mm++);
+ dbcc d0,BADD8 | if(Carry || ml--) goto BADD8
+ scs d0
+ negb d0
+ extbl d0
+ rts | return(Carry)
+BADD9: moveq #1,d0
+ rts | return(1);
+
+ .globl _BnnSubtractBorrow
+_BnnSubtractBorrow: BSBnn = 4
+ BSBnl = 8
+ BSBcar = 12
+ movl sp@(BSBcar),d0
+ jne BSB2 | if(car) return(car);
+ movl sp@(BSBnl),d0
+ jeq BSB3 | if(nl == 0) return(0);
+ movl sp@(BSBnn),a0
+ subql #1,d0 | nl--;
+BSB1: subql #1,a0@+ | (*nn++)--;
+ dbcc d0,BSB1 | if(Carry || nl--) goto BSB1
+ scc d0
+ negb d0
+ extbl d0
+BSB2: rts | return(Carry)
+BSB3: moveq #0,d0
+ rts | return(0);
+
+ .globl _BnnSubtract
+_BnnSubtract: BSmm = 4
+ BSml = 8
+ BSnn = 12
+ BSnl = 16
+ BScar = 20
+ movl sp@(BSmm),a0
+ movl sp@(BSnn),a1
+ movl sp@(BSnl),d1
+ subl d1,sp@(BSml) | ml -= nl;
+ tstl d1
+ jne BS1 | if(nl) goto BS1
+ tstl sp@(BScar)
+ jeq BS7 | if(!car) goto BS7
+ moveq #1,d0
+ rts | return(1);
+BS1: subql #1,d1 | nl--;
+ movl sp@(BScar),d0
+ negb d0 | /* Bit No 4 */
+ notb d0
+ movw d0,cc | X = ~car;
+ movl d2,sp@- ||| Save register.
+BSX: movl a1@+,d0
+ movl a0@,d2
+ subxl d0,d2 | N = *mm - *(nn++) - X
+ movl d2,a0@+ | X = N >> 32; *(mm++) = N;
+ dbf d1,BSX | if(nl--) goto BSX
+ movl sp@+,d2 ||| Restore register.
+ movw cc,d0
+ andw #0x10,d0
+ jne BS7 | if(X) goto BS7;
+ moveq #1,d0 | return(1);
+ rts
+BS7: movl sp@(BSml),d1
+ jeq BS9 | if(ml == 0) goto BS9;
+ subql #1,d1 | ml--;
+BS8: subql #1,a0@+ | --(*m++);
+ dbcc d1,BS8 | if(Carry || ml--) goto BS8
+ scc d0
+ negb d0
+ extbl d0
+ rts | return(C)
+BS9: clrl d0
+ rts | return(0);
+
+ .globl _BnnMultiplyDigit
+_BnnMultiplyDigit: BMDpp = 4
+ BMDpl = 8
+ BMDmm = 12
+ BMDml = 16
+ BMDd = 20
+ movl sp@(BMDd),d0
+ jne BMD1 | if(d) goto BMD1;
+ rts | return(0);
+BMD1: cmpl #1,d0
+ jne BMD2 | if(d != 1) goto BMD2;
+ clrl sp@(BMDd)
+ bra _BnnAdd | BnnAdd(p,pl,m,ml,0);
+BMD2: movl sp@(BMDpp),a0
+ movl sp@(BMDmm),a1
+ movl sp@(BMDml),d1
+ subl d1,sp@(BMDpl) | pl -= ml;
+ moveml #0x3c00,sp@- | Save 4 registers
+ clrl d2 | low = 0;
+ clrl d5
+ bra BMD6 | goto BMD6;
+BMD3: movl a1@+,d4 | X = *(mm++);
+ mulul d0,d3:d4 | X *= d;
+ addl d2,d4 | X += low;
+ addxl d5,d3 | X(hight) += Carry;
+ addl a0@,d4 | X += *pp;
+ addxl d5,d3 | X(hight) += Carry;
+ movl d4,a0@+ | *(pp++) = X(low);
+ movl d3,d2 | low = X(hight);
+BMD6: dbf d1,BMD3 | if(ml--) goto BMD3;
+ movl d2,d0
+ moveml a7@+,#0x003C | Restore 4 registers
+ addl d0,a0@+ | *(pp++) += low;
+ bcs BMD7 | if(Carry) goto BMD7;
+ clrl d0
+ rts | return(0);
+BMD7: movl sp@(BMDpl),d0
+ subql #1,d0 | pl--;
+ jeq BMD10 | if(!pl) goto BM10;
+ subql #1,d0 | pl--;
+BMD8: addql #1,a0@+ | ++(*pp++);
+BMD9: dbcc d0,BMD8 | if(Carry || pl--) goto BMD8
+ scs d0
+ negb d0
+ extbl d0
+ rts | return(Carry);
+BMD10: moveq #1,d0
+ rts | return(1);
+
+ .globl _BnnDivideDigit
+_BnnDivideDigit: BDDqq = 12
+ BDDnn = 16
+ BDDnl = 20
+ BDDd = 24
+ moveml #0x3000,sp@- | Save 2 registers
+ movl sp@(BDDqq),a1
+ movl sp@(BDDnn),a0
+ movl sp@(BDDnl),d0
+ movl sp@(BDDd),d1
+ lea a0@(0,d0:l:4),a0 | nn = &nn[nl];
+ subql #1,d0 | nl--;
+ lea a1@(0,d0:l:4),a1 | qq = &qq[nl];
+ movl a0@-,d2 || X(hight) = *(--nn);
+ bra BDD2 | goto BDD2;
+BDD1: movl a0@-,d3 | X(low) = *(--nn);
+ divul d1,d2:d3 | X(low) = X / d;
+ | X(hight) = X % d;
+ movl d3,a1@- | *(--qq) = X(low);
+BDD2: dbf d0,BDD1 | if(nl--) goto BDD1;
+ movl d2,d0 || return(X(hight));
+ moveml a7@+,#0x000C | Restore 2 registers
+ rts
diff --git a/otherlibs/num/bignum/s/68KerN_mot.s b/otherlibs/num/bignum/s/68KerN_mot.s
new file mode 100644
index 000000000..6baa43803
--- /dev/null
+++ b/otherlibs/num/bignum/s/68KerN_mot.s
@@ -0,0 +1,410 @@
+| Copyright Digital Equipment Corporation & INRIA 1988, 1989
+|
+| KerN for the 68020 : MOTOROLA syntax
+| [Bepaul]
+|
+ SECTION 10
+
+ XDEF _BnnSetToZero
+BSTZnn EQU 4
+BSTZnl EQU 8
+_BnnSetToZero MOVE.L BSTZnn(A7),A0
+ MOVE.L BSTZnl(A7),D0
+ DBF D0,BSTZ1 | if(nl--) goto BSTZ1;
+ RTS | return;
+BSTZ1 CLR.L (A0)+ | *(nn++) = 0;
+ DBF D0,BSTZ1 | if(nl--) goto BSTZ1;
+ RTS | return;
+
+ XDEF _BnnAssign
+BAGmm EQU 4
+BAGnn EQU 8
+BAGnl EQU 12
+_BnnAssign MOVE.L BAGmm(A7),A0
+ MOVE.L BAGnn(A7),A1
+ MOVE.L BAGnl(A7),D0
+ CMP.L A1,A0
+ BCC BAG2 | if(mm >= nn) goto BAG2;
+ DBF D0,BAG1 | if(nl--) goto BAG1;
+ RTS | return;
+BAG1 MOVE.L (A1)+,(A0)+ | *(mm++) = *(nn++);
+ DBF D0,BAG1 | if(nl--) goto BAG1;
+ RTS | return;
+BAG2 BLS BAG4 | if(mm <= nn) goto BAG4;
+ LEA 0(A0,D0.L*4),A0 | mm = &mm[nl];
+ LEA 0(A1,D0.L*4),A1 | nn = &nn[nl];
+ DBF D0,BAG3 | if(nl--) goto BAG3;
+ RTS | return;
+BAG3 MOVE.L -(A1),-(A0) | *(--mm) = *(--nn);
+ DBF D0,BAG3 | if(nl--) goto BAG3;
+BAG4 RTS | return;
+
+ XDEF _BnnSetDigit
+BSDnn EQU 4
+BSDd EQU 8
+_BnnSetDigit MOVE.L BSDnn(A7),A0
+ MOVE.L BSDd(A7),(A0) | *nn = d;
+ RTS | return;
+
+ XDEF _BnnGetDigit
+BGDnn EQU 4
+_BnnGetDigit MOVE.L BGDnn(A7),A0
+ MOVE.L (A0),D0 | return(*nn);
+ RTS
+
+ XDEF _BnnNumDigits
+BNDnn EQU 4
+BNDnl EQU 8
+_BnnNumDigits MOVE.L BNDnn(A7),A0
+ MOVE.L BNDnl(A7),D0
+ LEA 0(A0,D0.L*4),A0 | nn = &nn[nl];
+ DBF D0,BND1 | if(nl--) goto BND1;
+ MOVEQ #1,D0
+ RTS | return(1);
+BND1 TST.L -(A0)
+ BNE BND3 | if(*(--nn) != 0) goto BND3;
+ DBF D0,BND1 | if(nl--) goto BND1;
+ MOVEQ #1,D0
+ RTS | return(1);
+BND3 ADDQ.L #1,D0
+ RTS | return(nl + 1);
+
+ XDEF _BnnNumLeadingZeroBitsInDigit
+BLZd EQU 4
+_BnnNumLeadingZeroBitsInDigit
+ BFFFO BLZd(A7){#0:#32},D0
+ RTS
+
+ XDEF _BnnDoesDigitFitInWord
+BDFd EQU 4
+_BnnDoesDigitFitInWord
+ MOVEQ #1,D0 | C_VERSION
+ RTS
+
+ XDEF _BnnIsDigitZero
+BDZd EQU 4
+_BnnIsDigitZero CLR.L D0
+ TST.L BDZd(A7)
+ SEQ D0
+ RTS | return(d == 0);
+
+ XDEF _BnnIsDigitNormalized
+BDNd EQU 4
+_BnnIsDigitNormalized
+ CLR.L D0
+ TST.W BDNd(A7)
+ SMI D0
+ RTS | return(d < 0);
+
+ XDEF _BnnIsDigitOdd
+BDOd EQU 4
+_BnnIsDigitOdd CLR.L D0
+ MOVE BDOd+2(A7),CCR
+ SCS D0
+ RTS | return(d & 1);
+
+ XDEF _BnnCompareDigits
+BCDd1 EQU 4
+BCDd2 EQU 8
+_BnnCompareDigits
+ MOVE.L BCDd1(A7),D1
+ CMP.L BCDd2(A7),D1
+ BHI BCDsup | if(d1 > d2) goto BCDsup;
+ SNE D0
+ EXTB.L D0
+ RTS | return(-(d1 < d2));
+BCDsup MOVEQ #1,D0
+ RTS | return(1);
+
+ XDEF _BnnComplement
+BCMnn EQU 4
+BCMnl EQU 8
+_BnnComplement MOVE.L BCMnn(A7),A0
+ MOVE.L BCMnl(A7),D0
+ DBF D0,BCM1 | if(nl--) goto BCM1;
+ RTS | return;
+BCM1 NOT.L (A0)+ | *(nn++) ^= -1;
+ DBF D0,BCM1 | if(nl--) goto BCM1;
+ RTS | return;
+
+ XDEF _BnnAndDigits
+BADnn EQU 4
+BADd EQU 8
+_BnnAndDigits MOVE.L BADnn(A7),A0
+ MOVE.L BADd(A7),D0
+ AND.L D0,(A0) | *n &= d;
+ RTS | return;
+
+ XDEF _BnnOrDigits
+BODnn EQU 4
+BODd EQU 8
+_BnnOrDigits MOVE.L BODnn(A7),A0
+ MOVE.L BODd(A7),D0
+ OR.L D0,(A0) | *n |= d;
+ RTS | return;
+
+ XDEF _BnnXorDigits
+BXDnn EQU 4
+BXDd EQU 8
+_BnnXorDigits
+ MOVE.L BXDnn(A7),A0
+ MOVE.L BXDd(A7),D0
+ EOR.L D0,(A0) | *n ^= d;
+ RTS | return;
+
+ XDEF _BnnShiftLeft
+BSLmm EQU 4
+BSLml EQU 8
+BSLnbi EQU 12
+_BnnShiftLeft CLR.L D0 | res = 0;
+ MOVE.L BSLnbi(A7),D1
+ BNE BSL0 | if(nbi) goto BSL0;
+ RTS | return(res);
+BSL0 MOVE.L BSLmm(A7),A0
+ MOVEM.L D2-D5,-(A7) | Save 4 registers
+ MOVE.L BSLml+16(A7),D2
+ MOVEQ #32,D3 | rnbi = BN_DIGIT_SIZE;
+ SUB.L D1,D3 | rnbi -= nbi;
+ DBF D2,BSL1 | if(ml--) goto BSL1;
+ MOVEM.L (A7)+,D2-D5 | Restore 4 registers
+ RTS | return(res);
+BSL1 MOVE.L (A0),D4 | save = *mm;
+ MOVE.L D4,D5 | X = save;
+ LSL.L D1,D5 | X <<= nbi;
+ OR.L D0,D5 | X |= res;
+ MOVE.L D5,(A0)+ | *(mm++) = X;
+ MOVE.L D4,D0 | res = save;
+ LSR.L D3,D0 | res >>= rnbi;
+ DBF D2,BSL1 | if(ml--) goto BSL1;
+ MOVEM.L (A7)+,D2-D5 | Restore 4 registers
+ RTS | return(res);
+
+ XDEF _BnnShiftRight
+BSRmm EQU 4
+BSRml EQU 8
+BSRnbi EQU 12
+_BnnShiftRight CLR.L D0 | res = 0;
+ MOVE.L BSRnbi(A7),D1
+ BNE BSR0 | if(nbi) goto BSR0;
+ RTS | return(res);
+BSR0 MOVE.L BSRmm(A7),A0
+ MOVEM.L D2-D5,-(A7) | Save 4 registers
+ MOVE.L BSRml+16(A7),D2
+ LEA 0(A0,D2.L*4),A0 | mm = &mm[ml];
+ MOVEQ #32,D3 | lnbi = BN_DIGIT_SIZE;
+ SUB.L D1,D3 | lnbi -= nbi;
+ DBF D2,BSR1 | if(ml--) goto BSR1;
+ MOVEM.L (A7)+,D2-D5 | Restore 4 registers
+ RTS | return(res);
+BSR1 MOVE.L -(A0),D4 | save = *(--mm);
+ MOVE.L D4,D5 | X = save;
+ LSR.L D1,D5 | X >>= nbi;
+ OR.L D0,D5 | X |= res;
+ MOVE.L D5,(A0) | *mm = X;
+ MOVE.L D4,D0 | res = save;
+ LSL.L D3,D0 | res <<= lnbi;
+BSR2 DBF D2,BSR1 | if(ml--) goto BSR1;
+ MOVEM.L (A7)+,D2-D5 | Restore 4 registers
+ RTS | return(res);
+
+ XDEF _BnnAddCarry
+BACnn EQU 4
+BACnl EQU 8
+BACcar EQU 12
+_BnnAddCarry MOVE.L BACcar(A7),D0 |
+ BEQ BAC2 | if(car == 0) return(car);
+ MOVE.L BACnl(A7),D0 |
+ BEQ BAC3 | if(nl == 0) return(1);
+ MOVE.L BACnn(A7),A0
+ SUBQ.L #1,D0 | nl--;
+BAC1 ADDQ.L #1,(A0)+ | ++(*nn++);
+ DBCC D0,BAC1 | if(Carry || nl--) goto BAC1
+ SCS D0
+ NEG.B D0
+ EXTB.L D0
+BAC2 RTS | return(Carry)
+BAC3 MOVEQ #1,D0
+ RTS | return(1);
+
+ XDEF _BnnAdd
+BADDmm EQU 4
+BADDml EQU 8
+BADDnn EQU 12
+BADDnl EQU 16
+BADDcar EQU 20
+_BnnAdd MOVE.L BADDmm(A7),A0
+ MOVE.L BADDnn(A7),A1
+ MOVE.L BADDnl(A7),D1
+ SUB.L D1,BADDml(A7) | ml -= nl;
+ TST.L D1
+ BNE BADD1 | if(nl) goto BADD1
+ TST.L BADDcar(A7) ||
+ BNE BADD7 | if(car) goto BADD7
+ CLR.L D0
+ RTS | return(0);
+BADD1 SUBQ.L #1,D1 | nl--;
+ MOVE.L BADDcar(A7),D0
+ NEG.B D0 | /* Bit No 4 */
+ MOVE D0,CCR | X = car;
+ MOVE.L D2,-(A7) ||| Save register.
+BADDX MOVE.L (A1)+,D0
+ MOVE.L (A0),D2
+ ADDX.L D0,D2 | N = *mm + *(nn++) + X
+ MOVE.L D2,(A0)+ | X = N >> 32; *(mn++) = N;
+ DBF D1,BADDX | if(nl--) goto BADDX
+ MOVE.L (A7)+,D2 ||| Restore register.
+ MOVE CCR,D0
+ AND.W #0x10,D0
+ BNE BADD7 | if(X) goto BADD7;
+ CLR.L D0 | return(0);
+ RTS
+BADD7 MOVE.L BADDml(A7),D0
+ BEQ BADD9 | if(ml == 0) return(1);
+ SUBQ.L #1,D0 | ml--;
+BADD8 ADDQ.L #1,(A0)+ | ++(*mm++);
+ DBCC D0,BADD8 | if(Carry || ml--) goto BADD8
+ SCS D0
+ NEG.B D0
+ EXTB.L D0
+ RTS | return(Carry)
+BADD9 MOVEQ #1,D0
+ RTS | return(1);
+
+ XDEF _BnnSubtractBorrow
+BSBnn EQU 4
+BSBnl EQU 8
+BSBcar EQU 12
+_BnnSubtractBorrow
+ MOVE.L BSBcar(A7),D0
+ BNE BSB2 | if(car) return(car);
+ MOVE.L BSBnl(A7),D0
+ BEQ BSB3 | if(nl == 0) return(0);
+ MOVE.L BSBnn(A7),A0
+ SUBQ.L #1,D0 | nl--;
+BSB1 SUBQ.L #1,(A0)+ | (*nn++)--;
+ DBCC D0,BSB1 | if(Carry || nl--) goto BSB1
+ SCC D0
+ NEG.B D0
+ EXTB.L D0
+BSB2 RTS | return(Carry)
+BSB3 MOVEQ #0,D0
+ RTS | return(0);
+
+ XDEF _BnnSubtract
+BSmm EQU 4
+BSml EQU 8
+BSnn EQU 12
+BSnl EQU 16
+BScar EQU 20
+_BnnSubtract MOVE.L BSmm(A7),A0
+ MOVE.L BSnn(A7),A1
+ MOVE.L BSnl(A7),D1
+ SUB.L D1,BSml(A7) | ml -= nl;
+ TST.L D1
+ BNE BS1 | if(nl) goto BS1
+ TST.L BScar(A7)
+ BEQ BS7 | if(!car) goto BS7
+ MOVEQ #1,D0
+ RTS | return(1);
+BS1 SUBQ.L #1,D1 | nl--;
+ MOVE.L BScar(A7),D0
+ NEG.B D0 | /* Bit No 4 */
+ NOT.B D0
+ MOVE D0,CCR | X = ~car;
+ MOVE.L D2,-(A7) ||| Save register.
+BSX MOVE.L (A1)+,D0
+ MOVE.L (A0),D2
+ SUBX.L D0,D2 | N = *mm - *(nn++) - X
+ MOVE.L D2,(A0)+ | X = N >> 32; *(mm++) = N;
+ DBF D1,BSX | if(nl--) goto BSX
+ MOVE.L (A7)+,D2 ||| Restore register.
+ MOVE CCR,D0
+ AND.W #0x10,D0
+ BNE BS7 | if(X) goto BS7;
+ MOVEQ #1,D0 | return(1);
+ RTS
+BS7 MOVE.L BSml(A7),D1
+ BEQ BS9 | if(ml == 0) goto BS9;
+ SUBQ.L #1,D1 | ml--;
+BS8 SUBQ.L #1,(A0)+ | --(*m++);
+ DBCC D1,BS8 | if(Carry || ml--) goto BS8
+ SCC D0
+ NEG.B D0
+ EXTB.L D0
+ RTS | return(C)
+BS9 CLR.L D0
+ RTS | return(0);
+
+ XDEF _BnnMultiplyDigit
+BMDpp EQU 4
+BMDpl EQU 8
+BMDmm EQU 12
+BMDml EQU 16
+BMDd EQU 20
+_BnnMultiplyDigit
+ MOVE.L BMDd(A7),D0
+ BNE BMD1 | if(d) goto BMD1;
+ RTS | return(0);
+BMD1 CMP.L #1,D0
+ BNE BMD2 | if(d != 1) goto BMD2;
+ CLR.L BMDd(A7)
+ BRA _BnnAdd | BnnAdd(p,pl,m,ml,0);
+BMD2 MOVE.L BMDpp(A7),A0
+ MOVE.L BMDmm(A7),A1
+ MOVE.L BMDml(A7),D1
+ SUB.L D1,BMDpl(A7) | pl -= ml;
+ MOVEM.L D2-D5,-(A7) | Save 4 registers
+ CLR.L D2 | low = 0;
+ CLR.L D5
+ BRA BMD6 | goto BMD6;
+BMD3 MOVE.L (A1)+,D4 | X = *(mm++);
+ MULU.L D0,D3:D4 | X *= d;
+ ADD.L D2,D4 | X += low;
+ ADDX.L D5,D3 | X(hight) += Carry;
+ ADD.L (A0),D4 | X += *pp;
+ ADDX.L D5,D3 | X(hight) += Carry;
+ MOVE.L D4,(A0)+ | *(pp++) = X(low);
+ MOVE.L D3,D2 | low = X(hight);
+BMD6 DBF D1,BMD3 | if(ml--) goto BMD3;
+ MOVE.L D2,D0
+ MOVEM.L (A7)+,D2-D5 | Restore 4 registers
+ ADD.L D0,(A0)+ | *(pp++) += low;
+ BCS BMD7 | if(Carry) goto BMD7;
+ CLR.L D0
+ RTS | return(0);
+BMD7 MOVE.L BMDpl(A7),D0
+ SUBQ.L #1,D0 | pl--;
+ BEQ BMD10 | if(!pl) goto BM10;
+ SUBQ.L #1,D0 | pl--;
+BMD8 ADDQ.L #1,(A0)+ | ++(*pp++);
+BMD9 DBCC D0,BMD8 | if(Carry || pl--) goto BMD8
+ SCS D0
+ NEG.B D0
+ EXTB.L D0
+ RTS | return(Carry);
+BMD10 MOVEQ #1,D0
+ RTS | return(1);
+
+ XDEF _BnnDivideDigit
+BDDqq EQU 12
+BDDnn EQU 16
+BDDnl EQU 20
+BDDd EQU 24
+_BnnDivideDigit MOVEM.L D2-D3,-(A7) | Save 2 registers
+ MOVE.L BDDqq(A7),A1
+ MOVE.L BDDnn(A7),A0
+ MOVE.L BDDnl(A7),D0
+ MOVE.L BDDd(A7),D1
+ LEA 0(A0,D0.L*4),A0 | nn = &nn[nl];
+ SUBQ.L #1,D0 | nl--;
+ LEA 0(A1,D0.l*4),A1 | qq = &qq[nl];
+ MOVE.L -(A0),D2 || X(hight) = *(--nn);
+ BRA BDD2 | goto BDD2;
+BDD1 MOVE.L -(A0),D3 | X(low) = *(--nn);
+ DIVU.L D1,D2:D3 | X(low) = X / d;
+ | X(hight) = X % d;
+ MOVE.L D3,-(A1) | *(--qq) = X(low);
+BDD2 DBF D0,BDD1 | if(nl--) goto BDD1;
+ MOVE.L D2,D0 || return(X(hight));
+ MOVEM.L (A7)+,D2-D3 | Restore 2 registers
+ RTS
diff --git a/otherlibs/num/bignum/s/68KerN_sony.s b/otherlibs/num/bignum/s/68KerN_sony.s
new file mode 100644
index 000000000..ef5ae6aae
--- /dev/null
+++ b/otherlibs/num/bignum/s/68KerN_sony.s
@@ -0,0 +1,426 @@
+/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
+/* */
+/* KerN for the 68020 : SONY syntax */
+/* [Bepaul] */
+/* */
+ .text
+
+ .globl _BnnSetToZero
+_BnnSetToZero:
+ .set BSTZnn,4
+ .set BSTZnl,8
+ move.l BSTZnn(sp),a0
+ move.l BSTZnl(sp),d0
+ dbf d0,BSTZ1 /* if(nl--) goto BSTZ1; */
+ rts /* return; */
+BSTZ1: clr.l (a0)+ /* *(nn++) = 0; */
+ dbf d0,BSTZ1 /* if(nl--) goto BSTZ1; */
+ rts /* return; */
+
+ .globl _BnnAssign
+_BnnAssign:
+ .set BAGmm,4
+ .set BAGnn,8
+ .set BAGnl,12
+ move.l BAGmm(sp),a0
+ move.l BAGnn(sp),a1
+ move.l BAGnl(sp),d0
+ cmp.l a1,a0
+ bcc BAG2 /* if(mm >= nn) goto BAG2; */
+ dbf d0,BAG1 /* if(nl--) goto BAG1; */
+ rts /* return; */
+BAG1: move.l (a1)+,(a0)+ /* *(mm++) = *(nn++); */
+ dbf d0,BAG1 /* if(nl--) goto BAG1; */
+ rts /* return; */
+BAG2: bls BAG4 /* if(mm <= nn) goto BAG4; */
+ lea (0,a0,d0.l*4),a0 /* mm = &mm[nl]; */
+ lea (0,a1,d0.l*4),a1 /* nn = &nn[nl]; */
+ dbf d0,BAG3 /* if(nl--) goto BAG3; */
+ rts /* return; */
+BAG3: move.l -(a1),-(a0) /* *(--mm) = *(--nn); */
+ dbf d0,BAG3 /* if(nl--) goto BAG3; */
+BAG4: rts /* return; */
+
+ .globl _BnnSetDigit
+_BnnSetDigit:
+ .set BSDnn,4
+ .set BSDd,8
+ move.l BSDnn(sp),a0
+ move.l BSDd(sp),(a0) /* *nn = d; */
+ rts /* return; */
+
+ .globl _BnnGetDigit
+_BnnGetDigit:
+ .set BGDnn,4
+ move.l BGDnn(sp),a0
+ move.l (a0),d0 /* return(*nn); */
+ rts
+
+ .globl _BnnNumDigits
+_BnnNumDigits:
+ .set BNDnn,4
+ .set BNDnl,8
+ move.l BNDnn(sp),a0
+ move.l BNDnl(sp),d0
+ lea (0,a0,d0.l*4),a0 /* nn = &nn[nl]; */
+ dbf d0,BND1 /* if(nl--) goto BND1; */
+ moveq #1,d0
+ rts /* return(1); */
+BND1: tst.l -(a0)
+ bne BND3 /* if(*(--nn) != 0) goto BND3; */
+ dbf d0,BND1 /* if(nl--) goto BND1; */
+ moveq #1,d0
+ rts /* return(1); */
+BND3: addq.l #1,d0
+ rts /* return(nl + 1); */
+
+ .globl _BnnNumLeadingZeroBitsInDigit
+_BnnNumLeadingZeroBitsInDigit:
+ .set BLZd,4
+ bfffo BLZd(sp){0:32},d0
+ rts
+
+ .globl _BnnDoesDigitFitInWord
+_BnnDoesDigitFitInWord:
+ .set BDFd,4
+ moveq #1,d0 /* C_VERSION */
+ rts
+
+ .globl _BnnIsDigitZero
+_BnnIsDigitZero:
+ .set BDZd,4
+ clr.l d0
+ tst.l BDZd(sp)
+ seq d0
+ rts /* return(d == 0); */
+
+ .globl _BnnIsDigitNormalized
+_BnnIsDigitNormalized:
+ .set BDNd,4
+ clr.l d0
+ tst.w BDNd(sp)
+ smi d0
+ rts /* return(d < 0); */
+
+ .globl _BnnIsDigitOdd
+_BnnIsDigitOdd:
+ .set BDOd,4
+ clr.l d0
+ move.w BDOd+2(sp),ccr
+ scs d0
+ rts /* return(d & 1); */
+
+ .globl _BnnCompareDigits
+_BnnCompareDigits:
+ .set BCDd1,4
+ .set BCDd2,8
+ move.l BCDd1(sp),d1
+ cmp.l BCDd2(sp),d1
+ bhi BCDsup /* if(d1 > d2) goto BCDsup; */
+ sne d0
+ extb.l d0
+ rts /* return(-(d1 < d2)); */
+BCDsup: moveq #1,d0
+ rts /* return(1); */
+
+ .globl _BnnComplement
+_BnnComplement:
+ .set BCMnn,4
+ .set BCMnl,8
+ move.l BCMnn(sp),a0
+ move.l BCMnl(sp),d0
+ dbf d0,BCM1 /* if(nl--) goto BCM1; */
+ rts /* return; */
+BCM1: not.l (a0)+ /* *(nn++) ^= -1; */
+ dbf d0,BCM1 /* if(nl--) goto BCM1; */
+ rts /* return; */
+
+ .globl _BnnAndDigits
+_BnnAndDigits:
+ .set BADnn,4
+ .set BADd,8
+ move.l BADnn(sp),a0
+ move.l BADd(sp),d0
+ and.l d0,(a0) /* *n &= d; */
+ rts /* return; */
+
+ .globl _BnnOrDigits
+_BnnOrDigits:
+ .set BODnn,4
+ .set BODd,8
+ move.l BODnn(sp),a0
+ move.l BODd(sp),d0
+ or.l d0,(a0) /* *n |= d; */
+ rts /* return; */
+
+ .globl _BnnXorDigits
+_BnnXorDigits:
+ .set BXDnn,4
+ .set BXDd,8
+ move.l BXDnn(sp),a0
+ move.l BXDd(sp),d0
+ eor.l d0,(a0) /* *n ^= d; */
+ rts /* return; */
+
+ .globl _BnnShiftLeft
+_BnnShiftLeft:
+ .set BSLmm,4
+ .set BSLml,8
+ .set BSLnbi,12
+ clr.l d0 /* res = 0; */
+ move.l BSLnbi(sp),d1
+ bne BSL0 /* if(nbi) goto BSL0; */
+ rts /* return(res); */
+BSL0: move.l BSLmm(sp),a0
+ movem.l #0x3C00,-(sp) /* Save 4 registers */
+ move.l BSLml + 16(sp),d2
+ moveq #32,d3 /* rnbi = BN_DIGIT_SIZE; */
+ sub.l d1,d3 /* rnbi -= nbi; */
+ dbf d2,BSL1 /* if(ml--) goto BSL1; */
+ movem.l (a7)+,#0x003C /* Restore 4 registers */
+ rts /* return(res); */
+BSL1: move.l (a0),d4 /* save = *mm; */
+ move.l d4,d5 /* X = save; */
+ lsl.l d1,d5 /* X <<= nbi; */
+ or.l d0,d5 /* X |= res; */
+ move.l d5,(a0)+ /* *(mm++) = X; */
+ move.l d4,d0 /* res = save; */
+ lsr.l d3,d0 /* res >>= rnbi; */
+ dbf d2,BSL1 /* if(ml--) goto BSL1; */
+ movem.l (a7)+,#0x003C /* Restore 4 registers */
+ rts /* return(res); */
+
+ .globl _BnnShiftRight
+_BnnShiftRight:
+ .set BSRmm,4
+ .set BSRml,8
+ .set BSRnbi,12
+ clr.l d0 /* res = 0; */
+ move.l BSRnbi(sp),d1
+ bne BSR0 /* if(nbi) goto BSR0; */
+ rts /* return(res); */
+BSR0: move.l BSRmm(sp),a0
+ movem.l #0x3C00,-(sp) /* Save 4 registers */
+ move.l BSRml + 16(sp),d2
+ lea (0,a0,d2.l*4),a0 /* mm = &mm[ml]; */
+ moveq #32,d3 /* lnbi = BN_DIGIT_SIZE; */
+ sub.l d1,d3 /* lnbi -= nbi; */
+ dbf d2,BSR1 /* if(ml--) goto BSR1; */
+ movem.l (a7)+,#0x003C /* Restore 4 registers */
+ rts /* return(res); */
+BSR1: move.l -(a0),d4 /* save = *(--mm); */
+ move.l d4,d5 /* X = save; */
+ lsr.l d1,d5 /* X >>= nbi; */
+ or.l d0,d5 /* X |= res; */
+ move.l d5,(a0) /* *mm = X; */
+ move.l d4,d0 /* res = save; */
+ lsl.l d3,d0 /* res <<= lnbi; */
+BSR2: dbf d2,BSR1 /* if(ml--) goto BSR1; */
+ movem.l (a7)+,#0x003C /* Restore 4 registers */
+ rts /* return(res); */
+
+ .globl _BnnAddCarry
+_BnnAddCarry:
+ .set BACnn,4
+ .set BACnl,8
+ .set BACcar,12
+ move.l BACcar(sp),d0 /* */
+ beq BAC2 /* if(car == 0) return(car); */
+ move.l BACnl(sp),d0 /* */
+ beq BAC3 /* if(nl == 0) return(1); */
+ move.l BACnn(sp),a0
+ subq.l #1,d0 /* nl--; */
+BAC1: addq.l #1,(a0)+ /* ++(*nn++); */
+ dbcc d0,BAC1 /* if(Carry || nl--) goto BAC1 */
+ scs d0
+ neg.b d0
+ extb.l d0
+BAC2: rts /* return(Carry) */
+BAC3: moveq #1,d0
+ rts /* return(1); */
+
+ .globl _BnnAdd
+_BnnAdd:
+ .set BADDmm,4
+ .set BADDml,8
+ .set BADDnn,12
+ .set BADDnl,16
+ .set BADDcar,20
+ move.l BADDmm(sp),a0
+ move.l BADDnn(sp),a1
+ move.l BADDnl(sp),d1
+ sub.l d1,BADDml(sp) /* ml -= nl; */
+ tst.l d1
+ bne BADD1 /* if(nl) goto BADD1 */
+ tst.l BADDcar(sp) /*| */
+ bne BADD7 /* if(car) goto BADD7 */
+ clr.l d0
+ rts /* return(0); */
+BADD1: subq.l #1,d1 /* nl--; */
+ move.l BADDcar(sp),d0
+ neg.b d0 /* Bit No 4 */
+ move.w d0,ccr /* X = car; */
+ move.l d2,-(sp) /*|| Save register. */
+BADDX: move.l (a1)+,d0
+ move.l (a0),d2
+ addx.l d0,d2 /* N = *mm + *(nn++) + X */
+ move.l d2,(a0)+ /* X = N >> 32; *(mn++) = N; */
+ dbf d1,BADDX /* if(nl--) goto BADDX */
+ move.l (sp)+,d2 /*|| Restore register. */
+ move.w ccr,d0
+ and.w #0x10,d0
+ bne BADD7 /* if(X) goto BADD7; */
+ clr.l d0 /* return(0); */
+ rts
+BADD7: move.l BADDml(sp),d0
+ beq BADD9 /* if(ml == 0) return(1); */
+ subq.l #1,d0 /* ml--; */
+BADD8: addq.l #1,(a0)+ /* ++(*mm++); */
+ dbcc d0,BADD8 /* if(Carry || ml--) goto BADD8 */
+ scs d0
+ neg.b d0
+ extb.l d0
+ rts /* return(Carry) */
+BADD9: moveq #1,d0
+ rts /* return(1); */
+
+ .globl _BnnSubtractBorrow
+_BnnSubtractBorrow:
+ .set BSBnn,4
+ .set BSBnl,8
+ .set BSBcar,12
+ move.l BSBcar(sp),d0
+ bne BSB2 /* if(car) return(car); */
+ move.l BSBnl(sp),d0
+ beq BSB3 /* if(nl == 0) return(0); */
+ move.l BSBnn(sp),a0
+ subq.l #1,d0 /* nl--; */
+BSB1: subq.l #1,(a0)+ /* (*nn++)--; */
+ dbcc d0,BSB1 /* if(Carry || nl--) goto BSB1 */
+ scc d0
+ neg.b d0
+ extb.l d0
+BSB2: rts /* return(Carry) */
+BSB3: moveq #0,d0
+ rts /* return(0); */
+
+ .globl _BnnSubtract
+_BnnSubtract:
+ .set BSmm,4
+ .set BSml,8
+ .set BSnn,12
+ .set BSnl,16
+ .set BScar,20
+ move.l BSmm(sp),a0
+ move.l BSnn(sp),a1
+ move.l BSnl(sp),d1
+ sub.l d1,BSml(sp) /* ml -= nl; */
+ tst.l d1
+ bne BS1 /* if(nl) goto BS1 */
+ tst.l BScar(sp)
+ beq BS7 /* if(!car) goto BS7 */
+ moveq #1,d0
+ rts /* return(1); */
+BS1: subq.l #1,d1 /* nl--; */
+ move.l BScar(sp),d0
+ neg.b d0 /* Bit No 4 */
+ not.b d0
+ move.w d0,ccr /* X = ~car; */
+ move.l d2,-(sp) /*|| Save register. */
+BSX: move.l (a1)+,d0
+ move.l (a0),d2
+ subx.l d0,d2 /* N = *mm - *(nn++) - X */
+ move.l d2,(a0)+ /* X = N >> 32; *(mm++) = N; */
+ dbf d1,BSX /* if(nl--) goto BSX */
+ move.l (sp)+,d2 /*|| Restore register. */
+ move.w ccr,d0
+ and.w #0x10,d0
+ bne BS7 /* if(X) goto BS7; */
+ moveq #1,d0 /* return(1); */
+ rts
+BS7: move.l BSml(sp),d1
+ beq BS9 /* if(ml == 0) goto BS9; */
+ subq.l #1,d1 /* ml--; */
+BS8: subq.l #1,(a0)+ /* --(*m++); */
+ dbcc d1,BS8 /* if(Carry || ml--) goto BS8 */
+ scc d0
+ neg.b d0
+ extb.l d0
+ rts /* return(C) */
+BS9: clr.l d0
+ rts /* return(0); */
+
+ .globl _BnnMultiplyDigit
+_BnnMultiplyDigit:
+ .set BMDpp,4
+ .set BMDpl,8
+ .set BMDmm,12
+ .set BMDml,16
+ .set BMDd,20
+ move.l BMDd(sp),d0
+ bne BMD1 /* if(d) goto BMD1; */
+ rts /* return(0); */
+BMD1: cmp.l #1,d0
+ bne BMD2 /* if(d != 1) goto BMD2; */
+ clr.l BMDd(sp)
+ bra _BnnAdd /* BnnAdd(p,pl,m,ml,0); */
+BMD2: move.l BMDpp(sp),a0
+ move.l BMDmm(sp),a1
+ move.l BMDml(sp),d1
+ sub.l d1,BMDpl(sp) /* pl -= ml; */
+ movem.l #0x3c00,-(sp) /* Save 4 registers */
+ clr.l d2 /* low = 0; */
+ clr.l d5
+ bra BMD6 /* goto BMD6; */
+BMD3: move.l (a1)+,d4 /* X = *(mm++); */
+ mulu.l d0,d3:d4 /* X *= d; */
+ add.l d2,d4 /* X += low; */
+ addx.l d5,d3 /* X(hight) += Carry; */
+ add.l (a0),d4 /* X += *pp; */
+ addx.l d5,d3 /* X(hight) += Carry; */
+ move.l d4,(a0)+ /* *(pp++) = X(low); */
+ move.l d3,d2 /* low = X(hight); */
+BMD6: dbf d1,BMD3 /* if(ml--) goto BMD3; */
+ move.l d2,d0
+ movem.l (a7)+,#0x003C /* Restore 4 registers */
+ add.l d0,(a0)+ /* *(pp++) += low; */
+ bcs BMD7 /* if(Carry) goto BMD7; */
+ clr.l d0
+ rts /* return(0); */
+BMD7: move.l BMDpl(sp),d0
+ subq.l #1,d0 /* pl--; */
+ beq BMD10 /* if(!pl) goto BM10; */
+ subq.l #1,d0 /* pl--; */
+BMD8: addq.l #1,(a0)+ /* ++(*pp++); */
+BMD9: dbcc d0,BMD8 /* if(Carry || pl--) goto BMD8 */
+ scs d0
+ neg.b d0
+ extb.l d0
+ rts /* return(Carry); */
+BMD10: moveq #1,d0
+ rts /* return(1); */
+
+ .globl _BnnDivideDigit
+_BnnDivideDigit:
+ .set BDDqq,12
+ .set BDDnn,16
+ .set BDDnl,20
+ .set BDDd,24
+ movem.l #0x3000,-(sp) /* Save 2 registers */
+ move.l BDDqq(sp),a1
+ move.l BDDnn(sp),a0
+ move.l BDDnl(sp),d0
+ move.l BDDd(sp),d1
+ lea (0,a0,d0.l*4),a0 /* nn = &nn[nl]; */
+ subq.l #1,d0 /* nl--; */
+ lea (0,a1,d0.l*4),a1 /* qq = &qq[nl]; */
+ move.l -(a0),d2 /*| X(hight) = *(--nn); */
+ bra BDD2 /* goto BDD2; */
+BDD1: move.l -(a0),d3 /* X(low) = *(--nn); */
+ divu.l d1,d2:d3 /* X(low) = X / d; */
+ /* X(hight) = X % d; */
+ move.l d3,-(a1) /* *(--qq) = X(low); */
+BDD2: dbf d0,BDD1 /* if(nl--) goto BDD1; */
+ move.l d2,d0 /*| return(X(hight)); */
+ movem.l (a7)+,#0x000C /* Restore 2 registers */
+ rts
diff --git a/otherlibs/num/bignum/s/RS6000KerN.s b/otherlibs/num/bignum/s/RS6000KerN.s
new file mode 100644
index 000000000..e7a63b659
--- /dev/null
+++ b/otherlibs/num/bignum/s/RS6000KerN.s
@@ -0,0 +1,468 @@
+# Copyright Digital Equipment Corporation & INRIA 1988, 1989
+#
+# KerN for the RS6000
+# [Bepaul]
+#
+# La plupart du code est celui ge'ne're' par le compilo C (Cha^peau!)
+#
+ .set RES,3
+ .set CA1,3
+ .set CA2,4
+ .set CA3,5
+ .set CA4,6
+ .set CA5,7
+ .set X4,7
+ .set X3,8
+ .set X2,9
+ .set X1,10
+
+ .set NN1,CA1
+ .set MM1,CA1
+ .set D1,CA1
+ .set NN2,CA2
+ .set NL2,CA2
+ .set ML2,CA2
+ .set D2,CA2
+ .set NN3,CA3
+ .set NL3,CA3
+ .set NL4,CA4
+
+ .toc
+T.bignum_dat: .tc bignum_dat[TC],bignum_dat[RW]
+ .csect bignum_dat[RW]
+ .csect bignum_txt[PR]
+
+ .globl .BnnSetToZero # BnnSetToZero(nn, nl)
+.BnnSetToZero: cmpi 0,NL2,0 # if(nl <= 0) return;
+ bler
+ mtctr NL2 # ctr = nl;
+ lil X1,0 # cte = 0;
+ ai NN1,NN1,-4 # nn--;
+BSTZ1: stu X1,4(NN1) # *(++nn) = cte;
+ bdn BSTZ1 # if(--ctr != 0) goto BSTZ1;
+ br # return;
+
+ .globl .BnnAssign # BnnAssign(mm, nn, nl)
+.BnnAssign: cmpi 0,NL3,0 # if(nl <= 0) return;
+ bler
+ mtctr NL3 # ctr = nl;
+ cmpl 0,MM1,NN2 # if(mm >= nn) goto BAG2;
+ bge BAG2
+ ai MM1,MM1,-4 # mm--;
+ ai NN2,NN2,-4 # nn--;
+BAG1: lu X1,4(NN2) # X = *(++nn);
+ stu X1,4(MM1) # *(++mm) = X;
+ bdn BAG1 # if(--ctr != 0) goto BAG1;
+ br
+BAG2: beqr # if(mm == nn) return;
+ sli X1,NL3,2
+ a NN2,NN2,X1 # nn += nl;
+ a MM1,MM1,X1 # mm += nl;
+BAG3: lu X1,-4(NN2) # X = *(--nn);
+ stu X1,-4(MM1) # *(--mm) = X;
+ bdn BAG3 # (if(--ctr != 0) goto BAG3;
+ br # return;
+
+ .globl .BnnSetDigit # BnnSetDigit(nn, d)
+.BnnSetDigit: st D2,0(NN1)
+ br
+
+ .globl .BnnGetDigit # BnnGetDigit(nn)
+.BnnGetDigit: l RES,0(NN1)
+ br
+
+ .globl .BnnNumDigits # BnnNumDigits(nn, nl)
+.BnnNumDigits: cmpi 0,NL2,0 # if(nl <= 0) return(1);
+ ble BND2
+ sli X1,NL2,2
+ a NN1,NN1,X1 # nn += nl;
+ mtctr NL2 # ctr = nl;
+BND1: lu X1,-4(NN1) # X = *(--nn);
+ cmpi 0,X1,0 # if(X != 0) goto BND3
+ bne BND3
+ bdn BND1 # if(--ctr != 0) goto BND1;
+BND2: lil RES,1 # return(1);
+ br
+BND3: mfctr RES # return(ctr);
+ br
+
+ .globl .BnnNumLeadingZeroBitsInDigit # (d)
+.BnnNumLeadingZeroBitsInDigit:
+ cntlz RES,D1 # Yeah!
+ br
+
+ .globl .BnnDoesDigitFitInWord # (d)
+.BnnDoesDigitFitInWord:
+ lil RES,1 # return(1);
+ br
+
+ .globl .BnnIsDigitZero # BnnIsDigitZero(d)
+.BnnIsDigitZero: # Use the fact that nabs(d) >=0 <=> d == 0
+ nabs RES,D1
+ rlinm RES,RES,1,31,31 # sign in the lowest bit.
+ xoril RES,RES,1 # get the inverse.
+ br
+
+ .globl .BnnIsDigitNormalized # (d)
+.BnnIsDigitNormalized:
+ rlinm RES,D1,1,31,31 # sign in the lowest bit.
+ br
+
+ .globl .BnnIsDigitOdd # BnnIsDigitOdd(d)
+.BnnIsDigitOdd: rlinm RES,D1,0,31,31 # only the lowest bit.
+ br
+
+ .globl .BnnCompareDigits # BnnCompareDigits(d1, d2)
+.BnnCompareDigits:
+ cmpl 0,D1,D2 # if(d1 == d2) return(0);
+ beq BSD0
+ bgt BCDsup # if(d1 > d2) return(1);
+ lil RES,-1 # return(-1);
+BSDret: br
+BCDsup: lil RES,1 # return(1);
+ br
+BSD0: lil RES,0 # return(0);
+ br
+
+ .globl .BnnComplement #.BnnComplement(nn, nl)
+.BnnComplement: cmpi 0,NL2,0 # if(nl <= 0) return;
+ bler
+ ai NN1,NN1,-4 # nn--;
+ mtctr NL2 # ctr = nl;
+BCM1: l X1,4(NN1) # X = nn[1];
+ sfi X1,X1,-1 # X ^= -1;
+ stu X1,4(NN1) # *++nn = X;
+ bdn BCM1 # if(--ctr > 0) goto BCM1
+ br # return;
+
+ .globl .BnnAndDigits # BnnAndDigits(nn, d)
+.BnnAndDigits: l X1,0(NN1) # X = *nn;
+ and X1,X1,D2 # X &= d;
+ st X1,0(NN1) # *nn = X;
+ br
+
+ .globl .BnnOrDigits # BnnOrDigits(nn, d)
+.BnnOrDigits: l X1,0(NN1) # X = *nn;
+ or X1,X1,D2 # X |= d;
+ st X1,0(NN1) # *nn = X;
+ br
+
+ .globl .BnnXorDigits # BnnXorDigits(nn, d)
+.BnnXorDigits: l X1,0(NN1) # X = *nn;
+ xor X1,X1,D2 # X ^= d;
+ st X1,0(NN1) # *nn = X;
+ br
+
+ .globl .BnnShiftLeft # BnnShiftLeft(mm, ml, nbits)
+# here and in the next funxtion we use the fact that MM1 == RES.
+ .set NBI,CA3; .set SMM,X1; .set RNB,X2; .set SX,X3; .set SY,ML2
+.BnnShiftLeft: oril SMM,MM1,0
+ lil RES,0 # res = 0;
+ cmpi 0,NBI,0 # if(nbits == 0) return(res);
+ beqr
+ cmpi 0,ML2,0 # if(ml <= 0) return(res);
+ bler
+ sfi RNB,NBI,32 # rnbits = 32 - nbits;
+ ai SMM,SMM,-4 # mm--;
+ mtctr ML2 # ctr = ml;
+BSL1: l SX,4(SMM) # X = mm[1];
+ sl SY,SX,NBI # Y = X << nbits;
+ or SY,SY,RES # Y |= res;
+ stu SY,4(SMM) # *(++mm) = Y;
+ sr RES,SX,RNB # res = X >> rnbits;
+ bdn BSL1 # if(--ctr > 0) goto BSL1
+ br # return(res);
+
+ .globl .BnnShiftRight # BnnShiftRight(mm, ml, nbits)
+.BnnShiftRight: sli X1,ML2,2 # mm += ml;
+ a SMM,MM1,X1
+ lil RES,0 # res = 0;
+ cmpi 0,NBI,0 # if(nbits == 0) return(res);
+ beqr
+ cmpi 0,ML2,0 # if(ml <= 0) return(res);
+ bler
+ sfi RNB,NBI,32 # rnbits = 32 - nbits;
+ mtctr ML2 # ctr = ml;
+BSR1: lu SX,-4(SMM) # X = *(--mm);
+ sr SY,SX,NBI # Y = X >> nbits;
+ or SY,SY,RES # Y |= res;
+ st SY,0(SMM) # *(mm) = Y;
+ sl RES,SX,RNB # res = X << rnbits;
+ bdn BSR1 # if(--ctr > 0) goto BSR1
+ br # return(res);
+
+ .globl .BnnAddCarry # BnnAddCarry(nn, nl, carryin)
+ .set CARRY,CA3 # also for BnnSubtractBorrow
+.BnnAddCarry: cmpi 0,CARRY,0 # if(carryin == 0) return(0);
+ beq BAC3
+ cmpi 0,NL2,0 # if(nl == 0) return(1);
+ beq BAC2
+ ai NN1,NN1,-4 # nn--;
+ mtctr NL2 # ctr = nl;
+BAC1: l X1,4(NN1) # X = nn[1];
+ ai. X1,X1,1 # X++;
+ stu X1,4(NN1) # *(++nn) = X;
+ bne BAC3 # if(X != 0) return(0);
+ bdn BAC1 # if(--ctr > 0) goto BAC1
+BAC2: lil RES,1 # return(1);
+ br
+BAC3: lil RES,0 # return(0);
+ br
+
+ .globl .BnnAdd # BnnAdd(mm, ml, nn, nl, carryin)
+ .set CARRYIN,CA5 # also for BnnSubtract.
+.BnnAdd: sf ML2,NL4,ML2 # ml -= nl;
+ ai NN3,NN3,-4 # nn--;
+ ai MM1,MM1,-4 # mm--; carry = 1;
+ cmpi 0,NL4,0 # if(nl == 0) goto BADD2;
+ beq BADD2
+ mtctr NL4 # ctr = nl;
+ cmpi 0,CARRYIN,0 # if(carryin) goto BADD1;
+ bne BADD1
+ ai X1,X1,0 # carry = 0;
+BADD1: lu X2,4(NN3) # Y = *(++nn);
+ l X1,4(MM1) # X = mm[1];
+ ae X1,X1,X2 # X = X + Y + carry; carry = ??
+ stu X1,4(MM1) # *(++mm) = X;
+ bdn BADD1 # if(--ctr > 0) goto BADD1
+ lil X2,0
+ ae CARRYIN,X2,X2 # carryin = carry;
+BADD2: cmpi 0,CARRYIN,0 # if(carryin == 0) return(0);
+ beq BADD5
+ cmpi 0,ML2,0 # if(ml == 0) return(1);
+ beq BADD4
+ mtctr ML2 # ctr = ml;
+BADD3: l X1,4(MM1) # X = mm[1];
+ ai. X1,X1,1 # X++;
+ stu X1,4(MM1) # *(++mm) = X;
+ bne BADD5 # if(X != 0) return(0);
+ bdn BADD3 # if(--ctr > 0) goto BADD3;
+BADD4: lil RES,1 # return(1);
+ br
+BADD5: lil RES,0 # return(0);
+ br
+
+ .globl .BnnSubtractBorrow # (nn, nl, carryin)
+.BnnSubtractBorrow:
+ cmpi 0,CARRY,1 # if(carryin == 1) return(1);
+ beq BSB3
+ cmpi 0,NL2,0 # if(nl == 0) return(0);
+ beq BSB2
+ ai NN1,NN1,-4 # nn--;
+ mtctr NL2 # ctr = nl;
+BSB1: l X1,4(NN1) # X = nn[1];
+ si X2,X1,1 # Y= X-1;
+ stu X2,4(NN1) # *(++nn) = Y;
+ cmpi 0,X1,0
+ bne BSB3 # if(X != 0) return(1);
+ bdn BSB1 # if(--ctr > 0) goto BSB1
+BSB2: lil RES,0 # return(0);
+ br
+BSB3: lil RES,1 # return(1);
+ br
+
+ .globl .BnnSubtract # BnnSubtract(mm, ml, nn, nl, carryin)
+.BnnSubtract: sf ML2,NL4,ML2 # ml -= nl;
+ ai NN3,NN3,-4 # nn--;
+ ai MM1,MM1,-4 # mm--; carry = 1;
+ cmpi 0,NL4,0 # if(nl == 0) goto BS2
+ beq BS2
+ mtctr NL4 # ctr = nl;
+ cmpi 0,CARRYIN,0 # if(carryin) goto BS1
+ bne BS1
+ ai X1,X1,0 # carry = 0;
+BS1: lu X2,4(NN3) # Y = *(++nn);
+ l X1,4(MM1) # X = mm[1];
+ sfe X1,X2,X1 # X = X - (Y + carry); carry = ??
+ stu X1,4(MM1) # *(++mm) = X;
+ bdn BS1 # if(--ctr > 0) goto BS1
+ lil CA5,0
+ ae CA5,CA5,CA5 # carryin = carry;
+BS2: cmpi 0,CA5,1 # if(carryin == 0) return(1);
+ beq BS5
+ cmpi 0,ML2,0 # if(ml == 0) return(0);
+ beq BS4
+ mtctr ML2 # ctr = ml;
+BS3: l X1,4(MM1) # X = mm[1];
+ si X2,X1,1 # Y= X-1;
+ stu X2,4(MM1) # *(++mm) = Y;
+ cmpi 0,X1,0 # if(X != 0) return(1);
+ bne BS5
+ bdn BS3 # if(--ctr > 0) goto BS3
+BS4: lil RES,0 # return(0);
+ br
+BS5: lil RES,1 # return(1);
+ br
+
+ .globl .BnnMultiplyDigit # BnnMultiplyDigit(pp, pl, mm, ml, d)
+ .set PP,CA1; .set PL,CA2; .set MM,CA3; .set ML,CA4; .set D,CA5
+ .set LOW,X1; .set HIGHT,X2; .set OHIGHT,X3
+.BnnMultiplyDigit:
+ cmpi 0,D,0 # if(d == 0) return(0);
+ beq BMD7
+BMD1: cmpi 0,D,1 # if(d != 1) goto BMD2;
+ bne BMD2
+ lil CA5,0 # return(BnnAdd(pp, pl, mm, ml, 0));
+ b .BnnAdd
+BMD2: sf PL,ML,PL # pl -= ml;
+ ai MM,MM,-4 # mm--;
+ ai PP,PP,-4 # pp--;
+ cmpi 0,ML,0 # if(ml == 0) return(0);
+ beq BMD7
+ mtctr ML # ctr = ml;
+ lil OHIGHT,0 # OldHight = 0;
+ cmpi 0,D,0 # if(D < 0) goto BMD8;
+ blt BMD8
+BMD3: lu LOW,4(MM) # Low = mm[1];
+ mul HIGHT,LOW,D # Hight:MQ = Low*d
+ cmpi 0,LOW,0 # if(Low>=0) pas de correction.
+ bge BMD4
+ a HIGHT,HIGHT,D # Correction multiplication signe'.
+BMD4: mfmq LOW # Low = MQ;
+ a LOW,LOW,OHIGHT # Low += OldHight;
+ aze HIGHT,HIGHT # Hight += carry;
+ l OHIGHT,4(PP) # *++pp += Low;
+ a LOW,LOW,OHIGHT
+ stu LOW,4(PP)
+ aze OHIGHT,HIGHT # OldHight = Hight + carry;
+ bdn BMD3 # if(--ctr > 0) goto BMD3;
+BMD40: l LOW,4(PP) # *(++pp) += OldHight;
+ a LOW,LOW,OHIGHT
+ stu LOW,4(PP)
+ lil LOW,0 # if(carry == 0) return(0);
+ aze. LOW,LOW
+ beq BMD7
+ si. PL,PL,1 # pl--;
+ ble BMD6 # if(pl <= 0) return(1);
+ mtctr PL # ctr = pl;
+BMD5: l X1,4(PP) # X = pp[1];
+ ai. X1,X1,1 # X++;
+ stu X1,4(PP) # *(++pp) = X;
+ bne BMD7 # if(X != 0) return(0);
+ bdn BMD5 # if(--ctr > 0) goto BMD5;
+BMD6: lil RES,1 # return(1);
+ br
+BMD7: lil RES,0 # return(0);
+ br
+
+BMD8: lu LOW,4(MM) # Low = mm[1];
+ mul HIGHT,LOW,D # Hight:MQ = Low*d
+ a HIGHT,HIGHT,LOW # Correction pour d<0...
+ cmpi 0,LOW,0 # if(Low>=0) pas de correction.
+ bge BMD9
+ a HIGHT,HIGHT,D # Correction multiplication signe'.
+BMD9: mfmq LOW # Low = MQ;
+ a LOW,LOW,OHIGHT # Low += OldHight;
+ aze HIGHT,HIGHT # Hight += carry;
+ l OHIGHT,4(PP) # *pp += Low;
+ a LOW,LOW,OHIGHT
+ stu LOW,4(PP)
+ aze OHIGHT,HIGHT # OldHight = Hight + carry;
+ bdn BMD8 # if(--ctr > 0) goto BMD8;
+ b BMD40 # goto BMD40;
+
+ .globl .BnnDivideDigit # BnnDivideDigit(qq, nn, nl, d)
+ .set QQ,CA1; .set NN,CA2; .set NL,CA3; .set DD,CA4
+ .set SQQ,X1; .set R,CA1; .set Q,X2; .set NLOW,X2; .set DQ,X3
+ .set BITS,X4; .set AUX,CA3
+.BnnDivideDigit:
+ sli X1,NL,2
+ a NN,NN,X1 # nn = &nn[nl];
+ a SQQ,QQ,X1 # qq = &qq[nl];
+ si SQQ,SQQ,4 # qq--;
+ lu R,-4(NN) # R = *(--nn);
+ si. NL,NL,1 # nl--;
+ bler # if(nl <= 0) return(R);
+ mtctr NL # ctr = nl;
+ sri DQ,DD,1 # D'= D / 2;
+ cmpi 0,DD,0 # if(D<0) goto BDDinf;
+ blt BDDinf
+# D > 0
+BDDsup: lu NLOW,-4(NN) # Low = *(--nn);
+ cmpl 0,R,DQ # if (R < D') goto BDDsupinf;
+ blt BDDsupinf
+ andil. BITS,NLOW,1 # bits = Low & 1;
+ sri NLOW,NLOW,1 # Low >>= 1;
+ andil. AUX,R,1 # aux = R & 1;
+ sri R,R,1 # R >>= 1;
+ sli AUX,AUX,31 # Low |= aux << 31;
+ or NLOW,NLOW,AUX
+ mtmq NLOW # MQ = Low;
+ div Q,R,DD # Q=R:MQ/D; MQ=R:MQ%D;
+ mfmq R # R=MQ;
+ sli R,R,1 # R <<= 1;
+ sli Q,Q,1 # Q <<= 1;
+ a R,R,BITS # R+=bits;
+ cmpl 0,R,DD # si R<D => ok
+ blt BDDsup1
+ ai Q,Q,1 # Q++;
+ sf R,DD,R # R-=D;
+BDDsup1: stu Q,-4(SQQ) # *(--qq)=Q;
+ bdn BDDsup # if(--ctr > 0) goto BDDsup;
+ br # return(R);
+BDDsupinf: mtmq NLOW # MQ = XL;
+ div Q,R,DD # Q=R:MQ/D; MQ=R:MQ%D;
+ mfmq R # R=MQ;
+ stu Q,-4(SQQ) # *(--qq)=Q;
+ bdn BDDsup # if(--ctr > 0) goto BDDsup;
+ br # return(R);
+
+# D < 0
+BDDinf: lu NLOW,-4(NN) # Low = *(--nn);
+ andil. BITS,NLOW,7 # bits = Low & 7;
+ sri NLOW,NLOW,3 # Low >>= 3;
+ andil. AUX,R,7 # aux = R & 7;
+ sri R,R,3 # R >>= 3;
+ sli AUX,AUX,29 # Low |= aux << 29;
+ or NLOW,NLOW,AUX
+ mtmq NLOW # MQ = Low;
+ div Q,R,DQ # Q=R:MQ/D'; MQ=R:MQ%D';
+ mfmq R # R=MQ
+ sli R,R,1 # R *= 2;
+ andil. AUX,DD,1 # if((D & 1) == 0) rien a retrancher;
+ cmpli 0,AUX,0
+ beq BDDi4
+# R <- R - Q
+ cmpl 0,R,Q # On teste avant de faire la diff.
+ blt BDDi3 # la diff est < 0
+ sf R,Q,R # la diff est > 0
+ b BDDi4
+BDDi3: sf R,Q,R # On met a` jour
+ si Q,Q,1 # Q--;
+ a R,R,DD # R += D;
+# R <- 2R; Q <- 2Q;
+BDDi4: cmpl 0,R,DQ # On teste avant de faire la mult.
+ blt BDDi41 # Ca va passer..
+ bne BDDi40 # Ca va casser...
+ cmpli 0,AUX,0 # d0 = 1 ca passe...
+ bne BDDi41
+BDDi40: sli Q,Q,1 # Q *= 2;
+ sli R,R,1 # R *= 2;
+ ai Q,Q,1 # Q++;
+ sf R,DD,R # R -= D;
+ b BDDi5
+BDDi41: sli Q,Q,1 # Q *= 2;
+ sli R,R,1 # R *= 2;
+# R <- 2R; Q <- 2Q;
+BDDi5: cmpl 0,R,DQ # On teste avant de faire la mult.
+ blt BDDi51 # Ca va passer..
+ bne BDDi50 # Ca va casser...
+ cmpli 0,AUX,0 # d0 = 1 ca passe...
+ bne BDDi51
+BDDi50: sli Q,Q,1 # Q *= 2;
+ sli R,R,1 # R *= 2;
+ ai Q,Q,1 # Q++;
+ sf R,DD,R # R -= D;
+ b BDDi6
+BDDi51: sli Q,Q,1 # Q *= 2;
+ sli R,R,1 # R *= 2;
+# R += bits;
+BDDi6: sf AUX,BITS,DD # pour tester sans de'bordement..
+ cmpl 0,R,AUX
+ blt BDDi61 # Ca va passer..
+ ai Q,Q,1 # Q++;
+ sf R,DD,R # R -= D;
+BDDi61: a R,R,BITS # R += bits;
+ stu Q,-4(SQQ) # *(--qq)=Q;
+ bdn BDDinf # if(--ctr > 0) goto BDDinf;
+ br
diff --git a/otherlibs/num/bignum/s/alphaKerN.s b/otherlibs/num/bignum/s/alphaKerN.s
new file mode 100644
index 000000000..f9785794d
--- /dev/null
+++ b/otherlibs/num/bignum/s/alphaKerN.s
@@ -0,0 +1,2511 @@
+ .ugen
+ .verstamp 3 11
+ .data
+ .align 3
+ .align 0
+$$4:
+ .ascii "@(#)KerN.c: copyright Digital Equipment Corporation & INRIA 1988, 1989\X0A\X00"
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnSetToZero
+ .loc 2 63
+ # 63 {
+ .ent BnnSetToZero 2
+BnnSetToZero:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 63
+
+ .loc 2 65
+ # 64 BigNum nnlim;
+ # 65 if (nl <= 0)
+ beq $17, $33
+ .loc 2 66
+ # 66 return;
+ .loc 2 67
+ # 67 nnlim = nn+nl-1;
+ s8addq $17, $16, $0
+ addq $0, -8, $0
+ .loc 2 68
+ # 68 do *nn = 0; while(nn++ < nnlim);
+$32:
+ .loc 2 68
+
+ stq $31, 0($16)
+ cmpult $16, $0, $17
+ addq $16, 8, $16
+ bne $17, $32
+ .loc 2 69
+ # 69 }
+$33:
+ .livereg 0x007F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnSetToZero
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnAssign
+ .loc 2 80
+ # 80 {
+ .ent BnnAssign 2
+BnnAssign:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ bis $16, $16, $1
+ .loc 2 80
+
+ .loc 2 82
+ # 81 BigNum nnlim;
+ # 82 if (nl <= 0)
+ beq $18, $37
+ .loc 2 83
+ # 83 return;
+ .loc 2 84
+ # 84 nnlim = nn+nl;
+ sll $18, 3, $16
+ addq $16, $17, $19
+ bis $19, $19, $0
+ .loc 2 88
+ # 85 #ifdef MSDOS
+ # 86 if (realaddr(mm) < realaddr(nn) || realaddr(mm) > realaddr(nnlim))
+ # 87 #else
+ # 88 if ((mm < nn) || ( mm > nnlim))
+ cmpult $1, $17, $2
+ bne $2, $34
+ cmpult $19, $1, $3
+ beq $3, $35
+ .loc 2 90
+ # 89 #endif
+ # 90 do *mm++ = *nn++; while(nn < nnlim);
+$34:
+ .loc 2 90
+
+ ldq $4, 0($17)
+ stq $4, 0($1)
+ addq $1, 8, $1
+ addq $17, 8, $17
+ cmpult $17, $0, $5
+ bne $5, $34
+ .livereg 0x007F0002,0x3FC00000
+ ret $31, ($26), 1
+$35:
+ .loc 2 95
+ # 91 else
+ # 92 #ifdef MSDOS
+ # 93 if (realaddr(mm) > realaddr(nn))
+ # 94 #else
+ # 95 if (mm > nn)
+ cmpult $17, $1, $6
+ beq $6, $37
+ .loc 2 97
+ # 96 #endif
+ # 97 {
+ .loc 2 98
+ # 98 mm += nl;
+ addq $1, $16, $1
+ .loc 2 99
+ # 99 do *--mm = *--nnlim; while(nn < nnlim);
+$36:
+ .loc 2 99
+
+ addq $1, -8, $18
+ bis $18, $18, $16
+ bis $18, $18, $1
+ addq $0, -8, $0
+ ldq $7, 0($0)
+ stq $7, 0($16)
+ cmpult $17, $0, $8
+ bne $8, $36
+ .loc 2 101
+ # 100 }
+ # 101 }
+$37:
+ .livereg 0x007F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnAssign
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnSetDigit
+ .loc 2 113
+ # 113 {
+ .ent BnnSetDigit 2
+BnnSetDigit:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 113
+
+ .loc 2 114
+ # 114 *nn = d;
+ stq $17, 0($16)
+ .loc 2 115
+ # 115 }
+ .livereg 0x007F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnSetDigit
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnGetDigit
+ .loc 2 126
+ # 126 {
+ .ent BnnGetDigit 2
+BnnGetDigit:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 126
+
+ .loc 2 127
+ # 127 return (*nn);
+ ldq $0, 0($16)
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnGetDigit
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnNumDigits
+ .loc 2 140
+ # 140 {
+ .ent BnnNumDigits 2
+BnnNumDigits:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 140
+
+ .loc 2 141
+ # 141 nn += nl;
+ s8addq $17, $16, $16
+ .loc 2 143
+ # 142
+ # 143 while (nl != 0 && *--nn == 0)
+ beq $17, $39
+ addq $16, -8, $16
+ ldq $1, 0($16)
+ bne $1, $39
+$38:
+ .loc 2 144
+ # 144 nl--;
+ addq $17, -1, $17
+ beq $17, $39
+ addq $16, -8, $16
+ ldq $2, 0($16)
+ beq $2, $38
+$39:
+ .loc 2 146
+ # 145
+ # 146 return (nl == 0 ? 1 : nl);
+ bis $17, $17, $16
+ cmoveq $17, 1, $16
+ bis $16, $16, $0
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnNumDigits
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnNumLeadingZeroBitsInDigit
+ .loc 2 158
+ # 158 {
+ .ent BnnNumLeadingZeroBitsInDigit 2
+BnnNumLeadingZeroBitsInDigit:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ bis $16, $16, $1
+ .loc 2 158
+
+ .loc 2 159
+ # 159 register int p = 0;
+ bis $31, $31, $17
+ .loc 2 160
+ # 160 if (BN_DIGIT_SIZE == 16 || BN_DIGIT_SIZE == 32 || BN_DIGIT_SIZE == 64)
+ .loc 2 161
+ # 161 {
+ .loc 2 162
+ # 162 register BigNumDigit mask = (~(BigNumDigit)0) << (BN_DIGIT_SIZE/2);
+ ldiq $0, -4294967296
+ .loc 2 163
+ # 163 register BigNumLength maskl = BN_DIGIT_SIZE/2;
+ ldiq $16, 32
+ .loc 2 165
+ # 164
+ # 165 if (d == 0)
+ bne $1, $40
+ .loc 2 166
+ # 166 return (BN_DIGIT_SIZE);
+ ldiq $0, 64
+ .livereg 0x807F0002,0x3FC00000
+ ret $31, ($26), 1
+$40:
+ .loc 2 168
+ # 167 while (maskl)
+ # 168 {
+ .loc 2 169
+ # 169 if ((d & mask) == 0)
+ and $1, $0, $2
+ bne $2, $41
+ .loc 2 170
+ # 170 {
+ .loc 2 171
+ # 171 p += maskl;
+ addq $17, $16, $17
+ addl $17, 0, $17
+ .loc 2 172
+ # 172 d <<= maskl;
+ sll $1, $16, $1
+$41:
+ .loc 2 174
+ # 173 }
+ # 174 maskl >>= 1;
+ srl $16, 1, $16
+ .loc 2 175
+ # 175 mask <<= maskl;
+ sll $0, $16, $0
+ bne $16, $40
+ .loc 2 189
+ # 189 return (p);
+ bis $17, $17, $0
+$42:
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnNumLeadingZeroBitsInDigit
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnDoesDigitFitInWord
+ .loc 2 203
+ # 203 {
+ .ent BnnDoesDigitFitInWord 2
+BnnDoesDigitFitInWord:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 203
+
+ .loc 2 205
+ # 204 /* The C compiler must evaluate the predicate at compile time */
+ # 205 if (BN_DIGIT_SIZE > BN_WORD_SIZE)
+ .loc 2 206
+ # 206 return (d >= ((BigNumDigit)1) << BN_WORD_SIZE ? FALSE : TRUE);
+ cmpult $16, 4294967296, $17
+ bis $17, $17, $0
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnDoesDigitFitInWord
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnIsDigitZero
+ .loc 2 218
+ # 218 {
+ .ent BnnIsDigitZero 2
+BnnIsDigitZero:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 218
+
+ .loc 2 219
+ # 219 return (d == 0);
+ cmpeq $16, 0, $0
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnIsDigitZero
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnIsDigitNormalized
+ .loc 2 232
+ # 232 {
+ .ent BnnIsDigitNormalized 2
+BnnIsDigitNormalized:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 232
+
+ .loc 2 233
+ # 233 return (d & (((BigNumDigit)1) << (BN_DIGIT_SIZE - 1)) ? TRUE : FALSE);
+ ldil $17, 1
+ cmovge $16, 0, $17
+ bis $17, $17, $0
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnIsDigitNormalized
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnIsDigitOdd
+ .loc 2 245
+ # 245 {
+ .ent BnnIsDigitOdd 2
+BnnIsDigitOdd:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 245
+
+ .loc 2 246
+ # 246 return (d & 1 ? TRUE : FALSE);
+ ldil $17, 1
+ cmovlbc $16, 0, $17
+ bis $17, $17, $0
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnIsDigitOdd
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnCompareDigits
+ .loc 2 260
+ # 260 {
+ .ent BnnCompareDigits 2
+BnnCompareDigits:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 260
+
+ .loc 2 261
+ # 261 return (d1 > d2 ? BN_GT : (d1 == d2 ? BN_EQ : BN_LT));
+ cmpult $17, $16, $1
+ beq $1, $43
+ ldil $16, 1
+ br $31, $44
+$43:
+ subq $16, $17, $2
+ ldil $0, -1
+ cmoveq $2, 0, $0
+ bis $0, $0, $16
+$44:
+ bis $16, $16, $0
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnCompareDigits
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnComplement
+ .loc 2 273
+ # 273 {
+ .ent BnnComplement 2
+BnnComplement:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 273
+
+ .loc 2 276
+ # 274 BigNum nnlim;
+ # 275
+ # 276 if (nl <= 0)
+ beq $17, $46
+ .loc 2 277
+ # 277 return;
+ .loc 2 278
+ # 278 nnlim = nn+nl;
+ s8addq $17, $16, $0
+ .loc 2 279
+ # 279 do
+$45:
+ .loc 2 280
+ # 280 {
+ .loc 2 281
+ # 281 nn++;
+ addq $16, 8, $16
+ .loc 2 282
+ # 282 nn[-1] = ~nn[-1];
+ ldq $1, -8($16)
+ ornot $31, $1, $2
+ stq $2, -8($16)
+ cmpult $16, $0, $3
+ bne $3, $45
+ .loc 2 285
+ # 283 }
+ # 284 while (nn < nnlim);
+ # 285 }
+$46:
+ .livereg 0x007F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnComplement
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnAndDigits
+ .loc 2 297
+ # 297 {
+ .ent BnnAndDigits 2
+BnnAndDigits:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 297
+
+ .loc 2 298
+ # 298 *n &= d;
+ ldq $1, 0($16)
+ and $1, $17, $2
+ stq $2, 0($16)
+ .loc 2 299
+ # 299 }
+ .livereg 0x007F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnAndDigits
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnOrDigits
+ .loc 2 310
+ # 310 {
+ .ent BnnOrDigits 2
+BnnOrDigits:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 310
+
+ .loc 2 311
+ # 311 *n |= d;
+ ldq $1, 0($16)
+ or $1, $17, $2
+ stq $2, 0($16)
+ .loc 2 312
+ # 312 }
+ .livereg 0x007F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnOrDigits
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnXorDigits
+ .loc 2 323
+ # 323 {
+ .ent BnnXorDigits 2
+BnnXorDigits:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 323
+
+ .loc 2 324
+ # 324 *n ^= d;
+ ldq $1, 0($16)
+ xor $1, $17, $2
+ stq $2, 0($16)
+ .loc 2 325
+ # 325 }
+ .livereg 0x007F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnXorDigits
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnShiftLeft
+ .loc 2 341
+ # 341 {
+ .ent BnnShiftLeft 2
+BnnShiftLeft:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ bis $16, $16, $1
+ addl $18, 0, $18
+ .loc 2 341
+
+ .loc 2 342
+ # 342 register BigNumDigit res = 0, save;
+ bis $31, $31, $19
+ .loc 2 346
+ # 343 int rnbits;
+ # 344
+ # 345
+ # 346 if (nbits != 0)
+ beq $18, $48
+ ldiq $21, 1
+ .loc 2 347
+ # 347 {
+ .loc 2 348
+ # 348 rnbits = BN_DIGIT_SIZE - nbits;
+ .loc 2 350
+ # 349
+ # 350 while (ml-- > 0)
+ cmpule $21, $17, $16
+ addq $17, -1, $17
+ beq $16, $48
+ bis $18, $18, $0
+ ldiq $2, 64
+ subq $2, $0, $20
+ addl $20, 0, $20
+$47:
+ .loc 2 351
+ # 351 {
+ .loc 2 352
+ # 352 save = *mm;
+ ldq $18, 0($1)
+ .loc 2 353
+ # 353 *mm++ = (save << nbits) | res;
+ sll $18, $0, $3
+ or $3, $19, $4
+ stq $4, 0($1)
+ addq $1, 8, $1
+ .loc 2 354
+ # 354 res = save >> rnbits;
+ srl $18, $20, $19
+ cmpule $21, $17, $16
+ addq $17, -1, $17
+ bne $16, $47
+$48:
+ .loc 2 358
+ # 355 }
+ # 356 }
+ # 357
+ # 358 return (res);
+ bis $19, $19, $0
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnShiftLeft
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnShiftRight
+ .loc 2 373
+ # 373 {
+ .ent BnnShiftRight 2
+BnnShiftRight:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ addl $18, 0, $18
+ .loc 2 373
+
+ .loc 2 374
+ # 374 register BigNumDigit res = 0, save;
+ bis $31, $31, $19
+ .loc 2 378
+ # 375 int lnbits;
+ # 376
+ # 377
+ # 378 if (nbits != 0)
+ beq $18, $50
+ ldiq $1, 1
+ .loc 2 379
+ # 379 {
+ .loc 2 380
+ # 380 mm += ml;
+ s8addq $17, $16, $16
+ .loc 2 381
+ # 381 lnbits = BN_DIGIT_SIZE - nbits;
+ .loc 2 383
+ # 382
+ # 383 while (ml-- > 0)
+ cmpule $1, $17, $20
+ addq $17, -1, $17
+ beq $20, $50
+ bis $18, $18, $0
+ ldiq $2, 64
+ subq $2, $0, $21
+ addl $21, 0, $21
+$49:
+ .loc 2 384
+ # 384 {
+ .loc 2 385
+ # 385 save = *(--mm);
+ addq $16, -8, $16
+ ldq $18, 0($16)
+ .loc 2 386
+ # 386 *mm = (save >> nbits) | res;
+ srl $18, $0, $3
+ or $3, $19, $4
+ stq $4, 0($16)
+ .loc 2 387
+ # 387 res = save << lnbits;
+ sll $18, $21, $19
+ cmpule $1, $17, $20
+ addq $17, -1, $17
+ bne $20, $49
+$50:
+ .loc 2 391
+ # 388 }
+ # 389 }
+ # 390
+ # 391 return (res);
+ bis $19, $19, $0
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnShiftRight
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnAddCarry
+ .loc 2 408
+ # 408 {
+ .ent BnnAddCarry 2
+BnnAddCarry:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ .loc 2 408
+
+ .loc 2 409
+ # 409 if (carryin == 0)
+ bne $18, $51
+ .loc 2 410
+ # 410 return (0);
+ bis $31, $31, $0
+ .livereg 0x807F0002,0x3FC00000
+ ret $31, ($26), 1
+$51:
+ .loc 2 412
+ # 411
+ # 412 if (nl == 0)
+ bne $17, $52
+ .loc 2 413
+ # 413 return (1);
+ ldiq $0, 1
+ .livereg 0x807F0002,0x3FC00000
+ ret $31, ($26), 1
+$52:
+ ldiq $19, 1
+ .loc 2 415
+ # 414
+ # 415 while (nl > 0 && !(++(*nn++)))
+ cmpule $19, $17, $0
+ beq $0, $54
+ ldq $1, 0($16)
+ addq $1, 1, $2
+ stq $2, 0($16)
+ ldq $18, 0($16)
+ cmpeq $18, 0, $18
+ addq $16, 8, $16
+ beq $18, $54
+$53:
+ .loc 2 416
+ # 416 nl--;
+ addq $17, -1, $17
+ cmpule $19, $17, $0
+ beq $0, $54
+ ldq $3, 0($16)
+ addq $3, 1, $4
+ stq $4, 0($16)
+ ldq $18, 0($16)
+ cmpeq $18, 0, $18
+ addq $16, 8, $16
+ bne $18, $53
+$54:
+ .loc 2 418
+ # 417
+ # 418 return (nl > 0 ? 0 : 1);
+ bis $31, $31, $18
+ cmoveq $0, 1, $18
+ bis $18, $18, $0
+$55:
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnAddCarry
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnAdd
+ .loc 2 433
+ # 433 {
+ .ent BnnAdd 2
+BnnAdd:
+ .option O2
+ ldgp $gp, 0($27)
+ lda $sp, -16($sp)
+ stq $26, 0($sp)
+ .mask 0x04000000, -16
+ .frame $sp, 16, $26, 0
+ .prologue 1
+ bis $16, $16, $1
+ bis $17, $17, $2
+ .loc 2 433
+
+ .loc 2 434
+ # 434 register BigNumProduct c = carryin;
+ bis $20, $20, $21
+ .loc 2 437
+ # 435
+ # 436
+ # 437 ml -= nl;
+ subq $2, $19, $2
+ .loc 2 439
+ # 438 /* test computed at compile time */
+ # 439 if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ ldiq $17, 1
+ .loc 2 450
+ # 450 {
+ .loc 2 453
+ # 451 register BigNumProduct save;
+ # 452
+ # 453 while (nl > 0)
+ cmpult $19, $17, $3
+ bne $3, $59
+$56:
+ .loc 2 454
+ # 454 {
+ .loc 2 455
+ # 455 save = *mm;
+ ldq $0, 0($1)
+ .loc 2 456
+ # 456 c += save;
+ addq $21, $0, $21
+ .loc 2 457
+ # 457 if (c < save)
+ cmpult $21, $0, $4
+ beq $4, $57
+ .loc 2 458
+ # 458 {
+ .loc 2 459
+ # 459 *(mm++) = *(nn++);
+ ldq $5, 0($18)
+ stq $5, 0($1)
+ addq $1, 8, $1
+ addq $18, 8, $18
+ .loc 2 460
+ # 460 c = 1;
+ bis $17, $17, $21
+ br $31, $58
+$57:
+ .loc 2 463
+ # 461 }
+ # 462 else
+ # 463 {
+ .loc 2 464
+ # 464 save = *(nn++);
+ ldq $0, 0($18)
+ addq $18, 8, $18
+ .loc 2 465
+ # 465 c += save;
+ addq $21, $0, $21
+ .loc 2 466
+ # 466 *(mm++) = c;
+ stq $21, 0($1)
+ addq $1, 8, $1
+ .loc 2 467
+ # 467 c = (c < save) ? 1 : 0;
+ cmpult $21, $0, $16
+ ldiq $21, 1
+ cmoveq $16, 0, $21
+$58:
+ .loc 2 469
+ # 468 }
+ # 469 nl--;
+ addq $19, -1, $19
+ cmpult $19, $17, $6
+ beq $6, $56
+$59:
+ .loc 2 473
+ # 470 }
+ # 471 }
+ # 472
+ # 473 return (BnnAddCarry (mm, ml, (BigNumCarry) c));
+ bis $1, $1, $16
+ bis $2, $2, $17
+ bis $21, $21, $18
+ .livereg 0x0001F002,0x00000000
+ jsr $26, BnnAddCarry
+ ldgp $gp, 0($26)
+ .livereg 0xFC7F0002,0x3FC00000
+ ldq $26, 0($sp)
+ lda $sp, 16($sp)
+ ret $31, ($26), 1
+ .end BnnAdd
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnSubtractBorrow
+ .loc 2 490
+ # 490 {
+ .ent BnnSubtractBorrow 2
+BnnSubtractBorrow:
+ .option O2
+ ldgp $gp, 0($27)
+ .frame $sp, 0, $26, 0
+ .prologue 1
+ bis $16, $16, $1
+ .loc 2 490
+
+ .loc 2 491
+ # 491 if (carryin == 1)
+ subq $18, 1, $2
+ bne $2, $60
+ .loc 2 492
+ # 492 return (1);
+ ldiq $0, 1
+ .livereg 0x807F0002,0x3FC00000
+ ret $31, ($26), 1
+$60:
+ .loc 2 493
+ # 493 if (nl == 0)
+ bne $17, $61
+ .loc 2 494
+ # 494 return (0);
+ bis $31, $31, $0
+ .livereg 0x807F0002,0x3FC00000
+ ret $31, ($26), 1
+$61:
+ ldiq $19, 1
+ .loc 2 496
+ # 495
+ # 496 while (nl > 0 && !((*nn++)--))
+ cmpule $19, $17, $0
+ beq $0, $63
+ ldq $18, 0($1)
+ cmpeq $18, 0, $16
+ addq $18, -1, $3
+ stq $3, 0($1)
+ addq $1, 8, $1
+ beq $16, $63
+$62:
+ .loc 2 497
+ # 497 nl--;
+ addq $17, -1, $17
+ cmpule $19, $17, $0
+ beq $0, $63
+ ldq $18, 0($1)
+ cmpeq $18, 0, $16
+ addq $18, -1, $4
+ stq $4, 0($1)
+ addq $1, 8, $1
+ bne $16, $62
+$63:
+ .loc 2 499
+ # 498
+ # 499 return (nl > 0 ? 1 : 0);
+ ldil $16, 1
+ cmoveq $0, 0, $16
+ bis $16, $16, $0
+$64:
+ .livereg 0xFC7F0002,0x3FC00000
+ ret $31, ($26), 1
+ .end BnnSubtractBorrow
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnSubtract
+ .loc 2 514
+ # 514 {
+ .ent BnnSubtract 2
+BnnSubtract:
+ .option O2
+ ldgp $gp, 0($27)
+ lda $sp, -16($sp)
+ stq $26, 0($sp)
+ .mask 0x04000000, -16
+ .frame $sp, 16, $26, 0
+ .prologue 1
+ bis $16, $16, $1
+ bis $17, $17, $2
+ .loc 2 514
+
+ .loc 2 515
+ # 515 register BigNumProduct c = carryin;
+ bis $20, $20, $21
+ .loc 2 519
+ # 516 register BigNumDigit invn;
+ # 517
+ # 518
+ # 519 ml -= nl;
+ subq $2, $19, $2
+ .loc 2 521
+ # 520 /* test computed at compile time */
+ # 521 if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ ldiq $17, 1
+ .loc 2 533
+ # 533 {
+ .loc 2 536
+ # 534 register BigNumProduct save;
+ # 535
+ # 536 while (nl > 0)
+ cmpult $19, $17, $3
+ bne $3, $68
+$65:
+ .loc 2 537
+ # 537 {
+ .loc 2 538
+ # 538 save = *mm;
+ ldq $0, 0($1)
+ .loc 2 539
+ # 539 invn = *(nn++) ^ -1;
+ ldq $16, 0($18)
+ xor $16, -1, $16
+ addq $18, 8, $18
+ .loc 2 540
+ # 540 c += save;
+ addq $21, $0, $21
+ .loc 2 542
+ # 541
+ # 542 if (c < save)
+ cmpult $21, $0, $4
+ beq $4, $66
+ .loc 2 543
+ # 543 {
+ .loc 2 544
+ # 544 *(mm++) = invn;
+ stq $16, 0($1)
+ addq $1, 8, $1
+ .loc 2 545
+ # 545 c = 1;
+ bis $17, $17, $21
+ br $31, $67
+$66:
+ .loc 2 548
+ # 546 }
+ # 547 else
+ # 548 {
+ .loc 2 549
+ # 549 c += invn;
+ addq $21, $16, $21
+ .loc 2 550
+ # 550 *(mm++) = c;
+ stq $21, 0($1)
+ addq $1, 8, $1
+ .loc 2 551
+ # 551 c = (c < invn) ? 1 : 0;
+ cmpult $21, $16, $0
+ ldiq $21, 1
+ cmoveq $0, 0, $21
+$67:
+ .loc 2 553
+ # 552 }
+ # 553 nl--;
+ addq $19, -1, $19
+ cmpult $19, $17, $5
+ beq $5, $65
+$68:
+ .loc 2 557
+ # 554 }
+ # 555 }
+ # 556
+ # 557 return (BnnSubtractBorrow (mm, ml, (BigNumCarry) c)); }
+ bis $1, $1, $16
+ bis $2, $2, $17
+ bis $21, $21, $18
+ .livereg 0x0001F002,0x00000000
+ jsr $26, BnnSubtractBorrow
+ ldgp $gp, 0($26)
+ .livereg 0xFC7F0002,0x3FC00000
+ ldq $26, 0($sp)
+ lda $sp, 16($sp)
+ ret $31, ($26), 1
+ .end BnnSubtract
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnMultiplyDigit
+ .loc 2 577
+ # 577 {
+ .ent BnnMultiplyDigit 2
+BnnMultiplyDigit:
+ .option O2
+ ldgp $gp, 0($27)
+ lda $sp, -16($sp)
+ stq $26, 0($sp)
+ .mask 0x04000000, -16
+ .frame $sp, 16, $26, 0
+ .prologue 1
+ bis $16, $16, $1
+ bis $17, $17, $3
+ .loc 2 577
+
+ .loc 2 578
+ # 578 register BigNumProduct c = 0;
+ bis $31, $31, $21
+ .loc 2 581
+ # 579
+ # 580
+ # 581 if (d == 0)
+ bne $20, $69
+ .loc 2 582
+ # 582 return (0);
+ bis $31, $31, $0
+ br $31, $77
+$69:
+ .loc 2 584
+ # 583
+ # 584 if (d == 1)
+ subq $20, 1, $4
+ bne $4, $70
+ .loc 2 585
+ # 585 return (BnnAdd (pp, pl, mm, ml, (BigNumCarry) 0));
+ bis $1, $1, $16
+ bis $3, $3, $17
+ bis $31, $31, $20
+ .livereg 0x0001FC02,0x00000000
+ jsr $26, BnnAdd
+ ldgp $gp, 0($26)
+ br $31, $77
+$70:
+ .loc 2 587
+ # 586
+ # 587 pl -= ml;
+ subq $3, $19, $3
+ .loc 2 589
+ # 588 /* test computed at compile time */
+ # 589 if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ .loc 2 610
+ # 610 {
+ .loc 2 613
+ # 611 #ifdef __alpha /* _hack_to_produce_east_to_modify_assembler */
+ # 612 register BigNumDigit X0, m_digit,Lo,Hi;
+ # 613 while (ml != 0)
+ beq $19, $73
+ and $19, 3, $0
+ negq $0, $0
+ bis $0, $0, $2
+ beq $2, $72
+ addq $0, $19, $2
+$71:
+ addq $19, -1, $19
+ ldq $0, 0($1)
+ ldq $16, 0($18)
+ addq $18, 8, $18
+ addq $0, $21, $0
+ cmpult $0, $21, $21
+ mulq $20, $16, $5
+ addq $5, $0, $17
+ cmpult $17, $0, $6
+ addq $21, $6, $21
+ stq $17, 0($1)
+ addq $1, 8, $1
+ umulh $20, $16, $7
+ addq $21, $7, $21
+ subq $2, $19, $8
+ bne $8, $71
+ beq $19, $73
+$72:
+ .loc 2 614
+ # 614 {
+ .loc 2 615
+ # 615 ml--;
+ .loc 2 616
+ # 616 X0 = *pp;
+ ldq $0, 0($1)
+ .loc 2 617
+ # 617 m_digit = *(mm++);
+ ldq $16, 0($18)
+ addq $18, 8, $18
+ .loc 2 618
+ # 618 X0 += c;
+ addq $0, $21, $0
+ .loc 2 619
+ # 619 c = X0 < c;
+ cmpult $0, $21, $21
+ .loc 2 620
+ # 620 Lo = X0 + (d * m_digit);
+ .loc 2 621
+ # 621 c += Lo < X0;
+ mulq $20, $16, $22
+ addq $22, $0, $17
+ cmpult $17, $0, $23
+ addq $21, $23, $21
+ .loc 2 622
+ # 622 *(pp++) = Lo;
+ stq $17, 0($1)
+ addq $1, 8, $1
+ .loc 2 623
+ # 623 c += asm("umulh %a0, %a1, %v0",d,m_digit);
+ umulh $20, $16, $24
+ addq $21, $24, $21
+ ldq $0, 0($1)
+ ldq $16, 0($18)
+ addq $18, 8, $18
+ addq $0, $21, $0
+ cmpult $0, $21, $21
+ mulq $20, $16, $25
+ addq $25, $0, $17
+ cmpult $17, $0, $27
+ addq $21, $27, $21
+ stq $17, 0($1)
+ addq $1, 8, $1
+ umulh $20, $16, $4
+ addq $21, $4, $21
+ ldq $0, 0($1)
+ ldq $16, 0($18)
+ addq $18, 8, $18
+ addq $0, $21, $0
+ cmpult $0, $21, $21
+ mulq $20, $16, $5
+ addq $5, $0, $17
+ cmpult $17, $0, $6
+ addq $21, $6, $21
+ stq $17, 0($1)
+ addq $1, 8, $1
+ umulh $20, $16, $7
+ addq $21, $7, $21
+ addq $19, -4, $19
+ ldq $0, 0($1)
+ ldq $16, 0($18)
+ addq $18, 8, $18
+ addq $0, $21, $0
+ cmpult $0, $21, $21
+ mulq $20, $16, $8
+ addq $8, $0, $17
+ cmpult $17, $0, $22
+ addq $21, $22, $21
+ stq $17, 0($1)
+ addq $1, 8, $1
+ umulh $20, $16, $23
+ addq $21, $23, $21
+ bne $19, $72
+$73:
+ .loc 2 661
+ # 661 X0 = *pp;
+ ldq $0, 0($1)
+ .loc 2 662
+ # 662 c += X0;
+ addq $21, $0, $21
+ .loc 2 663
+ # 663 *(pp++) = c;
+ stq $21, 0($1)
+ addq $1, 8, $1
+ .loc 2 665
+ # 664
+ # 665 if (c >= X0)
+ cmpult $21, $0, $24
+ bne $24, $74
+ .loc 2 666
+ # 666 return (0);
+ bis $31, $31, $0
+ br $31, $77
+$74:
+ .loc 2 668
+ # 667
+ # 668 pl--;
+ addq $3, -1, $3
+ .loc 2 669
+ # 669 while (pl != 0 && !(++(*pp++)))
+ cmpeq $3, 0, $0
+ xor $0, 1, $0
+ beq $0, $76
+ ldq $25, 0($1)
+ addq $25, 1, $27
+ stq $27, 0($1)
+ ldq $16, 0($1)
+ cmpeq $16, 0, $16
+ addq $1, 8, $1
+ beq $16, $76
+$75:
+ .loc 2 670
+ # 670 pl--;
+ addq $3, -1, $3
+ cmpeq $3, 0, $0
+ xor $0, 1, $0
+ beq $0, $76
+ ldq $4, 0($1)
+ addq $4, 1, $5
+ stq $5, 0($1)
+ ldq $16, 0($1)
+ cmpeq $16, 0, $16
+ addq $1, 8, $1
+ bne $16, $75
+$76:
+ .loc 2 672
+ # 671
+ # 672 return (pl != 0 ? 0 : 1);
+ bis $31, $31, $16
+ cmoveq $0, 1, $16
+ bis $16, $16, $0
+$77:
+ .livereg 0xFC7F0002,0x3FC00000
+ ldq $26, 0($sp)
+ lda $sp, 16($sp)
+ ret $31, ($26), 1
+ .end BnnMultiplyDigit
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnMultiply2Digit
+ .loc 2 704
+ # 704 {
+ .ent BnnMultiply2Digit 2
+BnnMultiply2Digit:
+ .option O2
+ ldgp $gp, 0($27)
+ lda $sp, -416($sp)
+ stq $26, 0($sp)
+ stq $9, 8($sp)
+ stq $10, 16($sp)
+ stq $11, 24($sp)
+ stq $12, 32($sp)
+ stq $13, 40($sp)
+ stq $14, 48($sp)
+ stq $15, 56($sp)
+ .mask 0x0400FE00, -416
+ .frame $sp, 416, $26, 48
+ .prologue 1
+ bis $16, $16, $11
+ stq $17, 376($sp)
+ bis $18, $18, $9
+ bis $20, $20, $14
+ bis $21, $21, $15
+ .loc 2 704
+
+ .loc 2 706
+ # 705 BigNumDigit c0, c1, p0, p1;
+ # 706 if ((ml & 1))
+ blbc $19, $78
+ .loc 2 707
+ # 707 {
+ .loc 2 708
+ # 708 return
+ bis $11, $11, $16
+ ldq $17, 376($sp)
+ bis $9, $9, $18
+ bis $14, $14, $20
+ stq $19, 392($sp)
+ .livereg 0x0001FC02,0x00000000
+ jsr $26, BnnMultiplyDigit
+ ldgp $gp, 0($26)
+ ldq $19, 392($sp)
+ bis $0, $0, $10
+ addq $11, 8, $16
+ ldq $17, 376($sp)
+ addq $17, -1, $17
+ bis $9, $9, $18
+ bis $15, $15, $20
+ .livereg 0x0001FC02,0x00000000
+ jsr $26, BnnMultiplyDigit
+ ldgp $gp, 0($26)
+ addq $0, $10, $0
+ br $31, $90
+$78:
+ .loc 2 712
+ # 709 BnnMultiplyDigit (pp, pl, mm, ml, d0)
+ # 710 + BnnMultiplyDigit (pp+1, pl-1, mm, ml, d1);
+ # 711 }
+ # 712 c0 = c1 = 0;
+ bis $31, $31, $12
+ bis $31, $31, $0
+ .loc 2 725
+ # 725 if (d0 >= d1)
+ cmpult $14, $15, $22
+ bne $22, $82
+ .loc 2 726
+ # 726 {
+ .loc 2 728
+ # 727 BigNumDigit d0_1, c2, c3, ctmp1;
+ # 728 d0_1 = d0-d1;
+ subq $14, $15, $13
+ stq $13, 328($sp)
+ .loc 2 730
+ # 729
+ # 730 while (ml != 0)
+ beq $19, $86
+ stq $19, 392($sp)
+ stq $9, 384($sp)
+$79:
+ ldq $19, 392($sp)
+ ldq $9, 384($sp)
+ .loc 2 731
+ # 731 {
+ .loc 2 733
+ # 732 BigNumDigit m0,m1;
+ # 733 m0 = mm[0];
+ ldq $7, 0($9)
+ .loc 2 734
+ # 734 m1 = mm[1];
+ ldq $8, 8($9)
+ .loc 2 735
+ # 735 if (m0 >= m1)
+ cmpult $7, $8, $23
+ bne $23, $80
+ .loc 2 736
+ # 736 {
+ .loc 2 740
+ # 737 BigNumDigit m0_1;
+ # 738 BigNumDigit d0m0l, d0m0h, d1m1l, d1m1h, dfl, dfh;
+ # 739 BigNumDigit t0, t1, t2;
+ # 740 d0m0l = d0*m0;
+ .loc 2 741
+ # 741 d0m0h = asm("umulh %a0, %a1, %v0", d0,m0);
+ umulh $14, $7, $5
+ bis $5, $5, $20
+ .loc 2 742
+ # 742 m0_1 = m0-m1;
+ .loc 2 743
+ # 743 d1m1l = d1*m1;
+ .loc 2 744
+ # 744 d1m1h = asm("umulh %a0, %a1, %v0", d1,m1);
+ .loc 2 745
+ # 745 dfl = d0_1*m0_1;
+ .loc 2 746
+ # 746 dfh = asm("umulh %a0, %a1, %v0", d0_1,m0_1);
+ .loc 2 747
+ # 747 p0 = pp[0];
+ ldq $6, 0($11)
+ .loc 2 748
+ # 748 p1 = pp[1];
+ ldq $21, 8($11)
+ .loc 2 749
+ # 749 p0 += c0;
+ addq $6, $0, $6
+ .loc 2 750
+ # 750 ctmp1 = p0 < c0;
+ cmpult $6, $0, $26
+ .loc 2 751
+ # 751 p1 += c1;
+ addq $21, $12, $21
+ .loc 2 752
+ # 752 c2 = p1 < c1;
+ cmpult $21, $12, $18
+ .loc 2 753
+ # 753 p1 += ctmp1;
+ addq $21, $26, $21
+ .loc 2 754
+ # 754 c2 += p1 < ctmp1;
+ cmpult $21, $26, $24
+ addq $18, $24, $18
+ .loc 2 755
+ # 755 p0 += d0m0l;
+ mulq $14, $7, $2
+ addq $6, $2, $6
+ .loc 2 756
+ # 756 c1 = p0 < d0m0l;
+ .loc 2 758
+ # 757 /* compute: t2:t1:t0 = d0*m0 + d1*m1 */
+ # 758 t0 = d0m0l+d1m1l;
+ .loc 2 759
+ # 759 ctmp1 = t0 < d0m0l;
+ .loc 2 760
+ # 760 t1 = d0m0h+d1m1h;
+ .loc 2 761
+ # 761 t2 = t1 < d0m0h;
+ .loc 2 762
+ # 762 t1 += ctmp1;
+ umulh $15, $8, $10
+ addq $5, $10, $19
+ mulq $15, $8, $9
+ addq $2, $9, $4
+ cmpult $4, $2, $20
+ addq $19, $20, $16
+ bis $16, $16, $0
+ .loc 2 763
+ # 763 t2 += t1 < ctmp1;
+ .loc 2 767
+ # 764 /* t2:t1:t0 = d0*m0 + d1*m1 */
+ # 765 /* dfh:dfl = d0*m0 + d1*m1 - d0*m1 - d1*m0 */
+ # 766 /* compute: t2:t1:t0 = t2:t1:t0 - dfh:dfl */
+ # 767 ctmp1 = t0 < dfl;
+ .loc 2 768
+ # 768 t0 -= dfl;
+ .loc 2 769
+ # 769 t2 -= t1 < dfh;
+ subq $7, $8, $1
+ cmpult $19, $5, $25
+ cmpult $16, $20, $27
+ addq $25, $27, $22
+ ldq $23, 328($sp)
+ xor $23, $1, $24
+ cmpult $16, $24, $25
+ subq $22, $25, $3
+ .loc 2 770
+ # 770 t1 -= dfh;
+ umulh $13, $1, $27
+ subq $0, $27, $0
+ .loc 2 771
+ # 771 t2 -= t1 < ctmp1;
+ mulq $13, $1, $16
+ cmpult $4, $16, $17
+ cmpult $0, $17, $23
+ subq $3, $23, $3
+ .loc 2 772
+ # 772 t1 -= ctmp1;
+ subq $0, $17, $0
+ .loc 2 774
+ # 773 /* t2:t1:t0 = d0*m1 + d1*m0 */
+ # 774 ultra_parnoid(t0, t1, t2, d0, d1, m0, m1);
+ .loc 2 775
+ # 775 d0m0h += c1;
+ cmpult $6, $2, $24
+ addq $5, $24, $20
+ .loc 2 776
+ # 776 p1 += d0m0h;
+ addq $21, $20, $21
+ .loc 2 777
+ # 777 c2 += p1 < d0m0h;
+ cmpult $21, $20, $22
+ addq $18, $22, $18
+ .loc 2 778
+ # 778 p1 += t0;
+ subq $4, $16, $19
+ addq $21, $19, $21
+ .loc 2 779
+ # 779 c2 += p1 < t0;
+ cmpult $21, $19, $25
+ addq $18, $25, $18
+ .loc 2 780
+ # 780 t1 += c2;
+ addq $0, $18, $0
+ .loc 2 781
+ # 781 t2 += t1 < c2;
+ cmpult $0, $18, $27
+ addq $3, $27, $3
+ .loc 2 782
+ # 782 c2 = t1 + d1m1l;
+ addq $0, $9, $16
+ bis $16, $16, $18
+ .loc 2 783
+ # 783 c3 = t2 + d1m1h + (c2 < t1);
+ addq $3, $10, $23
+ cmpult $16, $0, $24
+ addq $23, $24, $19
+ br $31, $81
+$80:
+ .loc 2 786
+ # 784 }
+ # 785 else
+ # 786 {
+ .loc 2 790
+ # 787 BigNumDigit m0_1;
+ # 788 BigNumDigit d0m0l, d0m0h, d1m1l, d1m1h, dfl, dfh;
+ # 789 BigNumDigit t0, t1, t2;
+ # 790 d0m0l = d0*m0;
+ .loc 2 791
+ # 791 d0m0h = asm("umulh %a0, %a1, %v0", d0,m0);
+ umulh $14, $7, $5
+ bis $5, $5, $20
+ .loc 2 792
+ # 792 m0_1 = -m0+m1;
+ .loc 2 793
+ # 793 d1m1l = d1*m1;
+ .loc 2 794
+ # 794 d1m1h = asm("umulh %a0, %a1, %v0", d1,m1);
+ .loc 2 795
+ # 795 dfl = d0_1*m0_1;
+ .loc 2 796
+ # 796 dfh = asm("umulh %a0, %a1, %v0", d0_1,m0_1);
+ .loc 2 797
+ # 797 p0 = pp[0];
+ ldq $6, 0($11)
+ .loc 2 798
+ # 798 p1 = pp[1];
+ ldq $21, 8($11)
+ .loc 2 799
+ # 799 p0 += c0;
+ addq $6, $0, $6
+ .loc 2 800
+ # 800 ctmp1 = p0 < c0;
+ cmpult $6, $0, $26
+ .loc 2 801
+ # 801 p1 += c1;
+ addq $21, $12, $21
+ .loc 2 802
+ # 802 c2 = p1 < c1;
+ cmpult $21, $12, $18
+ .loc 2 803
+ # 803 p1 += ctmp1;
+ addq $21, $26, $21
+ .loc 2 804
+ # 804 c2 += p1 < ctmp1;
+ cmpult $21, $26, $22
+ addq $18, $22, $18
+ .loc 2 805
+ # 805 p0 += d0m0l;
+ mulq $14, $7, $2
+ addq $6, $2, $6
+ .loc 2 806
+ # 806 c1 = p0 < d0m0l;
+ .loc 2 807
+ # 807 t0 = d0m0l+d1m1l;
+ .loc 2 808
+ # 808 ctmp1 = t0 < d0m0l;
+ .loc 2 809
+ # 809 t1 = d0m0h+d1m1h;
+ .loc 2 810
+ # 810 t2 = t1 < d0m0h;
+ .loc 2 811
+ # 811 t1 += ctmp1;
+ .loc 2 812
+ # 812 t2 += t1 < ctmp1;
+ umulh $15, $8, $10
+ addq $5, $10, $19
+ mulq $15, $8, $9
+ addq $2, $9, $4
+ cmpult $4, $2, $20
+ addq $19, $20, $16
+ cmpult $19, $5, $25
+ cmpult $16, $20, $27
+ addq $25, $27, $1
+ .loc 2 816
+ # 813 /* t2:t1:t0 = d0*m0 + d1*m1 */
+ # 814 /* dfh:dfl = - d0*m0 - d1*m1 + d0*m1 + d1*m0 */
+ # 815 /* compute: t2:t1:t0 = t2:t1:t0 + dfh:dfl */
+ # 816 t0 += dfl;
+ .loc 2 817
+ # 817 ctmp1 = t0 < dfl;
+ .loc 2 818
+ # 818 t1 += dfh;
+ subq $8, $7, $3
+ ldq $23, 328($sp)
+ xor $23, $3, $24
+ addq $16, $24, $17
+ .loc 2 819
+ # 819 t2 += t1 < dfh;
+ umulh $13, $3, $22
+ cmpult $17, $22, $25
+ addq $1, $25, $1
+ .loc 2 820
+ # 820 t1 += ctmp1;
+ mulq $13, $3, $16
+ addq $4, $16, $0
+ cmpult $0, $16, $19
+ addq $17, $19, $17
+ .loc 2 821
+ # 821 t2 += t1 < ctmp1;
+ cmpult $17, $19, $27
+ addq $1, $27, $1
+ .loc 2 823
+ # 822 /* t2:t1:t0 = d0*m1 + d1*m0 */
+ # 823 ultra_parnoid(t0, t1, t2, d0, d1, m0, m1);
+ .loc 2 824
+ # 824 d0m0h += c1;
+ cmpult $6, $2, $23
+ addq $5, $23, $20
+ .loc 2 825
+ # 825 p1 += d0m0h;
+ addq $21, $20, $21
+ .loc 2 826
+ # 826 c2 += p1 < d0m0h;
+ cmpult $21, $20, $24
+ addq $18, $24, $18
+ .loc 2 827
+ # 827 p1 += t0;
+ addq $21, $0, $21
+ .loc 2 828
+ # 828 c2 += p1 < t0;
+ cmpult $21, $0, $22
+ addq $18, $22, $18
+ .loc 2 829
+ # 829 t1 += c2;
+ addq $17, $18, $17
+ .loc 2 830
+ # 830 t2 += t1 < c2;
+ cmpult $17, $18, $25
+ addq $1, $25, $1
+ .loc 2 831
+ # 831 c2 = t1 + d1m1l;
+ addq $17, $9, $0
+ bis $0, $0, $18
+ .loc 2 832
+ # 832 c3 = t2 + d1m1h + (c2 < t1);
+ addq $1, $10, $27
+ cmpult $0, $17, $23
+ addq $27, $23, $19
+$81:
+ ldq $16, 392($sp)
+ .loc 2 835
+ # 833 }
+ # 834
+ # 835 pp[0] = p0;
+ stq $6, 0($11)
+ .loc 2 836
+ # 836 pp[1] = p1;
+ stq $21, 8($11)
+ .loc 2 837
+ # 837 pp += 2;
+ addq $11, 16, $11
+ .loc 2 838
+ # 838 pl -= 2;
+ ldq $24, 376($sp)
+ addq $24, -2, $22
+ stq $22, 376($sp)
+ .loc 2 839
+ # 839 c0 = c2;
+ bis $18, $18, $0
+ .loc 2 840
+ # 840 c1 = c3;
+ bis $19, $19, $12
+ .loc 2 841
+ # 841 ml -= 2;
+ addq $16, -2, $16
+ .loc 2 842
+ # 842 mm += 2;
+ ldq $25, 384($sp)
+ addq $25, 16, $27
+ stq $27, 384($sp)
+ stq $16, 392($sp)
+ bne $16, $79
+ br $31, $86
+$82:
+ .loc 2 846
+ # 843 }
+ # 844 }
+ # 845 else
+ # 846 {
+ .loc 2 848
+ # 847 BigNumDigit d0_1, c2, c3, ctmp1;
+ # 848 d0_1 = d1-d0;
+ subq $15, $14, $13
+ stq $13, 120($sp)
+ .loc 2 850
+ # 849
+ # 850 while (ml != 0)
+ beq $19, $86
+ stq $19, 392($sp)
+ stq $9, 384($sp)
+$83:
+ ldq $19, 392($sp)
+ ldq $9, 384($sp)
+ .loc 2 851
+ # 851 {
+ .loc 2 853
+ # 852 BigNumDigit m0,m1;
+ # 853 m0 = mm[0];
+ ldq $7, 0($9)
+ .loc 2 854
+ # 854 m1 = mm[1];
+ ldq $8, 8($9)
+ .loc 2 855
+ # 855 if (m0 >= m1)
+ cmpult $7, $8, $23
+ bne $23, $84
+ .loc 2 856
+ # 856 {
+ .loc 2 860
+ # 857 BigNumDigit m0_1;
+ # 858 BigNumDigit d0m0l, d0m0h, d1m1l, d1m1h, dfl, dfh;
+ # 859 BigNumDigit t0, t1, t2;
+ # 860 d0m0l = d0*m0;
+ .loc 2 861
+ # 861 d0m0h = asm("umulh %a0, %a1, %v0", d0,m0);
+ umulh $14, $7, $5
+ bis $5, $5, $20
+ .loc 2 862
+ # 862 m0_1 = m0-m1;
+ .loc 2 863
+ # 863 d1m1l = d1*m1;
+ .loc 2 864
+ # 864 d1m1h = asm("umulh %a0, %a1, %v0", d1,m1);
+ .loc 2 865
+ # 865 dfl = d0_1*m0_1;
+ .loc 2 866
+ # 866 dfh = asm("umulh %a0, %a1, %v0", d0_1,m0_1);
+ .loc 2 867
+ # 867 p0 = pp[0];
+ ldq $6, 0($11)
+ .loc 2 868
+ # 868 p1 = pp[1];
+ ldq $21, 8($11)
+ .loc 2 869
+ # 869 p0 += c0;
+ addq $6, $0, $6
+ .loc 2 870
+ # 870 ctmp1 = p0 < c0;
+ cmpult $6, $0, $26
+ .loc 2 871
+ # 871 p1 += c1;
+ addq $21, $12, $21
+ .loc 2 872
+ # 872 c2 = p1 < c1;
+ cmpult $21, $12, $18
+ .loc 2 873
+ # 873 p1 += ctmp1;
+ addq $21, $26, $21
+ .loc 2 874
+ # 874 c2 += p1 < ctmp1;
+ cmpult $21, $26, $24
+ addq $18, $24, $18
+ .loc 2 875
+ # 875 p0 += d0m0l;
+ mulq $14, $7, $2
+ addq $6, $2, $6
+ .loc 2 876
+ # 876 c1 = p0 < d0m0l;
+ .loc 2 878
+ # 877 /* compute: t2:t1:t0 = d0*m0 + d1*m1 */
+ # 878 t0 = d0m0l+d1m1l;
+ .loc 2 879
+ # 879 ctmp1 = t0 < d0m0l;
+ .loc 2 880
+ # 880 t1 = d0m0h+d1m1h;
+ .loc 2 881
+ # 881 t2 = t1 < d0m0h;
+ .loc 2 882
+ # 882 t1 += ctmp1;
+ .loc 2 883
+ # 883 t2 += t1 < ctmp1;
+ umulh $15, $8, $10
+ addq $5, $10, $19
+ mulq $15, $8, $9
+ addq $2, $9, $4
+ cmpult $4, $2, $20
+ addq $19, $20, $16
+ cmpult $19, $5, $22
+ cmpult $16, $20, $25
+ addq $22, $25, $1
+ .loc 2 887
+ # 884 /* t2:t1:t0 = d0*m0 + d1*m1 */
+ # 885 /* dfh:dfl = - d0*m0 - d1*m1 + d0*m1 + d1*m0 */
+ # 886 /* compute: t2:t1:t0 = t2:t1:t0 + dfh:dfl */
+ # 887 t0 += dfl;
+ .loc 2 888
+ # 888 ctmp1 = t0 < dfl;
+ .loc 2 889
+ # 889 t1 += dfh;
+ subq $7, $8, $3
+ ldq $27, 120($sp)
+ xor $27, $3, $23
+ addq $16, $23, $17
+ .loc 2 890
+ # 890 t2 += t1 < dfh;
+ umulh $13, $3, $24
+ cmpult $17, $24, $22
+ addq $1, $22, $1
+ .loc 2 891
+ # 891 t1 += ctmp1;
+ mulq $13, $3, $16
+ addq $4, $16, $0
+ cmpult $0, $16, $19
+ addq $17, $19, $17
+ .loc 2 892
+ # 892 t2 += t1 < ctmp1;
+ cmpult $17, $19, $25
+ addq $1, $25, $1
+ .loc 2 894
+ # 893 /* t2:t1:t0 = d0*m1 + d1*m0 */
+ # 894 ultra_parnoid(t0, t1, t2, d0, d1, m0, m1);
+ .loc 2 895
+ # 895 d0m0h += c1;
+ cmpult $6, $2, $27
+ addq $5, $27, $20
+ .loc 2 896
+ # 896 p1 += d0m0h;
+ addq $21, $20, $21
+ .loc 2 897
+ # 897 c2 += p1 < d0m0h;
+ cmpult $21, $20, $23
+ addq $18, $23, $18
+ .loc 2 898
+ # 898 p1 += t0;
+ addq $21, $0, $21
+ .loc 2 899
+ # 899 c2 += p1 < t0;
+ cmpult $21, $0, $24
+ addq $18, $24, $18
+ .loc 2 900
+ # 900 t1 += c2;
+ addq $17, $18, $17
+ .loc 2 901
+ # 901 t2 += t1 < c2;
+ cmpult $17, $18, $22
+ addq $1, $22, $1
+ .loc 2 902
+ # 902 c2 = t1 + d1m1l;
+ addq $17, $9, $0
+ bis $0, $0, $18
+ .loc 2 903
+ # 903 c3 = t2 + d1m1h + (c2 < t1);
+ addq $1, $10, $25
+ cmpult $0, $17, $27
+ addq $25, $27, $19
+ br $31, $85
+$84:
+ .loc 2 906
+ # 904 }
+ # 905 else
+ # 906 {
+ .loc 2 910
+ # 907 BigNumDigit m0_1;
+ # 908 BigNumDigit d0m0l, d0m0h, d1m1l, d1m1h, dfl, dfh;
+ # 909 BigNumDigit t0, t1, t2;
+ # 910 d0m0l = d0*m0;
+ .loc 2 911
+ # 911 d0m0h = asm("umulh %a0, %a1, %v0", d0,m0);
+ umulh $14, $7, $5
+ bis $5, $5, $20
+ .loc 2 912
+ # 912 m0_1 = -m0+m1;
+ .loc 2 913
+ # 913 d1m1l = d1*m1;
+ .loc 2 914
+ # 914 d1m1h = asm("umulh %a0, %a1, %v0", d1,m1);
+ .loc 2 915
+ # 915 dfl = d0_1*m0_1;
+ .loc 2 916
+ # 916 dfh = asm("umulh %a0, %a1, %v0", d0_1,m0_1);
+ .loc 2 917
+ # 917 p0 = pp[0];
+ ldq $6, 0($11)
+ .loc 2 918
+ # 918 p1 = pp[1];
+ ldq $21, 8($11)
+ .loc 2 919
+ # 919 p0 += c0;
+ addq $6, $0, $6
+ .loc 2 920
+ # 920 ctmp1 = p0 < c0;
+ cmpult $6, $0, $26
+ .loc 2 921
+ # 921 p1 += c1;
+ addq $21, $12, $21
+ .loc 2 922
+ # 922 c2 = p1 < c1;
+ cmpult $21, $12, $18
+ .loc 2 923
+ # 923 p1 += ctmp1;
+ addq $21, $26, $21
+ .loc 2 924
+ # 924 c2 += p1 < ctmp1;
+ cmpult $21, $26, $23
+ addq $18, $23, $18
+ .loc 2 925
+ # 925 p0 += d0m0l;
+ mulq $14, $7, $2
+ addq $6, $2, $6
+ .loc 2 926
+ # 926 c1 = p0 < d0m0l;
+ .loc 2 927
+ # 927 t0 = d0m0l+d1m1l;
+ .loc 2 928
+ # 928 ctmp1 = t0 < d0m0l;
+ .loc 2 929
+ # 929 t1 = d0m0h+d1m1h;
+ .loc 2 930
+ # 930 t2 = t1 < d0m0h;
+ .loc 2 931
+ # 931 t1 += ctmp1;
+ umulh $15, $8, $10
+ addq $5, $10, $19
+ mulq $15, $8, $9
+ addq $2, $9, $4
+ cmpult $4, $2, $20
+ addq $19, $20, $16
+ bis $16, $16, $0
+ .loc 2 932
+ # 932 t2 += t1 < ctmp1;
+ .loc 2 936
+ # 933 /* t2:t1:t0 = d0*m0 + d1*m1 */
+ # 934 /* dfh:dfl = d0*m0 + d1*m1 - d0*m1 - d1*m0 */
+ # 935 /* compute: t2:t1:t0 = t2:t1:t0 - dfh:dfl */
+ # 936 ctmp1 = t0 < dfl;
+ .loc 2 937
+ # 937 t0 -= dfl;
+ .loc 2 938
+ # 938 t2 -= t1 < dfh;
+ subq $8, $7, $1
+ cmpult $19, $5, $24
+ cmpult $16, $20, $22
+ addq $24, $22, $25
+ ldq $27, 120($sp)
+ xor $27, $1, $23
+ cmpult $16, $23, $24
+ subq $25, $24, $3
+ .loc 2 939
+ # 939 t1 -= dfh;
+ umulh $13, $1, $22
+ subq $0, $22, $0
+ .loc 2 940
+ # 940 t2 -= t1 < ctmp1;
+ mulq $13, $1, $16
+ cmpult $4, $16, $17
+ cmpult $0, $17, $27
+ subq $3, $27, $3
+ .loc 2 941
+ # 941 t1 -= ctmp1;
+ subq $0, $17, $0
+ .loc 2 943
+ # 942 /* t2:t1:t0 = d0*m1 + d1*m0 */
+ # 943 ultra_parnoid(t0, t1, t2, d0, d1, m0, m1);
+ .loc 2 944
+ # 944 d0m0h += c1;
+ cmpult $6, $2, $23
+ addq $5, $23, $20
+ .loc 2 945
+ # 945 p1 += d0m0h;
+ addq $21, $20, $21
+ .loc 2 946
+ # 946 c2 += p1 < d0m0h;
+ cmpult $21, $20, $25
+ addq $18, $25, $18
+ .loc 2 947
+ # 947 p1 += t0;
+ subq $4, $16, $19
+ addq $21, $19, $21
+ .loc 2 948
+ # 948 c2 += p1 < t0;
+ cmpult $21, $19, $24
+ addq $18, $24, $18
+ .loc 2 949
+ # 949 t1 += c2;
+ addq $0, $18, $0
+ .loc 2 950
+ # 950 t2 += t1 < c2;
+ cmpult $0, $18, $22
+ addq $3, $22, $3
+ .loc 2 951
+ # 951 c2 = t1 + d1m1l;
+ addq $0, $9, $16
+ bis $16, $16, $18
+ .loc 2 952
+ # 952 c3 = t2 + d1m1h + (c2 < t1);
+ addq $3, $10, $27
+ cmpult $16, $0, $23
+ addq $27, $23, $19
+$85:
+ ldq $16, 392($sp)
+ .loc 2 955
+ # 953 }
+ # 954
+ # 955 pp[0] = p0;
+ stq $6, 0($11)
+ .loc 2 956
+ # 956 pp[1] = p1;
+ stq $21, 8($11)
+ .loc 2 957
+ # 957 pp += 2;
+ addq $11, 16, $11
+ .loc 2 958
+ # 958 pl -= 2;
+ ldq $25, 376($sp)
+ addq $25, -2, $24
+ stq $24, 376($sp)
+ .loc 2 959
+ # 959 c0 = c2;
+ bis $18, $18, $0
+ .loc 2 960
+ # 960 c1 = c3;
+ bis $19, $19, $12
+ .loc 2 961
+ # 961 ml -= 2;
+ addq $16, -2, $16
+ .loc 2 962
+ # 962 mm += 2;
+ ldq $22, 384($sp)
+ addq $22, 16, $27
+ stq $27, 384($sp)
+ stq $16, 392($sp)
+ bne $16, $83
+$86:
+ .loc 2 965
+ # 963 }
+ # 964 }
+ # 965 p0 = pp[0];
+ ldq $6, 0($11)
+ .loc 2 966
+ # 966 p1 = pp[1];
+ ldq $21, 8($11)
+ .loc 2 967
+ # 967 p0 += c0;
+ addq $6, $0, $6
+ .loc 2 968
+ # 968 pp[0] = p0;
+ stq $6, 0($11)
+ .loc 2 969
+ # 969 c1 += p0 < c0;
+ cmpult $6, $0, $23
+ addq $12, $23, $12
+ .loc 2 970
+ # 970 p1 += c1;
+ addq $21, $12, $21
+ .loc 2 971
+ # 971 pp[1] = p1;
+ stq $21, 8($11)
+ .loc 2 973
+ # 972
+ # 973 if (c1 <= p1)
+ cmpult $21, $12, $25
+ bne $25, $87
+ .loc 2 974
+ # 974 {
+ .loc 2 978
+ # 975 #ifdef PARANOID
+ # 976 assert(sc == 0 && BnnCompare(sp, sl, rp, sl) == BN_EQ);
+ # 977 #endif
+ # 978 return (0);
+ bis $31, $31, $0
+ br $31, $90
+$87:
+ ldq $17, 376($sp)
+ .loc 2 981
+ # 979 }
+ # 980
+ # 981 pl -= 2;
+ addq $17, -2, $17
+ .loc 2 982
+ # 982 pp+=2;
+ addq $11, 16, $11
+ .loc 2 983
+ # 983 while (pl != 0 && !(++(*pp++)))
+ cmpeq $17, 0, $0
+ xor $0, 1, $0
+ beq $0, $89
+ ldq $24, 0($11)
+ addq $24, 1, $22
+ stq $22, 0($11)
+ ldq $16, 0($11)
+ cmpeq $16, 0, $16
+ addq $11, 8, $11
+ beq $16, $89
+$88:
+ .loc 2 984
+ # 984 pl--;
+ addq $17, -1, $17
+ cmpeq $17, 0, $0
+ xor $0, 1, $0
+ beq $0, $89
+ ldq $27, 0($11)
+ addq $27, 1, $23
+ stq $23, 0($11)
+ ldq $16, 0($11)
+ cmpeq $16, 0, $16
+ addq $11, 8, $11
+ bne $16, $88
+$89:
+ .loc 2 990
+ # 985
+ # 986 #ifdef PARANOID
+ # 987 assert(sc == (pl != 0 ? 0 : 1));
+ # 988 assert(BnnCompare(sp, sl, rp, sl) == BN_EQ);
+ # 989 #endif
+ # 990 return (pl != 0 ? 0 : 1);
+ bis $31, $31, $16
+ cmoveq $0, 1, $16
+ bis $16, $16, $0
+$90:
+ .livereg 0xFC7F0002,0x3FC00000
+ ldq $26, 0($sp)
+ ldq $9, 8($sp)
+ ldq $10, 16($sp)
+ ldq $11, 24($sp)
+ ldq $12, 32($sp)
+ ldq $13, 40($sp)
+ ldq $14, 48($sp)
+ ldq $15, 56($sp)
+ lda $sp, 416($sp)
+ ret $31, ($26), 1
+ .end BnnMultiply2Digit
+ .text
+ .align 4
+ .file 2 "c/KerN.c"
+ .globl BnnDivideDigit
+ .loc 2 1019
+ # 1019 {
+ .ent BnnDivideDigit 2
+BnnDivideDigit:
+ .option O2
+ ldgp $gp, 0($27)
+ lda $sp, -240($sp)
+ stq $26, 0($sp)
+ stq $9, 8($sp)
+ stq $10, 16($sp)
+ stq $11, 24($sp)
+ stq $12, 32($sp)
+ .mask 0x04001E00, -240
+ .frame $sp, 240, $26, 48
+ .prologue 1
+ bis $16, $16, $10
+ bis $17, $17, $12
+ bis $18, $18, $11
+ bis $19, $19, $5
+ .loc 2 1019
+
+ .loc 2 1021
+ # 1020 /* test computed at compile time */
+ # 1021 if (sizeof (BigNumProduct) > sizeof (BigNumDigit))
+ .loc 2 1042
+ # 1042 {
+ .loc 2 1053
+ # 1053 k = BnnNumLeadingZeroBitsInDigit (d);
+ bis $5, $5, $16
+ stq $5, 216($sp)
+ .livereg 0x0001C002,0x00000000
+ jsr $26, BnnNumLeadingZeroBitsInDigit
+ ldgp $gp, 0($26)
+ ldq $5, 216($sp)
+ addl $0, 0, $16
+ stl $16, 176($sp)
+ .loc 2 1054
+ # 1054 if (k != 0)
+ beq $16, $91
+ .loc 2 1055
+ # 1055 {
+ .loc 2 1056
+ # 1056 prev_qq = qq[-1];
+ ldq $22, -8($10)
+ stq $22, 104($sp)
+ .loc 2 1057
+ # 1057 orig_nl = nl;
+ stq $11, 168($sp)
+ .loc 2 1058
+ # 1058 d <<= k;
+ ldl $23, 176($sp)
+ sll $5, $23, $5
+ .loc 2 1059
+ # 1059 BnnShiftLeft (nn, nl, k);
+ bis $12, $12, $16
+ bis $11, $11, $17
+ bis $23, $23, $18
+ stq $5, 216($sp)
+ .livereg 0x0001E002,0x00000000
+ jsr $26, BnnShiftLeft
+ ldgp $gp, 0($26)
+ ldq $5, 216($sp)
+$91:
+ .loc 2 1062
+ # 1060 }
+ # 1061
+ # 1062 nn += nl;
+ s8addq $11, $12, $12
+ .loc 2 1063
+ # 1063 nl--;
+ addq $11, -1, $11
+ .loc 2 1064
+ # 1064 qq += nl;
+ s8addq $11, $10, $10
+ .loc 2 1066
+ # 1065
+ # 1066 ch = HIGH (d);
+ srl $5, 32, $6
+ bis $6, $6, $26
+ .loc 2 1067
+ # 1067 cl = LOW (d);
+ and $5, 4294967295, $8
+ bis $8, $8, $9
+ .loc 2 1069
+ # 1068
+ # 1069 rl = *(--nn);
+ addq $12, -8, $12
+ ldq $7, 0($12)
+ .loc 2 1071
+ # 1070
+ # 1071 while (nl != 0)
+ beq $11, $103
+$92:
+ .loc 2 1072
+ # 1072 {
+ .loc 2 1073
+ # 1073 nl--;
+ addq $11, -1, $11
+ .loc 2 1074
+ # 1074 rh = rl;
+ bis $7, $7, $1
+ .loc 2 1075
+ # 1075 rl = *(--nn);
+ addq $12, -8, $12
+ ldq $7, 0($12)
+ .loc 2 1076
+ # 1076 qa = rh / ch; /* appr. quotient */
+ divqu $1, $6, $0
+ bis $0, $0, $3
+ .loc 2 1079
+ # 1077
+ # 1078 /* Compute ph, pl */
+ # 1079 pl = cl * qa;
+ .loc 2 1080
+ # 1080 ph = ch * qa;
+ .loc 2 1081
+ # 1081 ph += HIGH (pl);
+ mulq $9, $0, $18
+ mulq $6, $0, $24
+ srl $18, 32, $25
+ addq $24, $25, $19
+ bis $19, $19, $17
+ .loc 2 1082
+ # 1082 pl = L2H (pl);
+ sll $18, 32, $20
+ bis $20, $20, $16
+ .loc 2 1085
+ # 1083
+ # 1084 /* While ph:pl > rh:rl, decrement qa, adjust qh:ql */
+ # 1085 while (ph > rh || ph == rh && pl > rl)
+ cmpult $1, $19, $27
+ bne $27, $93
+ divqu $1, $26, $0
+ mulq $26, $0, $22
+ mulq $9, $0, $23
+ srl $23, 32, $24
+ addq $22, $24, $25
+ subq $25, $1, $27
+ bne $27, $96
+ cmpult $7, $20, $23
+ beq $23, $96
+$93:
+ .loc 2 1086
+ # 1086 {
+ .loc 2 1087
+ # 1087 qa--;
+ addq $3, -1, $3
+ .loc 2 1088
+ # 1088 SUB (ph, pl, ch, L2H (cl));
+ sll $8, 32, $0
+ cmpult $16, $0, $22
+ beq $22, $94
+ .loc 2 1088
+
+ .loc 2 1088
+
+ subq $16, $0, $16
+ .loc 2 1088
+
+ subq $17, $6, $17
+ addq $17, -1, $17
+ br $31, $95
+$94:
+ .loc 2 1088
+
+ .loc 2 1088
+
+ subq $16, $0, $16
+ .loc 2 1088
+
+ subq $17, $6, $17
+$95:
+ .loc 2 1088
+
+ cmpult $1, $17, $24
+ bne $24, $93
+ subq $17, $1, $25
+ bne $25, $96
+ cmpult $7, $16, $27
+ bne $27, $93
+$96:
+ .loc 2 1091
+ # 1089 }
+ # 1090
+ # 1091 SUB (rh, rl, ph, pl);
+ cmpult $7, $16, $23
+ beq $23, $97
+ .loc 2 1091
+
+ .loc 2 1091
+
+ subq $7, $16, $7
+ .loc 2 1091
+
+ subq $1, $17, $1
+ addq $1, -1, $1
+ br $31, $98
+$97:
+ .loc 2 1091
+
+ .loc 2 1091
+
+ subq $7, $16, $7
+ .loc 2 1091
+
+ subq $1, $17, $1
+$98:
+ .loc 2 1091
+
+ .loc 2 1094
+ # 1092
+ # 1093 /* Top half of quotient is correct; save it */
+ # 1094 *(--qq) = L2H (qa);
+ addq $10, -8, $18
+ bis $18, $18, $2
+ bis $18, $18, $10
+ sll $3, 32, $22
+ stq $22, 0($2)
+ .loc 2 1095
+ # 1095 qa = (L2H (rh) | HIGH (rl)) / ch;
+ sll $1, 32, $24
+ srl $7, 32, $25
+ or $24, $25, $4
+ divqu $4, $6, $0
+ bis $0, $0, $3
+ .loc 2 1099
+ # 1096
+ # 1097 /* Approx low half of q */
+ # 1098 /* Compute ph, pl, again */
+ # 1099 pl = cl * qa;
+ .loc 2 1100
+ # 1100 ph = ch * qa;
+ .loc 2 1101
+ # 1101 ph += HIGH (pl);
+ .loc 2 1102
+ # 1102 pl = LOW (pl) | L2H (LOW (ph));
+ mulq $9, $0, $19
+ mulq $6, $0, $27
+ srl $19, 32, $23
+ addq $27, $23, $20
+ and $19, 4294967295, $22
+ and $20, 4294967295, $24
+ sll $24, 32, $25
+ or $22, $25, $16
+ .loc 2 1103
+ # 1103 ph = HIGH (ph);
+ srl $20, 32, $21
+ bis $21, $21, $17
+ .loc 2 1106
+ # 1104
+ # 1105 /* While ph:pl > rh:rl, decrement qa, adjust qh:ql */
+ # 1106 while (ph > rh || ph == rh && pl > rl)
+ cmpult $1, $21, $27
+ bne $27, $99
+ divqu $4, $26, $0
+ mulq $26, $0, $23
+ mulq $9, $0, $24
+ srl $24, 32, $22
+ addq $23, $22, $25
+ srl $25, 32, $27
+ subq $27, $1, $24
+ bne $24, $102
+ cmpult $7, $16, $23
+ beq $23, $102
+$99:
+ .loc 2 1107
+ # 1107 {
+ .loc 2 1108
+ # 1108 qa--;
+ addq $3, -1, $3
+ .loc 2 1109
+ # 1109 SUB (ph, pl, 0, d);
+ cmpult $16, $5, $22
+ beq $22, $100
+ .loc 2 1109
+
+ .loc 2 1109
+
+ subq $16, $5, $16
+ .loc 2 1109
+
+ addq $17, -1, $17
+ br $31, $101
+$100:
+ .loc 2 1109
+
+ .loc 2 1109
+
+ subq $16, $5, $16
+ .loc 2 1109
+
+$101:
+ .loc 2 1109
+
+ cmpult $1, $17, $25
+ bne $25, $99
+ subq $17, $1, $27
+ bne $27, $102
+ cmpult $7, $16, $24
+ bne $24, $99
+$102:
+ .loc 2 1113
+ # 1110 }
+ # 1111
+ # 1112 /* Subtract ph:pl from rh:rl; we know rh will be 0 */
+ # 1113 rl -= pl;
+ subq $7, $16, $7
+ .loc 2 1114
+ # 1114 *qq |= qa;
+ ldq $23, 0($10)
+ or $23, $3, $22
+ stq $22, 0($10)
+ bne $11, $92
+$103:
+ .loc 2 1118
+ # 1115 }
+ # 1116
+ # 1117 /* Denormalize dividend */
+ # 1118 if (k != 0) {
+ ldl $25, 176($sp)
+ beq $25, $106
+ .loc 2 1118
+
+ .loc 2 1119
+ # 1119 if((qq > nn) && (qq < &nn[orig_nl])) {
+ cmpult $12, $10, $27
+ beq $27, $104
+ ldq $19, 168($sp)
+ s8addq $19, $12, $24
+ cmpult $10, $24, $23
+ beq $23, $104
+ .loc 2 1119
+
+ .loc 2 1121
+ # 1120 /* Overlap between qq and nn. Care of *qq! */
+ # 1121 orig_nl = (qq - nn);
+ .loc 2 1122
+ # 1122 BnnShiftRight (nn, orig_nl, k);
+ bis $12, $12, $16
+ subq $10, $12, $17
+ sra $17, 3, $17
+ bis $25, $25, $18
+ stq $17, 88($sp)
+ stq $7, 152($sp)
+ .livereg 0x0001E002,0x00000000
+ jsr $26, BnnShiftRight
+ ldgp $gp, 0($26)
+ ldq $17, 88($sp)
+ ldq $7, 152($sp)
+ .loc 2 1123
+ # 1123 nn[orig_nl - 1] = prev_qq;
+ ldq $22, 104($sp)
+ addq $17, -1, $27
+ s8addq $27, $12, $24
+ stq $22, 0($24)
+ br $31, $106
+$104:
+ ldq $19, 168($sp)
+ .loc 2 1124
+ # 1124 } else if(qq == nn) {
+ subq $10, $12, $23
+ bne $23, $105
+ .loc 2 1124
+
+ .loc 2 1125
+ # 1125 BnnShiftRight(&nn[orig_nl - 1], 1, k);
+ addq $19, -1, $25
+ s8addq $25, $12, $16
+ ldiq $17, 1
+ ldl $18, 176($sp)
+ stq $7, 152($sp)
+ .livereg 0x0001E002,0x00000000
+ jsr $26, BnnShiftRight
+ ldgp $gp, 0($26)
+ ldq $7, 152($sp)
+ br $31, $106
+$105:
+ .loc 2 1126
+ # 1126 } else {
+ .loc 2 1127
+ # 1127 BnnShiftRight (nn, orig_nl, k);
+ bis $12, $12, $16
+ bis $19, $19, $17
+ ldl $18, 176($sp)
+ stq $7, 152($sp)
+ .livereg 0x0001E002,0x00000000
+ jsr $26, BnnShiftRight
+ ldgp $gp, 0($26)
+ ldq $7, 152($sp)
+$106:
+ .loc 2 1129
+ # 1128 } }
+ # 1129 return (rl >> k);
+ ldl $27, 176($sp)
+ srl $7, $27, $0
+ .livereg 0xFC7F0002,0x3FC00000
+ ldq $26, 0($sp)
+ ldq $9, 8($sp)
+ ldq $10, 16($sp)
+ ldq $11, 24($sp)
+ ldq $12, 32($sp)
+ lda $sp, 240($sp)
+ ret $31, ($26), 1
+ .end BnnDivideDigit
diff --git a/otherlibs/num/bignum/s/hpKerN.s b/otherlibs/num/bignum/s/hpKerN.s
new file mode 100644
index 000000000..f6d53f37e
--- /dev/null
+++ b/otherlibs/num/bignum/s/hpKerN.s
@@ -0,0 +1,814 @@
+; Copyright Digital Equipment Corporation & INRIA 1988, 1989
+;
+; KerN for the HP 9000 600/700/800 (PA-RISC 1.1 only)
+; LERCIER Reynald (april 1993)
+;
+
+
+
+ .SPACE $TEXT, SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnSetToZero
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn, nl)
+ comb,<= %arg1, %r0, L$BSTZ0 ; if (nl <= 0) goto L$BSTZ0
+ nop
+L$BSTZ1 addibf,<= -1, %arg1, L$BSTZ1 ; while (nl-->0)
+ stwm %r0, 4(0, %arg0) ; { *(nn++)=0 }
+L$BSTZ0 bv,n %r0(%r2) ; return
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnAssign
+ .PROC
+ .CALLINFO
+ .ENTRY ; (mm, nn, nl)
+ comb,<= %arg2, %r0, L$BAG0 ; if (nl <= 0) goto L$BAG0
+ nop
+ comb,>>=,n %arg0, %arg1, L$BAG1 ; if (mm>=nn) goto L$BAG1
+L$BAG2 ldwm 4(%arg1), %r19 ; X=*(nn++)
+ addibf,<= -1, %arg2, L$BAG2 ; if ((nl--)>=0) goto L$BAG2
+ stwm %r19, 4(%arg0) ; *(mm++)=X
+ bv,n %r0(%r2) ; return
+L$BAG1 comb,=,n %arg0, %arg1, L$BAG0 ; if (mm==nn) goto L$BAG0
+ shd %arg2, %r0, 30, %r19 ; X = nl <<2
+ add %arg0, %r19, %arg0 ; mm+=X
+ add %arg1, %r19, %arg1 ; nn+=X
+L$BAG3 ldwm -4(%arg1), %r19 ; X=*(--nn)
+ addibf,<= -1, %arg2, L$BAG3 ; if (--nl>=0) goto L$BAG3
+ stwm %r19, -4(%arg0) ; *(--mm)=X
+L$BAG0 bv,n %r0(%r2) ; return
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnSetDigit
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn, d)
+ bv %r0(%r2) ; return
+ .EXIT
+ stws %arg1, 0(0, %arg0) ; *nn = d
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnGetDigit
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn)
+ bv %r0(%r2)
+ .EXIT
+ ldws 0(0, %arg0), %ret0 ; return (*nn)
+ .PROCEND
+
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnNumDigits
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn, nl)
+ comb,<=,n %arg1, %r0, L$BND0 ; if (nl <= 0) goto L$BND0
+ shd %arg1, %r0, 30, %r19 ; X = nl<<2
+ add %arg0, %r19, %arg0 ; nn+=nl
+ ldwm -4(%arg0), %r19 ; X=*(--nn)
+L$BND2 comb,<> %r19, %r0, L$BND1 ; if (X != 0) goto L$BND1
+ nop
+ addibf,<= -1, %arg1, L$BND2 ; if ((--nl)>0) goto L$BND2
+ ldwm -4(%arg0), %r19 ; X=*(--nn)
+L$BND0 bv %r0(%r2) ; return(1)
+ ldi 1, %ret0
+L$BND1 bv %r0(%r2) ; return(nl)
+ copy %arg1, %ret0
+ .EXIT
+ .PROCEND
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnNumLeadingZeroBitsInDigit
+ .PROC
+ .CALLINFO
+ .ENTRY ; (d)
+ ldi 0, %ret0 ; p=0
+ comb,<>,n %r0, %arg0, L$BLZ1 ; if (d<>0) goto L$BLZ1
+ bv %r0(%r2) ; return(32)
+ ldi 32, %ret0
+L$BLZ2 addi 1, %ret0, %ret0 ; p++
+L$BLZ1 comib,< 0, %arg0, L$BLZ2 ; if (d>0) goto L$BLZ2;
+ shd %arg0, %r0, 31, %arg0 ; d<<=1
+ bv,n %r0(%r2) ; return(p)
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnDoesDigitFitInWord
+ .PROC
+ .CALLINFO
+ .ENTRY
+ bv %r0(%r2) ; return
+ ldi 1, %ret0
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnIsDigitZero
+ .PROC
+ .CALLINFO
+ .ENTRY ; (d)
+ ldi 1, %ret0
+ or,= %r0, %arg0, %r0 ; if (d==0) return(1)
+ ldi 0, %ret0 ; return(0)
+ bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnIsDigitNormalized
+ .PROC
+ .CALLINFO
+ .ENTRY
+ bv %r0(%r2) ; return
+ extru %arg0, 0, 1, %ret0 ; the leftmost bit
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnIsDigitOdd
+ .PROC
+ .CALLINFO
+ .ENTRY
+ bv %r0(%r2) ; return
+ extru %arg0, 31, 1, %ret0 ; the rightmost bit
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnCompareDigits
+ .PROC
+ .CALLINFO
+ .ENTRY ; (d1, d2)
+ comb,= %arg0, %arg1, L$BCD0 ; if (d1==d2) goto L$BCD0
+ ldi 0, %ret0 ; return(0)
+ comb,>> %arg0, %arg1, L$BCD0 ; if (d1>d2) goto L$BCD0
+ ldi 1, %ret0 ; return(1)
+ ldi -1, %ret0 ; return(-1)
+L$BCD0 bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnComplement
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn, nl)
+ comb,<=,n %arg1, %r0, L$BCM0 ; if (nl <= 0) goto L$BCM0
+ ldi -1, %ret0 ; cste=-1
+L$BCM1 ldw (%arg0), %r19 ; X=*(nn)
+ xor %r19, %ret0, %r19 ; X ^= cste
+ addibf,<= -1, %arg1, L$BCM1 ; if ((--nl)>=0) goto L$BCM1
+ stwm %r19, 4(%arg0) ; *(nn++)=X
+L$BCM0 bv,n %r0(%r2) ; return
+ .EXIT
+ .PROCEND
+
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnAndDigits
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn, d)
+ ldw (%arg0), %r19 ; X=*nn
+ and %r19, %arg1, %r19 ; X &= d
+ stw %r19, (%arg0) ; *nn=X
+ bv,n %r0(%r2) ; return
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnOrDigits
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn, d)
+ ldw (%arg0), %r19 ; X=*nn
+ or %r19, %arg1, %r19 ; X &= d
+ stw %r19, (%arg0) ; *nn=X
+ bv,n %r0(%r2) ; return
+ .EXIT
+ .PROCEND
+
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnXorDigits
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn, d)
+ ldw (%arg0), %r19 ; X=*nn
+ xor %r19, %arg1, %r19 ; X &= d
+ stw %r19, (%arg0) ; *nn=X
+ bv,n %r0(%r2) ; return
+ .EXIT
+ .PROCEND
+
+
+; convention for BnnShiftLeft, BnnShiftRight
+nn1 .REG %arg0
+nl1 .REG %arg1
+nbits .REG %arg2
+res .REG %ret0
+X .REG %r19
+Y .REG %r20
+Z .REG %r21
+W .REG %r22
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnShiftLeft
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn1, nl1, nbits)
+ ldi 0, res ; res=0
+ comb,= nbits, %r0, L$BSL0 ; if (nbits = 0) goto L$BSL0
+ nop
+ comb,<= nl1, %r0, L$BSL0 ; if (nl1 <= 0) goto L$BSL0
+ nop
+ subi 32, nbits, nbits ; nbits-=32
+ mtsar nbits
+L$BSL1 ldw (nn1), X ; X=*(nn1)
+ vshd X, %r0, Y ; Y= X<<nbits
+ or Y, res, Y ; Y|=res
+ vshd %r0, X, res ; res= X>>nbits
+ addibf,<= -1, nl1, L$BSL1 ; if ((nl1--)>=0) goto L$BSL1
+ stwm Y, 4(nn1) ; *(nn1++)=Y
+L$BSL0 bv,n %r0(%r2) ; return
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnShiftRight
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn1, nl1, nbits)
+ ldi 0, res ; res=0
+ comb,= nbits, %r0, L$BSR0 ; if (nbits = 0) goto L$BSR0
+ nop
+ comb,<=,n nl1, %r0, L$BSR0 ; if (nl1 <= 0) goto L$BSR0
+ mtsar nbits
+ shd nl1, %r0, 30, Y ; Y=nl1<<2
+ add Y, nn1, nn1 ; nn1+=Y
+L$BSR1 ldwm -4(nn1), X ; X=*(--nn1)
+ vshd %r0, X, Y ; Y= X>>nbits
+ or Y, res, Y ; Y|=res
+ vshd X, %r0, res ; res= X<<rnbits
+ addibf,<= -1, nl1, L$BSR1 ; if ((nl1--)>=0) goto L$BSR1
+ stw Y, (nn1) ; *(nn1)=Y
+L$BSR0 bv,n %r0(%r2) ; return
+ .EXIT
+ .PROCEND
+
+; convention for BnnAddCarry, BnnSubtractBorrow
+carryin .REG %arg2
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnAddCarry
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn1, nl1, carryin)
+ comb,= carryin, %r0, L$BAC0 ; if (carryin == 0) goto L$BAC0
+ nop
+ comb,<=,n nl1, %r0, L$BAC1 ; if (nl1<= 0) goto L$BAC1
+ ldw (nn1), X ; X=*(nn1)
+L$BAC2 addi,UV 1, X, X ; X++
+ b L$BAC0 ; if (X<2^32) goto L$BAC0
+ stwm X, 4(nn1) ; *(nn1++)=X
+ addibf,<=,n -1, nl1, L$BAC2 ; if ((nl1--)>=0) goto L$BAC2
+ ldw (nn1), X ; X=*(nn1)
+L$BAC1 bv %r0(%r2) ; return(1)
+ ldi 1, res
+L$BAC0 bv %r0(%r2) ; return(0)
+ ldi 0, res
+ .EXIT
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnSubtractBorrow
+ .PROC
+ .CALLINFO
+ .ENTRY ; (nn1, nl1, d)
+ comib,= 1, carryin, L$BSB1 ; if (carryin == 1) goto L$BSB1
+ nop
+ comb,<=,n nl1, %r0, L$BSB0 ; if (nl1<= 0) goto L$BSB0
+ ldw (nn1), X ; X=*(nn1)
+L$BSB2 addi,nuv -1, X, X ; X--
+ b L$BSB1 ; if (X!=-1) goto L$BSB1
+ stwm X, 4(nn1) ; *(nn1++)=X
+ addibf,<=,n -1, nl1, L$BSB2 ; if ((nl1--)>=0) goto L$BSB2
+ ldw (nn1), X ; X=*(nn1)
+L$BSB0 bv %r0(%r2) ; return(0)
+ ldi 0, res
+L$BSB1 bv %r0(%r2) ; return(1)
+ ldi 1, res
+ .EXIT
+ .PROCEND
+
+; convention for BnnAdd, BnnSubtract
+mm2 .REG %arg0
+ml2 .REG %arg1
+nn2 .REG %arg2
+nl2 .REG %arg3
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnAdd
+ .PROC
+ .CALLINFO
+ .ENTER ; (mm2, ml2, nn2, nl2, carryin)
+ sub ml2, nl2, ml2 ; ml2 -= nl2
+ ldw -52(0, %r30), res ; res=carryin
+ comb,=,n nl2, %r0, L$BADD2 ; if (nl2==0) goto L$BADD2
+L$BADD1 ldwm 4(nn2), X ; X = *(nn2++)
+ ldw (mm2), Y ; Y = *(mm2)
+ copy res, Z ; Z=res
+ ldi 0, res ; res=0
+ add,nuv Y, Z, Y ; Y+=Z;
+ ldi 1, res ; if (Y>=2^32) res=1 Y-=2^32
+ add,nuv Y, X, Y ; Y+=X
+ ldi 1, res ; if (Y>=2^32) res=1 Y-=2^32
+ addibf,<= -1, nl2, L$BADD1 ; if ((nl2--)>=0) goto L$BADD1
+ stwm Y, 4(mm2) ; *(mm2++)=Y
+L$BADD2 comclr,<> res, %r0, %r0 ; if (res<>0) skip next operation
+ b,n L$BADD4 ; return(0)
+ comclr,<> ml2, %r0, %r0 ; if (ml2<>0) skip next operation
+ b L$BADD5 ; return(1)
+ ldw (mm2), X ; X=*mm2
+L$BADD3 addi,uv 1, X, X ; X++
+ b L$BADD4 ; if (X<2^32) goto L$BADD4
+ stwm X, 4(mm2) ; *(mm2++)=X
+ addibf,<= -1, ml2, L$BADD3 ; if ((ml2--)>=0) goto L$BADD3
+ ldw (mm2), X ; X=*mm2
+ b,n L$BADD5 ; return(1)
+L$BADD4 ldi 0, res
+L$BADD5 .LEAVE
+ .PROCEND
+
+
+ .SPACE $TEXT
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnSubtract
+ .PROC
+ .CALLINFO
+ .ENTRY ; (mm2, ml2, nn2, nl2, carryin)
+ sub ml2, nl2, ml2 ; ml2 -= nl2
+ ldw -52(0, %r30), res ; res=carryin
+ subi 1, res, res ; res=1-res
+ comb,=,n nl2, %r0, L$BS2 ; if (nl2==0) goto L$BS2
+L$BS1 ldwm 4(nn2), X ; X = *(nn2++)
+ ldw (mm2), Y ; Y = *(mm2)
+ copy res, Z ; Z=res
+ ldi 0, res ; res=0
+ sub,>>= Y, Z, Y ; Y-=Z;
+ ldi 1, res ; if (Y<=0) res=1 Y+=2^32
+ sub,>>= Y, X, Y ; Y-=X
+ ldi 1, res ; if (Y<=0) res=1 Y+=2^32
+ addibf,<= -1, nl2, L$BS1 ; if ((nl2--)>=0) goto L$BS1
+ stwm Y, 4(mm2) ; *(mm2++)=Y
+L$BS2 comb,= res, %r0, L$BS4 ; if (res==0) goto L$BS4
+ nop
+ comb,=,n ml2, %r0, L$BS5 ; if (ml2==0) goto L$BS5
+ ldw (mm2), X ; X=*mm2
+L$BS3 addi,nuv -1, X, X ; X--
+ b L$BS4 ; if (X!=-1) goto L$BS4
+ stwm X, 4(mm2) ; *(mm2++)=X
+ addibf,<=,n -1, ml2, L$BS3 ; if ((ml2--)>=0) goto L$BS3
+ ldw (mm2), X ; X=*mm2
+L$BS5 bv %r0(%r2) ; return(0)
+ ldi 0, res
+L$BS4 bv %r0(%r2) ; return(1)
+ ldi 1,res
+
+ .EXIT
+ .PROCEND
+
+
+; conventions for BnnMultiplyDigit
+pp .REG %arg0
+pl1 .REG %arg1
+mm .REG %arg2
+ml .REG %arg3
+X1 .REG %r22
+X3 .REG %r1
+dm .REG %r29
+fLd .REG %fr5L
+fHd .REG %fr5R
+fLm .REG %fr7L
+fHm .REG %fr8L
+
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnMultiplyDigit
+ .PROC
+ .CALLINFO CALLER, FRAME=8, SAVE_RP
+ .ENTER ; (pp, pl1, mm, ml, dm)
+
+ ldw -108(0, %r30), dm ; dm
+ comb,= dm, %r0, L$BMD7 ; if (dm==0) goto L$BMD7
+ nop
+ comib,<>,n 1, dm, L$BMD2 ; if (dm<>1) goto L$BMD2
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR ;in=24,25,26;out=28;
+ bl BnnAdd, %r2 ; return(BnnAdd(pp, pl1, mm, ml, 0))
+ stw %r0, -52(0, %r30)
+ b,n L$BMD8
+
+L$BMD2 comb,= ml, %r0, L$BMD7 ; if (ml==0) goto L$BMD7
+ nop
+ sub pl1, ml, pl1 ; pl1-=ml
+
+ ldo -52(%r30), %r21
+ extru dm, 31, 16, X ; Ld=dm & (2^16-1);
+ stws X, 0(0, %r21)
+ fldws 0(0, %r21), fLd
+ extru dm, 15, 16, X ; Hd=dm>>16;
+ stws X, 0(0, %r21)
+ fldws 0(0, %r21), fHd
+ ldi 0, dm ; dm=0
+
+L$BMD3 ldwm 4(mm), X1 ; X1=*(mm++)
+ extru X1, 31, 16, X ; Lm=X1 & (2^16-1)
+ stws X, 0(0, %r21)
+ fldws 0(0, %r21), fLm
+ extru X1, 15, 16, X ; Hm=X1>>16
+ stws X, 0(0, %r21)
+ fldws 0(0, %r21), fHm
+
+ xmpyu fHm, fHd, %fr4
+ fstws %fr4R, 0(0, %r21)
+ ldws 0(0, %r21), X3
+
+ xmpyu fLm, fHd, %fr4
+ fstws %fr4R, -4(0, %r21)
+
+ xmpyu fHm, fLd, %fr4
+ fstws %fr4R, 0(0, %r21)
+ ldws 0(0, %r21), X1
+
+ xmpyu fLm, fLd, %fr4
+ fstws %fr4R, 0(0, %r21)
+ ldws 0(0, %r21), X
+
+ add,nuv X, dm, dm
+ ldo 1(X3), X3
+ ldws -4(0, %r21), X
+ add,nuv X1, X, X1 ; X1+=X
+ addil L%(65536), X3 ; if overflow X3+=2^16;
+ extru X1, 15, 16, X ; X = X1 >> 16
+ add X3, X, X3 ; X3+=X
+ zdep X1, 15, 16, X1 ; X1 =<< 16
+ add,nuv dm, X1, dm ; dm+=X1
+ ldo 1(X3), X3 ; if overflow X3++;
+ ldws (pp), X ; X=*(pp)
+ add,nuv X, dm, dm ; dm+=X;
+ ldo 1(X3), X3 ; if overflow X3++;
+ stwm dm, 4(pp) ; *(pp++)=dm
+ addib,>,n -1, ml, L$BMD3 ; if ((--ml)>0) goto L$BMD3
+ copy X3, dm ; dm=X3
+
+ ldo -1(pl1), pl1 ; pl1--
+ ldi 0, dm ; dm=0
+ ldw (pp), X ; X=*pp
+ add,nuv X, X3, X ; X+= X3
+ ldi 1, dm ; if overflow dm=1;
+ comb,= dm, %r0, L$BMD7 ; if (dm==0) goto L$BMD7
+ stwm X, 4(pp) ; *(pp++)=X
+ comb,=,n pl1, %r0, L$BMD9 ; if (pl1==0) goto L$BMD9
+ ldw (pp), X
+L$BMD4 addi,uv 1, X, X ; X++
+ b L$BMD7 ; if no overflow goto L$BMD7
+ stwm X, 4(pp) ; *(pp++)=X
+ addib,>,n -1, pl1, L$BMD4 ; if ((--pl1)>0) goto L$BMD4
+ ldw (pp), X ; X=*(pp)
+L$BMD9 b L$BMD8 ; return(1)
+ ldi 1, res
+L$BMD7 ldi 0, res ; return(0)
+L$BMD8 .LEAVE
+ .PROCEND
+
+; conventions for BnnDivideDigit
+qq .REG %r3
+nn .REG %r4
+nl .REG %r5
+dd .REG %r6
+ch .REG %r7
+cl .REG %r8
+k .REG %r9
+f_qq .REG %r10
+o_nl .REG %r11
+rh .REG %r12
+rl .REG %r13
+ph .REG %r14
+pl .REG %r15
+qa .REG %r16
+fcl .REG %fr5L
+fch .REG %fr6L
+fqa .REG %fr7L
+
+
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+BnnDivideDigit
+ .PROC
+ .CALLINFO CALLER, FRAME=0, ENTRY_GR=16, SAVE_RP
+ .ENTER ; (qq, nn, nl, dd)
+ copy %arg0, qq ; qq=%arg0
+ copy %arg1, nn ; nn=%arg1
+ copy %arg2, nl ; nl=%arg2
+ copy %arg3, dd ; dd=%arg3
+ .CALL ;in=%arg0 ;out=%ret0 ; res=BnnNumLeadingZeroBitsInDigit(dd)
+ bl BnnNumLeadingZeroBitsInDigit, %r2
+ copy dd, %arg0
+ comib,= 0, res, L$BDD1 ; k=res; if (k==0) goto L$BDD1
+ copy res, k
+ ldw (qq), f_qq ; f_qq=*qq
+ copy nl, o_nl ; o_nl=nl
+ subi 32, k, X
+ mtsar X
+ vshd dd, %r0, dd ; dd<<=k
+ copy nn, %arg0
+ copy nl, %arg1
+ .CALL ;in=%arg0, %arg1, %arg2 ; out=%ret0
+ bl BnnShiftLeft, %r2 ; BnnShiftLeft(nn, nl, k)
+ copy k, %arg2
+
+L$BDD1 shd nl, %r0, 30, X ; X=nl<<2
+ add nn, X, nn ; nn+=nl
+ addi -1, nl, nl ; nl--
+ shd nl, %r0, 30, X ; X=nl<<2
+ add qq, X, qq ; qq+=nl
+ extru dd, 15, 16, ch ; ch=dd>>16
+ extru dd, 31, 16, cl ; cl=dd & (2^16-1)
+ ldo -48(%r30), %r21
+ stws cl, 0(0, %r21)
+ fldws 0(0, %r21), fcl
+ stws ch, 0(0, %r21)
+ fldws 0(0, %r21), fch
+ comib,= 0, nl, L$BDD3 ; if (nl==0) goto L$BDD3
+ ldwm -4(nn), rl ; rl=*(--nn)
+
+L$BDD2 copy rl, rh ; rh=rl
+ ldwm -4(nn), rl ; rl=*(--nn)
+
+ copy rh, %arg0
+ .CALL ;in=25,26;out=29; (MILLICALL)
+ bl $$divU,%r31 ; %r29=rh/ch
+ copy ch, %arg1
+ copy %r29, qa ; qa=%r29
+
+ stws qa, 0(0, %r21)
+ fldws 0(0, %r21), fqa
+ xmpyu fcl, fqa, %fr4
+ fstws %fr4R, 0(0, %r21)
+ ldws 0(0, %r21), pl
+ xmpyu fch, fqa, %fr4
+ fstws %fr4R, 0(0, %r21)
+ ldws 0(0, %r21), %r29
+
+ shd %r0, pl, 16, X ; X=pl>>16
+ add %r29, X, ph ; ph=X+%r29
+ comb,>> ph, rh, L$BDD84 ; if (ph>rh) goto L$BDD84
+ shd pl, %r0, 16, pl ; pl<<=16
+ comb,<> ph, rh, L$BDD88 ; if (ph!=rh) goto L$BDD88
+ nop
+ comb,<<=,n pl, rl, L$BDD88 ; if (pl<=rl) goto L$BDD88
+L$BDD84 shd cl, %r0, 16, X ; X = cl << 16
+L$BDD85 comb,<<= X, pl, L$BDD86 ; if (X<=pl) goto L$BDD86
+ addi -1, qa, qa ; qa--
+ addi -1, ph, ph ; ph--
+L$BDD86 sub pl, X, pl ; pl-=X
+ sub ph, ch, ph ; ph-=ch
+ comb,>> ph, rh, L$BDD85 ; if (ph>rh) goto L$BDD85
+ nop
+ comb,<> ph, rh, L$BDD88 ; if (ph!=rh) goto L$BDD88
+ nop
+ comb,>> pl, rl, L$BDD85 ; if (pl>rl) goto L$BDD85
+ nop
+L$BDD88 comb,<<=,n pl, rl, L$BDD89 ; if (pl<=rl) goto L$BDD89
+ addi -1, rh, rh ; rh--
+L$BDD89 sub rl, pl, rl ; rl-=pl
+ sub rh, ph, rh ; rh-=ph
+ shd qa, %r0, 16, X ; X=qa<<16
+ stwm X, -4(qq) ; *(--qq)=X
+ shd rh, %r0, 16, X ; X=rh<<16
+ shd %r0, rl, 16, qa ; qa=rl>>16
+ or qa, X, qa ; qa |=X
+ copy qa, %arg0
+ .CALL ;in=25,26;out=29; (MILLICALL)
+ bl $$divU,%r31 ; %r29=qa/ch
+ copy ch, %arg1
+ copy %r29, qa ; qa=%r29
+
+ stws qa, 0(0, %r21)
+ fldws 0(0, %r21), fqa
+ xmpyu fcl, fqa, %fr4
+ fstws %fr4R, 0(0, %r21)
+ ldws 0(0, %r21), pl
+ xmpyu fch, fqa, %fr4
+ fstws %fr4R, 0(0, %r21)
+ ldws 0(0, %r21), %r29
+
+ shd %r0, pl, 16, X ; X=pl>>16
+ add %r29, X, ph ; ph+=X
+ extru pl, 31, 16, pl ; pl &= (2^16-1)
+ shd ph, %r0, 16, X ; X = ph<<16
+ shd %r0, ph, 16, ph ; ph >>=16
+ comb,>> ph, rh, L$BDD41 ; if (ph>rh) goto L$BDD41
+ or X, pl, pl ; pl |= X
+ comb,<> ph, rh, L$BDD44 ; if (ph!=rh) goto L$BDD44
+ nop
+ comb,<<= pl, rl, L$BDD44 ; if (pl<=rl) goto L$BDD44
+ nop
+L$BDD41 comb,<<= dd, pl, L$BDD42 ; if (dd<=pl) goto L$BDD42
+ addi -1, qa, qa ; qa--
+ addi -1, ph, ph ; ph--
+L$BDD42 comb,>> ph, rh, L$BDD41 ; if (ph>rh) goto L$BDD4
+ sub pl, dd, pl ; pl-=dd
+ comb,<> ph, rh, L$BDD44 ; if (ph!=rh) goto L$BDD44
+ nop
+ comb,>>,n pl, rl, L$BDD41 ; if (pl>rl) goto L$BDD41
+ nop
+L$BDD44 sub rl, pl, rl ; rl-=pl
+ ldw (qq), X ; X=*qq
+ or X, qa, X ; X |= qa
+ addib,> -1, nl, L$BDD2 ; if ((--nl)>0) goto L$BDD2
+ stws X, (qq) ; *qq=X
+
+
+L$BDD3 comib,= 0, k, L$BDD5 ; if (k==0) goto L$BDD5
+ nop
+ comb,<<,n qq, nn, L$BDD31 ; if (qq<nn) goto L$BDD31
+ shd o_nl, %r0, 30, Y
+ add nn, Y, X ; X=nn+o_nl
+ comb,<<= X, qq, L$BDD31 ; if (X<=qq) goto L$BDD31
+ nop
+ sub qq, nn, o_nl ; o_nl=qq-nn
+ shd %r0, o_nl, 2, o_nl ; o_nl>>=2
+ ldw (qq), W ; W=*qq
+ stws f_qq, (qq) ; *qq=f_qq
+ copy nn, %arg0
+ addi 1, o_nl, %arg1 ; %arg1=o_nl+1
+ .CALL ;in=%arg0, %arg1, %arg2 ;out=%ret0
+ bl BnnShiftRight, %r2 ; BnnShiftRight(nn, o_nl, k)
+ copy k, %arg2
+ b L$BDD5
+ stws W, (qq) ; *qq=W
+L$BDD31 comb,<>,n qq, nn, L$BDD32 ; if (qq<>nn) goto L$BDD32
+ addi -1, o_nl, o_nl ; o_nl--
+ shd o_nl, %r0, 30, o_nl ; o_nl<<=2
+ add nn, o_nl, nn ; nn+=o_nl
+ ldi 1, o_nl
+L$BDD32 copy nn, %arg0
+ copy o_nl, %arg1
+ .CALL ;in=%arg0, %arg1, %arg2 ;out=%ret0
+ bl BnnShiftRight, %r2 ; BnnShiftRight(nn, o_nl, k)
+ copy k, %arg2
+
+L$BDD5 mtsar k
+ vshd %r0, rl, res ; return(rl>>k)
+L$BDD6 .LEAVE
+ .PROCEND
+
+
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44,SORT=16
+$THIS_LIT$
+
+ .SUBSPA $LITSTATIC$,QUAD=0,ALIGN=8,ACCESS=44,SORT=16
+$THIS_LITSTATIC$
+
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SUBSPA $CODE$
+ .SPACE $PRIVATE$,SORT=16
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31,SORT=16
+$THIS_DATA$
+
+ .SUBSPA $SHORTDATA$,QUAD=1,ALIGN=8,ACCESS=31,SORT=16
+$THIS_SHORTDATA$
+
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+$THIS_BSS$
+
+ .SUBSPA $SHORTBSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=80
+$THIS_SHORTBSS$
+
+ .SUBSPA $STATICDATA$,QUAD=1,ALIGN=8,ACCESS=31,SORT=16
+$THIS_STATICDATA$
+ .ALIGN 4
+ .STRINGZ "@(#)KerN.c: copyright Digital Equipment Corporation & INRIA 1988, 1989\n"
+ .SUBSPA $SHORTSTATICDATA$,QUAD=1,ALIGN=8,ACCESS=31,SORT=24
+$THIS_SHORTSTATICDATA$
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ .EXPORT BnnSetToZero,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR
+ .IMPORT bzero,CODE
+ .SUBSPA $CODE$
+ .EXPORT BnnAssign,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR
+ .IMPORT bcopy,CODE
+ .SUBSPA $CODE$
+ .EXPORT BnnSetDigit,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnGetDigit,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnNumDigits,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnNumLeadingZeroBitsInDigit,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnDoesDigitFitInWord,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnIsDigitZero,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnIsDigitNormalized,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnIsDigitOdd,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnCompareDigits,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnComplement,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnAndDigits,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnOrDigits,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnXorDigits,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnShiftLeft,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnShiftRight,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnAddCarry,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnAdd,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnSubtractBorrow,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnSubtract,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+ .SUBSPA $CODE$
+ .EXPORT BnnMultiplyDigit,ENTRY,PRIV_LEV=0,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+ .IMPORT $$mulU,MILLICODE
+ .SUBSPA $CODE$
+ .EXPORT BnnDivideDigit,ENTRY,PRIV_LEV=0,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+ .IMPORT $$divU,MILLICODE
+ .IMPORT $$remU,MILLICODE
+ .END
diff --git a/otherlibs/num/bignum/s/i960KerN.s b/otherlibs/num/bignum/s/i960KerN.s
new file mode 100644
index 000000000..2a23b6489
--- /dev/null
+++ b/otherlibs/num/bignum/s/i960KerN.s
@@ -0,0 +1,928 @@
+/*
+** (c) Copyright 1989 Digital Equipment Corporation
+**
+** Last modified_on Mon Apr 9 20:18:11 GMT+2:00 1990 by shand
+** modified_on Tue Apr 3 19:48:27 GMT+2:00 1990 by sills@notok.enet.dec.com
+**
+** KerN for 80960KA
+**
+** Author: Glenn Sills
+** Date: 1.1
+** Version: 1
+**
+*/
+
+
+/*
+** BnnSetToZero(nn, nl)
+** BigNum nn;
+** int nl;
+**
+** Set all of the digits specified by nn length nl to zero
+**
+** nn -> g0
+** nl -> g1
+*/
+
+.file "kern.s"
+.text
+.align 2
+.globl _BnnSetToZero
+.leafproc _BnnSetToZero
+
+_BnnSetToZero:
+ mov g14,g7 /* Preserve the return address */
+ ldconst 0,g14 /* Must always load g14 with 0 for*/
+ /* branch and link procs */
+
+ cmpobe 0,g1,.bstzxt /* if (!nl) return */
+
+ subo 1,g1,g1
+ shlo 2,g1,g1 /* Do some pointer arithmetic */
+ addc g0,g1,g1 /* nl = nn + nl*byte_per_digit */
+ /* (I happen to know that */
+ /* bytes_per_digit is 4 on 960 */
+
+.bstzlp: /* Do { */
+ ldconst 0,g3
+ st g3,(g0) /* *nn = 0 */
+ addc 4,g0,g0 /* } while (++nn <= nl) */
+ cmpoble g0,g1,.bstzlp
+
+.bstzxt:
+ bx (g7) /* Return voidly */
+
+/*
+** void BnnAssign(mm, nn, nl)
+** Bignum mm, nn;
+** int nl;
+**
+** Copies nn to mm. We copy from back to front to defend against
+** over lapping bignums.
+**
+** mm -> g0
+** nn -> g1
+** nl -> g2
+*/
+
+.globl _BnnAssign
+.leafproc _BnnAssign
+
+_BnnAssign:
+ mov g14,g7 /* Mandatory saving of g14 */
+ cmpo 0,g2
+ mov 0,g14
+ be .baexit
+ subo 1,g2,g2 /* Prepare for some pointer */
+ cmpo g0,g1
+ shlo 2,g2,g2 /* Arithmetic */
+ be .baexit /* if (mm == nn) exit */
+ /* if (mm >> nn) */
+ bg .balast1 /* then */
+ /* Copy from last to first */
+
+ addo g2,g1,g2
+
+.ba1last:
+ ld (g1),g3
+ addo 4,g1,g1 /* *mm++ == *nn++ */
+ st g3,(g0)
+ addo 4,g0,g0
+ cmpo g1,g2
+ ble .ba1last /* while (nl > 0) */
+ bx (g7)
+
+.balast1:
+ mov g1,g4
+ addo g2,g0,g0
+ addo g2,g1,g1 /* nn += nl */
+
+.baloop:
+ ld (g1),g3
+ subo 4,g1,g1 /* *mm-- == *nn-- */
+ st g3,(g0)
+ subo 4,g0,g0
+ cmpo g1,g4
+ bge .baloop
+
+.baexit:
+ bx (g7) /* Return voidly */
+
+
+/*
+** void BnnSetDigit(nn,d)
+** BigNum nn;
+** int d;
+**
+** Sets a single digit of N to the passed value
+**
+** g0 -> nn
+** g1 -> d
+**
+*/
+
+.globl _BnnSetDigit
+.leafproc _BnnSetDigit
+.align 2
+
+_BnnSetDigit:
+ mov g14,g7 /* Mandatory saving of g14 */
+ ldconst 0,g14
+
+ st g1,(g0) /* *nn = d */
+ bx (g7) /* Return ustedes */
+
+
+/*
+** BigNumDigit BnnGetDigit (nn)
+** BigNum nn;
+**
+** Returns digit pointed to by nn
+**
+** g0 -> nn
+*/
+
+.globl _BnnGetDigit
+.leafproc _BnnGetDigit
+.align 2
+
+_BnnGetDigit:
+ mov g14,g7
+ ldconst 0,g14
+
+ ld (g0),g0
+ bx (g7)
+
+
+/*
+** BigNumLength BnnNumDigits(nn, nl)
+** Bignum nn;
+** int nl;
+**
+** Returns the total number of digits in nn not counting leading
+** zeros.
+**
+** g0 -> nn
+** g1 -> nl
+**
+*/
+
+.globl _BnnNumDigits
+.leafproc _BnnNumDigits
+
+_BnnNumDigits:
+ mov g14,g7
+ ldconst 0,g14
+
+
+.bndnot0:
+ subo 1,g1,g2
+ shlo 2,g2,g2
+ addo g0,g2,g0
+
+.bndloop:
+ cmpobe 0,g1,.bndret1 /* while (nl && *nn == 0) */
+ ld (g0),g3
+ cmpobne 0,g3,.bndrett /* --nl; */
+ subo 4,g0,g0
+ subo 1,g1,g1
+ b .bndloop
+
+.bndret1:
+ ldconst 1,g0 /* If nl == 0 return 1 */
+ bx (g7)
+
+.bndrett:
+ mov g1,g0
+ bx (g7)
+
+
+/*
+** BigNumDigit BnnNumLeadingZeroBitsInDigit(d)
+** BigNumDigit d;
+**
+** How many leading zero bits are there in the digit? HUH???
+**
+** g0 -> d;
+**
+*/
+
+.globl _BnnNumLeadingZeroBitsInDigit
+.leafproc _BnnNumLeadingZeroBitsInDigit
+
+_BnnNumLeadingZeroBitsInDigit:
+ mov g14,g7
+ ldconst 0,g14
+
+ scanbit g0, g1
+ bo .bzidnz
+ ldconst 32,g0
+ bx (g7)
+
+.bzidnz:
+ subo g1,31,g0
+
+ bx (g7)
+
+/*
+** Boolean BnnDoesDigitFitInWord(d)
+** BigNumDigit d;
+**
+** Returns true if the digit d can fit in BNN_WORD_SIZE bits.
+** On the 80960, it always can.
+**
+** g0 -> d
+*/
+.globl _BnnDoesDigitFitInWord
+.leafproc _BnnDoesDigitFitInWord
+
+_BnnDoesDigitFitInWord:
+
+ mov g14,g7
+ ldconst 0,g14
+
+ ldconst 1,g0
+ bx (g7)
+
+
+/*
+** Boolean BnnIsDigitZero (d)
+** BigNumDigit d;
+**
+** Returns TRUE iff digit = 0. We can do this!
+**
+**
+** g0 -> d
+**
+*/
+
+.globl _BnnIsDigitZero
+.leafproc _BnnIsDigitZero
+
+_BnnIsDigitZero:
+
+ mov g14,g7
+ ldconst 0,g14
+
+ cmpobne 0,g0, .bidz1
+ ldconst 1,g0
+ bx (g7)
+
+.bidz1:
+ ldconst 0,g0
+ bx (g7)
+
+
+
+/*
+** Boolean BnnIsDigitNormalized (d)
+** BigNumDigit d
+**
+** Returns TRUE iff Base/2 <= digit < Base
+** i.e., if digit's leading bit is 1
+**
+** g0 -> d
+*/
+
+.globl _BnnIsDigitNormalized
+.leafproc _BnnIsDigitNormalized
+
+_BnnIsDigitNormalized:
+
+ mov g14,g7
+ ldconst 0,g14
+
+ scanbit g0,g0
+ cmpobe 31,g0,.bidnt
+ ldconst 0,g0
+ bx (g7)
+
+.bidnt:
+ ldconst 1,g0
+ bx (g7)
+
+
+/*
+** Boolean BnnIsDigitOdd (d)
+** BigNumDigit d;
+**
+** Returns TRUE iff digit is odd
+**
+** g0 -> d
+*/
+
+.globl _BnnIsDigitOdd
+.leafproc _BnnIsDigitOdd
+
+_BnnIsDigitOdd:
+ mov g14,g7
+ ldconst 0, g14
+
+ and 1, g0, g0
+ bx (g7)
+
+
+/*
+** BigNumCmp BnnCompareDigits (d1, d2)
+** BigNumDigit d1, d2
+**
+** Compares digits and returns
+**
+** BNN_GREATER d1 > d2
+** BNN_EQUAL d1 == d2
+** BNN_LESS d1 < d2
+**
+** g0 -> d1
+** g1 -> d2
+*/
+
+.globl _BnnCompareDigits
+.leafproc _BnnCompareDigits
+
+_BnnCompareDigits:
+
+ mov g14,g7
+ ldconst 0,g14
+
+ cmpobe g0,g1,.bcdequal
+ bg .bcdgreater
+ ldconst -1,g0 /* BNN_LESS */
+ bx (g7)
+
+.bcdequal:
+ ldconst 0,g0 /* BNN_EQUAL */
+ bx (g7)
+
+.bcdgreater:
+ ldconst 1,g0 /*BNN_GREATER */
+ bx (g7)
+
+
+
+/*
+** BnnComplement(nn, nl)
+** BigNum nn
+** int nl
+**
+** Complement nn and store result in nn
+**
+** g0 -> nn
+** g1 -> nl
+**
+*/
+
+.globl _BnnComplement
+.leafproc _BnnComplement
+
+_BnnComplement:
+
+ mov g14,g7
+ ldconst 0,g14
+
+ cmpobe 0,g1,.bcexit
+
+ subo 1,g1,g1
+ shlo 2,g1,g1
+ addo g1,g0,g1
+
+ ldconst 0xffffffff,g3
+.bcloop:
+ ld (g0),g2
+ xor g3,g2,g2
+ st g2, (g0)
+ addo 4,g0,g0
+ cmpoble g0,g1,.bcloop
+
+.bcexit:
+ bx (g7)
+
+
+/*
+** BnnAndDigits(n,d)
+** BigNum nn
+** BigNumDigit d
+**
+** And the digit d with the first digit in n
+**
+** g0 -> nn
+** g1 -> d
+**
+*/
+
+.globl _BnnAndDigits
+.leafproc _BnnAndDigits
+
+_BnnAndDigits:
+ mov g14,g7
+ ldconst 0,g14
+
+ ld (g0),g2
+ and g1,g2,g2
+ st g2,(g0)
+
+ bx (g7)
+
+
+/*
+** BnnOrDigits(n,d)
+** BigNum nn
+** BigNumDigit d
+**
+** Returns the logical computation nn[0] |= d;
+**
+** g0 -> nn
+** g1 -> d
+**
+*/
+
+.globl _BnnOrDigits
+.leafproc _BnnOrDigits
+
+_BnnOrDigits:
+ mov g14,g7
+ ldconst 0,g14
+
+ ld (g0),g2
+ or g1,g2,g2
+ st g2,(g0)
+
+ bx (g7)
+
+
+/*
+** void BnnXorDigits (n, d)
+** BigNum n
+** BigNumDigit d
+**
+** Returns the logical computation n[0] XOR d in n[0]
+**
+** g0 -> n
+** g1 -> d
+**
+*/
+
+.globl _BnnXorDigits
+.leafproc _BnnXorDigits
+
+_BnnXorDigits:
+ mov g14,g7
+ ldconst 0,g14
+
+ ld (g0),g2
+ xor g1,g2,g2
+ st g2,(g0)
+
+ bx (g7)
+
+
+/*
+** BigNumDigit BnnShiftLeft (mm, ml, nbits)
+** BigNum mm
+** int ml
+** int nbits
+**
+** Shifts M left by "nbits", filling with 0s.
+** Returns the leftmost "nbits" of M in a digit.
+** Assumes 0 <= nbits < BNN_DIGIT_SIZE.
+**
+** g0 -> mm
+** g1 -> ml
+** g2 -> nbits
+*/
+
+.globl _BnnShiftLeft
+.leafproc _BnnShiftLeft
+
+_BnnShiftLeft:
+
+ mov g14,g7
+ ldconst 0,g14
+ cmpo 0,g1
+ be .bslexit0
+ subo 1,g1,g1
+ shlo 2,g1,g1
+ addo g1,g0,g1 /* nl += nn i.e. get the final address */
+ mov g0,g3 /* Save beginning of mm */
+ ldconst 0,g0 /* pre-load result with 0 */
+ cmpo 0,g2
+ be .bslexit
+ ldconst 32,g6 /* BNN_DIGIT_SIZE */
+ subo g2,g6,g6
+
+.blsloop:
+ ld (g3),g4 /* Access *mm */
+ shlo g2,g4,g5 /* *mm == (*mm << nbits) */
+ or g5,g0,g5 /* or in remaining bits from last op */
+ st g5,(g3) /* save the stuff */
+ shro g6,g4,g0 /* Save the left over high bits */
+ /* for the next time through the loop */
+ addo 4,g3,g3 /* Increment to next address */
+ cmpi g3,g1
+ ble .blsloop
+
+.bslexit:
+ bx (g7) /* Note that g0 holds bits that where */
+ /* Shifted out at the end */
+
+.bslexit0:
+ mov 0,g0
+ bx (g7)
+/*
+** BigNumDigit BnnShiftRight (mm, ml, nbits)
+** BigNum mm;
+** int ml;
+** int nbits;
+**
+** Shifts M right by "nbits", filling with 0s.
+** Returns the rightmost "nbits" of M in a digit.
+** Assumes 0 <= nbits < BNN_DIGIT_SIZE.
+**
+** g0 -> mm
+** g1 -> ml
+** g2 -> nbits
+**
+** Returns result in g0
+**
+*/
+.globl _BnnShiftRight
+.leafproc _BnnShiftRight
+
+_BnnShiftRight:
+ mov g14,g7
+ ldconst 0,g14
+ mov g0,g3 /*Save mm in g3 and preload result */
+ ldconst 0,g0
+
+ cmpobe 0,g1,.bsrexit /* If this is a zero length Bignum or */
+ cmpobe 0,g2,.bsrexit /* there are no bits to shift, exit */
+
+ subo 1,g1,g1 /* Prepare for pointer arithmetic */
+ shlo 2,g1,g1
+ addo g3,g1,g1 /*Point to the last element in the array*/
+
+
+ ldconst 32,g8 /* BNN_DIGIT_SIZE */
+ subo g2,g8,g6
+
+.bsrloop:
+ ld (g1),g4 /* *mm = (*mm >> nbits)| leftover bits */
+ /* from the last time through the loop */
+ shro g2,g4,g5
+ or g0,g5,g5
+ st g5,(g1)
+ shlo g6,g4,g0
+ subo 4,g1,g1
+ cmpobge g1,g3,.bsrloop
+
+.bsrexit:
+ bx (g7) /* Bits shifted out are still in g0! */
+
+
+/*
+** BigNumCarry BnnAddCarry (nn, nl, carryin)
+** BigNum nn;
+** int nl;
+** BigNumCarry carryin;
+**
+** Performs the sum N + CarryIn => N. Returns the CarryOut.
+**
+** g0 -> nn
+** g1 -> nl
+** g2 -> carryin
+**
+** Result is in g0
+**
+*/
+
+.globl _BnnAddCarry
+.leafproc _BnnAddCarry
+
+_BnnAddCarry:
+ mov g14,g7
+ ldconst 0,g14
+
+ cmpobe 0,g2,.bacexit0 /* If carry == 0 return 0 */
+ cmpobe 0,g1,.bacexit1 /* If nl == 0 return 1 */
+
+.bacloop:
+ subo 1,g1,g1 /* --nl */
+ ld (g0),g3 /* g3= *nn */
+ addo 1,g3,g3 /* ++g3 */
+ st g3,(g0) /* *nn = g3 */
+ addo 4,g0,g0 /* ++nn */
+ cmpobne 0,g3,.bacexit0 /* if (g3) then return 0 */
+ cmpibl 0,g1,.bacloop /* If (nl) continue loop */
+
+.bacexit1:
+ ldconst 1,g0
+ bx (g7)
+
+.bacexit0:
+ ldconst 0,g0
+ bx (g7)
+
+
+
+
+/*
+** BigNumCarry BnnSubtractBorrow (nn, nl, carryin)
+** BigNum nn;
+** int nl;
+** BigNumCarry carryin;
+**
+** Performs the difference N + CarryIn - 1 => N. Returns the CarryOut.
+**
+** g0 -> nn
+** g1 -> nl
+** g2 -> carryin
+*/
+
+.globl _BnnSubtractBorrow
+.leafproc _BnnSubtractBorrow
+
+_BnnSubtractBorrow:
+ mov g14,g7
+ ldconst 0,g14
+
+ cmpibe 1,g2,.bsbexit1 /* If Carry return 1 */
+ cmpobe 0,g1,.bsbexit0 /* If (!nl) return 0 */
+
+.bsbloop:
+ subi 1,g1,g1 /* --nl */
+ ld (g0),g3 /* g3 = *nn */
+ mov g3,g5 /* g5 = *nn */
+ subo 1,g3,g3 /* --g3 */
+ st g3,(g0) /* *nn = g3 */
+ addo 4,g0,g0
+ cmpobne 0,g5,.bsbexit1
+ cmpibl 0,g1,.bsbloop
+
+.bsbexit0:
+ ldconst 0,g0
+ bx (g7)
+
+.bsbexit1:
+ ldconst 1,g0
+ bx (g7)
+
+
+
+/*
+** BigNumCarry BnnSubtract (mm, ml, nn, nl, carryin)
+** BigNum mm, nn;
+** int ml;
+** int nl;
+** BigNumCarry carryin;
+**
+** Performs the difference M - N + CarryIn - 1 => M.
+** Returns the CarryOut.
+** Assumes Size(M) >= Size(N).
+**
+** g0 -> mm
+** g1 -> ml
+** g2 -> nn
+** g3 -> nl
+** g4 -> carryin
+**
+*/
+
+.globl _BnnSubtract
+
+
+_BnnSubtract:
+ subo g3,g1,g1
+ cmpibe 0,g3,.bslpe /* While (--nl >= 0) */
+
+ ldconst -1,r5
+.bsloop:
+ subi 1,g3,g3
+ ld (g0),g5 /* g5 = *mm */
+ ld (g2),g6 /* g6 = *nn */
+ xor r5,g6,g6 /* g6 = (*nn) ^ -1 */
+ addo g4,g5,g4 /* c += *mm */
+ cmpobge g4,g5,.bsgt /* if (c < *mm) { */
+ mov g6,g5 /* *mm = invn */
+ ldconst 1,g4 /* c = 1 */
+ b .cleanup /* } */
+.bsgt:
+ addo g4,g6,g4 /* else { c += g6 */
+ mov g4,g5 /* *mm = c */
+ cmpobl g4,g6, .bsset1 /* if (c < g6) then c=1 */
+ ldconst 0,g4 /* else c = 0 */
+ b .cleanup /* } */
+.bsset1:
+ ldconst 1,g4
+
+.cleanup:
+ st g5,(g0)
+ addo 4,g0,g0
+ addo 4,g2,g2
+ cmpibl 0,g3,.bsloop /* While (--nl >= 0) */
+
+.bslpe:
+ mov g4,g2
+ lda .bsexit,g14
+ bal _BnnSubtractBorrow
+
+.bsexit:
+ ret
+
+
+/*
+** BigNumCarry BnnMultiplyDigit (pp, pl, mm, ml, d)
+
+** BigNum pp, mm;
+** int pl, ml;
+** BigNumDigit d;
+**
+** Performs the product:
+** Q = P + M * d
+** BB = BBase(P)
+** Q mod BB => P
+** Q div BB => CarryOut
+** Returns the CarryOut.
+** Assumes Size(P) >= Size(M) + 1.
+**
+**
+** g0 -> pp
+** g1 -> pl
+** g2 -> mm
+** g3 -> ml
+** g4 -> d
+*/
+
+.globl _BnnMultiplyDigit
+
+_BnnMultiplyDigit:
+ cmpo 0,g4
+ be .bmdexit0 /* if the multiplier is 0 */
+ cmpo 1,g4
+ be .bmdbnnadd
+ subo g3,g1,g1 /* pl -= ml */
+ mov 0,g6 /* Carry = 0 */
+ cmpo 0,g3
+ mov 0,g7
+ be .bmdbye /* While (m--) */
+
+.bmdlp1:
+ ld (g2),r3 /* r3 = *mm */
+ subo 1,g3,g3
+ ld (g0),r4 /* r4 = *p */
+ /* r5 = *(p++) */
+ emul g4,r3,r6 /* r6-r7 = *mm x d */
+ cmpo 1,0 /* Clear the carry bit */
+ addc r4,r6,r6
+ addc 0,r7,r7
+ addc r6,g6,g6
+ addc r7,g7,g7
+ st g6,(g0) /* *p = C */
+ mov g7,g6 /* c >> = BN_DIGIT_SIZE */
+ addo 4,g0,g0
+ mov 0,g7
+ addo 4,g2,g2
+ cmpo 0,g3
+ bl .bmdlp1 /* While (m--) */
+
+ cmpobl 0,g1, .bmdlp2
+ mov g6,g0
+ ret
+
+.bmdlp2:
+ ld (g0),r4
+ cmpo 1,0
+ addc g6,r4,g6
+ addc 0,g7,g7
+ st g6,(g0)
+ mov g7,g6
+ subo 1,g1,g1
+ mov 0,g7
+ addo 4,g0,g0
+ cmpobl 0,g1,.bmdlp2
+ mov g6,g0
+ ret
+
+
+.bmdbye:
+ mov 0,g0
+ ret
+
+.bmdexit0:
+ mov 0,g0 /* its a sure bet the result */
+ ret
+
+.bmdbnnadd:
+ mov 0,g4 /* Just add the 2 bignums */
+ call _BnnAdd /* of adding the 2 */
+ ret
+
+
+/*
+** BigNumDigit BnnDivideDigit (qq, nn, nl, d)
+** BigNum qq, nn;
+** int nl;
+** BigNumDigit d;
+**
+** Performs the quotient: N div d => Q
+** Returns R = N mod d
+** Assumes leading digit of N < d, and d > 0.
+**
+** g0 -> qq
+** g1 -> nn
+** g2 -> nl
+** g3 -> d
+*/
+
+.globl _BnnDivideDigit
+.leafproc _BnnDivideDigit
+
+_BnnDivideDigit:
+ mov g14,g7 /* Do standard leafproc stuff */
+ ldconst 0,g14
+ cmpo 0,g2
+ be .bddret0 /* Is this a Null length BIGNUM? */
+ cmpo 0,g3
+ be .bddret0 /* Is the divisor zero? */
+
+.bddndz:
+ subo 1,g2,g2
+ shlo 2,g2,g5
+ addo g1,g5,g1 /* nn += nl */
+ subo 4,g5,g5 /* --nl */
+ addo g0,g5,g0 /* qq += nl */
+ ld (g1),g9 /* Preset remainder */
+ subo 4,g1,g1 /* --nn */
+ cmpo 0,g2
+ be .bddexit
+.bddloop:
+ subo 1,g2,g2 /* --nl */
+ ld (g1),g8 /* LSB of quad is next digit */
+ ediv g3,g8,g8 /* remainder =quad%d, */
+ st g9,(g0) /* *qq = quad/d */
+ subo 4,g0,g0 /* --qq */
+ subo 4,g1,g1 /* --nn */
+ cmpo 0,g2
+ mov g8,g9
+ bne .bddloop /* } */
+
+.bddexit:
+ mov g9,g0 /* Return (remainder) */
+ bx (g7)
+
+.bddret0:
+ mov 0,g0
+ bx (g7)
+
+
+/*
+** BigNumCarry BnnAdd (mm, ml, nn, nl, carryin)
+** BigNum mm, nn;
+** int ml;
+** int nl;
+** BigNumCarry carryin;
+**
+** Performs the sum M + N + CarryIn => M.
+** Returns the CarryOut. Assumes Size(M) >= Size(N).
+**
+** g0 -> mm
+** g1 -> ml
+** g2 -> nn
+** g3 -> nl
+** g4 -> caryin;
+**
+** Result is in g0 and M (of course!)
+*/
+
+.text
+.align 2
+.globl _BnnAdd
+
+_BnnAdd:
+
+
+ subo g3,g1,g1 /* ml -= nl */
+ shlo 1,g4,g4
+ cmpobe 0,g3,.bafni /* if (!nl) */
+
+
+.balp:
+ modac 02,g4,g4
+ ld (g0),g5 /* g5 = *mm */
+ ld (g2),g6 /* g6 = *nn */
+ addc g6,g5,g7 /* g7 = *m + *n */
+ modac 00,00,g4 /* Save the carry bit */
+ st g7,(g0) /* *m = g7 */
+ addo 4,g0,g0 /* ++m */
+ addo 4,g2,g2 /* ++n */
+ subi 1,g3,g3 /* --nl */
+ cmpobl 0,g3,.balp
+
+.bafni:
+ shro 1,g4,g4
+ and 01,g4,g2
+ lda .bazit,g14
+ bal _BnnAddCarry
+
+.bazit:
+ ret
+
+
diff --git a/otherlibs/num/bignum/s/mipsKerN.s b/otherlibs/num/bignum/s/mipsKerN.s
new file mode 100644
index 000000000..672312ff8
--- /dev/null
+++ b/otherlibs/num/bignum/s/mipsKerN.s
@@ -0,0 +1,1382 @@
+ # Copyright Digital Equipment Corporation & INRIA 1988, 1989
+ # Last modified_on Tue Jul 31 17:48:45 GMT+2:00 1990 by shand
+ # modified_on Fri Mar 2 16:53:50 GMT+1:00 1990 by herve
+ #
+ # KerN for Mips
+ # Paul Zimmermann & Robert Ehrlich & Bernard Paul Serpette
+ # & Mark Shand
+ #
+ .text
+ .align 2
+ .globl BnnSetToZero
+ .ent BnnSetToZero # (nn nl)
+BnnSetToZero:
+ .frame $sp, 0, $31
+ sll $9,$5,2 # nl <<= 2;
+ beq $5,$0,BSTZ2 # if(nl == 0) goto BSTZ2;
+ andi $8,$9,0x1c
+ lw $10,BSTZTable($8)
+ addu $9,$4 # nl += nn;
+ addu $4,$8
+ j $10
+BSTZE8:
+BSTZLoop: addu $4,32 # nn++;
+ sw $0,-32($4) # *nn = 0;
+BSTZE7: sw $0,-28($4)
+BSTZE6: sw $0,-24($4)
+BSTZE5: sw $0,-20($4)
+BSTZE4: sw $0,-16($4) # *nn = 0;
+BSTZE3: sw $0,-12($4)
+BSTZE2: sw $0,-8($4)
+BSTZE1: sw $0,-4($4)
+ bne $4,$9,BSTZLoop # if(nn != nl) goto BSTZLoop;
+BSTZ2: j $31 # return;
+ .rdata
+BSTZTable:
+ .word BSTZE8
+ .word BSTZE1
+ .word BSTZE2
+ .word BSTZE3
+ .word BSTZE4
+ .word BSTZE5
+ .word BSTZE6
+ .word BSTZE7
+ .text
+ .end BnnSetToZero
+
+ .align 2
+ .globl BnnAssign
+ .ent BnnAssign # (mm nn nl)
+BnnAssign:
+ .frame $sp, 0, $31
+ ble $4,$5,BAG2 # if(mm <= nn) goto BAG2;
+ sll $12,$6,2 # X = nl << 2;
+ addu $4,$12 # mm += X;
+ addu $5,$12 # nn += X;
+ b BAG4 # goto BAG4;
+BAG1: lw $12,($5) # X = *(nn);
+ sw $12,($4) # *(mm) = X
+ addu $4,4 # mm++;
+ addu $5,4 # nn++;
+ subu $6,1 # nl--;
+BAG2: bnez $6,BAG1 # if(nl) goto BAG1;
+ j $31 # return;
+BAG3: subu $4,4 # mm--;
+ subu $5,4 # nn--;
+ lw $12,($5) # X = *(nn);
+ sw $12,($4) # *(mm) = X;
+ subu $6,1 # nl--;
+BAG4: bnez $6,BAG3 # if(nl) goto BAG3;
+ j $31 # return;
+ .end BnAssign
+
+ .align 2
+ .globl BnnSetDigit
+ .ent BnnSetDigit # (nn d)
+BnnSetDigit:
+ sw $5,0($4) # *nn = d;
+ j $31 # return;
+ .end BnnSetDigit
+
+ .align 2
+ .globl BnnGetDigit
+ .ent BnnGetDigit # (nn)
+BnnGetDigit:
+ lw $2,0($4) # return(*nn);
+ j $31
+ .end BnnGetDigit
+
+ .align 2
+ .globl BnnNumDigits
+ .ent BnnNumDigits # (nn nl)
+BnnNumDigits:
+ .frame $sp, 0, $31
+ sll $12,$5,2
+ addu $4,$12 # nn = &nn[nl];
+ b BND2 # goto BND2;
+BND1: subu $5,1 # nl--;
+ subu $4,4 # nn--;
+ lw $12,0($4) # X = *nn;
+ bnez $12,BND3 # if(X) goto BND3;
+BND2: bnez $5,BND1 # if(nl) goto BND1;
+ li $2,1 # return(1);
+ j $31
+BND3: addu $2,$5,1 # return(nl);
+ j $31
+ .end BnnNumDigits
+
+ .align 2
+ .globl BnnNumLeadingZeroBitsInDigit
+ .ent BnnNumLeadingZeroBitsInDigit # (d)
+BnnNumLeadingZeroBitsInDigit:
+ .frame $sp, 0, $31
+ move $2,$0 # p = 0;
+ bne $4,0,BLZ2 # if(!d) goto BLZ2;
+ li $2,32 # return(32);
+ j $31
+BLZ1: addu $2,1 # p++;
+ sll $4,1 # d <<= 1;
+BLZ2: bgtz $4,BLZ1 # while (d>0) goto BLZ1
+ j $31 # return(p);
+ .end BnnNumLeadingZeroBitsInDigit
+
+ .align 2
+ .globl BnnDoesDigitFitInWord
+ .ent BnnDoesDigitFitInWord # (d)
+BnnDoesDigitFitInWord:
+ .frame $sp, 0, $31
+ li $2,1 # return(1);
+ j $31
+ .end BnnDoesDigitFitInWord
+
+ .align 2
+ .globl BnnIsDigitZero
+ .ent BnnIsDigitZero # (d)
+BnnIsDigitZero:
+ .frame $sp, 0, $31
+ seq $2,$4,0 # return(d == 0);
+ j $31
+ .end BnnIsDigitZero
+
+ .align 2
+ .globl BnnIsDigitNormalized
+ .ent BnnIsDigitNormalized # (d)
+BnnIsDigitNormalized:
+ .frame $sp, 0, $31
+ slt $2,$4,$0 # return(d < 0);
+ j $31
+ .end BnnIsDigitNormalized
+
+ .align 2
+ .globl BnnIsDigitOdd
+ .ent BnnIsDigitOdd # (d)
+BnnIsDigitOdd:
+ .frame $sp, 0, $31
+ and $2,$4,1 # return(d & 1);
+ j $31
+ .end BnnIsDigitOdd
+
+ .align 2
+ .globl BnnCompareDigits
+ .ent BnnCompareDigits # (d1 d2)
+BnnCompareDigits:
+ .frame $sp, 0, $31
+ # 254 return ((d1 > d2) - (d1 < d2));
+ sltu $8,$5,$4 # t0 = (d2 < d1);
+ sltu $9,$4,$5 # t1 = (d1 < d2);
+ sub $2,$8,$9 # return t0-t1;
+ j $31
+ .end BnnCompareDigits
+
+ .align 2
+ .globl BnnComplement
+ .ent BnnComplement # (nn nl)
+BnnComplement:
+ .frame $sp, 0, $31
+ sll $8,$5,2 # bytes = nl*4;
+ beq $5,$0,BCM2 # if(nl == 0) goto BCM2;
+ add $8,$4 # lim = nn+bytes;
+BCM1:
+ lw $14,0($4) # X = *nn;
+ nor $14,$0 # X ^= -1;
+ sw $14,0($4) # *nn = X
+ addu $4,4 # nn++;
+ bne $8,$4,BCM1 # if(nl != 0) goto BCM1;
+BCM2: j $31 # return;
+ .end BnnComplement
+
+ .align 2
+ .globl BnnAndDigits
+ .ent BnnAndDigits # (nn d)
+BnnAndDigits:
+ .frame $sp, 0, $31
+ lw $14,0($4) # X = *nn;
+ and $14,$5 # X &= d;
+ sw $14,0($4) # *nn = X;
+ j $31 # return;
+ .end BnnAndDigits
+
+ .align 2
+ .globl BnnOrDigits
+ .ent BnnOrDigits # (nn d)
+BnnOrDigits:
+ .frame $sp, 0, $31
+ lw $14,0($4) # X = *nn;
+ or $14,$5 # X |= d;
+ sw $14,0($4) # *nn = X;
+ j $31 # return;
+ .end BnnOrDigits
+
+ .align 2
+ .globl BnnXorDigits
+ .ent BnnXorDigits # (nn d)
+BnnXorDigits:
+ .frame $sp, 0, $31
+ lw $14,0($4) # X = *nn;
+ xor $14,$5 # X ^= d;
+ sw $14,0($4) # *nn = X;
+ j $31 # return;
+ .end BnnXorDigits
+
+ .align 2
+ .globl BnnShiftLeft
+ .ent BnnShiftLeft # (mm ml nbi)
+BnnShiftLeft:
+ .frame $sp, 0, $31
+ move $2,$0 # res = 0;
+ beq $6,0,BSL2 # if(nbi == 0) goto BSL2;
+ li $14,32 # rnbi = 32;
+ subu $14,$6 # rnbi -= nbi;
+ beq $5,0,BSL2 # if(ml == 0) goto BSL2;
+ sll $15,$5,2 # bytes = 4*ml;
+ addu $15,$4 # lim = mm+size;
+BSL1:
+ lw $25,0($4) # save = *mm;
+ sll $24,$25,$6 # X = save << nbi;
+ or $24,$2 # X |= res;
+ sw $24,0($4) # *mm = X;
+ addu $4,4 # mm++;
+ srl $2,$25,$14 # res = save >> rnbi;
+ bne $4,$15,BSL1 # if(mm != lim) goto BSL1;
+BSL2: j $31 # return(res);
+ .end BnnShiftLeft
+
+ .align 2
+ .globl BnnShiftRight
+ .ent BnnShiftRight # (mm ml nbi)
+BnnShiftRight:
+ .frame $sp, 0, $31
+ move $2,$0 # res = 0;
+ beq $6,0,BSR2 # if(nbi == 0) goto BSR2;
+ sll $14,$5,2 # bytes = ml*4;
+ beq $5,0,BSR2 # if(ml == 0) goto BSR2
+ addu $15,$4,$14 # lim = mm; mm += bytes;
+ li $14,32 # lnbi = 32;
+ subu $14,$6 # lnbi -= nbi;
+BSR1:
+ subu $15,4 # mm--;
+ lw $25,0($15) # save = *mm;
+ srl $24,$25,$6 # X = save >> nbi;
+ or $24,$2 # X |= res
+ sw $24,0($15) # *mm = X;
+ sll $2,$25,$14 # res = save << lnbi;
+ bne $15,$4,BSR1 # if(mm != lim) goto BSR1;
+BSR2: j $31 # return(res);
+ .end BnnShiftRight
+
+ .align 2
+ .globl BnnAddCarry
+ .ent BnnAddCarry # (nn nl car)
+BnnAddCarry:
+ .frame $sp, 0, $31
+ beq $6,0,BAC3 # if(car == 0) return(0);
+ beq $5,0,BAC2 # if(nl == 0) return(1);
+BAC1: subu $5,1 # nl--;
+ lw $9,0($4) # X = *nn;
+ addu $9,1 # X++;
+ sw $9,0($4) # *nn = X;
+ addu $4,4 # nn++;
+ bne $9,$0,BAC3 # if(X) goto BAC3;
+ bne $5,$0,BAC1 # if(nl) goto BAC1;
+BAC2: li $2,1 # return(1);
+ j $31
+BAC3: li $2,0 # return(0);
+ j $31
+ .end BnnAddCarry
+
+ .align 2
+ .globl BnnAdd
+ .ent BnnAdd # (mm ml nn nl car)
+BnnAdd:
+ .frame $sp, 0, $31
+ lw $2, 16($sp) # c = carryin;
+ subu $5,$7 # ml -= nl;
+ bne $7,$0,BADD1 # if(nl) goto BADD1;
+ bne $2,$0,BADD2 # if(c) goto BADD2;
+BADD0: j $31 # return(c)
+BADD1a: # carry, save == 0
+ # hence (*nn == 0 && carry == 0) || (*nn == -1 && carry == 1)
+ # in either case, *mm++ += 0; carry is preserved
+ addu $4,4 # mm++;
+ beq $7,$0,BADD2
+BADD1: subu $7,1 # nl--;
+ lw $15,0($6) # save = *nn;
+ addu $6,4 # nn++;
+ addu $15,$2 # save += c;
+ beq $15,$0,BADD1a # if (save == 0);
+ # no carry
+ lw $10,0($4) # X = *mm;
+ addu $4,4 # mm++;
+ addu $10,$15 # X += save;
+ sw $10,-4($4) # mm[-1] = X
+ sltu $2,$10,$15 # c = (X < save);
+ bne $7,$0,BADD1 # if(nl) goto BADD1;
+
+BADD2: beq $5,0,BADD0 # if(ml == 0) return(c);
+ beq $2,0,BADD0 # if(c == 0) return(0);
+BADD3: subu $5,1 # ml--;
+ lw $9,0($4) # X = *mm;
+ addu $9,1 # X++;
+ sw $9,0($4) # *mm = X;
+ addu $4,4 # mm++;
+ bne $9,$0,BADD4 # if(X) return(0);
+ bne $5,$0,BADD3 # if(ml) goto BADD3;
+ j $31 # return(1);
+BADD4: move $2,$0 # return(0)
+ j $31
+ .end BnnAdd
+
+ .align 2
+ .globl BnnSubtractBorrow
+ .ent BnnSubtractBorrow # (nn nl car)
+BnnSubtractBorrow:
+ .frame $sp, 0, $31
+ bne $6,0,BSB3 # if(car) return(1);
+ beq $5,0,BSB2 # if(nl == 0) return(0);
+BSB1: subu $5,1 # nl--;
+ lw $9,0($4) # X = *nn;
+ subu $10,$9,1 # Y = X - 1;
+ sw $10,0($4) # *nn = Y;
+ addu $4,4 # nn++;
+ bne $9,$0,BSB3 # if(X) return(1);
+ bne $5,$0,BSB1 # if(nl) goto BSB1;
+BSB2: li $2,0 # return(0);
+ j $31
+BSB3: li $2,1 # return(1);
+ j $31
+ .end BnnSubtractBorrow
+
+ .align 2
+ .globl BnnSubtract
+ .ent BnnSubtract 2 # (mm ml nn nl car)
+BnnSubtract:
+ .frame $sp, 0, $31
+ subu $5,$7 # ml -= nl;
+ lw $2, 16($sp) # car;
+ xor $14,$2,1 # c = !car
+ bne $7,$0,BS1 # if(nl) goto BS1;
+ bne $2,$0,BS0 # if(!c) goto BS0
+ bne $5,$0,BSB1 # if (ml != 0) goto Borrow
+BS0: j $31 # $r2 == 1; return(1)
+BS1a: # sub == 0
+ # hence (*nn == 0 && carry == 0) || (*nn == -1 && carry == 1)
+ # in either case, *mm++ -= 0; carry is preserved
+ addu $4,4
+ beq $7,$0,BS2
+BS1: subu $7,1 # nl--;
+ lw $12,0($6) # sub = *nn;
+ addu $6,4 # nn++;
+ addu $12,$14 # sub += c;
+ beq $12,$0,BS1a # if(sub == 0) goto BS1a
+ lw $15,0($4) # X = *mm
+ addu $4,4 # mm++;
+ subu $10,$15,$12 # Y = X-sub (sub != 0)
+ sw $10,-4($4) # *mm = Y
+ sltu $14,$15,$10 # c = (Y > X) (note: X != Y)
+ bne $7,$0,BS1 # if(nl) goto BS1;
+
+BS2: beq $14,$0,BS3 # if (!c) return (!c)
+ bne $5,$0,BSB1 # if (ml != 0) goto Borrow
+BS3: xor $2,$14,1 # return(!c);
+ j $31
+ .end BnnSubtract
+
+ .align 2
+ .globl BnnMultiplyDigit
+ .ent BnnMultiplyDigit # (pp pl mm ml d)
+BnnMultiplyDigit:
+ .frame $sp, 0, $31
+ lw $8, 16($sp) # d;
+ move $9,$0 # low = 0;
+ li $2,1 # load 1 for comparison
+ beq $8,0,BMD7 # if(d == 0) return(0);
+ move $10,$0 # carry1 = 0
+ bne $8,$2,BMDFastLinkage # if(d!=1)goto BMDFastLinkage;
+ sw $0, 16($sp)
+ b BnnAdd # BnnAdd(pp, pl, mm, ml, 0);
+
+ # FastLinkage entry point takes 5th parameter in r8
+ # and two extra parameters in r9,r10 which must add to
+ # less than 2^32 and that are added to pp[0]
+ # used from BnnMultiply squaring code.
+BMDFastLinkage:
+ subu $5,$7 # pl -= ml;
+ move $11,$0 # inc = 0
+ # move $15,$0 save = 0; logically needed, but use is
+ # such that we can optimize out
+ beq $7,$0,BMD6 # if(ml==0) goto BMD6;
+ sll $7,$7,2 # ml *= 4;
+ addu $7,$7,$6 # ml = &mm[ml]
+BMD3: lw $13,0($6) # X = *mm;
+ addu $6,4 # mm++;
+ multu $13,$8 # HI-LO = X * d;
+ sltu $12,$15,$11 # carry2 = (save < inc)
+ lw $15,0($4) # save = *pp;
+ addu $9,$10 # low += carry1;
+ addu $9,$12 # low += carry2;
+ addu $15,$15,$9 # save = save + low;
+ sltu $10,$15,$9 # carry1 = (save < low)
+ addu $4,4 # pp++;
+ mflo $11 # inc = LO;
+ mfhi $9 # low = HI;
+ addu $15,$11 # save += inc;
+ sw $15,-4($4) # *pp = save;
+ bne $7,$6,BMD3 # if(mm != ml) goto BMD3;
+BMD6: sltu $12,$15,$11 # carry2 = (save < inc)
+ lw $15,($4) # save = *pp;
+ addu $9,$10 # low += carry1;
+ addu $9,$12 # low += carry2;
+ addu $9,$15 # low += save;
+ sw $9,0($4) # *pp = low;
+ addu $4,4 # pp++;
+ bltu $9,$15,BMD8 # if(low < save) goto BMD8;
+BMD7: move $2, $0 # return(0);
+ j $31
+BMD8: subu $5,1 # pl--;
+ beq $5,0,BMD10 # if(ml == 0) return(1);
+BMD9: subu $5,1 # pl--;
+ lw $9,0($4) # X = *pp;
+ addu $9,1 # X++;
+ sw $9,0($4) # *pp = X;
+ addu $4,4 # pp++;
+ bne $9,$0,BMD7 # if(X) return(0);
+ bne $5,$0,BMD9 # if(pl) goto BMD9;
+BMD10: li $2,1 # return(1);
+ j $31
+ .end BnnMultiplyDigit
+
+ .align 2
+ .globl BnnDivideDigit
+ .ent BnnDivideDigit # (qq nn nl d)
+BnnDivideDigit:
+ .frame $sp, 0, $31
+ move $11,$31
+ move $10,$4
+ move $9,$5
+ move $8,$6
+ move $4,$7 # k = BnnNumLeadingZeroBitsInDigit(d);
+ jal BnnNumLeadingZeroBitsInDigit
+ move $6,$2
+ beq $6,$0,BDD1 # if(k == 0) goto BDD1;
+ move $4,$9
+ move $5,$8
+ jal BnnShiftLeft # BnnShiftLeft(nn, nl, k);
+ lw $31,0($10) # first_qq = *qq;
+ move $5,$8 # o_nl = nl;
+ sll $7,$6 # d <<= k;
+BDD1: sll $3,$8,2
+ addu $9,$3 # nn = &nn[nl];
+ subu $8,1 # nl--;
+ subu $3,4
+ addu $10,$3 # qq = &qq[nl];
+ srl $25,$7,16 # ch = HIGH(d);
+ and $2,$7,65535 # cl = LOW(d);
+ subu $9,4 # nn--;
+ lw $13,0($9) # rl = *nn;
+ beq $8,0,BDDx # if(nl == 0) goto BDDx;
+BDD2: subu $8,1 # nl--;
+ move $12,$13 # rh = rl;
+ subu $9,4 # nn--;
+ lw $13,0($9) # rl = *nn;
+ divu $14,$12,$25 # qa = rh/ch;
+ multu $2,$14 # HI-LO = cl * qa;
+ mflo $24 # pl = LO;
+ multu $25,$14 # HI-LO = ch * qa;
+ mflo $15 # ph = LO;
+ srl $3,$24,16 # X = HIGH(pl);
+ addu $15,$3 # ph += X;
+ sll $24,16 # pl = L2H(pl);
+ bgtu $15,$12,BDD84 # if(ph > rh) goto BDD84;
+ bne $15,$12,BDD88 # if(ph != rh) goto BDD88;
+ bleu $24,$13,BDD88 # if(pl <= rl) goto BDD88;
+BDD84: sll $3,$2,16 # X = L2H(cl);
+BDD85: subu $14,1 # qa--;
+ bleu $3,$24,BDD86 # if(X <= pl) goto BDD86;
+ subu $15,1 # ph--;
+BDD86: subu $24,$3 # pl -= X;
+ subu $15,$25 # ph -= ch;
+ bgtu $15,$12,BDD85 # if(ph > rh) goto BDD85;
+ bne $15,$12,BDD88 # if(ph != rh) goto BDD88;
+ bgtu $24,$13,BDD85 # if(pl > rl) goto BDD85;
+BDD88: bleu $24,$13,BDD89 # if(pl <= rl) goto BDD89;
+ subu $12,1 # rh--;
+BDD89: subu $13,$24 # rl -= pl;
+ subu $12,$15 # rh -= ph;
+ subu $10,4 # qq--;
+ sll $3,$14,16 # X = L2H(qa);
+ sw $3,0($10) # *qq = X;
+ sll $3,$12,16 # X = L2H(rh);
+ srl $14,$13,16 # qa = HIGH(rl);
+ or $14,$3 # qa |= X;
+ divu $14,$14,$25 # qa /= ch;
+ multu $2,$14 # HI-LO = cl * qa;
+ mflo $24 # pl = LO;
+ multu $25,$14 # HI-LO = ch * qa;
+ mflo $15 # ph = LO;
+ srl $3,$24,16 # X = HIGH(pl);
+ addu $15,$3 # ph += X;
+ and $24,65535 # pl = LOW(pl);
+ and $3,$15,65535 # X = LOW(ph);
+ sll $3,16 # X = L2H(X)
+ or $24,$3 # pl |= X;
+ srl $15,16 # ph = HIGH(ph);
+ bgtu $15,$12,BDD41 # if(ph > rh) goto BDD841;
+ bne $15,$12,BDD44 # if(ph != rh) goto BDD44;
+ bleu $24,$13,BDD44 # if(pl <= rl) goto BDD44;
+BDD41: subu $14,1 # qa--;
+ bleu $7,$24,BDD42 # if(d <= pl) goto BDD42;
+ subu $15,1 # ph--;
+BDD42: subu $24,$7 # pl -= d;
+ bgtu $15,$12,BDD41 # if(ph > rh) goto BDD841;
+ bne $15,$12,BDD44 # if(ph == rh) goto BDD44;
+ bgtu $24,$13,BDD41 # if(pl > rl) goto BDD41;
+BDD44: subu $13,$24 # rl -= pl;
+ lw $3,0($10) # X = *qq;
+ or $3,$14 # X |= qa
+ sw $3,0($10) # *qq = X;
+ bne $8,0,BDD2
+BDDx: beq $6,0,BDD46 # if(k = 0) goto BDD46;
+ bleu $10,$9,BDD45 # if(qq < nn) goto BDD45;
+ sll $3,$5,2
+ addu $3,$9 # X = &nn[o_nl];
+ bleu $3,$10,BDD45 # if(X <= qq) goto BDD45;
+ subu $5,$10,$9 # o_nl = qq - nn;
+ srl $5,2 # o_nl >>= 2;
+ lw $8,0($10) # X = *qq;
+ sw $31,0($10) # *qq = first_qq;
+ addu $5,1 # o_nl++;
+ move $4,$9 # BnnShiftRight(nn, o_nl, k);
+ jal BnnShiftRight
+ sw $8,0($10) # X = *qq;
+ srl $2,$13,$6 # return(rl >> k);
+ j $11
+BDD45: bne $10,$9,BDD451 # if(qq == nn) goto BDD451;
+ subu $5,1 # o_nl--;
+ sll $5,2
+ addu $9,$5 # nn = &nn[o_nl];
+ li $5,1 # o_nl = 1;
+BDD451: move $4,$9 # BnnShiftRight(nn, o_nl, k);
+ jal BnnShiftRight
+BDD46: srl $2,$13,$6 # return(rl >> k);
+ j $11
+ .end BnnDivideDigit
+
+ #############################################################################
+ # Karatsuba Multiplication for Mips.
+ # Mark Shand & Jean Vuillemin, May 1989.
+ #
+ # Basic operation is to compute: (a1.B + a0) * (b1.B + b0)
+ # B is the base; a1,a0,b1,b0 <= B-1
+ # We compute PL = a0.b0
+ # PM = (a1-a0).(b0-b1)
+ # PH = a1.b1
+ # Then:
+ # (a1.B + a0) * (b1.B + b0) = PL + B.(PM+PL+PH) + B.B.PH
+ #
+ # Overall operation is BigNum mm * d0_d1.
+ # Each cycle computes m0_m1 * d0_d1
+ # to avoid underflow in (a1-a0) and (b0-b1) and the
+ # extra adds that it would entail, the main loop is
+ # broken into four variants:
+ # BM2DLLoop d0 >= d1, m0 <= m1
+ # BM2DNLLoop d0 >= d1, m0 > m1
+ # BM2DHLoop d0 < d1, m0 >= m1
+ # BM2DNHLoop d0 < d1, m0 < m1
+ # mm is assumed to be even length.
+ #
+ # The code within the loops is written on the assumption of an
+ # infinite supply of registers. Each name is used in a single
+ # assignment. Name are then assigned to the finite set of registers
+ # based on an analysis of lifetime of each name--this is the purpose
+ # of the "defines" at the start of the routine.
+
+ .align 2
+ .globl BnnMultiply2Digit
+ .globl BnnM2DFastLink
+#define c0 $2 /* low carry */
+#define tb1 $2
+#define tc1 $2
+#define tj1 $2
+#define tn1 $2
+#define tq1 $2
+#define tz1 $2
+#define tA2 $2
+#define c1 $3 /* high carry */
+#define th2 $3
+#define ti2 $3
+#define pH3 $3
+#define tx3 $3
+#define ty3 $3
+#define ss $4
+#define sl $5
+#define mm $6
+#define ml $7
+#define mlim $7
+#define d0 $8
+#define d1 $9
+#define ds $10 /* d0+d1 mod base */
+#define t_z $11
+#define tC3 $11
+#define s0 $11
+#define ta0 $11
+#define td0 $11
+#define te1 $11
+#define tf1 $11
+#define s1 $11
+#define to2 $11
+#define tp2 $11
+#define ts2 $11
+#define pM1 $11
+#define m0 $12
+#define ms $12 /* b0+b1 mod base */
+#define tr2 $12
+#define tu3 $12
+#define tv3 $12
+#define pL0 $13
+#define tg1 $13
+#define tk2 $13
+#define tm2 $13
+#define tt2 $13
+#define tw2 $13
+#define t_1 $14
+#define pL1 $14
+#define pH2 $14
+#define pM2 $14
+#define tB2 $14
+#define m1 $15
+#define borrow $15
+ # Special "friends" entry point--allows fast non-standard procedure linkage.
+ # Permits passing d0:d1 in r8-r9 and a low-order 64-bit integer in r2-r3
+ # that is added to final result.
+ # Used from BnnMultiply and most highly optimized version of PRL's RSA
+ # implemenatation.
+ .ent BnnM2DFastLink
+BnnM2DFastLink:
+ .frame $sp, 0, $31
+ subu sl,ml
+ blez ml,BM2D6
+ lw m0,0(mm)
+ b BnnM2DFLAux
+ .end BnnM2DFastLink # (ss sl mm ml d0, d1)
+
+ .ent BnnMultiply2Digit # (ss sl mm ml d0, d1)
+BnnMultiply2Digit:
+ .frame $sp, 0, $31
+
+ .set noreorder
+ lw d0, 16($sp) # d0;
+ lw d1, 20($sp) # d1;
+ li c0,0
+ li c1,0
+ blez ml,BM2D6 # if(ml <= 0) goto end_loop;
+ # BDSLOT
+ subu t_1,d0,1 # t_1 = d0-1
+ .set reorder
+ or t_z,d0,d1 # t_z = (d0 | d1)
+ beq t_z,0,BM2D7 # if(d0.d1 == 0)
+ # return(0);
+ lw m0,0(mm)
+ or t_1,d1 # t_1 = (d0-1)|d1
+ subu sl,ml # sl -= ml;
+ beq t_1,0,BM2DADD0 # if(d0.d1 != 1)
+ # BnnAdd(pp, pl, mm, ml, 0);
+ .set noreorder
+BnnM2DFLAux:
+ multu d0,m0
+#define EnableOddLength 1
+#ifdef EnableOddLength
+#define t_odd $15
+#define t_a $15
+#define t_b $14
+#define t_c $15
+#define t_d $15
+#define t_e $14
+#define t_f $13
+#define t_g $15
+ # the ifdef'ed code handles case when length of mm is odd.
+ and t_odd,ml,1
+ sll mlim,ml,2 # ml *= 4;
+ beq t_odd,$0,BM2DmlEven
+ addu mlim,mlim,mm # mlim = mm+ml;
+ lw s0,0(ss)
+ addu mm,4
+ addu ss,4
+ mflo t_a
+ mfhi t_b
+ addu s0,t_a,s0
+ sltu t_c,s0,t_a
+ multu d1,m0
+ lw m0,0(mm)
+ addu t_d,t_c,t_b
+ mflo t_e
+ mfhi t_f
+ addu c0,t_e,t_d
+ sltu t_g,c0,t_e
+ multu d0,m0
+ addu c1,t_g,t_f
+ beq mm,mlim,BM2D6
+ # BDSLOT
+ sw s0,-4(ss)
+
+BM2DmlEven:
+#else EnableOddLength
+ sll mlim,ml,2 # ml *= 4;
+ addu mlim,mlim,mm # mlim = mm+ml;
+#endif EnableOddLength
+ lw m1,4(mm) # ml *= 4;
+ bltu d0,d1,BM2DHighBig # expands to 2 instructions
+ # BDSLOT
+ nop
+ bltu m1,m0,BM2DLNeg # expands to 2 instructions
+ # BDSLOT
+ subu ds,d0,d1
+ b BM2DLPEntry
+ # BDSLOT
+ lw s0,0(ss)
+
+BM2DLLoop:
+ lw m0,0(mm)
+ sw tz1,4(ss) # (pM1+pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B -> ss[1] FIN
+ multu m0,d0
+ addu ss,8
+ sltu tA2,tz1,pM1
+ addu tB2,pM2,tA2 # tB2 = pM2 + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu c0,tB2,tw2 # c0 = pM2+pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B+pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ lw m1,4(mm)
+ sltu tC3,c0,tB2
+ bltu m1,m0,BM2DLNeg # expands to 2 instructions
+ # BDSLOT
+ addu c1,ty3,tC3
+
+BM2DLPos:
+ lw s0,0(ss)
+BM2DLPEntry:
+ subu ms,m1,m0
+ addu ta0,s0,c0 # ta0 = (s0+c0)%B
+ mfhi pL1
+ mflo pL0
+ sltu tb1,ta0,c0
+ addu tc1,pL1,tb1 # tc1 = pL1 + (s0+c0)/B
+ multu m1,d1
+ addu td0,pL0,ta0 # td0 = (pL0+s0+c0)%B
+ sw td0,0(ss) # (pL0+s0+c0)%B -> ss[0] FIN
+ sltu te1,td0,pL0
+ addu tf1,tc1,te1 # tf1 = pL1 + (pL0+s0+c0)/B
+ addu tg1,pL0,c1 # tg1 = (pL0+c1)%B
+ sltu th2,tg1,c1
+ addu ti2,pL1,th2 # ti2 = pL1 + (pL0+c1)/B
+ addu tj1,tg1,tf1 # tj1 = (pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu tk2,tj1,tg1
+ lw s1,4(ss)
+ addu tm2,ti2,tk2 # tm2 = pL1 + (pL1+(pL0+s0+c0)/B+pL0+c1)/B
+ mfhi pH3
+ mflo pH2
+ addu tn1,tj1,s1 # tn1 = (s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu to2,tn1,s1
+ multu ms,ds
+ addu tp2,pH3,to2 # tp2 = pH3 + (s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu tq1,pH2,tn1 # tq1 = (pH2+s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu tr2,tq1,pH2
+ addu ts2,tp2,tr2 # ts2 = pH3 + (pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu tt2,pH2,tm2 # tt2 = (pH2+pL1 + (pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B
+ sltu tu3,tt2,pH2
+ addu tv3,pH3,tu3 # tv3 = pH3 + (pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)/B
+ addu tw2,ts2,tt2 # tw2 = pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ sltu tx3,tw2,ts2
+ addu ty3,tv3,tx3 # ty3 = pH3 + (pH3+(pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B)/B+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)/B
+ addu mm,8
+ mflo pM1
+ mfhi pM2
+ bne mlim,mm,BM2DLLoop # if(mm!=mlim) goto BM2DLLoop;
+ # BDSLOT
+ addu tz1,pM1,tq1 # tz1 = (pM1+pH2+s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+
+ .set reorder
+ sw tz1,4(ss) # (pM1+pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B -> ss[1] FIN
+ addu ss,8
+ sltu tA2,tz1,pM1
+ addu tB2,pM2,tA2 # tB2 = pM2 + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu c0,tB2,tw2 # c0 = pM2+pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B+pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ sltu tC3,c0,tB2
+ addu c1,ty3,tC3
+ b BM2D6
+ .set noreorder
+
+BM2DNLLoop:
+ lw m0,0(mm)
+ subu tz1,tq1,pM1 # tz1 = (-pM1+pH2+s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ multu m0,d0
+ sw tz1,4(ss) # (pM1+pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B -> ss[1] FIN
+ addu ss,8
+ addu tB2,pM2,borrow
+ sltu tC3,tw2,tB2
+ lw m1,4(mm)
+ subu c0,tw2,tB2 # c0 = -pM2+pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B+pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ bgeu m1,m0,BM2DLPos # expands to 2 instructions
+ # BDSLOT
+ subu c1,ty3,tC3
+
+BM2DLNeg:
+ lw s0,0(ss)
+ subu ms,m0,m1
+ addu ta0,s0,c0 # ta0 = (s0+c0)%B
+ mfhi pL1
+ mflo pL0
+ sltu tb1,ta0,c0
+ addu tc1,pL1,tb1 # tc1 = pL1 + (s0+c0)/B
+ multu m1,d1
+ addu td0,pL0,ta0 # td0 = (pL0+s0+c0)%B
+ sw td0,0(ss) # (pL0+s0+c0)%B -> ss[0] FIN
+ sltu te1,td0,pL0
+ addu tf1,tc1,te1 # tf1 = pL1 + (pL0+s0+c0)/B
+ addu tg1,pL0,c1 # tg1 = (pL0+c1)%B
+ sltu th2,tg1,c1
+ addu ti2,pL1,th2 # ti2 = pL1 + (pL0+c1)/B
+ addu tj1,tg1,tf1 # tj1 = (pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu tk2,tj1,tg1
+ lw s1,4(ss)
+ addu tm2,ti2,tk2 # tm2 = pL1 + (pL1+(pL0+s0+c0)/B+pL0+c1)/B
+ mfhi pH3
+ mflo pH2
+ addu tn1,tj1,s1 # tn1 = (s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu to2,tn1,s1
+ multu ms,ds
+ addu tp2,pH3,to2 # tp2 = pH3 + (s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu tq1,pH2,tn1 # tq1 = (pH2+s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu tr2,tq1,pH2
+ addu ts2,tp2,tr2 # ts2 = pH3 + (pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu tt2,pH2,tm2 # tt2 = (pH2+pL1 + (pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B
+ sltu tu3,tt2,pH2
+ addu tv3,pH3,tu3 # tv3 = pH3 + (pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)/B
+ addu tw2,ts2,tt2 # tw2 = pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ sltu tx3,tw2,ts2
+ addu ty3,tv3,tx3 # ty3 = pH3 + (pH3+(pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B)/B+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)/B
+ # Subtract ds
+ # sltu borrow,tw2,ds
+ # subu tw2,ds
+ # subu ty3,borrow
+ # End Subtract
+ addu mm,8
+ mflo pM1
+ mfhi pM2
+ bne mlim,mm,BM2DNLLoop # if(mm!=mlim) goto BM2DNLLoop;
+ # BDSLOT
+ sltu borrow,tq1,pM1
+
+ .set reorder
+ subu tz1,tq1,pM1 # tz1 = (-pM1+pH2+s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sw tz1,4(ss) # (pM1+pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B -> ss[1] FIN
+ addu ss,8
+ addu tB2,pM2,borrow
+ sltu tC3,tw2,tB2
+ subu c0,tw2,tB2 # c0 = -pM2+pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B+pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ subu c1,ty3,tC3
+ b BM2D6
+ .set noreorder
+BM2DHighBig:
+ bltu m0,m1,BM2DHNeg # expands to 2 instructions
+ subu ds,d1,d0
+ # BDSLOT
+ b BM2DHEntry
+ # BDSLOT
+ lw s0,0(ss)
+
+BM2DHLoop:
+ lw m0,0(mm)
+ sw tz1,4(ss) # (pM1+pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B -> ss[1] FIN
+ multu m0,d0
+ addu ss,8
+ sltu tA2,tz1,pM1
+ addu tB2,pM2,tA2 # tB2 = pM2 + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu c0,tB2,tw2 # c0 = pM2+pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B+pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ lw m1,4(mm)
+ sltu tC3,c0,tB2
+ bltu m0,m1,BM2DHNeg # expands to 2 instructions
+ # BDSLOT
+ addu c1,ty3,tC3
+
+BM2DHPos:
+ lw s0,0(ss)
+BM2DHEntry:
+ subu ms,m0,m1
+ addu ta0,s0,c0 # ta0 = (s0+c0)%B
+ mfhi pL1
+ mflo pL0
+ sltu tb1,ta0,c0
+ addu tc1,pL1,tb1 # tc1 = pL1 + (s0+c0)/B
+ multu m1,d1
+ addu td0,pL0,ta0 # td0 = (pL0+s0+c0)%B
+ sw td0,0(ss) # (pL0+s0+c0)%B -> ss[0] FIN
+ sltu te1,td0,pL0
+ addu tf1,tc1,te1 # tf1 = pL1 + (pL0+s0+c0)/B
+ addu tg1,pL0,c1 # tg1 = (pL0+c1)%B
+ sltu th2,tg1,c1
+ addu ti2,pL1,th2 # ti2 = pL1 + (pL0+c1)/B
+ addu tj1,tg1,tf1 # tj1 = (pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu tk2,tj1,tg1
+ lw s1,4(ss)
+ addu tm2,ti2,tk2 # tm2 = pL1 + (pL1+(pL0+s0+c0)/B+pL0+c1)/B
+ mfhi pH3
+ mflo pH2
+ addu tn1,tj1,s1 # tn1 = (s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu to2,tn1,s1
+ multu ms,ds
+ addu tp2,pH3,to2 # tp2 = pH3 + (s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu tq1,pH2,tn1 # tq1 = (pH2+s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu tr2,tq1,pH2
+ addu ts2,tp2,tr2 # ts2 = pH3 + (pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu tt2,pH2,tm2 # tt2 = (pH2+pL1 + (pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B
+ sltu tu3,tt2,pH2
+ addu tv3,pH3,tu3 # tv3 = pH3 + (pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)/B
+ addu tw2,ts2,tt2 # tw2 = pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ sltu tx3,tw2,ts2
+ addu ty3,tv3,tx3 # ty3 = pH3 + (pH3+(pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B)/B+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)/B
+ addu mm,8
+ mflo pM1
+ mfhi pM2
+ bne mlim,mm,BM2DHLoop # if(mm!=mlim) goto BM2DHLoop;
+ # BDSLOT
+ addu tz1,pM1,tq1 # tz1 = (pM1+pH2+s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+
+ .set reorder
+ sw tz1,4(ss) # (pM1+pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B -> ss[1] FIN
+ addu ss,8
+ sltu tA2,tz1,pM1
+ addu tB2,pM2,tA2 # tB2 = pM2 + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu c0,tB2,tw2 # c0 = pM2+pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B+pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ sltu tC3,c0,tB2
+ addu c1,ty3,tC3
+ b BM2D6
+ .set noreorder
+
+BM2DNHLoop:
+ lw m0,0(mm)
+ subu tz1,tq1,pM1 # tz1 = (-pM1+pH2+s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ multu m0,d0
+ sw tz1,4(ss) # (pM1+pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B -> ss[1] FIN
+ addu ss,8
+ addu tB2,pM2,borrow
+ sltu tC3,tw2,tB2
+ lw m1,4(mm)
+ subu c0,tw2,tB2 # c0 = -pM2+pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B+pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ bgeu m0,m1,BM2DHPos # expands to 2 instructions
+ # BDSLOT
+ subu c1,ty3,tC3
+
+BM2DHNeg:
+ lw s0,0(ss)
+ subu ms,m1,m0
+ addu ta0,s0,c0 # ta0 = (s0+c0)%B
+ mfhi pL1
+ mflo pL0
+ sltu tb1,ta0,c0
+ addu tc1,pL1,tb1 # tc1 = pL1 + (s0+c0)/B
+ multu m1,d1
+ addu td0,pL0,ta0 # td0 = (pL0+s0+c0)%B
+ sw td0,0(ss) # (pL0+s0+c0)%B -> ss[0] FIN
+ sltu te1,td0,pL0
+ addu tf1,tc1,te1 # tf1 = pL1 + (pL0+s0+c0)/B
+ addu tg1,pL0,c1 # tg1 = (pL0+c1)%B
+ sltu th2,tg1,c1
+ addu ti2,pL1,th2 # ti2 = pL1 + (pL0+c1)/B
+ addu tj1,tg1,tf1 # tj1 = (pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu tk2,tj1,tg1
+ lw s1,4(ss)
+ addu tm2,ti2,tk2 # tm2 = pL1 + (pL1+(pL0+s0+c0)/B+pL0+c1)/B
+ mfhi pH3
+ mflo pH2
+ addu tn1,tj1,s1 # tn1 = (s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu to2,tn1,s1
+ multu ms,ds
+ addu tp2,pH3,to2 # tp2 = pH3 + (s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu tq1,pH2,tn1 # tq1 = (pH2+s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sltu tr2,tq1,pH2
+ addu ts2,tp2,tr2 # ts2 = pH3 + (pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ addu tt2,pH2,tm2 # tt2 = (pH2+pL1 + (pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B
+ sltu tu3,tt2,pH2
+ addu tv3,pH3,tu3 # tv3 = pH3 + (pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)/B
+ addu tw2,ts2,tt2 # tw2 = pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ sltu tx3,tw2,ts2
+ addu ty3,tv3,tx3 # ty3 = pH3 + (pH3+(pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B)/B+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)/B
+ # Subtract ds
+ # sltu borrow,tw2,ds
+ # subu tw2,ds
+ # subu ty3,borrow
+ # End Subtract
+ addu mm,8
+ mflo pM1
+ mfhi pM2
+ bne mlim,mm,BM2DNHLoop # if(mm!=mlim) goto BM2DHLoop;
+ # BDSLOT
+ sltu borrow,tq1,pM1
+
+ .set reorder
+ subu tz1,tq1,pM1 # tz1 = (-pM1+pH2+s1+pL1+pL0+c1 + (pL0+s0+c0)/B)%B
+ sw tz1,4(ss) # (pM1+pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B -> ss[1] FIN
+ addu ss,8
+ addu tB2,pM2,borrow
+ sltu tC3,tw2,tB2
+ subu c0,tw2,tB2 # c0 = -pM2+pH3+(pH2+pL1+(pL1+(pL0+s0+c0)/B+pL0+c1)/B)%B + (pM1+(pH2+s1+pL1+pL0+c1+(pL0+s0+c0)/B)%B+pH2+s1+(pL1+pL0+c1+(pL0+s0+c0)/B)%B)/B
+ subu c1,ty3,tC3
+ # b BM2D6
+
+BM2D6:
+ lw s0,0(ss) # s0 = *ss;
+ addu c0,s0 # c0 = (c0+s0)%B
+ sltu $12,c0,s0 # r = (c0+s0)/B
+ lw s1,4(ss) #
+ sw c0,0(ss) # *ss = c0;
+ addu c1,s1 # c1 = (c1+s1)%B
+ sltu c0,c1,s1 # c0 = (c1+s1)/B
+ addu c1,$12 # c1 = (c1+s1+(c0+s0)/B)%B
+ sltu $12,c1,$12 # r = ((c1+s1)%B+(c0+s0)/B)/B
+ sw c1,4(ss)
+ addu c0,$12 # c0 = (c1+s1+(c0+s0)/B)/B
+ addu ss,8 # ss+=2;
+ bne c0,0,BM2D8 # if(c0) goto BM2D8;
+BM2D7: li $2,0 # return(0);
+ j $31
+BM2D8: subu $5,2 # sl-=2;
+ blez $5,BM2D10 # if(sl <= 0) return(1);
+BM2D9: subu $5,1 # pl--;
+ lw $9,0($4) # X = *pp;
+ addu $9,1 # X++;
+ sw $9,0($4) # *ss = X;
+ bne $9,$0,BM2D7 # if(X) return(0);
+ addu $4,4 # ss++;
+ bgtz $5,BM2D9 # if(sl > 0) goto BM2D9;
+BM2D10: li $2,1 # return(1);
+ j $31
+
+ #==============================================================================
+
+BM2DADD0: li c0,0
+BM2DADD1: subu $7,1 # nl--;
+ lw $15,0($4) # save = *mm;
+ addu $4,4 # mm++;
+ addu $15,$2 # save += c;
+ sltu $14,$15,$2 # c' = (save < c);
+ lw $10,0($6) # X = *nn;
+ addu $6,4 # nn++;
+ addu $10,$15 # X += save;
+ sw $10,-4($4) # mm[-1] = X
+ sltu $15,$10,$15 # save = (X < save);
+ addu $2,$15,$14 # c = c' + save;
+ bne $7,$0,BM2DADD1 # if(nl) goto BM2DADD1;
+
+ beq $5,0,BM2D10 # if(ml == 0) return(c);
+ beq $2,0,BM2DADD3 # if(c == 0) return(0);
+BM2DADD2: subu $5,1 # ml--;
+ lw $9,0($4) # X = *mm;
+ addu $9,1 # X++;
+ sw $9,0($4) # *mm = X;
+ addu $4,4 # mm++;
+ bne $9,$0,BM2DADD3 # if(X) return(0);
+ bne $5,$0,BM2DADD2 # if(ml) goto BM2DADD2;
+ j $31 # return(1);
+BM2DADD3: move $2,$0 # return(0)
+ j $31
+#undef c0
+#undef tb1
+#undef tc1
+#undef tj1
+#undef tn1
+#undef tq1
+#undef tz1
+#undef tA2
+#undef c1
+#undef th2
+#undef ti2
+#undef pH3
+#undef tx3
+#undef ty3
+#undef ss
+#undef sl
+#undef mm
+#undef ml
+#undef mlim
+#undef d0
+#undef d1
+#undef ds
+#undef t_z
+#undef tC3
+#undef s0
+#undef ta0
+#undef td0
+#undef te1
+#undef tf1
+#undef s1
+#undef to2
+#undef tp2
+#undef ts2
+#undef pM1
+#undef m0
+#undef ms
+#undef tr2
+#undef tu3
+#undef tv3
+#undef pL0
+#undef tg1
+#undef tk2
+#undef tm2
+#undef tt2
+#undef tw2
+#undef t_1
+#undef pL1
+#undef pH2
+#undef pM2
+#undef tB2
+#undef m1
+#undef borrow
+#ifdef EnableOddLength
+#undef t_odd
+#undef t_a
+#undef t_b
+#undef t_c
+#undef t_d
+#undef t_e
+#undef t_f
+#undef t_g
+#endif EnableOddLength
+ .end BnnMultiply2Digit
+
+ .align 2
+ .globl BnnMultiply
+ #.loc 2 40
+ # 40 {
+ .ent BnnMultiply 2
+BnnMultiply:
+ subu $sp, 56
+ sw $31, 52($sp)
+ sw $22, 48($sp)
+ sd $20, 40($sp)
+ sd $18, 32($sp)
+ sd $16, 24($sp)
+ .mask 0x807F0000, -4
+ .frame $sp, 56, $31
+ move $17, $4
+ move $18, $5
+ move $21, $6
+ move $22, $7
+ lw $16, 72($sp)
+ lw $19, 76($sp)
+ #.loc 2 74
+ # 74 if (nl & 1)
+ and $14, $19, 1
+ bne $6, $16, $37
+ move $20, $0
+ beq $7, $19, $38
+ #.loc 2 73
+ # 73 c = 0;
+$37:
+ move $20, $0
+ bne $14, $0, $32
+ b $33
+$32:
+ #.loc 2 76
+ # 75 {
+ # 76 c += BnnMultiplyDigit (pp, pl, mm, ml, *nn);
+ move $4, $17
+ move $5, $18
+ move $6, $21
+ move $7, $22
+ lw $15, 0($16)
+ sw $15, 16($sp)
+ jal BnnMultiplyDigit
+ move $20, $2
+ #.loc 2 77
+ # 77 pp++, nn++, nl--, pl--;
+ addu $17, $17, 4
+ addu $16, $16, 4
+ addu $19, $19, -1
+ addu $18, $18, -1
+ #.loc 2 78
+ # 78 }
+$33:
+ #.loc 2 79
+ # 79 if ((ml & 1) && nl)
+ and $24, $22, 1
+ beq $24, $0, $34
+ beq $19, 0, $34
+ #.loc 2 81
+ # 80 {
+ # 81 c += BnnMultiplyDigit (pp, pl, nn, nl, *mm);
+ move $4, $17
+ move $5, $18
+ move $6, $16
+ move $7, $19
+ lw $25, 0($21)
+ sw $25, 16($sp)
+ jal BnnMultiplyDigit
+ addu $20, $20, $2
+ #.loc 2 82
+ # 82 pp++, mm++, ml--, pl--;
+ addu $17, $17, 4
+ addu $21, $21, 4
+ addu $22, $22, -1
+ addu $18, $18, -1
+ #.loc 2 83
+ # 83 }
+$34:
+ #.loc 2 84
+ # 84 while (nl > 0)
+ bleu $19, 0, $36
+$35:
+ #.loc 2 86
+ # 85 {
+ # 86 c += BnnMultiply2Digit (pp, pl, mm, ml, nn[0], nn[1]);
+ move $4, $17
+ move $5, $18
+ move $6, $21
+ move $7, $22
+ lw $8, 0($16)
+ lw $9, 4($16)
+ li $2, 0
+ li $3, 0
+ jal BnnM2DFastLink
+ addu $20, $20, $2
+ #.loc 2 87
+ # 87 pp += 2, nn += 2, nl -= 2, pl -= 2;
+ addu $17, $17, 8
+ addu $16, $16, 8
+ addu $19, $19, -2
+ addu $18, $18, -2
+ #.loc 2 88
+ # 88 }
+ #.loc 2 88
+ bgtu $19, 0, $35
+$36:
+ #.loc 2 89
+ # 89 return c;
+ move $2, $20
+ ld $16, 24($sp)
+ ld $18, 32($sp)
+ ld $20, 40($sp)
+ lw $22, 48($sp)
+ lw $31, 52($sp)
+ addu $sp, 56
+ j $31
+$38:
+ # We no longer need r21, r22 since nn == mm && nl == ml
+ li $21, 0
+ beq $14, $0, $40 # if ((nl&1) == 0) goto $40
+ lw $21, 0($16) # r10 = d = *nn
+ multu $21, $21 # d*d
+ lw $12, 0($17) # r12 = *pp
+ addu $16, 4 # nn++
+ addu $8, $21, $21 # d2 = 2*d
+ addu $17, 8 # pp += 2
+ mflo $13 # d*d % 2^32
+ addu $13, $12 # r13 = new pp[0] = (*pp + d*d) % 2^32
+ sltu $10, $13, $12 # r10 = carry = (*pp + d*d) / 2^32
+ mfhi $9 # r9 = save = d*d / 2^32
+ subu $4, $17, 4 # arg1 = pp-1
+ subu $5, $18, 1 # arg2 = pl-1
+ subu $18, 2 # pl -= 2
+ subu $19, 1 # nl--
+ move $6, $16 # arg3 = nn
+ move $7, $19
+ sw $13, -8($17)
+ jal BMDFastLinkage # BnnMultiplyDigit(r4,r5,r6,r7,r8)+(r9+r10)%2^32
+ addu $20, $2
+ sra $21,31
+$40:
+ # 84 while (nl > 0)
+ bleu $19, 0, $42
+$41:
+ # 85 {
+ # compute d0:d1*d0:d1+p0:p1+c0:c1 -> p0:p1:c0:c1 with maximal overlap of
+ # single cycle instruction with multiplier operation.
+ #
+ # observe a*b+c+d <= 2^64-1 for all a,b,c,d < 2^32
+ # we can exploit this property to minimize carry tests
+ # Accordingly, computation can be organized as follows:
+ # d0*d0 -> l0:l1 d0*d1 -> m0:m1 d1*d1 -> h0:h1
+ #
+ # c0 c1 L1 M1
+ # p0 p1 M0 N1
+ # l0:l1 m0:m1 m0:m1 h0:h1
+ # ===== ===== ===== =====
+ # L0:L1 M0:M1 N0:N1 H0:H1
+ # -> P0 P1 C0:C1
+ #
+ lw $8, 0($16)
+ lw $15, 4($16)
+ multu $8, $8 # d0*d0
+ and $2, $8, $21 # c0 = d0*sgn(n[-1])
+ and $3, $15, $21 # c1 = d1*sgn(n[-1])
+ slt $22, $21, $0 # r22 = n[-1] < 0
+ sra $21, $15, 31
+ lw $10, 0($17) # r10 = p0
+ lw $11, 4($17) # r11 = p1
+ addu $17, 16 # pp += 4
+ addu $10, $2 # r10 = L(p0+c0)
+ sltu $2, $10, $2 # r2 = H(p0+c0)
+ addu $11, $3 # r11 = L(p1+c1)
+ sltu $3, $11, $3 # r3 = H(p1+c1)
+ # enough computation to prevent a stall
+ mflo $12 # l0
+ mfhi $13 # l1
+ addu $10, $12 # r10 = L0 = L(p0+c0+l0)
+ sw $10,-16($17) # pp[-4] = L0
+ multu $8, $15 # d0*d1
+ addu $16, 8 # nn += 2
+ sltu $12, $10, $12 # r12 = H(L(p0+c0)+l0)
+ # r12+r2 = H(p0+c0+l0)
+ addu $12, $13 # assert r12 == 0 || r2 == 0
+ addu $12, $2 # r12 = L1 = l1+H(p0+c0+l0)
+ # Free: 2,9,10,13,14; Used: r11:r3 = p1+c1 r8=d0 r15=d1 r12=L1
+ slt $14, $8, $0 # r14 = n[0] < 0
+ addu $8, $8 # r8 = L(2*d0)
+ addu $8, $22 # r8 = L(2*d0+(n[-1] < 0))
+ addu $9, $15, $15 # r9 = L(2*d1)
+ addu $9, $14 # r9 = L(2*d1+(d0 < 0))
+ subu $18, 4 # pl -= 4
+ subu $19, 2 # nl -= 2
+ # enough computation to prevent a stall
+ mflo $10 # m0
+ mfhi $14 # m1
+ addu $11, $10 # r11 = M0 = L(p1+c1+m0)
+ sltu $13, $11, $10 # r13 = H(L(p1+c1)+m0)
+ # r13+r3 = H(p0+c0+l0)
+ multu $15, $15 # d1*d1
+ addu $13, $14 # assert before r11 == 0 || r3 == 0
+ addu $13, $3 # r13 = M1 = m1+H(p1+c1+m0)
+ # Free: 2,3,15; Used: r8:r9 = 2*d0:d1 r10=m0 r11=M0 r12=L1 r13=M1 r14=m1
+ addu $10, $11 # r10 = L(m0+M0)
+ sltu $11, $10, $11 # r11 = H(m0+M0)
+ addu $10, $12 # r10 = N0 = L(M0+m0+L1)
+ sw $10, -12($17) # pp[-3] = N0
+ sltu $12, $10, $12 # r12 = H(L(m0+M0)+L1)
+ # r12+r11 = H(M0+m0+L1)
+ addu $14, $11 # assert r11 == 0 || r12 == 0
+ addu $14, $12 # r14 = N1 = m1+H(M0+m0+L1)
+ addu $14, $13 # r14 = L(M1+N1)
+ sltu $13, $14, $13 # r13 = H(M1+N1)
+ # enough computation to prevent a stall
+ mflo $10 # h0
+ mfhi $11 # h1
+ addu $2, $10, $14 # c0 = L(M1+N1+h0)
+ sltu $14, $2, $14 # r14 = H(L(M1+N1)+h0)
+ # r14+r13 = H(M1+N1+h0)
+ addu $3, $11, $14 # assert r14 == 0 || r13 == 0
+ addu $3, $13 # c1 = H(M1+N1+h0)
+ addu $4, $17, -8 # arg1 = pp-2
+ addu $5, $18, 2 # arg2 = pl+2
+ move $6, $16 # arg3 = nn
+ move $7, $19 # arg4 = nl
+ jal BnnM2DFastLink
+ addu $20, $20, $2
+ # 88 }
+ bgtu $19, 0, $41
+$42:
+ # 89 return c;
+ move $2, $20
+ ld $16, 24($sp)
+ ld $18, 32($sp)
+ ld $20, 40($sp)
+ lw $22, 48($sp)
+ lw $31, 52($sp)
+ addu $sp, 56
+ j $31
+ .end BnnMultiply
diff --git a/otherlibs/num/bignum/s/nsKerN.s b/otherlibs/num/bignum/s/nsKerN.s
new file mode 100644
index 000000000..7df2f9eb2
--- /dev/null
+++ b/otherlibs/num/bignum/s/nsKerN.s
@@ -0,0 +1,427 @@
+# Copyright Digital Equipment Corporation & INRIA 1988, 1989
+#
+# KerN for NS32032
+# Francis Dupont
+#
+ .text
+
+ .globl _BnnSetToZero
+ .align 2
+_BnnSetToZero: .set BSTZnn,4
+ .set BSTZnl,8
+ movd BSTZnn(sp),r0
+ movd BSTZnl(sp),r1
+ acbd 0,r1,BSTZ1 # ?? test a 0 + rapide ??
+ ret 0
+BSTZ1: movqd 0,0(r0) # *nn = 0;
+ addqd 4,r0 # nn++;
+ acbd -1,r1,BSTZ1 # if!(--nl) goto BSTZ1;
+ ret 0
+
+ .globl _BnnAssign
+ .align 2
+_BnnAssign: .set BAGmm,4
+ .set BAGnn,8
+ .set BAGnl,12
+ movd BAGnl(sp),r0
+ movd BAGnn(sp),r1
+ movd BAGmm(sp),r2
+ cmpd r2,r1
+ bge BAG1 # if(mm >= nn) goto BAG1;
+ movsd # bcopy(nn, mm, 4*nl);
+ ret 0
+BAG1: addr r2[r0:d],r2 # mm = &mm[nl];
+ addr r1[r0:d],r1 # nn = &nn[nl];
+ addqd -4,r2 # mm--;
+ addqd -4,r1 # nn--;
+ movsd b # revbcopy(nn, mm, 4*nl);
+ ret 0
+
+ .globl _BnnSetDigit
+ .align 2
+_BnnSetDigit: .set BSDnn,4
+ .set BSDd,8
+ movd BSDd(sp),0(BSDnn(sp)) # *nn = d;
+ ret 0
+
+ .globl _BnnGetDigit
+ .align 2
+_BnnGetDigit: .set BGDnn,4
+ movd 0(BGDnn(sp)),r0 # return(*nn);
+ ret 0
+
+ .globl _BnnNumDigits
+ .align 2
+_BnnNumDigits: .set BNDnn,4
+ .set BNDnl,8
+ movd BNDnl(sp),r0
+ cmpqd 0,r0
+ beq BND2 # if(nl == 0) return(1);
+ addr 0(BNDnn(sp))[r0:d],r1 # nn = &nn[nd];
+BND1: addqd -4,r1 # --nn;
+ cmpqd 0,0(r1)
+ bne BND3 # if(*nn != 0) return(nl);
+ acbd -1,r0,BND1 # if(!--nl) goto BND1;
+BND2: movqd 1,r0 # return(1);
+BND3: ret 0
+
+ .globl _BnnNumLeadingZeroBitsInDigit
+ .align 2
+_BnnNumLeadingZeroBitsInDigit: .set BLZd,4
+ movd BLZd(sp),r1
+ movd 31,r0 # ret = 31;
+BLZ1: tbitd r0,r1
+ bfs BLZ2 # if(d & 2^ret) goto BLZ2;
+ addqd -1,r0
+ bcs BLZ1 # if(--ret) goto BLZ1;
+BLZ2: negd r0,r0
+ addd 31,r0 # return(31 - ret);
+ ret 0
+
+ .globl _BnnDoesDigitFitInWord
+ .align 2
+_BnnDoesDigitFitInWord: .set BDFd,4
+ movqd 1,r0 # return(1);
+ ret 0
+
+ .globl _BnnIsDigitZero
+ .align 2
+_BnnIsDigitZero: .set BDZd,4
+ cmpqd 0,BDZd(sp) # return(!d);
+ seqd r0
+ ret 0
+
+ .globl _BnnIsDigitNormalized
+ .align 2
+_BnnIsDigitNormalized: .set BDNd,4
+ tbitd 31,BDNd(sp) # return(d & 2^31);
+ sfsd r0
+ ret 0
+
+ .globl _BnnIsDigitOdd
+ .align 2
+_BnnIsDigitOdd: .set BDOd,4
+ movqd 1,r0 # return(d & 1);
+ andd BDOd(sp),r0
+ ret 0
+
+ .globl _BnnCompareDigits
+ .align 2
+_BnnCompareDigits: .set BCDd1,4
+ .set BCDd2,8
+ cmpd BCDd1(sp),BCDd2(sp)
+ bhs BCD1 # if(d1 >= d2)
+ movqd -1,r0 # return(-1);
+ ret 0
+BCD1: sned r0 # return(d1 != d2);
+ ret 0
+
+ .globl _BnnComplement
+ .align 2
+_BnnComplement: .set BCMnn,4
+ .set BCMnl,8
+ movd BCMnl(sp),r1
+ cmpqd 0,r1
+ beq BCM2 # if(nl == 0) return;
+ movd BCMnn(sp),r0
+BCM1: comd 0(r0),0(r0) # *nn ^= -1;
+ addqd 4,r0 # nn++;
+ acbd -1,r1,BCM1 # if(!--nl) goto BCM1;
+BCM2: ret 0
+
+ .globl _BnnAndDigits
+ .align 2
+_BnnAndDigits: .set BADnn,4
+ .set BADd,8
+ andd BADd(sp),0(BADnn(sp)) # *nn &= d;
+ ret 0
+
+ .globl _BnnOrDigits
+ .align 2
+_BnnOrDigits: .set BODnn,4
+ .set BODd,8
+ ord BODd(sp),0(BODnn(sp)) # *nn |= d;
+ ret 0
+
+ .globl _BnnXorDigits
+ .align 2
+_BnnXorDigits: .set BXDnn,4
+ .set BXDd,8
+ xord BXDd(sp),0(BXDnn(sp)) # *nn ^= d;
+ ret 0
+
+ .globl _BnnShiftLeft
+ .align 2
+_BnnShiftLeft: .set BSLmm,8
+ .set BSLml,12
+ .set BSLnbi,16
+ enter [r3,r4,r5,r6],0
+ movqd 0,r0 # res = 0;
+ movd BSLnbi(fp),r5
+ cmpqd 0,r5
+ beq BSL2 # if(nbi == 0) return(res);
+ movd BSLml(fp),r3
+ cmpqd 0,r3
+ beq BSL2 # if(ml == 0) return(res);
+ movd r5,r6
+ subd 32,r6 # rnbi = nbi - BN_DIGIT_SIZE;
+ movd BSLmm(fp),r2
+BSL1: movd 0(r2),r1 # save = *mm;
+ movd r1,r4 # X = save;
+ lshd r5,r4 # X <<= nbi;
+ ord r0,r4 # X |= res;
+ movd r4,0(r2) # *mm = X;
+ addqd 4,r2 # mm++;
+ movd r1,r0 # res = save;
+ lshd r6,r0 # res <<= rnbi;
+ acbd -1,r3,BSL1 # if(!--nl) goto BSL1;
+BSL2: exit [r3,r4,r5,r6]
+ ret 0
+
+ .globl _BnnShiftRight
+ .align 2
+_BnnShiftRight: .set BSRmm,8
+ .set BSRml,12
+ .set BSRnbi,16
+ enter [r3,r4,r5,r6],0
+ movqd 0,r0 # res = 0;
+ movd BSRnbi(fp),r1
+ cmpqd 0,r1 # if(nbi == 0) return(res);
+ beq BSR2
+ movd BSRml(fp),r3
+ cmpqd 0,r3
+ beq BSR2 # if(ml == 0) return(res);
+ addr @32,r6
+ subd r1,r6 # rnbi = BN_DIGIT_SIZE - nbi;
+ negd r1,r5 # nbi = - nbi;
+ addr 0(BSRmm(fp))[r3:d],r2 # mm = &mm[ml];
+BSR1: addqd -4,r2 # mm--;
+ movd 0(r2),r1 # save = *mm;
+ movd r1,r4 # X = save;
+ lshd r5,r4 # X <<= nbi;
+ ord r0,r4 # X |= res
+ movd r4,0(r2) # *mm = X;
+ movd r1,r0 # res = save;
+ lshd r6,r0 # res <<= rnbi;
+ acbd -1,r3,BSR1 # if(!--nl) goto BSR1;
+BSR2: exit [r3,r4,r5,r6]
+ ret 0
+
+ .globl _BnnAddCarry
+ .align 2
+_BnnAddCarry: .set BACnn,4
+ .set BACnl,8
+ .set BACcar,12
+ cmpqd 0,BACcar(sp)
+ beq BAC3 # if(car == 0) return(0);
+ movd BACnl(sp),r0
+ cmpqd 0,r0 # if(nl = 0) return(1);
+ beq BAC2
+ movd BACnn(sp),r1
+BAC1: addqd 1,0(r1) # ++(*nn);
+ bcc BAC3 # if(!Carry) return(0);
+ addqd 4,r1 # nn++;
+ acbd -1,r0,BAC1 # if(!--nl) goto BAC1;
+BAC2: movqd 1,r0 # return(1);
+ ret 0
+BAC3: movqd 0,r0 # return(0);
+ ret 0
+
+ .globl _BnnAdd
+ .align 2
+_BnnAdd: .set BADDmm,8
+ .set BADDml,12
+ .set BADDnn,16
+ .set BADDnl,20
+ .set BADDcar,24
+ enter [r3,r4,r5],0
+ movd BADDnl(fp),r4
+ movd BADDcar(fp),r1
+ movd BADDmm(fp),r2
+ movd BADDnn(fp),r3
+ movd BADDml(fp),r5
+ subd r4,r5 # ml -= nl
+BADD1: cmpqd 0,r4
+ beq BADD4 # if(nl == 0) goto BADD4;
+ addqd -1,r4 # nl--;
+ addd 0(r2),r1 # car += *mm;
+ bcc BADD2 # if(!Carry) goto BADD2;
+ movd 0(r3),0(r2) # *mm = *nn;
+ addqd 4,r3 # nn++;
+ addqd 4,r2 # mm++;
+ movqd 1,r1 # car = 1
+ br BADD1 # goto BADD1
+BADD2: movd 0(r3),r0 # save = *nn;
+ addqd 4,r3 # nn++;
+ addd r0,r1 # car += save;
+ movd r1,0(r2) # *mm = car;
+ addqd 4,r2 # mm++;
+ cmpd r1,r0
+ slod r1 # car = (car < save) ? 1 : 0;
+ br BADD1 # goto BADD1;
+
+BADD4: cmpqd 0,r1 # if (car == 0) return(0);
+ beq BADD8
+ cmpqd 0,r5 # if (ml == 0) return(1);
+ beq BADD9
+BADD5: addqd 1,0(r2) # ++(*mm);
+ bcc BADD8 # if(Carry) return(0):
+ addqd 4,r2 # mm++;
+ acbd -1,r5,BADD5 # if(!--ml) goto BADD5;
+BADD9: movqd 1,r0 # return(1);
+ exit [r3,r4,r5]
+ ret 0
+BADD8: movqd 0,r0 # return(0);
+ exit [r3,r4,r5]
+ ret 0
+
+ .globl _BnnSubtractBorrow
+ .align 2
+_BnnSubtractBorrow: .set BSBnn,4
+ .set BSBnl,8
+ .set BSBcar,12
+ cmpqd 1,BSBcar(sp)
+ beq BSB3 # if(car == 1) return(1);
+ movd BSBnl(sp),r0
+ cmpqd 0,r0
+ beq BSB2 # if(nl == 0) return(0);
+ movd BSBnn(sp),r1
+BSB1: addqd -1,0(r1) # (*nn)--;
+ bcs BSB3 # if(Carry) return(1);
+ addqd 4,r1 # nn++;
+ acbd -1,r0,BSB1 # if(!--nl) goto BSB1;
+BSB2: ret 0 # return(nl);
+BSB3: movqd 1,r0 # return(1);
+ ret 0
+
+
+ .globl _BnnSubtract
+ .align 2
+_BnnSubtract: .set BSmm,8
+ .set BSml,12
+ .set BSnn,16
+ .set BSnl,20
+ .set BScar,24
+ enter [r3,r4,r5,r6],0
+ movd BSmm(fp),r4
+ movd BSml(fp),r6
+ movd BSnn(fp),r3
+ movd BSnl(fp),r5
+ movd BScar(fp),r1
+ subd r5,r6 # ml -= nl;
+BS1: cmpqd 0,r5
+ beq BS4 # if (nl == 0) goto BS4;
+ addqd -1,r5 # nl--;
+ addd 0(r4),r1 # car += *mm;
+ bcc BS2 # if(!Carry) goto BS2;
+ comd 0(r3),0(r4) # *mm = ~*nn
+ addqd 4,r3 # nn++
+ addqd 4,r4 # mm++
+ movqd 1,r1 # car = 1;
+ br BS1 # goto BS1;
+BS2: comd 0(r3),r0 # save = *nn;
+ addqd 4,r3 # nn++;
+ addd r0,r1 # car += save;
+ movd r1,0(r4) # *mm = car;
+ addqd 4,r4 # mm++;
+ cmpd r1,r0
+ slod r1 # car = (car < save) ? 1 : 0;
+ br BS1 # goto BS1;
+
+BS4: cmpqd 1,r1
+ beq BS8 # if(car == 1) return(1);
+ cmpqd 0,r6
+ beq BS9 # if(ml != 0) return(0);
+BS5: addqd -1,0(r4) # (*mm)--;
+ bcs BS8 # if(Carry) return(1);
+ addqd 4,r4 # mm++;
+ acbd -1,r6,BS5 # if(!--ml) goto BS5;
+BS9: movqd 0,r0 # return(0);
+ exit [r3,r4,r5,r6]
+ ret 0
+BS8: movqd 1,r0 # return(1);
+ exit [r3,r4,r5,r6]
+ ret 0
+
+ .globl _BnnMultiplyDigit
+ .align 2
+_BnnMultiplyDigit: .set BMDpp,8
+ .set BMDpl,12
+ .set BMDmm,16
+ .set BMDml,20
+ .set BMDd,24
+ enter [r3,r4,r5,r6,r7],0
+ movd BMDd(fp),r0
+ cmpqd 0,r0
+ beq BMD10 # if(d == 0) return(0);
+ cmpqd 1,r0
+ bne BMD1 # if(d != 1) goto BMD1;
+ exit [r3,r4,r5,r6,r7]
+ movqd 0,20(sp)
+ br _BnnAdd # BnAdd(pp,pl,mm,ml,0);
+BMD1: movqd 0,r7 # c = 0;
+ movd BMDpp(fp),r4
+ movd BMDml(fp),r5
+ movd BMDpl(fp),r6
+ subd r5,r6 # pl -= ml;
+ cmpqd 0,r5
+ beq BMD7 # if(ml == 0) goto BMD7;
+ movd BMDmm(fp),r1
+BMD2: movd 0(r1),r2 # save = *mm;
+ addqd 4,r1 # mm++;
+ meid r0,r2 # X = d * save;
+ addd r7,r2 # X += c;
+ bcc BMD3 # if(Carry) XH++;
+ addqd 1,r3
+BMD3: addd r2,0(r4) # *pp += XL;
+ bcc BMD4 # if(Carry) XH++;
+ addqd 1,r3
+BMD4: addqd 4,r4 # pp++;
+ movd r3,r7 # c = XL;
+ acbd -1,r5,BMD2 # if(!--ml) goto BMD2;
+BMD7: addd r7,0(r4) # *pp += c;
+ bcc BMD10 # if(!Carry) return(0);
+ addqd 4,r4 # pp++;
+ addqd -1,r6 # pl--;
+ cmpqd 0,r6
+ beq BMD11 # if (pl == 0) goto BMD11;
+BMD8: addqd 1,0(r4) # ++(*p);
+ bcc BMD10 # if(!Carry) return(0);
+ addqd 4,r4 # pp++;
+ acbd -1,r6,BMD8 # if(!--pl) goto BMD8;
+BMD11: movqd 1,r0 # return(1);
+ exit [r3,r4,r5,r6,r7]
+ ret 0
+BMD10: movqd 0,r0 # return(0);
+ exit [r3,r4,r5,r6,r7]
+ ret 0
+
+ .globl _BnnDivideDigit
+ .align 2
+_BnnDivideDigit: .set BDDqq,8
+ .set BDDnn,12
+ .set BDDnl,16
+ .set BDDd,20
+ enter [r3,r4,r5],0
+ movd BDDd(fp),r2
+ movd BDDnl(fp),r3
+ addr 0(BDDnn(fp))[r3:d],r4 # nn = &nn[nl];
+ addqd -1,r3 # nl--;
+ addr 0(BDDqq(fp))[r3:d],r5 # qq = &qq[nl];
+ addqd -4,r4 # nn--;
+ movd 0(r4),r1 # Xhig = *nn;
+ cmpqd 0,r3
+ beq BDD2 # if(nl == 0) return(Xhig);
+BDD1: addqd -4,r4 # --nn;
+ addqd -4,r5 # --qq;
+ movd 0(r4),r0 # Xlow = *nn;
+ deid r2,r0 # Xlow = X % c;
+ # Xhig = X / c;
+ movd r1,0(r5) # *qq = Xhig;
+ movd r0,r1 # Xhig = Xlow;
+ acbd -1,r3,BDD1 # if(!--nl) goto BDD1;
+ exit [r3,r4,r5] # return(Xlow);
+ ret 0
+BDD2: movd r1,r0 # return(Xlow);
+ exit [r3,r4,r5]
+ ret 0
diff --git a/otherlibs/num/bignum/s/pyramidKerN.s b/otherlibs/num/bignum/s/pyramidKerN.s
new file mode 100644
index 000000000..51198b80a
--- /dev/null
+++ b/otherlibs/num/bignum/s/pyramidKerN.s
@@ -0,0 +1,454 @@
+# Copyright Digital Equipment Corporation & INRIA 1988, 1989
+#
+# KerN for Pyramid Architecture
+# Bernard Paul Serpette
+#
+ .text 0
+
+ .globl _BnnSetToZero
+_BnnSetToZero: subw $1,pr1 # nl--;
+ blt BSTZ2 # if(nl < 0) return;
+BSTZ1: movw $0,(pr0) # *nn = 0;
+ addw $4,pr0 # nn++;
+ subw $1,pr1 # nl--;
+ bge BSTZ1 # if(nl >= 0) goto BSTZ1;
+BSTZ2: ret # return;
+
+ .globl _BnnAssign
+_BnnAssign: ucmpw pr1,pr0
+ bgt BAG3 # if(mm > nn) goto BAG3;
+ subw $1,pr2 # nl--;
+ bge BAG2 # if(nl >= 0) goto BAG2;
+ ret
+BAG1: addw $4,pr0 # mm++;
+ addw $4,pr1 # nn++;
+BAG2: movw (pr1),(pr0) # *mm = *nn;
+ subw $1,pr2 # nl--;
+ bge BAG1 # if(nl >= 0) goto BAG1;
+ ret
+
+BAG3: mova (pr1)[pr2*0x4],pr1 # nn += nl;
+ mova (pr0)[pr2*0x4],pr0 # mm += nl;
+ subw $1,pr2 # nl--;
+ blt BAG5 # if(nl < 0) return;
+BAG4: subw $4,pr0 # mm--;
+ subw $4,pr1 # nn--;
+ movw (pr1),(pr0) # *mm = *nn;
+ subw $1,pr2 # nl--;
+ bge BAG4 # if(nl >= 0) goto BAG4;
+BAG5: ret
+
+ .globl _BnnSetDigit
+_BnnSetDigit: movw pr1,(pr0) # *nn = d;
+ ret
+
+ .globl _BnnGetDigit
+_BnnGetDigit: movw (pr0),pr0 # return(*nn);
+ ret
+
+ .globl _BnnNumDigits
+_BnnNumDigits:
+ mova (pr0)[pr1*0x4],pr0 # nn += nl;
+ br BND2
+BND1: subw $4,pr0 # nn--;
+ mtstw (pr0),pr2
+ bne BND3 # if(*nn) goto BND3
+ subw $1,pr1 # nl--;
+BND2: mtstw pr1,pr2
+ bne BND1 # if(nl) goto BND1;
+ movw $1,pr0 # return(1);
+ ret
+BND3: movw pr1,pr0 # return(nl);
+ ret
+
+ .globl _BnnNumLeadingZeroBitsInDigit
+_BnnNumLeadingZeroBitsInDigit:
+ movw $0,pr1 # p = 0;
+ mtstw pr0,pr0
+ bne BLZ2 # if(!d) goto BLZ2;
+ movw $32,pr0 # return(32);
+ ret
+BLZ1: addw $1,pr1 # p++;
+ lshlw $1,pr0 # d <<= 1;
+BLZ2: mtstw pr0,pr0
+ bgt BLZ1 # if(d > 0) goto BLZ1;
+ movw pr1,pr0 # return(p);
+ ret
+
+ .globl _BnnDoesDigitFitInWord
+_BnnDoesDigitFitInWord:
+ movw $1,pr0 # return(1);
+ ret
+
+ .globl _BnnIsDigitZero
+_BnnIsDigitZero:
+ mtstw pr0,pr0 # set NZVC flags
+ mpsw pr0 # mov NZVC flags in register
+ andw $4,pr0 # return(Z);
+ ret
+
+ .globl _BnnIsDigitNormalized
+_BnnIsDigitNormalized:
+ mtstw pr0,pr0 # set NZVC flags
+ mpsw pr0 # mov NZVC flags in register
+ andw $8,pr0 # return(N);
+ ret
+
+ .globl _BnnIsDigitOdd
+_BnnIsDigitOdd:
+ andw $1,pr0 # return(d & 1);
+ ret
+
+ .globl _BnnCompareDigits
+_BnnCompareDigits:
+ ucmpw pr1,pr0
+ bgt BCDsup
+ bne BCDinf
+ movw $0,pr0
+ ret
+BCDinf: movw $-1,pr0
+ ret
+BCDsup: movw $1,pr0
+ ret
+
+ .globl _BnnComplement
+_BnnComplement:
+ subw $1,pr1 # nl--;
+ blt BCM2 # if(nl < 0) goto BCM2
+BCM1: mcomw (pr0),pr2 # tmp = *nn ^ -1;
+ movw pr2,(pr0) # *nn = tmp;
+ addw $4,pr0 # nn++;
+ subw $1,pr1 # nl--;
+ bge BCM1 # if(nl >= 0) goto BCM1;
+BCM2: ret
+
+ .globl _BnnAndDigits
+_BnnAndDigits: andw (pr0),pr1 # d &= *nn;
+ movw pr1,(pr0) # *nn = d;
+ ret
+
+ .globl _BnnOrDigits
+_BnnOrDigits: orw (pr0),pr1 # d |= *nn;
+ movw pr1,(pr0) # *nn = d;
+ ret
+
+ .globl _BnnXorDigits
+_BnnXorDigits: xorw (pr0),pr1 # d ^= *nn;
+ movw pr1,(pr0) # *nn = d;
+ ret
+
+ .globl _BnnShiftLeft
+_BnnShiftLeft: movw $0,lr1 # res = 0;
+ mtstw pr2,pr2
+ beq BSL2 # if(!nbi) return(res);
+ movw $32,lr2 # rnbi = 32;
+ subw pr2,lr2 # rnbi -= nbi;
+ subw $1,pr1 # ml--;
+ blt BSL2 # if(ml < 0) return(res);
+BSL1: movw (pr0),lr0 # save = *mm;
+ movw lr0,pr3 # X = save;
+ lshlw pr2,pr3 # X <<= nbi;
+ orw lr1,pr3 # X |= res;
+ movw pr3,(pr0) # *mm = X;
+ addw $4,pr0 # mm++;
+ movw lr0,lr1 # res = save;
+ lshrw lr2,lr1 # res >>= rnbi;
+ subw $1,pr1 # ml--;
+ bge BSL1 # if(ml >= 0) goto BSL1;
+BSL2: movw lr1,pr0 # return(res);
+ ret
+
+ .globl _BnnShiftRight
+_BnnShiftRight: movw $0,lr1 # res = 0;
+ mtstw pr2,pr2
+ beq BSR2 # if(!nbi) return(res);
+ mova (pr0)[pr1*0x4],pr0 # mm += ml;
+ movw $32,lr2 # lnbi = 32;
+ subw pr2,lr2 # lnbi -= nbi;
+ subw $1,pr1 # ml--;
+ blt BSR2 # if(ml < 0) return(res);
+BSR1: subw $4,pr0 # mm--;
+ movw (pr0),lr0 # save = *mm;
+ movw lr0,pr3 # X = save;
+ lshrw pr2,pr3 # X >>= nbi;
+ orw lr1,pr3 # X |= res;
+ movw pr3,(pr0) # *mm = X;
+ movw lr0,lr1 # res = save;
+ lshlw lr2,lr1 # res <<= lnbi;
+ subw $1,pr1 # ml--;
+ bge BSR1 # if(ml >= 0) goto BSR1;
+BSR2: movw lr1,pr0 # return(res);
+ ret
+
+ .globl _BnnAddCarry
+_BnnAddCarry: mtstw pr2,pr2
+ beq BAC3 # if(!carryin) return(0);
+ mtstw pr1,pr1
+ beq BAC2 # if(!nl) return(1);
+ subw $1,pr1 # nl--;
+BAC1: icmpw $0,(pr0) # Z = (++(nn) == 0);
+ bne BAC3 # if(!Z) goto BAC3;
+ addw $4,pr0 # nn++;
+ subw $1,pr1 # nl--
+ bge BAC1 # if(nl >= 0) goto BAC1;
+BAC2: movw $1,pr0 # return(1);
+ ret
+BAC3: movw $0,pr0 # return(0);
+ ret
+
+ .globl _BnnAdd
+_BnnAdd: subw pr3,pr1 # ml -= nl;
+ mtstw pr3,pr3
+ beq BADD5 # if(!nl) goto BADD5;
+BADD1: subw $1,pr3 # nl--;
+BADDX: movw (pr0),pr5 # X1 = *mm
+ bicpsw $1
+ bispsw pr4 # Set the carry C;
+ addwc (pr2),pr5 # X1 += *nn + C;
+ mpsw pr4
+ andw $1,pr4 # get the carry C;
+ movw pr5,(pr0) # *mm = X1;
+ addw $4,pr0 # mm++;
+ addw $4,pr2 # nn++;
+ subw $1,pr3 # nl--;
+ bge BADDX # if(nl >= 0) goto BADDX;
+BADD5: mtstw pr4,pr4
+ bne BADD7 # if(car) goto BADD7;
+BADD6: movw $0,pr0 # return(0);
+ ret
+BADD7: mtstw pr1,pr1
+ beq BADD9 # if(!ml) return(1);
+ subw $1,pr1 # ml--;
+BADD8: icmpw $0,(pr0) # Z = (++(mm) == 0);
+ bne BADD6 # if(!Z) goto BADD6;
+ addw $4,pr0 # nn++;
+ subw $1,pr1 # nl--
+ bge BADD8 # if(nl >= 0) goto BADD8;
+BADD9: movw $1,pr0 # return(1);
+ ret
+
+ .globl _BnnSubtractBorrow
+_BnnSubtractBorrow:
+ mtstw pr2,pr2
+ bne BSB3 # if(carryin) return(1);
+ mtstw pr1,pr1
+ beq BSB2 # if(!nl) return(1);
+ subw $1,pr1 # nl--;
+BSB1: dcmpw $-1,(pr0) # Z = (--(nn) == -1);
+ bne BSB3 # if(!Z) goto BSB3;
+ addw $4,pr0 # nn++;
+ subw $1,pr1 # nl--
+ bge BSB1 # if(nl >= 0) goto BSB1;
+BSB2: movw $0,pr0 # return(0);
+ ret
+BSB3: movw $1,pr0 # return(1);
+ ret
+
+
+ .globl _BnnSubtract
+_BnnSubtract: subw pr3,pr1 # ml -= nl;
+ mtstw pr3,pr3
+ beq BS5 # if(!nl) goto BS5;
+BS1: subw $1,pr3 # nl--;
+BSX: movw (pr0),pr5 # X1 = *mm
+ bicpsw $1
+ bispsw pr4 # Set the carry C;
+ subwb (pr2),pr5 # X1 -= *nn + C;
+ mpsw pr4
+ andw $1,pr4 # get the carry C;
+ movw pr5,(pr0) # *mm = X1;
+ addw $4,pr0 # mm++;
+ addw $4,pr2 # nn++;
+ subw $1,pr3 # nl--;
+ bge BSX # if(nl >= 0) goto BSX;
+BS5: mtstw pr4,pr4
+ beq BS7 # if(!car) goto BS7;
+BS6: movw $1,pr0 # return(1);
+ ret
+BS7: mtstw pr1,pr1
+ beq BS9 # if(!ml) return(1);
+ subw $1,pr1 # ml--;
+BS8: dcmpw $-1,(pr0) # Z = (--(mm) == -1);
+ bne BS6 # if(!Z) goto BS6;
+ addw $4,pr0 # nn++;
+ subw $1,pr1 # nl--
+ bge BS8 # if(nl >= 0) goto BS8;
+BS9: movw $0,pr0 # return(0);
+ ret
+
+ .globl _BnnMultiplyDigit # (pp, pl, mm, ml, d)
+_BnnMultiplyDigit:
+ mtstw pr4,pr4
+ bne BMD1 # if(!d) return(0);
+ movw $0,pr0
+ ret
+BMD1: ucmpw $1,pr4
+ bne BMD2 # if(d != 1) goto BMD2;
+ movw $0,pr4
+ br _BnnAdd # BnnAdd(p,pl,m,ml,0);
+BMD2: subw pr3,pr1 # pl -= ml;
+ movw $0,pr8 # Un zero.
+ movw pr8,pr7 # low = 0;
+ br BMD4
+BMD3: subw $1,pr3 # pl--;
+ movw (pr2),pr6 # X = *mm;
+ addw $4,pr2 # mm++;
+ uemul pr4,pr5 # X *= d;
+ addw pr7,pr6 # X += low;
+ addwc pr8,pr5 # X(hight) += Carry;
+ addw (pr0),pr6 # X += *pp;
+ addwc pr8,pr5 # X(hight) += Carry;
+ movw pr6,(pr0) # *pp = X(low);
+ addw $4,pr0 # pp++;
+ movw pr5,pr7 # low = X(Hight);
+BMD4: mtstw pr3,pr3
+ bne BMD3 # if(ml) goto BMD3;
+ addw (pr0),pr7 # low += *pp;
+ movw pr7,(pr0) # *pp = low;
+ bcs BMD7 # if(Carry) goto BMD7;
+BMD6: movw $0,pr0 # return(0);
+ ret
+BMD7: addw $4,pr0 # pp++;
+ subw $1,pr1 # pl--;
+ beq BMD10 # if(!pl) return(1);
+ subw $1,pr1 # pl--;
+BMD8: icmpw $0,(pr0) # Z = (++(*pp) == 0)
+ bne BMD6 # if(!!Z) goto BADD6;
+ addw $4,pr0 # pp++;
+ subw $1,pr1 # pl--
+ bge BMD8 # if(pl >= 0) goto BADD8;
+BMD10: movw $1,pr0 # return(1);
+ ret
+
+# The 64 bits/32 bits unsigned division, like in Vaxes, must be simulated
+#by a 64/32 signed division:
+#
+#N = D*Q + R
+#D = 2D' + d0
+#Cas 1: 0 <= D < 2^31
+#------
+# Sous-cas 1: N < D'*2^32 -> Calcul direct signe'
+# -----------
+#
+# Sous-cas 2: N >= D'*2^32
+# -----------
+# N = 2N' + n0
+# N' = DQ' + R' (0 <= R' < D)
+# N = 2DQ' + 2R' + n0 (0 <= 2R' + n0 < 2D)
+# Si 2R' + n0 < D
+# Q = 2Q' et R = 2R' + n0
+# sinon Q = 2Q' + 1 et R = 2R' + n0 - D
+#
+#Cas 2: 2^31 <= D < 2^32
+#------
+# N = 8N' + 4n2 + 2n1 + n0
+# N' = D'Q' + R' (0 <= R' <= D' - 1)
+# N = 8D'Q' + 8R' + 4n2 + 2n1 + n0
+# N = 4DQ' + 8R' + 4n2 + 2n1 + n0 - 4Q'd0
+# N = 4DQ' + 2(2(2R' + n2 - Q'd0) + n1) + n0 (0 <= 2R' + n2 < D)
+# Q' < 2^31 <= D
+# -D <= R1 = 2R' + n2 - Q'd0 < D
+# Si d0 = 1 et -D < R1 < 0
+# Q1 = Q' - 1; R1 = R1 + D
+# N = 4Q1D + 2(2R1 + n1) + n0
+# Q0 = 2Q1; R0 = 2R1 + n1
+# Si R2 >= D
+# Q0 = Q0 + 1; R2 = R2 - D
+# N = 2Q0 + 2R0 + n0
+# Q = 2Q0; R = 2R0 + n0
+# Si R >= d
+# Q = Q + 1; R = R - D
+ .globl _BnnDivideDigit # (qq, nn, nl, d)
+_BnnDivideDigit:
+ subw $1,pr2 # nl--;
+ mova (pr1)[pr2*0x4],pr1 # nn += nl;
+ mova (pr0)[pr2*0x4],pr0 # qq += nl;
+ movw (pr1),pr4 # N(Hight) = *nn;
+ movw pr3,pr6
+ lshrw $1,pr6 # D' = D >> 1;
+ mtstw pr3,pr3
+ bge BDD2
+ movw pr3,lr5
+ andw $1,lr5
+ movw $1,lr6 # lr6 <- 0x1FFFFFFF
+ lshlw $29,lr6 # pour le
+ subw $1,lr6 # shift arithme'tique
+ br BDD5
+BDD1: subw $4,pr1 # nn--;
+ movw (pr1),pr5 # N(low) = *nn;
+ ucmpw pr6,pr4
+ blt BDD11 # if(N < D'*2^32) goto BDD11;
+ movw pr5,lr0
+ andw $1,lr0 # n0 = N & 1;
+ ashrl $1,pr4 # N = N' = N / 2;
+ ediv pr3,pr4 # Q = N' / D
+ # R = N' % D
+ lshlw $1,pr4 # Q = 2Q
+ lshlw $1,pr5 # R = 2R;
+ addw lr0,pr5 # R = R + n0
+ ucmpw pr3,pr5
+ blt BDD12 # if(R < D) goto BDD12;
+ addw $1,pr4 # Q = Q + 1;
+ subw pr3,pr5 # R = R - D;
+ br BDD12 # goto BDD12
+BDD11: ediv pr3,pr4 # N(Hight) = N / d;
+ # N(low) = N % d;
+BDD12: subw $4,pr0 # qq--;
+ movw pr4,(pr0) # *qq = X(low);
+ movw pr5,pr4
+BDD2: subw $1,pr2
+ bge BDD1
+ movw pr4,pr0
+ ret
+
+BDD3: subw $4,pr1 # nn--;
+ movw (pr1),pr5 # N(low) = *nn;
+ movw pr5,lr0
+ andw $1,lr0 # lr0 = n0 = N & 1;
+ movw pr5,lr1
+ andw $2,lr1 # lr1 = 2n1 = N & 2;
+ movw pr5,lr2
+ andw $4,lr2 # lr2 = 4n2 = N & 4;
+ ashrl $3,pr4 # N = N' = N / 8;
+ andw lr6,pr4 # shift arithme'tique!!
+ ediv pr6,pr4 # Q' = N' / D';
+ # R' = N' % D';
+ addw pr5,pr5 # R1 = 2 * R'; Q1 = Q';
+ mtstw lr5,lr5
+ beq BDD33 # if(d0 == 0) goto BDD33;
+ ucmpw pr4,pr5
+ bge BDD32 # if(R1 >= Q') goto BDD32;
+ subw pr4,pr5 # R1 = R1 - Q'
+ subw $1,pr4 # Q1 = Q1 - 1;
+ addw pr3,pr5 # R1 = R1 + D;
+ br BDD33
+BDD32: subw pr4,pr5 # R1 = R1 - Q'
+BDD33: addw pr4,pr4 # Q0 = 2 * Q1;
+ addw pr5,pr5 # R0 = 2 * R1;
+ bcs BDD4
+ ucmpw pr3,pr5
+ blt BDD40 # if(R0 < D) goto BDD40;
+BDD4: addw $1,pr4 # Q0 = Q0 + 1;
+ subw pr3,pr5 # R0 = R0 - D
+BDD40: addw pr4,pr4 # Q = 2 * Q0;
+ addw pr5,pr5 # R = 2 * R0;
+ bcs BDD41
+ ucmpw pr3,pr5
+ blt BDD42 # if(R < D) goto BDD42;
+BDD41: addw $1,pr4 # Q = Q + 1;
+ subw pr3,pr5 # R = R - D;
+BDD42: addw lr2,pr5
+ addw lr1,pr5
+ addw lr0,pr5 # R = R + lr2 + lr1 + lr0;
+ ucmpw pr3,pr5
+ blt BDD43 # if(R < D) goto BDD43
+ addw $1,pr4 # Q = Q + 1;
+ subw pr3,pr5 # R = R - D;
+BDD43: subw $4,pr0 # qq--;
+ movw pr4,(pr0) # *qq = X(low);
+ movw pr5,pr4
+BDD5: subw $1,pr2
+ bge BDD3
+ movw pr4,pr0
+ ret
+
diff --git a/otherlibs/num/bignum/s/sparcKerN.s b/otherlibs/num/bignum/s/sparcKerN.s
new file mode 100644
index 000000000..2626d70c4
--- /dev/null
+++ b/otherlibs/num/bignum/s/sparcKerN.s
@@ -0,0 +1,643 @@
+! Copyright Digital Equipment Corporation 1991
+! Last modified_on Fri Mar 1 17:21:25 GMT+1:00 1991 by shand
+!
+! KerN for SPARC
+! Mark Shand
+!
+! Implementation notes:
+!
+! Initial implementations of sparc offer very limited support for
+! integer multiplication, so BnnMultiplyDigit is based on
+! double precision floating point multiplies that compute
+! a 16x32->48 bit result without round-off. Performance is
+! not great, but is about twice as good as using the integer
+! multiply primitives directly.
+!
+! BnnDivideDigit uses the unmodified assembly code produced
+! by cc -O2 KerN.c
+!
+ .seg "text" ! [internal]
+ .proc 16
+ .global _BnnSetToZero
+_BnnSetToZero:
+ deccc %o1
+ bneg LBSZ3 ! is zero
+ andcc 1,%o1,%o2
+ be LBSZ2 ! is odd
+ nop
+ dec 4,%o0
+LBSZ1: ! [internal]
+ inc 8,%o0
+ st %g0,[%o0-4]
+LBSZ2:
+ deccc 2,%o1
+ bpos LBSZ1
+ st %g0,[%o0]
+LBSZ3:
+ retl
+ nop ! [internal]
+!
+!
+ .proc 16
+ .global _BnnAssign
+_BnnAssign:
+ cmp %o0,%o1
+ bgt,a LBAG2 ! if(mm >= nn) goto LBAG2
+ tst %o2
+ be LBAGX
+ tst %o2
+ be LBAGX ! if(nl==0) return
+ nop
+LBAG1:
+ ld [%o1],%o3
+ inc 4,%o1
+ st %o3,[%o0]
+ deccc %o2
+ bgt LBAG1
+ inc 4,%o0
+LBAGX:
+ retl
+ nop
+LBAG2:
+ be LBAGX ! if(nl==0) return
+ sll %o2,2,%o3 ! nl <<= 2
+ add %o1,%o3,%o1 ! nn += nl
+ add %o0,%o3,%o0 ! mm += nl
+LBAG3:
+ dec 4,%o1
+ ld [%o1],%o3 ! %o3 = *--nn
+ dec 4,%o0
+ deccc %o2
+ bgt LBAG3
+ st %o3,[%o0] ! *--mm = %o3
+ retl
+ nop
+!
+!
+ .proc 16
+ .global _BnnSetDigit
+_BnnSetDigit:
+ retl
+ st %o1,[%o0]
+!
+!
+ .proc 14
+ .global _BnnGetDigit
+_BnnGetDigit:
+ retl
+ ld [%o0],%o0
+!
+!
+ .proc 14
+ .global _BnnNumDigits
+_BnnNumDigits:
+ tst %o1
+ sll %o1,2,%o3
+ be LBND2
+ add %o0,%o3,%o4
+ dec 4,%o4
+LBND1:
+ ld [%o4],%o2
+ tst %o2
+ bne LBND2
+ deccc %o1
+ bne,a LBND1
+ dec 4,%o4
+LBND2:
+ retl
+ add 1,%o1,%o0
+!
+!
+ .proc 14
+ .global _BnnNumLeadingZeroBitsInDigit
+_BnnNumLeadingZeroBitsInDigit:
+ addcc %o0,%g0,%o5 ! %o5 = d
+ be LBLZX ! if(!d) goto BLZX
+ sethi %hi(0xffff0000),%o1 ! mask = 0xffff0000
+ mov 1,%o0 ! p = 1
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ1
+ sll %o1,8,%o1
+ sll %o5,16,%o5
+ or 16,%o0,%o0
+LBLZ1:
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ2
+ sll %o1,4,%o1
+ sll %o5,8,%o5
+ or 8,%o0,%o0
+LBLZ2:
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ3
+ sll %o1,2,%o1
+ sll %o5,4,%o5
+ or 4,%o0,%o0
+LBLZ3:
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ4
+ nop
+ sll %o5,2,%o5
+ or 2,%o0,%o0
+LBLZ4:
+ srl %o5,31,%o5 ! %o5 = (d & 0x80000000) != 0
+ retl
+ xor %o0,%o5,%o0
+LBLZX:
+ retl
+ mov 32,%o0
+ .proc 4
+ .global _BnnDoesDigitFitInWord
+_BnnDoesDigitFitInWord:
+ retl
+ mov 1,%o0
+ .proc 4
+ .global _BnnIsDigitZero
+_BnnIsDigitZero:
+ tst %o0
+ bne,a LBDZ0
+ mov 0,%o1
+ mov 1,%o1
+LBDZ0:
+ retl
+ add %g0,%o1,%o0
+ .proc 4
+ .global _BnnIsDigitNormalized
+_BnnIsDigitNormalized:
+ retl
+ srl %o0,31,%o0
+ .proc 4
+ .global _BnnIsDigitOdd
+_BnnIsDigitOdd:
+ retl
+ and %o0,1,%o0
+ .proc 4
+ .global _BnnCompareDigits
+_BnnCompareDigits:
+ cmp %o0,%o1
+ bleu LBCD1
+ mov -1,%o0
+ retl
+ mov 1,%o0
+LBCD1: ! [internal]
+ be,a LBCD2
+ mov 0,%o0
+LBCD2:
+ retl
+ nop ! [internal]
+ .proc 16
+ .global _BnnComplement
+_BnnComplement:
+ deccc %o1
+ bneg LE129
+ nop
+LY11: ! [internal]
+ ld [%o0],%o2
+ xor %o2,-1,%o2
+ st %o2,[%o0]
+ deccc %o1
+ bpos LY11
+ inc 4,%o0
+LE129:
+ retl
+ nop ! [internal]
+ .proc 16
+ .global _BnnAndDigits
+_BnnAndDigits:
+ ld [%o0],%o2
+ and %o2,%o1,%o2
+ retl
+ st %o2,[%o0]
+ .proc 16
+ .global _BnnOrDigits
+_BnnOrDigits:
+ ld [%o0],%o2
+ or %o2,%o1,%o2
+ retl
+ st %o2,[%o0]
+ .proc 16
+ .global _BnnXorDigits
+_BnnXorDigits:
+ ld [%o0],%o2
+ xor %o2,%o1,%o2
+ retl
+ st %o2,[%o0]
+ .proc 14
+ .global _BnnShiftLeft
+_BnnShiftLeft:
+ tst %o2
+ be L77105
+ mov 0,%o4
+ deccc %o1
+ mov 32,%o3
+ bneg L77105
+ sub %o3,%o2,%o3
+LY12: ! [internal]
+ ld [%o0],%o5
+ sll %o5,%o2,%g1
+ or %g1,%o4,%g1
+ st %g1,[%o0]
+ deccc %o1
+ srl %o5,%o3,%o4
+ bpos LY12
+ inc 4,%o0
+L77105:
+ retl
+ add %g0,%o4,%o0
+ .proc 14
+ .global _BnnShiftRight
+_BnnShiftRight:
+ tst %o2
+ be L77114
+ mov 0,%o4
+ sll %o1,2,%g1
+ deccc %o1
+ mov 32,%o3
+ add %o0,%g1,%o0
+ bneg L77114
+ sub %o3,%o2,%o3
+LY13: ! [internal]
+ dec 4,%o0
+ ld [%o0],%o5
+ srl %o5,%o2,%g2
+ or %g2,%o4,%g2
+ deccc %o1
+ sll %o5,%o3,%o4
+ bpos LY13
+ st %g2,[%o0]
+L77114:
+ retl
+ add %g0,%o4,%o0
+ .proc 14
+ .global _BnnAddCarry ! (mm, ml, car)
+_BnnAddCarry:
+ tst %o2
+ be LBACX0 ! if(car == 0) return(0);
+ tst %o1
+ be LBACX1 ! if(nl == 0) return(1);
+ nop
+LBACL:
+ ld [%o0],%o3
+ inccc %o3
+ bcc LBACX0
+ st %o3,[%o0]
+ deccc %o1
+ bgt LBACL
+ inc 4,%o0
+LBACX1:
+ retl
+ mov 1,%o0
+LBACX0:
+ retl
+ mov 0,%o0
+ .proc 14
+ .global _BnnAdd ! (mm ml nn nl car)
+_BnnAdd:
+ sub %o1,%o3,%o1 ! ml -= nl
+ tst %o3
+ be,a _BnnAddCarry ! if (nl == 0) %o2 = car; goto AddCarry
+ mov %o4,%o2
+LBAD1:
+ ld [%o2],%o5 ! o5 = *nn
+ addcc -1,%o4,%g0 ! set C = carin
+ ld [%o0],%o4 ! o4 = *mm
+ inc 4,%o2
+ addxcc %o5,%o4,%o5 ! o5 = *mm + *nn, C = carout
+ addx %g0,%g0,%o4 ! o4 = carout
+ st %o5,[%o0]
+ deccc %o3
+ bne LBAD1
+ inc 4,%o0
+ b _BnnAddCarry
+ mov %o4,%o2
+ .proc 14
+ .global _BnnSubtractBorrow ! (mm, ml, car)
+_BnnSubtractBorrow:
+ tst %o2
+ bne LSBBX1 ! if(car == 1) return(1);
+ tst %o1
+ be LSBBX0 ! if(nl == 0) return(0);
+ nop
+LSBBL:
+ ld [%o0],%o3
+ deccc %o3
+ bcc LSBBX1
+ st %o3,[%o0]
+ deccc %o1
+ bgt LSBBL
+ inc 4,%o0
+LSBBX0:
+ retl
+ mov 0,%o0
+LSBBX1:
+ retl
+ mov 1,%o0
+ .proc 14
+ .global _BnnSubtract ! (mm ml nn nl car)
+_BnnSubtract:
+ sub %o1,%o3,%o1 ! ml -= nl
+ tst %o3
+ be,a _BnnSubtractBorrow ! if (nl == 0) %o2 = car; goto SubBorrow
+ mov %o4,%o2
+LSUB1:
+ ld [%o2],%o5 ! o5 = *nn
+ deccc %o4 ! set C = carin
+ ld [%o0],%o4 ! o4 = *mm
+ inc 4,%o2
+ subxcc %o4,%o5,%o5 ! o5 = *mm + *nn, C = carout
+ mov 1,%o4
+ subx %o4,%g0,%o4 ! o4 = carout
+ st %o5,[%o0]
+ deccc %o3
+ bne LSUB1
+ inc 4,%o0
+ b _BnnSubtractBorrow
+ mov %o4,%o2
+ .proc 14
+ .global _BnnMultiplyDigit
+_BnnMultiplyDigit:
+!#PROLOGUE# 0
+!#PROLOGUE# 1
+ tst %o4
+ bne LMDnonzero
+ cmp %o4,1
+ retl
+ mov 0,%o0
+LMDnonzero:
+ bne LMD0
+ mov 0,%o5
+ b _BnnAdd ! shortcut to BnnAdd
+ mov 0,%o4 ! carry in = 0
+LMD0:
+ save %sp,-96,%sp
+ tst %i3
+ be L77007
+ sub %i1,%i3,%l1
+LMD1:
+ ld [%i0],%l7
+ mov %i4,%y
+ ld [%i2],%l0
+ addcc %g0,%g0,%o0 ! initialize
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%l0,%o0; mulscc %o0,%l0,%o0;
+ mulscc %o0,%g0,%o0 ! align
+ tst %l0
+ blt,a LMDsignfix
+ add %o0,%i4,%o0
+LMDsignfix:
+ mov %o0,%o1
+ mov %y,%o0
+ addcc %o0,%i5,%i1
+ inc 4,%i2
+ addx %o1,%g0,%i5
+ addcc %l7,%i1,%l7
+ addx %g0,%i5,%i5
+ st %l7,[%i0]
+ deccc %i3
+ bgt LMD1
+ inc 4,%i0
+L77007:
+ tst %i5
+ be LMDexit
+ deccc %l1
+LY3: ! [internal]
+ blt LMDexit
+ inc 4,%i0
+ ld [%i0-4],%i1
+ addcc %i1,%i5,%i1
+ addxcc %g0,%g0,%i5
+ st %i1,[%i0-4]
+ bne,a LY3
+ deccc %l1
+LMDexit:
+ ret
+ restore %g0,%i5,%o0
+ .proc 14
+ .align 4
+ .global _BnnDivideDigit
+ .proc 016
+_BnnDivideDigit:
+ !#PROLOGUE# 0
+ save %sp,-120,%sp
+ !#PROLOGUE# 1
+ mov %i0,%l3
+ call _BnnNumLeadingZeroBitsInDigit,0
+ mov %i3,%o0
+ orcc %o0,%g0,%l6
+ be L146
+ mov %i1,%o0
+ mov %i2,%l7
+ sll %i3,%l6,%i3
+ mov %l7,%o1
+ ld [%l3-4],%o3
+ mov %l6,%o2
+ call _BnnShiftLeft,0
+ st %o3,[%fp-20]
+L146:
+ sll %i2,2,%o0
+ add %i1,%o0,%i1
+ add %i2,-1,%i2
+ sll %i2,2,%o0
+ add %l3,%o0,%l3
+ add %i1,-4,%i1
+ ld [%i1],%i0
+ cmp %i2,0
+ srl %i3,16,%l4
+ sethi %hi(65535),%o0
+ or %o0,%lo(65535),%o0
+ be L148
+ and %i3,%o0,%i4
+ sll %i4,16,%l5
+ mov %o0,%i5
+L163:
+ add %i2,-1,%i2
+ mov %i0,%l1
+ add %i1,-4,%i1
+ ld [%i1],%i0
+ mov %l1,%o0
+ call .udiv,0
+ mov %l4,%o1
+ mov %o0,%l2
+ mov %i4,%o0
+ call .umul,0
+ mov %l2,%o1
+ mov %o0,%l0
+ mov %l4,%o0
+ call .umul,0
+ mov %l2,%o1
+ mov %o0,%o2
+ srl %l0,16,%o0
+ add %o2,%o0,%o2
+ b L149
+ sll %l0,16,%l0
+L154:
+ bleu L155
+ add %l1,-1,%o0
+ cmp %l5,%l0
+L172:
+ bleu L152
+ add %l2,-1,%l2
+ sub %l0,%l5,%l0
+ add %o2,-1,%o0
+ b L149
+ sub %o0,%l4,%o2
+L152:
+ sub %l0,%l5,%l0
+ sub %o2,%l4,%o2
+L149:
+ cmp %o2,%l1
+ bgu L172
+ cmp %l5,%l0
+ cmp %o2,%l1
+ be L154
+ cmp %l0,%i0
+ bleu L155
+ add %l1,-1,%o0
+ sub %i0,%l0,%i0
+ b L156
+ sub %o0,%o2,%l1
+L155:
+ sub %i0,%l0,%i0
+ sub %l1,%o2,%l1
+L156:
+ add %l3,-4,%l3
+ sll %l2,16,%o0
+ st %o0,[%l3]
+ sll %l1,16,%o0
+ srl %i0,16,%o1
+ or %o0,%o1,%o0
+ call .udiv,0
+ mov %l4,%o1
+ mov %o0,%l2
+ mov %i4,%o0
+ call .umul,0
+ mov %l2,%o1
+ mov %o0,%l0
+ mov %l4,%o0
+ call .umul,0
+ mov %l2,%o1
+ mov %o0,%o2
+ srl %l0,16,%o0
+ add %o2,%o0,%o2
+ and %l0,%i5,%o1
+ and %o2,%i5,%o0
+ sll %o0,16,%o0
+ or %o1,%o0,%l0
+ b L157
+ srl %o2,16,%o2
+L162:
+ bleu,a L173
+ sub %i0,%l0,%i0
+ cmp %i3,%l0
+L174:
+ bleu L160
+ add %l2,-1,%l2
+ sub %l0,%i3,%l0
+ b L157
+ add %o2,-1,%o2
+L160:
+ sub %l0,%i3,%l0
+L157:
+ cmp %o2,%l1
+ bgu L174
+ cmp %i3,%l0
+ cmp %o2,%l1
+ be L162
+ cmp %l0,%i0
+ sub %i0,%l0,%i0
+L173:
+ ld [%l3],%o0
+ cmp %i2,0
+ or %l2,%o0,%o0
+ bne L163
+ st %o0,[%l3]
+L148:
+ cmp %l6,0
+ be L164
+ cmp %l3,%i1
+ bleu L175
+ sll %l7,2,%o0
+ add %i1,%o0,%o0
+ cmp %l3,%o0
+ bgeu L165
+ sub %l3,%i1,%o0
+ sra %o0,2,%l7
+ mov %i1,%o0
+ mov %l7,%o1
+ call _BnnShiftRight,0
+ mov %l6,%o2
+ sll %l7,2,%o0
+ ld [%fp-20],%o3
+ add %o0,%i1,%o0
+ b L164
+ st %o3,[%o0-4]
+L165:
+ cmp %l3,%i1
+L175:
+ bne L167
+ mov %i1,%o0
+ sll %l7,2,%o0
+ add %o0,-4,%o0
+ add %i1,%o0,%o0
+ b L170
+ mov 1,%o1
+L167:
+ mov %l7,%o1
+L170:
+ call _BnnShiftRight,0
+ mov %l6,%o2
+L164:
+ srl %i0,%l6,%i0
+ ret
+ restore
+ .seg "data" ! [internal]
+_copyright:
+ .half 0x4028
+ .half 0x2329
+ .half 0x4b65
+ .half 0x724e
+ .half 0x2e63
+ .half 0x3a20
+ .half 0x636f
+ .half 0x7079
+ .half 0x7269
+ .half 0x6768
+ .half 0x7420
+ .half 0x4469
+ .half 0x6769
+ .half 0x7461
+ .half 0x6c20
+ .half 0x4571
+ .half 0x7569
+ .half 0x706d
+ .half 0x656e
+ .half 0x7420
+ .half 0x436f
+ .half 0x7270
+ .half 0x6f72
+ .half 0x6174
+ .half 0x696f
+ .half 0x6e20
+ .half 0x2620
+ .half 0x494e
+ .half 0x5249
+ .half 0x4120
+ .half 0x3139
+ .half 0x3838
+ .half 0x2c20
+ .half 0x3139
+ .half 0x3839
+ .half 0xa00
diff --git a/otherlibs/num/bignum/s/sparcfpuKerN.s b/otherlibs/num/bignum/s/sparcfpuKerN.s
new file mode 100644
index 000000000..5e0a6dfd0
--- /dev/null
+++ b/otherlibs/num/bignum/s/sparcfpuKerN.s
@@ -0,0 +1,741 @@
+! Copyright Digital Equipment Corporation 1991
+! Last modified_on Fri Jan 25 23:11:58 GMT+1:00 1991 by shand
+!
+! KerN for SPARC
+! Mark Shand
+!
+! Implementation notes:
+!
+! Initial implementations of sparc offer very limited support for
+! integer multiplication, so BnnMultiplyDigit is based on
+! double precision floating point multiplies that compute
+! a 16x32->48 bit result without round-off. Performance is
+! not great, but is about twice as good as using the integer
+! multiply primitives directly.
+!
+! BnnDivideDigit uses the unmodified assembly code produced
+! by cc -O2 KerN.c
+!
+ .seg "text" ! [internal]
+ .proc 16
+ .global _BnnSetToZero
+_BnnSetToZero:
+ deccc %o1
+ bneg LBSZ3 ! is zero
+ andcc 1,%o1,%o2
+ be LBSZ2 ! is odd
+ nop
+ dec 4,%o0
+LBSZ1: ! [internal]
+ inc 8,%o0
+ st %g0,[%o0-4]
+LBSZ2:
+ deccc 2,%o1
+ bpos LBSZ1
+ st %g0,[%o0]
+LBSZ3:
+ retl
+ nop ! [internal]
+!
+!
+ .proc 16
+ .global _BnnAssign
+_BnnAssign:
+ cmp %o0,%o1
+ bgt,a LBAG2 ! if(mm >= nn) goto LBAG2
+ tst %o2
+ be LBAGX
+ tst %o2
+ be LBAGX ! if(nl==0) return
+ nop
+LBAG1:
+ ld [%o1],%o3
+ inc 4,%o1
+ st %o3,[%o0]
+ deccc %o2
+ bgt LBAG1
+ inc 4,%o0
+LBAGX:
+ retl
+ nop
+LBAG2:
+ be LBAGX ! if(nl==0) return
+ sll %o2,2,%o3 ! nl <<= 2
+ add %o1,%o3,%o1 ! nn += nl
+ add %o0,%o3,%o0 ! mm += nl
+LBAG3:
+ dec 4,%o1
+ ld [%o1],%o3 ! %o3 = *--nn
+ dec 4,%o0
+ deccc %o2
+ bgt LBAG3
+ st %o3,[%o0] ! *--mm = %o3
+ retl
+ nop
+!
+!
+ .proc 16
+ .global _BnnSetDigit
+_BnnSetDigit:
+ retl
+ st %o1,[%o0]
+!
+!
+ .proc 14
+ .global _BnnGetDigit
+_BnnGetDigit:
+ retl
+ ld [%o0],%o0
+!
+!
+ .proc 14
+ .global _BnnNumDigits
+_BnnNumDigits:
+ tst %o1
+ sll %o1,2,%o3
+ be LBND2
+ add %o0,%o3,%o4
+ dec 4,%o4
+LBND1:
+ ld [%o4],%o2
+ tst %o2
+ bne LBND2
+ deccc %o1
+ bne,a LBND1
+ dec 4,%o4
+LBND2:
+ retl
+ add 1,%o1,%o0
+!
+!
+ .proc 14
+ .global _BnnNumLeadingZeroBitsInDigit
+_BnnNumLeadingZeroBitsInDigit:
+ addcc %o0,%g0,%o5 ! %o5 = d
+ be LBLZX ! if(!d) goto BLZX
+ sethi %hi(0xffff0000),%o1 ! mask = 0xffff0000
+ mov 1,%o0 ! p = 1
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ1
+ sll %o1,8,%o1
+ sll %o5,16,%o5
+ or 16,%o0,%o0
+LBLZ1:
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ2
+ sll %o1,4,%o1
+ sll %o5,8,%o5
+ or 8,%o0,%o0
+LBLZ2:
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ3
+ sll %o1,2,%o1
+ sll %o5,4,%o5
+ or 4,%o0,%o0
+LBLZ3:
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ4
+ nop
+ sll %o5,2,%o5
+ or 2,%o0,%o0
+LBLZ4:
+ srl %o5,31,%o5 ! %o5 = (d & 0x80000000) != 0
+ retl
+ xor %o0,%o5,%o0
+LBLZX:
+ retl
+ mov 32,%o0
+ .proc 4
+ .global _BnnDoesDigitFitInWord
+_BnnDoesDigitFitInWord:
+ retl
+ mov 1,%o0
+ .proc 4
+ .global _BnnIsDigitZero
+_BnnIsDigitZero:
+ tst %o0
+ bne,a LBDZ0
+ mov 0,%o1
+ mov 1,%o1
+LBDZ0:
+ retl
+ add %g0,%o1,%o0
+ .proc 4
+ .global _BnnIsDigitNormalized
+_BnnIsDigitNormalized:
+ retl
+ srl %o0,31,%o0
+ .proc 4
+ .global _BnnIsDigitOdd
+_BnnIsDigitOdd:
+ retl
+ and %o0,1,%o0
+ .proc 4
+ .global _BnnCompareDigits
+_BnnCompareDigits:
+ cmp %o0,%o1
+ bleu LBCD1
+ mov -1,%o0
+ retl
+ mov 1,%o0
+LBCD1: ! [internal]
+ be,a LBCD2
+ mov 0,%o0
+LBCD2:
+ retl
+ nop ! [internal]
+ .proc 16
+ .global _BnnComplement
+_BnnComplement:
+ deccc %o1
+ bneg LE129
+ nop
+LY11: ! [internal]
+ ld [%o0],%o2
+ xor %o2,-1,%o2
+ st %o2,[%o0]
+ deccc %o1
+ bpos LY11
+ inc 4,%o0
+LE129:
+ retl
+ nop ! [internal]
+ .proc 16
+ .global _BnnAndDigits
+_BnnAndDigits:
+ ld [%o0],%o2
+ and %o2,%o1,%o2
+ retl
+ st %o2,[%o0]
+ .proc 16
+ .global _BnnOrDigits
+_BnnOrDigits:
+ ld [%o0],%o2
+ or %o2,%o1,%o2
+ retl
+ st %o2,[%o0]
+ .proc 16
+ .global _BnnXorDigits
+_BnnXorDigits:
+ ld [%o0],%o2
+ xor %o2,%o1,%o2
+ retl
+ st %o2,[%o0]
+ .proc 14
+ .global _BnnShiftLeft
+_BnnShiftLeft:
+ tst %o2
+ be L77105
+ mov 0,%o4
+ deccc %o1
+ mov 32,%o3
+ bneg L77105
+ sub %o3,%o2,%o3
+LY12: ! [internal]
+ ld [%o0],%o5
+ sll %o5,%o2,%g1
+ or %g1,%o4,%g1
+ st %g1,[%o0]
+ deccc %o1
+ srl %o5,%o3,%o4
+ bpos LY12
+ inc 4,%o0
+L77105:
+ retl
+ add %g0,%o4,%o0
+ .proc 14
+ .global _BnnShiftRight
+_BnnShiftRight:
+ tst %o2
+ be L77114
+ mov 0,%o4
+ sll %o1,2,%g1
+ deccc %o1
+ mov 32,%o3
+ add %o0,%g1,%o0
+ bneg L77114
+ sub %o3,%o2,%o3
+LY13: ! [internal]
+ dec 4,%o0
+ ld [%o0],%o5
+ srl %o5,%o2,%g2
+ or %g2,%o4,%g2
+ deccc %o1
+ sll %o5,%o3,%o4
+ bpos LY13
+ st %g2,[%o0]
+L77114:
+ retl
+ add %g0,%o4,%o0
+ .proc 14
+ .global _BnnAddCarry ! (mm, ml, car)
+_BnnAddCarry:
+ tst %o2
+ be LBACX0 ! if(car == 0) return(0);
+ tst %o1
+ be LBACX1 ! if(nl == 0) return(1);
+ nop
+LBACL:
+ ld [%o0],%o3
+ inccc %o3
+ bcc LBACX0
+ st %o3,[%o0]
+ deccc %o1
+ bgt LBACL
+ inc 4,%o0
+LBACX1:
+ retl
+ mov 1,%o0
+LBACX0:
+ retl
+ mov 0,%o0
+ .proc 14
+ .global _BnnAdd ! (mm ml nn nl car)
+_BnnAdd:
+ sub %o1,%o3,%o1 ! ml -= nl
+ tst %o3
+ be,a _BnnAddCarry ! if (nl == 0) %o2 = car; goto AddCarry
+ mov %o4,%o2
+LBAD1:
+ ld [%o2],%o5 ! o5 = *nn
+ addcc -1,%o4,%g0 ! set C = carin
+ ld [%o0],%o4 ! o4 = *mm
+ inc 4,%o2
+ addxcc %o5,%o4,%o5 ! o5 = *mm + *nn, C = carout
+ addx %g0,%g0,%o4 ! o4 = carout
+ st %o5,[%o0]
+ deccc %o3
+ bne LBAD1
+ inc 4,%o0
+ b _BnnAddCarry
+ mov %o4,%o2
+ .proc 14
+ .global _BnnSubtractBorrow ! (mm, ml, car)
+_BnnSubtractBorrow:
+ tst %o2
+ bne LSBBX1 ! if(car == 1) return(1);
+ tst %o1
+ be LSBBX0 ! if(nl == 0) return(0);
+ nop
+LSBBL:
+ ld [%o0],%o3
+ deccc %o3
+ bcc LSBBX1
+ st %o3,[%o0]
+ deccc %o1
+ bgt LSBBL
+ inc 4,%o0
+LSBBX0:
+ retl
+ mov 0,%o0
+LSBBX1:
+ retl
+ mov 1,%o0
+ .proc 14
+ .global _BnnSubtract ! (mm ml nn nl car)
+_BnnSubtract:
+ sub %o1,%o3,%o1 ! ml -= nl
+ tst %o3
+ be,a _BnnSubtractBorrow ! if (nl == 0) %o2 = car; goto SubBorrow
+ mov %o4,%o2
+LSUB1:
+ ld [%o2],%o5 ! o5 = *nn
+ deccc %o4 ! set C = carin
+ ld [%o0],%o4 ! o4 = *mm
+ inc 4,%o2
+ subxcc %o4,%o5,%o5 ! o5 = *mm + *nn, C = carout
+ mov 1,%o4
+ subx %o4,%g0,%o4 ! o4 = carout
+ st %o5,[%o0]
+ deccc %o3
+ bne LSUB1
+ inc 4,%o0
+ b _BnnSubtractBorrow
+ mov %o4,%o2
+ .proc 14
+ .global _BnnMultiplyDigit ! (pp pl mm ml d)
+! Assembler version of BnnMultiplyDigit is derived from the
+! following code.
+!
+! BigNumCarry
+! BnnMultiplyDigit(pp, pl, mm, ml, d)
+! register BigNum pp, mm;
+! int pl, ml;
+! BigNumDigit d;
+! {
+! register double fd, lowAlignR;
+! register BigNumDigit carry = 0;
+!
+! fd = (double) d;
+! lowAlignR = (65536.0*65536.0*65536.0*16.0);
+!
+! pl -= ml;
+!
+! while (ml--)
+! {
+! BigNumDigit md, pd;
+! register BigNumDigit tmp0, tmp1;
+! register double fmh, fml;
+! double fmlxd, fmhxd;
+!
+! md = *mm++;
+! pd = *pp;
+! fml = (double) (int) (md & 0xffff);
+! fmh = (double) (int) (md >> 16);
+! fmlxd = fd*fml + lowAlignR;
+! fmhxd = fd*fmh + lowAlignR;
+! pd += carry;
+! carry = (pd < carry);
+! tmp0 = ((unsigned long *)(&fmlxd))[1];
+! carry += (((unsigned long *)(&fmlxd))[0]) &0xffff;
+! if ((pd += tmp0) < tmp0) carry++;
+! tmp0 = ((unsigned long *)(&fmhxd))[1];
+! tmp1 = tmp0 << 16;
+! if ((pd += tmp1) < tmp1) carry++;
+! carry += (tmp0 >> 16);
+! carry += (((unsigned long *)(&fmhxd))[0]) << 16;
+! /* assert carry:pd = d*md + *pp + carry(in) */
+! *pp++ = pd;
+! }
+!
+! while (carry && pl--)
+! {
+! BigNumDigit pd;
+!
+! pd = *pp;
+! carry = (pd += carry) < carry;
+! *pp++ = pd;
+! }
+! return carry;
+! }
+_BnnMultiplyDigit:
+!#PROLOGUE# 0
+!#PROLOGUE# 1
+ save %sp,-120,%sp ! establish stack frame
+ st %i4,[%sp+LP61+32] ! mem = d
+ ld [%sp+LP61+32],%f0 ! f0 = d
+ fitod %f0,%f26 ! f26 = (double) d
+ mov 0,%i5 ! carry = 0
+ tst %i4 ! if (i >= 0)
+ bge LBMD1 ! goto LBMD1
+ sethi %hi(L2pwr32),%o0
+ ldd [%o0+%lo(L2pwr32)],%f4 ! f4 = 2^32
+ faddd %f26,%f4,%f26 ! f26 += 2^32
+LBMD1:
+ sethi %hi(L2pwr52),%o1
+ ldd [%o1+%lo(L2pwr52)],%f24 ! f24 = 2^52
+ tst %i3 ! ml?
+ be LBMDExit ! if (ml == 0)
+ sub %i1,%i3,%i1 ! goto LBMDExit; pl -= ml
+ st %g0,[%sp+LP61+32] ! clr [%sp+LP61+32]
+LBMDpxdLoop:
+ ld [%i2],%o4 ! o4 = md = *mm
+ sth %o4,[%sp+LP61+34] ! o4 & 0xffff -> mem
+ ld [%sp+LP61+32],%f7 ! f7 <- mem
+ fitod %f7,%f30 ! fml = (double) (md & 0xffff)
+ srl %o4,16,%o4 ! o4 = md >> 16
+ st %o4,[%sp+LP61+32] ! i4 -> mem
+ ! fitod + 8 cycles. f30 ready on SS1
+ fmuld %f26,%f30,%f12 ! f12 = fd * fml
+ ld [%sp+LP61+32],%f9 ! f9 <- mem
+ fitod %f9,%f28 ! fmh = (double) (md >> 16)
+ ld [%i0],%l7 ! pd = l7 = *pp
+ inc 4,%i2 ! mm++
+ inc 4,%i0 ! pp++
+ ! fmuld + 10 fitod + 6. f28 ready, mul/add unit available on SS1
+ faddd %f12,%f24,%f14 ! f14 = f12 + 2^52
+ fmuld %f26,%f28,%f16 ! f16 = fd * fmh
+ addcc %l7,%i5,%i4 ! pd += carry{in}
+ ! 1 cycle stall of faddd
+ st %f15,[%fp-4] ! fmlxd[low] = f15
+ ! fmuld + 9. f16 ready on SS1
+ faddd %f16,%f24,%f18 ! f18 = f16 + 2^52
+ st %f14,[%fp-8] ! fmlxd[high] = f14
+ ld [%fp-4],%l7 ! tmp0 = l7 = fmlxd[low]
+ lduh [%fp-6],%i5 ! i5 = fmlxd[high] & 0xffff
+ addx %g0,%i5,%i5 ! carry = (fmlxd[high] & 0xffff)+C
+ addcc %i4,%l7,%l7 ! pd += tmp0
+ st %f18,[%fp-16] ! fmhxd = f18
+ ld [%fp-16],%o4 ! o4 = fmhxd[high]
+ st %f19,[%fp-12] ! fmhxd = f18
+ ld [%fp-12],%o5 ! o5 = fmhxd[low]
+ sll %o5,16,%l3 ! l3 = fmhxd[low] << 16
+ srl %o5,16,%o5 ! o5 = fmhxd[low] >> 16
+ addx %i5,%o5,%i5 ! carry += (fmhxd[low] >> 16) + C
+ addcc %l7,%l3,%l7 ! pd += fmhxd[low] << 16
+ sll %o4,16,%l3 ! l3 = fmlxd[high] << 16
+ addx %i5,%l3,%i5 ! carry += fmlxd[high] << 16 + C
+ deccc %i3 ! ml--
+ bne LBMDpxdLoop ! if (ml > 0)
+ st %l7,[%i0-4] ! goto LBMDpxdLoop; pp[-1] = pd
+ tst %i5
+ be LBMDExit ! if (!carry)
+ nop ! goto LBMDExit
+LBMDacLoop:
+ deccc %i1
+ blt LBMDExit
+ ld [%i0],%i3
+ addcc %i3,%i5,%i3
+ addxcc %g0,%g0,%i5
+ st %i3,[%i0]
+ bne LBMDacLoop
+ inc 4,%i0
+LBMDExit:
+ ret
+ restore %g0,%i5,%o0
+LP61 = 64
+ .seg "data" ! [internal]
+ .align 8
+L2pwr32:
+ .word 0x41f00000
+ .word 0
+ .align 8
+L2pwr52:
+ .word 0x43300000
+ .word 0
+ .seg "text"
+ .proc 14
+ .global _BnnDivideDigit
+_BnnDivideDigit:
+!#PROLOGUE# 0
+!#PROLOGUE# 1
+ save %sp,-112,%sp
+ call _BnnNumLeadingZeroBitsInDigit,1
+ mov %i3,%o0
+ mov %o0,%o2
+ tst %o2
+ be L77225
+ st %o2,[%fp-8]
+ ld [%i0-4],%o4
+ st %i2,[%fp-16]
+ st %o4,[%fp-12]
+ mov %i2,%o1
+ mov %i1,%o0
+ call _BnnShiftLeft,3
+ sll %i3,%o2,%i3
+L77225:
+ sub %i2,1,%l2
+ sethi %hi(0xffff),%o1 ! [internal]
+ or %o1,%lo(0xffff),%o1 ! [internal]
+ sll %i2,2,%l3
+ add %i1,%l3,%l3
+ dec 4,%l3
+ ld [%l3],%i2
+ and %i3,%o1,%l1
+ sll %l2,2,%l4
+ tst %l2
+ srl %i3,16,%l6
+ mov %o1,%l0
+ sll %l1,16,%l7
+ add %i0,%l4,%l4
+ be L77249
+ add %l6,1,%l5
+LY43: ! [internal]
+ dec 4,%l3
+ ld [%l3],%i4
+ mov %i2,%i5
+ mov %i5,%o0
+ call .udiv,2
+ mov %l6,%o1
+ mov %o0,%i1
+ mov %l1,%o0
+ call .umul,2
+ mov %i1,%o1
+ mov %o0,%i2
+ mov %l6,%o0
+ call .umul,2
+ mov %i1,%o1
+ srl %i2,16,%i0
+ add %o0,%i0,%i0
+ cmp %i0,%i5
+ dec %l2
+ bgu L77232
+ sll %i2,16,%i2
+ cmp %i0,%i5
+ bne LY57
+ cmp %i2,%i4
+LY54: ! [internal]
+ bleu,a LY57
+ cmp %i2,%i4
+L77232:
+ cmp %l7,%i2
+LY55: ! [internal]
+ bleu L77234
+ dec %i1
+ sub %i2,%l7,%i2
+ b L77228
+ sub %i0,%l5,%i0
+LY56: ! [internal]
+ ld [%fp-4],%o3
+ ld [%fp+68],%i0
+ ld [%fp+80],%o1
+ dec 4,%o0
+ ld [%o0],%o0
+ sll %o3,32,%o3
+ call .udiv,2
+ or %o3,%o0,%o0
+ dec 4,%i0
+ st %o0,[%i0]
+ ld [%fp+76],%o0
+ tst %o0
+ bne,a LY56
+ ld [%fp+72],%o0
+ b L77259
+ ld [%fp-4],%i2
+L77234:
+ sub %i0,%l6,%i0
+ sub %i2,%l7,%i2
+L77228:
+ cmp %i0,%i5
+ bgu,a LY55
+ cmp %l7,%i2
+ cmp %i0,%i5
+ be LY54
+ cmp %i2,%i4
+LY57: ! [internal]
+ bleu LY47
+ sub %i4,%i2,%i4
+ inc %i0
+LY47: ! [internal]
+ sub %i5,%i0,%i5
+ sll %i5,16,%o0
+ srl %i4,16,%o7
+ sll %i1,16,%i1
+ dec 4,%l4
+ st %i1,[%l4]
+ mov %l6,%o1
+ or %o0,%o7,%o0
+ call .udiv,2
+ nop
+ mov %o0,%i1
+ mov %l1,%o0
+ call .umul,2
+ mov %i1,%o1
+ mov %o0,%i2
+ mov %l6,%o0
+ call .umul,2
+ mov %i1,%o1
+ mov %o0,%i0
+ srl %i2,16,%o0
+ add %i0,%o0,%i0
+ and %i0,%l0,%o2
+ srl %i0,16,%i0
+ cmp %i0,%i5
+ sll %o2,16,%o2
+ and %i2,%l0,%i2
+ bgu L77244
+ or %i2,%o2,%i2
+ cmp %i0,%i5
+ bne,a LY53
+ ld [%l4],%o1
+ cmp %i2,%i4
+LY51: ! [internal]
+ bleu,a LY53
+ ld [%l4],%o1
+L77244:
+ cmp %i3,%i2
+LY52: ! [internal]
+ bleu L77246
+ dec %i1
+ sub %i2,%i3,%i2
+ b L77240
+ dec %i0
+L77246:
+ sub %i2,%i3,%i2
+L77240:
+ cmp %i0,%i5
+ bgu,a LY52
+ cmp %i3,%i2
+ cmp %i0,%i5
+ be,a LY51
+ cmp %i2,%i4
+ ld [%l4],%o1
+LY53: ! [internal]
+ tst %l2
+ or %o1,%i1,%o1
+ sub %i4,%i2,%i2
+ bne LY43
+ st %o1,[%l4]
+L77249:
+ ld [%fp-8],%o2
+ tst %o2
+ be,a LY50
+ ld [%fp-8],%o1
+ cmp %l4,%l3
+ bleu,a LY49
+ cmp %l4,%l3
+ ld [%fp-16],%o4
+ sll %o4,2,%o4
+ add %l3,%o4,%o4
+ cmp %l4,%o4
+ bcc,a LY49
+ cmp %l4,%l3
+ sub %l4,%l3,%i0
+ sra %i0,2,%i0
+ mov %i0,%o1
+ call _BnnShiftRight,3
+ mov %l3,%o0
+ ld [%fp-12],%o4
+ dec %i0
+ sll %i0,2,%i0
+ b L77258
+ st %o4,[%l3+%i0]
+LY49: ! [internal]
+ bne,a LY48
+ ld [%fp-16],%o1
+ ld [%fp-16],%o0
+ mov 1,%o1
+ dec %o0
+ sll %o0,2,%o0
+ b LY42
+ add %l3,%o0,%o0
+LY48: ! [internal]
+ mov %l3,%o0
+LY42: ! [internal]
+ call _BnnShiftRight,3
+ ld [%fp-8],%o2
+L77258:
+ ld [%fp-8],%o1
+LY50: ! [internal]
+ srl %i2,%o1,%i2
+L77259:
+ ret
+ restore %g0,%i2,%o0
+ .seg "data" ! [internal]
+_copyright:
+ .half 0x4028
+ .half 0x2329
+ .half 0x4b65
+ .half 0x724e
+ .half 0x2e63
+ .half 0x3a20
+ .half 0x636f
+ .half 0x7079
+ .half 0x7269
+ .half 0x6768
+ .half 0x7420
+ .half 0x4469
+ .half 0x6769
+ .half 0x7461
+ .half 0x6c20
+ .half 0x4571
+ .half 0x7569
+ .half 0x706d
+ .half 0x656e
+ .half 0x7420
+ .half 0x436f
+ .half 0x7270
+ .half 0x6f72
+ .half 0x6174
+ .half 0x696f
+ .half 0x6e20
+ .half 0x2620
+ .half 0x494e
+ .half 0x5249
+ .half 0x4120
+ .half 0x3139
+ .half 0x3838
+ .half 0x2c20
+ .half 0x3139
+ .half 0x3839
+ .half 0xa00
diff --git a/otherlibs/num/bignum/s/supersparcKerN.s b/otherlibs/num/bignum/s/supersparcKerN.s
new file mode 100644
index 000000000..27c0b8120
--- /dev/null
+++ b/otherlibs/num/bignum/s/supersparcKerN.s
@@ -0,0 +1,469 @@
+! Copyright Digital Equipment Corporation 1991
+! Last modified on Fri Mar 1 17:21:25 GMT+1:00 1991 by shand
+!
+! KerN for SPARC
+! Mark Shand
+!
+! Implementation notes:
+!
+! Initial implementations of sparc offer very limited support for
+! integer multiplication, so BnnMultiplyDigit is based on
+! double precision floating point multiplies that compute
+! a 16x32->48 bit result without round-off. Performance is
+! not great, but is about twice as good as using the integer
+! multiply primitives directly.
+!
+! BnnDivideDigit uses the unmodified assembly code produced
+! by cc -O2 KerN.c
+!
+ .seg "text" ! [internal]
+ .proc 16
+ .global _BnnSetToZero
+_BnnSetToZero:
+ deccc %o1
+ bneg LBSZ3 ! is zero
+ andcc 1,%o1,%o2
+ be LBSZ2 ! is odd
+ nop
+ dec 4,%o0
+LBSZ1: ! [internal]
+ inc 8,%o0
+ st %g0,[%o0-4]
+LBSZ2:
+ deccc 2,%o1
+ bpos LBSZ1
+ st %g0,[%o0]
+LBSZ3:
+ retl
+ nop ! [internal]
+!
+!
+ .proc 16
+ .global _BnnAssign
+_BnnAssign:
+ cmp %o0,%o1
+ bgt,a LBAG2 ! if(mm >= nn) goto LBAG2
+ tst %o2
+ be LBAGX
+ tst %o2
+ be LBAGX ! if(nl==0) return
+ nop
+LBAG1:
+ ld [%o1],%o3
+ inc 4,%o1
+ st %o3,[%o0]
+ deccc %o2
+ bgt LBAG1
+ inc 4,%o0
+LBAGX:
+ retl
+ nop
+LBAG2:
+ be LBAGX ! if(nl==0) return
+ sll %o2,2,%o3 ! nl <<= 2
+ add %o1,%o3,%o1 ! nn += nl
+ add %o0,%o3,%o0 ! mm += nl
+LBAG3:
+ dec 4,%o1
+ ld [%o1],%o3 ! %o3 = *--nn
+ dec 4,%o0
+ deccc %o2
+ bgt LBAG3
+ st %o3,[%o0] ! *--mm = %o3
+ retl
+ nop
+!
+!
+ .proc 16
+ .global _BnnSetDigit
+_BnnSetDigit:
+ retl
+ st %o1,[%o0]
+!
+!
+ .proc 14
+ .global _BnnGetDigit
+_BnnGetDigit:
+ retl
+ ld [%o0],%o0
+!
+!
+ .proc 14
+ .global _BnnNumDigits
+_BnnNumDigits:
+ tst %o1
+ sll %o1,2,%o3
+ be LBND2
+ add %o0,%o3,%o4
+ dec 4,%o4
+LBND1:
+ ld [%o4],%o2
+ tst %o2
+ bne LBND2
+ deccc %o1
+ bne,a LBND1
+ dec 4,%o4
+LBND2:
+ retl
+ add 1,%o1,%o0
+!
+!
+ .proc 14
+ .global _BnnNumLeadingZeroBitsInDigit
+_BnnNumLeadingZeroBitsInDigit:
+ addcc %o0,%g0,%o5 ! %o5 = d
+ be LBLZX ! if(!d) goto BLZX
+ sethi %hi(0xffff0000),%o1 ! mask = 0xffff0000
+ mov 1,%o0 ! p = 1
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ1
+ sll %o1,8,%o1
+ sll %o5,16,%o5
+ or 16,%o0,%o0
+LBLZ1:
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ2
+ sll %o1,4,%o1
+ sll %o5,8,%o5
+ or 8,%o0,%o0
+LBLZ2:
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ3
+ sll %o1,2,%o1
+ sll %o5,4,%o5
+ or 4,%o0,%o0
+LBLZ3:
+ andcc %o1,%o5,%g0 ! mask & d
+ bne LBLZ4
+ nop
+ sll %o5,2,%o5
+ or 2,%o0,%o0
+LBLZ4:
+ srl %o5,31,%o5 ! %o5 = (d & 0x80000000) != 0
+ retl
+ xor %o0,%o5,%o0
+LBLZX:
+ retl
+ mov 32,%o0
+ .proc 4
+ .global _BnnDoesDigitFitInWord
+_BnnDoesDigitFitInWord:
+ retl
+ mov 1,%o0
+ .proc 4
+ .global _BnnIsDigitZero
+_BnnIsDigitZero:
+ tst %o0
+ bne,a LBDZ0
+ mov 0,%o1
+ mov 1,%o1
+LBDZ0:
+ retl
+ add %g0,%o1,%o0
+ .proc 4
+ .global _BnnIsDigitNormalized
+_BnnIsDigitNormalized:
+ retl
+ srl %o0,31,%o0
+ .proc 4
+ .global _BnnIsDigitOdd
+_BnnIsDigitOdd:
+ retl
+ and %o0,1,%o0
+ .proc 4
+ .global _BnnCompareDigits
+_BnnCompareDigits:
+ cmp %o0,%o1
+ bleu LBCD1
+ mov -1,%o0
+ retl
+ mov 1,%o0
+LBCD1: ! [internal]
+ be,a LBCD2
+ mov 0,%o0
+LBCD2:
+ retl
+ nop ! [internal]
+ .proc 16
+ .global _BnnComplement
+_BnnComplement:
+ deccc %o1
+ bneg LE129
+ nop
+LY11: ! [internal]
+ ld [%o0],%o2
+ xor %o2,-1,%o2
+ st %o2,[%o0]
+ deccc %o1
+ bpos LY11
+ inc 4,%o0
+LE129:
+ retl
+ nop ! [internal]
+ .proc 16
+ .global _BnnAndDigits
+_BnnAndDigits:
+ ld [%o0],%o2
+ and %o2,%o1,%o2
+ retl
+ st %o2,[%o0]
+ .proc 16
+ .global _BnnOrDigits
+_BnnOrDigits:
+ ld [%o0],%o2
+ or %o2,%o1,%o2
+ retl
+ st %o2,[%o0]
+ .proc 16
+ .global _BnnXorDigits
+_BnnXorDigits:
+ ld [%o0],%o2
+ xor %o2,%o1,%o2
+ retl
+ st %o2,[%o0]
+ .proc 14
+ .global _BnnShiftLeft
+_BnnShiftLeft:
+ tst %o2
+ be L77105
+ mov 0,%o4
+ deccc %o1
+ mov 32,%o3
+ bneg L77105
+ sub %o3,%o2,%o3
+LY12: ! [internal]
+ ld [%o0],%o5
+ sll %o5,%o2,%g1
+ or %g1,%o4,%g1
+ st %g1,[%o0]
+ deccc %o1
+ srl %o5,%o3,%o4
+ bpos LY12
+ inc 4,%o0
+L77105:
+ retl
+ add %g0,%o4,%o0
+ .proc 14
+ .global _BnnShiftRight
+_BnnShiftRight:
+ tst %o2
+ be L77114
+ mov 0,%o4
+ sll %o1,2,%g1
+ deccc %o1
+ mov 32,%o3
+ add %o0,%g1,%o0
+ bneg L77114
+ sub %o3,%o2,%o3
+LY13: ! [internal]
+ dec 4,%o0
+ ld [%o0],%o5
+ srl %o5,%o2,%g2
+ or %g2,%o4,%g2
+ deccc %o1
+ sll %o5,%o3,%o4
+ bpos LY13
+ st %g2,[%o0]
+L77114:
+ retl
+ add %g0,%o4,%o0
+ .proc 14
+ .global _BnnAddCarry ! (mm, ml, car)
+_BnnAddCarry:
+ tst %o2
+ be LBACX0 ! if(car == 0) return(0);
+ tst %o1
+ be LBACX1 ! if(nl == 0) return(1);
+ nop
+LBACL:
+ ld [%o0],%o3
+ inccc %o3
+ bcc LBACX0
+ st %o3,[%o0]
+ deccc %o1
+ bgt LBACL
+ inc 4,%o0
+LBACX1:
+ retl
+ mov 1,%o0
+LBACX0:
+ retl
+ mov 0,%o0
+ .proc 14
+ .global _BnnAdd ! (mm ml nn nl car)
+_BnnAdd:
+ sub %o1,%o3,%o1 ! ml -= nl
+ tst %o3
+ be,a _BnnAddCarry ! if (nl == 0) %o2 = car; goto AddCarry
+ mov %o4,%o2
+LBAD1:
+ ld [%o2],%o5 ! o5 = *nn
+ addcc -1,%o4,%g0 ! set C = carin
+ ld [%o0],%o4 ! o4 = *mm
+ inc 4,%o2
+ addxcc %o5,%o4,%o5 ! o5 = *mm + *nn, C = carout
+ addx %g0,%g0,%o4 ! o4 = carout
+ st %o5,[%o0]
+ deccc %o3
+ bne LBAD1
+ inc 4,%o0
+ b _BnnAddCarry
+ mov %o4,%o2
+ .proc 14
+ .global _BnnSubtractBorrow ! (mm, ml, car)
+_BnnSubtractBorrow:
+ tst %o2
+ bne LSBBX1 ! if(car == 1) return(1);
+ tst %o1
+ be LSBBX0 ! if(nl == 0) return(0);
+ nop
+LSBBL:
+ ld [%o0],%o3
+ deccc %o3
+ bcc LSBBX1
+ st %o3,[%o0]
+ deccc %o1
+ bgt LSBBL
+ inc 4,%o0
+LSBBX0:
+ retl
+ mov 0,%o0
+LSBBX1:
+ retl
+ mov 1,%o0
+ .proc 14
+ .global _BnnSubtract ! (mm ml nn nl car)
+_BnnSubtract:
+ sub %o1,%o3,%o1 ! ml -= nl
+ tst %o3
+ be,a _BnnSubtractBorrow ! if (nl == 0) %o2 = car; goto SubBorrow
+ mov %o4,%o2
+LSUB1:
+ ld [%o2],%o5 ! o5 = *nn
+ deccc %o4 ! set C = carin
+ ld [%o0],%o4 ! o4 = *mm
+ inc 4,%o2
+ subxcc %o4,%o5,%o5 ! o5 = *mm + *nn, C = carout
+ mov 1,%o4
+ subx %o4,%g0,%o4 ! o4 = carout
+ st %o5,[%o0]
+ deccc %o3
+ bne LSUB1
+ inc 4,%o0
+ b _BnnSubtractBorrow
+ mov %o4,%o2
+ .proc 14
+ .global _BnnMultiplyDigit
+_BnnMultiplyDigit:
+!#PROLOGUE# 0
+!#PROLOGUE# 1
+ tst %o4
+ bne LMDnonzero
+ cmp %o4,1
+ retl
+ mov 0,%o0
+LMDnonzero:
+ bne LMD0
+ mov 0,%o5
+ b _BnnAdd ! shortcut to BnnAdd
+ mov 0,%o4 ! carry in = 0
+LMD0:
+ save %sp,-96,%sp
+ tst %i3
+ be L77007
+ sub %i1,%i3,%l1
+LMD1:
+ ld [%i0],%l7
+ ld [%i2],%l0
+ umul %l0,%i4,%o0
+ mov %y,%o1
+ addcc %o0,%i5,%i1
+ inc 4,%i2
+ addx %o1,%g0,%i5
+ addcc %l7,%i1,%l7
+ addx %g0,%i5,%i5
+ st %l7,[%i0]
+ deccc %i3
+ bgt LMD1
+ inc 4,%i0
+L77007:
+ tst %i5
+ be LMDexit
+ deccc %l1
+LY3: ! [internal]
+ blt LMDexit
+ inc 4,%i0
+ ld [%i0-4],%i1
+ addcc %i1,%i5,%i1
+ addxcc %g0,%g0,%i5
+ st %i1,[%i0-4]
+ bne,a LY3
+ deccc %l1
+LMDexit:
+ ret
+ restore %g0,%i5,%o0
+ .proc 14
+ .global _BnnDivideDigit
+_BnnDivideDigit:
+! BnnDivideDigit(qq, nn, nl, d)
+
+ save %sp,-96,%sp
+ mov %i0, %i5
+ deccc %i2 ! --%i2;
+ sll %i2, 2, %i2
+ blt bnnout
+ ld [%i1+%i2], %i0 ! X(hight) = %i1[%i2];
+bnndivloop:
+
+ deccc 4, %i2 ! --%i2;
+! condition code remains unchanged until bgt at loop end
+ ld [%i1+%i2], %i4 ! X(%i4) = %i1[%i2];
+ mov %i0, %y
+ udiv %i4, %i3, %l0 ! %l0 = %i0,%i4 / %i3;
+ umul %l0, %i3, %l1 ! %l1 = %l0 * %i3;
+ sub %i4, %l1, %i0 ! %i0 = %i0,%i4 % %i3;
+ bgt bnndivloop ! if (%i2 > 0) goto divloop;
+ st %l0,[%i5+%i2] ! %i5[%i2] = %l0;
+bnnout:
+ ret
+ restore
+
+ .seg "data" ! [internal]
+_copyright:
+ .half 0x4028
+ .half 0x2329
+ .half 0x4b65
+ .half 0x724e
+ .half 0x2e63
+ .half 0x3a20
+ .half 0x636f
+ .half 0x7079
+ .half 0x7269
+ .half 0x6768
+ .half 0x7420
+ .half 0x4469
+ .half 0x6769
+ .half 0x7461
+ .half 0x6c20
+ .half 0x4571
+ .half 0x7569
+ .half 0x706d
+ .half 0x656e
+ .half 0x7420
+ .half 0x436f
+ .half 0x7270
+ .half 0x6f72
+ .half 0x6174
+ .half 0x696f
+ .half 0x6e20
+ .half 0x2620
+ .half 0x494e
+ .half 0x5249
+ .half 0x4120
+ .half 0x3139
+ .half 0x3838
+ .half 0x2c20
+ .half 0x3139
+ .half 0x3839
+ .half 0xa00
+
diff --git a/otherlibs/num/bignum/s/unix2vms.sed b/otherlibs/num/bignum/s/unix2vms.sed
new file mode 100644
index 000000000..ba273375c
--- /dev/null
+++ b/otherlibs/num/bignum/s/unix2vms.sed
@@ -0,0 +1,28 @@
+s/^# >>> IMPORTANT <<< DO NOT MODIFY THIS LINE$/# >>> IMPORTANT <<< DO NOT MODIFY THIS FILE -- IT IS GENERATED FROM vaxKerN.s/
+s/^\([^#"]*\)#/\1;/
+/^\.set callee_save,~63$/s// callee_save = ^C3/
+{
+: all_at
+s/^\([^;"]*\)\*/\1@/
+t all_at
+}
+{
+: all_d
+s/^\([^;"]*\)\$/\1#/
+t all_d
+}
+s/^0x/^X/
+{
+: all_hex
+s/^\([^;"]*[^0-9A-Za-z_;"]\)0x/\1^X/
+t all_hex
+}
+{
+: all_usB
+s/^\([^;"]*\)_B/\1B/
+t all_usB
+}
+s/\.data[ ][ ]*;\(.*\)$/.psect \1,noexe,quad/
+s/\.text[ ][ ]*;\(.*\)$/.psect \1,exe,shr,pic,nowrt,quad/
+$a\
+ .end
diff --git a/otherlibs/num/bignum/s/vaxKerN.mar b/otherlibs/num/bignum/s/vaxKerN.mar
new file mode 100644
index 000000000..b6d4f95d7
--- /dev/null
+++ b/otherlibs/num/bignum/s/vaxKerN.mar
@@ -0,0 +1,701 @@
+; Copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990
+;
+; KerN for the VAX.
+; [Bepaul, Shand]
+; Last modified_on Mon Apr 2 21:03:05 GMT+2:00 1990 by shand
+; modified_on Mon Nov 20 13:51:10 GMT+1:00 1989 by herve
+; modified_on 17-OCT-1989 20:37:48 by Jim Lawton
+;
+; >>> IMPORTANT <<< DO NOT MODIFY THIS FILE -- IT IS GENERATED FROM vaxKerN.s
+;
+; >>> READ THIS <<<
+;
+; This file is automatically converted from unix to VAX/VMS assembler format.
+; On VMS it is the callee's rsponsiblity to save all modified registers
+; other than r0 and r1. On Ultrix r0-r5 are considered saved by caller.
+; Specify procedure entry masks that save ALL modified registers (including
+; r0 and r1) and "&" them with "callee_save" which is a predefined constant
+; that eliminates the saves which are unnecessary under whichever calling
+; convention the file is being assembler for.
+ callee_save = ^C3
+ ; WARNING: text after comment used in conversion to VMS format assembler
+ .psect vaxKerN_data,noexe,quad
+_copyright: .ascii "@(#)vaxKerN.s: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\12\0"
+ ; WARNING: text after comment used in conversion to VMS format assembler
+ .psect vaxKerN,exe,shr,pic,nowrt,quad
+ .globl BnnSetToZero
+ .align 3
+BnnSetToZero:
+ .word ^X3&callee_save ; mask<r0,r1>
+ movl 4(ap),r0 ; nn
+ movl 8(ap),r1 ; nl
+ sobgeq r1,LSTZ1 ; if(nl--) goto LSTZ1
+ ret ; return;
+LSTZ1: clrl (r0)+ ; *(nn++) = 0;
+ sobgeq r1,LSTZ1 ; if(nl--) goto LSTZ1;
+ ret
+
+ .globl BnnAssign
+ .align 3
+BnnAssign:
+ .word ^X7&callee_save ; mask<r0,r1,r2>
+ movl 4(ap),r0 ; mm
+ movl 8(ap),r1 ; nn
+ movl 12(ap),r2 ; nl
+ cmpl r0,r1
+ bgequ LAG2 ; if(mm >= nn) goto LAG2;
+ sobgeq r2,LAG1 ; if(nl--) goto LAG1;
+ ret ; return;
+LAG1: movl (r1)+,(r0)+ ; *(mm++) = *(nn++);
+ sobgeq r2,LAG1 ; if(nl--) goto LAG1;
+LAG2: blequ LAG4 ; if(mm <= nn) goto LAG4;
+ moval (r0)[r2],r0 ; mm = &mm[nl];
+ moval (r1)[r2],r1 ; nn = &nn[nl];
+ sobgeq r2,LAG3 ; if(nl--) goto LAG3;
+ ret ; return;
+LAG3: movl -(r1),-(r0) ; *(--mm) = *(--nn);
+ sobgeq r2,LAG3 ; if(nl--) goto LAG3;
+LAG4: ret ; return;
+
+ .globl BnnSetDigit
+ .align 3
+BnnSetDigit:
+ .word ^X0&callee_save ; mask<>
+ movl 8(ap),@4(ap) ; *nn = d;
+ ret
+
+ .globl BnnGetDigit
+ .align 3
+BnnGetDigit:
+ .word ^X0&callee_save ; mask<>
+ movl @4(ap),r0 ; return(*nn);
+ ret
+
+ .globl BnnNumDigits
+ .align 3
+BnnNumDigits:
+ .word ^X2&callee_save ; mask<r1>
+ movl 8(ap),r0 ; nl
+ moval @4(ap)[r0],r1 ; nn = &nn[nd];
+ sobgeq r0,LND1 ; if(nl-- != 0) goto LND1;
+ movl #1,r0
+ ret ; return(1);
+LND1: tstl -(r1)
+ bneq LND3 ; if(*(--n) != 0) goto LND3;
+ sobgeq r0,LND1 ; if(nl-- != 0) goto LND1;
+ movl #1,r0
+ ret ; return(1);
+LND3: incl r0
+ ret ; return(nl + 1);
+
+ .globl BnnNumLeadingZeroBitsInDigit
+ .align 3
+BnnNumLeadingZeroBitsInDigit:
+ .word ^X2&callee_save ; mask<r1>
+ movl 4(ap),r1 ; d
+ movl #31,r0
+LLZ1: bbs r0,r1,LLZ2
+ sobgeq r0,LLZ1
+LLZ2: subl3 r0,#31,r0
+ ret
+
+ .globl BnnDoesDigitFitInWord
+ .align 3
+BnnDoesDigitFitInWord:
+ .word ^X0&callee_save ; mask<>
+ movl #1,r0 ; C_VERSION
+ ret
+
+ .globl BnnIsDigitZero
+ .align 3
+BnnIsDigitZero:
+ .word ^X2&callee_save ; mask<r1>
+ tstl 4(ap) ; d
+ bneq LDZ1 ; if(d) goto LDZ1;
+ movl #1,r0
+ ret ; return(1);
+LDZ1: clrl r0
+ ret ; return(0);
+
+ .globl BnnIsDigitNormalized
+; Boolean BnIsDigitNormalized(n, nd) BigNum n; int nd; {
+ .align 3
+BnnIsDigitNormalized:
+ .word ^X0&callee_save ; mask<>
+ movl 4(ap),r0 ; d
+ extzv #31,#1,r0,r0 ; return(d >> 31);
+ ret
+
+ .globl BnnIsDigitOdd
+ .align 3
+BnnIsDigitOdd:
+ .word ^X0&callee_save ; mask<>
+ bicl3 #-2,4(ap),r0 ; return(d || 1);
+ ret
+
+ .globl BnnCompareDigits
+ .align 3
+BnnCompareDigits:
+ .word ^X0&callee_save ; mask<>
+ cmpl 4(ap),8(ap) ; cmpl d1,d2
+ beql LCDeq ; if(d0 == d1) goto LCDeq
+ blssu LCDinf ; if(d0 < d1) goto LCDinf
+ movl #1,r0 ; return(1);
+ ret
+LCDeq: clrl r0 ; return(0);
+ ret
+LCDinf: movl #-1,r0 ; return(-1);
+ ret
+
+ .globl BnnComplement
+ .align 3
+BnnComplement:
+ .word ^X2&callee_save ; mask<r1>
+ movl 4(ap),r0 ; nn
+ movl 8(ap),r1 ; nl
+ sobgeq r1,LCM1 ; if(nl-- != 0) goto LCM1;
+ ret
+LCM1: mcoml (r0),(r0)+ ; *(n++) ^= -1;
+ sobgeq r1,LCM1 ; if(nl-- != 0) goto LCM1;
+ ret
+
+ .globl BnnAndDigits
+ .align 3
+BnnAndDigits:
+ .word ^X0&callee_save ; mask<>
+ mcoml 8(ap),r0 ; d = ~d;
+ bicl2 r0,@4(ap) ; *nn &= ~d;
+ ret
+
+ .globl BnnOrDigits
+ .align 3
+BnnOrDigits:
+ .word ^X0&callee_save ; mask<>
+ bisl2 8(ap),@4(ap) ; *nn |= d;
+ ret
+
+ .globl BnnXorDigits
+ .align 3
+BnnXorDigits:
+ .word ^X0&callee_save ; mask<>
+ xorl2 8(ap),@4(ap) ; *nn ^= d;
+ ret
+
+ .globl BnnShiftLeft
+ .align 3
+BnnShiftLeft:
+ .word ^X7E&callee_save ; mask<r1,r2,r3,r4,r5,r6>
+ clrl r0 ; res = 0;
+ movl 12(ap),r3 ; nbi
+ bneq LSL0 ; if(nbi) goto LSL0
+ ret ; return(res);
+LSL0: movl 4(ap),r2 ; mm
+ movl 8(ap),r1 ; ml
+ subl3 r3,#32,r4 ; rnbi = BN_DIGIT_SIZE - nbi;
+ sobgeq r1,LSL1 ; if(ml-- != 0) goto LSL1;
+ ret ; return(res);
+LSL1: movl (r2),r5 ; save = *mm
+ ashl r3,r5,r6 ; X = save << nbi;
+ bisl3 r0,r6,(r2)+ ; *(mm++) = X | res;
+ extzv r4,r3,r5,r0 ; res = save >> rnbits;
+ sobgeq r1,LSL1 ; if(ml-- != 0) goto LSL1;
+ ret ; return(res);
+
+ .globl BnnShiftRight
+ .align 3
+BnnShiftRight:
+ .word ^X7E&callee_save ; mask<r1,r2,r3,r4,r5,r6>
+ clrl r0 ; res = 0;
+ movl 12(ap),r3 ; nbi
+ bneq LSR0 ; if(nbi) goto LSR0;
+ ret ; return(res);
+LSR0: movl 8(ap),r1 ; ml
+ moval @4(ap)[r1],r2 ; mm = &mm[ml];
+ subl3 r3,#32,r4 ; lnbi = BN_DIGIT_SIZE - nbi;
+ sobgeq r1,LSR1 ; if(ml-- != 0) goto LSR1;
+ ret ; return(res);
+LSR1: movl -(r2),r5 ; save = *(--mm);
+ extzv r3,r4,r5,r6 ; X = save >> nbi;
+ bisl3 r0,r6,(r2) ; *mm = X | res;
+ ashl r4,r5,r0 ; res = save << lnbi;
+ sobgeq r1,LSR1 ; if(ml-- != 0) goto LSR1;
+ ret ; return(res);
+
+ .globl BnnAddCarry
+ .align 3
+BnnAddCarry:
+ .word ^X2&callee_save ; mask<r1>
+ movl 12(ap),r0 ; car
+ beql LAC3 ; if(car == 0) return(car);
+ movl 8(ap),r0 ; nl
+ beql LAC2 ; if(nl == 0) return(1);
+ movl 4(ap),r1 ; nn
+LAC1: incl (r1)+ ; ++(*nn++);
+ bcc LAC4 ; if(!Carry) goto LAC4
+ sobgtr r0,LAC1 ; if(--nl > 0) goto LAC1;
+LAC2: movl #1,r0 ; return(1);
+LAC3: ret
+LAC4: clrl r0 ; return(0);
+ ret
+
+ .globl BnnAdd
+ .align 3
+BnnAdd:
+ .word ^X1E&callee_save ; mask<r1,r2,r3,r4>
+LADDEntry: movl 4(ap),r0 ; mm
+ movl 12(ap),r1 ; nn
+ movl 16(ap),r3 ; nl
+ bneq LADD1 ; if(nl) goto LADD1
+ subl3 r3,8(ap),r2 ; ml -= nl;
+ tstl 20(ap) ; car
+ bneq LADD5 ; if(car) goto LADD5
+ clrl r0
+ ret ; return(0);
+LADD1: subl3 r3,8(ap),r2 ; ml -= nl;
+ addl3 20(ap),#-1,r4 ; C = car
+
+LADD2: adwc (r1)+,(r0)+ ; *(m++) += *(n++) + C;
+LADD3: sobgtr r3,LADD2 ; if(--nl > 0) goto LADD2;
+ bcs LADD5 ; if(C) goto LADD5;
+LADD4: clrl r0
+ ret
+
+LADD6: incl (r0)+ ; ++(*m++);
+ bcc LADD4 ; if(!C) goto LADD4;
+LADD5: sobgeq r2,LADD6 ; if(--ml >= 0) goto LADD6;
+LADD7: movl #1,r0
+ ret
+
+ .globl BnnSubtractBorrow
+ .align 3
+BnnSubtractBorrow:
+ .word ^X2&callee_save ; mask<r1>
+ movl 12(ap),r0 ; car
+ bneq LSB2 ; if(car) return(car);
+ movl 8(ap),r0 ; nl
+ beql LSB20 ; if(nl == 0) return(0);
+ movl 4(ap),r1 ; nn
+LSB1: decl (r1)+ ; (*nn++)--;
+ bcc LSB3 ; if(!Carry) goto LSB3;
+ sobgtr r0,LSB1 ; if(--nl > 0) goto LSB1;
+LSB20: ; assert r0 == 0 return(0);
+LSB2: ret
+LSB3: movl #1,r0 ; return(1);
+ ret
+
+ .globl BnnSubtract
+ .align 3
+BnnSubtract:
+ .word ^X1E&callee_save ; mask<r1,r2,r3,r4>
+ movl 4(ap),r2 ; mm
+ movl 12(ap),r1 ; nn
+ movl 16(ap),r3 ; nl
+ bneq LS1 ; if(nl) goto LS1
+ subl3 r3,8(ap),r0 ; ml -= nl;
+ tstl 20(ap) ; car
+ beql LS5 ; if(car) goto LS5
+ movl #1,r0
+ ret ; return(1);
+LS1: subl3 r3,8(ap),r0 ; ml -= nl;
+ tstl 20(ap) ; C = 0; Z = (car == 0)
+ bneq LS2 ; if(!(Z = (car == 0))) goto LS2
+ addl3 #1,#-1,r4 ; C = 1;
+
+LS2: sbwc (r1)+,(r2)+ ; C..*m++ -= *n++ + C
+ sobgtr r3,LS2 ; if(--nl > 0) goto LS2
+ bcs LS5
+LS3: movl #1,r0
+ ret
+LS4: decl (r2)+
+ bcc LS3
+LS5: sobgeq r0,LS4 ; if (--ml >= 0) goto LS4
+ clrl r0
+ ret
+
+ .globl BnnMultiplyDigit
+; note1: (2^32-1)*(2^32-1) = 2^64-1 - 2*(2^32-1)
+; thus 64 bits accomodates a*b+c+d for all a,b,c,d < 2^32
+; note2: inner loop is doubled to avoid unnecessary register moves.
+ .align 3
+BnnMultiplyDigit:
+ .word ^X1FE&callee_save ; mask<r1,r2,r3,r4,r5,r6,r7,r8>
+ movl 20(ap),r2 ; r2 = d
+ blss LMDNeg ; if (d<0) goto LMDNeg
+ bneq LMD1 ; if (d) goto LMD1;
+ clrl r0
+ ret
+LMD1: cmpl #1,r2
+ bneq LMD2 ; if (d != 1) goto LMD2
+ clrl 20(ap) ; IN BnnAdd: car = 0
+ brw LADDEntry ; BnnAdd(pp,pl,mm,ml,0);
+
+LMD2: movl 4(ap),r3 ; r3 = p
+ movl 12(ap),r1 ; r1 = m
+ movl 16(ap),r7 ; r7 = ml
+ subl3 r7,8(ap),r8 ; r8 = pl-ml
+ ashl #-1,r7,r0 ; loop counter r0 = (ml+1)/2
+ clrl r5
+ bitl #1,r7
+ bneq LMDPOddLen ; if (ml is odd) goto LMDPOddLen
+ clrl r7
+ brb LMDPEvenLen ; if (ml is even) goto LMDPOddLen
+LMDPLoop: emul (r1)+,r2,#0,r4 ; r4:r5 = m[i]*d
+ bgeq LMDMPos1 ; if (m[i] < 0)
+ addl2 r2,r5 ; r5 += d
+LMDMPos1: addl2 r7,r4 ; r4 = (m[i]*d)%2^32+(m[i-1]*d)/2^32+C
+ adwc #0,r5 ; r5 = (m[i]*d)/2^32 + carry1
+ addl2 r4,(r3)+ ; *p++ += r4
+ adwc #0,r5 ; r5 = (m[i]*d)/2^32 + carry2
+LMDPOddLen: emul (r1)+,r2,#0,r6 ; r6:r7 = m[i+1]*d
+ bgeq LMDMPos2 ; if (m[i+1] < 0)
+ addl2 r2,r7 ; r7 += d
+LMDMPos2: addl2 r5,r6 ; r6 = (m[i+1]*d)%2^32+(m[i]*d)/2^32+C
+ adwc #0,r7 ; r7 = (m[i+1]*d)/2^32 + carry1
+ addl2 r6,(r3)+ ; *p++ += r6
+ adwc #0,r7 ; r7 = (m[i+1]*d)/2^32 + carry2
+LMDPEvenLen: sobgeq r0,LMDPLoop ; if ((i+=2)/2 < ml/2) repeat loop
+ addl2 r7,(r3)+ ; *p += (m[ml-1]*d)/2^32
+ bcs LMDTail
+LMDRet0: clrl r0
+ ret
+
+LMDNeg: movl 4(ap),r3 ; r3 = p
+ movl 12(ap),r1 ; r1 = m
+ movl 16(ap),r7 ; r7 = ml
+ subl3 r7,8(ap),r8 ; r8 = pl-ml
+ ashl #-1,r7,r0 ; loop counter r0 = (ml+1)/2
+ clrl r5
+ bitl #1,r7
+ bneq LMDNOddLen
+ clrl r7
+ brb LMDNEvenLen
+LMDNLoop: movl (r1)+,r6 ; r6 = m[i]
+ emul r6,r2,#0,r4 ; r4:r5 = m[i]*d
+ bleq LMDMPos3 ; if (m[i] < 0)
+ addl2 r2,r5 ; r5 += d
+LMDMPos3: addl2 r6,r5 ; r5 += m[i]
+ addl2 r7,r4 ; r4 = (m[i]*d)%2^32+(m[i-1]*d)/2^32+C
+ adwc #0,r5 ; r5 = (m[i]*d)/2^32 + carry1
+ addl2 r4,(r3)+ ; *p++ += r4
+ adwc #0,r5 ; r5 = (m[i]*d)/2^32 + carry2
+LMDNOddLen: movl (r1)+,r4 ; r6 = m[i+1]
+ emul r4,r2,#0,r6 ; r6:r7 = m[i+1]*d
+ bleq LMDMPos4 ; if (m[i+1] < 0)
+ addl2 r2,r7 ; r7 += d
+LMDMPos4: addl2 r4,r7 ; r7 += m[i+1]
+ addl2 r5,r6 ; r6 = (m[i+1]*d)%2^32+(m[i]*d)/2^32+C
+ adwc #0,r7 ; r7 = (m[i+1]*d)/2^32 + carry1
+ addl2 r6,(r3)+ ; *p++ += r6
+ adwc #0,r7 ; r7 = (m[i+1]*d)/2^32 + carry2
+LMDNEvenLen: sobgeq r0,LMDNLoop ; if ((i+=2)/2 < ml/2) repeat loop
+ addl2 r7,(r3)+ ; *p += (m[ml-1]*d)/2^32
+ bcs LMDTail
+ clrl r0 ; r0 = carry
+ ret
+
+LMDTailLoop: incl (r3)+
+ bcc LMDRet0
+LMDTail: sobgtr r8,LMDTailLoop
+ movl #1,r0 ; r0 = carry
+ ret
+
+ .globl BnnDivideDigit
+ .align 3
+BnnDivideDigit:
+ .word ^X3FE&callee_save ; mask<r1,r2,r3,r4,r5,r6,r7,r8,r9>
+ movl 12(ap),r2 ; nl
+ movl 16(ap),r3 ; d
+ moval @8(ap)[r2],r0 ; nn = &nn[nl];
+ decl r2 ; nl--;
+ moval @4(ap)[r2],r1 ; qq = &qq[nl];
+ movl -(r0),r5 ; X(hight) = *(--n);
+ extzv #1,#31,r3,r7 ; r7 = D' <- D div 2
+ tstl r3
+ bgeq Lndivc2
+ brw Lndiv5 ; D < 0!!
+
+ ; D < 2**31
+ brb Lndivc2 ; N < D * 2**32
+Lndivc1: movl -(r0),r4 ; (bdivu dx3 ax1 dx1)
+ cmpl r5,r7
+ blss Lndivc11
+ extzv #0,#1,r4,r6 ; r6 <- n0
+ ashq #-1,r4,r4 ; N' = r4 = N quo 2 < D * 2**31
+ ediv r3,r4,r4,r5 ; r4 <- Q' = N' quo D < 2**31
+ ; r5 <- R' = N' rem D < D
+ ashq #1,r4,r4 ; r4 <- 2 * Q' < 2**32
+ ; r5 <- 2 * R' < 2 * D
+ addl2 r6,r5 ; r5 <- 2 * R' + n0 < 2 * D
+ cmpl r5,r3 ; r5 < D -> Q = r4, R = r5
+ blssu Lndivc12 ; sinon
+ incl r4 ; Q = r4 + 1
+ subl2 r3,r5 ; R = r5 - D
+ brb Lndivc12
+Lndivc11: ediv r3,r4,r4,r5 ; Q = r4, R = r5
+Lndivc12: movl r4,-(r1) ; range r4 en me'moire
+Lndivc2: sobgeq r2,Lndivc1 ; (sobgez dx2 Lndivc1)
+ movl r5,r0 ; return(X(hight));
+ ret
+
+Lndiv3: movl -(r0),r4 ; r4 poid faible de N
+ extzv #0,#1,r4,r9 ; r9 <- n0
+ extzv #1,#1,r4,r6 ; r6 <- n1
+ extzv #2,#1,r4,r8 ; r8 <- n2
+ ashq #-3,r4,r4 ; r4 <- N'' = N quo 4
+ bicl2 #^XE0000000,r5 ; Le ashq ne le fait pas
+ ediv r7,r4,r4,r5 ; r4 <- Q' = N''' quo D'
+ ; r5 <- R' = N''' rem D'
+ ashl #1,r5,r5 ; r5 <- 2 * R'
+ addl2 r8,r5 ; r5 <- 2 * R' + n2
+ bbc #0,r3,Lndiv4 ; si d0 = 0
+ cmpl r5,r4 ; sinon r5 <- 2R' + n1 - Q'
+ blssu Lndiv30 ; la diff est < 0
+ subl2 r4,r5 ; la diff est > 0
+ brb Lndiv4 ; voila la diff!
+Lndiv30: subl2 r4,r5 ; la diff!
+ decl r4 ; r4 <- r4 - 1
+ addl2 r3,r5 ; r5 <- r5 + D
+Lndiv4: ashl #1,r4,r4 ; r4 <- 2Q'
+ addl2 r5,r5 ; r5 <- 2r5
+ bisl2 r6,r5 ; r5 <- r5 + n1 (flag C ok!)
+ bcs Lndiv40 ; On deborde sur!
+ cmpl r5,r3
+ blssu Lndiv42 ; depasse pas D
+Lndiv40: incl r4 ; Q = r4 + 1
+ subl2 r3,r5 ; R = r5 - D
+Lndiv42: ashl #1,r4,r4 ; r4 <- 2Q'
+ addl2 r5,r5 ; r5 <- 2r5
+ bisl2 r9,r5 ; r5 <- r5 + n0 (flag C ok!)
+ bcs Lndiv43 ; On deborde sur!
+ cmpl r5,r3
+ blssu Lndiv44 ; depasse pas D
+Lndiv43: incl r4 ; Q = r4 + 1
+ subl2 r3,r5 ; R = r5 - D
+Lndiv44: movl r4,-(r1) ; range le quotient en memoire
+Lndiv5: sobgeq r2,Lndiv3 ; On continue!
+ movl r5,r0 ; return(X(hight));
+ ret
+
+; BigNumCarry BnnMultiply (pp, pl, mm, ml, nn, nl)
+; BigNum pp, nn, mm;
+; BigNumLength pl, nl, ml;
+
+.globl BnnMultiply
+ .align 3
+BnnMultiply:
+ .word ^XFFE&callee_save ; mask<r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
+ movl 24(ap),r9 ; r9 = nl
+ bneq LMM_nl_pos
+LMM_Ret0a:
+ clrl r0
+LMM_Ret:
+ ret
+LMM_nl_pos:
+ movl 20(ap),r11 ; nn
+ cmpl 12(ap),r11 ; if (nn == mm)
+ beql BMM_Sqr
+LMM_NotSqr:
+ movl 4(ap),r10 ; pp
+ clrl r8 ; c_hi
+LMM_NLoop:
+ movl 16(ap),r7 ; ml
+ movl 12(ap),r1 ; mm
+ moval (r10)+,r3 ; pp
+ clrl r5 ; c_lo
+ movl (r11)+,r2 ; digit
+ bsbw BMM_MultiplyDigit
+ sobgtr r9,LMM_NLoop
+ movl r8,r0
+ beql LMM_Ret
+ movl 16(ap),r7 ; r7 = ml
+ subl3 r7,8(ap),r1 ; r7 = pl-ml
+ subl2 24(ap),r1 ; r7 = pl-ml-nl
+ bleq LMM_Ret
+ moval (r10)[r7],r10 ; pp += ml
+LMM_PLoop:
+ incl (r10)+
+ bcc LMM_Ret0a
+ sobgtr r1,LMM_PLoop
+ ret
+; Special squaring code based on:
+; n[0..nl-1]*n[0..nl-1] = sum (i = 0..nl-1):
+; B^2i * (n[i]*n[i] + 2*n[i] * n[i+1..nl-1] * B)
+; the 2*n[i] is tricky because it may overflow, but ...
+; suppose L[i] = 2*n[i]%2^32
+; and H[i] = 2*n[i]/2^32
+; Then:
+; sum (i = 0..nl-1):
+; B^2i * (n[i]*n[i] + L[i]+H[i-1] * n[i+1..nl-1] * B + H[i-1]*n[i])
+; notice that when i = nl-1 the final term is 2*n[nl-1] * n[nl..nl-1],
+; n[nl..nl-1] is zero length -- i.e. we can ignore it!
+; lastly we don't have quite enough registers to conveniently remember
+; the top bit of n[i-1] we encode it in the PC by duplicating
+; the loop--sometimes I love assembler.
+LMMS_NNLoop:
+ ; execute this version of loop if n[i-1] was >= 2^31
+ movl (r11)+,r0 ; d = r0 = *nn++
+ movl r11,r1 ; r1 = mm
+ emul r0,r0,#0,r4 ; r4:r5 = d*d
+ addl2 r0,r4 ; r4 += (2*n[i-1])/2^32*n[i] (= d)
+ adwc #0,r5
+ addl2 r4,(r10)+ ; *pp++ += d*d%2^32
+ adwc #0,r5 ; r5 += C
+ moval (r10)+,r3 ; arg-p = pp++
+ movl r9,r7 ; arg-ml = ml
+ addl3 r0,r0,r2 ; if (d >= 0)
+ bisl2 #1,r2
+ bcc LMMS_DPos ; switch to < 2^31 loop
+LMMS_DNeg:
+ addl2 r0,r5 ; compensate for signed mul
+ addl2 r0,r5 ; r4:r5 += 2*r2*2^32
+ tstl r2 ; set condition codes for entry to subr
+ ; MultiplyDigit(pp=r3, mm=r1, ml=r7, d=r2, c_hi=r8, c_lo=r5)
+ bsbb BMM_MultiplyDigit
+ sobgeq r9,LMMS_NNLoop
+ brb LMMS_Post
+; >>> ENTRY <<<
+BMM_Sqr:
+ ; r9 = nl, r11 = nn
+ movl 16(ap),r8 ; r8 = ml
+ bneq LMMS_ml_pos
+ clrl r0
+ ret ; return 0;
+LMMS_ml_pos:
+ cmpl r8,r9 ; if (ml != nl)
+ bneq LMM_NotSqr
+
+ ; r8 = 0, r9 = nl, r11 = nn, r10 = sgn(nn[nl-1])
+ movl 4(ap),r10 ; r10 = pp
+ ; r11 = nn
+ clrl r8 ; r8 = high carry = 0
+ decl r9 ; r9 = ml-1 = nl-1
+LMMS_NLoop:
+ ; execute this version of loop if n[i-1] was < 2^31
+ movl (r11)+,r0 ; d = r0 = *nn++
+ movl r11,r1 ; r1 = mm
+ emul r0,r0,#0,r4 ; r4:r5 = d*d
+ addl2 r4,(r10)+ ; *pp++ += d*d%2^32
+ adwc #0,r5 ; r5 += C
+ moval (r10)+,r3 ; arg-p = pp++
+ movl r9,r7 ; arg-ml = ml
+ addl3 r0,r0,r2 ; if (d < 0)
+ bcs LMMS_DNeg ; switch to >= 2^31 loop
+LMMS_DPos:
+ tstl r2 ; set condition codes for entry to subr
+ ; MultiplyDigit(pp=r3, mm=r1, ml=r7, d=r2, c_hi=r8, c_lo=r5)
+ bsbb BMM_MultiplyDigit
+ sobgeq r9,LMMS_NLoop
+ ; r9 = 0, r10 = pp+2*ml, r2 = 2*nn[nl-1], r8 = carry_hi, r11 = nn+nl
+LMMS_Post:
+ movl r8,r0
+ bneq LMMS_CProp ; if (c != 0)
+LMMS_ret:
+ ret ; return
+LMMS_CProp:
+ movl 16(ap),r7 ; r7 = nl
+ subl3 r7,8(ap),r2 ; r2 = pl-nl (note nl == ml)
+ subl2 r7,r2 ; r2 = pl-nl-ml
+ bleq LMMS_ret ; if (pl-nl > ml)
+ ; ret = BnnAddCarry(pp+ml, pl-ml, c);
+LMMS_CPLoop:
+ incl (r10)+ ; (*pp++)++
+ bcc LMMS_Ret0
+ sobgtr r2,LMMS_CPLoop
+ ret
+LMMS_Ret0:
+ clrl r0
+ ret
+
+; Subroutine: MultiplyDigit(pp,mm,ml,d,c_hi,c_lo)
+; returns:
+; c_hi*base^(ml+1)+ pp[0..ml] = pp[0..ml]+(mm[0..ml-1]*d)+c_hi*base^ml+c_lo
+;
+; In:
+; ml_entry:r7
+; ml/2: r0
+; mm: r1
+; digit: r2
+; pp: r3
+; c_hi: r8
+; c_lo: r5
+;
+; multiply scratch: r4,r5 / r6,r7
+;
+; Out:
+; c_hi: r8
+LMMD_C_hi:
+ addl2 r8,(r3)[r7] ; p[ml] += c_hi
+ clrl r8
+ adwc #0,r8
+ rsb
+LMMD_Zero:
+ tstl r5 ; Too complicated, return to
+ beql LMMD_ZC_lo ; normal case.
+ tstl r2
+ brb LMMD_Retry
+LMMD_ZC_lo:
+ tstl r8
+ bneq LMMD_C_hi
+ rsb
+BMM_MultiplyDigit:
+ beql LMMD_Zero
+LMMD_Retry:
+ blss LMMD_Neg ; if (d<0) goto LMMD_Neg
+ ashl #-1,r7,r0 ; loop counter r0 = ml/2
+ bitl #1,r7
+ bneq LMMD_POddLen ; if (ml is odd) goto LMMD_POddLen
+ movl r5,r7
+ brb LMMD_PEvenLen ; if (ml is even) goto LMMD_POddLen
+LMMD_PLoop: emul (r1)+,r2,#0,r4 ; r4:r5 = m[i]*d
+ bgeq LMMD_MPos1 ; if (m[i] < 0)
+ addl2 r2,r5 ; r5 += d
+LMMD_MPos1: addl2 r7,r4 ; r4 = (m[i]*d)%2^32+(m[i-1]*d)/2^32+C
+ adwc #0,r5 ; r5 = (m[i]*d)/2^32 + carry1
+ addl2 r4,(r3)+ ; *p++ += r4
+ adwc #0,r5 ; r5 = (m[i]*d)/2^32 + carry2
+LMMD_POddLen: emul (r1)+,r2,#0,r6 ; r6:r7 = m[i+1]*d
+ bgeq LMMD_MPos2 ; if (m[i+1] < 0)
+ addl2 r2,r7 ; r7 += d
+LMMD_MPos2: addl2 r5,r6 ; r6 = (m[i+1]*d)%2^32+(m[i]*d)/2^32+C
+ adwc #0,r7 ; r7 = (m[i+1]*d)/2^32 + carry1
+ addl2 r6,(r3)+ ; *p++ += r6
+ adwc #0,r7 ; r7 = (m[i+1]*d)/2^32 + carry2
+LMMD_PEvenLen: sobgeq r0,LMMD_PLoop ; if ((i+=2)/2 < ml/2) repeat loop
+ addl2 r8,r7
+ clrl r8
+ adwc #0,r8
+ addl2 r7,(r3) ; *p += (m[ml-1]*d)/2^32
+ adwc #0,r8
+ rsb
+LMMD_Neg:
+ ashl #-1,r7,r0 ; loop counter r0 = ml/2
+ bitl #1,r7
+ bneq LMMD_NOddLen
+ movl r5,r7
+ brb LMMD_NEvenLen
+LMMD_NLoop: movl (r1)+,r6 ; r6 = m[i]
+ emul r6,r2,#0,r4 ; r4:r5 = m[i]*d
+ bleq LMMD_MPos3 ; if (m[i] < 0)
+ addl2 r2,r5 ; r5 += d
+LMMD_MPos3: addl2 r6,r5 ; r5 += m[i]
+ addl2 r7,r4 ; r4 = (m[i]*d)%2^32+(m[i-1]*d)/2^32+C
+ adwc #0,r5 ; r5 = (m[i]*d)/2^32 + carry1
+ addl2 r4,(r3)+ ; *p++ += r4
+ adwc #0,r5 ; r5 = (m[i]*d)/2^32 + carry2
+LMMD_NOddLen: movl (r1)+,r4 ; r6 = m[i+1]
+ emul r4,r2,#0,r6 ; r6:r7 = m[i+1]*d
+ bleq LMMD_MPos4 ; if (m[i+1] < 0)
+ addl2 r2,r7 ; r7 += d
+LMMD_MPos4: addl2 r4,r7 ; r7 += m[i+1]
+ addl2 r5,r6 ; r6 = (m[i+1]*d)%2^32+(m[i]*d)/2^32+C
+ adwc #0,r7 ; r7 = (m[i+1]*d)/2^32 + carry1
+ addl2 r6,(r3)+ ; *p++ += r6
+ adwc #0,r7 ; r7 = (m[i+1]*d)/2^32 + carry2
+LMMD_NEvenLen: sobgeq r0,LMMD_NLoop ; if ((i+=2)/2 < ml/2) repeat loop
+ addl2 r8,r7
+ clrl r8
+ adwc #0,r8
+ addl2 r7,(r3) ; *p += (m[ml-1]*d)/2^32
+ adwc #0,r8
+ rsb
+.end
diff --git a/otherlibs/num/bignum/s/vaxKerN.s b/otherlibs/num/bignum/s/vaxKerN.s
new file mode 100644
index 000000000..c9f5d716d
--- /dev/null
+++ b/otherlibs/num/bignum/s/vaxKerN.s
@@ -0,0 +1,700 @@
+# Copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990
+#
+# KerN for the VAX.
+# [Bepaul, Shand]
+# Last modified_on Mon Apr 2 21:03:05 GMT+2:00 1990 by shand
+# modified_on Mon Nov 20 13:51:10 GMT+1:00 1989 by herve
+# modified_on 17-OCT-1989 20:37:48 by Jim Lawton
+#
+# >>> IMPORTANT <<< DO NOT MODIFY THIS LINE
+#
+# >>> READ THIS <<<
+#
+# This file is automatically converted from unix to VAX/VMS assembler format.
+# On VMS it is the callee's rsponsiblity to save all modified registers
+# other than r0 and r1. On Ultrix r0-r5 are considered saved by caller.
+# Specify procedure entry masks that save ALL modified registers (including
+# r0 and r1) and "&" them with "callee_save" which is a predefined constant
+# that eliminates the saves which are unnecessary under whichever calling
+# convention the file is being assembler for.
+.set callee_save,~63
+ # WARNING: text after comment used in conversion to VMS format assembler
+ .data # vaxKerN_data
+_copyright: .ascii "@(#)vaxKerN.s: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\12\0"
+ # WARNING: text after comment used in conversion to VMS format assembler
+ .text # vaxKerN
+ .globl _BnnSetToZero
+ .align 3
+_BnnSetToZero:
+ .word 0x3&callee_save # mask<r0,r1>
+ movl 4(ap),r0 # nn
+ movl 8(ap),r1 # nl
+ sobgeq r1,LSTZ1 # if(nl--) goto LSTZ1
+ ret # return;
+LSTZ1: clrl (r0)+ # *(nn++) = 0;
+ sobgeq r1,LSTZ1 # if(nl--) goto LSTZ1;
+ ret
+
+ .globl _BnnAssign
+ .align 3
+_BnnAssign:
+ .word 0x7&callee_save # mask<r0,r1,r2>
+ movl 4(ap),r0 # mm
+ movl 8(ap),r1 # nn
+ movl 12(ap),r2 # nl
+ cmpl r0,r1
+ bgequ LAG2 # if(mm >= nn) goto LAG2;
+ sobgeq r2,LAG1 # if(nl--) goto LAG1;
+ ret # return;
+LAG1: movl (r1)+,(r0)+ # *(mm++) = *(nn++);
+ sobgeq r2,LAG1 # if(nl--) goto LAG1;
+LAG2: blequ LAG4 # if(mm <= nn) goto LAG4;
+ moval (r0)[r2],r0 # mm = &mm[nl];
+ moval (r1)[r2],r1 # nn = &nn[nl];
+ sobgeq r2,LAG3 # if(nl--) goto LAG3;
+ ret # return;
+LAG3: movl -(r1),-(r0) # *(--mm) = *(--nn);
+ sobgeq r2,LAG3 # if(nl--) goto LAG3;
+LAG4: ret # return;
+
+ .globl _BnnSetDigit
+ .align 3
+_BnnSetDigit:
+ .word 0x0&callee_save # mask<>
+ movl 8(ap),*4(ap) # *nn = d;
+ ret
+
+ .globl _BnnGetDigit
+ .align 3
+_BnnGetDigit:
+ .word 0x0&callee_save # mask<>
+ movl *4(ap),r0 # return(*nn);
+ ret
+
+ .globl _BnnNumDigits
+ .align 3
+_BnnNumDigits:
+ .word 0x2&callee_save # mask<r1>
+ movl 8(ap),r0 # nl
+ moval *4(ap)[r0],r1 # nn = &nn[nd];
+ sobgeq r0,LND1 # if(nl-- != 0) goto LND1;
+ movl $1,r0
+ ret # return(1);
+LND1: tstl -(r1)
+ bneq LND3 # if(*(--n) != 0) goto LND3;
+ sobgeq r0,LND1 # if(nl-- != 0) goto LND1;
+ movl $1,r0
+ ret # return(1);
+LND3: incl r0
+ ret # return(nl + 1);
+
+ .globl _BnnNumLeadingZeroBitsInDigit
+ .align 3
+_BnnNumLeadingZeroBitsInDigit:
+ .word 0x2&callee_save # mask<r1>
+ movl 4(ap),r1 # d
+ movl $31,r0
+LLZ1: bbs r0,r1,LLZ2
+ sobgeq r0,LLZ1
+LLZ2: subl3 r0,$31,r0
+ ret
+
+ .globl _BnnDoesDigitFitInWord
+ .align 3
+_BnnDoesDigitFitInWord:
+ .word 0x0&callee_save # mask<>
+ movl $1,r0 # C_VERSION
+ ret
+
+ .globl _BnnIsDigitZero
+ .align 3
+_BnnIsDigitZero:
+ .word 0x2&callee_save # mask<r1>
+ tstl 4(ap) # d
+ bneq LDZ1 # if(d) goto LDZ1;
+ movl $1,r0
+ ret # return(1);
+LDZ1: clrl r0
+ ret # return(0);
+
+ .globl _BnnIsDigitNormalized
+# Boolean BnIsDigitNormalized(n, nd) BigNum n; int nd; {
+ .align 3
+_BnnIsDigitNormalized:
+ .word 0x0&callee_save # mask<>
+ movl 4(ap),r0 # d
+ extzv $31,$1,r0,r0 # return(d >> 31);
+ ret
+
+ .globl _BnnIsDigitOdd
+ .align 3
+_BnnIsDigitOdd:
+ .word 0x0&callee_save # mask<>
+ bicl3 $-2,4(ap),r0 # return(d || 1);
+ ret
+
+ .globl _BnnCompareDigits
+ .align 3
+_BnnCompareDigits:
+ .word 0x0&callee_save # mask<>
+ cmpl 4(ap),8(ap) # cmpl d1,d2
+ beql LCDeq # if(d0 == d1) goto LCDeq
+ blssu LCDinf # if(d0 < d1) goto LCDinf
+ movl $1,r0 # return(1);
+ ret
+LCDeq: clrl r0 # return(0);
+ ret
+LCDinf: movl $-1,r0 # return(-1);
+ ret
+
+ .globl _BnnComplement
+ .align 3
+_BnnComplement:
+ .word 0x2&callee_save # mask<r1>
+ movl 4(ap),r0 # nn
+ movl 8(ap),r1 # nl
+ sobgeq r1,LCM1 # if(nl-- != 0) goto LCM1;
+ ret
+LCM1: mcoml (r0),(r0)+ # *(n++) ^= -1;
+ sobgeq r1,LCM1 # if(nl-- != 0) goto LCM1;
+ ret
+
+ .globl _BnnAndDigits
+ .align 3
+_BnnAndDigits:
+ .word 0x0&callee_save # mask<>
+ mcoml 8(ap),r0 # d = ~d;
+ bicl2 r0,*4(ap) # *nn &= ~d;
+ ret
+
+ .globl _BnnOrDigits
+ .align 3
+_BnnOrDigits:
+ .word 0x0&callee_save # mask<>
+ bisl2 8(ap),*4(ap) # *nn |= d;
+ ret
+
+ .globl _BnnXorDigits
+ .align 3
+_BnnXorDigits:
+ .word 0x0&callee_save # mask<>
+ xorl2 8(ap),*4(ap) # *nn ^= d;
+ ret
+
+ .globl _BnnShiftLeft
+ .align 3
+_BnnShiftLeft:
+ .word 0x7E&callee_save # mask<r1,r2,r3,r4,r5,r6>
+ clrl r0 # res = 0;
+ movl 12(ap),r3 # nbi
+ bneq LSL0 # if(nbi) goto LSL0
+ ret # return(res);
+LSL0: movl 4(ap),r2 # mm
+ movl 8(ap),r1 # ml
+ subl3 r3,$32,r4 # rnbi = BN_DIGIT_SIZE - nbi;
+ sobgeq r1,LSL1 # if(ml-- != 0) goto LSL1;
+ ret # return(res);
+LSL1: movl (r2),r5 # save = *mm
+ ashl r3,r5,r6 # X = save << nbi;
+ bisl3 r0,r6,(r2)+ # *(mm++) = X | res;
+ extzv r4,r3,r5,r0 # res = save >> rnbits;
+ sobgeq r1,LSL1 # if(ml-- != 0) goto LSL1;
+ ret # return(res);
+
+ .globl _BnnShiftRight
+ .align 3
+_BnnShiftRight:
+ .word 0x7E&callee_save # mask<r1,r2,r3,r4,r5,r6>
+ clrl r0 # res = 0;
+ movl 12(ap),r3 # nbi
+ bneq LSR0 # if(nbi) goto LSR0;
+ ret # return(res);
+LSR0: movl 8(ap),r1 # ml
+ moval *4(ap)[r1],r2 # mm = &mm[ml];
+ subl3 r3,$32,r4 # lnbi = BN_DIGIT_SIZE - nbi;
+ sobgeq r1,LSR1 # if(ml-- != 0) goto LSR1;
+ ret # return(res);
+LSR1: movl -(r2),r5 # save = *(--mm);
+ extzv r3,r4,r5,r6 # X = save >> nbi;
+ bisl3 r0,r6,(r2) # *mm = X | res;
+ ashl r4,r5,r0 # res = save << lnbi;
+ sobgeq r1,LSR1 # if(ml-- != 0) goto LSR1;
+ ret # return(res);
+
+ .globl _BnnAddCarry
+ .align 3
+_BnnAddCarry:
+ .word 0x2&callee_save # mask<r1>
+ movl 12(ap),r0 # car
+ beql LAC3 # if(car == 0) return(car);
+ movl 8(ap),r0 # nl
+ beql LAC2 # if(nl == 0) return(1);
+ movl 4(ap),r1 # nn
+LAC1: incl (r1)+ # ++(*nn++);
+ bcc LAC4 # if(!Carry) goto LAC4
+ sobgtr r0,LAC1 # if(--nl > 0) goto LAC1;
+LAC2: movl $1,r0 # return(1);
+LAC3: ret
+LAC4: clrl r0 # return(0);
+ ret
+
+ .globl _BnnAdd
+ .align 3
+_BnnAdd:
+ .word 0x1E&callee_save # mask<r1,r2,r3,r4>
+LADDEntry: movl 4(ap),r0 # mm
+ movl 12(ap),r1 # nn
+ movl 16(ap),r3 # nl
+ bneq LADD1 # if(nl) goto LADD1
+ subl3 r3,8(ap),r2 # ml -= nl;
+ tstl 20(ap) # car
+ bneq LADD5 # if(car) goto LADD5
+ clrl r0
+ ret # return(0);
+LADD1: subl3 r3,8(ap),r2 # ml -= nl;
+ addl3 20(ap),$-1,r4 # C = car
+
+LADD2: adwc (r1)+,(r0)+ # *(m++) += *(n++) + C;
+LADD3: sobgtr r3,LADD2 # if(--nl > 0) goto LADD2;
+ bcs LADD5 # if(C) goto LADD5;
+LADD4: clrl r0
+ ret
+
+LADD6: incl (r0)+ # ++(*m++);
+ bcc LADD4 # if(!C) goto LADD4;
+LADD5: sobgeq r2,LADD6 # if(--ml >= 0) goto LADD6;
+LADD7: movl $1,r0
+ ret
+
+ .globl _BnnSubtractBorrow
+ .align 3
+_BnnSubtractBorrow:
+ .word 0x2&callee_save # mask<r1>
+ movl 12(ap),r0 # car
+ bneq LSB2 # if(car) return(car);
+ movl 8(ap),r0 # nl
+ beql LSB20 # if(nl == 0) return(0);
+ movl 4(ap),r1 # nn
+LSB1: decl (r1)+ # (*nn++)--;
+ bcc LSB3 # if(!Carry) goto LSB3;
+ sobgtr r0,LSB1 # if(--nl > 0) goto LSB1;
+LSB20: # assert r0 == 0 return(0);
+LSB2: ret
+LSB3: movl $1,r0 # return(1);
+ ret
+
+ .globl _BnnSubtract
+ .align 3
+_BnnSubtract:
+ .word 0x1E&callee_save # mask<r1,r2,r3,r4>
+ movl 4(ap),r2 # mm
+ movl 12(ap),r1 # nn
+ movl 16(ap),r3 # nl
+ bneq LS1 # if(nl) goto LS1
+ subl3 r3,8(ap),r0 # ml -= nl;
+ tstl 20(ap) # car
+ beql LS5 # if(car) goto LS5
+ movl $1,r0
+ ret # return(1);
+LS1: subl3 r3,8(ap),r0 # ml -= nl;
+ tstl 20(ap) # C = 0; Z = (car == 0)
+ bneq LS2 # if(!(Z = (car == 0))) goto LS2
+ addl3 $1,$-1,r4 # C = 1;
+
+LS2: sbwc (r1)+,(r2)+ # C..*m++ -= *n++ + C
+ sobgtr r3,LS2 # if(--nl > 0) goto LS2
+ bcs LS5
+LS3: movl $1,r0
+ ret
+LS4: decl (r2)+
+ bcc LS3
+LS5: sobgeq r0,LS4 # if (--ml >= 0) goto LS4
+ clrl r0
+ ret
+
+ .globl _BnnMultiplyDigit
+# note1: (2^32-1)*(2^32-1) = 2^64-1 - 2*(2^32-1)
+# thus 64 bits accomodates a*b+c+d for all a,b,c,d < 2^32
+# note2: inner loop is doubled to avoid unnecessary register moves.
+ .align 3
+_BnnMultiplyDigit:
+ .word 0x1FE&callee_save # mask<r1,r2,r3,r4,r5,r6,r7,r8>
+ movl 20(ap),r2 # r2 = d
+ blss LMDNeg # if (d<0) goto LMDNeg
+ bneq LMD1 # if (d) goto LMD1;
+ clrl r0
+ ret
+LMD1: cmpl $1,r2
+ bneq LMD2 # if (d != 1) goto LMD2
+ clrl 20(ap) # IN BnnAdd: car = 0
+ brw LADDEntry # BnnAdd(pp,pl,mm,ml,0);
+
+LMD2: movl 4(ap),r3 # r3 = p
+ movl 12(ap),r1 # r1 = m
+ movl 16(ap),r7 # r7 = ml
+ subl3 r7,8(ap),r8 # r8 = pl-ml
+ ashl $-1,r7,r0 # loop counter r0 = (ml+1)/2
+ clrl r5
+ bitl $1,r7
+ bneq LMDPOddLen # if (ml is odd) goto LMDPOddLen
+ clrl r7
+ brb LMDPEvenLen # if (ml is even) goto LMDPOddLen
+LMDPLoop: emul (r1)+,r2,$0,r4 # r4:r5 = m[i]*d
+ bgeq LMDMPos1 # if (m[i] < 0)
+ addl2 r2,r5 # r5 += d
+LMDMPos1: addl2 r7,r4 # r4 = (m[i]*d)%2^32+(m[i-1]*d)/2^32+C
+ adwc $0,r5 # r5 = (m[i]*d)/2^32 + carry1
+ addl2 r4,(r3)+ # *p++ += r4
+ adwc $0,r5 # r5 = (m[i]*d)/2^32 + carry2
+LMDPOddLen: emul (r1)+,r2,$0,r6 # r6:r7 = m[i+1]*d
+ bgeq LMDMPos2 # if (m[i+1] < 0)
+ addl2 r2,r7 # r7 += d
+LMDMPos2: addl2 r5,r6 # r6 = (m[i+1]*d)%2^32+(m[i]*d)/2^32+C
+ adwc $0,r7 # r7 = (m[i+1]*d)/2^32 + carry1
+ addl2 r6,(r3)+ # *p++ += r6
+ adwc $0,r7 # r7 = (m[i+1]*d)/2^32 + carry2
+LMDPEvenLen: sobgeq r0,LMDPLoop # if ((i+=2)/2 < ml/2) repeat loop
+ addl2 r7,(r3)+ # *p += (m[ml-1]*d)/2^32
+ bcs LMDTail
+LMDRet0: clrl r0
+ ret
+
+LMDNeg: movl 4(ap),r3 # r3 = p
+ movl 12(ap),r1 # r1 = m
+ movl 16(ap),r7 # r7 = ml
+ subl3 r7,8(ap),r8 # r8 = pl-ml
+ ashl $-1,r7,r0 # loop counter r0 = (ml+1)/2
+ clrl r5
+ bitl $1,r7
+ bneq LMDNOddLen
+ clrl r7
+ brb LMDNEvenLen
+LMDNLoop: movl (r1)+,r6 # r6 = m[i]
+ emul r6,r2,$0,r4 # r4:r5 = m[i]*d
+ bleq LMDMPos3 # if (m[i] < 0)
+ addl2 r2,r5 # r5 += d
+LMDMPos3: addl2 r6,r5 # r5 += m[i]
+ addl2 r7,r4 # r4 = (m[i]*d)%2^32+(m[i-1]*d)/2^32+C
+ adwc $0,r5 # r5 = (m[i]*d)/2^32 + carry1
+ addl2 r4,(r3)+ # *p++ += r4
+ adwc $0,r5 # r5 = (m[i]*d)/2^32 + carry2
+LMDNOddLen: movl (r1)+,r4 # r6 = m[i+1]
+ emul r4,r2,$0,r6 # r6:r7 = m[i+1]*d
+ bleq LMDMPos4 # if (m[i+1] < 0)
+ addl2 r2,r7 # r7 += d
+LMDMPos4: addl2 r4,r7 # r7 += m[i+1]
+ addl2 r5,r6 # r6 = (m[i+1]*d)%2^32+(m[i]*d)/2^32+C
+ adwc $0,r7 # r7 = (m[i+1]*d)/2^32 + carry1
+ addl2 r6,(r3)+ # *p++ += r6
+ adwc $0,r7 # r7 = (m[i+1]*d)/2^32 + carry2
+LMDNEvenLen: sobgeq r0,LMDNLoop # if ((i+=2)/2 < ml/2) repeat loop
+ addl2 r7,(r3)+ # *p += (m[ml-1]*d)/2^32
+ bcs LMDTail
+ clrl r0 # r0 = carry
+ ret
+
+LMDTailLoop: incl (r3)+
+ bcc LMDRet0
+LMDTail: sobgtr r8,LMDTailLoop
+ movl $1,r0 # r0 = carry
+ ret
+
+ .globl _BnnDivideDigit
+ .align 3
+_BnnDivideDigit:
+ .word 0x3FE&callee_save # mask<r1,r2,r3,r4,r5,r6,r7,r8,r9>
+ movl 12(ap),r2 # nl
+ movl 16(ap),r3 # d
+ moval *8(ap)[r2],r0 # nn = &nn[nl];
+ decl r2 # nl--;
+ moval *4(ap)[r2],r1 # qq = &qq[nl];
+ movl -(r0),r5 # X(hight) = *(--n);
+ extzv $1,$31,r3,r7 # r7 = D' <- D div 2
+ tstl r3
+ bgeq Lndivc2
+ brw Lndiv5 # D < 0!!
+
+ # D < 2**31
+ brb Lndivc2 # N < D * 2**32
+Lndivc1: movl -(r0),r4 # (bdivu dx3 ax1 dx1)
+ cmpl r5,r7
+ blss Lndivc11
+ extzv $0,$1,r4,r6 # r6 <- n0
+ ashq $-1,r4,r4 # N' = r4 = N quo 2 < D * 2**31
+ ediv r3,r4,r4,r5 # r4 <- Q' = N' quo D < 2**31
+ # r5 <- R' = N' rem D < D
+ ashq $1,r4,r4 # r4 <- 2 * Q' < 2**32
+ # r5 <- 2 * R' < 2 * D
+ addl2 r6,r5 # r5 <- 2 * R' + n0 < 2 * D
+ cmpl r5,r3 # r5 < D -> Q = r4, R = r5
+ blssu Lndivc12 # sinon
+ incl r4 # Q = r4 + 1
+ subl2 r3,r5 # R = r5 - D
+ brb Lndivc12
+Lndivc11: ediv r3,r4,r4,r5 # Q = r4, R = r5
+Lndivc12: movl r4,-(r1) # range r4 en me'moire
+Lndivc2: sobgeq r2,Lndivc1 # (sobgez dx2 Lndivc1)
+ movl r5,r0 # return(X(hight));
+ ret
+
+Lndiv3: movl -(r0),r4 # r4 poid faible de N
+ extzv $0,$1,r4,r9 # r9 <- n0
+ extzv $1,$1,r4,r6 # r6 <- n1
+ extzv $2,$1,r4,r8 # r8 <- n2
+ ashq $-3,r4,r4 # r4 <- N'' = N quo 4
+ bicl2 $0xE0000000,r5 # Le ashq ne le fait pas
+ ediv r7,r4,r4,r5 # r4 <- Q' = N''' quo D'
+ # r5 <- R' = N''' rem D'
+ ashl $1,r5,r5 # r5 <- 2 * R'
+ addl2 r8,r5 # r5 <- 2 * R' + n2
+ bbc $0,r3,Lndiv4 # si d0 = 0
+ cmpl r5,r4 # sinon r5 <- 2R' + n1 - Q'
+ blssu Lndiv30 # la diff est < 0
+ subl2 r4,r5 # la diff est > 0
+ brb Lndiv4 # voila la diff!
+Lndiv30: subl2 r4,r5 # la diff!
+ decl r4 # r4 <- r4 - 1
+ addl2 r3,r5 # r5 <- r5 + D
+Lndiv4: ashl $1,r4,r4 # r4 <- 2Q'
+ addl2 r5,r5 # r5 <- 2r5
+ bisl2 r6,r5 # r5 <- r5 + n1 (flag C ok!)
+ bcs Lndiv40 # On deborde sur!
+ cmpl r5,r3
+ blssu Lndiv42 # depasse pas D
+Lndiv40: incl r4 # Q = r4 + 1
+ subl2 r3,r5 # R = r5 - D
+Lndiv42: ashl $1,r4,r4 # r4 <- 2Q'
+ addl2 r5,r5 # r5 <- 2r5
+ bisl2 r9,r5 # r5 <- r5 + n0 (flag C ok!)
+ bcs Lndiv43 # On deborde sur!
+ cmpl r5,r3
+ blssu Lndiv44 # depasse pas D
+Lndiv43: incl r4 # Q = r4 + 1
+ subl2 r3,r5 # R = r5 - D
+Lndiv44: movl r4,-(r1) # range le quotient en memoire
+Lndiv5: sobgeq r2,Lndiv3 # On continue!
+ movl r5,r0 # return(X(hight));
+ ret
+
+# BigNumCarry BnnMultiply (pp, pl, mm, ml, nn, nl)
+# BigNum pp, nn, mm;
+# BigNumLength pl, nl, ml;
+
+.globl _BnnMultiply
+ .align 3
+_BnnMultiply:
+ .word 0xFFE&callee_save # mask<r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
+ movl 24(ap),r9 # r9 = nl
+ bneq LMM_nl_pos
+LMM_Ret0a:
+ clrl r0
+LMM_Ret:
+ ret
+LMM_nl_pos:
+ movl 20(ap),r11 # nn
+ cmpl 12(ap),r11 # if (nn == mm)
+ beql BMM_Sqr
+LMM_NotSqr:
+ movl 4(ap),r10 # pp
+ clrl r8 # c_hi
+LMM_NLoop:
+ movl 16(ap),r7 # ml
+ movl 12(ap),r1 # mm
+ moval (r10)+,r3 # pp
+ clrl r5 # c_lo
+ movl (r11)+,r2 # digit
+ bsbw BMM_MultiplyDigit
+ sobgtr r9,LMM_NLoop
+ movl r8,r0
+ beql LMM_Ret
+ movl 16(ap),r7 # r7 = ml
+ subl3 r7,8(ap),r1 # r7 = pl-ml
+ subl2 24(ap),r1 # r7 = pl-ml-nl
+ bleq LMM_Ret
+ moval (r10)[r7],r10 # pp += ml
+LMM_PLoop:
+ incl (r10)+
+ bcc LMM_Ret0a
+ sobgtr r1,LMM_PLoop
+ ret
+# Special squaring code based on:
+# n[0..nl-1]*n[0..nl-1] = sum (i = 0..nl-1):
+# B^2i * (n[i]*n[i] + 2*n[i] * n[i+1..nl-1] * B)
+# the 2*n[i] is tricky because it may overflow, but ...
+# suppose L[i] = 2*n[i]%2^32
+# and H[i] = 2*n[i]/2^32
+# Then:
+# sum (i = 0..nl-1):
+# B^2i * (n[i]*n[i] + L[i]+H[i-1] * n[i+1..nl-1] * B + H[i-1]*n[i])
+# notice that when i = nl-1 the final term is 2*n[nl-1] * n[nl..nl-1],
+# n[nl..nl-1] is zero length -- i.e. we can ignore it!
+# lastly we don't have quite enough registers to conveniently remember
+# the top bit of n[i-1] we encode it in the PC by duplicating
+# the loop--sometimes I love assembler.
+LMMS_NNLoop:
+ # execute this version of loop if n[i-1] was >= 2^31
+ movl (r11)+,r0 # d = r0 = *nn++
+ movl r11,r1 # r1 = mm
+ emul r0,r0,$0,r4 # r4:r5 = d*d
+ addl2 r0,r4 # r4 += (2*n[i-1])/2^32*n[i] (= d)
+ adwc $0,r5
+ addl2 r4,(r10)+ # *pp++ += d*d%2^32
+ adwc $0,r5 # r5 += C
+ moval (r10)+,r3 # arg-p = pp++
+ movl r9,r7 # arg-ml = ml
+ addl3 r0,r0,r2 # if (d >= 0)
+ bisl2 $1,r2
+ bcc LMMS_DPos # switch to < 2^31 loop
+LMMS_DNeg:
+ addl2 r0,r5 # compensate for signed mul
+ addl2 r0,r5 # r4:r5 += 2*r2*2^32
+ tstl r2 # set condition codes for entry to subr
+ # MultiplyDigit(pp=r3, mm=r1, ml=r7, d=r2, c_hi=r8, c_lo=r5)
+ bsbb BMM_MultiplyDigit
+ sobgeq r9,LMMS_NNLoop
+ brb LMMS_Post
+# >>> ENTRY <<<
+BMM_Sqr:
+ # r9 = nl, r11 = nn
+ movl 16(ap),r8 # r8 = ml
+ bneq LMMS_ml_pos
+ clrl r0
+ ret # return 0;
+LMMS_ml_pos:
+ cmpl r8,r9 # if (ml != nl)
+ bneq LMM_NotSqr
+
+ # r8 = 0, r9 = nl, r11 = nn, r10 = sgn(nn[nl-1])
+ movl 4(ap),r10 # r10 = pp
+ # r11 = nn
+ clrl r8 # r8 = high carry = 0
+ decl r9 # r9 = ml-1 = nl-1
+LMMS_NLoop:
+ # execute this version of loop if n[i-1] was < 2^31
+ movl (r11)+,r0 # d = r0 = *nn++
+ movl r11,r1 # r1 = mm
+ emul r0,r0,$0,r4 # r4:r5 = d*d
+ addl2 r4,(r10)+ # *pp++ += d*d%2^32
+ adwc $0,r5 # r5 += C
+ moval (r10)+,r3 # arg-p = pp++
+ movl r9,r7 # arg-ml = ml
+ addl3 r0,r0,r2 # if (d < 0)
+ bcs LMMS_DNeg # switch to >= 2^31 loop
+LMMS_DPos:
+ tstl r2 # set condition codes for entry to subr
+ # MultiplyDigit(pp=r3, mm=r1, ml=r7, d=r2, c_hi=r8, c_lo=r5)
+ bsbb BMM_MultiplyDigit
+ sobgeq r9,LMMS_NLoop
+ # r9 = 0, r10 = pp+2*ml, r2 = 2*nn[nl-1], r8 = carry_hi, r11 = nn+nl
+LMMS_Post:
+ movl r8,r0
+ bneq LMMS_CProp # if (c != 0)
+LMMS_ret:
+ ret # return
+LMMS_CProp:
+ movl 16(ap),r7 # r7 = nl
+ subl3 r7,8(ap),r2 # r2 = pl-nl (note nl == ml)
+ subl2 r7,r2 # r2 = pl-nl-ml
+ bleq LMMS_ret # if (pl-nl > ml)
+ # ret = BnnAddCarry(pp+ml, pl-ml, c);
+LMMS_CPLoop:
+ incl (r10)+ # (*pp++)++
+ bcc LMMS_Ret0
+ sobgtr r2,LMMS_CPLoop
+ ret
+LMMS_Ret0:
+ clrl r0
+ ret
+
+# Subroutine: MultiplyDigit(pp,mm,ml,d,c_hi,c_lo)
+# returns:
+# c_hi*base^(ml+1)+ pp[0..ml] = pp[0..ml]+(mm[0..ml-1]*d)+c_hi*base^ml+c_lo
+#
+# In:
+# ml_entry:r7
+# ml/2: r0
+# mm: r1
+# digit: r2
+# pp: r3
+# c_hi: r8
+# c_lo: r5
+#
+# multiply scratch: r4,r5 / r6,r7
+#
+# Out:
+# c_hi: r8
+LMMD_C_hi:
+ addl2 r8,(r3)[r7] # p[ml] += c_hi
+ clrl r8
+ adwc $0,r8
+ rsb
+LMMD_Zero:
+ tstl r5 # Too complicated, return to
+ beql LMMD_ZC_lo # normal case.
+ tstl r2
+ brb LMMD_Retry
+LMMD_ZC_lo:
+ tstl r8
+ bneq LMMD_C_hi
+ rsb
+BMM_MultiplyDigit:
+ beql LMMD_Zero
+LMMD_Retry:
+ blss LMMD_Neg # if (d<0) goto LMMD_Neg
+ ashl $-1,r7,r0 # loop counter r0 = ml/2
+ bitl $1,r7
+ bneq LMMD_POddLen # if (ml is odd) goto LMMD_POddLen
+ movl r5,r7
+ brb LMMD_PEvenLen # if (ml is even) goto LMMD_POddLen
+LMMD_PLoop: emul (r1)+,r2,$0,r4 # r4:r5 = m[i]*d
+ bgeq LMMD_MPos1 # if (m[i] < 0)
+ addl2 r2,r5 # r5 += d
+LMMD_MPos1: addl2 r7,r4 # r4 = (m[i]*d)%2^32+(m[i-1]*d)/2^32+C
+ adwc $0,r5 # r5 = (m[i]*d)/2^32 + carry1
+ addl2 r4,(r3)+ # *p++ += r4
+ adwc $0,r5 # r5 = (m[i]*d)/2^32 + carry2
+LMMD_POddLen: emul (r1)+,r2,$0,r6 # r6:r7 = m[i+1]*d
+ bgeq LMMD_MPos2 # if (m[i+1] < 0)
+ addl2 r2,r7 # r7 += d
+LMMD_MPos2: addl2 r5,r6 # r6 = (m[i+1]*d)%2^32+(m[i]*d)/2^32+C
+ adwc $0,r7 # r7 = (m[i+1]*d)/2^32 + carry1
+ addl2 r6,(r3)+ # *p++ += r6
+ adwc $0,r7 # r7 = (m[i+1]*d)/2^32 + carry2
+LMMD_PEvenLen: sobgeq r0,LMMD_PLoop # if ((i+=2)/2 < ml/2) repeat loop
+ addl2 r8,r7
+ clrl r8
+ adwc $0,r8
+ addl2 r7,(r3) # *p += (m[ml-1]*d)/2^32
+ adwc $0,r8
+ rsb
+LMMD_Neg:
+ ashl $-1,r7,r0 # loop counter r0 = ml/2
+ bitl $1,r7
+ bneq LMMD_NOddLen
+ movl r5,r7
+ brb LMMD_NEvenLen
+LMMD_NLoop: movl (r1)+,r6 # r6 = m[i]
+ emul r6,r2,$0,r4 # r4:r5 = m[i]*d
+ bleq LMMD_MPos3 # if (m[i] < 0)
+ addl2 r2,r5 # r5 += d
+LMMD_MPos3: addl2 r6,r5 # r5 += m[i]
+ addl2 r7,r4 # r4 = (m[i]*d)%2^32+(m[i-1]*d)/2^32+C
+ adwc $0,r5 # r5 = (m[i]*d)/2^32 + carry1
+ addl2 r4,(r3)+ # *p++ += r4
+ adwc $0,r5 # r5 = (m[i]*d)/2^32 + carry2
+LMMD_NOddLen: movl (r1)+,r4 # r6 = m[i+1]
+ emul r4,r2,$0,r6 # r6:r7 = m[i+1]*d
+ bleq LMMD_MPos4 # if (m[i+1] < 0)
+ addl2 r2,r7 # r7 += d
+LMMD_MPos4: addl2 r4,r7 # r7 += m[i+1]
+ addl2 r5,r6 # r6 = (m[i+1]*d)%2^32+(m[i]*d)/2^32+C
+ adwc $0,r7 # r7 = (m[i+1]*d)/2^32 + carry1
+ addl2 r6,(r3)+ # *p++ += r6
+ adwc $0,r7 # r7 = (m[i+1]*d)/2^32 + carry2
+LMMD_NEvenLen: sobgeq r0,LMMD_NLoop # if ((i+=2)/2 < ml/2) repeat loop
+ addl2 r8,r7
+ clrl r8
+ adwc $0,r8
+ addl2 r7,(r3) # *p += (m[ml-1]*d)/2^32
+ adwc $0,r8
+ rsb
diff --git a/otherlibs/num/int_misc.mli b/otherlibs/num/int_misc.mli
new file mode 100644
index 000000000..32693f1fe
--- /dev/null
+++ b/otherlibs/num/int_misc.mli
@@ -0,0 +1,23 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Some extra operations on integers *)
+
+val gcd_int: int -> int -> int
+val num_bits_int: int -> int
+val compare_int: int -> int -> int
+val sign_int: int -> int
+val length_of_int: int
+val biggest_int: int
+val least_int: int
+val monster_int: int
diff --git a/otherlibs/num/int_misc.mlp b/otherlibs/num/int_misc.mlp
new file mode 100644
index 000000000..a6ff5b425
--- /dev/null
+++ b/otherlibs/num/int_misc.mlp
@@ -0,0 +1,41 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Some extra operations on integers *)
+
+(*
+#include "../../config/m.h"
+*)
+
+let rec gcd_int i1 i2 =
+ if i2 = 0 then abs i1 else gcd_int i2 (i1 mod i2)
+;;
+
+let rec num_bits_int_aux n =
+ if n = 0 then 0 else succ(num_bits_int_aux (n lsr 1));;
+
+let num_bits_int n = num_bits_int_aux (abs n);;
+
+let sign_int i = if i = 0 then 0 else if i > 0 then 1 else -1;;
+
+#ifdef SIXTYFOUR
+let length_of_int = 62;;
+#else
+let length_of_int = 30;;
+#endif
+let monster_int = 1 lsl length_of_int;;
+let biggest_int = monster_int - 1;;
+let least_int = - biggest_int;;
+
+let compare_int n1 n2 =
+ if n1 == n2 then 0 else if n1 > n2 then 1 else -1;;
diff --git a/otherlibs/num/nat.mli b/otherlibs/num/nat.mli
new file mode 100644
index 000000000..72c971831
--- /dev/null
+++ b/otherlibs/num/nat.mli
@@ -0,0 +1,70 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Module [Nat]: operations on natural numbers *)
+
+type nat
+
+(* Natural numbers (type [nat]) are positive integers of arbitrary size.
+ All operations on [nat] are performed in-place. *)
+
+external create_nat: int -> nat = "create_nat"
+val make_nat: int -> nat
+external set_to_zero_nat: nat -> int -> int -> unit = "set_to_zero_nat"
+external blit_nat: nat -> int -> nat -> int -> int -> unit = "blit_nat"
+val copy_nat: nat -> int -> int -> nat
+external set_digit_nat: nat -> int -> int -> unit = "set_digit_nat"
+external nth_digit_nat: nat -> int -> int = "nth_digit_nat"
+external length_nat: nat -> int = "%array_length"
+val length_nat : nat -> int
+external num_digits_nat: nat -> int -> int -> int = "num_digits_nat"
+external num_leading_zero_bits_in_digit: nat -> int -> int = "num_leading_zero_bits_in_digit"
+external is_digit_int: nat -> int -> bool = "is_digit_int"
+external is_digit_zero: nat -> int -> bool = "is_digit_zero"
+external is_digit_normalized: nat -> int -> bool = "is_digit_normalized"
+external is_digit_odd: nat -> int -> bool = "is_digit_odd"
+val is_zero_nat: nat -> int -> int -> bool
+val is_nat_int: nat -> int -> int -> bool
+val int_of_nat: nat -> int
+val nat_of_int: int -> nat
+external incr_nat: nat -> int -> int -> int -> int = "incr_nat"
+external add_nat: nat -> int -> int -> nat -> int -> int -> int -> int = "add_nat" "add_nat_native"
+external complement_nat: nat -> int -> int -> unit = "complement_nat"
+external decr_nat: nat -> int -> int -> int -> int = "decr_nat"
+external sub_nat: nat -> int -> int -> nat -> int -> int -> int -> int = "sub_nat" "sub_nat_native"
+external mult_digit_nat: nat -> int -> int -> nat -> int -> int -> nat -> int -> int = "mult_digit_nat" "mult_digit_nat_native"
+external mult_nat: nat -> int -> int -> nat -> int -> int -> nat -> int -> int -> int = "mult_nat" "mult_nat_native"
+external shift_left_nat: nat -> int -> int -> nat -> int -> int -> unit = "shift_left_nat" "shift_left_nat_native"
+external div_digit_nat: nat -> int -> nat -> int -> nat -> int -> int -> nat -> int -> unit = "div_digit_nat" "div_digit_nat_native"
+external div_nat: nat -> int -> int -> nat -> int -> int -> unit = "div_nat" "div_nat_native"
+external shift_right_nat: nat -> int -> int -> nat -> int -> int -> unit = "shift_right_nat" "shift_right_nat_native"
+external compare_digits_nat: nat -> int -> nat -> int -> int = "compare_digits_nat"
+external compare_nat: nat -> int -> int -> nat -> int -> int -> int = "compare_nat" "compare_nat_native"
+val eq_nat : nat -> int -> int -> nat -> int -> int -> bool
+val le_nat : nat -> int -> int -> nat -> int -> int -> bool
+val lt_nat : nat -> int -> int -> nat -> int -> int -> bool
+val ge_nat : nat -> int -> int -> nat -> int -> int -> bool
+val gt_nat : nat -> int -> int -> nat -> int -> int -> bool
+external land_digit_nat: nat -> int -> nat -> int -> unit = "land_digit_nat"
+external lor_digit_nat: nat -> int -> nat -> int -> unit = "lor_digit_nat"
+external lxor_digit_nat: nat -> int -> nat -> int -> unit = "lxor_digit_nat"
+val square_nat : nat -> int -> int -> nat -> int -> int -> int
+val gcd_nat : nat -> int -> int -> nat -> int -> int -> int
+val sqrt_nat : nat -> int -> int -> nat
+val string_of_nat : nat -> string
+val nat_of_string : string -> nat
+val sys_nat_of_string : int -> string -> int -> int -> nat
+val float_of_nat : nat -> float
+val make_power_base : int -> nat -> int * int
+val power_base_int : int -> int -> nat
+val length_of_digit: int
diff --git a/otherlibs/num/nat.mlp b/otherlibs/num/nat.mlp
new file mode 100644
index 000000000..90877d521
--- /dev/null
+++ b/otherlibs/num/nat.mlp
@@ -0,0 +1,527 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(*
+#include "../../config/m.h"
+*)
+
+open Int_misc
+
+type nat;;
+
+external create_nat: int -> nat = "create_nat"
+external set_to_zero_nat: nat -> int -> int -> unit = "set_to_zero_nat"
+external blit_nat: nat -> int -> nat -> int -> int -> unit = "blit_nat"
+external set_digit_nat: nat -> int -> int -> unit = "set_digit_nat"
+external nth_digit_nat: nat -> int -> int = "nth_digit_nat"
+external length_nat: nat -> int = "%array_length"
+external num_digits_nat: nat -> int -> int -> int = "num_digits_nat"
+external num_leading_zero_bits_in_digit: nat -> int -> int = "num_leading_zero_bits_in_digit"
+external is_digit_int: nat -> int -> bool = "is_digit_int"
+external is_digit_zero: nat -> int -> bool = "is_digit_zero"
+external is_digit_normalized: nat -> int -> bool = "is_digit_normalized"
+external is_digit_odd: nat -> int -> bool = "is_digit_odd"
+external incr_nat: nat -> int -> int -> int -> int = "incr_nat"
+external add_nat: nat -> int -> int -> nat -> int -> int -> int -> int = "add_nat" "add_nat_native"
+external complement_nat: nat -> int -> int -> unit = "complement_nat"
+external decr_nat: nat -> int -> int -> int -> int = "decr_nat"
+external sub_nat: nat -> int -> int -> nat -> int -> int -> int -> int = "sub_nat" "sub_nat_native"
+external mult_digit_nat: nat -> int -> int -> nat -> int -> int -> nat -> int -> int = "mult_digit_nat" "mult_digit_nat_native"
+external mult_nat: nat -> int -> int -> nat -> int -> int -> nat -> int -> int -> int = "mult_nat" "mult_nat_native"
+external shift_left_nat: nat -> int -> int -> nat -> int -> int -> unit = "shift_left_nat" "shift_left_nat_native"
+external div_digit_nat: nat -> int -> nat -> int -> nat -> int -> int -> nat -> int -> unit = "div_digit_nat" "div_digit_nat_native"
+external div_nat: nat -> int -> int -> nat -> int -> int -> unit = "div_nat" "div_nat_native"
+external shift_right_nat: nat -> int -> int -> nat -> int -> int -> unit = "shift_right_nat" "shift_right_nat_native"
+external compare_digits_nat: nat -> int -> nat -> int -> int = "compare_digits_nat"
+external compare_nat: nat -> int -> int -> nat -> int -> int -> int = "compare_nat" "compare_nat_native"
+external land_digit_nat: nat -> int -> nat -> int -> unit = "land_digit_nat"
+external lor_digit_nat: nat -> int -> nat -> int -> unit = "lor_digit_nat"
+external lxor_digit_nat: nat -> int -> nat -> int -> unit = "lxor_digit_nat"
+
+#ifdef SIXTYFOUR
+let length_of_digit = 64
+#else
+let length_of_digit = 32
+#endif
+
+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 copy_nat nat off_set length =
+ let res = create_nat (length) in
+ blit_nat res 0 nat off_set length;
+ res
+
+let is_zero_nat n off len =
+ compare_nat (make_nat 1) 0 1 n off (num_digits_nat n off len) = 0
+
+let is_nat_int nat off len =
+ num_digits_nat nat off len = 1 & is_digit_int nat off
+
+let sys_int_of_nat nat off len =
+ if is_nat_int nat off len
+ then nth_digit_nat nat off
+ else failwith "int_of_nat"
+
+let int_of_nat nat =
+ sys_int_of_nat nat 0 (length_nat nat)
+
+let nat_of_int i =
+ if i < 0 then invalid_arg "nat_of_int" else
+ let res = make_nat 1 in
+ if i = 0 then res else begin set_digit_nat res 0 i; res end
+
+let eq_nat nat1 off1 len1 nat2 off2 len2 =
+ compare_nat nat1 off1 (num_digits_nat nat1 off1 len1)
+ nat2 off2 (num_digits_nat nat2 off2 len2) = 0
+and le_nat nat1 off1 len1 nat2 off2 len2 =
+ compare_nat nat1 off1 (num_digits_nat nat1 off1 len1)
+ nat2 off2 (num_digits_nat nat2 off2 len2) <= 0
+and lt_nat nat1 off1 len1 nat2 off2 len2 =
+ compare_nat nat1 off1 (num_digits_nat nat1 off1 len1)
+ nat2 off2 (num_digits_nat nat2 off2 len2) < 0
+and ge_nat nat1 off1 len1 nat2 off2 len2 =
+ compare_nat nat1 off1 (num_digits_nat nat1 off1 len1)
+ nat2 off2 (num_digits_nat nat2 off2 len2) >= 0
+and gt_nat nat1 off1 len1 nat2 off2 len2 =
+ compare_nat nat1 off1 (num_digits_nat nat1 off1 len1)
+ nat2 off2 (num_digits_nat nat2 off2 len2) > 0
+
+let square_nat nat1 off1 len1 nat2 off2 len2 =
+ let c = ref 0
+ and trash = make_nat 1 in
+ (* Double product *)
+ for i = 0 to len2 - 2 do
+ c := !c + mult_digit_nat
+ nat1
+ (succ (off1 + 2 * i))
+ (2 * (pred (len2 - i)))
+ nat2
+ (succ (off2 + i))
+ (pred (len2 - i))
+ nat2
+ (off2 + i)
+ done;
+ shift_left_nat nat1 0 len1 trash 0 1;
+ (* Square of digit *)
+ for i = 0 to len2 - 1 do
+ c := !c + mult_digit_nat
+ nat1
+ (off1 + 2 * i)
+ (len1 - 2 * i)
+ nat2
+ (off2 + i)
+ 1
+ nat2
+ (off2 + i)
+ done;
+ !c
+
+let gcd_int_nat i nat off len =
+ if i = 0 then 1 else
+ if is_nat_int nat off len then begin
+ set_digit_nat nat off (gcd_int (nth_digit_nat nat off) i); 0
+ end else begin
+ let len_copy = succ len in
+ let copy = create_nat len_copy
+ and quotient = create_nat 1
+ and remainder = create_nat 1 in
+ blit_nat copy 0 nat off len;
+ set_digit_nat copy len 0;
+ div_digit_nat quotient 0 remainder 0 copy 0 len_copy (nat_of_int i) 0;
+ set_digit_nat nat off (gcd_int (nth_digit_nat remainder 0) i);
+ 0
+ end
+
+let exchange r1 r2 =
+ let old1 = !r1 in r1 := !r2; r2 := old1
+
+let gcd_nat nat1 off1 len1 nat2 off2 len2 =
+ if is_zero_nat nat1 off1 len1 then begin
+ blit_nat nat1 off1 nat2 off2 len2; len2
+ end else begin
+ let copy1 = ref (create_nat (succ len1))
+ and copy2 = ref (create_nat (succ len2)) in
+ blit_nat !copy1 0 nat1 off1 len1;
+ blit_nat !copy2 0 nat2 off2 len2;
+ set_digit_nat !copy1 len1 0;
+ set_digit_nat !copy2 len2 0;
+ if lt_nat !copy1 0 len1 !copy2 0 len2
+ then exchange copy1 copy2;
+ let real_len1 =
+ ref (num_digits_nat !copy1 0 (length_nat !copy1))
+ and real_len2 =
+ ref (num_digits_nat !copy2 0 (length_nat !copy2)) in
+ while not (is_zero_nat !copy2 0 !real_len2) do
+ set_digit_nat !copy1 !real_len1 0;
+ div_nat !copy1 0 (succ !real_len1) !copy2 0 !real_len2;
+ exchange copy1 copy2;
+ real_len1 := !real_len2;
+ real_len2 := num_digits_nat !copy2 0 !real_len2
+ done;
+ blit_nat nat1 off1 !copy1 0 !real_len1;
+ !real_len1
+ end
+
+let sqrt_nat nat off len =
+ let size_copy = succ len in
+ let size_sqrt = len / 2 + len mod 2 in
+ let candidate = make_nat (size_sqrt)
+ and beginning = make_nat (size_sqrt) in
+ set_digit_nat candidate (size_sqrt - 1) 1;
+ shift_left_nat candidate (size_sqrt - 1) 1 beginning 0
+ (((if len mod 2 = 0 then 31 else 15) -
+ num_leading_zero_bits_in_digit nat (off + len - 1)) / 2);
+ let size_aux = size_copy - size_sqrt in
+ let copy = create_nat size_copy in
+ let aux = make_nat size_aux in
+ set_digit_nat copy len 0;
+ blit_nat copy 0 nat off len;
+ div_nat copy 0 size_copy candidate 0 size_sqrt;
+ blit_nat aux 0 copy size_sqrt size_aux;
+ add_nat aux 0 size_aux candidate 0 (num_digits_nat candidate 0 size_sqrt) 0;
+ shift_right_nat aux 0 size_aux beginning 0 1;
+ while not
+ (eq_nat aux 0 (num_digits_nat aux 0 size_aux)
+ candidate 0 (num_digits_nat candidate 0 size_sqrt))
+ do
+ blit_nat candidate 0 aux 0 size_aux;
+ set_digit_nat copy len 0;
+ blit_nat copy 0 nat off len;
+ div_nat copy 0 size_copy candidate 0 size_sqrt;
+ blit_nat aux 0 copy size_sqrt size_aux;
+ add_nat aux 0 size_aux candidate 0 (num_digits_nat candidate 0 size_sqrt) 0;
+ shift_right_nat aux 0 size_aux beginning 0 1
+ done;
+ candidate
+
+let power_base_max = make_nat 2
+
+#ifdef SIXTYFOUR
+let _ =
+ set_digit_nat power_base_max 0 1000000000000000000;
+ mult_digit_nat power_base_max 0 2
+ power_base_max 0 1 (nat_of_int 9) 0
+let pmax = 19
+#else
+let _ = set_digit_nat power_base_max 0 1000000000
+let pmax = 9
+#endif
+
+(* Nat temporaries *)
+let a_2 = make_nat 2
+and a_1 = make_nat 1
+and b_2 = make_nat 2
+
+#ifdef SIXTYFOUR
+let max_superscript_10_power_in_int = 18
+let max_power_10_power_in_int = nat_of_int 1000000000000000000
+#else
+let max_superscript_10_power_in_int = 9
+let max_power_10_power_in_int = nat_of_int 1000000000
+#endif
+
+let raw_string_of_digit nat off =
+ if is_nat_int nat off 1
+ then begin string_of_int (nth_digit_nat nat off) end
+ else begin
+ blit_nat b_2 0 nat off 1;
+ div_digit_nat a_2 0 a_1 0 b_2 0 2 max_power_10_power_in_int 0;
+ let leading_digits = nth_digit_nat a_2 0
+ and s1 = string_of_int (nth_digit_nat a_1 0) in
+ let len = String.length s1 in
+ if leading_digits < 10 then begin
+ let result = String.make (max_superscript_10_power_in_int+1) '0' in
+ String.set result 0
+ (Char.chr (48 + leading_digits));
+ String.blit s1 0
+ result (String.length result - len) len;
+ result
+ end else begin
+ let result = String.make (max_superscript_10_power_in_int+2) '0' in
+ String.blit (string_of_int leading_digits) 0 result 0 2;
+ String.blit s1 0
+ result (String.length result - len) len;
+ result
+ end
+ end
+
+(* XL: suppression de string_of_digit et de sys_string_of_digit.
+ La copie est de toute facon faite dans string_of_nat, qui est le
+ seul point d'entree public dans ce code. *)
+
+(******
+let sys_string_of_digit nat off =
+ let s = raw_string_of_digit nat off in
+ let result = String.create (String.length s) in
+ String.blit s 0 result 0 (String.length s);
+ s
+
+let string_of_digit nat =
+ sys_string_of_digit nat 0
+
+*******)
+
+let digits = "0123456789ABCDEF"
+
+(*
+ make_power_base affecte power_base des puissances successives de base a
+ partir de la puissance 1-ieme.
+ A la fin de la boucle i-1 est la plus grande puissance de la base qui tient
+ sur un seul digit et j est la plus grande puissance de la base qui tient
+ sur un int.
+*)
+let make_power_base base power_base =
+ let i = ref 0
+ and j = ref 0 in
+ set_digit_nat power_base 0 base;
+ while incr i; is_digit_zero power_base !i do
+ mult_digit_nat power_base !i 2
+ power_base (pred !i) 1
+ power_base 0
+ done;
+ while !j <= !i & is_digit_int power_base !j do incr j done;
+ (!i - 2, !j)
+
+(*
+ int_to_string place la representation de l entier int en base base
+ dans la chaine s en le rangeant de la fin indiquee par pos vers le
+ debut, sur times places et affecte a pos sa nouvelle valeur.
+*)
+let int_to_string int s pos_ref base times =
+ let i = ref int
+ and j = ref times in
+ while ((!i != 0) or (!j != 0)) & (!pos_ref != -1) do
+ String.set s !pos_ref (String.get digits (!i mod base));
+ decr pos_ref;
+ decr j;
+ i := !i / base
+ done
+
+(* XL: suppression de adjust_string *)
+
+let power_base_int base i =
+ if i = 0 then
+ nat_of_int 1
+ else if i < 0 then
+ invalid_arg "power_base_int"
+ else begin
+ let power_base = make_nat (succ length_of_digit) in
+ let (pmax, pint) = make_power_base base power_base in
+ let n = i / (succ pmax)
+ and rem = i mod (succ pmax) in
+ if n > 0 then begin
+ let newn =
+ if i = biggest_int then n else (succ n) in
+ let res = make_nat newn
+ and res2 = make_nat newn
+ and l = num_bits_int n - 2 in
+ let p = ref (1 lsl l) in
+ blit_nat res 0 power_base pmax 1;
+ for i = l downto 0 do
+ let len = num_digits_nat res 0 newn in
+ let len2 = min n (2 * len) in
+ let succ_len2 = succ len2 in
+ square_nat res2 0 len2 res 0 len;
+ if n land !p > 0 then begin
+ set_to_zero_nat res 0 len;
+ mult_digit_nat res 0 succ_len2
+ res2 0 len2
+ power_base pmax;
+ ()
+ end else
+ blit_nat res 0 res2 0 len2;
+ set_to_zero_nat res2 0 len2;
+ p := !p lsr 1
+ done;
+ if rem > 0 then begin
+ mult_digit_nat res2 0 newn
+ res 0 n power_base (pred rem);
+ res2
+ end else res
+ end else
+ copy_nat power_base (pred rem) 1
+ end
+
+(* the ith element (i >= 2) of num_digits_max_vector is :
+ | |
+ | biggest_string_length * log (i) |
+ | ------------------------------- | + 1
+ | length_of_digit * log (2) |
+ -- --
+*)
+
+(* XL: ai specialise le code d origine a length_of_digit = 32. *)
+(* Puis suppression (inutile?) *)
+
+(******
+let num_digits_max_vector =
+ [|0; 0; 1024; 1623; 2048; 2378; 2647; 2875; 3072; 3246; 3402;
+ 3543; 3671; 3789; 3899; 4001; 4096|]
+
+let num_digits_max_vector =
+ match length_of_digit with
+ 16 -> [|0; 0; 2048; 3246; 4096; 4755; 5294; 5749; 6144; 6492; 6803;
+ 7085; 7342; 7578; 7797; 8001; 8192|]
+(* If really exotic machines !!!!
+ | 17 -> [|0; 0; 1928; 3055; 3855; 4476; 4983; 5411; 5783; 6110; 6403;
+ 6668; 6910; 7133; 7339; 7530; 7710|]
+ | 18 -> [|0; 0; 1821; 2886; 3641; 4227; 4706; 5111; 5461; 5771; 6047;
+ 6298; 6526; 6736; 6931; 7112; 7282|]
+ | 19 -> [|0; 0; 1725; 2734; 3449; 4005; 4458; 4842; 5174; 5467; 5729;
+ 5966; 6183; 6382; 6566; 6738; 6898|]
+ | 20 -> [|0; 0; 1639; 2597; 3277; 3804; 4235; 4600; 4915; 5194; 5443;
+ 5668; 5874; 6063; 6238; 6401; 6553|]
+ | 21 -> [|0; 0; 1561; 2473; 3121; 3623; 4034; 4381; 4681; 4946; 5183;
+ 5398; 5594; 5774; 5941; 6096; 6241|]
+ | 22 -> [|0; 0; 1490; 2361; 2979; 3459; 3850; 4182; 4468; 4722; 4948;
+ 5153; 5340; 5512; 5671; 5819; 5958|]
+ | 23 -> [|0; 0; 1425; 2258; 2850; 3308; 3683; 4000; 4274; 4516; 4733;
+ 4929; 5108; 5272; 5424; 5566; 5699|]
+ | 24 -> [|0; 0; 1366; 2164; 2731; 3170; 3530; 3833; 4096; 4328; 4536;
+ 4723; 4895; 5052; 5198; 5334; 5461|]
+ | 25 -> [|0; 0; 1311; 2078; 2622; 3044; 3388; 3680; 3932; 4155; 4354;
+ 4534; 4699; 4850; 4990; 5121; 5243|]
+ | 26 -> [|0; 0; 1261; 1998; 2521; 2927; 3258; 3538; 3781; 3995; 4187;
+ 4360; 4518; 4664; 4798; 4924; 5041|]
+ | 27 -> [|0; 0; 1214; 1924; 2428; 2818; 3137; 3407; 3641; 3847; 4032;
+ 4199; 4351; 4491; 4621; 4742; 4855|]
+ | 28 -> [|0; 0; 1171; 1855; 2341; 2718; 3025; 3286; 3511; 3710; 3888;
+ 4049; 4196; 4331; 4456; 4572; 4681|]
+ | 29 -> [|0; 0; 1130; 1791; 2260; 2624; 2921; 3172; 3390; 3582; 3754;
+ 3909; 4051; 4181; 4302; 4415; 4520|]
+ | 30 -> [|0; 0; 1093; 1732; 2185; 2536; 2824; 3067; 3277; 3463; 3629;
+ 3779; 3916; 4042; 4159; 4267; 4369|]
+ | 31 -> [|0; 0; 1057; 1676; 2114; 2455; 2733; 2968; 3171; 3351; 3512;
+ 3657; 3790; 3912; 4025; 4130; 4228|]
+*)
+ | 32 -> [|0; 0; 1024; 1623; 2048; 2378; 2647; 2875; 3072; 3246; 3402;
+ 3543; 3671; 3789; 3899; 4001; 4096|]
+ | n -> failwith "num_digits_max_vector"
+******)
+
+(* XL: suppression de string_list_of_nat *)
+
+let unadjusted_string_of_nat nat off len_nat =
+ let len = num_digits_nat nat off len_nat in
+ if len = 1 then
+ raw_string_of_digit nat off
+ else
+ let len_copy = ref (succ len) in
+ let copy1 = create_nat !len_copy
+ and copy2 = make_nat !len_copy
+ and rest_digit = make_nat 2 in
+ if len > biggest_int / (succ pmax)
+ then failwith "number too long"
+ else let len_s = (succ pmax) * len in
+ let s = String.make len_s '0'
+ and pos_ref = ref len_s in
+ len_copy := pred !len_copy;
+ blit_nat copy1 0 nat off len;
+ set_digit_nat copy1 len 0;
+ while not (is_zero_nat copy1 0 !len_copy) do
+ div_digit_nat copy2 0
+ rest_digit 0
+ copy1 0 (succ !len_copy)
+ power_base_max 0;
+ let str = raw_string_of_digit rest_digit 0 in
+ String.blit str 0
+ s (!pos_ref - String.length str)
+ (String.length str);
+ (* XL: il y avait pmax a la place de String.length str
+ mais ca ne marche pas avec le blit de Caml Light,
+ qui ne verifie pas les debordements *)
+ pos_ref := !pos_ref - pmax;
+ len_copy := num_digits_nat copy2 0 !len_copy;
+ blit_nat copy1 0 copy2 0 !len_copy;
+ set_digit_nat copy1 !len_copy 0
+ done;
+ s
+
+let string_of_nat nat =
+ let s = unadjusted_string_of_nat nat 0 (length_nat nat)
+ and index = ref 0 in
+ begin try
+ for i = 0 to String.length s - 2 do
+ if String.get s i <> '0' then (index:= i; raise Exit)
+ done
+ with Exit -> ()
+ end;
+ String.sub s !index (String.length s - !index)
+
+(* XL: suppression de sys_string_of_nat *)
+
+(* XL: suppression de debug_string_nat *)
+
+let base_digit_of_char c base =
+ let n = Char.code c in
+ if n >= 48 & n <= 47 + min base 10 then n - 48
+ else if n >= 65 & n <= 65 + base - 11 then n - 55
+ else failwith "invalid digit"
+
+(*
+ La sous-chaine (s, off, len) represente un nat en base base que
+ on determine ici
+*)
+let sys_nat_of_string base s off len =
+ let power_base = make_nat (succ length_of_digit) in
+ let (pmax, pint) = make_power_base base power_base in
+ let new_len = ref (1 + len / (pmax + 1))
+ and current_len = ref 1 in
+ let possible_len = ref (min 2 !new_len) in
+
+ let nat1 = make_nat !new_len
+ and nat2 = make_nat !new_len
+
+ and digits_read = ref 0
+ and bound = off + len - 1
+ and int = ref 0 in
+
+ for i = off to bound do
+ (*
+ on lit pint (au maximum) chiffres, on en fait un int
+ et on l integre au nombre
+ *)
+ let c = String.get s i in
+ begin match c with
+ ' ' | '\t' | '\n' | '\r' | '\\' -> ()
+ | _ -> int := !int * base + base_digit_of_char c base;
+ incr digits_read
+ end;
+ if (!digits_read = pint or i = bound) & not (!digits_read = 0) then
+ begin
+ set_digit_nat nat1 0 !int;
+ for j = 1 to !current_len do
+ set_digit_nat nat1 j 0
+ done;
+ mult_digit_nat nat1 0 !possible_len
+ nat2 0 !current_len
+ power_base (pred !digits_read);
+ blit_nat nat2 0 nat1 0 !possible_len;
+ current_len := num_digits_nat nat1 0 !possible_len;
+ possible_len := min !new_len (succ !current_len);
+ int := 0;
+ digits_read := 0
+ end
+ done;
+ (*
+ On recadre le nat
+ *)
+ let nat = create_nat !current_len in
+ blit_nat nat 0 nat1 0 !current_len;
+ nat
+
+let nat_of_string s = sys_nat_of_string 10 s 0 (String.length s)
+
+let float_of_nat nat = float_of_string(string_of_nat nat)
diff --git a/otherlibs/num/num.ml b/otherlibs/num/num.ml
new file mode 100644
index 000000000..be61ff055
--- /dev/null
+++ b/otherlibs/num/num.ml
@@ -0,0 +1,398 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Int_misc
+open Nat
+open Big_int
+open Arith_flags
+open Ratio
+
+type num = Int of int | Big_int of big_int | Ratio of ratio
+ (* The type of numbers. *)
+
+let biggest_INT = big_int_of_int biggest_int
+and least_INT = big_int_of_int least_int
+
+(* Coercion big_int -> num *)
+let num_of_big_int bi =
+ if le_big_int bi biggest_INT & ge_big_int bi least_INT
+ then Int (int_of_big_int bi)
+ else Big_int bi
+
+let numerator_num = function
+ Ratio r -> normalize_ratio r; num_of_big_int (numerator_ratio r)
+| n -> n
+
+let denominator_num = function
+ Ratio r -> normalize_ratio r; num_of_big_int (denominator_ratio r)
+| n -> Int 1
+
+let normalize_num = function
+ Int i -> Int i
+| Big_int bi -> num_of_big_int bi
+| Ratio r -> if is_integer_ratio r
+ then num_of_big_int (numerator_ratio r)
+ else Ratio r
+
+let cautious_normalize_num_when_printing n =
+ if (!normalize_ratio_when_printing_flag) then (normalize_num n) else n
+
+(* Operations on num *)
+
+let add_num a b = match (a,b) with
+ ((Int int1), (Int int2)) ->
+ let r = int1 + int2 in
+ if (int1 lxor int2) lor (int1 lxor (r lxor (-1))) < 0
+ then Int r (* No overflow *)
+ else Big_int(add_big_int (big_int_of_int int1) (big_int_of_int int2))
+ | ((Int i), (Big_int bi)) ->
+ num_of_big_int (add_int_big_int i bi)
+ | ((Big_int bi), (Int i)) ->
+ num_of_big_int (add_int_big_int i bi)
+
+ | ((Int i), (Ratio r)) ->
+ Ratio (add_int_ratio i r)
+ | ((Ratio r), (Int i)) ->
+ Ratio (add_int_ratio i r)
+
+ | ((Big_int bi1), (Big_int bi2)) -> num_of_big_int (add_big_int bi1 bi2)
+
+ | ((Big_int bi), (Ratio r)) ->
+ Ratio (add_big_int_ratio bi r)
+ | ((Ratio r), (Big_int bi)) ->
+ Ratio (add_big_int_ratio bi r)
+
+ | ((Ratio r1), (Ratio r2)) -> Ratio (add_ratio r1 r2)
+
+let ( +/ ) = add_num
+
+let minus_num = function
+ Int i -> if i = monster_int
+ then Big_int (minus_big_int (big_int_of_int i))
+ else Int (-i)
+| Big_int bi -> Big_int (minus_big_int bi)
+| Ratio r -> Ratio (minus_ratio r)
+
+let sub_num n1 n2 = add_num n1 (minus_num n2)
+
+let ( -/ ) = sub_num
+
+let mult_num a b = match (a,b) with
+ ((Int int1), (Int int2)) ->
+ if num_bits_int int1 + num_bits_int int2 < length_of_int
+ then Int (int1 * int2)
+ else num_of_big_int (mult_big_int (big_int_of_int int1)
+ (big_int_of_int int2))
+
+ | ((Int i), (Big_int bi)) ->
+ num_of_big_int (mult_int_big_int i bi)
+ | ((Big_int bi), (Int i)) ->
+ num_of_big_int (mult_int_big_int i bi)
+
+ | ((Int i), (Ratio r)) ->
+ Ratio (mult_int_ratio i r)
+ | ((Ratio r), (Int i)) ->
+ Ratio (mult_int_ratio i r)
+
+ | ((Big_int bi1), (Big_int bi2)) ->
+ num_of_big_int (mult_big_int bi1 bi2)
+
+ | ((Big_int bi), (Ratio r)) ->
+ Ratio (mult_big_int_ratio bi r)
+ | ((Ratio r), (Big_int bi)) ->
+ Ratio (mult_big_int_ratio bi r)
+
+ | ((Ratio r1), (Ratio r2)) ->
+ Ratio (mult_ratio r1 r2)
+
+let ( */ ) = mult_num
+
+let square_num = function
+ Int i -> if 2 * num_bits_int i < length_of_int
+ then Int (i * i)
+ else num_of_big_int (square_big_int (big_int_of_int i))
+ | Big_int bi -> Big_int (square_big_int bi)
+ | Ratio r -> Ratio (square_ratio r)
+
+let div_num a b = match (a,b) with
+ ((Int int1), (Int int2)) ->
+ Ratio (create_ratio (big_int_of_int int1) (big_int_of_int int2))
+
+ | ((Int i), (Big_int bi)) ->
+ Ratio (create_ratio (big_int_of_int i) bi)
+
+ | ((Big_int bi), (Int i)) ->
+ Ratio (create_ratio bi (big_int_of_int i))
+
+ | ((Int i), (Ratio r)) ->
+ Ratio (div_int_ratio i r)
+ | ((Ratio r), (Int i)) ->
+ Ratio (div_ratio_int r i)
+
+ | ((Big_int bi1), (Big_int bi2)) ->
+ Ratio (create_ratio bi1 bi2)
+
+ | ((Big_int bi), (Ratio r)) ->
+ Ratio (div_big_int_ratio bi r)
+ | ((Ratio r), (Big_int bi)) ->
+ Ratio (div_ratio_big_int r bi)
+
+ | ((Ratio r1), (Ratio r2)) ->
+ Ratio (div_ratio r1 r2)
+
+let ( // ) = div_num
+
+let floor_num = function
+ Int i as n -> n
+| Big_int bi as n -> n
+| Ratio r -> num_of_big_int (floor_ratio r)
+
+let quo_num x y = floor_num (div_num x y)
+
+let mod_num x y = sub_num x (mult_num y (quo_num x y))
+
+let power_num_int a b = match (a,b) with
+ ((Int i), n) ->
+ (match sign_int n with
+ 0 -> Int 1
+ | 1 -> num_of_big_int (power_int_positive_int i n)
+ | _ -> Ratio (create_normalized_ratio
+ unit_big_int (power_int_positive_int i (-n))))
+| ((Big_int bi), n) ->
+ (match sign_int n with
+ 0 -> Int 1
+ | 1 -> num_of_big_int (power_big_int_positive_int bi n)
+ | _ -> Ratio (create_normalized_ratio
+ unit_big_int (power_big_int_positive_int bi (-n))))
+| ((Ratio r), n) ->
+ (match sign_int n with
+ 0 -> Int 1
+ | 1 -> Ratio (power_ratio_positive_int r n)
+ | _ -> Ratio (power_ratio_positive_int
+ (inverse_ratio r) (-n)))
+
+let power_num_big_int a b = match (a,b) with
+ ((Int i), n) ->
+ (match sign_big_int n with
+ 0 -> Int 1
+ | 1 -> num_of_big_int (power_int_positive_big_int i n)
+ | _ -> Ratio (create_normalized_ratio
+ unit_big_int
+ (power_int_positive_big_int i (minus_big_int n))))
+| ((Big_int bi), n) ->
+ (match sign_big_int n with
+ 0 -> Int 1
+ | 1 -> num_of_big_int (power_big_int_positive_big_int bi n)
+ | _ -> Ratio (create_normalized_ratio
+ unit_big_int
+ (power_big_int_positive_big_int bi (minus_big_int n))))
+| ((Ratio r), n) ->
+ (match sign_big_int n with
+ 0 -> Int 1
+ | 1 -> Ratio (power_ratio_positive_big_int r n)
+ | _ -> Ratio (power_ratio_positive_big_int
+ (inverse_ratio r) (minus_big_int n)))
+
+let power_num a b = match (a,b) with
+ (n, (Int i)) -> power_num_int n i
+| (n, (Big_int bi)) -> power_num_big_int n bi
+| _ -> invalid_arg "power_num"
+
+let ( **/ ) = power_num
+
+let is_integer_num = function
+ Int _ -> true
+| Big_int _ -> true
+| Ratio r -> is_integer_ratio r
+
+(* integer_num, floor_num, round_num, ceiling_num rendent des nums *)
+let integer_num = function
+ Int i as n -> n
+| Big_int bi as n -> n
+| Ratio r -> num_of_big_int (integer_ratio r)
+
+and round_num = function
+ Int i as n -> n
+| Big_int bi as n -> n
+| Ratio r -> num_of_big_int (round_ratio r)
+
+and ceiling_num = function
+ Int i as n -> n
+| Big_int bi as n -> n
+| Ratio r -> num_of_big_int (ceiling_ratio r)
+
+(* Comparisons on nums *)
+
+let sign_num = function
+ Int i -> sign_int i
+| Big_int bi -> sign_big_int bi
+| Ratio r -> sign_ratio r
+
+let eq_num a b = match (a,b) with
+ ((Int int1), (Int int2)) -> int1 = int2
+
+| ((Int i), (Big_int bi)) -> eq_big_int (big_int_of_int i) bi
+| ((Big_int bi), (Int i)) -> eq_big_int (big_int_of_int i) bi
+
+| ((Int i), (Ratio r)) -> eq_big_int_ratio (big_int_of_int i) r
+| ((Ratio r), (Int i)) -> eq_big_int_ratio (big_int_of_int i) r
+
+| ((Big_int bi1), (Big_int bi2)) -> eq_big_int bi1 bi2
+
+| ((Big_int bi), (Ratio r)) -> eq_big_int_ratio bi r
+| ((Ratio r), (Big_int bi)) -> eq_big_int_ratio bi r
+
+| ((Ratio r1), (Ratio r2)) -> eq_ratio r1 r2
+
+let ( =/ ) = eq_num
+
+let ( <>/ ) a b = not(eq_num a b)
+
+let compare_num a b = match (a,b) with
+ ((Int int1), (Int int2)) -> compare_int int1 int2
+
+| ((Int i), (Big_int bi)) -> compare_big_int (big_int_of_int i) bi
+| ((Big_int bi), (Int i)) -> compare_big_int bi (big_int_of_int i)
+
+| ((Int i), (Ratio r)) -> compare_big_int_ratio (big_int_of_int i) r
+| ((Ratio r), (Int i)) -> -(compare_big_int_ratio (big_int_of_int i) r)
+
+| ((Big_int bi1), (Big_int bi2)) -> compare_big_int bi1 bi2
+
+| ((Big_int bi), (Ratio r)) -> compare_big_int_ratio bi r
+| ((Ratio r), (Big_int bi)) -> -(compare_big_int_ratio bi r)
+
+| ((Ratio r1), (Ratio r2)) -> compare_ratio r1 r2
+
+let lt_num num1 num2 = compare_num num1 num2 < 0
+and le_num num1 num2 = compare_num num1 num2 <= 0
+and gt_num num1 num2 = compare_num num1 num2 > 0
+and ge_num num1 num2 = compare_num num1 num2 >= 0
+
+let ( </ ) = lt_num
+and ( <=/ ) = le_num
+and ( >/ ) = gt_num
+and ( >=/ ) = ge_num
+
+let max_num num1 num2 = if lt_num num1 num2 then num2 else num1
+and min_num num1 num2 = if gt_num num1 num2 then num2 else num1
+
+(* Coercions with basic types *)
+
+(* Coercion with int type *)
+let int_of_num = function
+ Int i -> i
+| Big_int bi -> int_of_big_int bi
+| Ratio r -> int_of_ratio r
+
+and num_of_int i =
+ if i = monster_int
+ then Big_int (big_int_of_int i)
+ else Int i
+
+(* Coercion with nat type *)
+let nat_of_num = function
+ Int i -> nat_of_int i
+| Big_int bi -> nat_of_big_int bi
+| Ratio r -> nat_of_ratio r
+
+and num_of_nat nat =
+ if (is_nat_int nat 0 (length_nat nat))
+ then Int (nth_digit_nat nat 0)
+ else Big_int (big_int_of_nat nat)
+
+(* Coercion with big_int type *)
+let big_int_of_num = function
+ Int i -> big_int_of_int i
+| Big_int bi -> bi
+| Ratio r -> big_int_of_ratio r
+
+(* Coercion with ratio type *)
+let ratio_of_num = function
+ Int i -> ratio_of_int i
+| Big_int bi -> ratio_of_big_int bi
+| Ratio r -> r
+
+and num_of_ratio r =
+ normalize_ratio r;
+ if not (is_integer_ratio r) then Ratio r
+ else if is_int_big_int (numerator_ratio r) then
+ Int (int_of_big_int (numerator_ratio r))
+ else Big_int (numerator_ratio r)
+
+let string_of_big_int_for_num bi =
+ if !approx_printing_flag
+ then approx_big_int !floating_precision bi
+ else string_of_big_int bi
+
+(* Coercion with string type *)
+
+(* XL: suppression de sys_string_of_num *)
+
+let string_of_normalized_num = function
+ Int i -> string_of_int i
+| Big_int bi -> string_of_big_int_for_num bi
+| Ratio r -> string_of_ratio r
+let string_of_num n =
+ string_of_normalized_num (cautious_normalize_num_when_printing n)
+let num_of_string s =
+ try
+ let flag = !normalize_ratio_flag in
+ normalize_ratio_flag := true;
+ let r = ratio_of_string s in
+ normalize_ratio_flag := flag;
+ if eq_big_int (denominator_ratio r) unit_big_int
+ then num_of_big_int (numerator_ratio r)
+ else Ratio r
+ with Failure _ ->
+ failwith "num_of_string"
+
+(* Coercion with float type *)
+let float_of_num = function
+ Int i -> float i
+| Big_int bi -> float_of_big_int bi
+| Ratio r -> float_of_ratio r
+
+(* XL: suppression de num_of_float, float_num *)
+
+let succ_num = function
+ Int i -> if i = biggest_int
+ then Big_int (succ_big_int (big_int_of_int i))
+ else Int (succ i)
+| Big_int bi -> num_of_big_int (succ_big_int bi)
+| Ratio r -> Ratio (add_int_ratio 1 r)
+
+and pred_num = function
+ Int i -> if i = monster_int
+ then Big_int (pred_big_int (big_int_of_int i))
+ else Int (pred i)
+| Big_int bi -> num_of_big_int (pred_big_int bi)
+| Ratio r -> Ratio (add_int_ratio (-1) r)
+
+let abs_num = function
+ Int i -> if i = monster_int
+ then Big_int (minus_big_int (big_int_of_int i))
+ else Int (abs i)
+ | Big_int bi -> Big_int (abs_big_int bi)
+ | Ratio r -> Ratio (abs_ratio r)
+
+let approx_num_fix n num = approx_ratio_fix n (ratio_of_num num)
+and approx_num_exp n num = approx_ratio_exp n (ratio_of_num num)
+
+let incr_num r = r := succ_num !r
+and decr_num r = r := pred_num !r
+
+
+
+
+
diff --git a/otherlibs/num/num.mli b/otherlibs/num/num.mli
new file mode 100644
index 000000000..77a82d728
--- /dev/null
+++ b/otherlibs/num/num.mli
@@ -0,0 +1,120 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Module [Num]: operation on arbitrary-precision numbers *)
+
+open Nat
+open Big_int
+open Ratio
+
+(* Numbers (type [num]) are arbitrary-precision rational numbers,
+ plus the special elements [1/0] (infinity) and [0/0] (undefined). *)
+
+type num = Int of int | Big_int of big_int | Ratio of ratio
+ (* The type of numbers. *)
+
+(* Arithmetic operations *)
+
+val (+/) : num -> num -> num
+val add_num : num -> num -> num
+ (* Addition *)
+val minus_num : num -> num
+ (* Unary negation. *)
+val (-/) : num -> num -> num
+val sub_num : num -> num -> num
+ (* Subtraction *)
+val ( */ ) : num -> num -> num
+val mult_num : num -> num -> num
+ (* Multiplication *)
+val square_num : num -> num
+ (* Squaring *)
+val (//) : num -> num -> num
+val div_num : num -> num -> num
+ (* Division *)
+val quo_num : num -> num -> num
+val mod_num : num -> num -> num
+ (* Euclidean division: quotient and remainder *)
+val ( **/ ) : num -> num -> num
+val power_num : num -> num -> num
+ (* Exponentiation *)
+val is_integer_num : num -> bool
+ (* Test if a number is an integer *)
+val integer_num : num -> num
+val floor_num : num -> num
+val round_num : num -> num
+val ceiling_num : num -> num
+ (* Approximate a number by an integer.
+ [floor_num n] returns the largest integer smaller or equal to [n].
+ [ceiling_num n] returns the smallest integer bigger or equal to [n].
+ [integer_num n] returns the integer closest to [n]. In case of ties,
+ rounds towards zero.
+ [round_num n] returns the integer closest to [n]. In case of ties,
+ rounds off zero. *)
+val sign_num : num -> int
+ (* Return [-1], [0] or [1] according to the sign of the argument. *)
+val (=/) : num -> num -> bool
+val (</) : num -> num -> bool
+val (>/) : num -> num -> bool
+val (<=/) : num -> num -> bool
+val (>=/) : num -> num -> bool
+val (<>/) : num -> num -> bool
+val eq_num : num -> num -> bool
+val lt_num : num -> num -> bool
+val le_num : num -> num -> bool
+val gt_num : num -> num -> bool
+val ge_num : num -> num -> bool
+ (* Usual comparisons between numbers *)
+val compare_num : num -> num -> int
+ (* Return [-1], [0] or [1] if the first argument is less than,
+ equal to, or greater than the second argument. *)
+val max_num : num -> num -> num
+val min_num : num -> num -> num
+ (* Return the greater (resp. the smaller) of the two arguments. *)
+val abs_num : num -> num
+ (* Absolute value. *)
+val succ_num: num -> num
+ (* [succ n] is [n+1] *)
+val pred_num: num -> num
+ (* [pred n] is [n-1] *)
+val incr_num: num ref -> unit
+ (* [incr r] is [r:=!r+1], where [r] is a reference to a number. *)
+val decr_num: num ref -> unit
+ (* [decr r] is [r:=!r-1], where [r] is a reference to a number. *)
+
+(* Coercions with strings *)
+
+val string_of_num : num -> string
+ (* Convert a number to a string, using fractional notation. *)
+val approx_num_fix : int -> num -> string
+val approx_num_exp : int -> num -> string
+ (* Approximate a number by a decimal. The first argument is the
+ required precision. The second argument is the number to
+ approximate. [approx_fix] uses decimal notation; the first
+ argument is the number of digits after the decimal point.
+ [approx_exp] uses scientific (exponential) notation; the
+ first argument is the number of digits in the mantissa. *)
+val num_of_string : string -> num
+ (* Convert a string to a number. *)
+
+(* Coercions between numerical types *)
+
+val int_of_num : num -> int
+val num_of_int : int -> num
+val nat_of_num : num -> nat
+val num_of_nat : nat -> num
+val num_of_big_int : big_int -> num
+val big_int_of_num : num -> big_int
+val ratio_of_num : num -> ratio
+val num_of_ratio : ratio -> num
+val float_of_num : num -> float
+
diff --git a/otherlibs/num/ratio.ml b/otherlibs/num/ratio.ml
new file mode 100644
index 000000000..d3168b239
--- /dev/null
+++ b/otherlibs/num/ratio.ml
@@ -0,0 +1,567 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+open Int_misc
+open String_misc
+open Nat
+open Big_int
+open Arith_flags
+
+(* Definition of the type ratio :
+ Conventions :
+ - the denominator is always a positive number
+ - the sign of n/0 is the sign of n
+These convention is automatically respected when a ratio is created with
+the create_ratio primitive
+*)
+
+type ratio = { mutable numerator : big_int;
+ mutable denominator : big_int;
+ mutable normalized : bool}
+
+let failwith_zero name =
+ let s = "infinite or undefined rational number" in
+ failwith (if String.length name = 0 then s else name ^ " " ^ s)
+
+let numerator_ratio r = r.numerator
+and denominator_ratio r = r.denominator
+
+let null_denominator r = sign_big_int r.denominator = 0
+
+let verify_null_denominator r =
+ if sign_big_int r.denominator = 0
+ then (if !error_when_null_denominator_flag
+ then (failwith_zero "")
+ else true)
+ else false
+
+let sign_ratio r = sign_big_int r.numerator
+
+(* Physical normalization of rational numbers *)
+(* 1/0, 0/0 and -1/0 are the normalized forms for n/0 numbers *)
+let normalize_ratio r =
+ if r.normalized then r
+ else if verify_null_denominator r then begin
+ r.numerator <- big_int_of_int (sign_big_int r.numerator);
+ r.normalized <- true;
+ r
+ end else begin
+ let p = gcd_big_int r.numerator r.denominator in
+ if eq_big_int p unit_big_int
+ then begin
+ r.normalized <- true; r
+ end else begin
+ r.numerator <- div_big_int (r.numerator) p;
+ r.denominator <- div_big_int (r.denominator) p;
+ r.normalized <- true; r
+ end
+ end
+
+let cautious_normalize_ratio r =
+ if (!normalize_ratio_flag) then (normalize_ratio r) else r
+
+let cautious_normalize_ratio_when_printing r =
+ if (!normalize_ratio_when_printing_flag) then (normalize_ratio r) else r
+
+let create_ratio bi1 bi2 =
+ match sign_big_int bi2 with
+ -1 -> cautious_normalize_ratio
+ { numerator = minus_big_int bi1;
+ denominator = minus_big_int bi2;
+ normalized = false }
+ | 0 -> if !error_when_null_denominator_flag
+ then (failwith_zero "create_ratio")
+ else cautious_normalize_ratio
+ { numerator = bi1; denominator = bi2; normalized = false }
+ | _ -> cautious_normalize_ratio
+ { numerator = bi1; denominator = bi2; normalized = false }
+
+let create_normalized_ratio bi1 bi2 =
+ match sign_big_int bi2 with
+ -1 -> { numerator = minus_big_int bi1;
+ denominator = minus_big_int bi2;
+ normalized = true }
+| 0 -> if !error_when_null_denominator_flag
+ then failwith_zero "create_normalized_ratio"
+ else { numerator = bi1; denominator = bi2; normalized = true }
+| _ -> { numerator = bi1; denominator = bi2; normalized = true }
+
+let is_normalized_ratio r = r.normalized
+
+let report_sign_ratio r bi =
+ if sign_ratio r = -1
+ then minus_big_int bi
+ else bi
+
+let abs_ratio r =
+ { numerator = abs_big_int r.numerator;
+ denominator = r.denominator;
+ normalized = r.normalized }
+
+let is_integer_ratio r =
+ eq_big_int ((normalize_ratio r).denominator) unit_big_int
+
+(* Operations on rational numbers *)
+
+let add_ratio r1 r2 =
+ if !normalize_ratio_flag then begin
+ let p = gcd_big_int ((normalize_ratio r1).denominator)
+ ((normalize_ratio r2).denominator) in
+ if eq_big_int p unit_big_int then
+ {numerator = add_big_int (mult_big_int (r1.numerator) r2.denominator)
+ (mult_big_int (r2.numerator) r1.denominator);
+ denominator = mult_big_int (r1.denominator) r2.denominator;
+ normalized = true}
+ else begin
+ let d1 = div_big_int (r1.denominator) p
+ and d2 = div_big_int (r2.denominator) p in
+ let n = add_big_int (mult_big_int (r1.numerator) d2)
+ (mult_big_int d1 r2.numerator) in
+ let p' = gcd_big_int n p in
+ { numerator = div_big_int n p';
+ denominator = mult_big_int d1 (div_big_int (r2.denominator) p');
+ normalized = true }
+ end
+ end else
+ { numerator = add_big_int (mult_big_int (r1.numerator) r2.denominator)
+ (mult_big_int (r1.denominator) r2.numerator);
+ denominator = mult_big_int (r1.denominator) r2.denominator;
+ normalized = false }
+
+let minus_ratio r =
+ { numerator = minus_big_int (r.numerator);
+ denominator = r.denominator;
+ normalized = r.normalized }
+
+let add_int_ratio i r =
+ cautious_normalize_ratio r;
+ { numerator = add_big_int (mult_int_big_int i r.denominator) r.numerator;
+ denominator = r.denominator;
+ normalized = r.normalized }
+
+let add_big_int_ratio bi r =
+ cautious_normalize_ratio r;
+ { numerator = add_big_int (mult_big_int bi r.denominator) r.numerator ;
+ denominator = r.denominator;
+ normalized = r.normalized }
+
+let sub_ratio r1 r2 = add_ratio r1 (minus_ratio r2)
+
+let mult_ratio r1 r2 =
+ if !normalize_ratio_flag then begin
+ let p1 = gcd_big_int ((normalize_ratio r1).numerator)
+ ((normalize_ratio r2).denominator)
+ and p2 = gcd_big_int (r2.numerator) r1.denominator in
+ let (n1, d2) =
+ if eq_big_int p1 unit_big_int
+ then (r1.numerator, r2.denominator)
+ else (div_big_int (r1.numerator) p1, div_big_int (r2.denominator) p1)
+ and (n2, d1) =
+ if eq_big_int p2 unit_big_int
+ then (r2.numerator, r1.denominator)
+ else (div_big_int r2.numerator p2, div_big_int r1.denominator p2) in
+ { numerator = mult_big_int n1 n2;
+ denominator = mult_big_int d1 d2;
+ normalized = true }
+ end else
+ { numerator = mult_big_int (r1.numerator) r2.numerator;
+ denominator = mult_big_int (r1.denominator) r2.denominator;
+ normalized = false }
+
+let mult_int_ratio i r =
+ if !normalize_ratio_flag then
+ begin
+ let p = gcd_big_int ((normalize_ratio r).denominator) (big_int_of_int i) in
+ if eq_big_int p unit_big_int
+ then { numerator = mult_big_int (big_int_of_int i) r.numerator;
+ denominator = r.denominator;
+ normalized = true }
+ else { numerator = mult_big_int (div_big_int (big_int_of_int i) p)
+ r.numerator;
+ denominator = div_big_int (r.denominator) p;
+ normalized = true }
+ end
+ else
+ { numerator = mult_int_big_int i r.numerator;
+ denominator = r.denominator;
+ normalized = false }
+
+let mult_big_int_ratio bi r =
+ if !normalize_ratio_flag then
+ begin
+ let p = gcd_big_int ((normalize_ratio r).denominator) bi in
+ if eq_big_int p unit_big_int
+ then { numerator = mult_big_int bi r.numerator;
+ denominator = r.denominator;
+ normalized = true }
+ else { numerator = mult_big_int (div_big_int bi p) r.numerator;
+ denominator = div_big_int (r.denominator) p;
+ normalized = true }
+ end
+ else
+ { numerator = mult_big_int bi r.numerator;
+ denominator = r.denominator;
+ normalized = false }
+
+let square_ratio r =
+ cautious_normalize_ratio r;
+ { numerator = square_big_int r.numerator;
+ denominator = square_big_int r.denominator;
+ normalized = r.normalized }
+
+let inverse_ratio r =
+ if !error_when_null_denominator_flag & (sign_big_int r.numerator) = 0
+ then failwith_zero "inverse_ratio"
+ else {numerator = report_sign_ratio r r.denominator;
+ denominator = abs_big_int r.numerator;
+ normalized = r.normalized}
+
+let div_ratio r1 r2 =
+ mult_ratio r1 (inverse_ratio r2)
+
+(* Integer part of a rational number *)
+(* Odd function *)
+let integer_ratio r =
+ if null_denominator r then failwith_zero "integer_ratio"
+ else if sign_ratio r = 0 then zero_big_int
+ else report_sign_ratio r (div_big_int (abs_big_int r.numerator)
+ (abs_big_int r.denominator))
+
+(* Floor of a rational number *)
+(* Always less or equal to r *)
+let floor_ratio r =
+ verify_null_denominator r;
+ div_big_int (r.numerator) r.denominator
+
+(* Round of a rational number *)
+(* Odd function, 1/2 -> 1 *)
+let round_ratio r =
+ verify_null_denominator r;
+ let abs_num = abs_big_int r.numerator in
+ let bi = div_big_int abs_num r.denominator in
+ report_sign_ratio r
+ (if sign_big_int
+ (sub_big_int
+ (mult_int_big_int
+ 2
+ (sub_big_int abs_num (mult_big_int (r.denominator) bi)))
+ r.denominator) = -1
+ then bi
+ else succ_big_int bi)
+
+let ceiling_ratio r =
+ if (is_integer_ratio r)
+ then r.numerator
+ else succ_big_int (floor_ratio r)
+
+
+(* Comparison operators on rational numbers *)
+let eq_ratio r1 r2 =
+ normalize_ratio r1;
+ normalize_ratio r2;
+ eq_big_int (r1.numerator) r2.numerator &
+ eq_big_int (r1.denominator) r2.denominator
+
+let compare_ratio r1 r2 =
+ if verify_null_denominator r1 then
+ let sign_num_r1 = sign_big_int r1.numerator in
+ if (verify_null_denominator r2)
+ then
+ let sign_num_r2 = sign_big_int r2.numerator in
+ if sign_num_r1 = 1 & sign_num_r2 = -1 then 1
+ else if sign_num_r1 = -1 & sign_num_r2 = 1 then -1
+ else 0
+ else sign_num_r1
+ else if verify_null_denominator r2 then
+ -(sign_big_int r2.numerator)
+ else match compare_int (sign_big_int r1.numerator)
+ (sign_big_int r2.numerator) with
+ 1 -> 1
+ | -1 -> -1
+ | _ -> if eq_big_int (r1.denominator) r2.denominator
+ then compare_big_int (r1.numerator) r2.numerator
+ else compare_big_int
+ (mult_big_int (r1.numerator) r2.denominator)
+ (mult_big_int (r1.denominator) r2.numerator)
+
+
+let lt_ratio r1 r2 = compare_ratio r1 r2 < 0
+and le_ratio r1 r2 = compare_ratio r1 r2 <= 0
+and gt_ratio r1 r2 = compare_ratio r1 r2 > 0
+and ge_ratio r1 r2 = compare_ratio r1 r2 >= 0
+
+let max_ratio r1 r2 = if lt_ratio r1 r2 then r2 else r1
+and min_ratio r1 r2 = if gt_ratio r1 r2 then r2 else r1
+
+let eq_big_int_ratio bi r =
+ (is_integer_ratio r) & eq_big_int bi r.numerator
+
+let compare_big_int_ratio bi r =
+ normalize_ratio r;
+ if (verify_null_denominator r)
+ then -(sign_big_int r.numerator)
+ else compare_big_int (mult_big_int bi r.denominator) r.numerator
+
+let lt_big_int_ratio bi r = compare_big_int_ratio bi r < 0
+and le_big_int_ratio bi r = compare_big_int_ratio bi r <= 0
+and gt_big_int_ratio bi r = compare_big_int_ratio bi r > 0
+and ge_big_int_ratio bi r = compare_big_int_ratio bi r >= 0
+
+(* Coercions *)
+
+(* Coercions with type int *)
+let int_of_ratio r =
+ if ((is_integer_ratio r) & (is_int_big_int r.numerator))
+ then (int_of_big_int r.numerator)
+ else failwith "integer argument required"
+
+and ratio_of_int i =
+ { numerator = big_int_of_int i;
+ denominator = unit_big_int;
+ normalized = true }
+
+(* Coercions with type nat *)
+let ratio_of_nat nat =
+ { numerator = big_int_of_nat nat;
+ denominator = unit_big_int;
+ normalized = true }
+
+and nat_of_ratio r =
+ normalize_ratio r;
+ if not (is_integer_ratio r) then
+ failwith "nat_of_ratio"
+ else if sign_big_int r.numerator > -1 then
+ nat_of_big_int (r.numerator)
+ else failwith "nat_of_ratio"
+
+(* Coercions with type big_int *)
+let ratio_of_big_int bi =
+ { numerator = bi; denominator = unit_big_int; normalized = true }
+
+and big_int_of_ratio r =
+ normalize_ratio r;
+ if is_integer_ratio r
+ then r.numerator
+ else failwith "big_int_of_ratio"
+
+let div_int_ratio i r =
+ verify_null_denominator r;
+ mult_int_ratio i (inverse_ratio r)
+
+let div_ratio_int r i =
+ div_ratio r (ratio_of_int i)
+
+let div_big_int_ratio bi r =
+ verify_null_denominator r;
+ mult_big_int_ratio bi (inverse_ratio r)
+
+let div_ratio_big_int r bi =
+ div_ratio r (ratio_of_big_int bi)
+
+(* Functions on type string *)
+(* giving floating point approximations of rational numbers *)
+
+let only_zeros s i l =
+ let res = ref true in
+ for j = i to i + l - 1 do
+ if s.[j] <> '0' then res := false
+ done;
+ !res
+
+(* Position of the leading digit of the decimal expansion *)
+(* of a strictly positive rational number *)
+(* if the decimal expansion of a non null rational r is equal to *)
+(* sigma for k=-P to N of r_k*10^k then msd_ratio r = N *)
+(* Nota : for a big_int we have msd_ratio = nums_digits_big_int -1 *)
+let msd_ratio r =
+ cautious_normalize_ratio r;
+ if null_denominator r then failwith_zero "msd_ratio"
+ else if sign_big_int r.numerator = 0 then 0
+ else begin
+ let str_num = string_of_big_int r.numerator
+ and str_den = string_of_big_int r.denominator in
+ let size_num = String.length str_num
+ and size_den = String.length str_den in
+ let rec msd_rec str_num nnum str_den nden i m =
+ if i > nnum then
+ if i > nden or only_zeros str_den i (nden - i)
+ then m else pred m
+ else if i > nden then m
+ else match compare_int (Char.code (String.get str_num i))
+ (Char.code (String.get str_den i)) with
+ 0 -> msd_rec str_num nnum str_den nden (succ i) m
+ | 1 -> m
+ | _ -> pred m
+ in msd_rec str_num (pred size_num) str_den (pred size_den)
+ 0 (size_num - size_den)
+ end
+
+(* Decimal approximations of rational numbers *)
+
+(* Approximation with fix decimal point *)
+(* This is an odd function and the last digit is round off *)
+(* Format integer_part . decimal_part_with_n_digits *)
+let approx_ratio_fix n r =
+ (* Don't need to normalize *)
+ if (null_denominator r) then failwith_zero "approx_ratio_fix"
+ else
+ let sign_r = sign_ratio r in
+ if sign_r = 0
+ then "+0" (* r = 0 *)
+ else (* r.numerator and r.denominator are not null numbers
+ s contains one more digit than desired for the round off operation
+ and to have enough room in s when including the decimal point *)
+ if n >= 0 then
+ let s =
+ let nat =
+ (nat_of_big_int
+ (div_big_int
+ (base_power_big_int
+ 10 (succ n) (abs_big_int r.numerator))
+ r.denominator))
+ in (if sign_r = -1 then "-" else "+") ^ string_of_nat nat in
+ let l = String.length s in
+ if round_futur_last_digit s 1 (pred l)
+ then begin (* if one more char is needed in s *)
+ let str = (String.make (succ l) '0') in
+ String.set str 0 (if sign_r = -1 then '-' else '+');
+ String.set str 1 '1';
+ String.set str (l - n) '.';
+ str
+ end else (* s can contain the final result *)
+ if l > n + 2
+ then begin (* |r| >= 1, set decimal point *)
+ let l2 = (pred l) - n in
+ String.blit s l2 s (succ l2) n;
+ String.set s l2 '.'; s
+ end else begin (* |r| < 1, there must be 0-characters *)
+ (* before the significant development, *)
+ (* with care to the sign of the number *)
+ let size = n + 3 in
+ let m = size - l + 2
+ and str = String.make size '0' in
+
+ (String.blit (if sign_r = 1 then "+0." else "-0.") 0 str 0 3);
+ (String.blit s 1 str m (l - 2));
+ str
+ end
+ else begin
+ let s = string_of_big_int
+ (div_big_int
+ (abs_big_int r.numerator)
+ (base_power_big_int
+ 10 (-n) r.denominator)) in
+ let len = succ (String.length s) in
+ let s' = String.make len '0' in
+ String.set s' 0 (if sign_r = -1 then '-' else '+');
+ String.blit s 0 s' 1 (pred len);
+ s'
+ end
+
+(* Number of digits of the decimal representation of an int *)
+let num_decimal_digits_int n =
+ String.length (string_of_int n)
+
+(* Approximation with floating decimal point *)
+(* This is an odd function and the last digit is round off *)
+(* Format (+/-)(0. n_first_digits e msd)/(1. n_zeros e (msd+1) *)
+let approx_ratio_exp n r =
+ (* Don't need to normalize *)
+ if (null_denominator r) then failwith_zero "approx_ratio_exp"
+ else if n <= 0 then invalid_arg "approx_ratio_exp"
+ else
+ let sign_r = sign_ratio r
+ and i = ref (n + 3) in
+ if sign_r = 0
+ then
+ let s = String.make (n + 5) '0' in
+ (String.blit "+0." 0 s 0 3);
+ (String.blit "e0" 0 s !i 2); s
+ else
+ let msd = msd_ratio (abs_ratio r) in
+ let k = n - msd in
+ let s =
+ (let nat = nat_of_big_int
+ (if k < 0
+ then
+ div_big_int (abs_big_int r.numerator)
+ (base_power_big_int 10 (-k)
+ r.denominator)
+ else
+ div_big_int (base_power_big_int
+ 10 k (abs_big_int r.numerator))
+ r.denominator) in
+ 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
+ let str = String.make (n + m + 4) '0' in
+ (String.blit (if sign_r = -1 then "-1." else "+1.") 0 str 0 3);
+ String.set str !i ('e');
+ incr i;
+ (if m = 0
+ then String.set str !i '0'
+ else String.blit (string_of_int (succ msd)) 0 str !i m);
+ str
+ else
+ let m = num_decimal_digits_int (succ msd)
+ and p = n + 3 in
+ let str = String.make (succ (m + p)) '0' in
+ (String.blit (if sign_r = -1 then "-0." else "+0.") 0 str 0 3);
+ (String.blit s 0 str 3 n);
+ String.set str p 'e';
+ (if m = 0
+ then String.set str (succ p) '0'
+ else (String.blit (string_of_int (succ msd)) 0 str (succ p) m));
+ str
+
+(* String approximation of a rational with a fixed number of significant *)
+(* digits printed *)
+let float_of_rational_string r =
+ let s = approx_ratio_exp !floating_precision r in
+ if String.get s 0 = '+'
+ then (String.sub s 1 (pred (String.length s)))
+ else s
+
+(* Coercions with type string *)
+let string_of_ratio r =
+ cautious_normalize_ratio_when_printing r;
+ if !approx_printing_flag
+ then float_of_rational_string r
+ else string_of_big_int r.numerator ^ "/" ^ string_of_big_int r.denominator
+
+(* XL: j'ai puissamment simplifie "ratio_of_string" en virant la notation
+ scientifique. *)
+
+let ratio_of_string s =
+ let n = index_char s '/' 0 in
+ if n = -1 then
+ { numerator = big_int_of_string s;
+ denominator = unit_big_int;
+ normalized = true }
+ else
+ create_ratio (sys_big_int_of_string s 0 n)
+ (sys_big_int_of_string s (n+1) (String.length s - n - 1))
+
+(* Coercion with type float *)
+
+let float_of_ratio r =
+ float_of_string (float_of_rational_string r)
+
+(* XL: suppression de ratio_of_float *)
+
+let power_ratio_positive_int r n =
+ create_ratio (power_big_int_positive_int (r.numerator) n)
+ (power_big_int_positive_int (r.denominator) n)
+
+let power_ratio_positive_big_int r bi =
+ create_ratio (power_big_int_positive_big_int (r.numerator) bi)
+ (power_big_int_positive_big_int (r.denominator) bi)
diff --git a/otherlibs/num/ratio.mli b/otherlibs/num/ratio.mli
new file mode 100644
index 000000000..524b7b48a
--- /dev/null
+++ b/otherlibs/num/ratio.mli
@@ -0,0 +1,86 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Module [Ratio]: operations on rational numbers *)
+
+open Nat
+open Big_int
+
+(* Rationals (type [ratio]) are arbitrary-precision rational numbers,
+ plus the special elements [1/0] (infinity) and [0/0] (undefined).
+ In constrast with numbers (type [num]), the special cases of
+ small integers and big integers are not optimized specially. *)
+
+type ratio
+
+val null_denominator : ratio -> bool
+val numerator_ratio : ratio -> big_int
+val denominator_ratio : ratio -> big_int
+val sign_ratio : ratio -> int
+val normalize_ratio : ratio -> ratio
+val cautious_normalize_ratio : ratio -> ratio
+val cautious_normalize_ratio_when_printing : ratio -> ratio
+val create_ratio : big_int -> big_int -> ratio
+val create_normalized_ratio : big_int -> big_int -> ratio
+val is_normalized_ratio : ratio -> bool
+val report_sign_ratio : ratio -> big_int -> big_int
+val abs_ratio : ratio -> ratio
+val is_integer_ratio : ratio -> bool
+val add_ratio : ratio -> ratio -> ratio
+val minus_ratio : ratio -> ratio
+val add_int_ratio : int -> ratio -> ratio
+val add_big_int_ratio : big_int -> ratio -> ratio
+val sub_ratio : ratio -> ratio -> ratio
+val mult_ratio : ratio -> ratio -> ratio
+val mult_int_ratio : int -> ratio -> ratio
+val mult_big_int_ratio : big_int -> ratio -> ratio
+val square_ratio : ratio -> ratio
+val inverse_ratio : ratio -> ratio
+val div_ratio : ratio -> ratio -> ratio
+val integer_ratio : ratio -> big_int
+val floor_ratio : ratio -> big_int
+val round_ratio : ratio -> big_int
+val ceiling_ratio : ratio -> big_int
+val eq_ratio : ratio -> ratio -> bool
+val compare_ratio : ratio -> ratio -> int
+val lt_ratio : ratio -> ratio -> bool
+val le_ratio : ratio -> ratio -> bool
+val gt_ratio : ratio -> ratio -> bool
+val ge_ratio : ratio -> ratio -> bool
+val max_ratio : ratio -> ratio -> ratio
+val min_ratio : ratio -> ratio -> ratio
+val eq_big_int_ratio : big_int -> ratio -> bool
+val compare_big_int_ratio : big_int -> ratio -> int
+val lt_big_int_ratio : big_int -> ratio -> bool
+val le_big_int_ratio : big_int -> ratio -> bool
+val gt_big_int_ratio : big_int -> ratio -> bool
+val ge_big_int_ratio : big_int -> ratio -> bool
+val int_of_ratio : ratio -> int
+val ratio_of_int : int -> ratio
+val ratio_of_nat : nat -> ratio
+val nat_of_ratio : ratio -> nat
+val ratio_of_big_int : big_int -> ratio
+val big_int_of_ratio : ratio -> big_int
+val div_int_ratio : int -> ratio -> ratio
+val div_ratio_int : ratio -> int -> ratio
+val div_big_int_ratio : big_int -> ratio -> ratio
+val div_ratio_big_int : ratio -> big_int -> ratio
+val approx_ratio_fix : int -> ratio -> string
+val approx_ratio_exp : int -> ratio -> string
+val float_of_rational_string : ratio -> string
+val string_of_ratio : ratio -> string
+val ratio_of_string : string -> ratio
+val float_of_ratio : ratio -> float
+val power_ratio_positive_int : ratio -> int -> ratio
+val power_ratio_positive_big_int : ratio -> big_int -> ratio
+
diff --git a/otherlibs/num/string_misc.ml b/otherlibs/num/string_misc.ml
new file mode 100644
index 000000000..ba86407d8
--- /dev/null
+++ b/otherlibs/num/string_misc.ml
@@ -0,0 +1,18 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+let rec index_char str chr pos =
+ if pos >= String.length str then -1
+ else if String.get str pos = chr then pos
+ else index_char str chr (pos + 1)
+;;
diff --git a/otherlibs/num/string_misc.mli b/otherlibs/num/string_misc.mli
new file mode 100644
index 000000000..cffd4729e
--- /dev/null
+++ b/otherlibs/num/string_misc.mli
@@ -0,0 +1,14 @@
+(***********************************************************************)
+(* *)
+(* Caml Special Light *)
+(* *)
+(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1995 Institut National de Recherche en Informatique et *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+val index_char: string -> char -> int -> int
diff --git a/otherlibs/num/test/Makefile b/otherlibs/num/test/Makefile
new file mode 100644
index 000000000..b6723b5cd
--- /dev/null
+++ b/otherlibs/num/test/Makefile
@@ -0,0 +1,36 @@
+CAMLC=../../../boot/cslrun ../../../cslc -I ../../../stdlib
+CAMLOPT=../../../boot/cslrun ../../../cslopt -I ../../../stdlib
+
+test: test.byt test.opt
+ ./test.byt
+ ./test.opt
+
+TESTFILES=test.cmo \
+ test_nats.cmo test_big_ints.cmo test_ratios.cmo test_nums.cmo end_test.cmo
+
+TESTOPTFILES=$(TESTFILES:.cmo=.cmx)
+
+test.byt: $(TESTFILES) ../nums.cma ../libnums.a
+ $(CAMLC) -o test.byt -custom ../nums.cma $(TESTFILES) ../libnums.a
+
+test.opt: $(TESTOPTFILES) ../nums.cmxa ../libnums.a
+ $(CAMLOPT) -o test.opt ../nums.cmxa $(TESTOPTFILES) ../libnums.a
+
+.SUFFIXES: .ml .cmo .cmx
+
+.ml.cmo:
+ $(CAMLC) -I .. -c $<
+
+.ml.cmx:
+ $(CAMLOPT) -I .. -c $<
+
+csltopnum:
+ cslmktop -o csltopnum -custom ../nums.cma ../libnums.a
+
+clean:
+ rm -f test.byt test.opt *.o *.cm? csltopnum
+
+depend:
+ csldep *.ml > .depend
+
+include .depend
diff --git a/otherlibs/num/test/end_test.ml b/otherlibs/num/test/end_test.ml
new file mode 100644
index 000000000..40aceb959
--- /dev/null
+++ b/otherlibs/num/test/end_test.ml
@@ -0,0 +1,8 @@
+open Test
+
+let _ =
+ print_newline();
+ if !error_occurred then begin
+ prerr_endline "************* TEST FAILED ****************"; exit 2
+ end else
+ exit 0
diff --git a/otherlibs/num/test/test.ml b/otherlibs/num/test/test.ml
new file mode 100644
index 000000000..8ad93204a
--- /dev/null
+++ b/otherlibs/num/test/test.ml
@@ -0,0 +1,60 @@
+open Printf
+
+let error_occurred = ref false
+
+let function_tested = ref ""
+
+let testing_function s =
+ function_tested := s;
+ print_newline();
+ print_string s;
+ print_newline()
+
+let test test_number eq_fun (answer, correct_answer) =
+ flush stdout;
+ flush stderr;
+ if not (eq_fun answer correct_answer) then begin
+ fprintf stderr ">>> Bad result (%s, test %d)\n" !function_tested test_number;
+ error_occurred := true;
+ false
+ end else begin
+ printf " %d..." test_number;
+ true
+ end
+
+let failure_test test_number fun_to_test arg =
+ flush stdout;
+ flush stderr;
+ try
+ fun_to_test arg;
+ fprintf stderr ">>> Failure expected (%s, test %d)\n"
+ !function_tested test_number;
+ error_occurred := true;
+ false
+ with _ ->
+ printf " %d..." test_number;
+ true
+
+let failwith_test test_number fun_to_test arg correct_failure =
+ try
+ fun_to_test arg;
+ fprintf stderr ">>> Failure expected (%s, test %d)\n"
+ !function_tested test_number;
+ error_occurred := true;
+ false
+ with x ->
+ if x = correct_failure then begin
+ printf " %d..." test_number;
+ true
+ end else begin
+ fprintf stderr ">>> Bad failure (%s, test %d)\n"
+ !function_tested test_number;
+ error_occurred := true;
+ false
+ end
+
+let eq = (==)
+let eq_int = (==)
+let eq_string = (=)
+
+let sixtyfour = (1 lsl 32) <> 0
diff --git a/otherlibs/num/test/test_big_ints.ml b/otherlibs/num/test/test_big_ints.ml
new file mode 100644
index 000000000..b7553044d
--- /dev/null
+++ b/otherlibs/num/test/test_big_ints.ml
@@ -0,0 +1,365 @@
+open Test;;
+open Nat;;
+open Big_int;;
+open Int_misc;;
+
+testing_function "compare_big_int";;
+
+test 1
+eq_int (compare_big_int zero_big_int zero_big_int, 0);;
+test 2
+eq_int (compare_big_int zero_big_int (big_int_of_int 1), (-1));;
+test 3
+eq_int (compare_big_int zero_big_int (big_int_of_int (-1)), 1);;
+test 4
+eq_int (compare_big_int (big_int_of_int 1) zero_big_int, 1);;
+test 5
+eq_int (compare_big_int (big_int_of_int (-1)) zero_big_int, (-1));;
+test 6
+eq_int (compare_big_int (big_int_of_int 1) (big_int_of_int 1), 0);;
+test 7
+eq_int (compare_big_int (big_int_of_int (-1)) (big_int_of_int (-1)), 0);;
+test 8
+eq_int (compare_big_int (big_int_of_int 1) (big_int_of_int (-1)), 1);;
+test 9
+eq_int (compare_big_int (big_int_of_int (-1)) (big_int_of_int 1), (-1));;
+test 10
+eq_int (compare_big_int (big_int_of_int 1) (big_int_of_int 2), (-1));;
+test 11
+eq_int (compare_big_int (big_int_of_int 2) (big_int_of_int 1), 1);;
+test 12
+eq_int (compare_big_int (big_int_of_int (-1)) (big_int_of_int (-2)), 1);;
+test 13
+eq_int (compare_big_int (big_int_of_int (-2)) (big_int_of_int (-1)), (-1));;
+
+
+testing_function "pred_big_int";;
+
+test 1
+eq_big_int (pred_big_int zero_big_int, big_int_of_int (-1));;
+test 2
+eq_big_int (pred_big_int unit_big_int, zero_big_int);;
+test 3
+eq_big_int (pred_big_int (big_int_of_int (-1)), big_int_of_int (-2));;
+
+testing_function "succ_big_int";;
+
+test 1
+eq_big_int (succ_big_int zero_big_int, unit_big_int);;
+test 2
+eq_big_int (succ_big_int unit_big_int, big_int_of_int 2);;
+test 3
+eq_big_int (succ_big_int (big_int_of_int (-1)), zero_big_int);;
+
+testing_function "add_big_int";;
+
+test 1
+eq_big_int (add_big_int zero_big_int zero_big_int, zero_big_int);;
+test 2
+eq_big_int (add_big_int zero_big_int (big_int_of_int 1),
+ big_int_of_int 1);;
+test 3
+eq_big_int (add_big_int (big_int_of_int 1) zero_big_int,
+ big_int_of_int 1);;
+test 4
+eq_big_int (add_big_int zero_big_int (big_int_of_int (-1)),
+ big_int_of_int (-1));;
+test 5
+eq_big_int (add_big_int (big_int_of_int (-1)) zero_big_int,
+ big_int_of_int (-1));;
+test 6
+eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int 1),
+ big_int_of_int 2);;
+test 7
+eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int 2),
+ big_int_of_int 3);;
+test 8
+eq_big_int (add_big_int (big_int_of_int 2) (big_int_of_int 1),
+ big_int_of_int 3);;
+test 9
+eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int (-1)),
+ big_int_of_int (-2));;
+test 10
+eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int (-2)),
+ big_int_of_int (-3));;
+test 11
+eq_big_int (add_big_int (big_int_of_int (-2)) (big_int_of_int (-1)),
+ big_int_of_int (-3));;
+test 12
+eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int (-1)),
+ zero_big_int);;
+test 13
+eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int 1),
+ zero_big_int);;
+test 14
+eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int (-2)),
+ big_int_of_int (-1));;
+test 15
+eq_big_int (add_big_int (big_int_of_int (-2)) (big_int_of_int 1),
+ big_int_of_int (-1));;
+test 16
+eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int 2),
+ big_int_of_int 1);;
+test 17
+eq_big_int (add_big_int (big_int_of_int 2) (big_int_of_int (-1)),
+ big_int_of_int 1);;
+
+
+testing_function "sub_big_int";;
+
+test 1
+eq_big_int (sub_big_int zero_big_int zero_big_int, zero_big_int);;
+test 2
+eq_big_int (sub_big_int zero_big_int (big_int_of_int 1),
+ big_int_of_int (-1));;
+test 3
+eq_big_int (sub_big_int (big_int_of_int 1) zero_big_int,
+ big_int_of_int 1);;
+test 4
+eq_big_int (sub_big_int zero_big_int (big_int_of_int (-1)),
+ big_int_of_int 1);;
+test 5
+eq_big_int (sub_big_int (big_int_of_int (-1)) zero_big_int,
+ big_int_of_int (-1));;
+test 6
+eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int 1),
+ zero_big_int);;
+test 7
+eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int 2),
+ big_int_of_int (-1));;
+test 8
+eq_big_int (sub_big_int (big_int_of_int 2) (big_int_of_int 1),
+ big_int_of_int 1);;
+test 9
+eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int (-1)),
+ zero_big_int);;
+test 10
+eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int (-2)),
+ big_int_of_int 1);;
+test 11
+eq_big_int (sub_big_int (big_int_of_int (-2)) (big_int_of_int (-1)),
+ big_int_of_int (-1));;
+test 12
+eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int (-1)),
+ big_int_of_int 2);;
+test 13
+eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int 1),
+ big_int_of_int (-2));;
+test 14
+eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int (-2)),
+ big_int_of_int 3);;
+test 15
+eq_big_int (sub_big_int (big_int_of_int (-2)) (big_int_of_int 1),
+ big_int_of_int (-3));;
+test 16
+eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int 2),
+ big_int_of_int (-3));;
+test 17
+eq_big_int (sub_big_int (big_int_of_int 2) (big_int_of_int (-1)),
+ big_int_of_int 3);;
+
+testing_function "mult_int_big_int";;
+
+test 1
+eq_big_int (mult_int_big_int 0 (big_int_of_int 3), zero_big_int);;
+test 2
+eq_big_int (mult_int_big_int 1 (big_int_of_int 3), big_int_of_int 3);;
+test 3
+eq_big_int (mult_int_big_int 1 zero_big_int, zero_big_int);;
+test 4
+eq_big_int (mult_int_big_int 2 (big_int_of_int 3), big_int_of_int 6);;
+
+testing_function "mult_big_int";;
+
+test 1
+eq_big_int (mult_big_int zero_big_int zero_big_int,
+ zero_big_int);;
+test 2
+eq_big_int (mult_big_int (big_int_of_int 2) (big_int_of_int 3),
+ big_int_of_int 6);;
+test 3
+eq_big_int (mult_big_int (big_int_of_int 2) (big_int_of_int (-3)),
+ big_int_of_int (-6));;
+test 4
+eq_big_int (mult_big_int (big_int_of_string "12724951")
+ (big_int_of_string "81749606400"),
+ big_int_of_string "1040259735709286400");;
+test 5
+eq_big_int (mult_big_int (big_int_of_string "26542080")
+ (big_int_of_string "81749606400"),
+ big_int_of_string "2169804593037312000");;
+
+testing_function "quomod_big_int";;
+
+let (quotient, modulo) =
+ quomod_big_int (big_int_of_int 1) (big_int_of_int 1) in
+ test 1 eq_big_int (quotient, big_int_of_int 1) &
+ test 2 eq_big_int (modulo, zero_big_int);;
+
+let (quotient, modulo) =
+ quomod_big_int (big_int_of_int 1) (big_int_of_int (-1)) in
+ test 3 eq_big_int (quotient, big_int_of_int (-1)) &
+ test 4 eq_big_int (modulo, zero_big_int);;
+
+let (quotient, modulo) =
+ quomod_big_int (big_int_of_int (-1)) (big_int_of_int 1) in
+ test 5 eq_big_int (quotient, big_int_of_int (-1)) &
+ test 6 eq_big_int (modulo, zero_big_int);;
+
+let (quotient, modulo) =
+ quomod_big_int (big_int_of_int 3) (big_int_of_int 2) in
+ test 7 eq_big_int (quotient, big_int_of_int 1) &
+ test 8 eq_big_int (modulo, big_int_of_int 1);;
+
+let (quotient, modulo) =
+ quomod_big_int (big_int_of_int 5) (big_int_of_int 3) in
+ test 9 eq_big_int (quotient, big_int_of_int 1) &
+ test 10 eq_big_int (modulo, big_int_of_int 2);;
+
+let (quotient, modulo) =
+ quomod_big_int (big_int_of_int (-5)) (big_int_of_int 3) in
+ test 11 eq_big_int (quotient, big_int_of_int (-2)) &
+ test 12 eq_big_int (modulo, big_int_of_int 1);;
+
+let (quotient, modulo) =
+ quomod_big_int (big_int_of_int 1) (big_int_of_int 2) in
+ test 13 eq_big_int (quotient, zero_big_int) &
+ test 14 eq_big_int (modulo, big_int_of_int 1);;
+
+let (quotient, modulo) =
+ quomod_big_int (big_int_of_int (-1)) (big_int_of_int 3) in
+ test 15 eq_big_int (quotient, minus_big_int unit_big_int) &
+ test 16 eq_big_int (modulo, big_int_of_int 2);;
+
+failwith_test 17
+(quomod_big_int (big_int_of_int 1)) zero_big_int
+Division_by_zero
+;;
+
+testing_function "gcd_big_int";;
+
+test 1
+eq_big_int (gcd_big_int zero_big_int zero_big_int,
+ zero_big_int);;
+test 2
+eq_big_int (gcd_big_int zero_big_int (big_int_of_int 1),
+ big_int_of_int 1);;
+test 3
+eq_big_int (gcd_big_int (big_int_of_int 1) zero_big_int,
+ big_int_of_int 1);;
+test 4
+eq_big_int (gcd_big_int (big_int_of_int 1) (big_int_of_int 2),
+ big_int_of_int 1);;
+test 5
+eq_big_int (gcd_big_int (big_int_of_int 2) (big_int_of_int 1),
+ big_int_of_int 1);;
+test 6
+eq_big_int (gcd_big_int (big_int_of_int 1) (big_int_of_int 1),
+ big_int_of_int 1);;
+test 7
+eq_big_int (gcd_big_int (big_int_of_int 9) (big_int_of_int 16),
+ big_int_of_int 1);;
+test 8
+eq_big_int (gcd_big_int (big_int_of_int 12) (big_int_of_int 16),
+ big_int_of_int 4);;
+
+for i = 9 to 28 do
+ let n1 = Random.int 1000000000
+ and n2 = Random.int 100000 in
+ test i eq
+ (int_of_big_int (gcd_big_int (big_int_of_int n1) (big_int_of_int n2)),
+ gcd_int n1 n2)
+done;;
+
+testing_function "int_of_big_int";;
+
+test 1
+eq_int (int_of_big_int (big_int_of_int 1), 1);;
+test 2
+eq (is_int_big_int (big_int_of_int 1), true);;
+test 3
+eq (is_int_big_int (succ_big_int (big_int_of_int biggest_int)),false);;
+
+testing_function "sys_string_of_big_int";;
+
+test 1
+eq_string (string_of_big_int (big_int_of_int 1), "1");;
+
+
+testing_function "big_int_of_string";;
+
+test 1
+eq_big_int (big_int_of_string "1", big_int_of_int 1);;
+test 2
+eq_big_int (big_int_of_string "-1", big_int_of_int (-1));;
+test 4
+eq_big_int (big_int_of_string "0", zero_big_int);;
+
+failwith_test 5 big_int_of_string "sdjdkfighdgf"
+ (Failure "invalid digit");;
+
+test 6
+eq_big_int (big_int_of_string "123", big_int_of_int 123);;
+test 7
+eq_big_int (big_int_of_string "3456", big_int_of_int 3456);;
+
+test 9
+eq_big_int (big_int_of_string "-3456", big_int_of_int (-3456));;
+
+
+let implode = List.fold_left (^) "";; (* Au diable l'efficacite *)
+
+let l = List.rev [
+"174679877494298468451661416292903906557638850173895426081611831060970135303";
+"044177587617233125776581034213405720474892937404345377707655788096850784519";
+"539374048533324740018513057210881137248587265169064879918339714405948322501";
+"445922724181830422326068913963858377101914542266807281471620827145038901025";
+"322784396182858865537924078131032036927586614781817695777639491934361211399";
+"888524140253852859555118862284235219972858420374290985423899099648066366558";
+"238523612660414395240146528009203942793935957539186742012316630755300111472";
+"852707974927265572257203394961525316215198438466177260614187266288417996647";
+"132974072337956513457924431633191471716899014677585762010115338540738783163";
+"739223806648361958204720897858193606022290696766988489073354139289154127309";
+"916985231051926209439373780384293513938376175026016587144157313996556653811";
+"793187841050456120649717382553450099049321059330947779485538381272648295449";
+"847188233356805715432460040567660999184007627415398722991790542115164516290";
+"619821378529926683447345857832940144982437162642295073360087284113248737998";
+"046564369129742074737760485635495880623324782103052289938185453627547195245";
+"688272436219215066430533447287305048225780425168823659431607654712261368560";
+"702129351210471250717394128044019490336608558608922841794819375031757643448";
+"32"
+] 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
+
+test 10
+eq_big_int (bi1, (add_big_int (mult_big_int bi2 (big_int_of_string "10"))
+ (big_int_of_string "2")));;
+
+testing_function "power_base_int";;
+
+test 1
+eq_big_int (big_int_of_nat (power_base_int 10 0), unit_big_int)
+;;
+test 2
+eq_big_int (big_int_of_nat (power_base_int 10 8), big_int_of_int 100000000)
+;;
+test 3
+eq_big_int (big_int_of_nat (power_base_int 2 (if sixtyfour then 64 else 32)),
+ big_int_of_nat (let nat = make_nat 2 in
+ set_digit_nat nat 1 1;
+ nat))
+;;
+
+testing_function "base_power_big_int";;
+
+test 1
+eq_big_int (base_power_big_int 10 0 (big_int_of_int 2), big_int_of_int 2);;
+test 2
+eq_big_int (base_power_big_int 10 2 (big_int_of_int 2), big_int_of_int 200);;
+test 3
+eq_big_int (base_power_big_int 10 1 (big_int_of_int 123), big_int_of_int 1230)
+;;
+
diff --git a/otherlibs/num/test/test_nats.ml b/otherlibs/num/test/test_nats.ml
new file mode 100644
index 000000000..ca4562fee
--- /dev/null
+++ b/otherlibs/num/test/test_nats.ml
@@ -0,0 +1,127 @@
+open Test;;
+open Nat;;
+
+(* Can compare nats less than 2**32 *)
+let equal_nat n1 n2 =
+ eq_nat n1 0 (num_digits_nat n1 0 1)
+ n2 0 (num_digits_nat n2 0 1);;
+
+testing_function "num_digits_nat";;
+
+test (-1) eq (false,not true);;
+test 0 eq (true,not false);;
+
+test 1
+eq_int
+(let r = make_nat 2 in
+ set_digit_nat r 1 1;
+ num_digits_nat r 0 1,1);;
+
+testing_function "length_nat";;
+
+test 1
+eq_int
+(let r = make_nat 2 in
+ set_digit_nat r 0 1;
+ length_nat r,2);;
+
+testing_function "equal_nat";;
+
+let zero_nat = make_nat 1 in
+
+test 1
+equal_nat (zero_nat,zero_nat);;
+test 2
+equal_nat (nat_of_int 1,nat_of_int 1);;
+
+test 3
+equal_nat (nat_of_string "2",nat_of_string "2");;
+test 4
+eq (equal_nat (nat_of_string "2")(nat_of_string "3"),false);;
+
+testing_function "incr_nat";;
+
+let zero = nat_of_int 0 in
+let res = incr_nat zero 0 1 1 in
+ test 1
+ equal_nat (zero, nat_of_int 1) &
+ test 2
+ eq (res,0);;
+
+let n = nat_of_int 1 in
+let res = incr_nat n 0 1 1 in
+ test 3
+ equal_nat (n, nat_of_int 2) &
+ test 4
+ eq (res,0);;
+
+
+testing_function "decr_nat";;
+
+let n = nat_of_int 1 in
+let res = decr_nat n 0 1 0 in
+ test 1
+ equal_nat (n, nat_of_int 0) &
+ test 2
+ eq (res,1);;
+
+let n = nat_of_int 2 in
+let res = decr_nat n 0 1 0 in
+ test 3
+ equal_nat (n, nat_of_int 1) &
+ test 4
+ eq (res,1);;
+
+testing_function "is_zero_nat";;
+
+let n = nat_of_int 1 in
+test 1 eq (is_zero_nat n 0 1,false) &
+test 2 eq (is_zero_nat (make_nat 1) 0 1, true) &
+test 3 eq (is_zero_nat (make_nat 2) 0 2, true) &
+(let r = make_nat 2 in
+ set_digit_nat r 1 1;
+ test 4 eq (is_zero_nat r 0 1, true))
+;;
+
+testing_function "string_of_nat";;
+
+let n = make_nat 4;;
+
+test 1 eq_string (string_of_nat n, "0");;
+
+complement_nat n 0 (if sixtyfour then 2 else 4);;
+
+test 2 eq_string (string_of_nat n, "340282366920938463463374607431768211455");;
+
+testing_function "string_of_nat & nat_of_string";;
+
+for i = 1 to 20 do
+ let s = String.make i '0' in
+ String.set s 0 '1';
+ test i eq_string (string_of_nat (nat_of_string s), s)
+done;;
+
+let s = "3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333" in
+test 21 equal_nat (
+nat_of_string s,
+(let nat = make_nat 15 in
+ set_digit_nat nat 0 3;
+ mult_digit_nat nat 0 15
+ (nat_of_string (String.sub s 0 135)) 0 14
+ (nat_of_int 10) 0;
+ nat))
+;;
+
+test 22 eq_string (string_of_nat(nat_of_string "1073741824"), "1073741824");;
+
+testing_function "gcd_nat";;
+
+for i = 1 to 20 do
+ let n1 = Random.int 1000000000
+ and n2 = Random.int 100000 in
+ let nat1 = nat_of_int n1
+ and nat2 = nat_of_int n2 in
+ gcd_nat nat1 0 1 nat2 0 1;
+ test i eq (int_of_nat nat1, Int_misc.gcd_int n1 n2)
+done
+;;
diff --git a/otherlibs/num/test/test_nums.ml b/otherlibs/num/test/test_nums.ml
new file mode 100644
index 000000000..424285808
--- /dev/null
+++ b/otherlibs/num/test/test_nums.ml
@@ -0,0 +1,220 @@
+open Test;;
+open Nat;;
+open Big_int;;
+open Ratio;;
+open Int_misc;;
+open Num;;
+open Arith_status;;
+
+testing_function "add_num";;
+
+test 1
+eq_num (add_num (Int 1) (Int 3), Int 4);;
+test 2
+eq_num (add_num (Int 1) (Big_int (big_int_of_int 3)), Int 4);;
+test 3
+eq_num (add_num (Int 1) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "7/4"));;
+test 4
+eq_num (add_num (Big_int (big_int_of_int 1)) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "7/4"));;
+test 5
+eq_num (add_num (Big_int (big_int_of_int 1)) (Big_int (big_int_of_int 3)),
+ Int 4);;
+test 6
+eq_num (add_num (Big_int (big_int_of_int 1)) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "7/4"));;
+test 7
+eq_num (add_num (Ratio (ratio_of_string "2/3")) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "17/12"));;
+test 8
+eq_num (add_num (Int least_int) (Int 1),
+ Int (- (pred biggest_int)));;
+test 9
+eq_num (add_num (Int biggest_int) (Int 1),
+ Big_int (minus_big_int (pred_big_int (big_int_of_int least_int))));;
+
+testing_function "sub_num";;
+
+test 1
+eq_num (sub_num (Int 1) (Int 3), Int (-2));;
+test 2
+eq_num (sub_num (Int 1) (Big_int (big_int_of_int 3)), Int (-2));;
+test 3
+eq_num (sub_num (Int 1) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "1/4"));;
+test 4
+eq_num (sub_num (Big_int (big_int_of_int 1)) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "1/4"));;
+test 5
+eq_num (sub_num (Big_int (big_int_of_int 1)) (Big_int (big_int_of_int 3)),
+ Int (-2));;
+test 7
+eq_num (sub_num (Big_int (big_int_of_int 1)) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "1/4"));;
+test 8
+eq_num (sub_num (Ratio (ratio_of_string "2/3")) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "-1/12"));;
+test 9
+eq_num (sub_num (Int least_int) (Int (-1)),
+ Int (- (pred biggest_int)));;
+test 10
+eq_num (sub_num (Int (-1)) (Int biggest_int), pred_num (Int least_int));;
+
+testing_function "mult_num";;
+
+test 1
+eq_num (mult_num (Int 2) (Int 3), Int 6);;
+test 2
+eq_num (mult_num (Int 127) (Int (int_of_string "257")),
+ Int (int_of_string "32639"));;
+test 3
+eq_num (mult_num (Int 257) (Int (int_of_string "260")),
+ Big_int (big_int_of_string "66820"));;
+test 4
+eq_num (mult_num (Int 2) (Big_int (big_int_of_int 3)), Int 6);;
+test 5
+eq_num (mult_num (Int 10) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "15/2"));;
+test 6
+eq_num (mult_num (Big_int (big_int_of_int 10)) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "15/2"));;
+test 7
+eq_num (mult_num (Big_int (big_int_of_int 2)) (Big_int (big_int_of_int 3)),
+ Int 6);;
+test 8
+eq_num (mult_num (Big_int (big_int_of_int 10)) (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "15/2"));;
+test 9
+eq_num (mult_num (Ratio (ratio_of_string "2/3")) (Ratio (ratio_of_string "3/4"))
+ , Ratio (ratio_of_string "1/2"));;
+
+testing_function "div_num";;
+
+test 1
+eq_num (div_num (Int 6) (Int 3), Int 2);;
+test 2
+eq_num (div_num (Int (int_of_string "32639"))
+ (Int (int_of_string "257")), Int 127);;
+test 3
+eq_num (div_num (Big_int (big_int_of_string "66820"))
+ (Int (int_of_string "257")),
+ Int 260);;
+test 4
+eq_num (div_num (Int 6) (Big_int (big_int_of_int 3)), Int 2);;
+test 5
+eq_num (div_num (Ratio (ratio_of_string "15/2"))
+ (Int 10),
+ Ratio (ratio_of_string "3/4"));;
+test 6
+eq_num (div_num (Big_int (big_int_of_int 6)) (Big_int (big_int_of_int 3)),
+ Int 2);;
+test 7
+eq_num (div_num (Ratio (ratio_of_string "15/2"))
+ (Big_int (big_int_of_int 10)),
+ Ratio (ratio_of_string "3/4"));;
+test 8
+eq_num (div_num (Ratio (ratio_of_string "15/2"))
+ (Ratio (ratio_of_string "3/4")),
+ Big_int (big_int_of_int 10));;
+test 9
+eq_num (div_num (Ratio (ratio_of_string "1/2"))
+ (Ratio (ratio_of_string "3/4")),
+ Ratio (ratio_of_string "2/3"));;
+
+testing_function "is_integer_num";;
+
+test 1
+eq (is_integer_num (Int 3),true);;
+test 2
+eq (is_integer_num (Big_int (big_int_of_string "1234567890")),true);;
+test 3
+eq (not (is_integer_num (Ratio (ratio_of_string "1/2"))),true);;
+test 4
+eq (is_integer_num (Ratio (ratio_of_string "1073774590/32770")),true);;
+
+testing_function "num_of_ratio";;
+
+test 1
+eq_num (num_of_ratio (ratio_of_string "4/2"), Int 2);;
+test 2
+eq_num (num_of_ratio (ratio_of_string "11811160075/11"),
+ Big_int (big_int_of_string "1073741825"));;
+test 3
+eq_num (num_of_ratio (ratio_of_string "123456789012/1234"),
+ Ratio (ratio_of_string "61728394506/617"));;
+
+testing_function "num_of_string";;
+
+test 1
+eq_num (num_of_string "123/3456", Ratio (ratio_of_string "123/3456"));;
+(*********
+test 2
+eq_num (num_of_string "12.3/34.56", Ratio (ratio_of_string "1230/3456"));;
+test 3
+eq_num (num_of_string "1.23/325.6", Ratio (ratio_of_string "123/32560"));;
+test 4
+eq_num (num_of_string "12.3/345.6", Ratio (ratio_of_string "123/3456"));;
+set_error_when_null_denominator false;;
+test 5
+eq_num (num_of_string "12.3/0.0", Ratio (ratio_of_string "123/0"));;
+test 6
+eq_num (num_of_string "0/0", Ratio (ratio_of_string "0/0"));;
+set_error_when_null_denominator true;;
+*********)
+test 7
+eq_num (num_of_string "1234567890",
+ Big_int (big_int_of_string "1234567890"));;
+test 8
+eq_num (num_of_string "12345", Int (int_of_string "12345"));;
+(*********
+test 9
+eq_num (num_of_string "0.23", Ratio (ratio_of_string "23/100"));;
+test 10
+eq_num (num_of_string "0.23", Ratio (ratio_of_string "0.23/1"));;
+********)
+
+failwith_test 11
+num_of_string ("frlshjkurty") (Failure "num_of_string");;
+
+(*******
+
+testing_function "immediate numbers";;
+
+standard arith false;;
+
+let x = (1/2) in
+test 0 eq_string (string_of_num x, "1/2");;
+
+let y = 12345678901 in
+test 1 eq_string (string_of_num y, "12345678901");;
+testing_function "immediate numbers";;
+
+let x = (1/2) in
+test 0 eq_string (string_of_num x, "1/2");;
+
+let y = 12345678901 in
+test 1 eq_string (string_of_num y, "12345678901");;
+
+testing_function "pattern_matching on nums";;
+
+let f1 = function 0 -> true | _ -> false;;
+
+test 1 eq (f1 0, true);;
+
+test 2 eq (f1 1, false);;
+
+test 3 eq (f1 (0/1), true);;
+
+test 4 eq (f1 (let n = num_of_string "2000000000000000000000000" in n-n) ,
+ true);;
+
+test 5 eq (f1 (let n = num_of_string "2000000000000000000000000" in n/n-1) ,
+ true);;
+
+test 6 eq (f1 (let n = num_of_string "2000000000000000000000000" in n+1) ,
+ false);;
+
+test 7 eq (f1 (1/2), false);;
+
+**************)
diff --git a/otherlibs/num/test/test_ratios.ml b/otherlibs/num/test/test_ratios.ml
new file mode 100644
index 000000000..692713c67
--- /dev/null
+++ b/otherlibs/num/test/test_ratios.ml
@@ -0,0 +1,928 @@
+open Test;;
+open Nat;;
+open Big_int;;
+open Ratio;;
+open Int_misc;;
+open Arith_status;;
+
+set_error_when_null_denominator false;;
+
+let infinite_failure = "infinite or undefined rational number";;
+
+testing_function "create_ratio";;
+
+let r = create_ratio (big_int_of_int 1) (big_int_of_int (-2)) in
+test 1 eq_big_int (numerator_ratio r, big_int_of_int (-1)) &
+test 2 eq_big_int (denominator_ratio r, big_int_of_int 2);;
+
+let r = create_ratio (big_int_of_int 2) (big_int_of_int 3) in
+test 3 eq_big_int (numerator_ratio r, big_int_of_int 2) &
+test 4 eq_big_int (denominator_ratio r, big_int_of_int 3);;
+
+set_normalize_ratio true;;
+
+let r = create_ratio (big_int_of_int 12) (big_int_of_int (-16)) in
+test 5 eq_big_int (numerator_ratio r, big_int_of_int (-3)) &
+test 6 eq_big_int (denominator_ratio r, big_int_of_int 4);;
+
+set_normalize_ratio false;;
+
+let r = create_ratio (big_int_of_int 0) (big_int_of_int 0) in
+test 7 eq_big_int (numerator_ratio r, big_int_of_int 0) &
+test 8 eq_big_int (denominator_ratio r, big_int_of_int 0);;
+
+testing_function "create_normalized_ratio";;
+
+let r = create_normalized_ratio (big_int_of_int 1) (big_int_of_int (-2)) in
+test 1 eq_big_int (numerator_ratio r, big_int_of_int (-1)) &
+test 2 eq_big_int (denominator_ratio r, big_int_of_int 2);;
+
+let r = create_normalized_ratio (big_int_of_int 2) (big_int_of_int 3) in
+test 3 eq_big_int (numerator_ratio r, big_int_of_int 2) &
+test 4 eq_big_int (denominator_ratio r, big_int_of_int 3);;
+
+set_normalize_ratio true;;
+
+let r = create_normalized_ratio (big_int_of_int 12) (big_int_of_int (-16)) in
+test 5 eq_big_int (numerator_ratio r, big_int_of_int (-12)) &
+test 6 eq_big_int (denominator_ratio r, big_int_of_int 16);;
+
+set_normalize_ratio false;;
+
+let r = create_normalized_ratio (big_int_of_int 1) (big_int_of_int 0) in
+test 7 eq_big_int (numerator_ratio r, big_int_of_int 1) &
+test 8 eq_big_int (denominator_ratio r, big_int_of_int 0);;
+
+let r = create_normalized_ratio (big_int_of_int 0) (big_int_of_int 0) in
+test 9 eq_big_int (numerator_ratio r, big_int_of_int 0) &
+test 10 eq_big_int (denominator_ratio r, big_int_of_int 0);;
+
+testing_function "null_denominator";;
+
+test 1
+ eq (null_denominator (create_ratio (big_int_of_int 1) (big_int_of_int (-2))),
+ false);;
+test 2 eq
+ (null_denominator (create_ratio (big_int_of_int 1) zero_big_int),true);;
+
+(*****
+testing_function "verify_null_denominator";;
+
+test 1
+ eq (verify_null_denominator (ratio_of_string "0/1"), false);;
+test 2
+ eq (verify_null_denominator (ratio_of_string "0/0"), true);;
+*****)
+
+testing_function "sign_ratio";;
+
+test 1
+eq_int (sign_ratio (create_ratio (big_int_of_int (-2)) (big_int_of_int (-3))),
+ 1);;
+test 2
+eq_int (sign_ratio (create_ratio (big_int_of_int 2) (big_int_of_int (-3))),
+ (-1));;
+test 3
+eq_int (sign_ratio (create_ratio zero_big_int (big_int_of_int (-3))), 0);;
+
+testing_function "normalize_ratio";;
+
+let r = create_ratio (big_int_of_int 12) (big_int_of_int (-16)) in
+normalize_ratio r;
+test 1 eq_big_int (numerator_ratio r, big_int_of_int (-3)) &
+test 2 eq_big_int (denominator_ratio r, big_int_of_int 4);;
+
+let r = create_ratio (big_int_of_int (-1)) zero_big_int in
+normalize_ratio r;
+test 3 eq_big_int (numerator_ratio r, big_int_of_int (-1)) &
+test 4 eq_big_int (denominator_ratio r, zero_big_int);;
+
+testing_function "report_sign_ratio";;
+
+test 1
+eq_big_int (report_sign_ratio
+ (create_ratio (big_int_of_int 2) (big_int_of_int (-3)))
+ (big_int_of_int 1),
+ big_int_of_int (-1));;
+test 2
+eq_big_int (report_sign_ratio
+ (create_ratio (big_int_of_int 2) (big_int_of_int 3))
+ (big_int_of_int 1),
+ big_int_of_int 1);;
+
+testing_function "is_integer_ratio";;
+
+test 1 eq
+ (is_integer_ratio (create_ratio (big_int_of_int 2) (big_int_of_int (-1))),
+ true);;
+test 2 eq
+ (is_integer_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3)),
+ false);;
+
+testing_function "add_ratio";;
+
+let r = add_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 2))
+ (create_ratio (big_int_of_int 2) (big_int_of_int 3)) in
+test 1 eq_big_int (numerator_ratio r, big_int_of_int 7) &
+test 2 eq_big_int (denominator_ratio r, big_int_of_int 6);;
+
+let r = add_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 1) (big_int_of_int (-2))) in
+test 3 eq_big_int (numerator_ratio r, big_int_of_int 1) &
+test 4 eq_big_int (denominator_ratio r, big_int_of_int 6);;
+
+let r = add_ratio (create_ratio (big_int_of_int 2) zero_big_int)
+ (create_ratio (big_int_of_int 1) (big_int_of_int (-2))) in
+test 5 eq_big_int (numerator_ratio r, big_int_of_int 4) &
+test 6 eq_big_int (denominator_ratio r, zero_big_int);;
+
+let r = add_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 1) zero_big_int) in
+test 7 eq_big_int (numerator_ratio r, big_int_of_int 3) &
+test 8 eq_big_int (denominator_ratio r, zero_big_int);;
+
+let r = add_ratio (create_ratio (big_int_of_int 2) zero_big_int)
+ (create_ratio (big_int_of_int 1) zero_big_int) in
+test 9 eq_big_int (numerator_ratio r, zero_big_int) &
+test 10 eq_big_int (denominator_ratio r, zero_big_int);;
+
+let r = add_ratio (create_ratio (big_int_of_string "12724951")
+ (big_int_of_string "26542080"))
+ (create_ratio (big_int_of_string "-1")
+ (big_int_of_string "81749606400")) in
+test 11 eq_big_int (numerator_ratio r,
+ big_int_of_string "1040259735682744320") &
+test 12 eq_big_int (denominator_ratio r,
+ big_int_of_string "2169804593037312000");;
+
+let r1,r2 =
+ (create_ratio (big_int_of_string "12724951")
+ (big_int_of_string "26542080"),
+ create_ratio (big_int_of_string "-1")
+ (big_int_of_string "81749606400")) in
+
+let bi1 = mult_big_int (numerator_ratio r1) (denominator_ratio r2)
+and bi2 = mult_big_int (numerator_ratio r2) (denominator_ratio r1)
+in
+test 1
+eq_big_int (bi1,
+ big_int_of_string "1040259735709286400")
+&
+test 2
+eq_big_int (bi2,
+ big_int_of_string "-26542080")
+& test 3
+eq_big_int (mult_big_int (denominator_ratio r1) (denominator_ratio r2),
+ big_int_of_string "2169804593037312000")
+& test 4
+eq_big_int (add_big_int bi1 bi2,
+ big_int_of_string "1040259735682744320")
+;;
+
+testing_function "sub_ratio";;
+
+let r = sub_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 1) (big_int_of_int 2)) in
+test 1 eq_big_int (numerator_ratio r, big_int_of_int 1) &
+test 2 eq_big_int (denominator_ratio r, big_int_of_int 6);;
+
+let r = sub_ratio (create_ratio (big_int_of_int 2) zero_big_int)
+ (create_ratio (big_int_of_int 1) (big_int_of_int (-2))) in
+test 3 eq_big_int (numerator_ratio r, big_int_of_int 4) &
+test 4 eq_big_int (denominator_ratio r, zero_big_int);;
+
+let r = sub_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 1) zero_big_int) in
+test 5 eq_big_int (numerator_ratio r, big_int_of_int (-3)) &
+test 6 eq_big_int (denominator_ratio r, zero_big_int);;
+
+let r = sub_ratio (create_ratio (big_int_of_int 2) zero_big_int)
+ (create_ratio (big_int_of_int 1) zero_big_int) in
+test 7 eq_big_int (numerator_ratio r, zero_big_int) &
+test 8 eq_big_int (denominator_ratio r, zero_big_int);;
+
+testing_function "mult_ratio";;
+
+let r = mult_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 7) (big_int_of_int 5)) in
+test 1 eq_big_int (numerator_ratio r, big_int_of_int 14) &
+test 2 eq_big_int (denominator_ratio r, big_int_of_int 15);;
+
+let r = mult_ratio (create_ratio (big_int_of_int 2) zero_big_int)
+ (create_ratio (big_int_of_int 1) (big_int_of_int (-2))) in
+test 3 eq_big_int (numerator_ratio r, big_int_of_int (-2)) &
+test 4 eq_big_int (denominator_ratio r, zero_big_int);;
+
+let r = mult_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 1) zero_big_int) in
+test 5 eq_big_int (numerator_ratio r, big_int_of_int 2) &
+test 6 eq_big_int (denominator_ratio r, zero_big_int);;
+
+let r = mult_ratio (create_ratio (big_int_of_int 2) zero_big_int)
+ (create_ratio (big_int_of_int 1) zero_big_int) in
+test 7 eq_big_int (numerator_ratio r, big_int_of_int 2) &
+test 8 eq_big_int (denominator_ratio r, zero_big_int);;
+
+testing_function "div_ratio";;
+
+let r = div_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 5) (big_int_of_int 7)) in
+test 1 eq_big_int (numerator_ratio r, big_int_of_int 14) &
+test 2 eq_big_int (denominator_ratio r, big_int_of_int 15);;
+
+let r = div_ratio (create_ratio (big_int_of_int 2) zero_big_int)
+ (create_ratio (big_int_of_int 1) (big_int_of_int (-2))) in
+test 3 eq_big_int (numerator_ratio r, big_int_of_int (-4)) &
+test 4 eq_big_int (denominator_ratio r, zero_big_int);;
+
+let r = div_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 1) zero_big_int) in
+test 5 eq_big_int (numerator_ratio r, zero_big_int) &
+test 6 eq_big_int (denominator_ratio r, big_int_of_int 3);;
+
+let r = div_ratio (create_ratio (big_int_of_int 2) zero_big_int)
+ (create_ratio (big_int_of_int 1) zero_big_int) in
+test 7 eq_big_int (numerator_ratio r, zero_big_int) &
+test 8 eq_big_int (denominator_ratio r, zero_big_int);;
+
+testing_function "integer_ratio";;
+
+test 1
+eq_big_int (integer_ratio
+ (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
+ big_int_of_int 1);;
+test 2
+eq_big_int (integer_ratio
+ (create_ratio (big_int_of_int 5) (big_int_of_int (-3))),
+ big_int_of_int (-1));;
+test 3
+eq_big_int (integer_ratio
+ (create_ratio (big_int_of_int 3) (big_int_of_int 2)),
+ big_int_of_int 1);;
+test 4
+eq_big_int (integer_ratio
+ (create_ratio (big_int_of_int 3) (big_int_of_int (-2))),
+ big_int_of_int (-1));;
+
+failwith_test 5
+integer_ratio (create_ratio (big_int_of_int 3) zero_big_int)
+(Failure("integer_ratio "^infinite_failure));;
+
+testing_function "floor_ratio";;
+
+test 1
+eq_big_int (floor_ratio
+ (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
+ big_int_of_int 1);;
+test 2
+eq_big_int (floor_ratio
+ (create_ratio (big_int_of_int 5) (big_int_of_int (-3))),
+ big_int_of_int (-2));;
+test 3
+eq_big_int (floor_ratio
+ (create_ratio (big_int_of_int 3) (big_int_of_int 2)),
+ big_int_of_int 1);;
+test 4
+eq_big_int (floor_ratio
+ (create_ratio (big_int_of_int 3) (big_int_of_int (-2))),
+ big_int_of_int (-2));;
+
+failwith_test 5 floor_ratio (create_ratio (big_int_of_int 3) zero_big_int)
+Division_by_zero;;
+
+
+testing_function "round_ratio";;
+
+test 1
+eq_big_int (round_ratio
+ (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
+ big_int_of_int 2);;
+test 2
+eq_big_int (round_ratio
+ (create_ratio (big_int_of_int 5) (big_int_of_int (-3))),
+ big_int_of_int (-2));;
+test 3
+eq_big_int (round_ratio
+ (create_ratio (big_int_of_int 3) (big_int_of_int 2)),
+ big_int_of_int 2);;
+test 4
+eq_big_int (round_ratio
+ (create_ratio (big_int_of_int 3) (big_int_of_int (-2))),
+ big_int_of_int (-2));;
+
+failwith_test 5
+round_ratio (create_ratio (big_int_of_int 3) zero_big_int)
+Division_by_zero;;
+
+
+testing_function "ceiling_ratio";;
+
+test 1
+eq_big_int (ceiling_ratio
+ (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
+ big_int_of_int 2);;
+test 2
+eq_big_int (ceiling_ratio
+ (create_ratio (big_int_of_int 5) (big_int_of_int (-3))),
+ big_int_of_int (-1));;
+test 3
+eq_big_int (ceiling_ratio
+ (create_ratio (big_int_of_int 3) (big_int_of_int 2)),
+ big_int_of_int 2);;
+test 4
+eq_big_int (ceiling_ratio
+ (create_ratio (big_int_of_int 3) (big_int_of_int (-2))),
+ big_int_of_int (-1));;
+test 5
+eq_big_int (ceiling_ratio
+ (create_ratio (big_int_of_int 4) (big_int_of_int 2)),
+ big_int_of_int 2);;
+failwith_test 6
+ceiling_ratio (create_ratio (big_int_of_int 3) zero_big_int)
+Division_by_zero;;
+
+testing_function "eq_ratio";;
+
+test 1
+eq_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3),
+ create_ratio (big_int_of_int (-20)) (big_int_of_int (-12)));;
+test 2
+eq_ratio (create_ratio (big_int_of_int 1) zero_big_int,
+ create_ratio (big_int_of_int 2) zero_big_int);;
+
+let neq_ratio x y = not (eq_ratio x y);;
+
+test 3
+neq_ratio (create_ratio (big_int_of_int 1) zero_big_int,
+ create_ratio (big_int_of_int (-1)) zero_big_int);;
+test 4
+neq_ratio (create_ratio (big_int_of_int 1) zero_big_int,
+ create_ratio zero_big_int zero_big_int);;
+test 5
+eq_ratio (create_ratio zero_big_int zero_big_int,
+ create_ratio zero_big_int zero_big_int);;
+
+testing_function "compare_ratio";;
+
+test 1
+eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
+ 0);;
+test 2
+eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 1) (big_int_of_int 0)),
+ 0);;
+test 3
+eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
+ (create_ratio (big_int_of_int (-1)) (big_int_of_int 0)),
+ 0);;
+test 4
+eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
+ 0);;
+test 5
+eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
+ 0);;
+test 6
+eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
+ 0);;
+test 7
+eq_int (compare_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
+ 0);;
+test 8
+eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
+ (create_ratio (big_int_of_int (-5)) (big_int_of_int 3)),
+ 0);;
+test 9
+eq_int (compare_ratio (create_ratio (big_int_of_int (-5)) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
+ 0);;
+test 10
+eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 1)),
+ 0);;
+test 11
+eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 1))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
+ 0);;
+test 12
+eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 1) (big_int_of_int 0)),
+ 0);;
+test 13
+eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 2) (big_int_of_int 0)),
+ 0);;
+test 14
+eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
+ (create_ratio (big_int_of_int (-1)) (big_int_of_int 0)),
+ 1);;
+test 15
+eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 1) (big_int_of_int 0)),
+ (-1));;
+test 16
+eq_int (compare_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 1) (big_int_of_int 0)),
+ (-1));;
+test 17
+eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
+ 1);;
+test 18
+eq_int (compare_ratio (create_ratio (big_int_of_int (-5)) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 1) (big_int_of_int 0)),
+ (-1));;
+test 19
+eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
+ (create_ratio (big_int_of_int (-5)) (big_int_of_int 3)),
+ 1);;
+test 20
+eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 3)),
+ 1);;
+test 21
+eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
+ (create_ratio (big_int_of_int (-1)) (big_int_of_int 0)),
+ 0);;
+test 22
+eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
+ (create_ratio (big_int_of_int (-2)) (big_int_of_int 0)),
+ 0);;
+test 23
+eq_int (compare_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3))
+ (create_ratio (big_int_of_int (-1)) (big_int_of_int 0)),
+ 1);;
+test 24
+eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
+ (-1));;
+test 25
+eq_int (compare_ratio (create_ratio (big_int_of_int (-5)) (big_int_of_int 3))
+ (create_ratio (big_int_of_int (-1)) (big_int_of_int 0)),
+ 1);;
+test 26
+eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
+ (create_ratio (big_int_of_int (-5)) (big_int_of_int 3)),
+ (-1));;
+test 27
+eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 3)),
+ (-1));;
+test 28
+eq_int (compare_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3))
+ (create_ratio (big_int_of_int 3) (big_int_of_int 2)),
+ 1);;
+test 29
+eq_int (compare_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 2))
+ (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
+ (-1));;
+test 30
+eq_int (compare_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3))
+ (create_ratio (big_int_of_int (-3)) (big_int_of_int 2)),
+ 1);;
+test 31
+eq_int (compare_ratio (create_ratio (big_int_of_int (-3)) (big_int_of_int 2))
+ (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
+ (-1));;
+test 32
+eq_int (compare_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 2))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 3)),
+ 1);;
+test 33
+eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 2))
+ (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
+ (-1));;
+test 34
+eq_int (compare_ratio (create_ratio (big_int_of_int (-3)) (big_int_of_int 2))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 3)),
+ (-1));;
+test 35
+eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 2))
+ (create_ratio (big_int_of_int (-5)) (big_int_of_int 3)),
+ 1);;
+test 36
+eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 2))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 3)),
+ 0);;
+
+testing_function "eq_big_int_ratio";;
+
+test 1
+eq_big_int_ratio (big_int_of_int 3,
+ (create_ratio (big_int_of_int 3) (big_int_of_int 1)));;
+test 2
+eq
+(not (eq_big_int_ratio (big_int_of_int 1)
+ (create_ratio (big_int_of_int 3) (big_int_of_int 1))),
+true);;
+
+test 3
+eq
+(not (eq_big_int_ratio (big_int_of_int 1)
+ (create_ratio (big_int_of_int 3) (big_int_of_int 2))),
+ true);;
+
+test 4
+eq
+(not (eq_big_int_ratio (big_int_of_int 1)
+ (create_ratio (big_int_of_int 3) (big_int_of_int 0))),
+ true);;
+
+test 5
+eq
+(not (eq_big_int_ratio (big_int_of_int 1)
+ (create_ratio (big_int_of_int (-3)) (big_int_of_int 2))),
+ true);;
+
+testing_function "compare_big_int_ratio";;
+
+test 1
+eq_int (compare_big_int_ratio
+ (big_int_of_int 1)
+ (create_ratio (big_int_of_int 3) (big_int_of_int 0)), (-1));;
+test 2
+eq_int (compare_big_int_ratio
+ (big_int_of_int 1)
+ (create_ratio (big_int_of_int 0) (big_int_of_int 0)), 0);;
+test 3
+eq_int (compare_big_int_ratio
+ (big_int_of_int 1)
+ (create_ratio (big_int_of_int (-3)) (big_int_of_int 0)), 1);;
+test 4
+eq_int (compare_big_int_ratio
+ (big_int_of_int (-1))
+ (create_ratio (big_int_of_int 3) (big_int_of_int 0)), (-1));;
+test 5
+eq_int (compare_big_int_ratio
+ (big_int_of_int (-1))
+ (create_ratio (big_int_of_int 0) (big_int_of_int 0)), 0);;
+test 6
+eq_int (compare_big_int_ratio
+ (big_int_of_int (-1))
+ (create_ratio (big_int_of_int (-3)) (big_int_of_int 0)), 1);;
+test 7
+eq_int (compare_big_int_ratio
+ (big_int_of_int 1)
+ (create_ratio (big_int_of_int 1) (big_int_of_int 1)), 0);;
+test 8
+eq_int (compare_big_int_ratio
+ (big_int_of_int 1)
+ (create_ratio (big_int_of_int 3) (big_int_of_int 2)), (-1));;
+test 9
+eq_int (compare_big_int_ratio
+ (big_int_of_int 1)
+ (create_ratio (big_int_of_int 2) (big_int_of_int 3)), 1);;
+
+
+
+testing_function "int_of_ratio";;
+
+test 1
+eq_int (int_of_ratio (create_ratio (big_int_of_int 4) (big_int_of_int 2)),
+ 2);;
+
+test 2
+eq_int (int_of_ratio
+ (create_ratio (big_int_of_int biggest_int) (big_int_of_int 1)),
+ biggest_int);;
+
+failwith_test 3
+int_of_ratio (create_ratio (big_int_of_int 4) (big_int_of_int 0))
+(Failure "integer argument required");;
+
+failwith_test 4
+int_of_ratio (create_ratio (succ_big_int (big_int_of_int biggest_int))
+ (big_int_of_int 1))
+(Failure "integer argument required");;
+
+failwith_test 5
+int_of_ratio (create_ratio (big_int_of_int 4) (big_int_of_int 3))
+(Failure "integer argument required");;
+
+testing_function "ratio_of_int";;
+
+test 1
+eq_ratio (ratio_of_int 3,
+ create_ratio (big_int_of_int 3) (big_int_of_int 1));;
+
+test 2
+eq_ratio (ratio_of_nat (nat_of_int 2),
+ create_ratio (big_int_of_int 2) (big_int_of_int 1));;
+
+testing_function "nat_of_ratio";;
+
+let nat1 = nat_of_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 1))
+and nat2 = nat_of_int 3 in
+test 1
+eq (eq_nat nat1 0 (length_nat nat1) nat2 0 (length_nat nat2), true)
+;;
+
+failwith_test 2
+nat_of_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 0))
+(Failure "nat_of_ratio");;
+
+failwith_test 3
+nat_of_ratio (create_ratio (big_int_of_int (-3)) (big_int_of_int 1))
+(Failure "nat_of_ratio");;
+
+failwith_test 4
+nat_of_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 2))
+(Failure "nat_of_ratio");;
+
+testing_function "ratio_of_big_int";;
+
+test 1
+eq_ratio (ratio_of_big_int (big_int_of_int 3),
+ create_ratio (big_int_of_int 3) (big_int_of_int 1));;
+
+testing_function "big_int_of_ratio";;
+
+test 1
+eq_big_int (big_int_of_ratio
+ (create_ratio (big_int_of_int 3) (big_int_of_int 1)),
+ big_int_of_int 3);;
+test 2
+eq_big_int (big_int_of_ratio
+ (create_ratio (big_int_of_int (-3)) (big_int_of_int 1)),
+ big_int_of_int (-3));;
+
+failwith_test 3
+big_int_of_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 0))
+(Failure "big_int_of_ratio");;
+
+testing_function "string_of_ratio";;
+
+test 1
+eq_string (string_of_ratio
+ (create_ratio (big_int_of_int 43) (big_int_of_int 35)),
+ "43/35");;
+test 2
+eq_string (string_of_ratio
+ (create_ratio (big_int_of_int 42) (big_int_of_int 0)),
+ "1/0");;
+
+set_normalize_ratio_when_printing false;;
+
+test 3
+eq_string (string_of_ratio
+ (create_ratio (big_int_of_int 42) (big_int_of_int 35)),
+ "42/35");;
+
+set_normalize_ratio_when_printing true;;
+
+test 4
+eq_string (string_of_ratio
+ (create_ratio (big_int_of_int 42) (big_int_of_int 35)),
+ "6/5");;
+
+testing_function "ratio_of_string";;
+
+test 1
+eq_ratio (ratio_of_string ("123/3456"),
+ create_ratio (big_int_of_int 123) (big_int_of_int 3456));;
+
+(***********
+test 2
+eq_ratio (ratio_of_string ("12.3/34.56"),
+ create_ratio (big_int_of_int 1230) (big_int_of_int 3456));;
+test 3
+eq_ratio (ratio_of_string ("1.23/325.6"),
+ create_ratio (big_int_of_int 123) (big_int_of_int 32560));;
+test 4
+eq_ratio (ratio_of_string ("12.3/345.6"),
+ create_ratio (big_int_of_int 123) (big_int_of_int 3456));;
+test 5
+eq_ratio (ratio_of_string ("12.3/0.0"),
+ create_ratio (big_int_of_int 123) (big_int_of_int 0));;
+***********)
+test 6
+eq_ratio (ratio_of_string ("0/0"),
+ create_ratio (big_int_of_int 0) (big_int_of_int 0));;
+
+test 7
+eq_ratio (ratio_of_string "1234567890",
+ create_ratio (big_int_of_string "1234567890") unit_big_int);;
+failwith_test 8
+ratio_of_string "frlshjkurty" (Failure "invalid digit");;
+
+(***********
+testing_function "msd_ratio";;
+
+test 1
+eq_int (msd_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 1)),
+ 0);;
+test 2
+eq_int (msd_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 12)),
+ (-2));;
+test 3
+eq_int (msd_ratio (create_ratio (big_int_of_int 12) (big_int_of_int 1)),
+ 1);;
+test 4
+eq_int (msd_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 2)),
+ (-1));;
+test 5
+eq_int (msd_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 1)),
+ 0);;
+test 6
+eq_int (msd_ratio (create_ratio (big_int_of_int 25) (big_int_of_int 21)),
+ 0);;
+test 7
+eq_int (msd_ratio (create_ratio (big_int_of_int 35) (big_int_of_int 21)),
+ 0);;
+test 8
+eq_int (msd_ratio (create_ratio (big_int_of_int 215) (big_int_of_int 31)),
+ 0);;
+test 9
+eq_int (msd_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 30)),
+ (-2));;
+test 10
+eq_int (msd_ratio (create_ratio (big_int_of_int 2345)
+ (big_int_of_int 23456)),
+ (-2));;
+test 11
+eq_int (msd_ratio (create_ratio (big_int_of_int 2345)
+ (big_int_of_int 2346)),
+ (-1));;
+test 12
+eq_int (msd_ratio (create_ratio (big_int_of_int 2345)
+ (big_int_of_int 2344)),
+ 0);;
+test 13
+eq_int (msd_ratio (create_ratio (big_int_of_int 23456)
+ (big_int_of_int 2345)),
+ 1);;
+test 14
+eq_int (msd_ratio (create_ratio (big_int_of_int 23467)
+ (big_int_of_int 2345)),
+ 1);;
+failwith_test 15
+msd_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
+("msd_ratio "^infinite_failure);;
+failwith_test 16
+msd_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
+("msd_ratio "^infinite_failure);;
+failwith_test 17
+msd_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
+("msd_ratio "^infinite_failure);;
+*************************)
+
+testing_function "round_futur_last_digit";;
+
+let s = "+123456" in
+test 1 eq (round_futur_last_digit s 1 (pred (String.length s)),
+ false) &
+test 2 eq_string (s, "+123466");;
+
+let s = "123456" in
+test 3 eq (round_futur_last_digit s 0 (String.length s), false) &
+test 4 eq_string (s, "123466");;
+
+let s = "-123456" in
+test 5 eq (round_futur_last_digit s 1 (pred (String.length s)),
+ false) &
+test 6 eq_string (s, "-123466");;
+
+let s = "+123496" in
+test 7 eq (round_futur_last_digit s 1 (pred (String.length s)),
+ false) &
+test 8 eq_string (s, "+123506");;
+
+let s = "123496" in
+test 9 eq (round_futur_last_digit s 0 (String.length s), false) &
+test 10 eq_string (s, "123506");;
+
+let s = "-123496" in
+test 11 eq (round_futur_last_digit s 1 (pred (String.length s)),
+ false) &
+test 12 eq_string (s, "-123506");;
+
+let s = "+996" in
+test 13 eq (round_futur_last_digit s 1 (pred (String.length s)),
+ true) &
+test 14 eq_string (s, "+006");;
+
+let s = "996" in
+test 15 eq (round_futur_last_digit s 0 (String.length s), true) &
+test 16 eq_string (s, "006");;
+
+let s = "-996" in
+test 17 eq (round_futur_last_digit s 1 (pred (String.length s)),
+ true) &
+test 18 eq_string (s, "-006");;
+
+let s = "+6666666" in
+test 19 eq (round_futur_last_digit s 1 (pred (String.length s)),
+ false) &
+test 20 eq_string (s, "+6666676") ;;
+
+let s = "6666666" in
+test 21 eq (round_futur_last_digit s 0 (String.length s), false) &
+test 22 eq_string (s, "6666676") ;;
+
+let s = "-6666666" in
+test 23 eq (round_futur_last_digit s 1 (pred (String.length s)),
+ false) &
+test 24 eq_string (s, "-6666676") ;;
+
+testing_function "approx_ratio_fix";;
+
+let s = approx_ratio_fix 5
+ (create_ratio (big_int_of_int 2)
+ (big_int_of_int 3)) in
+test 1
+eq_string (s, "+0.66667");;
+
+test 2
+eq_string (approx_ratio_fix 5
+ (create_ratio (big_int_of_int 20)
+ (big_int_of_int 3)),
+ "+6.66667");;
+test 3
+eq_string (approx_ratio_fix 5
+ (create_ratio (big_int_of_int 2)
+ (big_int_of_int 30)),
+ "+0.06667");;
+test 4
+eq_string (approx_ratio_fix 5
+ (create_ratio (big_int_of_string "999996")
+ (big_int_of_string "1000000")),
+ "+1.00000");;
+test 5
+eq_string (approx_ratio_fix 5
+ (create_ratio (big_int_of_string "299996")
+ (big_int_of_string "100000")),
+ "+2.99996");;
+test 6
+eq_string (approx_ratio_fix 5
+ (create_ratio (big_int_of_string "2999996")
+ (big_int_of_string "1000000")),
+ "+3.00000");;
+test 7
+eq_string (approx_ratio_fix 4
+ (create_ratio (big_int_of_string "299996")
+ (big_int_of_string "100000")),
+ "+3.0000");;
+test 8
+eq_string (approx_ratio_fix 5
+ (create_ratio (big_int_of_int 29996)
+ (big_int_of_string "100000")),
+ "+0.29996");;
+test 9
+eq_string (approx_ratio_fix 5
+ (create_ratio (big_int_of_int 0)
+ (big_int_of_int 1)),
+ "+0");;
+failwith_test 10
+(approx_ratio_fix 5) (create_ratio (big_int_of_int 1) (big_int_of_int 0))
+(Failure "approx_ratio_fix infinite or undefined rational number");;
+failwith_test 11
+(approx_ratio_fix 5) (create_ratio (big_int_of_int 0) (big_int_of_int 0))
+(Failure "approx_ratio_fix infinite or undefined rational number");;
+
+testing_function "approx_ratio_exp";;
+
+test 1
+eq_string (approx_ratio_exp 5
+ (create_ratio (big_int_of_int 2)
+ (big_int_of_int 3)),
+ "+0.66667e0");;
+test 2
+eq_string (approx_ratio_exp 5
+ (create_ratio (big_int_of_int 20)
+ (big_int_of_int 3)),
+ "+0.66667e1");;
+test 3
+eq_string (approx_ratio_exp 5
+ (create_ratio (big_int_of_int 2)
+ (big_int_of_int 30)),
+ "+0.66667e-1");;
+test 4
+eq_string (approx_ratio_exp 5
+ (create_ratio (big_int_of_string "999996")
+ (big_int_of_string "1000000")),
+ "+1.00000e0");;
+test 5
+eq_string (approx_ratio_exp 5
+ (create_ratio (big_int_of_string "299996")
+ (big_int_of_string "100000")),
+ "+0.30000e1");;
+test 6
+eq_string (approx_ratio_exp 5
+ (create_ratio (big_int_of_int 29996)
+ (big_int_of_string "100000")),
+ "+0.29996e0");;
+test 7
+eq_string (approx_ratio_exp 5
+ (create_ratio (big_int_of_int 0)
+ (big_int_of_int 1)),
+ "+0.00000e0");;
+failwith_test 8
+(approx_ratio_exp 5) (create_ratio (big_int_of_int 1) (big_int_of_int 0))
+(Failure "approx_ratio_exp infinite or undefined rational number");;
+failwith_test 9
+(approx_ratio_exp 5) (create_ratio (big_int_of_int 0) (big_int_of_int 0))
+(Failure "approx_ratio_exp infinite or undefined rational number");;