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); }
int BabyStepGiantStep(verylong zalpha, verylong zbeta, verylong zn, verylong zp, verylong *zx) /* given a generator alpha of a cyclic group G of order n and an element beta compute the discrete logarithm x returns 0 if not enough memory for the problem 1 otherwise */ { long i, j, m; static verylong za = 0, zd = 0, zg = 0, zm = 0; struct Element *element, temp; zsqrt(zn, &za, &zd); zsadd(za, 1l, &zm); m = ztoint(zm); element = (struct Element *) malloc(m * sizeof(struct Element)); if (element == 0) return 0; zone(&zd); /* construct table */ for (i = 0; i < m; i++) { element[i].index = i; element[i].alpha_index = 0; zcopy(zd, &element[i].alpha_index); zmul(zd, zalpha, &za); zmod(za, zp, &zd); } /* sort on second values */ for (i = 0; i < m - 1; i++) { for (j = i + 1; j < m; j++) { if (zcompare(element[i].alpha_index, element[j].alpha_index) > 0) { temp = element[i]; element[i] = element[j]; element[j] = temp; } } } zinvmod(zalpha, zp, &za); zexp(za, zm, &zg); zmod(zg, zp, &zd); zcopy(zbeta, &zg); for (i = 0; i < m; i++) { printf("%d ", element[i].index); zwriteln(element[i].alpha_index); } for (i = 0; i < m; i++) { j = Find(m, zg, element); if (j != - 1) { zsmul(zm, i, &za); zsadd(za, j, zx); for (j = 0; j < m; j++) zfree(&element[j].alpha_index); free(element); return 1; } zmul(zg, zd, &za); zmod(za, zp, &zg); } return 0; }
/* Matrix multiplication C = A * B */ extern void amMul(ArrayMatrix C, ArrayMatrix A, ArrayMatrix B) { mwSignedIndex np, nrow, ncol, nelem; /* Number of elements */ nelem = intmax(A.nelem, B.nelem); /* Check if any of the arguments are a scalar */ if (amIsScalar(A)) { /* Call scalar multiplication with A and B interchanged */ nrow = B.nrow; ncol = B.ncol; if (A.complex || B.complex) { /* Complex multiplication */ zsmul(C.data, B.data, A.data, B.nelem > 1, A.nelem > 1, nrow, ncol, nelem); } else { /* Real multiplication */ dsmul(C.data, B.data, A.data, B.nelem > 1, A.nelem > 1, nrow, ncol, nelem); } } else if (amIsScalar(B)) { nrow = A.nrow; ncol = A.ncol; if (A.complex || B.complex) { /* Complex multiplication */ zsmul(C.data, A.data, B.data, A.nelem > 1, B.nelem > 1, nrow, ncol, nelem); } else { /* Real multiplication */ dsmul(C.data, A.data, B.data, A.nelem > 1, B.nelem > 1, nrow, ncol, nelem); } } else { nrow = A.nrow; ncol = B.ncol; np = A.ncol; if (A.complex || B.complex) { /* Complex multiplication */ zgemul(C.data, A.data, B.data, A.nelem > 1, B.nelem > 1, np, nrow, ncol, nelem); } else { /* Real multiplication */ dgemul(C.data, A.data, B.data, A.nelem > 1, B.nelem > 1, np, nrow, ncol, nelem); } } }
void zai(verylong za0, verylong zn, verylong zx0, verylong *za1) { long x = zsmod(zx0, 3l); static verylong za = 0; if (x == 1) zcopy(za0, za1); else if (x == 0) { zsmul(za0, 2l, &za); zmod(za, zn, za1); } else { zsadd(za0, 1l, &za); zmod(za, zn, za1); } }
void zbi(verylong zb0, verylong zn, verylong zx0, verylong *zb1) { long x = zsmod(zx0, 3l); static verylong zb = 0; if (x == 1) { zsadd(zb0, 1l, &zb); zmod(zb, zn, zb1); } else if (x == 0) { zsmul(zb0, 2l, &zb); zmod(zb, zn, zb1); } else zcopy(zb0, zb1); }