Source code for flexfloat.bitarray.bitarray_bool

"""List-based BitArray implementation for the flexfloat package.

This implementation is best for small or dynamically sized bit arrays.
Bit order: LSB-first (least significant bit at index 0, increasing to MSB).

Example:
    from flexfloat.bitarray import ListBoolBitArray
    ba = ListBoolBitArray([True, False, True])
    print(list(ba))
    # Output: [True, False, True]
"""

from __future__ import annotations

import struct
from typing import Iterator, overload

from .bitarray import BitArray
from .bitarray_mixins import BitArrayCommonMixin


[docs] class ListBoolBitArray(BitArrayCommonMixin): """A bit array class that encapsulates a list of booleans with utility methods. This implementation uses a list of boolean values to represent the bits, allowing for dynamic resizing and easy manipulation of individual bits. """
[docs] def __init__(self, bits: list[bool] | None = None): """Initializes a ListBoolBitArray. Args: bits (list[bool] | None, optional): Initial list of boolean values. Defaults to empty list. """ super().__init__() if bits is not None: self._bits = bits else: self._bits = []
[docs] @classmethod def from_bits(cls, bits: list[bool] | None = None) -> "ListBoolBitArray": """Creates a BitArray from a list of boolean values. Args: bits (list[bool] | None, optional): List of boolean values. Defaults to None, which creates an empty BitArray. Returns: ListBoolBitArray: A BitArray created from the bits. """ return cls(bits)
[docs] @classmethod def zeros(cls, length: int) -> "ListBoolBitArray": """Creates a BitArray filled with zeros. Args: length (int): The length of the bit array. Returns: ListBoolBitArray: A BitArray filled with False values. """ return cls([False] * length)
[docs] @classmethod def ones(cls, length: int) -> "ListBoolBitArray": """Creates a BitArray filled with ones. Args: length (int): The length of the bit array. Returns: ListBoolBitArray: A BitArray filled with True values. """ return cls([True] * length)
[docs] def to_int(self) -> int: """Converts the bit array to an unsigned integer (LSB-first). Returns: int: The integer represented by the bit array. """ return sum((1 << i) for i, bit in enumerate(self._bits) if bit)
[docs] def copy(self) -> "ListBoolBitArray": """Creates a copy of the bit array. Returns: ListBoolBitArray: A new BitArray with the same bits. """ return ListBoolBitArray(self._bits.copy())
[docs] def to_float(self) -> float: """Converts a 64-bit array to a floating-point number (LSB-first). Returns: float: The floating-point number represented by the bit array. Raises: AssertionError: If the bit array is not 64 bits long. """ assert len(self._bits) == 64, "Bit array must be 64 bits long." byte_values = bytearray() for i in range(0, 64, 8): byte = 0 for j in range(8): if self._bits[i + j]: byte |= 1 << j # LSB-first byte_values.append(byte) float_value = struct.unpack("<d", bytes(byte_values))[0] return float_value # type: ignore
[docs] def __len__(self) -> int: """Returns the length of the bit array. Returns: int: The number of bits in the array. """ return len(self._bits)
@overload def __getitem__(self, index: int) -> bool: ... @overload def __getitem__(self, index: slice) -> ListBoolBitArray: ...
[docs] def __getitem__(self, index: int | slice) -> bool | ListBoolBitArray: """Get a bit or a slice of bits as a new ListBoolBitArray.""" if isinstance(index, slice): return ListBoolBitArray.from_bits(self._bits[index]) return self._bits[index]
@overload def __setitem__(self, index: int, value: bool) -> None: ... @overload def __setitem__(self, index: slice, value: BitArray | list[bool]) -> None: ...
[docs] def __setitem__( self, index: int | slice, value: bool | list[bool] | BitArray ) -> None: """Sets an item or slice in the bit array. Args: index (int or slice): The index or slice to set. value (bool or list[bool] or BitArray): The value(s) to assign. Raises: TypeError: If value type does not match index type. """ if isinstance(index, slice): if isinstance(value, BitArray): self._bits[index] = list(value) elif isinstance(value, list): self._bits[index] = value else: raise TypeError("Cannot assign a single bool to a slice") return if isinstance(value, bool): self._bits[index] = value else: raise TypeError("Cannot assign a list or BitArray to a single index")
[docs] def __iter__(self) -> Iterator[bool]: """Iterates over the bits in the array. Yields: bool: The next bit in the array. """ return iter(self._bits)
[docs] def __add__(self, other: BitArray | list[bool]) -> "ListBoolBitArray": """Concatenates two bit arrays. Args: other (BitArray or list[bool]): The other bit array or list to concatenate. Returns: ListBoolBitArray: The concatenated bit array. """ if isinstance(other, BitArray): return ListBoolBitArray(self._bits + list(other)) return ListBoolBitArray(self._bits + other)
[docs] def __radd__(self, other: list[bool]) -> "ListBoolBitArray": """Reverse concatenation with a list. Args: other (list[bool]): The list to concatenate before this bit array. Returns: ListBoolBitArray: The concatenated bit array. """ return ListBoolBitArray(other + self._bits)
[docs] def __repr__(self) -> str: """Returns a string representation of the BitArray. Returns: str: String representation of the BitArray. """ return f"ListBoolBitArray({self._bits})"