/****************************************************************************
**
*W  gmpints.h                   GAP source                     John McDermott
**                                                           
**                                                           
**
**
*Y  Copyright (C)  1996,  Lehrstuhl D für Mathematik,  RWTH Aachen,  Germany
*Y  (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
*Y  Copyright (C) 2002 The GAP Group
**
**  This file declares the functions handling gmp integers.
*/

#ifndef GAP_GMPINTS_H
#define GAP_GMPINTS_H

#ifdef USE_GMP

// GMP must be included outside of 'extern C'
#ifdef GAP_IN_EXTERN_C
}
#endif
#include <gmp.h>
#ifdef GAP_IN_EXTERN_C
extern "C" {
#endif

/****************************************************************************
**
*T  TypLimb . . . . . . . . . . . . . . . . . . . . . . .  type of a GMP Limb
**
**  
**  
*/
typedef mp_limb_t      TypLimb;
typedef mp_size_t   TypGMPSize;

#ifdef SYS_IS_64_BIT
typedef UInt4           TypDigit;
#define NR_HEX_DIGITS         8
#define SaveLimb SaveUInt8
#define LoadLimb LoadUInt8
#define INTEGER_UNIT_SIZE 8
#define INTEGER_ALLOCATION_SIZE 8
#else
typedef UInt2           TypDigit;
#define NR_HEX_DIGITS         4
#define SaveLimb SaveUInt4
#define LoadLimb LoadUInt4
#define INTEGER_UNIT_SIZE 4
#define INTEGER_ALLOCATION_SIZE 4
#endif

#if GMP_LIMB_BITS != NR_HEX_DIGITS * 8
#error Aborting compile: unexpected GMP limb size
#endif
#if GMP_NAIL_BITS != 0
#error Aborting compile: GAP does not support non-zero GMP nail size
#endif
#ifndef __GNU_MP_RELEASE
 #if __GMP_MP_RELEASE < 50002
 #error Aborting compile: GAP requires GMP 5.0.2 or newer
 #endif
#endif

#define NR_DIGIT_BITS      (8 * sizeof(TypDigit))
#define INTBASE            (1L << NR_DIGIT_BITS)
#define NR_SMALL_INT_BITS  (2*NR_DIGIT_BITS - 4)

#define ADDR_INT(obj)          (  (TypLimb *)ADDR_OBJ(obj)                  )
#define SIZE_INT(obj)          (  (TypGMPSize)SIZE_OBJ(obj)/sizeof(TypLimb) )
/* SIZE_INT gives a result in limbs                                        */


/**************************************************************************
** The following two functions convert a C Int or UInt respectively into
** a GAP integer, either an immediate, small integer if possible or 
** otherwise a new GAP bag with TNUM T_INTPOS or T_INTNEG.
**
*F ObjInt_Int(Int i)
*F ObjInt_UInt(UInt i)
**
****************************************************************************/

Obj ObjInt_Int(Int i);
Obj ObjInt_UInt(UInt i);

/****************************************************************************
**
*/
extern  Obj             GMP_REDUCE ( 
                               Obj                 gmp );
extern  Obj             GMP_NORMALIZE ( 
                               Obj                 gmp );


/****************************************************************************
**
*F  PrintInt( <int> ) . . . . . . . . . . . . . . . print an integer constant
**
**  'PrintInt'  prints  the integer  <int>   in the  usual  decimal notation.
**  'PrintInt' handles objects of type 'T_INT', 'T_INTPOS' and 'T_INTNEG'.
*/
extern  void            PrintInt (
            Obj                 op );


/****************************************************************************
**
*F  EqInt( <gmpL>, <gmpR> ) . . . . . test if two integers are equal
**
**  'EqInt' returns 1  if  the two GMP integer arguments <gmpL> and  
**  <gmpR> are equal and 0 otherwise.
*/
extern  Int             EqInt ( 
                               Obj                 opL,
                               Obj                 opR );


/****************************************************************************
**
*F  LtInt( <gmpL>, <gmpR> )  test if an integer is less than another
**
**  'LtInt' returns 1 if the integer <gmpL> is strictly less than the 
**  integer <gmpR> and 0 otherwise.
*/
extern  Int             LtInt (
                               Obj                 opL,
                               Obj                 opR );


/****************************************************************************
**
*F  SumInt( <gmpL>, <gmpR> )  . . . . . . . . .  sum of two integers
**
**  'SumInt' returns the sum of the two integer arguments <gmpL> and
**  <gmpR>.
**
*/
extern  Obj             SumInt (
                                Obj                 opL,
                                Obj                 opR );

/****************************************************************************
**
*F  SumOrDiffInt( <gmpL>, <gmpR>, <sign> )  . . . . . . . sum of two integers
**
**  'SumOrDiffInt' returns the sum or difference of the two GMP arguments
**  <gmpL> and <gmpR>, depending whether sign is +1 or -1.
**
*/
extern  Obj             SumOrDiffInt (
                                Obj                 opL,
                                Obj                 opR,
                                Int                 sign );


/****************************************************************************
**
*F  DiffInt( <gmpL>, <gmpR> ) . . . . difference of two GMP integers
**
**  'DiffInt' returns the difference of the two integer arguments <gmpL>
**  and <gmpR>.
**
*/
extern  Obj             DiffInt (
                                 Obj                 opL,
                                 Obj                 opR );

/****************************************************************************
**
*F  ProdInt( <gmpL>, <gmpR> ) . . . . .  product of two GMP integers
**
**  'ProdInt' returns the product of the two integer arguments <gmpL>
**  and <gmpR>.
**
*/
extern  Obj             ProdInt (
                                 Obj                 opL,
                                 Obj                 opR );


/****************************************************************************
**
*F  ModInt( <gmpL>, <gmpR> ) representant of res cl of a GMP integer
**
**  'ModInt' returns the smallest positive representant of the residue
**  class of the  integer  <gmpL>  modulo  the  integer  <gmpR>.
**
*/
extern  Obj             ModInt (
                                Obj                 opL,
                                Obj                 opR );


/****************************************************************************
**
*F  PowInt( <gmpL>, <gmpR> )  . . . . . . . . power of a GMP integer
**
**  'PowInt' returns the <gmpR>-th (a GMP int) power of the GMP integer
**  <gmpL>.
**
*/
extern  Obj             PowInt (
                                Obj                 opL,
                                Obj                 opR );


/****************************************************************************
**
*F  QuoInt( <gmpL>, <gmpR> )  . . . . . quotient of two GMP integers
**
**  'QuoInt' returns the integer part of the two integers <gmpL> and
**  <gmpR>.
**
*/
extern  Obj             QuoInt (
                                Obj                 opL,
                                Obj                 opR );


/****************************************************************************
**
*F  RemInt( <gmpL>, <gmpR> )  . . . .  remainder of two GMP integers
**
**  'RemInt' returns the remainder of the quotient of the GMP ints
**  <gmpL> and <gmpR>.
**
*/
extern  Obj             RemInt (
                                Obj                 opL,
                                Obj                 opR );


/****************************************************************************
**
*F  GcdInt( <gmpL>, <gmpR> )  . . . . . . .  gcd of two GMP integers
**
**  'GcdInt' returns the gcd of the two integers <gmpL> and <gmpR>.
*/
extern  Obj             GcdInt (
                                Obj                 opL,
                                Obj                 opR );


extern Obj FuncLog2Int( Obj self, Obj intnum);

extern Obj AInvInt ( Obj gmp );

/****************************************************************************
**
*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *
*/


/****************************************************************************
**
*F  InitInfoInt() . . . . . . . . . . . . . . . .  table of init functions
*/
StructInitInfo * InitInfoInt ( void );

#endif // USE_GMP

#endif // GAP_GMPINTS_H

/****************************************************************************
**
*E  gmpints.h . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
*/
