aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2026-05-17 14:28:21 +0200
committerMattias Andrée <m@maandree.se>2026-05-17 15:06:44 +0200
commitc77deb9313ee3c4ca9885191f5cb8e07d8d68ad3 (patch)
tree1de53628d7bffdac84992d8ae1e36d4bf0265c90
parentFix usage of va_arg (diff)
downloadlibj2-c77deb9313ee3c4ca9885191f5cb8e07d8d68ad3.tar.gz
libj2-c77deb9313ee3c4ca9885191f5cb8e07d8d68ad3.tar.bz2
libj2-c77deb9313ee3c4ca9885191f5cb8e07d8d68ad3.tar.xz
Fix undefined behaviour
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to '')
-rw-r--r--Makefile10
-rw-r--r--config-coverage-gcc.mk14
-rw-r--r--config.mk10
-rw-r--r--libj2/addition.h45
-rw-r--r--libj2/bit-shifting.h41
-rw-r--r--libj2/division.h64
-rw-r--r--libj2/mixed-comparison.h140
-rw-r--r--libj2/multiplication.h61
-rw-r--r--libj2/sign-shifting.h45
-rw-r--r--libj2/signed-comparison.h6
-rw-r--r--libj2/strings.h6
-rw-r--r--libj2/subtraction.h20
-rw-r--r--libj2_abs_j2i.c5
-rw-r--r--libj2_j2i_add_ji.c2
-rw-r--r--libj2_j2i_divmod_j2i_to_j2i.c2
-rw-r--r--libj2_j2i_lsh.c59
-rw-r--r--libj2_j2i_mul_ji.c19
-rw-r--r--libj2_j2i_sub_j2i.c27
-rw-r--r--libj2_j2i_sub_ji.c27
-rw-r--r--libj2_j2i_xor_sign.c11
-rw-r--r--libj2_j2u_divmod_j2u_to_j2u.c2
-rw-r--r--libj2_ji_sub_ji_to_j2i.c5
22 files changed, 435 insertions, 186 deletions
diff --git a/Makefile b/Makefile
index 57a5be8..942c481 100644
--- a/Makefile
+++ b/Makefile
@@ -600,19 +600,19 @@ $(TOBJ): $(HDR)
$(TEST): libj2.a
.c.o:
- $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS)
+ $(CC) -c -o $@ $< $(CFLAGS) $(COV_CFLAGS) $(CPPFLAGS) $(COV_CPPFLAGS)
.c.to:
- $(CC) -c -o $@ $< -DTEST $(CFLAGS) $(CPPFLAGS)
+ $(CC) -c -o $@ $< -DTEST $(CFLAGS) $(CPPFLAGS) $(COV_CPPFLAGS)
.to.t:
- $(CC) -o $@ $< libj2.a $(LDFLAGS)
+ $(CC) -o $@ $< libj2.a $(LDFLAGS) $(COV_LDFLAGS)
.c.t:
- $(CC) -o $@ $< libj2.a -DTEST $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
+ $(CC) -o $@ $< libj2.a -DTEST $(CFLAGS) $(CPPFLAGS) $(COV_CPPFLAGS) $(LDFLAGS) $(COV_LDFLAGS)
.c.lo:
- $(CC) -fPIC -c -o $@ $< $(CFLAGS) $(CPPFLAGS)
+ $(CC) -fPIC -c -o $@ $< $(CFLAGS) $(COV_CFLAGS) $(CPPFLAGS) $(COV_CPPFLAGS)
libj2.a: $(OBJ)
@rm -f -- $@
diff --git a/config-coverage-gcc.mk b/config-coverage-gcc.mk
new file mode 100644
index 0000000..8fc1905
--- /dev/null
+++ b/config-coverage-gcc.mk
@@ -0,0 +1,14 @@
+CONFIGFILE_PROPER = config.mk
+include $(CONFIGFILE_PROPER)
+
+CC = $(CC_PREFIX)gcc -std=c99
+GCOV = gcov
+
+COV_CPPFLAGS = -DCOVERAGE_TEST
+COV_CFLAGS = --coverage -g -O0
+COV_LDFLAGS = --coverage -g -O0
+
+LIBTEST_CHECK_PREFIX = :
+
+coverage: check
+ $(GCOV) -pr -- *.gcda 2>&1
diff --git a/config.mk b/config.mk
index f4adf12..9e3a2b4 100644
--- a/config.mk
+++ b/config.mk
@@ -3,6 +3,12 @@ MANPREFIX = $(PREFIX)/share/man
CC = c99
+COMMON_SANITIZE = -fsanitize=alignment,shift,signed-integer-overflow,object-size,null,undefined,bounds,address
+CLANG_SANITIZE = -O1 $(COMMON_SANITIZE),cfi -flto -fvisibility=hidden -fno-sanitize-trap=cfi
+GCC_SANITIZE = -O1 $(COMMON_SANITIZE)
+#SANITIZE = $(CLANG_SANITIZE)
+#SANITIZE = $(GCC_SANITIZE)
+
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE
-CFLAGS =
-LDFLAGS =
+CFLAGS = $(SANITIZE)
+LDFLAGS = $(SANITIZE)
diff --git a/libj2/addition.h b/libj2/addition.h
index c45716e..6d6e543 100644
--- a/libj2/addition.h
+++ b/libj2/addition.h
@@ -426,15 +426,17 @@ libj2_j2u_add_j2u_overflow_p(const struct libj2_j2u *a, const struct libj2_j2u *
inline void
libj2_j2i_add_ji(struct libj2_j2i *a, intmax_t b)
{
- struct libj2_j2u u;
+ struct libj2_j2u u, v;
if (b < 0) {
- u.high = UINTMAX_MAX;
- u.low = ~(uintmax_t)-(b + 1);
+ v.high = UINTMAX_MAX;
+ v.low = ~(uintmax_t)-(b + 1);
} else {
- u.high = 0;
- u.low = (uintmax_t)b;
+ v.high = 0;
+ v.low = (uintmax_t)b;
}
- libj2_j2u_add_j2u((void *)a, &u);
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2u_add_j2u(&u, &v);
+ libj2_j2u_to_j2i(&u, a);
}
@@ -452,7 +454,11 @@ libj2_j2i_add_ji(struct libj2_j2i *a, intmax_t b)
inline void
libj2_j2i_add_j2i(struct libj2_j2i *a, const struct libj2_j2i *b)
{
- libj2_j2u_add_j2u((void *)a, (const void *)b);
+ struct libj2_j2u u, v;
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2i_to_j2u(b, &v);
+ libj2_j2u_add_j2u(&u, &v);
+ libj2_j2u_to_j2i(&u, a);
}
@@ -472,15 +478,17 @@ libj2_j2i_add_j2i(struct libj2_j2i *a, const struct libj2_j2i *b)
inline void
libj2_j2i_add_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res)
{
- struct libj2_j2u u;
+ struct libj2_j2u u, v, r;
if (b < 0) {
- u.high = UINTMAX_MAX;
- u.low = ~(uintmax_t)-(b + 1);
+ v.high = UINTMAX_MAX;
+ v.low = ~(uintmax_t)-(b + 1);
} else {
- u.high = 0;
- u.low = (uintmax_t)b;
+ v.high = 0;
+ v.low = (uintmax_t)b;
}
- libj2_j2u_add_j2u_to_j2u((const void *)a, &u, (void *)res);
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2u_add_j2u_to_j2u(&u, &v, &r);
+ libj2_j2u_to_j2i(&r, res);
}
@@ -499,7 +507,11 @@ libj2_j2i_add_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i
inline void
libj2_j2i_add_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res)
{
- libj2_j2u_add_j2u_to_j2u((const void *)a, (const void *)b, (void *)res);
+ struct libj2_j2u u, v, r;
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2i_to_j2u(b, &v);
+ libj2_j2u_add_j2u_to_j2u(&u, &v, &r);
+ libj2_j2u_to_j2i(&r, res);
}
@@ -520,7 +532,7 @@ libj2_j2i_add_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, s
inline void
libj2_ji_add_ji_to_j2i(intmax_t a, intmax_t b, struct libj2_j2i *res)
{
- struct libj2_j2u u, v;
+ struct libj2_j2u u, v, r;
if (a < 0) {
u.high = UINTMAX_MAX;
u.low = ~(uintmax_t)-(a + 1);
@@ -535,7 +547,8 @@ libj2_ji_add_ji_to_j2i(intmax_t a, intmax_t b, struct libj2_j2i *res)
v.high = 0;
v.low = (uintmax_t)b;
}
- libj2_j2u_add_j2u_to_j2u(&u, &v, (void *)res);
+ libj2_j2u_add_j2u_to_j2u(&u, &v, &r);
+ libj2_j2u_to_j2i(&r, res);
}
diff --git a/libj2/bit-shifting.h b/libj2/bit-shifting.h
index 515a1d4..54c6a22 100644
--- a/libj2/bit-shifting.h
+++ b/libj2/bit-shifting.h
@@ -748,7 +748,10 @@ libj2_ju_rsh_underflow_p(uintmax_t a, unsigned b)
inline void
libj2_j2i_lsh(struct libj2_j2i *a, unsigned b)
{
- libj2_j2u_lsh((void *)a, b);
+ struct libj2_j2u u;
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2u_lsh(&u, b);
+ libj2_j2u_to_j2i(&u, a);
}
@@ -774,7 +777,10 @@ libj2_j2i_lsh(struct libj2_j2i *a, unsigned b)
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);
+ struct libj2_j2u u, r;
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2u_lsh_to_j2u(&u, b, &r);
+ libj2_j2u_to_j2i(&r, res);
}
@@ -1037,8 +1043,11 @@ libj2_ji_lsh_to_j2i_overflow(intmax_t a, unsigned b, struct libj2_j2i *res)
inline void
libj2_j2i_rsh_to_j2i(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *res)
{
+ struct libj2_j2u u, r;
if (!libj2_j2i_is_negative(a)) {
- libj2_j2u_rsh_to_j2u((const void *)a, b, (void *)res);
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2u_rsh_to_j2u(&u, b, &r);
+ libj2_j2u_to_j2i(&r, res);
} else if (b >= LIBJ2_J2U_BIT) {
res->high = UINTMAX_MAX;
res->low = UINTMAX_MAX;
@@ -1052,7 +1061,9 @@ libj2_j2i_rsh_to_j2i(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *re
res->low >>= b;
res->low |= UINTMAX_MAX << (LIBJ2_JU_BIT - b);
} else if (b) {
- libj2_j2u_rsh_to_j2u((const void *)a, b, (void *)res);
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2u_rsh_to_j2u(&u, b, &r);
+ libj2_j2u_to_j2i(&r, res);
res->high |= UINTMAX_MAX << (LIBJ2_JU_BIT - b);
} else {
*res = *a;
@@ -1146,14 +1157,20 @@ libj2_ji_rsh_to_j2i(intmax_t a, unsigned b, struct libj2_j2i *res)
inline int
libj2_j2i_rsh_to_j2i_underflow(const struct libj2_j2i *a, unsigned b, struct libj2_j2i *res)
{
+ struct libj2_j2u u, r;
+ libj2_j2i_to_j2u(a, &u);
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);
+ libj2_not_j2u_to_j2u(&u, &r);
+ underflow = libj2_j2u_rsh_underflow(&r, b);
+ libj2_not_j2u(&r);
+ libj2_j2u_to_j2i(&r, res);
return -underflow;
} else {
- return libj2_j2u_rsh_to_j2u_underflow((const void *)a, b, (void *)res);
+ int ret;
+ ret = libj2_j2u_rsh_to_j2u_underflow(&u, b, &r);
+ libj2_j2u_to_j2i(&r, res);
+ return ret;
}
}
@@ -1254,12 +1271,12 @@ libj2_ji_rsh_to_j2i_underflow(intmax_t a, unsigned b, struct libj2_j2i *res)
LIBJ2_PURE_ inline int
libj2_j2i_rsh_underflow_p(const struct libj2_j2i *a, unsigned b)
{
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
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);
+ libj2_not_j2u(&u);
+ return -libj2_j2u_rsh_underflow_p(&u, b);
} else {
- return libj2_j2u_rsh_underflow_p((const void *)a, b);
+ return libj2_j2u_rsh_underflow_p(&u, b);
}
}
diff --git a/libj2/division.h b/libj2/division.h
index 603a1b6..688768d 100644
--- a/libj2/division.h
+++ b/libj2/division.h
@@ -349,7 +349,7 @@ libj2_j2u_div_j2u_to_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b, s
*
* @since 1.0
*/
-inline uintmax_t
+LIBJ2_PURE_ inline uintmax_t
libj2_j2u_div_j2u_return(const struct libj2_j2u *a, const struct libj2_j2u *b)
{
struct libj2_j2u c = *a;
@@ -441,7 +441,7 @@ libj2_j2u_div_ju_to_j2u(const struct libj2_j2u *a, uintmax_t b, struct libj2_j2u
*
* @since 1.0
*/
-inline uintmax_t
+LIBJ2_PURE_ inline uintmax_t
libj2_j2u_div_ju_return(const struct libj2_j2u *a, uintmax_t b)
{
struct libj2_j2u c = *a;
@@ -733,14 +733,17 @@ libj2_j2i_divmod_j2i_to_j2i(struct libj2_j2i *a, const struct libj2_j2i *b, stru
{
int a_neg = libj2_j2i_is_negative(a);
int b_neg = libj2_j2i_is_negative(b);
- struct libj2_j2u u;
+ struct libj2_j2u u, v, rq;
if (b_neg)
- libj2_minus_j2i_to_j2u(b, &u);
+ libj2_minus_j2i_to_j2u(b, &v);
else
- libj2_j2i_to_j2u(b, &u);
+ libj2_j2i_to_j2u(b, &v);
if (a_neg)
libj2_minus_j2i(a);
- libj2_j2u_divmod_j2u_to_j2u((void *)a, &u, (void *)res_q);
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2u_divmod_j2u_to_j2u(&u, &v, &rq);
+ libj2_j2u_to_j2i(&u, a);
+ libj2_j2u_to_j2i(&rq, res_q);
if (a_neg)
libj2_minus_j2i(a);
if (a_neg != b_neg)
@@ -851,14 +854,17 @@ inline intmax_t
libj2_j2i_divmod_ji(struct libj2_j2i *a, intmax_t b)
{
int a_neg = libj2_j2i_is_negative(a);
- uintmax_t u, q;
+ struct libj2_j2u u;
+ uintmax_t v, q;
if (a_neg)
libj2_minus_j2i(a);
if (b < 0)
- u = (uintmax_t)-(b + 1) + 1U;
+ v = (uintmax_t)-(b + 1) + 1U;
else
- u = (uintmax_t)b;
- q = libj2_j2u_divmod_ju((void *)a, u);
+ v = (uintmax_t)b;
+ libj2_j2i_to_j2u(a, &u);
+ q = libj2_j2u_divmod_ju(&u, v);
+ libj2_j2u_to_j2i(&u, a);
if (a_neg)
libj2_minus_j2i(a);
return a_neg != (b < 0) ? -(intmax_t)q : (intmax_t)q;
@@ -891,15 +897,18 @@ inline void
libj2_j2i_divmod_ji_to_j2i(struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res_q)
{
int a_neg = libj2_j2i_is_negative(a);
- uintmax_t u;
+ struct libj2_j2u u;
+ uintmax_t v;
if (a_neg)
libj2_minus_j2i(a);
if (b < 0)
- u = (uintmax_t)-(b + 1) + 1U;
+ v = (uintmax_t)-(b + 1) + 1U;
else
- u = (uintmax_t)b;
- res_q->high = a->high / u;
- res_q->low = libj2_j2u_divmod_ju((void *)a, u);
+ v = (uintmax_t)b;
+ libj2_j2i_to_j2u(a, &u);
+ res_q->high = a->high / v;
+ res_q->low = libj2_j2u_divmod_ju(&u, v);
+ libj2_j2u_to_j2i(&u, a);
if (a_neg)
libj2_minus_j2i(a);
if (a_neg != (b < 0))
@@ -933,17 +942,19 @@ inline void
libj2_j2i_divmod_ji_to_j2i_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res_q, struct libj2_j2i *res_r)
{
int a_neg = libj2_j2i_is_negative(a);
+ struct libj2_j2u rr;
uintmax_t u;
if (a_neg)
- libj2_minus_j2i_to_j2u(a, (void *)res_r);
+ libj2_minus_j2i_to_j2u(a, &rr);
else
- *res_r = *a;
+ libj2_j2i_to_j2u(a, &rr);
if (b < 0)
u = (uintmax_t)-(b + 1) + 1U;
else
u = (uintmax_t)b;
- res_q->high = res_r->high / u;
- res_q->low = libj2_j2u_divmod_ju((void *)res_r, u);
+ res_q->high = rr.high / u;
+ res_q->low = libj2_j2u_divmod_ju(&rr, u);
+ libj2_j2u_to_j2i(&rr, res_r);
if (a_neg)
libj2_minus_j2i(res_r);
if (a_neg != (b < 0))
@@ -1088,7 +1099,7 @@ libj2_j2i_div_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, s
*
* @since 1.1
*/
-inline intmax_t
+LIBJ2_PURE_ inline intmax_t
libj2_j2i_div_j2i_return(const struct libj2_j2i *a, const struct libj2_j2i *b)
{
struct libj2_j2i c = *a;
@@ -1188,7 +1199,7 @@ libj2_j2i_div_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i
*
* @since 1.1
*/
-inline intmax_t
+LIBJ2_PURE_ inline intmax_t
libj2_j2i_div_ji_return(const struct libj2_j2i *a, intmax_t b)
{
struct libj2_j2i c = *a;
@@ -1287,14 +1298,17 @@ inline void
libj2_j2i_mod_ji(struct libj2_j2i *a, intmax_t b)
{
int a_neg = libj2_j2i_is_negative(a);
- uintmax_t u;
+ struct libj2_j2u u;
+ uintmax_t v;
if (a_neg)
libj2_minus_j2i(a);
if (b < 0)
- u = (uintmax_t)-(b + 1) + 1U;
+ v = (uintmax_t)-(b + 1) + 1U;
else
- u = (uintmax_t)b;
- libj2_j2u_mod_ju((void *)a, u);
+ v = (uintmax_t)b;
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2u_mod_ju(&u, v);
+ libj2_j2u_to_j2i(&u, a);
if (a_neg)
libj2_minus_j2i(a);
}
diff --git a/libj2/mixed-comparison.h b/libj2/mixed-comparison.h
index dedf18d..525e069 100644
--- a/libj2/mixed-comparison.h
+++ b/libj2/mixed-comparison.h
@@ -19,7 +19,10 @@
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 1;
+ return libj2_j2u_lt_j2u(&u, b);
}
@@ -38,7 +41,10 @@ libj2_j2i_lt_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 1;
+ return libj2_j2u_le_j2u(&u, b);
}
@@ -57,7 +63,10 @@ libj2_j2i_le_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 0;
+ return libj2_j2u_gt_j2u(&u, b);
}
@@ -76,7 +85,10 @@ libj2_j2i_gt_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 0;
+ return libj2_j2u_ge_j2u(&u, b);
}
@@ -95,7 +107,10 @@ libj2_j2i_ge_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 0;
+ return libj2_j2u_eq_j2u(&u, b);
}
@@ -114,7 +129,10 @@ libj2_j2i_eq_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 1;
+ return libj2_j2u_ne_j2u(&u, b);
}
@@ -136,7 +154,10 @@ libj2_j2i_ne_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return -1;
+ return libj2_j2u_cmp_j2u(&u, b);
}
@@ -155,7 +176,10 @@ libj2_j2i_cmp_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b)
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);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 0;
+ return libj2_j2u_lt_j2u(a, &u);
}
@@ -174,7 +198,10 @@ libj2_j2u_lt_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
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);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 0;
+ return libj2_j2u_le_j2u(a, &u);
}
@@ -193,7 +220,10 @@ libj2_j2u_le_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
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);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 1;
+ return libj2_j2u_gt_j2u(a, &u);
}
@@ -212,7 +242,10 @@ libj2_j2u_gt_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
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);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 1;
+ return libj2_j2u_ge_j2u(a, &u);
}
@@ -231,7 +264,10 @@ libj2_j2u_ge_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
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);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 0;
+ return libj2_j2u_eq_j2u(a, &u);
}
@@ -250,7 +286,10 @@ libj2_j2u_eq_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
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);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 1;
+ return libj2_j2u_ne_j2u(a, &u);
}
@@ -272,7 +311,10 @@ libj2_j2u_ne_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b)
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);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return +1;
+ return libj2_j2u_cmp_j2u(a, &u);
}
@@ -427,7 +469,10 @@ libj2_ji_cmp_j2u(intmax_t a, const struct libj2_j2u *b)
LIBJ2_PURE_ inline int
libj2_ju_lt_j2i(uintmax_t a, const struct libj2_j2i *b)
{
- return libj2_j2i_is_negative(b) ? 0 : libj2_ju_lt_j2u(a, (const void *)b);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 0;
+ return libj2_ju_lt_j2u(a, &u);
}
@@ -446,7 +491,10 @@ libj2_ju_lt_j2i(uintmax_t a, const struct libj2_j2i *b)
LIBJ2_PURE_ inline int
libj2_ju_le_j2i(uintmax_t a, const struct libj2_j2i *b)
{
- return libj2_j2i_is_negative(b) ? 0 : libj2_ju_le_j2u(a, (const void *)b);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 0;
+ return libj2_ju_le_j2u(a, &u);
}
@@ -465,7 +513,10 @@ libj2_ju_le_j2i(uintmax_t a, const struct libj2_j2i *b)
LIBJ2_PURE_ inline int
libj2_ju_gt_j2i(uintmax_t a, const struct libj2_j2i *b)
{
- return libj2_j2i_is_negative(b) ? 1 : libj2_ju_gt_j2u(a, (const void *)b);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 1;
+ return libj2_ju_gt_j2u(a, &u);
}
@@ -484,7 +535,10 @@ libj2_ju_gt_j2i(uintmax_t a, const struct libj2_j2i *b)
LIBJ2_PURE_ inline int
libj2_ju_ge_j2i(uintmax_t a, const struct libj2_j2i *b)
{
- return libj2_j2i_is_negative(b) ? 1 : libj2_ju_ge_j2u(a, (const void *)b);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 1;
+ return libj2_ju_ge_j2u(a, &u);
}
@@ -503,7 +557,10 @@ libj2_ju_ge_j2i(uintmax_t a, const struct libj2_j2i *b)
LIBJ2_PURE_ inline int
libj2_ju_eq_j2i(uintmax_t a, const struct libj2_j2i *b)
{
- return libj2_j2i_is_negative(b) ? 0 : libj2_ju_eq_j2u(a, (const void *)b);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 0;
+ return libj2_ju_eq_j2u(a, &u);
}
@@ -522,7 +579,10 @@ libj2_ju_eq_j2i(uintmax_t a, const struct libj2_j2i *b)
LIBJ2_PURE_ inline int
libj2_ju_ne_j2i(uintmax_t a, const struct libj2_j2i *b)
{
- return libj2_j2i_is_negative(b) ? 1 : libj2_ju_ne_j2u(a, (const void *)b);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return 1;
+ return libj2_ju_ne_j2u(a, &u);
}
@@ -544,7 +604,10 @@ libj2_ju_ne_j2i(uintmax_t a, const struct libj2_j2i *b)
LIBJ2_PURE_ inline int
libj2_ju_cmp_j2i(uintmax_t a, const struct libj2_j2i *b)
{
- return libj2_j2i_is_negative(b) ? +1 : libj2_ju_cmp_j2u(a, (const void *)b);
+ struct libj2_j2u u = {.high = b->high, .low = b->low};
+ if (libj2_j2i_is_negative(b))
+ return +1;
+ return libj2_ju_cmp_j2u(a, &u);
}
@@ -563,7 +626,10 @@ libj2_ju_cmp_j2i(uintmax_t a, const struct libj2_j2i *b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 1;
+ return libj2_j2u_lt_ju(&u, b);
}
@@ -582,7 +648,10 @@ libj2_j2i_lt_ju(const struct libj2_j2i *a, uintmax_t b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 1;
+ return libj2_j2u_le_ju(&u, b);
}
@@ -601,7 +670,10 @@ libj2_j2i_le_ju(const struct libj2_j2i *a, uintmax_t b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 0;
+ return libj2_j2u_gt_ju(&u, b);
}
@@ -620,7 +692,10 @@ libj2_j2i_gt_ju(const struct libj2_j2i *a, uintmax_t b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 0;
+ return libj2_j2u_ge_ju(&u, b);
}
@@ -639,7 +714,10 @@ libj2_j2i_ge_ju(const struct libj2_j2i *a, uintmax_t b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 0;
+ return libj2_j2u_eq_ju(&u, b);
}
@@ -658,7 +736,10 @@ libj2_j2i_eq_ju(const struct libj2_j2i *a, uintmax_t b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return 1;
+ return libj2_j2u_ne_ju(&u, b);
}
@@ -680,7 +761,10 @@ libj2_j2i_ne_ju(const struct libj2_j2i *a, uintmax_t b)
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);
+ struct libj2_j2u u = {.high = a->high, .low = a->low};
+ if (libj2_j2i_is_negative(a))
+ return -1;
+ return libj2_j2u_cmp_ju(&u, b);
}
diff --git a/libj2/multiplication.h b/libj2/multiplication.h
index a80161b..40d9eb0 100644
--- a/libj2/multiplication.h
+++ b/libj2/multiplication.h
@@ -667,18 +667,24 @@ libj2_ju_mul_j2u_to_j2u_overflow_p(uintmax_t a, const struct libj2_j2u *b, struc
inline int
libj2_j2i_mul_j2i_overflow(struct libj2_j2i *a, const struct libj2_j2i *b)
{
- struct libj2_j2u t;
+ struct libj2_j2u u, v;
int overflow, neg = libj2_j2i_is_negative(a);
if (neg)
libj2_minus_j2i(a);
+ libj2_j2i_to_j2u(a, &u);
if (a == b) {
neg = 0;
- } else if (libj2_j2i_is_negative(b)) {
- neg ^= 1;
- libj2_minus_j2i_to_j2u(b, &t);
- b = (const void *)&t;
+ overflow = libj2_j2u_mul_j2u_overflow(&u, &u);
+ } else {
+ if (libj2_j2i_is_negative(b)) {
+ neg ^= 1;
+ libj2_minus_j2i_to_j2u(b, &v);
+ } else {
+ libj2_j2i_to_j2u(b, &v);
+ }
+ overflow = libj2_j2u_mul_j2u_overflow(&u, &v);
}
- overflow = libj2_j2u_mul_j2u_overflow((void *)a, (const void *)b);
+ libj2_j2u_to_j2i(&u, a);
if (neg) {
if (overflow)
overflow = -overflow;
@@ -823,7 +829,11 @@ inline void
libj2_ji_mul_ji_to_j2i(intmax_t a, intmax_t b, struct libj2_j2i *res)
{
int neg = (a < 0) ^ (b < 0);
- libj2_ju_mul_ju_to_j2u((uintmax_t)(a < 0 ? -a : a), (uintmax_t)(b < 0 ? -b : b), (void *)res);
+ uintmax_t u = a < 0 ? (uintmax_t)-(a + 1) + 1U : (uintmax_t)a;
+ uintmax_t v = b < 0 ? (uintmax_t)-(b + 1) + 1U : (uintmax_t)b;
+ struct libj2_j2u r;
+ libj2_ju_mul_ju_to_j2u(u, v, &r);
+ libj2_j2u_to_j2i(&r, res);
if (neg)
libj2_minus_j2i(res);
}
@@ -847,13 +857,19 @@ inline void
libj2_j2i_mul_ji(struct libj2_j2i *a, intmax_t b)
{
int neg = libj2_j2i_is_negative(a);
+ struct libj2_j2u u;
+ uintmax_t v;
if (neg)
libj2_minus_j2i(a);
if (b < 0) {
neg ^= 1;
- b = -b;
+ v = (uintmax_t)-(b + 1) + 1U;
+ } else {
+ v = (uintmax_t)b;
}
- libj2_j2u_mul_ju((void *)a, (uintmax_t)b);
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2u_mul_ju(&u, v);
+ libj2_j2u_to_j2i(&u, a);
if (neg)
libj2_minus_j2i(a);
}
@@ -1000,18 +1016,24 @@ libj2_ji_mul_j2i_to_j2i_overflow(intmax_t a, const struct libj2_j2i *b, struct l
inline void
libj2_j2i_mul_j2i(struct libj2_j2i *a, const struct libj2_j2i *b)
{
- struct libj2_j2u t;
+ struct libj2_j2u u, v;
int neg = libj2_j2i_is_negative(a);
if (neg)
libj2_minus_j2i(a);
+ libj2_j2i_to_j2u(a, &u);
if (a == b) {
neg = 0;
- } else if (libj2_j2i_is_negative(b)) {
- neg ^= 1;
- libj2_minus_j2i_to_j2u(b, &t);
- b = (const void *)&t;
+ libj2_j2u_mul_j2u(&u, &u);
+ } else {
+ if (libj2_j2i_is_negative(b)) {
+ neg ^= 1;
+ libj2_minus_j2i_to_j2u(b, &v);
+ } else {
+ libj2_j2i_to_j2u(b, &v);
+ }
+ libj2_j2u_mul_j2u(&u, &v);
}
- libj2_j2u_mul_j2u((void *)a, (const void *)b);
+ libj2_j2u_to_j2i(&u, a);
if (neg)
libj2_minus_j2i(a);
}
@@ -1040,12 +1062,15 @@ libj2_j2i_mul_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, s
b = a;
goto common;
} else if (a == b) {
+ struct libj2_j2u u, r;
if (libj2_j2i_is_negative(a)) {
- libj2_minus_j2i_to_j2u(a, (void *)res);
- libj2_j2u_mul_j2u((void *)res, (const void *)res);
+ libj2_minus_j2i_to_j2u(a, &r);
+ libj2_j2u_mul_j2u(&r, &r);
} else {
- libj2_j2u_mul_j2u_to_j2u((const void *)a, (const void *)b, (void *)res);
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2u_mul_j2u_to_j2u(&u, &u, &r);
}
+ libj2_j2u_to_j2i(&r, res);
} else {
*res = *a;
goto common;
diff --git a/libj2/sign-shifting.h b/libj2/sign-shifting.h
index 75a4620..9ffd301 100644
--- a/libj2/sign-shifting.h
+++ b/libj2/sign-shifting.h
@@ -61,7 +61,10 @@ libj2_minus_j2u(struct libj2_j2u *a)
inline void
libj2_minus_j2i_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res)
{
- libj2_minus_j2u_to_j2u((const void *)a, (void *)res);
+ res->high = -a->high;
+ if (a->low)
+ res->high -= 1U;
+ res->low = -a->low;
}
@@ -81,7 +84,7 @@ libj2_minus_j2i_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res)
inline void
libj2_minus_j2i(struct libj2_j2i *a)
{
- libj2_minus_j2u_to_j2u((const void *)a, (void *)a);
+ libj2_minus_j2i_to_j2i(a, a);
}
@@ -103,7 +106,10 @@ libj2_minus_j2i(struct libj2_j2i *a)
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);
+ res->high = -a->high;
+ if (a->low)
+ res->high -= 1U;
+ res->low = -a->low;
}
@@ -126,7 +132,10 @@ libj2_minus_j2i_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res)
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);
+ res->high = -a->high;
+ if (a->low)
+ res->high -= 1U;
+ res->low = -a->low;
}
@@ -186,7 +195,10 @@ libj2_abs_j2i(struct libj2_j2i *a)
inline void
libj2_abs_j2i_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res)
{
- libj2_abs_j2i_to_j2i(a, (void *)res);
+ if (libj2_j2i_is_negative(a))
+ libj2_minus_j2i_to_j2u(a, res);
+ else
+ libj2_j2i_to_j2u(a, res);
}
@@ -240,17 +252,18 @@ libj2_minus_abs_j2i(struct libj2_j2i *a)
*
* @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
+ if (libj2_j2i_is_negative(a)) {
+ res->high = ~a->high;
+ res->low = ~a->low;
+ } else {
*res = *a;
+ }
}
@@ -266,7 +279,13 @@ libj2_j2i_xor_sign_to_j2i(const struct libj2_j2i *a, struct libj2_j2i *res)
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 (libj2_j2i_is_negative(a)) {
+ res->high = ~a->high;
+ res->low = ~a->low;
+ } else {
+ res->high = a->high;
+ res->low = a->low;
+ }
}
@@ -283,6 +302,8 @@ libj2_j2i_xor_sign_to_j2u(const struct libj2_j2i *a, struct libj2_j2u *res)
inline void
libj2_j2i_xor_sign(struct libj2_j2i *a)
{
- if (libj2_j2i_is_negative(a))
- libj2_not_j2u((void *)a);
+ if (libj2_j2i_is_negative(a)) {
+ a->high = ~a->high;
+ a->low = ~a->low;
+ }
}
diff --git a/libj2/signed-comparison.h b/libj2/signed-comparison.h
index 9d8025c..916edac 100644
--- a/libj2/signed-comparison.h
+++ b/libj2/signed-comparison.h
@@ -25,7 +25,7 @@ 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);
+ return a->high < b->high ? -1 : a->high > b->high ? +1 : a->low < b->low ? -1 : a->low > b->low;
}
@@ -120,7 +120,7 @@ libj2_j2i_ge_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b)
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);
+ return a->high == b->high && a->low == b->low;
}
@@ -139,7 +139,7 @@ libj2_j2i_eq_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b)
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);
+ return a->high != b->high || a->low != b->low;
}
diff --git a/libj2/strings.h b/libj2/strings.h
index 05ccc80..4b77725 100644
--- a/libj2/strings.h
+++ b/libj2/strings.h
@@ -197,8 +197,10 @@ libj2_j2i_to_str(const struct libj2_j2i *a, char *buf, size_t bufsize, const cha
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);
+ if (!libj2_j2i_is_negative(a)) {
+ libj2_j2i_to_j2u(a, &t);
+ return libj2_j2u_to_str(&t, buf, bufsize, digits);
+ }
libj2_minus_j2i_to_j2u(a, &t);
if (bufsize > 1U) {
bufsize -= 1U;
diff --git a/libj2/subtraction.h b/libj2/subtraction.h
index c4291d1..2a7ff06 100644
--- a/libj2/subtraction.h
+++ b/libj2/subtraction.h
@@ -672,7 +672,11 @@ libj2_j2u_rsub_ju_overflow_p(const struct libj2_j2u *a, uintmax_t b)
inline void
libj2_j2i_sub_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res)
{
- libj2_j2u_sub_j2u_to_j2u((const void *)a, (const void *)b, (void *)res);
+ struct libj2_j2u u, v, r;
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2i_to_j2u(b, &v);
+ libj2_j2u_sub_j2u_to_j2u(&u, &v, &r);
+ libj2_j2u_to_j2i(&r, res);
}
@@ -762,7 +766,11 @@ libj2_ji_sub_ji_to_j2i(intmax_t a, intmax_t b, struct libj2_j2i *res)
inline void
libj2_j2i_sub_j2i(struct libj2_j2i *a, const struct libj2_j2i *b)
{
- libj2_j2u_sub_j2u((void *)a, (const void *)b);
+ struct libj2_j2u u, v;
+ libj2_j2i_to_j2u(a, &u);
+ libj2_j2i_to_j2u(b, &v);
+ libj2_j2u_sub_j2u(&u, &v);
+ libj2_j2u_to_j2i(&u, a);
}
@@ -1240,7 +1248,7 @@ libj2_j2u_rsub_j2u_borrow(struct libj2_j2u *a, const struct libj2_j2u *b, int *b
* @param a The minuend (left-hand)
* @param b The subtrahend (right-hand)
* @param res The output parameter for the difference
- * @param borrow Shall point to the value +1, -1, or 0:
+ * @param carry Shall point to the value +1, -1, or 0:
* the result will be incremented
* with the value. When the function
* returns, it will be updated to +1
@@ -1369,10 +1377,12 @@ libj2_j2u_abs_diff_j2u(struct libj2_j2u *a, const struct libj2_j2u *b)
inline void
libj2_j2i_abs_diff_j2i_to_j2u(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2u *res)
{
+ struct libj2_j2i r;
if (libj2_j2i_ge_j2i(a, b))
- libj2_j2i_sub_j2i_to_j2i(a, b, (void *)res);
+ libj2_j2i_sub_j2i_to_j2i(a, b, &r);
else
- libj2_j2i_sub_j2i_to_j2i(b, a, (void *)res);
+ libj2_j2i_sub_j2i_to_j2i(b, a, &r);
+ libj2_j2i_to_j2u(&r, res);
}
diff --git a/libj2_abs_j2i.c b/libj2_abs_j2i.c
index e3c9d33..13965e0 100644
--- a/libj2_abs_j2i.c
+++ b/libj2_abs_j2i.c
@@ -88,7 +88,7 @@ check_min(void)
const uintmax_t high = ~(UINTMAX_MAX >> 1);
const uintmax_t low = 0;
struct libj2_j2i a, r;
- struct libj2_j2u u;
+ struct libj2_j2u u, v;
a.high = high;
a.low = low;
@@ -110,7 +110,8 @@ check_min(void)
libj2_abs_j2i_to_j2u((const struct libj2_j2i *)&a, &u);
EXPECT(a.high == high);
EXPECT(a.low == low);
- EXPECT(libj2_j2u_eq_j2u((const void *)&a, &u));
+ libj2_j2i_to_j2u(&a, &v);
+ EXPECT(libj2_j2u_eq_j2u(&v, &u));
a.high = high;
a.low = low;
diff --git a/libj2_j2i_add_ji.c b/libj2_j2i_add_ji.c
index d1e7e32..1fd5af9 100644
--- a/libj2_j2i_add_ji.c
+++ b/libj2_j2i_add_ji.c
@@ -65,7 +65,7 @@ self_check(uintmax_t a_high, uintmax_t a_low, uintmax_t b_high, uintmax_t b_low,
static void
check(uintmax_t a_high, uintmax_t a_low, uintmax_t ub)
{
- intmax_t b = ub > (uintmax_t)INTMAX_MAX ? (intmax_t)ub : -(intmax_t)~ub - 1;
+ intmax_t b = ub > (uintmax_t)INTMAX_MAX ? -(intmax_t)~ub - 1 : (intmax_t)ub;
struct libj2_j2i a, r;
uintmax_t expected_high, expected_low;
int expected_overflow;
diff --git a/libj2_j2i_divmod_j2i_to_j2i.c b/libj2_j2i_divmod_j2i_to_j2i.c
index 1a55f41..ef46f97 100644
--- a/libj2_j2i_divmod_j2i_to_j2i.c
+++ b/libj2_j2i_divmod_j2i_to_j2i.c
@@ -383,7 +383,7 @@ check(const struct libj2_j2i *a, const struct libj2_j2i *b)
v.high = random_ju();
v.low = random_ju();
} while (!v.high && !v.low);
- b = &u;
+ b = &v;
}
check_manual(a, b, NULL, NULL);
}
diff --git a/libj2_j2i_lsh.c b/libj2_j2i_lsh.c
index aff86bb..0184e2d 100644
--- a/libj2_j2i_lsh.c
+++ b/libj2_j2i_lsh.c
@@ -90,7 +90,7 @@ int
main(void)
{
struct libj2_j2i a, b;
- struct libj2_j2u t;
+ struct libj2_j2u u, v, t;
unsigned i, j, k, s;
int overflow;
@@ -101,29 +101,40 @@ main(void)
libj2_j2i_zero(&b);
check(&a, j, &b, 0);
- libj2_not_j2u((void *)&a);
- libj2_not_j2u((void *)&b);
- libj2_j2u_lsh((void *)&b, j);
+ libj2_j2i_to_j2u(&a, &t);
+ libj2_not_j2u(&t);
+ libj2_j2u_to_j2i(&t, &a);
+ libj2_j2i_to_j2u(&b, &t);
+ libj2_not_j2u(&t);
+ libj2_j2u_lsh(&t, j);
+ libj2_j2u_to_j2i(&t, &b);
check(&a, j, &b, j >= LIBJ2_J2I_BIT ? -1 : 0);
for (i = 0; i < LIBJ2_J2I_BIT; i++) {
libj2_j2i_zero(&a);
- libj2_j2u_or_bit((void *)&a, i);
+ libj2_j2i_to_j2u(&a, &t);
+ libj2_j2u_or_bit(&t, i);
+ libj2_j2u_to_j2i(&t, &a);
libj2_j2i_zero(&b);
- if (i + j < LIBJ2_J2I_BIT)
- libj2_j2u_or_bit((void *)&b, i + j);
+ if (i + j < LIBJ2_J2I_BIT) {
+ libj2_j2i_to_j2u(&b, &t);
+ libj2_j2u_or_bit(&t, i + j);
+ libj2_j2u_to_j2i(&t, &b);
+ }
overflow = i == LIBJ2_J2I_VBIT ? j ? -1 : 0 : i + j < LIBJ2_J2I_VBIT ? 0 : +1;
check(&a, j, &b, overflow);
- libj2_j2i_zero(&a);
- libj2_j2u_or_bit((void *)&a, i);
- libj2_not_j2u((void *)&a);
- libj2_j2i_zero(&b);
+ libj2_j2u_zero(&t);
+ libj2_j2u_or_bit(&t, i);
+ libj2_not_j2u(&t);
+ libj2_j2u_to_j2i(&t, &a);
+ libj2_j2u_zero(&t);
if (i + j < LIBJ2_J2I_BIT)
- libj2_j2u_or_bit((void *)&b, i + j);
+ libj2_j2u_or_bit(&t, i + j);
for (k = 0; k < j; k++)
- libj2_j2u_or_bit((void *)&b, k);
- libj2_not_j2u((void *)&b);
+ libj2_j2u_or_bit(&t, k);
+ libj2_not_j2u(&t);
+ libj2_j2u_to_j2i(&t, &b);
overflow = i == LIBJ2_J2I_VBIT ? j ? +1 : 0 : i + j < LIBJ2_J2I_VBIT ? 0 : -1;
check(&a, j, &b, overflow);
}
@@ -132,24 +143,28 @@ main(void)
for (i = 0; i < 32; i++) {
for (j = 0; j < LIBJ2_J2I_BIT - 1U; j++) {
for (k = 0; k <= LIBJ2_J2I_BIT + 1U; k++) {
- libj2_j2i_zero(&a);
- libj2_j2i_zero(&b);
+ libj2_j2u_zero(&u);
+ libj2_j2u_zero(&v);
for (s = 0; s <= j; s++) {
if (rand() < rand())
continue;
- libj2_j2u_or_bit((void *)&a, s);
- libj2_j2u_or_bit((void *)&b, s + k);
+ libj2_j2u_or_bit(&u, s);
+ libj2_j2u_or_bit(&v, s + k);
}
- overflow = libj2_co_j2u((const void *)&a) > libj2_co_j2u((const void *)&b);
+ libj2_j2u_to_j2i(&u, &a);
+ libj2_j2u_to_j2i(&v, &b);
+ overflow = libj2_co_j2u(&u) > libj2_co_j2u(&v);
overflow |= libj2_j2i_is_negative(&b);
check(&a, k, &b, overflow);
- libj2_not_j2u((void *)&a);
- libj2_not_j2u((void *)&b);
+ libj2_not_j2u(&u);
+ libj2_not_j2u(&v);
libj2_ju_lsh_to_j2u(1, k, &t);
libj2_j2u_sub_ju(&t, 1);
libj2_not_j2u(&t);
- libj2_j2u_and_j2u((void *)&b, &t);
+ libj2_j2u_and_j2u(&v, &t);
+ libj2_j2u_to_j2i(&u, &a);
+ libj2_j2u_to_j2i(&v, &b);
overflow = -overflow;
if (a.high == UINTMAX_MAX && a.low == UINTMAX_MAX && k >= LIBJ2_J2I_BIT)
overflow = -1;
diff --git a/libj2_j2i_mul_ji.c b/libj2_j2i_mul_ji.c
index 9c7ac3c..67de057 100644
--- a/libj2_j2i_mul_ji.c
+++ b/libj2_j2i_mul_ji.c
@@ -102,8 +102,12 @@ mul_(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *expected, int expe
t = *a;
libj2_j2i_sat_mul_ji(&t, b);
- EXPECT(expect_overflow > 0 ? libj2_j2i_is_max(&t) :
- expect_overflow ? libj2_j2i_is_min(&t) : libj2_j2i_eq_j2i(&t, expected));
+ if (expect_overflow > 0)
+ EXPECT(libj2_j2i_is_max(&t));
+ else if (expect_overflow)
+ EXPECT(libj2_j2i_is_min(&t));
+ else
+ EXPECT(libj2_j2i_eq_j2i(&t, expected));
t = *a;
EXPECT(libj2_j2i_mul_ji_overflow_p((const struct libj2_j2i *)&t, b) == expect_overflow);
@@ -195,7 +199,7 @@ static void
mul(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *expected, int expect_overflow)
{
struct libj2_j2i r, neg_a, e;
- struct libj2_j2u u;
+ struct libj2_j2u u, ue;
libj2_minus_j2i_to_j2i(a, &neg_a);
libj2_j2i_to_j2u(a, &u);
@@ -215,7 +219,8 @@ mul(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *expected, int expec
EXPECT(libj2_j2i_eq_j2i(&r, expected));
- expect_overflow = libj2_j2u_mul_ju_to_j2u_overflow(&u, (uintmax_t)b + 1U, (void *)&e);
+ expect_overflow = libj2_j2u_mul_ju_to_j2u_overflow(&u, (uintmax_t)b + 1U, &ue);
+ libj2_j2u_to_j2i(&ue, &e);
if (libj2_j2i_is_negative(&e))
expect_overflow = 1;
@@ -229,7 +234,8 @@ mul(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *expected, int expec
libj2_j2u_add_ju(&u, 1U);
libj2_j2i_add_ji(&neg_a, -1);
- expect_overflow = libj2_j2u_mul_ju_to_j2u_overflow(&u, (uintmax_t)b, (void *)&e);
+ expect_overflow = libj2_j2u_mul_ju_to_j2u_overflow(&u, (uintmax_t)b, &ue);
+ libj2_j2u_to_j2i(&ue, &e);
if (libj2_j2i_is_negative(&e))
expect_overflow = 1;
@@ -238,7 +244,8 @@ mul(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *expected, int expec
EXPECT(libj2_j2i_eq_j2i(&r, &e));
- expect_overflow = libj2_j2u_mul_ju_to_j2u_overflow(&u, (uintmax_t)b + 1U, (void *)&e);
+ expect_overflow = libj2_j2u_mul_ju_to_j2u_overflow(&u, (uintmax_t)b + 1U, &ue);
+ libj2_j2u_to_j2i(&ue, &e);
if (libj2_j2i_is_negative(&e))
expect_overflow = 1;
diff --git a/libj2_j2i_sub_j2i.c b/libj2_j2i_sub_j2i.c
index 24610cd..fbb569c 100644
--- a/libj2_j2i_sub_j2i.c
+++ b/libj2_j2i_sub_j2i.c
@@ -23,7 +23,7 @@ static void
validate(uintmax_t a_high, uintmax_t a_low, uintmax_t b_high, uintmax_t b_low, uintmax_t r_high, uintmax_t r_low, int r_overflow)
{
int a_neg, b_neg, overflow;
- struct libj2_j2u a, b;
+ struct libj2_j2u a, b, u;
struct libj2_j2i t, r;
t = (struct libj2_j2i){.high = a_high, .low = a_low};
@@ -41,31 +41,38 @@ validate(uintmax_t a_high, uintmax_t a_low, uintmax_t b_high, uintmax_t b_low, u
if (a_neg && b_neg) {
overflow = 0;
libj2_minus_j2u(&a);
- libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, (void *)&r);
- EXPECT(libj2_j2i_gt_j2i(&r, (const void *)&a));
+ libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, &u);
+ libj2_j2u_to_j2i(&u, &r);
+ libj2_j2u_to_j2i(&a, &t);
+ EXPECT(libj2_j2i_gt_j2i(&r, &t));
} else if (a_neg) {
- overflow = -libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, (void *)&r);
+ overflow = -libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, &u);
+ libj2_j2u_to_j2i(&u, &r);
EXPECT(overflow == 0 || overflow == -1);
libj2_minus_j2i(&r);
+ libj2_j2u_to_j2i(&a, &t);
if (!libj2_j2i_is_negative(&r))
overflow = -1;
else if (overflow)
- EXPECT(libj2_j2i_gt_j2i(&r, (const void *)&a));
+ EXPECT(libj2_j2i_gt_j2i(&r, &t));
if (!overflow)
- EXPECT(libj2_j2i_le_j2i(&r, (const void *)&a));
+ EXPECT(libj2_j2i_le_j2i(&r, &t));
} else if (b_neg) {
- overflow = +libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, (void *)&r);
+ overflow = +libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, &u);
+ libj2_j2u_to_j2i(&u, &r);
EXPECT(overflow == 0 || overflow == +1);
+ libj2_j2u_to_j2i(&a, &t);
if (!libj2_j2i_is_positive(&r))
overflow = +1;
else if (overflow)
- EXPECT(libj2_j2i_lt_j2i(&r, (const void *)&a));
+ EXPECT(libj2_j2i_lt_j2i(&r, &t));
if (!overflow)
- EXPECT(libj2_j2i_gt_j2i(&r, (const void *)&a));
+ EXPECT(libj2_j2i_gt_j2i(&r, &t));
} else {
overflow = 0;
libj2_minus_j2u(&b);
- libj2_j2u_add_j2u_to_j2u(&a, &b, (void *)&r);
+ libj2_j2u_add_j2u_to_j2u(&a, &b, &u);
+ libj2_j2u_to_j2i(&u, &r);
EXPECT(libj2_j2i_le_j2u(&r, &a));
}
diff --git a/libj2_j2i_sub_ji.c b/libj2_j2i_sub_ji.c
index 34222f6..1749c9d 100644
--- a/libj2_j2i_sub_ji.c
+++ b/libj2_j2i_sub_ji.c
@@ -23,7 +23,7 @@ static void
validate(uintmax_t a_high, uintmax_t a_low, uintmax_t b_high, uintmax_t b_low, uintmax_t r_high, uintmax_t r_low, int r_overflow)
{
int a_neg, b_neg, overflow;
- struct libj2_j2u a, b;
+ struct libj2_j2u a, b, u;
struct libj2_j2i t, r;
t = (struct libj2_j2i){.high = a_high, .low = a_low};
@@ -41,31 +41,38 @@ validate(uintmax_t a_high, uintmax_t a_low, uintmax_t b_high, uintmax_t b_low, u
if (a_neg && b_neg) {
overflow = 0;
libj2_minus_j2u(&a);
- libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, (void *)&r);
- EXPECT(libj2_j2i_gt_j2i(&r, (const void *)&a));
+ libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, &u);
+ libj2_j2u_to_j2i(&u, &r);
+ libj2_j2u_to_j2i(&a, &t);
+ EXPECT(libj2_j2i_gt_j2i(&r, &t));
} else if (a_neg) {
- overflow = -libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, (void *)&r);
+ overflow = -libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, &u);
+ libj2_j2u_to_j2i(&u, &r);
EXPECT(overflow == 0 || overflow == -1);
libj2_minus_j2i(&r);
+ libj2_j2u_to_j2i(&a, &t);
if (!libj2_j2i_is_negative(&r))
overflow = -1;
else if (overflow)
- EXPECT(libj2_j2i_gt_j2i(&r, (const void *)&a));
+ EXPECT(libj2_j2i_gt_j2i(&r, &t));
if (!overflow)
- EXPECT(libj2_j2i_le_j2i(&r, (const void *)&a));
+ EXPECT(libj2_j2i_le_j2i(&r, &t));
} else if (b_neg) {
- overflow = +libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, (void *)&r);
+ overflow = +libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, &u);
EXPECT(overflow == 0 || overflow == +1);
+ libj2_j2u_to_j2i(&a, &t);
+ libj2_j2u_to_j2i(&u, &r);
if (!libj2_j2i_is_positive(&r))
overflow = +1;
else if (overflow)
- EXPECT(libj2_j2i_lt_j2i(&r, (const void *)&a));
+ EXPECT(libj2_j2i_lt_j2i(&r, &t));
if (!overflow)
- EXPECT(libj2_j2i_gt_j2i(&r, (const void *)&a));
+ EXPECT(libj2_j2i_gt_j2i(&r, &t));
} else {
overflow = 0;
libj2_minus_j2u(&b);
- libj2_j2u_add_j2u_to_j2u(&a, &b, (void *)&r);
+ libj2_j2u_add_j2u_to_j2u(&a, &b, &u);
+ libj2_j2u_to_j2i(&u, &r);
EXPECT(libj2_j2i_le_j2u(&r, &a));
}
diff --git a/libj2_j2i_xor_sign.c b/libj2_j2i_xor_sign.c
index 6826f02..707774c 100644
--- a/libj2_j2i_xor_sign.c
+++ b/libj2_j2i_xor_sign.c
@@ -23,6 +23,7 @@ static void
check(struct libj2_j2i *a)
{
struct libj2_j2i r, saved, x;
+ struct libj2_j2u u;
saved = *a;
@@ -32,7 +33,8 @@ check(struct libj2_j2i *a)
EXPECT(libj2_j2i_eq_j2i(&r, &saved));
r = (struct libj2_j2i){111, 222};
- libj2_j2i_xor_sign_to_j2u((const struct libj2_j2i *)a, (struct libj2_j2u *)&r);
+ libj2_j2i_xor_sign_to_j2u((const struct libj2_j2i *)a, &u);
+ libj2_j2u_to_j2i(&u, &r);
EXPECT(libj2_j2i_eq_j2i(a, &saved));
EXPECT(libj2_j2i_eq_j2i(&r, &saved));
@@ -40,7 +42,9 @@ check(struct libj2_j2i *a)
libj2_j2i_xor_sign(&r);
EXPECT(libj2_j2i_eq_j2i(&r, &saved));
- libj2_not_j2u((void *)a);
+ libj2_j2i_to_j2u(a, &u);
+ libj2_not_j2u(&u);
+ libj2_j2u_to_j2i(&u, a);
x = *a;
r = (struct libj2_j2i){111, 222};
@@ -49,7 +53,8 @@ check(struct libj2_j2i *a)
EXPECT(libj2_j2i_eq_j2i(&r, &saved));
r = (struct libj2_j2i){111, 222};
- libj2_j2i_xor_sign_to_j2u((const struct libj2_j2i *)a, (struct libj2_j2u *)&r);
+ libj2_j2i_xor_sign_to_j2u((const struct libj2_j2i *)a, &u);
+ libj2_j2u_to_j2i(&u, &r);
EXPECT(libj2_j2i_eq_j2i(a, &x));
EXPECT(libj2_j2i_eq_j2i(&r, &saved));
diff --git a/libj2_j2u_divmod_j2u_to_j2u.c b/libj2_j2u_divmod_j2u_to_j2u.c
index 0b9ffff..a0618da 100644
--- a/libj2_j2u_divmod_j2u_to_j2u.c
+++ b/libj2_j2u_divmod_j2u_to_j2u.c
@@ -380,7 +380,7 @@ check(const struct libj2_j2u *a, const struct libj2_j2u *b)
v.high = random_ju();
v.low = random_ju();
} while (!v.high && !v.low);
- b = &u;
+ b = &v;
}
check_manual(a, b, NULL, NULL);
}
diff --git a/libj2_ji_sub_ji_to_j2i.c b/libj2_ji_sub_ji_to_j2i.c
index 1057db6..8bc5944 100644
--- a/libj2_ji_sub_ji_to_j2i.c
+++ b/libj2_ji_sub_ji_to_j2i.c
@@ -25,7 +25,7 @@ check(uintmax_t ua, uintmax_t ub)
intmax_t a = ua >> (LIBJ2_JU_BIT - 1U) ? -(intmax_t)~ua - 1 : (intmax_t)ua;
intmax_t b = ub >> (LIBJ2_JU_BIT - 1U) ? -(intmax_t)~ub - 1 : (intmax_t)ub;
struct libj2_j2i r, expected;
- struct libj2_j2u wa, wb;
+ struct libj2_j2u wa, wb, ue;
#if INTMAX_MIN + 1 != -INTMAX_MAX
if (ua == (UINTMAX >> 1) + 1U || ub == (UINTMAX >> 1) + 1U)
@@ -39,7 +39,8 @@ check(uintmax_t ua, uintmax_t ub)
wb.high = b < 0 ? UINTMAX_MAX : 0;
libj2_minus_j2u(&wb);
- libj2_j2u_add_j2u_to_j2u(&wa, &wb, (void *)&expected);
+ libj2_j2u_add_j2u_to_j2u(&wa, &wb, &ue);
+ libj2_j2u_to_j2i(&ue, &expected);
libj2_ji_sub_ji_to_j2i(a, b, &r);
EXPECT(libj2_j2i_eq_j2i(&r, &expected));
}