Is the Fixnum size difference a problem?

The size of Fixnum in a standard C implementation of Ruby is a machine
word
minus one bit. I.E. For most 32 bit machines that is 31 bits. (The
implementation uses the bottom bit as a flag). Therefore the largest
value
that you can hold in their Fixnum is 0x3fffffff.

IronRuby uses System.Int32 to hold its Fixnum values and doesn’t have a
flag
bit so the size of Fixnum in IronRuby is 32 bits. Therefore the largest
value you can hold is 0x7fffffff.

This shouldn’t run into any problems since the transition between Fixnum
and
Bignum is supposedly transparent; you don’t really care (although you
may
know) what class is representing the value you are working with.

Unfortunately, I recently noticed that the div method has different
semantics depending upon whether you are a Fixnum or Bignum.

some_fixnum.div(0.0) => raises FloatDomainError

some_bignum.div(0.0) => Infinity

IronRuby has the same semantics, except that of course what is a Bignum
for
CRuby is not a Bignum for IronRuby.

In CRuby:

0x40000000.div(0.0) => Infinity

In IronRuby:

0x40000000.div(0.0) => raises FloatDomainError

Now clearly this is a problem with the fundamental implementation of
Fixnum/Bignum but Rubinius seems to follow suit and I assume JRuby too
(although I haven’t checked).

What are your thoughts on dealing with this issue? Should we brush it
under
the carpet and hope that Ruby 2.0 will fix it or what? Should we force
IronRuby’s Fixnum to be 31 bits?

Any ideas most welcome.

Pete

Peter Bacon D.:

Now clearly this is a problem with the fundamental implementation of
Fixnum/Bignum but Rubinius seems to follow suit and I assume JRuby too
(although I haven’t checked).

What are your thoughts on dealing with this issue? Should we brush it
under the carpet and hope that Ruby 2.0 will fix it or what? Should
we force IronRuby’s Fixnum to be 31 bits?

I think we can keep Fixnums at 32 bits, and fix div to throw. Just tried
in JRuby:

irb(main):001:0> 0x4000_0000_0000_0000.class
=> Fixnum
irb(main):002:0> 0x4000_0000.div(0.0)
FloatDomainError: Infinity

They actually have 64bit Fixnums… wow :slight_smile:

  • John

John M. wrote:

I think we can keep Fixnums at 32 bits, and fix div to throw. Just tried in JRuby:

irb(main):001:0> 0x4000_0000_0000_0000.class
=> Fixnum
irb(main):002:0> 0x4000_0000.div(0.0)
FloatDomainError: Infinity

They actually have 64bit Fixnums… wow :slight_smile:

Yeah, we realized very recently that at some point we switches Fixnum to
64 bits, and now we don’t care to switch it back. So we’re using a Java
long primitive internally to represent it, and I believe we’re stripping
off the upper bit or two.

This issue actually came up today while I was fixing some spec failures
in JRuby. The specs do check that Fixnum is four bytes…but I talked
with Rubinius folks and they agree it should be made flexible enough for
other size Fixnums, since even Ruby’s own documentation says Fixnum may
be different sizes on different hardware (and perhaps we may have used a
64-bit machine to run Ruby at some point, leading to JRuby’s 64-bit
Fixnums).

I don’t think the precision of Fixnum is a specifiable detail,
especially since there’s no loss of precision from a rollover into
Bignum…whenever that happens.

  • Charlie