Feature #8738 ยป single_bit_p.patch
| 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);
|
||