Project

General

Profile

Feature #8738 ยป single_bit_p.patch

akr (Akira Tanaka), 08/05/2013 10:03 PM

View differences:

bignum.c (working copy)
}
/*
* call-seq:
* big.single_bit? -> true or false
*
* Returns true if abs(fixnum) has exactly a single one bit in binary format.
* In other words, it returns true if the number is a power of two.
*
* (-2**100-1).single_bit? #=> false
* (-2**100).single_bit? #=> true
* (-2**100+1).single_bit? #=> false
* (2**100-1).single_bit? #=> false
* (2**100).single_bit? #=> true
* (2**100+1).single_bit? #=> false
*
*/
static VALUE
rb_big_single_bit_p(VALUE num)
{
long n;
BDIGIT *ds, d;
ds = BDIGITS(num);
n = RBIGNUM_LEN(num);
while (0 < n) {
--n;
d = ds[n];
if (d != 0) {
if (d & (d-1))
return Qfalse;
goto single_bit_word_found;
}
}
return Qfalse;
single_bit_word_found:
while (0 < n) {
--n;
if (ds[n] != 0) {
return Qfalse;
}
}
return Qtrue;
}
/*
* Bignum objects hold integers outside the range of
* Fixnum. Bignum objects are created
* automatically when integer calculations would otherwise overflow a
......
rb_define_method(rb_cBignum, "size", rb_big_size, 0);
rb_define_method(rb_cBignum, "odd?", rb_big_odd_p, 0);
rb_define_method(rb_cBignum, "even?", rb_big_even_p, 0);
rb_define_method(rb_cBignum, "single_bit?", rb_big_single_bit_p, 0);
power_cache_init();
}
test/ruby/test_integer.rb (working copy)
end
assert_equal(3 ^ 10, 3 ^ obj)
end
def test_single_bit?
assert_equal(false,-5.single_bit?)
assert_equal(true ,-4.single_bit?)
assert_equal(false,-3.single_bit?)
assert_equal(true ,-2.single_bit?)
assert_equal(true ,-1.single_bit?)
assert_equal(false, 0.single_bit?)
assert_equal(true, 1.single_bit?)
assert_equal(true, 2.single_bit?)
assert_equal(false, 3.single_bit?)
assert_equal(true, 4.single_bit?)
assert_equal(false, 5.single_bit?)
assert_equal(false, (3*2**128).single_bit?)
2.upto(200) {|i|
n = 2**i
assert_equal(false, (n-1).single_bit?)
assert_equal(true , n.single_bit?)
assert_equal(false, (n+1).single_bit?)
n = -n
assert_equal(false, (n-1).single_bit?)
assert_equal(true , n.single_bit?)
assert_equal(false, (n+1).single_bit?)
}
end
end
numeric.c (working copy)
/*
* call-seq:
* fixnum.single_bit? -> true or false
*
* Returns true if abs(fixnum) has exactly a single one bit in binary format.
* In other words, it returns true if the number is a power of two.
* I.e. it returns true for 1, 2, 4, 8, ... and
* -1, -2, -4, -8, ...
*
* -9.single_bit? #=> false
* -8.single_bit? #=> true
* -7.single_bit? #=> false
* -6.single_bit? #=> false
* -5.single_bit? #=> false
* -4.single_bit? #=> true
* -3.single_bit? #=> false
* -2.single_bit? #=> true
* -1.single_bit? #=> true
* 0.single_bit? #=> false
* 1.single_bit? #=> true
* 2.single_bit? #=> true
* 3.single_bit? #=> false
* 4.single_bit? #=> true
* 5.single_bit? #=> false
* 6.single_bit? #=> false
* 7.single_bit? #=> false
* 8.single_bit? #=> true
* 9.single_bit? #=> false
*
* 256.single_bit? #=> true
* 65536.single_bit? #=> true
*
*/
static VALUE
fix_single_bit_p(VALUE num)
{
long i = FIX2LONG(num);
if (i == 0)
return Qfalse;
if (i < 0)
i = -i;
return (i & (i-1)) == 0 ? Qtrue : Qfalse;
}
/*
* call-seq:
* int.next -> integer
* int.succ -> integer
*
......
rb_define_method(rb_cFixnum, "odd?", fix_odd_p, 0);
rb_define_method(rb_cFixnum, "even?", fix_even_p, 0);
rb_define_method(rb_cFixnum, "succ", fix_succ, 0);
rb_define_method(rb_cFixnum, "single_bit?", fix_single_bit_p, 0);
rb_cFloat = rb_define_class("Float", rb_cNumeric);
    (1-1/1)