/* * mpbsubmod_w * computes the difference (modulo b) of x and y * needs a workspace of (4*size+2) words */ void mpbsubmod_w(const mpbarrett* b, size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata, mpw* result, mpw* wksp) { /* xsize and ysize must be less than or equal to b->size */ register size_t size = b->size; register mpw* temp = wksp + size*2+2; mpsetx(2*size, temp, xsize, xdata); if (mpsubx(2*size, temp, ysize, ydata)) /* if there's carry, i.e. the result would be negative, add the modulus */ while (!mpaddx(2*size, temp, size, b->modl)); /* keep adding the modulus until we get a carry */ mpbmod_w(b, temp, result, wksp); }
/* * mpbmod_w * computes the barrett modular reduction of a number x, which has twice the size of b * needs workspace of (2*size+2) words */ void mpbmod_w(const mpbarrett* b, const mpw* data, mpw* result, mpw* wksp) { register mpw rc; register size_t sp = 2; register const mpw* src = data+b->size+1; register mpw* dst = wksp+b->size+1; rc = mpsetmul(sp, dst, b->mu, *(--src)); *(--dst) = rc; while (sp <= b->size) { sp++; if ((rc = *(--src))) { rc = mpaddmul(sp, dst, b->mu, rc); *(--dst) = rc; } else *(--dst) = 0; } if ((rc = *(--src))) { rc = mpaddmul(sp, dst, b->mu, rc); *(--dst) = rc; } else *(--dst) = 0; sp = b->size; rc = 0; dst = wksp+b->size+1; src = dst; *dst = mpsetmul(sp, dst+1, b->modl, *(--src)); while (sp > 0) mpaddmul(sp--, dst, b->modl+(rc++), *(--src)); mpsetx(b->size+1, wksp, b->size*2, data); mpsub(b->size+1, wksp, wksp+b->size+1); while (mpgex(b->size+1, wksp, b->size, b->modl)) mpsubx(b->size+1, wksp, b->size, b->modl); mpcopy(b->size, result, wksp+1); }
static int Zmpbinv_w(const mpbarrett* b, size_t xsize, const mpw* xdata, mpw* result, mpw* wksp) { size_t ysize = b->size+1; size_t ubits, vbits; int k = 0; mpw* u = wksp; mpw* v = u+ysize; mpw* A = v+ysize; mpw* B = A+ysize; mpw* C = B+ysize; mpw* D = C+ysize; mpsetx(ysize, u, xsize, xdata); mpsetx(ysize, v, b->size, b->modl); mpsetw(ysize, A, 1); mpzero(ysize, B); mpzero(ysize, C); mpsetw(ysize, D, 1); for (k = 0; mpeven(ysize, u) && mpeven(ysize, v); k++) { mpdivtwo(ysize, u); mpdivtwo(ysize, v); } if (mpeven(ysize, u)) (void) mpadd(ysize, u, v); if (_debug < 0) fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); if (_debug < 0) fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); if (_debug < 0) fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); if (_debug < 0) fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); if (_debug < 0) fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); ubits = vbits = MP_WORDS_TO_BITS(ysize); do { while (mpeven(ysize, v)) { mpsdivtwo(ysize, v); vbits -= 1; if (mpodd(ysize, C)) { (void) mpaddx(ysize, C, b->size, b->modl); (void) mpsubx(ysize, D, xsize, xdata); } mpsdivtwo(ysize, C); mpsdivtwo(ysize, D); if (_debug < 0) fprintf(stderr, "-->> v: "), mpfprintln(stderr, ysize, v); } if (ubits >= vbits) { mpw* swapu; size_t swapi; if (_debug < 0) fprintf(stderr, "--> (swap u <-> v)\n"); swapu = u; u = v; v = swapu; swapi = ubits; ubits = vbits; vbits = swapi; swapu = A; A = C; C = swapu; swapu = B; B = D; D = swapu; } if (!((u[ysize-1] + v[ysize-1]) & 0x3)) { if (_debug < 0) fprintf(stderr, "--> (even parity)\n"); mpadd(ysize, v, u); mpadd(ysize, C, A); mpadd(ysize, D, B); } else { if (_debug < 0) fprintf(stderr, "--> (odd parity)\n"); mpsub(ysize, v, u); mpsub(ysize, C, A); mpsub(ysize, D, B); } if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); if (_debug < 0) fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); if (_debug < 0) fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); vbits++; } while (mpnz(ysize, v)); #ifdef NOTYET if (!mpisone(ysize, u)) return 0; #endif if (result) { mpsetx(b->size, result, ysize, A); /*@-usedef@*/ if (*A & 0x80000000) (void) mpneg(b->size, result); /*@=usedef@*/ while (--k > 0) mpadd(b->size, result, result); } fprintf(stderr, "=== EXIT: "), mpfprintln(stderr, b->size, result); fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); return 1; }
/** * Computes the inverse (modulo b) of x, and returns 1 if x was invertible. * needs workspace of (6*size+6) words * @note xdata and result cannot point to the same area */ static int Xmpbinv_w(const mpbarrett* b, size_t xsize, const mpw* xdata, mpw* result, mpw* wksp) { /* * Fact: if a element of Zn, then a is invertible if and only if gcd(a,n) = 1 * Hence: if b->modl is even, then x must be odd, otherwise the gcd(x,n) >= 2 * * The calling routine must guarantee this condition. */ size_t ysize = b->size+1; mpw* u = wksp; mpw* v = u+ysize; mpw* A = v+ysize; mpw* B = A+ysize; mpw* C = B+ysize; mpw* D = C+ysize; mpsetx(ysize, u, b->size, b->modl); mpsetx(ysize, v, xsize, xdata); mpsetw(ysize, A, 1); mpzero(ysize, B); mpzero(ysize, C); mpsetw(ysize, D, 1); if (_debug < 0) fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); if (_debug < 0) fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); if (_debug < 0) fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); if (_debug < 0) fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); if (_debug < 0) fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); do { while (mpeven(ysize, u)) { mpdivtwo(ysize, u); if (mpodd(ysize, A) || mpodd(ysize, B)) { (void) mpaddx(ysize, A, xsize, xdata); (void) mpsubx(ysize, B, b->size, b->modl); } mpsdivtwo(ysize, A); mpsdivtwo(ysize, B); } while (mpeven(ysize, v)) { mpdivtwo(ysize, v); if (mpodd(ysize, C) || mpodd(ysize, D)) { (void) mpaddx(ysize, C, xsize, xdata); (void) mpsubx(ysize, D, b->size, b->modl); } mpsdivtwo(ysize, C); mpsdivtwo(ysize, D); } if (mpge(ysize, u, v)) { if (_debug < 0) fprintf(stderr, "--> 5 (u >= v)\n"); (void) mpsub(ysize, u, v); (void) mpsub(ysize, A, C); (void) mpsub(ysize, B, D); if (_debug < 0) fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); if (_debug < 0) fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); if (_debug < 0) fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); } else { if (_debug < 0) fprintf(stderr, "--> 5 (u < v)\n"); (void) mpsub(ysize, v, u); (void) mpsub(ysize, C, A); (void) mpsub(ysize, D, B); if (_debug < 0) fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); if (_debug < 0) fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); if (_debug < 0) fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); } } while (mpnz(ysize, u)); if (!mpisone(ysize, v)) return 0; if (result) { mpsetx(b->size, result, ysize, D); /*@-usedef@*/ if (*D & 0x80000000) (void) mpadd(b->size, result, b->modl); /*@=usedef@*/ } fprintf(stderr, "=== EXIT: "), mpfprintln(stderr, b->size, result); fprintf(stderr, " u: "), mpfprintln(stderr, ysize, u); fprintf(stderr, " v: "), mpfprintln(stderr, ysize, v); fprintf(stderr, " A: "), mpfprintln(stderr, ysize, A); fprintf(stderr, " B: "), mpfprintln(stderr, ysize, B); fprintf(stderr, " C: "), mpfprintln(stderr, ysize, C); fprintf(stderr, " D: "), mpfprintln(stderr, ysize, D); return 1; }