bit_counter 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|