diff options
Diffstat (limited to '')
311 files changed, 7424 insertions, 208 deletions
@@ -386,13 +386,11 @@ OBJ =\ 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\ @@ -429,7 +427,86 @@ OBJ =\ libj2_j2i_lsh_overflow_p.o\ libj2_ji_lsh_overflow_p.o\ libj2_j2i_rsh_underflow_p.o\ - libj2_ji_rsh_underflow_p.o + libj2_ji_rsh_underflow_p.o\ + libj2_j2i_add_j2i.o\ + libj2_j2i_add_j2i_overflow.o\ + libj2_j2i_add_j2i_overflow_p.o\ + libj2_j2i_add_j2i_to_j2i.o\ + libj2_j2i_add_j2i_to_j2i_overflow.o\ + libj2_j2i_add_ji.o\ + libj2_j2i_add_ji_overflow.o\ + libj2_j2i_add_ji_overflow_p.o\ + libj2_j2i_add_ji_to_j2i.o\ + libj2_j2i_add_ji_to_j2i_overflow.o\ + libj2_ji_add_j2i_overflow_p.o\ + libj2_ji_add_j2i_to_j2i.o\ + libj2_ji_add_j2i_to_j2i_overflow.o\ + libj2_ji_add_ji_to_j2i.o\ + libj2_j2i_rsub_j2i.o\ + libj2_j2i_rsub_j2i_overflow.o\ + libj2_j2i_rsub_j2i_overflow_p.o\ + libj2_j2i_rsub_ji.o\ + libj2_j2i_rsub_ji_overflow.o\ + libj2_j2i_rsub_ji_overflow_p.o\ + libj2_j2i_sub_j2i.o\ + libj2_j2i_sub_j2i_overflow.o\ + libj2_j2i_sub_j2i_overflow_p.o\ + libj2_j2i_sub_j2i_to_j2i.o\ + libj2_j2i_sub_j2i_to_j2i_overflow.o\ + libj2_j2i_sub_ji.o\ + libj2_j2i_sub_ji_overflow.o\ + libj2_j2i_sub_ji_overflow_p.o\ + libj2_j2i_sub_ji_to_j2i.o\ + libj2_j2i_sub_ji_to_j2i_overflow.o\ + libj2_ji_sub_j2i_overflow_p.o\ + libj2_ji_sub_j2i_to_j2i.o\ + libj2_ji_sub_j2i_to_j2i_overflow.o\ + libj2_ji_sub_ji_to_j2i.o\ + libj2_j2i_mul_j2i.o\ + libj2_j2i_mul_j2i_overflow.o\ + libj2_j2i_mul_j2i_overflow_p.o\ + libj2_j2i_mul_j2i_overflow_p_quick.o\ + libj2_j2i_mul_j2i_to_j2i.o\ + libj2_j2i_mul_j2i_to_j2i_overflow.o\ + libj2_j2i_mul_j2i_to_j2i_overflow_p.o\ + libj2_j2i_mul_ji.o\ + libj2_j2i_mul_ji_overflow.o\ + libj2_j2i_mul_ji_overflow_p.o\ + libj2_j2i_mul_ji_overflow_p_quick.o\ + libj2_j2i_mul_ji_to_j2i.o\ + libj2_j2i_mul_ji_to_j2i_overflow.o\ + libj2_j2i_mul_ji_to_j2i_overflow_p.o\ + libj2_ji_mul_j2i_overflow_p.o\ + libj2_ji_mul_j2i_overflow_p_quick.o\ + libj2_ji_mul_j2i_to_j2i.o\ + libj2_ji_mul_j2i_to_j2i_overflow.o\ + libj2_ji_mul_j2i_to_j2i_overflow_p.o\ + libj2_ji_mul_ji_to_j2i.o\ + libj2_j2i_div_j2i.o\ + libj2_j2i_div_j2i_return.o\ + libj2_j2i_div_j2i_to_j2i.o\ + libj2_j2i_div_j2i_to_j2i_underflow.o\ + libj2_j2i_div_j2i_underflow.o\ + libj2_j2i_div_ji.o\ + libj2_j2i_div_ji_return.o\ + libj2_j2i_div_ji_to_j2i.o\ + libj2_j2i_div_ji_to_j2i_underflow.o\ + libj2_j2i_div_ji_underflow.o\ + libj2_j2i_divmod_j2i.o\ + libj2_j2i_divmod_j2i_to_j2i.o\ + libj2_j2i_divmod_j2i_to_j2i_j2i.o\ + libj2_j2i_divmod_ji.o\ + libj2_j2i_divmod_ji_to_j2i.o\ + libj2_j2i_divmod_ji_to_j2i_j2i.o\ + libj2_j2i_mod_j2i.o\ + libj2_j2i_mod_j2i_to_j2i.o\ + libj2_j2i_mod_ji.o\ + libj2_j2i_mod_ji_to_j2i.o\ + libj2_j2i_rdiv_j2i.o\ + libj2_j2i_rdiv_j2i_underflow.o\ + libj2_j2i_rdivmod_j2i.o\ + libj2_j2i_rdivmod_j2i_to_j2i.o\ + libj2_j2i_rmod_j2i.o SUBHDR =\ libj2/constants.h\ @@ -477,7 +554,8 @@ MAN3 =\ LIBJ2_POSITIVE_OVERFLOW_UNKNOWN.3\ LIBJ2_POSITIVE_OVERFLOW.3\ LIBJ2_NEGATIVE_OVERFLOW_UNKNOWN.3\ - LIBJ2_NEGATIVE_OVERFLOW.3 + LIBJ2_NEGATIVE_OVERFLOW.3\ + $(OBJ:.o=.3) all: libj2.a libj2.$(LIBEXT) $(TEST) @@ -516,6 +594,13 @@ check: $(TEST) $(CHECK_PREFIX) ./"$$t";\ done +makefile-check: + grep '\.o\\\{0,1\}$$' < Makefile |\ + sed 's/^'"$$(printf '\t')"'//' |\ + sed 's/\.o\\\{0,1\}$$/\.c/' |\ + sort |\ + diff -u <(printf '%s\n' *.c | sort) - + install: libj2.a libj2.$(LIBEXT) mkdir -p -- "$(DESTDIR)$(PREFIX)/lib" mkdir -p -- "$(DESTDIR)$(PREFIX)/include/libj2" @@ -553,4 +638,4 @@ clean: .SUFFIXES: .SUFFIXES: .lo .o .c .to .t -.PHONY: all install uninstall clean +.PHONY: all check release-check install uninstall clean @@ -340,18 +340,24 @@ DESCRIPTION libj2 provides the following arithmetic functions: + libj2_j2i_add_j2i(3), libj2_j2i_add_j2i_to_j2i(3), + libj2_j2i_add_ji(3), libj2_j2i_add_ji_to_j2ui3), + libj2_ji_add_j2i_to_j2i(3), libj2_ji_add_ji_to_j2i(3), libj2_j2u_add_j2u(3), libj2_j2u_add_j2u_to_j2u(3), libj2_j2u_add_ju(3), libj2_j2u_add_ju_to_j2u(3), libj2_ju_add_j2u_to_j2u(3), libj2_ju_add_ju_to_j2u(3) Calculate the sum of two values. - libj2_j2u_add_j2u_overflow(3), libj2_j2u_add_j2u_to_j2u_overflow(3), - libj2_j2u_add_ju_overflow(3), libj2_j2u_add_ju_to_j2u_overflow(3), - libj2_ju_add_j2u_to_j2u_overflow(3) + libj2_j2i_add_j2i_overflow(3), libj2_j2i_add_j2i_to_j2i_overflow(3), + libj2_j2i_add_ji_overflow(3), libj2_j2i_add_ji_to_j2i_overflow(3), + libj2_ji_add_j2i_to_j2i_overflow(3), libj2_j2u_add_j2u_overflow(3), + libj2_j2u_add_j2u_to_j2u_overflow(3), libj2_j2u_add_ju_overflow(3), + libj2_j2u_add_ju_to_j2u_overflow(3), libj2_ju_add_j2u_to_j2u_overflow(3) Calculate the sum of two values, and detect overflow. - libj2_j2u_add_j2u_overflow_p(3), libj2_j2u_add_ju_overflow_p(3), - libj2_ju_add_j2u_overflow_p(3) + libj2_j2i_add_j2i_overflow_p(3), libj2_j2i_add_ji_overflow_p(3), + libj2_ji_add_j2i_overflow_p(3), libj2_j2u_add_j2u_overflow_p(3), + libj2_j2u_add_ju_overflow_p(3), libj2_ju_add_j2u_overflow_p(3) Predict whether adding two values will result in an overflow. libj2_j2u_sat_add_j2u(3), libj2_j2u_sat_add_j2u_to_j2u(3), @@ -359,29 +365,40 @@ DESCRIPTION libj2_ju_sat_add_j2u_to_j2u(3) Calculate the sum of two values, but saturate on overflow. + libj2_j2i_sub_j2i(3), libj2_j2i_sub_j2i_to_j2i(3), + libj2_j2i_sub_ji(3), libj2_j2i_sub_ji_to_j2i(3), + libj2_ji_sub_j2i_to_j2i(3), libj2_ji_sub_ji_to_j2i(3), libj2_j2u_sub_j2u(3), libj2_j2u_sub_j2u_to_j2u(3), libj2_j2u_sub_ju(3), libj2_j2u_sub_ju_to_j2u(3), libj2_ju_sub_j2u_to_j2u(3), libj2_ju_sub_ju_to_j2u(3) Calculate the difference between two values. + libj2_j2i_rsub_j2i(3), libj2_j2i_rsub_ji(3), libj2_j2u_rsub_j2u(3), libj2_j2u_rsub_ju(3) Calculate the difference between two values. These functions swap the position of the two operands. - libj2_j2u_sub_j2u_overflow(3), libj2_j2u_sub_j2u_to_j2u_overflow(3), - libj2_j2u_sub_ju_overflow(3), libj2_j2u_sub_ju_to_j2u_overflow(3), - libj2_ju_sub_j2u_to_j2u_overflow(3), libj2_ju_sub_ju_to_j2u_overflow(3) + libj2_j2i_sub_j2i_overflow(3), libj2_j2i_sub_j2i_to_j2i_overflow(3), + libj2_j2i_sub_ji_overflow(3), libj2_j2i_sub_ji_to_j2i_overflow(3), + libj2_ji_sub_j2i_to_j2i_overflow(3), libj2_j2u_sub_j2u_overflow(3), + libj2_j2u_sub_j2u_to_j2u_overflow(3), libj2_j2u_sub_ju_overflow(3), + libj2_j2u_sub_ju_to_j2u_overflow(3), libj2_ju_sub_j2u_to_j2u_overflow(3), + libj2_ju_sub_ju_to_j2u_overflow(3) Calculate the difference between two values, and detect overflow. + libj2_j2i_rsub_j2i_overflow(3), libj2_j2i_rsub_ji_overflow(3), libj2_j2u_rsub_j2u_overflow(3), libj2_j2u_rsub_ju_overflow(3) Calculate the difference between two values, and detect overflow. These functions swap the position of the two operands. - libj2_j2u_sub_j2u_overflow_p(3), libj2_j2u_sub_ju_overflow_p(3), - libj2_ju_sub_j2u_overflow_p(3), libj2_ju_sub_ju_overflow_p(3) + libj2_j2i_sub_j2i_overflow_p(3), libj2_j2i_sub_ji_overflow_p(3), + libj2_ji_sub_j2i_overflow_p(3), libj2_j2u_sub_j2u_overflow_p(3), + libj2_j2u_sub_ju_overflow_p(3), libj2_ju_sub_j2u_overflow_p(3), + libj2_ju_sub_ju_overflow_p(3) Predict whether subtracting a value will result in an overflow. + libj2_j2i_rsub_j2i_overflow_p(3), libj2_j2i_rsub_ji_overflow_p(3), libj2_j2u_rsub_j2u_overflow_p(3), libj2_j2u_rsub_ju_overflow_p(3) Predict whether subtracting a value will result in an overflow. These functions swap the position of the two operands. @@ -396,29 +413,41 @@ DESCRIPTION Calculate the difference between two values, but saturate on overflow. These functions swap the position of the two operands. + libj2_j2i_mul_j2i(3), libj2_j2i_mul_j2i_to_j2i(3), + libj2_j2i_mul_ji(3), libj2_j2i_mul_ji_to_j2i(3), + libj2_ji_mul_j2i_to_j2i(3), libj2_ji_mul_ji_to_j2i(3), libj2_j2u_mul_j2u(3), libj2_j2u_mul_j2u_to_j2u(3), libj2_j2u_mul_ju(3), libj2_j2u_mul_ju_to_j2u(3), libj2_ju_mul_j2u_to_j2u(3), libj2_ju_mul_ju_to_j2u(3), libj2_j2u_mul_j2u_destructive(3) Calculate the product of two values. - libj2_j2u_mul_j2u_overflow(3), libj2_j2u_mul_j2u_to_j2u_overflow(3), - libj2_j2u_mul_ju_overflow(3), libj2_j2u_mul_ju_to_j2u_overflow(3), - libj2_ju_mul_j2u_to_j2u_overflow(3), + libj2_j2i_mul_j2i_overflow(3), libj2_j2i_mul_j2i_to_j2i_overflow(3), + libj2_j2i_mul_ji_overflow(3), libj2_j2i_mul_ji_to_j2i_overflow(3), + libj2_ji_mul_j2i_to_j2i_overflow(3), libj2_j2u_mul_j2u_overflow(3), + libj2_j2u_mul_j2u_to_j2u_overflow(3), libj2_j2u_mul_ju_overflow(3), + libj2_j2u_mul_ju_to_j2u_overflow(3), libj2_ju_mul_j2u_to_j2u_overflow(3), libj2_j2u_mul_j2u_overflow_destructive(3) Calculate the product of two values, and detect overflow. - libj2_j2u_mul_j2u_overflow_p(3), libj2_j2u_mul_ju_overflow_p(3), - libj2_ju_mul_j2u_overflow_p(3) + libj2_j2i_mul_j2i_overflow_p(3), libj2_j2i_mul_ji_overflow_p(3), + libj2_ji_mul_j2i_overflow_p(3), libj2_j2u_mul_j2u_overflow_p(3), + libj2_j2u_mul_ju_overflow_p(3), libj2_ju_mul_j2u_overflow_p(3) Predict whether multiplying two values will result in an overflow. + libj2_j2i_mul_j2i_overflow_p_quick(3), + libj2_j2i_mul_ji_overflow_p_quick(3), + libj2_ji_mul_j2i_overflow_p_quick(3), libj2_j2u_mul_j2u_overflow_p_quick(3), libj2_j2u_mul_ju_overflow_p_quick(3), libj2_ju_mul_j2u_overflow_p_quick(3) Predict whether multiplying two values will result in an overflow, but do not preform the prediction if it is costly. + libj2_j2i_mul_j2i_to_j2i_overflow_p(3), + libj2_j2i_mul_ji_to_j2i_overflow_p(3), + libj2_ji_mul_j2i_to_j2i_overflow_p(3), libj2_j2u_mul_j2u_to_j2u_overflow_p(3), libj2_j2u_mul_ju_to_j2u_overflow_p(3), libj2_ju_mul_j2u_to_j2u_overflow_p(3) @@ -431,44 +460,55 @@ DESCRIPTION libj2_ju_sat_mul_j2u_to_j2u(3), libj2_j2u_sat_mul_j2u_destructive(3) Calculate the product of two values, but saturate on overflow. + libj2_j2i_divmod_j2i(3), libj2_j2i_divmod_j2i_to_j2i(3), + libj2_j2i_divmod_j2i_to_j2i_j2i(3), libj2_j2i_divmod_ji(3), + libj2_j2i_divmod_ji_to_j2i(3), libj2_j2i_divmod_ji_to_j2i_j2i(3), libj2_j2u_divmod_j2u(3), libj2_j2u_divmod_j2u_to_j2u(3), libj2_j2u_divmod_j2u_to_j2u_j2u(3), libj2_j2u_divmod_ju(3), libj2_j2u_divmod_ju_to_j2u(3), libj2_j2u_divmod_ju_to_j2u_j2u(3) Calculate the ratio between values, and keep the computed remainder. + libj2_j2i_rdivmod_j2i(3), libj2_j2i_rdivmod_j2i_to_j2i(3), libj2_j2u_rdivmod_j2u(3), libj2_j2u_rdivmod_j2u_to_j2u(3) Calculate the ratio between values, and keep the computed remainder. These functions swap the position of the two operands. + libj2_j2i_div_j2i(3), libj2_j2i_div_j2i_to_j2i(3), + libj2_j2i_div_j2i_return(3), libj2_j2i_div_ji(3), + libj2_j2i_div_ji_to_j2i(3), libj2_j2i_div_ji_return(3), libj2_j2u_div_j2u(3), libj2_j2u_div_j2u_to_j2u(3), libj2_j2u_div_j2u_return(3), libj2_j2u_div_ju(3), libj2_j2u_div_ju_to_j2u(3), libj2_j2u_div_ju_return(3) Calculate the ratio between values, and discard the computed remainder. - libj2_j2u_rdiv_j2u(3) + libj2_j2i_rdiv_j2i(3), libj2_j2u_rdiv_j2u(3) Calculate the ratio between values, and discard the computed remainder. This function swaps the position of the two operands. + libj2_j2i_div_j2i_to_j2i_underflow(3), libj2_j2i_div_j2i_underflow(3), + libj2_j2i_div_ji_to_j2i_underflow(3), libj2_j2i_div_ji_underflow(3), libj2_j2u_div_j2u_to_j2u_underflow(3), libj2_j2u_div_j2u_underflow(3), libj2_j2u_div_ju_to_j2u_underflow(3), libj2_j2u_div_ju_underflow(3) Calculate the ratio between values, and discard the computed remainder, but detect underflow (non-zero remainder). - libj2_j2u_rdiv_j2u_underflow(3) + libj2_j2i_rdiv_j2i_underflow(3), libj2_j2u_rdiv_j2u_underflow(3) Calculate the ratio between values, and discard the computed remainder, but detect underflow (non-zero remainder). This function swaps the position of the two operands. - libj2_j2u_mod_j2u(3), libj2_j2u_mod_j2u_to_j2u(3), libj2_j2u_mod_ju(3), + libj2_j2i_mod_j2i(3), libj2_j2i_mod_j2i_to_j2i(3), libj2_j2i_mod_ji(3), + libj2_j2i_mod_ji_to_j2i(3), libj2_j2u_mod_j2u(3), + libj2_j2u_mod_j2u_to_j2u(3), libj2_j2u_mod_ju(3), libj2_j2u_mod_ju_to_j2u(3) Calculate the remainder of the integer division between two values. - libj2_j2u_rmod_j2u(3) + libj2_j2i_rmod_j2i(3), libj2_j2u_rmod_j2u(3) Calculate the remainder of the integer division between two values. This function swaps the position of the two operands. @@ -1,13 +1,8 @@ /* See LICENSE file for copyright and license details. */ +#define LIBJ2_COMPILING_ #include "libj2.h" -#if defined(__GNUC__) -# define CONST __attribute__((__const__)) -# define PURE __attribute__((__pure__)) -#else -# define CONST -# define PURE -#endif +#define PURE LIBJ2_PURE_ #if defined(__clang__) # pragma clang diagnostic ignored "-Wunsafe-buffer-usage" /* broken warning, spams false positives */ @@ -15,6 +10,11 @@ #endif #ifdef TEST +# if defined(__GNUC__) +# define CONST __attribute__((__const__)) +# else +# define CONST +# endif # include <stdlib.h> # include <stdio.h> # include <string.h> @@ -293,7 +293,7 @@ Check whether a value is positive. .BR libj2_j2i_is_negative (3) Check whether a value is negative. .TP -.BR ibj2_sgn_j2i (3), +.BR libj2_sgn_j2i (3), .TQ .BR libj2_sgn_j2u (3) Perform three-way comparision against the value zero (get the @@ -752,6 +752,18 @@ Set the least significant cleared bit. .B libj2 provides the following arithmetic functions: .TP +.BR libj2_j2i_add_j2i (3), +.TQ +.BR libj2_j2i_add_j2i_to_j2i (3), +.TQ +.BR libj2_j2i_add_ji (3), +.TQ +.BR libj2_j2i_add_ji_to_j2i (3), +.TQ +.BR libj2_ji_add_j2i_to_j2i (3), +.TQ +.BR libj2_ji_add_ji_to_j2i (3), +.TQ .BR libj2_j2u_add_j2u (3), .TQ .BR libj2_j2u_add_j2u_to_j2u (3), @@ -765,6 +777,16 @@ provides the following arithmetic functions: .BR libj2_ju_add_ju_to_j2u (3) Calculate the sum of two values. .TP +.BR libj2_j2i_add_j2i_overflow (3), +.TQ +.BR libj2_j2i_add_j2i_to_j2i_overflow (3), +.TQ +.BR libj2_j2i_add_ji_overflow (3), +.TQ +.BR libj2_j2i_add_ji_to_j2i_overflow (3), +.TQ +.BR libj2_ji_add_j2i_to_j2i_overflow (3), +.TQ .BR libj2_j2u_add_j2u_overflow (3), .TQ .BR libj2_j2u_add_j2u_to_j2u_overflow (3), @@ -776,6 +798,12 @@ Calculate the sum of two values. .BR libj2_ju_add_j2u_to_j2u_overflow (3) Calculate the sum of two values, and detect overflow. .TP +.BR libj2_j2i_add_j2i_overflow_p (3), +.TQ +.BR libj2_j2i_add_ji_overflow_p (3), +.TQ +.BR libj2_ji_add_j2i_overflow_p (3), +.TQ .BR libj2_j2u_add_j2u_overflow_p (3), .TQ .BR libj2_j2u_add_ju_overflow_p (3), @@ -794,6 +822,18 @@ Predict whether adding two values will result in an overflow. .BR libj2_ju_sat_add_j2u_to_j2u (3) Calculate the sum of two values, but saturate on overflow. .TP +.BR libj2_j2i_sub_j2i (3), +.TQ +.BR libj2_j2i_sub_j2i_to_j2i (3), +.TQ +.BR libj2_j2i_sub_ji (3), +.TQ +.BR libj2_j2i_sub_ji_to_j2i (3), +.TQ +.BR libj2_ji_sub_j2i_to_j2i (3), +.TQ +.BR libj2_ji_sub_ji_to_j2i (3), +.TQ .BR libj2_j2u_sub_j2u (3), .TQ .BR libj2_j2u_sub_j2u_to_j2u (3), @@ -806,6 +846,10 @@ Calculate the sum of two values, but saturate on overflow. .TQ .BR libj2_ju_sub_ju_to_j2u (3) Calculate the difference between two values. +.TP +.BR libj2_j2i_rsub_j2i (3), +.TQ +.BR libj2_j2i_rsub_ji (3), .TQ .BR libj2_j2u_rsub_j2u (3), .TQ @@ -813,6 +857,16 @@ Calculate the difference between two values. Calculate the difference between two values. These functions swap the position of the two operands. .TP +.BR libj2_j2i_sub_j2i_overflow (3), +.TQ +.BR libj2_j2i_sub_j2i_to_j2i_overflow (3), +.TQ +.BR libj2_j2i_sub_ji_overflow (3), +.TQ +.BR libj2_j2i_sub_ji_to_j2i_overflow (3), +.TQ +.BR libj2_ji_sub_j2i_to_j2i_overflow (3), +.TQ .BR libj2_j2u_sub_j2u_overflow (3), .TQ .BR libj2_j2u_sub_j2u_to_j2u_overflow (3), @@ -827,12 +881,22 @@ swap the position of the two operands. Calculate the difference between two values, and detect overflow. .TP +.BR libj2_j2i_rsub_j2i_overflow (3), +.TQ +.BR libj2_j2i_rsub_ji_overflow (3), +.TQ .BR libj2_j2u_rsub_j2u_overflow (3), .TQ .BR libj2_j2u_rsub_ju_overflow (3) Calculate the difference between two values, and detect overflow. These functions swap the position of the two operands. .TP +.BR libj2_j2i_sub_j2i_overflow_p (3), +.TQ +.BR libj2_j2i_sub_ji_overflow_p (3), +.TQ +.BR libj2_ji_sub_j2i_overflow_p (3), +.TQ .BR libj2_j2u_sub_j2u_overflow_p (3), .TQ .BR libj2_j2u_sub_ju_overflow_p (3), @@ -842,6 +906,10 @@ overflow. These functions swap the position of the two operands. .BR libj2_ju_sub_ju_overflow_p (3) Predict whether subtracting a value will result in an overflow. .TP +.BR libj2_j2i_rsub_j2i_overflow_p (3), +.TQ +.BR libj2_j2i_rsub_ji_overflow_p (3), +.TQ .BR libj2_j2u_rsub_j2u_overflow_p (3), .TQ .BR libj2_j2u_rsub_ju_overflow_p (3) @@ -868,6 +936,18 @@ overflow. Calculate the difference between two values, but saturate on overflow. These functions swap the position of the two operands. .TP +.BR libj2_j2i_mul_j2i (3), +.TQ +.BR libj2_j2i_mul_j2i_to_j2i (3), +.TQ +.BR libj2_j2i_mul_ji (3), +.TQ +.BR libj2_j2i_mul_ji_to_j2i (3), +.TQ +.BR libj2_ji_mul_j2i_to_j2i (3), +.TQ +.BR libj2_ji_mul_ji_to_j2i (3), +.TQ .BR libj2_j2u_mul_j2u (3), .TQ .BR libj2_j2u_mul_j2u_to_j2u (3), @@ -883,6 +963,16 @@ overflow. These functions swap the position of the two operands. .BR libj2_j2u_mul_j2u_destructive (3) Calculate the product of two values. .TP +.BR libj2_j2i_mul_j2i_overflow (3), +.TQ +.BR libj2_j2i_mul_j2i_to_j2i_overflow (3), +.TQ +.BR libj2_j2i_mul_ji_overflow (3), +.TQ +.BR libj2_j2i_mul_ji_to_j2i_overflow (3), +.TQ +.BR libj2_ji_mul_j2i_to_j2i_overflow (3), +.TQ .BR libj2_j2u_mul_j2u_overflow (3), .TQ .BR libj2_j2u_mul_j2u_to_j2u_overflow (3), @@ -896,6 +986,12 @@ Calculate the product of two values. .BR libj2_j2u_mul_j2u_overflow_destructive (3) Calculate the product of two values, and detect overflow. .TP +.BR libj2_j2i_mul_j2i_overflow_p (3), +.TQ +.BR libj2_j2i_mul_ji_overflow_p (3), +.TQ +.BR libj2_ji_mul_j2i_overflow_p (3), +.TQ .BR libj2_j2u_mul_j2u_overflow_p (3), .TQ .BR libj2_j2u_mul_ju_overflow_p (3), @@ -904,6 +1000,12 @@ Calculate the product of two values, and detect overflow. Predict whether multiplying two values will result in an overflow. .TP +.BR libj2_j2i_mul_j2i_overflow_p_quick (3), +.TQ +.BR libj2_j2i_mul_ji_overflow_p_quick (3), +.TQ +.BR libj2_ji_mul_j2i_overflow_p_quick (3), +.TQ .BR libj2_j2u_mul_j2u_overflow_p_quick (3), .TQ .BR libj2_j2u_mul_ju_overflow_p_quick (3), @@ -912,6 +1014,12 @@ overflow. Predict whether multiplying two values will result in an overflow, but do not preform the prediction if it is costly. .TP +.BR libj2_j2i_mul_j2i_to_j2i_overflow_p (3), +.TQ +.BR libj2_j2i_mul_ji_to_j2i_overflow_p (3), +.TQ +.BR libj2_ji_mul_j2i_to_j2i_overflow_p (3), +.TQ .BR libj2_j2u_mul_j2u_to_j2u_overflow_p (3), .TQ .BR libj2_j2u_mul_ju_to_j2u_overflow_p (3), @@ -934,6 +1042,18 @@ multiplication. .BR libj2_j2u_sat_mul_j2u_destructive (3) Calculate the product of two values, but saturate on overflow. .TP +.BR libj2_j2i_divmod_j2i (3), +.TQ +.BR libj2_j2i_divmod_j2i_to_j2i (3), +.TQ +.BR libj2_j2i_divmod_j2i_to_j2i_j2i (3), +.TQ +.BR libj2_j2i_divmod_ji (3), +.TQ +.BR libj2_j2i_divmod_ji_to_j2i (3), +.TQ +.BR libj2_j2i_divmod_ji_to_j2i_j2i (3), +.TQ .BR libj2_j2u_divmod_j2u (3), .TQ .BR libj2_j2u_divmod_j2u_to_j2u (3), @@ -948,12 +1068,28 @@ Calculate the product of two values, but saturate on overflow. Calculate the ratio between values, and keep the computed remainder. .TP +.BR libj2_j2i_rdivmod_j2i (3), +.TQ +.BR libj2_j2i_rdivmod_j2i_to_j2i (3), +.TQ .BR libj2_j2u_rdivmod_j2u (3), .TQ .BR libj2_j2u_rdivmod_j2u_to_j2u (3) Calculate the ratio between values, and keep the computed remainder. These functions swap the position of the two operands. +.TP +.BR libj2_j2i_div_j2i (3), +.TQ +.BR libj2_j2i_div_j2i_to_j2i (3), +.TQ +.BR libj2_j2i_div_j2i_return (3), +.TQ +.BR libj2_j2i_div_ji (3), +.TQ +.BR libj2_j2i_div_ji_to_j2i (3), +.TQ +.BR libj2_j2i_div_ji_return (3), .TQ .BR libj2_j2u_div_j2u (3), .TQ @@ -969,11 +1105,21 @@ operands. Calculate the ratio between values, and discard the computed remainder. .TP +.BR libj2_j2i_rdiv_j2i (3), +.TQ .BR libj2_j2u_rdiv_j2u (3) Calculate the ratio between values, and discard the computed remainder. This function swaps the position of the two operands. .TP +.BR libj2_j2i_div_j2i_to_j2i_underflow (3), +.TQ +.BR libj2_j2i_div_j2i_underflow (3), +.TQ +.BR libj2_j2i_div_ji_to_j2i_underflow (3), +.TQ +.BR libj2_j2i_div_ji_underflow (3), +.TQ .BR libj2_j2u_div_j2u_to_j2u_underflow (3), .TQ .BR libj2_j2u_div_j2u_underflow (3), @@ -984,11 +1130,21 @@ operands. Calculate the ratio between values, and discard the computed remainder, but detect underflow (non-zero remainder). .TP +.BR libj2_j2i_rdiv_j2i_underflow (3), +.TQ .BR libj2_j2u_rdiv_j2u_underflow (3) Calculate the ratio between values, and discard the computed remainder, but detect underflow (non-zero remainder). This function swaps the position of the two operands. .TP +.BR libj2_j2i_mod_j2i (3), +.TQ +.BR libj2_j2i_mod_j2i_to_j2i (3), +.TQ +.BR libj2_j2i_mod_ji (3), +.TQ +.BR libj2_j2i_mod_ji_to_j2i (3), +.TQ .BR libj2_j2u_mod_j2u (3), .TQ .BR libj2_j2u_mod_j2u_to_j2u (3), @@ -999,6 +1155,8 @@ This function swaps the position of the two operands. Calculate the remainder of the integer division between two values. .TP +.BR libj2_j2i_rmod_j2i (3), +.TQ .BR libj2_j2u_rmod_j2u (3) Calculate the remainder of the integer division between two values. This function swaps the position of the two operands. @@ -162,17 +162,22 @@ enum libj2_overflow { #include "libj2/sign-shifting.h" #include "libj2/bit-shifting.h" #include "libj2/bit-scanning.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/addition.h" +#include "libj2/subtraction.h" +#include "libj2/multiplication.h" +#include "libj2/division.h" #include "libj2/saturated-math.h" /* TODO add signed versions */ #include "libj2/strings.h" -#if defined(LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_) -# undef LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_ +#if !defined(LIBJ2_COMPILING_) +# if defined(LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_) +# undef LIBJ2_USE_GCC_INTRINSIC_FUNCTIONS_ +# endif +# if defined(LIBJ2_USE_GCC_PARITYG_) +# undef LIBJ2_USE_GCC_PARITYG_ +# endif +# undef LIBJ2_PURE_ #endif -#undef LIBJ2_PURE_ #endif diff --git a/libj2/addition.h b/libj2/addition.h index c0fed6e..de44e98 100644 --- a/libj2/addition.h +++ b/libj2/addition.h @@ -172,7 +172,7 @@ libj2_ju_add_j2u_to_j2u_overflow(uintmax_t a, const struct libj2_j2u *b, struct /** * Calculate the sum, as an unsigned double-max precision - * integer, of two unsigned double-max precision integers + * integer, of two unsigned max precision integers * * `libj2_ju_add_ju_to_j2u(a, b, res)` implements * `*res = a + b`, where `a` and `b` are converted to @@ -222,10 +222,11 @@ libj2_j2u_add_j2u(struct libj2_j2u *a, const struct libj2_j2u *b) /** - * Calculate the sum of two unsigned double-max precision - * integers + * Calculate the sum of two unsigned double-max + * precision integers * - * `libj2_j2u_add_j2u_to_j2u(a, b, res)` implements `*res = *a + *b` + * `libj2_j2u_add_j2u_to_j2u(a, b, res)` implements + * `*res = *a + *b` * * @param a The augend * @param b The addend @@ -350,7 +351,7 @@ libj2_j2u_add_j2u_to_j2u_overflow(const struct libj2_j2u *a, const struct libj2_ * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_j2u_add_ju_overflow_p(const struct libj2_j2u *a, uintmax_t b) { return a->low > UINTMAX_MAX - b && a->high == UINTMAX_MAX; @@ -371,7 +372,7 @@ libj2_j2u_add_ju_overflow_p(const struct libj2_j2u *a, uintmax_t b) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_ju_add_j2u_overflow_p(uintmax_t a, const struct libj2_j2u *b) { return libj2_j2u_add_ju_overflow_p(b, a); @@ -391,9 +392,10 @@ libj2_ju_add_j2u_overflow_p(uintmax_t a, const struct libj2_j2u *b) * @param b The addend * @return 1 if the addition would overflow, 0 otherwise * - * @since 1.0 + * @since 1.0 (broken) + * @since 1.1 (fixed) */ -inline int +LIBJ2_PURE_ inline int libj2_j2u_add_j2u_overflow_p(const struct libj2_j2u *a, const struct libj2_j2u *b) { if (a == b) @@ -405,3 +407,373 @@ libj2_j2u_add_j2u_overflow_p(const struct libj2_j2u *a, const struct libj2_j2u * else return a->high > UINTMAX_MAX - b->high; } + + + + + +/** + * Calculate the sum of a signed double-max precision + * integer and a signed max precision integer + * + * `libj2_j2i_add_ji(a, b)` implements `*a += b` + * + * @param a The augend, and output parameter for the sum + * @param b The addend + * + * @since 1.1 + */ +inline void +libj2_j2i_add_ji(struct libj2_j2i *a, intmax_t b) +{ + struct libj2_j2u u; + if (b < 0) { + u.high = UINTMAX_MAX; + u.low = ~(uintmax_t)-(b + 1); + } else { + u.high = 0; + u.low = (uintmax_t)b; + } + libj2_j2u_add_j2u((void *)a, &u); +} + + +/** + * Calculate the sum of two signed double-max precision + * integers + * + * `libj2_j2i_add_j2i(a, b)` implements `*a += *b` + * + * @param a The augend, and output parameter for the sum + * @param b The addend + * + * @since 1.1 + */ +inline void +libj2_j2i_add_j2i(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + libj2_j2u_add_j2u((void *)a, (const void *)b); +} + + +/** + * Calculate the sum of a signed double-max precision + * integer and a signed max precision integer + * + * `libj2_j2i_add_ji_to_j2i(a, b, res)` implements + * `*res = *a + b` + * + * @param a The augend + * @param b The addend + * @param res Output parameter for the sum + * + * @since 1.1 + */ +inline void +libj2_j2i_add_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res) +{ + struct libj2_j2u u; + if (b < 0) { + u.high = UINTMAX_MAX; + u.low = ~(uintmax_t)-(b + 1); + } else { + u.high = 0; + u.low = (uintmax_t)b; + } + libj2_j2u_add_j2u_to_j2u((const void *)a, &u, (void *)res); +} + + +/** + * Calculate the sum of two signed double-max precision + * integers + * + * `libj2_j2i_add_j2i_to_j2i(a, b, res)` implements `*res = *a + *b` + * + * @param a The augend + * @param b The addend + * @param res Output parameter for the sum + * + * @since 1.1 + */ +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); +} + + +/** + * Calculate the sum, as a signed double-max precision + * integer, of two signed max precision integers + * + * `libj2_ji_add_ji_to_j2i(a, b, res)` implements + * `*res = a + b`, where `a` and `b` are converted to + * `struct libj2_j2i`'s + * + * @param a The augend + * @param b The addend + * @param res Output parameter for the sum + * + * @since 1.1 + */ +inline void +libj2_ji_add_ji_to_j2i(intmax_t a, intmax_t b, struct libj2_j2i *res) +{ + struct libj2_j2u u, v; + if (a < 0) { + u.high = UINTMAX_MAX; + u.low = ~(uintmax_t)-(a + 1); + } else { + u.high = 0; + u.low = (uintmax_t)a; + } + if (b < 0) { + v.high = UINTMAX_MAX; + v.low = ~(uintmax_t)-(b + 1); + } else { + v.high = 0; + v.low = (uintmax_t)b; + } + libj2_j2u_add_j2u_to_j2u(&u, &v, (void *)res); +} + + +/** + * Calculate the sum of a signed max precision + * integer and a signed double-max precision integer + * + * `libj2_ji_add_j2i_to_j2i(a, b, res)` implements + * `*res = a + *b` + * + * @param a The augend + * @param b The addend + * @param res Output parameter for the sum + * + * @since 1.1 + */ +inline void +libj2_ji_add_j2i_to_j2i(intmax_t a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + libj2_j2i_add_ji_to_j2i(b, a, res); +} + + +/** + * Predict the result-overflow signal + * `libj2_j2i_add_j2i_to_j2i_overflow` or + * `libj2_j2i_add_j2i_overflow` will return + * + * `libj2_j2i_add_j2i_overflow_p(a, b)` implements + * `libj2_j2i_add_j2i_to_j2i_overflow(a, b, &(struct libj2_j2i){})` + * in an efficient manner + * + * @param a The augend + * @param b The addend + * @return +1 if the addition would overflow positively, + * -1 if the addition would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_j2i_add_j2i_overflow_p(const struct libj2_j2i *a, const struct libj2_j2i *b) +{ + if (libj2_j2i_is_positive(a) && libj2_j2i_is_positive(b)) { + if (a == b) + return (int)(a->high >> (LIBJ2_JU_BIT - 2U)); + if (a->low > UINTMAX_MAX - b->low) + return a->high >= (uintmax_t)INTMAX_MAX - b->high; + else + return a->high > (uintmax_t)INTMAX_MAX - b->high; + } else if (libj2_j2i_is_negative(a) && libj2_j2i_is_negative(b)) { + if (a == b) + return ~a->high >> (LIBJ2_JU_BIT - 2U) ? -1 : 0; + if (a->low > UINTMAX_MAX - b->low) + return a->high + b->high + 1U < ~(uintmax_t)INTMAX_MAX ? -1 : 0; + else + return a->high + b->high < ~(uintmax_t)INTMAX_MAX ? -1 : 0; + } else { + return 0; + } +} + + +/** + * Predict the result-overflow signal + * `libj2_j2i_add_ji_to_j2i_overflow` or + * `libj2_j2i_add_ji_overflow` will return + * + * `libj2_j2i_add_ji_overflow_p(a, b)` implements + * `libj2_j2i_add_ji_to_j2i_overflow(a, b, &(struct libj2_j2i){})` + * in an efficient manner + * + * @param a The augend + * @param b The addend + * @return +1 if the addition would overflow positively, + * -1 if the addition would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_j2i_add_ji_overflow_p(const struct libj2_j2i *a, intmax_t b) +{ + if (b > 0 && libj2_j2i_is_positive(a)) { + if (a->low > UINTMAX_MAX - (uintmax_t)b) + return a->high >= (uintmax_t)INTMAX_MAX; + else + return a->high > (uintmax_t)INTMAX_MAX; + } else if (b < 0 && libj2_j2i_is_negative(a)) { + if (a->low > UINTMAX_MAX - ~(uintmax_t)-(b + 1)) + return a->high < ~(uintmax_t)INTMAX_MAX ? -1 : 0; + else + return a->high <= ~(uintmax_t)INTMAX_MAX ? -1 : 0; + } else { + return 0; + } +} + + +/** + * Predict the result-overflow signal + * `libj2_ji_add_j2i_to_j2i_overflow` will return + * + * `libj2_ji_add_j2i_overflow_p(a, b)` implements + * `libj2_ji_add_j2i_to_j2i_overflow(a, b, &(struct libj2_j2i){})` + * in an efficient manner + * + * @param a The augend + * @param b The addend + * @return +1 if the addition would overflow positively, + * -1 if the addition would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_ji_add_j2i_overflow_p(intmax_t a, const struct libj2_j2i *b) +{ + return libj2_j2i_add_ji_overflow_p(b, a); +} + + +/** + * Calculate the sum of a signed double-max precision + * integer and a signed max precision integer + * + * `libj2_j2i_add_ji_overflow(a, b)` implements `*a += b` + * with overflow-detection + * + * @param a The augend, and output parameter for the sum + * @param b The addend + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_add_ji_overflow(struct libj2_j2i *a, intmax_t b) +{ + int overflow = libj2_j2i_add_ji_overflow_p(a, b); + libj2_j2i_add_ji(a, b); + return overflow; +} + + +/** + * Calculate the sum of two signed double-max precision + * integers + * + * `libj2_j2i_add_j2i_overflow(a, b)` implements `*a += *b` + * with overflow-detection + * + * @param a The augend, and output parameter for the sum + * @param b The addend + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_add_j2i_overflow(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + int overflow = libj2_j2i_add_j2i_overflow_p(a, b); + libj2_j2i_add_j2i(a, b); + return overflow; +} + + +/** + * Calculate the sum of a signed double-max precision + * integer and a signed max precision integer + * + * `libj2_j2i_add_ji_to_j2i_overflow(a, b, res)` implements + * `*res = *a + b` with overflow-detection + * + * @param a The augend + * @param b The addend + * @param res Output parameter for the sum + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_add_ji_to_j2i_overflow(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res) +{ + int overflow = libj2_j2i_add_ji_overflow_p(a, b); + libj2_j2i_add_ji_to_j2i(a, b, res); + return overflow; +} + + +/** + * Calculate the sum of two signed double-max precision + * integers + * + * `libj2_j2i_add_j2i_to_j2i_overflow(a, b, res)` implements + * `*res = *a + *b` with overflow-detection + * + * @param a The augend + * @param b The addend + * @param res Output parameter for the sum + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_add_j2i_to_j2i_overflow(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + int overflow = libj2_j2i_add_j2i_overflow_p(a, b); + libj2_j2i_add_j2i_to_j2i(a, b, res); + return overflow; +} + + +/** + * Calculate the sum of a signed max precision + * integer and a signed double-max precision integer + * + * `libj2_ji_add_j2i_to_j2i_overflow(a, b, res)` implements + * `*res = a + *b` with overflow-detection + * + * @param a The augend + * @param b The addend + * @param res Output parameter for the sum + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_ji_add_j2i_to_j2i_overflow(intmax_t a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + return libj2_j2i_add_ji_to_j2i_overflow(b, a, res); +} diff --git a/libj2/bit-shifting.h b/libj2/bit-shifting.h index 7cf44bf..b04a533 100644 --- a/libj2/bit-shifting.h +++ b/libj2/bit-shifting.h @@ -624,7 +624,7 @@ libj2_ju_rrot_to_j2u(uintmax_t a, unsigned b, struct libj2_j2u *res) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_j2u_lsh_overflow_p(const struct libj2_j2u *a, unsigned b) { if (b >= LIBJ2_J2U_BIT) @@ -654,7 +654,7 @@ libj2_j2u_lsh_overflow_p(const struct libj2_j2u *a, unsigned b) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_ju_lsh_overflow_p(uintmax_t a, unsigned b) { if (b >= LIBJ2_J2U_BIT) @@ -681,7 +681,7 @@ libj2_ju_lsh_overflow_p(uintmax_t a, unsigned b) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_j2u_rsh_underflow_p(const struct libj2_j2u *a, unsigned b) { if (b >= LIBJ2_J2U_BIT) @@ -711,7 +711,7 @@ libj2_j2u_rsh_underflow_p(const struct libj2_j2u *a, unsigned b) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_ju_rsh_underflow_p(uintmax_t a, unsigned b) { if (b >= LIBJ2_JU_BIT) @@ -839,7 +839,7 @@ libj2_ji_lsh_to_j2i(intmax_t a, unsigned b, struct libj2_j2i *res) * * @since 1.1 */ -inline int +LIBJ2_PURE_ inline int libj2_j2i_lsh_overflow_p(const struct libj2_j2i *a, unsigned b) { if (!b) { @@ -885,7 +885,7 @@ libj2_j2i_lsh_overflow_p(const struct libj2_j2i *a, unsigned b) * * @since 1.1 */ -inline int +LIBJ2_PURE_ inline int libj2_ji_lsh_overflow_p(intmax_t a, unsigned b) { if (b >= LIBJ2_J2I_BIT) @@ -1251,7 +1251,7 @@ libj2_ji_rsh_to_j2i_underflow(intmax_t a, unsigned b, struct libj2_j2i *res) * * @since 1.1 */ -inline int +LIBJ2_PURE_ inline int libj2_j2i_rsh_underflow_p(const struct libj2_j2i *a, unsigned b) { if (libj2_j2i_is_negative(a)) { @@ -1284,7 +1284,7 @@ libj2_j2i_rsh_underflow_p(const struct libj2_j2i *a, unsigned b) * * @since 1.1 */ -inline int +LIBJ2_PURE_ inline int libj2_ji_rsh_underflow_p(intmax_t a, unsigned b) { if (b >= LIBJ2_JU_BIT) diff --git a/libj2/division.h b/libj2/division.h index 274ce13..603a1b6 100644 --- a/libj2/division.h +++ b/libj2/division.h @@ -702,3 +702,761 @@ libj2_j2u_div_ju_to_j2u_underflow(const struct libj2_j2u *a, uintmax_t b, struct libj2_j2u_divmod_ju_to_j2u(&c, b, res); return c.high || c.low; } + + + + + +/** + * Calculate the integer quotient, rounded + * towards zero, and remainder of two signed + * double-max precision integers + * + * `libj2_j2i_divmod_j2i_to_j2i(a, b, res_q)` + * implements `*res_q = *a / *b, *a %= *b` + * + * For the quotient q, and remainder r, + * dividend n, and divisor d, it will be true + * that qd + r = n + * + * Overflows if `libj2_j2i_is_min(a) && libj2_j2i_eq_ji(b, -1)` + * + * @param a The dividend (left-hand), also used as + * the output parameter for the remainder + * @param b The divisor (right-hand) + * @param res_q Output parameter for the quotient + * + * @since 1.1 + */ +inline void +libj2_j2i_divmod_j2i_to_j2i(struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res_q) +{ + int a_neg = libj2_j2i_is_negative(a); + int b_neg = libj2_j2i_is_negative(b); + struct libj2_j2u u; + if (b_neg) + libj2_minus_j2i_to_j2u(b, &u); + else + libj2_j2i_to_j2u(b, &u); + if (a_neg) + libj2_minus_j2i(a); + libj2_j2u_divmod_j2u_to_j2u((void *)a, &u, (void *)res_q); + if (a_neg) + libj2_minus_j2i(a); + if (a_neg != b_neg) + libj2_minus_j2i(res_q); +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, and remainder of two signed + * double-max precision integers + * + * `libj2_j2i_divmod_j2i_to_j2i_j2i(a, b, res_q, res_r)` + * implements `*res_q = *a / *b, *res_r = *a % *b` + * + * For the quotient q, and remainder r, + * dividend n, and divisor d, it will be true + * that qd + r = n + * + * Overflows if `libj2_j2i_is_min(a) && libj2_j2i_eq_ji(b, -1)` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @param res_q Output parameter for the quotient + * @param res_r Output parameter for the remainder + * + * @since 1.1 + */ +inline void +libj2_j2i_divmod_j2i_to_j2i_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, + struct libj2_j2i *res_q, struct libj2_j2i *res_r) +{ + if (res_r == b) { + struct libj2_j2i r = *a; + libj2_j2i_divmod_j2i_to_j2i(&r, b, res_q); + *res_r = r; + } else { + *res_r = *a; + libj2_j2i_divmod_j2i_to_j2i(res_r, b, res_q); + } +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, and remainder of two signed + * double-max precision integers + * + * `libj2_j2i_divmod_j2i(a, b)` implements + * `t = (intmax_t)(*a / *b), *a %= *b, t` + * (using an intermediate variable `t`) + * + * For the quotient q, and remainder r, + * dividend n, and divisor d, it will be true + * that qd + r = n; however the high half + * of the q is discarded in this function's + * return value + * + * Overflows if `libj2_j2i_is_min(a) && libj2_j2i_eq_ji(b, -1)` + * + * @param a The dividend (left-hand), also used as + * the output parameter for the remainder + * @param b The divisor (right-hand) + * @return The low half of the quotient + * + * @since 1.1 + */ +inline intmax_t +libj2_j2i_divmod_j2i(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + struct libj2_j2i q; + libj2_j2i_divmod_j2i_to_j2i(a, b, &q); + if (libj2_j2i_is_negative(&q)) { + libj2_minus_j2i(&q); + return -(intmax_t)q.low; + } else { + return (intmax_t)q.low; + } +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, and remainder of a signed + * double-max precision integer (dividend) and + * a signed max precision integer (divisor) + * + * `libj2_j2i_divmod_ji(a, b)` implements + * `t = (intmax_t)(*a / b), *a %= b, t` + * (using an intermediate variable `t`) + * + * For the quotient q, and remainder r, + * dividend n, and divisor d, it will be true + * that qd + r = n; however the high half + * of the q is discarded in this function's + * return value + * + * Overflows if `libj2_j2i_is_min(a) && b == -1` + * + * @param a The dividend (left-hand), also used as + * the output parameter for the remainder + * @param b The divisor (right-hand) + * @return The low half of the quotient + * + * @since 1.1 + */ +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; + if (a_neg) + libj2_minus_j2i(a); + if (b < 0) + u = (uintmax_t)-(b + 1) + 1U; + else + u = (uintmax_t)b; + q = libj2_j2u_divmod_ju((void *)a, u); + if (a_neg) + libj2_minus_j2i(a); + return a_neg != (b < 0) ? -(intmax_t)q : (intmax_t)q; +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, and remainder of a signed + * double-max precision integer (dividend) and + * a signed max precision integer (divisor) + * + * `libj2_j2i_divmod_ji_to_j2i(a, b, res_q)` + * implements `*res_q = *a / b, *a %= b` + * + * For the quotient q, and remainder r, + * dividend n, and divisor d, it will be true + * that qd + r = n + * + * Overflows if `libj2_j2i_is_min(a) && b == -1` + * + * @param a The dividend (left-hand), also used as + * the output parameter for the remainder + * @param b The divisor (right-hand) + * @param res_q Output parameter for the quotient + * + * @since 1.1 + */ +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; + if (a_neg) + libj2_minus_j2i(a); + if (b < 0) + u = (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); + if (a_neg) + libj2_minus_j2i(a); + if (a_neg != (b < 0)) + libj2_minus_j2i(res_q); +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, and remainder of a signed + * double-max precision integer (dividend) and + * a signed max precision integer (divisor) + * + * `libj2_j2i_divmod_ji_to_j2i_j2i(a, b, res_q, res_r)` + * implements `*res_q = *a / b, *res_r = *a % b` + * + * For the quotient q, and remainder r, + * dividend n, and divisor d, it will be true + * that qd + r = n + * + * Overflows if `libj2_j2i_is_min(a) && b == -1` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @param res_q Output parameter for the quotient + * @param res_r Output parameter for the remainder + * + * @since 1.1 + */ +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); + uintmax_t u; + if (a_neg) + libj2_minus_j2i_to_j2u(a, (void *)res_r); + else + *res_r = *a; + 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); + if (a_neg) + libj2_minus_j2i(res_r); + if (a_neg != (b < 0)) + libj2_minus_j2i(res_q); +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, and remainder of two signed + * double-max precision integers; in this variant + * of `libj2_j2i_rdivmod_j2i_to_j2i`, the dividend + * (left-hand) is the second parameter and the + * divisor (right-hand) is the first parameter + * + * `libj2_j2i_rdivmod_j2i_to_j2i(a, b, res_q)` + * implements `*res_q = *b / *a, *a = *b % *a` + * + * For the quotient q, and remainder r, + * dividend n, and divisor d, it will be true + * that qd + r = n + * + * Overflows if `libj2_j2i_is_min(b) && libj2_j2i_eq_ji(a, -1)` + * + * @param a The divisor (right-hand), also used as + * the output parameter for the remainder + * @param b The dividend (left-hand) + * @param res_q Output parameter for the quotient + * + * @since 1.1 + */ +inline void +libj2_j2i_rdivmod_j2i_to_j2i(struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res_q) +{ + struct libj2_j2i res_r; + libj2_j2i_divmod_j2i_to_j2i_j2i(b, a, res_q, &res_r); + *a = res_r; +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, and remainder of two signed + * double-max precision integers; in this variant + * of `libj2_j2i_rdivmod_j2i_to_j2i`, the dividend + * (left-hand) is the second parameter and the + * divisor (right-hand) is the first parameter + * + * `libj2_j2i_rdivmod_j2i(a, b)` implements + * `t = (intmax_t)(*b / *a), *a = *b % *a, t` + * (using an intermediate variable `t`) + * + * For the quotient q, and remainder r, + * dividend n, and divisor d, it will be true + * that qd + r = n; however the high half + * of the q is discarded in this function's + * return value + * + * Overflows if `libj2_j2i_is_min(b) && libj2_j2i_eq_ji(a, -1)` + * + * @param a The divisor (right-hand), also used as + * the output parameter for the remainder + * @param b The dividend (left-hand) + * @return The low half of the quotient + * + * @since 1.1 + */ +inline intmax_t +libj2_j2i_rdivmod_j2i(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + struct libj2_j2i q; + libj2_j2i_divmod_j2i_to_j2i_j2i(b, a, &q, a); + if (libj2_j2i_is_negative(&q)) { + libj2_minus_j2i(&q); + return -(intmax_t)q.low; + } else { + return (intmax_t)q.low; + } +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of two signed double-max + * precision integers + * + * `libj2_j2i_div_j2i(a, b)` implements `*a /= *b` + * + * Overflows if `libj2_j2i_is_min(a) && libj2_j2i_eq_ji(b, -1)` + * + * @param a The dividend (left-hand), also used as + * the output parameter for the quotient + * @param b The divisor (right-hand) + * + * @since 1.1 + */ +inline void +libj2_j2i_div_j2i(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + struct libj2_j2i c = *a; + libj2_j2i_divmod_j2i_to_j2i(&c, b, a); +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of two signed double-max + * precision integers + * + * `libj2_j2i_div_j2i_to_j2i(a, b, res)` + * implements `*res = *a / *b` + * + * Overflows if `libj2_j2i_is_min(a) && libj2_j2i_eq_ji(b, -1)` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @param res Output parameter for the quotient + * + * @since 1.1 + */ +inline void +libj2_j2i_div_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + struct libj2_j2i c = *a; + libj2_j2i_divmod_j2i_to_j2i(&c, b, res); +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of two signed double-max + * precision integers + * + * `libj2_j2i_div_j2i_return(a, b)` + * implements `(intmax_t)(*a / *b)` + * + * Overflows if `libj2_j2i_is_min(a) && libj2_j2i_eq_ji(b, -1)` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @return The low half of the quotient + * + * @since 1.1 + */ +inline intmax_t +libj2_j2i_div_j2i_return(const struct libj2_j2i *a, const struct libj2_j2i *b) +{ + struct libj2_j2i c = *a; + return libj2_j2i_divmod_j2i(&c, b); +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of two signed double-max + * precision integers; in this variant + * of `libj2_j2i_div_j2i`, the dividend + * (left-hand) is the second parameter and the + * divisor (right-hand) is the first parameter + * + * `libj2_j2i_rdiv_j2i(a, b)` implements `*a = *b / *a` + * + * Overflows if `libj2_j2i_is_min(b) && libj2_j2i_eq_ji(a, -1)` + * + * @param a The divisor (right-hand), also used as + * the output parameter for the quotient + * @param b The dividend (left-hand) + * + * @since 1.1 + */ +inline void +libj2_j2i_rdiv_j2i(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + struct libj2_j2i c = *b; + libj2_j2i_divmod_j2i_to_j2i(&c, a, a); +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of a signed double-max + * precision integer (dividend) and a + * signed max precision integer (divisor) + * + * `libj2_j2i_div_ji(a, b)` implements `*a /= b` + * + * Overflows if `libj2_j2i_is_min(a) && b == -1` + * + * @param a The dividend (left-hand), also used as + * the output parameter for the quotient + * @param b The divisor (right-hand) + * + * @since 1.1 + */ +inline void +libj2_j2i_div_ji(struct libj2_j2i *a, intmax_t b) +{ + struct libj2_j2i c = *a; + libj2_j2i_divmod_ji_to_j2i(&c, b, a); +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of a signed double-max + * precision integer (dividend) and a + * signed max precision integer (divisor) + * + * `libj2_j2i_div_ji_to_j2i(a, b, res)` + * implements `*res = *a / b` + * + * Overflows if `libj2_j2i_is_min(a) && b == -1` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @param res Output parameter for the quotient + * + * @since 1.1 + */ +inline void +libj2_j2i_div_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res) +{ + struct libj2_j2i c = *a; + libj2_j2i_divmod_ji_to_j2i(&c, b, res); +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of a signed double-max + * precision integer (dividend) and a + * signed max precision integer (divisor) + * + * `libj2_j2i_div_ji_return(a, b)` + * implements `(intmax_t)(*a / b)` + * + * Overflows if `libj2_j2i_is_min(a) && b == -1` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @return The low half of the quotient + * + * @since 1.1 + */ +inline intmax_t +libj2_j2i_div_ji_return(const struct libj2_j2i *a, intmax_t b) +{ + struct libj2_j2i c = *a; + return libj2_j2i_divmod_ji(&c, b); +} + + +/** + * Calculate the integer remainder, for integer + * division with the quotient rounded towards zero, + * of two signed double-max precision integers + * + * `libj2_j2i_mod_j2i(a, b)` implements `*a %= *b` + * + * @param a The dividend (left-hand), also used as + * the output parameter for the remainder + * @param b The divisor (right-hand) + * + * @since 1.1 + */ +inline void +libj2_j2i_mod_j2i(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + (void) libj2_j2i_divmod_j2i(a, b); +} + + +/** + * Calculate the integer remainder, for integer + * division with the quotient rounded towards zero, + * of two signed double-max precision integers + * + * `libj2_j2i_mod_j2i_to_j2i(a, b, res)` + * implements `*res = *a % *b` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @param res Output parameter for the remainder + * + * @since 1.1 + */ +inline void +libj2_j2i_mod_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + if (res == b) { + struct libj2_j2i r = *a; + libj2_j2i_mod_j2i(&r, b); + *res = r; + } else { + *res = *a; + libj2_j2i_mod_j2i(res, b); + } +} + + +/** + * Calculate the integer remainder, for integer + * division with the quotient rounded towards zero, + * of two signed double-max precision integers; + * in this variant of `libj2_j2i_mod_j2i`, the + * dividend (left-hand) is the second parameter + * and the divisor (right-hand) is the first parameter + * + * `libj2_j2i_rmod_j2i_to_j2i(a, b)` implements + * `*a = *b % *a` + * + * @param a The divisor (right-hand), also used as + * the output parameter for the remainder + * @param b The dividend (left-hand) + * + * @since 1.1 + */ +inline void +libj2_j2i_rmod_j2i(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + libj2_j2i_mod_j2i_to_j2i(b, a, a); +} + + +/** + * Calculate the integer remainder, for integer + * division with the quotient rounded towards zero, + * of a signed double-max precision integer + * (dividend) and a signed max precision + * integer (divisor) + * + * `libj2_j2i_mod_ji(a, b)` implements `*a %= b` + * + * @param a The dividend (left-hand), also used as + * the output parameter for the remainder + * @param b The divisor (right-hand) + * + * @since 1.1 + */ +inline void +libj2_j2i_mod_ji(struct libj2_j2i *a, intmax_t b) +{ + int a_neg = libj2_j2i_is_negative(a); + uintmax_t u; + if (a_neg) + libj2_minus_j2i(a); + if (b < 0) + u = (uintmax_t)-(b + 1) + 1U; + else + u = (uintmax_t)b; + libj2_j2u_mod_ju((void *)a, u); + if (a_neg) + libj2_minus_j2i(a); +} + + +/** + * Calculate the integer remainder, for integer + * division with the quotient rounded towards zero, + * of a signed double-max precision integer + * (dividend) and a signed max precision + * integer (divisor) + * + * `libj2_j2i_mod_ji_to_j2i(a, b, res)` + * implements `*res = *a % b` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @param res Output parameter for the remainder + * + * @since 1.1 + */ +inline void +libj2_j2i_mod_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res) +{ + *res = *a; + libj2_j2i_mod_ji(res, b); +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of two signed double-max + * precision integers + * + * `libj2_j2i_div_j2i_underflow(a, b)` implements + * `t = !!(*a % b), *a /= *b, t` + * (using an intermediate variable `t`) + * + * Overflows if `libj2_j2i_is_min(a) && libj2_j2i_eq_ji(b, -1)` + * + * @param a The dividend (left-hand), also used as + * the output parameter for the quotient + * @param b The divisor (right-hand) + * @return 1 if the remainder is non-zero, 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_div_j2i_underflow(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + struct libj2_j2i c = *a; + libj2_j2i_divmod_j2i_to_j2i(&c, b, a); + return c.high || c.low; +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of two signed double-max + * precision integers + * + * `libj2_j2i_div_j2i_to_j2i_underflow(a, b, res)` + * implements `*res = *a / *b, !!(a % b)` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @param res Output parameter for the quotient + * @return 1 if the remainder is non-zero, 0 otherwise + * + * Overflows if `libj2_j2i_is_min(a) && libj2_j2i_eq_ji(b, -1)` + * + * @since 1.1 + */ +inline int +libj2_j2i_div_j2i_to_j2i_underflow(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + struct libj2_j2i c = *a; + libj2_j2i_divmod_j2i_to_j2i(&c, b, res); + return c.high || c.low; +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of two signed double-max + * precision integers; in this variant + * of `libj2_j2i_div_j2i`, the dividend + * (left-hand) is the second parameter and the + * divisor (right-hand) is the first parameter + * + * `libj2_j2i_rdiv_j2i_underflow(a, b)` implements + * `t = !!(*a % *b), *a = *b / *a, t` + * (using an intermediate variable `t`) + * + * Overflows if `libj2_j2i_is_min(b) && libj2_j2i_eq_ji(a, -1)` + * + * @param a The divisor (right-hand), also used as + * the output parameter for the quotient + * @param b The dividend (left-hand) + * @return 1 if the remainder is non-zero, 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_rdiv_j2i_underflow(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + struct libj2_j2i c = *b; + libj2_j2i_divmod_j2i_to_j2i(&c, a, a); + return c.high || c.low; +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of a signed double-max + * precision integer (dividend) and a + * signed max precision integer (divisor) + * + * `libj2_j2i_div_ji_underflow(a, b)` implements + * `t = !!(a % b), *a /= b, t` + * (using an intermediate variable `t`) + * + * Overflows if `libj2_j2i_is_min(a) && b == -1` + * + * @param a The dividend (left-hand), also used as + * the output parameter for the quotient + * @param b The divisor (right-hand) + * @return 1 if the remainder is non-zero, 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_div_ji_underflow(struct libj2_j2i *a, intmax_t b) +{ + struct libj2_j2i c = *a; + libj2_j2i_divmod_ji_to_j2i(&c, b, a); + return c.high || c.low; +} + + +/** + * Calculate the integer quotient, rounded + * towards zero, of a signed double-max + * precision integer (dividend) and a + * signed max precision integer (divisor) + * + * `libj2_j2i_div_ji_to_j2i_underflow(a, b, res)` + * implements `*res = *a / b, !!(a % b)` + * + * Overflows if `libj2_j2i_is_min(a) && b == -1` + * + * @param a The dividend (left-hand) + * @param b The divisor (right-hand) + * @param res Output parameter for the quotient + * @return 1 if the remainder is non-zero, 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_div_ji_to_j2i_underflow(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res) +{ + struct libj2_j2i c = *a; + libj2_j2i_divmod_ji_to_j2i(&c, b, res); + return c.high || c.low; +} diff --git a/libj2/multiplication.h b/libj2/multiplication.h index eb0d9a5..a80161b 100644 --- a/libj2/multiplication.h +++ b/libj2/multiplication.h @@ -6,7 +6,7 @@ /** * Calculate the unsigned double-max precision integer - * product of two unsigned double-max precision integers + * product of two unsigned max precision integers * * `libj2_ju_mul_ju_to_j2u(a, b, res)` implements * `*res = a * b`, where `a` and `b` are converted @@ -63,8 +63,8 @@ libj2_ju_mul_ju_to_j2u(uintmax_t a, uintmax_t b, struct libj2_j2u *res) /** - * Calculate the product of an unsigned double-max - * precision integer (multiplier) and an unsigned + * Calculate the product of a signed double-max + * precision integer (multiplier) and a signed * max precision integer (multiplicand) * * `libj2_j2u_mul_ju_to_j2u(a, b)` implements `*a *= b`, @@ -86,8 +86,8 @@ libj2_j2u_mul_ju(struct libj2_j2u *a, uintmax_t b) /** - * Calculate the product of an unsigned double-max - * precision integer (multiplier) and an unsigned + * Calculate the product of a signed double-max + * precision integer (multiplier) and a signed * max precision integer (multiplicand) * * `libj2_j2u_mul_ju_to_j2u(a, b, res)` implements @@ -109,8 +109,8 @@ libj2_j2u_mul_ju_to_j2u(const struct libj2_j2u *a, uintmax_t b, struct libj2_j2u /** - * Calculate the product of an unsigned max - * precision integer (multiplier) and an unsigned + * Calculate the product of a signed max + * precision integer (multiplier) and a signed * double-max precision integer (multiplicand) * * `libj2_ju_mul_j2u_to_j2u(a, b, res)` implements @@ -132,8 +132,8 @@ libj2_ju_mul_j2u_to_j2u(uintmax_t a, const struct libj2_j2u *b, struct libj2_j2u /** - * Calculate the product of an unsigned double-max - * precision integer (multiplier) and an unsigned + * Calculate the product of a signed double-max + * precision integer (multiplier) and a signed * max precision integer (multiplicand) * * `libj2_j2u_mul_ju_to_overflow(a, b)` implements @@ -176,8 +176,8 @@ libj2_j2u_mul_ju_overflow(struct libj2_j2u *a, uintmax_t b) /** - * Calculate the product of an unsigned double-max - * precision integer (multiplier) and an unsigned + * Calculate the product of a signed double-max + * precision integer (multiplier) and a signed * max precision integer (multiplicand) * * `libj2_j2u_mul_ju_to_j2u_overflow(a, b, res)` @@ -201,8 +201,8 @@ libj2_j2u_mul_ju_to_j2u_overflow(const struct libj2_j2u *a, uintmax_t b, struct /** - * Calculate the product of an unsigned max - * precision integer (multiplier) and an unsigned + * Calculate the product of a signed max + * precision integer (multiplier) and a signed * double-max precision integer (multiplicand) * * `libj2_ju_mul_j2u_to_j2u_overflow(a, b, res)` @@ -400,11 +400,11 @@ libj2_j2u_mul_j2u_to_j2u_overflow(const struct libj2_j2u *a, const struct libj2_ * @param b The multiplicand * @return `LIBJ2_OVERFLOW` (= 1) if the multiplication would overflow, * `LIBJ2_NO_OVERFLOW` (= 0) if the multiplication would not overflow, - * or `LIBJ2_OVERFLOW_UNKNOWN` if the prediction was not made + * or `LIBJ2_OVERFLOW_UNKNOWN` (= +2) if the prediction was not made * * @since 1.0 */ -inline enum libj2_overflow +LIBJ2_PURE_ inline enum libj2_overflow libj2_j2u_mul_j2u_overflow_p_quick(const struct libj2_j2u *a, const struct libj2_j2u *b) { unsigned lz; @@ -434,11 +434,11 @@ libj2_j2u_mul_j2u_overflow_p_quick(const struct libj2_j2u *a, const struct libj2 * @param b The multiplicand * @return `LIBJ2_OVERFLOW` (= 1) if the multiplication would overflow, * `LIBJ2_NO_OVERFLOW` (= 0) if the multiplication would not overflow, - * or `LIBJ2_OVERFLOW_UNKNOWN` if the prediction was not made + * or `LIBJ2_OVERFLOW_UNKNOWN` (= +2) if the prediction was not made * * @since 1.0 */ -inline enum libj2_overflow +LIBJ2_PURE_ inline enum libj2_overflow libj2_j2u_mul_ju_overflow_p_quick(const struct libj2_j2u *a, uintmax_t b) { return libj2_j2u_mul_j2u_overflow_p_quick(a, &(struct libj2_j2u){.high = 0, .low = b}); @@ -453,11 +453,11 @@ libj2_j2u_mul_ju_overflow_p_quick(const struct libj2_j2u *a, uintmax_t b) * @param b The multiplicand * @return `LIBJ2_OVERFLOW` (= 1) if the multiplication would overflow, * `LIBJ2_NO_OVERFLOW` (= 0) if the multiplication would not overflow, - * or `LIBJ2_OVERFLOW_UNKNOWN` if the prediction was not made + * or `LIBJ2_OVERFLOW_UNKNOWN` (= +2) if the prediction was not made * * @since 1.0 */ -inline enum libj2_overflow +LIBJ2_PURE_ inline enum libj2_overflow libj2_ju_mul_j2u_overflow_p_quick(uintmax_t a, const struct libj2_j2u *b) { return libj2_j2u_mul_ju_overflow_p_quick(b, a); @@ -479,7 +479,7 @@ libj2_ju_mul_j2u_overflow_p_quick(uintmax_t a, const struct libj2_j2u *b) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_j2u_mul_j2u_overflow_p(const struct libj2_j2u *a, const struct libj2_j2u *b) { enum libj2_overflow overflow; @@ -527,7 +527,7 @@ libj2_j2u_mul_j2u_overflow_p(const struct libj2_j2u *a, const struct libj2_j2u * * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_j2u_mul_ju_overflow_p(const struct libj2_j2u *a, uintmax_t b) { return libj2_j2u_mul_j2u_overflow_p(a, &(struct libj2_j2u){.high = 0, .low = b}); @@ -548,7 +548,7 @@ libj2_j2u_mul_ju_overflow_p(const struct libj2_j2u *a, uintmax_t b) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_ju_mul_j2u_overflow_p(uintmax_t a, const struct libj2_j2u *b) { return libj2_j2u_mul_ju_overflow_p(b, a); @@ -643,3 +643,556 @@ libj2_ju_mul_j2u_to_j2u_overflow_p(uintmax_t a, const struct libj2_j2u *b, struc { return libj2_j2u_mul_ju_to_j2u_overflow_p(b, a, res, res_set); } + + + + + +/** + * Calculate the product of two signed double-max + * precision integers + * + * `libj2_j2i_mul_j2i_overflow(a, b)` implements + * `*a *= *b` with overflow-detection + * + * @param a The multiplier, also used as the + * output parameter for the product + * @param b The multiplicand + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_mul_j2i_overflow(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + struct libj2_j2u t; + int overflow, neg = libj2_j2i_is_negative(a); + if (neg) + libj2_minus_j2i(a); + 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((void *)a, (const void *)b); + if (neg) { + if (overflow) + overflow = -overflow; + else if (libj2_j2i_is_min(a)) + return 0; + else if (libj2_j2i_is_negative(a)) + overflow = -1; + libj2_minus_j2i(a); + } else if (!overflow) { + overflow = libj2_j2i_is_negative(a); + } + return overflow; +} + + +/** + * Calculate the product of two signed double-max + * precision integers + * + * `libj2_j2i_mul_j2i_to_j2i_overflow(a, b, res)` + * implements `*res = *a * *b` with overflow-detection + * + * @param a The multiplier + * @param b The multiplicand + * @param res Output parameter for the product + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_mul_j2i_to_j2i_overflow(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + if (a == res) { + return libj2_j2i_mul_j2i_overflow(res, b); + } else if (b == res) { + return libj2_j2i_mul_j2i_overflow(res, a); + } else { + *res = *a; + return libj2_j2i_mul_j2i_overflow(res, b); + } +} + + +/** + * Predict whether `libj2_j2i_mul_j2i_overflow_destructive` + * `libj2_j2i_mul_j2i_overflow`, or `libj2_j2i_mul_j2i_to_j2i_overflow` + * will return a result-overflow signal + * + * `libj2_j2i_mul_j2i_overflow_p(a, b)` implements + * `libj2_j2i_mul_j2i_to_j2i_overflow(a, b, &(struct libj2_j2i){})` + * in an efficient manner for most cases + * + * @param a The multiplier + * @param b The multiplicand + * @return +1 if the multiplication would overflow positively, + * -1 if the multiplication would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_j2i_mul_j2i_overflow_p(const struct libj2_j2i *a, const struct libj2_j2i *b) /* TODO optimised impl */ +{ + return libj2_j2i_mul_j2i_to_j2i_overflow(a, b, &(struct libj2_j2i){0, 0}); +} + + +/** + * Variant of `libj2_j2i_mul_j2i_overflow_p` that + * that stops the overflow-prediction is costly + * + * @param a The multiplier + * @param b The multiplicand + * @return `LIBJ2_POSITIVE_OVERFLOW` (= +1) if the + * multiplication would overflow positively, + * `LIBJ2_NEGATIVE_OVERFLOW` (= -1) if the + * multiplication would overflow negatively, + * `LIBJ2_NO_OVERFLOW` (= 0) if the multiplication + * would not overflow, + * `LIBJ2_POSITIVE_OVERFLOW_UNKNOWN` (= +2) + * if the prediction was not made but the + * multiplication could overflow positively, or + * `LIBJ2_NEGATIVE_OVERFLOW_UNKNOWN` (= -2) + * if the prediction was not made but the + * multiplication could overflow negatively + * + * @since 1.1 + */ +LIBJ2_PURE_ inline enum libj2_overflow +libj2_j2i_mul_j2i_overflow_p_quick(const struct libj2_j2i *a, const struct libj2_j2i *b) /* TODO optimised impl */ +{ + int ret = libj2_j2i_mul_j2i_to_j2i_overflow(a, b, &(struct libj2_j2i){0, 0}); + return (enum libj2_overflow)ret; +} + + +/** + * Variant of `libj2_j2i_mul_j2i_overflow_p` that + * that performs the multiplication if the + * overflow-prediction is costly + * + * @param a The multiplier + * @param b The multiplicand + * @param res Output parameter for the product + * @param res_set Output parameter for whether `*res` is set, + * if set to 1 when the function returns, + * `*res` will be set to the product, + * if set to 0 when the function returns, + * `*res` will be unmodified; + * will never be set to any other value + * @return +1 if the multiplication would or did overflow positively, + * -1 if the multiplication would or did overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_mul_j2i_to_j2i_overflow_p(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res, int *res_set) /* TODO optimised impl */ +{ + *res_set = 1; + return libj2_j2i_mul_j2i_to_j2i_overflow(a, b, res); +} + + +/** + * Calculate the signed double-max precision integer + * product of two signed max precision integers + * + * `libj2_ji_mul_ji_to_j2i(a, b, res)` implements + * `*res = a * b`, where `a` and `b` are converted + * into `struct libj2_j2i`'s + * + * @param a The multiplier + * @param b The multiplicand + * @param res Output parameter for the product + * + * @since 1.1 + */ +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); + if (neg) + libj2_minus_j2i(res); +} + + +/** + * Calculate the product of a signed double-max + * precision integer (multiplier) and a signed + * max precision integer (multiplicand) + * + * `libj2_j2i_mul_ji_to_j2i(a, b)` implements `*a *= b`, + * where `b` are converted into an `struct libj2_j2i` + * + * @param a The multiplier, also used as the + * output parameter for the product + * @param b The multiplicand + * + * @since 1.1 + */ +inline void +libj2_j2i_mul_ji(struct libj2_j2i *a, intmax_t b) +{ + int neg = libj2_j2i_is_negative(a); + if (neg) + libj2_minus_j2i(a); + if (b < 0) { + neg ^= 1; + b = -b; + } + libj2_j2u_mul_ju((void *)a, (uintmax_t)b); + if (neg) + libj2_minus_j2i(a); +} + + +/** + * Calculate the product of a signed double-max + * precision integer (multiplier) and a signed + * max precision integer (multiplicand) + * + * `libj2_j2i_mul_ji_to_j2i(a, b, res)` implements + * `*res = *a * b`, where `b` are converted into + * an `struct libj2_j2i` + * + * @param a The multiplier + * @param b The multiplicand + * @param res Output parameter for the product + * + * @since 1.1 + */ +inline void +libj2_j2i_mul_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res) +{ + *res = *a; + libj2_j2i_mul_ji(res, b); +} + + +/** + * Calculate the product of a signed max + * precision integer (multiplier) and a signed + * double-max precision integer (multiplicand) + * + * `libj2_ji_mul_j2i_to_j2i(a, b, res)` implements + * `*res = a * *b`, where `a` are converted into + * an `struct libj2_j2i` + * + * @param a The multiplier + * @param b The multiplicand + * @param res Output parameter for the product + * + * @since 1.1 + */ +inline void +libj2_ji_mul_j2i_to_j2i(intmax_t a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + libj2_j2i_mul_ji_to_j2i(b, a, res); +} + + +/** + * Calculate the product of a signed double-max + * precision integer (multiplier) and a signed + * max precision integer (multiplicand) + * + * `libj2_j2i_mul_ji_to_overflow(a, b)` implements + * `*a *= b`, where `b` are converted into an + * `struct libj2_j2i`, with overflow-detection + * + * @param a The multiplier, also used as the + * output parameter for the product + * @param b The multiplicand + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_mul_ji_overflow(struct libj2_j2i *a, intmax_t b) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(b, &t); + return libj2_j2i_mul_j2i_overflow(a, &t); +} + + +/** + * Calculate the product of a signed double-max + * precision integer (multiplier) and a signed + * max precision integer (multiplicand) + * + * `libj2_j2i_mul_ji_to_j2i_overflow(a, b, res)` + * implements `*res = *a * b`, where `b` are + * converted into an `struct libj2_j2i`, with + * overflow-detection + * + * @param a The multiplier + * @param b The multiplicand + * @param res Output parameter for the product + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_mul_ji_to_j2i_overflow(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(b, &t); + return libj2_j2i_mul_j2i_to_j2i_overflow(a, &t, res); +} + + +/** + * Calculate the product of a signed max + * precision integer (multiplier) and a signed + * double-max precision integer (multiplicand) + * + * `libj2_ji_mul_j2i_to_j2i_overflow(a, b, res)` + * implements `*res = a * *b`, where `a` are + * converted into an `struct libj2_j2i`, with + * overflow-detection + * + * @param a The multiplier + * @param b The multiplicand + * @param res Output parameter for the product + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_ji_mul_j2i_to_j2i_overflow(intmax_t a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + return libj2_j2i_mul_ji_to_j2i_overflow(b, a, res); +} + + +/** + * Calculate the product of two signed double-max + * precision integers + * + * `libj2_j2i_mul_j2i(a, b)` implements `*a *= *b` + * + * @param a The multiplier, also used as the + * output parameter for the product + * @param b The multiplicand + * + * @since 1.1 + */ +inline void +libj2_j2i_mul_j2i(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + struct libj2_j2u t; + int neg = libj2_j2i_is_negative(a); + if (neg) + libj2_minus_j2i(a); + 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((void *)a, (const void *)b); + if (neg) + libj2_minus_j2i(a); +} + + +/** + * Calculate the product of two signed double-max + * precision integers + * + * `libj2_j2i_mul_j2i_to_j2i(a, b, res)` + * implements `*res = *a * *b` + * + * @param a The multiplier + * @param b The multiplicand + * @param res Output parameter for the product + * + * @since 1.1 + */ +inline void +libj2_j2i_mul_j2i_to_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + if (a == res) { + common: + libj2_j2i_mul_j2i(res, b); + } else if (b == res) { + b = a; + goto common; + } else if (a == b) { + if (libj2_j2i_is_negative(a)) { + libj2_minus_j2i_to_j2u(a, (void *)res); + libj2_j2u_mul_j2u((void *)res, (const void *)res); + } else { + libj2_j2u_mul_j2u_to_j2u((const void *)a, (const void *)b, (void *)res); + } + } else { + *res = *a; + goto common; + } +} + + +/** + * Variant of `libj2_j2i_mul_ji_overflow_p` that + * that stops the overflow-prediction is costly + * + * @param a The multiplier + * @param b The multiplicand + * @return `LIBJ2_OVERFLOW` (= 1) if the multiplication would overflow, + * `LIBJ2_NO_OVERFLOW` (= 0) if the multiplication would not overflow, + * or `LIBJ2_OVERFLOW_UNKNOWN` (= +2) if the prediction was not made + * + * @since 1.1 + */ +LIBJ2_PURE_ inline enum libj2_overflow +libj2_j2i_mul_ji_overflow_p_quick(const struct libj2_j2i *a, intmax_t b) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(b, &t); + return libj2_j2i_mul_j2i_overflow_p_quick(a, &t); +} + + +/** + * Variant of `libj2_ji_mul_j2i_overflow_p` that + * that stops the overflow-prediction is costly + * + * @param a The multiplier + * @param b The multiplicand + * @return `LIBJ2_OVERFLOW` (= 1) if the multiplication would overflow, + * `LIBJ2_NO_OVERFLOW` (= 0) if the multiplication would not overflow, + * or `LIBJ2_OVERFLOW_UNKNOWN` (= +2) if the prediction was not made + * + * @since 1.1 + */ +LIBJ2_PURE_ inline enum libj2_overflow +libj2_ji_mul_j2i_overflow_p_quick(intmax_t a, const struct libj2_j2i *b) +{ + return libj2_j2i_mul_ji_overflow_p_quick(b, a); +} + + +/** + * Predict whether `libj2_j2i_mul_ji_overflow` + * or `libj2_j2i_mul_ji_to_j2i_overflow` + * will return a result-overflow signal + * + * `libj2_j2i_mul_ji_overflow_p(a, b)` implements + * `libj2_j2i_mul_ji_to_j2i_overflow(a, b, &(struct libj2_j2i){})` + * in an efficient manner for most cases + * + * @param a The multiplier + * @param b The multiplicand + * @return +1 if the multiplication would overflow positively, + * -1 if the multiplication would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_j2i_mul_ji_overflow_p(const struct libj2_j2i *a, intmax_t b) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(b, &t); + return libj2_j2i_mul_j2i_overflow_p(a, &t); +} + + +/** + * Predict whether `libj2_ji_mul_j2i_overflow` + * will return a result-overflow signal + * + * `libj2_ji_mul_j2i_overflow_p(a, b)` implements + * `libj2_ji_mul_j2i(&(struct libj2_j2i){.high = a->high, .low = a->low}, b)` + * in an efficient manner for most cases + * + * @param a The multiplier + * @param b The multiplicand + * @return +1 if the multiplication would overflow positively, + * -1 if the multiplication would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_ji_mul_j2i_overflow_p(intmax_t a, const struct libj2_j2i *b) +{ + return libj2_j2i_mul_ji_overflow_p(b, a); +} + + +/** + * Variant of `libj2_j2i_mul_ji_overflow_p` that + * that performs the multiplication if the + * overflow-prediction is costly + * + * @param a The multiplier + * @param b The multiplicand + * @param res Output parameter for the product + * @param res_set Output parameter for whether `*res` is set, + * if set to 1 when the function returns, + * `*res` will be set to the product, + * if set to 0 when the function returns, + * `*res` will be unmodified; + * will never be set to any other value + * @return +1 if the multiplication would or did overflow positively, + * -1 if the multiplication would or did overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_mul_ji_to_j2i_overflow_p(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res, int *res_set) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(b, &t); + return libj2_j2i_mul_j2i_to_j2i_overflow_p(a, &t, res, res_set); +} + + +/** + * Variant of `libj2_ji_mul_j2i_overflow_p` that + * that performs the multiplication if the + * overflow-prediction is costly + * + * @param a The multiplier + * @param b The multiplicand + * @param res Output parameter for the product + * @param res_set Output parameter for whether `*res` is set, + * if set to 1 when the function returns, + * `*res` will be set to the product, + * if set to 0 when the function returns, + * `*res` will be unmodified; + * will never be set to any other value + * @return +1 if the multiplication would or did overflow positively, + * -1 if the multiplication would or did overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_ji_mul_j2i_to_j2i_overflow_p(intmax_t a, const struct libj2_j2i *b, struct libj2_j2i *res, int *res_set) +{ + return libj2_j2i_mul_ji_to_j2i_overflow_p(b, a, res, res_set); +} diff --git a/libj2/subtraction.h b/libj2/subtraction.h index 5d4ee2e..de4a225 100644 --- a/libj2/subtraction.h +++ b/libj2/subtraction.h @@ -388,9 +388,9 @@ libj2_ju_sub_j2u_to_j2u_overflow(uintmax_t a, const struct libj2_j2u *b, struct * `libj2_j2u_rsub_j2u(a, b, res)` implements * `*a = *b - *a` * - * @param a The subtrahend (right-hand), also used as - * the output parameter for the difference - * @param b The minuend (left-hand) + * @param a The subtrahend (right-hand), also used as + * the output parameter for the difference + * @param b The minuend (left-hand) * * @since 1.0 */ @@ -526,7 +526,7 @@ libj2_j2u_rsub_ju_overflow(struct libj2_j2u *a, uintmax_t b) /** - * Predict whether `libj2_j2u_sub_ju_to_j2u_overflow` + * Predict whether `libj2_j2u_sub_ju_to_j2u_overflow` * or `libj2_j2u_sub_ju_overflow` will return a * result-overflow signal * @@ -540,7 +540,7 @@ libj2_j2u_rsub_ju_overflow(struct libj2_j2u *a, uintmax_t b) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_j2u_sub_ju_overflow_p(const struct libj2_j2u *a, uintmax_t b) { return a->low < b && !a->high; @@ -548,7 +548,7 @@ libj2_j2u_sub_ju_overflow_p(const struct libj2_j2u *a, uintmax_t b) /** - * Predict whether `libj2_ju_sub_j2u_to_j2u_overflow` + * Predict whether `libj2_ju_sub_j2u_to_j2u_overflow` * will return a result-overflow signal * * `libj2_ju_sub_j2u_overflow_p(a, b)` implements @@ -561,7 +561,7 @@ libj2_j2u_sub_ju_overflow_p(const struct libj2_j2u *a, uintmax_t b) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_ju_sub_j2u_overflow_p(uintmax_t a, const struct libj2_j2u *b) { return b->high || b->low > a; @@ -569,7 +569,7 @@ libj2_ju_sub_j2u_overflow_p(uintmax_t a, const struct libj2_j2u *b) /** - * Predict whether `libj2_ju_sub_ju_to_j2u_overflow` + * Predict whether `libj2_ju_sub_ju_to_j2u_overflow` * will return a result-overflow signal * * `libj2_ju_sub_ju_overflow_p(a, b)` implements @@ -582,7 +582,7 @@ libj2_ju_sub_j2u_overflow_p(uintmax_t a, const struct libj2_j2u *b) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_ju_sub_ju_overflow_p(uintmax_t a, uintmax_t b) { return a < b; @@ -590,7 +590,7 @@ libj2_ju_sub_ju_overflow_p(uintmax_t a, uintmax_t b) /** - * Predict whether `libj2_j2u_sub_j2u_to_j2u_overflow` + * Predict whether `libj2_j2u_sub_j2u_to_j2u_overflow` * or `libj2_j2u_sub_j2u_overflow` will return a * result-overflow signal * @@ -604,7 +604,7 @@ libj2_ju_sub_ju_overflow_p(uintmax_t a, uintmax_t b) * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_j2u_sub_j2u_overflow_p(const struct libj2_j2u *a, const struct libj2_j2u *b) { return libj2_j2u_sub_ju_overflow_p(a, b->low) || a->high < b->high; @@ -625,7 +625,7 @@ libj2_j2u_sub_j2u_overflow_p(const struct libj2_j2u *a, const struct libj2_j2u * * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_j2u_rsub_j2u_overflow_p(const struct libj2_j2u *a, const struct libj2_j2u *b) { return libj2_j2u_sub_j2u_overflow_p(b, a); @@ -646,8 +646,497 @@ libj2_j2u_rsub_j2u_overflow_p(const struct libj2_j2u *a, const struct libj2_j2u * * @since 1.0 */ -inline int +LIBJ2_PURE_ inline int libj2_j2u_rsub_ju_overflow_p(const struct libj2_j2u *a, uintmax_t b) { return libj2_ju_sub_j2u_overflow_p(b, a); } + + + + + +/** + * Calculate the difference between two signed + * double-max precision integers + * + * `libj2_j2i_sub_j2i_to_j2i(a, b, res)` implements + * `*res = *a - *b` + * + * @param a The minuend (left-hand) + * @param b The subtrahend (right-hand) + * @param res Output parameter for the difference + * + * @since 1.1 + */ +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); +} + + +/** + * Calculate the difference between a signed + * double-max precision integer (minuend) and a + * signed max precision integer (subtrahend) + * + * `libj2_j2i_sub_ji_to_j2i(a, b, res)` + * implements `*res = *a - b` + * + * @param a The minuend (left-hand) + * @param b The subtrahend (right-hand) + * @param res Output parameter for the difference + * + * @since 1.1 + */ +inline void +libj2_j2i_sub_ji_to_j2i(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(b, &t); + libj2_j2i_sub_j2i_to_j2i(a, &t, res); +} + + +/** + * Calculate the difference between a signed + * max precision integer (minuend) and a signed + * double-max precision integer (subtrahend) + * + * `libj2_ji_sub_j2i_to_j2i(a, b, res)` + * implements `*res = a - *b` + * + * @param a The minuend (left-hand) + * @param b The subtrahend (right-hand) + * @param res Output parameter for the difference + * + * @since 1.1 + */ +inline void +libj2_ji_sub_j2i_to_j2i(intmax_t a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(a, &t); + libj2_j2i_sub_j2i_to_j2i(&t, b, res); +} + + +/** + * Calculate the difference between two signed + * max precision integers, as a signed double-max + * precision integer + * + * `libj2_ji_sub_ji_to_j2i(a, b, res)` + * implements `*res = a - b`, where `a` and `b` + * are converted into `struct libj2_j2i`'s + * + * @param a The minuend (left-hand) + * @param b The subtrahend (right-hand) + * @param res Output parameter for the difference + * + * @since 1.1 + */ +inline void +libj2_ji_sub_ji_to_j2i(intmax_t a, intmax_t b, struct libj2_j2i *res) +{ + struct libj2_j2i s, t; + libj2_ji_to_j2i(a, &s); + libj2_ji_to_j2i(b, &t); + libj2_j2i_sub_j2i_to_j2i(&s, &t, res); +} + + +/** + * Calculate the difference between two signed + * double-max precision integers + * + * `libj2_j2i_sub_j2i(a, b)` implements `*a -= *b` + * + * @param a The minuend (left-hand), also used + * as the output parameter for the difference + * @param b The subtrahend (right-hand) + * + * @since 1.1 + */ +inline void +libj2_j2i_sub_j2i(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + libj2_j2u_sub_j2u((void *)a, (const void *)b); +} + + +/** + * Calculate the difference between a signed + * double-max precision integer (minuend) and a + * signed max precision integer (subtrahend) + * + * `libj2_j2i_sub_ji(a, b)` implements `*a -= b` + * + * @param a The minuend (left-hand), also used as the + * output parameter for the difference + * @param b The subtrahend (right-hand) + * + * @since 1.1 + */ +inline void +libj2_j2i_sub_ji(struct libj2_j2i *a, intmax_t b) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(b, &t); + libj2_j2i_sub_j2i(a, &t); +} + + +/** + * Predict whether `libj2_j2i_sub_j2i_to_j2i_overflow` + * or `libj2_j2i_sub_j2i_overflow` will return a + * result-overflow signal + * + * `libj2_j2i_sub_j2i_overflow_p(a, b)` implements + * `libj2_j2i_sub_j2i_to_j2i_overflow(a, b, &(struct libj2_j2i){})` + * in an efficient manner + * + * @param a The minuend (left-hand) + * @param b The subtrahend (right-hand) + * @return +1 if the subtraction would overflow positively, + * -1 if the subtraction would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_j2i_sub_j2i_overflow_p(const struct libj2_j2i *a, const struct libj2_j2i *b) +{ + if (libj2_j2i_is_negative(a)) { + if (!libj2_j2i_is_positive(b)) + return 0; + return a->high - b->high - (uintmax_t)(a->low < b->low) <= (uintmax_t)INTMAX_MAX ? -1 : 0; + } else { + if (!libj2_j2i_is_negative(b)) + return 0; + return a->high - b->high - (uintmax_t)(a->low < b->low) > (uintmax_t)INTMAX_MAX; + } +} + + +/** + * Predict whether `libj2_j2i_sub_ji_to_j2i_overflow` + * or `libj2_j2i_sub_ji_overflow` will return a + * result-overflow signal + * + * `libj2_j2i_sub_ji_overflow_p(a, b)` implements + * `libj2_j2i_sub_ji_to_j2i_overflow(a, b, &(struct libj2_j2i){})` + * in an efficient manner + * + * @param a The minuend (left-hand) + * @param b The subtrahend (right-hand) + * @return +1 if the subtraction would overflow positively, + * -1 if the subtraction would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_j2i_sub_ji_overflow_p(const struct libj2_j2i *a, intmax_t b) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(b, &t); + return libj2_j2i_sub_j2i_overflow_p(a, &t); +} + + +/** + * Predict whether `libj2_ji_sub_j2i_to_j2i_overflow` + * will return a result-overflow signal + * + * `libj2_ji_sub_j2i_overflow_p(a, b)` implements + * `libj2_ji_sub_j2i_to_j2i_overflow(a, b, &(struct libj2_j2i){})` + * in an efficient manner + * + * @param a The minuend (left-hand) + * @param b The subtrahend (right-hand) + * @return +1 if the subtraction would overflow positively, + * -1 if the subtraction would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_ji_sub_j2i_overflow_p(intmax_t a, const struct libj2_j2i *b) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(a, &t); + return libj2_j2i_sub_j2i_overflow_p(&t, b); +} + + +/** + * Calculate the difference between two signed + * double-max precision integers + * + * `libj2_j2i_sub_j2i_to_j2i_overflow(a, b, res)` + * implements `*res = *a - *b` with overflow-detection + * + * @param a The minuend (left-hand) + * @param b The subtrahend (right-hand) + * @param res Output parameter for the difference + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_sub_j2i_to_j2i_overflow(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + int overflow = libj2_j2i_sub_j2i_overflow_p(a, b); + libj2_j2i_sub_j2i_to_j2i(a, b, res); + return overflow; +} + + +/** + * Calculate the difference between a signed + * double-max precision integer (minuend) and a + * signed max precision integer (subtrahend) + * + * `libj2_j2i_sub_ji_to_j2i_overflow(a, b, res)` + * implements `*res = *a - b` with overflow-detection + * + * @param a The minuend (left-hand) + * @param b The subtrahend (right-hand) + * @param res Output parameter for the difference + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_sub_ji_to_j2i_overflow(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(b, &t); + return libj2_j2i_sub_j2i_to_j2i_overflow(a, &t, res); +} + + +/** + * Calculate the difference between a signed + * max precision integer (minuend) and a signed + * double-max precision integer (subtrahend) + * + * `libj2_ji_sub_j2i_to_j2i_overflow(a, b, res)` + * implements `*res = a - *b` with overflow-detection + * + * @param a The minuend (left-hand) + * @param b The subtrahend (right-hand) + * @param res Output parameter for the difference + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_ji_sub_j2i_to_j2i_overflow(intmax_t a, const struct libj2_j2i *b, struct libj2_j2i *res) +{ + struct libj2_j2i t; + libj2_ji_to_j2i(a, &t); + return libj2_j2i_sub_j2i_to_j2i_overflow(&t, b, res); +} + + +/** + * Calculate the difference between two signed + * double-max precision integers + * + * `libj2_j2i_sub_j2i_overflow(a, b)` + * implements `*a -= *b` with overflow-detection + * + * @param a The minuend (left-hand), also used + * as the output parameter for the difference + * @param b The subtrahend (right-hand) + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_sub_j2i_overflow(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + return libj2_j2i_sub_j2i_to_j2i_overflow(a, b, a); +} + + +/** + * Calculate the difference between a signed + * double-max precision integer (minuend) and a + * signed max precision integer (subtrahend) + * + * `libj2_j2i_sub_ji_overflow(a, b)` implements + * `*a -= b` with overflow-detection + * + * @param a The minuend (left-hand), also used as the + * output parameter for the difference + * @param b The subtrahend (right-hand) + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_sub_ji_overflow(struct libj2_j2i *a, intmax_t b) +{ + return libj2_j2i_sub_ji_to_j2i_overflow(a, b, a); +} + + +/** + * Calculate the difference between two signed + * max precision integers; in this variant of + * `libj2_j2i_sub_j2i`, the minuend (left-hand) + * is the second parameter and the subtrahend + * (right-hand) is the first parameter + * + * `libj2_j2i_rsub_j2i(a, b, res)` implements + * `*a = *b - *a` + * + * @param a The subtrahend (right-hand), also used as + * the output parameter for the difference + * @param b The minuend (left-hand) + * + * @since 1.1 + */ +inline void +libj2_j2i_rsub_j2i(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + libj2_j2i_sub_j2i_to_j2i(b, a, a); +} + + +/** + * Calculate the difference between a signed + * max precision integer (minuend) and a signed + * double-max precision integer (subtrahend); + * in this variant of `libj2_j2i_sub_ji`, the + * minuend (left-hand) is the second parameter + * and the subtrahend (right-hand) is the first + * parameter + * + * `libj2_j2i_rsub_ji(a, b, res)` implements `*a = b - *a` + * + * @param a The subtrahend (right-hand), also used as + * the output parameter for the difference + * @param b The minuend (left-hand) + * + * @since 1.1 + */ +inline void +libj2_j2i_rsub_ji(struct libj2_j2i *a, intmax_t b) +{ + libj2_ji_sub_j2i_to_j2i(b, a, a); +} + + +/** + * Calculate the difference between two signed + * max precision integers; in this variant of + * `libj2_j2i_sub_j2i`, the minuend (left-hand) + * is the second parameter and the subtrahend + * (right-hand) is the first parameter + * + * `libj2_j2i_rsub_j2i_overflow(a, b, res)` + * implements `*a = *b - *a` with overflow-detection + * + * @param a The subtrahend (right-hand), also used as + * the output parameter for the difference + * @param b The minuend (left-hand) + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_rsub_j2i_overflow(struct libj2_j2i *a, const struct libj2_j2i *b) +{ + return libj2_j2i_sub_j2i_to_j2i_overflow(b, a, a); +} + + +/** + * Calculate the difference between a signed + * max precision integer (minuend) and a signed + * double-max precision integer (subtrahend); + * in this variant of `libj2_j2i_sub_ji`, the + * minuend (left-hand) is the second parameter + * and the subtrahend (right-hand) is the first + * parameter + * + * `libj2_j2i_rsub_ji_overflow(a, b, res)` + * implements `*a = b - *a` with overflow-detection + * + * @param a The subtrahend (right-hand), also used as + * the output parameter for the difference + * @param b The minuend (left-hand) + * @return +1 on positive overflow, + * -1 on negative overflow, + * 0 otherwise + * + * @since 1.1 + */ +inline int +libj2_j2i_rsub_ji_overflow(struct libj2_j2i *a, intmax_t b) +{ + return libj2_ji_sub_j2i_to_j2i_overflow(b, a, a); +} + + +/** + * Predict whether `libj2_j2i_rsub_j2i_overflow` + * will return a result-overflow signal + * + * `libj2_j2i_rsub_j2i_overflow_p(a, b)` implements + * `libj2_j2i_rsub_j2i_overflow(&(struct libj2_j2i){.high = a->high, .low = a->low}, b)` + * in an efficient manner + * + * @param a The subtrahend (right-hand) + * @param b The minuend (left-hand) + * @return +1 if the subtraction would overflow positively, + * -1 if the subtraction would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_j2i_rsub_j2i_overflow_p(const struct libj2_j2i *a, const struct libj2_j2i *b) +{ + return libj2_j2i_sub_j2i_overflow_p(b, a); +} + + +/** + * Predict whether `libj2_j2i_rsub_ji_overflow` + * will return a result-overflow signal + * + * `libj2_j2i_rsub_ji_overflow_p(a, b)` implements + * `libj2_j2i_rsub_ji_overflow(&(struct libj2_j2i){.high = a->high, .low = a->low}, b)` + * in an efficient manner + * + * @param a The subtrahend (right-hand) + * @param b The minuend (left-hand) + * @return +1 if the subtraction would overflow positively, + * -1 if the subtraction would overflow negatively, + * 0 otherwise + * + * @since 1.1 + */ +LIBJ2_PURE_ inline int +libj2_j2i_rsub_ji_overflow_p(const struct libj2_j2i *a, intmax_t b) +{ + return libj2_ji_sub_j2i_overflow_p(b, a); +} diff --git a/libj2_cfs_j2u.3 b/libj2_cfs_j2u.3 new file mode 100644 index 0000000..ee31cac --- /dev/null +++ b/libj2_cfs_j2u.3 @@ -0,0 +1,51 @@ +.TH LIBJ2_CFS_J2U 3 LIBJ2 +.SH NAME +libj2_cfs_j2u \- Clear first set bit + +.SH SYNOPSIS +.nf +#include <libj2.h> + +void \fBlibj2_cfs_j2u\fP(struct libj2_j2u *\fIa\fP); +void \fBlibj2_cfs_j2u_to_j2u\fP(const struct libj2_j2u *\fIa\fP, struct libj2_j2u *\fIr\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_cfs_j2u () +function clears the first (least significant) +set bit in +.I a +(no modification if all bits are cleared). +.PP +The +.BR libj2_cfs_j2u_to_j2u () +function performs the same action as +.BR libj2_cfs_j2u () +but instead of modifying +.IR a , +the result is stored in +.IR r . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +None. + +.SH ERRORS +The +.BR libj2_cfs_j2u () +and +.BR libj2_cfs_j2u_to_j2u () +functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_cls_j2u (3), +.BR libj2_ffs_j2u (3), +.BR libj2_kfs_j2u (3), +.BR libj2_sfc_j2u (3) diff --git a/libj2_cfs_j2u.c b/libj2_cfs_j2u.c index c2434e0..7a7793f 100644 --- a/libj2_cfs_j2u.c +++ b/libj2_cfs_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_cfs_j2u(struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_cfs_j2u_to_j2u.3 b/libj2_cfs_j2u_to_j2u.3 new file mode 120000 index 0000000..6e0d9f9 --- /dev/null +++ b/libj2_cfs_j2u_to_j2u.3 @@ -0,0 +1 @@ +libj2_cfs_j2u.3
\ No newline at end of file diff --git a/libj2_cfs_j2u_to_j2u.c b/libj2_cfs_j2u_to_j2u.c index 2e0a11e..7b79314 100644 --- a/libj2_cfs_j2u_to_j2u.c +++ b/libj2_cfs_j2u_to_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_cfs_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res); -/* TODO Add man page */ #else diff --git a/libj2_clo_j2u.3 b/libj2_clo_j2u.3 new file mode 100644 index 0000000..50362ff --- /dev/null +++ b/libj2_clo_j2u.3 @@ -0,0 +1,53 @@ +.TH LIBJ2_CLO_J2U 3 LIBJ2 +.SH NAME +libj2_clo_j2u \- Count leading ones + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_clo_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_clo_j2u () +function returns the number of leading set bits in +.IR a . +.PP +In the case that all bits in +.I a +are set, all of them are counted as leading. +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_clo_j2u () +function returns the number of set bits that +are more significant than the most significant +cleared bits in +.IR a , +or the total number of bits in +.I a +if all its bits are set. + +.SH ERRORS +The +.BR libj2_clo_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_clz_j2u (3), +.BR libj2_cto_j2u (3), +.BR libj2_co_j2u (3), +.BR libj2_fls_j2u (3), +.BR libj2_kls_j2u (3), +.BR libj2_cls_j2u (3), +.BR libj2_slc_j2u (3) diff --git a/libj2_clo_j2u.c b/libj2_clo_j2u.c index 8fa0d03..970f449 100644 --- a/libj2_clo_j2u.c +++ b/libj2_clo_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_clo_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_cls_j2u.3 b/libj2_cls_j2u.3 new file mode 100644 index 0000000..464a16a --- /dev/null +++ b/libj2_cls_j2u.3 @@ -0,0 +1,51 @@ +.TH LIBJ2_CLS_J2U 3 LIBJ2 +.SH NAME +libj2_cls_j2u \- Clear last set bit + +.SH SYNOPSIS +.nf +#include <libj2.h> + +void \fBlibj2_cls_j2u\fP(struct libj2_j2u *\fIa\fP); +void \fBlibj2_cls_j2u_to_j2u\fP(const struct libj2_j2u *\fIa\fP, struct libj2_j2u *\fIr\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_cls_j2u () +function clears the last (most significant) +set bit in +.I a +(no modification if all bits are cleared). +.PP +The +.BR libj2_cls_j2u_to_j2u () +function performs the same action as +.BR libj2_cls_j2u () +but instead of modifying +.IR a , +the result is stored in +.IR r . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +None. + +.SH ERRORS +The +.BR libj2_cls_j2u () +and +.BR libj2_cls_j2u_to_j2u () +functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_cfs_j2u (3), +.BR libj2_fls_j2u (3), +.BR libj2_kls_j2u (3), +.BR libj2_slc_j2u (3) diff --git a/libj2_cls_j2u.c b/libj2_cls_j2u.c index 78d5033..56aa707 100644 --- a/libj2_cls_j2u.c +++ b/libj2_cls_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_cls_j2u(struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_cls_j2u_to_j2u.3 b/libj2_cls_j2u_to_j2u.3 new file mode 120000 index 0000000..c29c72e --- /dev/null +++ b/libj2_cls_j2u_to_j2u.3 @@ -0,0 +1 @@ +libj2_cls_j2u.3
\ No newline at end of file diff --git a/libj2_cls_j2u_to_j2u.c b/libj2_cls_j2u_to_j2u.c index 2a8eca9..fda326d 100644 --- a/libj2_cls_j2u_to_j2u.c +++ b/libj2_cls_j2u_to_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_cls_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res); -/* TODO Add man page */ #else diff --git a/libj2_clz_j2u.3 b/libj2_clz_j2u.3 new file mode 100644 index 0000000..765c442 --- /dev/null +++ b/libj2_clz_j2u.3 @@ -0,0 +1,53 @@ +.TH LIBJ2_CLZ_J2U 3 LIBJ2 +.SH NAME +libj2_clz_j2u \- Count leading zeroes + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_clz_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_clz_j2u () +function returns the number of leading cleared bits in +.IR a . +.PP +In the case that all bits in +.I a +are cleared, all of them are counted as leading. +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_clz_j2u () +function returns the number of cleared bits that +are more significant than the most significant +set bits in +.IR a , +or the total number of bits in +.I a +if all its bits are cleared. + +.SH ERRORS +The +.BR libj2_clz_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_clo_j2u (3), +.BR libj2_ctz_j2u (3), +.BR libj2_cz_j2u (3), +.BR libj2_flc_j2u (3), +.BR libj2_kls_j2u (3), +.BR libj2_cls_j2u (3), +.BR libj2_slc_j2u (3) diff --git a/libj2_clz_j2u.c b/libj2_clz_j2u.c index 5e6f1f4..7409aaf 100644 --- a/libj2_clz_j2u.c +++ b/libj2_clz_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_clz_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_co_j2u.3 b/libj2_co_j2u.3 new file mode 100644 index 0000000..afa7913 --- /dev/null +++ b/libj2_co_j2u.3 @@ -0,0 +1,41 @@ +.TH LIBJ2_CO_J2U 3 LIBJ2 +.SH NAME +libj2_co_j2u \- Count ones + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_co_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_co_j2u () +function returns the number of set bits in +.IR a . +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_co_j2u () +function returns the number of set bits in +.IR a . + +.SH ERRORS +The +.BR libj2_co_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_cz_j2u (3), +.BR libj2_parity_j2u (3), +.BR libj2_clo_j2u (3), +.BR libj2_cto_j2u (3) diff --git a/libj2_co_j2u.c b/libj2_co_j2u.c index 6b1988a..72de832 100644 --- a/libj2_co_j2u.c +++ b/libj2_co_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_co_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_cto_j2u.3 b/libj2_cto_j2u.3 new file mode 100644 index 0000000..49acfb4 --- /dev/null +++ b/libj2_cto_j2u.3 @@ -0,0 +1,53 @@ +.TH LIBJ2_CTO_J2U 3 LIBJ2 +.SH NAME +libj2_cto_j2u \- Count trailing ones + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_cto_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_cto_j2u () +function returns the number of trailing set bits in +.IR a . +.PP +In the case that all bits in +.I a +are set, all of them are counted as trailing. +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_cto_j2u () +function returns the number of set bits that +are less significant than the least significant +cleared bits in +.IR a , +or the total number of bits in +.I a +if all its bits are set. + +.SH ERRORS +The +.BR libj2_cto_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_ctz_j2u (3), +.BR libj2_clo_j2u (3), +.BR libj2_co_j2u (3), +.BR libj2_ffs_j2u (3), +.BR libj2_kfs_j2u (3), +.BR libj2_cfs_j2u (3), +.BR libj2_sfc_j2u (3) diff --git a/libj2_cto_j2u.c b/libj2_cto_j2u.c index 17ea8b6..729bded 100644 --- a/libj2_cto_j2u.c +++ b/libj2_cto_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_cto_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_ctz_j2u.3 b/libj2_ctz_j2u.3 new file mode 100644 index 0000000..997fbc2 --- /dev/null +++ b/libj2_ctz_j2u.3 @@ -0,0 +1,53 @@ +.TH LIBJ2_CTZ_J2U 3 LIBJ2 +.SH NAME +libj2_ctz_j2u \- Count trailing zeroes + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_ctz_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_ctz_j2u () +function returns the number of trailing cleared bits in +.IR a . +.PP +In the case that all bits in +.I a +are cleared, all of them are counted as trailing. +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_ctz_j2u () +function returns the number of cleared bits that +are less significant than the least significant +set bits in +.IR a , +or the total number of bits in +.I a +if all its bits are cleared. + +.SH ERRORS +The +.BR libj2_ctz_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_cto_j2u (3), +.BR libj2_clz_j2u (3), +.BR libj2_cz_j2u (3), +.BR libj2_ffc_j2u (3), +.BR libj2_kfs_j2u (3), +.BR libj2_cfs_j2u (3), +.BR libj2_sfc_j2u (3) diff --git a/libj2_ctz_j2u.c b/libj2_ctz_j2u.c index 3c4ff87..2f41433 100644 --- a/libj2_ctz_j2u.c +++ b/libj2_ctz_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_ctz_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_cz_j2u.3 b/libj2_cz_j2u.3 new file mode 100644 index 0000000..1c95b54 --- /dev/null +++ b/libj2_cz_j2u.3 @@ -0,0 +1,41 @@ +.TH LIBJ2_CZ_J2U 3 LIBJ2 +.SH NAME +libj2_cz_j2u \- Count zeroes + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_cz_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_cz_j2u () +function returns the number of cleared bits in +.IR a . +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_cz_j2u () +function returns the number of cleared bits in +.IR a . + +.SH ERRORS +The +.BR libj2_cz_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_co_j2u (3), +.BR libj2_parity_j2u (3), +.BR libj2_clz_j2u (3), +.BR libj2_ctz_j2u (3) diff --git a/libj2_cz_j2u.c b/libj2_cz_j2u.c index 60da659..dfabf74 100644 --- a/libj2_cz_j2u.c +++ b/libj2_cz_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_cz_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_ffc_j2u.3 b/libj2_ffc_j2u.3 new file mode 100644 index 0000000..acc2b7a --- /dev/null +++ b/libj2_ffc_j2u.3 @@ -0,0 +1,52 @@ +.TH LIBJ2_FFC_J2U 3 LIBJ2 +.SH NAME +libj2_ffc_j2u \- Find first cleared bit + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_ffc_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_ffc_j2u () +function returns the index of the least +significant cleared bit in +.IR a , +where the index is counted from 1, +and from the the least significant bit. +.PP +In the case that no bit in +.I a +is cleared, 0 is returned. +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_ffc_j2u () +function returns the one-based index of +the first cleared bit in +.IR a , +or 0 if no bit is cleared. + +.SH ERRORS +The +.BR libj2_ffc_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_ffs_j2u (3), +.BR libj2_flc_j2u (3), +.BR libj2_cto_j2u (3), +.BR libj2_kfs_j2u (3), +.BR libj2_cfs_j2u (3), +.BR libj2_sfc_j2u (3) diff --git a/libj2_ffc_j2u.c b/libj2_ffc_j2u.c index 5d2c481..b31c3a0 100644 --- a/libj2_ffc_j2u.c +++ b/libj2_ffc_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_ffc_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_ffs_j2u.3 b/libj2_ffs_j2u.3 new file mode 100644 index 0000000..f064f32 --- /dev/null +++ b/libj2_ffs_j2u.3 @@ -0,0 +1,52 @@ +.TH LIBJ2_FFS_J2U 3 LIBJ2 +.SH NAME +libj2_ffs_j2u \- Find first set bit + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_ffs_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_ffs_j2u () +function returns the index of the least +significant set bit in +.IR a , +where the index is counted from 1, +and from the the least significant bit. +.PP +In the case that no bit in +.I a +is set, 0 is returned. +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_ffs_j2u () +function returns the one-based index of +the first set bit in +.IR a , +or 0 if no bit is set. + +.SH ERRORS +The +.BR libj2_ffs_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_ffc_j2u (3), +.BR libj2_fls_j2u (3), +.BR libj2_ctz_j2u (3), +.BR libj2_kfs_j2u (3), +.BR libj2_cfs_j2u (3), +.BR libj2_sfc_j2u (3) diff --git a/libj2_ffs_j2u.c b/libj2_ffs_j2u.c index 59b5996..c496973 100644 --- a/libj2_ffs_j2u.c +++ b/libj2_ffs_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_ffs_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_flc_j2u.3 b/libj2_flc_j2u.3 new file mode 100644 index 0000000..3968746 --- /dev/null +++ b/libj2_flc_j2u.3 @@ -0,0 +1,52 @@ +.TH LIBJ2_FLC_J2U 3 LIBJ2 +.SH NAME +libj2_flc_j2u \- Find last cleared bit + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_flc_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_flc_j2u () +function returns the index of the most +significant cleared bit in +.IR a , +where the index is counted from 1, +and from the the least significant bit. +.PP +In the case that no bit in +.I a +is cleared, 0 is returned. +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_flc_j2u () +function returns the one-based index of +the last cleared bit in +.IR a , +or 0 if no bit is set. + +.SH ERRORS +The +.BR libj2_flc_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_fls_j2u (3), +.BR libj2_ffc_j2u (3), +.BR libj2_clo_j2u (3), +.BR libj2_kls_j2u (3), +.BR libj2_cls_j2u (3), +.BR libj2_slc_j2u (3) diff --git a/libj2_flc_j2u.c b/libj2_flc_j2u.c index 905c350..8401cf3 100644 --- a/libj2_flc_j2u.c +++ b/libj2_flc_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_flc_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_fls_j2u.3 b/libj2_fls_j2u.3 new file mode 100644 index 0000000..9b63423 --- /dev/null +++ b/libj2_fls_j2u.3 @@ -0,0 +1,52 @@ +.TH LIBJ2_FLS_J2U 3 LIBJ2 +.SH NAME +libj2_fls_j2u \- Find last set bit + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_fls_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_fls_j2u () +function returns the index of the most +significant set bit in +.IR a , +where the index is counted from 1, +and from the the least significant bit. +.PP +In the case that no bit in +.I a +is set, 0 is returned. +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_fls_j2u () +function returns the one-based index of +the last set bit in +.IR a , +or 0 if no bit is set. + +.SH ERRORS +The +.BR libj2_fls_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_flc_j2u (3), +.BR libj2_ffs_j2u (3), +.BR libj2_clz_j2u (3), +.BR libj2_kls_j2u (3), +.BR libj2_cls_j2u (3), +.BR libj2_slc_j2u (3) diff --git a/libj2_fls_j2u.c b/libj2_fls_j2u.c index fe2d439..333e85b 100644 --- a/libj2_fls_j2u.c +++ b/libj2_fls_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_fls_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_j2i_add_j2i.c b/libj2_j2i_add_j2i.c new file mode 100644 index 0000000..f1889d8 --- /dev/null +++ b/libj2_j2i_add_j2i.c @@ -0,0 +1,341 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_add_j2i(struct libj2_j2i *a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +static uintmax_t +random_ju(void) +{ + size_t n = LIBJ2_JU_BIT; + uintmax_t r = 0; + while (n--) + if (rand() < rand()) + r |= (uintmax_t)1 << n; + return r; +} + + +static void +check_(uintmax_t 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) +{ + struct libj2_j2i a, b, r, a_saved, b_saved, expected; + + a_saved = (struct libj2_j2i){.high = a_high, .low = a_low}; + b_saved = (struct libj2_j2i){.high = b_high, .low = b_low}; + expected = (struct libj2_j2i){.high = r_high, .low = r_low}; + + a = a_saved; + b = b_saved; + libj2_j2i_add_j2i(&a, &b); + EXPECT(libj2_j2i_eq_j2i(&a, &expected)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + r = (struct libj2_j2i){111, 222}; + a = a_saved; + b = b_saved; + libj2_j2i_add_j2i_to_j2i(&a, &b, &r); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + a = a_saved; + b = b_saved; + libj2_j2i_add_j2i_to_j2i(&a, &b, &a); + EXPECT(libj2_j2i_eq_j2i(&a, &expected)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + a = a_saved; + b = b_saved; + libj2_j2i_add_j2i_to_j2i(&a, &b, &b); + EXPECT(libj2_j2i_eq_j2i(&b, &expected)); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + + a = a_saved; + b = b_saved; + EXPECT(libj2_j2i_add_j2i_overflow(&a, &b) == r_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &expected)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + +#if 0 /* TODO saturated addition */ + a = a_saved; + b = b_saved; + libj2_j2i_sat_add_j2i(&a, &b); + EXPECT(r_overflow ? libj2_j2i_is_max(&a) : libj2_j2i_eq_j2i(&a, &expected)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); +#endif + + a = a_saved; + b = b_saved; + EXPECT(libj2_j2i_add_j2i_overflow_p((const struct libj2_j2i *)&a, (const struct libj2_j2i *)&b) == r_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + r = (struct libj2_j2i){111, 222}; + a = a_saved; + b = b_saved; + EXPECT(libj2_j2i_add_j2i_to_j2i_overflow(&a, &b, &r) == r_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + a = a_saved; + b = b_saved; + EXPECT(libj2_j2i_add_j2i_to_j2i_overflow(&a, &b, &a) == r_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &expected)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + a = a_saved; + b = b_saved; + EXPECT(libj2_j2i_add_j2i_to_j2i_overflow(&a, &b, &b) == r_overflow); + EXPECT(libj2_j2i_eq_j2i(&b, &expected)); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + +#if 0 /* TODO saturated addition */ + r = (struct libj2_j2i){111, 222}; + a = a_saved; + b = b_saved; + libj2_j2i_sat_add_j2i_to_j2i(&a, &b, &r); + EXPECT(r_overflow ? libj2_j2i_is_max(&r) : libj2_j2i_eq_j2i(&r, &expected)); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + a = a_saved; + b = b_saved; + libj2_j2i_sat_add_j2i_to_j2i(&a, &b, &a); + EXPECT(r_overflow ? libj2_j2i_is_max(&a) : libj2_j2i_eq_j2i(&a, &expected)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + a = a_saved; + b = b_saved; + libj2_j2i_sat_add_j2i_to_j2i(&a, &b, &b); + EXPECT(r_overflow ? libj2_j2i_is_max(&b) : libj2_j2i_eq_j2i(&b, &expected)); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); +#endif +} + + +static void +check(uintmax_t a_high, uintmax_t a_low, uintmax_t b_high, uintmax_t b_low) +{ + uintmax_t a_neg = a_high >> (LIBJ2_JU_BIT - 1U); + uintmax_t b_neg = b_high >> (LIBJ2_JU_BIT - 1U); + uintmax_t r_high = 0, r_low = 0, carry = 0; + int r_overflow = 0; + unsigned i; + + for (i = 0; i < LIBJ2_JU_BIT; i++) { + carry += (a_low >> i) & 1U; + carry += (b_low >> i) & 1U; + r_low |= (carry & 1U) << i; + carry >>= 1; + } + + for (i = 0; i < LIBJ2_JU_BIT - 1U; i++) { + carry += (a_high >> i) & 1U; + carry += (b_high >> i) & 1U; + r_high |= (carry & 1U) << i; + carry >>= 1; + } + + carry += (a_high >> i) & 1U; + carry += (b_high >> i) & 1U; + r_high |= (carry & 1U) << i; + carry >>= 1; + + if (a_neg) + carry ^= 1U; + + if (a_neg ^ b_neg) + r_overflow = 0; + else if (a_neg) + r_overflow = -!(r_high >> (LIBJ2_JU_BIT - 1U)); + else + r_overflow = !!(r_high >> (LIBJ2_JU_BIT - 1U)); + + check_(a_high, a_low, b_high, b_low, r_high, r_low, r_overflow); +} + + +static void +check_manual(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) +{ + check_(a_high, a_low, b_high, b_low, r_high, r_low, r_overflow); + check(a_high, a_low, b_high, b_low); +} + + +static void +check_double(uintmax_t high, uintmax_t low) +{ + struct libj2_j2i a, r, a_saved, expected, b; + uintmax_t expected_high = (high << 1 | low >> (LIBJ2_JU_BIT - 1U)); + uintmax_t expected_low = low << 1; + int expected_overflow = (int)(high >> (LIBJ2_JU_BIT - 2U)); + + expected_overflow ^= expected_overflow >> 1; + expected_overflow &= 1; + + if (high >> (LIBJ2_JU_BIT - 1U)) + expected_overflow = -expected_overflow; + + a_saved = (struct libj2_j2i){.high = high, .low = low}; + expected = (struct libj2_j2i){.high = expected_high, .low = expected_low}; + + a = a_saved; + b = a_saved; + libj2_j2i_add_j2i(&a, &b); + EXPECT(libj2_j2i_eq_j2i(&a, &expected)); + + a = a_saved; + libj2_j2i_add_j2i(&a, &a); + EXPECT(libj2_j2i_eq_j2i(&a, &expected)); + + r = (struct libj2_j2i){111, 222}; + a = a_saved; + libj2_j2i_add_j2i_to_j2i(&a, &a, &r); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + + a = a_saved; + libj2_j2i_add_j2i_to_j2i(&a, &a, &a); + EXPECT(libj2_j2i_eq_j2i(&a, &expected)); + + a = a_saved; + EXPECT(libj2_j2i_add_j2i_overflow(&a, &a) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &expected)); + +#if 0 /* TODO saturated addition */ + a = a_saved; + libj2_j2i_sat_add_j2i(&a, &a); + EXPECT(expected_overflow ? libj2_j2i_is_max(&a) : libj2_j2i_eq_j2i(&a, &expected)); +#endif + + a = a_saved; + EXPECT(libj2_j2i_add_j2i_overflow_p((const struct libj2_j2i *)&a, (const struct libj2_j2i *)&a) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + + r = (struct libj2_j2i){111, 222}; + a = a_saved; + EXPECT(libj2_j2i_add_j2i_to_j2i_overflow(&a, &a, &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + + a = a_saved; + EXPECT(libj2_j2i_add_j2i_to_j2i_overflow(&a, &a, &a) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &expected)); + +#if 0 /* TODO saturated addition */ + r = (struct libj2_j2i){111, 222}; + a = a_saved; + libj2_j2i_sat_add_j2i_to_j2i(&a, &a, &r); + EXPECT(expected_overflow ? libj2_j2i_is_max(&r) : libj2_j2i_eq_j2i(&r, &expected)); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + + a = a_saved; + libj2_j2i_sat_add_j2i_to_j2i(&a, &a, &a); + EXPECT(expected_overflow ? libj2_j2i_is_max(&a) : libj2_j2i_eq_j2i(&a, &expected)); +#endif +} + + +int +main(void) +{ + uintmax_t a, b, c, d, max, min, umax, vs[12]; + unsigned i, ii, ij, jj, k; + + srand((unsigned)time(NULL)); + + umax = UINTMAX_MAX; + max = umax >> 1; + min = ~max; + + vs[0] = 0U; + vs[1] = 1U; + vs[2] = 2U; + vs[3] = umax - 0U; + vs[4] = umax - 1U; + vs[5] = umax - 2U; + vs[6] = max - 0U; + vs[7] = max - 1U; + vs[8] = max - 2U; + vs[9] = min + 0U; + vs[10] = min + 1U; + vs[11] = min + 2U; + + check_manual(0, 0, 0, 0, 0, 0, 0); + check_manual(0, 1, 0, 1, 0, 2, 0); + check_manual(0, UINTMAX_MAX, 0, 1, 1, 0, 0); + check_manual(0, UINTMAX_MAX, 0, UINTMAX_MAX, 1, UINTMAX_MAX - 1U, 0); + check_manual(UINTMAX_MAX >> 1, UINTMAX_MAX, UINTMAX_MAX >> 1, UINTMAX_MAX, UINTMAX_MAX, UINTMAX_MAX - 1U, +1); + check_manual((UINTMAX_MAX >> 1) + 1U, 0, (UINTMAX_MAX >> 1) + 1U, 0, 0, 0, -1); + + for (i = 0; i < 256; i++) + check(random_ju() >> 1, random_ju(), random_ju() >> 1, random_ju()); + + check_double(0, 0); + check_double(0, UINTMAX_MAX); + check_double(UINTMAX_MAX, UINTMAX_MAX); + check_double(UINTMAX_MAX, 0); + check_double(UINTMAX_MAX >> 1, 0); + check_double(UINTMAX_MAX >> 1, UINTMAX_MAX); + check_double((UINTMAX_MAX >> 1) + 1U, 0); + for (i = 0; i < 256; i++) { + check_double(0, random_ju()); + check_double(random_ju(), 0); + check_double(random_ju(), UINTMAX_MAX); + check_double(random_ju(), random_ju()); + check_double(UINTMAX_MAX >> 1, random_ju()); + check_double(UINTMAX_MAX, random_ju()); + check_double((UINTMAX_MAX >> 1) + 1U, random_ju()); + } + + check_manual((UINTMAX_MAX >> 1) - 1U, UINTMAX_MAX - 1U, 1, 1, UINTMAX_MAX >> 1, UINTMAX_MAX, 0); + check_manual((UINTMAX_MAX >> 1) - 1U, UINTMAX_MAX - 1U, 1, 2, ~(uintmax_t)INTMAX_MAX, 0, 1); + check_manual((UINTMAX_MAX >> 1) - 1U, UINTMAX_MAX - 1U, 1, 3, ~(uintmax_t)INTMAX_MAX, 1, 1); + + for (k = 0; k < 16U; k++) { + a = random_ju() >> 1; + b = random_ju() >> 1; + c = random_ju() >> 1; + d = random_ju() >> 1; + if (k & 1U) a = ~a; + if (k & 2U) b = ~b; + if (k & 4U) c = ~c; + if (k & 8U) d = ~d; + check(a, b, c, d); + for (i = 0; k < 8U && i < 12U; i++) { + check(a, b, c, vs[i]); + check(a, b, vs[i], c); + check(a, vs[i], b, c); + check(vs[i], a, b, c); + for (ii = 0; k < 4U && ii < 12U; ii++) { + check(a, b, vs[i], vs[ii]); + check(a, vs[i], b, vs[ii]); + check(a, vs[i], vs[ii], b); + check(vs[i], a, b, vs[ii]); + check(vs[i], a, vs[ii], b); + check(vs[i], vs[ii], a, b); + for (ij = 0; k < 2U && ij < 12U; ij++) { + check(vs[i], vs[ii], vs[ij], a); + check(vs[i], vs[ii], a, vs[ij]); + check(vs[i], a, vs[ii], vs[ij]); + check(a, vs[i], vs[ii], vs[ij]); + for (jj = 0; k < 1U && jj < 12U; jj++) + check(vs[i], vs[ii], vs[ij], vs[jj]); + } + } + } + } + + return 0; +} + +#endif diff --git a/libj2_j2i_add_j2i_overflow.c b/libj2_j2i_add_j2i_overflow.c new file mode 100644 index 0000000..02464d8 --- /dev/null +++ b/libj2_j2i_add_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_add_j2i_overflow(struct libj2_j2i *a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_add_j2i.c */ + +#endif diff --git a/libj2_j2i_add_j2i_overflow_p.c b/libj2_j2i_add_j2i_overflow_p.c new file mode 100644 index 0000000..3b703be --- /dev/null +++ b/libj2_j2i_add_j2i_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_add_j2i_overflow_p(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_add_j2i.c */ + +#endif diff --git a/libj2_j2i_add_j2i_to_j2i.c b/libj2_j2i_add_j2i_to_j2i.c new file mode 100644 index 0000000..259f91e --- /dev/null +++ b/libj2_j2i_add_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_add_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_add_j2i.c */ + +#endif diff --git a/libj2_j2i_add_j2i_to_j2i_overflow.c b/libj2_j2i_add_j2i_to_j2i_overflow.c new file mode 100644 index 0000000..b36ac10 --- /dev/null +++ b/libj2_j2i_add_j2i_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_add_j2i_to_j2i_overflow(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_add_j2i.c */ + +#endif diff --git a/libj2_j2i_add_ji.c b/libj2_j2i_add_ji.c new file mode 100644 index 0000000..97880e2 --- /dev/null +++ b/libj2_j2i_add_ji.c @@ -0,0 +1,253 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_add_ji(struct libj2_j2i *a, intmax_t b); +/* 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 +self_check(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) +{ + uintmax_t a_neg = a_high >> (LIBJ2_JU_BIT - 1U); + uintmax_t b_neg = b_high >> (LIBJ2_JU_BIT - 1U); + uintmax_t carry = 0; + unsigned i; + int overflow; + + for (i = 0; i < LIBJ2_JU_BIT; i++) { + carry += (a_low >> i) & 1U; + carry += (b_low >> i) & 1U; + EXPECT((carry & 1U) == ((r_low >> i) & 1U)); + carry >>= 1; + } + + for (i = 0; i < LIBJ2_JU_BIT - 1U; i++) { + carry += (a_high >> i) & 1U; + carry += (b_high >> i) & 1U; + EXPECT((carry & 1U) == ((r_high >> i) & 1U)); + carry >>= 1; + } + + carry += (a_high >> i) & 1U; + carry += (b_high >> i) & 1U; + r_high |= (carry & 1U) << i; + carry >>= 1; + + if (a_neg) + carry ^= 1U; + + if (a_neg ^ b_neg) + overflow = 0; + else if (a_neg) + overflow = -!(r_high >> (LIBJ2_JU_BIT - 1U)); + else + overflow = !!(r_high >> (LIBJ2_JU_BIT - 1U)); + + EXPECT(r_overflow == overflow); +} + + +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; + struct libj2_j2i a, r; + uintmax_t expected_high, expected_low; + int expected_overflow; + +#if INTMAX_MIN + 1 != -INTMAX_MAX + if (ub == ~(UINTMAX_MAX >> 1)) + return; +#endif + + expected_high = a_high + (uintmax_t)(a_low > UINTMAX_MAX - ub); + expected_low = a_low + ub; + if (b < 0) + expected_high += UINTMAX_MAX; + if (a_high >> (LIBJ2_JU_BIT - 1U) && b < 0) + expected_overflow = expected_high >> (LIBJ2_JU_BIT - 1U) ? 0 : -1; + else if (b < 0 || a_high >> (LIBJ2_JU_BIT - 1U)) + expected_overflow = 0; + else + expected_overflow = expected_high >> (LIBJ2_JU_BIT - 1U) ? +1 : 0; + + self_check(a_high, a_low, b < 0 ? UINTMAX_MAX : 0U, ub, expected_high, expected_low, expected_overflow); + + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + libj2_j2i_add_ji(&a, b); + EXPECT(a.high == expected_high); + EXPECT(a.low == expected_low); + + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + EXPECT(libj2_j2i_add_ji_overflow(&a, b) == expected_overflow); + EXPECT(a.high == expected_high); + EXPECT(a.low == expected_low); + +#if 0 /* TODO saturated addition */ + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + libj2_j2i_sat_add_ji(&a, b); + EXPECT(a.high == (expected_overflow ? UINTMAX_MAX : expected_high)); + EXPECT(a.low == (expected_overflow ? UINTMAX_MAX : expected_low)); +#endif + + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + EXPECT(libj2_j2i_add_ji_overflow_p((const struct libj2_j2i *)&a, b) == expected_overflow); + EXPECT(a.high == a_high); + EXPECT(a.low == a_low); + + r = (struct libj2_j2i){111, 222}; + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + libj2_j2i_add_ji_to_j2i(&a, b, &r); + EXPECT(a.high == a_high); + EXPECT(a.low == a_low); + EXPECT(r.high == expected_high); + EXPECT(r.low == expected_low); + + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + libj2_j2i_add_ji_to_j2i(&a, b, &a); + EXPECT(a.high == expected_high); + EXPECT(a.low == expected_low); + + r = (struct libj2_j2i){111, 222}; + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + EXPECT(libj2_j2i_add_ji_to_j2i_overflow(&a, b, &r) == expected_overflow); + EXPECT(a.high == a_high); + EXPECT(a.low == a_low); + EXPECT(r.high == expected_high); + EXPECT(r.low == expected_low); + + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + EXPECT(libj2_j2i_add_ji_to_j2i_overflow(&a, b, &a) == expected_overflow); + EXPECT(a.high == expected_high); + EXPECT(a.low == expected_low); + +#if 0 /* TODO saturated addition */ + r = (struct libj2_j2i){111, 222}; + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + libj2_j2i_sat_add_ji_to_j2i(&a, b, &r); + EXPECT(a.high == a_high); + EXPECT(a.low == a_low); + EXPECT(r.high == (expected_overflow ? UINTMAX_MAX : expected_high)); + EXPECT(r.low == (expected_overflow ? UINTMAX_MAX : expected_low)); + + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + libj2_j2i_sat_add_ji_to_j2i(&a, b, &a); + EXPECT(a.high == (expected_overflow ? UINTMAX_MAX : expected_high)); + EXPECT(a.low == (expected_overflow ? UINTMAX_MAX : expected_low)); +#endif + + r = (struct libj2_j2i){111, 222}; + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + libj2_ji_add_j2i_to_j2i(b, &a, &r); + EXPECT(a.high == a_high); + EXPECT(a.low == a_low); + EXPECT(r.high == expected_high); + EXPECT(r.low == expected_low); + + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + libj2_ji_add_j2i_to_j2i(b, &a, &a); + EXPECT(a.high == expected_high); + EXPECT(a.low == expected_low); + + r = (struct libj2_j2i){111, 222}; + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + EXPECT(libj2_ji_add_j2i_to_j2i_overflow(b, &a, &r) == expected_overflow); + EXPECT(a.high == a_high); + EXPECT(a.low == a_low); + EXPECT(r.high == expected_high); + EXPECT(r.low == expected_low); + + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + EXPECT(libj2_ji_add_j2i_to_j2i_overflow(b, &a, &a) == expected_overflow); + EXPECT(a.high == expected_high); + EXPECT(a.low == expected_low); + +#if 0 /* TODO saturated addition */ + r = (struct libj2_j2i){111, 222}; + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + libj2_ji_sat_add_j2i_to_j2i(b, &a, &r); + EXPECT(a.high == a_high); + EXPECT(a.low == a_low); + EXPECT(r.high == (expected_overflow ? UINTMAX_MAX : expected_high)); + EXPECT(r.low == (expected_overflow ? UINTMAX_MAX : expected_low)); + + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + libj2_ji_sat_add_j2i_to_j2i(b, &a, &a); + EXPECT(a.high == (expected_overflow ? UINTMAX_MAX : expected_high)); + EXPECT(a.low == (expected_overflow ? UINTMAX_MAX : expected_low)); +#endif + + a = (struct libj2_j2i){.high = a_high, .low = a_low}; + EXPECT(libj2_ji_add_j2i_overflow_p(b, (const struct libj2_j2i *)&a) == expected_overflow); + EXPECT(a.high == a_high); + EXPECT(a.low == a_low); +} + + +int +main(void) +{ + uintmax_t a, b, c, max, min, umax, vs[12]; + unsigned i, j, k; + + srand((unsigned)time(NULL)); + + umax = UINTMAX_MAX; + max = umax >> 1; + min = ~max; + + vs[0] = 0U; + vs[1] = 1U; + vs[2] = 2U; + vs[3] = umax - 0U; + vs[4] = umax - 1U; + vs[5] = umax - 2U; + vs[6] = max - 0U; + vs[7] = max - 1U; + vs[8] = max - 2U; + vs[9] = min + 0U; + vs[10] = min + 1U; + vs[11] = min + 2U; + + for (i = 0; i < 12U; i++) + for (j = 0; j < 12U; j++) + for (k = 0; k < 12U; k++) + check(vs[i], vs[j], vs[k]); + + for (k = 0; k < 256; k++) { + a = random_ju(); + b = random_ju(); + c = random_ju(); + for (i = 0; i < 12U; i++) { + for (j = 0; j < 12U; j++) { + check(a, vs[i], vs[j]); + check(vs[i], a, vs[j]); + check(vs[i], vs[j], a); + } + check(a, b, vs[i]); + check(a, vs[i], b); + check(vs[i], a, b); + } + check(a, b, c); + } + + return 0; +} + +#endif diff --git a/libj2_j2i_add_ji_overflow.c b/libj2_j2i_add_ji_overflow.c new file mode 100644 index 0000000..1686ae4 --- /dev/null +++ b/libj2_j2i_add_ji_overflow.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline int libj2_j2i_add_ji_overflow(struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_add_ji.c */ + +#endif diff --git a/libj2_j2i_add_ji_overflow_p.c b/libj2_j2i_add_ji_overflow_p.c new file mode 100644 index 0000000..76fff49 --- /dev/null +++ b/libj2_j2i_add_ji_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_add_ji_overflow_p(const struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_add_ji.c */ + +#endif diff --git a/libj2_j2i_add_ji_to_j2i.c b/libj2_j2i_add_ji_to_j2i.c new file mode 100644 index 0000000..787b563 --- /dev/null +++ b/libj2_j2i_add_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_add_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_add_ji.c */ + +#endif diff --git a/libj2_j2i_add_ji_to_j2i_overflow.c b/libj2_j2i_add_ji_to_j2i_overflow.c new file mode 100644 index 0000000..9e813ac --- /dev/null +++ b/libj2_j2i_add_ji_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_add_ji_to_j2i_overflow(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_add_ji.c */ + +#endif diff --git a/libj2_j2i_cmp_j2i.3 b/libj2_j2i_cmp_j2i.3 new file mode 100644 index 0000000..2230fd0 --- /dev/null +++ b/libj2_j2i_cmp_j2i.3 @@ -0,0 +1,65 @@ +.TH LIBJ2_J2I_CMP_J2I 3 LIBJ2 +.SH NAME +libj2_j2i_cmp_j2i \- Compare two values + +.SH SYNOPSIS +.nf +#include <libj2.h> + +int \fBlibj2_j2i_cmp_j2i\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_cmp_ji\fP(const struct libj2_j2i *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ji_cmp_j2i\fP(intmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_cmp_j2u\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2i_cmp_ju\fP(const struct libj2_j2i *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ji_cmp_j2u\fP(intmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_cmp_j2i\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_cmp_ji\fP(const struct libj2_j2u *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ju_cmp_j2i\fP(uintmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_cmp_j2u\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_cmp_ju\fP(const struct libj2_j2u *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ju_cmp_j2u\fP(uintmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The above listed functions return compare the of +.I a +to the value of +.IR b , +and return the signum of the difference +between +.I a +and +.IR b . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The functions return -1 if +.I a +is less than +.IR b , ++1 if +.I a +is greater than +.IR b , +and 0 if +.I a +and +.I b +are equals. + +.SH ERRORS +The functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_j2i_eq_j2i (3), +.BR libj2_j2i_ne_j2i (3), +.BR libj2_j2i_lt_j2i (3), +.BR libj2_j2i_le_j2i (3), +.BR libj2_j2i_gt_j2i (3), +.BR libj2_j2i_ge_j2i (3) diff --git a/libj2_j2i_cmp_j2i.c b/libj2_j2i_cmp_j2i.c index 7c750c3..bc26e62 100644 --- a/libj2_j2i_cmp_j2i.c +++ b/libj2_j2i_cmp_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_cmp_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_cmp_j2u.3 b/libj2_j2i_cmp_j2u.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_j2i_cmp_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_cmp_j2u.c b/libj2_j2i_cmp_j2u.c index d8071a7..6199b4c 100644 --- a/libj2_j2i_cmp_j2u.c +++ b/libj2_j2i_cmp_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_cmp_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_cmp_ji.3 b/libj2_j2i_cmp_ji.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_j2i_cmp_ji.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_cmp_ji.c b/libj2_j2i_cmp_ji.c index 371b382..f447daf 100644 --- a/libj2_j2i_cmp_ji.c +++ b/libj2_j2i_cmp_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_cmp_ji(const struct libj2_j2i *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_cmp_ju.3 b/libj2_j2i_cmp_ju.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_j2i_cmp_ju.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_cmp_ju.c b/libj2_j2i_cmp_ju.c index aa29cb8..77ee9ca 100644 --- a/libj2_j2i_cmp_ju.c +++ b/libj2_j2i_cmp_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_cmp_ju(const struct libj2_j2i *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_div_j2i.c b/libj2_j2i_div_j2i.c new file mode 100644 index 0000000..5b1658b --- /dev/null +++ b/libj2_j2i_div_j2i.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_div_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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_div_j2i_return.c b/libj2_j2i_div_j2i_return.c new file mode 100644 index 0000000..6385c20 --- /dev/null +++ b/libj2_j2i_div_j2i_return.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline intmax_t libj2_j2i_div_j2i_return(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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_div_j2i_to_j2i.c b/libj2_j2i_div_j2i_to_j2i.c new file mode 100644 index 0000000..3b13ff0 --- /dev/null +++ b/libj2_j2i_div_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_div_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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_div_j2i_to_j2i_underflow.c b/libj2_j2i_div_j2i_to_j2i_underflow.c new file mode 100644 index 0000000..4b89cb7 --- /dev/null +++ b/libj2_j2i_div_j2i_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_div_j2i_to_j2i_underflow(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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_div_j2i_underflow.c b/libj2_j2i_div_j2i_underflow.c new file mode 100644 index 0000000..da18e18 --- /dev/null +++ b/libj2_j2i_div_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_div_j2i_underflow(struct libj2_j2i *a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_div_ji.c b/libj2_j2i_div_ji.c new file mode 100644 index 0000000..7e8f0cc --- /dev/null +++ b/libj2_j2i_div_ji.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_div_ji(struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_div_ji_return.c b/libj2_j2i_div_ji_return.c new file mode 100644 index 0000000..7afd6f0 --- /dev/null +++ b/libj2_j2i_div_ji_return.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline intmax_t libj2_j2i_div_ji_return(const struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_div_ji_to_j2i.c b/libj2_j2i_div_ji_to_j2i.c new file mode 100644 index 0000000..44c5051 --- /dev/null +++ b/libj2_j2i_div_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_div_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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_div_ji_to_j2i_underflow.c b/libj2_j2i_div_ji_to_j2i_underflow.c new file mode 100644 index 0000000..1f07dc6 --- /dev/null +++ b/libj2_j2i_div_ji_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_div_ji_to_j2i_underflow(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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_div_ji_underflow.c b/libj2_j2i_div_ji_underflow.c new file mode 100644 index 0000000..b610fd9 --- /dev/null +++ b/libj2_j2i_div_ji_underflow.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline int libj2_j2i_div_ji_underflow(struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_divmod_j2i.c b/libj2_j2i_divmod_j2i.c new file mode 100644 index 0000000..dc6ef9a --- /dev/null +++ b/libj2_j2i_divmod_j2i.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline intmax_t libj2_j2i_divmod_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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_divmod_j2i_to_j2i.c b/libj2_j2i_divmod_j2i_to_j2i.c new file mode 100644 index 0000000..147fe0c --- /dev/null +++ b/libj2_j2i_divmod_j2i_to_j2i.c @@ -0,0 +1,459 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_divmod_j2i_to_j2i(struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res_q); +/* 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 +validate_result(const struct libj2_j2i *a, const struct libj2_j2i *b, + const struct libj2_j2i *q, const struct libj2_j2i *r) +{ + struct libj2_j2i v; + libj2_j2i_mul_j2i_to_j2i(q, b, &v); + libj2_j2i_add_j2i(&v, r); + EXPECT(libj2_j2i_eq_j2i(&v, a)); + + if (!a->high && !b->high) { + EXPECT(!q->high); + EXPECT(!r->high); + EXPECT(q->low == a->low / b->low); + EXPECT(r->low == a->low % b->low); + } +} + + +static void +check_manual(const struct libj2_j2i *a, const struct libj2_j2i *b, + const struct libj2_j2i *expected_q, const struct libj2_j2i *expected_r) +{ + struct libj2_j2i a_saved = *a, b_saved = *b, q, r, eq, er; + intmax_t b_low_ji; + int underflow; + + EXPECT(!libj2_j2i_is_zero(b)); + + r = (struct libj2_j2i){111, 222}; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_divmod_j2i_to_j2i_j2i(a, b, &q, &r); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + if (expected_q) { + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + } else { + eq = q; + expected_q = &eq; + } + if (expected_r) { + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + } else { + er = r; + expected_r = &er; + } + underflow = !libj2_j2i_is_zero(expected_r); + + validate_result(a, b, expected_q, expected_r); + + r = (struct libj2_j2i){111, 222}; + q = *a; + libj2_j2i_divmod_j2i_to_j2i_j2i(&q, b, &q, &r); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_divmod_j2i_to_j2i_j2i(&r, b, &q, &r); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = (struct libj2_j2i){111, 222}; + q = *b; + libj2_j2i_divmod_j2i_to_j2i_j2i(a, &q, &q, &r); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *b; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_divmod_j2i_to_j2i_j2i(a, &r, &q, &r); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *b; + q = *a; + libj2_j2i_divmod_j2i_to_j2i_j2i(&q, &r, &q, &r); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + q = *b; + libj2_j2i_divmod_j2i_to_j2i_j2i(&r, &q, &q, &r); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + q = (struct libj2_j2i){333, 444}; + libj2_j2i_div_j2i_to_j2i(a, b, &q); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *a; + libj2_j2i_div_j2i_to_j2i(&q, b, &q); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *b; + libj2_j2i_div_j2i_to_j2i(a, &q, &q); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = (struct libj2_j2i){333, 444}; + EXPECT(libj2_j2i_div_j2i_to_j2i_underflow(a, b, &q) == underflow); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *a; + EXPECT(libj2_j2i_div_j2i_to_j2i_underflow(&q, b, &q) == underflow); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *b; + EXPECT(libj2_j2i_div_j2i_to_j2i_underflow(a, &q, &q) == underflow); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + r = (struct libj2_j2i){111, 222}; + libj2_j2i_mod_j2i_to_j2i(a, b, &r); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + libj2_j2i_mod_j2i_to_j2i(&r, b, &r); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *b; + libj2_j2i_mod_j2i_to_j2i(a, &r, &r); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_divmod_j2i_to_j2i(&r, b, &q); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + q = *b; + libj2_j2i_divmod_j2i_to_j2i(&r, &q, &q); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + q = *a; + libj2_j2i_div_j2i(&q, b); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *a; + EXPECT(libj2_j2i_div_j2i_underflow(&q, b) == underflow); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + r = *a; + libj2_j2i_mod_j2i(&r, b); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *b; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_rdivmod_j2i_to_j2i(&r, a, &q); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *b; + q = *a; + libj2_j2i_rdivmod_j2i_to_j2i(&r, &q, &q); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + q = *b; + libj2_j2i_rdiv_j2i(&q, a); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *b; + EXPECT(libj2_j2i_rdiv_j2i_underflow(&q, a) == underflow); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + r = *b; + libj2_j2i_rmod_j2i(&r, a); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + EXPECT(libj2_j2i_divmod_j2i(&r, b) == (intmax_t)expected_q->low); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + EXPECT(libj2_j2i_div_j2i_return(a, b) == (intmax_t)expected_q->low); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(b, &b_saved)); + + if (!b->high && b->low <= (intmax_t)INTMAX_MAX) { + b_low_ji = (intmax_t)b->low; + + r = (struct libj2_j2i){111, 222}; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_divmod_ji_to_j2i_j2i(a, b_low_ji, &q, &r); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = (struct libj2_j2i){111, 222}; + q = *a; + libj2_j2i_divmod_ji_to_j2i_j2i(&q, b_low_ji, &q, &r); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_divmod_ji_to_j2i_j2i(&r, b_low_ji, &q, &r); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + q = (struct libj2_j2i){333, 444}; + libj2_j2i_div_ji_to_j2i(a, b_low_ji, &q); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *a; + libj2_j2i_div_ji_to_j2i(&q, b_low_ji, &q); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = (struct libj2_j2i){333, 444}; + EXPECT(libj2_j2i_div_ji_to_j2i_underflow(a, b_low_ji, &q) == underflow); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *a; + EXPECT(libj2_j2i_div_ji_to_j2i_underflow(&q, b_low_ji, &q) == underflow); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + r = (struct libj2_j2i){111, 222}; + libj2_j2i_mod_ji_to_j2i(a, b_low_ji, &r); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + libj2_j2i_mod_ji_to_j2i(&r, b_low_ji, &r); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_divmod_ji_to_j2i(&r, b_low_ji, &q); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + q = *a; + libj2_j2i_div_ji(&q, b_low_ji); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *a; + EXPECT(libj2_j2i_div_ji_underflow(&q, b_low_ji) == underflow); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + r = *a; + libj2_j2i_mod_ji(&r, b_low_ji); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *b; + EXPECT(libj2_j2i_rdivmod_j2i(&r, a) == (intmax_t)expected_q->low); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + EXPECT(libj2_j2i_divmod_ji(&r, b_low_ji) == (intmax_t)expected_q->low); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + EXPECT(libj2_j2i_div_ji_return(a, b_low_ji) == (intmax_t)expected_q->low); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + } + + if (a == b) { + r = (struct libj2_j2i){111, 222}; + q = *a; + libj2_j2i_divmod_j2i_to_j2i_j2i(&q, &q, &q, &r); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_divmod_j2i_to_j2i_j2i(&r, &r, &q, &r); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + q = *a; + libj2_j2i_div_j2i_to_j2i(&q, &q, &q); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *a; + EXPECT(libj2_j2i_div_j2i_to_j2i_underflow(&q, &q, &q) == underflow); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + r = *a; + libj2_j2i_mod_j2i_to_j2i(&r, &r, &r); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_divmod_j2i_to_j2i(&r, &r, &q); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + q = *a; + libj2_j2i_div_j2i(&q, &q); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *a; + EXPECT(libj2_j2i_div_j2i_underflow(&q, &q) == underflow); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + r = *a; + libj2_j2i_mod_j2i(&r, &r); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + q = (struct libj2_j2i){333, 444}; + libj2_j2i_rdivmod_j2i_to_j2i(&r, &r, &q); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + q = *a; + libj2_j2i_rdiv_j2i(&q, &q); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + q = *a; + EXPECT(libj2_j2i_rdiv_j2i_underflow(&q, &q) == underflow); + EXPECT(libj2_j2i_eq_j2i(&q, expected_q)); + + r = *a; + libj2_j2i_rmod_j2i(&r, &r); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + + r = *a; + EXPECT(libj2_j2i_divmod_j2i(&r, &r) == (intmax_t)expected_q->low); + EXPECT(libj2_j2i_eq_j2i(&r, expected_r)); + } +} + + +static void +check(const struct libj2_j2i *a, const struct libj2_j2i *b) +{ + struct libj2_j2i u, v; + if (!a) { + u.high = random_ju(); + u.low = random_ju(); + a = &u; + } + if (!b) { + do { + v.high = random_ju(); + v.low = random_ju(); + } while (!v.high && !v.low); + b = &u; + } + check_manual(a, b, NULL, NULL); +} + + +int +main(void) +{ + struct libj2_j2i a = {0, 0}, b = {0, 0}, q = {0, 0}, r = {0, 0}; + struct libj2_j2i zero = {0, 0}, one = {0, 0}, two = {0, 0}, minus_one; + unsigned i; + + srand((unsigned)time(NULL)); + + one.low = 1; + two.low = 2; + libj2_ji_to_j2i(-1, &minus_one); + + check_manual(&one, &one, &one, &zero); + check_manual(&two, &one, &two, &zero); + check_manual(&one, &two, &zero, &one); + check_manual(&zero, &one, &zero, &zero); + + a.low = 35; + b.low = 4; + q.low = 8; + r.low = 3; + check_manual(&a, &b, &q, &r); + + a.low = UINTMAX_C(0x14385c048097d350); + b.low = UINTMAX_C(0x1212734e33d9df1e); + r.low = a.low % b.low; + check(&a, &b); + check_manual(&a, &b, &one, &r); + + for (i = 0; i < 2048; i++) { + a.high = b.high = 0; + a.low = random_ju(); + b.low = random_ju(); + check(NULL, NULL); + check(NULL, &a); + check(&a, NULL); + check(&a, &b); + a.high = b.low; + check(&a, &a); + if (!libj2_j2i_is_zero(&a)) + check_manual(&zero, &a, &zero, &zero); + check_manual(&a, &one, &a, &zero); + b.high = a.high >> 1; + b.low = a.low >> 1; + b.low |= (a.high & 1U) << (LIBJ2_JU_BIT - 1U); + if (a.high & ((uintmax_t)INTMAX_MAX + 1U)) { + b.high |= (uintmax_t)INTMAX_MAX + 1U; + if (a.low & 1U) { + b.low += 1U; + if (b.low == 0U) + b.high += 1U; + check_manual(&a, &two, &b, &minus_one); + } else { + check_manual(&a, &two, &b, &zero); + } + } else { + check_manual(&a, &two, &b, (a.low & 1U) ? &one : &zero); + } + } + + /* TODO test sign-issues in a better way, especially ji divisor */ + + return 0; +} + +#endif diff --git a/libj2_j2i_divmod_j2i_to_j2i_j2i.c b/libj2_j2i_divmod_j2i_to_j2i_j2i.c new file mode 100644 index 0000000..63587d6 --- /dev/null +++ b/libj2_j2i_divmod_j2i_to_j2i_j2i.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_divmod_j2i_to_j2i_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b, + struct libj2_j2i *res_q, struct libj2_j2i *res_r); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_divmod_ji.c b/libj2_j2i_divmod_ji.c new file mode 100644 index 0000000..84f316b --- /dev/null +++ b/libj2_j2i_divmod_ji.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline intmax_t libj2_j2i_divmod_ji(struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_divmod_ji_to_j2i.c b/libj2_j2i_divmod_ji_to_j2i.c new file mode 100644 index 0000000..1a7d64c --- /dev/null +++ b/libj2_j2i_divmod_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_divmod_ji_to_j2i(struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res_q); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_divmod_ji_to_j2i_j2i.c b/libj2_j2i_divmod_ji_to_j2i_j2i.c new file mode 100644 index 0000000..853f385 --- /dev/null +++ b/libj2_j2i_divmod_ji_to_j2i_j2i.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern 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); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_eq_j2i.3 b/libj2_j2i_eq_j2i.3 new file mode 100644 index 0000000..e6aaacf --- /dev/null +++ b/libj2_j2i_eq_j2i.3 @@ -0,0 +1,53 @@ +.TH LIBJ2_J2I_EQ_J2I 3 LIBJ2 +.SH NAME +libj2_j2i_eq_j2i \- Check two values for equality + +.SH SYNOPSIS +.nf +#include <libj2.h> + +int \fBlibj2_j2i_eq_j2i\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_eq_ji\fP(const struct libj2_j2i *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ji_eq_j2i\fP(intmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_eq_j2u\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2i_eq_ju\fP(const struct libj2_j2i *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ji_eq_j2u\fP(intmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_eq_j2i\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_eq_ji\fP(const struct libj2_j2u *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ju_eq_j2i\fP(uintmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_eq_j2u\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_eq_ju\fP(const struct libj2_j2u *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ju_eq_j2u\fP(uintmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The above listed function checks whether +the value +.I a +is equal to the value of +.IR b . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The functions return 1 if +.I a +is equal to +.IR b , +and 0 otherwise. + +.SH ERRORS +The functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_j2i_cmp_j2i (3), +.BR libj2_j2i_ne_j2i (3), +.BR libj2_j2i_lt_j2i (3), +.BR libj2_j2i_le_j2i (3), +.BR libj2_j2i_gt_j2i (3), +.BR libj2_j2i_ge_j2i (3) diff --git a/libj2_j2i_eq_j2i.c b/libj2_j2i_eq_j2i.c index e73e91c..66c4aa7 100644 --- a/libj2_j2i_eq_j2i.c +++ b/libj2_j2i_eq_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_eq_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_eq_j2u.3 b/libj2_j2i_eq_j2u.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_j2i_eq_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_eq_j2u.c b/libj2_j2i_eq_j2u.c index d4ab711..2617e9f 100644 --- a/libj2_j2i_eq_j2u.c +++ b/libj2_j2i_eq_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_eq_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_eq_ji.3 b/libj2_j2i_eq_ji.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_j2i_eq_ji.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_eq_ji.c b/libj2_j2i_eq_ji.c index b22cad8..2b77a37 100644 --- a/libj2_j2i_eq_ji.c +++ b/libj2_j2i_eq_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_eq_ji(const struct libj2_j2i *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_eq_ju.3 b/libj2_j2i_eq_ju.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_j2i_eq_ju.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_eq_ju.c b/libj2_j2i_eq_ju.c index 8f3c119..00a7877 100644 --- a/libj2_j2i_eq_ju.c +++ b/libj2_j2i_eq_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_eq_ju(const struct libj2_j2i *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_ge_j2i.3 b/libj2_j2i_ge_j2i.3 new file mode 100644 index 0000000..d6e03b3 --- /dev/null +++ b/libj2_j2i_ge_j2i.3 @@ -0,0 +1,53 @@ +.TH LIBJ2_J2I_GE_J2I 3 LIBJ2 +.SH NAME +libj2_j2i_ge_j2i \- Check value greater than or equal to another value + +.SH SYNOPSIS +.nf +#include <libj2.h> + +int \fBlibj2_j2i_ge_j2i\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_ge_ji\fP(const struct libj2_j2i *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ji_ge_j2i\fP(intmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_ge_j2u\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2i_ge_ju\fP(const struct libj2_j2i *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ji_ge_j2u\fP(intmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_ge_j2i\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_ge_ji\fP(const struct libj2_j2u *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ju_ge_j2i\fP(uintmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_ge_j2u\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_ge_ju\fP(const struct libj2_j2u *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ju_ge_j2u\fP(uintmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The above listed function checks whether +the value +.I a +is greater than or equal to the value of +.IR b . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The functions return 1 if +.I a +is greater than or equal to +.IR b , +and 0 otherwise. + +.SH ERRORS +The functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_j2i_cmp_j2i (3), +.BR libj2_j2i_eq_j2i (3), +.BR libj2_j2i_ne_j2i (3), +.BR libj2_j2i_lt_j2i (3), +.BR libj2_j2i_le_j2i (3), +.BR libj2_j2i_gt_j2i (3) diff --git a/libj2_j2i_ge_j2i.c b/libj2_j2i_ge_j2i.c index cff7aef..c5c3fa8 100644 --- a/libj2_j2i_ge_j2i.c +++ b/libj2_j2i_ge_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_ge_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_ge_j2u.3 b/libj2_j2i_ge_j2u.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_j2i_ge_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_ge_j2u.c b/libj2_j2i_ge_j2u.c index b582faf..1c2d94c 100644 --- a/libj2_j2i_ge_j2u.c +++ b/libj2_j2i_ge_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_ge_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_ge_ji.3 b/libj2_j2i_ge_ji.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_j2i_ge_ji.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_ge_ji.c b/libj2_j2i_ge_ji.c index b74f642..ba3b007 100644 --- a/libj2_j2i_ge_ji.c +++ b/libj2_j2i_ge_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_ge_ji(const struct libj2_j2i *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_ge_ju.3 b/libj2_j2i_ge_ju.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_j2i_ge_ju.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_ge_ju.c b/libj2_j2i_ge_ju.c index 8b07a01..e2335bb 100644 --- a/libj2_j2i_ge_ju.c +++ b/libj2_j2i_ge_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_ge_ju(const struct libj2_j2i *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_gt_j2i.3 b/libj2_j2i_gt_j2i.3 new file mode 100644 index 0000000..9af2511 --- /dev/null +++ b/libj2_j2i_gt_j2i.3 @@ -0,0 +1,53 @@ +.TH LIBJ2_J2I_GT_J2I 3 LIBJ2 +.SH NAME +libj2_j2i_gt_j2i \- Check value greater than another value + +.SH SYNOPSIS +.nf +#include <libj2.h> + +int \fBlibj2_j2i_gt_j2i\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_gt_ji\fP(const struct libj2_j2i *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ji_gt_j2i\fP(intmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_gt_j2u\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2i_gt_ju\fP(const struct libj2_j2i *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ji_gt_j2u\fP(intmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_gt_j2i\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_gt_ji\fP(const struct libj2_j2u *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ju_gt_j2i\fP(uintmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_gt_j2u\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_gt_ju\fP(const struct libj2_j2u *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ju_gt_j2u\fP(uintmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The above listed function checks whether +the value +.I a +is greater than the value of +.IR b . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The functions return 1 if +.I a +is greater than +.IR b , +and 0 otherwise. + +.SH ERRORS +The functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_j2i_cmp_j2i (3), +.BR libj2_j2i_eq_j2i (3), +.BR libj2_j2i_ne_j2i (3), +.BR libj2_j2i_lt_j2i (3), +.BR libj2_j2i_le_j2i (3), +.BR libj2_j2i_ge_j2i (3) diff --git a/libj2_j2i_gt_j2i.c b/libj2_j2i_gt_j2i.c index 4d3f68c..5667477 100644 --- a/libj2_j2i_gt_j2i.c +++ b/libj2_j2i_gt_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_gt_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_gt_j2u.3 b/libj2_j2i_gt_j2u.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_j2i_gt_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_gt_j2u.c b/libj2_j2i_gt_j2u.c index de3282e..4915ae7 100644 --- a/libj2_j2i_gt_j2u.c +++ b/libj2_j2i_gt_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_gt_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_gt_ji.3 b/libj2_j2i_gt_ji.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_j2i_gt_ji.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_gt_ji.c b/libj2_j2i_gt_ji.c index f43b2cf..0836d3d 100644 --- a/libj2_j2i_gt_ji.c +++ b/libj2_j2i_gt_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_gt_ji(const struct libj2_j2i *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_gt_ju.3 b/libj2_j2i_gt_ju.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_j2i_gt_ju.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_gt_ju.c b/libj2_j2i_gt_ju.c index 89975e2..e452bd8 100644 --- a/libj2_j2i_gt_ju.c +++ b/libj2_j2i_gt_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_gt_ju(const struct libj2_j2i *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_le_j2i.3 b/libj2_j2i_le_j2i.3 new file mode 100644 index 0000000..4c309ea --- /dev/null +++ b/libj2_j2i_le_j2i.3 @@ -0,0 +1,53 @@ +.TH LIBJ2_J2I_LE_J2I 3 LIBJ2 +.SH NAME +libj2_j2i_le_j2i \- Check value less than or equal to another value + +.SH SYNOPSIS +.nf +#include <libj2.h> + +int \fBlibj2_j2i_le_j2i\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_le_ji\fP(const struct libj2_j2i *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ji_le_j2i\fP(intmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_le_j2u\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2i_le_ju\fP(const struct libj2_j2i *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ji_le_j2u\fP(intmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_le_j2i\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_le_ji\fP(const struct libj2_j2u *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ju_le_j2i\fP(uintmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_le_j2u\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_le_ju\fP(const struct libj2_j2u *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ju_le_j2u\fP(uintmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The above listed function checks whether +the value +.I a +is less than or equal to the value of +.IR b . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The functions return 1 if +.I a +is less than or equal to +.IR b , +and 0 otherwise. + +.SH ERRORS +The functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_j2i_cmp_j2i (3), +.BR libj2_j2i_eq_j2i (3), +.BR libj2_j2i_ne_j2i (3), +.BR libj2_j2i_lt_j2i (3), +.BR libj2_j2i_gt_j2i (3), +.BR libj2_j2i_ge_j2i (3) diff --git a/libj2_j2i_le_j2i.c b/libj2_j2i_le_j2i.c index 3569d7a..6eab5b4 100644 --- a/libj2_j2i_le_j2i.c +++ b/libj2_j2i_le_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_le_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_le_j2u.3 b/libj2_j2i_le_j2u.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_j2i_le_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_le_j2u.c b/libj2_j2i_le_j2u.c index f29aa40..7a41ed4 100644 --- a/libj2_j2i_le_j2u.c +++ b/libj2_j2i_le_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_le_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_le_ji.3 b/libj2_j2i_le_ji.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_j2i_le_ji.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_le_ji.c b/libj2_j2i_le_ji.c index 1ccd14b..ecd202c 100644 --- a/libj2_j2i_le_ji.c +++ b/libj2_j2i_le_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_le_ji(const struct libj2_j2i *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_le_ju.3 b/libj2_j2i_le_ju.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_j2i_le_ju.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_le_ju.c b/libj2_j2i_le_ju.c index 10e77ad..51bdbd6 100644 --- a/libj2_j2i_le_ju.c +++ b/libj2_j2i_le_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_le_ju(const struct libj2_j2i *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_lt_j2i.3 b/libj2_j2i_lt_j2i.3 new file mode 100644 index 0000000..cdb7265 --- /dev/null +++ b/libj2_j2i_lt_j2i.3 @@ -0,0 +1,53 @@ +.TH LIBJ2_J2I_LT_J2I 3 LIBJ2 +.SH NAME +libj2_j2i_lt_j2i \- Check value less than another value + +.SH SYNOPSIS +.nf +#include <libj2.h> + +int \fBlibj2_j2i_lt_j2i\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_lt_ji\fP(const struct libj2_j2i *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ji_lt_j2i\fP(intmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_lt_j2u\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2i_lt_ju\fP(const struct libj2_j2i *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ji_lt_j2u\fP(intmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_lt_j2i\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_lt_ji\fP(const struct libj2_j2u *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ju_lt_j2i\fP(uintmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_lt_j2u\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_lt_ju\fP(const struct libj2_j2u *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ju_lt_j2u\fP(uintmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The above listed function checks whether +the value +.I a +is less than the value of +.IR b . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The functions return 1 if +.I a +is less than +.IR b , +and 0 otherwise. + +.SH ERRORS +The functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_j2i_cmp_j2i (3), +.BR libj2_j2i_eq_j2i (3), +.BR libj2_j2i_ne_j2i (3), +.BR libj2_j2i_le_j2i (3), +.BR libj2_j2i_gt_j2i (3), +.BR libj2_j2i_ge_j2i (3) diff --git a/libj2_j2i_lt_j2i.c b/libj2_j2i_lt_j2i.c index 7da3b21..63fa0d4 100644 --- a/libj2_j2i_lt_j2i.c +++ b/libj2_j2i_lt_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_lt_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_lt_j2u.3 b/libj2_j2i_lt_j2u.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_j2i_lt_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_lt_j2u.c b/libj2_j2i_lt_j2u.c index 7cc4f25..d99d05f 100644 --- a/libj2_j2i_lt_j2u.c +++ b/libj2_j2i_lt_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_lt_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_lt_ji.3 b/libj2_j2i_lt_ji.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_j2i_lt_ji.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_lt_ji.c b/libj2_j2i_lt_ji.c index d2ae65b..a4e5441 100644 --- a/libj2_j2i_lt_ji.c +++ b/libj2_j2i_lt_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_lt_ji(const struct libj2_j2i *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_lt_ju.3 b/libj2_j2i_lt_ju.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_j2i_lt_ju.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_lt_ju.c b/libj2_j2i_lt_ju.c index 71fdb93..9aa1a01 100644 --- a/libj2_j2i_lt_ju.c +++ b/libj2_j2i_lt_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_lt_ju(const struct libj2_j2i *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_max.c b/libj2_j2i_max.c index 49de1f9..c751060 100644 --- a/libj2_j2i_max.c +++ b/libj2_j2i_max.c @@ -22,10 +22,8 @@ main(void) 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; } diff --git a/libj2_j2i_min.c b/libj2_j2i_min.c index 74b438b..201f69f 100644 --- a/libj2_j2i_min.c +++ b/libj2_j2i_min.c @@ -21,10 +21,8 @@ main(void) 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); + libj2_j2i_add_ji(&value, -1); EXPECT(libj2_j2i_is_max(&value)); -#endif return 0; } diff --git a/libj2_j2i_mod_j2i.c b/libj2_j2i_mod_j2i.c new file mode 100644 index 0000000..aad06b6 --- /dev/null +++ b/libj2_j2i_mod_j2i.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_mod_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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_mod_j2i_to_j2i.c b/libj2_j2i_mod_j2i_to_j2i.c new file mode 100644 index 0000000..2711b97 --- /dev/null +++ b/libj2_j2i_mod_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_mod_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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_mod_ji.c b/libj2_j2i_mod_ji.c new file mode 100644 index 0000000..85ff995 --- /dev/null +++ b/libj2_j2i_mod_ji.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_mod_ji(struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_mod_ji_to_j2i.c b/libj2_j2i_mod_ji_to_j2i.c new file mode 100644 index 0000000..526fe0d --- /dev/null +++ b/libj2_j2i_mod_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_mod_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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_mul_j2i.c b/libj2_j2i_mul_j2i.c new file mode 100644 index 0000000..51b3dc6 --- /dev/null +++ b/libj2_j2i_mul_j2i.c @@ -0,0 +1,284 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_mul_j2i(struct libj2_j2i *a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +#define CONST_ARG (const struct libj2_j2i *) + + +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 int +refmul(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *r) +{ + int overflow, neg = libj2_j2i_is_negative(a) ^ libj2_j2i_is_negative(b); + struct libj2_j2u ulimit, u, v, w; + struct libj2_j2i ilimit; + + libj2_abs_j2i_to_j2u(a, &u); + libj2_abs_j2i_to_j2u(b, &v); + overflow = libj2_j2u_mul_j2u_to_j2u_overflow(&u, &v, &w); + libj2_j2u_to_j2i(&w, r); + if (neg) + libj2_j2i_min(&ilimit); + else + libj2_j2i_max(&ilimit); + libj2_abs_j2i_to_j2u(&ilimit, &ulimit); + if (libj2_j2u_gt_j2u(&w, &ulimit)) + overflow = 1; + if (neg) + libj2_minus_j2i(r); + + return neg ? -overflow : +overflow; +} + + +static int +check_double(uintmax_t a_high, uintmax_t a_low, struct libj2_j2i *r_out) +{ + struct libj2_j2i a = {.high = a_high, .low = a_low}, a_saved = a; + struct libj2_j2i r, expected; + int expected_overflow, r_set; + enum libj2_overflow overflow; + + expected_overflow = refmul(&a, &a, &expected); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(expected_overflow >= 0); + + r = (struct libj2_j2i){111, 222}; + EXPECT(libj2_j2i_mul_j2i_to_j2i_overflow(CONST_ARG &a, CONST_ARG &a, &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + EXPECT(libj2_j2i_mul_j2i_to_j2i_overflow(CONST_ARG &r, CONST_ARG &r, &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + EXPECT(libj2_j2i_mul_j2i_overflow(&r, CONST_ARG &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = (struct libj2_j2i){111, 222}; + libj2_j2i_mul_j2i_to_j2i(CONST_ARG &a, CONST_ARG &a, &r); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_j2i_mul_j2i_to_j2i(CONST_ARG &r, CONST_ARG &r, &r); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_j2i_mul_j2i(&r, CONST_ARG &r); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + EXPECT(libj2_j2i_mul_j2i_overflow_p(CONST_ARG &a, CONST_ARG &a) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + + r = (struct libj2_j2i){111, 222}; + r_set = 999; + EXPECT(libj2_j2i_mul_j2i_to_j2i_overflow_p(CONST_ARG &a, CONST_ARG &a, &r, &r_set) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + EXPECT(r_set == 0 || r_set == 1); + EXPECT(libj2_j2i_eq_j2i(&r, r_set ? &expected : &(struct libj2_j2i){111, 222})); + + r = a; + r_set = 999; + EXPECT(libj2_j2i_mul_j2i_to_j2i_overflow_p(CONST_ARG &r, CONST_ARG &r, &r, &r_set) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + EXPECT(r_set == 0 || r_set == 1); + EXPECT(libj2_j2i_eq_j2i(&r, r_set ? &expected : &a_saved)); + + overflow = libj2_j2i_mul_j2i_overflow_p_quick(CONST_ARG &a, CONST_ARG &a); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(overflow == LIBJ2_POSITIVE_OVERFLOW_UNKNOWN || (int)overflow == expected_overflow); + + *r_out = expected; + return expected_overflow; +} + + +static void +check(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}, a_saved = a; + struct libj2_j2i b = {.high = b_high, .low = b_low}, b_saved = b; + struct libj2_j2i r, expected; + int expected_overflow, r_set; + enum libj2_overflow overflow; + + expected_overflow = refmul(&a, &b, &expected); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + if (a_high == b_high && a_low == b_low) { + r = (struct libj2_j2i){111, 222}; + EXPECT(check_double(a_high, a_low, &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + } + + r = (struct libj2_j2i){111, 222}; + EXPECT(libj2_j2i_mul_j2i_to_j2i_overflow(CONST_ARG &a, CONST_ARG &b, &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = (struct libj2_j2i){111, 222}; + libj2_j2i_mul_j2i_to_j2i(CONST_ARG &a, CONST_ARG &b, &r); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + EXPECT(libj2_j2i_mul_j2i_to_j2i_overflow(CONST_ARG &r, CONST_ARG &b, &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_j2i_mul_j2i_to_j2i(CONST_ARG &r, CONST_ARG &b, &r); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = b; + EXPECT(libj2_j2i_mul_j2i_to_j2i_overflow(CONST_ARG &a, CONST_ARG &r, &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = b; + libj2_j2i_mul_j2i_to_j2i(CONST_ARG &a, CONST_ARG &r, &r); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + EXPECT(libj2_j2i_mul_j2i_overflow(&r, CONST_ARG &b) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_j2i_mul_j2i(&r, CONST_ARG &b); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + EXPECT(libj2_j2i_mul_j2i_overflow_p(CONST_ARG &a, CONST_ARG &b) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + r = (struct libj2_j2i){111, 222}; + r_set = 999; + EXPECT(libj2_j2i_mul_j2i_to_j2i_overflow_p(CONST_ARG &a, CONST_ARG &b, &r, &r_set) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(r_set == 0 || r_set == 1); + EXPECT(libj2_j2i_eq_j2i(&r, r_set ? &expected : &(struct libj2_j2i){111, 222})); + + r = a; + r_set = 999; + EXPECT(libj2_j2i_mul_j2i_to_j2i_overflow_p(CONST_ARG &r, CONST_ARG &b, &r, &r_set) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(r_set == 0 || r_set == 1); + EXPECT(libj2_j2i_eq_j2i(&r, r_set ? &expected : &a_saved)); + + r = b; + r_set = 999; + EXPECT(libj2_j2i_mul_j2i_to_j2i_overflow_p(CONST_ARG &a, CONST_ARG &r, &r, &r_set) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(r_set == 0 || r_set == 1); + EXPECT(libj2_j2i_eq_j2i(&r, r_set ? &expected : &b_saved)); + + overflow = libj2_j2i_mul_j2i_overflow_p_quick(CONST_ARG &a, CONST_ARG &b); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + if (libj2_j2i_is_zero(&a) || libj2_j2i_is_zero(&b)) + EXPECT(overflow == LIBJ2_NO_OVERFLOW); + if (overflow == LIBJ2_POSITIVE_OVERFLOW_UNKNOWN) { + EXPECT(expected_overflow >= 0); + EXPECT(libj2_sgn_j2i(&a) == libj2_sgn_j2i(&b)); + } else if (overflow == LIBJ2_NEGATIVE_OVERFLOW_UNKNOWN) { + EXPECT(expected_overflow <= 0); + EXPECT(libj2_sgn_j2i(&a) == -libj2_sgn_j2i(&b)); + } else { + EXPECT((int)overflow == expected_overflow); + } +} + + +int +main(void) +{ + uintmax_t a, b, c, d, max, min, umax, vs[12]; + unsigned i, ii, iii, iv, k, j; + + srand((unsigned)time(NULL)); + + umax = UINTMAX_MAX; + max = umax >> 1; + min = ~max; + + vs[0] = 0U; + vs[1] = 1U; + vs[2] = 2U; + vs[3] = umax - 0U; + vs[4] = umax - 1U; + vs[5] = umax - 2U; + vs[6] = max - 0U; + vs[7] = max - 1U; + vs[8] = max - 2U; + vs[9] = min + 0U; + vs[10] = min + 1U; + vs[11] = min + 2U; + + for (j = 0; j < 32U; j++) { + for (k = 0; k < 16U; k++) { + a = random_ju() >> 1; + b = random_ju() >> 1; + c = random_ju() >> 1; + d = random_ju() >> 1; + if (k & 1U) a = ~a; + if (k & 2U) b = ~b; + if (k & 4U) c = ~c; + if (k & 8U) d = ~d; + check(a, b, c, d); + for (i = 0; k < 8U && i < 12U; i++) { + check(vs[i], a, b, c); + check(a, vs[i], b, c); + check(a, b, vs[i], c); + check(a, b, c, vs[i]); + for (ii = 0; k < 4U && ii < 12U; ii++) { + check(vs[i], vs[ii], a, b); + check(vs[i], a, vs[ii], b); + check(vs[i], a, b, vs[ii]); + check(a, vs[i], vs[ii], b); + check(a, vs[i], b, vs[ii]); + check(a, b, vs[i], vs[ii]); + for (iii = 0; k < 2U && iii < 12U; iii++) { + check(vs[i], vs[ii], vs[iii], a); + check(vs[i], vs[ii], a, vs[iii]); + check(vs[i], a, vs[ii], vs[iii]); + check(a, vs[i], vs[ii], vs[iii]); + for (iv = 0; !j && k < 1U && iv < 12U; iv++) + check(vs[i], vs[ii], vs[iii], vs[iv]); + } + } + } + } + } + + return 0; +} + +#endif diff --git a/libj2_j2i_mul_j2i_overflow.c b/libj2_j2i_mul_j2i_overflow.c new file mode 100644 index 0000000..c840edb --- /dev/null +++ b/libj2_j2i_mul_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_mul_j2i_overflow(struct libj2_j2i *a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_mul_j2i.c */ + +#endif diff --git a/libj2_j2i_mul_j2i_overflow_p.c b/libj2_j2i_mul_j2i_overflow_p.c new file mode 100644 index 0000000..1c707f1 --- /dev/null +++ b/libj2_j2i_mul_j2i_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_mul_j2i_overflow_p(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_mul_j2i.c */ + +#endif diff --git a/libj2_j2i_mul_j2i_overflow_p_quick.c b/libj2_j2i_mul_j2i_overflow_p_quick.c new file mode 100644 index 0000000..27b47b8 --- /dev/null +++ b/libj2_j2i_mul_j2i_overflow_p_quick.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline enum libj2_overflow libj2_j2i_mul_j2i_overflow_p_quick(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_mul_j2i.c */ + +#endif diff --git a/libj2_j2i_mul_j2i_to_j2i.c b/libj2_j2i_mul_j2i_to_j2i.c new file mode 100644 index 0000000..678f02c --- /dev/null +++ b/libj2_j2i_mul_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_mul_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_mul_j2i.c */ + +#endif diff --git a/libj2_j2i_mul_j2i_to_j2i_overflow.c b/libj2_j2i_mul_j2i_to_j2i_overflow.c new file mode 100644 index 0000000..466763c --- /dev/null +++ b/libj2_j2i_mul_j2i_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_mul_j2i_to_j2i_overflow(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_mul_j2i.c */ + +#endif diff --git a/libj2_j2i_mul_j2i_to_j2i_overflow_p.c b/libj2_j2i_mul_j2i_to_j2i_overflow_p.c new file mode 100644 index 0000000..dea6e8d --- /dev/null +++ b/libj2_j2i_mul_j2i_to_j2i_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_mul_j2i_to_j2i_overflow_p(const struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res, int *res_set); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_mul_j2i.c */ + +#endif diff --git a/libj2_j2i_mul_ji.c b/libj2_j2i_mul_ji.c new file mode 100644 index 0000000..e1e25ff --- /dev/null +++ b/libj2_j2i_mul_ji.c @@ -0,0 +1,373 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_mul_ji(struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +static uintmax_t +random_small_ju(size_t bits) +{ + uintmax_t r = 0; + while (bits--) + if (rand() < rand()) + r |= (uintmax_t)1 << bits; + return r; +} + +static uintmax_t +random_hju(void) +{ + return random_small_ju(LIBJ2_JU_BIT / 2U); +} + +static uintmax_t +random_ju(void) +{ + return random_small_ju(LIBJ2_JU_BIT); +} + + +static int +refmul(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *expected) +{ + struct libj2_j2u u; + struct libj2_j2i c; + uintmax_t v; + unsigned i; + int neg, overflow = 0; + + neg = libj2_j2i_is_negative(a) ^ (b < 0); + libj2_abs_j2i_to_j2u(a, &u); + v = b < 0 ? (uintmax_t)-(b + 1) + 1U : (uintmax_t)b; + + libj2_j2i_zero(expected); + for (i = 0; i < LIBJ2_J2U_BIT; i++, v >>= 1) { + if (v & 1U) { + overflow |= libj2_j2i_lsh_to_j2i_overflow(a, i, &c); + libj2_j2i_add_j2i(expected, &c); + } + } + + if (neg) { + overflow = -overflow; + libj2_minus_j2i(expected); + } + + return overflow; +} + + +static void +mul_(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *expected, int expect_overflow) +{ + struct libj2_j2i t, a_saved = *a, t_saved; + enum libj2_overflow ofp; + enum libj2_overflow unknown_overflow; + int set; + + if (libj2_j2i_is_zero(a) || b == 0) + unknown_overflow = LIBJ2_NO_OVERFLOW; + else if (libj2_j2i_is_negative(a) ^ (b < 0)) + unknown_overflow = LIBJ2_NEGATIVE_OVERFLOW_UNKNOWN; + else + unknown_overflow = LIBJ2_POSITIVE_OVERFLOW_UNKNOWN; + + *expected = *a; + libj2_j2i_mul_ji(expected, b); + + t = (struct libj2_j2i){111, 222}; + libj2_j2i_mul_ji_to_j2i(a, b, &t); + EXPECT(libj2_j2i_eq_j2i(&t, expected)); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + + t = *a; + libj2_j2i_mul_ji_to_j2i(&t, b, &t); + EXPECT(libj2_j2i_eq_j2i(&t, expected)); + + t = (struct libj2_j2i){111, 222}; + libj2_ji_mul_j2i_to_j2i(b, a, &t); + EXPECT(libj2_j2i_eq_j2i(&t, expected)); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + + t = *a; + libj2_ji_mul_j2i_to_j2i(b, &t, &t); + EXPECT(libj2_j2i_eq_j2i(&t, expected)); + + t = *a; + EXPECT(libj2_j2i_mul_ji_overflow(&t, b) == expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&t, expected)); + +#if 0 /* TODO saturated multiplication */ + t = *a; + libj2_j2u_sat_mul_ju(&t, b); + EXPECT(expect_overflow ? libj2_j2u_is_max(&t) : libj2_j2u_eq_j2u(&t, expected)); +#endif + + t = *a; + EXPECT(libj2_j2i_mul_ji_overflow_p((const struct libj2_j2i *)&t, b) == expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&t, a)); + + t = *a; + ofp = libj2_j2i_mul_ji_overflow_p_quick((const struct libj2_j2i *)&t, b); + EXPECT(ofp == unknown_overflow || (int)ofp == expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&t, a)); + + set = 999; + t = (struct libj2_j2i){111, 222}; + t_saved = t; + EXPECT(libj2_j2i_mul_ji_to_j2i_overflow_p((const struct libj2_j2i *)a, b, &t, &set) == expect_overflow); + EXPECT(set == 0 || set == 1); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&t, set ? expected : &t_saved)); + + set = 999; + t = *a; + EXPECT(libj2_j2i_mul_ji_to_j2i_overflow_p((const struct libj2_j2i *)&t, b, &t, &set) == expect_overflow); + EXPECT(set == 0 || set == 1); + EXPECT(libj2_j2i_eq_j2i(&t, set ? expected : a)); + + t = (struct libj2_j2i){111, 222}; + EXPECT(libj2_j2i_mul_ji_to_j2i_overflow(a, b, &t) == expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&t, expected)); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + + t = *a; + EXPECT(libj2_j2i_mul_ji_to_j2i_overflow(&t, b, &t) == expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&t, expected)); + +#if 0 /* TODO saturated multiplication */ + t = (struct libj2_j2u){111, 222}; + libj2_j2u_sat_mul_ju_to_j2u(a, b, &t); + EXPECT(expect_overflow ? libj2_j2u_is_max(&t) : libj2_j2u_eq_j2u(&t, expected)); + EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); + + t = *a; + libj2_j2u_sat_mul_ju_to_j2u(&t, b, &t); + EXPECT(expect_overflow ? libj2_j2u_is_max(&t) : libj2_j2u_eq_j2u(&t, expected)); +#endif + + t = (struct libj2_j2i){111, 222}; + EXPECT(libj2_ji_mul_j2i_to_j2i_overflow(b, a, &t) == expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&t, expected)); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + + t = *a; + EXPECT(libj2_ji_mul_j2i_to_j2i_overflow(b, &t, &t) == expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&t, expected)); + +#if 0 /* TODO saturated multiplication */ + t = (struct libj2_j2u){111, 222}; + libj2_ju_sat_mul_j2u_to_j2u(b, a, &t); + EXPECT(expect_overflow ? libj2_j2u_is_max(&t) : libj2_j2u_eq_j2u(&t, expected)); + EXPECT(libj2_j2u_eq_j2u(a, &a_saved)); + + t = *a; + libj2_ju_sat_mul_j2u_to_j2u(b, &t, &t); + EXPECT(expect_overflow ? libj2_j2u_is_max(&t) : libj2_j2u_eq_j2u(&t, expected)); +#endif + + set = 999; + t = (struct libj2_j2i){111, 222}; + t_saved = t; + EXPECT(libj2_ji_mul_j2i_to_j2i_overflow_p(b, a, &t, &set) == expect_overflow); + EXPECT(set == 0 || set == 1); + EXPECT(libj2_j2i_eq_j2i(&t, set ? expected : &t_saved)); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + + set = 999; + t = *a; + EXPECT(libj2_ji_mul_j2i_to_j2i_overflow_p(b, &t, &t, &set) == expect_overflow); + EXPECT(set == 0 || set == 1); + EXPECT(libj2_j2i_eq_j2i(&t, set ? expected : a)); + + EXPECT(libj2_ji_mul_j2i_overflow_p(b, (const struct libj2_j2i *)a) == expect_overflow); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); + + ofp = libj2_ji_mul_j2i_overflow_p_quick(b, (const struct libj2_j2i *)a); + EXPECT(ofp == unknown_overflow || (int)ofp == expect_overflow); + EXPECT(libj2_j2i_eq_j2i(a, &a_saved)); +} + + +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; + + libj2_minus_j2i_to_j2i(a, &neg_a); + libj2_j2i_to_j2u(a, &u); + + + mul_(a, b, expected, expect_overflow); + + mul_(&neg_a, -b, &r, expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, expected)); + + mul_(&neg_a, b, &r, -expect_overflow); + libj2_minus_j2i(&r); + EXPECT(libj2_j2i_eq_j2i(&r, expected)); + + mul_(a, -b, &r, -expect_overflow); + libj2_minus_j2i(&r); + EXPECT(libj2_j2i_eq_j2i(&r, expected)); + + + expect_overflow = libj2_j2u_mul_ju_to_j2u_overflow(&u, (uintmax_t)b + 1U, (void *)&e); + if (libj2_j2i_is_negative(&e)) + expect_overflow = 1; + + mul_(&neg_a, -b - 1, &r, expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &e)); + + mul_(a, -b - 1, &r, -expect_overflow); + libj2_minus_j2i(&r); + EXPECT(libj2_j2i_eq_j2i(&r, &e)); + + + 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); + if (libj2_j2i_is_negative(&e)) + expect_overflow = 1; + + mul_(&neg_a, b, &r, -expect_overflow); + libj2_minus_j2i(&r); + EXPECT(libj2_j2i_eq_j2i(&r, &e)); + + + expect_overflow = libj2_j2u_mul_ju_to_j2u_overflow(&u, (uintmax_t)b + 1U, (void *)&e); + if (libj2_j2i_is_negative(&e)) + expect_overflow = 1; + + mul_(&neg_a, -b - 1, &r, expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &e)); +} + + +int +main(void) +{ + struct libj2_j2i r, expected; + intmax_t u, v; + uintmax_t w; + unsigned i; + int expect_overflow; + + srand((unsigned)time(NULL)); + + /* self-check */ + r = (struct libj2_j2i){111, 222}; + EXPECT(refmul(&(struct libj2_j2i){.high = UINTMAX_MAX >> 1, .low = UINTMAX_MAX}, INTMAX_MAX, &r) == 1); + EXPECT(r.high == UINTMAX_MAX >> 1); + EXPECT(r.low == 2 + (uintmax_t)INTMAX_MAX); + + r = (struct libj2_j2i){111, 222}; + mul_(&(struct libj2_j2i){.high = (UINTMAX_MAX >> 2) + 1U, .low = 0}, 2, &r, 1); + EXPECT(r.high == (UINTMAX_MAX >> 1) + 1U); + EXPECT(r.low == 0); + + r = (struct libj2_j2i){111, 222}; + mul_(&(struct libj2_j2i){.high = (UINTMAX_MAX >> 2) + 1U, .low = 0}, -2, &r, 0); + EXPECT(r.high == (UINTMAX_MAX >> 1) + 1U); + EXPECT(r.low == 0); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = 0}, 0, &r, 0); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = 0}, 1, &r, 0); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = 0}, INTMAX_MAX, &r, 0); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = 1}, 0, &r, 0); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = UINTMAX_MAX}, 0, &r, 0); + EXPECT(libj2_j2i_is_zero(&r)); + + for (i = 0; i < 32; i++) { + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = 0}, (intmax_t)(random_ju() >> 1), &r, 0); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = random_ju()}, 0, &r, 0); + EXPECT(libj2_j2i_is_zero(&r)); + } + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = 1}, 1, &r, 0); + EXPECT(r.high == 0); + EXPECT(r.low == 1); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = 4}, 4, &r, 0); + EXPECT(r.high == 0); + EXPECT(r.low == 16); + + for (i = 0; i < 32; i++) { + r = (struct libj2_j2i){111, 222}; + v = (intmax_t)(random_ju() >> 1); + mul(&(struct libj2_j2i){.high = 0, .low = 1}, v, &r, 0); + EXPECT(r.high == 0); + EXPECT(r.low == (uintmax_t)v); + + r = (struct libj2_j2i){111, 222}; + v = (intmax_t)(random_ju() >> 1); + mul(&(struct libj2_j2i){.high = 0, .low = (uintmax_t)v}, 1, &r, 0); + EXPECT(r.high == 0); + EXPECT(r.low == (uintmax_t)v); + } + + for (i = 0; i < 32; i++) { + u = (intmax_t)random_hju(); + v = (intmax_t)random_hju(); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = (uintmax_t)u}, v, &r, 0); + EXPECT(r.high == 0); + EXPECT(r.low == (uintmax_t)u * (uintmax_t)v); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = (uintmax_t)v}, u, &r, 0); + EXPECT(r.high == 0); + EXPECT(r.low == (uintmax_t)u * (uintmax_t)v); + } + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = 0, .low = UINTMAX_MAX >> 1}, INTMAX_MAX, &r, 0); + EXPECT(r.high == UINTMAX_MAX >> 2); + EXPECT(r.low == 1); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){.high = UINTMAX_MAX >> 1, .low = UINTMAX_MAX}, INTMAX_MAX, &r, 1); + EXPECT(r.high == UINTMAX_MAX >> 1); + EXPECT(r.low == 2 + (uintmax_t)INTMAX_MAX); + + for (i = 0; i < 256; i++) { + u = (intmax_t)(random_ju() >> 1); + v = (intmax_t)(random_ju() >> 1); + w = random_ju(); + + expect_overflow = refmul(&(struct libj2_j2i){(uintmax_t)u, w}, v, &expected); + + r = (struct libj2_j2i){111, 222}; + mul(&(struct libj2_j2i){(uintmax_t)u, w}, v, &r, expect_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + } + + return 0; +} + +#endif diff --git a/libj2_j2i_mul_ji_overflow.c b/libj2_j2i_mul_ji_overflow.c new file mode 100644 index 0000000..c4ea82a --- /dev/null +++ b/libj2_j2i_mul_ji_overflow.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline int libj2_j2i_mul_ji_overflow(struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_mul_ji.c */ + +#endif diff --git a/libj2_j2i_mul_ji_overflow_p.c b/libj2_j2i_mul_ji_overflow_p.c new file mode 100644 index 0000000..f0fe02f --- /dev/null +++ b/libj2_j2i_mul_ji_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_mul_ji_overflow_p(const struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_mul_ji.c */ + +#endif diff --git a/libj2_j2i_mul_ji_overflow_p_quick.c b/libj2_j2i_mul_ji_overflow_p_quick.c new file mode 100644 index 0000000..de2bc83 --- /dev/null +++ b/libj2_j2i_mul_ji_overflow_p_quick.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline enum libj2_overflow libj2_j2i_mul_ji_overflow_p_quick(const struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_mul_ji.c */ + +#endif diff --git a/libj2_j2i_mul_ji_to_j2i.c b/libj2_j2i_mul_ji_to_j2i.c new file mode 100644 index 0000000..16a50f9 --- /dev/null +++ b/libj2_j2i_mul_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_mul_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_mul_ji.c */ + +#endif diff --git a/libj2_j2i_mul_ji_to_j2i_overflow.c b/libj2_j2i_mul_ji_to_j2i_overflow.c new file mode 100644 index 0000000..210c8ee --- /dev/null +++ b/libj2_j2i_mul_ji_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_mul_ji_to_j2i_overflow(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_mul_ji.c */ + +#endif diff --git a/libj2_j2i_mul_ji_to_j2i_overflow_p.c b/libj2_j2i_mul_ji_to_j2i_overflow_p.c new file mode 100644 index 0000000..e8b481a --- /dev/null +++ b/libj2_j2i_mul_ji_to_j2i_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_mul_ji_to_j2i_overflow_p(const struct libj2_j2i *a, intmax_t b, struct libj2_j2i *res, int *res_set); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_mul_ji.c */ + +#endif diff --git a/libj2_j2i_ne_j2i.3 b/libj2_j2i_ne_j2i.3 new file mode 100644 index 0000000..bf58b50 --- /dev/null +++ b/libj2_j2i_ne_j2i.3 @@ -0,0 +1,53 @@ +.TH LIBJ2_J2I_NE_J2I 3 LIBJ2 +.SH NAME +libj2_j2i_ne_j2i \- Check two values for inequality + +.SH SYNOPSIS +.nf +#include <libj2.h> + +int \fBlibj2_j2i_ne_j2i\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_ne_ji\fP(const struct libj2_j2i *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ji_ne_j2i\fP(intmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2i_ne_j2u\fP(const struct libj2_j2i *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2i_ne_ju\fP(const struct libj2_j2i *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ji_ne_j2u\fP(intmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_ne_j2i\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_ne_ji\fP(const struct libj2_j2u *\fIa\fP, intmax_t \fIb\fP); +int \fBlibj2_ju_ne_j2i\fP(uintmax_t \fIa\fP, const struct libj2_j2i *\fIb\fP); +int \fBlibj2_j2u_ne_j2u\fP(const struct libj2_j2u *\fIa\fP, const struct libj2_j2u *\fIb\fP); +int \fBlibj2_j2u_ne_ju\fP(const struct libj2_j2u *\fIa\fP, uintmax_t \fIb\fP); +int \fBlibj2_ju_ne_j2u\fP(uintmax_t \fIa\fP, const struct libj2_j2u *\fIb\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The above listed function checks whether +the value +.I a +is different from the value of +.IR b . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The functions return 0 if +.I a +is equal to +.IR b , +and 1 otherwise. + +.SH ERRORS +The functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_j2i_cmp_j2i (3), +.BR libj2_j2i_eq_j2i (3), +.BR libj2_j2i_lt_j2i (3), +.BR libj2_j2i_le_j2i (3), +.BR libj2_j2i_gt_j2i (3), +.BR libj2_j2i_ge_j2i (3) diff --git a/libj2_j2i_ne_j2i.c b/libj2_j2i_ne_j2i.c index 887d4eb..ec503e7 100644 --- a/libj2_j2i_ne_j2i.c +++ b/libj2_j2i_ne_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_ne_j2i(const struct libj2_j2i *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_ne_j2u.3 b/libj2_j2i_ne_j2u.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_j2i_ne_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_ne_j2u.c b/libj2_j2i_ne_j2u.c index a9ae130..6a2b7c6 100644 --- a/libj2_j2i_ne_j2u.c +++ b/libj2_j2i_ne_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_ne_j2u(const struct libj2_j2i *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_ne_ji.3 b/libj2_j2i_ne_ji.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_j2i_ne_ji.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_ne_ji.c b/libj2_j2i_ne_ji.c index 95e330d..499f406 100644 --- a/libj2_j2i_ne_ji.c +++ b/libj2_j2i_ne_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_ne_ji(const struct libj2_j2i *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_ne_ju.3 b/libj2_j2i_ne_ju.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_j2i_ne_ju.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_j2i_ne_ju.c b/libj2_j2i_ne_ju.c index bb055ef..b90f964 100644 --- a/libj2_j2i_ne_ju.c +++ b/libj2_j2i_ne_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2i_ne_ju(const struct libj2_j2i *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2i_rdiv_j2i.c b/libj2_j2i_rdiv_j2i.c new file mode 100644 index 0000000..893c33b --- /dev/null +++ b/libj2_j2i_rdiv_j2i.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_rdiv_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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_rdiv_j2i_underflow.c b/libj2_j2i_rdiv_j2i_underflow.c new file mode 100644 index 0000000..c32f7b5 --- /dev/null +++ b/libj2_j2i_rdiv_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_rdiv_j2i_underflow(struct libj2_j2i *a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_rdivmod_j2i.c b/libj2_j2i_rdivmod_j2i.c new file mode 100644 index 0000000..8b1bd41 --- /dev/null +++ b/libj2_j2i_rdivmod_j2i.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline intmax_t libj2_j2i_rdivmod_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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_rdivmod_j2i_to_j2i.c b/libj2_j2i_rdivmod_j2i_to_j2i.c new file mode 100644 index 0000000..60fc71f --- /dev/null +++ b/libj2_j2i_rdivmod_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_rdivmod_j2i_to_j2i(struct libj2_j2i *a, const struct libj2_j2i *b, struct libj2_j2i *res_q); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_rmod_j2i.c b/libj2_j2i_rmod_j2i.c new file mode 100644 index 0000000..0c6c990 --- /dev/null +++ b/libj2_j2i_rmod_j2i.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_rmod_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_divmod_j2i_to_j2i.c */ + +#endif diff --git a/libj2_j2i_rsub_j2i.c b/libj2_j2i_rsub_j2i.c new file mode 100644 index 0000000..ba68d80 --- /dev/null +++ b/libj2_j2i_rsub_j2i.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_rsub_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_sub_j2i.c */ + +#endif diff --git a/libj2_j2i_rsub_j2i_overflow.c b/libj2_j2i_rsub_j2i_overflow.c new file mode 100644 index 0000000..9840a41 --- /dev/null +++ b/libj2_j2i_rsub_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_rsub_j2i_overflow(struct libj2_j2i *a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_sub_j2i.c */ + +#endif diff --git a/libj2_j2i_rsub_j2i_overflow_p.c b/libj2_j2i_rsub_j2i_overflow_p.c new file mode 100644 index 0000000..a45675c --- /dev/null +++ b/libj2_j2i_rsub_j2i_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_rsub_j2i_overflow_p(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_sub_j2i.c */ + +#endif diff --git a/libj2_j2i_rsub_ji.c b/libj2_j2i_rsub_ji.c new file mode 100644 index 0000000..eb99109 --- /dev/null +++ b/libj2_j2i_rsub_ji.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_rsub_ji(struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_sub_ji.c */ + +#endif diff --git a/libj2_j2i_rsub_ji_overflow.c b/libj2_j2i_rsub_ji_overflow.c new file mode 100644 index 0000000..1fd1346 --- /dev/null +++ b/libj2_j2i_rsub_ji_overflow.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline int libj2_j2i_rsub_ji_overflow(struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_sub_ji.c */ + +#endif diff --git a/libj2_j2i_rsub_ji_overflow_p.c b/libj2_j2i_rsub_ji_overflow_p.c new file mode 100644 index 0000000..bad6009 --- /dev/null +++ b/libj2_j2i_rsub_ji_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_rsub_ji_overflow_p(const struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_sub_ji.c */ + +#endif diff --git a/libj2_j2i_sub_j2i.c b/libj2_j2i_sub_j2i.c new file mode 100644 index 0000000..92a344a --- /dev/null +++ b/libj2_j2i_sub_j2i.c @@ -0,0 +1,256 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_sub_j2i(struct libj2_j2i *a, const struct libj2_j2i *b); +/* 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 +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_j2i t, r; + + t = (struct libj2_j2i){.high = a_high, .low = a_low}; + if ((a_neg = libj2_j2i_is_negative(&t))) + libj2_minus_j2i_to_j2u(&t, &a); + else + libj2_j2i_to_j2u(&t, &a); + + t = (struct libj2_j2i){.high = b_high, .low = b_low}; + if ((b_neg = libj2_j2i_is_negative(&t))) + libj2_minus_j2i_to_j2u(&t, &b); + else + libj2_j2i_to_j2u(&t, &b); + + 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)); + } else if (a_neg) { + overflow = -libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, (void *)&r); + EXPECT(overflow == 0 || overflow == -1); + libj2_minus_j2i(&r); + if (!libj2_j2i_is_negative(&r)) + overflow = -1; + else if (overflow) + EXPECT(libj2_j2i_gt_j2i(&r, (const void *)&a)); + if (!overflow) + EXPECT(libj2_j2i_le_j2i(&r, (const void *)&a)); + } else if (b_neg) { + overflow = +libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, (void *)&r); + EXPECT(overflow == 0 || overflow == +1); + if (!libj2_j2i_is_positive(&r)) + overflow = +1; + else if (overflow) + EXPECT(libj2_j2i_lt_j2i(&r, (const void *)&a)); + if (!overflow) + EXPECT(libj2_j2i_gt_j2i(&r, (const void *)&a)); + } else { + overflow = 0; + libj2_minus_j2u(&b); + libj2_j2u_add_j2u_to_j2u(&a, &b, (void *)&r); + EXPECT(libj2_j2i_le_j2u(&r, &a)); + } + + EXPECT(r.high == r_high); + EXPECT(r.low == r_low); + EXPECT(overflow == r_overflow); +} + + +static void +check(uintmax_t a_high, uintmax_t a_low, uintmax_t b_high, uintmax_t b_low) +{ + struct libj2_j2i a, a_saved, b, b_saved, r, expected; + int expected_overflow; + + a.high = a_high; + a.low = a_low; + b.high = b_high; + b.low = b_low; + a_saved = a; + b_saved = b; + +#define CONST_ARG (const struct libj2_j2i *) + + expected = (struct libj2_j2i){111, 222}; + expected_overflow = libj2_j2i_sub_j2i_to_j2i_overflow(CONST_ARG &a, CONST_ARG &b, &expected); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_ne_j2i(&expected, &(struct libj2_j2i){111, 222})); + + validate(a.high, a.low, b.high, b.low, expected.high, expected.low, expected_overflow); + + r = a; + EXPECT(libj2_j2i_sub_j2i_to_j2i_overflow(CONST_ARG &r, CONST_ARG &b, &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = b; + EXPECT(libj2_j2i_sub_j2i_to_j2i_overflow(CONST_ARG &a, CONST_ARG &r, &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + EXPECT(libj2_j2i_sub_j2i_to_j2i_overflow(CONST_ARG &r, CONST_ARG &r, &r) == 0); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_j2i_sub_j2i_to_j2i(CONST_ARG &a, CONST_ARG &b, &r); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_j2i_sub_j2i_to_j2i(CONST_ARG &r, CONST_ARG &b, &r); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = b; + libj2_j2i_sub_j2i_to_j2i(CONST_ARG &a, CONST_ARG &r, &r); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_j2i_sub_j2i_to_j2i(CONST_ARG &r, CONST_ARG &r, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + EXPECT(libj2_j2i_sub_j2i_overflow_p(CONST_ARG &a, CONST_ARG &b) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + EXPECT(libj2_j2i_sub_j2i_overflow_p(CONST_ARG &a, CONST_ARG &a) == 0); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + r = a; + EXPECT(libj2_j2i_sub_j2i_overflow(&r, CONST_ARG &b) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + EXPECT(libj2_j2i_sub_j2i_overflow(&r, CONST_ARG &r) == 0); + EXPECT(libj2_j2i_is_zero(&r)); + + r = a; + libj2_j2i_sub_j2i(&r, CONST_ARG &b); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_j2i_sub_j2i(&r, CONST_ARG &r); + EXPECT(libj2_j2i_is_zero(&r)); + + EXPECT(libj2_j2i_rsub_j2i_overflow_p(&b, CONST_ARG &a) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + EXPECT(libj2_j2i_rsub_j2i_overflow_p(&a, CONST_ARG &a) == 0); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&b, &b_saved)); + + r = b; + EXPECT(libj2_j2i_rsub_j2i_overflow(&r, CONST_ARG &a) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + EXPECT(libj2_j2i_rsub_j2i_overflow(&r, CONST_ARG &r) == 0); + EXPECT(libj2_j2i_is_zero(&r)); + + r = b; + libj2_j2i_rsub_j2i(&r, CONST_ARG &a); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_j2i_rsub_j2i(&r, CONST_ARG &r); + EXPECT(libj2_j2i_is_zero(&r)); +} + + +int +main(void) +{ + uintmax_t a, b, c, d, max, min, umax, vs[12]; + unsigned i, ii, iii, iv, k, j; + + srand((unsigned)time(NULL)); + + umax = UINTMAX_MAX; + max = umax >> 1; + min = ~max; + + vs[0] = 0U; + vs[1] = 1U; + vs[2] = 2U; + vs[3] = umax - 0U; + vs[4] = umax - 1U; + vs[5] = umax - 2U; + vs[6] = max - 0U; + vs[7] = max - 1U; + vs[8] = max - 2U; + vs[9] = min + 0U; + vs[10] = min + 1U; + vs[11] = min + 2U; + + for (j = 0; j < 128U; j++) { + for (k = 0; k < 16U; k++) { + a = random_ju() >> 1; + b = random_ju() >> 1; + c = random_ju() >> 1; + d = random_ju() >> 1; + if (k & 1U) a = ~a; + if (k & 2U) b = ~b; + if (k & 4U) c = ~c; + if (k & 8U) d = ~d; + check(a, b, c, d); + for (i = 0; k < 8U && i < 12U; i++) { + check(vs[i], a, b, c); + check(a, vs[i], b, c); + check(a, b, vs[i], c); + check(a, b, c, vs[i]); + for (ii = 0; k < 4U && ii < 12U; ii++) { + check(vs[i], vs[ii], a, b); + check(vs[i], a, vs[ii], b); + check(vs[i], a, b, vs[ii]); + check(a, vs[i], vs[ii], b); + check(a, vs[i], b, vs[ii]); + check(a, b, vs[i], vs[ii]); + for (iii = 0; k < 2U && iii < 12U; iii++) { + check(vs[i], vs[ii], vs[iii], a); + check(vs[i], vs[ii], a, vs[iii]); + check(vs[i], a, vs[ii], vs[iii]); + check(a, vs[i], vs[ii], vs[iii]); + for (iv = 0; !j && k < 1U && iv < 12U; iv++) + check(vs[i], vs[ii], vs[iii], vs[iv]); + } + } + } + } + } + + return 0; +} + +#endif diff --git a/libj2_j2i_sub_j2i_overflow.c b/libj2_j2i_sub_j2i_overflow.c new file mode 100644 index 0000000..17275f2 --- /dev/null +++ b/libj2_j2i_sub_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_sub_j2i_overflow(struct libj2_j2i *a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_sub_j2i.c */ + +#endif diff --git a/libj2_j2i_sub_j2i_overflow_p.c b/libj2_j2i_sub_j2i_overflow_p.c new file mode 100644 index 0000000..0df616b --- /dev/null +++ b/libj2_j2i_sub_j2i_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_sub_j2i_overflow_p(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_sub_j2i.c */ + +#endif diff --git a/libj2_j2i_sub_j2i_to_j2i.c b/libj2_j2i_sub_j2i_to_j2i.c new file mode 100644 index 0000000..5522262 --- /dev/null +++ b/libj2_j2i_sub_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_sub_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_sub_j2i.c */ + +#endif diff --git a/libj2_j2i_sub_j2i_to_j2i_overflow.c b/libj2_j2i_sub_j2i_to_j2i_overflow.c new file mode 100644 index 0000000..db703c9 --- /dev/null +++ b/libj2_j2i_sub_j2i_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_sub_j2i_to_j2i_overflow(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_sub_j2i.c */ + +#endif diff --git a/libj2_j2i_sub_ji.c b/libj2_j2i_sub_ji.c new file mode 100644 index 0000000..27bf013 --- /dev/null +++ b/libj2_j2i_sub_ji.c @@ -0,0 +1,213 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_j2i_sub_ji(struct libj2_j2i *a, intmax_t b); +/* 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 +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_j2i t, r; + + t = (struct libj2_j2i){.high = a_high, .low = a_low}; + if ((a_neg = libj2_j2i_is_negative(&t))) + libj2_minus_j2i_to_j2u(&t, &a); + else + libj2_j2i_to_j2u(&t, &a); + + t = (struct libj2_j2i){.high = b_high, .low = b_low}; + if ((b_neg = libj2_j2i_is_negative(&t))) + libj2_minus_j2i_to_j2u(&t, &b); + else + libj2_j2i_to_j2u(&t, &b); + + 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)); + } else if (a_neg) { + overflow = -libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, (void *)&r); + EXPECT(overflow == 0 || overflow == -1); + libj2_minus_j2i(&r); + if (!libj2_j2i_is_negative(&r)) + overflow = -1; + else if (overflow) + EXPECT(libj2_j2i_gt_j2i(&r, (const void *)&a)); + if (!overflow) + EXPECT(libj2_j2i_le_j2i(&r, (const void *)&a)); + } else if (b_neg) { + overflow = +libj2_j2u_add_j2u_to_j2u_overflow(&a, &b, (void *)&r); + EXPECT(overflow == 0 || overflow == +1); + if (!libj2_j2i_is_positive(&r)) + overflow = +1; + else if (overflow) + EXPECT(libj2_j2i_lt_j2i(&r, (const void *)&a)); + if (!overflow) + EXPECT(libj2_j2i_gt_j2i(&r, (const void *)&a)); + } else { + overflow = 0; + libj2_minus_j2u(&b); + libj2_j2u_add_j2u_to_j2u(&a, &b, (void *)&r); + EXPECT(libj2_j2i_le_j2u(&r, &a)); + } + + EXPECT(r.high == r_high); + EXPECT(r.low == r_low); + EXPECT(overflow == r_overflow); +} + + +static void +check(uintmax_t a_high, uintmax_t a_low, uintmax_t ub) +{ + intmax_t b = ub >> (LIBJ2_JU_BIT - 1U) ? -(intmax_t)~ub - 1 : (intmax_t)ub; + struct libj2_j2i a, a_saved, r, expected; + int expected_overflow; + +#if INTMAX_MIN + 1 != -INTMAX_MAX + if (ub == (UINTMAX >> 1) + 1U) + return; +#endif + + a.high = a_high; + a.low = a_low; + a_saved = a; + expected = (struct libj2_j2i){111, 222}; + expected_overflow = libj2_j2i_sub_ji_to_j2i_overflow((const struct libj2_j2i *)&a, b, &expected); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_ne_j2i(&expected, &(struct libj2_j2i){111, 222})); + + validate(a.high, a.low, b < 0 ? UINTMAX_MAX : 0U, ub, expected.high, expected.low, expected_overflow); + + r = (struct libj2_j2i){111, 222}; + libj2_j2i_sub_ji_to_j2i((const struct libj2_j2i *)&a, b, &r); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_j2i_sub_ji_to_j2i((const struct libj2_j2i *)&r, b, &r); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + a_saved = a; + EXPECT(libj2_j2i_sub_ji_overflow_p((const struct libj2_j2i *)&a, b) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + + r = a; + EXPECT(libj2_j2i_sub_ji_overflow(&r, b) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_j2i_sub_ji(&r, b); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + libj2_minus_j2i(&expected); + + a = a_saved; + r = (struct libj2_j2i){111, 222}; + expected_overflow = libj2_ji_sub_j2i_to_j2i_overflow(b, (const struct libj2_j2i *)&a, &r); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + validate(b < 0 ? UINTMAX_MAX : 0U, ub, a.high, a.low, expected.high, expected.low, expected_overflow); + + EXPECT(libj2_ji_sub_j2i_overflow_p(b, (const struct libj2_j2i *)&a) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_sub_j2i_to_j2i(b, (const struct libj2_j2i *)&a, &r); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + libj2_ji_sub_j2i_to_j2i(b, (const struct libj2_j2i *)&r, &r); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + EXPECT(libj2_ji_sub_j2i_to_j2i_overflow(b, (const struct libj2_j2i *)&r, &r) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + r = a; + EXPECT(libj2_j2i_rsub_ji_overflow(&r, b) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + EXPECT(libj2_j2i_rsub_ji_overflow_p((const struct libj2_j2i *)&a, b) == expected_overflow); + EXPECT(libj2_j2i_eq_j2i(&a, &a_saved)); + + r = a; + libj2_j2i_rsub_ji(&r, b); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); +} + + +int +main(void) +{ + uintmax_t a, b, c, max, min, umax, vs[12]; + unsigned i, ii, iii, k, j; + + srand((unsigned)time(NULL)); + + umax = UINTMAX_MAX; + max = umax >> 1; + min = ~max; + + vs[0] = 0U; + vs[1] = 1U; + vs[2] = 2U; + vs[3] = umax - 0U; + vs[4] = umax - 1U; + vs[5] = umax - 2U; + vs[6] = max - 0U; + vs[7] = max - 1U; + vs[8] = max - 2U; + vs[9] = min + 0U; + vs[10] = min + 1U; + vs[11] = min + 2U; + + for (j = 0; j < 128U; j++) { + for (k = 0; k < 8U; k++) { + a = random_ju() >> 1; + b = random_ju() >> 1; + c = random_ju() >> 1; + if (k & 1U) a = ~a; + if (k & 2U) b = ~b; + if (k & 4U) c = ~c; + check(a, b, c); + for (i = 0; k < 4U && i < 12U; i++) { + check(a, b, vs[i]); + check(a, vs[i], b); + check(vs[i], a, b); + for (ii = 0; k < 2U && ii < 12U; ii++) { + check(vs[i], vs[ii], a); + check(vs[i], a, vs[ii]); + check(a, vs[i], vs[ii]); + for (iii = 0; !j && k < 1U && iii < 12U; iii++) + check(vs[i], vs[ii], vs[iii]); + } + } + } + } + + return 0; +} + +#endif diff --git a/libj2_j2i_sub_ji_overflow.c b/libj2_j2i_sub_ji_overflow.c new file mode 100644 index 0000000..d8201be --- /dev/null +++ b/libj2_j2i_sub_ji_overflow.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline int libj2_j2i_sub_ji_overflow(struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_sub_ji.c */ + +#endif diff --git a/libj2_j2i_sub_ji_overflow_p.c b/libj2_j2i_sub_ji_overflow_p.c new file mode 100644 index 0000000..1c07791 --- /dev/null +++ b/libj2_j2i_sub_ji_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_sub_ji_overflow_p(const struct libj2_j2i *a, intmax_t b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_sub_ji.c */ + +#endif diff --git a/libj2_j2i_sub_ji_to_j2i.c b/libj2_j2i_sub_ji_to_j2i.c new file mode 100644 index 0000000..4c06968 --- /dev/null +++ b/libj2_j2i_sub_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_sub_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_sub_ji.c */ + +#endif diff --git a/libj2_j2i_sub_ji_to_j2i_overflow.c b/libj2_j2i_sub_ji_to_j2i_overflow.c new file mode 100644 index 0000000..52b2d2f --- /dev/null +++ b/libj2_j2i_sub_ji_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_sub_ji_to_j2i_overflow(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_sub_ji.c */ + +#endif diff --git a/libj2_j2u_cmp_j2i.3 b/libj2_j2u_cmp_j2i.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_j2u_cmp_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_cmp_j2i.c b/libj2_j2u_cmp_j2i.c index 2ba1475..10c4d65 100644 --- a/libj2_j2u_cmp_j2i.c +++ b/libj2_j2u_cmp_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_cmp_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_cmp_j2u.3 b/libj2_j2u_cmp_j2u.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_j2u_cmp_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_cmp_j2u.c b/libj2_j2u_cmp_j2u.c index d096c33..ab780be 100644 --- a/libj2_j2u_cmp_j2u.c +++ b/libj2_j2u_cmp_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_cmp_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_cmp_ji.3 b/libj2_j2u_cmp_ji.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_j2u_cmp_ji.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_cmp_ji.c b/libj2_j2u_cmp_ji.c index e851830..c8afe64 100644 --- a/libj2_j2u_cmp_ji.c +++ b/libj2_j2u_cmp_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_cmp_ji(const struct libj2_j2u *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_cmp_ju.3 b/libj2_j2u_cmp_ju.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_j2u_cmp_ju.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_cmp_ju.c b/libj2_j2u_cmp_ju.c index d64d5ce..5832408 100644 --- a/libj2_j2u_cmp_ju.c +++ b/libj2_j2u_cmp_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_cmp_ju(const struct libj2_j2u *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_eq_j2i.3 b/libj2_j2u_eq_j2i.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_j2u_eq_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_eq_j2i.c b/libj2_j2u_eq_j2i.c index 95369c2..92e2106 100644 --- a/libj2_j2u_eq_j2i.c +++ b/libj2_j2u_eq_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_eq_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_eq_j2u.3 b/libj2_j2u_eq_j2u.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_j2u_eq_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_eq_j2u.c b/libj2_j2u_eq_j2u.c index 847f942..f527c18 100644 --- a/libj2_j2u_eq_j2u.c +++ b/libj2_j2u_eq_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_eq_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_eq_ji.3 b/libj2_j2u_eq_ji.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_j2u_eq_ji.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_eq_ji.c b/libj2_j2u_eq_ji.c index 4a794ee..ebb1484 100644 --- a/libj2_j2u_eq_ji.c +++ b/libj2_j2u_eq_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_eq_ji(const struct libj2_j2u *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_eq_ju.3 b/libj2_j2u_eq_ju.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_j2u_eq_ju.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_eq_ju.c b/libj2_j2u_eq_ju.c index 9012baa..e45a885 100644 --- a/libj2_j2u_eq_ju.c +++ b/libj2_j2u_eq_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_eq_ju(const struct libj2_j2u *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_ge_j2i.3 b/libj2_j2u_ge_j2i.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_j2u_ge_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_ge_j2i.c b/libj2_j2u_ge_j2i.c index adcaee9..bb9f313 100644 --- a/libj2_j2u_ge_j2i.c +++ b/libj2_j2u_ge_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_ge_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_ge_j2u.3 b/libj2_j2u_ge_j2u.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_j2u_ge_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_ge_j2u.c b/libj2_j2u_ge_j2u.c index 031b7dd..534a34a 100644 --- a/libj2_j2u_ge_j2u.c +++ b/libj2_j2u_ge_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_ge_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_ge_ji.3 b/libj2_j2u_ge_ji.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_j2u_ge_ji.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_ge_ji.c b/libj2_j2u_ge_ji.c index aef8ee7..f463a27 100644 --- a/libj2_j2u_ge_ji.c +++ b/libj2_j2u_ge_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_ge_ji(const struct libj2_j2u *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_ge_ju.3 b/libj2_j2u_ge_ju.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_j2u_ge_ju.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_ge_ju.c b/libj2_j2u_ge_ju.c index a348fa6..8acdd04 100644 --- a/libj2_j2u_ge_ju.c +++ b/libj2_j2u_ge_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_ge_ju(const struct libj2_j2u *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_gt_j2i.3 b/libj2_j2u_gt_j2i.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_j2u_gt_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_gt_j2i.c b/libj2_j2u_gt_j2i.c index 757f71b..01d9b39 100644 --- a/libj2_j2u_gt_j2i.c +++ b/libj2_j2u_gt_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_gt_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_gt_j2u.3 b/libj2_j2u_gt_j2u.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_j2u_gt_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_gt_j2u.c b/libj2_j2u_gt_j2u.c index bd4da14..7647b1a 100644 --- a/libj2_j2u_gt_j2u.c +++ b/libj2_j2u_gt_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_gt_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_gt_ji.3 b/libj2_j2u_gt_ji.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_j2u_gt_ji.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_gt_ji.c b/libj2_j2u_gt_ji.c index a3ae3ec..62beb9b 100644 --- a/libj2_j2u_gt_ji.c +++ b/libj2_j2u_gt_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_gt_ji(const struct libj2_j2u *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_gt_ju.3 b/libj2_j2u_gt_ju.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_j2u_gt_ju.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_gt_ju.c b/libj2_j2u_gt_ju.c index e7947d0..a750754 100644 --- a/libj2_j2u_gt_ju.c +++ b/libj2_j2u_gt_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_gt_ju(const struct libj2_j2u *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_le_j2i.3 b/libj2_j2u_le_j2i.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_j2u_le_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_le_j2i.c b/libj2_j2u_le_j2i.c index 8bfb213..bf202a5 100644 --- a/libj2_j2u_le_j2i.c +++ b/libj2_j2u_le_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_le_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_le_j2u.3 b/libj2_j2u_le_j2u.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_j2u_le_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_le_j2u.c b/libj2_j2u_le_j2u.c index 9403271..87b3dfa 100644 --- a/libj2_j2u_le_j2u.c +++ b/libj2_j2u_le_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_le_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_le_ji.3 b/libj2_j2u_le_ji.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_j2u_le_ji.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_le_ji.c b/libj2_j2u_le_ji.c index 96546e1..e78a2f2 100644 --- a/libj2_j2u_le_ji.c +++ b/libj2_j2u_le_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_le_ji(const struct libj2_j2u *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_le_ju.3 b/libj2_j2u_le_ju.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_j2u_le_ju.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_le_ju.c b/libj2_j2u_le_ju.c index a55bfff..b614ac4 100644 --- a/libj2_j2u_le_ju.c +++ b/libj2_j2u_le_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_le_ju(const struct libj2_j2u *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_lt_j2i.3 b/libj2_j2u_lt_j2i.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_j2u_lt_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_lt_j2i.c b/libj2_j2u_lt_j2i.c index 0fcf201..3711e55 100644 --- a/libj2_j2u_lt_j2i.c +++ b/libj2_j2u_lt_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_lt_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_lt_j2u.3 b/libj2_j2u_lt_j2u.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_j2u_lt_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_lt_j2u.c b/libj2_j2u_lt_j2u.c index 3dddb5e..4c1304b 100644 --- a/libj2_j2u_lt_j2u.c +++ b/libj2_j2u_lt_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_lt_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_lt_ji.3 b/libj2_j2u_lt_ji.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_j2u_lt_ji.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_lt_ji.c b/libj2_j2u_lt_ji.c index b4b4f64..38eb435 100644 --- a/libj2_j2u_lt_ji.c +++ b/libj2_j2u_lt_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_lt_ji(const struct libj2_j2u *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_lt_ju.3 b/libj2_j2u_lt_ju.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_j2u_lt_ju.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_lt_ju.c b/libj2_j2u_lt_ju.c index e467f58..02c5566 100644 --- a/libj2_j2u_lt_ju.c +++ b/libj2_j2u_lt_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_lt_ju(const struct libj2_j2u *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_ne_j2i.3 b/libj2_j2u_ne_j2i.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_j2u_ne_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_ne_j2i.c b/libj2_j2u_ne_j2i.c index 462862e..8894e83 100644 --- a/libj2_j2u_ne_j2i.c +++ b/libj2_j2u_ne_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_ne_j2i(const struct libj2_j2u *a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_ne_j2u.3 b/libj2_j2u_ne_j2u.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_j2u_ne_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_ne_j2u.c b/libj2_j2u_ne_j2u.c index 539d481..6a6d125 100644 --- a/libj2_j2u_ne_j2u.c +++ b/libj2_j2u_ne_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_ne_j2u(const struct libj2_j2u *a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_ne_ji.3 b/libj2_j2u_ne_ji.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_j2u_ne_ji.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_ne_ji.c b/libj2_j2u_ne_ji.c index 3b56e07..09b1308 100644 --- a/libj2_j2u_ne_ji.c +++ b/libj2_j2u_ne_ji.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_ne_ji(const struct libj2_j2u *a, intmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_j2u_ne_ju.3 b/libj2_j2u_ne_ju.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_j2u_ne_ju.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_j2u_ne_ju.c b/libj2_j2u_ne_ju.c index 128f3f6..30cc88f 100644 --- a/libj2_j2u_ne_ju.c +++ b/libj2_j2u_ne_ju.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_j2u_ne_ju(const struct libj2_j2u *a, uintmax_t b); -/* TODO Add man page */ #else diff --git a/libj2_ji_add_j2i_overflow_p.c b/libj2_ji_add_j2i_overflow_p.c new file mode 100644 index 0000000..82ccd0a --- /dev/null +++ b/libj2_ji_add_j2i_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_add_j2i_overflow_p(intmax_t a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Test in libj2_j2i_add_ji.c */ + +#endif diff --git a/libj2_ji_add_j2i_to_j2i.c b/libj2_ji_add_j2i_to_j2i.c new file mode 100644 index 0000000..dafa114 --- /dev/null +++ b/libj2_ji_add_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_ji_add_j2i_to_j2i(intmax_t 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_add_ji.c */ + +#endif diff --git a/libj2_ji_add_j2i_to_j2i_overflow.c b/libj2_ji_add_j2i_to_j2i_overflow.c new file mode 100644 index 0000000..bbdbd95 --- /dev/null +++ b/libj2_ji_add_j2i_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_add_j2i_to_j2i_overflow(intmax_t 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_add_ji.c */ + +#endif diff --git a/libj2_ji_add_ji_to_j2i.c b/libj2_ji_add_ji_to_j2i.c new file mode 100644 index 0000000..08bf2e1 --- /dev/null +++ b/libj2_ji_add_ji_to_j2i.c @@ -0,0 +1,153 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_ji_add_ji_to_j2i(intmax_t a, intmax_t b, struct libj2_j2i *res); +/* TODO Add man page */ + + +#else + +static intmax_t +random_ji(void) +{ + size_t n = LIBJ2_JU_BIT - 1U; + intmax_t r = 0; + while (n--) + if (rand() < rand()) + r |= (intmax_t)1 << n; + if (rand() < rand()) { + r = -r; +#if INTMAX_MIN + 1 == -INTMAX_MAX + r -= 1; +#endif + } + return r; +} + + +static void +get_expected(intmax_t a, intmax_t b, uintmax_t *expected_high, uintmax_t *expected_low) +{ + uintmax_t pos, neg; + if (a >= 0 && b >= 0) { + *expected_high = 0; + *expected_low = (uintmax_t)a + (uintmax_t)b; + } else if (a <= 0 && b <= 0) { + *expected_high = UINTMAX_MAX; + *expected_low = (uintmax_t)a + (uintmax_t)b; + } else if (a < 0) { + pos = (uintmax_t)b; + neg = (uintmax_t)-(a + 1) + 1U; + goto pos_neg; + } else { + pos = (uintmax_t)a; + neg = (uintmax_t)-(b + 1) + 1U; + pos_neg: + if (pos >= neg) + *expected_high = 0; + else + *expected_high = UINTMAX_MAX; + *expected_low = pos - neg; + } +} + + +static void +check(intmax_t a, intmax_t b) +{ + struct libj2_j2i r; + uintmax_t expected_high, expected_low; + + get_expected(a, b, &expected_high, &expected_low); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_add_ji_to_j2i(a, b, &r); + EXPECT(r.high == expected_high); + EXPECT(r.low == expected_low); + +#if INTMAX_MIN + 1 == -INTMAX_MAX + if (a == INTMAX_MIN || b == INTMAX_MIN) + return; +#endif + + r = (struct libj2_j2i){111, 222}; + libj2_ji_add_ji_to_j2i(-a, -b, &r); + libj2_minus_j2i(&r); + EXPECT(r.high == expected_high); + EXPECT(r.low == expected_low); +} + + +static void +check_manual(intmax_t a, intmax_t b, uintmax_t expected_high, uintmax_t expected_low) +{ + struct libj2_j2i r; + + r = (struct libj2_j2i){111, 222}; + libj2_ji_add_ji_to_j2i(a, b, &r); + EXPECT(r.high == expected_high); + EXPECT(r.low == expected_low); + +#if INTMAX_MIN + 1 == -INTMAX_MAX + if (a == INTMAX_MIN || b == INTMAX_MIN) + goto check; +#endif + + r = (struct libj2_j2i){111, 222}; + libj2_ji_add_ji_to_j2i(-a, -b, &r); + libj2_minus_j2i(&r); + EXPECT(r.high == expected_high); + EXPECT(r.low == expected_low); + +check: + check(a, b); +} + + +int +main(void) +{ + unsigned i; + + srand((unsigned)time(NULL)); + + check_manual(0, 0, 0, 0); + check_manual(0, INTMAX_MAX, 0, (uintmax_t)INTMAX_MAX); + check_manual(INTMAX_MAX, 0, 0, (uintmax_t)INTMAX_MAX); + check_manual(INTMAX_MAX, 1, 0, UINTMAX_MAX ^ (UINTMAX_MAX >> 1)); + check_manual(1, INTMAX_MAX, 0, UINTMAX_MAX ^ (UINTMAX_MAX >> 1)); + check_manual(INTMAX_MAX, INTMAX_MAX, 0, (uintmax_t)INTMAX_MAX << 1); + + check_manual(0, -INTMAX_MAX, UINTMAX_MAX, (UINTMAX_MAX ^ (UINTMAX_MAX >> 1)) + 1U); + check_manual(-INTMAX_MAX, 0, UINTMAX_MAX, (UINTMAX_MAX ^ (UINTMAX_MAX >> 1)) + 1U); + check_manual(INTMAX_MAX, -1, 0, (uintmax_t)INTMAX_MAX - 1U); + check_manual(-1, INTMAX_MAX, 0, (uintmax_t)INTMAX_MAX - 1U); + check_manual(-INTMAX_MAX, 1, UINTMAX_MAX, (UINTMAX_MAX ^ (UINTMAX_MAX >> 1)) + 2U); + check_manual(1, -INTMAX_MAX, UINTMAX_MAX, (UINTMAX_MAX ^ (UINTMAX_MAX >> 1)) + 2U); + check_manual(INTMAX_MAX, -INTMAX_MAX, 0, 0); + +#if INTMAX_MIN + 1 == -INTMAX_MAX + check_manual(0, INTMAX_MIN, UINTMAX_MAX, UINTMAX_MAX ^ (UINTMAX_MAX >> 1)); + check_manual(INTMAX_MIN, 0, UINTMAX_MAX, UINTMAX_MAX ^ (UINTMAX_MAX >> 1)); + check_manual(INTMAX_MIN, 1, UINTMAX_MAX, (UINTMAX_MAX ^ (UINTMAX_MAX >> 1)) + 1U); + check_manual(1, INTMAX_MIN, UINTMAX_MAX, (UINTMAX_MAX ^ (UINTMAX_MAX >> 1)) + 1U); + check_manual(INTMAX_MIN, INTMAX_MAX, UINTMAX_MAX, UINTMAX_MAX); + check_manual(INTMAX_MIN, -INTMAX_MAX, UINTMAX_MAX, 1); + check_manual(INTMAX_MIN, INTMAX_MIN, UINTMAX_MAX, 0); +#endif + + for (i = 0; i < 256; i++) { + check(0, random_ji()); + check(1, random_ji()); + check(random_ji(), 0); + check(random_ji(), 1); + check(random_ji(), random_ji()); + check(random_ji(), INTMAX_MAX); + check(INTMAX_MAX, random_ji()); + } + + return 0; +} + +#endif diff --git a/libj2_ji_cmp_j2i.3 b/libj2_ji_cmp_j2i.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_ji_cmp_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_ji_cmp_j2i.c b/libj2_ji_cmp_j2i.c index ff006b1..93ca067 100644 --- a/libj2_ji_cmp_j2i.c +++ b/libj2_ji_cmp_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_cmp_j2i(intmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_cmp_j2u.3 b/libj2_ji_cmp_j2u.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_ji_cmp_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_ji_cmp_j2u.c b/libj2_ji_cmp_j2u.c index 11a8d0d..052c6c1 100644 --- a/libj2_ji_cmp_j2u.c +++ b/libj2_ji_cmp_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_cmp_j2u(intmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_eq_j2i.3 b/libj2_ji_eq_j2i.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_ji_eq_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_ji_eq_j2i.c b/libj2_ji_eq_j2i.c index 4c7d0b1..e5f270f 100644 --- a/libj2_ji_eq_j2i.c +++ b/libj2_ji_eq_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_eq_j2i(intmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_eq_j2u.3 b/libj2_ji_eq_j2u.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_ji_eq_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_ji_eq_j2u.c b/libj2_ji_eq_j2u.c index e38bed3..ebc4598 100644 --- a/libj2_ji_eq_j2u.c +++ b/libj2_ji_eq_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_eq_j2u(intmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_ge_j2i.3 b/libj2_ji_ge_j2i.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_ji_ge_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_ji_ge_j2i.c b/libj2_ji_ge_j2i.c index b2d2104..c3797bd 100644 --- a/libj2_ji_ge_j2i.c +++ b/libj2_ji_ge_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_ge_j2i(intmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_ge_j2u.3 b/libj2_ji_ge_j2u.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_ji_ge_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_ji_ge_j2u.c b/libj2_ji_ge_j2u.c index e4d38c5..4a8399b 100644 --- a/libj2_ji_ge_j2u.c +++ b/libj2_ji_ge_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_ge_j2u(intmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_gt_j2i.3 b/libj2_ji_gt_j2i.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_ji_gt_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_ji_gt_j2i.c b/libj2_ji_gt_j2i.c index 2b982ca..19ec236 100644 --- a/libj2_ji_gt_j2i.c +++ b/libj2_ji_gt_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_gt_j2i(intmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_gt_j2u.3 b/libj2_ji_gt_j2u.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_ji_gt_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_ji_gt_j2u.c b/libj2_ji_gt_j2u.c index 6ed0474..b5c572a 100644 --- a/libj2_ji_gt_j2u.c +++ b/libj2_ji_gt_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_gt_j2u(intmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_le_j2i.3 b/libj2_ji_le_j2i.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_ji_le_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_ji_le_j2i.c b/libj2_ji_le_j2i.c index 653b6f8..43efec0 100644 --- a/libj2_ji_le_j2i.c +++ b/libj2_ji_le_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_le_j2i(intmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_le_j2u.3 b/libj2_ji_le_j2u.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_ji_le_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_ji_le_j2u.c b/libj2_ji_le_j2u.c index f765f80..c0d5ec1 100644 --- a/libj2_ji_le_j2u.c +++ b/libj2_ji_le_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_le_j2u(intmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_lt_j2i.3 b/libj2_ji_lt_j2i.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_ji_lt_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_ji_lt_j2i.c b/libj2_ji_lt_j2i.c index 2a4397b..4709d8e 100644 --- a/libj2_ji_lt_j2i.c +++ b/libj2_ji_lt_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_lt_j2i(intmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_lt_j2u.3 b/libj2_ji_lt_j2u.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_ji_lt_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_ji_lt_j2u.c b/libj2_ji_lt_j2u.c index 0a6096d..f874bf5 100644 --- a/libj2_ji_lt_j2u.c +++ b/libj2_ji_lt_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_lt_j2u(intmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_mul_j2i_overflow_p.c b/libj2_ji_mul_j2i_overflow_p.c new file mode 100644 index 0000000..07dec59 --- /dev/null +++ b/libj2_ji_mul_j2i_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_mul_j2i_overflow_p(intmax_t a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_mul_ji.c */ + +#endif diff --git a/libj2_ji_mul_j2i_overflow_p_quick.c b/libj2_ji_mul_j2i_overflow_p_quick.c new file mode 100644 index 0000000..84e4c35 --- /dev/null +++ b/libj2_ji_mul_j2i_overflow_p_quick.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline enum libj2_overflow libj2_ji_mul_j2i_overflow_p_quick(intmax_t a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_mul_ji.c */ + +#endif diff --git a/libj2_ji_mul_j2i_to_j2i.c b/libj2_ji_mul_j2i_to_j2i.c new file mode 100644 index 0000000..6fba771 --- /dev/null +++ b/libj2_ji_mul_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_ji_mul_j2i_to_j2i(intmax_t 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_mul_ji.c */ + +#endif diff --git a/libj2_ji_mul_j2i_to_j2i_overflow.c b/libj2_ji_mul_j2i_to_j2i_overflow.c new file mode 100644 index 0000000..3288e54 --- /dev/null +++ b/libj2_ji_mul_j2i_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_mul_j2i_to_j2i_overflow(intmax_t 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_mul_ji.c */ + +#endif diff --git a/libj2_ji_mul_j2i_to_j2i_overflow_p.c b/libj2_ji_mul_j2i_to_j2i_overflow_p.c new file mode 100644 index 0000000..2b02413 --- /dev/null +++ b/libj2_ji_mul_j2i_to_j2i_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_mul_j2i_to_j2i_overflow_p(intmax_t a, const struct libj2_j2i *b, struct libj2_j2i *res, int *res_set); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_mul_ji.c */ + +#endif diff --git a/libj2_ji_mul_ji_to_j2i.c b/libj2_ji_mul_ji_to_j2i.c new file mode 100644 index 0000000..ada66cc --- /dev/null +++ b/libj2_ji_mul_ji_to_j2i.c @@ -0,0 +1,221 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_ji_mul_ji_to_j2i(intmax_t a, intmax_t b, struct libj2_j2i *res); +/* TODO Add man page */ + + +#else + +static uintmax_t +random_small_ju(size_t bits) +{ + uintmax_t r = 0; + while (bits--) + if (rand() < rand()) + r |= (uintmax_t)1 << bits; + return r; +} + +static uintmax_t +random_hju(void) +{ + return random_small_ju(LIBJ2_JU_BIT / 2U); +} + +static uintmax_t +random_ju(void) +{ + return random_small_ju(LIBJ2_JU_BIT); +} + +static intmax_t +random_ji(void) +{ + uintmax_t u; + u = random_small_ju(LIBJ2_JU_BIT); + if (u >> (LIBJ2_JU_BIT - 1U)) + return (intmax_t)u; + return (intmax_t)~u - 1; +} + + +static void +mul(intmax_t a, intmax_t b, struct libj2_j2i *expected) +{ + int neg = (a < 0) ^ (b < 0); + uintmax_t u = a < 0 ? (uintmax_t)-(a + 1U) + 1U : (uintmax_t)a; + uintmax_t v = b < 0 ? (uintmax_t)-(b + 1U) + 1U : (uintmax_t)b; + struct libj2_j2u c; + libj2_ju_mul_ju_to_j2u(u, v, &c); + libj2_j2u_to_j2i(&c, expected); + if (neg) + libj2_minus_j2i(expected); +} + + +int +main(void) +{ + struct libj2_j2i r, expected; + intmax_t u, v; + unsigned i; + + srand((unsigned)time(NULL)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(0, 0, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(0, 1, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(0, -1, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(0, INTMAX_MAX, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(0, -INTMAX_MAX, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(0, INTMAX_MIN, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(1, 0, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(-1, 0, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(INTMAX_MAX, 0, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(-INTMAX_MAX, 0, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(INTMAX_MIN, 0, &r); + EXPECT(libj2_j2i_is_zero(&r)); + + for (i = 0; i < 32; i++) { + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(0, random_ji(), &r); + EXPECT(libj2_j2i_is_zero(&r)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(random_ji(), 0, &r); + EXPECT(libj2_j2i_is_zero(&r)); + } + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(1, 1, &r); + EXPECT(r.high == 0); + EXPECT(r.low == 1); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(4, 4, &r); + EXPECT(r.high == 0); + EXPECT(r.low == 16); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(2, 3, &r); + EXPECT(libj2_j2i_eq_ji(&r, 6)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(2, -3, &r); + EXPECT(libj2_j2i_eq_ji(&r, -6)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(-2, 3, &r); + EXPECT(libj2_j2i_eq_ji(&r, -6)); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(-2, -3, &r); + EXPECT(libj2_j2i_eq_ji(&r, 6)); + + for (i = 0; i < 32; i++) { + r = (struct libj2_j2i){111, 222}; + v = (intmax_t)(random_ju() >> 1); + libj2_ji_mul_ji_to_j2i(1, v, &r); + EXPECT(r.high == 0); + EXPECT(r.low == (uintmax_t)v); + + r = (struct libj2_j2i){111, 222}; + v = (intmax_t)(random_ju() >> 1); + libj2_ji_mul_ji_to_j2i(v, 1, &r); + EXPECT(r.high == 0); + EXPECT(r.low == (uintmax_t)v); + } + + for (i = 0; i < 32; i++) { + u = (intmax_t)random_hju(); + v = (intmax_t)random_hju(); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(u, v, &r); + EXPECT(r.high == 0); + EXPECT(r.low == (uintmax_t)u * (uintmax_t)v); + + libj2_ji_mul_ji_to_j2i(v, u, &r); + EXPECT(r.high == 0); + EXPECT(r.low == (uintmax_t)u * (uintmax_t)v); + } + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(INTMAX_MAX, INTMAX_MAX, &r); + EXPECT(r.high == (uintmax_t)INTMAX_MAX >> 1); + EXPECT(r.low == 1); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(INTMAX_MAX, -INTMAX_MAX, &r); + libj2_minus_j2i(&r); + EXPECT(r.high == (uintmax_t)INTMAX_MAX >> 1); + EXPECT(r.low == 1); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(-INTMAX_MAX, INTMAX_MAX, &r); + libj2_minus_j2i(&r); + EXPECT(r.high == (uintmax_t)INTMAX_MAX >> 1); + EXPECT(r.low == 1); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(-INTMAX_MAX, -INTMAX_MAX, &r); + EXPECT(r.high == (uintmax_t)INTMAX_MAX >> 1); + EXPECT(r.low == 1); + +#if INTMAX_MIN + 1 == -INTMAX_MAX + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(INTMAX_MIN, INTMAX_MIN, &r); + EXPECT(r.high == ((uintmax_t)INTMAX_MAX + 1U) >> 1); + EXPECT(r.low == 0); +#endif + + for (i = 0; i < 256; i++) { + u = random_ji(); + v = random_ji(); + + mul(u, v, &expected); + + r = (struct libj2_j2i){111, 222}; + libj2_ji_mul_ji_to_j2i(u, v, &r); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + + libj2_ji_mul_ji_to_j2i(v, u, &r); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); + } + + return 0; +} + +#endif diff --git a/libj2_ji_ne_j2i.3 b/libj2_ji_ne_j2i.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_ji_ne_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_ji_ne_j2i.c b/libj2_ji_ne_j2i.c index 88087a4..fccd668 100644 --- a/libj2_ji_ne_j2i.c +++ b/libj2_ji_ne_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_ne_j2i(intmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_ne_j2u.3 b/libj2_ji_ne_j2u.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_ji_ne_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_ji_ne_j2u.c b/libj2_ji_ne_j2u.c index 4591c92..6391e7d 100644 --- a/libj2_ji_ne_j2u.c +++ b/libj2_ji_ne_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ji_ne_j2u(intmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ji_sub_j2i_overflow_p.c b/libj2_ji_sub_j2i_overflow_p.c new file mode 100644 index 0000000..afd2d4d --- /dev/null +++ b/libj2_ji_sub_j2i_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_sub_j2i_overflow_p(intmax_t a, const struct libj2_j2i *b); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested in libj2_j2i_sub_ji.c */ + +#endif diff --git a/libj2_ji_sub_j2i_to_j2i.c b/libj2_ji_sub_j2i_to_j2i.c new file mode 100644 index 0000000..d77aca3 --- /dev/null +++ b/libj2_ji_sub_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_ji_sub_j2i_to_j2i(intmax_t 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_sub_ji.c */ + +#endif diff --git a/libj2_ji_sub_j2i_to_j2i_overflow.c b/libj2_ji_sub_j2i_to_j2i_overflow.c new file mode 100644 index 0000000..ff8a3a4 --- /dev/null +++ b/libj2_ji_sub_j2i_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_sub_j2i_to_j2i_overflow(intmax_t a, const struct libj2_j2i *b, struct libj2_j2i *res); +/* TODO Add man page */ + + +#else + +CONST int main(void) { return 0; } /* Tested libj2_j2i_sub_ji.c */ + +#endif diff --git a/libj2_ji_sub_ji_to_j2i.c b/libj2_ji_sub_ji_to_j2i.c new file mode 100644 index 0000000..018c93c --- /dev/null +++ b/libj2_ji_sub_ji_to_j2i.c @@ -0,0 +1,94 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +extern inline void libj2_ji_sub_ji_to_j2i(intmax_t a, intmax_t b, struct libj2_j2i *res); +/* TODO Add man page */ + + +#else + +static uintmax_t +random_ju(void) +{ + size_t n = LIBJ2_JU_BIT; + uintmax_t r = 0; + while (n--) + if (rand() < rand()) + r |= (uintmax_t)1 << n; + return r; +} + + +static void +check(uintmax_t 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; + +#if INTMAX_MIN + 1 != -INTMAX_MAX + if (ua == (UINTMAX >> 1) + 1U || ub == (UINTMAX >> 1) + 1U) + return; +#endif + + wa.low = ua; + wb.low = ub; + + wa.high = a < 0 ? UINTMAX_MAX : 0; + wb.high = b < 0 ? UINTMAX_MAX : 0; + + libj2_minus_j2u(&wb); + libj2_j2u_add_j2u_to_j2u(&wa, &wb, (void *)&expected); + libj2_ji_sub_ji_to_j2i(a, b, &r); + EXPECT(libj2_j2i_eq_j2i(&r, &expected)); +} + + +int +main(void) +{ + uintmax_t a, b, max, min, umax, vs[12]; + unsigned i, j, k; + + srand((unsigned)time(NULL)); + + umax = UINTMAX_MAX; + max = umax >> 1; + min = ~max; + + vs[0] = 0U; + vs[1] = 1U; + vs[2] = 2U; + vs[3] = umax - 0U; + vs[4] = umax - 1U; + vs[5] = umax - 2U; + vs[6] = max - 0U; + vs[7] = max - 1U; + vs[8] = max - 2U; + vs[9] = min + 0U; + vs[10] = min + 1U; + vs[11] = min + 2U; + + for (i = 0; i < 12U; i++) + for (j = 0; j < 12U; j++) + check(vs[i], vs[j]); + for (j = 0; j < 256U; j++) { + for (k = 0; k < 4U; k++) { + a = random_ju() >> 1; + b = random_ju() >> 1; + if (k & 1U) a = ~a; + if (k & 2U) b = ~b; + check(a, b); + for (i = 0; k < 2U && i < 12U; i++) { + check(a, vs[i]); + check(vs[i], a); + } + } + } + + return 0; +} + +#endif diff --git a/libj2_ju_cmp_j2i.3 b/libj2_ju_cmp_j2i.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_ju_cmp_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_ju_cmp_j2i.c b/libj2_ju_cmp_j2i.c index 4ffbadf..93ba66d 100644 --- a/libj2_ju_cmp_j2i.c +++ b/libj2_ju_cmp_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_cmp_j2i(uintmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_cmp_j2u.3 b/libj2_ju_cmp_j2u.3 new file mode 120000 index 0000000..3e9997a --- /dev/null +++ b/libj2_ju_cmp_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_cmp_j2i.3
\ No newline at end of file diff --git a/libj2_ju_cmp_j2u.c b/libj2_ju_cmp_j2u.c index e97d9be..57f1be0 100644 --- a/libj2_ju_cmp_j2u.c +++ b/libj2_ju_cmp_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_cmp_j2u(uintmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_eq_j2i.3 b/libj2_ju_eq_j2i.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_ju_eq_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_ju_eq_j2i.c b/libj2_ju_eq_j2i.c index 4adfc55..bcdbf61 100644 --- a/libj2_ju_eq_j2i.c +++ b/libj2_ju_eq_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_eq_j2i(uintmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_eq_j2u.3 b/libj2_ju_eq_j2u.3 new file mode 120000 index 0000000..8b297dd --- /dev/null +++ b/libj2_ju_eq_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_eq_j2i.3
\ No newline at end of file diff --git a/libj2_ju_eq_j2u.c b/libj2_ju_eq_j2u.c index c13e1b0..aa4e9f9 100644 --- a/libj2_ju_eq_j2u.c +++ b/libj2_ju_eq_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_eq_j2u(uintmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_ge_j2i.3 b/libj2_ju_ge_j2i.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_ju_ge_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_ju_ge_j2i.c b/libj2_ju_ge_j2i.c index 25e2d95..c14eb3a 100644 --- a/libj2_ju_ge_j2i.c +++ b/libj2_ju_ge_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_ge_j2i(uintmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_ge_j2u.3 b/libj2_ju_ge_j2u.3 new file mode 120000 index 0000000..e67e404 --- /dev/null +++ b/libj2_ju_ge_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_ge_j2i.3
\ No newline at end of file diff --git a/libj2_ju_ge_j2u.c b/libj2_ju_ge_j2u.c index 0787166..7e82611 100644 --- a/libj2_ju_ge_j2u.c +++ b/libj2_ju_ge_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_ge_j2u(uintmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_gt_j2i.3 b/libj2_ju_gt_j2i.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_ju_gt_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_ju_gt_j2i.c b/libj2_ju_gt_j2i.c index a649307..17f0e2b 100644 --- a/libj2_ju_gt_j2i.c +++ b/libj2_ju_gt_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_gt_j2i(uintmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_gt_j2u.3 b/libj2_ju_gt_j2u.3 new file mode 120000 index 0000000..2f99f07 --- /dev/null +++ b/libj2_ju_gt_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_gt_j2i.3
\ No newline at end of file diff --git a/libj2_ju_gt_j2u.c b/libj2_ju_gt_j2u.c index a7a4a2d..c152053 100644 --- a/libj2_ju_gt_j2u.c +++ b/libj2_ju_gt_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_gt_j2u(uintmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_le_j2i.3 b/libj2_ju_le_j2i.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_ju_le_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_ju_le_j2i.c b/libj2_ju_le_j2i.c index 57665ae..55300c9 100644 --- a/libj2_ju_le_j2i.c +++ b/libj2_ju_le_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_le_j2i(uintmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_le_j2u.3 b/libj2_ju_le_j2u.3 new file mode 120000 index 0000000..98e4335 --- /dev/null +++ b/libj2_ju_le_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_le_j2i.3
\ No newline at end of file diff --git a/libj2_ju_le_j2u.c b/libj2_ju_le_j2u.c index 0e428c2..ceaee9e 100644 --- a/libj2_ju_le_j2u.c +++ b/libj2_ju_le_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_le_j2u(uintmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_lt_j2i.3 b/libj2_ju_lt_j2i.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_ju_lt_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_ju_lt_j2i.c b/libj2_ju_lt_j2i.c index fed9aa2..b23ce6b 100644 --- a/libj2_ju_lt_j2i.c +++ b/libj2_ju_lt_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_lt_j2i(uintmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_lt_j2u.3 b/libj2_ju_lt_j2u.3 new file mode 120000 index 0000000..3bfb749 --- /dev/null +++ b/libj2_ju_lt_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_lt_j2i.3
\ No newline at end of file diff --git a/libj2_ju_lt_j2u.c b/libj2_ju_lt_j2u.c index b9d88e2..5c53c66 100644 --- a/libj2_ju_lt_j2u.c +++ b/libj2_ju_lt_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_lt_j2u(uintmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_mul_ju_to_j2u.c b/libj2_ju_mul_ju_to_j2u.c index 11daad4..4a4faf7 100644 --- a/libj2_ju_mul_ju_to_j2u.c +++ b/libj2_ju_mul_ju_to_j2u.c @@ -129,6 +129,11 @@ main(void) EXPECT(r.high == UINTMAX_MAX - 1U); EXPECT(r.low == 1); + r = (struct libj2_j2u){111, 222}; + libj2_ju_mul_ju_to_j2u(UINTMAX_MAX >> 1, UINTMAX_MAX >> 1, &r); + EXPECT(r.high == UINTMAX_MAX >> 2); + EXPECT(r.low == 1); + for (i = 0; i < 256; i++) { u = random_ju(); v = random_ju(); diff --git a/libj2_ju_ne_j2i.3 b/libj2_ju_ne_j2i.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_ju_ne_j2i.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_ju_ne_j2i.c b/libj2_ju_ne_j2i.c index 8cb6962..80a512e 100644 --- a/libj2_ju_ne_j2i.c +++ b/libj2_ju_ne_j2i.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_ne_j2i(uintmax_t a, const struct libj2_j2i *b); -/* TODO Add man page */ #else diff --git a/libj2_ju_ne_j2u.3 b/libj2_ju_ne_j2u.3 new file mode 120000 index 0000000..f9c58c2 --- /dev/null +++ b/libj2_ju_ne_j2u.3 @@ -0,0 +1 @@ +libj2_j2i_ne_j2i.3
\ No newline at end of file diff --git a/libj2_ju_ne_j2u.c b/libj2_ju_ne_j2u.c index 556d553..d7e1644 100644 --- a/libj2_ju_ne_j2u.c +++ b/libj2_ju_ne_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline int libj2_ju_ne_j2u(uintmax_t a, const struct libj2_j2u *b); -/* TODO Add man page */ #else diff --git a/libj2_kfs_j2u.3 b/libj2_kfs_j2u.3 new file mode 100644 index 0000000..de3841a --- /dev/null +++ b/libj2_kfs_j2u.3 @@ -0,0 +1,52 @@ +.TH LIBJ2_KFS_J2U 3 LIBJ2 +.SH NAME +libj2_kfs_j2u \- Keep first set bit, clear the rest + +.SH SYNOPSIS +.nf +#include <libj2.h> + +void \fBlibj2_kfs_j2u\fP(struct libj2_j2u *\fIa\fP); +void \fBlibj2_kfs_j2u_to_j2u\fP(const struct libj2_j2u *\fIa\fP, struct libj2_j2u *\fIr\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_kfs_j2u () +function clears all bits in +.I a +except the first (least significant) +set bit (no modification if all bits +are cleared). +.PP +The +.BR libj2_kfs_j2u_to_j2u () +function performs the same action as +.BR libj2_kfs_j2u () +but instead of modifying +.IR a , +the result is stored in +.IR r . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +None. + +.SH ERRORS +The +.BR libj2_kfs_j2u () +and +.BR libj2_kfs_j2u_to_j2u () +functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_kls_j2u (3), +.BR libj2_ffs_j2u (3), +.BR libj2_cfs_j2u (3), +.BR libj2_sfc_j2u (3) diff --git a/libj2_kfs_j2u.c b/libj2_kfs_j2u.c index af07619..7ed355a 100644 --- a/libj2_kfs_j2u.c +++ b/libj2_kfs_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_kfs_j2u(struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_kfs_j2u_to_j2u.3 b/libj2_kfs_j2u_to_j2u.3 new file mode 120000 index 0000000..e202a7c --- /dev/null +++ b/libj2_kfs_j2u_to_j2u.3 @@ -0,0 +1 @@ +libj2_kfs_j2u.3
\ No newline at end of file diff --git a/libj2_kfs_j2u_to_j2u.c b/libj2_kfs_j2u_to_j2u.c index afc09fe..5b0ce92 100644 --- a/libj2_kfs_j2u_to_j2u.c +++ b/libj2_kfs_j2u_to_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_kfs_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res); -/* TODO Add man page */ #else diff --git a/libj2_kls_j2u.3 b/libj2_kls_j2u.3 new file mode 100644 index 0000000..c327102 --- /dev/null +++ b/libj2_kls_j2u.3 @@ -0,0 +1,52 @@ +.TH LIBJ2_KLS_J2U 3 LIBJ2 +.SH NAME +libj2_kls_j2u \- Keep last set bit, clear the rest + +.SH SYNOPSIS +.nf +#include <libj2.h> + +void \fBlibj2_kls_j2u\fP(struct libj2_j2u *\fIa\fP); +void \fBlibj2_kls_j2u_to_j2u\fP(const struct libj2_j2u *\fIa\fP, struct libj2_j2u *\fIr\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_kls_j2u () +function clears all bits in +.I a +except the last (most significant) +set bit (no modification if all bits +are cleared). +.PP +The +.BR libj2_kls_j2u_to_j2u () +function performs the same action as +.BR libj2_kls_j2u () +but instead of modifying +.IR a , +the result is stored in +.IR r . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +None. + +.SH ERRORS +The +.BR libj2_kls_j2u () +and +.BR libj2_kls_j2u_to_j2u () +functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_kfs_j2u (3), +.BR libj2_fls_j2u (3), +.BR libj2_cls_j2u (3), +.BR libj2_slc_j2u (3) diff --git a/libj2_kls_j2u.c b/libj2_kls_j2u.c index 1c52f36..ee1b6c3 100644 --- a/libj2_kls_j2u.c +++ b/libj2_kls_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_kls_j2u(struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_kls_j2u_to_j2u.3 b/libj2_kls_j2u_to_j2u.3 new file mode 120000 index 0000000..bf6f801 --- /dev/null +++ b/libj2_kls_j2u_to_j2u.3 @@ -0,0 +1 @@ +libj2_kls_j2u.3
\ No newline at end of file diff --git a/libj2_kls_j2u_to_j2u.c b/libj2_kls_j2u_to_j2u.c index 4b13153..5251d21 100644 --- a/libj2_kls_j2u_to_j2u.c +++ b/libj2_kls_j2u_to_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_kls_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res); -/* TODO Add man page */ #else diff --git a/libj2_minus_j2i.c b/libj2_minus_j2i.c index bac519f..805afde 100644 --- a/libj2_minus_j2i.c +++ b/libj2_minus_j2i.c @@ -73,7 +73,6 @@ main(void) 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(); @@ -87,7 +86,6 @@ main(void) libj2_j2i_add_j2i(&a, &b); EXPECT(libj2_j2i_is_zero(&a)); } -#endif return 0; } diff --git a/libj2_parity_j2u.3 b/libj2_parity_j2u.3 new file mode 100644 index 0000000..067c0cf --- /dev/null +++ b/libj2_parity_j2u.3 @@ -0,0 +1,42 @@ +.TH LIBJ2_PARITY_J2U 3 LIBJ2 +.SH NAME +libj2_parity_j2u \- Calculate bit parity + +.SH SYNOPSIS +.nf +#include <libj2.h> + +unsigned \fBlibj2_parity_j2u\fP(const struct libj2_j2u *\fIa\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_parity_j2u () +function returns the parity of the bits in +.IR a . +.PP +.I a +is assumed to be +.RI non- NULL . + +.SH RETURN VALUE +The +.BR libj2_parity_j2u () +function returns the 1 if the number of +set bits (or equivalently the cleared bits) +in +.I a +is odd, and 0 otherwise. + +.SH ERRORS +The +.BR libj2_parity_j2u () +function cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_co_j2u (3), +.BR libj2_cz_j2u (3) diff --git a/libj2_parity_j2u.c b/libj2_parity_j2u.c index 5adafc6..fda18ad 100644 --- a/libj2_parity_j2u.c +++ b/libj2_parity_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline unsigned libj2_parity_j2u(const struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_sfc_j2u.3 b/libj2_sfc_j2u.3 new file mode 100644 index 0000000..ec993c8 --- /dev/null +++ b/libj2_sfc_j2u.3 @@ -0,0 +1,51 @@ +.TH LIBJ2_SFC_J2U 3 LIBJ2 +.SH NAME +libj2_sfc_j2u \- Set first cleared bit + +.SH SYNOPSIS +.nf +#include <libj2.h> + +void \fBlibj2_sfc_j2u\fP(struct libj2_j2u *\fIa\fP); +void \fBlibj2_sfc_j2u_to_j2u\fP(const struct libj2_j2u *\fIa\fP, struct libj2_j2u *\fIr\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_sfc_j2u () +function sets the first (least significant) +cleared bit in +.I a +(no modification if all bits are set). +.PP +The +.BR libj2_sfc_j2u_to_j2u () +function performs the same action as +.BR libj2_sfc_j2u () +but instead of modifying +.IR a , +the result is stored in +.IR r . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +None. + +.SH ERRORS +The +.BR libj2_sfc_j2u () +and +.BR libj2_sfc_j2u_to_j2u () +functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_slc_j2u (3), +.BR libj2_ffc_j2u (3), +.BR libj2_kfs_j2u (3), +.BR libj2_cfs_j2u (3) diff --git a/libj2_sfc_j2u.c b/libj2_sfc_j2u.c index 1b91a7e..9bc09ea 100644 --- a/libj2_sfc_j2u.c +++ b/libj2_sfc_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_sfc_j2u(struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_sfc_j2u_to_j2u.3 b/libj2_sfc_j2u_to_j2u.3 new file mode 120000 index 0000000..8824875 --- /dev/null +++ b/libj2_sfc_j2u_to_j2u.3 @@ -0,0 +1 @@ +libj2_sfc_j2u.3
\ No newline at end of file diff --git a/libj2_sfc_j2u_to_j2u.c b/libj2_sfc_j2u_to_j2u.c index a1a9e17..b2d6f72 100644 --- a/libj2_sfc_j2u_to_j2u.c +++ b/libj2_sfc_j2u_to_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_sfc_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res); -/* TODO Add man page */ #else diff --git a/libj2_slc_j2u.3 b/libj2_slc_j2u.3 new file mode 100644 index 0000000..d65b13a --- /dev/null +++ b/libj2_slc_j2u.3 @@ -0,0 +1,51 @@ +.TH LIBJ2_SLC_J2U 3 LIBJ2 +.SH NAME +libj2_slc_j2u \- Set last cleared bit + +.SH SYNOPSIS +.nf +#include <libj2.h> + +void \fBlibj2_slc_j2u\fP(struct libj2_j2u *\fIa\fP); +void \fBlibj2_slc_j2u_to_j2u\fP(const struct libj2_j2u *\fIa\fP, struct libj2_j2u *\fIr\fP); +.fi +.PP +Link with +.IR -lj2 . + +.SH DESCRIPTION +The +.BR libj2_slc_j2u () +function sets the last (most significant) +cleared bit in +.I a +(no modification if all bits are set). +.PP +The +.BR libj2_slc_j2u_to_j2u () +function performs the same action as +.BR libj2_slc_j2u () +but instead of modifying +.IR a , +the result is stored in +.IR r . +.PP +The arguments are assumed to be +.RI non- NULL . + +.SH RETURN VALUE +None. + +.SH ERRORS +The +.BR libj2_slc_j2u () +and +.BR libj2_slc_j2u_to_j2u () +functions cannot fail. + +.SH SEE ALSO +.BR libj2 (7), +.BR libj2_sfc_j2u (3), +.BR libj2_flc_j2u (3), +.BR libj2_kls_j2u (3), +.BR libj2_cls_j2u (3) diff --git a/libj2_slc_j2u.c b/libj2_slc_j2u.c index 500f633..7f65df4 100644 --- a/libj2_slc_j2u.c +++ b/libj2_slc_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_slc_j2u(struct libj2_j2u *a); -/* TODO Add man page */ #else diff --git a/libj2_slc_j2u_to_j2u.3 b/libj2_slc_j2u_to_j2u.3 new file mode 120000 index 0000000..96f60b0 --- /dev/null +++ b/libj2_slc_j2u_to_j2u.3 @@ -0,0 +1 @@ +libj2_slc_j2u.3
\ No newline at end of file diff --git a/libj2_slc_j2u_to_j2u.c b/libj2_slc_j2u_to_j2u.c index 874be05..933843e 100644 --- a/libj2_slc_j2u_to_j2u.c +++ b/libj2_slc_j2u_to_j2u.c @@ -3,7 +3,6 @@ #ifndef TEST extern inline void libj2_slc_j2u_to_j2u(const struct libj2_j2u *a, struct libj2_j2u *res); -/* TODO Add man page */ #else diff --git a/libj2_vmax_j2i_to_j2i.c b/libj2_vmax_j2i_to_j2i.c index 712cb9f..3606393 100644 --- a/libj2_vmax_j2i_to_j2i.c +++ b/libj2_vmax_j2i_to_j2i.c @@ -8,6 +8,6 @@ extern inline void libj2_vmax_j2i_to_j2i(const struct libj2_j2i *a, va_list args #else -CONST int main(void) { return 0; } /* Tested via libj2_vmax_j2i_to_j2i */ +CONST int main(void) { return 0; } /* Tested via libj2_max_j2i_to_j2i */ #endif diff --git a/libj2_vmax_j2u_to_j2u.c b/libj2_vmax_j2u_to_j2u.c index 9b421dc..616c196 100644 --- a/libj2_vmax_j2u_to_j2u.c +++ b/libj2_vmax_j2u_to_j2u.c @@ -8,6 +8,6 @@ extern inline void libj2_vmax_j2u_to_j2u(const struct libj2_j2u *a, va_list args #else -CONST int main(void) { return 0; } /* Tested via libj2_vmax_j2u_to_j2u */ +CONST int main(void) { return 0; } /* Tested via libj2_max_j2u_to_j2u */ #endif diff --git a/libj2_vmin_j2i_to_j2i.c b/libj2_vmin_j2i_to_j2i.c index 3ab12d5..ba8d4ed 100644 --- a/libj2_vmin_j2i_to_j2i.c +++ b/libj2_vmin_j2i_to_j2i.c @@ -8,6 +8,6 @@ extern inline void libj2_vmin_j2i_to_j2i(const struct libj2_j2i *a, va_list args #else -CONST int main(void) { return 0; } /* Tested via libj2_vmin_j2i_to_j2i */ +CONST int main(void) { return 0; } /* Tested via libj2_min_j2i_to_j2i */ #endif diff --git a/libj2_vmin_j2u_to_j2u.c b/libj2_vmin_j2u_to_j2u.c index 021e5ee..2cd4460 100644 --- a/libj2_vmin_j2u_to_j2u.c +++ b/libj2_vmin_j2u_to_j2u.c @@ -8,6 +8,6 @@ extern inline void libj2_vmin_j2u_to_j2u(const struct libj2_j2u *a, va_list args #else -CONST int main(void) { return 0; } /* Tested via libj2_vmin_j2u_to_j2u */ +CONST int main(void) { return 0; } /* Tested via libj2_min_j2u_to_j2u */ #endif |
