summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-04-12 12:01:51 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-04-12 12:01:51 +0000
commit16a2acca20c3ddc0454331df4c6a0cd2a8a0807c (patch)
tree062957e8ec2437e353f2919ceb7dd03461da8efb /bignum.c
parent3da834800e40980d7a75b82cc1a3b1abd9539e99 (diff)
* bignum.c (ones): Use __builtin_popcountl if available.
* internal.h (GCC_VERSION_SINCE): Macro moved from pack.c. * pack.c: Include internal.h for GCC_VERSION_SINCE. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40262 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c30
1 files changed, 17 insertions, 13 deletions
diff --git a/bignum.c b/bignum.c
index 6236ff32f7..306231c0df 100644
--- a/bignum.c
+++ b/bignum.c
@@ -887,27 +887,31 @@ static void bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *mo
static inline int
ones(register unsigned long x)
{
-#if SIZEOF_LONG == 8
-# define MASK_55 0x5555555555555555UL
-# define MASK_33 0x3333333333333333UL
-# define MASK_0f 0x0f0f0f0f0f0f0f0fUL
+#if GCC_VERSION_SINCE(3, 4, 0)
+ return __builtin_popcountl(x);
#else
-# define MASK_55 0x55555555UL
-# define MASK_33 0x33333333UL
-# define MASK_0f 0x0f0f0f0fUL
-#endif
+# if SIZEOF_LONG == 8
+# define MASK_55 0x5555555555555555UL
+# define MASK_33 0x3333333333333333UL
+# define MASK_0f 0x0f0f0f0f0f0f0f0fUL
+# else
+# define MASK_55 0x55555555UL
+# define MASK_33 0x33333333UL
+# define MASK_0f 0x0f0f0f0fUL
+# endif
x -= (x >> 1) & MASK_55;
x = ((x >> 2) & MASK_33) + (x & MASK_33);
x = ((x >> 4) + x) & MASK_0f;
x += (x >> 8);
x += (x >> 16);
-#if SIZEOF_LONG == 8
+# if SIZEOF_LONG == 8
x += (x >> 32);
-#endif
+# endif
return (int)(x & 0x7f);
-#undef MASK_0f
-#undef MASK_33
-#undef MASK_55
+# undef MASK_0f
+# undef MASK_33
+# undef MASK_55
+#endif
}
static inline unsigned long