From 3d98741fa1bacf02f7fa74b477c1b9741e98d027 Mon Sep 17 00:00:00 2001
From: Marcus Comstedt <marcus@mc.pp.se>
Date: Sat, 30 May 2020 16:21:15 +0200
Subject: [PATCH] CritBit: Fix FloatTree with 128bit floats

---
 src/bitvector.h                              | 17 +++++++++++++++++
 src/post_modules/CritBit/critbit/key_float.h | 11 +++++++++--
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/src/bitvector.h b/src/bitvector.h
index c53fba1449..30763bf3e0 100644
--- a/src/bitvector.h
+++ b/src/bitvector.h
@@ -165,6 +165,23 @@ static INLINE unsigned INT64 ATTRIBUTE((unused)) bswap64(unsigned INT64 x) {
 }
 #endif /* !HAVE___BSWAP64 && !HAVE_BSWAP64 */
 
+#if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16
+/**
+ * Counts the number of leading zeros in a 128-bit unsigned
+ * integer. Returns a value between 0 and 128.
+ */
+static INLINE unsigned INT32 PIKE_UNUSED_ATTRIBUTE clz128(unsigned __int128 i) {
+# if SIZEOF_LONG == 16 && defined(HAS___BUILTIN_CLZL)
+    return i ? __builtin_clzl(i) : 128;
+# elif SIZEOF_LONG_LONG == 16 && defined(HAS___BUILTIN_CLZLL)
+    return i ? __builtin_clzll(i) : 128;
+# else
+    unsigned INT64 hi = i >> 64;
+    return hi? clz64(hi) : 64 + clz64((unsigned INT64)i);
+# endif
+}
+#endif /* __SIZEOF_INT128__ */
+
 static INLINE unsigned INT64 PIKE_UNUSED_ATTRIBUTE round_up64(unsigned INT64 v) {
     unsigned INT32 i;
 
diff --git a/src/post_modules/CritBit/critbit/key_float.h b/src/post_modules/CritBit/critbit/key_float.h
index 8eee37d159..3dd40f73ae 100644
--- a/src/post_modules/CritBit/critbit/key_float.h
+++ b/src/post_modules/CritBit/critbit/key_float.h
@@ -7,9 +7,14 @@
 #if SIZEOF_FLOAT_TYPE == 8
 typedef unsigned INT64 CB_NAME(string);
 typedef unsigned INT64 CB_NAME(char);
-#else
+#elif SIZEOF_FLOAT_TYPE == 4
 typedef unsigned INT32 CB_NAME(string);
 typedef unsigned INT32 CB_NAME(char);
+#elif SIZEOF_FLOAT_TYPE == 16 && defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16
+typedef unsigned __int128 CB_NAME(string);
+typedef unsigned __int128 CB_NAME(char);
+#else
+#error Size of FLOAT_TYPE not supported.
 #endif
 
 
@@ -26,8 +31,10 @@ typedef unsigned INT32 CB_NAME(char);
 #ifdef CB_SOURCE
 #if SIZEOF_FLOAT_TYPE == 4
 # define gclz(x) clz32(x)
-#else
+#elif SIZEOF_FLOAT_TYPE == 8
 # define gclz(x) clz64(x)
+#else
+# define gclz(x) clz128(x)
 #endif
 #define bitsof(x)	(sizeof(x)*8)
 #define int2float(x)	(*(FLOAT_TYPE*)&(x))
-- 
GitLab