void zmodpowu(z_t a, z_t b, unsigned long long int c, z_t d) { if (unlikely(!c)) { if (check(zzero(b))) libzahl_failure(-ZERROR_0_POW_0); else if (check(zzero(d))) libzahl_failure(-ZERROR_DIV_0); else zsetu(a, 1); return; } else if (check(zzero(d))) { libzahl_failure(-ZERROR_DIV_0); } else if (unlikely(zzero(b))) { SET_SIGNUM(a, 0); return; } zmod(tb, b, d); zset(td, d); if (c & 1) zset(a, tb); else zsetu(a, 1); while (c >>= 1) { zmodsqr(tb, tb, td); if (c & 1) zmodmul(a, a, tb, td); } }
int PollardRho(verylong zalpha, verylong zbeta, verylong zn, verylong zp, verylong *zx) { long i = 2, j; static verylong za0 = 0, za1 = 0, za2 = 0, za3 = 0; static verylong zb0 = 0, zb1 = 0, zb2 = 0, zb3 = 0; static verylong zx0 = 0, zx1 = 0, zx2 = 0, zx3 = 0; static verylong zr = 0, zri = 0; zone(&zx0); zzero(&za0); zzero(&zb0); zfi(zalpha, zbeta, zp, zx0, &zx1); zai(za0, zn, zx0, &za1); zbi(zb0, zn, zx0, &zb1); zfi(zalpha, zbeta, zp, zx1, &zx2); zai(za1, zn, zx1, &za2); zbi(zb1, zn, zx1, &zb2); zcopy(za1, &za0); zcopy(zb1, &zb0); zcopy(zx1, &zx0); for (;;) { zfi(zalpha, zbeta, zp, zx0, &zx1); zai(za0, zn, zx0, &za1); zbi(zb0, zn, zx0, &zb1); zcopy(za1, &za2); zcopy(zb1, &zb2); zcopy(zx1, &zx2); i++; for (j = 0; j < i; j++) { zfi(zalpha, zbeta, zp, zx2, &zx3); zai(za2, zn, zx2, &za3); zbi(zb2, zn, zx2, &zb3); zcopy(za3, &za2); zcopy(zb3, &zb2); zcopy(zx3, &zx2); } if (zcompare(zx1, zx3) == 0) { zsubmod(zb1, zb3, zn, &zr); if (zscompare(zr, 0) == 0) return 0; zinvmod(zr, zn, &zri); zsub(za3, za1, &za0); zmulmod(za0, zri, zn, zx); return 1; } zcopy(za1, &za0); zcopy(zb1, &zb0); zcopy(zx1, &zx0); } }
void scalar(long n, verylong *za, verylong *zb, verylong *zs) { /* *s = inner_product(a, b) */ long i; verylong zt = 0, zu = 0; zzero(zs); for (i = 1; i <= n; i++) { zmul(za[i], zb[i], &zt); zadd(zt, *zs, &zu); zcopy(zu, zs); } zfree(&zt); zfree(&zu); }
void Montgomery_multiplication(long b, long n, verylong zm, verylong zx, verylong zy, verylong *zA) { long i, n1 = n + 1, u, mp, *a, *m, *x, *y; verylong za = 0, zb = 0, zc = 0, zd = 0, zs = 0; a = calloc(n1, sizeof(long)); m = calloc(n1, sizeof(long)); x = calloc(n1, sizeof(long)); y = calloc(n1, sizeof(long)); if (a == 0 || m == 0 || x == 0 || y == 0) { printf("*error*\ncan't get memory from Montgomery"); printf(" multiplication"); exit(1); } zintoz(b, &zb); zinvmod(zm, zb, &za); znegate(&za); mp = zsmod(za, b); radix_representation(b, n1, m, zm); radix_representation(b, n1, x, zx); radix_representation(b, n1, y, zy); zzero(zA); for (i = 0; i < n; i++) { radix_representation(b, n1, a, *zA); u = ((a[0] + x[i] * y[0]) * mp) % b; zsmul(zy, x[i], &za); zsmul(zm, u, &zc); zadd(*zA, za, &zs); zadd(zs, zc, &zd); zsdiv(zd, b, zA); } if (zcompare(*zA, zm) >= 0) { zsub(*zA, zm, &za); zcopy(za, zA); } free(a); free(m); free(x); free(y); zfree(&za); zfree(&zb); zfree(&zc); zfree(&zd); zfree(&zs); }
void zbinary_ext_gcd(verylong zx, verylong zy, verylong *za, verylong *zb, verylong *zv) /* returns a * x + b * y = v, v = gcd(x, y) */ { verylong zA = 0, zB = 0, zC = 0, zD = 0; verylong zX = 0, zY = 0, zc = 0, zg = 0; verylong zu = 0; zone(&zg); zcopy(zx, &zX); zcopy(zy, &zY); while (!zodd(zX) && !zodd(zY)) { zrshift(zX, 1l, &zc); zcopy(zc, &zX); zrshift(zY, 1l, &zc); zcopy(zc, &zY); zlshift(zg, 1l, &zc); zcopy(zc, &zg); } zcopy(zX, &zu); zcopy(zY, zv); zone(&zA); zzero(&zB); zzero(&zC); zone(&zD); do { while (!zodd(zu)) { zrshift(zu, 1l, &zc); zcopy(zc, &zu); if (!zodd(zA) && !zodd(zB)) { zrshift(zA, 1l, &zc); zcopy(zc, &zA); zrshift(zB, 1l, &zc); zcopy(zc, &zB); } else { zadd(zA, zY, &zc); zrshift(zc, 1l, &zA); zsub(zB, zX, &zc); zrshift(zc, 1l, &zB); } } while (!zodd(*zv)) { zrshift(*zv, 1l, &zc); zcopy(zc, zv); if (!zodd(zC) && !zodd(zD)) { zrshift(zC, 1l, &zc); zcopy(zc, &zC); zrshift(zD, 1l, &zc); zcopy(zc, &zD); } else { zadd(zC, zY, &zc); zrshift(zc, 1l, &zC); zsub(zD, zX, &zc); zrshift(zc, 1l, &zD); } } if (zcompare(zu, *zv) >= 0) { zsub(zu, *zv, &zc); zcopy(zc, &zu); zsub(zA, zC, &zc); zcopy(zc, &zA); zsub(zB, zD, &zc); zcopy(zc, &zB); } else { zsub(*zv, zu, &zc); zcopy(zc, zv); zsub(zC, zA, &zc); zcopy(zc, &zC); zsub(zD, zB, &zc); zcopy(zc, &zD); } #ifdef DEBUG zwrite(zu); printf(" "); zwrite(*zv); printf(" "); zwrite(zA); printf(" "); zwrite(zB); printf(" "); zwrite(zC); printf(" "); zwriteln(zD); #endif } while (zscompare(zu, 0l) != 0); zcopy(zC, za); zcopy(zD, zb); zmul(zg, *zv, &zc); zcopy(zc, zv); zfree(&zA); zfree(&zB); zfree(&zC); zfree(&zD); zfree(&zX); zfree(&zY); zfree(&zc); zfree(&zg); zfree(&zu); }
void int_LLL(long n, verylong **zb, verylong **zh) { double x, y; long i, j, k = 2, k1, kmax = 1, l; verylong zr = 0, zs = 0, zt = 0, zu = 0; verylong *zB = allocate_very_vector(1, n); verylong *zd = allocate_very_vector(0, n); verylong **zl = allocate_very_matrix(1, n, 1, n); zone(&zd[0]); scalar(n, zb[1], zb[1], &zd[1]); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) zzero(&zh[i][j]); zone(&zh[i][i]); } #ifdef DEBUG if (n <= 17) { printf("the basis to be reduced is:\n"); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { zwrite(zb[i][j]); printf(" "); } printf("\n"); } } #endif L2: if (k <= kmax) goto L3; kmax = k; for (j = 1; j <= k; j++) { scalar(n, zb[k], zb[j], &zu); for (i = 1; i <= j - 1; i++) { zmul(zd[i], zu, &zr); zmul(zl[k][i], zl[j][i], &zs); zsub(zr, zs, &zt); zdiv(zt, zd[i - 1], &zu, &zr); } if (j < k) zcopy(zu, &zl[k][j]); else if (j == k) { zcopy(zu, &zd[k]); if (zscompare(zd[k], 0l) == 0) system_error("Failure in int_LLL."); } } L3: k1 = k - 1; RED(k, k1, n, zd, zb, zh, zl); zmul(zd[k], zd[k - 2], &zr); zsq(zd[k1], &zs); zsq(zl[k][k1], &zt); x = zdoub(zr); y = 3.0 * zdoub(zs) / 4.0 - zdoub(zt); if (x < y) { SWAP(k, k1, kmax, n, zd, zb, zh, zl); k = max(2, k1); goto L3; } for (l = k - 2; l >= 1; l--) RED(k, l, n, zd, zb, zh, zl); if (++k <= n) goto L2; #ifdef DEBUG if (n <= 17) { printf("the LLL-reduced basis is:\n"); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { zwrite(zb[i][j]); printf(" "); } printf("\n"); } } #endif free_very_matrix(zl, 1, n, 1, n); free_very_vector(zB, 1, n); free_very_vector(zd, 0, n); zfree(&zr); zfree(&zs); zfree(&zt); zfree(&zu); }