bitcount 0.1.0

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 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: []