in src/fpx.c [1081:1137]
static inline void fpinv_mont_bingcd_partial(const felm_t a, felm_t x1, unsigned int* k)
{ // Partial Montgomery inversion via the binary GCD algorithm.
felm_t u, v, x2;
unsigned int cwords; // Number of words necessary for x1, x2
fpcopy(a, u);
fpcopy((digit_t*)PRIME, v);
fpzero(x1); x1[0] = 1;
fpzero(x2);
*k = 0;
while (!is_felm_zero(v)) {
cwords = ((*k + 1) / RADIX) + 1;
if ((cwords < NWORDS_FIELD)) {
if (is_felm_even(v)) {
mp_shiftr1(v, NWORDS_FIELD);
mp_shiftl1(x1, cwords);
} else if (is_felm_even(u)) {
mp_shiftr1(u, NWORDS_FIELD);
mp_shiftl1(x2, cwords);
} else if (!is_felm_lt(v, u)) {
mp_sub(v, u, v, NWORDS_FIELD);
mp_shiftr1(v, NWORDS_FIELD);
mp_add(x1, x2, x2, cwords);
mp_shiftl1(x1, cwords);
} else {
mp_sub(u, v, u, NWORDS_FIELD);
mp_shiftr1(u, NWORDS_FIELD);
mp_add(x1, x2, x1, cwords);
mp_shiftl1(x2, cwords);
}
} else {
if (is_felm_even(v)) {
mp_shiftr1(v, NWORDS_FIELD);
mp_shiftl1(x1, NWORDS_FIELD);
} else if (is_felm_even(u)) {
mp_shiftr1(u, NWORDS_FIELD);
mp_shiftl1(x2, NWORDS_FIELD);
} else if (!is_felm_lt(v, u)) {
mp_sub(v, u, v, NWORDS_FIELD);
mp_shiftr1(v, NWORDS_FIELD);
mp_add(x1, x2, x2, NWORDS_FIELD);
mp_shiftl1(x1, NWORDS_FIELD);
} else {
mp_sub(u, v, u, NWORDS_FIELD);
mp_shiftr1(u, NWORDS_FIELD);
mp_add(x1, x2, x1, NWORDS_FIELD);
mp_shiftl1(x2, NWORDS_FIELD);
}
}
*k += 1;
}
if (is_felm_lt((digit_t*)PRIME, x1)) {
mp_sub(x1, (digit_t*)PRIME, x1, NWORDS_FIELD);
}
}