X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/98421fc1a6832ad5de4b3f6171852437aa3e0fb2..HEAD:/math/mp-arith.c diff --git a/math/mp-arith.c b/math/mp-arith.c index 61780b0f..048f4c66 100644 --- a/math/mp-arith.c +++ b/math/mp-arith.c @@ -667,10 +667,41 @@ mp *mp_odd(mp *d, mp *m, size_t *s) return (mp_lsr(d, m, ss)); } +/* --- @mp_leastcongruent@ --- * + * + * Arguments: @mp *d@ = pointer to destination + * @mp *b@ = lower bound + * @mp *r@ = representative + * @mp *m@ = modulus + * + * Returns: The smallest integer %$x \equiv r \pmod{m}$% such that + * %$x \ge b$%. + */ + +mp *mp_leastcongruent(mp *d, mp *b, mp *r, mp *m) +{ + /* --- Strategy --- * + * + * Start by finding %$u \equiv b - r \pmod{m}$% with %$0 < u \le m$%. Then + * %$b \le x = b + m - u < b + m$%, and %$x \equiv r \pmod{m}$% as + * required. + */ + + MP_COPY(b); MP_COPY(m); + d = mp_sub(d, b, r); + mp_div(0, &d, d, m); + if (MP_ZEROP(d)) { MP_DROP(d); d = MP_COPY(b); } + else { d = mp_sub(d, b, d); d = mp_add(d, d, m); } + MP_DROP(b); MP_DROP(m); + return (d); +} + /*----- Test rig ----------------------------------------------------------*/ #ifdef TEST_RIG +#include + static int verify(const char *op, mp *expect, mp *result, mp *a, mp *b) { if (!MP_EQ(expect, result)) { @@ -758,11 +789,11 @@ MPX_DOBIN(DO) mp *r = *(mp **)v[3].buf; mp *c; - if (strcmp(v[0].buf, "and") == 0) op = 1; - else if (strcmp(v[0].buf, "or") == 0) op = 7; - else if (strcmp(v[0].buf, "nand") == 0) op = 14; - else if (strcmp(v[0].buf, "nor") == 0) op = 8; - else if (strcmp(v[0].buf, "xor") == 0) op = 6; + if (STRCMP(v[0].buf, ==, "and")) op = 1; + else if (STRCMP(v[0].buf, ==, "or")) op = 7; + else if (STRCMP(v[0].buf, ==, "nand")) op = 14; + else if (STRCMP(v[0].buf, ==, "nor")) op = 8; + else if (STRCMP(v[0].buf, ==, "xor")) op = 6; else { char *p = v[0].buf; while (*p) {