Edit

kc3-lang/libtommath/tommath.h

Branch :

  • Show log

    Commit

  • Author : Tom St Denis
    Date : 2003-02-28 16:08:34
    Hash : 57354e11
    Message : added libtommath-0.12

  • tommath.h
  • /* LibTomMath, multiple-precision integer library -- Tom St Denis
     *
     * LibTomMath is library that provides for multiple-precision 
     * integer arithmetic as well as number theoretic functionality.
     * 
     * The library is designed directly after the MPI library by
     * Michael Fromberger but has been written from scratch with 
     * additional optimizations in place.  
     *
     * The library is free for all purposes without any express
     * guarantee it works.
     *
     * Tom St Denis, tomstdenis@iahu.ca, http://libtommath.iahu.ca
     */
    #ifndef BN_H_
    #define BN_H_
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <limits.h>
    
    #undef MIN
    #define MIN(x,y) ((x)<(y)?(x):(y))
    #undef MAX
    #define MAX(x,y) ((x)>(y)?(x):(y))
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    
    /* some default configurations.  
     *
     * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits 
     * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits 
     *
     * At the very least a mp_digit must be able to hold 7 bits 
     * [any size beyond that is ok provided it overflow the data type]
     */
    #ifdef MP_8BIT
       typedef unsigned char      mp_digit;
       typedef unsigned short     mp_word;
    #elif defined(MP_16BIT)
       typedef unsigned short     mp_digit;
       typedef unsigned long      mp_word;
    #else
    #ifndef CRYPT
       #ifdef _MSC_VER
          typedef unsigned __int64   ulong64;
          typedef signed __int64     long64;
       #else
          typedef unsigned long long ulong64;
          typedef signed long long   long64;
       #endif   
    #endif   
    
       /* default case */
       typedef unsigned long      mp_digit;
       typedef ulong64            mp_word;
      
       #define DIGIT_BIT          28
    #endif  
    
    #ifndef DIGIT_BIT
       #define DIGIT_BIT     ((CHAR_BIT * sizeof(mp_digit) - 1))  /* bits per digit */
    #endif
    
    #define MP_DIGIT_BIT     DIGIT_BIT
    #define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
    #define MP_DIGIT_MAX     MP_MASK   
    
    /* equalities */
    #define MP_LT        -1   /* less than */
    #define MP_EQ         0   /* equal to */
    #define MP_GT         1   /* greater than */
    
    #define MP_ZPOS       0   /* positive integer */
    #define MP_NEG        1   /* negative */
    
    #define MP_OKAY       0   /* ok result */
    #define MP_MEM        -2  /* out of mem */
    #define MP_VAL        -3  /* invalid input */
    #define MP_RANGE      MP_VAL
    
    typedef int           mp_err;
    
    /* you'll have to tune these... */
    extern int KARATSUBA_MUL_CUTOFF,
               KARATSUBA_SQR_CUTOFF,
               MONTGOMERY_EXPT_CUTOFF;
    
    #define MP_PREC                 64      /* default digits of precision */
    
    typedef struct  {
        int used, alloc, sign;
        mp_digit *dp;
    } mp_int;
    
    #define USED(m)    ((m)->used)
    #define DIGIT(m,k) ((m)->dp[k])
    #define SIGN(m)    ((m)->sign)
    
    /* ---> init and deinit bignum functions <--- */
    
    /* init a bignum */
    int mp_init(mp_int *a);
    
    /* free a bignum */
    void mp_clear(mp_int *a);
    
    /* exchange two ints */
    void mp_exch(mp_int *a, mp_int *b);
    
    /* shrink ram required for a bignum */
    int mp_shrink(mp_int *a);
    
    /* ---> Basic Manipulations <--- */
    
    #define mp_iszero(a) (((a)->used == 0) ? 1 : 0)
    #define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? 1 : 0)
    #define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? 1 : 0)
    
    /* set to zero */
    void mp_zero(mp_int *a);
    
    /* set to a digit */
    void mp_set(mp_int *a, mp_digit b);
    
    /* set a 32-bit const */
    int mp_set_int(mp_int *a, unsigned long b);
    
    /* grow an int to a given size */
    int mp_grow(mp_int *a, int size);
    
    /* init to a given number of digits */
    int mp_init_size(mp_int *a, int size);
    
    /* copy, b = a */
    int mp_copy(mp_int *a, mp_int *b);
    
    /* inits and copies, a = b */
    int mp_init_copy(mp_int *a, mp_int *b);
    
    /* trim unused digits */
    void mp_clamp(mp_int *a);
    
    /* ---> digit manipulation <--- */
    
    /* right shift by "b" digits */
    void mp_rshd(mp_int *a, int b);
    
    /* left shift by "b" digits */
    int mp_lshd(mp_int *a, int b);
    
    /* c = a / 2^b */
    int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
    
    /* b = a/2 */
    int mp_div_2(mp_int *a, mp_int *b);
    
    /* c = a * 2^b */
    int mp_mul_2d(mp_int *a, int b, mp_int *c);
    
    /* b = a*2 */
    int mp_mul_2(mp_int *a, mp_int *b);
    
    /* c = a mod 2^d */
    int mp_mod_2d(mp_int *a, int b, mp_int *c);
    
    /* computes a = 2^b */
    int mp_2expt(mp_int *a, int b);
    
    /* makes a pseudo-random int of a given size */
    int mp_rand(mp_int *a, int digits);
    
    /* ---> binary operations <--- */
    /* c = a XOR b  */
    int mp_xor(mp_int *a, mp_int *b, mp_int *c);
    
    /* c = a OR b */
    int mp_or(mp_int *a, mp_int *b, mp_int *c);
    
    /* c = a AND b */
    int mp_and(mp_int *a, mp_int *b, mp_int *c);
    
    /* ---> Basic arithmetic <--- */
    
    /* b = -a */
    int mp_neg(mp_int *a, mp_int *b);
    
    /* b = |a| */
    int mp_abs(mp_int *a, mp_int *b);
    
    /* compare a to b */
    int mp_cmp(mp_int *a, mp_int *b);
    
    /* compare |a| to |b| */
    int mp_cmp_mag(mp_int *a, mp_int *b);
    
    /* c = a + b */
    int mp_add(mp_int *a, mp_int *b, mp_int *c);
    
    
    /* c = a - b */
    int mp_sub(mp_int *a, mp_int *b, mp_int *c);
    
    /* c = a * b */
    int mp_mul(mp_int *a, mp_int *b, mp_int *c);
    
    /* b = a^2 */
    int mp_sqr(mp_int *a, mp_int *b);
    
    /* a/b => cb + d == a */
    int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
    
    /* c = a mod b, 0 <= c < b  */
    int mp_mod(mp_int *a, mp_int *b, mp_int *c);
    
    /* ---> single digit functions <--- */
    
    /* compare against a single digit */
    int mp_cmp_d(mp_int *a, mp_digit b);
    
    /* c = a + b */
    int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
    
    /* c = a - b */
    int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
    
    /* c = a * b */
    int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
    
    /* a/b => cb + d == a */
    int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
    
    /* c = a^b */
    int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
    
    /* c = a mod b, 0 <= c < b  */
    int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
    
    /* ---> number theory <--- */
    
    /* d = a + b (mod c) */
    int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
    
    /* d = a - b (mod c) */
    int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
    
    /* d = a * b (mod c) */
    int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
    
    /* c = a * a (mod b) */
    int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
    
    /* c = 1/a (mod b) */
    int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
    
    /* c = (a, b) */
    int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
    
    /* c = [a, b] or (a*b)/(a, b) */
    int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
    
    /* finds one of the b'th root of a, such that |c|^b <= |a| 
     *
     * returns error if a < 0 and b is even
     */
    int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
    
    /* shortcut for square root */
    #define mp_sqrt(a, b) mp_n_root(a, 2, b)
    
    /* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
    int mp_jacobi(mp_int *a, mp_int *n, int *c);
    
    /* used to setup the Barrett reduction for a given modulus b */
    int mp_reduce_setup(mp_int *a, mp_int *b);
    
    /* Barrett Reduction, computes a (mod b) with a precomputed value c
     *
     * Assumes that 0 < a <= b^2, note if 0 > a > -(b^2) then you can merely
     * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
     */
    int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
    
    /* setups the montgomery reduction */
    int mp_montgomery_setup(mp_int *a, mp_digit *mp);
    
    /* computes xR^-1 == x (mod N) via Montgomery Reduction */
    int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
    
    /* d = a^b (mod c) */
    int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
    
    /* ---> radix conversion <--- */
    int mp_count_bits(mp_int *a);
    
    int mp_unsigned_bin_size(mp_int *a);
    int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
    int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
    
    int mp_signed_bin_size(mp_int *a);
    int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
    int mp_to_signed_bin(mp_int *a, unsigned char *b);
    
    int mp_read_radix(mp_int *a, char *str, int radix);
    int mp_toradix(mp_int *a, char *str, int radix);
    int mp_radix_size(mp_int *a, int radix);
    
    #define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
    #define mp_raw_size(mp)           mp_signed_bin_size(mp)
    #define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
    #define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
    #define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
    #define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))
    
    #define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
    #define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
    #define mp_todecimal(M, S) mp_toradix((M), (S), 10)
    #define mp_tohex(M, S)     mp_toradix((M), (S), 16)
    
    /* lowlevel functions, do not call! */
    int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
    int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
    #define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
    int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
    int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
    int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
    int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
    int fast_s_mp_sqr(mp_int *a, mp_int *b);
    int s_mp_sqr(mp_int *a, mp_int *b);
    int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
    int mp_karatsuba_sqr(mp_int *a, mp_int *b);
    int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
    int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
    int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y);
    void bn_reverse(unsigned char *s, int len);
    
    #ifdef __cplusplus
       }
    #endif
    
    
    #endif