[Pkg-ocaml-maint-commits] [ocaml-zarith] 02/07: New upstream version 1.5
Stéphane Glondu
glondu at moszumanska.debian.org
Fri Sep 22 13:25:46 UTC 2017
This is an automated email from the git hooks/post-receive script.
glondu pushed a commit to branch master
in repository ocaml-zarith.
commit f0827a1c06b2667dbdd8efd207be9e8261b0f13f
Author: Stephane Glondu <steph at glondu.net>
Date: Fri Sep 22 15:08:34 2017 +0200
New upstream version 1.5
---
.gitignore | 10 +++++
Changes | 13 +++++-
META | 2 +-
Makefile | 25 -----------
README | 130 -------------------------------------------------------
README.md | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++
caml_z.c | 6 +--
project.mak | 7 +--
q.ml | 36 ++++++++++++++-
q.mli | 5 +++
tests/bi.ml | 14 +++---
tests/tofloat.ml | 80 ++++++++++++++++++++++++++--------
z.mlip | 52 +++++++++++++---------
z.mlp | 30 ++++++-------
z_pp.pl | 8 ++++
15 files changed, 320 insertions(+), 224 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..afef917
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+*.a
+*.cm?
+*.cmxa
+*.cmxs
+*.exe
+*.o
+Makefile
+z.ml
+z.mli
+z_features.h
diff --git a/Changes b/Changes
index 7f16b4d..2ddfaa2 100644
--- a/Changes
+++ b/Changes
@@ -1,3 +1,14 @@
+Release 1.5 (2017-05-26):
+- Install all .cmx files, improving performance of clients and
+ avoiding a warning from OCaml 4.03 and up.
+- Z.of_float: fix a bug in the fast path [Richard Jones]
+ (See https://bugzilla.redhat.com/show_bug.cgi?id=1392247)
+- Improve compatibility with OCaml 4.03 and up
+ [Bernhard Schommer]
+- Overflow issue in Z.pow and Z.root with very large exponents (GPR#5)
+ [Andre Maroneze]
+- Added function Q.to_float.
+
Release 1.4.1 (2015-11-09):
- Fixed ml_z_of_substring_base and Z.of_substring [Thomas Braibant]
- Integrated Opam fix for Perl scripts [Thomas Braibant]
@@ -12,7 +23,7 @@ Release 1.4 (2015-11-02):
- Added Z.trailing_zeros.
- Added Z.testbit, Z.is_even, Z.is_odd.
- Added Z.numbits, Z.log2 and Z.log2up.
-- PR$1467: Z.hash is declared as "noalloc" [François Bobot]
+- PR#1467: Z.hash is declared as "noalloc" [François Bobot]
- PR#1451: configure fix [Spiros Eliopoulos]
- PR#1436: disable "(void)" trick for unused variables on Windows [Bernhard Schommer]
- PR#1434: removed dependencies on printf & co when Z_PERFORM_CHECK is 0 [Hannes Mehnert]
diff --git a/META b/META
index 854de4b..d2aeb02 100644
--- a/META
+++ b/META
@@ -1,5 +1,5 @@
description = "Arbitrary precision integers"
requires = ""
-version = "1.4.1"
+version = "1.5"
archive(byte) = "zarith.cma"
archive(native) = "zarith.cmxa"
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 7c4c31f..0000000
--- a/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-# generated by ./configure
-
-CC=gcc
-OCAMLC=ocamlc
-OCAMLOPT=ocamlopt
-OCAMLDEP=ocamldep
-OCAMLMKLIB=ocamlmklib
-OCAMLDOC=ocamldoc
-OCAMLFLAGS=
-OCAMLOPTFLAGS=
-OCAMLINC=
-CFLAGS=-I/home/mine/.opam/4.02.1/lib/ocaml -DZ_OCAML_HASH -DZ_OCAML_COMPARE_EXT -DHAS_GMP -DZ_ELF -DZ_DOT_LABEL_PREFIX -O3 -Wall -Wextra -I/home/mine/include -I/usr/local/include
-ASFLAGS=-DZ_OCAML_HASH -DZ_OCAML_COMPARE_EXT -DHAS_GMP -DZ_ELF -DZ_DOT_LABEL_PREFIX
-LIBS=-L/home/mine/lib -L/usr/local/lib -lgmp
-ARCH=x86_64
-INSTALLDIR=/home/mine/.opam/4.02.1/lib
-AR=ar
-INSTALL=install
-OCAMLFIND=ocamlfind
-INSTMETH=findlib
-OBJSUFFIX=o
-HASOCAMLOPT=yes
-HASDYNLINK=yes
-
-include project.mak
diff --git a/README b/README
deleted file mode 100644
index 6f934b8..0000000
--- a/README
+++ /dev/null
@@ -1,130 +0,0 @@
->OVERVIEW:
-
-This library implements arithmetic and logical operations over
-arbitrary-precision integers.
-
-The module is simply named "Z". Its interface is similar to that of
-the Int32, Int64 and Nativeint modules from the OCaml standard
-library, with some additional functions. See the file z.mlip for
-documentation.
-
-The implementation uses GMP (the GNU Multiple Precision arithmetic
-library) to compute over big integers.
-However, small integers are represented as unboxed Caml integers, to save
-space and improve performance. Big integers are allocated in the Caml heap,
-bypassing GMP's memory management and achieving better GC behavior than e.g.
-the MLGMP library.
-Computations on small integers use a special, faster path (coded in assembly
-for some platforms and functions) eschewing calls to GMP, while computations
-on large intergers use the low-level MPN functions from GMP.
-
-Arbitrary-precision integers can be compared correctly using OCaml's
-polymorphic comparison operators (=, <, >, etc.).
-This requires OCaml version 3.12.1 or later, though.
-
-Additional features include:
-- a module Q for rationals, built on top of Z (see q.mli)
-- a compatibility layer Big_int_Z that implements the same API as Big_int,
-but uses Z internally
-
-
-
-REQUIREMENTS:
-
-- OCaml, preferably version 3.12.1 or later.
-(Earlier versions are usable but generic comparisons will misbehave.)
-- Either the GMP library or the MPIR library, including development files.
-- A gcc-compatible C compiler and assembler (other compilers may work).
-- The Perl programming language.
-- (optional) The Findlib package manager.
-
-
-INSTALLATION:
-
-1) First, run the "configure" script by typing:
-
- ./configure
-
-2) It creates a Makefile, which can be invoked by:
-
- make
-
-This builds native and bytecode versions of the library.
-
-3) The libraries are installed by typing:
-
- make install
-
-or, if you install to a system location but are not an administrator
-
- sudo make install
-
-If Findlib is detected, it is used to install files.
-Otherwise, the files are copied to a zarith subdirectory of the directory
-given by `ocamlc -where`.
-The libraries are named "zarith.cmxa" and "zarith.cma", and the Findlib module
-is named "zarith".
-Compiling and linking with the library requires passing the "-I +zarith"
-option to ocamlc / ocamlopt.
-The "configure" script has a few options. Use the "-help" option to get a
-list and short description of each option.
-
-4) (optional)
-HTML API documentation is built (using ocamldoc) by the additional command
-
- make doc
-
-Test programs are built by the additional command
-
- make tests
-
-(but these are not installed).
-
-
-
-LICENSE:
-
-This Library is distributed under the terms of the GNU Library General
-Public License version 2, with a special exception allowing unconstrained
-static linking.
-See LICENSE file for details.
-
-
-
-AUTHORS:
-
-Antoine Miné, ENS Paris.
-Xavier Leroy, INRIA Paris-Rocquencourt.
-Pascal Cuoq, CEA LIST.
-
-
-
-COPYRIGHT:
-
-Copyright (c) 2010-2011 Antoine Miné, Abstraction project.
-Abstraction is part of the LIENS (Laboratoire d'Informatique de l'ENS),
-a joint laboratory by:
-CNRS (Centre national de la recherche scientifique, France),
-ENS (École normale supérieure, Paris, France),
-INRIA Rocquencourt (Institut national de recherche en informatique, France).
-
-
-
-CONTENTS:
-
-The source files are:
-* configure - configuration script
-* caml_z.c - C implementation of all functions
-* caml_z_*.S - asm implementation for a few functions
-* z_pp.pl - script to generate z.ml[i] from z.ml[i]p
-* z.ml[i]p - templates used to generate z.ml[i]p
-* big_int_z.ml[i] - wrapper to provide a Big_int compatible API to Z
-* q.ml[i] - rational library, pure OCaml on top of Z
-* projet.mak - builds Z, Q and the tests
-* tests/ - simple regression tests and benchmarks
-
-Note: z_pp.pl simply scans the asm file (if any) to see which functions have
-an asm implementation. It then fixes the external statements in .mlp and
-.mlip accordingly.
-The argument to z_pp.pl is the suffix * of the caml_z_*.S to use (guessed by
-configure).
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9388897
--- /dev/null
+++ b/README.md
@@ -0,0 +1,126 @@
+# The Zarith library
+
+## OVERVIEW
+
+This library implements arithmetic and logical operations over
+arbitrary-precision integers.
+
+The module is simply named `Z`. Its interface is similar to that of
+the `Int32`, `Int64` and `Nativeint` modules from the OCaml standard
+library, with some additional functions. See the file `z.mlip` for
+documentation.
+
+The implementation uses GMP (the GNU Multiple Precision arithmetic
+library) to compute over big integers.
+However, small integers are represented as unboxed Caml integers, to save
+space and improve performance. Big integers are allocated in the Caml heap,
+bypassing GMP's memory management and achieving better GC behavior than e.g.
+the MLGMP library.
+Computations on small integers use a special, faster path (coded in assembly
+for some platforms and functions) eschewing calls to GMP, while computations
+on large intergers use the low-level MPN functions from GMP.
+
+Arbitrary-precision integers can be compared correctly using OCaml's
+polymorphic comparison operators (`=`, `<`, `>`, etc.).
+This requires OCaml version 3.12.1 or later, though.
+
+Additional features include:
+* a module `Q` for rationals, built on top of `Z` (see `q.mli`)
+* a compatibility layer `Big_int_Z` that implements the same API as Big_int from the legacy `Num` library, but uses `Z` internally
+
+## REQUIREMENTS
+
+* OCaml, preferably version 3.12.1 or later. (Earlier versions are usable but generic comparisons will misbehave.)
+* Either the GMP library or the MPIR library, including development files.
+* GCC or Clang or a gcc-compatible C compiler and assembler (other compilers may work).
+* The Perl programming language.
+* The Findlib package manager (optional, recommended).
+
+
+## INSTALLATION
+
+1) First, run the "configure" script by typing:
+```
+ ./configure
+```
+The `configure` script has a few options. Use the `-help` option to get a
+list and short description of each option.
+
+2) It creates a Makefile, which can be invoked by:
+```
+ make
+```
+This builds native and bytecode versions of the library.
+
+3) The libraries are installed by typing:
+```
+ make install
+```
+or, if you install to a system location but are not an administrator
+```
+ sudo make install
+```
+If Findlib is detected, it is used to install files.
+Otherwise, the files are copied to a `zarith/` subdirectory of the directory
+given by `ocamlc -where`.
+
+The libraries are named `zarith.cmxa` and `zarith.cma`, and the Findlib module
+is named `zarith`.
+
+Compiling and linking with the library requires passing the `-I +zarith`
+option to `ocamlc` / `ocamlopt`, or the `-package zarith` option to `ocamlfind`.
+
+4) (optional, recommended) Test programs are built and run by the additional command
+```
+ make tests
+```
+(but these are not installed).
+
+5) (optional) HTML API documentation is built (using `ocamldoc`) by the additional command
+```
+ make doc
+```
+
+## LICENSE
+
+This Library is distributed under the terms of the GNU Library General
+Public License version 2, with a special exception allowing unconstrained
+static linking.
+See LICENSE file for details.
+
+
+## AUTHORS
+
+* Antoine Miné, Université Pierre et Marie Curie, formerly ENS Paris.
+* Xavier Leroy, INRIA Paris-Rocquencourt.
+* Pascal Cuoq, CEA LIST.
+
+
+## COPYRIGHT
+
+Copyright (c) 2010-2011 Antoine Miné, Abstraction project.
+Abstraction is part of the LIENS (Laboratoire d'Informatique de l'ENS),
+a joint laboratory by:
+CNRS (Centre national de la recherche scientifique, France),
+ENS (École normale supérieure, Paris, France),
+INRIA Rocquencourt (Institut national de recherche en informatique, France).
+
+
+## CONTENTS
+
+Source files | Description
+--------------------|-----------------------------------------
+ configure | configuration script
+ caml_z.c | C implementation of all functions
+ caml_z_*.S | asm implementation for a few functions
+ z_pp.pl | script to generate z.ml[i] from z.ml[i]p
+ z.ml[i]p | templates used to generate z.ml[i]p
+ big_int_z.ml[i] | wrapper to provide a Big_int compatible API to Z
+ q.ml[i] | rational library, pure OCaml on top of Z
+ projet.mak | builds Z, Q and the tests
+ tests/ | simple regression tests and benchmarks
+
+Note: `z_pp.pl` simply scans the asm file (if any) to see which functions have
+an asm implementation. It then fixes the external statements in .mlp and
+.mlip accordingly.
+The argument to `z_pp.pl` is the suffix `*` of the `caml_z_*.S` to use (guessed by configure).
diff --git a/caml_z.c b/caml_z.c
index b690a2a..5d258b9 100644
--- a/caml_z.c
+++ b/caml_z.c
@@ -521,7 +521,7 @@ CAMLprim value ml_z_of_float(value v)
Z_MARK_OP;
x = Double_val(v);
#if Z_USE_NATINT
- if (x >= Z_MIN_INT_FL && x <= Z_MAX_INT_FL) return Val_long(x);
+ if (x >= Z_MIN_INT_FL && x <= Z_MAX_INT_FL) return Val_long((intnat) x);
#endif
Z_MARK_SLOW;
#ifdef ARCH_ALIGN_INT64
@@ -2713,7 +2713,7 @@ CAMLprim value ml_z_pow(value base, value exp)
CAMLparam2(base,exp);
CAMLlocal1(r);
mpz_t mbase;
- int e = Long_val(exp);
+ intnat e = Long_val(exp);
if (e < 0)
caml_invalid_argument("Z.pow: exponent must be non-negative");
ml_z_mpz_init_set_z(mbase, base);
@@ -2728,7 +2728,7 @@ CAMLprim value ml_z_root(value a, value b)
CAMLparam2(a,b);
CAMLlocal1(r);
mpz_t ma;
- int mb = Long_val(b);
+ intnat mb = Long_val(b);
if (mb < 0)
caml_invalid_argument("Z.root: exponent must be non-negative");
ml_z_mpz_init_set_z(ma, a);
diff --git a/project.mak b/project.mak
index 79d5750..4857feb 100644
--- a/project.mak
+++ b/project.mak
@@ -39,10 +39,11 @@ MLISRC = z.mli q.mli big_int_Z.mli
AUTOGEN = z.ml z.mli z_features.h
CMIOBJ = $(MLISRC:%.mli=%.cmi)
+CMXOBJ = $(MLISRC:%.mli=%.cmx)
TOINSTALL := zarith.h zarith.cma libzarith.$(LIBSUFFIX) $(MLISRC) $(CMIOBJ)
ifeq ($(HASOCAMLOPT),yes)
-TOINSTALL := $(TOINSTALL) zarith.$(LIBSUFFIX) zarith.cmxa
+TOINSTALL := $(TOINSTALL) zarith.$(LIBSUFFIX) zarith.cmxa $(CMXOBJ)
endif
ifeq ($(HASDYNLINK),yes)
@@ -65,7 +66,7 @@ zarith.cmxa zarith.$(LIBSUFFIX): $(MLSRC:%.ml=%.cmx)
$(OCAMLMKLIB) -failsafe -o zarith $+ $(LIBS)
zarith.cmxs: zarith.cmxa libzarith.$(LIBSUFFIX)
- $(OCAMLOPT) -shared -o $@ -I . zarith.cmxa
+ $(OCAMLOPT) -shared -o $@ -I . zarith.cmxa -linkall
libzarith.$(LIBSUFFIX) dllzarith.$(DLLSUFFIX): $(SSRC:%.S=%.$(OBJSUFFIX)) $(CSRC:%.c=%.$(OBJSUFFIX))
$(OCAMLMKLIB) -failsafe -o zarith $+ $(LIBS)
@@ -132,7 +133,7 @@ clean:
make -C tests clean
depend: $(AUTOGEN)
- $(OCAMLDEP) -native $(OCAMLINC) *.ml *.mli > depend
+ $(OCAMLDEP) -native $(OCAMLINC) $(MLSRC) $(MLISRC) > depend
include depend
diff --git a/q.ml b/q.ml
index d6e5f6c..e7dfd81 100644
--- a/q.ml
+++ b/q.ml
@@ -189,7 +189,41 @@ let to_int64 x = Z.to_int64 (to_bigint x)
let to_nativeint x = Z.to_nativeint (to_bigint x)
-
+let to_float x =
+ match classify x with
+ | ZERO -> 0.0
+ | INF -> infinity
+ | MINF -> neg_infinity
+ | UNDEF -> nan
+ | NZERO ->
+ let p = x.num and q = x.den in
+ let np = Z.numbits p and nq = Z.numbits q in
+ if np <= 53 && nq <= 53 then
+ (* p and q convert to floats exactly; use FP division to get the
+ correctly-rounded result. *)
+ Int64.to_float (Z.to_int64 p) /. Int64.to_float (Z.to_int64 q)
+ else begin
+ (* |p| is in [2^(np-1), 2^np)
+ q is in [2^(nq-1), 2^nq)
+ hence |p/q| is in (2^(np-nq-1), 2^(np-nq+1)).
+ We define n such that |p/q*2^n| is in [2^54, 2^56).
+ >= 2^54 so that the round to odd technique applies.
+ < 2^56 so that the integral part is representable as an int64. *)
+ let n = 55 - (np - nq) in
+ (* Scaling p/q by 2^n *)
+ let (p', q') =
+ if n >= 0
+ then (Z.shift_left p n, q)
+ else (p, Z.shift_left q (-n)) in
+ (* Euclidean division of p' by q' *)
+ let (quo, rem) = Z.ediv_rem p' q' in
+ (* quo is the integral part of p/q*2^n
+ rem/q' is the fractional part. *)
+ (* Round quo to float *)
+ let f = Z.round_to_float quo (Z.sign rem = 0) in
+ (* Apply exponent *)
+ ldexp f (-n)
+ end
(* operations *)
(* ---------- *)
diff --git a/q.mli b/q.mli
index f398d37..c43ca1b 100644
--- a/q.mli
+++ b/q.mli
@@ -164,6 +164,11 @@ val to_nativeint: t -> nativeint
val to_string: t -> string
(** Converts to human-readable, decimal, [/]-separated rational. *)
+val to_float: t -> float
+(** Converts to a floating-point number, using the current
+ floating-point rounding mode. With the default rounding mode,
+ the result is the floating-point number closest to the given
+ rational; ties break to even mantissa. *)
(** {1 Arithmetic operations} *)
diff --git a/tests/bi.ml b/tests/bi.ml
index 7d7b9ea..415d0ca 100644
--- a/tests/bi.ml
+++ b/tests/bi.ml
@@ -35,12 +35,16 @@ let random_int64 () =
let random_int () = Int64.to_int (random_int64 ())
let random_string () =
- let s = String.create (1 + Random.int 200) in
- for i = 0 to String.length s - 1 do
- s.[i] <- Char.chr (48 + Random.int 10)
+ let l = 1 + Random.int 200 in
+ let s = Buffer.create l in
+ let st = if l > 1 && Random.bool () then begin
+ Buffer.add_char s '-';
+ 1
+ end else 0 in
+ for i = st to l - 1 do
+ Buffer.add_char s (Char.chr (48 + Random.int 10))
done;
- if String.length s > 1 && Random.bool () then s.[0] <- '-';
- s
+ Buffer.contents s
(* list utility *)
diff --git a/tests/tofloat.ml b/tests/tofloat.ml
index 291c50d..511daa1 100644
--- a/tests/tofloat.ml
+++ b/tests/tofloat.ml
@@ -25,6 +25,14 @@ let test1 (mant: int64) (exp: int) =
false
end
+let rnd64 () =
+ let m1 = Random.bits() in (* 30 bits *)
+ let m2 = Random.bits() in (* 30 bits *)
+ let m3 = Random.bits() in
+ Int64.(logor (of_int m1)
+ (logor (shift_left (of_int m2) 30)
+ (shift_left (of_int m3) 60)))
+
let testN numrounds =
printf " (%d tests)... %!" numrounds;
let errors = ref 0 in
@@ -36,12 +44,7 @@ let testN numrounds =
done;
(* Some random int64 values scaled by some random power of 2 *)
for i = 1 to numrounds do
- let m1 = Random.bits() in (* 30 bits *)
- let m2 = Random.bits() in (* 30 bits *)
- let m3 = Random.bits() in
- let m = Int64.(logor (of_int m1)
- (logor (shift_left (of_int m2) 30)
- (shift_left (of_int m3) 60))) in
+ let m = rnd64() in
let exp = Random.int 1100 in (* sometimes +inf will result *)
if not (test1 m exp) then incr errors
done;
@@ -55,38 +58,77 @@ let testN numrounds =
then printf "passed\n%!"
else printf "FAILED (%d errors)\n%!" !errors
+let testQ1 (mant1: int64) (exp1: int) (mant2: int64) (exp2: int) =
+ let expected =
+ ldexp (Int64.to_float mant1) exp1 /. ldexp (Int64.to_float mant2) exp2 in
+ let actual =
+ Q.to_float (Q.make (Z.shift_left (Z.of_int64 mant1) exp1)
+ (Z.shift_left (Z.of_int64 mant2) exp2)) in
+ if compare actual expected = 0 then true else begin
+ printf "%Ld * 2^%d / %Ld * 2^%d : expected %s, got %s\n"
+ mant1 exp1 mant2 exp2 (hex_of_float expected) (hex_of_float actual);
+ false
+ end
+
+let testQN numrounds =
+ printf " (%d tests)... %!" numrounds;
+ let errors = ref 0 in
+ (* Some special values *)
+ if not (testQ1 0L 0 1L 0) then incr errors;
+ if not (testQ1 1L 0 0L 0) then incr errors;
+ if not (testQ1 (-1L) 0 0L 0) then incr errors;
+ if not (testQ1 0L 0 0L 0) then incr errors;
+ (* Some random fractions *)
+ for i = 1 to numrounds do
+ let m1 = Random.int64 0x20000000000000L in
+ let m1 = if Random.bool() then m1 else Int64.neg m1 in
+ let exp1 = Random.int 500 in
+ let m2 = Random.int64 0x20000000000000L in
+ let exp2 = Random.int 500 in
+ if not (testQ1 m1 exp1 m2 exp2) then incr errors
+ done;
+ if !errors = 0
+ then printf "passed\n%!"
+ else printf "FAILED (%d errors)\n%!" !errors
+
let _ =
let numrounds =
if Array.length Sys.argv >= 2
then int_of_string Sys.argv.(1)
else 100_000 in
- printf "Default rounding mode";
+ printf "Default rounding mode (Z)";
testN numrounds;
+ printf "Default rounding mode (Q)";
+ testQN numrounds;
if setround FE_TOWARDZERO then begin
- printf "Round toward zero";
- testN numrounds
+ printf "Round toward zero (Z)";
+ testN numrounds;
+ printf "Round toward zero (Q)";
+ testQN numrounds
end else begin
printf "Round toward zero not supported, skipping\n"
end;
if setround FE_DOWNWARD then begin
- printf "Round downward";
- testN numrounds
+ printf "Round downward (Z)";
+ testN numrounds;
+ printf "Round downward (Q)";
+ testQN numrounds
end else begin
printf "Round downward not supported, skipping\n"
end;
if setround FE_UPWARD then begin
- printf "Round upward";
- testN numrounds
+ printf "Round upward (Z)";
+ testN numrounds;
+ printf "Round upward (Q)";
+ testQN numrounds
end else begin
printf "Round upward not supported, skipping\n"
end;
if setround FE_TONEAREST then begin
- printf "Round to nearest";
- testN numrounds
+ printf "Round to nearest (Z)";
+ testN numrounds;
+ printf "Round to nearest (Q)";
+ testQN numrounds
end else begin
printf "Round to nearest not supported, skipping\n"
end
-
-
-
-
diff --git a/z.mlip b/z.mlip
index 9cf13f8..fdddc7f 100644
--- a/z.mlip
+++ b/z.mlip
@@ -60,7 +60,7 @@ val one: t
val minus_one: t
(** The number -1. *)
-external of_int: int -> t = "ml_z_of_int" "noalloc"
+external of_int: int -> t = "ml_z_of_int" @NOALLOC
(** Converts from a base integer. *)
external of_int32: int32 -> t = "ml_z_of_int32"
@@ -74,7 +74,7 @@ external of_nativeint: nativeint -> t = "ml_z_of_nativeint"
external of_float: float -> t = "ml_z_of_float"
(** Converts from a floating-point value.
- The value is truncated.
+ The value is truncated (rounded towards zero).
Raises [Overflow] on infinity and NaN arguments.
*)
@@ -87,6 +87,8 @@ val of_string: string -> t
represented, in hexadecimal, octal, or binary, respectively.
Otherwise, base 10 is assumed.
(Unlike C, a lone [0] prefix does not denote octal.)
+ Raises an [Invalid_argument] exception if the string is not a
+ syntactically correct representation of an integer.
*)
val of_substring : string -> pos:int -> len:int -> t
@@ -226,14 +228,14 @@ external shift_right_trunc: t -> int -> t = shift_right_trunc at ASM
The second argument must be non-negative.
*)
-external numbits: t -> int = "ml_z_numbits" "noalloc"
+external numbits: t -> int = "ml_z_numbits" @NOALLOC
(** Returns the number of significant bits in the given number.
If [x] is zero, [numbits x] returns 0. Otherwise,
[numbits x] returns a positive integer [n] such that
[2^{n-1} <= |x| < 2^n]. Note that [numbits] is defined
for negative arguments, and that [numbits (-x) = numbits x]. *)
-external trailing_zeros: t -> int = "ml_z_trailing_zeros" "noalloc"
+external trailing_zeros: t -> int = "ml_z_trailing_zeros" @NOALLOC
(** Returns the number of trailing 0 bits in the given number.
If [x] is zero, [trailing_zeros x] returns [max_int].
Otherwise, [trailing_zeros x] returns a nonnegative integer [n]
@@ -266,16 +268,16 @@ external hamdist: t -> t -> int = "ml_z_hamdist"
*)
external to_int: t -> int = "ml_z_to_int"
-(** Converts to a base integer. May raise an [Overflow]. *)
+(** Converts to a base integer. May raise [Overflow]. *)
external to_int32: t -> int32 = "ml_z_to_int32"
-(** Converts to a 32-bit integer. May raise an [Overflow]. *)
+(** Converts to a 32-bit integer. May raise [Overflow]. *)
external to_int64: t -> int64 = "ml_z_to_int64"
(** Converts to a 64-bit integer. May raise [Overflow]. *)
external to_nativeint: t -> nativeint = "ml_z_to_nativeint"
-(** Converts to a native integer. May raise an [Overflow]. *)
+(** Converts to a native integer. May raise [Overflow]. *)
val to_float: t -> float
(** Converts to a floating-point value.
@@ -315,16 +317,16 @@ external format: string -> t -> string = "ml_z_format"
are simply ignored (and not copied in the output).
*)
-external fits_int: t -> bool = "ml_z_fits_int" "noalloc"
+external fits_int: t -> bool = "ml_z_fits_int" @NOALLOC
(** Whether the argument fits in a regular [int]. *)
-external fits_int32: t -> bool = "ml_z_fits_int32" "noalloc"
+external fits_int32: t -> bool = "ml_z_fits_int32" @NOALLOC
(** Whether the argument fits in an [int32]. *)
-external fits_int64: t -> bool = "ml_z_fits_int64" "noalloc"
+external fits_int64: t -> bool = "ml_z_fits_int64" @NOALLOC
(** Whether the argument fits in an [int64]. *)
-external fits_nativeint: t -> bool = "ml_z_fits_nativeint" "noalloc"
+external fits_nativeint: t -> bool = "ml_z_fits_nativeint" @NOALLOC
(** Whether the argument fits in a [nativeint]. *)
@@ -353,7 +355,7 @@ val pp_print: Format.formatter -> t -> unit
(** {1 Ordering} *)
-external compare: t -> t -> int = "ml_z_compare" "noalloc"
+external compare: t -> t -> int = "ml_z_compare" @NOALLOC
(** Comparison. [compare x y] returns 0 if [x] equals [y],
-1 if [x] is smaller than [y], and 1 if [x] is greater than [y].
@@ -361,7 +363,7 @@ external compare: t -> t -> int = "ml_z_compare" "noalloc"
only on OCaml 3.12.1 and later versions.
*)
-external equal: t -> t -> bool = "ml_z_equal" "noalloc"
+external equal: t -> t -> bool = "ml_z_equal" @NOALLOC
(** Equality test. *)
val leq: t -> t -> bool
@@ -376,7 +378,7 @@ val lt: t -> t -> bool
val gt: t -> t -> bool
(** Greater than (and not equal). *)
-external sign: t -> int = "ml_z_sign" "noalloc"
+external sign: t -> int = "ml_z_sign" @NOALLOC
(** Returns -1, 0, or 1 when the argument is respectively negative, null, or
positive.
*)
@@ -393,7 +395,7 @@ val is_even: t -> bool
val is_odd: t -> bool
(** Returns true if the argument is odd, false if even. *)
-external hash: t -> int = "ml_z_hash" "noalloc"
+external hash: t -> int = "ml_z_hash" @NOALLOC
(** Hashes a number.
This functions gives the same result as OCaml's polymorphic hashing
function.
@@ -410,10 +412,12 @@ external gcd: t -> t -> t = "ml_z_gcd"
*)
val gcdext: t -> t -> (t * t * t)
-(** [gcd_ext u v] returns [(g,s,t)] where [g] is the greatest common divisor
+(** [gcdext u v] returns [(g,s,t)] where [g] is the greatest common divisor
and [g=us+vt].
- [g] is always positive.
+ [g] is always positive.
Raises a [Division_by_zero] is either argument is null.
+
+ Note: the function is based on the GMP [mpn_gcdext] function. The exact choice of [s] and [t] such that [g=us+vt] is not specified, as it may vary from a version of GMP to another (it has changed notably in GMP 4.3.0 and 4.3.1).
*)
val lcm: t -> t -> t
@@ -469,7 +473,8 @@ external pow: t -> int -> t = "ml_z_pow"
*)
external sqrt: t -> t = "ml_z_sqrt"
-(** Returns the square root. The result is truncated.
+(** Returns the square root. The result is truncated (rounded down
+ to an integer).
Raises an [Invalid_argument] on negative arguments.
*)
@@ -503,7 +508,7 @@ val log2up: t -> int
(** {1 Representation} *)
-external size: t -> int = "ml_z_size" "noalloc"
+external size: t -> int = "ml_z_size" @NOALLOC
(** Returns the number of machine words used to represent the number. *)
external extract: t -> int -> int -> t = "ml_z_extract"
@@ -517,7 +522,7 @@ val signed_extract: t -> int -> int -> t
(** [signed_extract a off len] extracts bits [off] to [off]+[len]-1 of [b],
as [extract] does, then sign-extends bit [len-1] of the result
(that is, bit [off + len - 1] of [a]). The result is between
- [- 2{^[len]-1}] (included) and [2{^[len]-1}] excluded,
+ [- 2{^[len]-1}] (included) and [2{^[len]-1}] (excluded),
and equal to [extract a off len] modulo [2{^len}].
*)
@@ -598,7 +603,7 @@ external (lsl): t -> int -> t = shift_left at ASM
external (asr): t -> int -> t = shift_right at ASM
(** Bit-wise shift to the right [shift_right]. *)
-external (~$): int -> t = "ml_z_of_int" "noalloc"
+external (~$): int -> t = "ml_z_of_int" @NOALLOC
(** Conversion from [int] [of_int]. *)
external ( ** ): t -> int -> t = "ml_z_pow"
@@ -608,3 +613,8 @@ external ( ** ): t -> int -> t = "ml_z_pow"
val version: string
(** Library version (this file refers to version [@VERSION]). *)
+
+(**/**)
+
+(** For internal use in module [Q]. *)
+val round_to_float: t -> bool -> float
diff --git a/z.mlp b/z.mlp
index ee7b8f5..58763de 100644
--- a/z.mlp
+++ b/z.mlp
@@ -47,7 +47,7 @@ external lognot: t -> t = lognot at ASM
external shift_left: t -> int -> t = shift_left at ASM
external shift_right: t -> int -> t = shift_right at ASM
external shift_right_trunc: t -> int -> t = shift_right_trunc at ASM
-external of_int: int -> t = "ml_z_of_int" "noalloc"
+external of_int: int -> t = "ml_z_of_int" @NOALLOC
external of_int32: int32 -> t = "ml_z_of_int32"
external of_int64: int64 -> t = "ml_z_of_int64"
external of_nativeint: nativeint -> t = "ml_z_of_nativeint"
@@ -58,22 +58,22 @@ external to_int64: t -> int64 = "ml_z_to_int64"
external to_nativeint: t -> nativeint = "ml_z_to_nativeint"
external format: string -> t -> string = "ml_z_format"
external of_substring_base: int -> string -> pos:int -> len:int -> t = "ml_z_of_substring_base"
-external compare: t -> t -> int = "ml_z_compare" "noalloc"
-external equal: t -> t -> bool = "ml_z_equal" "noalloc"
-external sign: t -> int = "ml_z_sign" "noalloc"
+external compare: t -> t -> int = "ml_z_compare" @NOALLOC
+external equal: t -> t -> bool = "ml_z_equal" @NOALLOC
+external sign: t -> int = "ml_z_sign" @NOALLOC
external gcd: t -> t -> t = "ml_z_gcd"
external gcdext_intern: t -> t -> (t * t * bool) = "ml_z_gcdext_intern"
external sqrt: t -> t = "ml_z_sqrt"
external sqrt_rem: t -> (t * t) = "ml_z_sqrt_rem"
-external numbits: t -> int = "ml_z_numbits" "noalloc"
-external trailing_zeros: t -> int = "ml_z_trailing_zeros" "noalloc"
+external numbits: t -> int = "ml_z_numbits" @NOALLOC
+external trailing_zeros: t -> int = "ml_z_trailing_zeros" @NOALLOC
external popcount: t -> int = "ml_z_popcount"
external hamdist: t -> t -> int = "ml_z_hamdist"
-external size: t -> int = "ml_z_size" "noalloc"
-external fits_int: t -> bool = "ml_z_fits_int" "noalloc"
-external fits_int32: t -> bool = "ml_z_fits_int32" "noalloc"
-external fits_int64: t -> bool = "ml_z_fits_int64" "noalloc"
-external fits_nativeint: t -> bool = "ml_z_fits_nativeint" "noalloc"
+external size: t -> int = "ml_z_size" @NOALLOC
+external fits_int: t -> bool = "ml_z_fits_int" @NOALLOC
+external fits_int32: t -> bool = "ml_z_fits_int32" @NOALLOC
+external fits_int64: t -> bool = "ml_z_fits_int64" @NOALLOC
+external fits_nativeint: t -> bool = "ml_z_fits_nativeint" @NOALLOC
external extract: t -> int -> int -> t = "ml_z_extract"
external powm: t -> t -> t -> t = "ml_z_powm"
external pow: t -> int -> t = "ml_z_pow"
@@ -85,7 +85,7 @@ external perfect_power: t -> bool = "ml_z_perfect_power"
external perfect_square: t -> bool = "ml_z_perfect_square"
external probab_prime: t -> int -> int = "ml_z_probab_prime"
external nextprime: t -> t = "ml_z_nextprime"
-external hash: t -> int = "ml_z_hash" "noalloc"
+external hash: t -> int = "ml_z_hash" @NOALLOC
external to_bits: t -> string = "ml_z_to_bits"
external of_bits: string -> t = "ml_z_of_bits"
@@ -108,7 +108,7 @@ let of_substring = of_substring_base 0
let of_string_base base s = of_substring_base base s ~pos:0 ~len:(String.length s)
let ediv_rem a b =
- (* we have a = a * b + r, but [Big_int]'s remainder satisfies 0 <= r < |b|,
+ (* we have a = q * b + r, but [Big_int]'s remainder satisfies 0 <= r < |b|,
while [Z]'s remainder satisfies -|b| < r < |b| and sign(r) = sign(a)
*)
let q,r = div_rem a b in
@@ -132,7 +132,7 @@ let lcm u v =
let g = gcd u v in
abs (mul (divexact u g) v)
-external testbit_internal: t -> int -> bool = "ml_z_testbit" "noalloc"
+external testbit_internal: t -> int -> bool = "ml_z_testbit" @NOALLOC
let testbit x n =
if n >= 0 then testbit_internal x n else invalid_arg "Z.testbit"
(* The test [n >= 0] is done in Caml rather than in the C stub code
@@ -213,7 +213,7 @@ external (lxor): t -> t -> t = logxor at ASM
external (~!): t -> t = lognot at ASM
external (lsl): t -> int -> t = shift_left at ASM
external (asr): t -> int -> t = shift_right at ASM
-external (~$): int -> t = "ml_z_of_int" "noalloc"
+external (~$): int -> t = "ml_z_of_int" @NOALLOC
external ( ** ): t -> int -> t = "ml_z_pow"
let version = @VERSION
diff --git a/z_pp.pl b/z_pp.pl
index ff10581..48a163a 100755
--- a/z_pp.pl
+++ b/z_pp.pl
@@ -25,6 +25,13 @@ die "Usage: './z_pp.pl architecture'" unless $#ARGV==0;
$v = `grep version META`;
($ver) = $v =~ /version\s*=\s*(\S+)/;
+$ov = `ocamlc -version`;
+($major,$minor,$extra) = split(/\./, $ov, 3);
+if ($major > 4 || ($major == 4 && $minor >= 3)) {
+ $noalloc = "[\@\@noalloc]";
+} else {
+ $noalloc = "\"noalloc\"";
+}
# scan assembly
@@ -64,6 +71,7 @@ sub doml {
$l =~ s/$f\@ASM/$r/g;
}
$l =~ s/\@VERSION/$ver/;
+ $l =~ s/\@NOALLOC/$noalloc/;
print O "$l";
}
close F;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ocaml-maint/packages/ocaml-zarith.git
More information about the Pkg-ocaml-maint-commits
mailing list