00001 #include "multiprec.h" 00002 #include <string.h> 00003 #include <math.h> 00004 00019 inline void 00020 ymp_initialize(mp_ref_t self) 00021 { 00022 static const struct multiprec prototype = MULTIPREC_INITIALIZER; 00023 memcpy(self, &prototype, sizeof(struct multiprec)); 00024 } 00025 00026 00032 inline void 00033 ymp_destroy(mp_ref_t self) 00034 { 00035 YMP_FREE_DIGITS(self); 00036 } 00037 00045 void 00046 ymp_reinitialize(mp_ref_t self) 00047 { 00048 ymp_destroy(self); 00049 ymp_initialize(self); 00050 } 00051 00052 00060 inline void 00061 ymp_initialize_by_mp(mp_ref_t self, mp_cref_t other) 00062 { 00063 memcpy(self, other, sizeof(*self)-sizeof(digit_t*)); 00064 YMP_ALLOC_DIGITS(self, self->len); 00065 memcpy(self->digits, other->digits, sizeof(digit_t)*self->used); 00066 } 00067 00075 inline void 00076 ymp_reserve_and_initialize_by_digit(mp_ref_t self, size_t len, digit_t d) 00077 { 00078 self->sign = positive_sign; 00079 YMP_ALLOC_DIGITS(self, len); 00080 self->used = 1; 00081 self->digits[0] = d; 00082 } 00083 00090 void 00091 ymp_initialize_by_digit(mp_ref_t self, digit_t d) 00092 { 00093 ymp_reserve_and_initialize_by_digit(self, 1, d); 00094 } 00095 00102 void 00103 ymp_reserve_and_initialize(mp_ref_t self, size_t len) 00104 { 00105 ymp_reserve_and_initialize_by_digit(self, len, 0); 00106 } 00107 00108 00117 void 00118 ymp_initialize_by_array(mp_ref_t self, size_t len, const digit_t *array) 00119 { 00120 self->sign = positive_sign; 00121 self->used = len; 00122 YMP_ALLOC_DIGITS(self, len); 00123 memcpy(self->digits, array, len); 00124 } 00125 00126 00136 #define to_sign_check(self, val) \ 00137 if (val >= 0) \ 00138 { \ 00139 self->sign = positive_sign; \ 00140 } \ 00141 else \ 00142 { \ 00143 self->sign = negative_sign; \ 00144 val = -val; \ 00145 } 00146 00155 #define not_to_sign_check(self, val) (void)(self->sign = positive_sign) 00156 00157 00158 00168 #define do_assign_integral_value(type, self, val, allocator, sign_check) \ 00169 static const size_t len \ 00170 = sizeof(type)/sizeof(digit_t)+!!(sizeof(type)%sizeof(digit_t)); \ 00171 size_t i; \ 00172 \ 00173 sign_check(self, val); \ 00174 allocator(self, len); \ 00175 \ 00176 for (i=0; val; ++i) \ 00177 { \ 00178 self->digits[i] = (digit_t)val & DIGIT_MAX; \ 00179 val >>= DIGIT_BIT; \ 00180 } \ 00181 self->used = i; 00182 00183 00192 #define define_ymp_initialize_integral_type(type, postfix, sign_check) \ 00193 \ 00199 void ymp_initialize_by_##postfix(mp_ref_t self, type val) \ 00200 { \ 00201 do_assign_integral_value(type, self, val, YMP_ALLOC_DIGITS, sign_check); \ 00202 } 00203 00204 define_ymp_initialize_integral_type(signed char, char, to_sign_check); 00205 define_ymp_initialize_integral_type(short, short, to_sign_check); 00206 define_ymp_initialize_integral_type(int, int, to_sign_check); 00207 define_ymp_initialize_integral_type(long, long, to_sign_check); 00208 define_ymp_initialize_integral_type(unsigned char, uchar, not_to_sign_check); 00209 define_ymp_initialize_integral_type(unsigned short, ushort, not_to_sign_check); 00210 define_ymp_initialize_integral_type(unsigned int, uint, not_to_sign_check); 00211 define_ymp_initialize_integral_type(unsigned long, ulong, not_to_sign_check); 00212 #ifdef C99 00213 define_ymp_initialize_integral_type(intmax_t, intmax, to_sign_check); 00214 define_ymp_initialize_integral_type(uintmax_t, uintmax, to_sign_check); 00215 #endif 00216 00217 00218 #define do_assign_floating_value(type, sys_suffix, funcname, allocator) \ 00219 size_t i, len; \ 00220 type val2; \ 00221 \ 00222 if (!isfinite(val)) \ 00223 { \ 00224 ymp_error(funcname, ": 初期化子が有限値でない"); \ 00225 return; \ 00226 } \ 00227 \ 00228 if ( val >= 0) \ 00229 { \ 00230 self->sign = positive_sign; \ 00231 val = floor##sys_suffix(val); \ 00232 } \ 00233 else \ 00234 { \ 00235 self->sign = negative_sign; \ 00236 val = -ceil##sys_suffix(val); \ 00237 } \ 00238 \ 00239 for (len=0, val2=val; val2!=0.0; ++len) \ 00240 { \ 00241 val2 = floor##sys_suffix(val2/MULTIPREC_RADIX); \ 00242 } \ 00243 \ 00244 allocator(self, len); \ 00245 \ 00246 for (i=0; i<len; ++i) \ 00247 { \ 00248 self->digits[i] = (digit_t)val; \ 00249 val /= MULTIPREC_RADIX; \ 00250 } \ 00251 self->used = len; 00252 00253 00262 void ymp_initialize_by_double(mp_ref_t self, double val) 00263 { 00264 do_assign_floating_value(double,, "ymp_initialize_by_double", YMP_ALLOC_DIGITS); 00265 } 00266 00267 00268 00269 00275 mp_ref_t ymp_dup(mp_cref_t orig) 00276 { 00277 struct multiprec *p = ymp_malloc(sizeof(struct multiprec)); 00278 if (!p) 00279 ymp_alloc_error("can't dup struct multiprec", sizeof(struct multiprec)); 00280 00281 ymp_initialize_by_mp(p, orig); 00282 return p; 00283 } 00284 00294 void 00295 ymp_reserve(mp_ref_t self, size_t len) 00296 { 00297 if (self->len < len) YMP_REALLOC_DIGITS(self, len); 00298 } 00299 00309 void 00310 ymp_cut_down(mp_ref_t self) 00311 { 00312 YMP_REALLOC_DIGITS(self, self->used); 00313 } 00314 00335 inline void 00336 ymp_assign_abs(mp_ref_t self, mp_cref_t other) 00337 { 00338 ymp_reserve(self, other->used); 00339 self->used = other->used; 00340 memcpy(self->digits, other->digits, self->used*sizeof(digit_t)); 00341 } 00342 00351 inline void 00352 ymp_assign_abs_digit(mp_ref_t self, digit_t other) 00353 { 00354 ymp_reserve(self, 1); 00355 self->used = 1; 00356 self->digits[0] = other; 00357 } 00358 00368 inline void 00369 ymp_assign_abs_array(mp_ref_t self, size_t len, const digit_t *array) 00370 { 00371 self->used = len; 00372 ymp_reserve(self, len); 00373 memcpy(self->digits, array, len*sizeof(digit_t)); 00374 } 00375 00388 void 00389 ymp_assign(mp_ref_t self, mp_cref_t other) 00390 { 00391 self->sign = other->sign; 00392 ymp_assign_abs(self, other); 00393 } 00394 00395 00403 void 00404 ymp_assign_digit(mp_ref_t self, digit_t other) 00405 { 00406 self->sign = positive_sign; 00407 ymp_assign_abs_digit(self, other); 00408 } 00409 00418 void 00419 ymp_assign_array(mp_ref_t self, size_t len, const digit_t *array) 00420 { 00421 self->sign = positive_sign; 00422 ymp_assign_abs_array(self, len, array); 00423 } 00424 00425 00426 00435 #define define_ymp_assign_integral_type(type, postfix, sign_check) \ 00436 \ 00442 void ymp_assign_##postfix(mp_ref_t self, type val) \ 00443 { \ 00444 do_assign_integral_value(type, self, val, ymp_reserve, sign_check); \ 00445 } 00446 00447 define_ymp_assign_integral_type(signed char, char, to_sign_check); 00448 define_ymp_assign_integral_type(short, short, to_sign_check); 00449 define_ymp_assign_integral_type(int, int, to_sign_check); 00450 define_ymp_assign_integral_type(long, long, to_sign_check); 00451 define_ymp_assign_integral_type(unsigned char, uchar, not_to_sign_check); 00452 define_ymp_assign_integral_type(unsigned short, ushort, not_to_sign_check); 00453 define_ymp_assign_integral_type(unsigned int, uint, not_to_sign_check); 00454 define_ymp_assign_integral_type(unsigned long, ulong, not_to_sign_check); 00455 #ifdef C99 00456 define_ymp_assign_integral_type(intmax_t, intmax, to_sign_check); 00457 define_ymp_assign_integral_type(uintmax_t, uintmax, not_to_sign_check); 00458 #endif 00459 00468 void ymp_assign_double(mp_ref_t self, double val) 00469 { 00470 do_assign_floating_value(double,, "ymp_assign_by_double", ymp_reserve); 00471 } 00472 00481 void ymp_assign_2exp(mp_ref_t self, size_t pow) 00482 { 00483 size_t n_digits = pow / DIGIT_BIT, n_bits = pow % DIGIT_BIT; 00484 00485 self->sign = positive_sign; 00486 ymp_reserve(self, n_digits+1); 00487 self->used = n_digits + 1; 00488 memset(self->digits, 0, sizeof(digit_t)*n_digits); 00489 self->digits[n_digits] = 1u << n_bits; 00490 } 00491 00499 void ymp_swap(mp_ref_t self, mp_ref_t other) 00500 { 00501 enum mp_sign_t tmp_sign; 00502 size_t tmp_size; 00503 digit_t *tmp_digits; 00504 00505 tmp_sign = self->sign; 00506 self->sign = other->sign; 00507 other->sign = tmp_sign; 00508 00509 tmp_size = self->len; 00510 self->len = other->len; 00511 other->len = tmp_size; 00512 00513 tmp_size = self->used; 00514 self->used = other->used; 00515 other->used = tmp_size; 00516 00517 tmp_digits = self->digits; 00518 self->digits = other->digits; 00519 other->digits = tmp_digits; 00520 } 00521