-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move bit-twiddling helpers to their own file (#299)
This also deduplicates a repeated bit of code that iterates over bits
- Loading branch information
1 parent
3ce2ef1
commit 26c333c
Showing
3 changed files
with
66 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
""" Helpers for efficient bit operations | ||
Bitmaps are used in clifford as representations of basis blades, hence the need | ||
for these operations. These are only for internal use. | ||
""" | ||
|
||
from typing import Iterator | ||
|
||
import numba | ||
import numba.extending | ||
import numba.types | ||
import numba.config | ||
|
||
|
||
def set_bit_indices(x: int) -> Iterator[int]: | ||
""" Iterate over the indices of bits set to 1 in `x`, in ascending order """ | ||
n = 0 | ||
while x > 0: | ||
if x & 1: | ||
yield n | ||
x = x >> 1 | ||
n = n + 1 | ||
|
||
|
||
@numba.extending.intrinsic | ||
def __builtin_popcnt(tyctx, x): | ||
""" Emulate clang and GCC's `__builtin_popcnt` """ | ||
if isinstance(x, numba.types.Integer): | ||
def impl(cgctx, builder, sig, args): | ||
x, = args | ||
return builder.ctpop(x) | ||
sig = x(x) | ||
return sig, impl | ||
|
||
|
||
if numba.config.DISABLE_JIT: | ||
def count_set_bits(bitmap: int) -> int: | ||
""" Counts the number of bits set to 1 in bitmap """ | ||
count = 0 | ||
for i in set_bit_indices(bitmap): | ||
count += 1 | ||
return count | ||
|
||
else: | ||
@numba.njit | ||
def count_set_bits(x: int) -> int: | ||
""" Counts the number of bits set to 1 in bitmap """ | ||
return __builtin_popcnt(x) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
""" Tests of clifford._bit_helpers """ | ||
from clifford._bit_helpers import count_set_bits, set_bit_indices | ||
|
||
|
||
def test_count_bits(): | ||
assert count_set_bits(0b0) == 0 | ||
assert count_set_bits(0b1) == 1 | ||
assert count_set_bits(0b1001) == 2 | ||
assert count_set_bits(0b1111) == 4 | ||
|
||
|
||
def test_bit_indices(): | ||
assert list(set_bit_indices(0b0)) == [] | ||
assert list(set_bit_indices(0b1)) == [0] | ||
assert list(set_bit_indices(0b101)) == [0, 2] | ||
assert list(set_bit_indices(0b101010)) == [1, 3, 5] |