Blame isl-0.16.1/imath/imath.h

Packit fb9d21
/*
Packit fb9d21
  Name:     imath.h
Packit fb9d21
  Purpose:  Arbitrary precision integer arithmetic routines.
Packit fb9d21
  Author:   M. J. Fromberger <http://spinning-yarns.org/michael/>
Packit fb9d21
Packit fb9d21
  Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
Packit fb9d21
Packit fb9d21
  Permission is hereby granted, free of charge, to any person obtaining a copy
Packit fb9d21
  of this software and associated documentation files (the "Software"), to deal
Packit fb9d21
  in the Software without restriction, including without limitation the rights
Packit fb9d21
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Packit fb9d21
  copies of the Software, and to permit persons to whom the Software is
Packit fb9d21
  furnished to do so, subject to the following conditions:
Packit fb9d21
Packit fb9d21
  The above copyright notice and this permission notice shall be included in
Packit fb9d21
  all copies or substantial portions of the Software.
Packit fb9d21
Packit fb9d21
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit fb9d21
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit fb9d21
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
Packit fb9d21
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit fb9d21
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Packit fb9d21
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit fb9d21
  SOFTWARE.
Packit fb9d21
 */
Packit fb9d21
Packit fb9d21
#ifndef IMATH_H_
Packit fb9d21
#define IMATH_H_
Packit fb9d21
Packit fb9d21
#include <stdint.h>
Packit fb9d21
#include <limits.h>
Packit fb9d21
Packit fb9d21
#ifdef __cplusplus
Packit fb9d21
extern "C" {
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
typedef unsigned char      mp_sign;
Packit fb9d21
typedef unsigned int       mp_size;
Packit fb9d21
typedef int                mp_result;
Packit fb9d21
typedef long               mp_small;  /* must be a signed type */
Packit fb9d21
typedef unsigned long      mp_usmall; /* must be an unsigned type */
Packit fb9d21
Packit fb9d21
/* Force building with uint64_t so that the library builds consistently
Packit fb9d21
 * whether we build from the makefile or by embedding imath in another project.
Packit fb9d21
 */
Packit fb9d21
#undef  USE_64BIT_WORDS
Packit fb9d21
#define USE_64BIT_WORDS
Packit fb9d21
#ifdef  USE_64BIT_WORDS
Packit fb9d21
typedef uint32_t           mp_digit;
Packit fb9d21
typedef uint64_t           mp_word;
Packit fb9d21
#else
Packit fb9d21
typedef uint16_t           mp_digit;
Packit fb9d21
typedef uint32_t           mp_word;
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
typedef struct mpz {
Packit fb9d21
  mp_digit    single;
Packit fb9d21
  mp_digit   *digits;
Packit fb9d21
  mp_size     alloc;
Packit fb9d21
  mp_size     used;
Packit fb9d21
  mp_sign     sign;
Packit fb9d21
} mpz_t, *mp_int;
Packit fb9d21
Packit fb9d21
#define MP_DIGITS(Z) ((Z)->digits)
Packit fb9d21
#define MP_ALLOC(Z)  ((Z)->alloc)
Packit fb9d21
#define MP_USED(Z)   ((Z)->used)
Packit fb9d21
#define MP_SIGN(Z)   ((Z)->sign)
Packit fb9d21
Packit fb9d21
extern const mp_result MP_OK;
Packit fb9d21
extern const mp_result MP_FALSE;
Packit fb9d21
extern const mp_result MP_TRUE;
Packit fb9d21
extern const mp_result MP_MEMORY;
Packit fb9d21
extern const mp_result MP_RANGE;
Packit fb9d21
extern const mp_result MP_UNDEF;
Packit fb9d21
extern const mp_result MP_TRUNC;
Packit fb9d21
extern const mp_result MP_BADARG;
Packit fb9d21
extern const mp_result MP_MINERR;
Packit fb9d21
Packit fb9d21
#define MP_DIGIT_BIT    (sizeof(mp_digit) * CHAR_BIT)
Packit fb9d21
#define MP_WORD_BIT     (sizeof(mp_word) * CHAR_BIT)
Packit fb9d21
#define MP_SMALL_MIN    LONG_MIN
Packit fb9d21
#define MP_SMALL_MAX    LONG_MAX
Packit fb9d21
#define MP_USMALL_MIN   ULONG_MIN
Packit fb9d21
#define MP_USMALL_MAX   ULONG_MAX
Packit fb9d21
Packit fb9d21
#ifdef USE_64BIT_WORDS
Packit fb9d21
#  define MP_DIGIT_MAX   (UINT32_MAX * UINT64_C(1))
Packit fb9d21
#  define MP_WORD_MAX    (UINT64_MAX)
Packit fb9d21
#else
Packit fb9d21
#  define MP_DIGIT_MAX   (UINT16_MAX * 1UL)
Packit fb9d21
#  define MP_WORD_MAX    (UINT32_MAX * 1UL)
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
#define MP_MIN_RADIX    2
Packit fb9d21
#define MP_MAX_RADIX    36
Packit fb9d21
Packit fb9d21
/* Values with fewer than this many significant digits use the standard
Packit fb9d21
   multiplication algorithm; otherwise, a recursive algorithm is used.  
Packit fb9d21
   Choose a value to suit your platform.
Packit fb9d21
 */
Packit fb9d21
#define MP_MULT_THRESH  22
Packit fb9d21
Packit fb9d21
#define MP_DEFAULT_PREC 8   /* default memory allocation, in digits */
Packit fb9d21
Packit fb9d21
extern const mp_sign   MP_NEG;
Packit fb9d21
extern const mp_sign   MP_ZPOS;
Packit fb9d21
Packit fb9d21
#define mp_int_is_odd(Z)  ((Z)->digits[0] & 1)
Packit fb9d21
#define mp_int_is_even(Z) !((Z)->digits[0] & 1)
Packit fb9d21
Packit fb9d21
mp_result mp_int_init(mp_int z);
Packit fb9d21
mp_int    mp_int_alloc(void);
Packit fb9d21
mp_result mp_int_init_size(mp_int z, mp_size prec);
Packit fb9d21
mp_result mp_int_init_copy(mp_int z, mp_int old);
Packit fb9d21
mp_result mp_int_init_value(mp_int z, mp_small value);
Packit fb9d21
mp_result mp_int_init_uvalue(mp_int z, mp_usmall uvalue);
Packit fb9d21
mp_result mp_int_set_value(mp_int z, mp_small value);
Packit fb9d21
mp_result mp_int_set_uvalue(mp_int z, mp_usmall uvalue);
Packit fb9d21
void      mp_int_clear(mp_int z);
Packit fb9d21
void      mp_int_free(mp_int z);
Packit fb9d21
Packit fb9d21
mp_result mp_int_copy(mp_int a, mp_int c);           /* c = a     */
Packit fb9d21
void      mp_int_swap(mp_int a, mp_int c);           /* swap a, c */
Packit fb9d21
void      mp_int_zero(mp_int z);                     /* z = 0     */
Packit fb9d21
mp_result mp_int_abs(mp_int a, mp_int c);            /* c = |a|   */
Packit fb9d21
mp_result mp_int_neg(mp_int a, mp_int c);            /* c = -a    */
Packit fb9d21
mp_result mp_int_add(mp_int a, mp_int b, mp_int c);  /* c = a + b */
Packit fb9d21
mp_result mp_int_add_value(mp_int a, mp_small value, mp_int c);
Packit fb9d21
mp_result mp_int_sub(mp_int a, mp_int b, mp_int c);  /* c = a - b */
Packit fb9d21
mp_result mp_int_sub_value(mp_int a, mp_small value, mp_int c);
Packit fb9d21
mp_result mp_int_mul(mp_int a, mp_int b, mp_int c);  /* c = a * b */
Packit fb9d21
mp_result mp_int_mul_value(mp_int a, mp_small value, mp_int c);
Packit fb9d21
mp_result mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c);
Packit fb9d21
mp_result mp_int_sqr(mp_int a, mp_int c);            /* c = a * a */
Packit fb9d21
mp_result mp_int_div(mp_int a, mp_int b,             /* q = a / b */
Packit fb9d21
		     mp_int q, mp_int r);            /* r = a % b */
Packit fb9d21
mp_result mp_int_div_value(mp_int a, mp_small value, /* q = a / value */
Packit fb9d21
			   mp_int q, mp_small *r);   /* r = a % value */
Packit fb9d21
mp_result mp_int_div_pow2(mp_int a, mp_small p2,     /* q = a / 2^p2  */
Packit fb9d21
			  mp_int q, mp_int r);       /* r = q % 2^p2  */
Packit fb9d21
mp_result mp_int_mod(mp_int a, mp_int m, mp_int c);  /* c = a % m */
Packit fb9d21
#define   mp_int_mod_value(A, V, R) mp_int_div_value((A), (V), 0, (R))
Packit fb9d21
mp_result mp_int_expt(mp_int a, mp_small b, mp_int c);         /* c = a^b */
Packit fb9d21
mp_result mp_int_expt_value(mp_small a, mp_small b, mp_int c); /* c = a^b */
Packit fb9d21
mp_result mp_int_expt_full(mp_int a, mp_int b, mp_int c);      /* c = a^b */
Packit fb9d21
Packit fb9d21
int       mp_int_compare(mp_int a, mp_int b);          /* a <=> b     */
Packit fb9d21
int       mp_int_compare_unsigned(mp_int a, mp_int b); /* |a| <=> |b| */
Packit fb9d21
int       mp_int_compare_zero(mp_int z);                 /* a <=> 0  */
Packit fb9d21
int       mp_int_compare_value(mp_int z, mp_small v);    /* a <=> v  */
Packit fb9d21
int       mp_int_compare_uvalue(mp_int z, mp_usmall uv); /* a <=> uv */
Packit fb9d21
Packit fb9d21
/* Returns true if v|a, false otherwise (including errors) */
Packit fb9d21
int       mp_int_divisible_value(mp_int a, mp_small v);
Packit fb9d21
Packit fb9d21
/* Returns k >= 0 such that z = 2^k, if one exists; otherwise < 0 */
Packit fb9d21
int       mp_int_is_pow2(mp_int z);
Packit fb9d21
Packit fb9d21
mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m,
Packit fb9d21
			 mp_int c);                    /* c = a^b (mod m) */
Packit fb9d21
mp_result mp_int_exptmod_evalue(mp_int a, mp_small value,
Packit fb9d21
				mp_int m, mp_int c);   /* c = a^v (mod m) */
Packit fb9d21
mp_result mp_int_exptmod_bvalue(mp_small value, mp_int b,
Packit fb9d21
				mp_int m, mp_int c);   /* c = v^b (mod m) */
Packit fb9d21
mp_result mp_int_exptmod_known(mp_int a, mp_int b,
Packit fb9d21
			       mp_int m, mp_int mu,
Packit fb9d21
			       mp_int c);              /* c = a^b (mod m) */
Packit fb9d21
mp_result mp_int_redux_const(mp_int m, mp_int c);
Packit fb9d21
Packit fb9d21
mp_result mp_int_invmod(mp_int a, mp_int m, mp_int c); /* c = 1/a (mod m) */
Packit fb9d21
Packit fb9d21
mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c);    /* c = gcd(a, b)   */
Packit fb9d21
Packit fb9d21
mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c,    /* c = gcd(a, b)   */
Packit fb9d21
		      mp_int x, mp_int y);             /* c = ax + by     */
Packit fb9d21
Packit fb9d21
mp_result mp_int_lcm(mp_int a, mp_int b, mp_int c);    /* c = lcm(a, b)   */
Packit fb9d21
Packit fb9d21
mp_result mp_int_root(mp_int a, mp_small b, mp_int c); /* c = floor(a^{1/b}) */
Packit fb9d21
#define   mp_int_sqrt(a, c) mp_int_root(a, 2, c)       /* c = floor(sqrt(a)) */
Packit fb9d21
Packit fb9d21
/* Convert to a small int, if representable; else MP_RANGE */
Packit fb9d21
mp_result mp_int_to_int(mp_int z, mp_small *out);
Packit fb9d21
mp_result mp_int_to_uint(mp_int z, mp_usmall *out);
Packit fb9d21
Packit fb9d21
/* Convert to nul-terminated string with the specified radix, writing at
Packit fb9d21
   most limit characters including the nul terminator  */
Packit fb9d21
mp_result mp_int_to_string(mp_int z, mp_size radix,
Packit fb9d21
			   char *str, int limit);
Packit fb9d21
Packit fb9d21
/* Return the number of characters required to represent
Packit fb9d21
   z in the given radix.  May over-estimate. */
Packit fb9d21
mp_result mp_int_string_len(mp_int z, mp_size radix);
Packit fb9d21
Packit fb9d21
/* Read zero-terminated string into z */
Packit fb9d21
mp_result mp_int_read_string(mp_int z, mp_size radix, const char *str);
Packit fb9d21
mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str,
Packit fb9d21
			      char **end);
Packit fb9d21
Packit fb9d21
/* Return the number of significant bits in z */
Packit fb9d21
mp_result mp_int_count_bits(mp_int z);
Packit fb9d21
Packit fb9d21
/* Convert z to two's complement binary, writing at most limit bytes */
Packit fb9d21
mp_result mp_int_to_binary(mp_int z, unsigned char *buf, int limit);
Packit fb9d21
Packit fb9d21
/* Read a two's complement binary value into z from the given buffer */
Packit fb9d21
mp_result mp_int_read_binary(mp_int z, unsigned char *buf, int len);
Packit fb9d21
Packit fb9d21
/* Return the number of bytes required to represent z in binary. */
Packit fb9d21
mp_result mp_int_binary_len(mp_int z);
Packit fb9d21
Packit fb9d21
/* Convert z to unsigned binary, writing at most limit bytes */
Packit fb9d21
mp_result mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit);
Packit fb9d21
Packit fb9d21
/* Read an unsigned binary value into z from the given buffer */
Packit fb9d21
mp_result mp_int_read_unsigned(mp_int z, unsigned char *buf, int len);
Packit fb9d21
Packit fb9d21
/* Return the number of bytes required to represent z as unsigned output */
Packit fb9d21
mp_result mp_int_unsigned_len(mp_int z);
Packit fb9d21
Packit fb9d21
/* Return a statically allocated string describing error code res */
Packit fb9d21
const char *mp_error_string(mp_result res);
Packit fb9d21
Packit fb9d21
#if DEBUG
Packit fb9d21
void      s_print(char *tag, mp_int z);
Packit fb9d21
void      s_print_buf(char *tag, mp_digit *buf, mp_size num);
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
#ifdef __cplusplus
Packit fb9d21
}
Packit fb9d21
#endif
Packit fb9d21
#endif /* end IMATH_H_ */