|
"""A representation of the two's complement format used for INT8.""" |
|
from dataclasses import dataclass |
|
from functools import total_ordering |
|
from typing import Any |
|
|
|
|
|
@dataclass |
|
class TwosComplementFormat: |
|
"""Can be used to express any two's complement signed integer.""" |
|
|
|
width: int |
|
|
|
@property |
|
def abs_min(self) -> float: |
|
"""Absolute minimum representable value.""" |
|
return 1 |
|
|
|
@property |
|
def abs_max(self) -> float: |
|
"""Absolute maximum representable value.""" |
|
return float(2 ** (self.width - 1) - 1) |
|
|
|
|
|
@dataclass |
|
class ScaledTwosComplementFormat(TwosComplementFormat): |
|
"""A scaled (multiply all values by `scale`) version of `TwosComplementFormat`.""" |
|
|
|
scale: int |
|
|
|
@property |
|
def abs_min(self) -> float: |
|
return super().abs_min * self.scale |
|
|
|
@property |
|
def abs_max(self) -> float: |
|
return super().abs_max * self.scale |
|
|
|
|
|
@dataclass |
|
@total_ordering |
|
class TwosComplementInstance: |
|
"""An instance of a number using a (possibly scaled) `TwosComplementFormat`.""" |
|
|
|
format: TwosComplementFormat |
|
uint: int |
|
|
|
def __post_init__(self) -> None: |
|
assert 0 <= self.uint < 2**self.format.width, self.uint |
|
|
|
@property |
|
def value(self) -> float: |
|
"""The numerical value of the bitstring, |
|
as defined by the two's complement format. |
|
""" |
|
if self.uint <= self.format.abs_max: |
|
return self.uint |
|
return float(self.uint - 2**self.format.width) |
|
|
|
def __repr__(self) -> str: |
|
return str(self.value) |
|
|
|
def __eq__(self, other: Any) -> bool: |
|
return self.value.__eq__(other) |
|
|
|
def __lt__(self, other: Any) -> bool: |
|
return self.value.__lt__(other) |