#include <tommath.h>
#ifdef BN_MP_REDUCE_C
int
mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
{
mp_int q;
int
res, um = m->used;
if
((res = mp_init_copy (&q, x)) != MP_OKAY) {
return
res;
}
mp_rshd (&q, um - 1);
if
(((unsigned
long
) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
if
((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
goto
CLEANUP;
}
}
else
{
#ifdef BN_S_MP_MUL_HIGH_DIGS_C
if
((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
goto
CLEANUP;
}
#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
if
((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
goto
CLEANUP;
}
#else
{
res = MP_VAL;
goto
CLEANUP;
}
#endif
}
mp_rshd (&q, um + 1);
if
((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
goto
CLEANUP;
}
if
((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
goto
CLEANUP;
}
if
((res = mp_sub (x, &q, x)) != MP_OKAY) {
goto
CLEANUP;
}
if
(mp_cmp_d (x, 0) == MP_LT) {
mp_set (&q, 1);
if
((res = mp_lshd (&q, um + 1)) != MP_OKAY)
goto
CLEANUP;
if
((res = mp_add (x, &q, x)) != MP_OKAY)
goto
CLEANUP;
}
while
(mp_cmp (x, m) != MP_LT) {
if
((res = s_mp_sub (x, m, x)) != MP_OKAY) {
goto
CLEANUP;
}
}
CLEANUP:
mp_clear (&q);
return
res;
}
#endif