//
// LiDIA - a library for computational number theory
//   Copyright (c) 1996 by the LiDIA Group
//
// File        : udigit.h
// Author      : Thomas Pfahler (TPf)
//               Volker Mueller (VM)
// Last change : TPf, Apr 10 1995, initial version
//               VM,  Sep  3 1996, libI version
//		 MM,  Oct  1 1996, interface version
//


#ifndef LIDIA_UDIGIT_H
#define LIDIA_UDIGIT_H

#ifndef HEADBANGER

//
// Exactly the following functions has to be
// defined and implemented in 
// udigit_def.h and udigit_def.c:
//

// udigit max_udigit()
        //RV = maximal udigit
        //RADIX = max_udigit()+1

// unsigned int bits_per_udigit()
         // RV = number of bits a udigit consists of

// udigit max_udigit_modulus()
        //RV = maximal udigit which can be used in
        //     the _mod - functions below

// unsigned int bits_per_udigit_modulus()
         // RV = number of bits a udigit modulus consists of

// udigit udigit_add(udigit & sum, udigit a, udigit b, udigit carry = 0)
        //RV * RADIX + sum = a + b + carry

// udigit udigit_subtract(udigit & sum, udigit a, udigit b, udigit carry = 0)
        //-RV * RADIX + diff = a - b - carry

// udigit udigit_multiply(udigit & prod, udigit a, udigit b)
        //RV * RADIX + prod = a * b

// udigit udigit_divide(udigit & quot, udigit a1, udigit a0, udigit b)
        //a1 * RADIX + a0 = quot * b + RV
	//a1 must be less than b


//
// The input to the modular functions must 
// be reduced modulo p.
//

// udigit udigit_add_mod(udigit a, udigit b, udigit p)
	//RV = (a + b) mod p
	//assumes a,b < p, p > 1

// udigit udigit_subtract_mod(udigit a, udigit b, udigit p)
	//RV = (a - b) mod p
	//assumes a,b < p, p > 1

// udigit udigit_multiply_mod(udigit a, udigit b, udigit p)
        // RV = (a * b) mod p 
        // assumes a,b < p, p > 1


#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:lidia.h>
#include <LiDIA:udigit_def.h>
#else
#include <LiDIA/lidia.h>
#include <LiDIA/udigit_def.h>
#endif




//
// The following functions are implemented in udigit.c
// and need not be changed for use with a different kernel:
//

udigit udigit_power(udigit a, unsigned int e);
       // compute a^e, without taking care of carrys

udigit udigit_sqrt_mod(udigit a, udigit p); 
       // p is assumed to be prime

udigit udigit_power_mod(udigit a, udigit e, udigit p);  
       // compute (a^e) mod p

bool udigit_is_prime(udigit n, unsigned int trials = 9);
       // returns true if n passes the Miller-Rabin test,
       // otherwise it returns false

int udigit_jacobi(udigit a, udigit b);
       // returns 1 if a is a square mod b, -1 if not 
       // and zero if b divides a.

udigit udigit_next_prime(udigit a);
       // returns next prime which is larger than a.
       // UEBERLAUF ?????

udigit udigit_previous_prime(udigit a);
       // returns the next prime smaller than a.

udigit udigit_gcd(udigit a, udigit b);
       // binary gcd algorithm

udigit udigit_xgcd(udigit &u, udigit &v, udigit a, udigit b); 
       // extended binary gcd algorithm, we take care of overflows
       // RV = u * a - v * b, |RV| = gcd(a,b)

udigit udigit_negate_mod(udigit a, udigit p);
        // RV = -a mod p
        // assumes a < p, p > 1

udigit udigit_invert_mod(udigit a, udigit p);
       // invert a mod p, binary gcd algorithm, 
       // only coefficient for a is computed 

inline
udigit udigit_divide_mod(udigit a, udigit b, udigit p)
{ udigit binv = udigit_invert_mod(b, p);
  return udigit_multiply_mod(a, binv, p);}

#endif
#endif



