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