summaryrefslogtreecommitdiff
path: root/support/dktools/dk3mal.ctr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk3mal.ctr
Initial commit
Diffstat (limited to 'support/dktools/dk3mal.ctr')
-rw-r--r--support/dktools/dk3mal.ctr943
1 files changed, 943 insertions, 0 deletions
diff --git a/support/dktools/dk3mal.ctr b/support/dktools/dk3mal.ctr
new file mode 100644
index 0000000000..730cbf7b4e
--- /dev/null
+++ b/support/dktools/dk3mal.ctr
@@ -0,0 +1,943 @@
+%% options
+
+copyright owner = Dirk Krause
+copyright year = 2014-xxxx
+license = bsd
+
+
+
+%% header
+
+/** @file dk3mal.h Mathematical operations on long, long long,
+ intmax_t and dk3_im_t.
+*/
+
+#include <dk3conf.h>
+
+#include <stdio.h>
+#if DK3_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if DK3_HAVE_STDINT
+#include <stdint.h>
+#endif
+#if DK3_HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#if DK3_HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#if DK3_HAVE_MATH_H
+#include <math.h>
+#endif
+#if DK3_HAVE_FLOAT_H
+#include <float.h>
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Absolute value.
+ @param a Original value.
+ @param ec Pointer to error code variable, may be NULL.
+ @return Non-negative value on success,
+ DK3_L_MAX and ec = DK3_ERROR_MATH_OVERFLOW on error.
+*/
+long
+dk3ma_l_abs_ok(long a, int *ec);
+
+/** Addition.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Summary of a and b.
+*/
+long
+dk3ma_l_add_ok(long a, long b, int *ec);
+
+/** Substraction.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Difference of a and b.
+*/
+long
+dk3ma_l_sub_ok(long a, long b, int *ec);
+
+/** Multiplication.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Product of a and b.
+*/
+long
+dk3ma_l_mul_ok(long a, long b, int *ec);
+
+/** Division.
+ @param a Left operand (nominator).
+ @param b Right operand (denominator).
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW or
+ DK3_ERROR_MATH_DIVZERO when returning.
+ @return Fraction of a and b.
+*/
+long
+dk3ma_l_div_ok(long a, long b, int *ec);
+
+/** Greatest common divisor.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Greatest common divisor of a and b on success,
+ 0L and ec = DK3_ERROR_MATH_OVERFLOW on error.
+*/
+long
+dk3ma_l_gcd_ok(long a, long b, int *ec);
+
+
+
+#if DK3_HAVE_LONG_LONG
+
+/** Absolute value.
+ @param a Original value.
+ @param ec Pointer to error code variable, may be NULL.
+ @return Non-negative value on success,
+ DK3_L_MAX and ec = DK3_ERROR_MATH_OVERFLOW on error.
+*/
+long long
+dk3ma_ll_abs_ok(long long a, int *ec);
+
+/** Addition.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Summary of a and b.
+*/
+long long
+dk3ma_ll_add_ok(long long a, long long b, int *ec);
+
+/** Substraction.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Difference of a and b.
+*/
+long long
+dk3ma_ll_sub_ok(long long a, long long b, int *ec);
+
+/** Multiplication.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Product of a and b.
+*/
+long long
+dk3ma_ll_mul_ok(long long a, long long b, int *ec);
+
+/** Division.
+ @param a Left operand (nominator).
+ @param b Right operand (denominator).
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW or
+ DK3_ERROR_MATH_DIVZERO when returning.
+ @return Fraction of a and b.
+*/
+long long
+dk3ma_ll_div_ok(long long a, long long b, int *ec);
+
+/** Greatest common divisor.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Greatest common divisor of a and b on success,
+ 0L and ec = DK3_ERROR_MATH_OVERFLOW on error.
+*/
+long long
+dk3ma_ll_gcd_ok(long long a, long long b, int *ec);
+
+#endif
+/* if DK3_HAVE_LONG_LONG */
+
+
+
+#if DK3_HAVE_INTMAX_T
+
+/** Absolute value.
+ @param a Original value.
+ @param ec Pointer to error code variable, may be NULL.
+ @return Non-negative value on success,
+ DK3_L_MAX and ec = DK3_ERROR_MATH_OVERFLOW on error.
+*/
+intmax_t
+dk3ma_intmax_t_abs_ok(intmax_t a, int *ec);
+
+/** Addition.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Summary of a and b.
+*/
+intmax_t
+dk3ma_intmax_t_add_ok(intmax_t a, intmax_t b, int *ec);
+
+/** Substraction.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Difference of a and b.
+*/
+intmax_t
+dk3ma_intmax_t_sub_ok(intmax_t a, intmax_t b, int *ec);
+
+/** Multiplication.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Product of a and b.
+*/
+intmax_t
+dk3ma_intmax_t_mul_ok(intmax_t a, intmax_t b, int *ec);
+
+/** Division.
+ @param a Left operand (nominator).
+ @param b Right operand (denominator).
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW or
+ DK3_ERROR_MATH_DIVZERO when returning.
+ @return Fraction of a and b.
+*/
+intmax_t
+dk3ma_intmax_t_div_ok(intmax_t a, intmax_t b, int *ec);
+
+/** Greatest common divisor.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Greatest common divisor of a and b on success,
+ 0L and ec = DK3_ERROR_MATH_OVERFLOW on error.
+*/
+intmax_t
+dk3ma_intmax_t_gcd_ok(intmax_t a, intmax_t b, int *ec);
+
+#endif
+
+/** Absolute value.
+ @param a Original value.
+ @param ec Pointer to error code variable, may be NULL.
+ @return Non-negative value on success,
+ DK3_L_MAX and ec = DK3_ERROR_MATH_OVERFLOW on error.
+*/
+dk3_im_t
+dk3ma_im_abs_ok(dk3_im_t a, int *ec);
+
+/** Addition.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Summary of a and b.
+*/
+dk3_im_t
+dk3ma_im_add_ok(dk3_im_t a, dk3_im_t b, int *ec);
+
+/** Substraction.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Difference of a and b.
+*/
+dk3_im_t
+dk3ma_im_sub_ok(dk3_im_t a, dk3_im_t b, int *ec);
+
+/** Multiplication.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Product of a and b.
+*/
+dk3_im_t
+dk3ma_im_mul_ok(dk3_im_t a, dk3_im_t b, int *ec);
+
+/** Division.
+ @param a Left operand (nominator).
+ @param b Right operand (denominator).
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW or
+ DK3_ERROR_MATH_DIVZERO when returning.
+ @return Fraction of a and b.
+*/
+dk3_im_t
+dk3ma_im_div_ok(dk3_im_t a, dk3_im_t b, int *ec);
+
+/** Greatest common divisor.
+ @param a Left operand.
+ @param b Right operand.
+ @param ec Pointer to error code variable, may be NULL.
+ The variable may be set to DK3_ERROR_MATH_OVERFLOW when returning.
+ @return Greatest common divisor of a and b on success,
+ 0L and ec = DK3_ERROR_MATH_OVERFLOW on error.
+*/
+dk3_im_t
+dk3ma_im_gcd_ok(dk3_im_t a, dk3_im_t b, int *ec);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+%% module
+
+
+
+#include "dk3ma.h"
+
+
+
+$!trace-include
+
+
+
+long
+dk3ma_l_abs_ok(long a, int *ec)
+{
+ if (NULL != ec) { if(DK3_L_MIN == a) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
+ return ((0L <= a) ? a : (0L - a));
+}
+
+
+
+long
+dk3ma_l_add_ok(long a, long b, int *ec)
+{
+ if (NULL != ec) {
+ if ((0L < a) && (0L < b)) {
+ if((DK3_L_MAX - a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ } else {
+ if ((0L > a) && (0L > b)) {
+ if (DK3_L_MIN == a) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ } else {
+ if ((DK3_L_MIN - a) > b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ }
+ }
+ }
+ }
+ return (a + b);
+}
+
+
+
+long
+dk3ma_l_sub_ok(long a, long b, int *ec)
+{
+ if (NULL != ec) {
+ if ((0L < a) && (0L > b)) {
+ if((DK3_L_MAX + b) < a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ } else {
+ if ((0L > a) && (0L < b)) {
+ if((DK3_L_MIN + b) > a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ }
+ }
+ }
+ return (a - b);
+}
+
+
+
+#if VERSION_BEFORE_20141018
+long
+dk3ma_l_mul_ok(long a, long b, int *ec)
+{
+ if (NULL != ec) {
+ if ((0L != a) && (0L != b)) {
+ if ((DK3_L_MIN == a) && (1L != b)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ goto checksfinished;
+ }
+ if ((DK3_L_MIN == b) && (1L != a)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ goto checksfinished;
+ }
+ if ((DK3_L_MAX / dk3ma_l_abs_ok(a, ec)) < dk3ma_l_abs_ok(b, ec)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ /* goto checksfinished; -- when adding further tests -- */
+ }
+ }
+ }
+ checksfinished:
+ return (a * b);
+}
+#else
+long
+dk3ma_l_mul_ok(long a, long b, int *ec)
+{
+ if ((NULL != ec) && (0L != a) && (0L != b)) {
+ if (DK3_L_MIN == a) {
+ if (1L != b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ goto finished;
+ }
+ if (DK3_L_MIN == b) {
+ if (1L != a) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ goto finished;
+ }
+ if (0L < a) {
+ if (0L < b) {
+ if ((DK3_L_MAX / a) < b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ } else {
+ if ((DK3_L_MIN / a) > b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ }
+ } else {
+ if (0L < b) {
+ if ((DK3_L_MIN / b) > a) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ } else {
+ if ((DK3_L_MAX / (0L - a)) < (0L - b)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ }
+ }
+ }
+finished:
+ return (a * b);
+}
+#endif
+
+
+
+long
+dk3ma_l_div_ok(long a, long b, int *ec)
+{
+ long back = 0L;
+ if (0L != b) {
+ if ((DK3_L_MIN == a) && (-1L == b)) {
+ back = DK3_L_MAX;
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ } else {
+ back = a / b;
+ }
+ } else {
+ if (NULL != ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
+ if (0L <= a) { back = DK3_L_MAX; }
+ else { back = DK3_L_MIN; }
+ }
+ return back;
+}
+
+
+
+long
+dk3ma_l_gcd_ok(long a, long b, int *ec)
+{
+ long h;
+ if (0L > a) {
+ if (DK3_L_MIN == a) {
+ a = 0L;
+ if (NULL != ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ goto finished;
+ } else {
+ a = 0L - a;
+ }
+ }
+ if (0L > b) {
+ if (DK3_L_MIN == b) {
+ a = 0L;
+ if (NULL != ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ goto finished;
+ } else {
+ b = 0L - b;
+ }
+ }
+ while (0L < b) {
+ h = a % b;
+ a = b;
+ b = h;
+ }
+ if (0L == a) { a = 1L; }
+ finished:
+ return a;
+}
+
+
+
+#if DK3_HAVE_LONG_LONG
+
+
+
+long long
+dk3ma_ll_abs_ok(long long a, int *ec)
+{
+ if (NULL != ec) { if(DK3_LL_MIN == a) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
+ return ((0LL <= a) ? a : (0L - a));
+}
+
+
+
+long long
+dk3ma_ll_add_ok(long long a, long long b, int *ec)
+{
+ if (NULL != ec) {
+ if ((0LL < a) && (0LL < b)) {
+ if((DK3_LL_MAX - a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ } else {
+ if ((0LL > a) && (0LL > b)) {
+ if (DK3_LL_MIN == a) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ } else {
+ if ((DK3_LL_MIN - a) > b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ }
+ }
+ }
+ }
+ return (a + b);
+}
+
+
+
+long long
+dk3ma_ll_sub_ok(long long a, long long b, int *ec)
+{
+ if (NULL != ec) {
+ if ((0LL < a) && (0LL > b)) {
+ if((DK3_LL_MAX + b) < a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ } else {
+ if ((0LL > a) && (0LL < b)) {
+ if((DK3_LL_MIN + b) > a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ }
+ }
+ }
+ return (a - b);
+}
+
+
+
+#if VERSION_BEFORE_20141018
+long long
+dk3ma_ll_mul_ok(long long a, long long b, int *ec)
+{
+ if (NULL != ec) {
+ if ((0LL != a) && (0LL != b)) {
+ if ((DK3_LL_MIN == a) && (1LL != b)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ goto checksfinished;
+ }
+ if ((DK3_LL_MIN == b) && (1LL != a)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ goto checksfinished;
+ }
+ if ((DK3_LL_MAX / dk3ma_ll_abs_ok(a, ec)) < dk3ma_ll_abs_ok(b, ec)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ /* goto checksfinished; -- when adding further tests -- */
+ }
+ }
+ }
+ checksfinished:
+ return (a * b);
+}
+#else
+long long
+dk3ma_ll_mul_ok(long long a, long long b, int *ec)
+{
+ if ((NULL != ec) && (0LL != a) && (0LL != b)) {
+ if (DK3_LL_MIN == a) {
+ if (1LL != b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ goto finished;
+ }
+ if (DK3_LL_MIN == b) {
+ if (1LL != a) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ goto finished;
+ }
+ if (0LL < a) {
+ if (0LL < b) {
+ if ((DK3_LL_MAX / a) < b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ } else {
+ if ((DK3_LL_MIN / a) > b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ }
+ } else {
+ if (0LL < b) {
+ if ((DK3_LL_MIN / b) > a) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ } else {
+ if ((DK3_LL_MAX / (0LL - a)) < (0LL - b)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ }
+ }
+ }
+finished:
+ return (a * b);
+}
+#endif
+
+
+
+long long
+dk3ma_ll_div_ok(long long a, long long b, int *ec)
+{
+ long long back = 0L;
+ if (0LL != b) {
+ if ((DK3_LL_MIN == a) && (-1LL == b)) {
+ back = DK3_LL_MAX;
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ } else {
+ back = a / b;
+ }
+ } else {
+ if (NULL != ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
+ if (0LL <= a) { back = DK3_LL_MAX; }
+ else { back = DK3_LL_MIN; }
+ }
+ return back;
+}
+
+
+
+long long
+dk3ma_ll_gcd_ok(long long a, long long b, int *ec)
+{
+ long long h;
+ if (0LL > a) {
+ if (DK3_LL_MIN == a) {
+ a = 0LL;
+ if (NULL != ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ goto finished;
+ } else {
+ a = 0LL - a;
+ }
+ }
+ if (0LL > b) {
+ if (DK3_LL_MIN == b) {
+ a = 0LL;
+ if (NULL != ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ goto finished;
+ } else {
+ b = 0LL - b;
+ }
+ }
+ while (0LL < b) {
+ h = a % b;
+ a = b;
+ b = h;
+ }
+ if (0LL == a) { a = 1LL; }
+ finished:
+ return a;
+}
+
+
+#endif
+
+
+
+#if DK3_HAVE_INTMAX_T
+
+intmax_t
+dk3ma_intmax_t_abs_ok(intmax_t a, int *ec)
+{
+ if (ec) { if (DK3_INTMAX_T_MIN == a) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
+ return ((DK3_INTMAX_T_0 <= a) ? a : (DK3_INTMAX_T_0 - a));
+}
+
+
+
+intmax_t
+dk3ma_intmax_t_add_ok(intmax_t a, intmax_t b, int *ec)
+{
+ if (NULL != ec) {
+ if ((DK3_INTMAX_T_0 < a) && (DK3_INTMAX_T_0 < b)) {
+ if ((DK3_INTMAX_T_MAX - a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ } else {
+ if ((DK3_INTMAX_T_0 > a) && (DK3_INTMAX_T_0 > b)) {
+ if (DK3_INTMAX_T_MIN == a) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ } else {
+ if ((DK3_INTMAX_T_MIN - a) > b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ }
+ }
+ }
+ }
+ return (a + b);
+}
+
+
+
+intmax_t
+dk3ma_intmax_t_sub_ok(intmax_t a, intmax_t b, int *ec)
+{
+ if (NULL != ec) {
+ if((DK3_INTMAX_T_0 < a) && (DK3_INTMAX_T_0 > b)) {
+ if((DK3_INTMAX_T_MAX + b) < a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ } else {
+ if((DK3_INTMAX_T_0 > a) && (DK3_INTMAX_T_0 < b)) {
+ if((DK3_INTMAX_T_MIN + b) > a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ }
+ }
+ }
+ return (a - b);
+}
+
+
+
+#if VERSION_BEFORE_20141018
+intmax_t
+dk3ma_intmax_t_mul_ok(intmax_t a, intmax_t b, int *ec)
+{
+ if (NULL != ec) {
+ if ((DK3_INTMAX_T_0 != a) && (DK3_INTMAX_T_0 != b)) {
+ if ((DK3_INTMAX_T_MIN == a) && (DK3_INTMAX_T_1 != b)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ goto checksfinished;
+ }
+ if ((DK3_INTMAX_T_MIN == b) && (DK3_INTMAX_T_1 != a)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ goto checksfinished;
+ }
+ if (
+ (DK3_INTMAX_T_MAX / dk3ma_intmax_t_abs_ok(a, ec))
+ < dk3ma_intmax_t_abs_ok(b, ec)
+ )
+ {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ /* goto checksfinished; -- when adding further tests -- */
+ }
+ }
+ }
+ checksfinished:
+ return (a * b);
+}
+#else
+intmax_t
+dk3ma_intmax_t_mul_ok(intmax_t a, intmax_t b, int *ec)
+{
+ if ((NULL != ec) && (DK3_INTMAX_T_0 != a) && (DK3_INTMAX_T_0 != b)) {
+ if (DK3_INTMAX_T_MIN == a) {
+ if (DK3_INTMAX_T_1 != b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ goto finished;
+ }
+ if (DK3_INTMAX_T_MIN == b) {
+ if (DK3_INTMAX_T_1 != a) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ goto finished;
+ }
+ if (DK3_INTMAX_T_0 < a) {
+ if (DK3_INTMAX_T_0 < b) {
+ if ((DK3_INTMAX_T_MAX / a) < b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ } else {
+ if ((DK3_INTMAX_T_MIN / a) > b) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ }
+ } else {
+ if (DK3_INTMAX_T_0 < b) {
+ if ((DK3_INTMAX_T_MIN / b) > a) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ } else {
+ if ((DK3_INTMAX_T_MAX / (DK3_INTMAX_T_0 - a)) < (DK3_INTMAX_T_0 - b)) {
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ }
+ }
+ }
+ }
+finished:
+ return (a * b);
+}
+#endif
+
+
+
+intmax_t
+dk3ma_intmax_t_div_ok(intmax_t a, intmax_t b, int *ec)
+{
+ intmax_t back = DK3_INTMAX_T_0;
+ if (DK3_INTMAX_T_0 != b) {
+ if ((DK3_INTMAX_T_MIN == a) && ((-DK3_INTMAX_T_1) == b)) {
+ back = DK3_INTMAX_T_MAX;
+ *ec = DK3_ERROR_MATH_OVERFLOW;
+ } else {
+ back = (a / b);
+ }
+ } else {
+ if (NULL != ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
+ if (DK3_INTMAX_T_0 <= a) { back = DK3_INTMAX_T_MAX; }
+ else { back = DK3_INTMAX_T_MIN; }
+ }
+ return back;
+}
+
+
+
+intmax_t
+dk3ma_intmax_t_gcd_ok(intmax_t a, intmax_t b, int *ec)
+{
+ intmax_t h;
+ if (DK3_INTMAX_T_0 > a) {
+ if (DK3_INTMAX_T_MIN == a) {
+ a = DK3_INTMAX_T_0;
+ if (NULL != ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ goto finished;
+ } else {
+ a = DK3_INTMAX_T_0 - a;
+ }
+ }
+ if (DK3_INTMAX_T_0 > b) {
+ if (DK3_INTMAX_T_MIN == b) {
+ a = DK3_INTMAX_T_0;
+ if (NULL != ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
+ goto finished;
+ } else {
+ b = DK3_INTMAX_T_0 - b;
+ }
+ }
+ while (DK3_INTMAX_T_0 < b) {
+ h = a % b;
+ a = b;
+ b = h;
+ }
+ if (DK3_INTMAX_T_0 == a) { a = DK3_INTMAX_T_1 ; }
+ finished:
+ return a;
+}
+
+#endif
+
+
+
+dk3_im_t
+dk3ma_im_abs_ok(dk3_im_t a, int *ec)
+{
+#if DK3_HAVE_INTMAX_T
+ return (dk3ma_intmax_t_abs_ok(a, ec));
+#else
+#if DK3_HAVE_LONG_LONG
+ return (dk3ma_ll_abs_ok(a, ec));
+#else
+ return (dk3ma_l_abs_ok(a, ec));
+#endif
+#endif
+}
+
+
+
+dk3_im_t
+dk3ma_im_add_ok(dk3_im_t a, dk3_im_t b, int *ec)
+{
+#if DK3_HAVE_INTMAX_T
+ return (dk3ma_intmax_t_add_ok(a, b, ec));
+#else
+#if DK3_HAVE_LONG_LONG
+ return (dk3ma_ll_add_ok(a, b, ec));
+#else
+ return (dk3ma_l_add_ok(a, b, ec));
+#endif
+#endif
+}
+
+
+
+dk3_im_t
+dk3ma_im_sub_ok(dk3_im_t a, dk3_im_t b, int *ec)
+{
+#if DK3_HAVE_INTMAX_T
+ return (dk3ma_intmax_t_sub_ok(a, b, ec));
+#else
+#if DK3_HAVE_LONG_LONG
+ return (dk3ma_ll_sub_ok(a, b, ec));
+#else
+ return (dk3ma_l_sub_ok(a, b, ec));
+#endif
+#endif
+}
+
+
+
+dk3_im_t
+dk3ma_im_mul_ok(dk3_im_t a, dk3_im_t b, int *ec)
+{
+#if DK3_HAVE_INTMAX_T
+ return (dk3ma_intmax_t_mul_ok(a, b, ec));
+#else
+#if DK3_HAVE_LONG_LONG
+ return (dk3ma_ll_mul_ok(a, b, ec));
+#else
+ return (dk3ma_l_mul_ok(a, b, ec));
+#endif
+#endif
+}
+
+
+
+dk3_im_t
+dk3ma_im_div_ok(dk3_im_t a, dk3_im_t b, int *ec)
+{
+#if DK3_HAVE_INTMAX_T
+ return (dk3ma_intmax_t_div_ok(a, b, ec));
+#else
+#if DK3_HAVE_LONG_LONG
+ return (dk3ma_ll_div_ok(a, b, ec));
+#else
+ return (dk3ma_l_div_ok(a, b, ec));
+#endif
+#endif
+}
+
+
+
+dk3_im_t
+dk3ma_im_gcd_ok(dk3_im_t a, dk3_im_t b, int *ec)
+{
+#if DK3_HAVE_INTMAX_T
+ return (dk3ma_intmax_t_gcd_ok(a, b, ec));
+#else
+#if DK3_HAVE_LONG_LONG
+ return (dk3ma_ll_gcd_ok(a, b, ec));
+#else
+ return (dk3ma_l_gcd_ok(a, b, ec));
+#endif
+#endif
+}
+
+