aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib/numX.c.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/stdlib/numX.c.h')
-rw-r--r--src/stdlib/numX.c.h38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/stdlib/numX.c.h b/src/stdlib/numX.c.h
index 22db3ca3..bef78c5b 100644
--- a/src/stdlib/numX.c.h
+++ b/src/stdlib/numX.c.h
@@ -6,11 +6,13 @@
//
#include <float.h>
#include <gc.h>
+#include <gmp.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
+#include "fail.h"
#include "text.h"
#include "types.h"
@@ -91,6 +93,42 @@ PUREFUNC int32_t NAMESPACED(compare)(const void *x, const void *y, const TypeInf
}
#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+public
+CONSTFUNC NUM_T NAMESPACED(from_int)(Int_t i, bool truncate) {
+ if likely (i.small & 0x1) {
+ NUM_T ret = (NUM_T)(i.small >> 2);
+ if unlikely (!truncate && (int64_t)ret != (i.small >> 2))
+ fail_text(Text$concat(Text("Could not convert integer to " TYPE_STR " without losing precision: "),
+ Int64$value_as_text(i.small >> 2)));
+ return ret;
+ } else {
+ NUM_T ret = mpz_get_d(i.big);
+ if (!truncate) {
+ mpz_t roundtrip;
+ mpz_init_set_d(roundtrip, (double)ret);
+ if unlikely (mpz_cmp(i.big, roundtrip) != 0)
+ fail_text(Text$concat(Text("Could not convert integer to " TYPE_STR " without losing precision: "),
+ Int$value_as_text(i)));
+ }
+ return ret;
+ }
+}
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+public
+CONSTFUNC NUM_T NAMESPACED(from_int64)(Int64_t i, bool truncate) {
+ NUM_T n = (NUM_T)i;
+ if unlikely (!truncate && (Int64_t)n != i)
+ fail_text(Text$concat(Text("Could not convert integer to " TYPE_STR " without losing precision: "),
+ Int64$value_as_text(i)));
+ return n;
+}
+
public
PUREFUNC bool NAMESPACED(equal)(const void *x, const void *y, const TypeInfo_t *info) {
(void)info;