bit_counter 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -98
- data/Rakefile +1 -14
- data/bin/console +0 -0
- data/bin/setup +0 -0
- data/bit_counter.gemspec +2 -7
- data/lib/bit_counter.rb +3 -15
- data/lib/bit_counter/core_ext.rb +3 -9
- data/lib/bit_counter/version.rb +1 -1
- metadata +20 -28
- data/ext/bit_counter/big_pack.h +0 -14
- data/ext/bit_counter/bignum_in_ulong.h +0 -18
- data/ext/bit_counter/bit_counter.c +0 -172
- data/ext/bit_counter/bit_counter.h +0 -24
- data/ext/bit_counter/extconf.rb +0 -48
- data/ext/bit_counter/popcountl.h +0 -48
- data/lib/bit_counter/cruby.rb +0 -8
- data/lib/bit_counter/jruby.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3eed4de856b07637b20f84640b104a9168b19a0
|
4
|
+
data.tar.gz: 306c444ba3024ebbf67fee6b8637e83cf3eba707
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43b49e9041e956e3beab3442e134fc62be84227ce4310cb5a873aa4779384acd7d80c1b88a91c9eaaf2fcedd9089ae76a30145a621085e810391730cb6a4a755
|
7
|
+
data.tar.gz: 6003d335a50407c8761790f75b96488c68a00675267500d7721d51529c8621f49afe05a7b2fa25e7de739fce619f557e85864be0e26dc2efc49b998633f8f750
|
data/README.md
CHANGED
@@ -1,100 +1,5 @@
|
|
1
|
-
# BitCounter
|
1
|
+
# BitCounter is deprecated
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
Add this line to your application's Gemfile:
|
8
|
-
|
9
|
-
```ruby
|
10
|
-
gem 'bit_counter'
|
11
|
-
```
|
12
|
-
|
13
|
-
And then execute:
|
14
|
-
|
15
|
-
$ bundle
|
16
|
-
|
17
|
-
Or install it yourself as:
|
18
|
-
|
19
|
-
$ gem install bit_counter
|
20
|
-
|
21
|
-
## Usage
|
22
|
-
|
23
|
-
Module `BitCounter` appears after `require 'bit_counter'`.
|
24
|
-
|
25
|
-
`BitCounter.count(num)` returns bit count of `num`. (`num` must be `Integer` (`Fixnum` or `Bignum`); otherwise raises `TypeError`)
|
26
|
-
|
27
|
-
`BitCounter.count_fixnum(num)` and `BitCounter.count_bignum(num)` are provided, but directly using these are not recommended.
|
28
|
-
|
29
|
-
To use `Integer#bit_count`, `require 'bit_counter/core_ext'`. (This feature is not default behavior)
|
30
|
-
|
31
|
-
### for negative numbers
|
32
|
-
Theoretically, Ruby treats negative integers as if *infinite* 1-bits are leaded (`printf '%x', -1` gives `..f` ),
|
33
|
-
so counting 1 bits for negative numbers is meaningless.
|
34
|
-
|
35
|
-
In this implementation, `bit_count` for negative number counts *0* bits and negates the result. (distinguishing with positive version) Same in Ruby:
|
36
|
-
```rb
|
37
|
-
return -bit_count(~num) if num < 0
|
38
|
-
```
|
39
|
-
|
40
|
-
Note that both `bit_count(0)` and `bit_count(-1)` still return 0.
|
41
|
-
|
42
|
-
## Development
|
43
|
-
|
44
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
45
|
-
|
46
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
47
|
-
|
48
|
-
## Implementations
|
49
|
-
|
50
|
-
### JRuby
|
51
|
-
Java offers `Long.bitCount`, so simply calling this for `Fixnum`.
|
52
|
-
|
53
|
-
JRuby uses [`java.lang.BigInteger`](https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html) for Ruby's `Bignum`, which also has `bitCount()` method.
|
54
|
-
|
55
|
-
### CRuby & Rubinius
|
56
|
-
In C extensions, `Bignum` is converted to array of `long`, and bit is counted using loops.
|
57
|
-
Bit counting of `long` is done by using `POPCNT` instruction, if available.
|
58
|
-
|
59
|
-
### Limitations
|
60
|
-
This gem is mainly developed on x64 GCC environment, so in other environments it may not work or be slow.
|
61
|
-
|
62
|
-
Pull requests for other environments are welcome.
|
63
|
-
|
64
|
-
## Benchmark
|
65
|
-
Compared to `num.to_s(2).count('1')` (popular method for popcount in CRuby), this gem is 5x - 20x faster.
|
66
|
-
|
67
|
-
```
|
68
|
-
# for fixnum
|
69
|
-
user system total real
|
70
|
-
String 7.770000 0.000000 7.770000 ( 7.771210)
|
71
|
-
Arithmetic 4.950000 0.000000 4.950000 ( 4.953082)
|
72
|
-
Loop 9.860000 0.000000 9.860000 ( 9.863400)
|
73
|
-
Gem 0.610000 0.000000 0.610000 ( 0.612627)
|
74
|
-
|
75
|
-
# for bignum
|
76
|
-
for 280736 bits, 1000 times
|
77
|
-
user system total real
|
78
|
-
String 1.470000 0.030000 1.500000 ( 1.491823)
|
79
|
-
Pack 8.810000 0.000000 8.810000 ( 8.823835)
|
80
|
-
Gem 0.040000 0.000000 0.040000 ( 0.032927)
|
81
|
-
|
82
|
-
for 80 bits, 1000000 times
|
83
|
-
user system total real
|
84
|
-
String 0.820000 0.000000 0.820000 ( 0.827302)
|
85
|
-
Pack 3.860000 0.000000 3.860000 ( 3.869715)
|
86
|
-
Gem 0.160000 0.000000 0.160000 ( 0.150728)
|
87
|
-
|
88
|
-
```
|
89
|
-
|
90
|
-
(Done in Core i3 (with POPCNT instruction), Linux x64, Ruby 2.3.0)
|
91
|
-
|
92
|
-
## Contributing
|
93
|
-
|
94
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/jkr2255/bit_counter.
|
95
|
-
|
96
|
-
|
97
|
-
## License
|
98
|
-
|
99
|
-
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
3
|
+
[`BitUtils`](https://github.com/jkr2255/bit_utils) is released with more functionalities, please use it.
|
100
4
|
|
5
|
+
This gem is currently only a wrapper of `BitUtils` with older `BitCounter` interface.
|
data/Rakefile
CHANGED
@@ -2,17 +2,4 @@ require "bundler/gem_tasks"
|
|
2
2
|
require "rspec/core/rake_task"
|
3
3
|
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
5
|
-
|
6
|
-
if RUBY_PLATFORM =~ /java/
|
7
|
-
task :default => [:spec]
|
8
|
-
else
|
9
|
-
require "rake/extensiontask"
|
10
|
-
|
11
|
-
task :build => :compile
|
12
|
-
|
13
|
-
Rake::ExtensionTask.new("bit_counter") do |ext|
|
14
|
-
ext.lib_dir = "lib/bit_counter"
|
15
|
-
end
|
16
|
-
|
17
|
-
task :default => [:clobber, :compile, :spec]
|
18
|
-
end
|
5
|
+
task :default => [:spec]
|
data/bin/console
CHANGED
File without changes
|
data/bin/setup
CHANGED
File without changes
|
data/bit_counter.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Jkr2255"]
|
10
10
|
spec.email = ["magnesium.oxide.play@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{Calculate bit count (popcount, Hamming weight) faster in many environments.}
|
12
|
+
spec.summary = %q{Calculate bit count (popcount, Hamming weight) faster in many environments (deprecated).}
|
13
13
|
spec.homepage = "https://github.com/jkr2255/bit_counter"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
@@ -17,14 +17,9 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.bindir = "exe"
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
19
|
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.platform = 'java'
|
22
|
-
else
|
23
|
-
spec.extensions = ["ext/bit_counter/extconf.rb"]
|
24
|
-
end
|
20
|
+
spec.add_dependency 'bit_utils', '>= 0.1.1'
|
25
21
|
|
26
22
|
spec.add_development_dependency "bundler", "~> 1.11"
|
27
23
|
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
-
spec.add_development_dependency "rake-compiler"
|
29
24
|
spec.add_development_dependency "rspec", "~> 3.0"
|
30
25
|
end
|
data/lib/bit_counter.rb
CHANGED
@@ -1,14 +1,9 @@
|
|
1
1
|
require "bit_counter/version"
|
2
|
-
|
3
|
-
if RUBY_PLATFORM =~ /java/
|
4
|
-
require 'bit_counter/jruby'
|
5
|
-
else
|
6
|
-
require "bit_counter/bit_counter"
|
7
|
-
require 'bit_counter/cruby'
|
8
|
-
end
|
2
|
+
require 'bit_utils'
|
9
3
|
|
10
4
|
#
|
11
5
|
# module for bit counting
|
6
|
+
# @deprecated use `bit_utils`.
|
12
7
|
#
|
13
8
|
module BitCounter
|
14
9
|
|
@@ -22,13 +17,6 @@ module BitCounter
|
|
22
17
|
# @raise [TypeError] when non-Integer was given.
|
23
18
|
#
|
24
19
|
def count(num)
|
25
|
-
|
26
|
-
when Fixnum
|
27
|
-
count_fixnum(num)
|
28
|
-
when Bignum
|
29
|
-
count_bignum(num)
|
30
|
-
else
|
31
|
-
raise TypeError
|
32
|
-
end
|
20
|
+
BitUtils.popcount(num)
|
33
21
|
end
|
34
22
|
end
|
data/lib/bit_counter/core_ext.rb
CHANGED
@@ -1,21 +1,15 @@
|
|
1
|
-
require '
|
1
|
+
require 'bit_utils'
|
2
2
|
|
3
3
|
# :nodoc:
|
4
4
|
class Fixnum
|
5
|
-
#
|
6
|
-
# calling BitCounter.#count with self
|
7
|
-
#
|
8
5
|
def bit_count
|
9
|
-
|
6
|
+
BitUtils.popcount_fixnum(self)
|
10
7
|
end
|
11
8
|
end
|
12
9
|
|
13
10
|
# :nodoc:
|
14
11
|
class Bignum
|
15
|
-
#
|
16
|
-
# calling BitCounter.#count with self
|
17
|
-
#
|
18
12
|
def bit_count
|
19
|
-
|
13
|
+
BitUtils.popcount_bignum(self)
|
20
14
|
end
|
21
15
|
end
|
data/lib/bit_counter/version.rb
CHANGED
metadata
CHANGED
@@ -1,57 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bit_counter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jkr2255
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bit_utils
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
-
type: :
|
19
|
+
version: 0.1.1
|
20
|
+
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.1.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.11'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '1.11'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
42
|
+
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
47
|
+
version: '10.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
54
|
+
version: '10.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,8 +70,7 @@ description:
|
|
70
70
|
email:
|
71
71
|
- magnesium.oxide.play@gmail.com
|
72
72
|
executables: []
|
73
|
-
extensions:
|
74
|
-
- ext/bit_counter/extconf.rb
|
73
|
+
extensions: []
|
75
74
|
extra_rdoc_files: []
|
76
75
|
files:
|
77
76
|
- ".gitignore"
|
@@ -86,16 +85,8 @@ files:
|
|
86
85
|
- bin/console
|
87
86
|
- bin/setup
|
88
87
|
- bit_counter.gemspec
|
89
|
-
- ext/bit_counter/big_pack.h
|
90
|
-
- ext/bit_counter/bignum_in_ulong.h
|
91
|
-
- ext/bit_counter/bit_counter.c
|
92
|
-
- ext/bit_counter/bit_counter.h
|
93
|
-
- ext/bit_counter/extconf.rb
|
94
|
-
- ext/bit_counter/popcountl.h
|
95
88
|
- lib/bit_counter.rb
|
96
89
|
- lib/bit_counter/core_ext.rb
|
97
|
-
- lib/bit_counter/cruby.rb
|
98
|
-
- lib/bit_counter/jruby.rb
|
99
90
|
- lib/bit_counter/version.rb
|
100
91
|
homepage: https://github.com/jkr2255/bit_counter
|
101
92
|
licenses:
|
@@ -117,8 +108,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
108
|
version: '0'
|
118
109
|
requirements: []
|
119
110
|
rubyforge_project:
|
120
|
-
rubygems_version: 2.
|
111
|
+
rubygems_version: 2.6.4
|
121
112
|
signing_key:
|
122
113
|
specification_version: 4
|
123
|
-
summary: Calculate bit count (popcount, Hamming weight) faster in many environments
|
114
|
+
summary: Calculate bit count (popcount, Hamming weight) faster in many environments
|
115
|
+
(deprecated).
|
124
116
|
test_files: []
|
data/ext/bit_counter/big_pack.h
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#ifndef BIG_PACK_H
|
2
|
-
#define BIG_PACK_H 1
|
3
|
-
|
4
|
-
#ifdef HAVE_RB_BIG_PACK
|
5
|
-
#define BIG_PACK(val, ptr, cnt) rb_big_pack(val, ptr, cnt)
|
6
|
-
#elif defined(HAVE_RB_INTEGER_PACK)
|
7
|
-
#define BIG_PACK(val, ptr, cnt) rb_integer_pack(val, ptr, cnt, sizeof(long), 0, \
|
8
|
-
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER| \
|
9
|
-
INTEGER_PACK_2COMP)
|
10
|
-
#else
|
11
|
-
#error This Ruby is not supported.
|
12
|
-
#endif
|
13
|
-
|
14
|
-
#endif
|
@@ -1,18 +0,0 @@
|
|
1
|
-
#ifndef BIGNUM_IN_ULONG_H
|
2
|
-
#define BIGNUM_IN_ULONG_H 1
|
3
|
-
|
4
|
-
#ifdef HAVE_RB_ABSINT_NUMWORDS
|
5
|
-
#define BIGNUM_IN_ULONG(v) rb_absint_numwords(v, sizeof(unsigned long), NULL)
|
6
|
-
#else
|
7
|
-
static size_t BIGNUM_IN_ULONG(VALUE v){
|
8
|
-
static ID size_id = 0;
|
9
|
-
VALUE ret_val;
|
10
|
-
if(!size_id){
|
11
|
-
size_id = rb_intern("size");
|
12
|
-
}
|
13
|
-
ret_val = rb_funcall(v, size_id, 0);
|
14
|
-
return (NUM2SIZET(ret_val) + sizeof(unsigned long) - 1) / sizeof(unsigned long);
|
15
|
-
}
|
16
|
-
#endif
|
17
|
-
|
18
|
-
#endif
|
@@ -1,172 +0,0 @@
|
|
1
|
-
#include "bit_counter.h"
|
2
|
-
|
3
|
-
VALUE rb_mBitCounter;
|
4
|
-
|
5
|
-
static VALUE bitcounter_cimpl_count_fixnum(VALUE self, VALUE num){
|
6
|
-
long l_num = NUM2LONG(num);
|
7
|
-
int val = POPCOUNTL(l_num);
|
8
|
-
if(l_num < 0) val -= sizeof(long) * CHAR_BIT;
|
9
|
-
return INT2FIX(val);
|
10
|
-
}
|
11
|
-
|
12
|
-
#ifdef HAVE___GET_CPUID
|
13
|
-
static VALUE bitcounter_cimpl_cpu_popcnt_p(VALUE self){
|
14
|
-
unsigned int eax, ebx, ecx = 0, edx;
|
15
|
-
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
|
16
|
-
return (ecx & bit_POPCNT) ? Qtrue : Qfalse;
|
17
|
-
}
|
18
|
-
#else
|
19
|
-
static VALUE bitcounter_cimpl_cpu_popcnt_p(VALUE self){
|
20
|
-
return Qfalse;
|
21
|
-
}
|
22
|
-
#endif
|
23
|
-
|
24
|
-
#ifdef HAVE_POPCNT_GCC_ASM
|
25
|
-
static VALUE bitcounter_cimpl_count_fixnum_asm(VALUE self, VALUE num){
|
26
|
-
long l_num = NUM2LONG(num);
|
27
|
-
long val;
|
28
|
-
__asm__ volatile ("POPCNT %1, %0;": "=r"(val): "r"(l_num) : );
|
29
|
-
if(l_num < 0) val -= sizeof(long) * CHAR_BIT;
|
30
|
-
return INT2FIX(val);
|
31
|
-
}
|
32
|
-
#define ASM_POPCOUNT 1
|
33
|
-
#else
|
34
|
-
static VALUE bitcounter_cimpl_count_fixnum_asm(VALUE self, VALUE num){
|
35
|
-
/* dummy function for C compiler, never called from Ruby */
|
36
|
-
return Qnil;
|
37
|
-
}
|
38
|
-
#define ASM_POPCOUNT 0
|
39
|
-
#endif
|
40
|
-
|
41
|
-
/* for bignum */
|
42
|
-
static VALUE bitcounter_cimpl_count_bignum(VALUE self, VALUE num){
|
43
|
-
int negated = 0;
|
44
|
-
unsigned long * packed;
|
45
|
-
VALUE abs_num;
|
46
|
-
size_t words, i;
|
47
|
-
LONG_LONG ret = 0;
|
48
|
-
if(FIXNUM_P(num)){
|
49
|
-
return bitcounter_cimpl_count_fixnum(self, num);
|
50
|
-
}
|
51
|
-
Check_Type(num, T_BIGNUM);
|
52
|
-
if(RBIGNUM_NEGATIVE_P(num)){
|
53
|
-
negated = 1;
|
54
|
-
abs_num = BIG_NEG(num);
|
55
|
-
}else{
|
56
|
-
abs_num = num;
|
57
|
-
}
|
58
|
-
words = BIGNUM_IN_ULONG(abs_num);
|
59
|
-
if(words < ALLOCA_THRESHOLD){
|
60
|
-
packed = ALLOCA_N(unsigned long, words);
|
61
|
-
}else{
|
62
|
-
packed = ALLOC_N(unsigned long, words);
|
63
|
-
}
|
64
|
-
BIG_PACK(abs_num, packed, words);
|
65
|
-
for(i = 0; i < words; ++i){
|
66
|
-
ret += POPCOUNTL(packed[i]);
|
67
|
-
}
|
68
|
-
if(negated) ret = -ret;
|
69
|
-
if(words >= ALLOCA_THRESHOLD) xfree(packed);
|
70
|
-
return LL2NUM(ret);
|
71
|
-
}
|
72
|
-
|
73
|
-
#if defined(HAVE_POPCNT_LL_GCC_ASM) && (SIZEOF_LONG_LONG == SIZEOF_LONG * 2)
|
74
|
-
/* for Windows */
|
75
|
-
static VALUE bitcounter_cimpl_count_bignum_asm(VALUE self, VALUE num){
|
76
|
-
int negated = 0;
|
77
|
-
unsigned long * packed;
|
78
|
-
unsigned long long * ull_packed;
|
79
|
-
unsigned long long ull_i, ull_o = 0;
|
80
|
-
VALUE abs_num;
|
81
|
-
size_t words, i, ull_words;
|
82
|
-
LONG_LONG ret = 0;
|
83
|
-
if(FIXNUM_P(num)){
|
84
|
-
return bitcounter_cimpl_count_fixnum(self, num);
|
85
|
-
}
|
86
|
-
Check_Type(num, T_BIGNUM);
|
87
|
-
if(RBIGNUM_NEGATIVE_P(num)){
|
88
|
-
negated = 1;
|
89
|
-
abs_num = BIG_NEG(num);
|
90
|
-
}else{
|
91
|
-
abs_num = num;
|
92
|
-
}
|
93
|
-
words = BIGNUM_IN_ULONG(abs_num);
|
94
|
-
if(words < ALLOCA_THRESHOLD){
|
95
|
-
packed = ALLOCA_N(unsigned long, words);
|
96
|
-
}else{
|
97
|
-
packed = ALLOC_N(unsigned long, words);
|
98
|
-
}
|
99
|
-
BIG_PACK(abs_num, packed, words);
|
100
|
-
ull_words = words / 2;
|
101
|
-
ull_packed = (unsigned long long *) packed;
|
102
|
-
for(i = 0; i < ull_words; ++i){
|
103
|
-
ull_i = ull_packed[i];
|
104
|
-
__asm__ volatile ("POPCNT %1, %0;": "=r"(ull_o): "r"(ull_i) : );
|
105
|
-
ret += ull_o;
|
106
|
-
}
|
107
|
-
if(words & 1) ret += POPCOUNTL(packed[words-1]);
|
108
|
-
if(negated) ret = -ret;
|
109
|
-
if(words >= ALLOCA_THRESHOLD) xfree(packed);
|
110
|
-
return LL2NUM(ret);
|
111
|
-
}
|
112
|
-
|
113
|
-
#elif defined(HAVE_POPCNT_GCC_ASM)
|
114
|
-
static VALUE bitcounter_cimpl_count_bignum_asm(VALUE self, VALUE num){
|
115
|
-
int negated = 0;
|
116
|
-
unsigned long * packed;
|
117
|
-
unsigned long ul_i, ul_o = 0;
|
118
|
-
VALUE abs_num;
|
119
|
-
size_t words, i;
|
120
|
-
LONG_LONG ret = 0;
|
121
|
-
if(FIXNUM_P(num)){
|
122
|
-
return bitcounter_cimpl_count_fixnum(self, num);
|
123
|
-
}
|
124
|
-
Check_Type(num, T_BIGNUM);
|
125
|
-
if(RBIGNUM_NEGATIVE_P(num)){
|
126
|
-
negated = 1;
|
127
|
-
abs_num = BIG_NEG(num);
|
128
|
-
}else{
|
129
|
-
abs_num = num;
|
130
|
-
}
|
131
|
-
words = BIGNUM_IN_ULONG(abs_num);
|
132
|
-
if(words < ALLOCA_THRESHOLD){
|
133
|
-
packed = ALLOCA_N(unsigned long, words);
|
134
|
-
}else{
|
135
|
-
packed = ALLOC_N(unsigned long, words);
|
136
|
-
}
|
137
|
-
BIG_PACK(abs_num, packed, words);
|
138
|
-
for(i = 0; i < words; ++i){
|
139
|
-
ul_i = packed[i];
|
140
|
-
__asm__ volatile ("POPCNT %1, %0;": "=r"(ul_o): "r"(ul_i) : );
|
141
|
-
ret += ul_o;
|
142
|
-
}
|
143
|
-
if(negated) ret = -ret;
|
144
|
-
if(words >= ALLOCA_THRESHOLD) xfree(packed);
|
145
|
-
return LL2NUM(ret);
|
146
|
-
}
|
147
|
-
#else
|
148
|
-
static VALUE bitcounter_cimpl_count_bignum_asm(VALUE self, VALUE num){
|
149
|
-
/* dummy function for C compiler, never called from Ruby */
|
150
|
-
return Qnil;
|
151
|
-
}
|
152
|
-
|
153
|
-
#endif
|
154
|
-
|
155
|
-
|
156
|
-
void
|
157
|
-
Init_bit_counter(void)
|
158
|
-
{
|
159
|
-
VALUE rb_mCImpl;
|
160
|
-
VALUE have_cpu_popcnt;
|
161
|
-
rb_mBitCounter = rb_define_module("BitCounter");
|
162
|
-
rb_mCImpl = rb_define_module_under(rb_mBitCounter, "CImpl");
|
163
|
-
have_cpu_popcnt = bitcounter_cimpl_cpu_popcnt_p(rb_mCImpl);
|
164
|
-
rb_define_module_function(rb_mCImpl, "cpu_popcnt?", bitcounter_cimpl_cpu_popcnt_p, 0);
|
165
|
-
if(ASM_POPCOUNT && have_cpu_popcnt){
|
166
|
-
rb_define_method(rb_mCImpl, "count_fixnum", bitcounter_cimpl_count_fixnum_asm, 1);
|
167
|
-
rb_define_method(rb_mCImpl, "count_bignum", bitcounter_cimpl_count_bignum_asm, 1);
|
168
|
-
}else{
|
169
|
-
rb_define_method(rb_mCImpl, "count_fixnum", bitcounter_cimpl_count_fixnum, 1);
|
170
|
-
rb_define_method(rb_mCImpl, "count_bignum", bitcounter_cimpl_count_bignum, 1);
|
171
|
-
}
|
172
|
-
}
|
@@ -1,24 +0,0 @@
|
|
1
|
-
#ifndef BIT_COUNTER_H
|
2
|
-
#define BIT_COUNTER_H 1
|
3
|
-
|
4
|
-
#include "ruby.h"
|
5
|
-
|
6
|
-
#include <limits.h>
|
7
|
-
|
8
|
-
#ifdef HAVE_CPUID_H
|
9
|
-
#include <cpuid.h>
|
10
|
-
#endif
|
11
|
-
|
12
|
-
#include "popcountl.h"
|
13
|
-
#include "bignum_in_ulong.h"
|
14
|
-
#include "big_pack.h"
|
15
|
-
|
16
|
-
#ifdef HAVE_RB_BIG_XOR
|
17
|
-
#define BIG_NEG(val) rb_big_xor(val, INT2FIX(-1))
|
18
|
-
#else
|
19
|
-
#define BIG_NEG(val) rb_funcall(val, rb_intern("~"), 0)
|
20
|
-
#endif
|
21
|
-
|
22
|
-
#define ALLOCA_THRESHOLD (8192 / sizeof(unsigned long))
|
23
|
-
|
24
|
-
#endif /* BIT_COUNTER_H */
|
data/ext/bit_counter/extconf.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
require "mkmf"
|
2
|
-
|
3
|
-
have_func('__builtin_popcountl(1)')
|
4
|
-
have_func('rb_absint_numwords')
|
5
|
-
have_func('rb_big_pack')
|
6
|
-
have_func('rb_integer_pack')
|
7
|
-
have_func('rb_big_xor')
|
8
|
-
have_header('cpuid.h') && have_func('__get_cpuid', 'cpuid.h')
|
9
|
-
check_sizeof('long')
|
10
|
-
check_sizeof('long long')
|
11
|
-
message 'checking for usability of POPCNT in GCC-style inline assembler... '
|
12
|
-
gcc_popcount = try_compile <<SRC
|
13
|
-
int main(){
|
14
|
-
long a=1, b=2;
|
15
|
-
__asm__ volatile ("POPCNT %1, %0;"
|
16
|
-
:"=r"(b)
|
17
|
-
:"r"(a)
|
18
|
-
:
|
19
|
-
);
|
20
|
-
return 0;
|
21
|
-
}
|
22
|
-
SRC
|
23
|
-
if gcc_popcount
|
24
|
-
message "yes\n"
|
25
|
-
$defs << '-DHAVE_POPCNT_GCC_ASM'
|
26
|
-
message 'checking for usability of POPCNT for long long in GCC-style inline assembler... '
|
27
|
-
gcc_ll_popcount = try_compile <<SRC
|
28
|
-
int main(){
|
29
|
-
long long a=1, b=2;
|
30
|
-
__asm__ volatile ("POPCNT %1, %0;"
|
31
|
-
:"=r"(b)
|
32
|
-
:"r"(a)
|
33
|
-
:
|
34
|
-
);
|
35
|
-
return 0;
|
36
|
-
}
|
37
|
-
SRC
|
38
|
-
if gcc_ll_popcount
|
39
|
-
message "yes\n"
|
40
|
-
$defs << '-DHAVE_POPCNT_LL_GCC_ASM'
|
41
|
-
else
|
42
|
-
message "no\n"
|
43
|
-
end
|
44
|
-
else
|
45
|
-
message "no\n"
|
46
|
-
end
|
47
|
-
|
48
|
-
create_makefile("bit_counter/bit_counter")
|
data/ext/bit_counter/popcountl.h
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
/* header for long popcount (without CPU-native) */
|
2
|
-
|
3
|
-
#ifndef POPCOUNTL_H
|
4
|
-
#define POPCOUNTL_H 1
|
5
|
-
|
6
|
-
#ifdef HAVE___BUILTIN_POPCOUNTL
|
7
|
-
#define POPCOUNTL(x) __builtin_popcountl(x)
|
8
|
-
#elif SIZEOF_LONG == 8
|
9
|
-
static inline int POPCOUNTL(unsigned long x){
|
10
|
-
x = ((x & 0xaaaaaaaaaaaaaaaaUL) >> 1)
|
11
|
-
+ (x & 0x5555555555555555UL);
|
12
|
-
x = ((x & 0xccccccccccccccccUL) >> 2)
|
13
|
-
+ (x & 0x3333333333333333UL);
|
14
|
-
x = ((x & 0xf0f0f0f0f0f0f0f0UL) >> 4)
|
15
|
-
+ (x & 0x0f0f0f0f0f0f0f0fUL);
|
16
|
-
x = ((x & 0xff00ff00ff00ff00UL) >> 8)
|
17
|
-
+ (x & 0x00ff00ff00ff00ffUL);
|
18
|
-
x = ((x & 0xffff0000ffff0000UL) >> 16)
|
19
|
-
+ (x & 0x0000ffff0000ffffUL);
|
20
|
-
x = ((x & 0xffffffff00000000UL) >> 32)
|
21
|
-
+ (x & 0x00000000ffffffffUL);
|
22
|
-
return (int) x;
|
23
|
-
}
|
24
|
-
#elif SIZEOF_LONG == 4
|
25
|
-
static inline int POPCOUNTL(unsigned long x){
|
26
|
-
x = ((x & 0xaaaaaaaaUL) >> 1)
|
27
|
-
+ (x & 0x55555555UL);
|
28
|
-
x = ((x & 0xccccccccUL) >> 2)
|
29
|
-
+ (x & 0x33333333UL);
|
30
|
-
x = ((x & 0xf0f0f0f0UL) >> 4)
|
31
|
-
+ (x & 0x0f0f0f0fUL);
|
32
|
-
x = ((x & 0xff00ff00UL) >> 8)
|
33
|
-
+ (x & 0x00ff00ffUL);
|
34
|
-
x = ((x & 0xffff0000UL) >> 16)
|
35
|
-
+ (x & 0x0000ffffUL);
|
36
|
-
return (int) x;
|
37
|
-
}
|
38
|
-
#else
|
39
|
-
#error Unsupported architecture
|
40
|
-
#endif
|
41
|
-
|
42
|
-
#if SIZEOF_LONG == 8
|
43
|
-
#define BER_MASK 0x7f7f7f7f7f7f7f7fUL
|
44
|
-
#elif SIZEOF_LONG == 4
|
45
|
-
#define BER_MASK 0x7f7f7f7fUL
|
46
|
-
#endif
|
47
|
-
|
48
|
-
#endif
|
data/lib/bit_counter/cruby.rb
DELETED
data/lib/bit_counter/jruby.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'java'
|
2
|
-
|
3
|
-
#
|
4
|
-
# module for bit counting
|
5
|
-
#
|
6
|
-
module BitCounter
|
7
|
-
|
8
|
-
#
|
9
|
-
# module for Java-specific codes of BitCounter.
|
10
|
-
# @note not intended for direct use.
|
11
|
-
#
|
12
|
-
module JavaImpl
|
13
|
-
def count_fixnum(num)
|
14
|
-
raise TypeError unless num.is_a?(::Fixnum)
|
15
|
-
count = Java::JavaLang::Long.bitCount(num)
|
16
|
-
num >= 0 ? count : count - 64
|
17
|
-
end
|
18
|
-
|
19
|
-
def count_bignum(num)
|
20
|
-
raise TypeError unless num.is_a?(::Bignum)
|
21
|
-
count = num.to_java.bitCount
|
22
|
-
num >= 0 ? count : -count
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
extend JavaImpl
|
27
|
-
|
28
|
-
end
|