00001 #ifndef MULTIPREC_H
00002 #define MULTIPREC_H
00003
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include <limits.h>
00007 #include <stdarg.h>
00008
00009 #ifndef C99
00010 # if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
00011 # ifndef __CYGWIN__
00012 # define C99
00013 # endif
00014 # endif
00015 #endif
00016
00017 #ifdef C99
00018 # include <stdint.h>
00019 #endif
00020
00025 typedef unsigned digit_t;
00027 #define DIGIT_BIT (sizeof(digit_t)*CHAR_BIT)
00028
00029 #define DIGIT_MAX UINT_MAX
00030 #define DIGIT_HIGHEST_BIT ((digit_t)(1<<(DIGIT_BIT-1)))
00031
00036 typedef unsigned long long double_digit_t;
00038 #define DOUBLE_DIGIT_BIT (sizeof(double_digit_t)*CHAR_BIT)
00039
00040 #define DOUBLE_DIGIT_MAX ULONGLONG_MAX
00041
00043 #define HIGH_DIGIT(dd) ((digit_t)((dd) >> DIGIT_BIT))
00044
00045 #define LOW_DIGIT(dd) ((digit_t)(dd))
00046
00047 #define LOW_DIGIT_TO_HIGH_DIGIT(dd) ((dd) << DIGIT_BIT)
00048
00052 #define MULTIPREC_RADIX (((double_digit_t)DIGIT_MAX)+1)
00053
00054
00056 enum mp_sign_t { positive_sign=0, negative_sign=1 };
00057
00061 struct multiprec
00062 {
00064 enum mp_sign_t sign;
00065
00067 size_t len;
00068
00070 size_t used;
00071
00073 digit_t *digits;
00074 };
00075
00077 typedef struct multiprec *mp_ref_t;
00078
00080 typedef const struct multiprec *mp_cref_t;
00081
00087 #define MULTIPREC_INITIALIZER {positive_sign, 0, 0, NULL}
00088
00089
00093 #ifndef MAX
00094 # define MAX(a,b) ( ((a)>(b))?(a):(b) )
00095 #endif
00096
00097
00104 #define UINT_IS_2POW(u) ( ((u) & ((u)-1)) == 0 )
00105
00106 size_t digit_len_to_str_len(size_t len, digit_t r);
00107
00113 extern void *(*ymp_malloc)(size_t size);
00114 extern void *(*ymp_realloc)(void *pv_mem, size_t size);
00115 extern void (*ymp_free)(void *pv_mem);
00116
00130 #define YMP_ALLOCATE(result, type, count) \
00131 do { \
00132 register type *ptr_tmp = (type*)ymp_malloc(sizeof(type)*(count)); \
00133 if (!ptr_tmp) \
00134 { \
00135 ymp_alloc_error("確保失敗", sizeof(type)*(count)); \
00136 break; \
00137 } \
00138 (result) = ptr_tmp; \
00139 } while(0)
00140
00141
00156 #define YMP_REALLOCATE(ptr, type, count) \
00157 do { \
00158 register type *ptr_tmp = (type*)ymp_realloc((ptr), sizeof(type)*(count)); \
00159 if (!ptr_tmp) \
00160 { \
00161 ymp_alloc_error("再確保失敗", sizeof(type)*(count)); \
00162 break; \
00163 } \
00164 (ptr) = ptr_tmp; \
00165 } while(0)
00166
00167
00174 #define YMP_FREE(ptr) \
00175 ymp_free(ptr)
00176
00177
00178
00192 #define YMP_TEMP_ALLOCATE(result, type, count) \
00193 do { \
00194 register type *ptr_tmp = (type*)alloca(sizeof(type)*(count)); \
00195 if (!ptr_tmp) \
00196 { \
00197 ymp_alloc_error("確保失敗", sizeof(type)*(count)); \
00198 break; \
00199 } \
00200 (result) = ptr_tmp; \
00201 } while(0)
00202
00203
00204
00213 #define YMP_ALLOC_DIGITS(self, new_len) \
00214 do { \
00215 YMP_ALLOCATE((self)->digits, digit_t, new_len); \
00216 (self)->len = new_len; \
00217 } while(0)
00218
00227 #define YMP_REALLOC_DIGITS(self, new_len) \
00228 do { \
00229 YMP_REALLOCATE((self)->digits, digit_t, new_len); \
00230 (self)->len = new_len; \
00231 } while(0)
00232
00239 #define YMP_FREE_DIGITS(self) \
00240 do { \
00241 YMP_FREE((self)->digits); \
00242 (self)->digits = NULL; \
00243 } while(0)
00244
00245
00250 extern void (*ymp_warning)(const char *format, ...);
00251 extern void (*ymp_error)(const char *format, ...);
00252 extern void (*ymp_fatal)(const char *format, ...);
00253 extern void (*ymp_alloc_error)(const char *psz_msg, size_t size);
00261 void ymp_initialize(mp_ref_t self);
00262 void ymp_destroy(mp_ref_t self);
00263 void ymp_reinitialize(mp_ref_t self);
00264
00265 void ymp_initialize_by_mp(mp_ref_t self, mp_cref_t other);
00266 void ymp_reserve_and_initialize_by_digit(mp_ref_t self, size_t len, digit_t d);
00267 void ymp_reserve_and_initialize(mp_ref_t self, size_t len);
00268
00276 #define ymp_alloca_initialize(self, new_len) \
00277 do { \
00278 (self)->sign = positive_sign; \
00279 (self)->len = (self)->used = 0; \
00280 YMP_TEMP_ALLOCATE((self)->digits, digit_t, (new_len)); \
00281 (self)->len = (new_len); \
00282 } while (0)
00283
00284
00285 void ymp_initialize_by_array(mp_ref_t self, size_t len, const digit_t *array);
00286 void ymp_initialize_by_digit(mp_ref_t self, digit_t d);
00287 void ymp_initialize_by_string(mp_ref_t self,
00288 const char *text, char **endptr, unsigned radix);
00289
00290 void ymp_initialize_by_char(mp_ref_t self, signed char val);
00291 void ymp_initialize_by_short(mp_ref_t self, short val);
00292 void ymp_initialize_by_int(mp_ref_t self, int val);
00293 void ymp_initialize_by_long(mp_ref_t self, long val);
00294 void ymp_initialize_by_uchar(mp_ref_t self, unsigned char val);
00295 void ymp_initialize_by_ushort(mp_ref_t self, unsigned short val);
00296 void ymp_initialize_by_uint(mp_ref_t self, unsigned val);
00297 void ymp_initialize_by_ulong(mp_ref_t self, unsigned long val);
00298 #ifdef C99
00299 void ymp_initialize_by_intmax(mp_ref_t self, intmax_t val);
00300 void ymp_initialize_by_uintmax(mp_ref_t self, uintmax_t val);
00301 #endif
00302 void ymp_initialize_by_double(mp_ref_t self, double val);
00303
00304 mp_ref_t ymp_dup(mp_cref_t orig);
00305
00306 void ymp_reserve(mp_ref_t self, size_t len);
00307 void ymp_cut_down(mp_ref_t self);
00308
00318 void ymp_assign_abs(mp_ref_t self, mp_cref_t other);
00319 void ymp_assign_abs_digit(mp_ref_t self, digit_t other);
00320 void ymp_assign_abs_array(mp_ref_t self, size_t len, const digit_t *array);
00323 void ymp_assign(mp_ref_t self, mp_cref_t other);
00324 void ymp_assign_digit(mp_ref_t self, digit_t other);
00325 void ymp_assign_array(mp_ref_t self, size_t len, const digit_t *array);
00326 void ymp_assign_string(mp_ref_t self,
00327 const char *text, char **endptr, unsigned radix);
00328
00329 void ymp_assign_char(mp_ref_t self, signed char val);
00330 void ymp_assign_short(mp_ref_t self, short val);
00331 void ymp_assign_int(mp_ref_t self, int val);
00332 void ymp_assign_long(mp_ref_t self, long val);
00333 void ymp_assign_uchar(mp_ref_t self, unsigned char val);
00334 void ymp_assign_ushort(mp_ref_t self, unsigned short val);
00335 void ymp_assign_uint(mp_ref_t self, unsigned val);
00336 void ymp_assign_ulong(mp_ref_t self, unsigned long val);
00337 #ifdef C99
00338 void ymp_assign_intmax(mp_ref_t self, intmax_t val);
00339 void ymp_assign_uintmax(mp_ref_t self, uintmax_t val);
00340 #endif
00341 void ymp_assign_double(mp_ref_t self, double val);
00342 void ymp_assign_2exp(mp_ref_t self, size_t pow);
00343
00344
00351 #define ymp_assign_zero(self) \
00352 (void)((self)->used = 0)
00353
00354
00355 void ymp_swap(mp_ref_t self, mp_ref_t other);
00368 size_t
00369 ymp_rshiftabs(digit_t *result, const digit_t *source, size_t len, size_t width);
00370 size_t
00371 ymp_lshiftabs(digit_t *result, const digit_t *source, size_t len, size_t width);
00383 size_t ymp_addabs(digit_t *result, const digit_t *lhs, const digit_t *rhs,
00384 size_t lhs_len, size_t rhs_len);
00385 size_t ymp_subabs(digit_t *result, const digit_t *lhs, const digit_t *rhs,
00386 size_t lhs_len, size_t rhs_len);
00387 size_t ymp_mulabs(digit_t *result, const digit_t *lhs, const digit_t *rhs,
00388 size_t lhs_len, size_t rhs_len);
00389 size_t ymp_mulabs_digit(digit_t *result, const digit_t *lhs, digit_t rhs,
00390 size_t lhs_len);
00391 size_t ymp_modmulabs(digit_t *result, const digit_t *lhs, const digit_t *rhs,
00392 const digit_t *modulus,
00393 size_t lhs_len, size_t rhs_len, size_t modulus_len);
00394 size_t ymp_modmulabs_2exp(digit_t *result,
00395 const digit_t *lhs, const digit_t *rhs,
00396 size_t pow, size_t lhs_len, size_t rhs_len);
00397
00398 size_t ymp_modabs_2exp(digit_t *result, const digit_t *self,
00399 size_t len, size_t pow);
00400
00401 size_t ymp_divmodabs(digit_t *quotient, digit_t *remainder,
00402 const digit_t *lhs, const digit_t *rhs,
00403 size_t lhs_len, size_t rhs_len);
00404 digit_t ymp_divmodabs_digit(digit_t *quotient, const digit_t *lhs, digit_t rhs,
00405 size_t lhs_len);
00406
00407
00408
00409
00410 size_t ymp_modpowabs(digit_t *result,
00411 const digit_t *source, const digit_t *modulus,
00412 const digit_t *pow,
00413 size_t source_len, size_t modulus_len, size_t pow_len);
00414
00415 size_t ymp_modpowabs_z(digit_t *result,
00416 const digit_t *source, const digit_t *modulus,
00417 size_t source_len, size_t modulus_len, size_t pow);
00418
00419 size_t ymp_modpowabs_2exp_z(digit_t *result, const digit_t *source,
00420 size_t len, size_t emod, size_t pow);
00421
00422 size_t ymp_powabs(digit_t *result, const digit_t *source,
00423 size_t source_len, size_t pow);
00426 void ymp_neg(mp_ref_t result, mp_cref_t orig);
00427 void ymp_add(mp_ref_t result, mp_cref_t self, mp_cref_t other);
00428 void ymp_sub(mp_ref_t result, mp_cref_t self, mp_cref_t other);
00429 void ymp_add_digit(mp_ref_t result, mp_cref_t self, digit_t other);
00430 void ymp_sub_digit(mp_ref_t result, mp_cref_t self, digit_t other);
00431
00432 void ymp_mul(mp_ref_t result, mp_cref_t self, mp_cref_t other);
00433 void ymp_mul_digit(mp_ref_t result, mp_cref_t self, digit_t other);
00434 void ymp_modmul(mp_ref_t result,
00435 mp_cref_t self, mp_cref_t other, mp_cref_t modulus);
00436 void ymp_modmul_2exp(mp_ref_t result,
00437 mp_cref_t self, mp_cref_t other, size_t pow);
00438
00439 void ymp_mul_2exp(mp_ref_t result, mp_cref_t self, size_t pow);
00440 void ymp_div_2exp(mp_ref_t result, mp_cref_t self, size_t pow);
00441 void ymp_mod_2exp(mp_ref_t result, mp_cref_t self, size_t pow);
00442
00443
00444 void ymp_divmod(mp_ref_t quotient, mp_ref_t remainder, mp_cref_t self, mp_cref_t other);
00445 digit_t ymp_divmod_digit(mp_ref_t quotient, mp_cref_t self, digit_t other);
00446
00458 #define ymp_div(quotient, self, other) \
00459 ymp_divmod((quotient), NULL, (self), (other))
00460
00470 #define ymp_mod(remainder, self, other) \
00471 ymp_divmod(NULL, (remainder), (self), (other))
00472
00482 #define ymp_div_digit(quotient, self, other) \
00483 (void)ymp_divmod_digit((quotient), (self), (other))
00484
00494 #define ymp_mod_digit(self, other) \
00495 ymp_divmod_digit(NULL, (self), (other))
00496
00497
00498
00499 int ymp_div_if_divisible(mp_ref_t quotient, mp_cref_t self, mp_cref_t other);
00500 int ymp_div_if_divisible_digit(mp_ref_t quotient,
00501 mp_cref_t self, digit_t other);
00502
00512 #define ymp_is_divisible(self, other) \
00513 ymp_div_if_divisible(NULL, (self), (other))
00514
00524 #define ymp_is_divisible_digit(self, other) \
00525 ymp_div_if_divisible_digit(NULL, (self), (other))
00526
00527 void ymp_pow(mp_ref_t result, mp_cref_t self, size_t pow);
00528 void ymp_modpow(mp_ref_t result, mp_cref_t self,
00529 mp_cref_t modulus, mp_cref_t pow);
00530 void ymp_modpow_z(mp_ref_t result, mp_cref_t self, mp_cref_t modulus, size_t pow);
00531
00532 void ymp_modpow_2exp_z(mp_ref_t result, mp_cref_t self, size_t emod, size_t pow);
00533 void ymp_iroot(mp_ref_t result, mp_cref_t self, size_t pow);
00534
00540 void ymp_euclid(mp_ref_t g, mp_cref_t a, mp_cref_t b);
00541 void ymp_euclid_ex(mp_ref_t g, mp_ref_t s, mp_ref_t t,
00542 mp_cref_t a, mp_cref_t b);
00543 void ymp_multi_euclid(mp_ref_t result,
00544 size_t len, const struct multiprec *ary);
00545 int ymp_modinv(mp_ref_t result, mp_cref_t self, mp_cref_t modulus);
00546 int ymp_binary_sunzi(mp_ref_t result,
00547 const mp_cref_t remainders[2], const mp_cref_t moduli[2]);
00548
00549 int ymp_proot(mp_ref_t result, mp_cref_t self, size_t pow);
00550 int ymp_is_perfect_power(mp_cref_t self);
00551
00559 void ymp_dump(FILE *fp, mp_cref_t mz);
00560 int ymp_print_hex(FILE *fp, mp_cref_t mz);
00561
00566 int ymp_snprint(char *buf, size_t len, mp_cref_t mz, digit_t radix);
00567 int ymp_fprint(FILE *fp, mp_cref_t mz, digit_t radix);
00568
00579 int ymp_compare_abs(mp_cref_t lhs, mp_cref_t rhs);
00580 int ymp_compare(mp_cref_t lhs, mp_cref_t rhs);
00581 int ymp_compare_digit(mp_cref_t lhs, digit_t rhs);
00582 int ymp_is_zero(mp_cref_t self);
00583 int ymp_is_even(mp_cref_t self);
00584
00590 #define ymp_is_odd(self) !ymp_is_even((self))
00591
00599 size_t ymp_ilog2(mp_cref_t self);
00600 size_t ymp_abs_clog2(const digit_t *digits, size_t len);
00601
00606 #endif