aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2025-12-11 18:32:27 +0100
committerMattias Andrée <m@maandree.se>2025-12-11 18:32:27 +0100
commit50bb696a6b4d75a097f22274834f67961fa9e440 (patch)
tree44270d52d6440c02b30b4b7d49950519770585c2
parentcleanup (diff)
downloadlibj2-50bb696a6b4d75a097f22274834f67961fa9e440.tar.gz
libj2-50bb696a6b4d75a097f22274834f67961fa9e440.tar.bz2
libj2-50bb696a6b4d75a097f22274834f67961fa9e440.tar.xz
Add signed integers (arithmetics and some testing not implemented yet)
Signed-off-by: Mattias Andrée <m@maandree.se>
-rw-r--r--Makefile134
-rw-r--r--libj2.h64
-rw-r--r--libj2/bit-shifting.h570
-rw-r--r--libj2/bitwise-logic.h3
-rw-r--r--libj2/constants.h121
-rw-r--r--libj2/constructors.h92
-rw-r--r--libj2/mixed-comparsion.h820
-rw-r--r--libj2/sign-shifting.h271
-rw-r--r--libj2/signed-comparsion.h858
-rw-r--r--libj2/signum.h61
-rw-r--r--libj2/strings.h194
-rw-r--r--libj2/unsigned-comparsion.h9
-rw-r--r--libj2_abs_j2i.c14
-rw-r--r--libj2_abs_j2i_to_j2i.c13
-rw-r--r--libj2_abs_j2i_to_j2u.c13
-rw-r--r--libj2_j2i_cmp_j2i.c244
-rw-r--r--libj2_j2i_cmp_j2u.c14
-rw-r--r--libj2_j2i_cmp_ji.c188
-rw-r--r--libj2_j2i_cmp_ju.c14
-rw-r--r--libj2_j2i_eq_j2i.c13
-rw-r--r--libj2_j2i_eq_j2u.c13
-rw-r--r--libj2_j2i_eq_ji.c13
-rw-r--r--libj2_j2i_eq_ju.c13
-rw-r--r--libj2_j2i_ge_j2i.c13
-rw-r--r--libj2_j2i_ge_j2u.c13
-rw-r--r--libj2_j2i_ge_ji.c13
-rw-r--r--libj2_j2i_ge_ju.c13
-rw-r--r--libj2_j2i_gt_j2i.c13
-rw-r--r--libj2_j2i_gt_j2u.c13
-rw-r--r--libj2_j2i_gt_ji.c13
-rw-r--r--libj2_j2i_gt_ju.c13
-rw-r--r--libj2_j2i_is_max.c225
-rw-r--r--libj2_j2i_is_min.c225
-rw-r--r--libj2_j2i_is_negative.c228
-rw-r--r--libj2_j2i_is_positive.c228
-rw-r--r--libj2_j2i_is_zero.c225
-rw-r--r--libj2_j2i_le_j2i.c13
-rw-r--r--libj2_j2i_le_j2u.c13
-rw-r--r--libj2_j2i_le_ji.c13
-rw-r--r--libj2_j2i_le_ju.c13
-rw-r--r--libj2_j2i_lsh.c14
-rw-r--r--libj2_j2i_lsh_overflow.c13
-rw-r--r--libj2_j2i_lsh_overflow_p.c13
-rw-r--r--libj2_j2i_lsh_to_j2i.c13
-rw-r--r--libj2_j2i_lsh_to_j2i_overflow.c13
-rw-r--r--libj2_j2i_lt_j2i.c13
-rw-r--r--libj2_j2i_lt_j2u.c13
-rw-r--r--libj2_j2i_lt_ji.c13
-rw-r--r--libj2_j2i_lt_ju.c13
-rw-r--r--libj2_j2i_max.c33
-rw-r--r--libj2_j2i_max_j2i.c13
-rw-r--r--libj2_j2i_max_j2i_to_j2i.c13
-rw-r--r--libj2_j2i_max_ji.c13
-rw-r--r--libj2_j2i_max_ji_to_j2i.c13
-rw-r--r--libj2_j2i_min.c32
-rw-r--r--libj2_j2i_min_j2i.c13
-rw-r--r--libj2_j2i_min_j2i_to_j2i.c13
-rw-r--r--libj2_j2i_min_ji.c13
-rw-r--r--libj2_j2i_min_ji_to_j2i.c13
-rw-r--r--libj2_j2i_ne_j2i.c13
-rw-r--r--libj2_j2i_ne_j2u.c13
-rw-r--r--libj2_j2i_ne_ji.c13
-rw-r--r--libj2_j2i_ne_ju.c13
-rw-r--r--libj2_j2i_rsh.c14
-rw-r--r--libj2_j2i_rsh_to_j2i.c13
-rw-r--r--libj2_j2i_rsh_to_j2i_underflow.c13
-rw-r--r--libj2_j2i_rsh_underflow.c13
-rw-r--r--libj2_j2i_rsh_underflow_p.c13
-rw-r--r--libj2_j2i_to_j2u.c77
-rw-r--r--libj2_j2i_xor_sign.c14
-rw-r--r--libj2_j2i_xor_sign_to_j2i.c13
-rw-r--r--libj2_j2i_xor_sign_to_j2u.c13
-rw-r--r--libj2_j2i_zero.c27
-rw-r--r--libj2_j2u_cmp_j2i.c13
-rw-r--r--libj2_j2u_cmp_j2u.c17
-rw-r--r--libj2_j2u_cmp_ji.c14
-rw-r--r--libj2_j2u_cmp_ju.c25
-rw-r--r--libj2_j2u_eq_j2i.c13
-rw-r--r--libj2_j2u_eq_ji.c13
-rw-r--r--libj2_j2u_ge_j2i.c13
-rw-r--r--libj2_j2u_ge_ji.c13
-rw-r--r--libj2_j2u_gt_j2i.c13
-rw-r--r--libj2_j2u_gt_ji.c13
-rw-r--r--libj2_j2u_is_max.c66
-rw-r--r--libj2_j2u_is_min.c66
-rw-r--r--libj2_j2u_is_positive.c66
-rw-r--r--libj2_j2u_is_zero.c66
-rw-r--r--libj2_j2u_le_j2i.c13
-rw-r--r--libj2_j2u_le_ji.c13
-rw-r--r--libj2_j2u_lt_j2i.c13
-rw-r--r--libj2_j2u_lt_ji.c13
-rw-r--r--libj2_j2u_max.c3
-rw-r--r--libj2_j2u_min.c3
-rw-r--r--libj2_j2u_ne_j2i.c13
-rw-r--r--libj2_j2u_ne_ji.c13
-rw-r--r--libj2_j2u_to_j2i.c77
-rw-r--r--libj2_j2u_to_str.c2
-rw-r--r--libj2_j2u_zero.c8
-rw-r--r--libj2_ji_cmp_j2i.c13
-rw-r--r--libj2_ji_cmp_j2u.c13
-rw-r--r--libj2_ji_eq_j2i.c13
-rw-r--r--libj2_ji_eq_j2u.c13
-rw-r--r--libj2_ji_ge_j2i.c13
-rw-r--r--libj2_ji_ge_j2u.c13
-rw-r--r--libj2_ji_gt_j2i.c13
-rw-r--r--libj2_ji_gt_j2u.c13
-rw-r--r--libj2_ji_le_j2i.c13
-rw-r--r--libj2_ji_le_j2u.c13
-rw-r--r--libj2_ji_lsh_overflow_p.c13
-rw-r--r--libj2_ji_lsh_to_j2i.c14
-rw-r--r--libj2_ji_lsh_to_j2i_overflow.c13
-rw-r--r--libj2_ji_lt_j2i.c13
-rw-r--r--libj2_ji_lt_j2u.c13
-rw-r--r--libj2_ji_ne_j2i.c13
-rw-r--r--libj2_ji_ne_j2u.c13
-rw-r--r--libj2_ji_rsh_to_j2i.c14
-rw-r--r--libj2_ji_rsh_to_j2i_underflow.c13
-rw-r--r--libj2_ji_rsh_underflow_p.c13
-rw-r--r--libj2_ji_to_j2i.c54
-rw-r--r--libj2_ju_cmp_j2i.c13
-rw-r--r--libj2_ju_eq_j2i.c13
-rw-r--r--libj2_ju_ge_j2i.c13
-rw-r--r--libj2_ju_gt_j2i.c13
-rw-r--r--libj2_ju_le_j2i.c13
-rw-r--r--libj2_ju_lt_j2i.c13
-rw-r--r--libj2_ju_ne_j2i.c13
-rw-r--r--libj2_ju_to_j2i.c39
-rw-r--r--libj2_ju_to_j2u.c10
-rw-r--r--libj2_max_j2i.c185
-rw-r--r--libj2_max_j2i_return.c13
-rw-r--r--libj2_max_j2i_to_j2i.c13
-rw-r--r--libj2_max_j2u.c24
-rw-r--r--libj2_min_j2i.c197
-rw-r--r--libj2_min_j2i_return.c13
-rw-r--r--libj2_min_j2i_to_j2i.c13
-rw-r--r--libj2_min_j2u.c24
-rw-r--r--libj2_minus_abs_j2i.c13
-rw-r--r--libj2_minus_abs_j2i_to_j2i.c13
-rw-r--r--libj2_minus_j2i.c95
-rw-r--r--libj2_minus_j2i_to_j2i.c13
-rw-r--r--libj2_minus_j2i_to_j2u.c14
-rw-r--r--libj2_minus_j2u.c8
-rw-r--r--libj2_minus_j2u_to_j2i.c14
-rw-r--r--libj2_sgn_j2i.c228
-rw-r--r--libj2_sgn_j2u.c66
-rw-r--r--libj2_str_to_j2i.c138
-rw-r--r--libj2_str_to_j2u.c266
-rw-r--r--libj2_str_to_j2u_sign.c350
-rw-r--r--libj2_vmax_j2i.c13
-rw-r--r--libj2_vmax_j2i_return.c13
-rw-r--r--libj2_vmax_j2i_to_j2i.c13
-rw-r--r--libj2_vmin_j2i.c13
-rw-r--r--libj2_vmin_j2i_return.c13
-rw-r--r--libj2_vmin_j2i_to_j2i.c13
154 files changed, 7969 insertions, 432 deletions
diff --git a/Makefile b/Makefile
index b00a8ce..5750c29 100644
--- a/Makefile
+++ b/Makefile
@@ -300,17 +300,147 @@ OBJ =\
libj2_j2u_sat_mul_j2u.o\
libj2_j2u_sat_mul_j2u_to_j2u.o\
libj2_j2u_to_str.o\
- libj2_str_to_j2u.o
+ libj2_str_to_j2u.o\
+ libj2_str_to_j2u_sign.o\
+ libj2_str_to_j2i.o\
+ libj2_j2i_is_zero.o\
+ libj2_j2i_zero.o\
+ libj2_j2i_is_max.o\
+ libj2_j2i_max.o\
+ libj2_j2i_is_min.o\
+ libj2_j2i_min.o\
+ libj2_ju_to_j2i.o\
+ libj2_ji_to_j2i.o\
+ libj2_j2u_to_j2i.o\
+ libj2_j2i_to_j2u.o\
+ libj2_j2i_is_positive.o\
+ libj2_j2i_is_negative.o\
+ libj2_sgn_j2i.o\
+ libj2_j2i_eq_j2i.o\
+ libj2_j2i_eq_ji.o\
+ libj2_j2i_ge_j2i.o\
+ libj2_j2i_ge_ji.o\
+ libj2_j2i_gt_j2i.o\
+ libj2_j2i_gt_ji.o\
+ libj2_j2i_le_j2i.o\
+ libj2_j2i_le_ji.o\
+ libj2_j2i_lt_j2i.o\
+ libj2_j2i_lt_ji.o\
+ libj2_j2i_ne_j2i.o\
+ libj2_j2i_ne_ji.o\
+ libj2_ji_eq_j2i.o\
+ libj2_ji_ge_j2i.o\
+ libj2_ji_gt_j2i.o\
+ libj2_ji_le_j2i.o\
+ libj2_ji_lt_j2i.o\
+ libj2_ji_ne_j2i.o\
+ libj2_j2u_eq_j2i.o\
+ libj2_j2u_eq_ji.o\
+ libj2_j2u_ge_j2i.o\
+ libj2_j2u_ge_ji.o\
+ libj2_j2u_gt_j2i.o\
+ libj2_j2u_gt_ji.o\
+ libj2_j2u_le_j2i.o\
+ libj2_j2u_le_ji.o\
+ libj2_j2u_lt_j2i.o\
+ libj2_j2u_lt_ji.o\
+ libj2_j2u_ne_j2i.o\
+ libj2_j2u_ne_ji.o\
+ libj2_ju_eq_j2i.o\
+ libj2_ju_ge_j2i.o\
+ libj2_ju_gt_j2i.o\
+ libj2_ju_le_j2i.o\
+ libj2_ju_lt_j2i.o\
+ libj2_ju_ne_j2i.o\
+ libj2_j2i_eq_j2u.o\
+ libj2_j2i_eq_ju.o\
+ libj2_j2i_ge_j2u.o\
+ libj2_j2i_ge_ju.o\
+ libj2_j2i_gt_j2u.o\
+ libj2_j2i_gt_ju.o\
+ libj2_j2i_le_j2u.o\
+ libj2_j2i_le_ju.o\
+ libj2_j2i_lt_j2u.o\
+ libj2_j2i_lt_ju.o\
+ libj2_j2i_ne_j2u.o\
+ libj2_j2i_ne_ju.o\
+ libj2_ji_eq_j2u.o\
+ libj2_ji_ge_j2u.o\
+ libj2_ji_gt_j2u.o\
+ libj2_ji_le_j2u.o\
+ libj2_ji_lt_j2u.o\
+ libj2_ji_ne_j2u.o\
+ libj2_ji_cmp_j2i.o\
+ libj2_j2i_cmp_ji.o\
+ libj2_j2i_cmp_j2i.o\
+ libj2_j2i_max_j2i_to_j2i.o\
+ libj2_j2i_max_ji_to_j2i.o\
+ libj2_j2i_max_j2i.o\
+ libj2_j2i_max_ji.o\
+ libj2_j2i_min_j2i_to_j2i.o\
+ libj2_j2i_min_ji_to_j2i.o\
+ libj2_j2i_min_j2i.o\
+ libj2_j2i_min_ji.o\
+ libj2_vmax_j2i.o\
+ libj2_max_j2i.o\
+ libj2_vmin_j2i.o\
+ libj2_min_j2i.o\
+ libj2_vmax_j2i_to_j2i.o\
+ libj2_max_j2i_to_j2i.o\
+ libj2_min_j2i_to_j2i.o\
+ libj2_vmin_j2i_to_j2i.o\
+ libj2_vmin_j2i_return.o\
+ libj2_min_j2i_return.o\
+ libj2_max_j2i_to_j2i.o\
+ libj2_vmax_j2i_to_j2i.o\
+ libj2_vmax_j2i_return.o\
+ libj2_max_j2i_return.o\
+ libj2_minus_j2i_to_j2i.o\
+ libj2_minus_j2i.o\
+ libj2_minus_j2i_to_j2u.o\
+ libj2_minus_j2u_to_j2i.o\
+ libj2_abs_j2i_to_j2i.o\
+ libj2_abs_j2i.o\
+ libj2_abs_j2i_to_j2u.o\
+ libj2_minus_abs_j2i_to_j2i.o\
+ libj2_minus_abs_j2i.o\
+ libj2_j2i_xor_sign_to_j2i.o\
+ libj2_j2i_xor_sign_to_j2u.o\
+ libj2_j2i_xor_sign.o\
+ libj2_j2i_cmp_j2u.o\
+ libj2_j2u_cmp_j2i.o\
+ libj2_ji_cmp_j2u.o\
+ libj2_ju_cmp_j2i.o\
+ libj2_j2i_cmp_ju.o\
+ libj2_j2u_cmp_ji.o\
+ libj2_j2i_lsh.o\
+ libj2_j2i_lsh_to_j2i.o\
+ libj2_ji_lsh_to_j2i.o\
+ libj2_j2i_lsh_overflow.o\
+ libj2_j2i_lsh_to_j2i_overflow.o\
+ libj2_ji_lsh_to_j2i_overflow.o\
+ libj2_j2i_rsh_to_j2i.o\
+ libj2_j2i_rsh.o\
+ libj2_ji_rsh_to_j2i.o\
+ libj2_j2i_rsh_to_j2i_underflow.o\
+ libj2_j2i_rsh_underflow.o\
+ libj2_ji_rsh_to_j2i_underflow.o\
+ libj2_j2i_lsh_overflow_p.o\
+ libj2_ji_lsh_overflow_p.o\
+ libj2_j2i_rsh_underflow_p.o\
+ libj2_ji_rsh_underflow_p.o
SUBHDR =\
libj2/constants.h\
libj2/signum.h\
libj2/constructors.h\
libj2/unsigned-comparsion.h\
+ libj2/signed-comparsion.h\
+ libj2/mixed-comparsion.h\
libj2/bitwise-logic.h\
+ libj2/sign-shifting.h\
libj2/bit-shifting.h\
libj2/bit-scanning.h\
- libj2/sign-shifting.h\
libj2/addition.h\
libj2/subtraction.h\
libj2/multiplication.h\
diff --git a/libj2.h b/libj2.h
index 6d45d26..dd7fc35 100644
--- a/libj2.h
+++ b/libj2.h
@@ -32,12 +32,29 @@
#define LIBJ2_JU_BIT ((unsigned)CHAR_BIT * (unsigned)sizeof(uintmax_t))
/**
- * The number of bits in an `struct libj2_j2u`
+ * The number of bits in a `struct libj2_j2u`
*
* @since 1.0
*/
#define LIBJ2_J2U_BIT (2U * LIBJ2_JU_BIT)
+/**
+ * The number of bits in a `struct libj2_j2i`,
+ * including the sign bit
+ *
+ * @since 1.1
+ */
+#define LIBJ2_J2I_BIT LIBJ2_J2U_BIT
+
+/**
+ * The number of value bits in a `struct libj2_j2i`,
+ * that is, the number of bits excluding the sign
+ * bit
+ *
+ * @since 1.1
+ */
+#define LIBJ2_J2I_VBIT (LIBJ2_J2I_BIT - 1U)
+
/**
* Unsigned double-maximum precision integer
@@ -60,6 +77,37 @@ struct libj2_j2u {
/**
+ * Signed double-maximum precision integer,
+ * using two's complement
+ *
+ * libj2 does not implement bitwise operations,
+ * bit-scanning, or bit-rotation operations
+ * for this type, but a `struct libj2_j2i *`
+ * can safetly be casted to `struct libj2_j2u *`
+ * for such operators as well as the for
+ * unsigned bit shifting operations
+ *
+ * If `a` is the maximum representable value,
+ * `-a - 1` is the minimum representable value;
+ * there is only one zero value (has no sign)
+ *
+ * @since 1.1
+ */
+struct libj2_j2i {
+ /**
+ * Most significant half, of which the most
+ * significant bit is the sign bit
+ */
+ uintmax_t high;
+
+ /**
+ * Least significant half
+ */
+ uintmax_t low;
+};
+
+
+/**
* Arithmetic overflow prediction result
*
* Use by some functions for which prediction
@@ -91,15 +139,17 @@ enum libj2_overflow {
#include "libj2/signum.h"
#include "libj2/constructors.h"
#include "libj2/unsigned-comparsion.h"
+#include "libj2/signed-comparsion.h"
+#include "libj2/mixed-comparsion.h"
#include "libj2/bitwise-logic.h"
+#include "libj2/sign-shifting.h"
#include "libj2/bit-shifting.h"
#include "libj2/bit-scanning.h"
-#include "libj2/sign-shifting.h"
-#include "libj2/addition.h"
-#include "libj2/subtraction.h"
-#include "libj2/multiplication.h"
-#include "libj2/division.h"
-#include "libj2/saturated-math.h"
+#include "libj2/addition.h" /* TODO add signed versions */
+#include "libj2/subtraction.h" /* TODO add signed versions */
+#include "libj2/multiplication.h" /* TODO add signed versions */
+#include "libj2/division.h" /* TODO add signed versions */
+#include "libj2/saturated-math.h" /* TODO add signed versions */
#include "libj2/strings.h"
diff --git a/libj2/bit-shifting.h b/libj2/bit-shifting.h
index c31674f..e09213d 100644
--- a/libj2/bit-shifting.h
+++ b/libj2/bit-shifting.h
@@ -372,8 +372,8 @@ libj2_j2u_rsh_underflow(struct libj2_j2u *a, unsigned b)
* and positions without any new bit will be assigned
* the bit value 0
*
- * `libj2_j2u_rsh_to_j2u_underflow(a, b, res)` implements
- * `*res = *a >> b, a != *res << b`
+ * `libj2_j2u_rsh_to_j2u_underflow(a, b, res)`
+ * implements `*res = *a >> b, a != *res << b`
*
* This is equivalent to dividing `a` by the `b`th
* power of 2
@@ -721,3 +721,569 @@ libj2_ju_rsh_underflow_p(uintmax_t a, unsigned b)
else
return 0;
}
+
+
+
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer to more signficant positions (left-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_j2i_lsh(a, b)` implements `*a <<= b`
+ *
+ * This is equivalent to multiplying `a` by the `b`th
+ * power of 2
+ *
+ * @param a The integer to shift, also used as the
+ * output parameter for the result
+ * @param b The number of positions to shift each bit
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_lsh(struct libj2_j2i *a, unsigned b)
+{
+ libj2_j2u_lsh((void *)a, b);
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer to more signficant positions (left-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_j2i_lsh_to_j2i(a, b, res)` implements `*res = *a << b`
+ *
+ * This is equivalent to multiplying `a` by the `b`th
+ * power of 2
+ *
+ * @param a The integer to shift
+ * @param b The number of positions to shift each bit
+ * @param res Output parameter for the result
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_lsh_to_j2i(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *res)
+{
+ libj2_j2u_lsh_to_j2u((const void *)a, b, (void *)res);
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer, represented by a signed max precision
+ * integer and whose absolute value's high part is
+ * treated as having the value 0, to more signficant
+ * positions (left-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_ji_lsh_to_j2i(a, b, res)` implements `*res = a << b`,
+ * where `a` is converted to a `struct libj2_j2i`
+ *
+ * This is equivalent to multiplying `a` by the `b`th
+ * power of 2
+ *
+ * You can rely on `libj2_ji_lsh_to_j2i(1, LIBJ2_J2I_BIT, res)`
+ * overflowing and assigning 0 to `*res`, and thus, subtracting
+ * 1 from `*res` afterwards will set all bits; and so,
+ * `libj2_ji_lsh_to_j2i(1, n, a), libj2_j2i_sub_j2(a, 1)` will
+ * always set the `n` least significant bits in `a` and clear
+ * all other bits
+ *
+ * @param a The integer to shift
+ * @param b The number of positions to shift each bit
+ * @param res Output parameter for the result
+ *
+ * @since 1.1
+ */
+inline void
+libj2_ji_lsh_to_j2i(intmax_t a, unsigned b, struct libj2_j2i *res)
+{
+ libj2_ji_to_j2i(a, res);
+ libj2_j2i_lsh(res, b);
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer to more signficant positions (left-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_j2i_lsh_overflow(a, b)` implements
+ * `(*a << b) >> b == *a ? (*a <<= b, 0) : (*a <<= b, sgn(*a))`
+ *
+ * This is equivalent to multiplying `a` by the `b`th
+ * power of 2
+ *
+ * @param a The integer to shift, also used as the
+ * output parameter for the result
+ * @param b The number of positions to shift each bit
+ * @return +1 if `*a` was non-negative and a set bit
+ * was shifted out of precision (discarded or
+ * into the sign-bit position), that is, a
+ * positive overflow,
+ * -1 if `*a` was negative and a cleared bit
+ * was shifted out of precision (discarded or
+ * into the sign-bit position), that is, a
+ * negative overflow,
+ * 0 otherwise
+ *
+ * @since 1.1
+ */
+inline int
+libj2_j2i_lsh_overflow(struct libj2_j2i *a, unsigned b)
+{
+ if (libj2_j2i_is_negative(a)) {
+ int overflow;
+ libj2_not_j2u((void *)a);
+ overflow = libj2_j2u_lsh_overflow((void *)a, b) || libj2_j2i_is_negative(a);
+ libj2_not_j2u((void *)a);
+ return -overflow;
+ } else {
+ return libj2_j2u_lsh_overflow((void *)a, b) || libj2_j2i_is_negative(a);
+ }
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer to more signficant positions (left-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_j2i_lsh_to_j2i_overflow(a, b, res)` implements
+ * `*res = *a << b, sgn(*a) * (*a != *res >> b)`
+ *
+ * This is equivalent to multiplying `a` by the `b`th
+ * power of 2
+ *
+ * @param a The integer to shift
+ * @param b The number of positions to shift each bit
+ * @param res Output parameter for the result
+ * @return +1 if `*a` was non-negative and a set bit
+ * was shifted out of precision (discarded or
+ * into the sign-bit position), that is, a
+ * positive overflow,
+ * -1 if `*a` was negative and a cleared bit
+ * was shifted out of precision (discarded or
+ * into the sign-bit position), that is, a
+ * negative overflow,
+ * 0 otherwise
+ *
+ * @since 1.1
+ */
+inline int
+libj2_j2i_lsh_to_j2i_overflow(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *res)
+{
+ *res = *a;
+ return libj2_j2i_lsh_overflow(res, b);
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer, represented by a signed max precision
+ * integer and whose high part is treated as having
+ * the value 0, to more signficant positions (left-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_ji_lsh_to_j2i_overflow(a, b, res)` implements
+ * `*res = a << b, sgn(a) * (a != *res >> b`), where `a`
+ * is converted to a `struct libj2_j2i`
+ *
+ * This is equivalent to multiplying `a` by the `b`th
+ * power of 2
+ *
+ * @param a The integer to shift
+ * @param b The number of positions to shift each bit
+ * @param res Output parameter for the result
+ * @return +1 if `a` was non-negative and a set bit
+ * was shifted out of precision (discarded or
+ * into the sign-bit position), that is, a
+ * positive overflow,
+ * -1 if `a` was negative and a cleared bit
+ * was shifted out of precision (discarded or
+ * into the sign-bit position), that is, a
+ * negative overflow,
+ * 0 otherwise
+ *
+ * @since 1.1
+ */
+inline int
+libj2_ji_lsh_to_j2i_overflow(intmax_t a, unsigned b, struct libj2_j2i *res)
+{
+ libj2_ji_to_j2i(a, res);
+ return libj2_j2i_lsh_overflow(res, b);
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer to less signficant positions (right-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_j2i_rsh_to_j2i(a, b, res)` implements `*res = *a >> b`
+ *
+ * This is equivalent to dividing `a` by the `b`th
+ * power of 2, using floored division
+ *
+ * @param a The integer to shift
+ * @param b The number of positions to shift each bit
+ * @param res Output parameter for the result
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_rsh_to_j2i(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *res)
+{
+ if (!libj2_j2i_is_negative(a)) {
+ libj2_j2u_rsh_to_j2u((const void *)a, b, (void *)res);
+ } else if (b >= LIBJ2_J2U_BIT) {
+ res->high = UINTMAX_MAX;
+ res->low = UINTMAX_MAX;
+ } else if (b == LIBJ2_JU_BIT) {
+ res->low = a->high;
+ res->high = UINTMAX_MAX;
+ } else if (b > LIBJ2_JU_BIT) {
+ res->low = a->high;
+ res->high = UINTMAX_MAX;
+ b -= LIBJ2_JU_BIT;
+ res->low >>= b;
+ res->low |= ((uintmax_t)1 << (LIBJ2_JU_BIT - 1U)) - 1U;
+ } else if (b) {
+ libj2_j2u_rsh_to_j2u((const void *)a, b, (void *)res);
+ res->high |= ((uintmax_t)1 << (LIBJ2_JU_BIT - 1U)) - 1U;
+ }
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer to less signficant positions (right-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_j2i_rsh(a, b)` implements `*a >>= b`
+ *
+ * This is equivalent to dividing `a` by the `b`th
+ * power of 2, using floored division
+ *
+ * @param a The integer to shift, also used as the
+ * output parameter for the result
+ * @param b The number of positions to shift each bit
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_rsh(struct libj2_j2i *a, unsigned b)
+{
+ libj2_j2i_rsh_to_j2i(a, b, a);
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer, represented by a signed max precision
+ * integer and whose high part is treated as having
+ * the value 0, to less signficant positions (right-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_ji_rsh_to_j2i(a, b, res)` implements `*res = a >> b`,
+ * where `a` is converted to a `struct libj2_j2i`
+ *
+ * This is equivalent to dividing `a` by the `b`th
+ * power of 2, using floored division
+ *
+ * @param a The integer to shift
+ * @param b The number of positions to shift each bit
+ * @param res Output parameter for the result
+ *
+ * @since 1.1
+ */
+inline void
+libj2_ji_rsh_to_j2i(intmax_t a, unsigned b, struct libj2_j2i *res)
+{
+ libj2_ji_to_j2i(a, res);
+ libj2_j2i_rsh(res, b);
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer to less signficant positions (right-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_j2i_rsh_to_j2i_underflow(a, b, res)`
+ * implements `*res = *a >> b, sign(*a) * (*a != *res << b)`
+ *
+ * This is equivalent to dividing `a` by the `b`th
+ * power of 2, using floored division
+ *
+ * @param a The integer to shift
+ * @param b The number of positions to shift each bit
+ * @param res Output parameter for the result
+ * @return +1 if `*a` was non-negative and a set bit
+ * was shifted out (discarded), that is, a
+ * positive underflow,
+ * -1 if `*a` was negative and a cleared bit
+ * was shifted out (discarded), that is, a
+ * positive underflow,
+ * 0 otherwise
+ *
+ * @since 1.1
+ */
+inline int
+libj2_j2i_rsh_to_j2i_underflow(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *res)
+{
+ if (libj2_j2i_is_negative(a)) {
+ int underflow;
+ libj2_not_j2u_to_j2u((const void *)a, (void *)res);
+ underflow = libj2_j2u_rsh_underflow((void *)res, b);
+ libj2_not_j2u((void *)res);
+ return -underflow;
+ } else {
+ return libj2_j2u_rsh_to_j2u_underflow((const void *)a, b, (void *)res);
+ }
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer to less signficant positions (right-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_j2i_rsh_underflow(a, b)` implements
+ * `(*a >> b) << b == *a ? (*a >>= b, 0) : (*a >>= b, sgn(*a))`
+ *
+ * This is equivalent to dividing `a` by the `b`th
+ * power of 2, using floored division
+ *
+ * @param a The integer to shift, also used as the
+ * output parameter for the result
+ * @param b The number of positions to shift each bit
+ * @return +1 if `*a` was non-negative and a set bit
+ * was shifted out (discarded), that is, a
+ * positive underflow,
+ * -1 if `*a` was negative and a cleared bit
+ * was shifted out (discarded), that is, a
+ * positive underflow,
+ * 0 otherwise
+ *
+ * @since 1.1
+ */
+inline int
+libj2_j2i_rsh_underflow(struct libj2_j2i *a, unsigned b)
+{
+ return libj2_j2i_rsh_to_j2i_underflow(a, b, a);
+}
+
+
+/**
+ * Shift the bits in a signed double-max precision
+ * integer, represented by a signed max precision
+ * integer and whose high part is treated as having
+ * the value 0, to less signficant positions (right-shift)
+ *
+ * Bits shifted out of precision will be discarded,
+ * and positions without any new bit will be assigned
+ * the bit value 0
+ *
+ * `libj2_ji_rsh_to_j2i_underflow(a, b, res)` implements
+ * `*res = a >> b, sgn(a) * (a != *res << b`), where `a`
+ * is converted to a `struct libj2_j2i`
+ *
+ * This is equivalent to dividing `a` by the `b`th
+ * power of 2, using floored division
+ *
+ * @param a The integer to shift
+ * @param b The number of positions to shift each bit
+ * @param res Output parameter for the result
+ * @return +1 if `a` was non-negative and a set bit
+ * was shifted out (discarded), that is, a
+ * positive underflow,
+ * -1 if `a` was negative and a cleared bit
+ * was shifted out (discarded), that is, a
+ * positive underflow,
+ * 0 otherwise
+ *
+ * @since 1.1
+ */
+inline int
+libj2_ji_rsh_to_j2i_underflow(intmax_t a, unsigned b, struct libj2_j2i *res)
+{
+ libj2_ji_to_j2i(a, res);
+ return libj2_j2i_rsh_underflow(res, b);
+}
+
+
+/**
+ * Predict whether `libj2_j2i_lsh_overflow` or
+ * `libj2_j2i_lsh_to_j2i_overflow` will return
+ * a result-overflow signal
+ *
+ * `libj2_j2i_lsh_overflow_p(a, b)` implements
+ * `libj2_j2i_lsh_to_j2i_overflow(a, b, &(struct libj2_j2i){})`
+ * in an efficient manner
+ *
+ * @param a The integer to shift (dry-run)
+ * @param b The number of positions to shift each bit
+ * @return +1 if `*a` is non-negative and a set bit
+ * would be shifted out of precision (discarded
+ * or into the sign-bit position), that is, a
+ * positive overflow,
+ * -1 if `*a` is negative and a cleared bit
+ * would be shifted out of precision (discarded
+ * or into the sign-bit position), that is, a
+ * negative overflow,
+ * 0 otherwise
+ *
+ * @since 1.1
+ */
+inline int
+libj2_j2i_lsh_overflow_p(const struct libj2_j2i *a, unsigned b)
+{
+ struct libj2_j2u t;
+ int overflow;
+ libj2_j2i_xor_sign_to_j2u(a, &t);
+ b = b > LIBJ2_J2I_BIT ? LIBJ2_J2I_BIT + 1U : b + 1U;
+ overflow = libj2_j2u_lsh_overflow_p(&t, b);
+ return overflow && libj2_j2i_is_negative(a) ? -1 : overflow;
+}
+
+
+/**
+ * Predict whether `libj2_ji_lsh_to_j2i_overflow`
+ * will return a result-overflow signal
+ *
+ * `libj2_ji_lsh_overflow_p(a, b)` implements
+ * `libj2_ji_lsh_to_j2i_overflow(a, b, &(struct libj2_j2i){})`
+ * in an efficient manner
+ *
+ * @param a The integer to shift (dry-run)
+ * @param b The number of positions to shift each bit
+ * @return +1 if `a` is non-negative and a set bit
+ * would be shifted out of precision (discarded
+ * or into the sign-bit position), that is, a
+ * positive overflow,
+ * -1 if `a` is negative and a cleared bit
+ * would be shifted out of precision (discarded
+ * or into the sign-bit position), that is, a
+ * negative overflow,
+ * 0 otherwise
+ *
+ * @since 1.1
+ */
+inline int
+libj2_ji_lsh_overflow_p(intmax_t a, unsigned b)
+{
+ if (b >= LIBJ2_J2I_BIT)
+ return a < 0 ? -1 : a > 0;
+ else if (b <= LIBJ2_JU_BIT)
+ return 0;
+ else if (a >= 0)
+ return !!((uintmax_t)a >> (LIBJ2_J2I_BIT - b));
+ else
+ return !!(~(uintmax_t)a >> (LIBJ2_J2I_BIT - b));
+}
+
+
+/**
+ * Predict whether `libj2_j2i_rsh_underflow` or
+ * `libj2_j2i_rsh_to_j2i_underflow` will return
+ * a result-underflow signal
+ *
+ * `libj2_j2i_rsh_underflow_p(a, b)` implements
+ * `libj2_j2i_rsh_to_j2i_underflow(a, b, &(struct libj2_j2i){})`
+ * in an efficient manner
+ *
+ * @param a The integer to shift (dry-run)
+ * @param b The number of positions to shift each bit
+ * @return +1 if `*a` is non-negative and a set bit
+ * would be shifted out (discarded), that is,
+ * a positive underflow,
+ * -1 if `*a` is negative and a cleared bit
+ * would be shifted out (discarded), that is,
+ * a positive underflow,
+ * 0 otherwise
+ *
+ * @since 1.1
+ */
+inline int
+libj2_j2i_rsh_underflow_p(const struct libj2_j2i *a, unsigned b)
+{
+ if (libj2_j2i_is_negative(a)) {
+ struct libj2_j2u t;
+ libj2_not_j2u_to_j2u((const void *)a, &t);
+ return -libj2_j2u_rsh_underflow_p(&t, b);
+ } else {
+ return libj2_j2u_rsh_underflow_p((const void *)a, b);
+ }
+}
+
+
+/**
+ * Predict whether `libj2_ji_rsh_to_j2i_underflow`
+ * will return a result-underflowflow signal
+ *
+ * `libj2_ji_rsh_underflow_p(a, b)` implements
+ * `libj2_ji_rsh_to_j2i_underflow(a, b, &(struct libj2_j2i){})`
+ * in an efficient manner
+ *
+ * @param a The integer to shift (dry-run)
+ * @param b The number of positions to shift each bit
+ * @return +1 if `a` is non-negative and a set bit
+ * would be shifted out (discarded), that is,
+ * a positive underflow,
+ * -1 if `a` is negative and a cleared bit
+ * would be shifted out (discarded), that is,
+ * a positive underflow,
+ * 0 otherwise
+ *
+ * @since 1.1
+ */
+inline int
+libj2_ji_rsh_underflow_p(intmax_t a, unsigned b)
+{
+ if (b >= LIBJ2_JU_BIT)
+ return a < -1 ? -1 : a > 0;
+ else if (!b)
+ return 0;
+ else if (a >= 0)
+ return !!((uintmax_t)a << (LIBJ2_JU_BIT - b));
+ else
+ return !!(~(uintmax_t)a << (LIBJ2_JU_BIT - b));
+}
diff --git a/libj2/bitwise-logic.h b/libj2/bitwise-logic.h
index b833e38..2a8539b 100644
--- a/libj2/bitwise-logic.h
+++ b/libj2/bitwise-logic.h
@@ -1723,3 +1723,6 @@ libj2_j2u_has_high_ju(const struct libj2_j2u *a, uintmax_t b)
{
return (a->high & b) == b;
}
+
+
+/* libj2_j2i_xor_sign_to_j2i, libj2_j2i_xor_sign_to_j2u, and libj2_j2i_xor_sign are located in sign-shifting.h */
diff --git a/libj2/constants.h b/libj2/constants.h
index 481c431..d83c9eb 100644
--- a/libj2/constants.h
+++ b/libj2/constants.h
@@ -23,7 +23,8 @@ libj2_j2u_is_zero(const struct libj2_j2u *a)
/**
- * Assign the value 0 to unsigned double-max precision integer
+ * Assign the value 0 to an unsigned double-max
+ * precision integer
*
* `libj2_j2u_zero(res)` implements `(void)(*res = 0)`
*
@@ -39,8 +40,8 @@ libj2_j2u_zero(struct libj2_j2u *res)
/**
- * Check whether an unsigned double-max precision integer has
- * the highest representable value
+ * Check whether an unsigned double-max precision
+ * integer has the highest representable value
*
* @param a The integer to inspect
* @return 1 if `a` has highest representable value, 0 otherwise
@@ -55,8 +56,8 @@ libj2_j2u_is_max(const struct libj2_j2u *a)
/**
- * Assign the highest representable value to unsigned double-max
- * precision integer
+ * Assign the highest representable value to an
+ * unsigned double-max precision integer
*
* @param res The integer to assign the value to
*
@@ -70,8 +71,8 @@ libj2_j2u_max(struct libj2_j2u *res)
/**
- * Check whether an unsigned double-max precision integer has
- * the lowest representable value
+ * Check whether an unsigned double-max precision
+ * integer has the lowest representable value
*
* Since the integer type is unsigned, this function
* does the same thing as `libj2_j2u_is_zero(a)`
@@ -89,8 +90,8 @@ libj2_j2u_is_min(const struct libj2_j2u *a)
/**
- * Assign the lowest representable value to unsigned double-max
- * precision integer
+ * Assign the lowest representable value to an
+ * unsigned double-max precision integer
*
* Since the integer type is unsigned, this function
* does the same thing as `libj2_j2u_zero(res)`
@@ -104,3 +105,105 @@ libj2_j2u_min(struct libj2_j2u *res)
{
libj2_j2u_zero(res);
}
+
+
+
+
+
+/**
+ * Check whether a signed double-max precision integer has
+ * the value 0 (or equivalently, a non-positive value)
+ *
+ * `libj2_j2i_is_zero(a)` implements `*a == 0`
+ *
+ * @param a The integer to inspect
+ * @return 1 if `a` has the value 0, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_is_zero(const struct libj2_j2i *a)
+{
+ return !a->high && !a->low;
+}
+
+
+/**
+ * Assign the value 0 to a signed double-max
+ * precision integer
+ *
+ * `libj2_j2i_zero(res)` implements `(void)(*res = 0)`
+ *
+ * @param res The integer to assign the value 0 to
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_zero(struct libj2_j2i *res)
+{
+ res->high = res->low = 0;
+}
+
+
+/**
+ * Check whether a signed double-max precision
+ * integer has the highest representable value
+ *
+ * @param a The integer to inspect
+ * @return 1 if `a` has highest representable value, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_is_max(const struct libj2_j2i *a)
+{
+ return a->high == UINTMAX_MAX >> 1 && a->low == UINTMAX_MAX;
+}
+
+
+/**
+ * Assign the highest representable value to a signed
+ * double-max precision integer
+ *
+ * @param res The integer to assign the value to
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_max(struct libj2_j2i *res)
+{
+ res->high = UINTMAX_MAX >> 1;
+ res->low = UINTMAX_MAX;
+}
+
+
+/**
+ * Check whether a signed double-max precision
+ * integer has the lowest representable value
+ *
+ * @param a The integer to inspect
+ * @return 1 if `a` has lowest representable value, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_is_min(const struct libj2_j2i *a)
+{
+ return a->high == ~(UINTMAX_MAX >> 1) && !a->low;
+}
+
+
+/**
+ * Assign the lowest representable value to an nsigned
+ * double-max precision integer
+ *
+ * @param res The integer to assign the value to
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_min(struct libj2_j2i *res)
+{
+ res->high = ~(UINTMAX_MAX >> 1);
+ res->low = 0;
+}
diff --git a/libj2/constructors.h b/libj2/constructors.h
index 12fd8f0..763f838 100644
--- a/libj2/constructors.h
+++ b/libj2/constructors.h
@@ -5,8 +5,8 @@
/**
- * Cast an unsigned max precision integer to an unsigned
- * double-max precision integer
+ * Cast an unsigned max precision integer to an
+ * unsigned double-max precision integer
*
* `libj2_ju_to_j2u(a, res)` implements `*res = a`
*
@@ -23,4 +23,90 @@ libj2_ju_to_j2u(uintmax_t a, struct libj2_j2u *res)
}
-/* libj2_j2u_zero, libj2_j2u_max, libj2_j2u_min are located in constants.h */
+/**
+ * Cast an unsigned max precision integer to a signed
+ * double-max precision integer
+ *
+ * `libj2_ju_to_j2i(a, res)` implements `*res = a`
+ *
+ * @param a The value to assign to `*res`
+ * @param res The integer to assign the value `a` to
+ *
+ * @since 1.1
+ */
+inline void
+libj2_ju_to_j2i(uintmax_t a, struct libj2_j2i *res)
+{
+ res->high = 0;
+ res->low = a;
+}
+
+
+/**
+ * Cast a signed max precision integer to a signed
+ * double-max precision integer
+ *
+ * `libj2_ji_to_j2i(a, res)` implements `*res = a`
+ *
+ * @param a The value to assign to `*res`
+ * @param res The integer to assign the value `a` to
+ *
+ * @since 1.1
+ */
+inline void
+libj2_ji_to_j2i(intmax_t a, struct libj2_j2i *res)
+{
+ if (a >= 0) {
+ res->high = 0;
+ res->low = (uintmax_t)a;
+ } else {
+ res->high = UINTMAX_MAX;
+ res->low = ~(uintmax_t)-(a + 1);
+ }
+}
+
+
+/**
+ * Cast an unsigned double-max precision integer
+ * to a signed double-max precision integer
+ *
+ * `libj2_j2i_to_j2u(a, res)` implements `*res = a`
+ *
+ * Overflows if `libj2_j2u_test_bit(a, LIBJ2_J2U_BIT - 1U)`
+ *
+ * @param a The value to assign to `*res`
+ * @param res The integer to assign the value `a` to
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2u_to_j2i(const struct libj2_j2u *a, struct libj2_j2i *res)
+{
+ res->high = a->high;
+ res->low = a->low;
+}
+
+
+/**
+ * Cast a signed double-max precision integer to
+ * an unsigned double-max precision integer
+ *
+ * `libj2_j2i_to_j2u(a, res)` implements `*res = a`
+ *
+ * Overflows if `libj2_j2i_is_negative(a)`
+ *
+ * @param a The value to assign to `*res`
+ * @param res The integer to assign the value `a` to
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res)
+{
+ res->high = a->high;
+ res->low = a->low;
+}
+
+
+/* libj2_j2u_zero, libj2_j2u_max, libj2_j2u_min, libj2_j2i_zero,
+ * libj2_j2i_max, and libj2_j2i_min are located in constants.h */
diff --git a/libj2/mixed-comparsion.h b/libj2/mixed-comparsion.h
new file mode 100644
index 0000000..2d07956
--- /dev/null
+++ b/libj2/mixed-comparsion.h
@@ -0,0 +1,820 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBJ2_H
+# error Do not include this header directly, include <libj2.h> instead
+#endif
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is less than an unsigned double-max precision integer
+ *
+ * `libj2_j2i_lt_j2u(a, b)` implements `*a < *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_lt_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
+{
+ return libj2_j2i_is_negative(a) ? 1 : libj2_j2u_lt_j2u((const void *)a, b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is less
+ * than or equal to an unsigned double-max precision integer
+ *
+ * `libj2_j2i_le_j2u(a, b)` implements `*a <= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_le_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
+{
+ return libj2_j2i_is_negative(a) ? 1 : libj2_j2u_le_j2u((const void *)a, b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is greater than an unsigned double-max precision integer
+ *
+ * `libj2_j2i_gt_j2u(a, b)` implements `*a > *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_gt_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
+{
+ return libj2_j2i_is_negative(a) ? 0 : libj2_j2u_gt_j2u((const void *)a, b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is greater
+ * than or equal to an unsigned double-max precision integer
+ *
+ * `libj2_j2i_ge_j2u(a, b)` implements `*a >= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_ge_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
+{
+ return libj2_j2i_is_negative(a) ? 0 : libj2_j2u_ge_j2u((const void *)a, b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is equal to an unsigned double-max precision integer
+ *
+ * `libj2_j2i_eq_j2u(a, b)` implements `*a == *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_eq_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
+{
+ return libj2_j2i_is_negative(a) ? 0 : libj2_j2u_eq_j2u((const void *)a, b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is not equal to an unsigned double-max precision integer
+ *
+ * `libj2_j2i_ne_j2u(a, b)` implements `*a != *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is not equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_ne_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
+{
+ return libj2_j2i_is_negative(a) ? 1 : libj2_j2u_ne_j2u((const void *)a, b);
+}
+
+
+/**
+ * Compare a signed double-max precision integer
+ * against an unsigned double-max precision integer
+ *
+ * `libj2_j2i_cmp_j2u(a, b)` implements `*a < *b ? -1 : *a > *b ? +1 : 0`,
+ * or equivalently, the signum of `*a - *b` where the signum is 0 for 0
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return -1 if `*a` is less than `*b`,
+ * +1 if `*a` is greater than `*b`,
+ * 0 if `*a` is equal to `*b`
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_cmp_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
+{
+ return libj2_j2i_is_negative(a) ? -1 : libj2_j2u_cmp_j2u((const void *)a, b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is less than a signed double-max precision integer
+ *
+ * `libj2_j2u_lt_j2i(a, b)` implements `*a < *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_lt_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) ? 0 : libj2_j2u_lt_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer is less
+ * than or equal to a signed double-max precision integer
+ *
+ * `libj2_j2u_le_j2i(a, b)` implements `*a <= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_le_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) ? 0 : libj2_j2u_le_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is greater than a signed double-max precision integer
+ *
+ * `libj2_j2u_gt_j2i(a, b)` implements `*a > *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_gt_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) ? 1 : libj2_j2u_gt_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer is
+ * greater than or equal to a signed double-max precision integer
+ *
+ * `libj2_j2u_ge_j2i(a, b)` implements `*a >= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_ge_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) ? 1 : libj2_j2u_ge_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is equal to a signed double-max precision integer
+ *
+ * `libj2_j2u_eq_j2i(a, b)` implements `*a == *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_eq_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) ? 0 : libj2_j2u_eq_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is not equal to a signed double-max precision integer
+ *
+ * `libj2_j2u_ne_j2i(a, b)` implements `*a != *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is not equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_ne_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) ? 1 : libj2_j2u_ne_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Compare an unsigned double-max precision integer
+ * against a signed double-max precision integer
+ *
+ * `libj2_j2u_cmp_j2i(a, b)` implements `*a < *b ? -1 : *a > *b ? +1 : 0`,
+ * or equivalently, the signum of `*a - *b` where the signum is 0 for 0
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return -1 if `*a` is less than `*b`,
+ * +1 if `*a` is greater than `*b`,
+ * 0 if `*a` is equal to `*b`
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_cmp_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) ? +1 : libj2_j2u_cmp_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether a signed max precision integer
+ * is less than an unsigned double-max precision integer
+ *
+ * `libj2_ji_lt_j2u(a, b)` implements `*a < *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_lt_j2u(intmax_t a, const struct libj2_j2u *b)
+{
+ return a < 0 ? 1 : libj2_ju_lt_j2u((uintmax_t)a, b);
+}
+
+
+/**
+ * Check whether a signed max precision integer is less
+ * than or equal to an unsigned double-max precision integer
+ *
+ * `libj2_ji_le_j2u(a, b)` implements `*a <= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_le_j2u(intmax_t a, const struct libj2_j2u *b)
+{
+ return a < 0 ? 1 : libj2_ju_le_j2u((uintmax_t)a, b);
+}
+
+
+/**
+ * Check whether a signed max precision integer
+ * is greater than an unsigned double-max precision integer
+ *
+ * `libj2_ji_gt_j2u(a, b)` implements `*a > *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_gt_j2u(intmax_t a, const struct libj2_j2u *b)
+{
+ return a < 0 ? 0 : libj2_ju_gt_j2u((uintmax_t)a, b);
+}
+
+
+/**
+ * Check whether a signed max precision integer is greater
+ * than or equal to an unsigned double-max precision integer
+ *
+ * `libj2_ji_ge_j2u(a, b)` implements `*a >= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_ge_j2u(intmax_t a, const struct libj2_j2u *b)
+{
+ return a < 0 ? 0 : libj2_ju_ge_j2u((uintmax_t)a, b);
+}
+
+
+/**
+ * Check whether a signed max precision integer
+ * is equal to an unsigned double-max precision integer
+ *
+ * `libj2_ji_eq_j2u(a, b)` implements `*a == *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_eq_j2u(intmax_t a, const struct libj2_j2u *b)
+{
+ return a < 0 ? 0 : libj2_ju_eq_j2u((uintmax_t)a, b);
+}
+
+
+/**
+ * Check whether a signed max precision integer
+ * is not equal to an unsigned double-max precision integer
+ *
+ * `libj2_ji_ne_j2u(a, b)` implements `*a != *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is not equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_ne_j2u(intmax_t a, const struct libj2_j2u *b)
+{
+ return a < 0 ? 1 : libj2_ju_ne_j2u((uintmax_t)a, b);
+}
+
+
+/**
+ * Compare a signed max precision integer
+ * against an unsigned double-max precision integer
+ *
+ * `libj2_ji_cmp_j2u(a, b)` implements `*a < *b ? -1 : *a > *b ? +1 : 0`,
+ * or equivalently, the signum of `*a - *b` where the signum is 0 for 0
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return -1 if `*a` is less than `*b`,
+ * +1 if `*a` is greater than `*b`,
+ * 0 if `*a` is equal to `*b`
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_cmp_j2u(intmax_t a, const struct libj2_j2u *b)
+{
+ return a < 0 ? -1 : libj2_ju_cmp_j2u((uintmax_t)a, b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is less than a signed max precision integer
+ *
+ * `libj2_ju_lt_j2i(a, b)` implements `*a < *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ju_lt_j2i(uintmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) < 0 ? 0 : libj2_ju_lt_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is less than or equal to a signed max precision integer
+ *
+ * `libj2_ju_le_j2i(a, b)` implements `*a <= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ju_le_j2i(uintmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) < 0 ? 0 : libj2_ju_le_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is greater than a signed max precision integer
+ *
+ * `libj2_ju_gt_j2i(a, b)` implements `*a > *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ju_gt_j2i(uintmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) < 0 ? 1 : libj2_ju_gt_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer is
+ * greater than or equal to a signed max precision integer
+ *
+ * `libj2_ju_ge_j2i(a, b)` implements `*a >= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ju_ge_j2i(uintmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) < 0 ? 1 : libj2_ju_ge_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is equal to a signed max precision integer
+ *
+ * `libj2_ju_eq_j2i(a, b)` implements `*a == *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ju_eq_j2i(uintmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) < 0 ? 0 : libj2_ju_eq_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is not equal to a signed max precision integer
+ *
+ * `libj2_ju_ne_j2i(a, b)` implements `*a != *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is not equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ju_ne_j2i(uintmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) < 0 ? 1 : libj2_ju_ne_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Compare an unsigned double-max precision integer
+ * against a signed max precision integer
+ *
+ * `libj2_ju_cmp_j2i(a, b)` implements `*a < *b ? -1 : *a > *b ? +1 : 0`,
+ * or equivalently, the signum of `*a - *b` where the signum is 0 for 0
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return -1 if `*a` is less than `*b`,
+ * +1 if `*a` is greater than `*b`,
+ * 0 if `*a` is equal to `*b`
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ju_cmp_j2i(uintmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_is_negative(b) < 0 ? +1 : libj2_ju_cmp_j2u(a, (const void *)b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is less than an unsigned max precision integer
+ *
+ * `libj2_j2i_lt_ju(a, b)` implements `*a < *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_lt_ju(const struct libj2_j2i *a, uintmax_t b)
+{
+ return libj2_j2i_is_negative(a) ? 1 : libj2_j2u_lt_ju((const void *)a, b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is less
+ * than or equal to an unsigned max precision integer
+ *
+ * `libj2_j2i_le_ju(a, b)` implements `*a <= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_le_ju(const struct libj2_j2i *a, uintmax_t b)
+{
+ return libj2_j2i_is_negative(a) ? 1 : libj2_j2u_le_ju((const void *)a, b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is greater than an unsigned max precision integer
+ *
+ * `libj2_j2i_gt_ju(a, b)` implements `*a > *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_gt_ju(const struct libj2_j2i *a, uintmax_t b)
+{
+ return libj2_j2i_is_negative(a) ? 0 : libj2_j2u_gt_ju((const void *)a, b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is greater
+ * than or equal to an unsigned max precision integer
+ *
+ * `libj2_j2i_ge_ju(a, b)` implements `*a >= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_ge_ju(const struct libj2_j2i *a, uintmax_t b)
+{
+ return libj2_j2i_is_negative(a) ? 0 : libj2_j2u_ge_ju((const void *)a, b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is equal to an unsigned max precision integer
+ *
+ * `libj2_j2i_eq_ju(a, b)` implements `*a == *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_eq_ju(const struct libj2_j2i *a, uintmax_t b)
+{
+ return libj2_j2i_is_negative(a) ? 0 : libj2_j2u_eq_ju((const void *)a, b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is not equal to an unsigned max precision integer
+ *
+ * `libj2_j2i_ne_ju(a, b)` implements `*a != *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is not equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_ne_ju(const struct libj2_j2i *a, uintmax_t b)
+{
+ return libj2_j2i_is_negative(a) ? 1 : libj2_j2u_ne_ju((const void *)a, b);
+}
+
+
+/**
+ * Compare a signed double-max precision integer
+ * against an unsigned max precision integer
+ *
+ * `libj2_j2i_cmp_ju(a, b)` implements `*a < *b ? -1 : *a > *b ? +1 : 0`,
+ * or equivalently, the signum of `*a - *b` where the signum is 0 for 0
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return -1 if `*a` is less than `*b`,
+ * +1 if `*a` is greater than `*b`,
+ * 0 if `*a` is equal to `*b`
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_cmp_ju(const struct libj2_j2i *a, uintmax_t b)
+{
+ return libj2_j2i_is_negative(a) ? -1 : libj2_j2u_cmp_ju((const void *)a, b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is less than a signed max precision integer
+ *
+ * `libj2_j2u_lt_ji(a, b)` implements `*a < *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_lt_ji(const struct libj2_j2u *a, intmax_t b)
+{
+ return b < 0 ? 0 : libj2_j2u_lt_ju(a, (uintmax_t)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer is
+ * less than or equal to a signed max precision integer
+ *
+ * `libj2_j2u_le_ji(a, b)` implements `*a <= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_le_ji(const struct libj2_j2u *a, intmax_t b)
+{
+ return b < 0 ? 0 : libj2_j2u_le_ju(a, (uintmax_t)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is greater than a signed max precision integer
+ *
+ * `libj2_j2u_gt_ji(a, b)` implements `*a > *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_gt_ji(const struct libj2_j2u *a, intmax_t b)
+{
+ return b < 0 ? 1 : libj2_j2u_gt_ju(a, (uintmax_t)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer is
+ * greater than or equal to a signed max precision integer
+ *
+ * `libj2_j2u_ge_ji(a, b)` implements `*a >= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_ge_ji(const struct libj2_j2u *a, intmax_t b)
+{
+ return b < 0 ? 1 : libj2_j2u_ge_ju(a, (uintmax_t)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is equal to a signed max precision integer
+ *
+ * `libj2_j2u_eq_ji(a, b)` implements `*a == *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_eq_ji(const struct libj2_j2u *a, intmax_t b)
+{
+ return b < 0 ? 0 : libj2_j2u_eq_ju(a, (uintmax_t)b);
+}
+
+
+/**
+ * Check whether an unsigned double-max precision integer
+ * is not equal to a signed max precision integer
+ *
+ * `libj2_j2u_ne_ji(a, b)` implements `*a != *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is not equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_ne_ji(const struct libj2_j2u *a, intmax_t b)
+{
+ return b < 0 ? 1 : libj2_j2u_ne_ju(a, (uintmax_t)b);
+}
+
+
+/**
+ * Compare an unsigned double-max precision integer
+ * against a signed max precision integer
+ *
+ * `libj2_j2u_cmp_ji(a, b)` implements `*a < *b ? -1 : *a > *b ? +1 : 0`,
+ * or equivalently, the signum of `*a - *b` where the signum is 0 for 0
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return -1 if `*a` is less than `*b`,
+ * +1 if `*a` is greater than `*b`,
+ * 0 if `*a` is equal to `*b`
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_cmp_ji(const struct libj2_j2u *a, intmax_t b)
+{
+ return b < 0 ? +1 : libj2_j2u_cmp_ju(a, (uintmax_t)b);
+}
diff --git a/libj2/sign-shifting.h b/libj2/sign-shifting.h
index 89c2ecf..7f57136 100644
--- a/libj2/sign-shifting.h
+++ b/libj2/sign-shifting.h
@@ -8,40 +8,281 @@
* Calculate the additive inverse of an unsigned
* double-max precision integer
*
+ * `libj2_minus_j2u_to_j2u(a, res)` implements
+ * `*res = -*a`
+ *
+ * @param a The integer to invert
+ * @param res Output parameter for the inverse
+ *
+ * @since 1.0
+ */
+inline void
+libj2_minus_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res)
+{
+ res->high = -a->high;
+ if (a->low)
+ res->high -= 1U;
+ res->low = -a->low;
+}
+
+
+/**
+ * Calculate the additive inverse of an unsigned
+ * double-max precision integer
+ *
* `libj2_minus_j2u(a)` implements `*a = -*a`
*
- * @param a The integer to invert, also used as the
- * output parameter for the inverse
+ * @param a The integer to invert, also used as
+ * the output parameter for the inverse
*
* @since 1.0
*/
inline void
libj2_minus_j2u(struct libj2_j2u *a)
{
- a->high = -a->high;
- if (a->low) {
- a->high -= 1U;
- a->low = -a->low;
- }
+ libj2_minus_j2u_to_j2u(a, a);
}
/**
- * Calculate the additive inverse of an unsigned
+ * Calculate the additive inverse of a signed
* double-max precision integer
*
- * `libj2_minus_j2u_j2u(a, res)` implements `*res = -*a`
+ * `libj2_minus_j2i_to_j2i(a, res)` implements
+ * `*res = -*a`
+ *
+ * Overflows if `libj2_j2i_is_min(a)`
*
* @param a The integer to invert
* @param res Output parameter for the inverse
*
- * @since 1.0
+ * @since 1.1
*/
inline void
-libj2_minus_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res)
+libj2_minus_j2i_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res)
{
- res->high = -a->high;
- if (a->low)
- res->high -= 1U;
- res->low = -a->low;
+ libj2_minus_j2u_to_j2u((const void *)a, (void *)res);
+}
+
+
+/**
+ * Calculate the additive inverse of a signed
+ * double-max precision integer
+ *
+ * `libj2_minus_j2i(a)` implements `*a = -*a`
+ *
+ * Overflows if `libj2_j2i_is_min(a)`
+ *
+ * @param a The integer to invert, also used as
+ * the output parameter for the inverse
+ *
+ * @since 1.1
+ */
+inline void
+libj2_minus_j2i(struct libj2_j2i *a)
+{
+ libj2_minus_j2u_to_j2u((const void *)a, (void *)a);
+}
+
+
+/**
+ * Calculate the additive inverse of a signed
+ * double-max precision integer and stored it as
+ * an unsigned double-max precision integer
+ *
+ * `libj2_minus_j2i_to_j2u(a, res)` implements
+ * `*res = -*a`
+ *
+ * Overflows if `libj2_j2i_is_min(a) || libj2_j2i_is_positive(a)`
+ *
+ * @param a The integer to invert
+ * @param res Output parameter for the inverse
+ *
+ * @since 1.1
+ */
+inline void
+libj2_minus_j2i_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res)
+{
+ libj2_minus_j2u_to_j2u((const void *)a, (void *)res);
+}
+
+
+/**
+ * Calculate the additive inverse of an unsigned
+ * double-max precision integer and stored it as
+ * a signed double-max precision integer
+ *
+ * `libj2_minus_j2u_to_j2i(a, res)` implements
+ * `*res = -*a`
+ *
+ * Overflows if `libj2_co_j2u(a) > 1U &&
+ * libj2_j2u_test_bit(a, LIBJ2_J2U_BIT - 1U)`
+ *
+ * @param a The integer to invert
+ * @param res Output parameter for the inverse
+ *
+ * @since 1.1
+ */
+inline void
+libj2_minus_j2u_to_j2i(const struct libj2_j2u *a, struct libj2_j2i *res)
+{
+ libj2_minus_j2u_to_j2u((const void *)a, (void *)res);
+}
+
+
+
+
+
+/**
+ * Calculate the absolute value of a signed
+ * double-max precision integer
+ *
+ * Overflows if `libj2_j2i_is_min(a)`
+ *
+ * @param a The integer
+ * @param res Output parameter for the absolute value
+ *
+ * @since 1.1
+ */
+inline void
+libj2_abs_j2i_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res)
+{
+ if (libj2_j2i_is_negative(a))
+ libj2_minus_j2i_to_j2i(a, res);
+ else if (a != res)
+ *res = *a;
+}
+
+
+/**
+ * Calculate the absolute value of a signed
+ * double-max precision integer
+ *
+ * Overflows if `libj2_j2i_is_min(a)`
+ *
+ * @param a The integer, also used as the
+ * output parameter for the absolute value
+ *
+ * @since 1.1
+ */
+inline void
+libj2_abs_j2i(struct libj2_j2i *a)
+{
+ if (libj2_j2i_is_negative(a))
+ libj2_minus_j2i(a);
+}
+
+
+/**
+ * Calculate the absolute value of a signed
+ * double-max precision integer and stored it as
+ * an unsigned double-max precision integer
+ *
+ * @param a The integer
+ * @param res Output parameter for the absolute value
+ *
+ * @since 1.1
+ */
+inline void
+libj2_abs_j2i_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res)
+{
+ libj2_abs_j2i_to_j2i(a, (void *)res);
+}
+
+
+
+
+
+/**
+ * Calculate the additive inverse of the absolute
+ * value of a signed double-max precision integer
+ *
+ * @param a The integer
+ * @param res Output parameter for the inverse
+ * of the absolute value
+ *
+ * @since 1.1
+ */
+inline void
+libj2_minus_abs_j2i_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res)
+{
+ if (libj2_j2i_is_positive(a))
+ libj2_minus_j2i_to_j2i(a, res);
+ else if (a != res)
+ *res = *a;
+}
+
+
+/**
+ * Calculate the additive inverse of the absolute
+ * value of a signed double-max precision integer
+ *
+ * @param a The integer, also used as the
+ * output parameter for the inverse
+ * of the absolute value
+ *
+ * @since 1.1
+ */
+inline void
+libj2_minus_abs_j2i(struct libj2_j2i *a)
+{
+ if (libj2_j2i_is_positive(a))
+ libj2_minus_j2i(a);
+}
+
+
+
+
+
+/**
+ * If the sign-bit is set in a signed double-max
+ * precision integer, flip all bits
+ *
+ * @param a The integer to conditionally invert
+ * @param res Output parameter for the sign-xor
+ * @param res Output parameter for the inverse
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_xor_sign_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res)
+{
+ if (libj2_j2i_is_negative(a))
+ libj2_not_j2u_to_j2u((const void *)a, (void *)res);
+ else
+ *res = *a;
+}
+
+
+/**
+ * If the sign-bit is set in a signed double-max
+ * precision integer, flip all bits
+ *
+ * @param a The integer to conditionally invert
+ * @param res Output parameter for the sign-xor
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_xor_sign_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res)
+{
+ libj2_j2i_xor_sign_to_j2i(a, (void *)res);
+}
+
+
+/**
+ * If the sign-bit is set in a signed double-max
+ * precision integer, flip all bits
+ *
+ * @param a The integer to conditionally invert,
+ * also used as the output parameter for
+ * the sign-xor
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_xor_sign(struct libj2_j2i *a)
+{
+ if (libj2_j2i_is_negative(a))
+ libj2_not_j2u((void *)a);
}
diff --git a/libj2/signed-comparsion.h b/libj2/signed-comparsion.h
new file mode 100644
index 0000000..1bed2f1
--- /dev/null
+++ b/libj2/signed-comparsion.h
@@ -0,0 +1,858 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBJ2_H
+# error Do not include this header directly, include <libj2.h> instead
+#endif
+
+
+/**
+ * Compare a signed double-max precision integer
+ * against another signed double-max precision integer
+ *
+ * `libj2_j2i_cmp_j2i(a, b)` implements `*a < *b ? -1 : *a > *b ? +1 : 0`,
+ * or equivalently, the signum of `*a - *b` where the signum is 0 for 0
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return -1 if `*a` is less than `*b`,
+ * +1 if `*a` is greater than `*b`,
+ * 0 if `*a` is equal to `*b`
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_cmp_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b)
+{
+ int cmp = libj2_sgn_j2i(a) - libj2_sgn_j2i(b);
+ if (cmp)
+ return cmp < 0 ? -1 : +1;
+ return libj2_j2u_cmp_j2u((const void *)a, (const void *)b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is
+ * less than another signed double-max precision integer
+ *
+ * `libj2_j2i_lt_j2i(a, b)` implements `*a < *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_lt_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_cmp_j2i(a, b) < 0;
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is less
+ * than or equal to another signed double-max precision integer
+ *
+ * `libj2_j2i_le_j2i(a, b)` implements `*a <= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_le_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_cmp_j2i(a, b) <= 0;
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is
+ * greater than another signed double-max precision integer
+ *
+ * `libj2_j2i_gt_j2i(a, b)` implements `*a > *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_gt_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_cmp_j2i(a, b) > 0;
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is greater
+ * than or equal to another signed double-max precision integer
+ *
+ * `libj2_j2i_ge_j2i(a, b)` implements `*a >= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_ge_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_cmp_j2i(a, b) >= 0;
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is
+ * equal to another signed double-max precision integer
+ *
+ * `libj2_j2i_eq_j2i(a, b)` implements `*a == *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_eq_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b)
+{
+ return libj2_j2u_eq_j2u((const void *)a, (const void *)b);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is
+ * not equal to another signed double-max precision integer
+ *
+ * `libj2_j2i_ne_j2i(a, b)` implements `*a != *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is not equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_ne_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b)
+{
+ return libj2_j2u_ne_j2u((const void *)a, (const void *)b);
+}
+
+
+/**
+ * Compare a signed double-max precision integer
+ * against a signed max precision integer
+ *
+ * `libj2_j2i_cmp_ji(a, b)` implements `*a < b ? -1 : *a > b ? +1 : 0`,
+ * or equivalently, the signum of `*a - b` where the signum is 0 for 0
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return -1 if `*a` is less than `b`,
+ * +1 if `*a` is greater than `b`,
+ * 0 if `*a` is equal to `b`
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_cmp_ji(const struct libj2_j2i *a, intmax_t b)
+{
+ struct libj2_j2i t;
+ libj2_ji_to_j2i(b, &t);
+ return libj2_j2i_cmp_j2i(a, &t);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is less than a signed max precision integer
+ *
+ * `libj2_j2i_lt_ji(a, b)` implements `*a < b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than `b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_lt_ji(const struct libj2_j2i *a, intmax_t b)
+{
+ return libj2_j2i_cmp_ji(a, b) < 0;
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is
+ * less than or equal to a signed max precision integer
+ *
+ * `libj2_j2i_le_ji(a, b)` implements `*a <= b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than or equal to `b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_le_ji(const struct libj2_j2i *a, intmax_t b)
+{
+ return libj2_j2i_cmp_ji(a, b) <= 0;
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is greater than a signed max precision integer
+ *
+ * `libj2_j2i_gt_ji(a, b)` implements `*a > b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is less than `b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_gt_ji(const struct libj2_j2i *a, intmax_t b)
+{
+ return libj2_j2i_cmp_ji(a, b) > 0;
+}
+
+
+/**
+ * Check whether a signed double-max precision integer is
+ * greater than or equal to a signed max precision integer
+ *
+ * `libj2_j2i_ge_ji(a, b)` implements `*a >= b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is greater than or equal to `b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_ge_ji(const struct libj2_j2i *a, intmax_t b)
+{
+ return libj2_j2i_cmp_ji(a, b) >= 0;
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is equal to a signed max precision integer
+ *
+ * `libj2_j2i_eq_ji(a, b)` implements `*a == b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is equal to `b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_eq_ji(const struct libj2_j2i *a, intmax_t b)
+{
+ if (b >= 0)
+ return !a->high && a->low == (uintmax_t)b;
+ return a->high == UINTMAX_MAX && a->low == ~(uintmax_t)-(b + 1);
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * is not equal to a signed max precision integer
+ *
+ * `libj2_j2i_ne_ji(a, b)` implements `*a != b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `*a` is not equal to `b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_ne_ji(const struct libj2_j2i *a, intmax_t b)
+{
+ return !libj2_j2i_eq_ji(a, b);
+}
+
+
+/**
+ * Compare a signed max precision integer
+ * against a signed double-max precision integer
+ *
+ * `libj2_ji_cmp_j2i(a, b)` implements `a < *b ? -1 : a > *b ? +1 : 0`,
+ * or equivalently, the signum of `a - *b` where the signum is 0 for 0
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return -1 if `a` is less than `*b`,
+ * +1 if `a` is greater than `*b`,
+ * 0 if `a` is equal to `*b`
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_cmp_j2i(intmax_t a, const struct libj2_j2i *b)
+{
+ struct libj2_j2i t;
+ libj2_ji_to_j2i(a, &t);
+ return libj2_j2i_cmp_j2i(&t, b);
+}
+
+
+/**
+ * Check whether a signed max precision integer is
+ * less than a signed double-max precision integer
+ *
+ * `libj2_ji_lt_j2i(a, b)` implements `a < *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `a` is less than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_lt_j2i(intmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_gt_ji(b, a);
+}
+
+
+/**
+ * Check whether a signed max precision integer is less
+ * than or equal to a signed double-max precision integer
+ *
+ * `libj2_ji_le_j2i(a, b)` implements `a <= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `a` is less than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_le_j2i(intmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_ge_ji(b, a);
+}
+
+
+/**
+ * Check whether a signed max precision integer is
+ * greater than a signed double-max precision integer
+ *
+ * `libj2_ji_gt_j2i(a, b)` implements `a > *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `a` is less than `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_gt_j2i(intmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_lt_ji(b, a);
+}
+
+
+/**
+ * Check whether a signed max precision integer is greater
+ * than or equal to a signed double-max precision integer
+ *
+ * `libj2_ji_ge_j2i(a, b)` implements `a >= *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `a` is greater than or equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_ge_j2i(intmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_le_ji(b, a);
+}
+
+
+/**
+ * Check whether a signed max precision integer is
+ * equal to a signed double-max precision integer
+ *
+ * `libj2_ji_eq_j2i(a, b)` implements `a == *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `a` is equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_eq_j2i(intmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_eq_ji(b, a);
+}
+
+
+/**
+ * Check whether a signed max precision integer is
+ * not equal to a signed double-max precision integer
+ *
+ * `libj2_ji_ne_j2i(a, b)` implements `a != *b`
+ *
+ * @param a The left-hand value
+ * @param b The right-hand value
+ * @return 1 if `a` is not equal to `*b`, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_ji_ne_j2i(intmax_t a, const struct libj2_j2i *b)
+{
+ return libj2_j2i_ne_ji(b, a);
+}
+
+
+
+
+
+/**
+ * Get the maximum of two signed double-max
+ * precision integers
+ *
+ * `libj2_j2i_max_j2i_to_ji2(a, b, res)` implements
+ * `*res = *a > *b ? *a : *b`
+ *
+ * @param a One of the values
+ * @param b The other value
+ * @param res Output parameter for the maximum of `*a` and `*b`
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_max_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res)
+{
+ *res = libj2_j2i_gt_j2i(a, b) ? *a : *b;
+}
+
+
+/**
+ * Get the maximum of two signed double-max
+ * precision integers
+ *
+ * `libj2_j2i_max_j2i(a, b)` implements
+ * `*a = *a > *b ? *a : *b`
+ *
+ * @param a One of the values, and output parameter
+ * for the maximum of `*a` and `*b`
+ * @param b The other value
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_max_j2i(struct libj2_j2i *a, const struct libj2_j2i *b)
+{
+ if (libj2_j2i_gt_j2i(b, a))
+ *a = *b;
+}
+
+
+/**
+ * Get the maximum of a signed double-max
+ * precision integer and a signed precision
+ * integer
+ *
+ * `libj2_j2i_max_ji(a, b)` implements
+ * `*a = *a > b ? *a : b`
+ *
+ * @param a One of the values, and output parameter
+ * for the maximum of `*a` and `b`
+ * @param b The other value
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_max_ji(struct libj2_j2i *a, intmax_t b)
+{
+ if (libj2_j2i_lt_ji(a, b))
+ libj2_ji_to_j2i(b, a);
+}
+
+
+/**
+ * Get the maximum of a signed double-max
+ * precision integer and a signed precision
+ * integer
+ *
+ * `libj2_j2i_max_ji_to_j2i(a, b, res)` implements
+ * `*res = *a > b ? *a : b`
+ *
+ * @param a One of the values
+ * @param b The other value
+ * @param res Output parameter for the maximum of `*a` and `b`
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_max_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res)
+{
+ if (libj2_j2i_lt_ji(a, b))
+ libj2_ji_to_j2i(b, res);
+ else
+ *res = *a;
+}
+
+
+/**
+ * Get the minimum of two signed double-max
+ * precision integers
+ *
+ * `libj2_j2i_min_j2i_to_ji2(a, b, res)` implements
+ * `*res = *a < *b ? *a : *b`
+ *
+ * @param a One of the values
+ * @param b The other value
+ * @param res Output parameter for the minimum of `*a` and `*b`
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_min_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res)
+{
+ *res = libj2_j2i_lt_j2i(a, b) ? *a : *b;
+}
+
+
+/**
+ * Get the minimum of two signed double-max
+ * precision integers
+ *
+ * `libj2_j2i_min_j2i(a, b)` implements
+ * `*a = *a < *b ? *a : *b`
+ *
+ * @param a One of the values, and output parameter
+ * for the minimum of `*a` and `*b`
+ * @param b The other value
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_min_j2i(struct libj2_j2i *a, const struct libj2_j2i *b)
+{
+ if (libj2_j2i_lt_j2i(b, a))
+ *a = *b;
+}
+
+
+/**
+ * Get the minimum of a signed double-max
+ * precision integer and a signed precision
+ * integer
+ *
+ * `libj2_j2i_min_ji(a, b)` implements
+ * `*a = *a < b ? *a : b`
+ *
+ * @param a One of the values, and output parameter
+ * for the minimum of `*a` and `b`
+ * @param b The other value
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_min_ji(struct libj2_j2i *a, intmax_t b)
+{
+ if (libj2_j2i_gt_ji(a, b))
+ libj2_ji_to_j2i(b, a);
+}
+
+
+/**
+ * Get the minimum of a signed double-max
+ * precision integer and a signed precision
+ * integer
+ *
+ * `libj2_j2i_min_ji_to_j2i(a, b, res)` implements
+ * `*res = *a < b ? *a : b`
+ *
+ * @param a One of the values
+ * @param b The other value
+ * @param res Output parameter for the minimum of `*a` and `b`
+ *
+ * @since 1.1
+ */
+inline void
+libj2_j2i_min_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res)
+{
+ if (libj2_j2i_gt_ji(a, b))
+ libj2_ji_to_j2i(b, res);
+ else
+ *res = *a;
+}
+
+
+/**
+ * Get the maximum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values, and output parameter for
+ * the maximum of the values
+ * @param args `NULL` terminated list of additional values; each
+ * argument shall have the type `const struct libj2_j2i *`
+ *
+ * @since 1.1
+ */
+inline void
+libj2_vmax_j2i(struct libj2_j2i *a, va_list args)
+{
+ const struct libj2_j2i *b;
+ while ((b = va_arg(args, const struct libj2_j2i *)))
+ libj2_j2i_max_j2i(a, b);
+}
+
+
+/**
+ * Get the maximum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values, and output parameter for
+ * the maximum of the values
+ * @param ... `NULL` terminated list of additional values; each
+ * argument shall have the type `const struct libj2_j2i *`
+ *
+ * @since 1.1
+ */
+inline void
+libj2_max_j2i(struct libj2_j2i *a, ... /*, NULL */)
+{
+ va_list args;
+ va_start(args, a);
+ libj2_vmax_j2i(a, args);
+ va_end(args);
+}
+
+
+/**
+ * Get the maximum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values
+ * @param args `NULL` terminated list of additional values; each
+ * argument shall have the type `const struct libj2_j2i *`
+ * @return One of the `const struct libj2_j2i *` that as the
+ * maximum of the values of each argument
+ *
+ * @since 1.1
+ */
+inline const struct libj2_j2i *
+libj2_vmax_j2i_return(const struct libj2_j2i *a, va_list args)
+{
+ const struct libj2_j2i *b;
+ while ((b = va_arg(args, const struct libj2_j2i *)))
+ if (libj2_j2i_gt_j2i(b, a))
+ a = b;
+ return a;
+}
+
+
+/**
+ * Get the maximum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values
+ * @param ... `NULL` terminated list of additional values; each
+ * argument shall have the type `const struct libj2_j2i *`
+ * @return One of the `const struct libj2_j2i *` that as the
+ * maximum of the values of each argument
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline const struct libj2_j2i *
+libj2_max_j2i_return(const struct libj2_j2i *a, ... /*, NULL */)
+{
+ va_list args;
+ va_start(args, a);
+ return libj2_vmax_j2i_return(a, args);
+ va_end(args);
+}
+
+
+/**
+ * Get the maximum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values
+ * @param args `NULL` terminated list of additional values, each
+ * argument shall have the type `const struct libj2_j2i *`,
+ * followed by a `struct libj2_j2i *` is used as the
+ * output parameter for the maximum of the values
+ *
+ * @since 1.1
+ */
+inline void
+libj2_vmax_j2i_to_j2i(const struct libj2_j2i *a, va_list args)
+{
+ struct libj2_j2i *res;
+ a = libj2_vmax_j2i_return(a, args);
+ res = va_arg(args, struct libj2_j2i *);
+ *res = *a;
+}
+
+
+/**
+ * Get the maximum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values
+ * @param ... `NULL` terminated list of additional values, each
+ * argument shall have the type `const struct libj2_j2i *`,
+ * followed by a `struct libj2_j2i *` is used as the
+ * output parameter for the maximum of the values
+ *
+ * @since 1.1
+ */
+inline void
+libj2_max_j2i_to_j2i(const struct libj2_j2i *a, ... /*, NULL, struct libj2_j2i *res */)
+{
+ va_list args;
+ va_start(args, a);
+ libj2_vmax_j2i_to_j2i(a, args);
+ va_end(args);
+}
+
+
+/**
+ * Get the minimum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values, and output parameter for
+ * the minimum of the values
+ * @param args `NULL` terminated list of additional values; each
+ * argument shall have the type `const struct libj2_j2i *`
+ *
+ * @since 1.1
+ */
+inline void
+libj2_vmin_j2i(struct libj2_j2i *a, va_list args)
+{
+ const struct libj2_j2i *b;
+ while ((b = va_arg(args, const struct libj2_j2i *)))
+ libj2_j2i_min_j2i(a, b);
+}
+
+
+/**
+ * Get the minimum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values, and output parameter for
+ * the minimum of the values
+ * @param ... `NULL` terminated list of additional values; each
+ * argument shall have the type `const struct libj2_j2i *`
+ *
+ * @since 1.1
+ */
+inline void
+libj2_min_j2i(struct libj2_j2i *a, ... /*, NULL */)
+{
+ va_list args;
+ va_start(args, a);
+ libj2_vmin_j2i(a, args);
+ va_end(args);
+}
+
+
+/**
+ * Get the minimum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values
+ * @param args `NULL` terminated list of additional values; each
+ * argument shall have the type `const struct libj2_j2i *`
+ * @return One of the `const struct libj2_j2i *` that as the
+ * minimum of the values of each argument
+ *
+ * @since 1.1
+ */
+inline const struct libj2_j2i *
+libj2_vmin_j2i_return(const struct libj2_j2i *a, va_list args)
+{
+ const struct libj2_j2i *b;
+ while ((b = va_arg(args, const struct libj2_j2i *)))
+ if (libj2_j2i_lt_j2i(b, a))
+ a = b;
+ return a;
+}
+
+
+/**
+ * Get the minimum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values
+ * @param ... `NULL` terminated list of additional values; each
+ * argument shall have the type `const struct libj2_j2i *`
+ * @return One of the `const struct libj2_j2i *` that as the
+ * minimum of the values of each argument
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline const struct libj2_j2i *
+libj2_min_j2i_return(const struct libj2_j2i *a, ... /*, NULL */)
+{
+ va_list args;
+ va_start(args, a);
+ return libj2_vmin_j2i_return(a, args);
+ va_end(args);
+}
+
+
+/**
+ * Get the minimum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values
+ * @param args `NULL` terminated list of additional values, each
+ * argument shall have the type `const struct libj2_j2i *`,
+ * followed by a `struct libj2_j2i *` is used as the
+ * output parameter for the minimum of the values
+ *
+ * @since 1.1
+ */
+inline void
+libj2_vmin_j2i_to_j2i(const struct libj2_j2i *a, va_list args)
+{
+ struct libj2_j2i *res;
+ a = libj2_vmin_j2i_return(a, args);
+ res = va_arg(args, struct libj2_j2i *);
+ *res = *a;
+}
+
+
+/**
+ * Get the minimum of a set of signed double-max
+ * precision integers
+ *
+ * @param a One of the values
+ * @param ... `NULL` terminated list of additional values, each
+ * argument shall have the type `const struct libj2_j2i *`,
+ * followed by a `struct libj2_j2i *` is used as the
+ * output parameter for the minimum of the values
+ *
+ * @since 1.1
+ */
+inline void
+libj2_min_j2i_to_j2i(const struct libj2_j2i *a, ... /*, NULL, struct libj2_j2i *res */)
+{
+ va_list args;
+ va_start(args, a);
+ libj2_vmin_j2i_to_j2i(a, args);
+ va_end(args);
+}
diff --git a/libj2/signum.h b/libj2/signum.h
index 60b37c1..c4138bd 100644
--- a/libj2/signum.h
+++ b/libj2/signum.h
@@ -46,4 +46,63 @@ libj2_sgn_j2u(const struct libj2_j2u *a)
}
-/* libj2_j2u_is_zero is located in constants.h */
+
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * has a positive value
+ *
+ * `libj2_j2i_is_positive(a)` implements `*a > 0`
+ *
+ * @param a The integer to inspect
+ * @return 1 if `a` has a positive value, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_is_positive(const struct libj2_j2i *a)
+{
+ return a->high ? a->high <= UINTMAX_MAX >> 1 : a->low > 0;
+}
+
+
+/**
+ * Check whether a signed double-max precision integer
+ * has a negative value
+ *
+ * `libj2_j2i_is_negative(a)` implements `*a < 0`
+ *
+ * @param a The integer to inspect
+ * @return 1 if `a` has a negaitve value, 0 otherwise
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_j2i_is_negative(const struct libj2_j2i *a)
+{
+ return a->high > UINTMAX_MAX >> 1;
+}
+
+
+/**
+ * Get the sign (signum function) of a signed double-max
+ * precision integer
+ *
+ * `libj2_sgn_j2i(a)` implements `*a < 0 ? -1 : *a > 0 ? +1 : 0`
+ *
+ * @param a The integer to inspect
+ * @return -1 if `a` is negative,
+ * +1 if `a` is positive, and
+ * 0 if `a` is 0
+ *
+ * @since 1.1
+ */
+LIBJ2_PURE_ inline int
+libj2_sgn_j2i(const struct libj2_j2i *a)
+{
+ return libj2_j2i_is_negative(a) ? -1 : libj2_j2i_is_positive(a);
+}
+
+
+/* libj2_j2u_is_zero and libj2_j2i_is_zero are located in constants.h */
diff --git a/libj2/strings.h b/libj2/strings.h
index 567cd3d..3fc2d7e 100644
--- a/libj2/strings.h
+++ b/libj2/strings.h
@@ -39,7 +39,69 @@ size_t libj2_j2u_to_str(const struct libj2_j2u *a, char *buf, size_t bufsize, co
/**
- * Convert a string into a an unsigned
+ * Convert a string into an unsigned
+ * double-max precision integer
+ *
+ * Any leading ASCII whitespace, as well
+ * as any leading '+' character, will be
+ * ignored, the all digits will be parsed
+ * until any other character is encountered;
+ * additionally, unless `negative` is `NULL`
+ * `*negative` will be set the parity of
+ * the number of '-' characters intermixed
+ * with the leading characters
+ *
+ * Parsing will stop after `slen` bytes,
+ * when a NUL byte is encountered, or a
+ * non-digit is encountered after any
+ * leading skipped character; whichever
+ * comes first
+ *
+ * @param s The string to parse
+ * @param slen The maximum number of bytes to read from `s`
+ * @param end Output parameter for where parsing stopped
+ * (pointing to the first byte that is is not
+ * a leading ASCII whitespace, leading '+'
+ * character, nor a digit)
+ * @param digits1 List of digits to use, each byte is
+ * regarded as a symbol, starting from
+ * the zero-digit. If `NULL`, "0123456789"
+ * (the decimal system) will be used. Any
+ * symbol in this list will be removed from the
+ * set of ignored leading characeters; minimum
+ * length is 2. May not contain duplicates.
+ * @param digits2 List of symbols to use as synonyms for
+ * the symbols in `digits`, must be of the
+ * same length as `digits1`, or `NULL` if
+ * `digits1` is `NULL` or to use no additional
+ * symbols; it contains common it has any
+ * symbols in common with `digits1`, they
+ * must be in the same position
+ * @param a Output parameter for the decoded integer
+ * @param negative Output parameter for whether the value is
+ * negative (even if zero); `NULL` to disallow
+ * '-' prefix characters
+ * @return 0 upon successful completion, or an error
+ * code on failure
+ *
+ * @throws EINVAL `digits1` or `digits2` is misconfigured
+ * @throws EINVAL No digit was encountered;
+ * `*a` (unless it's `NULL`) will be set to
+ * the value zero
+ * @throws ERANGE The value is too large to be represented;
+ * `*a` (unless it's `NULL`) will be set to
+ * the maximum value
+ *
+ * This function does not set `errno`
+ *
+ * @since 1.1
+ */
+int libj2_str_to_j2u_sign(const char *s, size_t slen, char **end, const char *digits1,
+ const char *digits2, struct libj2_j2u *a, int *negative);
+
+
+/**
+ * Convert a string into an unsigned
* double-max precision integer
*
* Any leading ASCII whitespace, as well
@@ -69,8 +131,10 @@ size_t libj2_j2u_to_str(const struct libj2_j2u *a, char *buf, size_t bufsize, co
* @param digits2 List of symbols to use as synonyms for
* the symbols in `digits`, must be of the
* same length as `digits1`, or `NULL` if
- * `digit1` is `NULL` or to use no additional
- * symbols
+ * `digits1` is `NULL` or to use no additional
+ * symbols; it contains common it has any
+ * symbols in common with `digits1`, they
+ * must be in the same position
* @param a Output parameter for the decoded integer
* @return 0 upon successful completion, or an error
* code on failure
@@ -87,5 +151,125 @@ size_t libj2_j2u_to_str(const struct libj2_j2u *a, char *buf, size_t bufsize, co
*
* @since 1.1
*/
-int libj2_str_to_j2u(const char *s, size_t slen, char **end, const char *digits1,
- const char *digits2, struct libj2_j2u *a);
+inline int
+libj2_str_to_j2u(const char *s, size_t slen, char **end, const char *digits1,
+ const char *digits2, struct libj2_j2u *a)
+{
+ return libj2_str_to_j2u_sign(s, slen, end, digits1, digits2, a, NULL);
+}
+
+
+/**
+ * Convert a signed double-max precision
+ * integer to a string
+ *
+ * The string will be terminated by a NUL byte
+ * (unless `bufsize` is 0) and will otherwise
+ * only contain the digits, and if negative a
+ * "-" prefix, and will not contain any leading
+ * zeroes (except that the value zero will be
+ * represented as "0")
+ *
+ * @param a The integer to convert into a string
+ * @param buf Buffer for the string
+ * @param bufsize The size of `buf`
+ * @param digits List of digits to use, each byte is
+ * regarded as a symbol, starting from
+ * the zero-digit. If `NULL`, "0123456789"
+ * (the decimal system) will be used. Minimum
+ * length is 2. May not contain duplicates.
+ * @return The number of digits used to represent
+ * the integer, even if not all of them
+ * fit into the buffer; or zero on failure
+ * (`digits` has a length less than 2 or
+ * contains duplicate symbols)
+ *
+ * This function does not set `errno`
+ *
+ * @since 1.1
+ */
+#if defined(__GNUC__)
+__attribute__((__nonnull__(1)))
+#endif
+inline size_t
+libj2_j2i_to_str(const struct libj2_j2i *a, char *buf, size_t bufsize, const char *digits)
+{
+ char *sigc;
+ struct libj2_j2u t;
+ size_t r;
+ if (!libj2_j2i_is_negative(a))
+ return libj2_j2u_to_str((const void *)a, buf, bufsize, digits);
+ libj2_abs_j2i_to_j2u(a, &t);
+ if (bufsize > 1U) {
+ sigc = buf;
+ bufsize -= 1U;
+ } else {
+ sigc = NULL;
+ }
+ r = libj2_j2u_to_str(&t, buf, bufsize, digits);
+ if (!r)
+ return 0;
+ if (sigc)
+ *sigc = '-';
+ return r + 1U;
+}
+
+
+/**
+ * Convert a string into an unsigned
+ * double-max precision integer
+ *
+ * Any leading ASCII whitespace, as well
+ * as any leading '+' character, will be
+ * ignored, the all digits will be parsed
+ * until any other character is encountered;
+ * additionally, the if the parity of the
+ * number of '-' characters intermixed with
+ * the leading characters is odd, the result
+ * will be negative
+ *
+ * Parsing will stop after `slen` bytes,
+ * when a NUL byte is encountered, or a
+ * non-digit is encountered after any
+ * leading skipped character; whichever
+ * comes first
+ *
+ * @param s The string to parse
+ * @param slen The maximum number of bytes to read from `s`
+ * @param end Output parameter for where parsing stopped
+ * (pointing to the first byte that is is not
+ * a leading ASCII whitespace, leading '+'
+ * character, nor a digit)
+ * @param digits1 List of digits to use, each byte is
+ * regarded as a symbol, starting from
+ * the zero-digit. If `NULL`, "0123456789"
+ * (the decimal system) will be used. Any
+ * symbol in this list will be removed from the
+ * set of ignored leading characeters; minimum
+ * length is 2. May not contain duplicates.
+ * @param digits2 List of symbols to use as synonyms for
+ * the symbols in `digits`, must be of the
+ * same length as `digits1`, or `NULL` if
+ * `digits1` is `NULL` or to use no additional
+ * symbols; it contains common it has any
+ * symbols in common with `digits1`, they
+ * must be in the same position
+ * @param a Output parameter for the decoded integer
+ * @return 0 upon successful completion, or an error
+ * code on failure
+ *
+ * @throws EINVAL `digits1` or `digits2` is misconfigured
+ * @throws EINVAL No digit was encountered;
+ * `*a` (unless it's `NULL`) will be set to
+ * the value zero
+ * @throws ERANGE The value is too large to be represented;
+ * `*a` (unless it's `NULL`) will be set to
+ * the maximum value if the value is positive,
+ * or minimum value if the value is negative
+ *
+ * This function does not set `errno`
+ *
+ * @since 1.1
+ */
+int libj2_str_to_j2i(const char *s, size_t slen, char **end, const char *digits1,
+ const char *digits2, struct libj2_j2i *a);
diff --git a/libj2/unsigned-comparsion.h b/libj2/unsigned-comparsion.h
index 39fdd07..c13397a 100644
--- a/libj2/unsigned-comparsion.h
+++ b/libj2/unsigned-comparsion.h
@@ -4,7 +4,6 @@
#endif
-
/**
* Check whether an unsigned double-max precision integer is
* less than another unsigned double-max precision integer
@@ -104,7 +103,7 @@ libj2_j2u_eq_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
* Check whether an unsigned double-max precision integer is
* not equal to another unsigned double-max precision integer
*
- * `libj2_j2u_eq_j2u(a, b)` implements `*a != *b`
+ * `libj2_j2u_ne_j2u(a, b)` implements `*a != *b`
*
* @param a The left-hand value
* @param b The right-hand value
@@ -121,7 +120,7 @@ libj2_j2u_ne_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
/**
* Compare an unsigned double-max precision integer
- * to another unsigned double-max precision integer
+ * against another unsigned double-max precision integer
*
* `libj2_j2u_cmp_j2u(a, b)` implements `*a < *b ? -1 : *a > *b ? +1 : 0`,
* or equivalently, the signum of `*a - *b` where the signum is 0 for 0
@@ -257,7 +256,7 @@ libj2_j2u_ne_ju(const struct libj2_j2u *a, uintmax_t b)
/**
* Compare an unsigned double-max precision integer
- * to an unsigned max precision integer
+ * against an unsigned max precision integer
*
* `libj2_j2u_cmp_ju(a, b)` implements `*a < b ? -1 : *a > b ? +1 : 0`,
* or equivalently, the signum of `*a - b` where the signum is 0 for 0
@@ -393,7 +392,7 @@ libj2_ju_ne_j2u(uintmax_t a, const struct libj2_j2u *b)
/**
* Compare an unsigned max precision integer
- * to an unsigned double-max precision integer
+ * against an unsigned double-max precision integer
*
* `libj2_ju_cmp_j2u(a, b)` implements `a < *b ? -1 : a > *b ? +1 : 0`,
* or equivalently, the signum of `a - *b` where the signum is 0 for 0
diff --git a/libj2_abs_j2i.c b/libj2_abs_j2i.c
new file mode 100644
index 0000000..253f44d
--- /dev/null
+++ b/libj2_abs_j2i.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_abs_j2i(struct libj2_j2i *a);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; }
+/* TODO test libj2_abs_j2i{,_to_j2i,_to_j2u} libj2_minus_abs_j2i{,_to_j2i} */
+
+#endif
diff --git a/libj2_abs_j2i_to_j2i.c b/libj2_abs_j2i_to_j2i.c
new file mode 100644
index 0000000..00776ce
--- /dev/null
+++ b/libj2_abs_j2i_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_abs_j2i_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_abs_j2i.c */
+
+#endif
diff --git a/libj2_abs_j2i_to_j2u.c b/libj2_abs_j2i_to_j2u.c
new file mode 100644
index 0000000..a50de01
--- /dev/null
+++ b/libj2_abs_j2i_to_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_abs_j2i_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_abs_j2i.c */
+
+#endif
diff --git a/libj2_j2i_cmp_j2i.c b/libj2_j2i_cmp_j2i.c
new file mode 100644
index 0000000..7c750c3
--- /dev/null
+++ b/libj2_j2i_cmp_j2i.c
@@ -0,0 +1,244 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_cmp_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+static int
+cmp_(uintmax_t a_high, uintmax_t a_low, uintmax_t b_high, uintmax_t b_low)
+{
+ struct libj2_j2i a, b, c;
+ int ret;
+
+ a.high = a_high;
+ a.low = a_low;
+ b.high = b_high;
+ b.low = b_low;
+
+ ret = libj2_j2i_cmp_j2i(&a, &b);
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+
+ EXPECT(libj2_j2i_cmp_j2i(&b, &a) == (ret ? -ret : 0));
+
+ EXPECT(libj2_j2i_lt_j2i(&a, &b) == (ret < 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+
+ EXPECT(libj2_j2i_le_j2i(&a, &b) == (ret <= 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+
+ EXPECT(libj2_j2i_gt_j2i(&a, &b) == (ret > 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+
+ EXPECT(libj2_j2i_ge_j2i(&a, &b) == (ret >= 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+
+ EXPECT(libj2_j2i_eq_j2i(&a, &b) == (ret == 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+
+ EXPECT(libj2_j2i_ne_j2i(&a, &b) == (ret != 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+
+ EXPECT(libj2_j2i_lt_j2i(&b, &a) == (ret > 0));
+ EXPECT(libj2_j2i_le_j2i(&b, &a) == (ret >= 0));
+ EXPECT(libj2_j2i_gt_j2i(&b, &a) == (ret < 0));
+ EXPECT(libj2_j2i_ge_j2i(&b, &a) == (ret <= 0));
+ EXPECT(libj2_j2i_eq_j2i(&b, &a) == (ret == 0));
+ EXPECT(libj2_j2i_ne_j2i(&b, &a) == (ret != 0));
+
+ c = (struct libj2_j2i){111, 222};
+ libj2_j2i_max_j2i_to_j2i(&a, &b, &c);
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &b) == 1);
+
+ c = (struct libj2_j2i){111, 222};
+ libj2_j2i_max_j2i_to_j2i(&b, &a, &c);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &b) == 1);
+
+ c = a;
+ libj2_j2i_max_j2i(&c, &b);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &b) == 1);
+
+ c = b;
+ libj2_j2i_max_j2i(&c, &a);
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &b) == 1);
+
+ c = (struct libj2_j2i){111, 222};
+ libj2_j2i_min_j2i_to_j2i(&a, &b, &c);
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &b) == 1);
+
+ c = (struct libj2_j2i){111, 222};
+ libj2_j2i_min_j2i_to_j2i(&b, &a, &c);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &b) == 1);
+
+ c = a;
+ libj2_j2i_min_j2i(&c, &b);
+ EXPECT(b.high == b_high);
+ EXPECT(b.low == b_low);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &b) == 1);
+
+ c = b;
+ libj2_j2i_min_j2i(&c, &a);
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &b) == 1);
+
+ return ret;
+}
+
+
+static int
+cmp(uintmax_t a_high, uintmax_t a_low, uintmax_t b_high, uintmax_t b_low)
+{
+ struct libj2_j2i a = {.high = a_high, .low = a_low};
+ struct libj2_j2i b = {.high = b_high, .low = b_low};
+ int ret;
+
+ libj2_minus_j2i(&a);
+ libj2_minus_j2i(&b);
+
+ ret = cmp_(a_high, a_low, b_high, b_low);
+
+ EXPECT(cmp_(a_high, a_low, b.high, b.low) == (libj2_j2i_is_zero(&b) ? ret : +1));
+
+ if (!a_high && !a_low)
+ return ret;
+
+ EXPECT(cmp_(a.high, a.low, b_high, b_low) == -1);
+ EXPECT(cmp_(a.high, a.low, b.high, b.low) == -ret);
+
+ return ret;
+}
+
+
+int
+main(void)
+{
+ const uintmax_t umax = UINTMAX_MAX;
+ const uintmax_t max = (uintmax_t)INTMAX_MAX;
+ const uintmax_t min = (uintmax_t)INTMAX_MIN;
+
+ EXPECT(cmp(0, 0, 0, 0) == 0);
+ EXPECT(cmp(0, 0, 0, 1) == -1);
+ EXPECT(cmp(0, 0, 1, 0) == -1);
+ EXPECT(cmp(0, 0, 1, 1) == -1);
+ EXPECT(cmp(0, 0, 0, umax) == -1);
+ EXPECT(cmp(0, 0, max, 0) == -1);
+ EXPECT(cmp(0, 0, max, umax) == -1);
+ EXPECT(cmp(0, 0, max, umax - 1U) == -1);
+
+ EXPECT(cmp(0, 1, 0, 1) == 0);
+ EXPECT(cmp(0, 1, 1, 0) == -1);
+ EXPECT(cmp(0, 1, 1, 1) == -1);
+ EXPECT(cmp(0, 1, 0, umax) == -1);
+ EXPECT(cmp(0, 1, max, 0) == -1);
+ EXPECT(cmp(0, 1, max, umax) == -1);
+ EXPECT(cmp(0, 1, max, umax - 1U) == -1);
+
+ EXPECT(cmp(1, 0, 1, 0) == 0);
+ EXPECT(cmp(1, 0, 1, 1) == -1);
+ EXPECT(cmp(1, 0, 0, umax) == +1);
+ EXPECT(cmp(1, 0, max, 0) == -1);
+ EXPECT(cmp(1, 0, max, umax) == -1);
+ EXPECT(cmp(1, 0, max, umax - 1U) == -1);
+
+ EXPECT(cmp(1, 1, 1, 1) == 0);
+ EXPECT(cmp(1, 1, 0, umax) == +1);
+ EXPECT(cmp(1, 1, max, 0) == -1);
+ EXPECT(cmp(1, 1, max, umax) == -1);
+ EXPECT(cmp(1, 1, max, umax - 1U) == -1);
+
+ EXPECT(cmp(0, umax, 0, umax) == 0);
+ EXPECT(cmp(0, umax, max, 0) == -1);
+ EXPECT(cmp(0, umax, max, umax) == -1);
+ EXPECT(cmp(0, umax, max, umax - 1U) == -1);
+
+ EXPECT(cmp(max, 0, max, 0) == 0);
+ EXPECT(cmp(max, 0, max, umax) == -1);
+ EXPECT(cmp(max, 0, max, umax - 1U) == -1);
+
+ EXPECT(cmp(max, umax, max, umax) == 0);
+ EXPECT(cmp(max, umax, max, umax - 1U) == +1);
+
+ EXPECT(cmp(max, umax - 1U, max, umax - 1U) == 0);
+
+ EXPECT(cmp_(min, 0, 0, 0) == -1);
+ EXPECT(cmp_(min, 0, 0, 1) == -1);
+ EXPECT(cmp_(min, 0, 1, 0) == -1);
+ EXPECT(cmp_(min, 0, 1, 1) == -1);
+ EXPECT(cmp_(min, 0, max, umax) == -1);
+ EXPECT(cmp_(min, 0, min, 1) == -1);
+
+ EXPECT(cmp_(0, 0, min, 0) == +1);
+ EXPECT(cmp_(0, 1, min, 0) == +1);
+ EXPECT(cmp_(1, 0, min, 0) == +1);
+ EXPECT(cmp_(1, 1, min, 0) == +1);
+ EXPECT(cmp_(max, umax, min, 0) == +1);
+ EXPECT(cmp_(min, 1, min, 0) == +1);
+
+ EXPECT(cmp_(min, 0, min, 0) == 0);
+ EXPECT(cmp_(min, 1, min, 1) == 0);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2i_cmp_j2u.c b/libj2_j2i_cmp_j2u.c
new file mode 100644
index 0000000..9e59d12
--- /dev/null
+++ b/libj2_j2i_cmp_j2u.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_cmp_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; }
+/* TODO test libj2_j2u_cmp_j2i, libj2_j2i_cmp_j2u */
+
+#endif
diff --git a/libj2_j2i_cmp_ji.c b/libj2_j2i_cmp_ji.c
new file mode 100644
index 0000000..371b382
--- /dev/null
+++ b/libj2_j2i_cmp_ji.c
@@ -0,0 +1,188 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_cmp_ji(const struct libj2_j2i *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+static int
+cmp_(uintmax_t a_high, uintmax_t a_low, intmax_t b)
+{
+ struct libj2_j2i a, c;
+ int ret;
+
+ a.high = a_high;
+ a.low = a_low;
+
+ ret = libj2_j2i_cmp_ji(&a, b);
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+
+ EXPECT(libj2_ji_cmp_j2i(b, &a) == (ret ? -ret : 0));
+
+ EXPECT(libj2_j2i_lt_ji(&a, b) == (ret < 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+
+ EXPECT(libj2_j2i_le_ji(&a, b) == (ret <= 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+
+ EXPECT(libj2_j2i_gt_ji(&a, b) == (ret > 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+
+ EXPECT(libj2_j2i_ge_ji(&a, b) == (ret >= 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+
+ EXPECT(libj2_j2i_eq_ji(&a, b) == (ret == 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+
+ EXPECT(libj2_j2i_ne_ji(&a, b) == (ret != 0));
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+
+ EXPECT(libj2_ji_lt_j2i(b, &a) == (ret > 0));
+ EXPECT(libj2_ji_le_j2i(b, &a) == (ret >= 0));
+ EXPECT(libj2_ji_gt_j2i(b, &a) == (ret < 0));
+ EXPECT(libj2_ji_ge_j2i(b, &a) == (ret <= 0));
+ EXPECT(libj2_ji_eq_j2i(b, &a) == (ret == 0));
+ EXPECT(libj2_ji_ne_j2i(b, &a) == (ret != 0));
+
+ c = (struct libj2_j2i){111, 222};
+ libj2_j2i_max_ji_to_j2i(&a, b, &c);
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_ji(&c, b) == 1);
+
+ c = a;
+ libj2_j2i_max_ji(&c, b);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_ji(&c, b) == 1);
+
+ c = (struct libj2_j2i){111, 222};
+ libj2_j2i_min_ji_to_j2i(&a, b, &c);
+ EXPECT(a.high == a_high);
+ EXPECT(a.low == a_low);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_ji(&c, b) == 1);
+
+ c = a;
+ libj2_j2i_min_ji(&c, b);
+ if (ret <= 0)
+ EXPECT(libj2_j2i_eq_j2i(&c, &a) == 1);
+ if (ret >= 0)
+ EXPECT(libj2_j2i_eq_ji(&c, b) == 1);
+
+ return ret;
+}
+
+
+static int
+cmp(uintmax_t a_high, uintmax_t a_low, uintmax_t b)
+{
+ struct libj2_j2i a;
+ int ret;
+
+ ret = cmp_(a_high, a_low, +(intmax_t)b);
+
+ EXPECT(cmp_(a_high, a_low, -(intmax_t)b) == (b ? +1 : ret));
+
+ if (!a_high && !a_low)
+ return ret;
+
+ a.high = a_high;
+ a.low = a_low;
+ libj2_minus_j2i(&a);
+
+ EXPECT(cmp_(a.high, a.low, +(intmax_t)b) == -1);
+ EXPECT(cmp_(a.high, a.low, -(intmax_t)b) == -ret);
+
+ return ret;
+}
+
+
+int
+main(void)
+{
+ const uintmax_t umax = UINTMAX_MAX;
+ const uintmax_t max = (uintmax_t)INTMAX_MAX;
+ const uintmax_t min = (uintmax_t)INTMAX_MIN;
+
+ EXPECT(cmp(0, 0, 0) == 0);
+ EXPECT(cmp(0, 1, 0) == +1);
+ EXPECT(cmp(1, 0, 0) == +1);
+ EXPECT(cmp(1, 1, 0) == +1);
+ EXPECT(cmp(0, umax, 0) == +1);
+ EXPECT(cmp(max, 0, 0) == +1);
+ EXPECT(cmp(max, umax, 0) == +1);
+ EXPECT(cmp(max, umax - 1U, 0) == +1);
+
+ EXPECT(cmp(0, 0, 1) == -1);
+ EXPECT(cmp(0, 1, 1) == 0);
+ EXPECT(cmp(1, 0, 1) == +1);
+ EXPECT(cmp(1, 1, 1) == +1);
+ EXPECT(cmp(0, umax, 1) == +1);
+ EXPECT(cmp(max, 0, 1) == +1);
+ EXPECT(cmp(max, umax, 1) == +1);
+ EXPECT(cmp(max, umax - 1U, 1) == +1);
+
+ EXPECT(cmp(0, 0, 2) == -1);
+ EXPECT(cmp(0, 1, 2) == -1);
+ EXPECT(cmp(1, 0, 2) == +1);
+ EXPECT(cmp(1, 1, 2) == +1);
+ EXPECT(cmp(0, umax, 2) == +1);
+ EXPECT(cmp(max, 0, 2) == +1);
+ EXPECT(cmp(max, umax, 2) == +1);
+ EXPECT(cmp(max, umax - 1U, 2) == +1);
+
+ EXPECT(cmp(0, 0, max) == -1);
+ EXPECT(cmp(0, 1, max) == -1);
+ EXPECT(cmp(1, 0, max) == +1);
+ EXPECT(cmp(1, 1, max) == +1);
+ EXPECT(cmp(0, umax, max) == +1);
+ EXPECT(cmp(0, max, max) == 0);
+ EXPECT(cmp(0, max + 1U, max) == +1);
+ EXPECT(cmp(max, 0, max) == +1);
+ EXPECT(cmp(max, umax, max) == +1);
+ EXPECT(cmp(max, umax - 1U, max) == +1);
+
+ EXPECT(cmp(0, 0, max - 1U) == -1);
+ EXPECT(cmp(0, 1, max - 1U) == -1);
+ EXPECT(cmp(1, 0, max - 1U) == +1);
+ EXPECT(cmp(1, 1, max - 1U) == +1);
+ EXPECT(cmp(0, umax, max - 1U) == +1);
+ EXPECT(cmp(max, 0, max - 1U) == +1);
+ EXPECT(cmp(max, umax, max - 1U) == +1);
+ EXPECT(cmp(max, umax - 1U, max - 1U) == +1);
+
+ EXPECT(cmp_(min, 0, 0) == -1);
+ EXPECT(cmp_(min, 0, 1) == -1);
+ EXPECT(cmp_(min, 0, (intmax_t)max) == -1);
+
+ EXPECT(cmp_(0, 0, (intmax_t)min) == +1);
+ EXPECT(cmp_(0, 1, (intmax_t)min) == +1);
+ EXPECT(cmp_(1, 0, (intmax_t)min) == +1);
+ EXPECT(cmp_(1, 1, (intmax_t)min) == +1);
+ EXPECT(cmp_(max, umax, (intmax_t)min) == +1);
+ EXPECT(cmp_(min, 1, (intmax_t)min) == -1);
+
+ EXPECT(cmp_(min, 0, (intmax_t)min) == -1);
+ EXPECT(cmp_(umax, min, (intmax_t)min) == 0);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2i_cmp_ju.c b/libj2_j2i_cmp_ju.c
new file mode 100644
index 0000000..2d334f8
--- /dev/null
+++ b/libj2_j2i_cmp_ju.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_cmp_ju(const struct libj2_j2i *a, uintmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; }
+/* TODO test libj2_j2i_cmp_ju, libj2_ju_cmp_j2i */
+
+#endif
diff --git a/libj2_j2i_eq_j2i.c b/libj2_j2i_eq_j2i.c
new file mode 100644
index 0000000..e73e91c
--- /dev/null
+++ b/libj2_j2i_eq_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_eq_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2i_eq_j2u.c b/libj2_j2i_eq_j2u.c
new file mode 100644
index 0000000..d4ab711
--- /dev/null
+++ b/libj2_j2i_eq_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_eq_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2u.c */
+
+#endif
diff --git a/libj2_j2i_eq_ji.c b/libj2_j2i_eq_ji.c
new file mode 100644
index 0000000..b22cad8
--- /dev/null
+++ b/libj2_j2i_eq_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_eq_ji(const struct libj2_j2i *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2i_eq_ju.c b/libj2_j2i_eq_ju.c
new file mode 100644
index 0000000..8f3c119
--- /dev/null
+++ b/libj2_j2i_eq_ju.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_eq_ju(const struct libj2_j2i *a, uintmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_j2i_ge_j2i.c b/libj2_j2i_ge_j2i.c
new file mode 100644
index 0000000..cff7aef
--- /dev/null
+++ b/libj2_j2i_ge_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_ge_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2i_ge_j2u.c b/libj2_j2i_ge_j2u.c
new file mode 100644
index 0000000..b582faf
--- /dev/null
+++ b/libj2_j2i_ge_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_ge_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2u.c */
+
+#endif
diff --git a/libj2_j2i_ge_ji.c b/libj2_j2i_ge_ji.c
new file mode 100644
index 0000000..b74f642
--- /dev/null
+++ b/libj2_j2i_ge_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_ge_ji(const struct libj2_j2i *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2i_ge_ju.c b/libj2_j2i_ge_ju.c
new file mode 100644
index 0000000..8b07a01
--- /dev/null
+++ b/libj2_j2i_ge_ju.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_ge_ju(const struct libj2_j2i *a, uintmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_j2i_gt_j2i.c b/libj2_j2i_gt_j2i.c
new file mode 100644
index 0000000..4d3f68c
--- /dev/null
+++ b/libj2_j2i_gt_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_gt_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2i_gt_j2u.c b/libj2_j2i_gt_j2u.c
new file mode 100644
index 0000000..de3282e
--- /dev/null
+++ b/libj2_j2i_gt_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_gt_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2u.c */
+
+#endif
diff --git a/libj2_j2i_gt_ji.c b/libj2_j2i_gt_ji.c
new file mode 100644
index 0000000..f43b2cf
--- /dev/null
+++ b/libj2_j2i_gt_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_gt_ji(const struct libj2_j2i *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2i_gt_ju.c b/libj2_j2i_gt_ju.c
new file mode 100644
index 0000000..89975e2
--- /dev/null
+++ b/libj2_j2i_gt_ju.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_gt_ju(const struct libj2_j2i *a, uintmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_j2i_is_max.c b/libj2_j2i_is_max.c
new file mode 100644
index 0000000..78c9448
--- /dev/null
+++ b/libj2_j2i_is_max.c
@@ -0,0 +1,225 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_is_max(const struct libj2_j2i *a);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2i value;
+ uintmax_t a, b;
+ unsigned i, j;
+
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = i + 1U;
+ value.low = b = j + 1U;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = j + 1U;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = i + 1U;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = a = i + 1U;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = i + 1U;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ b = ~(uintmax_t)0;
+
+ value.high = b;
+ value.low = a = i + 1U;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = i + 1U;
+ value.low = b;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b;
+ EXPECT(libj2_j2i_is_max(&value) == (a == (uintmax_t)INTMAX_MAX));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ a = ~(uintmax_t)0;
+
+ value.high = 0;
+ value.low = a;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = a;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == a);
+
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_j2i_is_max(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2i_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2i_is_min.c b/libj2_j2i_is_min.c
new file mode 100644
index 0000000..2393b72
--- /dev/null
+++ b/libj2_j2i_is_min.c
@@ -0,0 +1,225 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_is_min(const struct libj2_j2i *a);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2i value;
+ uintmax_t a, b;
+ unsigned i, j;
+
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = i + 1U;
+ value.low = b = j + 1U;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = j + 1U;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = i + 1U;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = a = i + 1U;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = i + 1U;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_min(&value) == (i == LIBJ2_JU_BIT - 1U));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ b = ~(uintmax_t)0;
+
+ value.high = b;
+ value.low = a = i + 1U;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = i + 1U;
+ value.low = b;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_min(&value) == 0);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ a = ~(uintmax_t)0;
+
+ value.high = 0;
+ value.low = a;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = a;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == a);
+
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_min(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2i_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2i_is_negative.c b/libj2_j2i_is_negative.c
new file mode 100644
index 0000000..6970cb2
--- /dev/null
+++ b/libj2_j2i_is_negative.c
@@ -0,0 +1,228 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_is_negative(const struct libj2_j2i *a);
+/* TODO Add man page */
+
+
+#else
+
+#define JI_VBIT (LIBJ2_JU_BIT - 1U)
+
+
+int
+main(void)
+{
+ struct libj2_j2i value;
+ uintmax_t a, b;
+ unsigned i, j;
+
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = i + 1U;
+ value.low = b = j + 1U;
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = j + 1U;
+ EXPECT(libj2_j2i_is_negative(&value) == (i == JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = i + 1U;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(libj2_j2i_is_negative(&value) == (i == JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(libj2_j2i_is_negative(&value) == (i < JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(libj2_j2i_is_negative(&value) == (i < JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = a = i + 1U;
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = i + 1U;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_negative(&value) == (i == JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = 0;
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = 0;
+ EXPECT(libj2_j2i_is_negative(&value) == (i < JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ b = ~(uintmax_t)0;
+
+ value.high = b;
+ value.low = a = i + 1U;
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = i + 1U;
+ value.low = b;
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b;
+ EXPECT(libj2_j2i_is_negative(&value) == (i == JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b;
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b;
+ EXPECT(libj2_j2i_is_negative(&value) == (i < JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_negative(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ a = ~(uintmax_t)0;
+
+ value.high = 0;
+ value.low = a;
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = a;
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == a);
+
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_j2i_is_negative(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_j2i_is_negative(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2i_is_positive.c b/libj2_j2i_is_positive.c
new file mode 100644
index 0000000..d36d5ec
--- /dev/null
+++ b/libj2_j2i_is_positive.c
@@ -0,0 +1,228 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_is_positive(const struct libj2_j2i *a);
+/* TODO Add man page */
+
+
+#else
+
+#define JI_VBIT (LIBJ2_JU_BIT - 1U)
+
+
+int
+main(void)
+{
+ struct libj2_j2i value;
+ uintmax_t a, b;
+ unsigned i, j;
+
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = i + 1U;
+ value.low = b = j + 1U;
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = j + 1U;
+ EXPECT(libj2_j2i_is_positive(&value) == (i < JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = i + 1U;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(libj2_j2i_is_positive(&value) == (i < JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(libj2_j2i_is_positive(&value) == (i == JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(libj2_j2i_is_positive(&value) == (i == JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = a = i + 1U;
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = i + 1U;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_positive(&value) == (i < JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = 0;
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = 0;
+ EXPECT(libj2_j2i_is_positive(&value) == (i == JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ b = ~(uintmax_t)0;
+
+ value.high = b;
+ value.low = a = i + 1U;
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = i + 1U;
+ value.low = b;
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b;
+ EXPECT(libj2_j2i_is_positive(&value) == (i < JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b;
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b;
+ EXPECT(libj2_j2i_is_positive(&value) == (i == JI_VBIT));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_positive(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ a = ~(uintmax_t)0;
+
+ value.high = 0;
+ value.low = a;
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = a;
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == a);
+
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_j2i_is_positive(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_j2i_is_positive(&value) == 0);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2i_is_zero.c b/libj2_j2i_is_zero.c
new file mode 100644
index 0000000..7559674
--- /dev/null
+++ b/libj2_j2i_is_zero.c
@@ -0,0 +1,225 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_is_zero(const struct libj2_j2i *a);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2i value;
+ uintmax_t a, b;
+ unsigned i, j;
+
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = i + 1U;
+ value.low = b = j + 1U;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = j + 1U;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = i + 1U;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = a = i + 1U;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = i + 1U;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ b = ~(uintmax_t)0;
+
+ value.high = b;
+ value.low = a = i + 1U;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = i + 1U;
+ value.low = b;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = 0;
+ EXPECT(libj2_j2i_is_zero(&value) == 1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ a = ~(uintmax_t)0;
+
+ value.high = 0;
+ value.low = a;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = a;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == a);
+
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2i_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2i_le_j2i.c b/libj2_j2i_le_j2i.c
new file mode 100644
index 0000000..3569d7a
--- /dev/null
+++ b/libj2_j2i_le_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_le_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2i_le_j2u.c b/libj2_j2i_le_j2u.c
new file mode 100644
index 0000000..f29aa40
--- /dev/null
+++ b/libj2_j2i_le_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_le_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2u.c */
+
+#endif
diff --git a/libj2_j2i_le_ji.c b/libj2_j2i_le_ji.c
new file mode 100644
index 0000000..1ccd14b
--- /dev/null
+++ b/libj2_j2i_le_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_le_ji(const struct libj2_j2i *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2i_le_ju.c b/libj2_j2i_le_ju.c
new file mode 100644
index 0000000..10e77ad
--- /dev/null
+++ b/libj2_j2i_le_ju.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_le_ju(const struct libj2_j2i *a, uintmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_j2i_lsh.c b/libj2_j2i_lsh.c
new file mode 100644
index 0000000..14ea251
--- /dev/null
+++ b/libj2_j2i_lsh.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_lsh(struct libj2_j2i *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; }
+/* TODO test libj2_j2i_lsh{,_to_j2i}{,_overflow}, libj2_j2i_lsh_overflow_p */
+
+#endif
diff --git a/libj2_j2i_lsh_overflow.c b/libj2_j2i_lsh_overflow.c
new file mode 100644
index 0000000..92b5e71
--- /dev/null
+++ b/libj2_j2i_lsh_overflow.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_lsh_overflow(struct libj2_j2i *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_lsh.c */
+
+#endif
diff --git a/libj2_j2i_lsh_overflow_p.c b/libj2_j2i_lsh_overflow_p.c
new file mode 100644
index 0000000..2360265
--- /dev/null
+++ b/libj2_j2i_lsh_overflow_p.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_lsh_overflow_p(const struct libj2_j2i *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_lsh.c */
+
+#endif
diff --git a/libj2_j2i_lsh_to_j2i.c b/libj2_j2i_lsh_to_j2i.c
new file mode 100644
index 0000000..b9907c5
--- /dev/null
+++ b/libj2_j2i_lsh_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_lsh_to_j2i(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2ui_lsh.c */
+
+#endif
diff --git a/libj2_j2i_lsh_to_j2i_overflow.c b/libj2_j2i_lsh_to_j2i_overflow.c
new file mode 100644
index 0000000..d6c4f50
--- /dev/null
+++ b/libj2_j2i_lsh_to_j2i_overflow.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_lsh_to_j2i_overflow(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_lsh.c */
+
+#endif
diff --git a/libj2_j2i_lt_j2i.c b/libj2_j2i_lt_j2i.c
new file mode 100644
index 0000000..7da3b21
--- /dev/null
+++ b/libj2_j2i_lt_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_lt_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2i_lt_j2u.c b/libj2_j2i_lt_j2u.c
new file mode 100644
index 0000000..7cc4f25
--- /dev/null
+++ b/libj2_j2i_lt_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_lt_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2u.c */
+
+#endif
diff --git a/libj2_j2i_lt_ji.c b/libj2_j2i_lt_ji.c
new file mode 100644
index 0000000..d2ae65b
--- /dev/null
+++ b/libj2_j2i_lt_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_lt_ji(const struct libj2_j2i *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2i_lt_ju.c b/libj2_j2i_lt_ju.c
new file mode 100644
index 0000000..71fdb93
--- /dev/null
+++ b/libj2_j2i_lt_ju.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_lt_ju(const struct libj2_j2i *a, uintmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_j2i_max.c b/libj2_j2i_max.c
new file mode 100644
index 0000000..49de1f9
--- /dev/null
+++ b/libj2_j2i_max.c
@@ -0,0 +1,33 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_max(struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2i value = {1, 2};
+
+ libj2_j2i_max(&value);
+ EXPECT(value.high == (uintmax_t)INTMAX_MAX);
+ EXPECT(value.high == UINTMAX_MAX >> 1);
+ EXPECT(value.low == UINTMAX_MAX);
+
+ libj2_j2i_max(&value);
+ EXPECT(value.high == (uintmax_t)INTMAX_MAX);
+ EXPECT(value.low == UINTMAX_MAX);
+
+#ifdef TODO /* requires libj2_j2i_add_ji */
+ libj2_j2i_add_ji(&value, 1);
+ EXPECT(libj2_j2i_is_min(&value));
+#endif
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2i_max_j2i.c b/libj2_j2i_max_j2i.c
new file mode 100644
index 0000000..29f0976
--- /dev/null
+++ b/libj2_j2i_max_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_max_j2i(struct libj2_j2i *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2i_max_j2i_to_j2i.c b/libj2_j2i_max_j2i_to_j2i.c
new file mode 100644
index 0000000..a7521c3
--- /dev/null
+++ b/libj2_j2i_max_j2i_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_max_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2i_max_ji.c b/libj2_j2i_max_ji.c
new file mode 100644
index 0000000..86387fb
--- /dev/null
+++ b/libj2_j2i_max_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_max_ji(struct libj2_j2i *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2i_max_ji_to_j2i.c b/libj2_j2i_max_ji_to_j2i.c
new file mode 100644
index 0000000..6b3a39b
--- /dev/null
+++ b/libj2_j2i_max_ji_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_max_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2i_min.c b/libj2_j2i_min.c
new file mode 100644
index 0000000..74b438b
--- /dev/null
+++ b/libj2_j2i_min.c
@@ -0,0 +1,32 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_min(struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2i value = {1, 2};
+
+ libj2_j2i_min(&value);
+ EXPECT(value.high == (uintmax_t)INTMAX_MAX + 1U);
+ EXPECT(value.low == 0);
+
+ libj2_j2i_min(&value);
+ EXPECT(value.high == (uintmax_t)INTMAX_MAX + 1U);
+ EXPECT(value.low == 0);
+
+#ifdef TODO /* requires libj2_j2i_sub_ji */
+ libj2_j2i_sub_ji(&value, 1);
+ EXPECT(libj2_j2i_is_max(&value));
+#endif
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2i_min_j2i.c b/libj2_j2i_min_j2i.c
new file mode 100644
index 0000000..687840d
--- /dev/null
+++ b/libj2_j2i_min_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_min_j2i(struct libj2_j2i *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2i_min_j2i_to_j2i.c b/libj2_j2i_min_j2i_to_j2i.c
new file mode 100644
index 0000000..81efb4e
--- /dev/null
+++ b/libj2_j2i_min_j2i_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_min_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2i_min_ji.c b/libj2_j2i_min_ji.c
new file mode 100644
index 0000000..63609f0
--- /dev/null
+++ b/libj2_j2i_min_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_min_ji(struct libj2_j2i *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_j2i_min_ji_to_j2i.c b/libj2_j2i_min_ji_to_j2i.c
new file mode 100644
index 0000000..7c6fa38
--- /dev/null
+++ b/libj2_j2i_min_ji_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_min_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_j2i_ne_j2i.c b/libj2_j2i_ne_j2i.c
new file mode 100644
index 0000000..887d4eb
--- /dev/null
+++ b/libj2_j2i_ne_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_ne_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2i_ne_j2u.c b/libj2_j2i_ne_j2u.c
new file mode 100644
index 0000000..a9ae130
--- /dev/null
+++ b/libj2_j2i_ne_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_ne_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2u.c */
+
+#endif
diff --git a/libj2_j2i_ne_ji.c b/libj2_j2i_ne_ji.c
new file mode 100644
index 0000000..95e330d
--- /dev/null
+++ b/libj2_j2i_ne_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_ne_ji(const struct libj2_j2i *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2i_ne_ju.c b/libj2_j2i_ne_ju.c
new file mode 100644
index 0000000..bb055ef
--- /dev/null
+++ b/libj2_j2i_ne_ju.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_ne_ju(const struct libj2_j2i *a, uintmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_j2i_rsh.c b/libj2_j2i_rsh.c
new file mode 100644
index 0000000..768930c
--- /dev/null
+++ b/libj2_j2i_rsh.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_rsh(struct libj2_j2i *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; }
+/* TODO test libj2_j2i_rsh{,_to_j2i}{,_underflow}, libj2_j2i_rsh_underflow_p */
+
+#endif
diff --git a/libj2_j2i_rsh_to_j2i.c b/libj2_j2i_rsh_to_j2i.c
new file mode 100644
index 0000000..958891f
--- /dev/null
+++ b/libj2_j2i_rsh_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_rsh_to_j2i(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_rsh.c */
+
+#endif
diff --git a/libj2_j2i_rsh_to_j2i_underflow.c b/libj2_j2i_rsh_to_j2i_underflow.c
new file mode 100644
index 0000000..e571712
--- /dev/null
+++ b/libj2_j2i_rsh_to_j2i_underflow.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_rsh_to_j2i_underflow(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_rsh.c */
+
+#endif
diff --git a/libj2_j2i_rsh_underflow.c b/libj2_j2i_rsh_underflow.c
new file mode 100644
index 0000000..ecc3984
--- /dev/null
+++ b/libj2_j2i_rsh_underflow.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_rsh_underflow(struct libj2_j2i *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_rsh.c */
+
+#endif
diff --git a/libj2_j2i_rsh_underflow_p.c b/libj2_j2i_rsh_underflow_p.c
new file mode 100644
index 0000000..6dfcf50
--- /dev/null
+++ b/libj2_j2i_rsh_underflow_p.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2i_rsh_underflow_p(const struct libj2_j2i *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_rsh.c */
+
+#endif
diff --git a/libj2_j2i_to_j2u.c b/libj2_j2i_to_j2u.c
new file mode 100644
index 0000000..b3d42d1
--- /dev/null
+++ b/libj2_j2i_to_j2u.c
@@ -0,0 +1,77 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2u u;
+ struct libj2_j2i v;
+ uintmax_t a, b, i;
+
+ for (i = 0; i < 10U; i++) {
+ u = (struct libj2_j2u){111, 222};
+ v.high = a = UINTMAX_MAX - i;
+ v.low = b = i;
+ libj2_j2i_to_j2u(&v, &u);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+
+ u = (struct libj2_j2u){111, 222};
+ v.high = a = i;
+ v.low = b = UINTMAX_MAX - i;
+ libj2_j2i_to_j2u(&v, &u);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+
+ u = (struct libj2_j2u){111, 222};
+ v.high = a = (uintmax_t)INTMAX_MAX + i;
+ v.low = b = i;
+ libj2_j2i_to_j2u(&v, &u);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+
+ u = (struct libj2_j2u){111, 222};
+ v.high = a = (uintmax_t)INTMAX_MIN + i;
+ v.low = b = i;
+ libj2_j2i_to_j2u(&v, &u);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+
+ u = (struct libj2_j2u){111, 222};
+ v.high = a = (uintmax_t)INTMAX_MAX - i;
+ v.low = b = i;
+ libj2_j2i_to_j2u(&v, &u);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+
+ u = (struct libj2_j2u){111, 222};
+ v.high = a = (uintmax_t)INTMAX_MIN - i;
+ v.low = b = i;
+ libj2_j2i_to_j2u(&v, &u);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2i_xor_sign.c b/libj2_j2i_xor_sign.c
new file mode 100644
index 0000000..fd29268
--- /dev/null
+++ b/libj2_j2i_xor_sign.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_xor_sign(struct libj2_j2i *a);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; }
+/* TODO test libj2_j2i_xor_sign{,_to_j2i,_to_j2u} */
+
+#endif
diff --git a/libj2_j2i_xor_sign_to_j2i.c b/libj2_j2i_xor_sign_to_j2i.c
new file mode 100644
index 0000000..5b4dfa4
--- /dev/null
+++ b/libj2_j2i_xor_sign_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_xor_sign_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_xor_sign.c */
+
+#endif
diff --git a/libj2_j2i_xor_sign_to_j2u.c b/libj2_j2i_xor_sign_to_j2u.c
new file mode 100644
index 0000000..f84c6ca
--- /dev/null
+++ b/libj2_j2i_xor_sign_to_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2i_xor_sign_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_xor_sign.c */
+
+#endif
diff --git a/libj2_j2i_zero.c b/libj2_j2i_zero.c
new file mode 100644
index 0000000..ae8f904
--- /dev/null
+++ b/libj2_j2i_zero.c
@@ -0,0 +1,27 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_zero(struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2u value = {1, 2};
+
+ libj2_j2u_zero(&value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ libj2_j2u_zero(&value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_cmp_j2i.c b/libj2_j2u_cmp_j2i.c
new file mode 100644
index 0000000..2ba1475
--- /dev/null
+++ b/libj2_j2u_cmp_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_cmp_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_j2u.c */
+
+#endif
diff --git a/libj2_j2u_cmp_j2u.c b/libj2_j2u_cmp_j2u.c
index a5072d8..d096c33 100644
--- a/libj2_j2u_cmp_j2u.c
+++ b/libj2_j2u_cmp_j2u.c
@@ -145,6 +145,7 @@ cmp(uintmax_t a_high, uintmax_t a_low, uintmax_t b_high, uintmax_t b_low)
return ret;
}
+
int
main(void)
{
@@ -157,7 +158,7 @@ main(void)
EXPECT(cmp(0, 0, 0, max) == -1);
EXPECT(cmp(0, 0, max, 0) == -1);
EXPECT(cmp(0, 0, max, max) == -1);
- EXPECT(cmp(0, 0, max, max - 1) == -1);
+ EXPECT(cmp(0, 0, max, max - 1U) == -1);
EXPECT(cmp(0, 1, 0, 1) == 0);
EXPECT(cmp(0, 1, 1, 0) == -1);
@@ -165,34 +166,34 @@ main(void)
EXPECT(cmp(0, 1, 0, max) == -1);
EXPECT(cmp(0, 1, max, 0) == -1);
EXPECT(cmp(0, 1, max, max) == -1);
- EXPECT(cmp(0, 1, max, max - 1) == -1);
+ EXPECT(cmp(0, 1, max, max - 1U) == -1);
EXPECT(cmp(1, 0, 1, 0) == 0);
EXPECT(cmp(1, 0, 1, 1) == -1);
EXPECT(cmp(1, 0, 0, max) == +1);
EXPECT(cmp(1, 0, max, 0) == -1);
EXPECT(cmp(1, 0, max, max) == -1);
- EXPECT(cmp(1, 0, max, max - 1) == -1);
+ EXPECT(cmp(1, 0, max, max - 1U) == -1);
EXPECT(cmp(1, 1, 1, 1) == 0);
EXPECT(cmp(1, 1, 0, max) == +1);
EXPECT(cmp(1, 1, max, 0) == -1);
EXPECT(cmp(1, 1, max, max) == -1);
- EXPECT(cmp(1, 1, max, max - 1) == -1);
+ EXPECT(cmp(1, 1, max, max - 1U) == -1);
EXPECT(cmp(0, max, 0, max) == 0);
EXPECT(cmp(0, max, max, 0) == -1);
EXPECT(cmp(0, max, max, max) == -1);
- EXPECT(cmp(0, max, max, max - 1) == -1);
+ EXPECT(cmp(0, max, max, max - 1U) == -1);
EXPECT(cmp(max, 0, max, 0) == 0);
EXPECT(cmp(max, 0, max, max) == -1);
- EXPECT(cmp(max, 0, max, max - 1) == -1);
+ EXPECT(cmp(max, 0, max, max - 1U) == -1);
EXPECT(cmp(max, max, max, max) == 0);
- EXPECT(cmp(max, max, max, max - 1) == +1);
+ EXPECT(cmp(max, max, max, max - 1U) == +1);
- EXPECT(cmp(max, max - 1, max, max - 1) == 0);
+ EXPECT(cmp(max, max - 1U, max, max - 1U) == 0);
return 0;
}
diff --git a/libj2_j2u_cmp_ji.c b/libj2_j2u_cmp_ji.c
new file mode 100644
index 0000000..5ed427f
--- /dev/null
+++ b/libj2_j2u_cmp_ji.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_cmp_ji(const struct libj2_j2u *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; }
+/* TODO test libj2_j2u_cmp_ji, libj2_ji_cmp_j2u */
+
+#endif
diff --git a/libj2_j2u_cmp_ju.c b/libj2_j2u_cmp_ju.c
index ba45409..d64d5ce 100644
--- a/libj2_j2u_cmp_ju.c
+++ b/libj2_j2u_cmp_ju.c
@@ -89,6 +89,7 @@ cmp(uintmax_t a_high, uintmax_t a_low, uintmax_t b)
return ret;
}
+
int
main(void)
{
@@ -101,7 +102,7 @@ main(void)
EXPECT(cmp(0, max, 0) == +1);
EXPECT(cmp(max, 0, 0) == +1);
EXPECT(cmp(max, max, 0) == +1);
- EXPECT(cmp(max, max - 1, 0) == +1);
+ EXPECT(cmp(max, max - 1U, 0) == +1);
EXPECT(cmp(0, 0, 1) == -1);
EXPECT(cmp(0, 1, 1) == 0);
@@ -110,7 +111,7 @@ main(void)
EXPECT(cmp(0, max, 1) == +1);
EXPECT(cmp(max, 0, 1) == +1);
EXPECT(cmp(max, max, 1) == +1);
- EXPECT(cmp(max, max - 1, 1) == +1);
+ EXPECT(cmp(max, max - 1U, 1) == +1);
EXPECT(cmp(0, 0, 2) == -1);
EXPECT(cmp(0, 1, 2) == -1);
@@ -119,7 +120,7 @@ main(void)
EXPECT(cmp(0, max, 2) == +1);
EXPECT(cmp(max, 0, 2) == +1);
EXPECT(cmp(max, max, 2) == +1);
- EXPECT(cmp(max, max - 1, 2) == +1);
+ EXPECT(cmp(max, max - 1U, 2) == +1);
EXPECT(cmp(0, 0, max) == -1);
EXPECT(cmp(0, 1, max) == -1);
@@ -128,16 +129,16 @@ main(void)
EXPECT(cmp(0, max, max) == 0);
EXPECT(cmp(max, 0, max) == +1);
EXPECT(cmp(max, max, max) == +1);
- EXPECT(cmp(max, max - 1, max) == +1);
+ EXPECT(cmp(max, max - 1U, max) == +1);
- EXPECT(cmp(0, 0, max - 1) == -1);
- EXPECT(cmp(0, 1, max - 1) == -1);
- EXPECT(cmp(1, 0, max - 1) == +1);
- EXPECT(cmp(1, 1, max - 1) == +1);
- EXPECT(cmp(0, max, max - 1) == +1);
- EXPECT(cmp(max, 0, max - 1) == +1);
- EXPECT(cmp(max, max, max - 1) == +1);
- EXPECT(cmp(max, max - 1, max - 1) == +1);
+ EXPECT(cmp(0, 0, max - 1U) == -1);
+ EXPECT(cmp(0, 1, max - 1U) == -1);
+ EXPECT(cmp(1, 0, max - 1U) == +1);
+ EXPECT(cmp(1, 1, max - 1U) == +1);
+ EXPECT(cmp(0, max, max - 1U) == +1);
+ EXPECT(cmp(max, 0, max - 1U) == +1);
+ EXPECT(cmp(max, max, max - 1U) == +1);
+ EXPECT(cmp(max, max - 1U, max - 1U) == +1);
return 0;
}
diff --git a/libj2_j2u_eq_j2i.c b/libj2_j2u_eq_j2i.c
new file mode 100644
index 0000000..95369c2
--- /dev/null
+++ b/libj2_j2u_eq_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_eq_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2u_eq_ji.c b/libj2_j2u_eq_ji.c
new file mode 100644
index 0000000..4a794ee
--- /dev/null
+++ b/libj2_j2u_eq_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_eq_ji(const struct libj2_j2u *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2u_ge_j2i.c b/libj2_j2u_ge_j2i.c
new file mode 100644
index 0000000..adcaee9
--- /dev/null
+++ b/libj2_j2u_ge_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_ge_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2u_ge_ji.c b/libj2_j2u_ge_ji.c
new file mode 100644
index 0000000..aef8ee7
--- /dev/null
+++ b/libj2_j2u_ge_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_ge_ji(const struct libj2_j2u *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2u_gt_j2i.c b/libj2_j2u_gt_j2i.c
new file mode 100644
index 0000000..757f71b
--- /dev/null
+++ b/libj2_j2u_gt_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_gt_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2u_gt_ji.c b/libj2_j2u_gt_ji.c
new file mode 100644
index 0000000..a3ae3ec
--- /dev/null
+++ b/libj2_j2u_gt_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_gt_ji(const struct libj2_j2u *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2u_is_max.c b/libj2_j2u_is_max.c
index 45df414..5e90264 100644
--- a/libj2_j2u_is_max.c
+++ b/libj2_j2u_is_max.c
@@ -13,23 +13,23 @@ main(void)
{
struct libj2_j2u value;
uintmax_t a, b;
- int i, j;
+ unsigned i, j;
- for (i = 0; i < CHAR_BIT * (int)sizeof(uintmax_t); i++) {
- for (j = 0; j < CHAR_BIT * (int)sizeof(uintmax_t); j++) {
- value.high = a = (uintmax_t)(i + 1);
- value.low = b = (uintmax_t)(j + 1);
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = i + 1U;
+ value.low = b = j + 1U;
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
value.high = a = (uintmax_t)1 << i;
- value.low = b = (uintmax_t)(j + 1);
+ value.low = b = j + 1U;
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = b = (uintmax_t)1 << j;
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == a);
@@ -41,19 +41,19 @@ main(void)
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = ~((uintmax_t)(i + 1));
- value.low = b = ~((uintmax_t)(j + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
value.high = a = ~((uintmax_t)1 << i);
- value.low = b = ~((uintmax_t)(j + 1));
+ value.low = b = ~((uintmax_t)(j + 1U));
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = b = ~((uintmax_t)1 << j);
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == a);
@@ -67,12 +67,12 @@ main(void)
}
value.high = 0;
- value.low = a = (uintmax_t)(i + 1);
+ value.low = a = i + 1U;
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == 0);
EXPECT(value.low == a);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = 0;
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == a);
@@ -91,12 +91,12 @@ main(void)
EXPECT(value.low == 0);
value.high = 0;
- value.low = a = ~((uintmax_t)(i + 1));
+ value.low = a = ~((uintmax_t)(i + 1U));
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == 0);
EXPECT(value.low == a);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = 0;
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == a);
@@ -117,12 +117,12 @@ main(void)
b = ~(uintmax_t)0;
value.high = b;
- value.low = a = (uintmax_t)(i + 1);
+ value.low = a = i + 1U;
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == b);
EXPECT(value.low == a);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = b;
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == a);
@@ -141,12 +141,12 @@ main(void)
EXPECT(value.low == b);
value.high = b;
- value.low = a = ~((uintmax_t)(i + 1));
+ value.low = a = ~((uintmax_t)(i + 1U));
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == b);
EXPECT(value.low == a);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = b;
EXPECT(!libj2_j2u_is_max(&value));
EXPECT(value.high == a);
@@ -191,6 +191,34 @@ main(void)
EXPECT(value.high == a);
EXPECT(value.low == a);
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2u_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2u_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2u_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2u_is_max(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
return 0;
}
diff --git a/libj2_j2u_is_min.c b/libj2_j2u_is_min.c
index a2a7565..7a50372 100644
--- a/libj2_j2u_is_min.c
+++ b/libj2_j2u_is_min.c
@@ -13,23 +13,23 @@ main(void)
{
struct libj2_j2u value;
uintmax_t a, b;
- int i, j;
+ unsigned i, j;
- for (i = 0; i < CHAR_BIT * (int)sizeof(uintmax_t); i++) {
- for (j = 0; j < CHAR_BIT * (int)sizeof(uintmax_t); j++) {
- value.high = a = (uintmax_t)(i + 1);
- value.low = b = (uintmax_t)(j + 1);
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = i + 1U;
+ value.low = b = j + 1U;
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
value.high = a = (uintmax_t)1 << i;
- value.low = b = (uintmax_t)(j + 1);
+ value.low = b = j + 1U;
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = b = (uintmax_t)1 << j;
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == a);
@@ -41,19 +41,19 @@ main(void)
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = ~((uintmax_t)(i + 1));
- value.low = b = ~((uintmax_t)(j + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
value.high = a = ~((uintmax_t)1 << i);
- value.low = b = ~((uintmax_t)(j + 1));
+ value.low = b = ~((uintmax_t)(j + 1U));
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = b = ~((uintmax_t)1 << j);
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == a);
@@ -67,12 +67,12 @@ main(void)
}
value.high = 0;
- value.low = a = (uintmax_t)(i + 1);
+ value.low = a = i + 1U;
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == 0);
EXPECT(value.low == a);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = 0;
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == a);
@@ -91,12 +91,12 @@ main(void)
EXPECT(value.low == 0);
value.high = 0;
- value.low = a = ~((uintmax_t)(i + 1));
+ value.low = a = ~((uintmax_t)(i + 1U));
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == 0);
EXPECT(value.low == a);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = 0;
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == a);
@@ -117,12 +117,12 @@ main(void)
b = ~(uintmax_t)0;
value.high = b;
- value.low = a = (uintmax_t)(i + 1);
+ value.low = a = i + 1U;
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == b);
EXPECT(value.low == a);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = b;
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == a);
@@ -141,12 +141,12 @@ main(void)
EXPECT(value.low == b);
value.high = b;
- value.low = a = ~((uintmax_t)(i + 1));
+ value.low = a = ~((uintmax_t)(i + 1U));
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == b);
EXPECT(value.low == a);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = b;
EXPECT(!libj2_j2u_is_min(&value));
EXPECT(value.high == a);
@@ -191,6 +191,34 @@ main(void)
EXPECT(value.high == a);
EXPECT(value.low == a);
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2u_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2u_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2u_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2u_is_min(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
return 0;
}
diff --git a/libj2_j2u_is_positive.c b/libj2_j2u_is_positive.c
index 21a9dd7..f4b7cfc 100644
--- a/libj2_j2u_is_positive.c
+++ b/libj2_j2u_is_positive.c
@@ -13,23 +13,23 @@ main(void)
{
struct libj2_j2u value;
uintmax_t a, b;
- int i, j;
+ unsigned i, j;
- for (i = 0; i < CHAR_BIT * (int)sizeof(uintmax_t); i++) {
- for (j = 0; j < CHAR_BIT * (int)sizeof(uintmax_t); j++) {
- value.high = a = (uintmax_t)(i + 1);
- value.low = b = (uintmax_t)(j + 1);
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = i + 1U;
+ value.low = b = j + 1U;
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == a);
EXPECT(value.low == b);
value.high = a = (uintmax_t)1 << i;
- value.low = b = (uintmax_t)(j + 1);
+ value.low = b = j + 1U;
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = b = (uintmax_t)1 << j;
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == a);
@@ -41,19 +41,19 @@ main(void)
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = ~((uintmax_t)(i + 1));
- value.low = b = ~((uintmax_t)(j + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == a);
EXPECT(value.low == b);
value.high = a = ~((uintmax_t)1 << i);
- value.low = b = ~((uintmax_t)(j + 1));
+ value.low = b = ~((uintmax_t)(j + 1U));
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = b = ~((uintmax_t)1 << j);
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == a);
@@ -67,12 +67,12 @@ main(void)
}
value.high = 0;
- value.low = a = (uintmax_t)(i + 1);
+ value.low = a = i + 1U;
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == 0);
EXPECT(value.low == a);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = 0;
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == a);
@@ -91,12 +91,12 @@ main(void)
EXPECT(value.low == 0);
value.high = 0;
- value.low = a = ~((uintmax_t)(i + 1));
+ value.low = a = ~((uintmax_t)(i + 1U));
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == 0);
EXPECT(value.low == a);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = 0;
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == a);
@@ -117,12 +117,12 @@ main(void)
b = ~(uintmax_t)0;
value.high = b;
- value.low = a = (uintmax_t)(i + 1);
+ value.low = a = i + 1U;
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == b);
EXPECT(value.low == a);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = b;
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == a);
@@ -141,12 +141,12 @@ main(void)
EXPECT(value.low == b);
value.high = b;
- value.low = a = ~((uintmax_t)(i + 1));
+ value.low = a = ~((uintmax_t)(i + 1U));
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == b);
EXPECT(value.low == a);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = b;
EXPECT(libj2_j2u_is_positive(&value) == 1);
EXPECT(value.high == a);
@@ -191,6 +191,34 @@ main(void)
EXPECT(value.high == a);
EXPECT(value.low == a);
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_j2u_is_positive(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_j2u_is_positive(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_j2u_is_positive(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_j2u_is_positive(&value) == 1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
return 0;
}
diff --git a/libj2_j2u_is_zero.c b/libj2_j2u_is_zero.c
index 7058bbe..4c2adf9 100644
--- a/libj2_j2u_is_zero.c
+++ b/libj2_j2u_is_zero.c
@@ -13,23 +13,23 @@ main(void)
{
struct libj2_j2u value;
uintmax_t a, b;
- int i, j;
+ unsigned i, j;
- for (i = 0; i < CHAR_BIT * (int)sizeof(uintmax_t); i++) {
- for (j = 0; j < CHAR_BIT * (int)sizeof(uintmax_t); j++) {
- value.high = a = (uintmax_t)(i + 1);
- value.low = b = (uintmax_t)(j + 1);
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = i + 1U;
+ value.low = b = j + 1U;
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
value.high = a = (uintmax_t)1 << i;
- value.low = b = (uintmax_t)(j + 1);
+ value.low = b = j + 1U;
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = b = (uintmax_t)1 << j;
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == a);
@@ -41,19 +41,19 @@ main(void)
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = ~((uintmax_t)(i + 1));
- value.low = b = ~((uintmax_t)(j + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
value.high = a = ~((uintmax_t)1 << i);
- value.low = b = ~((uintmax_t)(j + 1));
+ value.low = b = ~((uintmax_t)(j + 1U));
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = b = ~((uintmax_t)1 << j);
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == a);
@@ -67,12 +67,12 @@ main(void)
}
value.high = 0;
- value.low = a = (uintmax_t)(i + 1);
+ value.low = a = i + 1U;
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == 0);
EXPECT(value.low == a);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = 0;
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == a);
@@ -91,12 +91,12 @@ main(void)
EXPECT(value.low == 0);
value.high = 0;
- value.low = a = ~((uintmax_t)(i + 1));
+ value.low = a = ~((uintmax_t)(i + 1U));
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == 0);
EXPECT(value.low == a);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = 0;
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == a);
@@ -117,12 +117,12 @@ main(void)
b = ~(uintmax_t)0;
value.high = b;
- value.low = a = (uintmax_t)(i + 1);
+ value.low = a = i + 1U;
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == b);
EXPECT(value.low == a);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = b;
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == a);
@@ -141,12 +141,12 @@ main(void)
EXPECT(value.low == b);
value.high = b;
- value.low = a = ~((uintmax_t)(i + 1));
+ value.low = a = ~((uintmax_t)(i + 1U));
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == b);
EXPECT(value.low == a);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = b;
EXPECT(!libj2_j2u_is_zero(&value));
EXPECT(value.high == a);
@@ -191,6 +191,34 @@ main(void)
EXPECT(value.high == a);
EXPECT(value.low == a);
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2u_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2u_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(!libj2_j2u_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(!libj2_j2u_is_zero(&value));
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
return 0;
}
diff --git a/libj2_j2u_le_j2i.c b/libj2_j2u_le_j2i.c
new file mode 100644
index 0000000..8bfb213
--- /dev/null
+++ b/libj2_j2u_le_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_le_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2u_le_ji.c b/libj2_j2u_le_ji.c
new file mode 100644
index 0000000..96546e1
--- /dev/null
+++ b/libj2_j2u_le_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_le_ji(const struct libj2_j2u *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2u_lt_j2i.c b/libj2_j2u_lt_j2i.c
new file mode 100644
index 0000000..0fcf201
--- /dev/null
+++ b/libj2_j2u_lt_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_lt_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2u_lt_ji.c b/libj2_j2u_lt_ji.c
new file mode 100644
index 0000000..b4b4f64
--- /dev/null
+++ b/libj2_j2u_lt_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_lt_ji(const struct libj2_j2u *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2u_max.c b/libj2_j2u_max.c
index a6b7317..49fbb28 100644
--- a/libj2_j2u_max.c
+++ b/libj2_j2u_max.c
@@ -21,6 +21,9 @@ main(void)
EXPECT(~value.high == 0);
EXPECT(~value.low == 0);
+ libj2_j2u_add_ju(&value, 1U);
+ EXPECT(libj2_j2u_is_zero(&value));
+
return 0;
}
diff --git a/libj2_j2u_min.c b/libj2_j2u_min.c
index 4ede699..f2f78ae 100644
--- a/libj2_j2u_min.c
+++ b/libj2_j2u_min.c
@@ -21,6 +21,9 @@ main(void)
EXPECT(value.high == 0);
EXPECT(value.low == 0);
+ libj2_j2u_sub_ju(&value, 1U);
+ EXPECT(libj2_j2u_is_max(&value));
+
return 0;
}
diff --git a/libj2_j2u_ne_j2i.c b/libj2_j2u_ne_j2i.c
new file mode 100644
index 0000000..462862e
--- /dev/null
+++ b/libj2_j2u_ne_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_ne_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_j2i.c */
+
+#endif
diff --git a/libj2_j2u_ne_ji.c b/libj2_j2u_ne_ji.c
new file mode 100644
index 0000000..3b56e07
--- /dev/null
+++ b/libj2_j2u_ne_ji.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_ne_ji(const struct libj2_j2u *a, intmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_j2u_to_j2i.c b/libj2_j2u_to_j2i.c
new file mode 100644
index 0000000..041c79c
--- /dev/null
+++ b/libj2_j2u_to_j2i.c
@@ -0,0 +1,77 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_to_j2i(const struct libj2_j2u *a, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2u u;
+ struct libj2_j2i v;
+ uintmax_t a, b, i;
+
+ for (i = 0; i < 10U; i++) {
+ v = (struct libj2_j2i){111, 222};
+ u.high = a = UINTMAX_MAX - i;
+ u.low = b = i;
+ libj2_j2u_to_j2i(&u, &v);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+
+ v = (struct libj2_j2i){111, 222};
+ u.high = a = i;
+ u.low = b = UINTMAX_MAX - i;
+ libj2_j2u_to_j2i(&u, &v);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+
+ v = (struct libj2_j2i){111, 222};
+ u.high = a = (uintmax_t)INTMAX_MAX + i;
+ u.low = b = i;
+ libj2_j2u_to_j2i(&u, &v);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+
+ v = (struct libj2_j2i){111, 222};
+ u.high = a = (uintmax_t)INTMAX_MIN + i;
+ u.low = b = i;
+ libj2_j2u_to_j2i(&u, &v);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+
+ v = (struct libj2_j2i){111, 222};
+ u.high = a = (uintmax_t)INTMAX_MAX - i;
+ u.low = b = i;
+ libj2_j2u_to_j2i(&u, &v);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+
+ v = (struct libj2_j2i){111, 222};
+ u.high = a = (uintmax_t)INTMAX_MIN - i;
+ u.low = b = i;
+ libj2_j2u_to_j2i(&u, &v);
+ EXPECT(v.high == a);
+ EXPECT(v.low == b);
+ EXPECT(u.high == a);
+ EXPECT(u.low == b);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_to_str.c b/libj2_j2u_to_str.c
index 9398d0a..40ead84 100644
--- a/libj2_j2u_to_str.c
+++ b/libj2_j2u_to_str.c
@@ -164,7 +164,7 @@ out:
#else
-#define BUFFER_SIZE 1024
+#define BUFFER_SIZE (128U + LIBJ2_J2U_BIT)
static uintmax_t
diff --git a/libj2_j2u_zero.c b/libj2_j2u_zero.c
index ae8f904..b95a91d 100644
--- a/libj2_j2u_zero.c
+++ b/libj2_j2u_zero.c
@@ -2,7 +2,7 @@
#include "common.h"
#ifndef TEST
-extern inline void libj2_j2u_zero(struct libj2_j2u *res);
+extern inline void libj2_j2i_zero(struct libj2_j2i *res);
/* TODO Add man page */
@@ -11,13 +11,13 @@ extern inline void libj2_j2u_zero(struct libj2_j2u *res);
int
main(void)
{
- struct libj2_j2u value = {1, 2};
+ struct libj2_j2i value = {1, 2};
- libj2_j2u_zero(&value);
+ libj2_j2i_zero(&value);
EXPECT(value.high == 0);
EXPECT(value.low == 0);
- libj2_j2u_zero(&value);
+ libj2_j2i_zero(&value);
EXPECT(value.high == 0);
EXPECT(value.low == 0);
diff --git a/libj2_ji_cmp_j2i.c b/libj2_ji_cmp_j2i.c
new file mode 100644
index 0000000..ff006b1
--- /dev/null
+++ b/libj2_ji_cmp_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_cmp_j2i(intmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_cmp_j2u.c b/libj2_ji_cmp_j2u.c
new file mode 100644
index 0000000..e0bbf04
--- /dev/null
+++ b/libj2_ji_cmp_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_cmp_j2u(intmax_t a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_eq_j2i.c b/libj2_ji_eq_j2i.c
new file mode 100644
index 0000000..4c7d0b1
--- /dev/null
+++ b/libj2_ji_eq_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_eq_j2i(intmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_eq_j2u.c b/libj2_ji_eq_j2u.c
new file mode 100644
index 0000000..e38bed3
--- /dev/null
+++ b/libj2_ji_eq_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_eq_j2u(intmax_t a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_ge_j2i.c b/libj2_ji_ge_j2i.c
new file mode 100644
index 0000000..b2d2104
--- /dev/null
+++ b/libj2_ji_ge_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_ge_j2i(intmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_ge_j2u.c b/libj2_ji_ge_j2u.c
new file mode 100644
index 0000000..e4d38c5
--- /dev/null
+++ b/libj2_ji_ge_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_ge_j2u(intmax_t a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_gt_j2i.c b/libj2_ji_gt_j2i.c
new file mode 100644
index 0000000..2b982ca
--- /dev/null
+++ b/libj2_ji_gt_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_gt_j2i(intmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_gt_j2u.c b/libj2_ji_gt_j2u.c
new file mode 100644
index 0000000..6ed0474
--- /dev/null
+++ b/libj2_ji_gt_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_gt_j2u(intmax_t a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_le_j2i.c b/libj2_ji_le_j2i.c
new file mode 100644
index 0000000..653b6f8
--- /dev/null
+++ b/libj2_ji_le_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_le_j2i(intmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_le_j2u.c b/libj2_ji_le_j2u.c
new file mode 100644
index 0000000..f765f80
--- /dev/null
+++ b/libj2_ji_le_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_le_j2u(intmax_t a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_lsh_overflow_p.c b/libj2_ji_lsh_overflow_p.c
new file mode 100644
index 0000000..332a6c9
--- /dev/null
+++ b/libj2_ji_lsh_overflow_p.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_lsh_overflow_p(intmax_t a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_ji_lsh_to_j2i.c */
+
+#endif
diff --git a/libj2_ji_lsh_to_j2i.c b/libj2_ji_lsh_to_j2i.c
new file mode 100644
index 0000000..cc61b01
--- /dev/null
+++ b/libj2_ji_lsh_to_j2i.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_ji_lsh_to_j2i(intmax_t a, unsigned b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; };
+/* TODO test libj2_ji_lsh_to_j2i, libj2_ji_lsh_to_j2i_overflow, libj2_ji_lsh_overflow_p */
+
+#endif
diff --git a/libj2_ji_lsh_to_j2i_overflow.c b/libj2_ji_lsh_to_j2i_overflow.c
new file mode 100644
index 0000000..187d84d
--- /dev/null
+++ b/libj2_ji_lsh_to_j2i_overflow.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_lsh_to_j2i_overflow(intmax_t a, unsigned b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_ji_lsh_to_j2i.c */
+
+#endif
diff --git a/libj2_ji_lt_j2i.c b/libj2_ji_lt_j2i.c
new file mode 100644
index 0000000..2a4397b
--- /dev/null
+++ b/libj2_ji_lt_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_lt_j2i(intmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_lt_j2u.c b/libj2_ji_lt_j2u.c
new file mode 100644
index 0000000..0a6096d
--- /dev/null
+++ b/libj2_ji_lt_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_lt_j2u(intmax_t a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_ne_j2i.c b/libj2_ji_ne_j2i.c
new file mode 100644
index 0000000..88087a4
--- /dev/null
+++ b/libj2_ji_ne_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_ne_j2i(intmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_ne_j2u.c b/libj2_ji_ne_j2u.c
new file mode 100644
index 0000000..4591c92
--- /dev/null
+++ b/libj2_ji_ne_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_ne_j2u(intmax_t a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_cmp_ji.c */
+
+#endif
diff --git a/libj2_ji_rsh_to_j2i.c b/libj2_ji_rsh_to_j2i.c
new file mode 100644
index 0000000..128cec0
--- /dev/null
+++ b/libj2_ji_rsh_to_j2i.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_ji_rsh_to_j2i(intmax_t a, unsigned b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; }
+/* TODO test libj2_ji_rsh_to_j2i, libj2_ji_rsh_to_j2i_underflow, libj2_ji_rsh_underflow_p */
+
+#endif
diff --git a/libj2_ji_rsh_to_j2i_underflow.c b/libj2_ji_rsh_to_j2i_underflow.c
new file mode 100644
index 0000000..28dcd59
--- /dev/null
+++ b/libj2_ji_rsh_to_j2i_underflow.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_rsh_to_j2i_underflow(intmax_t a, unsigned b, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_ji_rsh_to_j2i.c */
+
+#endif
diff --git a/libj2_ji_rsh_underflow_p.c b/libj2_ji_rsh_underflow_p.c
new file mode 100644
index 0000000..7f08c1a
--- /dev/null
+++ b/libj2_ji_rsh_underflow_p.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ji_rsh_underflow_p(intmax_t a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_ji_rsh_to_j2i.c */
+
+#endif
diff --git a/libj2_ji_to_j2i.c b/libj2_ji_to_j2i.c
new file mode 100644
index 0000000..25618ca
--- /dev/null
+++ b/libj2_ji_to_j2i.c
@@ -0,0 +1,54 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_ji_to_j2i(intmax_t a, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2i value;
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ji_to_j2i(0, &value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ji_to_j2i(5, &value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 5);
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ji_to_j2i(10, &value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 10);
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ji_to_j2i(INTMAX_MAX, &value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == (uintmax_t)INTMAX_MAX);
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ji_to_j2i(-1, &value);
+ EXPECT(value.high == UINTMAX_MAX);
+ EXPECT(value.low == UINTMAX_MAX);
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ji_to_j2i(-2, &value);
+ EXPECT(value.high == UINTMAX_MAX);
+ EXPECT(value.low == UINTMAX_MAX - 1U);
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ji_to_j2i(INTMAX_MIN, &value);
+ EXPECT(value.high == UINTMAX_MAX);
+ EXPECT(value.low == ~(uintmax_t)INTMAX_MAX);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_ju_cmp_j2i.c b/libj2_ju_cmp_j2i.c
new file mode 100644
index 0000000..4ffbadf
--- /dev/null
+++ b/libj2_ju_cmp_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ju_cmp_j2i(uintmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_ju_eq_j2i.c b/libj2_ju_eq_j2i.c
new file mode 100644
index 0000000..4adfc55
--- /dev/null
+++ b/libj2_ju_eq_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ju_eq_j2i(uintmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_ju_ge_j2i.c b/libj2_ju_ge_j2i.c
new file mode 100644
index 0000000..25e2d95
--- /dev/null
+++ b/libj2_ju_ge_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ju_ge_j2i(uintmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_ju_gt_j2i.c b/libj2_ju_gt_j2i.c
new file mode 100644
index 0000000..a649307
--- /dev/null
+++ b/libj2_ju_gt_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ju_gt_j2i(uintmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_ju_le_j2i.c b/libj2_ju_le_j2i.c
new file mode 100644
index 0000000..57665ae
--- /dev/null
+++ b/libj2_ju_le_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ju_le_j2i(uintmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_ju_lt_j2i.c b/libj2_ju_lt_j2i.c
new file mode 100644
index 0000000..fed9aa2
--- /dev/null
+++ b/libj2_ju_lt_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ju_lt_j2i(uintmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_ju_ne_j2i.c b/libj2_ju_ne_j2i.c
new file mode 100644
index 0000000..8cb6962
--- /dev/null
+++ b/libj2_ju_ne_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_ju_ne_j2i(uintmax_t a, const struct libj2_j2i *b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2i_cmp_ju.c */
+
+#endif
diff --git a/libj2_ju_to_j2i.c b/libj2_ju_to_j2i.c
new file mode 100644
index 0000000..fd828d8
--- /dev/null
+++ b/libj2_ju_to_j2i.c
@@ -0,0 +1,39 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_ju_to_j2i(uintmax_t a, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2i value;
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ju_to_j2i(0, &value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ju_to_j2i(5, &value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 5);
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ju_to_j2i(10, &value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 10);
+
+ value = (struct libj2_j2i){1, 2};
+ libj2_ju_to_j2i(UINTMAX_MAX, &value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == UINTMAX_MAX);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_ju_to_j2u.c b/libj2_ju_to_j2u.c
index ce3ccb6..914850c 100644
--- a/libj2_ju_to_j2u.c
+++ b/libj2_ju_to_j2u.c
@@ -14,6 +14,11 @@ main(void)
struct libj2_j2u value;
value = (struct libj2_j2u){1, 2};
+ libj2_ju_to_j2u(0, &value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ value = (struct libj2_j2u){1, 2};
libj2_ju_to_j2u(5, &value);
EXPECT(value.high == 0);
EXPECT(value.low == 5);
@@ -23,6 +28,11 @@ main(void)
EXPECT(value.high == 0);
EXPECT(value.low == 10);
+ value = (struct libj2_j2u){1, 2};
+ libj2_ju_to_j2u(UINTMAX_MAX, &value);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == UINTMAX_MAX);
+
return 0;
}
diff --git a/libj2_max_j2i.c b/libj2_max_j2i.c
new file mode 100644
index 0000000..0c5451e
--- /dev/null
+++ b/libj2_max_j2i.c
@@ -0,0 +1,185 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_max_j2i(struct libj2_j2i *a, ... /*, NULL */);
+/* TODO Add man page */
+
+
+#else
+
+static struct libj2_j2i v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13;
+
+
+static void
+reset(void)
+{
+ const uintmax_t umax = UINTMAX_MAX;
+ const uintmax_t max = UINTMAX_MAX >> 1;
+ v1 = (struct libj2_j2i){0, 0};
+ v2 = (struct libj2_j2i){0, 1};
+ v3 = (struct libj2_j2i){0, 2};
+ v4 = (struct libj2_j2i){0, umax - 1U};
+ v5 = (struct libj2_j2i){1, 0};
+ v6 = (struct libj2_j2i){1, 1};
+ v7 = (struct libj2_j2i){max - 1U, 0};
+ v8 = (struct libj2_j2i){max - 1U, 1};
+ v9 = (struct libj2_j2i){max - 1U, umax};
+ v10 = (struct libj2_j2i){max, 0};
+ v11 = (struct libj2_j2i){max, 1};
+ v12 = (struct libj2_j2i){max, umax - 1U};
+ v13 = (struct libj2_j2i){max, umax};
+}
+
+
+static void
+expect_untouched(void)
+{
+ const uintmax_t umax = UINTMAX_MAX;
+ const uintmax_t max = UINTMAX_MAX >> 1;
+ EXPECT(libj2_j2i_eq_j2i(&v1, &(struct libj2_j2i){0, 0}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v2, &(struct libj2_j2i){0, 1}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v3, &(struct libj2_j2i){0, 2}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v4, &(struct libj2_j2i){0, umax - 1U}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v5, &(struct libj2_j2i){1, 0}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v6, &(struct libj2_j2i){1, 1}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v7, &(struct libj2_j2i){max - 1U, 0}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v8, &(struct libj2_j2i){max - 1U, 1}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v9, &(struct libj2_j2i){max - 1U, umax}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v10, &(struct libj2_j2i){max, 0}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v11, &(struct libj2_j2i){max, 1}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v12, &(struct libj2_j2i){max, umax - 1U}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v13, &(struct libj2_j2i){max, umax}) == 1);
+}
+
+
+#define HEAD(X, ...) X
+#define TAIL(X, ...) __VA_ARGS__
+
+#define CHECK(MAX, ...)\
+ do {\
+ reset();\
+ \
+ r = *(HEAD(__VA_ARGS__));\
+ libj2_max_j2i(&r, TAIL(__VA_ARGS__));\
+ expect_untouched();\
+ EXPECT(libj2_j2i_eq_j2i(&(MAX), &r));\
+ \
+ p = libj2_max_j2i_return(__VA_ARGS__);\
+ expect_untouched();\
+ EXPECT(p != NULL);\
+ EXPECT(libj2_j2i_eq_j2i(&(MAX), p));\
+ \
+ r = (struct libj2_j2i){111, 222};\
+ libj2_max_j2i_to_j2i(__VA_ARGS__, &r);\
+ expect_untouched();\
+ EXPECT(libj2_j2i_eq_j2i(&(MAX), &r));\
+ } while (0)
+
+
+int
+main(void)
+{
+ struct libj2_j2i r;
+ const struct libj2_j2i *p;
+
+ CHECK(v1, &v1, NULL);
+ CHECK(v2, &v2, NULL);
+ CHECK(v3, &v3, NULL);
+
+ CHECK(v2, &v1, &v2, NULL);
+ CHECK(v2, &v2, &v1, NULL);
+ CHECK(v3, &v2, &v3, NULL);
+ CHECK(v3, &v3, &v2, NULL);
+ CHECK(v4, &v3, &v4, NULL);
+ CHECK(v4, &v4, &v3, NULL);
+ CHECK(v5, &v4, &v5, NULL);
+ CHECK(v5, &v5, &v4, NULL);
+ CHECK(v6, &v5, &v6, NULL);
+ CHECK(v6, &v6, &v5, NULL);
+ CHECK(v7, &v6, &v7, NULL);
+ CHECK(v7, &v7, &v6, NULL);
+ CHECK(v8, &v7, &v8, NULL);
+ CHECK(v8, &v8, &v7, NULL);
+ CHECK(v9, &v8, &v9, NULL);
+ CHECK(v9, &v9, &v8, NULL);
+ CHECK(v10, &v9, &v10, NULL);
+ CHECK(v10, &v10, &v9, NULL);
+ CHECK(v11, &v10, &v11, NULL);
+ CHECK(v11, &v11, &v10, NULL);
+ CHECK(v12, &v11, &v12, NULL);
+ CHECK(v12, &v12, &v11, NULL);
+ CHECK(v13, &v12, &v13, NULL);
+ CHECK(v13, &v13, &v12, NULL);
+
+ CHECK(v6, &v1, &v2, &v3, &v4, &v5, &v6, NULL);
+ CHECK(v6, &v1, &v2, &v3, &v4, &v6, &v5, NULL);
+ CHECK(v6, &v1, &v2, &v3, &v6, &v4, &v5, NULL);
+ CHECK(v6, &v1, &v2, &v6, &v3, &v4, &v5, NULL);
+ CHECK(v6, &v1, &v6, &v2, &v3, &v4, &v5, NULL);
+ CHECK(v6, &v6, &v1, &v2, &v3, &v4, &v5, NULL);
+
+ CHECK(v6, &v6, &v5, &v4, &v3, &v2, &v1, NULL);
+ CHECK(v6, &v5, &v6, &v4, &v3, &v2, &v1, NULL);
+ CHECK(v6, &v5, &v4, &v6, &v3, &v2, &v1, NULL);
+ CHECK(v6, &v5, &v4, &v3, &v6, &v2, &v1, NULL);
+ CHECK(v6, &v5, &v4, &v3, &v2, &v6, &v1, NULL);
+ CHECK(v6, &v5, &v4, &v3, &v2, &v1, &v6, NULL);
+
+ CHECK(v13, &v1, &v6, &v9, &v11, &v12, &v4, &v8, &v2, &v3, &v10, &v7, &v5, &v13, NULL);
+ CHECK(v13, &v12, &v2, &v11, &v13, &v7, &v4, &v9, &v10, &v1, &v6, &v3, &v8, &v5, NULL);
+ CHECK(v13, &v5, &v13, &v6, &v12, &v8, &v10, &v3, &v9, &v7, &v2, &v11, &v1, &v4, NULL);
+ CHECK(v13, &v4, &v13, &v10, &v11, &v5, &v12, &v9, &v3, &v7, &v6, &v1, &v8, &v2, NULL);
+ CHECK(v13, &v5, &v7, &v6, &v3, &v2, &v1, &v11, &v12, &v8, &v4, &v9, &v13, &v10, NULL);
+ CHECK(v13, &v3, &v8, &v7, &v10, &v1, &v11, &v13, &v12, &v5, &v4, &v2, &v6, &v9, NULL);
+ CHECK(v13, &v11, &v2, &v8, &v3, &v5, &v12, &v4, &v13, &v1, &v10, &v7, &v6, &v9, NULL);
+ CHECK(v13, &v8, &v6, &v2, &v10, &v9, &v13, &v12, &v4, &v7, &v1, &v11, &v5, &v3, NULL);
+ CHECK(v13, &v4, &v8, &v7, &v12, &v13, &v1, &v6, &v11, &v2, &v3, &v10, &v9, &v5, NULL);
+ CHECK(v13, &v13, &v11, &v1, &v4, &v8, &v10, &v12, &v5, &v3, &v2, &v9, &v7, &v6, NULL);
+ CHECK(v13, &v13, &v3, &v12, &v8, &v10, &v11, &v7, &v2, &v4, &v1, &v9, &v6, &v5, NULL);
+ CHECK(v13, &v9, &v8, &v13, &v7, &v1, &v5, &v6, &v11, &v12, &v4, &v3, &v2, &v10, NULL);
+ CHECK(v13, &v9, &v8, &v10, &v6, &v3, &v1, &v12, &v2, &v5, &v11, &v4, &v7, &v13, NULL);
+ CHECK(v13, &v5, &v4, &v12, &v13, &v8, &v7, &v9, &v1, &v6, &v10, &v3, &v2, &v11, NULL);
+ CHECK(v13, &v5, &v4, &v11, &v9, &v8, &v7, &v10, &v6, &v2, &v3, &v1, &v13, &v12, NULL);
+ CHECK(v13, &v12, &v1, &v13, &v10, &v7, &v6, &v5, &v2, &v11, &v4, &v3, &v8, &v9, NULL);
+ CHECK(v13, &v2, &v1, &v8, &v7, &v13, &v5, &v9, &v10, &v6, &v3, &v11, &v12, &v4, NULL);
+ CHECK(v13, &v3, &v7, &v13, &v9, &v6, &v8, &v5, &v12, &v4, &v11, &v2, &v10, &v1, NULL);
+ CHECK(v13, &v12, &v3, &v6, &v5, &v2, &v9, &v4, &v11, &v8, &v10, &v13, &v1, &v7, NULL);
+ CHECK(v13, &v1, &v13, &v7, &v4, &v3, &v12, &v2, &v9, &v5, &v10, &v11, &v6, &v8, NULL);
+ CHECK(v13, &v7, &v3, &v8, &v1, &v2, &v4, &v13, &v5, &v6, &v10, &v9, &v11, &v12, NULL);
+ CHECK(v13, &v2, &v3, &v13, &v8, &v12, &v5, &v11, &v1, &v9, &v10, &v4, &v7, &v6, NULL);
+ CHECK(v13, &v10, &v6, &v7, &v5, &v11, &v9, &v1, &v3, &v13, &v4, &v2, &v8, &v12, NULL);
+ CHECK(v13, &v6, &v9, &v12, &v7, &v2, &v1, &v10, &v4, &v13, &v11, &v3, &v5, &v8, NULL);
+ CHECK(v13, &v5, &v1, &v9, &v6, &v4, &v8, &v7, &v11, &v13, &v3, &v2, &v12, &v10, NULL);
+ CHECK(v13, &v1, &v10, &v11, &v2, &v9, &v12, &v7, &v5, &v3, &v8, &v13, &v6, &v4, NULL);
+ CHECK(v13, &v3, &v10, &v2, &v4, &v8, &v9, &v11, &v7, &v5, &v1, &v13, &v6, &v12, NULL);
+ CHECK(v13, &v8, &v10, &v11, &v6, &v5, &v2, &v9, &v4, &v3, &v13, &v7, &v12, &v1, NULL);
+ CHECK(v13, &v4, &v12, &v11, &v7, &v3, &v13, &v10, &v2, &v5, &v9, &v1, &v6, &v8, NULL);
+ CHECK(v13, &v7, &v13, &v12, &v3, &v4, &v8, &v11, &v9, &v1, &v10, &v6, &v2, &v5, NULL);
+ CHECK(v13, &v5, &v4, &v2, &v1, &v8, &v7, &v13, &v10, &v11, &v3, &v9, &v6, &v12, NULL);
+ CHECK(v13, &v7, &v8, &v10, &v2, &v4, &v1, &v11, &v9, &v12, &v6, &v13, &v5, &v3, NULL);
+ CHECK(v13, &v3, &v7, &v2, &v13, &v5, &v10, &v12, &v6, &v8, &v1, &v11, &v9, &v4, NULL);
+ CHECK(v13, &v12, &v13, &v6, &v9, &v4, &v11, &v8, &v3, &v2, &v1, &v7, &v10, &v5, NULL);
+ CHECK(v13, &v2, &v9, &v10, &v13, &v1, &v3, &v5, &v8, &v7, &v6, &v11, &v4, &v12, NULL);
+ CHECK(v13, &v7, &v5, &v10, &v11, &v3, &v12, &v4, &v9, &v6, &v13, &v1, &v2, &v8, NULL);
+ CHECK(v13, &v1, &v3, &v4, &v8, &v2, &v13, &v11, &v7, &v10, &v5, &v6, &v12, &v9, NULL);
+ CHECK(v13, &v7, &v2, &v1, &v13, &v5, &v10, &v3, &v9, &v6, &v4, &v11, &v8, &v12, NULL);
+ CHECK(v13, &v6, &v5, &v3, &v11, &v8, &v9, &v1, &v12, &v7, &v13, &v4, &v10, &v2, NULL);
+ CHECK(v13, &v13, &v6, &v5, &v4, &v3, &v8, &v1, &v2, &v7, &v9, &v10, &v11, &v12, NULL);
+ CHECK(v13, &v13, &v12, &v4, &v3, &v11, &v6, &v1, &v7, &v10, &v2, &v5, &v9, &v8, NULL);
+ CHECK(v13, &v13, &v6, &v7, &v2, &v8, &v4, &v1, &v5, &v12, &v11, &v3, &v10, &v9, NULL);
+ CHECK(v13, &v13, &v5, &v12, &v11, &v10, &v9, &v2, &v6, &v4, &v8, &v3, &v1, &v7, NULL);
+ CHECK(v13, &v1, &v8, &v7, &v6, &v13, &v9, &v3, &v11, &v10, &v4, &v2, &v12, &v5, NULL);
+ CHECK(v13, &v8, &v9, &v3, &v7, &v1, &v11, &v2, &v13, &v4, &v6, &v12, &v10, &v5, NULL);
+ CHECK(v13, &v4, &v5, &v13, &v2, &v7, &v8, &v9, &v10, &v11, &v1, &v3, &v6, &v12, NULL);
+ CHECK(v13, &v7, &v4, &v11, &v9, &v6, &v12, &v3, &v5, &v10, &v8, &v1, &v2, &v13, NULL);
+ CHECK(v13, &v8, &v9, &v6, &v2, &v11, &v5, &v13, &v1, &v3, &v7, &v10, &v12, &v4, NULL);
+ CHECK(v13, &v10, &v4, &v5, &v6, &v3, &v7, &v13, &v8, &v12, &v2, &v9, &v1, &v11, NULL);
+ CHECK(v13, &v9, &v1, &v3, &v8, &v12, &v5, &v6, &v2, &v10, &v11, &v4, &v7, &v13, NULL);
+
+ return 0;
+}
+
+/* TODO test with negative values, and mixing positive and negative values */
+
+#endif
diff --git a/libj2_max_j2i_return.c b/libj2_max_j2i_return.c
new file mode 100644
index 0000000..a7123d8
--- /dev/null
+++ b/libj2_max_j2i_return.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline const struct libj2_j2i *libj2_max_j2i_return(const struct libj2_j2i *a, ... /*, NULL */);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_max_j2i.c */
+
+#endif
diff --git a/libj2_max_j2i_to_j2i.c b/libj2_max_j2i_to_j2i.c
new file mode 100644
index 0000000..598c65e
--- /dev/null
+++ b/libj2_max_j2i_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_max_j2i_to_j2i(const struct libj2_j2i *a, ... /*, NULL, struct libj2_j2i *res */);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_max_j2i.c */
+
+#endif
diff --git a/libj2_max_j2u.c b/libj2_max_j2u.c
index edef85c..18e4270 100644
--- a/libj2_max_j2u.c
+++ b/libj2_max_j2u.c
@@ -10,6 +10,7 @@ extern inline void libj2_max_j2u(struct libj2_j2u *a, ... /*, NULL */);
static struct libj2_j2u v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13;
+
static void
reset(void)
{
@@ -17,18 +18,19 @@ reset(void)
v1 = (struct libj2_j2u){0, 0};
v2 = (struct libj2_j2u){0, 1};
v3 = (struct libj2_j2u){0, 2};
- v4 = (struct libj2_j2u){0, max - 1};
+ v4 = (struct libj2_j2u){0, max - 1U};
v5 = (struct libj2_j2u){1, 0};
v6 = (struct libj2_j2u){1, 1};
- v7 = (struct libj2_j2u){max - 1, 0};
- v8 = (struct libj2_j2u){max - 1, 1};
- v9 = (struct libj2_j2u){max - 1, max};
+ v7 = (struct libj2_j2u){max - 1U, 0};
+ v8 = (struct libj2_j2u){max - 1U, 1};
+ v9 = (struct libj2_j2u){max - 1U, max};
v10 = (struct libj2_j2u){max, 0};
v11 = (struct libj2_j2u){max, 1};
- v12 = (struct libj2_j2u){max, max - 1};
+ v12 = (struct libj2_j2u){max, max - 1U};
v13 = (struct libj2_j2u){max, max};
}
+
static void
expect_untouched(void)
{
@@ -36,18 +38,19 @@ expect_untouched(void)
EXPECT(libj2_j2u_eq_j2u(&v1, &(struct libj2_j2u){0, 0}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v2, &(struct libj2_j2u){0, 1}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v3, &(struct libj2_j2u){0, 2}) == 1);
- EXPECT(libj2_j2u_eq_j2u(&v4, &(struct libj2_j2u){0, max - 1}) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&v4, &(struct libj2_j2u){0, max - 1U}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v5, &(struct libj2_j2u){1, 0}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v6, &(struct libj2_j2u){1, 1}) == 1);
- EXPECT(libj2_j2u_eq_j2u(&v7, &(struct libj2_j2u){max - 1, 0}) == 1);
- EXPECT(libj2_j2u_eq_j2u(&v8, &(struct libj2_j2u){max - 1, 1}) == 1);
- EXPECT(libj2_j2u_eq_j2u(&v9, &(struct libj2_j2u){max - 1, max}) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&v7, &(struct libj2_j2u){max - 1U, 0}) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&v8, &(struct libj2_j2u){max - 1U, 1}) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&v9, &(struct libj2_j2u){max - 1U, max}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v10, &(struct libj2_j2u){max, 0}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v11, &(struct libj2_j2u){max, 1}) == 1);
- EXPECT(libj2_j2u_eq_j2u(&v12, &(struct libj2_j2u){max, max - 1}) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&v12, &(struct libj2_j2u){max, max - 1U}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v13, &(struct libj2_j2u){max, max}) == 1);
}
+
#define HEAD(X, ...) X
#define TAIL(X, ...) __VA_ARGS__
@@ -71,6 +74,7 @@ expect_untouched(void)
EXPECT(libj2_j2u_eq_j2u(&(MAX), &r));\
} while (0)
+
int
main(void)
{
diff --git a/libj2_min_j2i.c b/libj2_min_j2i.c
new file mode 100644
index 0000000..039fa44
--- /dev/null
+++ b/libj2_min_j2i.c
@@ -0,0 +1,197 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_min_j2i(struct libj2_j2i *a, ... /*, NULL */);
+/* TODO Add man page */
+
+
+#else
+
+static struct libj2_j2i v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13;
+
+
+static void
+reset(void)
+{
+ const uintmax_t umax = UINTMAX_MAX;
+ const uintmax_t max = UINTMAX_MAX >> 1;
+ v1 = (struct libj2_j2i){0, 0};
+ v2 = (struct libj2_j2i){0, 1};
+ v3 = (struct libj2_j2i){0, 2};
+ v4 = (struct libj2_j2i){0, umax - 1U};
+ v5 = (struct libj2_j2i){1, 0};
+ v6 = (struct libj2_j2i){1, 1};
+ v7 = (struct libj2_j2i){max - 1U, 0};
+ v8 = (struct libj2_j2i){max - 1U, 1};
+ v9 = (struct libj2_j2i){max - 1U, umax};
+ v10 = (struct libj2_j2i){max, 0};
+ v11 = (struct libj2_j2i){max, 1};
+ v12 = (struct libj2_j2i){max, umax - 1U};
+ v13 = (struct libj2_j2i){max, umax};
+}
+
+
+static void
+expect_untouched(void)
+{
+ const uintmax_t umax = UINTMAX_MAX;
+ const uintmax_t max = UINTMAX_MAX >> 1;
+ EXPECT(libj2_j2i_eq_j2i(&v1, &(struct libj2_j2i){0, 0}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v2, &(struct libj2_j2i){0, 1}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v3, &(struct libj2_j2i){0, 2}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v4, &(struct libj2_j2i){0, umax - 1U}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v5, &(struct libj2_j2i){1, 0}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v6, &(struct libj2_j2i){1, 1}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v7, &(struct libj2_j2i){max - 1U, 0}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v8, &(struct libj2_j2i){max - 1U, 1}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v9, &(struct libj2_j2i){max - 1U, umax}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v10, &(struct libj2_j2i){max, 0}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v11, &(struct libj2_j2i){max, 1}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v12, &(struct libj2_j2i){max, umax - 1U}) == 1);
+ EXPECT(libj2_j2i_eq_j2i(&v13, &(struct libj2_j2i){max, umax}) == 1);
+}
+
+
+#define HEAD(X, ...) X
+#define TAIL(X, ...) __VA_ARGS__
+
+#define CHECK(MIN, ...)\
+ do {\
+ reset();\
+ \
+ r = *(HEAD(__VA_ARGS__));\
+ libj2_min_j2i(&r, TAIL(__VA_ARGS__));\
+ expect_untouched();\
+ EXPECT(libj2_j2i_eq_j2i(&(MIN), &r));\
+ \
+ p = libj2_min_j2i_return(__VA_ARGS__);\
+ expect_untouched();\
+ EXPECT(p != NULL);\
+ EXPECT(libj2_j2i_eq_j2i(&(MIN), p));\
+ \
+ r = (struct libj2_j2i){111, 222};\
+ libj2_min_j2i_to_j2i(__VA_ARGS__, &r);\
+ expect_untouched();\
+ EXPECT(libj2_j2i_eq_j2i(&(MIN), &r));\
+ } while (0)
+
+
+int
+main(void)
+{
+ struct libj2_j2i r;
+ const struct libj2_j2i *p;
+
+ CHECK(v1, &v1, NULL);
+ CHECK(v2, &v2, NULL);
+ CHECK(v3, &v3, NULL);
+
+ CHECK(v1, &v1, &v2, NULL);
+ CHECK(v1, &v2, &v1, NULL);
+ CHECK(v2, &v2, &v3, NULL);
+ CHECK(v2, &v3, &v2, NULL);
+ CHECK(v3, &v3, &v4, NULL);
+ CHECK(v3, &v4, &v3, NULL);
+ CHECK(v4, &v4, &v5, NULL);
+ CHECK(v4, &v5, &v4, NULL);
+ CHECK(v5, &v5, &v6, NULL);
+ CHECK(v5, &v6, &v5, NULL);
+ CHECK(v6, &v6, &v7, NULL);
+ CHECK(v6, &v7, &v6, NULL);
+ CHECK(v7, &v7, &v8, NULL);
+ CHECK(v7, &v8, &v7, NULL);
+ CHECK(v8, &v8, &v9, NULL);
+ CHECK(v8, &v9, &v8, NULL);
+ CHECK(v9, &v9, &v10, NULL);
+ CHECK(v9, &v10, &v9, NULL);
+ CHECK(v10, &v10, &v11, NULL);
+ CHECK(v10, &v11, &v10, NULL);
+ CHECK(v11, &v11, &v12, NULL);
+ CHECK(v11, &v12, &v11, NULL);
+ CHECK(v12, &v12, &v13, NULL);
+ CHECK(v12, &v13, &v12, NULL);
+
+ CHECK(v1, &v1, &v2, &v3, &v4, &v5, &v6, NULL);
+ CHECK(v1, &v2, &v1, &v3, &v4, &v5, &v6, NULL);
+ CHECK(v1, &v2, &v3, &v1, &v4, &v5, &v6, NULL);
+ CHECK(v1, &v2, &v3, &v4, &v1, &v5, &v6, NULL);
+ CHECK(v1, &v2, &v3, &v4, &v5, &v1, &v6, NULL);
+ CHECK(v1, &v2, &v3, &v4, &v5, &v6, &v1, NULL);
+
+ CHECK(v1, &v6, &v5, &v4, &v3, &v2, &v1, NULL);
+ CHECK(v1, &v6, &v5, &v4, &v3, &v1, &v2, NULL);
+ CHECK(v1, &v6, &v5, &v4, &v1, &v3, &v2, NULL);
+ CHECK(v1, &v6, &v5, &v1, &v4, &v3, &v2, NULL);
+ CHECK(v1, &v6, &v1, &v5, &v4, &v3, &v2, NULL);
+ CHECK(v1, &v1, &v6, &v5, &v4, &v3, &v2, NULL);
+
+ CHECK(v2, &v2, &v3, &v4, &v5, &v6, NULL);
+ CHECK(v2, &v3, &v2, &v4, &v5, &v6, NULL);
+ CHECK(v2, &v3, &v4, &v2, &v5, &v6, NULL);
+ CHECK(v2, &v3, &v4, &v5, &v2, &v6, NULL);
+ CHECK(v2, &v3, &v4, &v5, &v6, &v2, NULL);
+
+ CHECK(v2, &v6, &v5, &v4, &v3, &v2, NULL);
+ CHECK(v2, &v6, &v5, &v4, &v2, &v3, NULL);
+ CHECK(v2, &v6, &v5, &v2, &v4, &v3, NULL);
+ CHECK(v2, &v6, &v2, &v5, &v4, &v3, NULL);
+ CHECK(v2, &v2, &v6, &v5, &v4, &v3, NULL);
+
+ CHECK(v2, &v6, &v9, &v11, &v12, &v4, &v8, &v2, &v3, &v10, &v7, &v5, &v13, NULL);
+ CHECK(v2, &v12, &v2, &v11, &v13, &v7, &v4, &v9, &v10, &v6, &v3, &v8, &v5, NULL);
+ CHECK(v2, &v5, &v13, &v6, &v12, &v8, &v10, &v3, &v9, &v7, &v2, &v11, &v4, NULL);
+ CHECK(v2, &v4, &v13, &v10, &v11, &v5, &v12, &v9, &v3, &v7, &v6, &v8, &v2, NULL);
+ CHECK(v2, &v5, &v7, &v6, &v3, &v2, &v11, &v12, &v8, &v4, &v9, &v13, &v10, NULL);
+ CHECK(v2, &v3, &v8, &v7, &v10, &v11, &v13, &v12, &v5, &v4, &v2, &v6, &v9, NULL);
+ CHECK(v2, &v11, &v2, &v8, &v3, &v5, &v12, &v4, &v13, &v10, &v7, &v6, &v9, NULL);
+ CHECK(v2, &v8, &v6, &v2, &v10, &v9, &v13, &v12, &v4, &v7, &v11, &v5, &v3, NULL);
+ CHECK(v2, &v4, &v8, &v7, &v12, &v13, &v6, &v11, &v2, &v3, &v10, &v9, &v5, NULL);
+ CHECK(v2, &v13, &v11, &v4, &v8, &v10, &v12, &v5, &v3, &v2, &v9, &v7, &v6, NULL);
+ CHECK(v2, &v13, &v3, &v12, &v8, &v10, &v11, &v7, &v2, &v4, &v9, &v6, &v5, NULL);
+ CHECK(v2, &v9, &v8, &v13, &v7, &v5, &v6, &v11, &v12, &v4, &v3, &v2, &v10, NULL);
+ CHECK(v2, &v9, &v8, &v10, &v6, &v3, &v12, &v2, &v5, &v11, &v4, &v7, &v13, NULL);
+ CHECK(v2, &v5, &v4, &v12, &v13, &v8, &v7, &v9, &v6, &v10, &v3, &v2, &v11, NULL);
+ CHECK(v2, &v5, &v4, &v11, &v9, &v8, &v7, &v10, &v6, &v2, &v3, &v13, &v12, NULL);
+ CHECK(v2, &v12, &v13, &v10, &v7, &v6, &v5, &v2, &v11, &v4, &v3, &v8, &v9, NULL);
+ CHECK(v2, &v2, &v8, &v7, &v13, &v5, &v9, &v10, &v6, &v3, &v11, &v12, &v4, NULL);
+ CHECK(v2, &v3, &v7, &v13, &v9, &v6, &v8, &v5, &v12, &v4, &v11, &v2, &v10, NULL);
+ CHECK(v2, &v12, &v3, &v6, &v5, &v2, &v9, &v4, &v11, &v8, &v10, &v13, &v7, NULL);
+ CHECK(v2, &v13, &v7, &v4, &v3, &v12, &v2, &v9, &v5, &v10, &v11, &v6, &v8, NULL);
+ CHECK(v2, &v7, &v3, &v8, &v2, &v4, &v13, &v5, &v6, &v10, &v9, &v11, &v12, NULL);
+ CHECK(v2, &v2, &v3, &v13, &v8, &v12, &v5, &v11, &v9, &v10, &v4, &v7, &v6, NULL);
+ CHECK(v2, &v10, &v6, &v7, &v5, &v11, &v9, &v3, &v13, &v4, &v2, &v8, &v12, NULL);
+ CHECK(v2, &v6, &v9, &v12, &v7, &v2, &v10, &v4, &v13, &v11, &v3, &v5, &v8, NULL);
+ CHECK(v2, &v5, &v9, &v6, &v4, &v8, &v7, &v11, &v13, &v3, &v2, &v12, &v10, NULL);
+ CHECK(v2, &v10, &v11, &v2, &v9, &v12, &v7, &v5, &v3, &v8, &v13, &v6, &v4, NULL);
+ CHECK(v2, &v3, &v10, &v2, &v4, &v8, &v9, &v11, &v7, &v5, &v13, &v6, &v12, NULL);
+ CHECK(v2, &v8, &v10, &v11, &v6, &v5, &v2, &v9, &v4, &v3, &v13, &v7, &v12, NULL);
+ CHECK(v2, &v4, &v12, &v11, &v7, &v3, &v13, &v10, &v2, &v5, &v9, &v6, &v8, NULL);
+ CHECK(v2, &v7, &v13, &v12, &v3, &v4, &v8, &v11, &v9, &v10, &v6, &v2, &v5, NULL);
+ CHECK(v2, &v5, &v4, &v2, &v8, &v7, &v13, &v10, &v11, &v3, &v9, &v6, &v12, NULL);
+ CHECK(v2, &v7, &v8, &v10, &v2, &v4, &v11, &v9, &v12, &v6, &v13, &v5, &v3, NULL);
+ CHECK(v2, &v3, &v7, &v2, &v13, &v5, &v10, &v12, &v6, &v8, &v11, &v9, &v4, NULL);
+ CHECK(v2, &v12, &v13, &v6, &v9, &v4, &v11, &v8, &v3, &v2, &v7, &v10, &v5, NULL);
+ CHECK(v2, &v2, &v9, &v10, &v13, &v3, &v5, &v8, &v7, &v6, &v11, &v4, &v12, NULL);
+ CHECK(v2, &v7, &v5, &v10, &v11, &v3, &v12, &v4, &v9, &v6, &v13, &v2, &v8, NULL);
+ CHECK(v2, &v3, &v4, &v8, &v2, &v13, &v11, &v7, &v10, &v5, &v6, &v12, &v9, NULL);
+ CHECK(v2, &v7, &v2, &v13, &v5, &v10, &v3, &v9, &v6, &v4, &v11, &v8, &v12, NULL);
+ CHECK(v2, &v6, &v5, &v3, &v11, &v8, &v9, &v12, &v7, &v13, &v4, &v10, &v2, NULL);
+ CHECK(v2, &v13, &v6, &v5, &v4, &v3, &v8, &v2, &v7, &v9, &v10, &v11, &v12, NULL);
+ CHECK(v2, &v13, &v12, &v4, &v3, &v11, &v6, &v7, &v10, &v2, &v5, &v9, &v8, NULL);
+ CHECK(v2, &v13, &v6, &v7, &v2, &v8, &v4, &v5, &v12, &v11, &v3, &v10, &v9, NULL);
+ CHECK(v2, &v13, &v5, &v12, &v11, &v10, &v9, &v2, &v6, &v4, &v8, &v3, &v7, NULL);
+ CHECK(v2, &v8, &v7, &v6, &v13, &v9, &v3, &v11, &v10, &v4, &v2, &v12, &v5, NULL);
+ CHECK(v2, &v8, &v9, &v3, &v7, &v11, &v2, &v13, &v4, &v6, &v12, &v10, &v5, NULL);
+ CHECK(v2, &v4, &v5, &v13, &v2, &v7, &v8, &v9, &v10, &v11, &v3, &v6, &v12, NULL);
+ CHECK(v2, &v7, &v4, &v11, &v9, &v6, &v12, &v3, &v5, &v10, &v8, &v2, &v13, NULL);
+ CHECK(v2, &v8, &v9, &v6, &v2, &v11, &v5, &v13, &v3, &v7, &v10, &v12, &v4, NULL);
+ CHECK(v2, &v10, &v4, &v5, &v6, &v3, &v7, &v13, &v8, &v12, &v2, &v9, &v11, NULL);
+ CHECK(v2, &v9, &v3, &v8, &v12, &v5, &v6, &v2, &v10, &v11, &v4, &v7, &v13, NULL);
+
+ return 0;
+}
+
+/* TODO test with negative values, and mixing positive and negative values */
+
+#endif
diff --git a/libj2_min_j2i_return.c b/libj2_min_j2i_return.c
new file mode 100644
index 0000000..5d25a60
--- /dev/null
+++ b/libj2_min_j2i_return.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline const struct libj2_j2i *libj2_min_j2i_return(const struct libj2_j2i *a, ... /*, NULL */);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_min_j2i.c */
+
+#endif
diff --git a/libj2_min_j2i_to_j2i.c b/libj2_min_j2i_to_j2i.c
new file mode 100644
index 0000000..e17e517
--- /dev/null
+++ b/libj2_min_j2i_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_min_j2i_to_j2i(const struct libj2_j2i *a, ... /*, NULL, struct libj2_j2i *res */);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_min_j2i.c */
+
+#endif
diff --git a/libj2_min_j2u.c b/libj2_min_j2u.c
index 729bbfd..d74359a 100644
--- a/libj2_min_j2u.c
+++ b/libj2_min_j2u.c
@@ -10,6 +10,7 @@ extern inline void libj2_min_j2u(struct libj2_j2u *a, ... /*, NULL */);
static struct libj2_j2u v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13;
+
static void
reset(void)
{
@@ -17,18 +18,19 @@ reset(void)
v1 = (struct libj2_j2u){0, 0};
v2 = (struct libj2_j2u){0, 1};
v3 = (struct libj2_j2u){0, 2};
- v4 = (struct libj2_j2u){0, max - 1};
+ v4 = (struct libj2_j2u){0, max - 1U};
v5 = (struct libj2_j2u){1, 0};
v6 = (struct libj2_j2u){1, 1};
- v7 = (struct libj2_j2u){max - 1, 0};
- v8 = (struct libj2_j2u){max - 1, 1};
- v9 = (struct libj2_j2u){max - 1, max};
+ v7 = (struct libj2_j2u){max - 1U, 0};
+ v8 = (struct libj2_j2u){max - 1U, 1};
+ v9 = (struct libj2_j2u){max - 1U, max};
v10 = (struct libj2_j2u){max, 0};
v11 = (struct libj2_j2u){max, 1};
- v12 = (struct libj2_j2u){max, max - 1};
+ v12 = (struct libj2_j2u){max, max - 1U};
v13 = (struct libj2_j2u){max, max};
}
+
static void
expect_untouched(void)
{
@@ -36,18 +38,19 @@ expect_untouched(void)
EXPECT(libj2_j2u_eq_j2u(&v1, &(struct libj2_j2u){0, 0}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v2, &(struct libj2_j2u){0, 1}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v3, &(struct libj2_j2u){0, 2}) == 1);
- EXPECT(libj2_j2u_eq_j2u(&v4, &(struct libj2_j2u){0, max - 1}) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&v4, &(struct libj2_j2u){0, max - 1U}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v5, &(struct libj2_j2u){1, 0}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v6, &(struct libj2_j2u){1, 1}) == 1);
- EXPECT(libj2_j2u_eq_j2u(&v7, &(struct libj2_j2u){max - 1, 0}) == 1);
- EXPECT(libj2_j2u_eq_j2u(&v8, &(struct libj2_j2u){max - 1, 1}) == 1);
- EXPECT(libj2_j2u_eq_j2u(&v9, &(struct libj2_j2u){max - 1, max}) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&v7, &(struct libj2_j2u){max - 1U, 0}) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&v8, &(struct libj2_j2u){max - 1U, 1}) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&v9, &(struct libj2_j2u){max - 1U, max}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v10, &(struct libj2_j2u){max, 0}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v11, &(struct libj2_j2u){max, 1}) == 1);
- EXPECT(libj2_j2u_eq_j2u(&v12, &(struct libj2_j2u){max, max - 1}) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&v12, &(struct libj2_j2u){max, max - 1U}) == 1);
EXPECT(libj2_j2u_eq_j2u(&v13, &(struct libj2_j2u){max, max}) == 1);
}
+
#define HEAD(X, ...) X
#define TAIL(X, ...) __VA_ARGS__
@@ -71,6 +74,7 @@ expect_untouched(void)
EXPECT(libj2_j2u_eq_j2u(&(MIN), &r));\
} while (0)
+
int
main(void)
{
diff --git a/libj2_minus_abs_j2i.c b/libj2_minus_abs_j2i.c
new file mode 100644
index 0000000..d2f56b4
--- /dev/null
+++ b/libj2_minus_abs_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_minus_abs_j2i(struct libj2_j2i *a);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_minus_abs_j2i.c */
+
+#endif
diff --git a/libj2_minus_abs_j2i_to_j2i.c b/libj2_minus_abs_j2i_to_j2i.c
new file mode 100644
index 0000000..8f41cab
--- /dev/null
+++ b/libj2_minus_abs_j2i_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_minus_abs_j2i_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_abs_j2i.c */
+
+#endif
diff --git a/libj2_minus_j2i.c b/libj2_minus_j2i.c
new file mode 100644
index 0000000..bac519f
--- /dev/null
+++ b/libj2_minus_j2i.c
@@ -0,0 +1,95 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_minus_j2i(struct libj2_j2i *a);
+/* TODO Add man page */
+
+
+#else
+
+static uintmax_t
+random_ju(void)
+{
+ size_t n = LIBJ2_JU_BIT;
+ uintmax_t r = 0;
+ while (n--)
+ if (rand() < rand())
+ r |= (uintmax_t)1 << n;
+ return r;
+}
+
+
+static void
+minus_j2i(struct libj2_j2i *a)
+{
+ struct libj2_j2i r, a_saved = *a;
+ r = (struct libj2_j2i){111, 222};
+ libj2_minus_j2i_to_j2i(a, &r);
+ EXPECT(libj2_j2i_eq_j2i(a, &a_saved));
+ libj2_minus_j2i(a);
+ EXPECT(libj2_j2i_eq_j2i(a, &r));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+ struct libj2_j2i a, b;
+ uintmax_t v;
+
+ libj2_j2i_zero(&a);
+ minus_j2i(&a);
+ EXPECT(libj2_j2i_is_zero(&a));
+
+ for (i = 1; i < 256; i++) {
+ libj2_ji_to_j2i((intmax_t)i, &a);
+ minus_j2i(&a);
+ EXPECT(libj2_j2i_eq_ji(&a, -(intmax_t)i));
+ minus_j2i(&a);
+ EXPECT(libj2_j2i_eq_ji(&a, (intmax_t)i));
+ }
+
+ a = (struct libj2_j2i){.high = 0, .low = 1};
+ minus_j2i(&a);
+ EXPECT(libj2_j2i_eq_j2i(&a, &(struct libj2_j2i){.high = UINTMAX_MAX, .low = UINTMAX_MAX}));
+
+ a = (struct libj2_j2i){.high = UINTMAX_MAX, .low = UINTMAX_MAX};
+ minus_j2i(&a);
+ EXPECT(libj2_j2i_eq_j2i(&a, &(struct libj2_j2i){.high = 0, .low = 1}));
+
+ for (i = 0; i < 256; i++) {
+ a.high = 0;
+ a.low = v = random_ju();
+ minus_j2i(&a);
+ EXPECT(a.high == UINTMAX_MAX);
+ EXPECT(a.low == 0U - v);
+
+ a.high = UINTMAX_MAX;
+ a.low = v = random_ju();
+ minus_j2i(&a);
+ EXPECT(a.high == 0);
+ EXPECT(a.low == 0U - v);
+ }
+
+#ifdef TODO /* requires libj2_j2i_add_j2i */
+ for (i = 0; i < 256; i++) {
+ a.high = b.high = random_ju() >> 1;
+ a.low = b.low = random_ju();
+ minus_j2i(&a);
+ libj2_j2i_add_j2i(&a, &b);
+ EXPECT(libj2_j2i_is_zero(&a));
+
+ a.high = b.high ^= UINTMAX_MAX;
+ a.low = b.low ^= UINTMAX_MAX;
+ minus_j2i(&a);
+ libj2_j2i_add_j2i(&a, &b);
+ EXPECT(libj2_j2i_is_zero(&a));
+ }
+#endif
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_minus_j2i_to_j2i.c b/libj2_minus_j2i_to_j2i.c
new file mode 100644
index 0000000..01e559a
--- /dev/null
+++ b/libj2_minus_j2i_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_minus_j2i_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_minus_j2i.c */
+
+#endif
diff --git a/libj2_minus_j2i_to_j2u.c b/libj2_minus_j2i_to_j2u.c
new file mode 100644
index 0000000..a5fb3d1
--- /dev/null
+++ b/libj2_minus_j2i_to_j2u.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_minus_j2i_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; }
+/* TODO test */
+
+#endif
diff --git a/libj2_minus_j2u.c b/libj2_minus_j2u.c
index c0609f9..f19c5b7 100644
--- a/libj2_minus_j2u.c
+++ b/libj2_minus_j2u.c
@@ -66,11 +66,17 @@ main(void)
}
for (i = 0; i < 256; i++) {
- a.high = b.high = random_ju();
+ a.high = b.high = random_ju() >> 1;
a.low = b.low = random_ju();
minus_j2u(&a);
libj2_j2u_add_j2u(&a, &b);
EXPECT(libj2_j2u_is_zero(&a));
+
+ a.high = b.high ^= UINTMAX_MAX;
+ a.low = b.low ^= UINTMAX_MAX;
+ minus_j2u(&a);
+ libj2_j2u_add_j2u(&a, &b);
+ EXPECT(libj2_j2u_is_zero(&a));
}
return 0;
diff --git a/libj2_minus_j2u_to_j2i.c b/libj2_minus_j2u_to_j2i.c
new file mode 100644
index 0000000..efda5d5
--- /dev/null
+++ b/libj2_minus_j2u_to_j2i.c
@@ -0,0 +1,14 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_minus_j2u_to_j2i(const struct libj2_j2u *a, struct libj2_j2i *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; }
+/* TODO test */
+
+#endif
diff --git a/libj2_sgn_j2i.c b/libj2_sgn_j2i.c
new file mode 100644
index 0000000..f2c0265
--- /dev/null
+++ b/libj2_sgn_j2i.c
@@ -0,0 +1,228 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_sgn_j2i(const struct libj2_j2i *a);
+/* TODO Add man page */
+
+
+#else
+
+#define JI_VBIT (LIBJ2_JU_BIT - 1U)
+
+
+int
+main(void)
+{
+ struct libj2_j2i value;
+ uintmax_t a, b;
+ unsigned i, j;
+
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = (uintmax_t)(i + 1);
+ value.low = b = j + 1U;
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = j + 1U;
+ EXPECT(libj2_sgn_j2i(&value) == (i == JI_VBIT ? -1 : +1));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)(i + 1);
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b = (uintmax_t)1 << j;
+ EXPECT(libj2_sgn_j2i(&value) == (i == JI_VBIT ? -1 : +1));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)(j + 1U));
+ EXPECT(libj2_sgn_j2i(&value) == (i == JI_VBIT ? +1 : -1));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b = ~((uintmax_t)1 << j);
+ EXPECT(libj2_sgn_j2i(&value) == (i == JI_VBIT ? +1 : -1));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = a = (uintmax_t)(i + 1);
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)(i + 1);
+ value.low = 0;
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = 0;
+ EXPECT(libj2_sgn_j2i(&value) == (i == JI_VBIT ? -1 : +1));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = 0;
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = 0;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = 0;
+ EXPECT(libj2_sgn_j2i(&value) == (i < JI_VBIT ? -1 : +1));
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ b = ~(uintmax_t)0;
+
+ value.high = b;
+ value.low = a = (uintmax_t)(i + 1);
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)(i + 1);
+ value.low = b;
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = (uintmax_t)1 << i;
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = (uintmax_t)1 << i;
+ value.low = b;
+ EXPECT(libj2_sgn_j2i(&value) == (i == JI_VBIT ? -1 : +1));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)(i + 1U));
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b;
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+
+ value.high = b;
+ value.low = a = ~((uintmax_t)1 << i);
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == b);
+ EXPECT(value.low == a);
+
+ value.high = a = ~((uintmax_t)1 << i);
+ value.low = b;
+ EXPECT(libj2_sgn_j2i(&value) == (i < JI_VBIT ? -1 : +1));
+ EXPECT(value.high == a);
+ EXPECT(value.low == b);
+ }
+
+ value.high = 0;
+ value.low = 0;
+ EXPECT(libj2_sgn_j2i(&value) == 0);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == 0);
+
+ a = ~(uintmax_t)0;
+
+ value.high = 0;
+ value.low = a;
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == 0);
+ EXPECT(value.low == a);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = a;
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == a);
+
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_sgn_j2i(&value) == +1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_sgn_j2i(&value) == -1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_sgn_j2u.c b/libj2_sgn_j2u.c
index d20aa6f..5638388 100644
--- a/libj2_sgn_j2u.c
+++ b/libj2_sgn_j2u.c
@@ -13,23 +13,23 @@ main(void)
{
struct libj2_j2u value;
uintmax_t a, b;
- int i, j;
+ unsigned i, j;
- for (i = 0; i < CHAR_BIT * (int)sizeof(uintmax_t); i++) {
- for (j = 0; j < CHAR_BIT * (int)sizeof(uintmax_t); j++) {
- value.high = a = (uintmax_t)(i + 1);
- value.low = b = (uintmax_t)(j + 1);
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ value.high = a = i + 1U;
+ value.low = b = j + 1U;
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == a);
EXPECT(value.low == b);
value.high = a = (uintmax_t)1 << i;
- value.low = b = (uintmax_t)(j + 1);
+ value.low = b = j + 1U;
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = b = (uintmax_t)1 << j;
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == a);
@@ -41,19 +41,19 @@ main(void)
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = ~((uintmax_t)(i + 1));
- value.low = b = ~((uintmax_t)(j + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
+ value.low = b = ~((uintmax_t)(j + 1U));
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == a);
EXPECT(value.low == b);
value.high = a = ~((uintmax_t)1 << i);
- value.low = b = ~((uintmax_t)(j + 1));
+ value.low = b = ~((uintmax_t)(j + 1U));
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == a);
EXPECT(value.low == b);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = b = ~((uintmax_t)1 << j);
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == a);
@@ -67,12 +67,12 @@ main(void)
}
value.high = 0;
- value.low = a = (uintmax_t)(i + 1);
+ value.low = a = i + 1U;
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == 0);
EXPECT(value.low == a);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = 0;
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == a);
@@ -91,12 +91,12 @@ main(void)
EXPECT(value.low == 0);
value.high = 0;
- value.low = a = ~((uintmax_t)(i + 1));
+ value.low = a = ~((uintmax_t)(i + 1U));
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == 0);
EXPECT(value.low == a);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = 0;
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == a);
@@ -117,12 +117,12 @@ main(void)
b = ~(uintmax_t)0;
value.high = b;
- value.low = a = (uintmax_t)(i + 1);
+ value.low = a = i + 1U;
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == b);
EXPECT(value.low == a);
- value.high = a = (uintmax_t)(i + 1);
+ value.high = a = i + 1U;
value.low = b;
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == a);
@@ -141,12 +141,12 @@ main(void)
EXPECT(value.low == b);
value.high = b;
- value.low = a = ~((uintmax_t)(i + 1));
+ value.low = a = ~((uintmax_t)(i + 1U));
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == b);
EXPECT(value.low == a);
- value.high = a = ~((uintmax_t)(i + 1));
+ value.high = a = ~((uintmax_t)(i + 1U));
value.low = b;
EXPECT(libj2_sgn_j2u(&value) == +1);
EXPECT(value.high == a);
@@ -191,6 +191,34 @@ main(void)
EXPECT(value.high == a);
EXPECT(value.low == a);
+ a >>= 1;
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_sgn_j2u(&value) == +1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_sgn_j2u(&value) == +1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
+ a = UINTMAX_MAX ^ (UINTMAX_MAX >> 1);
+
+ value.high = a;
+ value.low = 0;
+ EXPECT(libj2_sgn_j2u(&value) == +1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == 0);
+
+ value.high = a;
+ value.low = ~(uintmax_t)0;
+ EXPECT(libj2_sgn_j2u(&value) == +1);
+ EXPECT(value.high == a);
+ EXPECT(value.low == ~(uintmax_t)0);
+
return 0;
}
diff --git a/libj2_str_to_j2i.c b/libj2_str_to_j2i.c
new file mode 100644
index 0000000..990d3b9
--- /dev/null
+++ b/libj2_str_to_j2i.c
@@ -0,0 +1,138 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#include <errno.h>
+#ifndef TEST
+
+/* TODO Add man page */
+
+int
+libj2_str_to_j2i(const char *s, size_t slen, char **end, const char *digits1, const char *digits2, struct libj2_j2i *a)
+{
+ struct libj2_j2u u;
+ int neg, r;
+
+ r = libj2_str_to_j2u_sign(s, slen, end, digits1, digits2, &u, &neg);
+ switch (r) {
+ case 0:
+ break;
+ overflow:
+ r = ERANGE;
+ /* fall-through */
+ case ERANGE:
+ if (neg)
+ libj2_j2i_min(a);
+ else
+ libj2_j2i_max(a);
+ /* fall-through */
+ default:
+ return r;
+ }
+
+ if (neg) {
+#if defined(LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_)
+ if (libj2_co_j2u(&u) > 1U)
+ goto may_overflow;
+#else
+ if (u.high) {
+ if (u.low)
+ goto may_overflow;
+ if (u.high & (u.high - 1U))
+ goto may_overflow;
+ } else {
+ if (u.low & (u.low - 1U))
+ goto may_overflow;
+ }
+#endif
+ if (0) {
+ may_overflow:
+ if (libj2_j2u_test_bit(&u, LIBJ2_J2U_BIT - 1U))
+ goto overflow;
+ }
+ libj2_minus_j2u_to_j2i(&u, a);
+ } else {
+ if (libj2_j2u_test_bit(&u, LIBJ2_J2U_BIT - 1U))
+ goto overflow;
+ libj2_j2u_to_j2i(&u, a);
+ }
+
+ return r;
+
+}
+
+
+#else
+
+
+int
+main(void)
+{
+ /* Primarily tested via libj2_str_to_j2u(_sign) */
+
+ char buf[128U + LIBJ2_J2U_BIT];
+ struct libj2_j2i a, a_saved;
+ struct libj2_j2u u;
+
+ a = (struct libj2_j2i){111, 222};
+ EXPECT(libj2_str_to_j2i("123", SIZE_MAX, NULL, NULL, NULL, &a) == 0);
+ EXPECT(libj2_j2i_eq_ji(&a, 123));
+
+ a = (struct libj2_j2i){111, 222};
+ EXPECT(libj2_str_to_j2i("+123", SIZE_MAX, NULL, NULL, NULL, &a) == 0);
+ EXPECT(libj2_j2i_eq_ji(&a, 123));
+
+ a = (struct libj2_j2i){111, 222};
+ EXPECT(libj2_str_to_j2i("-123", SIZE_MAX, NULL, NULL, NULL, &a) == 0);
+ EXPECT(libj2_j2i_eq_ji(&a, -123));
+
+ a = (struct libj2_j2i){111, 222};
+ EXPECT(libj2_str_to_j2i("--123", SIZE_MAX, NULL, NULL, NULL, &a) == 0);
+ EXPECT(libj2_j2i_eq_ji(&a, 123));
+
+ a = (struct libj2_j2i){111, 222};
+ EXPECT(libj2_str_to_j2i("-+-123", SIZE_MAX, NULL, NULL, NULL, &a) == 0);
+ EXPECT(libj2_j2i_eq_ji(&a, 123));
+
+ a = (struct libj2_j2i){111, 222};
+ EXPECT(libj2_str_to_j2i("---123", SIZE_MAX, NULL, NULL, NULL, &a) == 0);
+ EXPECT(libj2_j2i_eq_ji(&a, -123));
+
+ libj2_j2i_max(&a);
+ a_saved = a;
+ libj2_j2i_to_j2u(&a, &u);
+ a = (struct libj2_j2i){111, 222};
+ EXPECT(libj2_j2u_to_str(&u, buf, sizeof(buf), NULL) < sizeof(buf));
+ EXPECT(libj2_str_to_j2i(buf, SIZE_MAX, NULL, NULL, NULL, &a) == 0);
+ EXPECT(libj2_j2i_eq_j2i(&a, &a_saved));
+
+ libj2_j2i_min(&a);
+ a_saved = a;
+ libj2_minus_j2i_to_j2u(&a, &u);
+ a = (struct libj2_j2i){111, 222};
+ EXPECT(libj2_j2u_to_str(&u, &buf[1], sizeof(buf) - 1U, NULL) < sizeof(buf) - 1U);
+ buf[0] = '-';
+ EXPECT(libj2_str_to_j2i(buf, SIZE_MAX, NULL, NULL, NULL, &a) == 0);
+ EXPECT(libj2_j2i_eq_j2i(&a, &a_saved));
+
+ libj2_j2i_max(&a);
+ a_saved = a;
+ libj2_j2i_to_j2u(&a, &u);
+ libj2_j2u_add_ju(&u, 1);
+ a = (struct libj2_j2i){111, 222};
+ EXPECT(libj2_j2u_to_str(&u, buf, sizeof(buf), NULL) < sizeof(buf));
+ EXPECT(libj2_str_to_j2i(buf, SIZE_MAX, NULL, NULL, NULL, &a) == ERANGE);
+ EXPECT(libj2_j2i_eq_j2i(&a, &a_saved));
+
+ libj2_j2i_min(&a);
+ a_saved = a;
+ libj2_minus_j2i_to_j2u(&a, &u);
+ libj2_j2u_add_ju(&u, 1);
+ a = (struct libj2_j2i){111, 222};
+ EXPECT(libj2_j2u_to_str(&u, &buf[1], sizeof(buf) - 1U, NULL) < sizeof(buf) - 1U);
+ buf[0] = '-';
+ EXPECT(libj2_str_to_j2i(buf, SIZE_MAX, NULL, NULL, NULL, &a) == ERANGE);
+ EXPECT(libj2_j2i_eq_j2i(&a, &a_saved));
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_str_to_j2u.c b/libj2_str_to_j2u.c
index b7a1bc0..80c22c3 100644
--- a/libj2_str_to_j2u.c
+++ b/libj2_str_to_j2u.c
@@ -5,252 +5,13 @@
/* TODO Add man page */
-
-static int
-from_generic(const unsigned char *s, size_t slen, const unsigned char **end,
- const intmax_t symbols[256], unsigned radix, struct libj2_j2u *a)
-{
- const uintmax_t high_required_at = (UINTMAX_MAX - radix + 1U) / radix;
- uintmax_t radix_pow[9];
- uintmax_t v;
- size_t i, x;
-
- for (i = 0; i < slen; i++)
- if (symbols[s[i]] < 0)
- break;
- slen = i;
- *end = &s[slen];
-
- for (;;) {
- if (!slen)
- return 0;
- a->low *= (uintmax_t)radix;
- a->low += (uintmax_t)symbols[*s++];
- slen--;
- if (a->low > high_required_at) {
- if (!slen)
- return 0;
- break;
- }
- }
-
- radix_pow[0] = 1U;
- radix_pow[1] = (uintmax_t)radix;
- radix_pow[2] = (uintmax_t)radix * radix_pow[1];
- radix_pow[3] = (uintmax_t)radix * radix_pow[2];
- radix_pow[4] = (uintmax_t)radix * radix_pow[3];
- radix_pow[5] = (uintmax_t)radix * radix_pow[4];
- radix_pow[6] = (uintmax_t)radix * radix_pow[5];
- radix_pow[7] = (uintmax_t)radix * radix_pow[6];
- radix_pow[8] = (uintmax_t)radix * radix_pow[7];
-
- x = slen & 7U;
- x = x ? x : 8U;
- slen -= x;
- if (libj2_j2u_mul_ju_overflow(a, radix_pow[x]))
- return ERANGE;
- v = 0;
- switch (x) {
- while (slen) {
- slen -= 8U;
- if (libj2_j2u_mul_ju_overflow(a, radix_pow[8]))
- return ERANGE;
- v = 0;
- /* This isn't even a case, but GCC warns fall-through here */
- /* fall-through */
- case 8:
- v += (uintmax_t)symbols[*s++] * radix_pow[7]; /* fall-through */
- case 7:
- v += (uintmax_t)symbols[*s++] * radix_pow[6]; /* fall-through */
- case 6:
- v += (uintmax_t)symbols[*s++] * radix_pow[5]; /* fall-through */
- case 5:
- v += (uintmax_t)symbols[*s++] * radix_pow[4]; /* fall-through */
- case 4:
- v += (uintmax_t)symbols[*s++] * radix_pow[3]; /* fall-through */
- case 3:
- v += (uintmax_t)symbols[*s++] * radix_pow[2]; /* fall-through */
- case 2:
- v += (uintmax_t)symbols[*s++] * radix_pow[1]; /* fall-through */
- case 1:
- v += (uintmax_t)symbols[*s++];
- if (libj2_j2u_add_ju_overflow(a, v))
- return ERANGE;
- }
- }
-
- return 0;
-}
-
-
-static int
-from_power_of_two(const unsigned char *s, size_t slen, const unsigned char **end,
- const intmax_t symbols[256], unsigned radix, struct libj2_j2u *a)
-{
- uintmax_t high_required_at;
- uintmax_t v;
- unsigned shift, u, shift_mul[9];
- size_t i, x;
-
- shift = 0;
- for (u = radix; u >>= 1;)
- shift += 1U;
-
- for (i = 0; i < slen; i++)
- if (symbols[s[i]] < 0)
- break;
- slen = i;
- *end = &s[slen];
-
- high_required_at = (uintmax_t)1 << (LIBJ2_JU_BIT - shift);
- for (;;) {
- if (!slen)
- return 0;
- a->low <<= shift;
- a->low |= (uintmax_t)symbols[*s++];
- slen--;
- if (a->low >= high_required_at) {
- if (!slen)
- return 0;
- break;
- }
- }
-
- shift_mul[0] = 0U;
- shift_mul[1] = shift_mul[0] + shift;
- shift_mul[2] = shift_mul[1] + shift;
- shift_mul[3] = shift_mul[2] + shift;
- shift_mul[4] = shift_mul[3] + shift;
- shift_mul[5] = shift_mul[4] + shift;
- shift_mul[6] = shift_mul[5] + shift;
- shift_mul[7] = shift_mul[6] + shift;
- shift_mul[8] = shift_mul[7] + shift;
-
- x = slen & 7U;
- x = x ? x : 8U;
- slen -= x;
- if (libj2_j2u_lsh_overflow(a, shift_mul[x]))
- return ERANGE;
- v = 0;
- switch (x) {
- while (slen) {
- slen -= 8U;
- if (libj2_j2u_lsh_overflow(a, shift_mul[8]))
- return ERANGE;
- v = 0;
- /* This isn't even a case, but GCC warns fall-through here */
- /* fall-through */
- case 8:
- v |= (uintmax_t)symbols[*s++] << shift_mul[7]; /* fall-through */
- case 7:
- v |= (uintmax_t)symbols[*s++] << shift_mul[6]; /* fall-through */
- case 6:
- v |= (uintmax_t)symbols[*s++] << shift_mul[5]; /* fall-through */
- case 5:
- v |= (uintmax_t)symbols[*s++] << shift_mul[4]; /* fall-through */
- case 4:
- v |= (uintmax_t)symbols[*s++] << shift_mul[3]; /* fall-through */
- case 3:
- v |= (uintmax_t)symbols[*s++] << shift_mul[2]; /* fall-through */
- case 2:
- v |= (uintmax_t)symbols[*s++] << shift_mul[1]; /* fall-through */
- case 1:
- v |= (uintmax_t)symbols[*s++];
- libj2_j2u_or_ju(a, v);
- }
- }
-
- return 0;
-}
-
-
-int
-libj2_str_to_j2u(const char *str, size_t slen, char **end, const char *digits1,
- const char *digits2, struct libj2_j2u *a)
-{
- const unsigned char *s = (const unsigned char *)str;
- intmax_t symbols[256];
- unsigned i, radix = 0;
- struct libj2_j2u a_discard;
- char *end_discard;
- int r;
-
- if (!end)
- end = &end_discard;
- if (!a)
- a = &a_discard;
- libj2_j2u_zero(a);
-
- if (!s)
- slen = 0;
- if (!digits1) {
- digits1 = "0123456789";
- if (digits2)
- goto einval;
- }
-
- for (i = 0; i < sizeof(symbols) / sizeof(*symbols); i++)
- symbols[i] = -2;
- symbols[' '] = -1;
- symbols['\r'] = -1;
- symbols['\t'] = -1;
- symbols['\f'] = -1;
- symbols['\v'] = -1;
- symbols['\n'] = -1;
- symbols['+'] = -1;
- while (digits1[radix]) {
- if (symbols[(unsigned char)digits1[radix]] >= 0)
- goto einval;
- symbols[(unsigned char)digits1[radix]] = (intmax_t)radix;
- radix++;
- }
-
- if (digits2) {
- for (i = 0; digits2[i]; i++) {
- if (symbols[(unsigned char)digits2[i]] >= 256)
- goto einval;
- symbols[(unsigned char)digits2[i]] = (intmax_t)(i | 256U);
- }
- if (i != radix)
- goto einval;
- for (i = 0; digits2[i]; i++)
- symbols[(unsigned char)digits2[i]] &= 255;
- }
-
- if (radix < 2) {
- einval:
- *(const unsigned char **)(void *)end = s;
- return EINVAL;
- }
-
- for (;; slen--, s++) {
- if (!slen)
- goto einval;
- if (symbols[*s] != -1) {
- if (symbols[*s] >= 0)
- break;
- goto einval;
- }
- }
-
- while (slen && symbols[*s] == 0) {
- s++;
- slen--;
- }
-
- if ((radix & (radix - 1U)) == 0U)
- r = from_power_of_two(s, slen, (void *)end, symbols, radix, a);
- else
- r = from_generic(s, slen, (void *)end, symbols, radix, a);
- if (r == ERANGE)
- libj2_j2u_max(a);
- return r;
-}
+extern inline int libj2_str_to_j2u(const char *str, size_t slen, char **end, const char *digits1,
+ const char *digits2, struct libj2_j2u *a);
#else
-CONST int
+int
main(void)
{
/* Primarily tested in libj2_j2u_to_str.c */
@@ -283,6 +44,13 @@ main(void)
EXPECT(!strcmp(end, "10000"));
a = (struct libj2_j2u){111, 222};
+ end = NULL;
+ EXPECT(libj2_str_to_j2u("-10000", 5, &end, NULL, NULL, &a) == EINVAL);
+ EXPECT(libj2_j2u_is_zero(&a));
+ EXPECT(end);
+ EXPECT(!strcmp(end, "-10000"));
+
+ a = (struct libj2_j2u){111, 222};
EXPECT(libj2_str_to_j2u("10000", 3, NULL, NULL, NULL, &a) == 0);
EXPECT(libj2_j2u_eq_ju(&a, 100));
@@ -417,6 +185,20 @@ main(void)
EXPECT(end);
EXPECT(*end == 'B');
+ a = (struct libj2_j2u){111, 222};
+ end = NULL;
+ EXPECT(libj2_str_to_j2u("ba", SIZE_MAX, &end, "ab", "ba", &a) == EINVAL);
+ EXPECT(libj2_j2u_is_zero(&a));
+ EXPECT(end);
+ EXPECT(*end == 'b');
+
+ a = (struct libj2_j2u){111, 222};
+ end = NULL;
+ EXPECT(libj2_str_to_j2u("ba", SIZE_MAX, &end, "ab", "bc", &a) == EINVAL);
+ EXPECT(libj2_j2u_is_zero(&a));
+ EXPECT(end);
+ EXPECT(*end == 'b');
+
sprintf(buf, "%jx%jx", UINTMAX_MAX, UINTMAX_MAX);
a = (struct libj2_j2u){111, 222};
end = NULL;
diff --git a/libj2_str_to_j2u_sign.c b/libj2_str_to_j2u_sign.c
new file mode 100644
index 0000000..4ec0651
--- /dev/null
+++ b/libj2_str_to_j2u_sign.c
@@ -0,0 +1,350 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#include <errno.h>
+#ifndef TEST
+
+/* TODO Add man page */
+
+
+static int
+from_generic(const unsigned char *s, size_t slen, const unsigned char **end,
+ const intmax_t symbols[256], unsigned radix, struct libj2_j2u *a)
+{
+ const uintmax_t high_required_at = (UINTMAX_MAX - radix + 1U) / radix;
+ uintmax_t radix_pow[9];
+ uintmax_t v;
+ size_t i, x;
+
+ for (i = 0; i < slen; i++)
+ if (symbols[s[i]] < 0)
+ break;
+ slen = i;
+ *end = &s[slen];
+
+ for (;;) {
+ if (!slen)
+ return 0;
+ a->low *= (uintmax_t)radix;
+ a->low += (uintmax_t)symbols[*s++];
+ slen--;
+ if (a->low > high_required_at) {
+ if (!slen)
+ return 0;
+ break;
+ }
+ }
+
+ radix_pow[0] = 1U;
+ radix_pow[1] = (uintmax_t)radix;
+ radix_pow[2] = (uintmax_t)radix * radix_pow[1];
+ radix_pow[3] = (uintmax_t)radix * radix_pow[2];
+ radix_pow[4] = (uintmax_t)radix * radix_pow[3];
+ radix_pow[5] = (uintmax_t)radix * radix_pow[4];
+ radix_pow[6] = (uintmax_t)radix * radix_pow[5];
+ radix_pow[7] = (uintmax_t)radix * radix_pow[6];
+ radix_pow[8] = (uintmax_t)radix * radix_pow[7];
+
+ x = slen & 7U;
+ x = x ? x : 8U;
+ slen -= x;
+ if (libj2_j2u_mul_ju_overflow(a, radix_pow[x]))
+ return ERANGE;
+ v = 0;
+ switch (x) {
+ while (slen) {
+ slen -= 8U;
+ if (libj2_j2u_mul_ju_overflow(a, radix_pow[8]))
+ return ERANGE;
+ v = 0;
+ /* This isn't even a case, but GCC warns fall-through here */
+ /* fall-through */
+ case 8:
+ v += (uintmax_t)symbols[*s++] * radix_pow[7]; /* fall-through */
+ case 7:
+ v += (uintmax_t)symbols[*s++] * radix_pow[6]; /* fall-through */
+ case 6:
+ v += (uintmax_t)symbols[*s++] * radix_pow[5]; /* fall-through */
+ case 5:
+ v += (uintmax_t)symbols[*s++] * radix_pow[4]; /* fall-through */
+ case 4:
+ v += (uintmax_t)symbols[*s++] * radix_pow[3]; /* fall-through */
+ case 3:
+ v += (uintmax_t)symbols[*s++] * radix_pow[2]; /* fall-through */
+ case 2:
+ v += (uintmax_t)symbols[*s++] * radix_pow[1]; /* fall-through */
+ case 1:
+ v += (uintmax_t)symbols[*s++];
+ if (libj2_j2u_add_ju_overflow(a, v))
+ return ERANGE;
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+from_power_of_two(const unsigned char *s, size_t slen, const unsigned char **end,
+ const intmax_t symbols[256], unsigned radix, struct libj2_j2u *a)
+{
+ uintmax_t high_required_at;
+ uintmax_t v;
+ unsigned shift, u, shift_mul[9];
+ size_t i, x;
+
+ shift = 0;
+ for (u = radix; u >>= 1;)
+ shift += 1U;
+
+ for (i = 0; i < slen; i++)
+ if (symbols[s[i]] < 0)
+ break;
+ slen = i;
+ *end = &s[slen];
+
+ high_required_at = (uintmax_t)1 << (LIBJ2_JU_BIT - shift);
+ for (;;) {
+ if (!slen)
+ return 0;
+ a->low <<= shift;
+ a->low |= (uintmax_t)symbols[*s++];
+ slen--;
+ if (a->low >= high_required_at) {
+ if (!slen)
+ return 0;
+ break;
+ }
+ }
+
+ shift_mul[0] = 0U;
+ shift_mul[1] = shift_mul[0] + shift;
+ shift_mul[2] = shift_mul[1] + shift;
+ shift_mul[3] = shift_mul[2] + shift;
+ shift_mul[4] = shift_mul[3] + shift;
+ shift_mul[5] = shift_mul[4] + shift;
+ shift_mul[6] = shift_mul[5] + shift;
+ shift_mul[7] = shift_mul[6] + shift;
+ shift_mul[8] = shift_mul[7] + shift;
+
+ x = slen & 7U;
+ x = x ? x : 8U;
+ slen -= x;
+ if (libj2_j2u_lsh_overflow(a, shift_mul[x]))
+ return ERANGE;
+ v = 0;
+ switch (x) {
+ while (slen) {
+ slen -= 8U;
+ if (libj2_j2u_lsh_overflow(a, shift_mul[8]))
+ return ERANGE;
+ v = 0;
+ /* This isn't even a case, but GCC warns fall-through here */
+ /* fall-through */
+ case 8:
+ v |= (uintmax_t)symbols[*s++] << shift_mul[7]; /* fall-through */
+ case 7:
+ v |= (uintmax_t)symbols[*s++] << shift_mul[6]; /* fall-through */
+ case 6:
+ v |= (uintmax_t)symbols[*s++] << shift_mul[5]; /* fall-through */
+ case 5:
+ v |= (uintmax_t)symbols[*s++] << shift_mul[4]; /* fall-through */
+ case 4:
+ v |= (uintmax_t)symbols[*s++] << shift_mul[3]; /* fall-through */
+ case 3:
+ v |= (uintmax_t)symbols[*s++] << shift_mul[2]; /* fall-through */
+ case 2:
+ v |= (uintmax_t)symbols[*s++] << shift_mul[1]; /* fall-through */
+ case 1:
+ v |= (uintmax_t)symbols[*s++];
+ libj2_j2u_or_ju(a, v);
+ }
+ }
+
+ return 0;
+}
+
+
+int
+libj2_str_to_j2u_sign(const char *str, size_t slen, char **end, const char *digits1,
+ const char *digits2, struct libj2_j2u *a, int *negative)
+{
+ const unsigned char *s = (const unsigned char *)str;
+ intmax_t symbols[256];
+ unsigned i, radix = 0;
+ struct libj2_j2u a_discard;
+ char *end_discard;
+ int r;
+
+ if (negative)
+ *negative = 0;
+
+ if (!end)
+ end = &end_discard;
+ if (!a)
+ a = &a_discard;
+ libj2_j2u_zero(a);
+
+ if (!s)
+ slen = 0;
+ if (!digits1) {
+ digits1 = "0123456789";
+ if (digits2)
+ goto einval;
+ }
+
+ for (i = 0; i < sizeof(symbols) / sizeof(*symbols); i++)
+ symbols[i] = -2;
+ symbols[' '] = -1;
+ symbols['\r'] = -1;
+ symbols['\t'] = -1;
+ symbols['\f'] = -1;
+ symbols['\v'] = -1;
+ symbols['\n'] = -1;
+ symbols['+'] = -1;
+ if (negative)
+ symbols['-'] = -3;
+ while (digits1[radix]) {
+ if (symbols[(unsigned char)digits1[radix]] >= 0)
+ goto einval;
+ symbols[(unsigned char)digits1[radix]] = (intmax_t)radix;
+ radix++;
+ }
+
+ if (digits2) {
+ for (i = 0; digits2[i]; i++) {
+ if (symbols[(unsigned char)digits2[i]] >= 256)
+ goto einval;
+ else if (symbols[(unsigned char)digits2[i]] >= 0)
+ if (symbols[(unsigned char)digits2[i]] != (intmax_t)i)
+ goto einval;
+ symbols[(unsigned char)digits2[i]] = (intmax_t)(i | 256U);
+ }
+ if (i != radix)
+ goto einval;
+ for (i = 0; digits2[i]; i++)
+ symbols[(unsigned char)digits2[i]] &= 255;
+ }
+
+ if (radix < 2) {
+ einval:
+ *(const unsigned char **)(void *)end = s;
+ return EINVAL;
+ }
+
+ for (;; slen--, s++) {
+ if (!slen)
+ goto einval;
+ if (symbols[*s] == -3) {
+ *negative ^= 1;
+ } else if (symbols[*s] != -1) {
+ if (symbols[*s] >= 0)
+ break;
+ goto einval;
+ }
+ }
+ if (symbols[(unsigned char)'-'] == -3)
+ symbols[(unsigned char)'-'] = -1;
+
+ while (slen && symbols[*s] == 0) {
+ s++;
+ slen--;
+ }
+
+ if ((radix & (radix - 1U)) == 0U)
+ r = from_power_of_two(s, slen, (void *)end, symbols, radix, a);
+ else
+ r = from_generic(s, slen, (void *)end, symbols, radix, a);
+ if (r == ERANGE)
+ libj2_j2u_max(a);
+ return r;
+}
+
+
+#else
+
+int
+main(void)
+{
+ /* Primarily tested via libj2_str_to_j2u */
+
+ struct libj2_j2u a;
+ int neg;
+
+ EXPECT(libj2_str_to_j2u_sign("-1", SIZE_MAX, NULL, NULL, NULL, &a, NULL) == EINVAL);
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign("1", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 0);
+ EXPECT(libj2_j2u_eq_ju(&a, 1));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign("-1", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 1);
+ EXPECT(libj2_j2u_eq_ju(&a, 1));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign("0", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 0);
+ EXPECT(libj2_j2u_eq_ju(&a, 0));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign("-0", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 1);
+ EXPECT(libj2_j2u_eq_ju(&a, 0));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign("--1", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 0);
+ EXPECT(libj2_j2u_eq_ju(&a, 1));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign("---1", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 1);
+ EXPECT(libj2_j2u_eq_ju(&a, 1));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign(" - - - 123", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 1);
+ EXPECT(libj2_j2u_eq_ju(&a, 123));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign("-", SIZE_MAX, NULL, "*+-", NULL, &a, &neg) == 0);
+ EXPECT(neg == 0);
+ EXPECT(libj2_j2u_eq_ju(&a, 2));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign("-+1", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 1);
+ EXPECT(libj2_j2u_eq_ju(&a, 1));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign("+-1", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 1);
+ EXPECT(libj2_j2u_eq_ju(&a, 1));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign("- 1", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 1);
+ EXPECT(libj2_j2u_eq_ju(&a, 1));
+
+ a = (struct libj2_j2u){111, 222};
+ neg = 333;
+ EXPECT(libj2_str_to_j2u_sign(" -1", SIZE_MAX, NULL, NULL, NULL, &a, &neg) == 0);
+ EXPECT(neg == 1);
+ EXPECT(libj2_j2u_eq_ju(&a, 1));
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_vmax_j2i.c b/libj2_vmax_j2i.c
new file mode 100644
index 0000000..f3fd4f3
--- /dev/null
+++ b/libj2_vmax_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_vmax_j2i(struct libj2_j2i *a, va_list args);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested via libj2_max_j2i */
+
+#endif
diff --git a/libj2_vmax_j2i_return.c b/libj2_vmax_j2i_return.c
new file mode 100644
index 0000000..f1a8ca6
--- /dev/null
+++ b/libj2_vmax_j2i_return.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline const struct libj2_j2i *libj2_vmax_j2i_return(const struct libj2_j2i *a, va_list args);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested via libj2_max_j2i_return */
+
+#endif
diff --git a/libj2_vmax_j2i_to_j2i.c b/libj2_vmax_j2i_to_j2i.c
new file mode 100644
index 0000000..712cb9f
--- /dev/null
+++ b/libj2_vmax_j2i_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_vmax_j2i_to_j2i(const struct libj2_j2i *a, va_list args);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested via libj2_vmax_j2i_to_j2i */
+
+#endif
diff --git a/libj2_vmin_j2i.c b/libj2_vmin_j2i.c
new file mode 100644
index 0000000..9f03fcb
--- /dev/null
+++ b/libj2_vmin_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_vmin_j2i(struct libj2_j2i *a, va_list args);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested via libj2_min_j2i */
+
+#endif
diff --git a/libj2_vmin_j2i_return.c b/libj2_vmin_j2i_return.c
new file mode 100644
index 0000000..6592577
--- /dev/null
+++ b/libj2_vmin_j2i_return.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline const struct libj2_j2i *libj2_vmin_j2i_return(const struct libj2_j2i *a, va_list args);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested via libj2_min_j2i_return */
+
+#endif
diff --git a/libj2_vmin_j2i_to_j2i.c b/libj2_vmin_j2i_to_j2i.c
new file mode 100644
index 0000000..3ab12d5
--- /dev/null
+++ b/libj2_vmin_j2i_to_j2i.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_vmin_j2i_to_j2i(const struct libj2_j2i *a, va_list args);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested via libj2_vmin_j2i_to_j2i */
+
+#endif