Commit 98055bed authored by Stephane Glondu's avatar Stephane Glondu

New upstream version 1.2

parents
*.o
*.a
*.so
*.obj
*.lib
*.dll
*.cm[ioxat]
*.cmx[as]
*.cmti
*.annot
src/META
test/test.byt
test/test.exe
Release 1.2 (2019-06-21)
- Issue #9: install all .cmx files.
- Pull request #6: provide findlib-install target to install everything
using ocamlfind.
- Issue #3: make sur the stublibs/ directory exists before installing DLLs
inside it.
- Issue #4: wrong DLL file names for Win32 ports, causing errors at
installation time.
Release 1.1 (2017-10-13):
- Install .cmx files as well.
- Fix permissions on installed files.
- Make tests compatible with safe strings.
Release 1.0 (2017-06-04):
- Fix build rule for nums.cmxs.
- Typo in LICENSE file.
Initialization (2016-12-08):
- Initial import of the sources and test suite from the core OCaml system,
version 4.04.
- Restructure as independent project with standalone Makefiles.
- Integrate findlib support, including printers for toplevel use.
This diff is collapsed.
all:
$(MAKE) -C src all
$(MAKE) -C toplevel all
test:
$(MAKE) -C test all
clean:
$(MAKE) -C src clean
$(MAKE) -C toplevel clean
$(MAKE) -C test clean
install:
$(MAKE) -C src install
$(MAKE) -C toplevel install
findlib-install:
$(MAKE) -C src findlib-install
$(MAKE) -C toplevel install
uninstall:
$(MAKE) -C src uninstall
$(MAKE) -C toplevel uninstall
findlib-uninstall:
$(MAKE) -C src findlib-uninstall
$(MAKE) -C toplevel uninstall
.PHONY: all test clean install uninstall findlib-install findlib-uninstall
# The Num library for arithmetic on big integers and rationals
## Overview
This library implements arbitrary-precision arithmetic on big integers and on rationals.
This is a legacy library. It used to be part of the core OCaml distribution (in <code>otherlibs/num</code>) but is now distributed separately. New applications that need arbitrary-precision arithmetic should use the Zarith library (https://github.com/ocaml/Zarith) instead of the Num library, and older applications that already use Num are encouraged to switch to Zarith. Zarith delivers much better performance than Num and has a nicer API.
## Usage
To use the bignum library from your programs, it is recommended to use ocamlfind:
```
ocamlfind ocamlc -package num ...
ocamlfind ocamlopt -package num ...
```
Alternatively, you can do
```
ocamlc <options> nums.cma <.cmo and .ml files>
ocamlopt <options> nums.cmxa <.cmx and .ml files>
```
For toplevel use, just issue the commands
```
#use "topfind";;
#package "num";;
```
or
```
#load "nums.cma";;
```
## Documentation
The following modules are documented in their interfaces:
* `Big_int`: operations on arbitrary-precision integers
* `Num`: operations on arbitrary-precision numbers (integers and rationals)
* `Arith_status`: flags that control rational arithmetic
More documentation on the functions provided in this library can be found in _The CAML Numbers Reference Manual_ by Valérie Ménissier-Morain, INRIA technical report 141, july 1992, http://hal.inria.fr/docs/00/07/00/27/PDF/RT-0141.pdf
## Compilation and installation
Prerequisites: OCaml version 4.04 or newer.
```
make all
make test
make install
make clean
```
## History
This library is derived from Valérie Ménissier-Morain's implementation of rational arithmetic for Caml V3.1. Xavier Leroy did the Caml Light port. Victor Manuel Gulias Fernandez did the initial Caml Special Light / OCaml port. Pierre Weis did most of the maintenance and bug fixing.
Initially, the low-level big integer operations were provided by the BigNum package developed by Bernard Serpette, Jean Vuillemin and Jean-Claude Hervé (INRIA and Digital PRL). License issues forced us to replace the BigNum package. The current implementation of low-level big integer operations is due to Xavier Leroy.
arith_flags.cmi :
arith_status.cmi :
big_int.cmi : nat.cmi
int_misc.cmi :
nat.cmi :
num.cmi : ratio.cmi nat.cmi big_int.cmi
ratio.cmi : nat.cmi big_int.cmi
arith_flags.cmo : arith_flags.cmi
arith_flags.cmx : arith_flags.cmi
arith_status.cmo : arith_flags.cmi arith_status.cmi
arith_status.cmx : arith_flags.cmx arith_status.cmi
big_int.cmo : nat.cmi int_misc.cmi big_int.cmi
big_int.cmx : nat.cmx int_misc.cmx big_int.cmi
int_misc.cmo : int_misc.cmi
int_misc.cmx : int_misc.cmi
nat.cmo : int_misc.cmi nat.cmi
nat.cmx : int_misc.cmx nat.cmi
num.cmo : ratio.cmi nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi num.cmi
num.cmx : ratio.cmx nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx num.cmi
ratio.cmo : nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi ratio.cmi
ratio.cmx : nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx ratio.cmi
# This META is the one provided by findlib when the "num" library was
# part of the core OCaml distribution. For backward compatibility,
# it is installed into OCaml's standard library directory. If the
# directory line below is removed, then it's installed in a
# subdirectory, as normal for a findlib package.
requires = "num.core"
requires(toploop) = "num.core,num-top"
version = "1.0"
description = "Arbitrary-precision rational arithmetic"
package "core" (
directory = "^"
version = "1.0"
browse_interfaces = ""
archive(byte) = "nums.cma"
archive(native) = "nums.cmxa"
plugin(byte) = "nums.cma"
plugin(native) = "nums.cmxs"
)
OCAMLC=ocamlc
OCAMLOPT=ocamlopt
OCAMLDEP=ocamldep
OCAMLMKLIB=ocamlmklib
OCAMLFIND=ocamlfind
INSTALL_DATA=install -m 644
INSTALL_DLL=install
INSTALL_DIR=install -d
STDLIBDIR=$(shell $(OCAMLC) -where)
include $(STDLIBDIR)/Makefile.config
ifeq "$(ARCH)" "i386"
BNG_ARCH=ia32
else ifeq "$(ARCH)" "amd64"
BNG_ARCH=amd64
else ifeq "$(ARCH)" "arm64"
BNG_ARCH=arm64
else ifeq "$(ARCH)" "power"
BNG_ARCH=ppc
else
BNG_ARCH=generic
endif
CAMLCFLAGS=-w +a-4-9-41-42-44-45-48 -warn-error A -bin-annot -g \
-safe-string -strict-sequence -strict-formats
CAMLOPTFLAGS=$(CAMLCFLAGS)
ifeq "$(FLAMBDA)" "true"
CAMLOPTFLAGS+=-O3
endif
CMIS=big_int.cmi nat.cmi num.cmi ratio.cmi arith_status.cmi
CMOS=int_misc.cmo nat.cmo big_int.cmo arith_flags.cmo \
ratio.cmo num.cmo arith_status.cmo
CMXS=$(CMOS:.cmo=.cmx)
COBJS=bng.$(O) nat_stubs.$(O)
all:: libnums.$(A) nums.cma
ifneq "$(ARCH)" "none"
all:: nums.cmxa
endif
ifeq "$(NATDYNLINK)" "true"
all:: nums.cmxs
endif
libnums.$(A): $(COBJS)
$(OCAMLMKLIB) -oc nums $(COBJS)
nums.cma: $(CMOS)
$(OCAMLMKLIB) -o nums -oc nums -linkall $(CMOS)
nums.cmxa: $(CMXS)
$(OCAMLMKLIB) -o nums -oc nums -linkall $(CMXS)
nums.cmxs: nums.cmxa libnums.$(A)
$(OCAMLOPT) $(CAMLOPTFLAGS) -I . -shared -o nums.cmxs nums.cmxa
# We hard-code the C dependencies rather than having them generated
# because the dependencies are so simple.
bng.$(O): bng.h bng_*.c
nat_stubs.$(O): bng.h nat.h
%.cmi: %.mli
$(OCAMLC) $(CAMLCFLAGS) -c $*.mli
%.cmo: %.ml
$(OCAMLC) $(CAMLCFLAGS) -c $*.ml
%.cmx: %.ml
$(OCAMLOPT) $(CAMLOPTFLAGS) -c $*.ml
%.$(O): %.c
$(OCAMLC) -ccopt -DBNG_ARCH_$(BNG_ARCH) -c $*.c
# Legacy installation: files go into OCaml's stdlib directory; only META
# is installed via findlib
TOINSTALL=nums.cma libnums.$(A) $(CMIS) $(CMIS:.cmi=.mli) $(CMIS:.cmi=.cmti)
ifneq "$(ARCH)" "none"
TOINSTALL+=nums.cmxa nums.$(A) $(CMXS)
endif
ifeq "$(NATDYNLINK)" "true"
TOINSTALL+=nums.cmxs
endif
ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true"
TOINSTALL_STUBS=dllnums$(EXT_DLL)
else
TOINSTALL_STUBS=
endif
install:
cp META.in META
$(OCAMLFIND) install num META
rm -f META
$(INSTALL_DATA) $(TOINSTALL) $(STDLIBDIR)
ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true"
$(INSTALL_DIR) $(STDLIBDIR)/stublibs
$(INSTALL_DLL) $(TOINSTALL_STUBS) $(STDLIBDIR)/stublibs
endif
findlib-install:
grep -Fv '^' META.in > META
$(OCAMLFIND) install num META $(TOINSTALL) $(TOINSTALL_STUBS)
rm -f META
findlib-uninstall:
$(OCAMLFIND) remove num
uninstall: findlib-uninstall
cd $(STDLIBDIR) && rm -f $(TOINSTALL)
ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true"
cd $(STDLIBDIR)/stublibs && rm -f $(TOINSTALL_STUBS)
endif
clean:
rm -f *.cm[ioxta] *.cmx[as] *.cmti *.$(O) *.$(A) *$(EXT_DLL)
depend:
$(OCAMLDEP) -slash *.mli *.ml > .depend
include .depend
(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1996 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
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;;
(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1996 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
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
(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1996 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
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 ()
;;
(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1996 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
(** 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
(** See {!Arith_status.set_error_when_null_denominator}.*)
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
(** See {!Arith_status.set_normalize_ratio}.*)
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
(** See {!Arith_status.set_normalize_ratio_when_printing}.*)
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
(** See {!Arith_status.set_approx_printing}.*)
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
(** See {!Arith_status.set_floating_precision}.*)
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. *)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/**************************************************************************/
/* */
/* OCaml */
/* */
/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
/* */
/* Copyright 2003 Institut National de Recherche en Informatique et */
/* en Automatique. */
/* */
/* All rights reserved. This file is distributed under the terms of */
/* the GNU Lesser General Public License version 2.1, with the */
/* special exception on linking described in the file LICENSE. */
/* */
/**************************************************************************/
#include <string.h>
#include "caml/config.h"
typedef uintnat bngdigit;
typedef bngdigit * bng;
typedef unsigned int bngcarry;
typedef uintnat bngsize;
#define BNG_BITS_PER_DIGIT (sizeof(bngdigit) * 8)
#define BNG_BITS_PER_HALF_DIGIT (sizeof(bngdigit) * 4)
struct bng_operations {
/* {a,alen} := {a, alen} + carry. Return carry out. */
bngcarry (*add_carry)
(bng a/*[alen]*/, bngsize alen, bngcarry carry);
#define bng_add_carry bng_ops.add_carry
/* {a,alen} := {a,alen} + {b,blen} + carry. Return carry out.
Require alen >= blen. */
bngcarry (*add)
(bng a/*[alen]*/, bngsize alen,
bng b/*[blen]*/, bngsize blen,
bngcarry carry);
#define bng_add bng_ops.add
/* {a,alen} := {a, alen} - carry. Return carry out. */
bngcarry (*sub_carry)
(bng a/*[alen]*/, bngsize alen, bngcarry carry);
#define bng_sub_carry bng_ops.sub_carry
/* {a,alen} := {a,alen} - {b,blen} - carry. Return carry out.
Require alen >= blen. */
bngcarry (*sub)
(bng a/*[alen]*/, bngsize alen,
bng b/*[blen]*/, bngsize blen,
bngcarry carry);
#define bng_sub bng_ops.sub
/* {a,alen} := {a,alen} << shift.
Return the bits shifted out of the most significant digit of a.
Require 0 <= shift < BITS_PER_BNGDIGIT. */
bngdigit (*shift_left)
(bng a/*[alen]*/, bngsize alen,
int shift);
#define bng_shift_left bng_ops.shift_left
/* {a,alen} := {a,alen} >> shift.
Return the bits shifted out of the least significant digit of a.
Require 0 <= shift < BITS_PER_BNGDIGIT. */
bngdigit (*shift_right)
(bng a/*[alen]*/, bngsize alen,
int shift);
#define bng_shift_right bng_ops.shift_right
/* {a,alen} := {a,alen} + d * {b,blen}. Return carry out.
Require alen >= blen.
If alen > blen, the carry out returned is 0 or 1.
If alen == blen, the carry out returned is a full digit. */
bngdigit (*mult_add_digit)
(bng a/*[alen]*/, bngsize alen,
bng b/*[blen]*/, bngsize blen,
bngdigit d);
#define bng_mult_add_digit bng_ops.mult_add_digit
/* {a,alen} := {a,alen} - d * {b,blen}. Return carry out.
Require alen >= blen.
If alen > blen, the carry out returned is 0 or 1.
If alen == blen, the carry out returned is a full digit. */
bngdigit (*mult_sub_digit)
(bng a/*[alen]*/, bngsize alen,
bng b/*[blen]*/, bngsize blen,
bngdigit d);
#define bng_mult_sub_digit bng_ops.mult_sub_digit
/* {a,alen} := {a,alen} + {b,blen} * {c,clen}. Return carry out.
Require alen >= blen + clen. */
bngcarry (*mult_add)
(bng a/*[alen]*/, bngsize alen,
bng b/*[blen]*/, bngsize blen,
bng c/*[clen]*/, bngsize clen);
#define bng_mult_add bng_ops.mult_add
/* {a,alen} := 2 * {a,alen} + {b,blen}^2. Return carry out.
Require alen >= 2 * blen. */
bngcarry (*square_add)
(bng a/*[alen]*/, bngsize alen,
bng b/*[blen]*/, bngsize blen);
#define bng_square_add bng_ops.square_add
/* {a,len-1} := {b,len} / d. Return {b,len} modulo d.
Require d is normalized and MSD of b < d.
See div_rem_digit for a function that does not require d
to be normalized */
bngdigit (*div_rem_norm_digit)
(bng a/*[len-1]*/, bng b/*[len]*/, bngsize len, bngdigit d);
#define bng_div_rem_norm_digit bng_ops.div_rem_norm_digit
/* {a,len-1} := {b,len} / d. Return {b,len} modulo d.
Require MSD of b < d. */
bngdigit (*div_rem_digit)
(bng a/*[len-1]*/, bng b/*[len]*/, bngsize len, bngdigit d);
#define bng_div_rem_digit bng_ops.div_rem_digit
/* {n+dlen, nlen-dlen} := {n,nlen} / {d, dlen}.
{n, dlen} := {n,nlen} modulo {d, dlen}.
Require nlen > dlen and MSD of n < MSD of d (which implies d != 0). */
void (*div_rem)
(bng n/*[nlen]*/, bngsize nlen,
bng d/*[nlen]*/, bngsize dlen);
#define bng_div_rem bng_ops.div_rem
};
extern struct bng_operations bng_ops;
/* Initialize the BNG library */
extern void bng_init(void);
/* {a,alen} := 0 */
#define bng_zero(a,alen) memset((a), 0, (alen) * sizeof(bngdigit))
/* {a,len} := {b,len} */
#define bng_assign(a,b,len) memmove((a), (b), (len) * sizeof(bngdigit))
/* Complement the digits of {a,len} */
extern void bng_complement(bng a/*[alen]*/, bngsize alen);
/* Return number of significant digits in {a,alen}. */
extern bngsize bng_num_digits(bng a/*[alen]*/, bngsize alen);
/* Return 1 if {a,alen} is 0, 0 otherwise. */
#define bng_is_zero(a,alen) (bng_num_digits(a,alen) == 0)
/* Return 0 if {a,alen} = {b,blen}
<0 if {a,alen} < {b,blen}
>0 if {a,alen} > {b,blen}. */
extern int bng_compare(bng a/*[alen]*/, bngsize alen,
bng b/*[blen]*/, bngsize blen);
/* Return the number of leading zero bits in digit d. */
extern int bng_leading_zero_bits(bngdigit d);
/**************************************************************************/
/* */
/* OCaml */
/* */
/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
/* */
/* Copyright 2003 Institut National de Recherche en Informatique et */
/* en Automatique. */
/* */
/* All rights reserved. This file is distributed under the terms of */
/* the GNU Lesser General Public License version 2.1, with the */
/* special exception on linking described in the file LICENSE. */
/* */
/**************************************************************************/
/* Code specific to the AMD x86_64 architecture. */
#define BngAdd2(res,carryout,arg1,arg2) \
asm("xorl %1, %1 \n\t" \
"addq %3, %0 \n\t" \
"setc %b1" \
: "=r" (res), "=&q" (carryout) \
: "0" (arg1), "rm" (arg2))
#define BngSub2(res,carryout,arg1,arg2) \
asm("xorl %1, %1 \n\t" \
"subq %3, %0 \n\t" \
"setc %b1" \
: "=r" (res), "=&q" (carryout) \
: "0" (arg1), "rm" (arg2))
#define BngMult(resh,resl,arg1,arg2) \
asm("mulq %3" \
: "=a" (resl), "=d" (resh) \
: "a" (arg1), "r" (arg2))
#define BngDiv(quo,rem,nh,nl,d) \
asm("divq %4" \
: "=a" (quo), "=d" (rem) \
: "a" (nl), "d" (nh), "r" (d))
/* Reimplementation in asm of some of the bng operations. */
static bngcarry bng_amd64_add
(bng a/*[alen]*/, bngsize alen,
bng b/*[blen]*/, bngsize blen,
bngcarry carry)
{
bngdigit tmp;
alen -= blen;
if (blen > 0) {
asm("negb %b3 \n\t"
"1: \n\t"
"movq (%0), %4 \n\t"
"adcq (%1), %4 \n\t"
"movq %4, (%0) \n\t"
"leaq 8(%0), %0 \n\t"
"leaq 8(%1), %1 \n\t"
"decq %2 \n\t"
"jnz 1b \n\t"
"setc %b3"
: "=r" (a), "=r" (b), "=r" (blen), "=q" (carry), "=r" (tmp)
: "0" (a), "1" (b), "2" (blen), "3" (carry));
}
if (carry == 0 || alen == 0) return carry;
do {
if (++(*a) != 0) return 0;
a++;
} while (--alen);
return 1;
}
static bngcarry bng_amd64_sub
(bng a/*[alen]*/, bngsize alen,
bng b/*[blen]*/, bngsize blen,
bngcarry carry)
{
bngdigit tmp;
alen -= blen;
if (blen > 0) {
asm("negb %b3 \n\t"
"1: \n\t"
"movq (%0), %4 \n\t"