Header And Logo

PostgreSQL
| The world's most advanced open source database.

imath.h

Go to the documentation of this file.
00001 /*
00002   Name:     imath.h
00003   Purpose:  Arbitrary precision integer arithmetic routines.
00004   Author:   M. J. Fromberger <http://spinning-yarns.org/michael/sw/>
00005   Info:     Id: imath.h 21 2006-04-02 18:58:36Z sting
00006 
00007   Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
00008 
00009   Permission is hereby granted, free of charge, to any person
00010   obtaining a copy of this software and associated documentation files
00011   (the "Software"), to deal in the Software without restriction,
00012   including without limitation the rights to use, copy, modify, merge,
00013   publish, distribute, sublicense, and/or sell copies of the Software,
00014   and to permit persons to whom the Software is furnished to do so,
00015   subject to the following conditions:
00016 
00017   The above copyright notice and this permission notice shall be
00018   included in all copies or substantial portions of the Software.
00019 
00020   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00021   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00022   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00023   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
00024   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
00025   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00026   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00027   SOFTWARE.
00028  */
00029 /* contrib/pgcrypto/imath.h */
00030 
00031 #ifndef IMATH_H_
00032 #define IMATH_H_
00033 
00034 /* use always 32bit digits - should some arch use 16bit digits? */
00035 #define USE_LONG_LONG
00036 
00037 #include <limits.h>
00038 
00039 typedef unsigned char mp_sign;
00040 typedef unsigned int mp_size;
00041 typedef int mp_result;
00042 
00043 #ifdef USE_LONG_LONG
00044 typedef uint32 mp_digit;
00045 typedef uint64 mp_word;
00046 
00047 #define MP_DIGIT_MAX       0xFFFFFFFFULL
00048 #define MP_WORD_MAX        0xFFFFFFFFFFFFFFFFULL
00049 #else
00050 typedef uint16 mp_digit;
00051 typedef uint32 mp_word;
00052 
00053 #define MP_DIGIT_MAX       0xFFFFUL
00054 #define MP_WORD_MAX        0xFFFFFFFFUL
00055 #endif
00056 
00057 typedef struct mpz
00058 {
00059     mp_digit   *digits;
00060     mp_size     alloc;
00061     mp_size     used;
00062     mp_sign     sign;
00063 } mpz_t    ,
00064            *mp_int;
00065 
00066 #define MP_DIGITS(Z) ((Z)->digits)
00067 #define MP_ALLOC(Z)  ((Z)->alloc)
00068 #define MP_USED(Z)   ((Z)->used)
00069 #define MP_SIGN(Z)   ((Z)->sign)
00070 
00071 extern const mp_result MP_OK;
00072 extern const mp_result MP_FALSE;
00073 extern const mp_result MP_TRUE;
00074 extern const mp_result MP_MEMORY;
00075 extern const mp_result MP_RANGE;
00076 extern const mp_result MP_UNDEF;
00077 extern const mp_result MP_TRUNC;
00078 extern const mp_result MP_BADARG;
00079 
00080 #define MP_DIGIT_BIT    (sizeof(mp_digit) * CHAR_BIT)
00081 #define MP_WORD_BIT     (sizeof(mp_word) * CHAR_BIT)
00082 
00083 #define MP_MIN_RADIX    2
00084 #define MP_MAX_RADIX    36
00085 
00086 extern const mp_sign MP_NEG;
00087 extern const mp_sign MP_ZPOS;
00088 
00089 #define mp_int_is_odd(Z)  ((Z)->digits[0] & 1)
00090 #define mp_int_is_even(Z) !((Z)->digits[0] & 1)
00091 
00092 mp_size     mp_get_default_precision(void);
00093 void        mp_set_default_precision(mp_size s);
00094 mp_size     mp_get_multiply_threshold(void);
00095 void        mp_set_multiply_threshold(mp_size s);
00096 
00097 mp_result   mp_int_init(mp_int z);
00098 mp_int      mp_int_alloc(void);
00099 mp_result   mp_int_init_size(mp_int z, mp_size prec);
00100 mp_result   mp_int_init_copy(mp_int z, mp_int old);
00101 mp_result   mp_int_init_value(mp_int z, int value);
00102 mp_result   mp_int_set_value(mp_int z, int value);
00103 void        mp_int_clear(mp_int z);
00104 void        mp_int_free(mp_int z);
00105 
00106 mp_result   mp_int_copy(mp_int a, mp_int c);    /* c = a     */
00107 void        mp_int_swap(mp_int a, mp_int c);    /* swap a, c */
00108 void        mp_int_zero(mp_int z);      /* z = 0     */
00109 mp_result   mp_int_abs(mp_int a, mp_int c);     /* c = |a|   */
00110 mp_result   mp_int_neg(mp_int a, mp_int c);     /* c = -a    */
00111 mp_result   mp_int_add(mp_int a, mp_int b, mp_int c);   /* c = a + b */
00112 mp_result   mp_int_add_value(mp_int a, int value, mp_int c);
00113 mp_result   mp_int_sub(mp_int a, mp_int b, mp_int c);   /* c = a - b */
00114 mp_result   mp_int_sub_value(mp_int a, int value, mp_int c);
00115 mp_result   mp_int_mul(mp_int a, mp_int b, mp_int c);   /* c = a * b */
00116 mp_result   mp_int_mul_value(mp_int a, int value, mp_int c);
00117 mp_result   mp_int_mul_pow2(mp_int a, int p2, mp_int c);
00118 mp_result   mp_int_sqr(mp_int a, mp_int c);     /* c = a * a */
00119 
00120 mp_result
00121 mp_int_div(mp_int a, mp_int b,  /* q = a / b */
00122            mp_int q, mp_int r); /* r = a % b */
00123 mp_result
00124 mp_int_div_value(mp_int a, int value,   /* q = a / value */
00125                  mp_int q, int *r);     /* r = a % value */
00126 mp_result
00127 mp_int_div_pow2(mp_int a, int p2,       /* q = a / 2^p2  */
00128                 mp_int q, mp_int r);    /* r = q % 2^p2  */
00129 mp_result   mp_int_mod(mp_int a, mp_int m, mp_int c);   /* c = a % m */
00130 
00131 #define   mp_int_mod_value(A, V, R) mp_int_div_value((A), (V), 0, (R))
00132 mp_result   mp_int_expt(mp_int a, int b, mp_int c);     /* c = a^b   */
00133 mp_result   mp_int_expt_value(int a, int b, mp_int c);  /* c = a^b   */
00134 
00135 int         mp_int_compare(mp_int a, mp_int b); /* a <=> b     */
00136 int         mp_int_compare_unsigned(mp_int a, mp_int b);        /* |a| <=> |b| */
00137 int         mp_int_compare_zero(mp_int z);      /* a <=> 0     */
00138 int         mp_int_compare_value(mp_int z, int value);  /* a <=> v     */
00139 
00140 /* Returns true if v|a, false otherwise (including errors) */
00141 int         mp_int_divisible_value(mp_int a, int v);
00142 
00143 /* Returns k >= 0 such that z = 2^k, if one exists; otherwise < 0 */
00144 int         mp_int_is_pow2(mp_int z);
00145 
00146 mp_result
00147 mp_int_exptmod(mp_int a, mp_int b, mp_int m,
00148                mp_int c);       /* c = a^b (mod m) */
00149 mp_result
00150 mp_int_exptmod_evalue(mp_int a, int value,
00151                       mp_int m, mp_int c);      /* c = a^v (mod m) */
00152 mp_result
00153 mp_int_exptmod_bvalue(int value, mp_int b,
00154                       mp_int m, mp_int c);      /* c = v^b (mod m) */
00155 mp_result
00156 mp_int_exptmod_known(mp_int a, mp_int b,
00157                      mp_int m, mp_int mu,
00158                      mp_int c); /* c = a^b (mod m) */
00159 mp_result   mp_int_redux_const(mp_int m, mp_int c);
00160 
00161 mp_result   mp_int_invmod(mp_int a, mp_int m, mp_int c);        /* c = 1/a (mod m) */
00162 
00163 mp_result   mp_int_gcd(mp_int a, mp_int b, mp_int c);   /* c = gcd(a, b)   */
00164 
00165 mp_result
00166 mp_int_egcd(mp_int a, mp_int b, mp_int c,       /* c = gcd(a, b)   */
00167             mp_int x, mp_int y);    /* c = ax + by     */
00168 
00169 mp_result   mp_int_sqrt(mp_int a, mp_int c);    /* c = floor(sqrt(q)) */
00170 
00171 /* Convert to an int, if representable (returns MP_RANGE if not). */
00172 mp_result   mp_int_to_int(mp_int z, int *out);
00173 
00174 /* Convert to nul-terminated string with the specified radix, writing at
00175    most limit characters including the nul terminator  */
00176 mp_result mp_int_to_string(mp_int z, mp_size radix,
00177                  char *str, int limit);
00178 
00179 /* Return the number of characters required to represent
00180    z in the given radix.  May over-estimate. */
00181 mp_result   mp_int_string_len(mp_int z, mp_size radix);
00182 
00183 /* Read zero-terminated string into z */
00184 mp_result   mp_int_read_string(mp_int z, mp_size radix, const char *str);
00185 mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str,
00186                     char **end);
00187 
00188 /* Return the number of significant bits in z */
00189 mp_result   mp_int_count_bits(mp_int z);
00190 
00191 /* Convert z to two's complement binary, writing at most limit bytes */
00192 mp_result   mp_int_to_binary(mp_int z, unsigned char *buf, int limit);
00193 
00194 /* Read a two's complement binary value into z from the given buffer */
00195 mp_result   mp_int_read_binary(mp_int z, unsigned char *buf, int len);
00196 
00197 /* Return the number of bytes required to represent z in binary. */
00198 mp_result   mp_int_binary_len(mp_int z);
00199 
00200 /* Convert z to unsigned binary, writing at most limit bytes */
00201 mp_result   mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit);
00202 
00203 /* Read an unsigned binary value into z from the given buffer */
00204 mp_result   mp_int_read_unsigned(mp_int z, unsigned char *buf, int len);
00205 
00206 /* Return the number of bytes required to represent z as unsigned output */
00207 mp_result   mp_int_unsigned_len(mp_int z);
00208 
00209 /* Return a statically allocated string describing error code res */
00210 const char *mp_error_string(mp_result res);
00211 
00212 #if 0
00213 void        s_print(char *tag, mp_int z);
00214 void        s_print_buf(char *tag, mp_digit *buf, mp_size num);
00215 #endif
00216 
00217 #endif   /* end IMATH_H_ */