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