{
Copyright (C) 1998-99 Free Software Foundation, Inc.

Author: Frank Heckenbach <frank@pascal.gnu.de>

Definitions for GNU multiple precision functions. Translation of the
C header (gmp.h) of the GMP library. Only tested with GMP version 2.0.2!

gmp.h is part of the GNU MP Library.
Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.

The GNU MP Library as well as this file is free software; you can
redistribute it and/or modify it under the terms of the GNU Library
General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.

The GNU MP Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
License for more details.

You should have received a copy of the GNU Library General Public License
along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
}

{$if __GPC_RELEASE__ < 19981206}
{$error This unit requires GPC release 19981206 or newer}
{$endif}

unit gmp;

interface

uses GPC;

type
  {$ifdef _SHORT_LIMB}
  mp_limb_t        = Cardinal;
  mp_limb_signed_t = Integer;
  {$elif defined(_LONG_LONG_LIMB)}
  mp_limb_t        = LongCard;
  mp_limb_signed_t = LongInt;
  {$else}
  mp_limb_t        = MedCard;
  mp_limb_signed_t = MedInt;
  {$endif}

  mp_ptr           = ^mp_limb_t;
  mp_size_t        = MedInt;
  mp_exp_t         = MedInt;

  mpz_t = record
    mp_alloc,
    mp_size  : {$ifdef __MP_SMALL__} ShortInt {$else} Integer {$endif};
    mp_d     : mp_ptr
  end;

  mpz_array_ptr = ^mpz_array;
  mpz_array = array [0..MaxInt] of mpz_t;

  mpq_t = record
    mp_num,
    mp_den : mpz_t
  end;

  mpf_t = record
    mp_prec,
    mp_size : Integer;
    mp_exp  : mp_exp_t;
    mp_d    : mp_ptr
  end;

  TAllocFunction    = function (Size : SizeType) : Pointer;
  TReAllocFunction  = function (var Dest : Pointer; OldSize, NewSize : SizeType) : Pointer;
  TDeAllocProcedure = procedure (Src : Pointer; Size : SizeType);

procedure mp_set_memory_functions (AllocFunction : TAllocFunction;
                                   ReAllocFunction : TReAllocFunction;
                                   DeAllocProcedure : TDeAllocProcedure); C;

var
  mp_bits_per_limb : external Integer;

{**************** Integer (i.e. Z) routines.  ****************}

procedure mpz_init             (var Dest : mpz_t); C;
procedure mpz_clear            (var Dest : mpz_t); C;
function  mpz_realloc          (var Dest : mpz_t; NewAlloc : mp_size_t) : Pointer; asmname '_mpz_realloc';
procedure mpz_array_init       (Dest : mpz_array_ptr; ArraySize, FixedNumBits : mp_size_t); C;

procedure mpz_set              (var Dest : mpz_t; const Src : mpz_t); C;
procedure mpz_set_ui           (var Dest : mpz_t; Src : MedCard); C;
procedure mpz_set_si           (var Dest : mpz_t; Src : MedInt); C;
procedure mpz_set_d            (var Dest : mpz_t; Src : Double); C;
procedure mpz_set_q            (var Dest : mpz_t; Src : mpq_t); C;
procedure mpz_set_f            (var Dest : mpz_t; Src : mpf_t); C;
function  mpz_set_str          (var Dest : mpz_t; Src : CString; Base : Integer) : Integer; C;

procedure mpz_init_set         (var Dest : mpz_t; const Src : mpz_t); C;
procedure mpz_init_set_ui      (var Dest : mpz_t; Src : MedCard); C;
procedure mpz_init_set_si      (var Dest : mpz_t; Src : MedInt); C;
procedure mpz_init_set_d       (var Dest : mpz_t; Src : Double); C;
function  mpz_init_set_str     (var Dest : mpz_t; Src : CString; Base : Integer) : Integer; C;

function  mpz_get_ui           (const Src : mpz_t) : MedCard; C;
function  mpz_get_si           (const Src : mpz_t) : MedInt; C;
function  mpz_get_d            (const Src : mpz_t) : Double; C;
{ Pass nil for Dest to let the function allocate memory for it }
function  mpz_get_str          (Dest : CString; Base : Integer; const Src : mpz_t) : CString; C;

procedure mpz_add              (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
procedure mpz_add_ui           (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;
procedure mpz_sub              (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
procedure mpz_sub_ui           (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;
procedure mpz_mul              (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
procedure mpz_mul_ui           (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;
procedure mpz_mul_2exp         (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;
procedure mpz_neg              (var Dest : mpz_t; const Src : mpz_t); C;
procedure mpz_abs              (var Dest : mpz_t; const Src : mpz_t); C;
procedure mpz_fac_ui           (var Dest : mpz_t; Src : MedCard); C;

procedure mpz_tdiv_q           (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
procedure mpz_tdiv_q_ui        (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;
procedure mpz_tdiv_r           (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
procedure mpz_tdiv_r_ui        (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;
procedure mpz_tdiv_qr          (var DestQ, DestR : mpz_t; const Src1, Src2 : mpz_t); C;
procedure mpz_tdiv_qr_ui       (var DestQ, DestR : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;

procedure mpz_fdiv_q           (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
function  mpz_fdiv_q_ui        (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard) : MedCard; C;
procedure mpz_fdiv_r           (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
function  mpz_fdiv_r_ui        (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard) : MedCard; C;
procedure mpz_fdiv_qr          (var DestQ, DestR : mpz_t; const Src1, Src2 : mpz_t); C;
function  mpz_fdiv_qr_ui       (var DestQ, DestR : mpz_t; const Src1 : mpz_t; Src2 : MedCard) : MedCard; C;
function  mpz_fdiv_ui          (const Src1 : mpz_t; Src2 : MedCard) : MedCard; C;

procedure mpz_cdiv_q           (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
function  mpz_cdiv_q_ui        (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard) : MedCard; C;
procedure mpz_cdiv_r           (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
function  mpz_cdiv_r_ui        (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard) : MedCard; C;
procedure mpz_cdiv_qr          (var DestQ, DestR : mpz_t; const Src1,Src2 : mpz_t); C;
function  mpz_cdiv_qr_ui       (var DestQ, DestR : mpz_t; const Src1 : mpz_t; Src2 : MedCard) : MedCard; C;
function  mpz_cdiv_ui          (const Src1 : mpz_t; Src2:MedCard) : MedCard; C;

procedure mpz_mod              (var Dest : mpz_t; const Src1,Src2 : mpz_t); C;
procedure mpz_divexact         (var Dest : mpz_t; const Src1,Src2 : mpz_t); C;

procedure mpz_tdiv_q_2exp      (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;
procedure mpz_tdiv_r_2exp      (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;
procedure mpz_fdiv_q_2exp      (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;
procedure mpz_fdiv_r_2exp      (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard); C;

procedure mpz_powm             (var Dest : mpz_t; const Base, Exp, Modulus : mpz_t); C;
procedure mpz_powm_ui          (var Dest : mpz_t; const Base : mpz_t; Exp : MedCard; const Modulus : mpz_t); C;
procedure mpz_pow_ui           (var Dest : mpz_t; const Base : mpz_t; Exp : MedCard); C;
procedure mpz_ui_pow_ui        (var Dest : mpz_t; Base, Exp : MedCard); C;

procedure mpz_sqrt             (var Dest : mpz_t; const Src : mpz_t); C;
procedure mpz_sqrtrem          (var Dest, DestR : mpz_t; const Src : mpz_t); C;
function  mpz_perfect_square_p (const Src : mpz_t) : Integer; C;

function  mpz_probab_prime_p   (const Src : mpz_t; Repetitions : Integer) : Integer; C;
procedure mpz_gcd              (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
function  mpz_gcd_ui           (var Dest : mpz_t; const Src1 : mpz_t; Src2 : MedCard) : MedCard; C;
procedure mpz_gcdext           (var Dest, DestA, DestB : mpz_t; const SrcA, SrcB : mpz_t); C;
function  mpz_invert           (var Dest : mpz_t; const Src, Modulus : mpz_t) : Integer; C;
function  mpz_jacobi           (const Src1, Src2 : mpz_t) : Integer; C;
function  mpz_legendre         (const Src1, Src2 : mpz_t) : Integer; C;

function  mpz_cmp              (const Src1, Src2 : mpz_t) : Integer; C;
function  mpz_cmp_ui           (const Src1 : mpz_t; Src2 : MedCard) : Integer; C;
function  mpz_cmp_si           (const Src1 : mpz_t; Src2 : MedInt) : Integer; C;
function  mpz_sgn              (const Src : mpz_t) : Integer;

procedure mpz_and              (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
procedure mpz_ior              (var Dest : mpz_t; const Src1, Src2 : mpz_t); C;
procedure mpz_com              (var Dest : mpz_t; const Src : mpz_t); C;
function  mpz_popcount         (const Src : mpz_t) : MedCard; C;
function  mpz_hamdist          (const Src1, Src2 : mpz_t) : MedCard; C;
function  mpz_scan0            (const Src : mpz_t; StartingBit : MedCard) : MedCard; C;
function  mpz_scan1            (const Src : mpz_t; StartingBit : MedCard) : MedCard; C;
procedure mpz_setbit           (var Dest : mpz_t; BitIndex : MedCard); C;
procedure mpz_clrbit           (var Dest : mpz_t; BitIndex : MedCard); C;

function  mpz_out_str          (Dest : CFilePtr; Base : Integer; const Src : mpz_t) : SizeType; C;
function  mpz_inp_str          (var Dest : mpz_t; Src : CFilePtr; Base : Integer) : SizeType; C;
function  mpz_out_raw          (Dest : CFilePtr; const Src : mpz_t) : SizeType ; C;
function  mpz_inp_raw          (var Dest : mpz_t; Src : CFilePtr) : SizeType ; C;

procedure mpz_random           (var Dest : mpz_t; MaxSize : mp_size_t); C;
procedure mpz_random2          (var Dest : mpz_t; MaxSize : mp_size_t); C;
function  mpz_sizeinbase       (const Src : mpz_t; Base : Integer) : SizeType; C;

{**************** Rational (i.e. Q) routines.  ****************}

procedure mpq_canonicalize     (var Dest : mpq_t); C;

procedure mpq_init             (var Dest : mpq_t); C;
procedure mpq_clear            (var Dest : mpq_t); C;
procedure mpq_set              (var Dest : mpq_t; const Src : mpq_t); C;
procedure mpq_set_z            (var Dest : mpq_t; const Src : mpz_t); C;
procedure mpq_set_ui           (var Dest : mpq_t; Nom, Den : MedCard); C;
procedure mpq_set_si           (var Dest : mpq_t; Nom : MedInt; Den : MedCard); C;

procedure mpq_add              (var Dest : mpq_t; const Src1, Src2 : mpq_t); C;
procedure mpq_sub              (var Dest : mpq_t; const Src1, Src2 : mpq_t); C;
procedure mpq_mul              (var Dest : mpq_t; const Src1, Src2 : mpq_t); C;
procedure mpq_div              (var Dest : mpq_t; const Src1, Src2 : mpq_t); C;
procedure mpq_neg              (var Dest : mpq_t; const Src : mpq_t); C;
procedure mpq_inv              (var Dest : mpq_t; const Src : mpq_t); C;

function  mpq_cmp              (const Src1, Src2 : mpq_t) : Integer; C;
function  mpq_cmp_ui           (const Src1 : mpq_t; Nom2, Den2 : MedCard) : Integer; C;
function  mpq_sgn              (const Src : mpq_t) : Integer;
function  mpq_equal            (const Src1, Src2 : mpq_t) : Integer; C;

function  mpq_get_d            (const Src : mpq_t) : Double; C;
procedure mpq_set_num          (var Dest : mpq_t; const Src : mpz_t); C;
procedure mpq_set_den          (var Dest : mpq_t; const Src : mpz_t); C;
procedure mpq_get_num          (var Dest : mpz_t; const Src : mpq_t); C;
procedure mpq_get_den          (var Dest : mpz_t; const Src : mpq_t); C;

{**************** Float (i.e. R) routines.  ****************}

procedure mpf_set_default_prec (Precision : MedCard); C;
procedure mpf_init             (var Dest : mpf_t); C;
procedure mpf_init2            (var Dest : mpf_t; Precision : MedCard); C;
procedure mpf_clear            (var Dest : mpf_t); C;
procedure mpf_set_prec         (var Dest : mpf_t; Precision : MedCard); C;
function  mpf_get_prec         (const Src : mpf_t) : MedCard; C;
procedure mpf_set_prec_raw     (var Dest : mpf_t; Precision : MedCard); C;

procedure mpf_set              (var Dest : mpf_t; const Src : mpf_t); C;
procedure mpf_set_ui           (var Dest : mpf_t; Src : MedCard); C;
procedure mpf_set_si           (var Dest : mpf_t; Src : MedInt); C;
procedure mpf_set_d            (var Dest : mpf_t; Src : Double); C;
procedure mpf_set_z            (var Dest : mpf_t; const Src : mpz_t); C;
procedure mpf_set_q            (var Dest : mpf_t; const Src : mpq_t); C;
function  mpf_set_str          (var Dest : mpf_t; Src : CString; Base : Integer) : Integer; C;

procedure mpf_init_set         (var Dest : mpf_t; const Src : mpf_t); C;
procedure mpf_init_set_ui      (var Dest : mpf_t; Src : MedCard); C;
procedure mpf_init_set_si      (var Dest : mpf_t; Src : MedInt); C;
procedure mpf_init_set_d       (var Dest : mpf_t; Src : Double); C;
function  mpf_init_set_str     (var Dest : mpf_t; Src : CString; Base : Integer) : Integer; C;

function  mpf_get_d            (const Src : mpf_t) : Double; C;
{ Pass nil for Dest to let the function allocate memory for it }
function  mpf_get_str          (Dest : CString; var Exp : mp_exp_t; Base : Integer; NumberOfDigits : SizeType; const Src : mpf_t) : CString; C;

procedure mpf_add              (var Dest : mpf_t; const Src1, Src2 : mpf_t); C;
procedure mpf_add_ui           (var Dest : mpf_t; const Src1 : mpf_t; Src2 : MedCard); C;
procedure mpf_sub              (var Dest : mpf_t; const Src1, Src2 : mpf_t); C;
procedure mpf_ui_sub           (var Dest : mpf_t; Src1 : MedCard; const Src2 : mpf_t); C;
procedure mpf_sub_ui           (var Dest : mpf_t; const Src1 : mpf_t; Src2 : MedCard); C;
procedure mpf_mul              (var Dest : mpf_t; const Src1, Src2 : mpf_t); C;
procedure mpf_mul_ui           (var Dest : mpf_t; const Src1 : mpf_t; Src2 : MedCard); C;
procedure mpf_div              (var Dest : mpf_t; const Src1, Src2 : mpf_t); C;
procedure mpf_ui_div           (var Dest : mpf_t; Src1 : MedCard; const Src2 : mpf_t); C;
procedure mpf_div_ui           (var Dest : mpf_t; const Src1 : mpf_t; Src2 : MedCard); C;
procedure mpf_sqrt             (var Dest : mpf_t; const Src : mpf_t); C;
procedure mpf_sqrt_ui          (var Dest : mpf_t; Src : MedCard); C;
procedure mpf_neg              (var Dest : mpf_t; const Src : mpf_t); C;
procedure mpf_abs              (var Dest : mpf_t; const Src : mpf_t); C;
procedure mpf_mul_2exp         (var Dest : mpf_t; const Src1 : mpf_t; Src2 : MedCard); C;
procedure mpf_div_2exp         (var Dest : mpf_t; const Src1 : mpf_t; Src2 : MedCard); C;

function  mpf_cmp              (const Src1, Src2 : mpf_t) : Integer; C;
function  mpf_cmp_si           (const Src1 : mpf_t; Src2 : MedInt) : Integer;
function  mpf_cmp_ui           (const Src1 : mpf_t; Src2 : MedCard) : Integer;
function  mpf_eq               (const Src1, Src2; NumberOfBits : MedCard) : Integer; C;
procedure mpf_reldiff          (var Dest : mpf_t; const Src1, Src2 : mpf_t); C;
function  mpf_sgn              (const Src : mpf_t)  : Integer;

(*@@ mpf_out_str has a bug in GMP 2.0.2: it writes a spurious #0 before the exponent for negative numbers*)
function  mpf_out_str          (Dest : CFilePtr; Base : Integer; NumberOfDigits : SizeType; const Src : mpf_t) : SizeType; C;
function  mpf_inp_str          (var Dest : mpf_t; Src : CFilePtr; Base : Integer) : SizeType; C;

procedure mpf_random2          (var Dest : mpf_t; MaxSize : mp_size_t; MaxExp : mp_exp_t); C;

implementation

{$L gmp}

{ @@ Should rather be inline and in the interface }
function mpz_sgn (const Src : mpz_t) : Integer;
begin
  if Src.mp_size < 0 then
    mpz_sgn := -1
  else if Src.mp_size > 0 then
    mpz_sgn := 1
  else
    mpz_sgn := 0
end;

function mpq_sgn (const Src : mpq_t) : Integer;
begin
  if Src.mp_num.mp_size < 0 then
    mpq_sgn := -1
  else if Src.mp_num.mp_size > 0 then
    mpq_sgn := 1
  else
    mpq_sgn := 0
end;

function mpf_sgn (const Src : mpf_t)  : Integer;
begin
  if Src.mp_size < 0 then
    mpf_sgn := -1
  else if Src.mp_size > 0 then
    mpf_sgn := 1
  else
    mpf_sgn := 0
end;

(*@@ GMP 2.0.2 has a bug in the following routines, so work around :-( *)

function mpf_cmp_si (const Src1 : mpf_t; Src2 : MedInt) : Integer;
var Temp : mpf_t;
begin
  mpf_init_set_si (Temp, Src2);
  mpf_cmp_si := mpf_cmp (Src1, Temp);
  mpf_clear (Temp)
end;

function mpf_cmp_ui (const Src1 : mpf_t; Src2 : MedCard) : Integer;
var Temp : mpf_t;
begin
  mpf_init_set_ui (Temp, Src2);
  mpf_cmp_ui := mpf_cmp (Src1, Temp);
  mpf_clear (Temp)
end;

end.
