aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Makefile7
-rw-r--r--libj2/division.h128
-rw-r--r--libj2_j2u_div_j2u_to_j2u_underflow.c13
-rw-r--r--libj2_j2u_div_j2u_underflow.c13
-rw-r--r--libj2_j2u_div_ju_to_j2u_underflow.c13
-rw-r--r--libj2_j2u_div_ju_underflow.c13
-rw-r--r--libj2_j2u_divmod_j2u_to_j2u.c53
-rw-r--r--libj2_j2u_rdiv_j2u_underflow.c13
8 files changed, 252 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 4890df6..7cf9041 100644
--- a/Makefile
+++ b/Makefile
@@ -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