summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-01-25 07:06:05 -0800
committerKaz Kylheku <kaz@kylheku.com>2019-01-25 07:06:05 -0800
commit8fe261d344eb7607ffbe05713bd808cd1d766e46 (patch)
tree71087ef24f5655e451a5de1aedaa6e368ab20421
parent66c305a07d3e485a8e1212ef7bb296fc8464b7ac (diff)
downloadtxr-8fe261d344eb7607ffbe05713bd808cd1d766e46.tar.gz
txr-8fe261d344eb7607ffbe05713bd808cd1d766e46.tar.bz2
txr-8fe261d344eb7607ffbe05713bd808cd1d766e46.zip
itypes: take advantage of double_intptr_t.
If double_intptr_t is at least 64 bits wide (which is always going to be true) we can take advantage of it. * itypes.c (c_i64, c_u64): Provide implementations that use the new dbl_intptr_t and dbl_uintptr_t infrastructure. The fallback implementation that uses ash and logior is basically not used now. (num_64, unum_64): New functions for obtaining a Lisp value from a 64 bit number, abstracting whether this is done via the cnum or dbl_cnum route. * itypes.h (u64_t, i64_t): Define in terms of double_uintptr_t and double_intptr_t, if no other 64 bit type is available. (num_64, unum_64): Declared.
-rw-r--r--itypes.c48
-rw-r--r--itypes.h7
2 files changed, 54 insertions, 1 deletions
diff --git a/itypes.c b/itypes.c
index 5c1e3e69..d9aa7aaa 100644
--- a/itypes.c
+++ b/itypes.c
@@ -98,7 +98,8 @@ u32_t c_u32(val n, val self)
#endif
#if HAVE_I64
-#if CHAR_BIT * SIZEOF_PTR == 64
+
+#if CHAR_BIT * SIZEOF_PTR >= 64
i64_t c_i64(val n, val self)
{
cnum v = c_num(n);
@@ -116,6 +117,24 @@ u64_t c_u64(val n, val self)
self, n, nao);
return v;
}
+#elif HAVE_DOUBLE_INTPTR_T && CHAR_BIT * SIZEOF_DOUBLE_INTPTR >= 64
+i64_t c_i64(val n, val self)
+{
+ dbl_cnum v = c_dbl_num(n);
+ if (v < (- (dbl_cnum) 0x7FFFFFFFFFFFFFFF - 1) || v > (dbl_cnum) 0x7FFFFFFFFFFFFFFF)
+ uw_throwf(error_s, lit("~a: value ~s is out of signed 64 bit range"),
+ self, n, nao);
+ return v;
+}
+
+u64_t c_u64(val n, val self)
+{
+ dbl_ucnum v = c_dbl_unum(n);
+ if (v > (dbl_ucnum) 0xFFFFFFFFFFFFFFFF)
+ uw_throwf(error_s, lit("~a: value ~s is out of unsigned 64 bit range"),
+ self, n, nao);
+ return v;
+}
#else
i64_t c_i64(val n, val self)
{
@@ -131,6 +150,33 @@ u64_t c_u64(val n, val self)
return convert(u64_t, c_u32(high32, self)) << 32 | c_u32(low32, self);
}
#endif
+
+val num_64(i64_t n)
+{
+#if CHAR_BIT * SIZEOF_PTR >= 64
+ return num(n);
+#elif HAVE_DOUBLE_INTPTR_T && CHAR_BIT * SIZEOF_DOUBLE_INTPTR >= 64
+ return normalize(bignum_dbl_ipt(n));
+#else
+ cnum hi32 = n >> 32;
+ ucnum lo32 = n & 0xFFFFFFFFU;
+ return logior(ash(num(hi32), num_fast(32)), unum(lo32));
+#endif
+}
+
+val unum_64(u64_t n)
+{
+#if CHAR_BIT * SIZEOF_PTR >= 64
+ return unum(n);
+#elif HAVE_DOUBLE_INTPTR_T && CHAR_BIT * SIZEOF_DOUBLE_INTPTR >= 64
+ return normalize(bignum_dbl_uipt(n));
+#else
+ ucnum hi32 = n >> 32;
+ ucnum lo32 = n & 0xFFFFFFFFU;
+ return logior(ash(unum(hi32), num_fast(32)), unum(lo32));
+#endif
+}
+
#endif
char c_char(val n, val self)
diff --git a/itypes.h b/itypes.h
index 23fd5581..a2e38672 100644
--- a/itypes.h
+++ b/itypes.h
@@ -75,6 +75,10 @@ typedef long i64_t;
#define HAVE_I64 1
typedef ulonglong_t u64_t;
typedef longlong_t i64_t;
+#elif HAVE_DBL_INTPTR_T && (SIZEOF_DOUBLE_INTPTR * CHAR_BIT) == 64
+#define HAVE_I64 1
+typedef double_uintptr_t u64_t;
+typedef double_intptr_t i64_t;
#endif
#if HAVE_I8
@@ -95,6 +99,9 @@ u32_t c_u32(val, val self);
#if HAVE_I64
i64_t c_i64(val, val self);
u64_t c_u64(val, val self);
+
+val num_64(i64_t n);
+val unum_64(u64_t n);
#endif
char c_char(val, val self);