1from __future__ import annotations
2
3import struct
4import math
5import functools
6from typing import Union, Optional, Dict, Callable
7import bitarray
8import bitstring
9from bitstring.fp8 import p4binary_fmt, p3binary_fmt
10from bitstring.mxfp import (e3m2mxfp_fmt, e2m3mxfp_fmt, e2m1mxfp_fmt, e4m3mxfp_saturate_fmt,
11 e5m2mxfp_saturate_fmt, e4m3mxfp_overflow_fmt, e5m2mxfp_overflow_fmt)
12from bitstring.helpers import tidy_input_string
13
14ConstBitStore = bitstring.bitstore.ConstBitStore
15MutableBitStore = bitstring.bitstore.MutableBitStore
16
17
18def bin2bitstore(binstring: str) -> ConstBitStore:
19 binstring = tidy_input_string(binstring)
20 binstring = binstring.replace('0b', '')
21 try:
22 return ConstBitStore.from_bin(binstring)
23 except ValueError:
24 raise bitstring.CreationError(f"Invalid character in bin initialiser {binstring}.")
25
26
27def hex2bitstore(hexstring: str) -> ConstBitStore:
28 hexstring = tidy_input_string(hexstring)
29 hexstring = hexstring.replace('0x', '')
30 try:
31 ba = bitarray.util.hex2ba(hexstring)
32 except ValueError:
33 raise bitstring.CreationError("Invalid symbol in hex initialiser.")
34 return ConstBitStore(ba)
35
36
37def oct2bitstore(octstring: str) -> ConstBitStore:
38 octstring = tidy_input_string(octstring)
39 octstring = octstring.replace('0o', '')
40 try:
41 ba = bitarray.util.base2ba(8, octstring)
42 except ValueError:
43 raise bitstring.CreationError("Invalid symbol in oct initialiser.")
44 return ConstBitStore(ba)
45
46
47def int2bitstore(i: int, length: int, signed: bool) -> ConstBitStore:
48 i = int(i)
49 try:
50 x = ConstBitStore(bitarray.util.int2ba(i, length=length, endian='big', signed=signed))
51 except OverflowError as e:
52 if signed:
53 if i >= (1 << (length - 1)) or i < -(1 << (length - 1)):
54 raise bitstring.CreationError(f"{i} is too large a signed integer for a bitstring of length {length}. "
55 f"The allowed range is [{-(1 << (length - 1))}, {(1 << (length - 1)) - 1}].")
56 else:
57 if i >= (1 << length):
58 raise bitstring.CreationError(f"{i} is too large an unsigned integer for a bitstring of length {length}. "
59 f"The allowed range is [0, {(1 << length) - 1}].")
60 if i < 0:
61 raise bitstring.CreationError("uint cannot be initialised with a negative number.")
62 raise e
63 return x
64
65
66def intle2bitstore(i: int, length: int, signed: bool) -> ConstBitStore:
67 x = int2bitstore(i, length, signed).to_bytes()
68 return ConstBitStore.from_bytes(x[::-1])
69
70
71def float2bitstore(f: Union[str, float], length: int, big_endian: bool) -> ConstBitStore:
72 f = float(f)
73 fmt = {16: '>e', 32: '>f', 64: '>d'}[length] if big_endian else {16: '<e', 32: '<f', 64: '<d'}[length]
74 try:
75 b = struct.pack(fmt, f)
76 except OverflowError:
77 # If float64 doesn't fit it automatically goes to 'inf'. This reproduces that behaviour for other types.
78 b = struct.pack(fmt, float('inf') if f > 0 else float('-inf'))
79 return ConstBitStore.from_bytes(b)
80