working on toom-cook multiplication
[bigint-presentation-code.git] / src / bigint_presentation_code / util.py
1 from typing import (TYPE_CHECKING, AbstractSet, Iterable, Iterator, Mapping,
2 MutableSet, TypeVar, Union)
3
4 if TYPE_CHECKING:
5 from typing_extensions import Literal, final
6 else:
7 def final(v):
8 return v
9
10 class _Literal:
11 def __getitem__(self, v):
12 if isinstance(v, tuple):
13 return Union[tuple(type(i) for i in v)]
14 return type(v)
15
16 Literal = _Literal()
17
18 _T_co = TypeVar("_T_co", covariant=True)
19 _T = TypeVar("_T")
20
21 __all__ = ["final", "Literal", "OFSet", "OSet", "FMap"]
22
23
24 class OFSet(AbstractSet[_T_co]):
25 """ ordered frozen set """
26 __slots__ = "__items",
27
28 def __init__(self, items=()):
29 # type: (Iterable[_T_co]) -> None
30 self.__items = {v: None for v in items}
31
32 def __contains__(self, x):
33 return x in self.__items
34
35 def __iter__(self):
36 return iter(self.__items)
37
38 def __len__(self):
39 return len(self.__items)
40
41 def __hash__(self):
42 return self._hash()
43
44 def __repr__(self):
45 if len(self) == 0:
46 return "OFSet()"
47 return f"OFSet({list(self)})"
48
49
50 class OSet(MutableSet[_T]):
51 """ ordered mutable set """
52 __slots__ = "__items",
53
54 def __init__(self, items=()):
55 # type: (Iterable[_T]) -> None
56 self.__items = {v: None for v in items}
57
58 def __contains__(self, x):
59 return x in self.__items
60
61 def __iter__(self):
62 return iter(self.__items)
63
64 def __len__(self):
65 return len(self.__items)
66
67 def add(self, value):
68 # type: (_T) -> None
69 self.__items[value] = None
70
71 def discard(self, value):
72 # type: (_T) -> None
73 self.__items.pop(value, None)
74
75 def __repr__(self):
76 if len(self) == 0:
77 return "OSet()"
78 return f"OSet({list(self)})"
79
80
81 class FMap(Mapping[_T, _T_co]):
82 """ordered frozen hashable mapping"""
83 __slots__ = "__items", "__hash"
84
85 def __init__(self, items=()):
86 # type: (Mapping[_T, _T_co] | Iterable[tuple[_T, _T_co]]) -> None
87 self.__items = dict(items) # type: dict[_T, _T_co]
88 self.__hash = None # type: None | int
89
90 def __getitem__(self, item):
91 # type: (_T) -> _T_co
92 return self.__items[item]
93
94 def __iter__(self):
95 # type: () -> Iterator[_T]
96 return iter(self.__items)
97
98 def __len__(self):
99 return len(self.__items)
100
101 def __eq__(self, other):
102 # type: (object) -> bool
103 if isinstance(other, FMap):
104 return self.__items == other.__items
105 return super().__eq__(other)
106
107 def __hash__(self):
108 if self.__hash is None:
109 self.__hash = hash(frozenset(self.items()))
110 return self.__hash
111
112 def __repr__(self):
113 return f"FMap({self.__items})"