aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2025-12-05 20:43:23 +0100
committerMattias Andrée <m@maandree.se>2025-12-05 20:48:59 +0100
commitf05fdeb727a2fc8052900a159c225d328d603acc (patch)
tree9c56ef8fea9964decd3c24f5b03f1341266f779b
parentFirst commit (diff)
downloadlibj2-f05fdeb727a2fc8052900a159c225d328d603acc.tar.gz
libj2-f05fdeb727a2fc8052900a159c225d328d603acc.tar.bz2
libj2-f05fdeb727a2fc8052900a159c225d328d603acc.tar.xz
Second commit
Signed-off-by: Mattias Andrée <m@maandree.se>
-rw-r--r--Makefile49
-rw-r--r--libj2.h12
-rw-r--r--libj2/bit-scanning.h457
-rw-r--r--libj2/bitwise-logic.h593
-rw-r--r--libj2/constants.h6
-rw-r--r--libj2/division.h4
-rw-r--r--libj2/signum.h4
-rw-r--r--libj2/unsigned-comparsion.h46
-rw-r--r--libj2_cfs_j2u.c116
-rw-r--r--libj2_cfs_j2u_to_j2u.c13
-rw-r--r--libj2_clo_j2u.c64
-rw-r--r--libj2_cls_j2u.c119
-rw-r--r--libj2_cls_j2u_to_j2u.c13
-rw-r--r--libj2_clz_j2u.c61
-rw-r--r--libj2_co_j2u.c95
-rw-r--r--libj2_cto_j2u.c62
-rw-r--r--libj2_ctz_j2u.c61
-rw-r--r--libj2_cz_j2u.c95
-rw-r--r--libj2_ffc_j2u.c125
-rw-r--r--libj2_ffs_j2u.c110
-rw-r--r--libj2_flc_j2u.c125
-rw-r--r--libj2_fls_j2u.c110
-rw-r--r--libj2_j2u_and_bit.c13
-rw-r--r--libj2_j2u_and_bit_to_j2u.c72
-rw-r--r--libj2_j2u_has_high_ju.c40
-rw-r--r--libj2_j2u_has_j2u.c36
-rw-r--r--libj2_j2u_has_ju.c40
-rw-r--r--libj2_j2u_if_bit.c13
-rw-r--r--libj2_j2u_if_bit_to_j2u.c72
-rw-r--r--libj2_j2u_imply_bit.c13
-rw-r--r--libj2_j2u_imply_bit_to_j2u.c72
-rw-r--r--libj2_j2u_nand_bit.c13
-rw-r--r--libj2_j2u_nand_bit_to_j2u.c72
-rw-r--r--libj2_j2u_nif_bit.c13
-rw-r--r--libj2_j2u_nif_bit_to_j2u.c72
-rw-r--r--libj2_j2u_nimply_bit.c13
-rw-r--r--libj2_j2u_nimply_bit_to_j2u.c72
-rw-r--r--libj2_j2u_nor_bit.c13
-rw-r--r--libj2_j2u_nor_bit_to_j2u.c72
-rw-r--r--libj2_j2u_or_bit.c13
-rw-r--r--libj2_j2u_or_bit_to_j2u.c72
-rw-r--r--libj2_j2u_test_high_ju.c2
-rw-r--r--libj2_j2u_test_j2u.c2
-rw-r--r--libj2_j2u_test_ju.c2
-rw-r--r--libj2_j2u_xnor_bit.c13
-rw-r--r--libj2_j2u_xnor_bit_to_j2u.c72
-rw-r--r--libj2_j2u_xor_bit.c13
-rw-r--r--libj2_j2u_xor_bit_to_j2u.c72
-rw-r--r--libj2_kfs_j2u.c13
-rw-r--r--libj2_kfs_j2u_to_j2u.c13
-rw-r--r--libj2_kls_j2u.c13
-rw-r--r--libj2_kls_j2u_to_j2u.c13
-rw-r--r--libj2_parity_j2u.c95
-rw-r--r--libj2_sfc_j2u.c13
-rw-r--r--libj2_sfc_j2u_to_j2u.c13
-rw-r--r--libj2_slc_j2u.c13
-rw-r--r--libj2_slc_j2u_to_j2u.c13
57 files changed, 3475 insertions, 36 deletions
diff --git a/Makefile b/Makefile
index 482e2b3..bd51b5c 100644
--- a/Makefile
+++ b/Makefile
@@ -203,7 +203,53 @@ OBJ =\
libj2_vmax_j2u_to_j2u.o\
libj2_vmin_j2u.o\
libj2_vmin_j2u_return.o\
- libj2_vmin_j2u_to_j2u.o
+ libj2_vmin_j2u_to_j2u.o\
+ libj2_j2u_and_bit_to_j2u.o\
+ libj2_j2u_and_bit.o\
+ libj2_j2u_or_bit_to_j2u.o\
+ libj2_j2u_or_bit.o\
+ libj2_j2u_xor_bit_to_j2u.o\
+ libj2_j2u_xor_bit.o\
+ libj2_j2u_if_bit_to_j2u.o\
+ libj2_j2u_if_bit.o\
+ libj2_j2u_imply_bit_to_j2u.o\
+ libj2_j2u_imply_bit.o\
+ libj2_j2u_nand_bit_to_j2u.o\
+ libj2_j2u_nand_bit.o\
+ libj2_j2u_nor_bit_to_j2u.o\
+ libj2_j2u_nor_bit.o\
+ libj2_j2u_xnor_bit_to_j2u.o\
+ libj2_j2u_xnor_bit.o\
+ libj2_j2u_nif_bit_to_j2u.o\
+ libj2_j2u_nif_bit.o\
+ libj2_j2u_nimply_bit_to_j2u.o\
+ libj2_j2u_nimply_bit.o\
+ libj2_clz_j2u.o\
+ libj2_clo_j2u.o\
+ libj2_ctz_j2u.o\
+ libj2_cto_j2u.o\
+ libj2_co_j2u.o\
+ libj2_cz_j2u.o\
+ libj2_ffs_j2u.o\
+ libj2_ffc_j2u.o\
+ libj2_fls_j2u.o\
+ libj2_flc_j2u.o\
+ libj2_parity_j2u.o\
+ libj2_kfs_j2u.o\
+ libj2_kfs_j2u_to_j2u.o\
+ libj2_kls_j2u.o\
+ libj2_kls_j2u_to_j2u.o\
+ libj2_cfs_j2u.o\
+ libj2_cfs_j2u_to_j2u.o\
+ libj2_cls_j2u.o\
+ libj2_cls_j2u_to_j2u.o\
+ libj2_sfc_j2u.o\
+ libj2_sfc_j2u_to_j2u.o\
+ libj2_slc_j2u.o\
+ libj2_slc_j2u_to_j2u.o\
+ libj2_j2u_has_j2u.o\
+ libj2_j2u_has_ju.o\
+ libj2_j2u_has_high_ju.o
SUBHDR =\
libj2/constants.h\
@@ -212,6 +258,7 @@ SUBHDR =\
libj2/unsigned-comparsion.h\
libj2/bitwise-logic.h\
libj2/bit-shifting.h\
+ libj2/bit-scanning.h\
libj2/sign-shifting.h\
libj2/addition.h\
libj2/subtraction.h\
diff --git a/libj2.h b/libj2.h
index 0c3d882..aa1747f 100644
--- a/libj2.h
+++ b/libj2.h
@@ -9,10 +9,20 @@
#if 1
# if defined(__GNUC__)
# define LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_
+# if !defined(__clang__)
+# define LIBJ2_USE_GCC_PARITYG_
+# endif
# endif
#endif
+#if defined(__GNUC__)
+# define LIBJ2_PURE_ __attribute__((__pure__))
+#else
+# define LIBJ2_PURE_
+#endif
+
+
/**
* The number of bits in an `uintmax_t`
*/
@@ -48,6 +58,7 @@ struct libj2_j2u {
#include "libj2/unsigned-comparsion.h"
#include "libj2/bitwise-logic.h"
#include "libj2/bit-shifting.h"
+#include "libj2/bit-scanning.h"
#include "libj2/sign-shifting.h"
#include "libj2/addition.h"
#include "libj2/subtraction.h"
@@ -58,5 +69,6 @@ struct libj2_j2u {
#if defined(LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_)
# undef LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_
#endif
+#undef LIBJ2_PURE_
#endif
diff --git a/libj2/bit-scanning.h b/libj2/bit-scanning.h
new file mode 100644
index 0000000..963f2e2
--- /dev/null
+++ b/libj2/bit-scanning.h
@@ -0,0 +1,457 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBJ2_H
+# error Do not include this header directly, include <libj2.h> instead
+#endif
+
+
+/**
+ * Get the number of leading zeroes in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return The number of zeroes after the most signficant set
+ * bit in `a`, `LIBJ2_J2U_BIT` if `a` has the value 0
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_clz_j2u(const struct libj2_j2u *a)
+{
+ uintmax_t x;
+ unsigned r, n;
+ if (a->high) {
+ x = a->high;
+ r = 0;
+ } else if (a->low) {
+ x = a->low;
+ r = LIBJ2_JU_BIT;
+ } else {
+ return LIBJ2_J2U_BIT;
+ }
+#if defined(LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_)
+ n = (unsigned)__builtin_clzg(x);
+ return r + n;
+#else
+ for (n = LIBJ2_JU_BIT; !((x >> --n) & 1U); r++);
+ return r;
+#endif
+}
+
+
+/**
+ * Get the number of leading ones in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return The number of ones after the most signficant cleared
+ * bit in `a`, `LIBJ2_J2U_BIT` if all bits in `a` are set
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_clo_j2u(const struct libj2_j2u *a)
+{
+ return libj2_clz_j2u(&(struct libj2_j2u){.high = ~a->high, .low = ~a->low});
+}
+
+
+/**
+ * Get the number of trailing zeroes in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return The number of zeroes before the least signficant set
+ * bit in `a`, `LIBJ2_J2U_BIT` if `a` has the value 0
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_ctz_j2u(const struct libj2_j2u *a)
+{
+ uintmax_t x;
+ unsigned r, n;
+ if (a->low) {
+ x = a->low;
+ r = 0;
+ } else if (a->high) {
+ x = a->high;
+ r = LIBJ2_JU_BIT;
+ } else {
+ return LIBJ2_J2U_BIT;
+ }
+#if defined(LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_)
+ n = (unsigned)__builtin_ctzg(x);
+#else
+ for (n = 0; !((x >> n) & 1U); n++);
+#endif
+ return r + n;
+}
+
+
+/**
+ * Get the number of trailing ones in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return The number of ones before the leadt signficant cleared
+ * bit in `a`, `LIBJ2_J2U_BIT` if all bits in `a` are set
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_cto_j2u(const struct libj2_j2u *a)
+{
+ return libj2_ctz_j2u(&(struct libj2_j2u){.high = ~a->high, .low = ~a->low});
+}
+
+
+/**
+ * Count the number of set bits in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return The number of set bits in `a`
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_co_j2u(const struct libj2_j2u *a)
+{
+#if defined(LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_)
+ return (unsigned)__builtin_popcountg(a->high) + (unsigned)__builtin_popcountg(a->low);
+#else
+ uintmax_t x, r = 0;
+#if UINT64_MAX < UINTMAX_MAX
+ uintmax_t y;
+ for (y = a->low; y; y >>= 64) {
+ x = y & UINT64_MAX;
+#else
+ x = a->high;
+#endif
+ x = (x & UINTMAX_C(0x5555555555555555)) + ((x >> 1) & UINTMAX_C(0x5555555555555555));
+ x = (x & UINTMAX_C(0x3333333333333333)) + ((x >> 2) & UINTMAX_C(0x3333333333333333));
+ x = (x & UINTMAX_C(0x0F0F0F0F0F0F0F0F)) + ((x >> 4) & UINTMAX_C(0x0F0F0F0F0F0F0F0F));
+ x = (x & UINTMAX_C(0x00FF00FF00FF00FF)) + ((x >> 8) & UINTMAX_C(0x00FF00FF00FF00FF));
+ x = (x & UINTMAX_C(0x0000FFFF0000FFFF)) + ((x >> 16) & UINTMAX_C(0x0000FFFF0000FFFF));
+ x = (x & UINTMAX_C(0x00000000FFFFFFFF)) + ((x >> 32) & UINTMAX_C(0x00000000FFFFFFFF));
+ r += x;
+#if UINT64_MAX < UINTMAX_MAX
+ }
+#endif
+#if UINT64_MAX < UINTMAX_MAX
+ for (y = a->low; y; y >>= 64) {
+ x = y & UINT64_MAX;
+#else
+ x = a->low;
+#endif
+ x = (x & UINTMAX_C(0x5555555555555555)) + ((x >> 1) & UINTMAX_C(0x5555555555555555));
+ x = (x & UINTMAX_C(0x3333333333333333)) + ((x >> 2) & UINTMAX_C(0x3333333333333333));
+ x = (x & UINTMAX_C(0x0F0F0F0F0F0F0F0F)) + ((x >> 4) & UINTMAX_C(0x0F0F0F0F0F0F0F0F));
+ x = (x & UINTMAX_C(0x00FF00FF00FF00FF)) + ((x >> 8) & UINTMAX_C(0x00FF00FF00FF00FF));
+ x = (x & UINTMAX_C(0x0000FFFF0000FFFF)) + ((x >> 16) & UINTMAX_C(0x0000FFFF0000FFFF));
+ x = (x & UINTMAX_C(0x00000000FFFFFFFF)) + ((x >> 32) & UINTMAX_C(0x00000000FFFFFFFF));
+ r += x;
+#if UINT64_MAX < UINTMAX_MAX
+ }
+#endif
+ return (unsigned)r;
+#endif
+}
+
+
+/**
+ * Count the number of cleared bits in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return The number of cleared bits in `a`
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_cz_j2u(const struct libj2_j2u *a)
+{
+ return LIBJ2_J2U_BIT - libj2_co_j2u(a);
+}
+
+
+/**
+ * Get the index of the least significant set
+ * bit in an unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return The index, counting from index one
+ * at the least significant bit, of the
+ * least significant set bit in `a`, or
+ * 0 if no bit is set
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_ffs_j2u(const struct libj2_j2u *a)
+{
+ unsigned r = libj2_ctz_j2u(a);
+ return r == LIBJ2_J2U_BIT ? 0U : r + 1U;
+}
+
+
+/**
+ * Get the index of the least significant cleared
+ * bit in an unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return The index, counting from index one
+ * at the least significant bit, of the
+ * least significant cleared bit in `a`,
+ * or 0 if no bit is cleared
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_ffc_j2u(const struct libj2_j2u *a)
+{
+ return libj2_ffs_j2u(&(struct libj2_j2u){.high = ~a->high, .low = ~a->low});
+}
+
+
+/**
+ * Get the index of the most significant set
+ * bit in an unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return The index, counting from index one
+ * at the least significant bit, of the
+ * most significant set bit in `a`,
+ * or 0 if no bit is set
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_fls_j2u(const struct libj2_j2u *a)
+{
+ unsigned r = libj2_clz_j2u(a);
+ return LIBJ2_J2U_BIT - r;
+}
+
+
+/**
+ * Get the index of the most significant cleared
+ * bit in an unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return The index, counting from index one
+ * at the least significant bit, of the
+ * most significant cleared bit in `a`,
+ * or 0 if no bit is cleared
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_flc_j2u(const struct libj2_j2u *a)
+{
+ return libj2_fls_j2u(&(struct libj2_j2u){.high = ~a->high, .low = ~a->low});
+}
+
+
+/**
+ * Calculate the parity of the bits in
+ * an unsigned double-max precision integer
+ *
+ * @param a The integer to inspect
+ * @return 1 if the number of set bits in `a`
+ * is odd, 0 otherwise (if even)
+ */
+LIBJ2_PURE_ inline unsigned
+libj2_parity_j2u(const struct libj2_j2u *a)
+{
+#if defined(LIBJ2_USE_GCC_PARITYG_)
+ return (unsigned)(__builtin_parityg(a->high) ^ __builtin_parityg(a->low));
+#else
+ unsigned s = LIBJ2_JU_BIT >> 1;
+ uintmax_t x = a->high ^ a->low;
+ uintmax_t mask = ((uintmax_t)1 << s) - 1U;
+ while (s) {
+ x = (x ^ (x >> s)) & mask;
+ mask >>= s >>= 1;
+ }
+ return (unsigned)x;
+#endif
+}
+
+
+/**
+ * Clears all bits in an unsigned double-max precision
+ * integer except the least significant set bit
+ *
+ * @param a The integer to modify; will be updated
+ */
+inline void
+libj2_kfs_j2u(struct libj2_j2u *a)
+{
+ unsigned i = libj2_ffs_j2u(a);
+ if (i)
+ libj2_j2u_and_bit(a, i - 1U);
+}
+
+
+/**
+ * Clears all bits in an unsigned double-max precision
+ * integer except the least significant set bit
+ *
+ * @param a The integer to modify
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_kfs_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res)
+{
+ unsigned i = libj2_ffs_j2u(a);
+ if (i)
+ libj2_j2u_and_bit_to_j2u(a, i - 1U, res);
+ else
+ *res = *a;
+}
+
+
+/**
+ * Clears all bits in an unsigned double-max precision
+ * integer except the most significant set bit
+ *
+ * @param a The integer to modify; will be modified
+ */
+inline void
+libj2_kls_j2u(struct libj2_j2u *a)
+{
+ unsigned i = libj2_fls_j2u(a);
+ if (i)
+ libj2_j2u_and_bit(a, i - 1U);
+}
+
+
+/**
+ * Clears all bits in an unsigned double-max precision
+ * integer except the most significant set bit
+ *
+ * @param a The integer to modify
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_kls_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res)
+{
+ unsigned i = libj2_fls_j2u(a);
+ if (i)
+ libj2_j2u_and_bit_to_j2u(a, i - 1U, res);
+ else
+ *res = *a;
+}
+
+
+/**
+ * Clear the least significant set bit in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to modify; will be updated
+ */
+inline void
+libj2_cfs_j2u(struct libj2_j2u *a)
+{
+ unsigned i = libj2_ffs_j2u(a);
+ if (i)
+ libj2_j2u_xor_bit(a, i - 1U);
+}
+
+
+/**
+ * Clear the least significant set bit in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to modify
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_cfs_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res)
+{
+ unsigned i = libj2_ffs_j2u(a);
+ if (i)
+ libj2_j2u_xor_bit_to_j2u(a, i - 1U, res);
+ else
+ *res = *a;
+}
+
+
+/**
+ * Clear the most significant set bit in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to modify; will be modified
+ */
+inline void
+libj2_cls_j2u(struct libj2_j2u *a)
+{
+ unsigned i = libj2_fls_j2u(a);
+ if (i)
+ libj2_j2u_xor_bit(a, i - 1U);
+}
+
+
+/**
+ * Clear the most significant set bit in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to modify
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_cls_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res)
+{
+ unsigned i = libj2_fls_j2u(a);
+ if (i)
+ libj2_j2u_xor_bit_to_j2u(a, i - 1U, res);
+ else
+ *res = *a;
+}
+
+
+/**
+ * Set the least significant cleared bit in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to modify; will be updated
+ */
+inline void
+libj2_sfc_j2u(struct libj2_j2u *a)
+{
+ unsigned i = libj2_ffc_j2u(a);
+ if (i)
+ libj2_j2u_or_bit(a, i - 1U);
+}
+
+
+/**
+ * Set the least significant cleared bit in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to modify
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_sfc_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res)
+{
+ unsigned i = libj2_ffc_j2u(a);
+ if (i)
+ libj2_j2u_or_bit_to_j2u(a, i - 1U, res);
+ else
+ *res = *a;
+}
+
+
+/**
+ * Set the most significant cleared bit in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to modify; will be modified
+ */
+inline void
+libj2_slc_j2u(struct libj2_j2u *a)
+{
+ unsigned i = libj2_flc_j2u(a);
+ if (i)
+ libj2_j2u_or_bit(a, i - 1U);
+}
+
+
+/**
+ * Set the most significant cleared bit in an
+ * unsigned double-max precision integer
+ *
+ * @param a The integer to modify
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_slc_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res)
+{
+ unsigned i = libj2_flc_j2u(a);
+ if (i)
+ libj2_j2u_or_bit_to_j2u(a, i - 1U, res);
+ else
+ *res = *a;
+}
diff --git a/libj2/bitwise-logic.h b/libj2/bitwise-logic.h
index 6ec362e..288994b 100644
--- a/libj2/bitwise-logic.h
+++ b/libj2/bitwise-logic.h
@@ -13,7 +13,7 @@
* 0 for the least significant bit
* @return 1 if the bit is set, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_test_bit(const struct libj2_j2u *a, unsigned b)
{
if (b >= LIBJ2_J2U_BIT)
@@ -34,7 +34,7 @@ libj2_j2u_test_bit(const struct libj2_j2u *a, unsigned b)
* @return 1 if the two integers have set bits
* in common, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_test_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
{
return (a->high & b->high) || (a->low & b->low);
@@ -51,7 +51,7 @@ libj2_j2u_test_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
* @return 1 if the two integers have set bits
* in common, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_test_ju(const struct libj2_j2u *a, uintmax_t b)
{
return !!(a->low & b);
@@ -68,7 +68,7 @@ libj2_j2u_test_ju(const struct libj2_j2u *a, uintmax_t b)
* @return 1 if high part of `a` have set bits
* in common with `b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_test_high_ju(const struct libj2_j2u *a, uintmax_t b)
{
return !!(a->high & b);
@@ -978,3 +978,588 @@ libj2_ju_nif_j2u_to_j2u(uintmax_t a, const struct libj2_j2u *b, struct libj2_j2u
{
libj2_j2u_nimply_ju_to_j2u(b, a, res);
}
+
+
+/**
+ * Calculate the bitwise AND of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This clears all but the specified bit
+ *
+ * @param a The left-hand integer
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_j2u_and_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res)
+{
+ if (b >= LIBJ2_J2U_BIT) {
+ res->high = 0;
+ res->low = 0;
+ } else if (b >= LIBJ2_JU_BIT) {
+ res->high = a->high & ((uintmax_t)1 << (b - LIBJ2_JU_BIT));
+ res->low = 0;
+ } else {
+ res->high = 0;
+ res->low = a->low & ((uintmax_t)1 << b);
+ }
+}
+
+
+/**
+ * Calculate the bitwise AND of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This clears all but the specified bit
+ *
+ * @param a The left-hand integer, also used as the
+ * output parameter for the result
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ */
+inline void
+libj2_j2u_and_bit(struct libj2_j2u *a, unsigned b)
+{
+ libj2_j2u_and_bit_to_j2u(a, b, a);
+}
+
+
+/**
+ * Calculate the bitwise OR of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This sets the specified bit
+ *
+ * @param a The left-hand integer
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_j2u_or_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res)
+{
+ if (b >= LIBJ2_J2U_BIT) {
+ res->high = a->high;
+ res->low = a->low;
+ } else if (b >= LIBJ2_JU_BIT) {
+ res->high = a->high | ((uintmax_t)1 << (b - LIBJ2_JU_BIT));
+ res->low = a->low;
+ } else {
+ res->high = a->high;
+ res->low = a->low | ((uintmax_t)1 << b);
+ }
+}
+
+
+/**
+ * Calculate the bitwise OR of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This sets the specified bit
+ *
+ * @param a The left-hand integer, also used as the
+ * output parameter for the result
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ */
+inline void
+libj2_j2u_or_bit(struct libj2_j2u *a, unsigned b)
+{
+ if (b >= LIBJ2_JU_BIT) {
+ if (b >= LIBJ2_J2U_BIT)
+ return;
+ a->high |= (uintmax_t)1 << (b - LIBJ2_JU_BIT);
+ } else {
+ a->low |= (uintmax_t)1 << b;
+ }
+}
+
+
+/**
+ * Calculate the bitwise XOR of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This flips the specified bit
+ *
+ * @param a The left-hand integer
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_j2u_xor_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res)
+{
+ if (b >= LIBJ2_J2U_BIT) {
+ res->high = a->high;
+ res->low = a->low;
+ } else if (b >= LIBJ2_JU_BIT) {
+ res->high = a->high ^ ((uintmax_t)1 << (b - LIBJ2_JU_BIT));
+ res->low = a->low;
+ } else {
+ res->high = a->high;
+ res->low = a->low ^ ((uintmax_t)1 << b);
+ }
+}
+
+
+/**
+ * Calculate the bitwise XOR of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This flips the specified bit
+ *
+ * @param a The left-hand integer, also used as the
+ * output parameter for the result
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ */
+inline void
+libj2_j2u_xor_bit(struct libj2_j2u *a, unsigned b)
+{
+ if (b >= LIBJ2_JU_BIT) {
+ if (b >= LIBJ2_J2U_BIT)
+ return;
+ a->high ^= (uintmax_t)1 << (b - LIBJ2_JU_BIT);
+ } else {
+ a->low ^= (uintmax_t)1 << b;
+ }
+}
+
+
+/**
+ * Calculate the bitwise IF of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This sets all but the specified bit
+ *
+ * @param a The left-hand integer
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_j2u_if_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res)
+{
+ if (b >= LIBJ2_J2U_BIT) {
+ res->high = UINTMAX_MAX;
+ res->low = UINTMAX_MAX;
+ } else if (b >= LIBJ2_JU_BIT) {
+ res->high = a->high | ~((uintmax_t)1 << (b - LIBJ2_JU_BIT));
+ res->low = UINTMAX_MAX;
+ } else {
+ res->high = UINTMAX_MAX;
+ res->low = a->low | ~((uintmax_t)1 << b);
+ }
+}
+
+
+/**
+ * Calculate the bitwise IF of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This sets all but the specified bit
+ *
+ * @param a The left-hand integer, also used as the
+ * output parameter for the result
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ */
+inline void
+libj2_j2u_if_bit(struct libj2_j2u *a, unsigned b)
+{
+ libj2_j2u_if_bit_to_j2u(a, b, a);
+}
+
+
+/**
+ * Calculate the bitwise IMPLY of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This sets the specified bit and flips the rest
+ *
+ * @param a The left-hand integer
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_j2u_imply_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res)
+{
+ res->high = a->high ^ UINTMAX_MAX;
+ res->low = a->low ^ UINTMAX_MAX;
+ if (b >= LIBJ2_JU_BIT) {
+ if (b >= LIBJ2_J2U_BIT)
+ return;
+ res->high |= (uintmax_t)1 << (b - LIBJ2_JU_BIT);
+ } else {
+ res->low |= (uintmax_t)1 << b;
+ }
+}
+
+
+/**
+ * Calculate the bitwise IMPLY of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This sets the specified bit and flips the rest
+ *
+ * @param a The left-hand integer, also used as the
+ * output parameter for the result
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ */
+inline void
+libj2_j2u_imply_bit(struct libj2_j2u *a, unsigned b)
+{
+ libj2_j2u_imply_bit_to_j2u(a, b, a);
+}
+
+
+/**
+ * Calculate the bitwise NAND of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This flips the specified bit and sets the rest
+ *
+ * @param a The left-hand integer
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_j2u_nand_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res)
+{
+ if (b >= LIBJ2_J2U_BIT) {
+ res->high = UINTMAX_MAX;
+ res->low = UINTMAX_MAX;
+ } else if (b >= LIBJ2_JU_BIT) {
+ res->high = a->high ^ UINTMAX_MAX;
+ res->high |= ~((uintmax_t)1 << (b - LIBJ2_JU_BIT));
+ res->low = UINTMAX_MAX;
+ } else {
+ res->high = UINTMAX_MAX;
+ res->low = a->low ^ UINTMAX_MAX;
+ res->low |= ~((uintmax_t)1 << b);
+ }
+}
+
+
+/**
+ * Calculate the bitwise NAND of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This flips the specified bit and sets the rest
+ *
+ * @param a The left-hand integer, also used as the
+ * output parameter for the result
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ */
+inline void
+libj2_j2u_nand_bit(struct libj2_j2u *a, unsigned b)
+{
+ libj2_j2u_nand_bit_to_j2u(a, b, a);
+}
+
+
+/**
+ * Calculate the bitwise NOR of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This clears the specified bit and flips the rest
+ *
+ * @param a The left-hand integer
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_j2u_nor_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res)
+{
+ res->high = a->high ^ UINTMAX_MAX;
+ res->low = a->low ^ UINTMAX_MAX;
+ if (b >= LIBJ2_JU_BIT) {
+ if (b >= LIBJ2_J2U_BIT)
+ return;
+ res->high &= ~((uintmax_t)1 << (b - LIBJ2_JU_BIT));
+ } else {
+ res->low &= ~((uintmax_t)1 << b);
+ }
+}
+
+
+/**
+ * Calculate the bitwise NOR of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This clears the specified bit and flips the rest
+ *
+ * @param a The left-hand integer, also used as the
+ * output parameter for the result
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ */
+inline void
+libj2_j2u_nor_bit(struct libj2_j2u *a, unsigned b)
+{
+ libj2_j2u_nor_bit_to_j2u(a, b, a);
+}
+
+
+/**
+ * Calculate the bitwise XNOR of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This flips all but the specified bit
+ *
+ * @param a The left-hand integer
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_j2u_xnor_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res)
+{
+ res->high = a->high ^ UINTMAX_MAX;
+ res->low = a->low ^ UINTMAX_MAX;
+ if (b >= LIBJ2_JU_BIT) {
+ if (b >= LIBJ2_J2U_BIT)
+ return;
+ res->high ^= (uintmax_t)1 << (b - LIBJ2_JU_BIT);
+ } else {
+ res->low ^= (uintmax_t)1 << b;
+ }
+}
+
+
+/**
+ * Calculate the bitwise XNOR of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This flips all but the specified bit
+ *
+ * @param a The left-hand integer, also used as the
+ * output parameter for the result
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ */
+inline void
+libj2_j2u_xnor_bit(struct libj2_j2u *a, unsigned b)
+{
+ libj2_j2u_xnor_bit_to_j2u(a, b, a);
+}
+
+
+/**
+ * Calculate the bitwise NIF of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This flips the specified bit and clears the rest
+ *
+ * @param a The left-hand integer
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_j2u_nif_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res)
+{
+ if (b >= LIBJ2_J2U_BIT) {
+ res->high = 0;
+ res->low = 0;
+ } else if (b >= LIBJ2_JU_BIT) {
+ res->high = a->high & ((uintmax_t)1 << (b - LIBJ2_JU_BIT));
+ res->high ^= (uintmax_t)1 << (b - LIBJ2_JU_BIT);
+ res->low = 0;
+ } else {
+ res->high = 0;
+ res->low = a->low & ((uintmax_t)1 << b);
+ res->low ^= (uintmax_t)1 << b;
+ }
+}
+
+
+/**
+ * Calculate the bitwise NIF of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This flips the specified bit and clears the rest
+ *
+ * @param a The left-hand integer, also used as the
+ * output parameter for the result
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ */
+inline void
+libj2_j2u_nif_bit(struct libj2_j2u *a, unsigned b)
+{
+ libj2_j2u_nif_bit_to_j2u(a, b, a);
+}
+
+
+/**
+ * Calculate the bitwise NIMPLY of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This clears the specified bit
+ *
+ * @param a The left-hand integer
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ * @param res Output parameter for the result
+ */
+inline void
+libj2_j2u_nimply_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res)
+{
+ if (b >= LIBJ2_J2U_BIT) {
+ res->high = a->high;
+ res->low = a->low;
+ } else if (b >= LIBJ2_JU_BIT) {
+ res->high = a->high & ~((uintmax_t)1 << (b - LIBJ2_JU_BIT));
+ res->low = a->low;
+ } else {
+ res->high = a->high;
+ res->low = a->low & ~((uintmax_t)1 << b);
+ }
+}
+
+
+/**
+ * Calculate the bitwise NIMPLY of an unsigned double-max
+ * precision integer (left-hand) and unsigned double-max
+ * precision integer with one specified bit set and the
+ * reset cleared (right-hand)
+ *
+ * This clears the specified bit
+ *
+ * @param a The left-hand integer, also used as the
+ * output parameter for the result
+ * @param b The index of bit that shall be set in
+ * the right-hand integer, 0 for the least
+ * significant bit
+ */
+inline void
+libj2_j2u_nimply_bit(struct libj2_j2u *a, unsigned b)
+{
+ if (b >= LIBJ2_JU_BIT) {
+ if (b >= LIBJ2_J2U_BIT)
+ return;
+ a->high &= ~((uintmax_t)1 << (b - LIBJ2_JU_BIT));
+ } else {
+ a->low &= ~((uintmax_t)1 << b);
+ }
+}
+
+
+/**
+ * Check that all of some specified bits are set
+ * in an unsigned double-max precision integer
+ *
+ * `libj2_j2u_has_j2u(a, b)` implements `(*a & *b) == *b`
+ *
+ * @param a The integer to inspect
+ * @param b Integer whose set bits should also be set in `a`
+ * @return 1 if the set bits in `b` are also set in `a`,
+ * 0 otherwise
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_has_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
+{
+ return (a->low & b->low) == b->low && (a->high & b->high) == b->high;
+}
+
+
+/**
+ * Check that all of some specified bits are set
+ * in an unsigned double-max precision integer
+ *
+ * `libj2_j2u_has_ju(a, b)` implements `(*a & b) == b`
+ *
+ * @param a The integer to inspect
+ * @param b Integer whose set bits should also be set in `a`
+ * @return 1 if the set bits in `b` are also set in `a`,
+ * 0 otherwise
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_has_ju(const struct libj2_j2u *a, uintmax_t b)
+{
+ return (a->low & b) == b;
+}
+
+
+/**
+ * Check that all of some specified bits are set
+ * in the most significant half of an unsigned
+ * double-max precision integer
+ *
+ * `libj2_j2u_has_ju(a, b)` implements `(a->high & b) == b`
+ *
+ * @param a The integer to inspect
+ * @param b Integer whose set bits should also be set in `a`'s
+ * most significant half (`a->high`)
+ * @return 1 if the set bits in `b` are also set in `a->high`,
+ * 0 otherwise
+ */
+LIBJ2_PURE_ inline int
+libj2_j2u_has_high_ju(const struct libj2_j2u *a, uintmax_t b)
+{
+ return (a->high & b) == b;
+}
diff --git a/libj2/constants.h b/libj2/constants.h
index e33fbff..a13eeac 100644
--- a/libj2/constants.h
+++ b/libj2/constants.h
@@ -13,7 +13,7 @@
* @param a The integer to inspect
* @return 1 if `a` has the value 0, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_is_zero(const struct libj2_j2u *a)
{
return !a->high && !a->low;
@@ -41,7 +41,7 @@ libj2_j2u_zero(struct libj2_j2u *res)
* @param a The integer to inspect
* @return 1 if `a` has highest representable value, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_is_max(const struct libj2_j2u *a)
{
return a->high == UINTMAX_MAX && a->low == UINTMAX_MAX;
@@ -71,7 +71,7 @@ libj2_j2u_max(struct libj2_j2u *res)
* @param a The integer to inspect
* @return 1 if `a` has lowest representable value, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_is_min(const struct libj2_j2u *a)
{
return libj2_j2u_is_zero(a);
diff --git a/libj2/division.h b/libj2/division.h
index 9607b1b..9797f4e 100644
--- a/libj2/division.h
+++ b/libj2/division.h
@@ -38,7 +38,9 @@ libj2_j2u_divmod_j2u_to_j2u(struct libj2_j2u *a, const struct libj2_j2u *b, stru
goto out;
}
- /* TODO e = leading_zeroes(a) - leading_zeroes(b) + 1 */
+#if defined(LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_)
+ e = libj2_clz_j2u(b) - libj2_clz_j2u(a) + 1U;
+#endif
while (!libj2_j2u_is_zero(a) && e--) {
if (libj2_j2u_lsh_to_j2u_overflow(&d, e, &c))
diff --git a/libj2/signum.h b/libj2/signum.h
index 7ae1833..cfd047d 100644
--- a/libj2/signum.h
+++ b/libj2/signum.h
@@ -13,7 +13,7 @@
* @param a The integer to inspect
* @return 1 if `a` has a positive value, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_is_positive(const struct libj2_j2u *a)
{
return a->high || a->low;
@@ -35,7 +35,7 @@ libj2_j2u_is_positive(const struct libj2_j2u *a)
* +1 if `a` is positive, and
* 0 if `a` is 0
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_sgn_j2u(const struct libj2_j2u *a)
{
return libj2_j2u_is_positive(a);
diff --git a/libj2/unsigned-comparsion.h b/libj2/unsigned-comparsion.h
index 3362753..fcc81c9 100644
--- a/libj2/unsigned-comparsion.h
+++ b/libj2/unsigned-comparsion.h
@@ -15,7 +15,7 @@
* @param b The right-hand value
* @return 1 if `*a` is less than `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_lt_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
{
return a->high < b->high || (a->high == b->high && a->low < b->low);
@@ -32,7 +32,7 @@ libj2_j2u_lt_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `*a` is less than or equal to `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_le_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
{
return a->high < b->high || (a->high == b->high && a->low <= b->low);
@@ -49,7 +49,7 @@ libj2_j2u_le_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `*a` is greater than `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_gt_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
{
return a->high > b->high || (a->high == b->high && a->low > b->low);
@@ -66,7 +66,7 @@ libj2_j2u_gt_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `*a` is greater than or equal to `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_ge_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
{
return a->high > b->high || (a->high == b->high && a->low >= b->low);
@@ -83,7 +83,7 @@ libj2_j2u_ge_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `*a` is equal to `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_eq_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
{
return a->high == b->high && a->low == b->low;
@@ -100,7 +100,7 @@ libj2_j2u_eq_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `*a` is not equal to `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_ne_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
{
return a->high != b->high || a->low != b->low;
@@ -120,7 +120,7 @@ libj2_j2u_ne_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
* +1 if `*a` is greater than `*b`,
* 0 if `*a` is equal to `*b`
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_cmp_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
{
return a->high < b->high ? -1 : a->high > b->high ? +1 : a->low < b->low ? -1 : a->low > b->low;
@@ -137,7 +137,7 @@ libj2_j2u_cmp_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `*a` is less than `b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_lt_ju(const struct libj2_j2u *a, uintmax_t b)
{
return !a->high && a->low < b;
@@ -154,7 +154,7 @@ libj2_j2u_lt_ju(const struct libj2_j2u *a, uintmax_t b)
* @param b The right-hand value
* @return 1 if `*a` is less than or equal to `b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_le_ju(const struct libj2_j2u *a, uintmax_t b)
{
return !a->high && a->low <= b;
@@ -171,7 +171,7 @@ libj2_j2u_le_ju(const struct libj2_j2u *a, uintmax_t b)
* @param b The right-hand value
* @return 1 if `*a` is less than `b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_gt_ju(const struct libj2_j2u *a, uintmax_t b)
{
return a->high || a->low > b;
@@ -188,7 +188,7 @@ libj2_j2u_gt_ju(const struct libj2_j2u *a, uintmax_t b)
* @param b The right-hand value
* @return 1 if `*a` is greater than or equal to `b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_ge_ju(const struct libj2_j2u *a, uintmax_t b)
{
return a->high || a->low >= b;
@@ -205,7 +205,7 @@ libj2_j2u_ge_ju(const struct libj2_j2u *a, uintmax_t b)
* @param b The right-hand value
* @return 1 if `*a` is equal to `b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_eq_ju(const struct libj2_j2u *a, uintmax_t b)
{
return !a->high && a->low == b;
@@ -222,7 +222,7 @@ libj2_j2u_eq_ju(const struct libj2_j2u *a, uintmax_t b)
* @param b The right-hand value
* @return 1 if `*a` is not equal to `b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_ne_ju(const struct libj2_j2u *a, uintmax_t b)
{
return a->high || a->low != b;
@@ -242,7 +242,7 @@ libj2_j2u_ne_ju(const struct libj2_j2u *a, uintmax_t b)
* +1 if `*a` is greater than `b`,
* 0 if `*a` is equal to `b`
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_j2u_cmp_ju(const struct libj2_j2u *a, uintmax_t b)
{
return a->high ? +1 : a->low < b ? -1 : a->low > b;
@@ -259,7 +259,7 @@ libj2_j2u_cmp_ju(const struct libj2_j2u *a, uintmax_t b)
* @param b The right-hand value
* @return 1 if `a` is less than `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_ju_lt_j2u(uintmax_t a, const struct libj2_j2u *b)
{
return libj2_j2u_gt_ju(b, a);
@@ -276,7 +276,7 @@ libj2_ju_lt_j2u(uintmax_t a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `a` is less than or equal to `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_ju_le_j2u(uintmax_t a, const struct libj2_j2u *b)
{
return libj2_j2u_ge_ju(b, a);
@@ -293,7 +293,7 @@ libj2_ju_le_j2u(uintmax_t a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `a` is less than `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_ju_gt_j2u(uintmax_t a, const struct libj2_j2u *b)
{
return libj2_j2u_lt_ju(b, a);
@@ -310,7 +310,7 @@ libj2_ju_gt_j2u(uintmax_t a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `a` is greater than or equal to `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_ju_ge_j2u(uintmax_t a, const struct libj2_j2u *b)
{
return libj2_j2u_le_ju(b, a);
@@ -327,7 +327,7 @@ libj2_ju_ge_j2u(uintmax_t a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `a` is equal to `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_ju_eq_j2u(uintmax_t a, const struct libj2_j2u *b)
{
return libj2_j2u_eq_ju(b, a);
@@ -344,7 +344,7 @@ libj2_ju_eq_j2u(uintmax_t a, const struct libj2_j2u *b)
* @param b The right-hand value
* @return 1 if `a` is not equal to `*b`, 0 otherwise
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_ju_ne_j2u(uintmax_t a, const struct libj2_j2u *b)
{
return libj2_j2u_ne_ju(b, a);
@@ -364,7 +364,7 @@ libj2_ju_ne_j2u(uintmax_t a, const struct libj2_j2u *b)
* +1 if `a` is greater than `*b`,
* 0 if `a` is equal to `*b`
*/
-inline int
+LIBJ2_PURE_ inline int
libj2_ju_cmp_j2u(uintmax_t a, const struct libj2_j2u *b)
{
return b->high ? -1 : a < b->low ? -1 : a > b->low;
@@ -606,7 +606,7 @@ libj2_vmax_j2u_return(const struct libj2_j2u *a, va_list args)
* @return One of the `const struct libj2_j2u *` that as the
* maximum of the values of each argument
*/
-inline const struct libj2_j2u *
+LIBJ2_PURE_ inline const struct libj2_j2u *
libj2_max_j2u_return(const struct libj2_j2u *a, ... /*, NULL */)
{
va_list args;
@@ -724,7 +724,7 @@ libj2_vmin_j2u_return(const struct libj2_j2u *a, va_list args)
* @return One of the `const struct libj2_j2u *` that as the
* minimum of the values of each argument
*/
-inline const struct libj2_j2u *
+LIBJ2_PURE_ inline const struct libj2_j2u *
libj2_min_j2u_return(const struct libj2_j2u *a, ... /*, NULL */)
{
va_list args;
diff --git a/libj2_cfs_j2u.c b/libj2_cfs_j2u.c
new file mode 100644
index 0000000..c2434e0
--- /dev/null
+++ b/libj2_cfs_j2u.c
@@ -0,0 +1,116 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_cfs_j2u(struct libj2_j2u *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
+cfs(const struct libj2_j2u *a, struct libj2_j2u *res)
+{
+ struct libj2_j2u a_saved = *a, r, b;
+
+ *res = (struct libj2_j2u){111, 222};
+ libj2_cfs_j2u_to_j2u(a, res);
+ EXPECT(libj2_j2u_eq_j2u(a, &a_saved));
+
+ r = *a;
+ libj2_cfs_j2u_to_j2u(&r, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ r = *a;
+ libj2_cfs_j2u(&r);
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_not_j2u_to_j2u(a, &b);
+ libj2_sfc_j2u_to_j2u((const struct libj2_j2u *)&b, &r);
+ libj2_not_j2u(&b);
+ libj2_not_j2u(&r);
+ EXPECT(libj2_j2u_eq_j2u(&b, &a_saved));
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ r = *a;
+ libj2_not_j2u(&r);
+ libj2_sfc_j2u_to_j2u(&r, &r);
+ libj2_not_j2u(&r);
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ r = *a;
+ libj2_not_j2u(&r);
+ libj2_sfc_j2u(&r);
+ libj2_not_j2u(&r);
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ b = (struct libj2_j2u){333, 444};
+ libj2_kfs_j2u_to_j2u(a, &b);
+ EXPECT(libj2_j2u_eq_j2u(a, &a_saved));
+ libj2_j2u_sub_j2u_to_j2u(a, &b, &r);
+ EXPECT(libj2_j2u_eq_j2u(a, &a_saved));
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ r = *a;
+ libj2_kfs_j2u(&r);
+ EXPECT(libj2_j2u_eq_j2u(a, &a_saved));
+ EXPECT(libj2_j2u_eq_j2u(&r, &b));
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a, r, t;
+ unsigned i, j;
+
+ libj2_j2u_max(&a);
+ for (i = 0; i < LIBJ2_J2U_BIT; i++) {
+ cfs(&a, &r);
+ libj2_j2u_lsh_to_j2u(&a, 1, &a);
+ EXPECT(libj2_j2u_eq_j2u(&r, &a));
+ }
+ EXPECT(libj2_j2u_is_zero(&a));
+ cfs(&a, &r);
+ EXPECT(libj2_j2u_is_zero(&r));
+
+ libj2_j2u_max(&a);
+ a.high = 0;
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ cfs(&a, &r);
+ libj2_j2u_lsh_to_j2u(&a, 1, &a);
+ a.high = 0;
+ EXPECT(libj2_j2u_eq_j2u(&r, &a));
+ }
+ EXPECT(libj2_j2u_is_zero(&a));
+
+ for (j = 1; j <= 3; j++) {
+ for (i = 0; i < 256; i++) {
+ a.high = (j & 1) ? random_ju() : 0;
+ a.low = (j & 2) ? random_ju() : 0;
+ while (!libj2_j2u_is_zero(&a)) {
+ cfs(&a, &r);
+ libj2_j2u_sub_ju_to_j2u(&a, 1, &t);
+ libj2_j2u_and_j2u(&a, &t);
+ EXPECT(libj2_j2u_eq_j2u(&r, &a));
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_cfs_j2u_to_j2u.c b/libj2_cfs_j2u_to_j2u.c
new file mode 100644
index 0000000..2e0a11e
--- /dev/null
+++ b/libj2_cfs_j2u_to_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_cfs_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_cfs_j2u.c */
+
+#endif
diff --git a/libj2_clo_j2u.c b/libj2_clo_j2u.c
new file mode 100644
index 0000000..8fa0d03
--- /dev/null
+++ b/libj2_clo_j2u.c
@@ -0,0 +1,64 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_clo_j2u(const struct libj2_j2u *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;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a, a_saved, t;
+ unsigned i, j;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i <= LIBJ2_J2U_BIT; i++) {
+ for (j = 0; j < 64; j++) {
+ a.high = random_ju();
+ a.low = random_ju();
+ libj2_j2u_nimply_bit(&a, LIBJ2_J2U_BIT - 1U);
+ libj2_j2u_rsh(&a, i);
+ libj2_j2u_max(&t);
+ libj2_j2u_lsh(&t, LIBJ2_J2U_BIT - i);
+ libj2_j2u_or_j2u(&a, &t);
+ a_saved = a;
+
+ EXPECT(libj2_clo_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ if (i <= LIBJ2_JU_BIT) {
+ a.low = 0;
+ a_saved.low = 0;
+ EXPECT(libj2_clo_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ if (i < LIBJ2_JU_BIT) {
+ a.low = UINTMAX_MAX;
+ a_saved.low = UINTMAX_MAX;
+ EXPECT(libj2_clo_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_cls_j2u.c b/libj2_cls_j2u.c
new file mode 100644
index 0000000..78d5033
--- /dev/null
+++ b/libj2_cls_j2u.c
@@ -0,0 +1,119 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_cls_j2u(struct libj2_j2u *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
+cls(const struct libj2_j2u *a, struct libj2_j2u *res)
+{
+ struct libj2_j2u a_saved = *a, r, b;
+
+ *res = (struct libj2_j2u){111, 222};
+ libj2_cls_j2u_to_j2u(a, res);
+ EXPECT(libj2_j2u_eq_j2u(a, &a_saved));
+
+ r = *a;
+ libj2_cls_j2u_to_j2u(&r, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ r = *a;
+ libj2_cls_j2u(&r);
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_not_j2u_to_j2u(a, &b);
+ libj2_slc_j2u_to_j2u((const struct libj2_j2u *)&b, &r);
+ libj2_not_j2u(&b);
+ libj2_not_j2u(&r);
+ EXPECT(libj2_j2u_eq_j2u(&b, &a_saved));
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ r = *a;
+ libj2_not_j2u(&r);
+ libj2_slc_j2u_to_j2u(&r, &r);
+ libj2_not_j2u(&r);
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ r = *a;
+ libj2_not_j2u(&r);
+ libj2_slc_j2u(&r);
+ libj2_not_j2u(&r);
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ b = (struct libj2_j2u){333, 444};
+ libj2_kls_j2u_to_j2u(a, &b);
+ EXPECT(libj2_j2u_eq_j2u(a, &a_saved));
+ libj2_j2u_sub_j2u_to_j2u(a, &b, &r);
+ EXPECT(libj2_j2u_eq_j2u(a, &a_saved));
+ EXPECT(libj2_j2u_eq_j2u(&r, res));
+
+ r = *a;
+ libj2_kls_j2u(&r);
+ EXPECT(libj2_j2u_eq_j2u(a, &a_saved));
+ EXPECT(libj2_j2u_eq_j2u(&r, &b));
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a, r;
+ unsigned i, j, bit;
+
+ libj2_j2u_max(&a);
+ for (i = 0; i < LIBJ2_J2U_BIT; i++) {
+ cls(&a, &r);
+ libj2_j2u_rsh_to_j2u(&a, 1, &a);
+ EXPECT(libj2_j2u_eq_j2u(&r, &a));
+ }
+ EXPECT(libj2_j2u_is_zero(&a));
+ cls(&a, &r);
+ EXPECT(libj2_j2u_is_zero(&r));
+
+ libj2_j2u_max(&a);
+ a.low = 0;
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ cls(&a, &r);
+ libj2_j2u_rsh_to_j2u(&a, 1, &a);
+ a.low = 0;
+ EXPECT(libj2_j2u_eq_j2u(&r, &a));
+ }
+ EXPECT(libj2_j2u_is_zero(&a));
+
+ for (j = 1; j <= 3; j++) {
+ for (i = 0; i < 256; i++) {
+ a.high = (j & 1) ? random_ju() : 0;
+ a.low = (j & 2) ? random_ju() : 0;
+ while (!libj2_j2u_is_zero(&a)) {
+ cls(&a, &r);
+ bit = libj2_fls_j2u(&a);
+ EXPECT(bit);
+ bit -= 1U;
+ EXPECT(libj2_j2u_test_bit(&a, bit));
+ libj2_j2u_xor_bit(&a, bit);
+ EXPECT(libj2_j2u_eq_j2u(&r, &a));
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_cls_j2u_to_j2u.c b/libj2_cls_j2u_to_j2u.c
new file mode 100644
index 0000000..2a8eca9
--- /dev/null
+++ b/libj2_cls_j2u_to_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_cls_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_cls_j2u.c */
+
+#endif
diff --git a/libj2_clz_j2u.c b/libj2_clz_j2u.c
new file mode 100644
index 0000000..5e6f1f4
--- /dev/null
+++ b/libj2_clz_j2u.c
@@ -0,0 +1,61 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_clz_j2u(const struct libj2_j2u *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;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a, a_saved;
+ unsigned i, j;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i <= LIBJ2_J2U_BIT; i++) {
+ for (j = 0; j < 64; j++) {
+ a.high = random_ju();
+ a.low = random_ju();
+ libj2_j2u_or_bit(&a, LIBJ2_J2U_BIT - 1U);
+ libj2_j2u_rsh(&a, i);
+ a_saved = a;
+
+ EXPECT(libj2_clz_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ if (i <= LIBJ2_JU_BIT) {
+ a.low = UINTMAX_MAX;
+ a_saved.low = UINTMAX_MAX;
+ EXPECT(libj2_clz_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ if (i < LIBJ2_JU_BIT) {
+ a.low = 0;
+ a_saved.low = 0;
+ EXPECT(libj2_clz_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_co_j2u.c b/libj2_co_j2u.c
new file mode 100644
index 0000000..6b1988a
--- /dev/null
+++ b/libj2_co_j2u.c
@@ -0,0 +1,95 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_co_j2u(const struct libj2_j2u *a);
+/* TODO Add man page */
+
+
+#else
+
+static uintmax_t
+random_ju(unsigned *popcount)
+{
+ size_t n = LIBJ2_JU_BIT;
+ uintmax_t r = 0;
+ *popcount = 0;
+ while (n--) {
+ if (rand() < rand()) {
+ r |= (uintmax_t)1 << n;
+ *popcount += 1U;
+ }
+ }
+ return r;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a;
+ uintmax_t high, low;
+ unsigned i, high_n, low_n;
+
+ srand((unsigned)time(NULL));
+
+ a.high = 0;
+ a.low = 0;
+ EXPECT(libj2_co_j2u(&a) == 0);
+ EXPECT(a.high == 0);
+ EXPECT(a.low == 0);
+
+ a.high = 0;
+ a.low = UINTMAX_MAX;
+ EXPECT(libj2_co_j2u(&a) == LIBJ2_JU_BIT);
+ EXPECT(a.high == 0);
+ EXPECT(a.low == UINTMAX_MAX);
+
+ a.high = UINTMAX_MAX;
+ a.low = 0;
+ EXPECT(libj2_co_j2u(&a) == LIBJ2_JU_BIT);
+ EXPECT(a.high == UINTMAX_MAX);
+ EXPECT(a.low == 0);
+
+ a.high = UINTMAX_MAX;
+ a.low = UINTMAX_MAX;
+ EXPECT(libj2_co_j2u(&a) == LIBJ2_J2U_BIT);
+ EXPECT(a.high == UINTMAX_MAX);
+ EXPECT(a.low == UINTMAX_MAX);
+
+ for (i = 0; i < 256; i++) {
+ a.high = high = random_ju(&high_n);
+ a.low = low = random_ju(&low_n);
+ EXPECT(libj2_co_j2u(&a) == high_n + low_n);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+
+ a.high = high = random_ju(&high_n);
+ a.low = low = 0;
+ EXPECT(libj2_co_j2u(&a) == high_n);
+ EXPECT(a.high == high);
+ EXPECT(a.low == 0);
+
+ a.high = high = random_ju(&high_n);
+ a.low = low = UINTMAX_MAX;
+ EXPECT(libj2_co_j2u(&a) == high_n + LIBJ2_JU_BIT);
+ EXPECT(a.high == high);
+ EXPECT(a.low == UINTMAX_MAX);
+
+ a.high = high = 0;
+ a.low = low = random_ju(&low_n);
+ EXPECT(libj2_co_j2u(&a) == low_n);
+ EXPECT(a.high == 0);
+ EXPECT(a.low == low);
+
+ a.high = high = UINTMAX_MAX;
+ a.low = low = random_ju(&low_n);
+ EXPECT(libj2_co_j2u(&a) == LIBJ2_JU_BIT + low_n);
+ EXPECT(a.high == UINTMAX_MAX);
+ EXPECT(a.low == low);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_cto_j2u.c b/libj2_cto_j2u.c
new file mode 100644
index 0000000..17ea8b6
--- /dev/null
+++ b/libj2_cto_j2u.c
@@ -0,0 +1,62 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_cto_j2u(const struct libj2_j2u *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;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a, a_saved;
+ unsigned i, j;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i <= LIBJ2_J2U_BIT; i++) {
+ for (j = 0; j < 64; j++) {
+ a.high = random_ju();
+ a.low = random_ju();
+ libj2_j2u_or_bit(&a, 0);
+ libj2_j2u_lsh(&a, i);
+ libj2_j2u_sub_ju(&a, 1);
+ a_saved = a;
+
+ EXPECT(libj2_cto_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ if (i <= LIBJ2_JU_BIT) {
+ a.high = 0;
+ a_saved.high = 0;
+ EXPECT(libj2_cto_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ if (i < LIBJ2_JU_BIT) {
+ a.high = UINTMAX_MAX;
+ a_saved.high = UINTMAX_MAX;
+ EXPECT(libj2_cto_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_ctz_j2u.c b/libj2_ctz_j2u.c
new file mode 100644
index 0000000..3c4ff87
--- /dev/null
+++ b/libj2_ctz_j2u.c
@@ -0,0 +1,61 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_ctz_j2u(const struct libj2_j2u *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;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a, a_saved;
+ unsigned i, j;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i <= LIBJ2_J2U_BIT; i++) {
+ for (j = 0; j < 64; j++) {
+ a.high = random_ju();
+ a.low = random_ju();
+ libj2_j2u_or_bit(&a, 0);
+ libj2_j2u_lsh(&a, i);
+ a_saved = a;
+
+ EXPECT(libj2_ctz_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ if (i <= LIBJ2_JU_BIT) {
+ a.high = UINTMAX_MAX;
+ a_saved.high = UINTMAX_MAX;
+ EXPECT(libj2_ctz_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ if (i < LIBJ2_JU_BIT) {
+ a.high = 0;
+ a_saved.high = 0;
+ EXPECT(libj2_ctz_j2u(&a) == i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_cz_j2u.c b/libj2_cz_j2u.c
new file mode 100644
index 0000000..60da659
--- /dev/null
+++ b/libj2_cz_j2u.c
@@ -0,0 +1,95 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_cz_j2u(const struct libj2_j2u *a);
+/* TODO Add man page */
+
+
+#else
+
+static uintmax_t
+random_ju(unsigned *popcount)
+{
+ size_t n = LIBJ2_JU_BIT;
+ uintmax_t r = 0;
+ *popcount = 0;
+ while (n--) {
+ if (rand() < rand()) {
+ r |= (uintmax_t)1 << n;
+ *popcount += 1U;
+ }
+ }
+ return r;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a;
+ uintmax_t high, low;
+ unsigned i, high_n, low_n;
+
+ srand((unsigned)time(NULL));
+
+ a.high = 0;
+ a.low = 0;
+ EXPECT(libj2_cz_j2u(&a) == LIBJ2_J2U_BIT);
+ EXPECT(a.high == 0);
+ EXPECT(a.low == 0);
+
+ a.high = 0;
+ a.low = UINTMAX_MAX;
+ EXPECT(libj2_cz_j2u(&a) == LIBJ2_JU_BIT);
+ EXPECT(a.high == 0);
+ EXPECT(a.low == UINTMAX_MAX);
+
+ a.high = UINTMAX_MAX;
+ a.low = 0;
+ EXPECT(libj2_cz_j2u(&a) == LIBJ2_JU_BIT);
+ EXPECT(a.high == UINTMAX_MAX);
+ EXPECT(a.low == 0);
+
+ a.high = UINTMAX_MAX;
+ a.low = UINTMAX_MAX;
+ EXPECT(libj2_cz_j2u(&a) == 0);
+ EXPECT(a.high == UINTMAX_MAX);
+ EXPECT(a.low == UINTMAX_MAX);
+
+ for (i = 0; i < 256; i++) {
+ a.high = high = ~random_ju(&high_n);
+ a.low = low = ~random_ju(&low_n);
+ EXPECT(libj2_cz_j2u(&a) == high_n + low_n);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+
+ a.high = high = ~random_ju(&high_n);
+ a.low = low = 0;
+ EXPECT(libj2_cz_j2u(&a) == high_n + LIBJ2_JU_BIT);
+ EXPECT(a.high == high);
+ EXPECT(a.low == 0);
+
+ a.high = high = ~random_ju(&high_n);
+ a.low = low = UINTMAX_MAX;
+ EXPECT(libj2_cz_j2u(&a) == high_n);
+ EXPECT(a.high == high);
+ EXPECT(a.low == UINTMAX_MAX);
+
+ a.high = high = 0;
+ a.low = low = ~random_ju(&low_n);
+ EXPECT(libj2_cz_j2u(&a) == LIBJ2_JU_BIT + low_n);
+ EXPECT(a.high == 0);
+ EXPECT(a.low == low);
+
+ a.high = high = UINTMAX_MAX;
+ a.low = low = ~random_ju(&low_n);
+ EXPECT(libj2_cz_j2u(&a) == low_n);
+ EXPECT(a.high == UINTMAX_MAX);
+ EXPECT(a.low == low);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_ffc_j2u.c b/libj2_ffc_j2u.c
new file mode 100644
index 0000000..5d2c481
--- /dev/null
+++ b/libj2_ffc_j2u.c
@@ -0,0 +1,125 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_ffc_j2u(const struct libj2_j2u *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;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a, b, a_saved, b_saved;
+ unsigned i, j;
+
+ srand((unsigned)time(NULL));
+
+ libj2_ju_to_j2u(0, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == 0);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(1, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(2, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == 2);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(3, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(4, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == 3);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(5, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(6, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == 2);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_j2u_max(&a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ for (i = 0; i < LIBJ2_J2U_BIT; i++) {
+ libj2_j2u_zero(&a);
+ libj2_j2u_or_bit(&a, i);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ libj2_j2u_zero(&a);
+ libj2_j2u_or_bit(&a, i);
+ a.high = UINTMAX_MAX;
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ for (i = 0; i < LIBJ2_J2U_BIT; i++) {
+ libj2_j2u_max(&a);
+ libj2_j2u_lsh(&a, i);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_ffc_j2u(&a) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ libj2_not_j2u(&a);
+ a_saved = a;
+
+ for (j = 0; j < 32; j++) {
+ EXPECT(libj2_j2u_test_bit(&a, i));
+ b.high = random_ju();
+ b.low = random_ju();
+ libj2_j2u_and_j2u(&b, &a);
+ libj2_j2u_or_bit(&b, i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ libj2_not_j2u(&b);
+ b_saved = b;
+ EXPECT(libj2_ffc_j2u(&b) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&b, &b_saved));
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_ffs_j2u.c b/libj2_ffs_j2u.c
new file mode 100644
index 0000000..59b5996
--- /dev/null
+++ b/libj2_ffs_j2u.c
@@ -0,0 +1,110 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_ffs_j2u(const struct libj2_j2u *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;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a, b, a_saved, b_saved;
+ unsigned i, j;
+
+ srand((unsigned)time(NULL));
+
+ libj2_ju_to_j2u(0, &a);
+ a_saved = a;
+ EXPECT(libj2_ffs_j2u(&a) == 0);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(1, &a);
+ a_saved = a;
+ EXPECT(libj2_ffs_j2u(&a) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(2, &a);
+ a_saved = a;
+ EXPECT(libj2_ffs_j2u(&a) == 2);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(3, &a);
+ a_saved = a;
+ EXPECT(libj2_ffs_j2u(&a) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(4, &a);
+ a_saved = a;
+ EXPECT(libj2_ffs_j2u(&a) == 3);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(5, &a);
+ a_saved = a;
+ EXPECT(libj2_ffs_j2u(&a) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(6, &a);
+ a_saved = a;
+ EXPECT(libj2_ffs_j2u(&a) == 2);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_j2u_max(&a);
+ EXPECT(libj2_ffs_j2u(&a) == 1);
+ EXPECT(libj2_j2u_is_max(&a));
+
+ for (i = 0; i < LIBJ2_J2U_BIT; i++) {
+ libj2_j2u_zero(&a);
+ libj2_j2u_or_bit(&a, i);
+ a_saved = a;
+ EXPECT(libj2_ffs_j2u(&a) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ for (i = 0; i < LIBJ2_JU_BIT; i++) {
+ libj2_j2u_zero(&a);
+ libj2_j2u_or_bit(&a, i);
+ a.high = UINTMAX_MAX;
+ a_saved = a;
+ EXPECT(libj2_ffs_j2u(&a) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ for (i = 0; i < LIBJ2_J2U_BIT; i++) {
+ libj2_j2u_max(&a);
+ libj2_j2u_lsh(&a, i);
+ a_saved = a;
+ EXPECT(libj2_ffs_j2u(&a) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ for (j = 0; j < 32; j++) {
+ EXPECT(libj2_j2u_test_bit(&a, i));
+ b.high = random_ju();
+ b.low = random_ju();
+ libj2_j2u_and_j2u(&b, &a);
+ libj2_j2u_or_bit(&b, i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ b_saved = b;
+ EXPECT(libj2_ffs_j2u(&b) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&b, &b_saved));
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_flc_j2u.c b/libj2_flc_j2u.c
new file mode 100644
index 0000000..905c350
--- /dev/null
+++ b/libj2_flc_j2u.c
@@ -0,0 +1,125 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_flc_j2u(const struct libj2_j2u *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;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a, b, a_saved, b_saved;
+ unsigned i, j;
+
+ srand((unsigned)time(NULL));
+
+ libj2_ju_to_j2u(0, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == 0);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(1, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(2, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == 2);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(3, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == 2);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(4, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == 3);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(5, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == 3);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(6, &a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == 3);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_j2u_max(&a);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == LIBJ2_J2U_BIT);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ for (i = 0; i < LIBJ2_J2U_BIT; i++) {
+ libj2_j2u_zero(&a);
+ libj2_j2u_or_bit(&a, i);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ for (i = LIBJ2_JU_BIT; i < LIBJ2_J2U_BIT; i++) {
+ libj2_j2u_zero(&a);
+ libj2_j2u_or_bit(&a, i);
+ a.low = UINTMAX_MAX;
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ for (i = 0; i < LIBJ2_J2U_BIT; i++) {
+ libj2_j2u_max(&a);
+ libj2_j2u_rsh(&a, i);
+ libj2_not_j2u(&a);
+ a_saved = a;
+ EXPECT(libj2_flc_j2u(&a) == LIBJ2_J2U_BIT - i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ libj2_not_j2u(&a);
+ a_saved = a;
+
+ for (j = 0; j < 32; j++) {
+ EXPECT(libj2_j2u_test_bit(&a, LIBJ2_J2U_BIT - 1U - i));
+ b.high = random_ju();
+ b.low = random_ju();
+ libj2_j2u_and_j2u(&b, &a);
+ libj2_j2u_or_bit(&b, LIBJ2_J2U_BIT - 1U - i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ libj2_not_j2u(&b);
+ b_saved = b;
+ EXPECT(libj2_flc_j2u(&b) == LIBJ2_J2U_BIT - i);
+ EXPECT(libj2_j2u_eq_j2u(&b, &b_saved));
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_fls_j2u.c b/libj2_fls_j2u.c
new file mode 100644
index 0000000..fe2d439
--- /dev/null
+++ b/libj2_fls_j2u.c
@@ -0,0 +1,110 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_fls_j2u(const struct libj2_j2u *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;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a, b, a_saved, b_saved;
+ unsigned i, j;
+
+ srand((unsigned)time(NULL));
+
+ libj2_ju_to_j2u(0, &a);
+ a_saved = a;
+ EXPECT(libj2_fls_j2u(&a) == 0);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(1, &a);
+ a_saved = a;
+ EXPECT(libj2_fls_j2u(&a) == 1);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(2, &a);
+ a_saved = a;
+ EXPECT(libj2_fls_j2u(&a) == 2);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(3, &a);
+ a_saved = a;
+ EXPECT(libj2_fls_j2u(&a) == 2);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(4, &a);
+ a_saved = a;
+ EXPECT(libj2_fls_j2u(&a) == 3);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(5, &a);
+ a_saved = a;
+ EXPECT(libj2_fls_j2u(&a) == 3);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_ju_to_j2u(6, &a);
+ a_saved = a;
+ EXPECT(libj2_fls_j2u(&a) == 3);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ libj2_j2u_max(&a);
+ EXPECT(libj2_fls_j2u(&a) == LIBJ2_J2U_BIT);
+ EXPECT(libj2_j2u_is_max(&a));
+
+ for (i = 0; i < LIBJ2_J2U_BIT; i++) {
+ libj2_j2u_zero(&a);
+ libj2_j2u_or_bit(&a, i);
+ a_saved = a;
+ EXPECT(libj2_fls_j2u(&a) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ for (i = LIBJ2_JU_BIT; i < LIBJ2_J2U_BIT; i++) {
+ libj2_j2u_zero(&a);
+ libj2_j2u_or_bit(&a, i);
+ a.low = UINTMAX_MAX;
+ a_saved = a;
+ EXPECT(libj2_fls_j2u(&a) == i + 1U);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ }
+
+ for (i = 0; i < LIBJ2_J2U_BIT; i++) {
+ libj2_j2u_max(&a);
+ libj2_j2u_rsh(&a, i);
+ a_saved = a;
+ EXPECT(libj2_fls_j2u(&a) == LIBJ2_J2U_BIT - i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+
+ for (j = 0; j < 32; j++) {
+ EXPECT(libj2_j2u_test_bit(&a, LIBJ2_J2U_BIT - 1U - i));
+ b.high = random_ju();
+ b.low = random_ju();
+ libj2_j2u_and_j2u(&b, &a);
+ libj2_j2u_or_bit(&b, LIBJ2_J2U_BIT - 1U - i);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ b_saved = b;
+ EXPECT(libj2_fls_j2u(&b) == LIBJ2_J2U_BIT - i);
+ EXPECT(libj2_j2u_eq_j2u(&b, &b_saved));
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_and_bit.c b/libj2_j2u_and_bit.c
new file mode 100644
index 0000000..502f72d
--- /dev/null
+++ b/libj2_j2u_and_bit.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_and_bit(struct libj2_j2u *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_and_bit_to_j2u.c */
+
+#endif
diff --git a/libj2_j2u_and_bit_to_j2u.c b/libj2_j2u_and_bit_to_j2u.c
new file mode 100644
index 0000000..0c54279
--- /dev/null
+++ b/libj2_j2u_and_bit_to_j2u.c
@@ -0,0 +1,72 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_and_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res);
+/* 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
+check(uintmax_t high, uintmax_t low, unsigned shift)
+{
+ struct libj2_j2u a, r, expected;
+
+ a.high = high;
+ a.low = low;
+
+ libj2_ju_lsh_to_j2u(1U, shift, &expected);
+ libj2_j2u_and_j2u_to_j2u(&a, &expected, &expected);
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_j2u_and_bit_to_j2u(&a, shift, &r);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_and_bit_to_j2u(&r, shift, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_and_bit(&r, shift);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i < LIBJ2_J2U_BIT + 4U; i++) {
+ check(0, 0, i);
+ check(0, random_ju(), i);
+ check(0, UINTMAX_MAX, i);
+ check(random_ju(), 0, i);
+ check(random_ju(), random_ju(), i);
+ check(random_ju(), UINTMAX_MAX, i);
+ check(UINTMAX_MAX, 0, i);
+ check(UINTMAX_MAX, random_ju(), i);
+ check(UINTMAX_MAX, UINTMAX_MAX, i);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_has_high_ju.c b/libj2_j2u_has_high_ju.c
new file mode 100644
index 0000000..eb34043
--- /dev/null
+++ b/libj2_j2u_has_high_ju.c
@@ -0,0 +1,40 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_has_high_ju(const struct libj2_j2u *a, uintmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2u a;
+ uintmax_t h, i, j, b;
+ int expected;
+
+ for (h = 0; h < 10; h++) {
+ a.low = h;
+ for (i = 0; i < 128; i++) {
+ a.high = i;
+ for (b = 0; b < 128; b++) {
+ expected = 1;
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ if (((b & ~a.high) >> j) & 1U) {
+ expected = 0;
+ break;
+ }
+ }
+ EXPECT(libj2_j2u_has_high_ju(&a, b) == expected);
+ EXPECT(a.low == h);
+ EXPECT(a.high == i);
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_has_j2u.c b/libj2_j2u_has_j2u.c
new file mode 100644
index 0000000..6a1f96d
--- /dev/null
+++ b/libj2_j2u_has_j2u.c
@@ -0,0 +1,36 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_has_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2u a, b, a_saved, b_saved;
+ int expected;
+
+ for (a.high = 0; a.high < 32U; a.high++) {
+ for (a.low = 0; a.low < 32U; a.low++) {
+ for (b.high = 0; b.high < 32U; b.high++) {
+ for (b.low = 0; b.low < 32U; b.low++) {
+ a_saved = a;
+ b_saved = b;
+ expected = libj2_j2u_has_ju(&a, b.low);
+ expected &= libj2_j2u_has_high_ju(&a, b.high);
+ EXPECT(libj2_j2u_has_j2u(&a, &b) == expected);
+ EXPECT(libj2_j2u_eq_j2u(&a, &a_saved));
+ EXPECT(libj2_j2u_eq_j2u(&b, &b_saved));
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_has_ju.c b/libj2_j2u_has_ju.c
new file mode 100644
index 0000000..b531c50
--- /dev/null
+++ b/libj2_j2u_has_ju.c
@@ -0,0 +1,40 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline int libj2_j2u_has_ju(const struct libj2_j2u *a, uintmax_t b);
+/* TODO Add man page */
+
+
+#else
+
+int
+main(void)
+{
+ struct libj2_j2u a;
+ uintmax_t h, i, j, b;
+ int expected;
+
+ for (h = 0; h < 10; h++) {
+ a.high = h;
+ for (i = 0; i < 128; i++) {
+ a.low = i;
+ for (b = 0; b < 128; b++) {
+ expected = 1;
+ for (j = 0; j < LIBJ2_JU_BIT; j++) {
+ if (((b & ~a.low) >> j) & 1U) {
+ expected = 0;
+ break;
+ }
+ }
+ EXPECT(libj2_j2u_has_ju(&a, b) == expected);
+ EXPECT(a.high == h);
+ EXPECT(a.low == i);
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_if_bit.c b/libj2_j2u_if_bit.c
new file mode 100644
index 0000000..1c17b70
--- /dev/null
+++ b/libj2_j2u_if_bit.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_if_bit(struct libj2_j2u *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_if_bit_to_j2u.c */
+
+#endif
diff --git a/libj2_j2u_if_bit_to_j2u.c b/libj2_j2u_if_bit_to_j2u.c
new file mode 100644
index 0000000..edd5193
--- /dev/null
+++ b/libj2_j2u_if_bit_to_j2u.c
@@ -0,0 +1,72 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_if_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res);
+/* 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
+check(uintmax_t high, uintmax_t low, unsigned shift)
+{
+ struct libj2_j2u a, r, expected;
+
+ a.high = high;
+ a.low = low;
+
+ libj2_ju_lsh_to_j2u(1U, shift, &expected);
+ libj2_j2u_if_j2u_to_j2u(&a, &expected, &expected);
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_j2u_if_bit_to_j2u(&a, shift, &r);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_if_bit_to_j2u(&r, shift, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_if_bit(&r, shift);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i < LIBJ2_J2U_BIT + 4U; i++) {
+ check(0, 0, i);
+ check(0, random_ju(), i);
+ check(0, UINTMAX_MAX, i);
+ check(random_ju(), 0, i);
+ check(random_ju(), random_ju(), i);
+ check(random_ju(), UINTMAX_MAX, i);
+ check(UINTMAX_MAX, 0, i);
+ check(UINTMAX_MAX, random_ju(), i);
+ check(UINTMAX_MAX, UINTMAX_MAX, i);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_imply_bit.c b/libj2_j2u_imply_bit.c
new file mode 100644
index 0000000..08191df
--- /dev/null
+++ b/libj2_j2u_imply_bit.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_imply_bit(struct libj2_j2u *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_imply_bit_to_j2u.c */
+
+#endif
diff --git a/libj2_j2u_imply_bit_to_j2u.c b/libj2_j2u_imply_bit_to_j2u.c
new file mode 100644
index 0000000..7dfc6d4
--- /dev/null
+++ b/libj2_j2u_imply_bit_to_j2u.c
@@ -0,0 +1,72 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_imply_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res);
+/* 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
+check(uintmax_t high, uintmax_t low, unsigned shift)
+{
+ struct libj2_j2u a, r, expected;
+
+ a.high = high;
+ a.low = low;
+
+ libj2_ju_lsh_to_j2u(1U, shift, &expected);
+ libj2_j2u_imply_j2u_to_j2u(&a, &expected, &expected);
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_j2u_imply_bit_to_j2u(&a, shift, &r);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_imply_bit_to_j2u(&r, shift, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_imply_bit(&r, shift);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i < LIBJ2_J2U_BIT + 4U; i++) {
+ check(0, 0, i);
+ check(0, random_ju(), i);
+ check(0, UINTMAX_MAX, i);
+ check(random_ju(), 0, i);
+ check(random_ju(), random_ju(), i);
+ check(random_ju(), UINTMAX_MAX, i);
+ check(UINTMAX_MAX, 0, i);
+ check(UINTMAX_MAX, random_ju(), i);
+ check(UINTMAX_MAX, UINTMAX_MAX, i);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_nand_bit.c b/libj2_j2u_nand_bit.c
new file mode 100644
index 0000000..d139564
--- /dev/null
+++ b/libj2_j2u_nand_bit.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_nand_bit(struct libj2_j2u *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_nand_bit_to_j2u.c */
+
+#endif
diff --git a/libj2_j2u_nand_bit_to_j2u.c b/libj2_j2u_nand_bit_to_j2u.c
new file mode 100644
index 0000000..30488ee
--- /dev/null
+++ b/libj2_j2u_nand_bit_to_j2u.c
@@ -0,0 +1,72 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_nand_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res);
+/* 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
+check(uintmax_t high, uintmax_t low, unsigned shift)
+{
+ struct libj2_j2u a, r, expected;
+
+ a.high = high;
+ a.low = low;
+
+ libj2_ju_lsh_to_j2u(1U, shift, &expected);
+ libj2_j2u_nand_j2u_to_j2u(&a, &expected, &expected);
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_j2u_nand_bit_to_j2u(&a, shift, &r);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_nand_bit_to_j2u(&r, shift, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_nand_bit(&r, shift);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i < LIBJ2_J2U_BIT + 4U; i++) {
+ check(0, 0, i);
+ check(0, random_ju(), i);
+ check(0, UINTMAX_MAX, i);
+ check(random_ju(), 0, i);
+ check(random_ju(), random_ju(), i);
+ check(random_ju(), UINTMAX_MAX, i);
+ check(UINTMAX_MAX, 0, i);
+ check(UINTMAX_MAX, random_ju(), i);
+ check(UINTMAX_MAX, UINTMAX_MAX, i);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_nif_bit.c b/libj2_j2u_nif_bit.c
new file mode 100644
index 0000000..379a051
--- /dev/null
+++ b/libj2_j2u_nif_bit.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_nif_bit(struct libj2_j2u *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_nif_bit_to_j2u.c */
+
+#endif
diff --git a/libj2_j2u_nif_bit_to_j2u.c b/libj2_j2u_nif_bit_to_j2u.c
new file mode 100644
index 0000000..f88a54e
--- /dev/null
+++ b/libj2_j2u_nif_bit_to_j2u.c
@@ -0,0 +1,72 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_nif_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res);
+/* 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
+check(uintmax_t high, uintmax_t low, unsigned shift)
+{
+ struct libj2_j2u a, r, expected;
+
+ a.high = high;
+ a.low = low;
+
+ libj2_ju_lsh_to_j2u(1U, shift, &expected);
+ libj2_j2u_nif_j2u_to_j2u(&a, &expected, &expected);
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_j2u_nif_bit_to_j2u(&a, shift, &r);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_nif_bit_to_j2u(&r, shift, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_nif_bit(&r, shift);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i < LIBJ2_J2U_BIT + 4U; i++) {
+ check(0, 0, i);
+ check(0, random_ju(), i);
+ check(0, UINTMAX_MAX, i);
+ check(random_ju(), 0, i);
+ check(random_ju(), random_ju(), i);
+ check(random_ju(), UINTMAX_MAX, i);
+ check(UINTMAX_MAX, 0, i);
+ check(UINTMAX_MAX, random_ju(), i);
+ check(UINTMAX_MAX, UINTMAX_MAX, i);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_nimply_bit.c b/libj2_j2u_nimply_bit.c
new file mode 100644
index 0000000..9ad7acd
--- /dev/null
+++ b/libj2_j2u_nimply_bit.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_nimply_bit(struct libj2_j2u *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_nimply_bit_to_j2u.c */
+
+#endif
diff --git a/libj2_j2u_nimply_bit_to_j2u.c b/libj2_j2u_nimply_bit_to_j2u.c
new file mode 100644
index 0000000..e7fc922
--- /dev/null
+++ b/libj2_j2u_nimply_bit_to_j2u.c
@@ -0,0 +1,72 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_nimply_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res);
+/* 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
+check(uintmax_t high, uintmax_t low, unsigned shift)
+{
+ struct libj2_j2u a, r, expected;
+
+ a.high = high;
+ a.low = low;
+
+ libj2_ju_lsh_to_j2u(1U, shift, &expected);
+ libj2_j2u_nimply_j2u_to_j2u(&a, &expected, &expected);
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_j2u_nimply_bit_to_j2u(&a, shift, &r);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_nimply_bit_to_j2u(&r, shift, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_nimply_bit(&r, shift);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i < LIBJ2_J2U_BIT + 4U; i++) {
+ check(0, 0, i);
+ check(0, random_ju(), i);
+ check(0, UINTMAX_MAX, i);
+ check(random_ju(), 0, i);
+ check(random_ju(), random_ju(), i);
+ check(random_ju(), UINTMAX_MAX, i);
+ check(UINTMAX_MAX, 0, i);
+ check(UINTMAX_MAX, random_ju(), i);
+ check(UINTMAX_MAX, UINTMAX_MAX, i);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_nor_bit.c b/libj2_j2u_nor_bit.c
new file mode 100644
index 0000000..e4d6471
--- /dev/null
+++ b/libj2_j2u_nor_bit.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_nor_bit(struct libj2_j2u *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_nor_bit_to_j2u.c */
+
+#endif
diff --git a/libj2_j2u_nor_bit_to_j2u.c b/libj2_j2u_nor_bit_to_j2u.c
new file mode 100644
index 0000000..aed8465
--- /dev/null
+++ b/libj2_j2u_nor_bit_to_j2u.c
@@ -0,0 +1,72 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_nor_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res);
+/* 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
+check(uintmax_t high, uintmax_t low, unsigned shift)
+{
+ struct libj2_j2u a, r, expected;
+
+ a.high = high;
+ a.low = low;
+
+ libj2_ju_lsh_to_j2u(1U, shift, &expected);
+ libj2_j2u_nor_j2u_to_j2u(&a, &expected, &expected);
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_j2u_nor_bit_to_j2u(&a, shift, &r);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_nor_bit_to_j2u(&r, shift, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_nor_bit(&r, shift);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i < LIBJ2_J2U_BIT + 4U; i++) {
+ check(0, 0, i);
+ check(0, random_ju(), i);
+ check(0, UINTMAX_MAX, i);
+ check(random_ju(), 0, i);
+ check(random_ju(), random_ju(), i);
+ check(random_ju(), UINTMAX_MAX, i);
+ check(UINTMAX_MAX, 0, i);
+ check(UINTMAX_MAX, random_ju(), i);
+ check(UINTMAX_MAX, UINTMAX_MAX, i);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_or_bit.c b/libj2_j2u_or_bit.c
new file mode 100644
index 0000000..109d5b9
--- /dev/null
+++ b/libj2_j2u_or_bit.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_or_bit(struct libj2_j2u *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_or_bit_to_j2u.c */
+
+#endif
diff --git a/libj2_j2u_or_bit_to_j2u.c b/libj2_j2u_or_bit_to_j2u.c
new file mode 100644
index 0000000..fc2a235
--- /dev/null
+++ b/libj2_j2u_or_bit_to_j2u.c
@@ -0,0 +1,72 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_or_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res);
+/* 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
+check(uintmax_t high, uintmax_t low, unsigned shift)
+{
+ struct libj2_j2u a, r, expected;
+
+ a.high = high;
+ a.low = low;
+
+ libj2_ju_lsh_to_j2u(1U, shift, &expected);
+ libj2_j2u_or_j2u_to_j2u(&a, &expected, &expected);
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_j2u_or_bit_to_j2u(&a, shift, &r);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_or_bit_to_j2u(&r, shift, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_or_bit(&r, shift);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i < LIBJ2_J2U_BIT + 4U; i++) {
+ check(0, 0, i);
+ check(0, random_ju(), i);
+ check(0, UINTMAX_MAX, i);
+ check(random_ju(), 0, i);
+ check(random_ju(), random_ju(), i);
+ check(random_ju(), UINTMAX_MAX, i);
+ check(UINTMAX_MAX, 0, i);
+ check(UINTMAX_MAX, random_ju(), i);
+ check(UINTMAX_MAX, UINTMAX_MAX, i);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_test_high_ju.c b/libj2_j2u_test_high_ju.c
index 0d03b40..5b73c5e 100644
--- a/libj2_j2u_test_high_ju.c
+++ b/libj2_j2u_test_high_ju.c
@@ -17,8 +17,8 @@ main(void)
for (h = 0; h < 10; h++) {
a.low = h;
for (i = 0; i < 128; i++) {
+ a.high = i;
for (j = 0; j < 128; j++) {
- a.high = i;
if (i & j)
EXPECT(libj2_j2u_test_high_ju(&a, j) == 1);
else
diff --git a/libj2_j2u_test_j2u.c b/libj2_j2u_test_j2u.c
index 682da56..1c6725b 100644
--- a/libj2_j2u_test_j2u.c
+++ b/libj2_j2u_test_j2u.c
@@ -24,6 +24,7 @@ set_pattern(struct libj2_j2u *a, unsigned off, unsigned mod)
}
}
+
CONST static int
expected(unsigned a_off, unsigned a_mod, unsigned b_off, unsigned b_mod)
{
@@ -45,6 +46,7 @@ expected(unsigned a_off, unsigned a_mod, unsigned b_off, unsigned b_mod)
return 0;
}
+
int
main(void)
{
diff --git a/libj2_j2u_test_ju.c b/libj2_j2u_test_ju.c
index 5752bf2..adb8dd4 100644
--- a/libj2_j2u_test_ju.c
+++ b/libj2_j2u_test_ju.c
@@ -17,8 +17,8 @@ main(void)
for (h = 0; h < 10; h++) {
a.high = h;
for (i = 0; i < 128; i++) {
+ a.low = i;
for (j = 0; j < 128; j++) {
- a.low = i;
if (i & j)
EXPECT(libj2_j2u_test_ju(&a, j) == 1);
else
diff --git a/libj2_j2u_xnor_bit.c b/libj2_j2u_xnor_bit.c
new file mode 100644
index 0000000..927a371
--- /dev/null
+++ b/libj2_j2u_xnor_bit.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_xnor_bit(struct libj2_j2u *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_xnor_bit_to_j2u.c */
+
+#endif
diff --git a/libj2_j2u_xnor_bit_to_j2u.c b/libj2_j2u_xnor_bit_to_j2u.c
new file mode 100644
index 0000000..cf91139
--- /dev/null
+++ b/libj2_j2u_xnor_bit_to_j2u.c
@@ -0,0 +1,72 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_xnor_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res);
+/* 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
+check(uintmax_t high, uintmax_t low, unsigned shift)
+{
+ struct libj2_j2u a, r, expected;
+
+ a.high = high;
+ a.low = low;
+
+ libj2_ju_lsh_to_j2u(1U, shift, &expected);
+ libj2_j2u_xnor_j2u_to_j2u(&a, &expected, &expected);
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_j2u_xnor_bit_to_j2u(&a, shift, &r);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_xnor_bit_to_j2u(&r, shift, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_xnor_bit(&r, shift);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i < LIBJ2_J2U_BIT + 4U; i++) {
+ check(0, 0, i);
+ check(0, random_ju(), i);
+ check(0, UINTMAX_MAX, i);
+ check(random_ju(), 0, i);
+ check(random_ju(), random_ju(), i);
+ check(random_ju(), UINTMAX_MAX, i);
+ check(UINTMAX_MAX, 0, i);
+ check(UINTMAX_MAX, random_ju(), i);
+ check(UINTMAX_MAX, UINTMAX_MAX, i);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_j2u_xor_bit.c b/libj2_j2u_xor_bit.c
new file mode 100644
index 0000000..d125e16
--- /dev/null
+++ b/libj2_j2u_xor_bit.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_xor_bit(struct libj2_j2u *a, unsigned b);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_j2u_xor_bit_to_j2u.c */
+
+#endif
diff --git a/libj2_j2u_xor_bit_to_j2u.c b/libj2_j2u_xor_bit_to_j2u.c
new file mode 100644
index 0000000..262648b
--- /dev/null
+++ b/libj2_j2u_xor_bit_to_j2u.c
@@ -0,0 +1,72 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_j2u_xor_bit_to_j2u(const struct libj2_j2u *a, unsigned b, struct libj2_j2u *res);
+/* 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
+check(uintmax_t high, uintmax_t low, unsigned shift)
+{
+ struct libj2_j2u a, r, expected;
+
+ a.high = high;
+ a.low = low;
+
+ libj2_ju_lsh_to_j2u(1U, shift, &expected);
+ libj2_j2u_xor_j2u_to_j2u(&a, &expected, &expected);
+
+ r = (struct libj2_j2u){111, 222};
+ libj2_j2u_xor_bit_to_j2u(&a, shift, &r);
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_xor_bit_to_j2u(&r, shift, &r);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+
+ r = a;
+ libj2_j2u_xor_bit(&r, shift);
+ EXPECT(libj2_j2u_eq_j2u(&r, &expected));
+}
+
+
+int
+main(void)
+{
+ unsigned i;
+
+ srand((unsigned)time(NULL));
+
+ for (i = 0; i < LIBJ2_J2U_BIT + 4U; i++) {
+ check(0, 0, i);
+ check(0, random_ju(), i);
+ check(0, UINTMAX_MAX, i);
+ check(random_ju(), 0, i);
+ check(random_ju(), random_ju(), i);
+ check(random_ju(), UINTMAX_MAX, i);
+ check(UINTMAX_MAX, 0, i);
+ check(UINTMAX_MAX, random_ju(), i);
+ check(UINTMAX_MAX, UINTMAX_MAX, i);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_kfs_j2u.c b/libj2_kfs_j2u.c
new file mode 100644
index 0000000..af07619
--- /dev/null
+++ b/libj2_kfs_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_kfs_j2u(struct libj2_j2u *a);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_cfs_j2u.c */
+
+#endif
diff --git a/libj2_kfs_j2u_to_j2u.c b/libj2_kfs_j2u_to_j2u.c
new file mode 100644
index 0000000..afc09fe
--- /dev/null
+++ b/libj2_kfs_j2u_to_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_kfs_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_kfs_j2u.c */
+
+#endif
diff --git a/libj2_kls_j2u.c b/libj2_kls_j2u.c
new file mode 100644
index 0000000..1c52f36
--- /dev/null
+++ b/libj2_kls_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_kls_j2u(struct libj2_j2u *a);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_cls_j2u.c */
+
+#endif
diff --git a/libj2_kls_j2u_to_j2u.c b/libj2_kls_j2u_to_j2u.c
new file mode 100644
index 0000000..4b13153
--- /dev/null
+++ b/libj2_kls_j2u_to_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_kls_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_kls_j2u.c */
+
+#endif
diff --git a/libj2_parity_j2u.c b/libj2_parity_j2u.c
new file mode 100644
index 0000000..5adafc6
--- /dev/null
+++ b/libj2_parity_j2u.c
@@ -0,0 +1,95 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline unsigned libj2_parity_j2u(const struct libj2_j2u *a);
+/* TODO Add man page */
+
+
+#else
+
+static uintmax_t
+random_ju(unsigned *popcount)
+{
+ size_t n = LIBJ2_JU_BIT;
+ uintmax_t r = 0;
+ *popcount = 0;
+ while (n--) {
+ if (rand() < rand()) {
+ r |= (uintmax_t)1 << n;
+ *popcount += 1U;
+ }
+ }
+ return r;
+}
+
+
+int
+main(void)
+{
+ struct libj2_j2u a;
+ uintmax_t high, low;
+ unsigned i, high_n, low_n;
+
+ srand((unsigned)time(NULL));
+
+ a.high = 0;
+ a.low = 0;
+ EXPECT(libj2_parity_j2u(&a) == 0);
+ EXPECT(a.high == 0);
+ EXPECT(a.low == 0);
+
+ a.high = 0;
+ a.low = UINTMAX_MAX;
+ EXPECT(libj2_parity_j2u(&a) == (LIBJ2_JU_BIT & 1U));
+ EXPECT(a.high == 0);
+ EXPECT(a.low == UINTMAX_MAX);
+
+ a.high = UINTMAX_MAX;
+ a.low = 0;
+ EXPECT(libj2_parity_j2u(&a) == (LIBJ2_JU_BIT & 1U));
+ EXPECT(a.high == UINTMAX_MAX);
+ EXPECT(a.low == 0);
+
+ a.high = UINTMAX_MAX;
+ a.low = UINTMAX_MAX;
+ EXPECT(libj2_parity_j2u(&a) == (LIBJ2_J2U_BIT & 1U));
+ EXPECT(a.high == UINTMAX_MAX);
+ EXPECT(a.low == UINTMAX_MAX);
+
+ for (i = 0; i < 256; i++) {
+ a.high = high = random_ju(&high_n);
+ a.low = low = random_ju(&low_n);
+ EXPECT(libj2_parity_j2u(&a) == ((high_n + low_n) & 1U));
+ EXPECT(a.high == high);
+ EXPECT(a.low == low);
+
+ a.high = high = random_ju(&high_n);
+ a.low = low = 0;
+ EXPECT(libj2_parity_j2u(&a) == (high_n & 1U));
+ EXPECT(a.high == high);
+ EXPECT(a.low == 0);
+
+ a.high = high = random_ju(&high_n);
+ a.low = low = UINTMAX_MAX;
+ EXPECT(libj2_parity_j2u(&a) == ((high_n + LIBJ2_JU_BIT) & 1U));
+ EXPECT(a.high == high);
+ EXPECT(a.low == UINTMAX_MAX);
+
+ a.high = high = 0;
+ a.low = low = random_ju(&low_n);
+ EXPECT(libj2_parity_j2u(&a) == (low_n & 1U));
+ EXPECT(a.high == 0);
+ EXPECT(a.low == low);
+
+ a.high = high = UINTMAX_MAX;
+ a.low = low = random_ju(&low_n);
+ EXPECT(libj2_parity_j2u(&a) == ((LIBJ2_JU_BIT + low_n) & 1U));
+ EXPECT(a.high == UINTMAX_MAX);
+ EXPECT(a.low == low);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/libj2_sfc_j2u.c b/libj2_sfc_j2u.c
new file mode 100644
index 0000000..1b91a7e
--- /dev/null
+++ b/libj2_sfc_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_sfc_j2u(struct libj2_j2u *a);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_cfs_j2u.c */
+
+#endif
diff --git a/libj2_sfc_j2u_to_j2u.c b/libj2_sfc_j2u_to_j2u.c
new file mode 100644
index 0000000..a1a9e17
--- /dev/null
+++ b/libj2_sfc_j2u_to_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_sfc_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_cfs_j2u.c */
+
+#endif
diff --git a/libj2_slc_j2u.c b/libj2_slc_j2u.c
new file mode 100644
index 0000000..500f633
--- /dev/null
+++ b/libj2_slc_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_slc_j2u(struct libj2_j2u *a);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_cls_j2u.c */
+
+#endif
diff --git a/libj2_slc_j2u_to_j2u.c b/libj2_slc_j2u_to_j2u.c
new file mode 100644
index 0000000..874be05
--- /dev/null
+++ b/libj2_slc_j2u_to_j2u.c
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+extern inline void libj2_slc_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res);
+/* TODO Add man page */
+
+
+#else
+
+CONST int main(void) { return 0; } /* Tested in libj2_cls_j2u.c */
+
+#endif