aboutsummaryrefslogtreecommitdiffstats
path: root/common.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--common.h91
1 files changed, 91 insertions, 0 deletions
diff --git a/common.h b/common.h
new file mode 100644
index 0000000..b299fd1
--- /dev/null
+++ b/common.h
@@ -0,0 +1,91 @@
+/* See LICENSE file for copyright and license details. */
+#include "libquanta.h"
+#include <errno.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+
+
+#define PALETTE_BASE_SIZE offsetof(struct libquanta_palette, palette)
+#define PALETTE_VALUE_TYPE uint64_t
+#define PALETTE_VALUE_SIZE sizeof(PALETTE_VALUE_TYPE)
+#define PALETTE_VALUE_MAX_BITS 64U
+
+
+struct bigint {
+ uintmax_t high, low;
+};
+
+
+#if defined(__GNUC__)
+__attribute__((__visibility__("hidden")))
+#endif
+uintmax_t libquanta_bigint_divmod_small__(struct bigint *big, uintmax_t small);
+#define bigint_divmod_small libquanta_bigint_divmod_small__
+
+
+static inline void
+bigint_add_small(struct bigint *big, uintmax_t small)
+{
+#if defined(__GNUC__)
+ if (__builtin_add_overflow(big->low, small, &big->low))
+ big->high += 1U;
+#else
+ if (big->low > UINTMAX_MAX - small)
+ big->high += 1U;
+ big->low += small;
+#endif
+}
+
+
+static inline void
+bigint_sub_small(struct bigint *big, uintmax_t small)
+{
+#if defined(__GNUC__)
+ if (__builtin_sub_overflow(big->low, small, &big->low))
+ big->high -= 1U;
+#else
+ if (big->low < small)
+ big->high -= 1U;
+ big->low -= small;
+#endif
+}
+
+
+static inline void
+bigint_add_big(struct bigint *res, const struct bigint *restrict other)
+{
+ bigint_add_small(res, other->low);
+ res->high += other->high;
+}
+
+
+static inline void
+bigint_sub_big(struct bigint *res, const struct bigint *restrict other)
+{
+ bigint_sub_small(res, other->low);
+ res->high -= other->high;
+}
+
+
+static inline void
+bigint_rsub_big(struct bigint *res, const struct bigint *restrict other)
+{
+ res->high = other->high - res->high;
+#if defined(__GNUC__)
+ if (__builtin_sub_overflow(other->low, res->low, &res->low))
+ res->high -= 1U;
+#else
+ if (res->low > other->low)
+ res->high -= 1U;
+ res->low = other->low - res->low;
+#endif
+}
+
+
+static inline uintmax_t
+bigint_div_small(const struct bigint *big, uintmax_t small)
+{
+ struct bigint big_copy = *big;
+ return bigint_divmod_small(&big_copy, small);
+}