モジュール | |
| 下位関数群 | |
マクロ定義 | |
| #define | ymp_div(quotient, self, other) ymp_divmod((quotient), NULL, (self), (other)) |
| 多倍長整数の整除. より詳しく... | |
| #define | ymp_mod(remainder, self, other) ymp_divmod(NULL, (remainder), (self), (other)) |
| 多倍長整数の剰余計算. より詳しく... | |
| #define | ymp_div_digit(quotient, self, other) (void)ymp_divmod_digit((quotient), (self), (other)) |
| 多倍長整数のdigit_tによる整除. より詳しく... | |
| #define | ymp_mod_digit(self, other) ymp_divmod_digit(NULL, (self), (other)) |
| 多倍長整数のdigit_tによる剰余計算. より詳しく... | |
| #define | ymp_is_divisible(self, other) ymp_div_if_divisible(NULL, (self), (other)) |
| 多倍長整数が割り切れるかを判定. より詳しく... | |
| #define | ymp_is_divisible_digit(self, other) ymp_div_if_divisible_digit(NULL, (self), (other)) |
| 多倍長整数がdigit_tで割り切れるかを判定. より詳しく... | |
関数 | |
| void | ymp_do_add (mp_ref_t result, mp_cref_t self, mp_cref_t other, int is_add) |
| 加減算を実行する。. より詳しく... | |
| void | ymp_do_add_digit (mp_ref_t result, mp_cref_t self, digit_t other, int is_add) |
| digit_tとの加減算を実行する。. より詳しく... | |
| void | ymp_add (mp_ref_t result, mp_cref_t self, mp_cref_t other) |
| 多倍長整数の加算. より詳しく... | |
| void | ymp_sub (mp_ref_t result, mp_cref_t self, mp_cref_t other) |
| 多倍長整数の減算. より詳しく... | |
| void | ymp_add_digit (mp_ref_t result, mp_cref_t self, digit_t val) |
| 多倍長整数にdigit_tを足す. より詳しく... | |
| void | ymp_sub_digit (mp_ref_t result, mp_cref_t self, digit_t val) |
| 多倍長整数からdigit_tを引く. より詳しく... | |
| void | ymp_neg (mp_ref_t result, mp_cref_t orig) |
| 多倍長整数の符号反転. より詳しく... | |
| void | ymp_divmod (mp_ref_t quotient, mp_ref_t remainder, mp_cref_t self, mp_cref_t other) |
| 多倍長整数の除算. より詳しく... | |
| digit_t | ymp_divmod_digit (mp_ref_t quotient, mp_cref_t self, digit_t other) |
| 多倍長整数の、digit_tによる除算. より詳しく... | |
| int | ymp_div_if_divisible (mp_ref_t quotient, mp_cref_t self, mp_cref_t other) |
| 多倍長整数を、もし可能なら割る. より詳しく... | |
| int | ymp_div_if_divisible_digit (mp_ref_t quotient, mp_cref_t self, digit_t other) |
| 多倍長整数をdigit_tで、もし可能なら割る. より詳しく... | |
| void | ymp_mul (mp_ref_t result, mp_cref_t self, mp_cref_t other) |
| 多倍長整数同士を掛ける. より詳しく... | |
| void | ymp_modmul (mp_ref_t result, mp_cref_t self, mp_cref_t other, mp_cref_t modulus) |
| 多倍長整数の積の剰余を求める. より詳しく... | |
| void | ymp_modmul_2exp (mp_ref_t result, mp_cref_t self, mp_cref_t other, size_t pow) |
| 多倍長自然数の積の、2の冪による剰余を求める. より詳しく... | |
| void | ymp_mul_digit (mp_ref_t result, mp_cref_t self, digit_t other) |
| 多倍長整数にdigit_tを掛ける. より詳しく... | |
| void | ymp_pow (mp_ref_t result, mp_cref_t self, size_t pow) |
| 多倍長整数の冪 (冪指数はsize_t). より詳しく... | |
| void | ymp_modpow_z (mp_ref_t result, mp_cref_t self, mp_cref_t modulus, size_t pow) |
| 多倍長整数の冪の剰余を求める(冪指数はsize_t). より詳しく... | |
| void | ymp_modpow_2exp_z (mp_ref_t result, mp_cref_t self, size_t emod, size_t pow) |
| 多倍長整数の冪の、2の冪による剰余を求める(冪指数はsize_t). より詳しく... | |
| void | ymp_modpow (mp_ref_t result, mp_cref_t self, mp_cref_t modulus, mp_cref_t pow) |
| 多倍長整数の冪の剰余を求める(冪指数は多倍長). より詳しく... | |
| void | ymp_mul_2exp (mp_ref_t result, mp_cref_t self, size_t pow) |
| 多倍長整数を2の冪乗倍する. より詳しく... | |
| void | ymp_div_2exp (mp_ref_t result, mp_cref_t self, size_t pow) |
| 多倍長整数を2の冪乗で割る. より詳しく... | |
| void | ymp_mod_2exp (mp_ref_t result, mp_cref_t self, size_t pow) |
| 多倍長整数を2の冪乗で割った剰余. より詳しく... | |
| void | ymp_iroot (mp_ref_t result, mp_cref_t self, size_t pow) |
| 多倍長整数の冪乗根の整数部分. より詳しく... | |
|
|
多倍長整数の整除.
multiprec.h の 458 行で定義されています。 呼出 ymp_iroot. |
|
|
多倍長整数の剰余計算.
multiprec.h の 470 行で定義されています。 呼出 ymp_binary_sunzi, と ymp_modinv. |
|
|
多倍長整数のdigit_tによる整除.
multiprec.h の 482 行で定義されています。 |
|
|
多倍長整数のdigit_tによる剰余計算.
multiprec.h の 494 行で定義されています。 |
|
|
多倍長整数が割り切れるかを判定.
multiprec.h の 512 行で定義されています。 |
|
|
多倍長整数がdigit_tで割り切れるかを判定.
multiprec.h の 524 行で定義されています。 |
|
||||||||||||||||||||
|
加減算を実行する。.
参照 multiprec::digits, mp_cref_t, positive_sign, multiprec::sign, multiprec::used, ymp_addabs, ymp_reserve, と ymp_subabs.
00128 {
00129 if (self->used > other->used)
00130 {
00131 if (is_add)
00132 {
00133 ymp_reserve(result, self->used+1);
00134 result->used
00135 = ymp_addabs(result->digits, self->digits, other->digits,
00136 self->used, other->used);
00137 result->sign = self->sign;
00138 }
00139 else
00140 {
00141 ymp_reserve(result, self->used);
00142 result->used
00143 = ymp_subabs(result->digits, self->digits, other->digits,
00144 self->used, other->used);
00145 result->sign = self->sign;
00146 }
00147 return;
00148 }
00149 else if (self->used < other->used)
00150 {
00151 if (is_add)
00152 {
00153 ymp_reserve(result, other->used+1);
00154 result->used
00155 = ymp_addabs(result->digits, other->digits, self->digits,
00156 other->used, self->used);
00157 result->sign = self->sign;
00158 }
00159 else
00160 {
00161 ymp_reserve(result, other->used);
00162 result->used
00163 = ymp_subabs(result->digits, other->digits, self->digits,
00164 other->used, self->used);
00165 result->sign = !self->sign;
00166 }
00167 return;
00168 }
00169
00170
00171
00172 /* self->used == other->used */
00173
00174 if (is_add)
00175 {
00176 ymp_reserve(result, self->used+1);
00177 result->used
00178 = ymp_addabs(result->digits, self->digits, other->digits,
00179 self->used, other->used);
00180 result->sign = self->sign;
00181 }
00182 else
00183 {
00184 size_t i = self->used;
00185 while (i-- > 0)
00186 {
00187 if ( self->digits[i] > other->digits[i])
00188 {
00189 ymp_reserve(result, ++i);
00190 result->used
00191 = ymp_subabs(result->digits, self->digits, other->digits,
00192 i, i);
00193 result->sign = self->sign;
00194 return;
00195 }
00196 else if (self->digits[i] < other->digits[i])
00197 {
00198 ymp_reserve(result, ++i);
00199 result->used
00200 = ymp_subabs(result->digits, other->digits, self->digits,
00201 i, i);
00202 result->sign = !self->sign;
00203 return;
00204 }
00205 }
00206 result->sign = positive_sign;
00207 result->used = 0;
00208 }
00209 }
|
|
||||||||||||||||||||
|
digit_tとの加減算を実行する。.
参照 digit_t, multiprec::digits, double_digit_t, HIGH_DIGIT, LOW_DIGIT, mp_cref_t, multiprec::sign, multiprec::used, ymp_addabs, ymp_reserve, と ymp_subabs. 呼出 ymp_add_digit, と ymp_sub_digit.
00229 {
00230 switch (self->used)
00231 {
00232 case 0:
00233 ymp_reserve(result, 1);
00234 result->sign = self->sign;
00235 result->used = 1;
00236 result->digits[0] = other;
00237 return;
00238
00239 case 1:
00240 if (is_add)
00241 {
00242 double_digit_t tmp;
00243
00244 ymp_reserve(result, 2);
00245 result->sign = self->sign;
00246 result->used = 1;
00247
00248 tmp = other;
00249 tmp += self->digits[0];
00250
00251 result->digits[0] = LOW_DIGIT(tmp);
00252 if ( (tmp = HIGH_DIGIT(tmp)) )
00253 {
00254 self->digits[1] = LOW_DIGIT(tmp);
00255 ++result->used;
00256 }
00257 return;
00258 }
00259 else
00260 {
00261 ymp_reserve(result, 1);
00262 result->used = 1;
00263 if (self->digits[0] > other)
00264 {
00265 result->sign = self->sign;
00266 result->digits[0] = self->digits[0] - other;
00267 }
00268 else
00269 {
00270 result->sign = !self->sign;
00271 self->digits[0] = other - self->digits[0];
00272 }
00273 return;
00274 }
00275 default:
00276 if (is_add)
00277 {
00278 ymp_reserve(result, self->used+1);
00279 result->used
00280 = ymp_addabs(result->digits, self->digits, &other, self->used, 1);
00281 result->sign = self->sign;
00282 return;
00283 }
00284 else
00285 {
00286 ymp_reserve(result, self->used+1);
00287 result->used
00288 = ymp_subabs(result->digits, self->digits, &other, self->used, 1);
00289 result->sign = self->sign;
00290 return;
00291 }
00292 }
00293 }
|
|
||||||||||||||||
|
多倍長整数の加算. <result>に<self> + <other>を格納する
参照 mp_cref_t, multiprec::sign, と ymp_do_add.
00310 {
00311 ymp_do_add(result, self, other, self->sign==other->sign);
00312 }
|
|
||||||||||||||||
|
多倍長整数の減算. <result>に<self> - <other>を格納する
参照 mp_cref_t, multiprec::sign, と ymp_do_add.
00325 {
00326 ymp_do_add(result, self, other, self->sign!=other->sign);
00327 }
|
|
||||||||||||||||
|
多倍長整数にdigit_tを足す.
参照 digit_t, mp_cref_t, positive_sign, multiprec::sign, と ymp_do_add_digit.
00340 {
00341 ymp_do_add_digit(result, self, val, self->sign==positive_sign);
00342 }
|
|
||||||||||||||||
|
多倍長整数からdigit_tを引く.
参照 digit_t, mp_cref_t, positive_sign, multiprec::sign, と ymp_do_add_digit.
00353 {
00354 ymp_do_add_digit(result, self, val, self->sign!=positive_sign);
00355 }
|
|
||||||||||||
|
多倍長整数の符号反転. <result> := -<self>
参照 digit_t, multiprec::digits, mp_cref_t, multiprec::sign, multiprec::used, と ymp_reserve.
|
|
||||||||||||||||||||
|
多倍長整数の除算.
参照 multiprec::digits, mp_cref_t, mp_sign_t, multiprec::sign, multiprec::used, ymp_assign, ymp_divmodabs, ymp_fatal, ymp_is_zero, と ymp_reserve.
00264 {
00265 enum mp_sign_t rem_sign;
00266 size_t rem_used;
00267
00268 /* 0除算を弾く */
00269 if (ymp_is_zero(other))
00270 {
00271 ymp_fatal("0による除算");
00272 return;
00273 }
00274
00275 /* 明らかに (被除数) < (除数) と分かる場合:
00276 商は0、剰余は被除数に等しい */
00277 if (self->used < other->used)
00278 {
00279 if (quotient) quotient->used = 0;
00280 if (self != remainder && remainder) ymp_assign(remainder, self);
00281 return;
00282 }
00283
00284 /* 商・剰余の格納に十分な領域を確保 */
00285 if (quotient) ymp_reserve(quotient, self->used-other->used+1);
00286 if (remainder) ymp_reserve(remainder, other->used);
00287
00288 /* 絶対値同士の除算を行う */
00289 rem_sign = self->sign;
00290 rem_used = ymp_divmodabs(quotient?quotient->digits:NULL,
00291 remainder?remainder->digits:NULL,
00292 self->digits, other->digits,
00293 self->used, other->used);
00294
00295 /*
00296 * remainder==selfまたはremainder==otherのときにも
00297 * 商のの符号と桁数の調整に影響を与えないように、
00298 * 剰余の符号と桁数は直ぐには書き込まない
00299 */
00300
00301 if (quotient)
00302 {
00303 /* 商の符号と桁数の調整 */
00304 quotient->sign = self->sign != other->sign;
00305 quotient->used = self->used - other->used + 1;
00306 if (!quotient->digits[quotient->used-1]) --quotient->used;
00307 }
00308
00309 if (remainder)
00310 {
00311 /* 剰余の符号と桁数を書き込む */
00312 remainder->sign = rem_sign;
00313 remainder->used = rem_used;
00314 }
00315 }
|
|
||||||||||||||||
|
多倍長整数の、digit_tによる除算.
参照 digit_t, multiprec::digits, multiprec::len, mp_cref_t, multiprec::sign, multiprec::used, ymp_addabs, ymp_divmodabs_digit, ymp_fatal, と ymp_reserve.
00334 {
00335 digit_t rem; /* 剰余の絶対値 */
00336
00337 /* 0除算を弾く */
00338 if (other == 0)
00339 {
00340 ymp_fatal("0による除算");
00341 return 0;
00342 }
00343
00344 /* 被除数が0の場合、商と剰余も0 */
00345 if (self->used == 0)
00346 {
00347 if (quotient) quotient->used = 0;
00348 return 0;
00349 }
00350
00351 /* 商を格納するのに十分な領域を確保 */
00352 if (quotient) ymp_reserve(quotient, self->used);
00353
00354 /* 絶対値の除算を行う */
00355 rem = ymp_divmodabs_digit(quotient?quotient->digits:NULL,
00356 self->digits,
00357 other,
00358 self->used);
00359
00360 /* 桁数と符号の設定 */
00361 if (quotient)
00362 {
00363 if (quotient->digits[quotient->used-1]) --quotient->used;
00364 quotient->sign = self->sign;
00365 }
00366
00367 if (self->sign && rem)
00368 {
00369 /* 剰余が正になるように調整 */
00370 if (quotient)
00371 {
00372 quotient->used = ymp_addabs(quotient->digits, quotient->digits,
00373 &other, quotient->len, 1);
00374 }
00375 return other - rem;
00376 }
00377 else
00378 {
00379 return rem;
00380 }
00381 }
|
|
||||||||||||||||
|
多倍長整数を、もし可能なら割る. selfがotherで割れるかどうか調べ、もし割り切れるなら商をquotientに代入する 割り切れないときはquotientは変化しない
参照 digit_t, multiprec::digits, mp_cref_t, multiprec::sign, multiprec::used, ymp_divmodabs, ymp_fatal, ymp_is_zero, ymp_reserve, と YMP_TEMP_ALLOCATE.
00400 {
00401 size_t rem_used; /* 剰余の桁数 */
00402 digit_t *quot_buf=NULL, *rem_buf=NULL; /* 商・剰余の一時格納用 */
00403
00404 /* 0除算を弾く */
00405 if (ymp_is_zero(other))
00406 {
00407 ymp_fatal("0による除算");
00408 return 2;
00409 }
00410
00411 /* 明らかな場合 */
00412 if (self->used < other->used)
00413 {
00414 if (ymp_is_zero(self))
00415 {
00416 if (quotient) quotient->used = 0;
00417 return 1;
00418 }
00419 else
00420 {
00421 return 0;
00422 }
00423 }
00424
00425 /* 格納領域を確保 */
00426 if (quotient) YMP_TEMP_ALLOCATE(quot_buf, digit_t, self->used-other->used+1);
00427 YMP_TEMP_ALLOCATE(rem_buf, digit_t, other->used);
00428
00429 /* 絶対値の除算を実行 */
00430 rem_used = ymp_divmodabs(quot_buf, rem_buf, self->digits, other->digits,
00431 self->used, other->used);
00432
00433 /* 剰余が0なら (そのときrem_usedは必ず0) */
00434 if (rem_used==0)
00435 {
00436 if (quotient)
00437 {
00438 /* *quotientに商のデータをコピー */
00439 size_t quot_used;
00440 quotient->sign = self->sign != other->sign;
00441
00442 quot_used = self->used - other->used + 1;
00443 if (!quot_buf[quot_used-1]) --quot_used;
00444 quotient->used = quot_used;
00445 ymp_reserve(quotient, quot_used);
00446 memcpy(quotient->digits, quot_buf, quot_used);
00447 }
00448 return 1;
00449 }
00450 else
00451 {
00452 return 0;
00453 }
00454 }
|
|
||||||||||||||||
|
多倍長整数をdigit_tで、もし可能なら割る. selfがotherで割れるかどうか調べ、もし割り切れるなら商をquotientに代入する 割り切れないときはquotientは変化しない
参照 digit_t, multiprec::digits, mp_cref_t, multiprec::sign, multiprec::used, ymp_divmodabs_digit, ymp_fatal, ymp_is_zero, ymp_reserve, と YMP_TEMP_ALLOCATE.
00475 {
00476 digit_t rem;
00477 digit_t *quot_buf=NULL;
00478
00479 /* 0除算を弾く */
00480 if (other == 0)
00481 {
00482 ymp_fatal("0による除算");
00483 return 2;
00484 }
00485
00486 /* 明らかな場合 */
00487 if (ymp_is_zero(self))
00488 {
00489 if (quotient) quotient->used = 0;
00490 return 1;
00491 }
00492
00493 /* 格納領域を確保 */
00494 if (quotient) YMP_TEMP_ALLOCATE(quot_buf, digit_t, self->used);
00495
00496 /* 絶対値の除算を実行 */
00497 rem = ymp_divmodabs_digit(quot_buf, self->digits, other, self->used);
00498
00499 /* 剰余が0なら */
00500 if (rem == 0)
00501 {
00502 if (quotient)
00503 {
00504 /* *quotientに商のデータをコピー */
00505 size_t quot_used;
00506 quotient->sign = self->sign;
00507
00508 quot_used = self->used;
00509 if (!quot_buf[quot_used-1]) --quot_used;
00510 quotient->used = quot_used;
00511 ymp_reserve(quotient, quot_used);
00512 memcpy(quotient->digits, quot_buf, quot_used);
00513 }
00514 return 1;
00515 }
00516 else
00517 {
00518 return 0;
00519 }
00520 }
|
|
||||||||||||||||
|
多倍長整数同士を掛ける.
参照 digit_t, multiprec::digits, mp_cref_t, multiprec::sign, multiprec::used, ymp_mulabs, ymp_reserve, と YMP_TEMP_ALLOCATE.
00238 {
00239 digit_t *self_digits = self->digits;
00240 digit_t *other_digits = other->digits;
00241 if (result == self)
00242 {
00243 YMP_TEMP_ALLOCATE(self_digits, digit_t, self->used);
00244 memcpy(self_digits, self->digits, sizeof(digit_t)*self->used);
00245 }
00246 if (result == other)
00247 {
00248 YMP_TEMP_ALLOCATE(other_digits, digit_t, self->used);
00249 memcpy(other_digits, other->digits, sizeof(digit_t)*self->used);
00250 }
00251
00252 ymp_reserve(result, self->used+other->used);
00253 result->used = ymp_mulabs(result->digits, self_digits, other_digits,
00254 self->used, other->used);
00255
00256 result->sign = self->sign != other->sign;
00257 }
|
|
||||||||||||||||||||
|
多倍長整数の積の剰余を求める. <result> := <self> * <other> % <modulus>
参照 digit_t, multiprec::digits, mp_cref_t, multiprec::sign, multiprec::used, ymp_modmulabs, ymp_reserve, と YMP_TEMP_ALLOCATE.
00276 {
00277 digit_t *self_digits = self->digits;
00278 digit_t *other_digits = other->digits;
00279
00280 if (result == self)
00281 {
00282 YMP_TEMP_ALLOCATE(self_digits, digit_t, self->used);
00283 memcpy(self_digits, self->digits, sizeof(digit_t)*self->used);
00284 }
00285 if (result == other)
00286 {
00287 YMP_TEMP_ALLOCATE(other_digits, digit_t, self->used);
00288 memcpy(other_digits, other->digits, sizeof(digit_t)*self->used);
00289 }
00290
00291 ymp_reserve(result, modulus->used);
00292
00293 result->used = ymp_modmulabs(result->digits,
00294 self_digits, other->digits, modulus->digits,
00295 self->used, other->used, modulus->used);
00296
00297 result->sign = self->sign != other->sign;
00298 }
|
|
||||||||||||||||||||
|
多倍長自然数の積の、2の冪による剰余を求める. <result> := <self> * <other> % (2**pow)
参照 DIGIT_BIT, multiprec::digits, mp_cref_t, multiprec::sign, multiprec::used, ymp_modmulabs_2exp, と ymp_reserve.
00316 {
00317 ymp_reserve(result, pow/DIGIT_BIT + 1);
00318
00319 result->used = ymp_modmulabs_2exp(result->digits,
00320 self->digits, other->digits,
00321 pow, self->used, other->used);
00322
00323 result->sign = self->sign != other->sign;
00324 }
|
|
||||||||||||||||
|
多倍長整数にdigit_tを掛ける.
参照 digit_t, multiprec::digits, mp_cref_t, multiprec::sign, multiprec::used, ymp_mulabs_digit, と ymp_reserve.
00338 {
00339 ymp_reserve(result, self->used+1);
00340 result->used = ymp_mulabs_digit(result->digits,
00341 self->digits, other, self->used);
00342 result->sign = self->sign;
00343 }
|
|
||||||||||||||||
|
多倍長整数の冪 (冪指数はsize_t). <result> := <self>**<pow>
参照 multiprec::digits, MAX, mp_cref_t, multiprec::sign, multiprec::used, ymp_powabs, と ymp_reserve.
00648 {
00649 /* 結果の格納領域を確保 */
00650 ymp_reserve(result, self->used*MAX(pow, 1));
00651
00652 result->sign = self->sign && (pow & 0x01);
00653 result->used = ymp_powabs(result->digits, self->digits, self->used, pow);
00654 }
|
|
||||||||||||||||||||
|
多倍長整数の冪の剰余を求める(冪指数はsize_t). <result> := <self>**<pow> % <modulus>
参照 multiprec::digits, mp_cref_t, multiprec::sign, multiprec::used, ymp_modpowabs_z, と ymp_reserve.
00671 {
00672 /* 十分な格納領域を確保 */
00673 ymp_reserve(result, modulus->used);
00674
00675 result->sign = self->sign && (pow & 0x01);
00676 result->used = ymp_modpowabs_z(result->digits, self->digits, modulus->digits,
00677 self->used, modulus->used, pow);
00678 }
|
|
||||||||||||||||||||
|
多倍長整数の冪の、2の冪による剰余を求める(冪指数はsize_t). <result> := <self>**<pow> % (2**emod)
参照 DIGIT_BIT, multiprec::digits, mp_cref_t, multiprec::sign, multiprec::used, ymp_modpowabs_2exp_z, と ymp_reserve.
00696 {
00697 /* 十分な格納領域を確保 */
00698 ymp_reserve(result, emod / DIGIT_BIT + 1);
00699
00700 result->sign = self->sign && (pow & 0x01);
00701 result->used = ymp_modpowabs_2exp_z(result->digits, self->digits,
00702 self->used, emod, pow);
00703 }
|
|
||||||||||||||||||||
|
多倍長整数の冪の剰余を求める(冪指数は多倍長). <result> := <self>**<pow> % <modulus>
参照 multiprec::digits, mp_cref_t, multiprec::sign, multiprec::used, ymp_modpowabs, と ymp_reserve.
00719 {
00720 /* 十分な格納領域を確保 */
00721 ymp_reserve(result, modulus->used);
00722
00723 result->sign = self->sign && (pow->used != 0 || (pow->digits[0] & 0x01));
00724 result->used = ymp_modpowabs(result->digits,
00725 self->digits, modulus->digits, pow->digits,
00726 self->used, modulus->used, pow->used);
00727 }
|
|
||||||||||||||||
|
多倍長整数を2の冪乗倍する. <self>に2のpow乗を掛けた積をresultに格納する。
00170 {
00171 result->sign = self->sign;
00172 ymp_reserve(result, self->used+pow/DIGIT_BIT+1);
00173 result->used = ymp_lshiftabs(result->digits, self->digits, self->used, pow);
00174 }
|
|
||||||||||||||||
|
多倍長整数を2の冪乗で割る. <self>を2のpow乗で割った商をresultに格納する。
00190 {
00191 size_t n_shift_digits = pow/DIGIT_BIT;
00192
00193 if (self->used > n_shift_digits)
00194 {
00195 result->sign = self->sign;
00196 ymp_reserve(result, self->used - n_shift_digits);
00197 result->used
00198 = ymp_rshiftabs(result->digits, self->digits, self->used, pow);
00199 }
00200 else
00201 {
00202 result->used = 0;
00203 }
00204 }
|
|
||||||||||||||||
|
多倍長整数を2の冪乗で割った剰余. <self>を2のpow乗で割った剰余をresultに格納する。
00218 {
00219 size_t n_digits = pow / DIGIT_BIT;
00220 ymp_reserve(result, n_digits>self->used ? self->used : n_digits);
00221 result->sign = self->sign;
00222 result->used = ymp_modabs_2exp(result->digits, self->digits, self->used, pow);
00223 }
|
|
||||||||||||||||
|
多倍長整数の冪乗根の整数部分. result := floor( <self> ** (1/n) )
00017 {
00018 /* Newton法による */
00019
00020 size_t i;
00021 size_t ilog2, bit_len;
00022 struct multiprec x, x_prev; /* 近似途中の値を保持 */
00023 struct multiprec tmp; /* 計算上の一時領域 */
00024 struct multiprec self_copy;
00025
00026 if (!self->sign)
00027 { /* 非負ならば良い */
00028 result->sign = positive_sign;
00029 }
00030 else
00031 { /* そうでないとき */
00032 /* 偶数乗根はエラー */
00033 if ( (n & 0x01) == 0) ymp_fatal("負数の偶数乗根");
00034
00035 /* 結果の符号が確定 */
00036 result->sign = self->sign;
00037
00038 /* 以下、-<self> >= 0 の絶対値を算出すれば良い */
00039 memcpy(&self_copy, self, sizeof(struct multiprec));
00040 self_copy.sign = positive_sign;
00041 self = &self_copy;
00042 }
00043
00044 /* bit長により、初期値を大まかに決定 */
00045 /* (初期値) >= (収束値) を保証して収束が遅くなるのを防止する */
00046 /* ilog2 := { 2**k > |<self>|なる最小のk } */
00047 ilog2 = ymp_ilog2(self); ++ilog2;
00048
00049 bit_len = ilog2 / n;
00050 if (bit_len == 0)
00051 {
00052 if (ymp_is_zero(self)) ymp_assign_abs_digit(result, 0);
00053 else ymp_assign_abs_digit(result, 1);
00054 return;
00055 }
00056 if (ilog2 % n) ++bit_len;
00057
00058 ymp_alloca_initialize(&x, self->used * n + 1);
00059 for (i=0; i<bit_len/DIGIT_BIT; ++i) x.digits[i] = 0;
00060 x.digits[i] = 1u << (bit_len%DIGIT_BIT);
00061 x.used = ++i;
00062
00063 /* 今、x は (2**k)**n > |<self>| なる最小の2**k */
00064
00065
00066 /* 作業領域確保 */
00067 ymp_alloca_initialize(&tmp, self->used * n + 1);
00068 ymp_alloca_initialize(&x_prev, self->used * n + 1);
00069
00070
00071 /* f(x) = x**n - |<self>| に対するNetwon法 */
00072 for (;;)
00073 {
00074 l_newton_iteration:
00075 ymp_assign(&x_prev, &x);
00076
00077 /* x_{i+1} = ((n-1) * x_i**n + a) / (n * x_i**(n-1)) */
00078 ymp_pow(&tmp, &x_prev, n-1); /* tmp = x_i ** (n-1) */
00079
00080 ymp_assign(&x, &tmp); /* x = x_i ** n */
00081 ymp_mul(&x, &x, &x_prev);
00082 ymp_mul_digit(&x, &x, n-1); /* x = (n-1) * x_i**n */
00083 ymp_add(&x, &x, self); /* (n-1) * x_i**n + a */
00084
00085 ymp_mul_digit(&tmp, &tmp, n); /* tmp = n*x_i**(n-1) */
00086
00087 ymp_div(&x, &x, &tmp); /* x = x_{i+1} */
00088
00089
00090 if (x.used != x_prev.used) continue; /* まだ誤差が大きい */
00091
00092 for (i=1; i<x.used; ++i)
00093 {
00094 if (x.digits[i] != x_prev.digits[i]) /* まだ誤差が大きい */
00095 goto l_newton_iteration; /* Newton法続行 */
00096 }
00097
00098 /* かなり収束した。現在の誤差の絶対値が1以下なら、あとは微調整 */
00099 switch ((int)(x.digits[0] - x_prev.digits[0]))
00100 {
00101 case 0:
00102 ymp_assign_abs(result, &x);
00103 return;
00104
00105 case 1:
00106 for (;;)
00107 {
00108 ymp_pow(&tmp, &x, n);
00109 if (ymp_compare_abs(&tmp, self) > 0) break;
00110 ymp_add_digit(&x, &x, 1);
00111 }
00112 ymp_sub_digit(&x, &x, 1);
00113 ymp_assign_abs(result, &x);
00114 return;
00115
00116 case -1:
00117 for (;;)
00118 {
00119 ymp_pow(&tmp, &x, n);
00120 if (ymp_compare_abs(&tmp, self) <= 0) break;
00121 ymp_sub_digit(&x, &x, 1);
00122 }
00123 ymp_assign_abs(result, &x);
00124 return;
00125 }
00126 }
00127 }
|
1.2.14 作者 Dimitri van Heesch,
© 1997-2002