This repository has been archived by the owner on Aug 28, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace broken backports gem Bignum#bit_length with custom monkey-pat…
…ch for MRI < 2.1 I filed the following bug with backports gem: marcandre/backports#95 Added some tests to cover this function, but they will only be using the backport version if the current Ruby runtime doesn't support #bit_length Also, backports gem need require => false in Gemfile so *all* backports don't get loaded which we don't want. That is why I had to also bring in Range#bsearch manually. So now we are not using the backports gem at all.
- Loading branch information
Showing
4 changed files
with
145 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Backport support for Bignum#bit_length and Fixnum#bit_length which were added in Ruby 2.1 | ||
# See : http://globaldev.co.uk/2014/05/ruby-2-1-in-detail/ | ||
# See : https://github.com/marcandre/backports | ||
# | ||
# NOTE: Had to add this as a monkey patch here since Bignum#bit_length is broken | ||
# in the backports gem. Bug filed: | ||
# https://github.com/marcandre/backports/issues/95 | ||
|
||
# Supports #bit_length | ||
# a direct copy from backports gem | ||
unless Range.method_defined? :bsearch | ||
class Range | ||
def bsearch | ||
return to_enum(:bsearch) unless block_given? | ||
from = self.begin | ||
to = self.end | ||
unless from.is_a?(Numeric) && to.is_a?(Numeric) | ||
raise TypeError, "can't do binary search for #{from.class}" | ||
end | ||
|
||
midpoint = nil | ||
if from.is_a?(Integer) && to.is_a?(Integer) | ||
convert = Proc.new{ midpoint } | ||
else | ||
map = Proc.new do |pk, unpk, nb| | ||
result, = [nb.abs].pack(pk).unpack(unpk) | ||
nb < 0 ? -result : result | ||
end | ||
from = map['D', 'q', to.to_f] | ||
to = map['D', 'q', to.to_f] | ||
convert = Proc.new{ map['q', 'D', midpoint] } | ||
end | ||
to -= 1 if exclude_end? | ||
satisfied = nil | ||
while from <= to do | ||
midpoint = (from + to).div(2) | ||
result = yield(cur = convert.call) | ||
case result | ||
when Numeric | ||
return cur if result == 0 | ||
result = result < 0 | ||
when true | ||
satisfied = cur | ||
when nil, false | ||
# nothing to do | ||
else | ||
raise TypeError, "wrong argument type #{result.class} (must be numeric, true, false or nil)" | ||
end | ||
|
||
if result | ||
to = midpoint - 1 | ||
else | ||
from = midpoint + 1 | ||
end | ||
end | ||
satisfied | ||
end | ||
end | ||
end | ||
|
||
# For MRI < 2.1, and other Rubies | ||
# A direct copy from backports gem | ||
unless Fixnum.method_defined? :bit_length | ||
# require 'backports/2.0.0/range/bsearch' | ||
class Fixnum | ||
def bit_length | ||
n = if self >= 0 | ||
self + 1 | ||
else | ||
-self | ||
end | ||
(0...8 * size).bsearch{|i| n <= (1 << i) } | ||
end | ||
end | ||
end | ||
|
||
# For MRI < 2.1, and other Rubies | ||
# My own temporary implementation of bit_length. Until the bug report | ||
# above is resolved. | ||
unless Bignum.method_defined? :bit_length | ||
class Bignum | ||
def bit_length | ||
(self).abs.to_s(2).length | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# -*- encoding: utf-8 -*- | ||
|
||
# Copyright 2011-2015 Glenn Rempe | ||
|
||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
|
||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
require File.expand_path('../spec_helper', __FILE__) | ||
|
||
# NOTE : these backport tests are only meaninful when run on | ||
# a Ruby runtime that doesn't natively support Bignum.bit_length | ||
describe 'Bignum#bit_length' do | ||
include SecretSharing::Shamir | ||
|
||
it 'will return the expected bit_length for multiples of 256' do | ||
[256, 512, 768, 1024].each do |i| | ||
r = get_random_number_with_bitlength(i) | ||
r.bit_length.must_equal(i) | ||
end | ||
end | ||
|
||
it 'will return the expected bit_length for multiples of 256 + 1' do | ||
[257, 513, 769, 1025].each do |i| | ||
r = get_random_number_with_bitlength(i) | ||
r.bit_length.must_equal(i) | ||
end | ||
end | ||
end | ||
|
||
# NOTE : these backport tests are only meaninful when run on | ||
# a Ruby runtime that doesn't natively support Fixnum.bit_length | ||
describe 'Fixnum#bit_length' do | ||
include SecretSharing::Shamir | ||
|
||
it 'will return the expected bit_length for multiples of 8' do | ||
[1, 8, 16, 24, 32].each do |i| | ||
r = get_random_number_with_bitlength(i) | ||
r.bit_length.must_equal(i) | ||
end | ||
end | ||
|
||
it 'will return the expected bit_length for multiples of 8 + 1' do | ||
[2, 9, 17, 25, 33].each do |i| | ||
r = get_random_number_with_bitlength(i) | ||
r.bit_length.must_equal(i) | ||
end | ||
end | ||
end |