From: "akr (Akira Tanaka)" Date: 2013-06-24T13:28:43+09:00 Subject: [ruby-core:55622] [ruby-trunk - Feature #8553] Bignum#size (and Fixnum#size) Issue #8553 has been updated by akr (Akira Tanaka). File bignum-size-abs-bytewise.patch added > In JRuby, Bignum#size is implemented using Java's BigInteger.bitLength(). ... > Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit. For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation. (Computes (ceil(log2(this < 0 ? -this : this+1))). I think two's complement representation excluding a sign bit is not familiar for most people. Especially Bignum#size is bytewise, unlike Java's BigInteger.bitLength(). So it is not useful for calculating required number of bytes as two's complement signed integers. > This leads to the deviation you see in RubySpec, where JRuby and Rubinius differ from MRI on various Bignum sizes. We should ignore RubySpec. > Perhaps the least impact and most value would be to reimplement MRI's Bignum#size in terms of actual 2's complement bit length, the same way as JRuby (and apparently Rubinius)? It seems Rubinius uses absolute value. % bin/rbx -ve ' 1.upto(200) {|n| v = (1< RE: Fixnum#size... I think Ruby should introduce a new constant for native word size, and encourage people to use it. It is another issue. However I guess several developers may oppose new Fixnum dependent features as https://bugs.ruby-lang.org/issues/7517 ---------------------------------------- Feature #8553: Bignum#size (and Fixnum#size) https://bugs.ruby-lang.org/issues/8553#change-40111 Author: akr (Akira Tanaka) Status: Open Priority: Normal Assignee: Category: Target version: How about changing Bignum#size to a well defined behavior? Recently I changed Bignum implementation to use 128 bit integer type if the type is available. (r41379) After that, rubyspec fails with Bignum#size as follows: | 1) | Bignum#size returns the number of bytes in the machine representation in multiples of four FAILED | Expected 16 | to equal 12 | http://a.mrkn.jp/~mrkn/chkbuild/mavericks/ruby-trunk-m64-o3/log/20130620T231101Z.log.html.gz I think this failure itself is not a problem. This is just an over-specification of rubyspec. Actually the test also fails before r41379 on platforms which doesn't support 64 bit integer type. It is because the Bignum#size returns multiples of sizeof(BDIGIT), not 4. sizeof(BDIGIT) can be 2 or 4 before r41379 or 8 since r41379. The test only considers platforms sizeof(BDIGIT) is 4. However this test failure reminds me that I always felt that current Bignum#size (and Fixnum#size) behavior is not useful. I guess almost all people doesn't interest sizeof(BDIGIT). So I'd like to change Bignum#size to return number of bytes. It means val.size returns n if val is a Bignum and 256**n <= abs(val) < 256**(n+1). One exception is that val.size returns 0 if val is Bignum zero. My considerations: * The above Bignum#size behavior is based on absolute values, abs(n). This is compatible to current behavior and easy to understand. There are other possibilities: exception on negative values and definition on 2's complement value. I think exception is too different from current behavior. A definition based on 2's complement is difficult to treat sign bits. * Bignum#size returns number of bytes, not bits. I think some method which returns number of bits may be useful but it is different from current Bignum#size. It is better to name another one, such as bitsize and it is not this issue. * Fixnum#size is difficult to change. Currently Fixnum#size returns sizeof(long). Some programs, mspec for example, uses it to obtain a word size. So it is difficult to change because compatibility. However I doubt such use is correct. If a program want to detect 64bit platform, Fixnum#size should not be used because it returns 4 on LLP64 platforms (64bit Windows). It is better to use [0].pack("l!").size for sizof(long) and [nil].pack("p").size for sizeof(char *). However some people may hope Fixnum and Bignum consistent. For that purpose, Fixnum#size should also be changed same way. It will breaks some applications, though. Any opinion? -- http://bugs.ruby-lang.org/