bitlength.patch

Akira Tanaka, 08/01/2013 08:47 PM

Download (4.94 KB)

View differences:

bignum.c (working copy)
6439 6439

  
6440 6440
/*
6441 6441
 *  call-seq:
6442
 *     big.bitlength -> integer
6443
 *
6444
 *  Returns the number of bits of the absolute value of <i>big</i>.
6445
 *
6446
 *     (-2**10000-1).bitlength  #=> 10001
6447
 *     (-2**10000).bitlength    #=> 10001
6448
 *     (-2**10000+1).bitlength  #=> 10000
6449
 *
6450
 *     (-2**1000-1).bitlength   #=> 1001
6451
 *     (-2**1000).bitlength     #=> 1001
6452
 *     (-2**1000+1).bitlength   #=> 1000
6453
 *
6454
 *     (2**1000-1).bitlength    #=> 1000
6455
 *     (2**1000).bitlength      #=> 1001
6456
 *     (2**1000+1).bitlength    #=> 1001
6457
 *
6458
 *     (2**10000-1).bitlength   #=> 10000
6459
 *     (2**10000).bitlength     #=> 10001
6460
 *     (2**10000+1).bitlength   #=> 10001
6461
 *
6462
 */
6463

  
6464
static VALUE
6465
rb_big_bitlength(VALUE big)
6466
{
6467
    int nlz_bits;
6468
    size_t numbytes;
6469

  
6470
    static const BDIGIT char_bit[1] = { CHAR_BIT };
6471
    BDIGIT numbytes_bary[bdigit_roomof(sizeof(size_t))];
6472
    BDIGIT nlz_bary[1];
6473
    BDIGIT result_bary[bdigit_roomof(sizeof(size_t)+1)];
6474

  
6475
    numbytes = rb_absint_size(big, &nlz_bits);
6476

  
6477
    if (numbytes <= SIZE_MAX / CHAR_BIT) {
6478
        return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
6479
    }
6480

  
6481
    nlz_bary[0] = nlz_bits;
6482

  
6483
    bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
6484
            INTEGER_PACK_NATIVE_BYTE_ORDER);
6485
    BARY_MUL1(result_bary, numbytes_bary, char_bit);
6486
    BARY_SUB(result_bary, result_bary, nlz_bary);
6487

  
6488
    return rb_integer_unpack(result_bary, numberof(result_bary), sizeof(BDIGIT), 0,
6489
            INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
6490
}
6491

  
6492
/*
6493
 *  call-seq:
6494
 *     fix.bitlength -> integer
6495
 *
6496
 *  Returns the number of bits of the absolute value of <i>fix</i>.
6497
 *
6498
 *     (-2**12-1).bitlength)    #=> 13
6499
 *     (-2**12).bitlength)      #=> 13
6500
 *     (-2**12+1).bitlength)    #=> 12
6501
 *     -0x100.bitlength         #=> 9
6502
 *     -0xff.bitlength          #=> 8
6503
 *     -1.bitlength             #=> 1
6504
 *     0.bitlength              #=> 0
6505
 *     1.bitlength              #=> 1
6506
 *     0xff.bitlength           #=> 8
6507
 *     0x100.bitlength          #=> 9
6508
 *     (2**12-1).bitlength      #=> 12
6509
 *     (2**12).bitlength        #=> 13
6510
 *     (2**12+1).bitlength      #=> 13
6511
 */
6512

  
6513
static VALUE
6514
rb_fix_bitlength(VALUE fix)
6515
{
6516
    long v = FIX2LONG(fix);
6517
    if (v < 0)
6518
        v = -v;
6519
    return LONG2FIX(bitsize(v));
6520
}
6521

  
6522
/*
6523
 *  call-seq:
6442 6524
 *     big.odd? -> true or false
6443 6525
 *
6444 6526
 *  Returns <code>true</code> if <i>big</i> is an odd number.
......
6528 6610
    rb_define_method(rb_cBignum, "abs", rb_big_abs, 0);
6529 6611
    rb_define_method(rb_cBignum, "magnitude", rb_big_abs, 0);
6530 6612
    rb_define_method(rb_cBignum, "size", rb_big_size, 0);
6613
    rb_define_method(rb_cBignum, "bitlength", rb_big_bitlength, 0);
6531 6614
    rb_define_method(rb_cBignum, "odd?", rb_big_odd_p, 0);
6532 6615
    rb_define_method(rb_cBignum, "even?", rb_big_even_p, 0);
6533 6616

  
6617
    rb_define_method(rb_cFixnum, "bitlength", rb_fix_bitlength, 0);
6618

  
6534 6619
    power_cache_init();
6535 6620
}
test/ruby/test_fixnum.rb (working copy)
299 299
    assert_raise(ZeroDivisionError, bug5713) { 0 ** -big }
300 300
    assert_raise(ZeroDivisionError, bug5713) { 0 ** Rational(-2,3) }
301 301
  end
302

  
303
  def test_bitlength
304
    assert_equal(13, (-2**12-1).bitlength)
305
    assert_equal(13, (-2**12).bitlength)
306
    assert_equal(12, (-2**12+1).bitlength)
307
    assert_equal(9, -0x100.bitlength)
308
    assert_equal(8, -0xff.bitlength)
309
    assert_equal(1, -1.bitlength)
310
    assert_equal(0, 0.bitlength)
311
    assert_equal(1, 1.bitlength)
312
    assert_equal(8, 0xff.bitlength)
313
    assert_equal(9, 0x100.bitlength)
314
    assert_equal(12, (2**12-1).bitlength)
315
    assert_equal(13, (2**12).bitlength)
316
    assert_equal(13, (2**12+1).bitlength)
317
  end
302 318
end
test/ruby/test_bignum.rb (working copy)
701 701
    end
702 702
    assert_equal(T1024 ^ 10, T1024 ^ obj)
703 703
  end
704

  
705
  def test_bitlength
706
    assert_equal(10001, (-2**10000-1).bitlength)
707
    assert_equal(10001, (-2**10000).bitlength)
708
    assert_equal(10000, (-2**10000+1).bitlength)
709
    assert_equal(10000, (2**10000-1).bitlength)
710
    assert_equal(10001, (2**10000).bitlength)
711
    assert_equal(10001, (2**10000+1).bitlength)
712

  
713
    1.upto(1000) {|i|
714
      n = 2**i
715
      assert_equal(i+1, (-n-1).bitlength)
716
      assert_equal(i+1, (-n).bitlength)
717
      assert_equal(i,   (-n+1).bitlength)
718
      assert_equal(i,   (n-1).bitlength)
719
      assert_equal(i+1, (n).bitlength)
720
      assert_equal(i+1, (n+1).bitlength)
721
    }
722
  end
704 723
end