This commit is contained in:
Bill Breitmayer 2024-05-28 21:53:34 -04:00
commit a471d00d75

View File

@ -14,9 +14,9 @@ All parameters must be must be int >= 0, referred to as a 'bit integer'.
index:int
The offset into the bit position from right,
0b010111 -> list [1,1,1,0,1,0]. big-endian -> little-endian
0b010111 -> list [1,1,1,0,1,0]. big-endian -> little-endian
For inserts, index is the position to the right of index,
index 0 -> right of rightmost bit.
index 0 -> right of rightmost bit.
For gets, sets and removes, it is the position of the bit itself.
value:int
@ -24,7 +24,7 @@ All parameters must be must be int >= 0, referred to as a 'bit integer'.
bitlen:int
The effective mask length, spec. leading zeros
( bitlen 4 value 1 -> 0001 )
( bitlen 4 value 1 -> 0001 )
The bitwise expressions may look convoluted, but basically, there are
just three parts: left-hand side, value, right-hand side.
@ -59,7 +59,7 @@ and slicing, but this bitwise implementation is significantly faster
See https://github.com/billbreit/BitWiseApps/blob/main/dev/time_ops.py
"""
"""
bit_length = int.bit_length
@ -67,164 +67,169 @@ bit_length = int.bit_length
and for bit_length(value) > bit_len, which can cause silent errors.
Anything like int(None) is going to cause a loud error. """
def bit_get(bint: int, index: int):
"""Get value of bit at index in bint.
"""Get value of bit at index in bint.
>>> bit_get(15, 0)
1
>>> bit_get(15, 4)
0
>>> bit_get(0, 4)
0
>>> bit_get(-1, 2) is None
True
>>> bit_get(0, -1) is None
True
"""
>>> bit_get(15, 0)
1
>>> bit_get(15, 4)
0
>>> bit_get(0, 4)
0
>>> bit_get(-1, 2) is None
True
>>> bit_get(0, -1) is None
True
"""
return multibit_get(bint, index, 1)
return multibit_get(bint, index, 1)
def bit_set(bint: int, index: int, value: int = 1):
"""Set bit at index to value 1 or 0, like set() or unset().
"""Set bit at index to value 1 or 0, like set() or unset().
>>> bit_set(15, 0, 0)
14
>>> bit_set(15, 4, 1)
31
>>> bit_set(31, 6, 0)
31
>>> bit_set(31, 6, 3) is None
True
"""
>>> bit_set(15, 0, 0)
14
>>> bit_set(15, 4, 1)
31
>>> bit_set(31, 6, 0)
31
>>> bit_set(31, 6, 3) is None
True
"""
if value not in [0, 1]:
return None # error
if value not in [0, 1]:
return None # error
return multibit_set(bint, index, 1, value)
return multibit_set(bint, index, 1, value)
def bit_insert(bint: int, index: int, value: int = 1):
"""Insert bit value before index.
"""Insert bit value before index.
>>> bit_insert(15, 0, 0)
30
>>> bit_insert(15, 0, 1)
31
>>> bit_insert(15, 4, 1)
31
>>> bit_insert(31, 6, 0)
31
"""
>>> bit_insert(15, 0, 0)
30
>>> bit_insert(15, 0, 1)
31
>>> bit_insert(15, 4, 1)
31
>>> bit_insert(31, 6, 0)
31
"""
if value not in [0, 1]:
return None # error
if value not in [0, 1]:
return None # error
return multibit_insert(bint, index, 1, value)
return multibit_insert(bint, index, 1, value)
def bit_remove(bint: int, index: int) -> int:
"""Remove the bit at index from bint.
"""Remove the bit at index from bint.
>>> bit_remove(15, 0)
7
>>> bit_remove(15, 1)
7
>>> bit_remove(31, 4)
15
>>> bit_remove(31, 6)
31
"""
>>> bit_remove(15, 0)
7
>>> bit_remove(15, 1)
7
>>> bit_remove(31, 4)
15
>>> bit_remove(31, 6)
31
"""
return multibit_remove(bint, index, 1)
return multibit_remove(bint, index, 1)
def multibit_get(bint: int, index: int, bit_len: int) -> int:
"""Get bit_len number of bits starting from index.
819 = 1100110011.
"""Get bit_len number of bits starting from index.
819 = 1100110011.
>>> multibit_get(0, 1, 1)
0
>>> multibit_get(15, 0, 3)
7
>>> multibit_get(819, 2, 4)
12
>>> multibit_get(819, 4, 6)
51
"""
>>> multibit_get(0, 1, 1)
0
>>> multibit_get(15, 0, 3)
7
>>> multibit_get(819, 2, 4)
12
>>> multibit_get(819, 4, 6)
51
"""
if bint < 0 or index < 0 or bit_len < 0:
return None # error
if bint < 0 or index < 0 or bit_len < 0:
return None # error
return (bint >> index) & ((1 << bit_len) - 1)
return (bint >> index) & ((1 << bit_len) - 1)
def multibit_set(bint: int, index: int, bit_len: int, value: int) -> int:
"""Overlay bint at index with value for bit_len bits.
"""Overlay bint at index with value for bit_len bits.
>>> multibit_set(0, 1, 1, 0)
0
>>> multibit_set(15, 0, 2, 0)
12
>>> multibit_set(22, 0, 1, 1)
23
>>> multibit_set(22, 2, 1, 0)
18
>>> multibit_set(22, 2, 1, 3) is None
True
"""
>>> multibit_set(0, 1, 1, 0)
0
>>> multibit_set(15, 0, 2, 0)
12
>>> multibit_set(22, 0, 1, 1)
23
>>> multibit_set(22, 2, 1, 0)
18
>>> multibit_set(22, 2, 1, 3) is None
True
"""
if bint < 0 or index < 0 or bit_len < 0 or value < 0:
return None # error
if bit_length(value) > bit_len:
return None
if bint < 0 or index < 0 or bit_len < 0 or value < 0:
return None # error
if bit_length(value) > bit_len:
return None
return ((((bint >> (index + bit_len)) << bit_len) | value) << index) | (
bint & (1 << index) - 1
)
return ((((bint >> (index + bit_len)) << bit_len) | value) << index) | (
bint & (1 << index) - 1
)
def multibit_insert(bint: int, index: int, bit_len: int, value: int) -> int:
"""Insert before index-th slot
"""Insert before index-th slot
>>> multibit_insert(0, 1, 1, 1)
2
>>> multibit_insert(15, 1, 2, 0)
57
>>> multibit_insert(22, 0, 1, 1)
45
>>> multibit_insert(22, 2, 1, 0)
42
>>> multibit_insert(22, 2, 1, 3) is None
True
"""
>>> multibit_insert(0, 1, 1, 1)
2
>>> multibit_insert(15, 1, 2, 0)
57
>>> multibit_insert(22, 0, 1, 1)
45
>>> multibit_insert(22, 2, 1, 0)
42
>>> multibit_insert(22, 2, 1, 3) is None
True
"""
if bint < 0 or index < 0 or bit_len < 0 or value < 0:
return None # error
if bit_length(value) > bit_len:
return None
if bint < 0 or index < 0 or bit_len < 0 or value < 0:
return None # error
if bit_length(value) > bit_len:
return None
return ((((bint >> index) << bit_len) | value) << index) | bint & ((1 << index) - 1)
return ((((bint >> index) << bit_len) | value) << index) | bint & ((1 << index) - 1)
def multibit_remove(bint: int, index: int, bit_len: int) -> int:
"""Remove bits in bint from index to index+bit_len.
"""Remove bits in bint from index to index+bit_len.
>>> multibit_remove(3, 1, 1)
1
>>> multibit_remove(15, 1, 2)
3
>>> multibit_remove(22, 0, 1)
11
>>> multibit_remove(22, 2, 2)
6
>>> multibit_remove(22, 2, 6)
2
"""
>>> multibit_remove(3, 1, 1)
1
>>> multibit_remove(15, 1, 2)
3
>>> multibit_remove(22, 0, 1)
11
>>> multibit_remove(22, 2, 2)
6
>>> multibit_remove(22, 2, 6)
2
"""
if bint < 0 or index < 0:
return None # error
if bint < 0 or index < 0:
return None # error
return ((bint >> index + bit_len) << index) | bint & ((1 << index) - 1)
return ((bint >> index + bit_len) << index) | bint & ((1 << index) - 1)
if __name__ == "__main__":
import doctest
import doctest
doctest.testmod()
doctest.testmod()