## Bug #8697

### Fixnum complement operator issue

**Description**

=begin

By the (()), bitwise complement operator ((*~*)) to Fixnum instance should do ((*one's complement*)) with just flipping all bits. In fact, current implementation does ((*two's complement*)) due to or-ing with FIXNUM_FLAG, which is defined as 1.

Either fix the documentation or the fix_rev function implementation.

Affected versions: both 1.9.3 and 2.0.0

=end

### History

#### #1 [ruby-core:56232] Updated by akr (Akira Tanaka) almost 4 years ago

**Status**changed from*Open*to*Feedback*

Please show us an actual problem.

At least, ~0 is -1 as follows.

% ./ruby -v -e 'p ~0'

ruby 2.1.0dev (2013-07-26 trunk 42199) [x86_64-linux]

-1

-1 is the number which all bits are one.

0 is the number which all bits are zero.

So, -1 is the one's complement of 0 as documented.

#### #2 [ruby-core:56234] Updated by torimus (Torimus GL) almost 4 years ago

=begin

When one's complement is applied to zero, the result is ((*not*)) -1 but so called "negative zero", ie. -0.

What you are talking about is two's complement, ie. "the value of 1 is then added to the resulting value of bitwise not operation".

It's all about improper use of terminology.

See related articles on Wikipedia: (()) and (()) .

=end

#### #3 [ruby-core:56236] Updated by mame (Yusuke Endoh) almost 4 years ago

=begin

I guess you mistake "the ones' complement of a binary number" for "the ones' complement system".

The former is a kind of operation for the binary representation of a number, no matter what the number itself is.

The latter gives a mapping that corresponds the binary representations to mathematical numbers.

See related articles on Wikipedia: (())

Actually it says:

The ones' complement of a binary number is defined as the value obtained by inverting all the bits in the binary representation of the number

For example, the bit pattern of +0 is "all 0s" in both ones' and twos' complement systems.

By the definition above, applying the ones' complement to +0 yields a number whose binary representation is "all 1s".

This number that has "all 1" bit pattern represents -0 in ones' complement system, and -1 in twos' complement system.

Ruby's Integer uses twos' complement system.

Even without knowledge of it, "the ones' complement of 0 is -1", is very common phrase in the computer science. There is nothing wrong in both the implementation and documentation of Fixnum#~.

=end

#### #4 [ruby-core:56241] Updated by torimus (Torimus GL) almost 4 years ago

=begin

As you've admitted, ~ operator implementation does more than ((*just flipping of it's each bit*)). It also does an additional step when converting to two's complement by doing bitwise or with number 1 ((({return ~num | FIXNUM_FLAG}))). As the rest of bit operators also counts in two's complement and also #to_s method is aware of it, this fact is then shadowed. If Ruby wouldn't automatically convert to BigDecimal when the register size is exceed, this would show off when the highest bit 'overflows'.

I can understand why Ruby does this conversions internally but I see no reason for vague descriptions in the documentation and hiding this fact. Why current text to FixNum's ~ simply doesn't speak about two's complement directly ?

=end

#### #5 [ruby-core:56264] Updated by david_macmahon (David MacMahon) almost 4 years ago

The bit inverted VALUE is OR'd with FIXNUM_FLAG so that Ruby will still recognize the VALUE as a Fixnum. It is NOT done to convert to two's complement (which would actually require adding 1 to the bit inverted value rather).

You can see that the OR with FIXNUM_FLAG does not show up in the result by looking at the binary representation of any bit inverted odd number (e.g. ~1):

$ ruby -e 'puts "%b" % ~1'

..10

Dave

On Jul 28, 2013, at 1:39 AM, torimus (Torimus GL) wrote:

Issue #8697 has been updated by torimus (Torimus GL).

=begin

As you've admitted, ~ operator implementation does more than ((just flipping of it's each bit)). It also does an additional step when converting to two's complement by doing bitwise or with number 1 ((({return ~num | FIXNUM_FLAG}))). As the rest of bit operators also counts in two's complement and also #to_s method is aware of it, this fact is then shadowed. If Ruby wouldn't automatically convert to BigDecimal when the register size is exceed, this would show off when the highest bit 'overflows'.I can understand why Ruby does this conversions internally but I see no reason for vague descriptions in the documentation and hiding this fact. Why current text to FixNum's ~ simply doesn't speak about two's complement directly ?

=end

Bug #8697: Fixnum complement operator issue

https://bugs.ruby-lang.org/issues/8697#change-40731Author: torimus (Torimus GL)

Status: Feedback

Priority: Normal

Assignee:

Category: core

Target version: current: 2.1.0

ruby -v: 1.9.3p448

Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN=begin

By the (()), bitwise complement operator ((~)) to Fixnum instance should do ((one's complement)) with just flipping all bits. In fact, current implementation does ((two's complement)) due to or-ing with FIXNUM_FLAG, which is defined as 1.Either fix the documentation or the fix_rev function implementation.

Affected versions: both 1.9.3 and 2.0.0

=end

#### #6 [ruby-core:56465] Updated by phluid61 (Matthew Kerwin) almost 4 years ago

Can we close this issue? The original report confuses MRI implementation details (storing of small integers in Fixnum VALUEs) with language-level operations, which I believe has been explained sufficiently. This is a non-issue.

#### #7 [ruby-core:56466] Updated by charliesome (Charlie Somerville) almost 4 years ago

**Status**changed from*Feedback*to*Rejected*