Skip to content

Commit ff1a96c

Browse files
committed
py/mpz: Add commented-out mpz_pow3_inpl function, to compute (x**y)%z.
This function computes (x**y)%z in an efficient way. For large arguments this operation is otherwise not computable by doing x**y and then %z. It's currently not used, but is added in case it's useful one day.
1 parent 2e2e15c commit ff1a96c

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

py/mpz.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,44 @@ void mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {
13741374
#if 0
13751375
these functions are unused
13761376

1377+
/* computes dest = (lhs ** rhs) % mod
1378+
can have dest, lhs, rhs the same; mod can't be the same as dest
1379+
*/
1380+
void mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t *mod) {
1381+
if (lhs->len == 0 || rhs->neg != 0) {
1382+
mpz_set_from_int(dest, 0);
1383+
return;
1384+
}
1385+
1386+
if (rhs->len == 0) {
1387+
mpz_set_from_int(dest, 1);
1388+
return;
1389+
}
1390+
1391+
mpz_t *x = mpz_clone(lhs);
1392+
mpz_t *n = mpz_clone(rhs);
1393+
mpz_t quo; mpz_init_zero(&quo);
1394+
1395+
mpz_set_from_int(dest, 1);
1396+
1397+
while (n->len > 0) {
1398+
if ((n->dig[0] & 1) != 0) {
1399+
mpz_mul_inpl(dest, dest, x);
1400+
mpz_divmod_inpl(&quo, dest, dest, mod);
1401+
}
1402+
n->len = mpn_shr(n->dig, n->dig, n->len, 1);
1403+
if (n->len == 0) {
1404+
break;
1405+
}
1406+
mpz_mul_inpl(x, x, x);
1407+
mpz_divmod_inpl(&quo, x, x, mod);
1408+
}
1409+
1410+
mpz_deinit(&quo);
1411+
mpz_free(x);
1412+
mpz_free(n);
1413+
}
1414+
13771415
/* computes gcd(z1, z2)
13781416
based on Knuth's modified gcd algorithm (I think?)
13791417
gcd(z1, z2) >= 0

0 commit comments

Comments
 (0)