aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib/bigint.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-12-24 12:45:29 -0500
committerBruce Hill <bruce@bruce-hill.com>2025-12-24 12:52:48 -0500
commit649977aae7e5922f992cd69eb84da0a2db368580 (patch)
treee61d35b74d2551901cc8f3f034aca7da1f375a8c /src/stdlib/bigint.c
parent88ccdab43c0a3ee53177e21a28724e496406a376 (diff)
Split out new()/gc logic from stdlib/util.h
Diffstat (limited to 'src/stdlib/bigint.c')
-rw-r--r--src/stdlib/bigint.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/stdlib/bigint.c b/src/stdlib/bigint.c
index 2d145bd5..84da1468 100644
--- a/src/stdlib/bigint.c
+++ b/src/stdlib/bigint.c
@@ -18,6 +18,35 @@
#include "text.h"
#include "types.h"
+#define Int$from_mpz(mpz) \
+ (mpz_cmpabs_ui(mpz, BIGGEST_SMALL_INT) <= 0 \
+ ? ((Int_t){.small = (mpz_get_si(mpz) << 2L) | 1L}) \
+ : ((Int_t){.big = memcpy(GC_MALLOC(sizeof(__mpz_struct)), mpz, sizeof(__mpz_struct))}))
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+public
+PUREFUNC Int_t Int$from_num64(double n, bool truncate) {
+ mpz_t result;
+ mpz_init_set_d(result, n);
+ if (!truncate && unlikely(mpz_get_d(result) != n)) fail("Could not convert to an integer without truncation: ", n);
+ return Int$from_mpz(result);
+}
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+public
+PUREFUNC Int_t Int$from_int64(int64_t i) {
+ if likely (i >= SMALLEST_SMALL_INT && i <= BIGGEST_SMALL_INT) return (Int_t){.small = (i << 2L) | 1L};
+ mpz_t result;
+ mpz_init_set_si(result, i);
+ return Int$from_mpz(result);
+}
+
public
int Int$print(FILE *f, Int_t i) {
if (likely(i.small & 1L)) {