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.
@@ -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
- class BitArray:
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 from_float(cls, value: float) -> BitArray:
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
- BitArray: A BitArray filled with False values.
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) -> BitArray:
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
- BitArray: A BitArray filled with True values.
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) -> BitArray:
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 BitArray(bits)
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) -> BitArray:
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
- BitArray: A new BitArray with the bits shifted and filled.
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 BitArray(new_bits)
124
+ return ListBitArray(new_bits)
163
125
 
164
- def copy(self) -> BitArray:
126
+ def copy(self) -> ListBitArray:
165
127
  """Create a copy of the bit array.
166
128
 
167
129
  Returns:
168
- BitArray: A new BitArray with the same bits.
130
+ ListBitArray: A new BitArray with the same bits.
169
131
  """
170
- return BitArray(self._bits.copy())
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) -> BitArray: ...
141
+ def __getitem__(self, index: slice) -> ListBitArray: ...
180
142
 
181
- def __getitem__(self, index: int | slice) -> bool | BitArray:
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 BitArray(self._bits[index])
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._bits
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]) -> BitArray:
175
+ def __add__(self, other: BitArray | list[bool]) -> ListBitArray:
214
176
  """Concatenate two bit arrays."""
215
177
  if isinstance(other, BitArray):
216
- return BitArray(self._bits + other._bits)
217
- return BitArray(self._bits + other)
178
+ return ListBitArray(self._bits + list(other))
179
+ return ListBitArray(self._bits + other)
218
180
 
219
- def __radd__(self, other: list[bool]) -> BitArray:
181
+ def __radd__(self, other: list[bool]) -> ListBitArray:
220
182
  """Reverse concatenation with a list."""
221
- return BitArray(other + self._bits)
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"BitArray({self._bits})"
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