bitcount 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 00044fb7d9178864fb0805b0ca619c0e52aca752f2300114cc31b49535bb8c50
4
+ data.tar.gz: 6edadce559de31f3620cb84c15129462fb4e7657d48dd7350a4ec822467ead89
5
+ SHA512:
6
+ metadata.gz: 71ffad74ea1e03ced6f59c74086f2682c6f034f339bfcc1f12f27c308f46e6485902221902255a75a07c230cdc485ddc1bc4101ac201cdfe7a727e44c2a8087f
7
+ data.tar.gz: f351d06612197586fdd763ef2a843d581176342e8091025f5107a31f4e4fae42c1cf39e677843f806e9900785dceda7f15cf6ddaabff0925658a758ab0007e80
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /ext/Makefile
10
+ /lib/bitcount_ext
11
+ Gemfile.lock
12
+ *.gem
13
+
14
+ # rspec failure tracking
15
+ .rspec_status
16
+ /nbproject
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,32 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+
5
+ script: bundle exec rake test
6
+
7
+ rvm:
8
+ - 2.3
9
+ - 2.7
10
+ - jruby-9.2.9.0
11
+ - truffleruby
12
+ - ruby-head
13
+ - jruby-head
14
+
15
+ matrix:
16
+ include:
17
+ - name: benchmark-ruby
18
+ rvm: 2.7
19
+ script:
20
+ - bundle exec rake compile:bitcount_ext
21
+ - bundle exec ruby -S benchmark-driver benchmark/bitcount.yml
22
+ - name: benchmark-jruby
23
+ rvm: jruby-head
24
+ script:
25
+ - bundle exec rake compile:bitcount_ext
26
+ - bundle exec ruby -S benchmark-driver benchmark/bitcount.yml
27
+ allow_failures:
28
+ - rvm: ruby-head
29
+ - rvm: jruby-head
30
+ - rvm: truffleruby
31
+ - name: benchmark-ruby
32
+ - name: benchmark-jruby
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. For info on how to format all future additions to this file please reference [Keep A Changelog](https://keepachangelog.com/en/1.0.0/).
4
+
5
+ ## [0.1.1] - Unreleased
6
+
7
+ ## [0.1.0] - 2020-02-09
8
+ ### Added
9
+ - init
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in bitcount.gemspec
4
+ gemspec
5
+
6
+ gem "rake"
7
+ gem "rspec"
8
+ gem "benchmark_driver"
9
+ gem "rake-compiler"
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Pavel Rosický
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # Bitcount
2
+
3
+ __builtin_popcount - Returns the number of 1 bits
4
+ ```ruby
5
+ 1 => 00000000000000000000000000000001 => 1
6
+ 2147483648 => 10000000000000000000000000000000 => 1
7
+ 2147500033 => 10000000000000000100000000000001 => 3
8
+ ```
9
+
10
+ __builtin_clz - Returns leading zeros
11
+
12
+ ```ruby
13
+ 1 => 00000000000000000000000000000001 => 31
14
+ 2147483648 => 10000000000000000000000000000000 => 0
15
+ 2147500033 => 10000000000000000100000000000001 => 0
16
+ ```
17
+
18
+ __builtin_ctz - Returns trailing zeros
19
+
20
+ ```ruby
21
+ 1 => 00000000000000000000000000000001 => 0
22
+ 2147483648 => 10000000000000000000000000000000 => 31
23
+ 2147500033 => 10000000000000000100000000000001 => 0
24
+ ```
25
+
26
+ ## Installation
27
+
28
+ Add this line to your application's Gemfile:
29
+
30
+ ```ruby
31
+ gem 'bitcount'
32
+ ```
33
+
34
+ And then execute:
35
+
36
+ $ bundle install
37
+
38
+ Or install it yourself as:
39
+
40
+ $ gem install bitcount
41
+
42
+ ## Usage
43
+ ```ruby
44
+ require 'bitcount'
45
+ Bitcount.popcount(1)
46
+ => 1
47
+
48
+ Bitcount.nlz(1)
49
+ => 63
50
+
51
+ Bitcount.ntz(1)
52
+ => 0
53
+ ```
54
+
55
+ or
56
+
57
+ ```ruby
58
+ require 'bitcount/integer'
59
+ 1.popcount
60
+ => 1
61
+
62
+ 1.nlz
63
+ => 63
64
+
65
+ 1.ntz
66
+ => 0
67
+ ```
68
+
69
+ you can specify a different layout, but if the layout doesn't match your platform a slower version will be used
70
+ ```ruby
71
+ 1.nlz(32)
72
+ => 31
73
+
74
+ Bitcount::Native.layout_size
75
+ => 64
76
+ ```
77
+
78
+ ## Contributing
79
+
80
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ahorek/bitcount.
81
+
82
+
83
+ ## License
84
+
85
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+ require 'rake/extensiontask'
6
+
7
+ gem_spec = Gem::Specification.load("bitcount.gemspec")
8
+
9
+ module FixRequiredRubyVersion
10
+ def required_ruby_version=(*); end
11
+ end
12
+ Gem::Specification.send(:prepend, FixRequiredRubyVersion)
13
+
14
+ Rake::ExtensionTask.new('bitcount_ext', gem_spec) do |ext|
15
+ ext.name = 'bitcount_ext'
16
+ ext.ext_dir = 'ext'
17
+ ext.lib_dir = 'lib/bitcount_ext'
18
+ end
19
+
20
+ CLEAN.include 'lib/bitcount_ext/bitcount_ext.{so,bundle,dll}',
21
+ 'ext/*.{o,so,bundle,dll}', 'ext/Makefile', 'tmp'
22
+
23
+ RSpec::Core::RakeTask.new(:spec)
24
+ task test: 'compile:bitcount_ext' do
25
+ Rake::Task['spec'].invoke
26
+ end
27
+ task default: :test
@@ -0,0 +1,8 @@
1
+ prelude: require 'bitcount'
2
+ benchmark:
3
+ native_popcount: Bitcount::Native.popcount(122)
4
+ native_nlz: Bitcount::Native.nlz(122)
5
+ native_ntz: Bitcount::Native.ntz(122)
6
+ ruby_popcount: Bitcount::Pure.popcount(122)
7
+ ruby_nlz: Bitcount::Pure.nlz(122)
8
+ ruby_ntz: Bitcount::Pure.ntz(122)
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "bitcount"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/bitcount.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ require_relative 'lib/bitcount/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "bitcount"
5
+ spec.version = Bitcount::VERSION
6
+ spec.authors = ["Pavel Rosický"]
7
+ spec.email = ["pdahorek@seznam.cz"]
8
+
9
+ spec.summary = %q{Bitcount helper methods.}
10
+ spec.homepage = "https://github.com/ahorek/bitcount"
11
+ spec.license = "MIT"
12
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
13
+
14
+ spec.metadata["homepage_uri"] = spec.homepage
15
+ spec.metadata["source_code_uri"] = spec.homepage
16
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGELOG.md"
17
+
18
+ spec.platform = Gem::Platform::RUBY
19
+ spec.extensions = ["ext/extconf.rb"]
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
25
+ end
26
+ spec.require_paths = ["lib", "lib/bitcount"]
27
+
28
+ spec.add_runtime_dependency 'ffi'
29
+ end
@@ -0,0 +1,28 @@
1
+ #include <limits.h>
2
+ #include <stdint.h>
3
+ #include <stddef.h>
4
+
5
+ #ifndef GCC_VERSION_SINCE
6
+ # if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
7
+ # define GCC_VERSION_SINCE(major, minor, patchlevel) \
8
+ ((__GNUC__ > (major)) || \
9
+ ((__GNUC__ == (major) && \
10
+ ((__GNUC_MINOR__ > (minor)) || \
11
+ (__GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel))))))
12
+ # else
13
+ # define GCC_VERSION_SINCE(major, minor, patchlevel) 0
14
+ # endif
15
+ #endif
16
+
17
+ #ifndef __has_builtin
18
+ #if GCC_VERSION_SINCE(4, 8, 0)
19
+ # define __has_builtin(x) 1
20
+ # else
21
+ # define __has_builtin(x) 0
22
+ #endif
23
+ #endif
24
+
25
+ size_t ext_layout();
26
+ size_t ext_popcount(size_t x);
27
+ size_t ext_nlz(size_t x);
28
+ size_t ext_ntz(size_t x);
@@ -0,0 +1,46 @@
1
+ #include "bitcount_ext.h"
2
+ #include "helpers.c"
3
+
4
+ size_t ext_layout()
5
+ {
6
+ return sizeof(size_t) * CHAR_BIT;
7
+ }
8
+
9
+ size_t ext_popcount(size_t x)
10
+ {
11
+ if (sizeof(size_t) * CHAR_BIT == 64) {
12
+ return ext_popcount64((uint64_t)x);
13
+ }
14
+ else if (sizeof(size_t) * CHAR_BIT == 32) {
15
+ return ext_popcount32((uint32_t)x);
16
+ }
17
+ else {
18
+ __builtin_unreachable();
19
+ }
20
+ }
21
+
22
+ size_t ext_nlz(size_t x)
23
+ {
24
+ if (sizeof(size_t) * CHAR_BIT == 32) {
25
+ return nlz_int32((uint32_t)x);
26
+ }
27
+ else if (sizeof(size_t) * CHAR_BIT == 64) {
28
+ return nlz_int64((uint64_t)x);
29
+ }
30
+ else {
31
+ __builtin_unreachable();
32
+ }
33
+ }
34
+
35
+ size_t ext_ntz(size_t x)
36
+ {
37
+ if (sizeof(size_t) * CHAR_BIT == 64) {
38
+ return ntz_int64((uint64_t)x);
39
+ }
40
+ else if (sizeof(size_t) * CHAR_BIT == 32) {
41
+ return ntz_int32((uint32_t)x);
42
+ }
43
+ else {
44
+ __builtin_unreachable();
45
+ }
46
+ }
@@ -0,0 +1,114 @@
1
+ unsigned int ext_popcount64(uint64_t x)
2
+ {
3
+ #if __has_builtin(__builtin_popcount)
4
+ if (sizeof(long) * CHAR_BIT == 64) {
5
+ return (unsigned int)__builtin_popcountl((unsigned long)x);
6
+ }
7
+ else if (sizeof(long long) * CHAR_BIT == 64) {
8
+ return (unsigned int)__builtin_popcountll((unsigned long long)x);
9
+ }
10
+ else {
11
+ __builtin_unreachable();
12
+ }
13
+ #else
14
+ x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
15
+ x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
16
+ x = (x & 0x0707070707070707) + (x >> 4 & 0x0707070707070707);
17
+ x = (x & 0x001f001f001f001f) + (x >> 8 & 0x001f001f001f001f);
18
+ x = (x & 0x0000003f0000003f) + (x >>16 & 0x0000003f0000003f);
19
+ x = (x & 0x000000000000007f) + (x >>32 & 0x000000000000007f);
20
+ return (unsigned int)x;
21
+
22
+ #endif
23
+ }
24
+
25
+ unsigned int ext_popcount32(uint32_t x)
26
+ {
27
+ #if __has_builtin(__builtin_popcount)
28
+ return (unsigned int)__builtin_popcount(x);
29
+
30
+ #else
31
+ x = (x & 0x55555555) + (x >> 1 & 0x55555555);
32
+ x = (x & 0x33333333) + (x >> 2 & 0x33333333);
33
+ x = (x & 0x0f0f0f0f) + (x >> 4 & 0x0f0f0f0f);
34
+ x = (x & 0x001f001f) + (x >> 8 & 0x001f001f);
35
+ x = (x & 0x0000003f) + (x >>16 & 0x0000003f);
36
+ return (unsigned int)x;
37
+ #endif
38
+ }
39
+
40
+ unsigned int nlz_int32(uint32_t x)
41
+ {
42
+ #if __has_builtin(__builtin_clz)
43
+ return (unsigned int)__builtin_clz(x);
44
+
45
+ #else
46
+ uint32_t y;
47
+ unsigned n = 32;
48
+ y = x >> 16; if (y) {n -= 16; x = y;}
49
+ y = x >> 8; if (y) {n -= 8; x = y;}
50
+ y = x >> 4; if (y) {n -= 4; x = y;}
51
+ y = x >> 2; if (y) {n -= 2; x = y;}
52
+ y = x >> 1; if (y) {return n - 2;}
53
+ return (unsigned int)(n - x);
54
+ #endif
55
+ }
56
+
57
+ unsigned int nlz_int64(uint64_t x)
58
+ {
59
+ #if __has_builtin(__builtin_clzl)
60
+ if (x == 0) {
61
+ return 64;
62
+ }
63
+ else if (sizeof(long) * CHAR_BIT == 64) {
64
+ return (unsigned int)__builtin_clzl((unsigned long)x);
65
+ }
66
+ else if (sizeof(long long) * CHAR_BIT == 64) {
67
+ return (unsigned int)__builtin_clzll((unsigned long long)x);
68
+ }
69
+ else {
70
+ __builtin_unreachable();
71
+ }
72
+
73
+ #else
74
+ uint64_t y;
75
+ unsigned int n = 64;
76
+ y = x >> 32; if (y) {n -= 32; x = y;}
77
+ y = x >> 16; if (y) {n -= 16; x = y;}
78
+ y = x >> 8; if (y) {n -= 8; x = y;}
79
+ y = x >> 4; if (y) {n -= 4; x = y;}
80
+ y = x >> 2; if (y) {n -= 2; x = y;}
81
+ y = x >> 1; if (y) {return n - 2;}
82
+ return (unsigned int)(n - x);
83
+
84
+ #endif
85
+ }
86
+
87
+ unsigned int ntz_int32(uint32_t x)
88
+ {
89
+ #if __has_builtin(__builtin_ctz)
90
+ return (unsigned)__builtin_ctz(x);
91
+ #else
92
+ return ext_popcount32((~x) & (x-1));
93
+ #endif
94
+ }
95
+
96
+ unsigned int ntz_int64(uint64_t x)
97
+ {
98
+ #if __has_builtin(__builtin_ctzl)
99
+ if (x == 0) {
100
+ return 64;
101
+ }
102
+ else if (sizeof(long) * CHAR_BIT == 64) {
103
+ return (unsigned)__builtin_ctzl((unsigned long)x);
104
+ }
105
+ else if (sizeof(long long) * CHAR_BIT == 64) {
106
+ return (unsigned)__builtin_ctzll((unsigned long long)x);
107
+ }
108
+ else {
109
+ __builtin_unreachable();
110
+ }
111
+ #else
112
+ return ext_popcount64((~x) & (x-1));
113
+ #endif
114
+ }
data/ext/depend ADDED
@@ -0,0 +1 @@
1
+ $(OBJS): $(HDRS)
data/ext/extconf.rb ADDED
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mkmf'
4
+
5
+ $CFLAGS << ' -std=c99'
6
+
7
+ if enable_config('march-tune-native', false)
8
+ $CFLAGS << ' -march=native -mtune=native'
9
+ end
10
+
11
+ if enable_config('lto', false)
12
+ $CFLAGS << ' -flto'
13
+ $LDFLAGS << ' -flto'
14
+ end
15
+
16
+ $warnflags = ''
17
+ $CFLAGS.gsub!(/[\s+](-ansi|-std=[^\s]+)/, '')
18
+
19
+ dir_config 'bitcount_ext'
20
+
21
+ $INCFLAGS << " -I$(srcdir)/bitcount_ext/include"
22
+ $VPATH << "$(srcdir)/bitcount_ext/src"
23
+ Dir.chdir(__dir__) do
24
+ $VPATH += Dir['bitcount_ext/src/*/'].map { |p| "$(srcdir)/#{p}" }
25
+ $srcs = Dir['bitcount_ext/src/bitcount_ext.c']
26
+ end
27
+
28
+ $LIBRUBYARG = nil
29
+ MakeMakefile::LINK_SO << "\nstrip -x $@"
30
+
31
+ MakeMakefile.send(:remove_const, :EXPORT_PREFIX)
32
+ MakeMakefile::EXPORT_PREFIX = nil
33
+
34
+ create_makefile 'bitcount/bitcount_ext'
data/lib/bitcount.rb ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bitcount/version"
4
+ require "bitcount/pure"
5
+ begin
6
+ require "bitcount/native"
7
+ rescue LoadError
8
+ puts 'bitcount_ext not loaded'
9
+ end
10
+
11
+ module Bitcount
12
+ class << self
13
+ def popcount(n)
14
+ type_error unless n.is_a?(Integer)
15
+ negative_error if n < 0
16
+ implementation.popcount(n)
17
+ end
18
+
19
+ def ntz(n, size = nil)
20
+ type_error unless n.is_a?(Integer)
21
+ negative_error if n < 0
22
+ implementation.ntz(n, size)
23
+ end
24
+
25
+ def nlz(n, size = nil)
26
+ type_error unless n.is_a?(Integer)
27
+ negative_error if n < 0
28
+ implementation.nlz(n, size)
29
+ end
30
+
31
+ private
32
+
33
+ def implementation
34
+ defined?(:"Bitcount::Native") ? Bitcount::Native : Bitcount::Pure
35
+ end
36
+
37
+ def type_error
38
+ raise TypeError, 'not a number'
39
+ end
40
+
41
+ def negative_error
42
+ raise ArgumentError, 'number is negative'
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bitcount"
4
+
5
+ class Integer
6
+ def popcount
7
+ Bitcount.popcount(self)
8
+ end
9
+
10
+ def ntz(size = nil)
11
+ Bitcount.ntz(self, size)
12
+ end
13
+
14
+ def nlz(size = nil)
15
+ Bitcount.nlz(self, size)
16
+ end
17
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ffi"
4
+
5
+ module Bitcount
6
+ module Native
7
+ class << self
8
+ extend FFI::Library
9
+
10
+ dl_ext = RbConfig::MAKEFILE_CONFIG['DLEXT']
11
+ begin
12
+ ffi_lib File.expand_path("../bitcount_ext/bitcount_ext.#{dl_ext}", __dir__)
13
+ rescue LoadError
14
+ ffi_lib File.expand_path("bitcount_ext.#{dl_ext}", "#{__dir__}/../../ext")
15
+ end
16
+
17
+ attach_function :ext_layout, [], :size_t
18
+ attach_function :ext_popcount, [:size_t], :size_t
19
+ attach_function :ext_nlz, [:size_t], :size_t
20
+ attach_function :ext_ntz, [:size_t], :size_t
21
+
22
+ def layout_size
23
+ ext_layout
24
+ rescue
25
+ 64
26
+ end
27
+
28
+ def popcount(n)
29
+ return Bitcount::Pure.popcount(n) if defined?(JRUBY_VERSION) && n > max_value
30
+ begin
31
+ ext_popcount(n)
32
+ rescue
33
+ Bitcount::Pure.popcount(n)
34
+ end
35
+ end
36
+
37
+ def ntz(n, size = nil)
38
+ size ||= layout_size
39
+ return Bitcount::Pure.ntz(n, size) if layout_size != size || (defined?(JRUBY_VERSION) && n > max_value)
40
+ begin
41
+ ext_ntz(n)
42
+ rescue
43
+ Bitcount::Pure.ntz(n, size)
44
+ end
45
+ end
46
+
47
+ def nlz(n, size = nil)
48
+ size ||= layout_size
49
+ return Bitcount::Pure.nlz(n, size) if layout_size != size || (defined?(JRUBY_VERSION) && n > max_value)
50
+ begin
51
+ ext_nlz(n)
52
+ rescue
53
+ Bitcount::Pure.nlz(n, size)
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def max_value
60
+ (2 ** layout_size) - 1
61
+ end
62
+
63
+ def layout_error
64
+ raise RangeError, 'number is too large'
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bitcount
4
+ module Pure
5
+ class << self
6
+ def layout_size
7
+ 64
8
+ end
9
+
10
+ def popcount(n)
11
+ n.to_s(2).count("1")
12
+ end
13
+
14
+ def ntz(n, size = nil)
15
+ size ||= layout_size
16
+ count = 0
17
+ bits = n.to_s(2)
18
+ layout_error if bits.size > size
19
+ bits.rjust(size, "0").reverse.each_char do |b|
20
+ (b == '0') ? count += 1 : break
21
+ end
22
+ count
23
+ end
24
+
25
+ def nlz(n, size = nil)
26
+ size ||= layout_size
27
+ count = 0
28
+ bits = n.to_s(2)
29
+ layout_error if bits.size > size
30
+ bits.rjust(size, "0").each_char do |b|
31
+ (b == '0') ? count += 1 : break
32
+ end
33
+ count
34
+ end
35
+
36
+ private
37
+
38
+ def layout_error
39
+ raise RangeError, 'number is too large'
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ module Bitcount
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bitcount
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Pavel Rosický
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description:
28
+ email:
29
+ - pdahorek@seznam.cz
30
+ executables: []
31
+ extensions:
32
+ - ext/extconf.rb
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".gitignore"
36
+ - ".rspec"
37
+ - ".travis.yml"
38
+ - CHANGELOG.md
39
+ - Gemfile
40
+ - LICENSE.txt
41
+ - README.md
42
+ - Rakefile
43
+ - benchmark/bitcount.yml
44
+ - bin/console
45
+ - bin/setup
46
+ - bitcount.gemspec
47
+ - ext/bitcount_ext/include/bitcount_ext.h
48
+ - ext/bitcount_ext/src/bitcount_ext.c
49
+ - ext/bitcount_ext/src/helpers.c
50
+ - ext/depend
51
+ - ext/extconf.rb
52
+ - lib/bitcount.rb
53
+ - lib/bitcount/integer.rb
54
+ - lib/bitcount/native.rb
55
+ - lib/bitcount/pure.rb
56
+ - lib/bitcount/version.rb
57
+ homepage: https://github.com/ahorek/bitcount
58
+ licenses:
59
+ - MIT
60
+ metadata:
61
+ homepage_uri: https://github.com/ahorek/bitcount
62
+ source_code_uri: https://github.com/ahorek/bitcount
63
+ changelog_uri: https://github.com/ahorek/bitcount/CHANGELOG.md
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ - lib/bitcount
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 2.3.0
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubygems_version: 3.1.2
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Bitcount helper methods.
84
+ test_files: []