summaryrefslogtreecommitdiffstats
path: root/arith.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-02-19 06:39:02 -0800
committerKaz Kylheku <kaz@kylheku.com>2019-02-19 06:39:02 -0800
commit15b7c542dc44899e8db7addfcc2f1c1c4a188b49 (patch)
tree3857de5f06aae8f5bf25acebe306920545fc7ee4 /arith.c
parent2b3179ea5e50778f1f19054b9d6d8aa06d683081 (diff)
downloadtxr-15b7c542dc44899e8db7addfcc2f1c1c4a188b49.tar.gz
txr-15b7c542dc44899e8db7addfcc2f1c1c4a188b49.tar.bz2
txr-15b7c542dc44899e8db7addfcc2f1c1c4a188b49.zip
mpi/arith: optimize "highest bit" with GCC builtins.
* arith.c (highest_bit): On GCC, use __builtin_clz. * mpi/mpi.c (s_highest_bit): Likewise.
Diffstat (limited to 'arith.c')
-rw-r--r--arith.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/arith.c b/arith.c
index f36c76ec..968d4a2c 100644
--- a/arith.c
+++ b/arith.c
@@ -268,7 +268,13 @@ val bignum_len(val num)
int highest_bit(int_ptr_t n)
{
-#if CHAR_BIT * SIZEOF_PTR == 64
+#if defined __GNUC__ && SIZEOF_PTR == SIZEOF_INT
+ return (n == 0) ? 0 : (CHAR_BIT * SIZEOF_PTR - __builtin_clz(n));
+#elif defined __GNUC__ && SIZEOF_PTR == SIZEOF_LONG
+ return (n == 0) ? 0 : (CHAR_BIT * SIZEOF_PTR - __builtin_clzl(n));
+#elif defined __GNUC__ && SIZEOF_PTR == SIZEOF_LONGLONG_T
+ return (n == 0) ? 0 : (CHAR_BIT * SIZEOF_PTR - __builtin_clzll(n));
+#elif CHAR_BIT * SIZEOF_PTR == 64
if (n & 0x7FFFFFFF00000000) {
if (n & 0x7FFF000000000000) {
if (n & 0x7F00000000000000) {