Skip to content

Commit de63b92

Browse files
authored
feat: added bits function to standardlib (#622)
Created bits functions in the standard library (and created new a subpackage for the standard library). **Changes** - Created "stdlib" submodule - Added functions in "stdlib/bits.py", exposing "bit_length" and "convert_bits" - Added tests
1 parent 005e664 commit de63b92

4 files changed

Lines changed: 133 additions & 1 deletion

File tree

src/kirin/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# re-exports the public API of the kirin package
2-
from . import ir as ir, types as types, lowering as lowering
2+
from . import ir as ir, types as types, stdlib as stdlib, lowering as lowering
33
from .exception import enable_stracetrace, disable_stracetrace
44

55
__all__ = ["ir", "types", "lowering", "enable_stracetrace", "disable_stracetrace"]

src/kirin/stdlib/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import bits as bits

src/kirin/stdlib/bits.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""Bit-oriented helpers implemented as reusable Kirin kernels."""
2+
3+
from kirin.prelude import basic
4+
from kirin.dialects import ilist
5+
6+
7+
@basic
8+
def _bit_length_rec(x: int, i: int) -> int:
9+
y = x >> i
10+
if y:
11+
return _bit_length_rec(x, i + 1)
12+
else:
13+
return i
14+
15+
16+
@basic
17+
def bit_length(x: int) -> int:
18+
"""Return the number of bits required to represent ``x``."""
19+
x = abs(x)
20+
if x == 0:
21+
return 0
22+
return _bit_length_rec(x, 1)
23+
24+
25+
@basic
26+
def convert_bits(x: int, length: int):
27+
"""Return the low ``length`` bits of ``x`` in least-significant-bit order. Note that the return type puts the least-significant-bit in the earliest index."""
28+
29+
def _shift(i: int):
30+
return (x >> i) & 1
31+
32+
return ilist.map(_shift, ilist.range(length))

test/stdlib/test_bits.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
from kirin.dialects import ilist
2+
from kirin.stdlib.bits import bit_length, convert_bits
3+
4+
5+
def test_bit_length_negative():
6+
assert bit_length(-13) == 4
7+
8+
9+
def test_bit_length_zero():
10+
assert bit_length(0) == 0
11+
12+
13+
def test_bit_length_positive():
14+
assert bit_length(7) == 3
15+
16+
17+
def test_bit_length_large():
18+
x = (1 << 80) + 12345
19+
assert bit_length(x) == x.bit_length()
20+
21+
22+
def test_bit_length_large_power_of_two():
23+
x = 1 << 80
24+
assert bit_length(x) == 81
25+
26+
27+
def test_bit_length_small():
28+
assert bit_length(3) == 2
29+
30+
31+
def test_bit_length_small_single_bit():
32+
assert bit_length(1) == 1
33+
34+
35+
def test_convert_bits_length_greater_than_bit_length():
36+
out = convert_bits(5, 5)
37+
assert isinstance(out, ilist.IList)
38+
assert out.data == [1, 0, 1, 0, 0]
39+
40+
41+
def test_convert_bits_length_equal_to_bit_length():
42+
out = convert_bits(5, 3)
43+
assert isinstance(out, ilist.IList)
44+
assert out.data == [1, 0, 1]
45+
46+
47+
def test_convert_bits_length_less_than_bit_length():
48+
out = convert_bits(13, 2)
49+
assert isinstance(out, ilist.IList)
50+
assert out.data == [1, 0]
51+
52+
53+
def test_convert_bits_negative_x():
54+
out = convert_bits(-1, 4)
55+
assert isinstance(out, ilist.IList)
56+
assert out.data == [1, 1, 1, 1]
57+
58+
59+
def test_convert_bits_negative_length():
60+
out = convert_bits(5, -3)
61+
assert isinstance(out, ilist.IList)
62+
assert out.data == []
63+
64+
65+
def test_convert_bits_zero_x():
66+
out = convert_bits(0, 4)
67+
assert isinstance(out, ilist.IList)
68+
assert out.data == [0, 0, 0, 0]
69+
70+
71+
def test_convert_bits_zero_length():
72+
out = convert_bits(7, 0)
73+
assert isinstance(out, ilist.IList)
74+
assert out.data == []
75+
76+
77+
def test_convert_bits_small_x():
78+
out = convert_bits(2, 3)
79+
assert isinstance(out, ilist.IList)
80+
assert out.data == [0, 1, 0]
81+
82+
83+
def test_convert_bits_small_length():
84+
out = convert_bits(7, 1)
85+
assert isinstance(out, ilist.IList)
86+
assert out.data == [1]
87+
88+
89+
def test_convert_bits_large_x():
90+
x = (1 << 12) + (1 << 5) + 1
91+
out = convert_bits(x, 13)
92+
assert isinstance(out, ilist.IList)
93+
assert out.data == [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1]
94+
95+
96+
def test_convert_bits_large_length():
97+
out = convert_bits(3, 10)
98+
assert isinstance(out, ilist.IList)
99+
assert out.data == [1, 1, 0, 0, 0, 0, 0, 0, 0, 0]

0 commit comments

Comments
 (0)