flexfloat 0.1.2__py3-none-any.whl → 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flexfloat/__init__.py +22 -3
- flexfloat/bitarray/__init__.py +90 -0
- flexfloat/bitarray/bitarray.py +198 -0
- flexfloat/bitarray/bitarray_int64.py +308 -0
- flexfloat/{bitarray.py → bitarray/bitarray_list.py} +27 -97
- flexfloat/bitarray/bitarray_mixins.py +93 -0
- flexfloat/core.py +306 -20
- flexfloat-0.1.3.dist-info/METADATA +340 -0
- flexfloat-0.1.3.dist-info/RECORD +14 -0
- flexfloat-0.1.2.dist-info/METADATA +0 -147
- flexfloat-0.1.2.dist-info/RECORD +0 -10
- {flexfloat-0.1.2.dist-info → flexfloat-0.1.3.dist-info}/WHEEL +0 -0
- {flexfloat-0.1.2.dist-info → flexfloat-0.1.3.dist-info}/licenses/LICENSE +0 -0
- {flexfloat-0.1.2.dist-info → flexfloat-0.1.3.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,15 @@
|
|
1
|
-
"""BitArray implementation for the flexfloat package."""
|
1
|
+
"""List-based BitArray implementation for the flexfloat package."""
|
2
2
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
5
|
import struct
|
6
6
|
from typing import Iterator, overload
|
7
7
|
|
8
|
+
from .bitarray import BitArray
|
9
|
+
from .bitarray_mixins import BitArrayCommonMixin
|
8
10
|
|
9
|
-
|
11
|
+
|
12
|
+
class ListBitArray(BitArrayCommonMixin):
|
10
13
|
"""A bit array class that encapsulates a list of booleans with utility methods.
|
11
14
|
|
12
15
|
This class provides all the functionality previously available through utility
|
@@ -22,73 +25,32 @@ class BitArray:
|
|
22
25
|
self._bits = bits if bits is not None else []
|
23
26
|
|
24
27
|
@classmethod
|
25
|
-
def
|
26
|
-
"""Convert a floating-point number to a bit array.
|
27
|
-
|
28
|
-
Args:
|
29
|
-
value (float): The floating-point number to convert.
|
30
|
-
Returns:
|
31
|
-
BitArray: A BitArray representing the bits of the floating-point number.
|
32
|
-
"""
|
33
|
-
# Pack as double precision (64 bits)
|
34
|
-
packed = struct.pack("!d", value)
|
35
|
-
# Convert to boolean list
|
36
|
-
bits = [bool((byte >> bit) & 1) for byte in packed for bit in range(7, -1, -1)]
|
37
|
-
return cls(bits)
|
38
|
-
|
39
|
-
@classmethod
|
40
|
-
def from_signed_int(cls, value: int, length: int) -> BitArray:
|
41
|
-
"""Convert a signed integer to a bit array using off-set binary representation.
|
42
|
-
|
43
|
-
Args:
|
44
|
-
value (int): The signed integer to convert.
|
45
|
-
length (int): The length of the resulting bit array.
|
46
|
-
Returns:
|
47
|
-
BitArray: A BitArray representing the bits of the signed integer.
|
48
|
-
Raises:
|
49
|
-
AssertionError: If the value is out of range for the specified length.
|
50
|
-
"""
|
51
|
-
half = 1 << (length - 1)
|
52
|
-
max_value = half - 1
|
53
|
-
min_value = -half
|
54
|
-
|
55
|
-
assert (
|
56
|
-
min_value <= value <= max_value
|
57
|
-
), "Value out of range for specified length."
|
58
|
-
|
59
|
-
# Convert to unsigned integer representation
|
60
|
-
unsigned_value = value - half
|
61
|
-
|
62
|
-
bits = [(unsigned_value >> i) & 1 == 1 for i in range(length - 1, -1, -1)]
|
63
|
-
return cls(bits)
|
64
|
-
|
65
|
-
@classmethod
|
66
|
-
def zeros(cls, length: int) -> BitArray:
|
28
|
+
def zeros(cls, length: int) -> ListBitArray:
|
67
29
|
"""Create a BitArray filled with zeros.
|
68
30
|
|
69
31
|
Args:
|
70
32
|
length: The length of the bit array.
|
71
33
|
Returns:
|
72
|
-
|
34
|
+
ListBitArray: A BitArray filled with False values.
|
73
35
|
"""
|
74
36
|
return cls([False] * length)
|
75
37
|
|
76
38
|
@classmethod
|
77
|
-
def ones(cls, length: int) ->
|
39
|
+
def ones(cls, length: int) -> ListBitArray:
|
78
40
|
"""Create a BitArray filled with ones.
|
79
41
|
|
80
42
|
Args:
|
81
43
|
length: The length of the bit array.
|
82
44
|
Returns:
|
83
|
-
|
45
|
+
ListBitArray: A BitArray filled with True values.
|
84
46
|
"""
|
85
47
|
return cls([True] * length)
|
86
48
|
|
87
49
|
@staticmethod
|
88
|
-
def parse_bitarray(bitstring: str) ->
|
50
|
+
def parse_bitarray(bitstring: str) -> ListBitArray:
|
89
51
|
"""Parse a string of bits (with optional spaces) into a BitArray instance."""
|
90
52
|
bits = [c == "1" for c in bitstring if c in "01"]
|
91
|
-
return
|
53
|
+
return ListBitArray(bits)
|
92
54
|
|
93
55
|
def to_float(self) -> float:
|
94
56
|
"""Convert a 64-bit array to a floating-point number.
|
@@ -135,7 +97,7 @@ class BitArray:
|
|
135
97
|
# If the sign bit is set, subtract the bias
|
136
98
|
return int_value - bias
|
137
99
|
|
138
|
-
def shift(self, shift_amount: int, fill: bool = False) ->
|
100
|
+
def shift(self, shift_amount: int, fill: bool = False) -> ListBitArray:
|
139
101
|
"""Shift the bit array left or right by a specified number of bits.
|
140
102
|
|
141
103
|
This function shifts the bits in the array, filling in new bits with the
|
@@ -149,7 +111,7 @@ class BitArray:
|
|
149
111
|
fill (bool): The value to fill in the new bits created by the shift.
|
150
112
|
Defaults to False.
|
151
113
|
Returns:
|
152
|
-
|
114
|
+
ListBitArray: A new BitArray with the bits shifted and filled.
|
153
115
|
"""
|
154
116
|
if shift_amount == 0:
|
155
117
|
return self.copy()
|
@@ -159,15 +121,15 @@ class BitArray:
|
|
159
121
|
new_bits = [fill] * shift_amount + self._bits[:-shift_amount]
|
160
122
|
else:
|
161
123
|
new_bits = self._bits[-shift_amount:] + [fill] * (-shift_amount)
|
162
|
-
return
|
124
|
+
return ListBitArray(new_bits)
|
163
125
|
|
164
|
-
def copy(self) ->
|
126
|
+
def copy(self) -> ListBitArray:
|
165
127
|
"""Create a copy of the bit array.
|
166
128
|
|
167
129
|
Returns:
|
168
|
-
|
130
|
+
ListBitArray: A new BitArray with the same bits.
|
169
131
|
"""
|
170
|
-
return
|
132
|
+
return ListBitArray(self._bits.copy())
|
171
133
|
|
172
134
|
def __len__(self) -> int:
|
173
135
|
"""Return the length of the bit array."""
|
@@ -176,12 +138,12 @@ class BitArray:
|
|
176
138
|
@overload
|
177
139
|
def __getitem__(self, index: int) -> bool: ...
|
178
140
|
@overload
|
179
|
-
def __getitem__(self, index: slice) ->
|
141
|
+
def __getitem__(self, index: slice) -> ListBitArray: ...
|
180
142
|
|
181
|
-
def __getitem__(self, index: int | slice) -> bool |
|
143
|
+
def __getitem__(self, index: int | slice) -> bool | ListBitArray:
|
182
144
|
"""Get an item or slice from the bit array."""
|
183
145
|
if isinstance(index, slice):
|
184
|
-
return
|
146
|
+
return ListBitArray(self._bits[index])
|
185
147
|
return self._bits[index]
|
186
148
|
|
187
149
|
@overload
|
@@ -195,7 +157,7 @@ class BitArray:
|
|
195
157
|
"""Set an item or slice in the bit array."""
|
196
158
|
if isinstance(index, slice):
|
197
159
|
if isinstance(value, BitArray):
|
198
|
-
self._bits[index] = value
|
160
|
+
self._bits[index] = list(value)
|
199
161
|
elif isinstance(value, list):
|
200
162
|
self._bits[index] = value
|
201
163
|
else:
|
@@ -210,48 +172,16 @@ class BitArray:
|
|
210
172
|
"""Iterate over the bits in the array."""
|
211
173
|
return iter(self._bits)
|
212
174
|
|
213
|
-
def __add__(self, other: BitArray | list[bool]) ->
|
175
|
+
def __add__(self, other: BitArray | list[bool]) -> ListBitArray:
|
214
176
|
"""Concatenate two bit arrays."""
|
215
177
|
if isinstance(other, BitArray):
|
216
|
-
return
|
217
|
-
return
|
178
|
+
return ListBitArray(self._bits + list(other))
|
179
|
+
return ListBitArray(self._bits + other)
|
218
180
|
|
219
|
-
def __radd__(self, other: list[bool]) ->
|
181
|
+
def __radd__(self, other: list[bool]) -> ListBitArray:
|
220
182
|
"""Reverse concatenation with a list."""
|
221
|
-
return
|
222
|
-
|
223
|
-
def __eq__(self, other: object) -> bool:
|
224
|
-
"""Check equality with another BitArray or list."""
|
225
|
-
if isinstance(other, BitArray):
|
226
|
-
return self._bits == other._bits
|
227
|
-
if isinstance(other, list):
|
228
|
-
return self._bits == other
|
229
|
-
return False
|
230
|
-
|
231
|
-
def __bool__(self) -> bool:
|
232
|
-
"""Return True if any bit is set."""
|
233
|
-
return any(self._bits)
|
183
|
+
return ListBitArray(other + self._bits)
|
234
184
|
|
235
185
|
def __repr__(self) -> str:
|
236
186
|
"""Return a string representation of the BitArray."""
|
237
|
-
return f"
|
238
|
-
|
239
|
-
def __str__(self) -> str:
|
240
|
-
"""Return a string representation of the bits."""
|
241
|
-
return "".join("1" if bit else "0" for bit in self._bits)
|
242
|
-
|
243
|
-
def any(self) -> bool:
|
244
|
-
"""Return True if any bit is set to True."""
|
245
|
-
return any(self._bits)
|
246
|
-
|
247
|
-
def all(self) -> bool:
|
248
|
-
"""Return True if all bits are set to True."""
|
249
|
-
return all(self._bits)
|
250
|
-
|
251
|
-
def count(self, value: bool = True) -> int:
|
252
|
-
"""Count the number of bits set to the specified value."""
|
253
|
-
return self._bits.count(value)
|
254
|
-
|
255
|
-
def reverse(self) -> BitArray:
|
256
|
-
"""Return a new BitArray with the bits in reverse order."""
|
257
|
-
return BitArray(self._bits[::-1])
|
187
|
+
return f"ListBitArray({self._bits})"
|
@@ -0,0 +1,93 @@
|
|
1
|
+
"""Mixin classes providing common BitArray functionality."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
import struct
|
6
|
+
from typing import Any
|
7
|
+
|
8
|
+
from .bitarray import BitArray
|
9
|
+
|
10
|
+
|
11
|
+
class BitArrayCommonMixin(BitArray):
|
12
|
+
"""Mixin providing common methods that can be implemented using the BitArray
|
13
|
+
protocol.
|
14
|
+
|
15
|
+
This mixin provides default implementations for methods that can be expressed
|
16
|
+
in terms of the core BitArray protocol methods (__iter__, __len__, etc.).
|
17
|
+
|
18
|
+
Classes using this mixin must implement the BitArray protocol.
|
19
|
+
"""
|
20
|
+
|
21
|
+
@classmethod
|
22
|
+
def from_float(cls, value: float) -> Any:
|
23
|
+
"""Convert a floating-point number to a bit array.
|
24
|
+
|
25
|
+
Args:
|
26
|
+
value (float): The floating-point number to convert.
|
27
|
+
Returns:
|
28
|
+
BitArray: A BitArray representing the bits of the floating-point number.
|
29
|
+
"""
|
30
|
+
# Pack as double precision (64 bits)
|
31
|
+
packed = struct.pack("!d", value)
|
32
|
+
# Convert to boolean list
|
33
|
+
bits = [bool((byte >> bit) & 1) for byte in packed for bit in range(7, -1, -1)]
|
34
|
+
return cls(bits)
|
35
|
+
|
36
|
+
@classmethod
|
37
|
+
def from_signed_int(cls, value: int, length: int) -> Any:
|
38
|
+
"""Convert a signed integer to a bit array using off-set binary representation.
|
39
|
+
|
40
|
+
Args:
|
41
|
+
value (int): The signed integer to convert.
|
42
|
+
length (int): The length of the resulting bit array.
|
43
|
+
Returns:
|
44
|
+
BitArray: A BitArray representing the bits of the signed integer.
|
45
|
+
Raises:
|
46
|
+
AssertionError: If the value is out of range for the specified length.
|
47
|
+
"""
|
48
|
+
half = 1 << (length - 1)
|
49
|
+
max_value = half - 1
|
50
|
+
min_value = -half
|
51
|
+
|
52
|
+
assert (
|
53
|
+
min_value <= value <= max_value
|
54
|
+
), "Value out of range for specified length."
|
55
|
+
|
56
|
+
# Convert to unsigned integer representation
|
57
|
+
unsigned_value = value - half
|
58
|
+
|
59
|
+
bits = [(unsigned_value >> i) & 1 == 1 for i in range(length - 1, -1, -1)]
|
60
|
+
return cls(bits)
|
61
|
+
|
62
|
+
def __str__(self) -> str:
|
63
|
+
"""Return a string representation of the bits."""
|
64
|
+
# This assumes self implements __iter__ as per the BitArray protocol
|
65
|
+
return "".join("1" if bit else "0" for bit in self) # type: ignore
|
66
|
+
|
67
|
+
def __eq__(self, other: object) -> bool:
|
68
|
+
"""Check equality with another BitArray or list."""
|
69
|
+
if hasattr(other, "__iter__") and hasattr(other, "__len__"):
|
70
|
+
if len(self) != len(other): # type: ignore
|
71
|
+
return False
|
72
|
+
return all(a == b for a, b in zip(self, other)) # type: ignore
|
73
|
+
return False
|
74
|
+
|
75
|
+
def __bool__(self) -> bool:
|
76
|
+
"""Return True if any bit is set."""
|
77
|
+
return self.any()
|
78
|
+
|
79
|
+
def any(self) -> bool:
|
80
|
+
"""Return True if any bit is set to True."""
|
81
|
+
return any(self) # type: ignore
|
82
|
+
|
83
|
+
def all(self) -> bool:
|
84
|
+
"""Return True if all bits are set to True."""
|
85
|
+
return all(self) # type: ignore
|
86
|
+
|
87
|
+
def count(self, value: bool = True) -> int:
|
88
|
+
"""Count the number of bits set to the specified value."""
|
89
|
+
return sum(1 for bit in self if bit == value) # type: ignore
|
90
|
+
|
91
|
+
def reverse(self) -> Any:
|
92
|
+
"""Return a new BitArray with the bits in reverse order."""
|
93
|
+
return self.__class__(list(self)[::-1]) # type: ignore
|