From: Daniel Martin Date: 2006-07-01T09:57:18+09:00 Subject: Re: [QUIZ] C-Style Ints (#85) I have some questions about some more edge cases. Ruby Quiz writes: > irb(main):001:0> n = UnsignedFixedWidthInt.new(0xFF, 8) > => 255 > irb(main):002:0> n += 2 > => 1 > irb(main):003:0> n = n << 1 > => 2 > irb(main):004:0> n = n >> 1 > => 1 > irb(main):005:0> ~n > => 254 > irb(main):006:0> n += 12 > => 13 > irb(main):007:0> n = n & 0x0E > => 12 > irb(main):008:0> It would seem from the above that whenever there's arithmetic with a FWI as one operand and an Integer as the other, the result should be a FWI and we should do simple twos-complement arithmetic in that width. Now, should we also try to ensure that (2 + n) has the same result as (n + 2) ? What happens when we operate on two FWIs at once? I would propose that the answer should be that the result is a FWI with as many bits as the larger of the two operands, but I'm stuck as to what to do when you add a SignedFixedWidthInt to an UnsignedFixedWidthInt. What is the result? I'd like to propose these rules of arithmetic: Any operation between a FWI and a Float, Rational, or Complex has the same result as though the FWI were replaced by an Integer of equal value. For operations +, -, ^, &&, *, /, %, and ||, an Integer with a FWI (in either order) produces the same type of FWI as the FWI argument. For those same operations, two FWIs produce an FWI with as many bits as the longer of the two and unsigned if either operand is unsigned. (rationale: like C) An alternative set of rules (I'm asking for a ruling here) sets the result of * and / to the same type as the first argument, and % to the same type as the second argument. (Rationale: a * 2 is (a + a), whether a is a Fixnum, Float, Array, or String. This seems like a property we might want to preserve when a is a FWI, even if "2" is only a FWI with the value of "2") For ** (exponentiation), I'm not sure. My instinct is to say that it's an error to raise a FWI to a negative power, and that FWI ** FWI should produce the same type as the first argument. (Rationale: it's like repeated multiplication) As for just taking the last n bits when passed an initial argument that's too wide - that's exactly what you want to do. That lets us emulate the C cast-to-smaller-type: short int g = (short int) some_big_variable; with FWI.new(). C is always taking only the least significant portion, so if we want to look like C...