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