From: "garrison (Garrison Jensen) via ruby-core" <ruby-core@...>
Date: 2024-01-10T01:17:01+00:00
Subject: [ruby-core:116130] [Ruby master Feature#20163] Introduce #bit_count method on Integer

Issue #20163 has been updated by garrison (Garrison Jensen).


I like `popcount`, and have no strong preferences for the chosen name. 

I want to share my performance tests in case they are helpful for the discussion. As you can see, the built-in method is significantly faster. 

```
(0..10_000_000).each { |x| x.to_s(2).count('1') }
processing time: 3.714706s

(0..10_000_000).each { |x| ruby_pop_count(x) }
processing time: 3.367775s

(0..10_000_000).each { |x| x.pop_count }
processing time: 0.515767s
```

Here are my implementations: 
```
def ruby_pop_count(n)
  n = n.abs
  count = 0
  while n > 0
    n &= n - 1 
    count += 1
  end
  count
end
```

```
unsigned int pop_count(long value) {
#ifdef __GNUC__
    // Use GCC built-in
    return __builtin_popcountl(value);
#else
    // Fallback method for compilers without the built-in
    unsigned int count = 0;
    while (value) {
        count += value & 1;
        value >>= 1;
    }
    return count;
#endif
}

// Wrapper function for Ruby
VALUE rb_pop_count(VALUE self) {
    long value = NUM2LONG(self);
    unsigned int count =  pop_count(labs(value));
    return UINT2NUM(count);
}
```


----------------------------------------
Feature #20163: Introduce #bit_count method on Integer
https://bugs.ruby-lang.org/issues/20163#change-106136

* Author: garrison (Garrison Jensen)
* Status: Open
* Priority: Normal
----------------------------------------
This feature request is to implement a method called #bit_count on Integer that returns the number of ones in the binary representation of the absolute value of the integer.
```
n = 19
n.bit_count #=> 3
(-n).bit_count #=> 3
```
This is often useful when you use an integer as a bitmask and want to count how many bits are set. 

This would be equivalent to
```
n.to_s(2).count("1")
```

However, this can be outperformed by
```
def bit_count(n)
  count = 0
  while n > 0
    n &= n - 1 # Flip the least significant 1 bit to 0
    count += 1
  end
  count
end
```

I think this would be a useful addition because it would fit alongside the other bit-related methods defined on integer: `#bit_length,` `#allbits?`, `#anybits?`, `#nobits?`. Also, when working with bitmasks, a minor upgrade to performance often results in a significant improvement. 

Similar methods from other languages:
https://docs.python.org/3/library/stdtypes.html#int.bit_count
https://doc.rust-lang.org/std/primitive.i32.html#method.count_ones



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/