diff options
Diffstat (limited to '')
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | libj2/division.h | 128 | ||||
| -rw-r--r-- | libj2_j2u_div_j2u_to_j2u_underflow.c | 13 | ||||
| -rw-r--r-- | libj2_j2u_div_j2u_underflow.c | 13 | ||||
| -rw-r--r-- | libj2_j2u_div_ju_to_j2u_underflow.c | 13 | ||||
| -rw-r--r-- | libj2_j2u_div_ju_underflow.c | 13 | ||||
| -rw-r--r-- | libj2_j2u_divmod_j2u_to_j2u.c | 53 | ||||
| -rw-r--r-- | libj2_j2u_rdiv_j2u_underflow.c | 13 |
8 files changed, 252 insertions, 1 deletions
@@ -271,7 +271,12 @@ OBJ =\ libj2_ju_mul_j2u_overflow_p.o\ libj2_j2u_mul_j2u_to_j2u_overflow_p.o\ libj2_j2u_mul_ju_to_j2u_overflow_p.o\ - libj2_ju_mul_j2u_to_j2u_overflow_p.o + libj2_ju_mul_j2u_to_j2u_overflow_p.o\ + libj2_j2u_div_j2u_underflow.o\ + libj2_j2u_div_j2u_to_j2u_underflow.o\ + libj2_j2u_rdiv_j2u_underflow.o\ + libj2_j2u_div_ju_underflow.o\ + libj2_j2u_div_ju_to_j2u_underflow.o SUBHDR =\ libj2/constants.h\ diff --git a/libj2/division.h b/libj2/division.h index 427c75e..274ce13 100644 --- a/libj2/division.h +++ b/libj2/division.h @@ -574,3 +574,131 @@ libj2_j2u_mod_ju_to_j2u(const struct libj2_j2u *a, uintmax_t b, struct libj2_j2u *res = *a; libj2_j2u_mod_ju(res, b); } + + +/** + * Calculate the integer quotient, rounded + * towards zero, of two unsigned double-max + * precision integers + * + * `libj2_j2u_div_j2u_underflow(a, b)` implements + * `t = !!(*a % b), *a /= *b, t` + * (using an intermediate variable `t`) + * + * @param a The dividend (left-hand), also used as + * the output parameter for the quotient + * @param b The divisor (right-hand) + * @return 1 if the remainder is non-zero, 0 otherwise + * + * @since 1.0 + */ +inline int +libj2_j2u_div_j2u_underflow(struct libj2_j2u *a, const struct libj2_j2u *b) +{ + struct libj2_j2u c = *a; + libj2_j2u_divmod_j2u_to_j2u(&c, b, a); + return c.high || c.low; +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of two unsigned double-max + * precision integers + * + * `libj2_j2u_div_j2u_to_j2u_underflow(a, b, res)` + * implements `*res = *a / *b, !!(a % b)` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @param res Output parameter for the quotient + * @return 1 if the remainder is non-zero, 0 otherwise + * + * @since 1.0 + */ +inline int +libj2_j2u_div_j2u_to_j2u_underflow(const struct libj2_j2u *a, const struct libj2_j2u *b, struct libj2_j2u *res) +{ + struct libj2_j2u c = *a; + libj2_j2u_divmod_j2u_to_j2u(&c, b, res); + return c.high || c.low; +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of two unsigned double-max + * precision integers; in this variant + * of `libj2_j2u_div_j2u`, the dividend + * (left-hand) is the second parameter and the + * divisor (right-hand) is the first parameter + * + * `libj2_j2u_rdiv_j2u_underflow(a, b)` implements + * `t = !!(*a % *b), *a = *b / *a, t` + * (using an intermediate variable `t`) + * + * @param a The divisor (right-hand), also used as + * the output parameter for the quotient + * @param b The dividend (left-hand) + * @return 1 if the remainder is non-zero, 0 otherwise + * + * @since 1.0 + */ +inline int +libj2_j2u_rdiv_j2u_underflow(struct libj2_j2u *a, const struct libj2_j2u *b) +{ + struct libj2_j2u c = *b; + libj2_j2u_divmod_j2u_to_j2u(&c, a, a); + return c.high || c.low; +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of an unsigned double-max + * precision integer (dividend) and an + * unsigned max precision integer (divisor) + * + * `libj2_j2u_div_ju_underflow(a, b)` implements + * `t = !!(a % b), *a /= b, t` + * (using an intermediate variable `t`) + * + * @param a The dividend (left-hand), also used as + * the output parameter for the quotient + * @param b The divisor (right-hand) + * @return 1 if the remainder is non-zero, 0 otherwise + * + * @since 1.0 + */ +inline int +libj2_j2u_div_ju_underflow(struct libj2_j2u *a, uintmax_t b) +{ + struct libj2_j2u c = *a; + libj2_j2u_divmod_ju_to_j2u(&c, b, a); + return c.high || c.low; +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of an unsigned double-max + * precision integer (dividend) and an + * unsigned max precision integer (divisor) + * + * `libj2_j2u_div_ju_to_j2u_underflow(a, b, res)` + * implements `*res = *a / b, !!(a % b)` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @param res Output parameter for the quotient + * @return 1 if the remainder is non-zero, 0 otherwise + * + * @since 1.0 + */ +inline int +libj2_j2u_div_ju_to_j2u_underflow(const struct libj2_j2u *a, uintmax_t b, struct libj2_j2u *res) +{ + struct libj2_j2u c = *a; + libj2_j2u_divmod_ju_to_j2u(&c, b, res); + return c.high || c.low; +} diff --git a/libj2_j2u_div_j2u_to_j2u_underflow.c b/libj2_j2u_div_j2u_to_j2u_underflow.c new file mode 100644 index 0000000..51985af --- /dev/null +++ b/libj2_j2u_div_j2u_to_j2u_underflow.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline int libj2_j2u_div_j2u_to_j2u_underflow(const struct libj2_j2u *a, const struct libj2_j2u *b, struct libj2_j2u *res); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2u_divmod_j2u_to_j2u.c */ + +#endif diff --git a/libj2_j2u_div_j2u_underflow.c b/libj2_j2u_div_j2u_underflow.c new file mode 100644 index 0000000..4ec62bd --- /dev/null +++ b/libj2_j2u_div_j2u_underflow.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline int libj2_j2u_div_j2u_underflow(struct libj2_j2u *a, const struct libj2_j2u *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2u_divmod_j2u_to_j2u.c */ + +#endif diff --git a/libj2_j2u_div_ju_to_j2u_underflow.c b/libj2_j2u_div_ju_to_j2u_underflow.c new file mode 100644 index 0000000..cc72dfb --- /dev/null +++ b/libj2_j2u_div_ju_to_j2u_underflow.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline int libj2_j2u_div_ju_to_j2u_underflow(const struct libj2_j2u *a, uintmax_t b, struct libj2_j2u *res); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2u_divmod_j2u_to_j2u.c */ + +#endif diff --git a/libj2_j2u_div_ju_underflow.c b/libj2_j2u_div_ju_underflow.c new file mode 100644 index 0000000..4117569 --- /dev/null +++ b/libj2_j2u_div_ju_underflow.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline int libj2_j2u_div_ju_underflow(struct libj2_j2u *a, uintmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2u_divmod_j2u_to_j2u.c */ + +#endif diff --git a/libj2_j2u_divmod_j2u_to_j2u.c b/libj2_j2u_divmod_j2u_to_j2u.c index 3c5e756..754a738 100644 --- a/libj2_j2u_divmod_j2u_to_j2u.c +++ b/libj2_j2u_divmod_j2u_to_j2u.c @@ -43,6 +43,7 @@ check_manual(const struct libj2_j2u *a, const struct libj2_j2u *b, const struct libj2_j2u *expected_q, const struct libj2_j2u *expected_r) { struct libj2_j2u a_saved = *a, b_saved = *b, q, r, eq, er; + int underflow; EXPECT(!libj2_j2u_is_zero(b)); @@ -63,6 +64,7 @@ check_manual(const struct libj2_j2u *a, const struct libj2_j2u *b, er = r; expected_r = &er; } + underflow = !libj2_j2u_is_zero(expected_r); validate_result(a, b, expected_q, expected_r); @@ -122,6 +124,22 @@ check_manual(const struct libj2_j2u *a, const struct libj2_j2u *b, EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + q = (struct libj2_j2u){333, 444}; + EXPECT(libj2_j2u_div_j2u_to_j2u_underflow(a, b, &q) == underflow); + EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); + EXPECT(libj2_j2u_eq_j2u(b, &b_saved)); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + + q = *a; + EXPECT(libj2_j2u_div_j2u_to_j2u_underflow(&q, b, &q) == underflow); + EXPECT(libj2_j2u_eq_j2u(b, &b_saved)); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + + q = *b; + EXPECT(libj2_j2u_div_j2u_to_j2u_underflow(a, &q, &q) == underflow); + EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + r = (struct libj2_j2u){111, 222}; libj2_j2u_mod_j2u_to_j2u(a, b, &r); EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); @@ -156,6 +174,11 @@ check_manual(const struct libj2_j2u *a, const struct libj2_j2u *b, EXPECT(libj2_j2u_eq_j2u(b, &b_saved)); EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + q = *a; + EXPECT(libj2_j2u_div_j2u_underflow(&q, b) == underflow); + EXPECT(libj2_j2u_eq_j2u(b, &b_saved)); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + r = *a; libj2_j2u_mod_j2u(&r, b); EXPECT(libj2_j2u_eq_j2u(b, &b_saved)); @@ -179,6 +202,11 @@ check_manual(const struct libj2_j2u *a, const struct libj2_j2u *b, EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + q = *b; + EXPECT(libj2_j2u_rdiv_j2u_underflow(&q, a) == underflow); + EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + r = *b; libj2_j2u_rmod_j2u(&r, a); EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); @@ -222,6 +250,15 @@ check_manual(const struct libj2_j2u *a, const struct libj2_j2u *b, libj2_j2u_div_ju_to_j2u(&q, b->low, &q); EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + q = (struct libj2_j2u){333, 444}; + EXPECT(libj2_j2u_div_ju_to_j2u_underflow(a, b->low, &q) == underflow); + EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + + q = *a; + EXPECT(libj2_j2u_div_ju_to_j2u_underflow(&q, b->low, &q) == underflow); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + r = (struct libj2_j2u){111, 222}; libj2_j2u_mod_ju_to_j2u(a, b->low, &r); EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); @@ -241,6 +278,10 @@ check_manual(const struct libj2_j2u *a, const struct libj2_j2u *b, libj2_j2u_div_ju(&q, b->low); EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + q = *a; + EXPECT(libj2_j2u_div_ju_underflow(&q, b->low) == underflow); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + r = *a; libj2_j2u_mod_ju(&r, b->low); EXPECT(libj2_j2u_eq_j2u(&r, expected_r)); @@ -275,6 +316,10 @@ check_manual(const struct libj2_j2u *a, const struct libj2_j2u *b, libj2_j2u_div_j2u_to_j2u(&q, &q, &q); EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + q = *a; + EXPECT(libj2_j2u_div_j2u_to_j2u_underflow(&q, &q, &q) == underflow); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + r = *a; libj2_j2u_mod_j2u_to_j2u(&r, &r, &r); EXPECT(libj2_j2u_eq_j2u(&r, expected_r)); @@ -289,6 +334,10 @@ check_manual(const struct libj2_j2u *a, const struct libj2_j2u *b, libj2_j2u_div_j2u(&q, &q); EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + q = *a; + EXPECT(libj2_j2u_div_j2u_underflow(&q, &q) == underflow); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + r = *a; libj2_j2u_mod_j2u(&r, &r); EXPECT(libj2_j2u_eq_j2u(&r, expected_r)); @@ -303,6 +352,10 @@ check_manual(const struct libj2_j2u *a, const struct libj2_j2u *b, libj2_j2u_rdiv_j2u(&q, &q); EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + q = *a; + EXPECT(libj2_j2u_rdiv_j2u_underflow(&q, &q) == underflow); + EXPECT(libj2_j2u_eq_j2u(&q, expected_q)); + r = *a; libj2_j2u_rmod_j2u(&r, &r); EXPECT(libj2_j2u_eq_j2u(&r, expected_r)); diff --git a/libj2_j2u_rdiv_j2u_underflow.c b/libj2_j2u_rdiv_j2u_underflow.c new file mode 100644 index 0000000..db5239a --- /dev/null +++ b/libj2_j2u_rdiv_j2u_underflow.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline int libj2_j2u_rdiv_j2u_underflow(struct libj2_j2u *a, const struct libj2_j2u *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2u_divmod_j2u_to_j2u.c */ + +#endif |
