00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "postgres.h"
00033 #include "px.h"
00034 #include "imath.h"
00035
00036 #undef assert
00037 #define assert(TEST) Assert(TEST)
00038 #define TRACEABLE_CLAMP 0
00039 #define TRACEABLE_FREE 0
00040
00041
00042
00043 const mp_result MP_OK = 0;
00044 const mp_result MP_FALSE = 0;
00045 const mp_result MP_TRUE = -1;
00046 const mp_result MP_MEMORY = -2;
00047 const mp_result MP_RANGE = -3;
00048 const mp_result MP_UNDEF = -4;
00049 const mp_result MP_TRUNC = -5;
00050 const mp_result MP_BADARG = -6;
00051
00052 const mp_sign MP_NEG = 1;
00053 const mp_sign MP_ZPOS = 0;
00054
00055 static const char *s_unknown_err = "unknown result code";
00056 static const char *s_error_msg[] = {
00057 "error code 0",
00058 "boolean true",
00059 "out of memory",
00060 "argument out of range",
00061 "result undefined",
00062 "output truncated",
00063 "invalid null argument",
00064 NULL
00065 };
00066
00067
00068
00069
00070 #define MP_CAP_DIGITS 1
00071
00072
00073
00074 #define CHECK(TEST) assert(TEST)
00075 #define NRCHECK(TEST) assert(TEST)
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 static const double s_log2[] = {
00086 0.000000000, 0.000000000, 1.000000000, 0.630929754,
00087 0.500000000, 0.430676558, 0.386852807, 0.356207187,
00088 0.333333333, 0.315464877, 0.301029996, 0.289064826,
00089 0.278942946, 0.270238154, 0.262649535, 0.255958025,
00090 0.250000000, 0.244650542, 0.239812467, 0.235408913,
00091 0.231378213, 0.227670249, 0.224243824, 0.221064729,
00092 0.218104292, 0.215338279, 0.212746054, 0.210309918,
00093 0.208014598, 0.205846832, 0.203795047, 0.201849087,
00094 0.200000000, 0.198239863, 0.196561632, 0.194959022,
00095 0.193426404, 0.191958720, 0.190551412, 0.189200360,
00096 0.187901825, 0.186652411, 0.185449023, 0.184288833,
00097 0.183169251, 0.182087900, 0.181042597, 0.180031327,
00098 0.179052232, 0.178103594, 0.177183820, 0.176291434,
00099 0.175425064, 0.174583430, 0.173765343, 0.172969690,
00100 0.172195434, 0.171441601, 0.170707280, 0.169991616,
00101 0.169293808, 0.168613099, 0.167948779, 0.167300179,
00102 0.166666667
00103 };
00104
00105
00106
00107
00108
00109 #define MP_VALUE_DIGITS(V) \
00110 ((sizeof(V)+(sizeof(mp_digit)-1))/sizeof(mp_digit))
00111
00112
00113 #define ROUND_PREC(P) ((mp_size)(2*(((P)+1)/2)))
00114
00115
00116 #define ZERO(P, S) \
00117 do{mp_size i__=(S)*sizeof(mp_digit);mp_digit *p__=(P);memset(p__,0,i__);}while(0)
00118
00119
00120 #define COPY(P, Q, S) \
00121 do{mp_size i__=(S)*sizeof(mp_digit);mp_digit *p__=(P),*q__=(Q);\
00122 memcpy(q__,p__,i__);}while(0)
00123
00124
00125 #define REV(T, A, N) \
00126 do{T *u_=(A),*v_=u_+(N)-1;while(u_<v_){T xch=*u_;*u_++=*v_;*v_--=xch;}}while(0)
00127
00128 #if TRACEABLE_CLAMP
00129 #define CLAMP(Z) s_clamp(Z)
00130 #else
00131 #define CLAMP(Z) \
00132 do{mp_int z_=(Z);mp_size uz_=MP_USED(z_);mp_digit *dz_=MP_DIGITS(z_)+uz_-1;\
00133 while(uz_ > 1 && (*dz_-- == 0)) --uz_;MP_USED(z_)=uz_;}while(0)
00134 #endif
00135
00136 #undef MIN
00137 #undef MAX
00138 #define MIN(A, B) ((B)<(A)?(B):(A))
00139 #define MAX(A, B) ((B)>(A)?(B):(A))
00140 #define SWAP(T, A, B) do{T t_=(A);A=(B);B=t_;}while(0)
00141
00142 #define TEMP(K) (temp + (K))
00143 #define SETUP(E, C) \
00144 do{if((res = (E)) != MP_OK) goto CLEANUP; ++(C);}while(0)
00145
00146 #define CMPZ(Z) \
00147 (((Z)->used==1&&(Z)->digits[0]==0)?0:((Z)->sign==MP_NEG)?-1:1)
00148
00149 #define UMUL(X, Y, Z) \
00150 do{mp_size ua_=MP_USED(X),ub_=MP_USED(Y);mp_size o_=ua_+ub_;\
00151 ZERO(MP_DIGITS(Z),o_);\
00152 (void) s_kmul(MP_DIGITS(X),MP_DIGITS(Y),MP_DIGITS(Z),ua_,ub_);\
00153 MP_USED(Z)=o_;CLAMP(Z);}while(0)
00154
00155 #define USQR(X, Z) \
00156 do{mp_size ua_=MP_USED(X),o_=ua_+ua_;ZERO(MP_DIGITS(Z),o_);\
00157 (void) s_ksqr(MP_DIGITS(X),MP_DIGITS(Z),ua_);MP_USED(Z)=o_;CLAMP(Z);}while(0)
00158
00159 #define UPPER_HALF(W) ((mp_word)((W) >> MP_DIGIT_BIT))
00160 #define LOWER_HALF(W) ((mp_digit)(W))
00161 #define HIGH_BIT_SET(W) ((W) >> (MP_WORD_BIT - 1))
00162 #define ADD_WILL_OVERFLOW(W, V) ((MP_WORD_MAX - (V)) < (W))
00163
00164
00165
00166
00167 static mp_size default_precision = 64;
00168
00169
00170 static mp_size multiply_threshold = 32;
00171
00172
00173 static mp_word mp_flags = MP_CAP_DIGITS;
00174
00175
00176
00177 static mp_digit *s_alloc(mp_size num);
00178
00179 #if TRACEABLE_FREE
00180 static void s_free(void *ptr);
00181 #else
00182 #define s_free(P) px_free(P)
00183 #endif
00184
00185
00186
00187 static int s_pad(mp_int z, mp_size min);
00188
00189
00190 #if TRACEABLE_CLAMP
00191 static void s_clamp(mp_int z);
00192 #endif
00193
00194
00195 static void s_fake(mp_int z, int value, mp_digit vbuf[]);
00196
00197
00198 static int s_cdig(mp_digit *da, mp_digit *db, mp_size len);
00199
00200
00201 static int s_vpack(int v, mp_digit t[]);
00202
00203
00204 static int s_ucmp(mp_int a, mp_int b);
00205
00206
00207 static int s_vcmp(mp_int a, int v);
00208
00209
00210
00211 static mp_digit s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc,
00212 mp_size size_a, mp_size size_b);
00213
00214
00215 static void s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
00216 mp_size size_a, mp_size size_b);
00217
00218
00219 static int s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
00220 mp_size size_a, mp_size size_b);
00221
00222
00223 static void s_umul(mp_digit *da, mp_digit *db, mp_digit *dc,
00224 mp_size size_a, mp_size size_b);
00225
00226
00227 static int s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a);
00228
00229
00230 static void s_usqr(mp_digit *da, mp_digit *dc, mp_size size_a);
00231
00232
00233 static void s_dadd(mp_int a, mp_digit b);
00234
00235
00236 static void s_dmul(mp_int a, mp_digit b);
00237
00238
00239 static void s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc,
00240 mp_size size_a);
00241
00242
00243
00244 static mp_digit s_ddiv(mp_int a, mp_digit b);
00245
00246
00247 static void s_qdiv(mp_int z, mp_size p2);
00248
00249
00250 static void s_qmod(mp_int z, mp_size p2);
00251
00252
00253
00254 static int s_qmul(mp_int z, mp_size p2);
00255
00256
00257
00258 static int s_qsub(mp_int z, mp_size p2);
00259
00260
00261 static int s_dp2k(mp_int z);
00262
00263
00264 static int s_isp2(mp_int z);
00265
00266
00267 static int s_2expt(mp_int z, int k);
00268
00269
00270 static int s_norm(mp_int a, mp_int b);
00271
00272
00273
00274 static mp_result s_brmu(mp_int z, mp_int m);
00275
00276
00277 static int s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2);
00278
00279
00280 static mp_result s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c);
00281
00282
00283
00284 static mp_result s_udiv(mp_int a, mp_int b);
00285
00286
00287
00288 static int s_outlen(mp_int z, mp_size r);
00289
00290
00291
00292
00293 static mp_size s_inlen(int len, mp_size r);
00294
00295
00296
00297 static int s_ch2val(char c, int r);
00298
00299
00300 static char s_val2ch(int v, int caps);
00301
00302
00303 static void s_2comp(unsigned char *buf, int len);
00304
00305
00306
00307
00308 static mp_result s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad);
00309
00310 #if 0
00311
00312 void s_print(char *tag, mp_int z);
00313 void s_print_buf(char *tag, mp_digit *buf, mp_size num);
00314 #endif
00315
00316
00317
00318 mp_size
00319 mp_get_default_precision(void)
00320 {
00321 return default_precision;
00322 }
00323
00324
00325
00326
00327
00328 void
00329 mp_set_default_precision(mp_size s)
00330 {
00331 NRCHECK(s > 0);
00332
00333 default_precision = (mp_size) ROUND_PREC(s);
00334 }
00335
00336
00337
00338
00339
00340 mp_size
00341 mp_get_multiply_threshold(void)
00342 {
00343 return multiply_threshold;
00344 }
00345
00346
00347
00348
00349
00350 void
00351 mp_set_multiply_threshold(mp_size s)
00352 {
00353 multiply_threshold = s;
00354 }
00355
00356
00357
00358
00359
00360 mp_result
00361 mp_int_init(mp_int z)
00362 {
00363 return mp_int_init_size(z, default_precision);
00364 }
00365
00366
00367
00368
00369
00370 mp_int
00371 mp_int_alloc(void)
00372 {
00373 mp_int out = px_alloc(sizeof(mpz_t));
00374
00375 assert(out != NULL);
00376 out->digits = NULL;
00377 out->used = 0;
00378 out->alloc = 0;
00379 out->sign = 0;
00380
00381 return out;
00382 }
00383
00384
00385
00386
00387
00388 mp_result
00389 mp_int_init_size(mp_int z, mp_size prec)
00390 {
00391 CHECK(z != NULL);
00392
00393 prec = (mp_size) ROUND_PREC(prec);
00394 prec = MAX(prec, default_precision);
00395
00396 if ((MP_DIGITS(z) = s_alloc(prec)) == NULL)
00397 return MP_MEMORY;
00398
00399 z->digits[0] = 0;
00400 MP_USED(z) = 1;
00401 MP_ALLOC(z) = prec;
00402 MP_SIGN(z) = MP_ZPOS;
00403
00404 return MP_OK;
00405 }
00406
00407
00408
00409
00410
00411 mp_result
00412 mp_int_init_copy(mp_int z, mp_int old)
00413 {
00414 mp_result res;
00415 mp_size uold,
00416 target;
00417
00418 CHECK(z != NULL && old != NULL);
00419
00420 uold = MP_USED(old);
00421 target = MAX(uold, default_precision);
00422
00423 if ((res = mp_int_init_size(z, target)) != MP_OK)
00424 return res;
00425
00426 MP_USED(z) = uold;
00427 MP_SIGN(z) = MP_SIGN(old);
00428 COPY(MP_DIGITS(old), MP_DIGITS(z), uold);
00429
00430 return MP_OK;
00431 }
00432
00433
00434
00435
00436
00437 mp_result
00438 mp_int_init_value(mp_int z, int value)
00439 {
00440 mp_result res;
00441
00442 CHECK(z != NULL);
00443
00444 if ((res = mp_int_init(z)) != MP_OK)
00445 return res;
00446
00447 return mp_int_set_value(z, value);
00448 }
00449
00450
00451
00452
00453
00454 mp_result
00455 mp_int_set_value(mp_int z, int value)
00456 {
00457 mp_size ndig;
00458
00459 CHECK(z != NULL);
00460
00461
00462 ndig = (mp_size) MP_VALUE_DIGITS(value);
00463
00464 if (!s_pad(z, ndig))
00465 return MP_MEMORY;
00466
00467 MP_USED(z) = (mp_size) s_vpack(value, MP_DIGITS(z));
00468 MP_SIGN(z) = (value < 0) ? MP_NEG : MP_ZPOS;
00469
00470 return MP_OK;
00471 }
00472
00473
00474
00475
00476
00477 void
00478 mp_int_clear(mp_int z)
00479 {
00480 if (z == NULL)
00481 return;
00482
00483 if (MP_DIGITS(z) != NULL)
00484 {
00485 s_free(MP_DIGITS(z));
00486 MP_DIGITS(z) = NULL;
00487 }
00488 }
00489
00490
00491
00492
00493
00494 void
00495 mp_int_free(mp_int z)
00496 {
00497 NRCHECK(z != NULL);
00498
00499 if (z->digits != NULL)
00500 mp_int_clear(z);
00501
00502 px_free(z);
00503 }
00504
00505
00506
00507
00508
00509 mp_result
00510 mp_int_copy(mp_int a, mp_int c)
00511 {
00512 CHECK(a != NULL && c != NULL);
00513
00514 if (a != c)
00515 {
00516 mp_size ua = MP_USED(a);
00517 mp_digit *da,
00518 *dc;
00519
00520 if (!s_pad(c, ua))
00521 return MP_MEMORY;
00522
00523 da = MP_DIGITS(a);
00524 dc = MP_DIGITS(c);
00525 COPY(da, dc, ua);
00526
00527 MP_USED(c) = ua;
00528 MP_SIGN(c) = MP_SIGN(a);
00529 }
00530
00531 return MP_OK;
00532 }
00533
00534
00535
00536
00537
00538 void
00539 mp_int_swap(mp_int a, mp_int c)
00540 {
00541 if (a != c)
00542 {
00543 mpz_t tmp = *a;
00544
00545 *a = *c;
00546 *c = tmp;
00547 }
00548 }
00549
00550
00551
00552
00553
00554 void
00555 mp_int_zero(mp_int z)
00556 {
00557 NRCHECK(z != NULL);
00558
00559 z->digits[0] = 0;
00560 MP_USED(z) = 1;
00561 MP_SIGN(z) = MP_ZPOS;
00562 }
00563
00564
00565
00566
00567
00568 mp_result
00569 mp_int_abs(mp_int a, mp_int c)
00570 {
00571 mp_result res;
00572
00573 CHECK(a != NULL && c != NULL);
00574
00575 if ((res = mp_int_copy(a, c)) != MP_OK)
00576 return res;
00577
00578 MP_SIGN(c) = MP_ZPOS;
00579 return MP_OK;
00580 }
00581
00582
00583
00584
00585
00586 mp_result
00587 mp_int_neg(mp_int a, mp_int c)
00588 {
00589 mp_result res;
00590
00591 CHECK(a != NULL && c != NULL);
00592
00593 if ((res = mp_int_copy(a, c)) != MP_OK)
00594 return res;
00595
00596 if (CMPZ(c) != 0)
00597 MP_SIGN(c) = 1 - MP_SIGN(a);
00598
00599 return MP_OK;
00600 }
00601
00602
00603
00604
00605
00606 mp_result
00607 mp_int_add(mp_int a, mp_int b, mp_int c)
00608 {
00609 mp_size ua,
00610 ub,
00611 uc,
00612 max;
00613
00614 CHECK(a != NULL && b != NULL && c != NULL);
00615
00616 ua = MP_USED(a);
00617 ub = MP_USED(b);
00618 uc = MP_USED(c);
00619 max = MAX(ua, ub);
00620
00621 if (MP_SIGN(a) == MP_SIGN(b))
00622 {
00623
00624 mp_digit carry;
00625
00626 if (!s_pad(c, max))
00627 return MP_MEMORY;
00628
00629 carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
00630 uc = max;
00631
00632 if (carry)
00633 {
00634 if (!s_pad(c, max + 1))
00635 return MP_MEMORY;
00636
00637 c->digits[max] = carry;
00638 ++uc;
00639 }
00640
00641 MP_USED(c) = uc;
00642 MP_SIGN(c) = MP_SIGN(a);
00643
00644 }
00645 else
00646 {
00647
00648 mp_int x,
00649 y;
00650 int cmp = s_ucmp(a, b);
00651
00652
00653 if (cmp >= 0)
00654 {
00655 x = a;
00656 y = b;
00657 }
00658 else
00659 {
00660 x = b;
00661 y = a;
00662 }
00663
00664 if (!s_pad(c, MP_USED(x)))
00665 return MP_MEMORY;
00666
00667
00668 s_usub(MP_DIGITS(x), MP_DIGITS(y), MP_DIGITS(c), MP_USED(x), MP_USED(y));
00669 MP_USED(c) = MP_USED(x);
00670 CLAMP(c);
00671
00672
00673 MP_SIGN(c) = MP_SIGN(x);
00674 }
00675
00676 return MP_OK;
00677 }
00678
00679
00680
00681
00682
00683 mp_result
00684 mp_int_add_value(mp_int a, int value, mp_int c)
00685 {
00686 mpz_t vtmp;
00687 mp_digit vbuf[MP_VALUE_DIGITS(value)];
00688
00689 s_fake(&vtmp, value, vbuf);
00690
00691 return mp_int_add(a, &vtmp, c);
00692 }
00693
00694
00695
00696
00697
00698 mp_result
00699 mp_int_sub(mp_int a, mp_int b, mp_int c)
00700 {
00701 mp_size ua,
00702 ub,
00703 uc,
00704 max;
00705
00706 CHECK(a != NULL && b != NULL && c != NULL);
00707
00708 ua = MP_USED(a);
00709 ub = MP_USED(b);
00710 uc = MP_USED(c);
00711 max = MAX(ua, ub);
00712
00713 if (MP_SIGN(a) != MP_SIGN(b))
00714 {
00715
00716 mp_digit carry;
00717
00718 if (!s_pad(c, max))
00719 return MP_MEMORY;
00720
00721 carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
00722 uc = max;
00723
00724 if (carry)
00725 {
00726 if (!s_pad(c, max + 1))
00727 return MP_MEMORY;
00728
00729 c->digits[max] = carry;
00730 ++uc;
00731 }
00732
00733 MP_USED(c) = uc;
00734 MP_SIGN(c) = MP_SIGN(a);
00735
00736 }
00737 else
00738 {
00739
00740 mp_int x,
00741 y;
00742 mp_sign osign;
00743 int cmp = s_ucmp(a, b);
00744
00745 if (!s_pad(c, max))
00746 return MP_MEMORY;
00747
00748 if (cmp >= 0)
00749 {
00750 x = a;
00751 y = b;
00752 osign = MP_ZPOS;
00753 }
00754 else
00755 {
00756 x = b;
00757 y = a;
00758 osign = MP_NEG;
00759 }
00760
00761 if (MP_SIGN(a) == MP_NEG && cmp != 0)
00762 osign = 1 - osign;
00763
00764 s_usub(MP_DIGITS(x), MP_DIGITS(y), MP_DIGITS(c), MP_USED(x), MP_USED(y));
00765 MP_USED(c) = MP_USED(x);
00766 CLAMP(c);
00767
00768 MP_SIGN(c) = osign;
00769 }
00770
00771 return MP_OK;
00772 }
00773
00774
00775
00776
00777
00778 mp_result
00779 mp_int_sub_value(mp_int a, int value, mp_int c)
00780 {
00781 mpz_t vtmp;
00782 mp_digit vbuf[MP_VALUE_DIGITS(value)];
00783
00784 s_fake(&vtmp, value, vbuf);
00785
00786 return mp_int_sub(a, &vtmp, c);
00787 }
00788
00789
00790
00791
00792
00793 mp_result
00794 mp_int_mul(mp_int a, mp_int b, mp_int c)
00795 {
00796 mp_digit *out;
00797 mp_size osize,
00798 ua,
00799 ub,
00800 p = 0;
00801 mp_sign osign;
00802
00803 CHECK(a != NULL && b != NULL && c != NULL);
00804
00805
00806 if (mp_int_compare_zero(a) == 0 || mp_int_compare_zero(b) == 0)
00807 {
00808 mp_int_zero(c);
00809 return MP_OK;
00810 }
00811
00812
00813 osign = (MP_SIGN(a) == MP_SIGN(b)) ? MP_ZPOS : MP_NEG;
00814
00815
00816
00817
00818
00819 ua = MP_USED(a);
00820 ub = MP_USED(b);
00821 osize = ua + ub;
00822
00823 if (c == a || c == b)
00824 {
00825 p = ROUND_PREC(osize);
00826 p = MAX(p, default_precision);
00827
00828 if ((out = s_alloc(p)) == NULL)
00829 return MP_MEMORY;
00830 }
00831 else
00832 {
00833 if (!s_pad(c, osize))
00834 return MP_MEMORY;
00835
00836 out = MP_DIGITS(c);
00837 }
00838 ZERO(out, osize);
00839
00840 if (!s_kmul(MP_DIGITS(a), MP_DIGITS(b), out, ua, ub))
00841 return MP_MEMORY;
00842
00843
00844
00845
00846
00847 if (out != MP_DIGITS(c))
00848 {
00849 s_free(MP_DIGITS(c));
00850 MP_DIGITS(c) = out;
00851 MP_ALLOC(c) = p;
00852 }
00853
00854 MP_USED(c) = osize;
00855 CLAMP(c);
00856 MP_SIGN(c) = osign;
00857
00858 return MP_OK;
00859 }
00860
00861
00862
00863
00864
00865 mp_result
00866 mp_int_mul_value(mp_int a, int value, mp_int c)
00867 {
00868 mpz_t vtmp;
00869 mp_digit vbuf[MP_VALUE_DIGITS(value)];
00870
00871 s_fake(&vtmp, value, vbuf);
00872
00873 return mp_int_mul(a, &vtmp, c);
00874 }
00875
00876
00877
00878
00879
00880 mp_result
00881 mp_int_mul_pow2(mp_int a, int p2, mp_int c)
00882 {
00883 mp_result res;
00884
00885 CHECK(a != NULL && c != NULL && p2 >= 0);
00886
00887 if ((res = mp_int_copy(a, c)) != MP_OK)
00888 return res;
00889
00890 if (s_qmul(c, (mp_size) p2))
00891 return MP_OK;
00892 else
00893 return MP_MEMORY;
00894 }
00895
00896
00897
00898
00899
00900 mp_result
00901 mp_int_sqr(mp_int a, mp_int c)
00902 {
00903 mp_digit *out;
00904 mp_size osize,
00905 p = 0;
00906
00907 CHECK(a != NULL && c != NULL);
00908
00909
00910 osize = (mp_size) 2 *MP_USED(a);
00911
00912 if (a == c)
00913 {
00914 p = ROUND_PREC(osize);
00915 p = MAX(p, default_precision);
00916
00917 if ((out = s_alloc(p)) == NULL)
00918 return MP_MEMORY;
00919 }
00920 else
00921 {
00922 if (!s_pad(c, osize))
00923 return MP_MEMORY;
00924
00925 out = MP_DIGITS(c);
00926 }
00927 ZERO(out, osize);
00928
00929 s_ksqr(MP_DIGITS(a), out, MP_USED(a));
00930
00931
00932
00933
00934
00935 if (out != MP_DIGITS(c))
00936 {
00937 s_free(MP_DIGITS(c));
00938 MP_DIGITS(c) = out;
00939 MP_ALLOC(c) = p;
00940 }
00941
00942 MP_USED(c) = osize;
00943 CLAMP(c);
00944 MP_SIGN(c) = MP_ZPOS;
00945
00946 return MP_OK;
00947 }
00948
00949
00950
00951
00952
00953 mp_result
00954 mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r)
00955 {
00956 int cmp,
00957 last = 0,
00958 lg;
00959 mp_result res = MP_OK;
00960 mpz_t temp[2];
00961 mp_int qout,
00962 rout;
00963 mp_sign sa = MP_SIGN(a),
00964 sb = MP_SIGN(b);
00965
00966 CHECK(a != NULL && b != NULL && q != r);
00967
00968 if (CMPZ(b) == 0)
00969 return MP_UNDEF;
00970 else if ((cmp = s_ucmp(a, b)) < 0)
00971 {
00972
00973
00974
00975 if (r && (res = mp_int_copy(a, r)) != MP_OK)
00976 return res;
00977
00978 if (q)
00979 mp_int_zero(q);
00980
00981 return MP_OK;
00982 }
00983 else if (cmp == 0)
00984 {
00985
00986
00987
00988 if (r)
00989 mp_int_zero(r);
00990
00991 if (q)
00992 {
00993 mp_int_zero(q);
00994 q->digits[0] = 1;
00995
00996 if (sa != sb)
00997 MP_SIGN(q) = MP_NEG;
00998 }
00999
01000 return MP_OK;
01001 }
01002
01003
01004
01005
01006
01007
01008 if ((lg = s_isp2(b)) < 0)
01009 {
01010 if (q && b != q && (res = mp_int_copy(a, q)) == MP_OK)
01011 {
01012 qout = q;
01013 }
01014 else
01015 {
01016 qout = TEMP(last);
01017 SETUP(mp_int_init_copy(TEMP(last), a), last);
01018 }
01019
01020 if (r && a != r && (res = mp_int_copy(b, r)) == MP_OK)
01021 {
01022 rout = r;
01023 }
01024 else
01025 {
01026 rout = TEMP(last);
01027 SETUP(mp_int_init_copy(TEMP(last), b), last);
01028 }
01029
01030 if ((res = s_udiv(qout, rout)) != MP_OK)
01031 goto CLEANUP;
01032 }
01033 else
01034 {
01035 if (q && (res = mp_int_copy(a, q)) != MP_OK)
01036 goto CLEANUP;
01037 if (r && (res = mp_int_copy(a, r)) != MP_OK)
01038 goto CLEANUP;
01039
01040 if (q)
01041 s_qdiv(q, (mp_size) lg);
01042 qout = q;
01043 if (r)
01044 s_qmod(r, (mp_size) lg);
01045 rout = r;
01046 }
01047
01048
01049 if (rout)
01050 {
01051 MP_SIGN(rout) = sa;
01052 if (CMPZ(rout) == 0)
01053 MP_SIGN(rout) = MP_ZPOS;
01054 }
01055 if (qout)
01056 {
01057 MP_SIGN(qout) = (sa == sb) ? MP_ZPOS : MP_NEG;
01058 if (CMPZ(qout) == 0)
01059 MP_SIGN(qout) = MP_ZPOS;
01060 }
01061
01062 if (q && (res = mp_int_copy(qout, q)) != MP_OK)
01063 goto CLEANUP;
01064 if (r && (res = mp_int_copy(rout, r)) != MP_OK)
01065 goto CLEANUP;
01066
01067 CLEANUP:
01068 while (--last >= 0)
01069 mp_int_clear(TEMP(last));
01070
01071 return res;
01072 }
01073
01074
01075
01076
01077
01078 mp_result
01079 mp_int_mod(mp_int a, mp_int m, mp_int c)
01080 {
01081 mp_result res;
01082 mpz_t tmp;
01083 mp_int out;
01084
01085 if (m == c)
01086 {
01087 if ((res = mp_int_init(&tmp)) != MP_OK)
01088 return res;
01089
01090 out = &tmp;
01091 }
01092 else
01093 {
01094 out = c;
01095 }
01096
01097 if ((res = mp_int_div(a, m, NULL, out)) != MP_OK)
01098 goto CLEANUP;
01099
01100 if (CMPZ(out) < 0)
01101 res = mp_int_add(out, m, c);
01102 else
01103 res = mp_int_copy(out, c);
01104
01105 CLEANUP:
01106 if (out != c)
01107 mp_int_clear(&tmp);
01108
01109 return res;
01110 }
01111
01112
01113
01114
01115
01116
01117 mp_result
01118 mp_int_div_value(mp_int a, int value, mp_int q, int *r)
01119 {
01120 mpz_t vtmp,
01121 rtmp;
01122 mp_digit vbuf[MP_VALUE_DIGITS(value)];
01123 mp_result res;
01124
01125 if ((res = mp_int_init(&rtmp)) != MP_OK)
01126 return res;
01127 s_fake(&vtmp, value, vbuf);
01128
01129 if ((res = mp_int_div(a, &vtmp, q, &rtmp)) != MP_OK)
01130 goto CLEANUP;
01131
01132 if (r)
01133 (void) mp_int_to_int(&rtmp, r);
01134
01135 CLEANUP:
01136 mp_int_clear(&rtmp);
01137 return res;
01138 }
01139
01140
01141
01142
01143
01144 mp_result
01145 mp_int_div_pow2(mp_int a, int p2, mp_int q, mp_int r)
01146 {
01147 mp_result res = MP_OK;
01148
01149 CHECK(a != NULL && p2 >= 0 && q != r);
01150
01151 if (q != NULL && (res = mp_int_copy(a, q)) == MP_OK)
01152 s_qdiv(q, (mp_size) p2);
01153
01154 if (res == MP_OK && r != NULL && (res = mp_int_copy(a, r)) == MP_OK)
01155 s_qmod(r, (mp_size) p2);
01156
01157 return res;
01158 }
01159
01160
01161
01162
01163
01164 mp_result
01165 mp_int_expt(mp_int a, int b, mp_int c)
01166 {
01167 mpz_t t;
01168 mp_result res;
01169 unsigned int v = abs(b);
01170
01171 CHECK(b >= 0 && c != NULL);
01172
01173 if ((res = mp_int_init_copy(&t, a)) != MP_OK)
01174 return res;
01175
01176 (void) mp_int_set_value(c, 1);
01177 while (v != 0)
01178 {
01179 if (v & 1)
01180 {
01181 if ((res = mp_int_mul(c, &t, c)) != MP_OK)
01182 goto CLEANUP;
01183 }
01184
01185 v >>= 1;
01186 if (v == 0)
01187 break;
01188
01189 if ((res = mp_int_sqr(&t, &t)) != MP_OK)
01190 goto CLEANUP;
01191 }
01192
01193 CLEANUP:
01194 mp_int_clear(&t);
01195 return res;
01196 }
01197
01198
01199
01200
01201
01202 mp_result
01203 mp_int_expt_value(int a, int b, mp_int c)
01204 {
01205 mpz_t t;
01206 mp_result res;
01207 unsigned int v = abs(b);
01208
01209 CHECK(b >= 0 && c != NULL);
01210
01211 if ((res = mp_int_init_value(&t, a)) != MP_OK)
01212 return res;
01213
01214 (void) mp_int_set_value(c, 1);
01215 while (v != 0)
01216 {
01217 if (v & 1)
01218 {
01219 if ((res = mp_int_mul(c, &t, c)) != MP_OK)
01220 goto CLEANUP;
01221 }
01222
01223 v >>= 1;
01224 if (v == 0)
01225 break;
01226
01227 if ((res = mp_int_sqr(&t, &t)) != MP_OK)
01228 goto CLEANUP;
01229 }
01230
01231 CLEANUP:
01232 mp_int_clear(&t);
01233 return res;
01234 }
01235
01236
01237
01238
01239
01240 int
01241 mp_int_compare(mp_int a, mp_int b)
01242 {
01243 mp_sign sa;
01244
01245 CHECK(a != NULL && b != NULL);
01246
01247 sa = MP_SIGN(a);
01248 if (sa == MP_SIGN(b))
01249 {
01250 int cmp = s_ucmp(a, b);
01251
01252
01253
01254
01255
01256 if (sa == MP_ZPOS)
01257 return cmp;
01258 else
01259 return -cmp;
01260
01261 }
01262 else
01263 {
01264 if (sa == MP_ZPOS)
01265 return 1;
01266 else
01267 return -1;
01268 }
01269 }
01270
01271
01272
01273
01274
01275 int
01276 mp_int_compare_unsigned(mp_int a, mp_int b)
01277 {
01278 NRCHECK(a != NULL && b != NULL);
01279
01280 return s_ucmp(a, b);
01281 }
01282
01283
01284
01285
01286
01287 int
01288 mp_int_compare_zero(mp_int z)
01289 {
01290 NRCHECK(z != NULL);
01291
01292 if (MP_USED(z) == 1 && z->digits[0] == 0)
01293 return 0;
01294 else if (MP_SIGN(z) == MP_ZPOS)
01295 return 1;
01296 else
01297 return -1;
01298 }
01299
01300
01301
01302
01303
01304 int
01305 mp_int_compare_value(mp_int z, int value)
01306 {
01307 mp_sign vsign = (value < 0) ? MP_NEG : MP_ZPOS;
01308 int cmp;
01309
01310 CHECK(z != NULL);
01311
01312 if (vsign == MP_SIGN(z))
01313 {
01314 cmp = s_vcmp(z, value);
01315
01316 if (vsign == MP_ZPOS)
01317 return cmp;
01318 else
01319 return -cmp;
01320 }
01321 else
01322 {
01323 if (value < 0)
01324 return 1;
01325 else
01326 return -1;
01327 }
01328 }
01329
01330
01331
01332
01333
01334 mp_result
01335 mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c)
01336 {
01337 mp_result res;
01338 mp_size um;
01339 mpz_t temp[3];
01340 mp_int s;
01341 int last = 0;
01342
01343 CHECK(a != NULL && b != NULL && c != NULL && m != NULL);
01344
01345
01346 if (CMPZ(m) == 0)
01347 return MP_UNDEF;
01348 if (CMPZ(b) < 0)
01349 return MP_RANGE;
01350
01351 um = MP_USED(m);
01352 SETUP(mp_int_init_size(TEMP(0), 2 * um), last);
01353 SETUP(mp_int_init_size(TEMP(1), 2 * um), last);
01354
01355 if (c == b || c == m)
01356 {
01357 SETUP(mp_int_init_size(TEMP(2), 2 * um), last);
01358 s = TEMP(2);
01359 }
01360 else
01361 {
01362 s = c;
01363 }
01364
01365 if ((res = mp_int_mod(a, m, TEMP(0))) != MP_OK)
01366 goto CLEANUP;
01367
01368 if ((res = s_brmu(TEMP(1), m)) != MP_OK)
01369 goto CLEANUP;
01370
01371 if ((res = s_embar(TEMP(0), b, m, TEMP(1), s)) != MP_OK)
01372 goto CLEANUP;
01373
01374 res = mp_int_copy(s, c);
01375
01376 CLEANUP:
01377 while (--last >= 0)
01378 mp_int_clear(TEMP(last));
01379
01380 return res;
01381 }
01382
01383
01384
01385
01386
01387 mp_result
01388 mp_int_exptmod_evalue(mp_int a, int value, mp_int m, mp_int c)
01389 {
01390 mpz_t vtmp;
01391 mp_digit vbuf[MP_VALUE_DIGITS(value)];
01392
01393 s_fake(&vtmp, value, vbuf);
01394
01395 return mp_int_exptmod(a, &vtmp, m, c);
01396 }
01397
01398
01399
01400
01401
01402 mp_result
01403 mp_int_exptmod_bvalue(int value, mp_int b,
01404 mp_int m, mp_int c)
01405 {
01406 mpz_t vtmp;
01407 mp_digit vbuf[MP_VALUE_DIGITS(value)];
01408
01409 s_fake(&vtmp, value, vbuf);
01410
01411 return mp_int_exptmod(&vtmp, b, m, c);
01412 }
01413
01414
01415
01416
01417
01418 mp_result
01419 mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
01420 {
01421 mp_result res;
01422 mp_size um;
01423 mpz_t temp[2];
01424 mp_int s;
01425 int last = 0;
01426
01427 CHECK(a && b && m && c);
01428
01429
01430 if (CMPZ(m) == 0)
01431 return MP_UNDEF;
01432 if (CMPZ(b) < 0)
01433 return MP_RANGE;
01434
01435 um = MP_USED(m);
01436 SETUP(mp_int_init_size(TEMP(0), 2 * um), last);
01437
01438 if (c == b || c == m)
01439 {
01440 SETUP(mp_int_init_size(TEMP(1), 2 * um), last);
01441 s = TEMP(1);
01442 }
01443 else
01444 {
01445 s = c;
01446 }
01447
01448 if ((res = mp_int_mod(a, m, TEMP(0))) != MP_OK)
01449 goto CLEANUP;
01450
01451 if ((res = s_embar(TEMP(0), b, m, mu, s)) != MP_OK)
01452 goto CLEANUP;
01453
01454 res = mp_int_copy(s, c);
01455
01456 CLEANUP:
01457 while (--last >= 0)
01458 mp_int_clear(TEMP(last));
01459
01460 return res;
01461 }
01462
01463
01464
01465
01466
01467 mp_result
01468 mp_int_redux_const(mp_int m, mp_int c)
01469 {
01470 CHECK(m != NULL && c != NULL && m != c);
01471
01472 return s_brmu(c, m);
01473 }
01474
01475
01476
01477
01478
01479 mp_result
01480 mp_int_invmod(mp_int a, mp_int m, mp_int c)
01481 {
01482 mp_result res;
01483 mp_sign sa;
01484 int last = 0;
01485 mpz_t temp[2];
01486
01487 CHECK(a != NULL && m != NULL && c != NULL);
01488
01489 if (CMPZ(a) == 0 || CMPZ(m) <= 0)
01490 return MP_RANGE;
01491
01492 sa = MP_SIGN(a);
01493
01494 for (last = 0; last < 2; ++last)
01495 if ((res = mp_int_init(TEMP(last))) != MP_OK)
01496 goto CLEANUP;
01497
01498 if ((res = mp_int_egcd(a, m, TEMP(0), TEMP(1), NULL)) != MP_OK)
01499 goto CLEANUP;
01500
01501 if (mp_int_compare_value(TEMP(0), 1) != 0)
01502 {
01503 res = MP_UNDEF;
01504 goto CLEANUP;
01505 }
01506
01507
01508 if ((res = mp_int_mod(TEMP(1), m, TEMP(1))) != MP_OK)
01509 goto CLEANUP;
01510
01511
01512
01513
01514
01515
01516
01517 if (sa == MP_NEG)
01518 res = mp_int_sub(m, TEMP(1), c);
01519 else
01520 res = mp_int_copy(TEMP(1), c);
01521
01522 CLEANUP:
01523 while (--last >= 0)
01524 mp_int_clear(TEMP(last));
01525
01526 return res;
01527 }
01528
01529
01530
01531
01532
01533
01534 mp_result
01535 mp_int_gcd(mp_int a, mp_int b, mp_int c)
01536 {
01537 int ca,
01538 cb,
01539 k = 0;
01540 mpz_t u,
01541 v,
01542 t;
01543 mp_result res;
01544
01545 CHECK(a != NULL && b != NULL && c != NULL);
01546
01547 ca = CMPZ(a);
01548 cb = CMPZ(b);
01549 if (ca == 0 && cb == 0)
01550 return MP_UNDEF;
01551 else if (ca == 0)
01552 return mp_int_abs(b, c);
01553 else if (cb == 0)
01554 return mp_int_abs(a, c);
01555
01556 if ((res = mp_int_init(&t)) != MP_OK)
01557 return res;
01558 if ((res = mp_int_init_copy(&u, a)) != MP_OK)
01559 goto U;
01560 if ((res = mp_int_init_copy(&v, b)) != MP_OK)
01561 goto V;
01562
01563 MP_SIGN(&u) = MP_ZPOS;
01564 MP_SIGN(&v) = MP_ZPOS;
01565
01566 {
01567 int div2_u = s_dp2k(&u),
01568 div2_v = s_dp2k(&v);
01569
01570 k = MIN(div2_u, div2_v);
01571 s_qdiv(&u, (mp_size) k);
01572 s_qdiv(&v, (mp_size) k);
01573 }
01574
01575 if (mp_int_is_odd(&u))
01576 {
01577 if ((res = mp_int_neg(&v, &t)) != MP_OK)
01578 goto CLEANUP;
01579 }
01580 else
01581 {
01582 if ((res = mp_int_copy(&u, &t)) != MP_OK)
01583 goto CLEANUP;
01584 }
01585
01586 for (;;)
01587 {
01588 s_qdiv(&t, s_dp2k(&t));
01589
01590 if (CMPZ(&t) > 0)
01591 {
01592 if ((res = mp_int_copy(&t, &u)) != MP_OK)
01593 goto CLEANUP;
01594 }
01595 else
01596 {
01597 if ((res = mp_int_neg(&t, &v)) != MP_OK)
01598 goto CLEANUP;
01599 }
01600
01601 if ((res = mp_int_sub(&u, &v, &t)) != MP_OK)
01602 goto CLEANUP;
01603
01604 if (CMPZ(&t) == 0)
01605 break;
01606 }
01607
01608 if ((res = mp_int_abs(&u, c)) != MP_OK)
01609 goto CLEANUP;
01610 if (!s_qmul(c, (mp_size) k))
01611 res = MP_MEMORY;
01612
01613 CLEANUP:
01614 mp_int_clear(&v);
01615 V: mp_int_clear(&u);
01616 U: mp_int_clear(&t);
01617
01618 return res;
01619 }
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629 mp_result
01630 mp_int_egcd(mp_int a, mp_int b, mp_int c,
01631 mp_int x, mp_int y)
01632 {
01633 int k,
01634 last = 0,
01635 ca,
01636 cb;
01637 mpz_t temp[8];
01638 mp_result res;
01639
01640 CHECK(a != NULL && b != NULL && c != NULL &&
01641 (x != NULL || y != NULL));
01642
01643 ca = CMPZ(a);
01644 cb = CMPZ(b);
01645 if (ca == 0 && cb == 0)
01646 return MP_UNDEF;
01647 else if (ca == 0)
01648 {
01649 if ((res = mp_int_abs(b, c)) != MP_OK)
01650 return res;
01651 mp_int_zero(x);
01652 (void) mp_int_set_value(y, 1);
01653 return MP_OK;
01654 }
01655 else if (cb == 0)
01656 {
01657 if ((res = mp_int_abs(a, c)) != MP_OK)
01658 return res;
01659 (void) mp_int_set_value(x, 1);
01660 mp_int_zero(y);
01661 return MP_OK;
01662 }
01663
01664
01665
01666
01667 for (last = 0; last < 4; ++last)
01668 {
01669 if ((res = mp_int_init(TEMP(last))) != MP_OK)
01670 goto CLEANUP;
01671 }
01672 TEMP(0)->digits[0] = 1;
01673 TEMP(3)->digits[0] = 1;
01674
01675 SETUP(mp_int_init_copy(TEMP(4), a), last);
01676 SETUP(mp_int_init_copy(TEMP(5), b), last);
01677
01678
01679 MP_SIGN(TEMP(4)) = MP_ZPOS;
01680 MP_SIGN(TEMP(5)) = MP_ZPOS;
01681
01682 {
01683 int div2_u = s_dp2k(TEMP(4)),
01684 div2_v = s_dp2k(TEMP(5));
01685
01686 k = MIN(div2_u, div2_v);
01687 s_qdiv(TEMP(4), k);
01688 s_qdiv(TEMP(5), k);
01689 }
01690
01691 SETUP(mp_int_init_copy(TEMP(6), TEMP(4)), last);
01692 SETUP(mp_int_init_copy(TEMP(7), TEMP(5)), last);
01693
01694 for (;;)
01695 {
01696 while (mp_int_is_even(TEMP(4)))
01697 {
01698 s_qdiv(TEMP(4), 1);
01699
01700 if (mp_int_is_odd(TEMP(0)) || mp_int_is_odd(TEMP(1)))
01701 {
01702 if ((res = mp_int_add(TEMP(0), TEMP(7), TEMP(0))) != MP_OK)
01703 goto CLEANUP;
01704 if ((res = mp_int_sub(TEMP(1), TEMP(6), TEMP(1))) != MP_OK)
01705 goto CLEANUP;
01706 }
01707
01708 s_qdiv(TEMP(0), 1);
01709 s_qdiv(TEMP(1), 1);
01710 }
01711
01712 while (mp_int_is_even(TEMP(5)))
01713 {
01714 s_qdiv(TEMP(5), 1);
01715
01716 if (mp_int_is_odd(TEMP(2)) || mp_int_is_odd(TEMP(3)))
01717 {
01718 if ((res = mp_int_add(TEMP(2), TEMP(7), TEMP(2))) != MP_OK)
01719 goto CLEANUP;
01720 if ((res = mp_int_sub(TEMP(3), TEMP(6), TEMP(3))) != MP_OK)
01721 goto CLEANUP;
01722 }
01723
01724 s_qdiv(TEMP(2), 1);
01725 s_qdiv(TEMP(3), 1);
01726 }
01727
01728 if (mp_int_compare(TEMP(4), TEMP(5)) >= 0)
01729 {
01730 if ((res = mp_int_sub(TEMP(4), TEMP(5), TEMP(4))) != MP_OK)
01731 goto CLEANUP;
01732 if ((res = mp_int_sub(TEMP(0), TEMP(2), TEMP(0))) != MP_OK)
01733 goto CLEANUP;
01734 if ((res = mp_int_sub(TEMP(1), TEMP(3), TEMP(1))) != MP_OK)
01735 goto CLEANUP;
01736 }
01737 else
01738 {
01739 if ((res = mp_int_sub(TEMP(5), TEMP(4), TEMP(5))) != MP_OK)
01740 goto CLEANUP;
01741 if ((res = mp_int_sub(TEMP(2), TEMP(0), TEMP(2))) != MP_OK)
01742 goto CLEANUP;
01743 if ((res = mp_int_sub(TEMP(3), TEMP(1), TEMP(3))) != MP_OK)
01744 goto CLEANUP;
01745 }
01746
01747 if (CMPZ(TEMP(4)) == 0)
01748 {
01749 if (x && (res = mp_int_copy(TEMP(2), x)) != MP_OK)
01750 goto CLEANUP;
01751 if (y && (res = mp_int_copy(TEMP(3), y)) != MP_OK)
01752 goto CLEANUP;
01753 if (c)
01754 {
01755 if (!s_qmul(TEMP(5), k))
01756 {
01757 res = MP_MEMORY;
01758 goto CLEANUP;
01759 }
01760
01761 res = mp_int_copy(TEMP(5), c);
01762 }
01763
01764 break;
01765 }
01766 }
01767
01768 CLEANUP:
01769 while (--last >= 0)
01770 mp_int_clear(TEMP(last));
01771
01772 return res;
01773 }
01774
01775
01776
01777
01778
01779 int
01780 mp_int_divisible_value(mp_int a, int v)
01781 {
01782 int rem = 0;
01783
01784 if (mp_int_div_value(a, v, NULL, &rem) != MP_OK)
01785 return 0;
01786
01787 return rem == 0;
01788 }
01789
01790
01791
01792
01793
01794 int
01795 mp_int_is_pow2(mp_int z)
01796 {
01797 CHECK(z != NULL);
01798
01799 return s_isp2(z);
01800 }
01801
01802
01803
01804
01805
01806 mp_result
01807 mp_int_sqrt(mp_int a, mp_int c)
01808 {
01809 mp_result res = MP_OK;
01810 mpz_t temp[2];
01811 int last = 0;
01812
01813 CHECK(a != NULL && c != NULL);
01814
01815
01816 if (MP_SIGN(a) == MP_NEG)
01817 return MP_UNDEF;
01818
01819 SETUP(mp_int_init_copy(TEMP(last), a), last);
01820 SETUP(mp_int_init(TEMP(last)), last);
01821
01822 for (;;)
01823 {
01824 if ((res = mp_int_sqr(TEMP(0), TEMP(1))) != MP_OK)
01825 goto CLEANUP;
01826
01827 if (mp_int_compare_unsigned(a, TEMP(1)) == 0)
01828 break;
01829
01830 if ((res = mp_int_copy(a, TEMP(1))) != MP_OK)
01831 goto CLEANUP;
01832 if ((res = mp_int_div(TEMP(1), TEMP(0), TEMP(1), NULL)) != MP_OK)
01833 goto CLEANUP;
01834 if ((res = mp_int_add(TEMP(0), TEMP(1), TEMP(1))) != MP_OK)
01835 goto CLEANUP;
01836 if ((res = mp_int_div_pow2(TEMP(1), 1, TEMP(1), NULL)) != MP_OK)
01837 goto CLEANUP;
01838
01839 if (mp_int_compare_unsigned(TEMP(0), TEMP(1)) == 0)
01840 break;
01841 if ((res = mp_int_sub_value(TEMP(0), 1, TEMP(0))) != MP_OK)
01842 goto CLEANUP;
01843 if (mp_int_compare_unsigned(TEMP(0), TEMP(1)) == 0)
01844 break;
01845
01846 if ((res = mp_int_copy(TEMP(1), TEMP(0))) != MP_OK)
01847 goto CLEANUP;
01848 }
01849
01850 res = mp_int_copy(TEMP(0), c);
01851
01852 CLEANUP:
01853 while (--last >= 0)
01854 mp_int_clear(TEMP(last));
01855
01856 return res;
01857 }
01858
01859
01860
01861
01862
01863 mp_result
01864 mp_int_to_int(mp_int z, int *out)
01865 {
01866 unsigned int uv = 0;
01867 mp_size uz;
01868 mp_digit *dz;
01869 mp_sign sz;
01870
01871 CHECK(z != NULL);
01872
01873
01874 sz = MP_SIGN(z);
01875 if ((sz == MP_ZPOS && mp_int_compare_value(z, INT_MAX) > 0) ||
01876 mp_int_compare_value(z, INT_MIN) < 0)
01877 return MP_RANGE;
01878
01879 uz = MP_USED(z);
01880 dz = MP_DIGITS(z) + uz - 1;
01881
01882 while (uz > 0)
01883 {
01884 uv <<= MP_DIGIT_BIT / 2;
01885 uv = (uv << (MP_DIGIT_BIT / 2)) | *dz--;
01886 --uz;
01887 }
01888
01889 if (out)
01890 *out = (sz == MP_NEG) ? -(int) uv : (int) uv;
01891
01892 return MP_OK;
01893 }
01894
01895
01896
01897
01898
01899 mp_result
01900 mp_int_to_string(mp_int z, mp_size radix,
01901 char *str, int limit)
01902 {
01903 mp_result res;
01904 int cmp = 0;
01905
01906 CHECK(z != NULL && str != NULL && limit >= 2);
01907
01908 if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
01909 return MP_RANGE;
01910
01911 if (CMPZ(z) == 0)
01912 {
01913 *str++ = s_val2ch(0, mp_flags & MP_CAP_DIGITS);
01914 }
01915 else
01916 {
01917 mpz_t tmp;
01918 char *h,
01919 *t;
01920
01921 if ((res = mp_int_init_copy(&tmp, z)) != MP_OK)
01922 return res;
01923
01924 if (MP_SIGN(z) == MP_NEG)
01925 {
01926 *str++ = '-';
01927 --limit;
01928 }
01929 h = str;
01930
01931
01932 for ( ; limit > 0; --limit)
01933 {
01934 mp_digit d;
01935
01936 if ((cmp = CMPZ(&tmp)) == 0)
01937 break;
01938
01939 d = s_ddiv(&tmp, (mp_digit) radix);
01940 *str++ = s_val2ch(d, mp_flags & MP_CAP_DIGITS);
01941 }
01942 t = str - 1;
01943
01944
01945 while (h < t)
01946 {
01947 char tc = *h;
01948
01949 *h++ = *t;
01950 *t-- = tc;
01951 }
01952
01953 mp_int_clear(&tmp);
01954 }
01955
01956 *str = '\0';
01957 if (cmp == 0)
01958 return MP_OK;
01959 else
01960 return MP_TRUNC;
01961 }
01962
01963
01964
01965
01966
01967 mp_result
01968 mp_int_string_len(mp_int z, mp_size radix)
01969 {
01970 int len;
01971
01972 CHECK(z != NULL);
01973
01974 if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
01975 return MP_RANGE;
01976
01977 len = s_outlen(z, radix) + 1;
01978
01979
01980 if (MP_SIGN(z) == MP_NEG)
01981 len += 1;
01982
01983 return len;
01984 }
01985
01986
01987
01988
01989
01990
01991 mp_result
01992 mp_int_read_string(mp_int z, mp_size radix, const char *str)
01993 {
01994 return mp_int_read_cstring(z, radix, str, NULL);
01995
01996 }
01997
01998
01999
02000
02001
02002 mp_result
02003 mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
02004 {
02005 int ch;
02006
02007 CHECK(z != NULL && str != NULL);
02008
02009 if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
02010 return MP_RANGE;
02011
02012
02013 while (isspace((unsigned char) *str))
02014 ++str;
02015
02016
02017 switch (*str)
02018 {
02019 case '-':
02020 MP_SIGN(z) = MP_NEG;
02021 ++str;
02022 break;
02023 case '+':
02024 ++str;
02025 default:
02026 MP_SIGN(z) = MP_ZPOS;
02027 break;
02028 }
02029
02030
02031 while ((ch = s_ch2val(*str, radix)) == 0)
02032 ++str;
02033
02034
02035 if (!s_pad(z, s_inlen(strlen(str), radix)))
02036 return MP_MEMORY;
02037
02038 MP_USED(z) = 1;
02039 z->digits[0] = 0;
02040
02041 while (*str != '\0' && ((ch = s_ch2val(*str, radix)) >= 0))
02042 {
02043 s_dmul(z, (mp_digit) radix);
02044 s_dadd(z, (mp_digit) ch);
02045 ++str;
02046 }
02047
02048 CLAMP(z);
02049
02050
02051 if (CMPZ(z) == 0)
02052 MP_SIGN(z) = MP_ZPOS;
02053
02054 if (end != NULL)
02055 *end = (char *) str;
02056
02057
02058
02059
02060
02061 if (*str != '\0')
02062 return MP_TRUNC;
02063 else
02064 return MP_OK;
02065 }
02066
02067
02068
02069
02070
02071 mp_result
02072 mp_int_count_bits(mp_int z)
02073 {
02074 mp_size nbits = 0,
02075 uz;
02076 mp_digit d;
02077
02078 CHECK(z != NULL);
02079
02080 uz = MP_USED(z);
02081 if (uz == 1 && z->digits[0] == 0)
02082 return 1;
02083
02084 --uz;
02085 nbits = uz * MP_DIGIT_BIT;
02086 d = z->digits[uz];
02087
02088 while (d != 0)
02089 {
02090 d >>= 1;
02091 ++nbits;
02092 }
02093
02094 return nbits;
02095 }
02096
02097
02098
02099
02100
02101 mp_result
02102 mp_int_to_binary(mp_int z, unsigned char *buf, int limit)
02103 {
02104 static const int PAD_FOR_2C = 1;
02105
02106 mp_result res;
02107 int limpos = limit;
02108
02109 CHECK(z != NULL && buf != NULL);
02110
02111 res = s_tobin(z, buf, &limpos, PAD_FOR_2C);
02112
02113 if (MP_SIGN(z) == MP_NEG)
02114 s_2comp(buf, limpos);
02115
02116 return res;
02117 }
02118
02119
02120
02121
02122
02123 mp_result
02124 mp_int_read_binary(mp_int z, unsigned char *buf, int len)
02125 {
02126 mp_size need,
02127 i;
02128 unsigned char *tmp;
02129 mp_digit *dz;
02130
02131 CHECK(z != NULL && buf != NULL && len > 0);
02132
02133
02134 need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
02135 if (!s_pad(z, need))
02136 return MP_MEMORY;
02137
02138 mp_int_zero(z);
02139
02140
02141
02142
02143
02144 if (buf[0] >> (CHAR_BIT - 1))
02145 {
02146 MP_SIGN(z) = MP_NEG;
02147 s_2comp(buf, len);
02148 }
02149
02150 dz = MP_DIGITS(z);
02151 for (tmp = buf, i = len; i > 0; --i, ++tmp)
02152 {
02153 s_qmul(z, (mp_size) CHAR_BIT);
02154 *dz |= *tmp;
02155 }
02156
02157
02158 if (MP_SIGN(z) == MP_NEG)
02159 s_2comp(buf, len);
02160
02161 return MP_OK;
02162 }
02163
02164
02165
02166
02167
02168 mp_result
02169 mp_int_binary_len(mp_int z)
02170 {
02171 mp_result res = mp_int_count_bits(z);
02172 int bytes = mp_int_unsigned_len(z);
02173
02174 if (res <= 0)
02175 return res;
02176
02177 bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT;
02178
02179
02180
02181
02182
02183
02184 if (bytes * CHAR_BIT == res)
02185 ++bytes;
02186
02187 return bytes;
02188 }
02189
02190
02191
02192
02193
02194 mp_result
02195 mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit)
02196 {
02197 static const int NO_PADDING = 0;
02198
02199 CHECK(z != NULL && buf != NULL);
02200
02201 return s_tobin(z, buf, &limit, NO_PADDING);
02202 }
02203
02204
02205
02206
02207
02208 mp_result
02209 mp_int_read_unsigned(mp_int z, unsigned char *buf, int len)
02210 {
02211 mp_size need,
02212 i;
02213 unsigned char *tmp;
02214 mp_digit *dz;
02215
02216 CHECK(z != NULL && buf != NULL && len > 0);
02217
02218
02219 need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
02220 if (!s_pad(z, need))
02221 return MP_MEMORY;
02222
02223 mp_int_zero(z);
02224
02225 dz = MP_DIGITS(z);
02226 for (tmp = buf, i = len; i > 0; --i, ++tmp)
02227 {
02228 (void) s_qmul(z, CHAR_BIT);
02229 *dz |= *tmp;
02230 }
02231
02232 return MP_OK;
02233 }
02234
02235
02236
02237
02238
02239 mp_result
02240 mp_int_unsigned_len(mp_int z)
02241 {
02242 mp_result res = mp_int_count_bits(z);
02243 int bytes;
02244
02245 if (res <= 0)
02246 return res;
02247
02248 bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT;
02249
02250 return bytes;
02251 }
02252
02253
02254
02255
02256
02257 const char *
02258 mp_error_string(mp_result res)
02259 {
02260 int ix;
02261
02262 if (res > 0)
02263 return s_unknown_err;
02264
02265 res = -res;
02266 for (ix = 0; ix < res && s_error_msg[ix] != NULL; ++ix)
02267 ;
02268
02269 if (s_error_msg[ix] != NULL)
02270 return s_error_msg[ix];
02271 else
02272 return s_unknown_err;
02273 }
02274
02275
02276
02277
02278
02279
02280
02281
02282 static mp_digit *
02283 s_alloc(mp_size num)
02284 {
02285 mp_digit *out = px_alloc(num * sizeof(mp_digit));
02286
02287 assert(out != NULL);
02288
02289 return out;
02290 }
02291
02292
02293
02294
02295
02296 static mp_digit *
02297 s_realloc(mp_digit *old, mp_size num)
02298 {
02299 mp_digit *new = px_realloc(old, num * sizeof(mp_digit));
02300
02301 assert(new != NULL);
02302
02303 return new;
02304 }
02305
02306
02307
02308
02309
02310 #if TRACEABLE_FREE
02311 static void
02312 s_free(void *ptr)
02313 {
02314 px_free(ptr);
02315 }
02316 #endif
02317
02318
02319
02320
02321
02322 static int
02323 s_pad(mp_int z, mp_size min)
02324 {
02325 if (MP_ALLOC(z) < min)
02326 {
02327 mp_size nsize = ROUND_PREC(min);
02328 mp_digit *tmp = s_realloc(MP_DIGITS(z), nsize);
02329
02330 if (tmp == NULL)
02331 return 0;
02332
02333 MP_DIGITS(z) = tmp;
02334 MP_ALLOC(z) = nsize;
02335 }
02336
02337 return 1;
02338 }
02339
02340
02341
02342
02343
02344 #if TRACEABLE_CLAMP
02345 static void
02346 s_clamp(mp_int z)
02347 {
02348 mp_size uz = MP_USED(z);
02349 mp_digit *zd = MP_DIGITS(z) + uz - 1;
02350
02351 while (uz > 1 && (*zd-- == 0))
02352 --uz;
02353
02354 MP_USED(z) = uz;
02355 }
02356 #endif
02357
02358
02359
02360
02361
02362 static void
02363 s_fake(mp_int z, int value, mp_digit vbuf[])
02364 {
02365 mp_size uv = (mp_size) s_vpack(value, vbuf);
02366
02367 z->used = uv;
02368 z->alloc = MP_VALUE_DIGITS(value);
02369 z->sign = (value < 0) ? MP_NEG : MP_ZPOS;
02370 z->digits = vbuf;
02371 }
02372
02373
02374
02375
02376
02377 static int
02378 s_cdig(mp_digit *da, mp_digit *db, mp_size len)
02379 {
02380 mp_digit *dat = da + len - 1,
02381 *dbt = db + len - 1;
02382
02383 for ( ; len != 0; --len, --dat, --dbt)
02384 {
02385 if (*dat > *dbt)
02386 return 1;
02387 else if (*dat < *dbt)
02388 return -1;
02389 }
02390
02391 return 0;
02392 }
02393
02394
02395
02396
02397
02398 static int
02399 s_vpack(int v, mp_digit t[])
02400 {
02401 unsigned int uv = (unsigned int) ((v < 0) ? -v : v);
02402 int ndig = 0;
02403
02404 if (uv == 0)
02405 t[ndig++] = 0;
02406 else
02407 {
02408 while (uv != 0)
02409 {
02410 t[ndig++] = (mp_digit) uv;
02411 uv >>= MP_DIGIT_BIT / 2;
02412 uv >>= MP_DIGIT_BIT / 2;
02413 }
02414 }
02415
02416 return ndig;
02417 }
02418
02419
02420
02421
02422
02423 static int
02424 s_ucmp(mp_int a, mp_int b)
02425 {
02426 mp_size ua = MP_USED(a),
02427 ub = MP_USED(b);
02428
02429 if (ua > ub)
02430 return 1;
02431 else if (ub > ua)
02432 return -1;
02433 else
02434 return s_cdig(MP_DIGITS(a), MP_DIGITS(b), ua);
02435 }
02436
02437
02438
02439
02440
02441 static int
02442 s_vcmp(mp_int a, int v)
02443 {
02444 mp_digit vdig[MP_VALUE_DIGITS(v)];
02445 int ndig = 0;
02446 mp_size ua = MP_USED(a);
02447
02448 ndig = s_vpack(v, vdig);
02449
02450 if (ua > ndig)
02451 return 1;
02452 else if (ua < ndig)
02453 return -1;
02454 else
02455 return s_cdig(MP_DIGITS(a), vdig, ndig);
02456 }
02457
02458
02459
02460
02461
02462 static mp_digit
02463 s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc,
02464 mp_size size_a, mp_size size_b)
02465 {
02466 mp_size pos;
02467 mp_word w = 0;
02468
02469
02470 if (size_b > size_a)
02471 {
02472 SWAP(mp_digit *, da, db);
02473 SWAP(mp_size, size_a, size_b);
02474 }
02475
02476
02477 for (pos = 0; pos < size_b; ++pos, ++da, ++db, ++dc)
02478 {
02479 w = w + (mp_word) *da + (mp_word) *db;
02480 *dc = LOWER_HALF(w);
02481 w = UPPER_HALF(w);
02482 }
02483
02484
02485 for ( ; pos < size_a; ++pos, ++da, ++dc)
02486 {
02487 w = w + *da;
02488
02489 *dc = LOWER_HALF(w);
02490 w = UPPER_HALF(w);
02491 }
02492
02493
02494 return (mp_digit) w;
02495 }
02496
02497
02498
02499
02500
02501 static void
02502 s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
02503 mp_size size_a, mp_size size_b)
02504 {
02505 mp_size pos;
02506 mp_word w = 0;
02507
02508
02509 assert(size_a >= size_b);
02510
02511
02512 for (pos = 0; pos < size_b; ++pos, ++da, ++db, ++dc)
02513 {
02514 w = ((mp_word) MP_DIGIT_MAX + 1 +
02515 (mp_word) *da) - w - (mp_word) *db;
02516
02517 *dc = LOWER_HALF(w);
02518 w = (UPPER_HALF(w) == 0);
02519 }
02520
02521
02522 for ( ; pos < size_a; ++pos, ++da, ++dc)
02523 {
02524 w = ((mp_word) MP_DIGIT_MAX + 1 +
02525 (mp_word) *da) - w;
02526
02527 *dc = LOWER_HALF(w);
02528 w = (UPPER_HALF(w) == 0);
02529 }
02530
02531
02532 assert(w == 0);
02533 }
02534
02535
02536
02537
02538
02539 static int
02540 s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
02541 mp_size size_a, mp_size size_b)
02542 {
02543 mp_size bot_size;
02544
02545
02546 if (size_b > size_a)
02547 {
02548 SWAP(mp_digit *, da, db);
02549 SWAP(mp_size, size_a, size_b);
02550 }
02551
02552
02553
02554
02555
02556 bot_size = (size_a + 1) / 2;
02557
02558
02559
02560
02561
02562
02563 if (multiply_threshold &&
02564 size_a >= multiply_threshold &&
02565 size_b > bot_size)
02566 {
02567
02568 mp_digit *t1,
02569 *t2,
02570 *t3,
02571 carry;
02572
02573 mp_digit *a_top = da + bot_size;
02574 mp_digit *b_top = db + bot_size;
02575
02576 mp_size at_size = size_a - bot_size;
02577 mp_size bt_size = size_b - bot_size;
02578 mp_size buf_size = 2 * bot_size;
02579
02580
02581
02582
02583
02584
02585
02586 if ((t1 = s_alloc(4 * buf_size)) == NULL)
02587 return 0;
02588 t2 = t1 + buf_size;
02589 t3 = t2 + buf_size;
02590 ZERO(t1, 4 * buf_size);
02591
02592
02593
02594
02595
02596 carry = s_uadd(da, a_top, t1, bot_size, at_size);
02597 t1[bot_size] = carry;
02598
02599 carry = s_uadd(db, b_top, t2, bot_size, bt_size);
02600 t2[bot_size] = carry;
02601
02602 (void) s_kmul(t1, t2, t3, bot_size + 1, bot_size + 1);
02603
02604
02605
02606
02607
02608 ZERO(t1, bot_size + 1);
02609 ZERO(t2, bot_size + 1);
02610 (void) s_kmul(da, db, t1, bot_size, bot_size);
02611 (void) s_kmul(a_top, b_top, t2, at_size, bt_size);
02612
02613
02614 s_usub(t3, t1, t3, buf_size + 2, buf_size);
02615 s_usub(t3, t2, t3, buf_size + 2, buf_size);
02616
02617
02618 COPY(t1, dc, buf_size);
02619 (void) s_uadd(t3, dc + bot_size, dc + bot_size,
02620 buf_size + 1, buf_size + 1);
02621
02622 (void) s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size,
02623 buf_size, buf_size);
02624
02625 s_free(t1);
02626
02627 }
02628 else
02629 {
02630 s_umul(da, db, dc, size_a, size_b);
02631 }
02632
02633 return 1;
02634 }
02635
02636
02637
02638
02639
02640 static void
02641 s_umul(mp_digit *da, mp_digit *db, mp_digit *dc,
02642 mp_size size_a, mp_size size_b)
02643 {
02644 mp_size a,
02645 b;
02646 mp_word w;
02647
02648 for (a = 0; a < size_a; ++a, ++dc, ++da)
02649 {
02650 mp_digit *dct = dc;
02651 mp_digit *dbt = db;
02652
02653 if (*da == 0)
02654 continue;
02655
02656 w = 0;
02657 for (b = 0; b < size_b; ++b, ++dbt, ++dct)
02658 {
02659 w = (mp_word) *da * (mp_word) *dbt + w + (mp_word) *dct;
02660
02661 *dct = LOWER_HALF(w);
02662 w = UPPER_HALF(w);
02663 }
02664
02665 *dct = (mp_digit) w;
02666 }
02667 }
02668
02669
02670
02671
02672
02673 static int
02674 s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a)
02675 {
02676 if (multiply_threshold && size_a > multiply_threshold)
02677 {
02678 mp_size bot_size = (size_a + 1) / 2;
02679 mp_digit *a_top = da + bot_size;
02680 mp_digit *t1,
02681 *t2,
02682 *t3;
02683 mp_size at_size = size_a - bot_size;
02684 mp_size buf_size = 2 * bot_size;
02685
02686 if ((t1 = s_alloc(4 * buf_size)) == NULL)
02687 return 0;
02688 t2 = t1 + buf_size;
02689 t3 = t2 + buf_size;
02690 ZERO(t1, 4 * buf_size);
02691
02692 (void) s_ksqr(da, t1, bot_size);
02693 (void) s_ksqr(a_top, t2, at_size);
02694
02695 (void) s_kmul(da, a_top, t3, bot_size, at_size);
02696
02697
02698 {
02699 int i,
02700 top = bot_size + at_size;
02701 mp_word w,
02702 save = 0;
02703
02704 for (i = 0; i < top; ++i)
02705 {
02706 w = t3[i];
02707 w = (w << 1) | save;
02708 t3[i] = LOWER_HALF(w);
02709 save = UPPER_HALF(w);
02710 }
02711 t3[i] = LOWER_HALF(save);
02712 }
02713
02714
02715 COPY(t1, dc, 2 * bot_size);
02716 (void) s_uadd(t3, dc + bot_size, dc + bot_size,
02717 buf_size + 1, buf_size + 1);
02718
02719 (void) s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size,
02720 buf_size, buf_size);
02721
02722 px_free(t1);
02723
02724
02725 }
02726 else
02727 {
02728 s_usqr(da, dc, size_a);
02729 }
02730
02731 return 1;
02732 }
02733
02734
02735
02736
02737
02738 static void
02739 s_usqr(mp_digit *da, mp_digit *dc, mp_size size_a)
02740 {
02741 mp_size i,
02742 j;
02743 mp_word w;
02744
02745 for (i = 0; i < size_a; ++i, dc += 2, ++da)
02746 {
02747 mp_digit *dct = dc,
02748 *dat = da;
02749
02750 if (*da == 0)
02751 continue;
02752
02753
02754 w = (mp_word) *dat * (mp_word) *dat + (mp_word) *dct;
02755 *dct = LOWER_HALF(w);
02756 w = UPPER_HALF(w);
02757 ++dat;
02758 ++dct;
02759
02760 for (j = i + 1; j < size_a; ++j, ++dat, ++dct)
02761 {
02762 mp_word t = (mp_word) *da * (mp_word) *dat;
02763 mp_word u = w + (mp_word) *dct,
02764 ov = 0;
02765
02766
02767 if (HIGH_BIT_SET(t))
02768 ov = 1;
02769
02770 w = t + t;
02771
02772
02773 if (ADD_WILL_OVERFLOW(w, u))
02774 ov = 1;
02775
02776 w += u;
02777
02778 *dct = LOWER_HALF(w);
02779 w = UPPER_HALF(w);
02780 if (ov)
02781 {
02782 w += MP_DIGIT_MAX;
02783 ++w;
02784 }
02785 }
02786
02787 w = w + *dct;
02788 *dct = (mp_digit) w;
02789 while ((w = UPPER_HALF(w)) != 0)
02790 {
02791 ++dct;
02792 w = w + *dct;
02793 *dct = LOWER_HALF(w);
02794 }
02795
02796 assert(w == 0);
02797 }
02798 }
02799
02800
02801
02802
02803
02804 static void
02805 s_dadd(mp_int a, mp_digit b)
02806 {
02807 mp_word w = 0;
02808 mp_digit *da = MP_DIGITS(a);
02809 mp_size ua = MP_USED(a);
02810
02811 w = (mp_word) *da + b;
02812 *da++ = LOWER_HALF(w);
02813 w = UPPER_HALF(w);
02814
02815 for (ua -= 1; ua > 0; --ua, ++da)
02816 {
02817 w = (mp_word) *da + w;
02818
02819 *da = LOWER_HALF(w);
02820 w = UPPER_HALF(w);
02821 }
02822
02823 if (w)
02824 {
02825 *da = (mp_digit) w;
02826 MP_USED(a) += 1;
02827 }
02828 }
02829
02830
02831
02832
02833
02834 static void
02835 s_dmul(mp_int a, mp_digit b)
02836 {
02837 mp_word w = 0;
02838 mp_digit *da = MP_DIGITS(a);
02839 mp_size ua = MP_USED(a);
02840
02841 while (ua > 0)
02842 {
02843 w = (mp_word) *da * b + w;
02844 *da++ = LOWER_HALF(w);
02845 w = UPPER_HALF(w);
02846 --ua;
02847 }
02848
02849 if (w)
02850 {
02851 *da = (mp_digit) w;
02852 MP_USED(a) += 1;
02853 }
02854 }
02855
02856
02857
02858
02859
02860 static void
02861 s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc, mp_size size_a)
02862 {
02863 mp_word w = 0;
02864
02865 while (size_a > 0)
02866 {
02867 w = (mp_word) *da++ * (mp_word) b + w;
02868
02869 *dc++ = LOWER_HALF(w);
02870 w = UPPER_HALF(w);
02871 --size_a;
02872 }
02873
02874 if (w)
02875 *dc = LOWER_HALF(w);
02876 }
02877
02878
02879
02880
02881
02882 static mp_digit
02883 s_ddiv(mp_int a, mp_digit b)
02884 {
02885 mp_word w = 0,
02886 qdigit;
02887 mp_size ua = MP_USED(a);
02888 mp_digit *da = MP_DIGITS(a) + ua - 1;
02889
02890 for ( ; ua > 0; --ua, --da)
02891 {
02892 w = (w << MP_DIGIT_BIT) | *da;
02893
02894 if (w >= b)
02895 {
02896 qdigit = w / b;
02897 w = w % b;
02898 }
02899 else
02900 {
02901 qdigit = 0;
02902 }
02903
02904 *da = (mp_digit) qdigit;
02905 }
02906
02907 CLAMP(a);
02908 return (mp_digit) w;
02909 }
02910
02911
02912
02913
02914
02915 static void
02916 s_qdiv(mp_int z, mp_size p2)
02917 {
02918 mp_size ndig = p2 / MP_DIGIT_BIT,
02919 nbits = p2 % MP_DIGIT_BIT;
02920 mp_size uz = MP_USED(z);
02921
02922 if (ndig)
02923 {
02924 mp_size mark;
02925 mp_digit *to,
02926 *from;
02927
02928 if (ndig >= uz)
02929 {
02930 mp_int_zero(z);
02931 return;
02932 }
02933
02934 to = MP_DIGITS(z);
02935 from = to + ndig;
02936
02937 for (mark = ndig; mark < uz; ++mark)
02938 *to++ = *from++;
02939
02940 MP_USED(z) = uz - ndig;
02941 }
02942
02943 if (nbits)
02944 {
02945 mp_digit d = 0,
02946 *dz,
02947 save;
02948 mp_size up = MP_DIGIT_BIT - nbits;
02949
02950 uz = MP_USED(z);
02951 dz = MP_DIGITS(z) + uz - 1;
02952
02953 for ( ; uz > 0; --uz, --dz)
02954 {
02955 save = *dz;
02956
02957 *dz = (*dz >> nbits) | (d << up);
02958 d = save;
02959 }
02960
02961 CLAMP(z);
02962 }
02963
02964 if (MP_USED(z) == 1 && z->digits[0] == 0)
02965 MP_SIGN(z) = MP_ZPOS;
02966 }
02967
02968
02969
02970
02971
02972 static void
02973 s_qmod(mp_int z, mp_size p2)
02974 {
02975 mp_size start = p2 / MP_DIGIT_BIT + 1,
02976 rest = p2 % MP_DIGIT_BIT;
02977 mp_size uz = MP_USED(z);
02978 mp_digit mask = (1 << rest) - 1;
02979
02980 if (start <= uz)
02981 {
02982 MP_USED(z) = start;
02983 z->digits[start - 1] &= mask;
02984 CLAMP(z);
02985 }
02986 }
02987
02988
02989
02990
02991
02992 static int
02993 s_qmul(mp_int z, mp_size p2)
02994 {
02995 mp_size uz,
02996 need,
02997 rest,
02998 extra,
02999 i;
03000 mp_digit *from,
03001 *to,
03002 d;
03003
03004 if (p2 == 0)
03005 return 1;
03006
03007 uz = MP_USED(z);
03008 need = p2 / MP_DIGIT_BIT;
03009 rest = p2 % MP_DIGIT_BIT;
03010
03011
03012
03013
03014
03015
03016 extra = 0;
03017 if (rest != 0)
03018 {
03019 mp_digit *dz = MP_DIGITS(z) + uz - 1;
03020
03021 if ((*dz >> (MP_DIGIT_BIT - rest)) != 0)
03022 extra = 1;
03023 }
03024
03025 if (!s_pad(z, uz + need + extra))
03026 return 0;
03027
03028
03029
03030
03031
03032 if (need > 0)
03033 {
03034 from = MP_DIGITS(z) + uz - 1;
03035 to = from + need;
03036
03037 for (i = 0; i < uz; ++i)
03038 *to-- = *from--;
03039
03040 ZERO(MP_DIGITS(z), need);
03041 uz += need;
03042 }
03043
03044 if (rest)
03045 {
03046 d = 0;
03047 for (i = need, from = MP_DIGITS(z) + need; i < uz; ++i, ++from)
03048 {
03049 mp_digit save = *from;
03050
03051 *from = (*from << rest) | (d >> (MP_DIGIT_BIT - rest));
03052 d = save;
03053 }
03054
03055 d >>= (MP_DIGIT_BIT - rest);
03056 if (d != 0)
03057 {
03058 *from = d;
03059 uz += extra;
03060 }
03061 }
03062
03063 MP_USED(z) = uz;
03064 CLAMP(z);
03065
03066 return 1;
03067 }
03068
03069
03070
03071
03072
03073
03074 static int
03075 s_qsub(mp_int z, mp_size p2)
03076 {
03077 mp_digit hi = (1 << (p2 % MP_DIGIT_BIT)),
03078 *zp;
03079 mp_size tdig = (p2 / MP_DIGIT_BIT),
03080 pos;
03081 mp_word w = 0;
03082
03083 if (!s_pad(z, tdig + 1))
03084 return 0;
03085
03086 for (pos = 0, zp = MP_DIGITS(z); pos < tdig; ++pos, ++zp)
03087 {
03088 w = ((mp_word) MP_DIGIT_MAX + 1) - w - (mp_word) *zp;
03089
03090 *zp = LOWER_HALF(w);
03091 w = UPPER_HALF(w) ? 0 : 1;
03092 }
03093
03094 w = ((mp_word) MP_DIGIT_MAX + 1 + hi) - w - (mp_word) *zp;
03095 *zp = LOWER_HALF(w);
03096
03097 assert(UPPER_HALF(w) != 0);
03098
03099 MP_SIGN(z) = MP_ZPOS;
03100 CLAMP(z);
03101
03102 return 1;
03103 }
03104
03105
03106
03107
03108
03109 static int
03110 s_dp2k(mp_int z)
03111 {
03112 int k = 0;
03113 mp_digit *dp = MP_DIGITS(z),
03114 d;
03115
03116 if (MP_USED(z) == 1 && *dp == 0)
03117 return 1;
03118
03119 while (*dp == 0)
03120 {
03121 k += MP_DIGIT_BIT;
03122 ++dp;
03123 }
03124
03125 d = *dp;
03126 while ((d & 1) == 0)
03127 {
03128 d >>= 1;
03129 ++k;
03130 }
03131
03132 return k;
03133 }
03134
03135
03136
03137
03138
03139 static int
03140 s_isp2(mp_int z)
03141 {
03142 mp_size uz = MP_USED(z),
03143 k = 0;
03144 mp_digit *dz = MP_DIGITS(z),
03145 d;
03146
03147 while (uz > 1)
03148 {
03149 if (*dz++ != 0)
03150 return -1;
03151 k += MP_DIGIT_BIT;
03152 --uz;
03153 }
03154
03155 d = *dz;
03156 while (d > 1)
03157 {
03158 if (d & 1)
03159 return -1;
03160 ++k;
03161 d >>= 1;
03162 }
03163
03164 return (int) k;
03165 }
03166
03167
03168
03169
03170
03171 static int
03172 s_2expt(mp_int z, int k)
03173 {
03174 mp_size ndig,
03175 rest;
03176 mp_digit *dz;
03177
03178 ndig = (k + MP_DIGIT_BIT) / MP_DIGIT_BIT;
03179 rest = k % MP_DIGIT_BIT;
03180
03181 if (!s_pad(z, ndig))
03182 return 0;
03183
03184 dz = MP_DIGITS(z);
03185 ZERO(dz, ndig);
03186 *(dz + ndig - 1) = (1 << rest);
03187 MP_USED(z) = ndig;
03188
03189 return 1;
03190 }
03191
03192
03193
03194
03195
03196 static int
03197 s_norm(mp_int a, mp_int b)
03198 {
03199 mp_digit d = b->digits[MP_USED(b) - 1];
03200 int k = 0;
03201
03202 while (d < (mp_digit) ((mp_digit) 1 << (MP_DIGIT_BIT - 1)))
03203 {
03204 d <<= 1;
03205 ++k;
03206 }
03207
03208
03209 if (k != 0)
03210 {
03211 (void) s_qmul(a, (mp_size) k);
03212 (void) s_qmul(b, (mp_size) k);
03213 }
03214
03215 return k;
03216 }
03217
03218
03219
03220
03221
03222 static mp_result
03223 s_brmu(mp_int z, mp_int m)
03224 {
03225 mp_size um = MP_USED(m) * 2;
03226
03227 if (!s_pad(z, um))
03228 return MP_MEMORY;
03229
03230 s_2expt(z, MP_DIGIT_BIT * um);
03231 return mp_int_div(z, m, z, NULL);
03232 }
03233
03234
03235
03236
03237
03238 static int
03239 s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2)
03240 {
03241 mp_size um = MP_USED(m),
03242 umb_p1,
03243 umb_m1;
03244
03245 umb_p1 = (um + 1) * MP_DIGIT_BIT;
03246 umb_m1 = (um - 1) * MP_DIGIT_BIT;
03247
03248 if (mp_int_copy(x, q1) != MP_OK)
03249 return 0;
03250
03251
03252 s_qdiv(q1, umb_m1);
03253 UMUL(q1, mu, q2);
03254 s_qdiv(q2, umb_p1);
03255
03256
03257 s_qmod(x, umb_p1);
03258
03259
03260
03261
03262
03263
03264 UMUL(q2, m, q1);
03265 s_qmod(q1, umb_p1);
03266 (void) mp_int_sub(x, q1, x);
03267
03268
03269
03270
03271
03272 if ((CMPZ(x) < 0) && !s_qsub(x, umb_p1))
03273 return 0;
03274
03275
03276
03277
03278
03279 if (mp_int_compare(x, m) >= 0)
03280 (void) mp_int_sub(x, m, x);
03281 if (mp_int_compare(x, m) >= 0)
03282 (void) mp_int_sub(x, m, x);
03283
03284
03285 return 1;
03286 }
03287
03288
03289
03290
03291
03292
03293
03294 static mp_result
03295 s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
03296 {
03297 mp_digit *db,
03298 *dbt,
03299 umu,
03300 d;
03301 mpz_t temp[3];
03302 mp_result res;
03303 int last = 0;
03304
03305 umu = MP_USED(mu);
03306 db = MP_DIGITS(b);
03307 dbt = db + MP_USED(b) - 1;
03308
03309 while (last < 3)
03310 SETUP(mp_int_init_size(TEMP(last), 2 * umu), last);
03311
03312 (void) mp_int_set_value(c, 1);
03313
03314
03315 while (db < dbt)
03316 {
03317 int i;
03318
03319 for (d = *db, i = MP_DIGIT_BIT; i > 0; --i, d >>= 1)
03320 {
03321 if (d & 1)
03322 {
03323
03324 UMUL(c, a, TEMP(0));
03325 if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
03326 {
03327 res = MP_MEMORY;
03328 goto CLEANUP;
03329 }
03330 mp_int_copy(TEMP(0), c);
03331 }
03332
03333
03334 USQR(a, TEMP(0));
03335 assert(MP_SIGN(TEMP(0)) == MP_ZPOS);
03336 if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
03337 {
03338 res = MP_MEMORY;
03339 goto CLEANUP;
03340 }
03341 assert(MP_SIGN(TEMP(0)) == MP_ZPOS);
03342 mp_int_copy(TEMP(0), a);
03343
03344
03345 }
03346
03347 ++db;
03348 }
03349
03350
03351 d = *dbt;
03352 for (;;)
03353 {
03354 if (d & 1)
03355 {
03356 UMUL(c, a, TEMP(0));
03357 if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
03358 {
03359 res = MP_MEMORY;
03360 goto CLEANUP;
03361 }
03362 mp_int_copy(TEMP(0), c);
03363 }
03364
03365 d >>= 1;
03366 if (!d)
03367 break;
03368
03369 USQR(a, TEMP(0));
03370 if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2)))
03371 {
03372 res = MP_MEMORY;
03373 goto CLEANUP;
03374 }
03375 (void) mp_int_copy(TEMP(0), a);
03376 }
03377
03378 CLEANUP:
03379 while (--last >= 0)
03380 mp_int_clear(TEMP(last));
03381
03382 return res;
03383 }
03384
03385
03386
03387
03388
03389
03390
03391
03392 static mp_result
03393 s_udiv(mp_int a, mp_int b)
03394 {
03395 mpz_t q,
03396 r,
03397 t;
03398 mp_size ua,
03399 ub,
03400 qpos = 0;
03401 mp_digit *da,
03402 btop;
03403 mp_result res = MP_OK;
03404 int k,
03405 skip = 0;
03406
03407
03408 MP_SIGN(a) = MP_ZPOS;
03409 MP_SIGN(b) = MP_ZPOS;
03410
03411
03412 k = s_norm(a, b);
03413
03414 ua = MP_USED(a);
03415 ub = MP_USED(b);
03416 btop = b->digits[ub - 1];
03417 if ((res = mp_int_init_size(&q, ua)) != MP_OK)
03418 return res;
03419 if ((res = mp_int_init_size(&t, ua + 1)) != MP_OK)
03420 goto CLEANUP;
03421
03422 da = MP_DIGITS(a);
03423 r.digits = da + ua - 1;
03424 r.used = 1;
03425 r.sign = MP_ZPOS;
03426 r.alloc = MP_ALLOC(a);
03427 ZERO(t.digits, t.alloc);
03428
03429
03430 while (r.digits >= da)
03431 {
03432 assert(qpos <= q.alloc);
03433
03434 if (s_ucmp(b, &r) > 0)
03435 {
03436 r.digits -= 1;
03437 r.used += 1;
03438
03439 if (++skip > 1)
03440 q.digits[qpos++] = 0;
03441
03442 CLAMP(&r);
03443 }
03444 else
03445 {
03446 mp_word pfx = r.digits[r.used - 1];
03447 mp_word qdigit;
03448
03449 if (r.used > 1 && (pfx < btop || r.digits[r.used - 2] == 0))
03450 {
03451 pfx <<= MP_DIGIT_BIT / 2;
03452 pfx <<= MP_DIGIT_BIT / 2;
03453 pfx |= r.digits[r.used - 2];
03454 }
03455
03456 qdigit = pfx / btop;
03457 if (qdigit > MP_DIGIT_MAX)
03458 qdigit = 1;
03459
03460 s_dbmul(MP_DIGITS(b), (mp_digit) qdigit, t.digits, ub);
03461 t.used = ub + 1;
03462 CLAMP(&t);
03463 while (s_ucmp(&t, &r) > 0)
03464 {
03465 --qdigit;
03466 (void) mp_int_sub(&t, b, &t);
03467 }
03468
03469 s_usub(r.digits, t.digits, r.digits, r.used, t.used);
03470 CLAMP(&r);
03471
03472 q.digits[qpos++] = (mp_digit) qdigit;
03473 ZERO(t.digits, t.used);
03474 skip = 0;
03475 }
03476 }
03477
03478
03479 q.used = qpos;
03480 REV(mp_digit, q.digits, qpos);
03481 CLAMP(&q);
03482
03483
03484 CLAMP(a);
03485 if (k != 0)
03486 s_qdiv(a, k);
03487
03488 mp_int_copy(a, b);
03489 mp_int_copy(&q, a);
03490
03491 mp_int_clear(&t);
03492 CLEANUP:
03493 mp_int_clear(&q);
03494 return res;
03495 }
03496
03497
03498
03499
03500
03501
03502 static int
03503 s_outlen(mp_int z, mp_size r)
03504 {
03505 mp_result bits;
03506 double raw;
03507
03508 bits = mp_int_count_bits(z);
03509 raw = (double) bits *s_log2[r];
03510
03511 return (int) (raw + 0.999999);
03512 }
03513
03514
03515
03516
03517
03518 static mp_size
03519 s_inlen(int len, mp_size r)
03520 {
03521 double raw = (double) len / s_log2[r];
03522 mp_size bits = (mp_size) (raw + 0.5);
03523
03524 return (mp_size) ((bits + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT);
03525 }
03526
03527
03528
03529
03530
03531 static int
03532 s_ch2val(char c, int r)
03533 {
03534 int out;
03535
03536 if (isdigit((unsigned char) c))
03537 out = c - '0';
03538 else if (r > 10 && isalpha((unsigned char) c))
03539 out = toupper((unsigned char) c) - 'A' + 10;
03540 else
03541 return -1;
03542
03543 return (out >= r) ? -1 : out;
03544 }
03545
03546
03547
03548
03549
03550 static char
03551 s_val2ch(int v, int caps)
03552 {
03553 assert(v >= 0);
03554
03555 if (v < 10)
03556 return v + '0';
03557 else
03558 {
03559 char out = (v - 10) + 'a';
03560
03561 if (caps)
03562 return toupper((unsigned char) out);
03563 else
03564 return out;
03565 }
03566 }
03567
03568
03569
03570
03571
03572 static void
03573 s_2comp(unsigned char *buf, int len)
03574 {
03575 int i;
03576 unsigned short s = 1;
03577
03578 for (i = len - 1; i >= 0; --i)
03579 {
03580 unsigned char c = ~buf[i];
03581
03582 s = c + s;
03583 c = s & UCHAR_MAX;
03584 s >>= CHAR_BIT;
03585
03586 buf[i] = c;
03587 }
03588
03589
03590 }
03591
03592
03593
03594
03595
03596 static mp_result
03597 s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad)
03598 {
03599 mp_size uz;
03600 mp_digit *dz;
03601 int pos = 0,
03602 limit = *limpos;
03603
03604 uz = MP_USED(z);
03605 dz = MP_DIGITS(z);
03606 while (uz > 0 && pos < limit)
03607 {
03608 mp_digit d = *dz++;
03609 int i;
03610
03611 for (i = sizeof(mp_digit); i > 0 && pos < limit; --i)
03612 {
03613 buf[pos++] = (unsigned char) d;
03614 d >>= CHAR_BIT;
03615
03616
03617 if (d == 0 && uz == 1)
03618 i = 0;
03619 }
03620
03621
03622 if (i > 0)
03623 break;
03624
03625 --uz;
03626 }
03627
03628 if (pad != 0 && (buf[pos - 1] >> (CHAR_BIT - 1)))
03629 {
03630 if (pos < limit)
03631 buf[pos++] = 0;
03632 else
03633 uz = 1;
03634 }
03635
03636
03637 REV(unsigned char, buf, pos);
03638
03639
03640 *limpos = pos;
03641
03642 return (uz == 0) ? MP_OK : MP_TRUNC;
03643 }
03644
03645
03646
03647
03648
03649 #if 0
03650 void
03651 s_print(char *tag, mp_int z)
03652 {
03653 int i;
03654
03655 fprintf(stderr, "%s: %c ", tag,
03656 (MP_SIGN(z) == MP_NEG) ? '-' : '+');
03657
03658 for (i = MP_USED(z) - 1; i >= 0; --i)
03659 fprintf(stderr, "%0*X", (int) (MP_DIGIT_BIT / 4), z->digits[i]);
03660
03661 fputc('\n', stderr);
03662
03663 }
03664
03665 void
03666 s_print_buf(char *tag, mp_digit *buf, mp_size num)
03667 {
03668 int i;
03669
03670 fprintf(stderr, "%s: ", tag);
03671
03672 for (i = num - 1; i >= 0; --i)
03673 fprintf(stderr, "%0*X", (int) (MP_DIGIT_BIT / 4), buf[i]);
03674
03675 fputc('\n', stderr);
03676 }
03677 #endif
03678
03679
03680
03681