diff options
author | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
---|---|---|
committer | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
commit | 4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch) | |
tree | ee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/fixedint | |
parent | cc961e04ba734dd72309fb548a2f97d67d578813 (diff) | |
download | gn-ai-master.tar.gz |
Diffstat (limited to '.venv/lib/python3.12/site-packages/fixedint')
6 files changed, 835 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/fixedint/__init__.py b/.venv/lib/python3.12/site-packages/fixedint/__init__.py new file mode 100644 index 00000000..c9c575a8 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/fixedint/__init__.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from fixedint.base import FixedInt, MutableFixedInt +from fixedint.aliases import * + +def test(verbosity=1, repeat=1): + from fixedint import test_fixedint + return test_fixedint.run(verbosity, repeat) diff --git a/.venv/lib/python3.12/site-packages/fixedint/aliases.py b/.venv/lib/python3.12/site-packages/fixedint/aliases.py new file mode 100644 index 00000000..66c379a9 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/fixedint/aliases.py @@ -0,0 +1,11 @@ +from fixedint.base import FixedInt, MutableFixedInt + +__all__ = [] + +for i in [8,16,32,64]: + for s in [True, False]: + for m in [True, False]: + cls = FixedInt(i, signed=s, mutable=m) + cls.__module__ = __name__ + __all__ += [cls.__name__] + globals()[cls.__name__] = cls diff --git a/.venv/lib/python3.12/site-packages/fixedint/base.py b/.venv/lib/python3.12/site-packages/fixedint/base.py new file mode 100644 index 00000000..ff93d43b --- /dev/null +++ b/.venv/lib/python3.12/site-packages/fixedint/base.py @@ -0,0 +1,468 @@ +# -*- coding: utf-8 -*- + +import sys +from fixedint.compat import * +from weakref import WeakValueDictionary + +class FixedProperty(object): + def __init__(self, val, doc): + self.val = val + self.__doc__ = doc + def __get__(self, obj, type=None): + return self.val + def __set__(self, obj, value): + raise AttributeError("property is read-only") + +class FixedMetaProperty(object): + def __init__(self, name, doc): + self.name = name + self.__doc__ = doc + def __get__(self, obj, type=None): + if self.name not in obj.__dict__: + # this should only happen when trying to access FixedInt.prop, which help() does + raise AttributeError("Attribute %s not defined on base class" % self.name) + prop = obj.__dict__[self.name] + return prop.__get__(obj) + def __set__(self, obj, value): + raise AttributeError("property %s is read-only" % self.name) + +if not PY3K: + # While it'd be nice to put machine-sized integers into Python 2.x "int"s, + # it turns out that the int methods occasionally freak out when given longs. + # So, we use arbitrary-precision ints for all Pythons. + int = long + +_class_cache = WeakValueDictionary() + +_doc_width = "Bit width of this integer, including the sign bit." +_doc_signed = "True if this integer is a twos-complement signed type." +_doc_mutable = "True if this integer is mutable (modifiable in-place)." +_doc_minval = "Minimum representable value of this integer type" +_doc_maxval = "Maximum representable value of this integer type" + +_subclass_token = object() +class _FixedIntBaseMeta(type): + def __new__(cls, name, bases, dict): + if dict.get('_subclass_enable', None) == _subclass_token: + del dict['_subclass_enable'] + return type.__new__(cls, name, bases, dict) + + for base in bases: + if issubclass(base, FixedInt): + basename = base.__name__ + raise Exception("Cannot subclass %s; use the %s constructor to produce new subclasses." % (basename, basename)) + raise Exception("Cannot subclass this class.") + + def __call__(self, width, signed=True, mutable=None): + signed = bool(signed) + if mutable is None: + # Take mutable from constructor used (FixedInt or MutableFixedInt) + mutable = (self == MutableFixedInt) + + cachekey = (width, signed, mutable) + try: + return _class_cache[cachekey] + except KeyError: + pass + + if signed: + min = -1<<(width-1) + max = (1<<(width-1))-1 + else: + min = 0 + max = (1<<width)-1 + + if mutable: + bases = (MutableFixedInt,) + else: + bases = (FixedInt, int) + + dict = {} + dict['width'] = FixedProperty(width, doc=_doc_width) + dict['signed'] = FixedProperty(signed, doc=_doc_signed) + dict['mutable'] = FixedProperty(mutable, doc=_doc_mutable) + dict['minval'] = FixedProperty(min, doc=_doc_minval) + dict['maxval'] = FixedProperty(max, doc=_doc_maxval) + + if signed: + _mask1 = (1<<(width-1)) - 1 + _mask2 = 1<<(width-1) + def _rectify(val): + return (val & _mask1) - (val & _mask2) + else: + _mask = (1<<width) - 1 + def _rectify(val): + return val & _mask + dict['_rectify'] = staticmethod(_rectify) + + if not mutable: + intbase = bases[1] + def _newfunc(cls, val=0): + ''' Convert an integer into a fixed-width integer. ''' + return intbase.__new__(cls, _rectify(int(val))) + _newfunc.__name__ = '__new__' + dict['__new__'] = _newfunc + + name = ''.join(['Mutable'*mutable, 'U'*(not signed), 'Int', str(width)]) + + cls = _FixedIntMeta(name, bases, dict) + _class_cache[cachekey] = cls + return cls + + width = FixedMetaProperty('width', doc=_doc_width) + signed = FixedMetaProperty('signed', doc=_doc_signed) + mutable = FixedMetaProperty('mutable', doc=_doc_mutable) + minval = FixedMetaProperty('minval', doc=_doc_minval) + maxval = FixedMetaProperty('maxval', doc=_doc_maxval) + +class _FixedIntMeta(_FixedIntBaseMeta): + __new__ = type.__new__ + __call__ = type.__call__ + + +def int_method(f): + if isinstance(f, str): + def wrapper(f2): + f2.__name__ = f + return int_method(f2) + return wrapper + else: + f.__doc__ = getattr(int, f.__name__).__doc__ + return f + +class FixedInt: + __slots__ = () + _subclass_enable = _subclass_token + + # width, signed, mutable, minval, maxval defined in metaclass + # _rectify defined in metaclass + # __new__ defined in metaclass + + if not PY3K: + @int_method + def __hex__(self): + return '%#x' % int(self) + def __oct__(self): + return '%#o' % int(self) + + @int_method + def __pow__(self, other, modulo=None): + # Jython can't handle int.__pow__(x, y, None) + if modulo is None: + return type(self)(int.__pow__(int(self), int(other))) + return type(self)(int.__pow__(int(self), int(other), modulo)) + + @int_method + def __rpow__(self, other): + return type(other)(int.__rpow__(int(self), int(other))) + + @int_method + def __repr__(self): + return '%s(%s)' % (type(self).__name__, self) + + @int_method + def __str__(self): + return str(int(self)) + + @classmethod + def _canonicalize_index(cls, idx): + if idx < 0: + idx += cls.width + return idx + + @classmethod + def _canonicalize_slice(cls, slice): + start = slice.start + stop = slice.stop + + if slice.step is not None: + raise ValueError("slice step unsupported") + + if start is None: + start = 0 + else: + start = cls._canonicalize_index(start) + + if stop is None: + stop = cls.width + elif isinstance(stop, complex): + if stop.real: + raise ValueError("invalid slice stop: must be integer or pure-imaginary complex number") + stop = int(stop.imag) + start + else: + stop = cls._canonicalize_index(stop) + + if 0 <= start < stop <= cls.width: + return (start, stop) + else: + raise IndexError("invalid slice %d:%d" % (start, stop)) + + def __getitem__(self, item): + ''' Slice the bits of an integer. + + x[a] gets a single bit at position a, returning a bool. + x[a:b] gets a range of bits as a FixedInt. + + For slice notation, b may be of the form 'bj' (a complex number) to treat it + as a length rather than a stop index. + The result will be of the type UIntX, where X is the number of bits in the range. + + Examples: + x[0]: equal to (x & 1) + x[1:5] or x[1:4j]: equal to (x & 31) >> 1 + x[:5]: equal to (x & 31) + ''' + + if isinstance(item, slice): + start, stop = self._canonicalize_slice(item) + return FixedInt(stop - start, signed=False)(int(self) >> start) + else: + item = self._canonicalize_index(item) + if 0 <= item < self.width: + return bool(int(self) & (1 << item)) + else: + raise IndexError("index %d out of range" % item) + + def to_bytes(self, length=None, byteorder=sys.byteorder): + if length is None: + length = (self.width + 7) // 8 + try: + return int(self).to_bytes(length, byteorder=byteorder, signed=self.signed) + except (OverflowError, AttributeError): + pass + + val = int(self) & ((1 << (length * 8)) - 1) + out = [] + while length > 0: + out.append(val & 0xff) + val >>= 8 + length -= 1 + if byteorder == 'big': + out = reversed(out) + if PY3K: + return bytes(out) + else: + return ''.join(map(chr, out)) + + @classmethod + def from_bytes(cls, bytes, byteorder=sys.byteorder, signed=None): + if cls in (FixedInt, MutableFixedInt): + if signed is None: + signed = False + elif signed is None: + signed = cls.signed + else: + raise ValueError("can't set signed with a concrete FixedInt") + + blen = len(bytes) + try: + val = int.from_bytes(bytes, byteorder=byteorder, signed=signed) + except AttributeError: + val = 0 + if byteorder == 'big': + bytes = reversed(bytes) + if PY3K: + for i,c in enumerate(bytes): + val |= c << (8 * i) + else: + for i,c in enumerate(bytes): + val |= ord(c) << (8 * i) + + if cls in (FixedInt, MutableFixedInt): + return cls(blen*8, signed=signed)(val) + else: + return cls(val) + + if PY3K: + @int_method + def __round__(self, n=0): + return int(self) + + # Inherited methods which are fine as-is: + # complex, int, long, float, index + # truediv, rtruediv, divmod, rdivmod, rlshift, rrshift + # format + +FixedInt = add_metaclass(_FixedIntBaseMeta)(FixedInt) + + +class MutableFixedInt(FixedInt): + _subclass_enable = _subclass_token + + def __init__(self, val=0, base=None): + ''' Convert an integer into a fixed-width integer. ''' + if base is None: + val = int(val) + else: + val = int(val, base) + + self._val = self._rectify(val) + + if PY3K: + @int_method + def __format__(self, format_spec): + return format(self._val, format_spec) + + def __ipow__(self, other, modulo=None): + if modulo is None: + self._val = self._rectify(int.__pow__(int(self), int(other))) + else: + self._val = self._rectify(int.__pow__(int(self), int(other), modulo)) + return self + + def __setitem__(self, item, value): + ''' Modify a slice of an integer. + + x[a]=y sets a single bit at position a. + x[a:b]=y sets a range of bits from an integer. + + See __getitem__ for more details on the slice notation. + ''' + + value = int(value) + if isinstance(item, slice): + start, stop = self._canonicalize_slice(item) + mask = (1 << (stop - start)) - 1 + self._val = (self._val & ~(mask << start)) | ((value & mask) << start) + else: + item = self._canonicalize_index(item) + if 0 <= item < self.width: + if value: + self._val |= (1 << item) + else: + self._val &= ~(1 << item) + return bool(int(self) & (1 << item)) + else: + raise IndexError("index %d out of range" % item) + +## Arithmetic methods +def _arith_unary_factory(name, mutable): + ''' Factory function producing methods for unary operations. ''' + intfunc = getattr(int, name) + if mutable: + @int_method(name) + def _f(self): + return type(self)(intfunc(self._val)) + else: + @int_method(name) + def _f(self): + return type(self)(intfunc(self)) + return _f + +_arith_unary = 'neg pos abs invert'.split() +for f in _arith_unary: + s = '__%s__' % f + setattr(FixedInt, s, _arith_unary_factory(s, mutable=False)) + setattr(MutableFixedInt, s, _arith_unary_factory(s, mutable=True)) + + +def _arith_convert(t1, t2): + if not issubclass(t2, FixedInt): + return t1 + + # Follow C conversion rules (ISO/IEC 9899:TC3 ยง6.3.1.8) + if t1.signed == t2.signed: + # If both are signed or both are unsigned, return the larger type. + if t1.width >= t2.width: + return t1 + return t2 + + if not t1.signed: + ut, st = t1, t2 + else: + ut, st = t2, t1 + + if ut.width >= st.width: + # If the unsigned type has rank >= the signed type, convert the signed type to the unsigned type. + return ut + else: + return st + +def _arith_binfunc_factory(name): + ''' Factory function producing methods for arithmetic operators ''' + intfunc = getattr(int, name) + @int_method(name) + def _f(self, other): + nt = _arith_convert(type(self), type(other)) + return nt(intfunc(int(self), int(other))) + return _f + +# divmod, rdivmod, truediv, rtruediv are considered non-arithmetic since they don't return ints +# pow, rpow, rlshift, and rrshift are special since the LHS and RHS are very different +_arith_binfunc = 'add sub mul floordiv mod lshift rshift and xor or'.split() +_arith_binfunc += 'radd rsub rmul rfloordiv rmod rand rxor ror'.split() +if not PY3K: + _arith_binfunc += 'div rdiv'.split() + +for f in _arith_binfunc: + s = '__%s__' % f + setattr(FixedInt, s, _arith_binfunc_factory(s)) + + +## Non-arithmetic methods (Mutable only) +def _nonarith_unary_factory_mutable(name): + ''' Factory function producing methods for unary operations. ''' + intfunc = getattr(int, name) + @int_method(name) + def _f(self): + return intfunc(self._val) + return _f + +_mutable_unary = 'int float'.split() +if sys.version_info[:2] >= (2,5): + _mutable_unary += ['index'] +if sys.version_info[:2] >= (2,6): + _mutable_unary += ['trunc'] +if PY3K: + _mutable_unary += 'bool'.split() +else: + _mutable_unary += 'nonzero long'.split() + +for f in _mutable_unary: + s = '__%s__' % f + setattr(MutableFixedInt, s, _nonarith_unary_factory_mutable(s)) + + +def _nonarith_binfunc_factory_mutable(name): + ''' Factory function producing methods for non-arithmetic binary operators on Mutable instances. ''' + intfunc = getattr(int, name) + @int_method(name) + def _f(self, other): + return intfunc(self._val, int(other)) + return _f + +_mutable_binfunc = 'truediv rtruediv divmod rdivmod rlshift rrshift'.split() +if hasattr(int, '__cmp__'): + _mutable_binfunc += ['cmp'] +else: + _mutable_binfunc += 'lt le eq ne gt ge'.split() +for f in _mutable_binfunc: + s = '__%s__' % f + setattr(MutableFixedInt, s, _nonarith_binfunc_factory_mutable(s)) + + +## In-place operators +def _inplace_factory_mutable(iname, name, op): + ''' Factory function producing methods for augmented assignments on Mutable instances. ''' + # This uses compiled operators instead of an int.__X__ function call for speed. + # Measured improvement is about 15% speed increase. + exec(""" +def _f(self, other): + self._val = self._rectify(self._val %s int(other)) + return self +globals()['_f'] = _f""" % op) + _f.__name__ = iname + doc = list.__iadd__.__doc__ + if doc: + _f.__doc__ = doc.replace('__iadd__', name).replace('+=', op+'=') + return _f + +# pow is special because it takes three arguments. +_inplace_func = 'add,+ sub,- mul,* truediv,/ floordiv,// mod,% lshift,<< rshift,<< and,& or,| xor,^'.split() +if not PY3K: + _inplace_func += ['div,/'] +for f in _inplace_func: + fn, op = f.split(',') + si = '__i%s__' % fn + so = '__%s__' % fn + setattr(MutableFixedInt, si, _inplace_factory_mutable(si, so, op)) diff --git a/.venv/lib/python3.12/site-packages/fixedint/compat.py b/.venv/lib/python3.12/site-packages/fixedint/compat.py new file mode 100644 index 00000000..4dcc240c --- /dev/null +++ b/.venv/lib/python3.12/site-packages/fixedint/compat.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +import sys + +PY3K = sys.version_info[0] >= 3 + +# add_metaclass from six.py, (c) 2010-2014 Benjamin Peterson +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper diff --git a/.venv/lib/python3.12/site-packages/fixedint/test_fixedint.py b/.venv/lib/python3.12/site-packages/fixedint/test_fixedint.py new file mode 100644 index 00000000..721f6742 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/fixedint/test_fixedint.py @@ -0,0 +1,319 @@ +import unittest +import sys + +PY3K = sys.version_info[0] >= 3 + +from fixedint import * + +tests = [] + +# ---------------------------------------------------------------------------- +class ClassTests(unittest.TestCase): + def test_subclass_base(self): + self.assertRaises(Exception, type, 'TestClass', (FixedInt,), {}) + self.assertRaises(Exception, type, 'TestClass', (MutableFixedInt,), {}) + + def test_class_cache(self): + self.assertEqual(FixedInt(99), FixedInt(99)) + self.assertEqual(MutableFixedInt(42), MutableFixedInt(42)) + + def test_aliases(self): + self.assertEqual(FixedInt(8), Int8) + self.assertEqual(FixedInt(16), Int16) + self.assertEqual(FixedInt(32), Int32) + self.assertEqual(FixedInt(64), Int64) + self.assertEqual(FixedInt(8, signed=False), UInt8) + self.assertEqual(FixedInt(16, signed=False), UInt16) + self.assertEqual(FixedInt(32, signed=False), UInt32) + self.assertEqual(FixedInt(64, signed=False), UInt64) + + def test_subclassing(self): + from fixedint.util import HexFormattingMixin + class MyUInt32(HexFormattingMixin, UInt32): + pass + self.assertEqual(str(MyUInt32(32)), '0x00000020') + +tests.append(ClassTests) + +# ---------------------------------------------------------------------------- +class BasicTests(unittest.TestCase): + def test_properties(self): + f3 = FixedInt(3) + self.assertEqual(f3.width, 3) + self.assertEqual(f3.mutable, False) + self.assertEqual(f3.signed, True) + self.assertEqual(f3.minval, -4) + self.assertEqual(f3.maxval, 3) + + f3 = MutableFixedInt(3) + self.assertEqual(f3.width, 3) + self.assertEqual(f3.mutable, True) + self.assertEqual(f3.signed, True) + self.assertEqual(f3.minval, -4) + self.assertEqual(f3.maxval, 3) + + f3 = FixedInt(3, signed=False) + self.assertEqual(f3.width, 3) + self.assertEqual(f3.mutable, False) + self.assertEqual(f3.signed, False) + self.assertEqual(f3.minval, 0) + self.assertEqual(f3.maxval, 7) + + f3 = MutableFixedInt(3, signed=False) + self.assertEqual(f3.width, 3) + self.assertEqual(f3.mutable, True) + self.assertEqual(f3.signed, False) + self.assertEqual(f3.minval, 0) + self.assertEqual(f3.maxval, 7) + + def test_rectify(self): + for f10 in [FixedInt(10), MutableFixedInt(10)]: + self.assertEqual(int(f10(1024)), 0) + self.assertEqual(int(f10(1025)), 1) + self.assertEqual(int(f10(511)), 511) + self.assertEqual(int(f10(512)), -512) + + for f10 in [FixedInt(10, signed=False), MutableFixedInt(10, signed=False)]: + self.assertEqual(int(f10(1024)), 0) + self.assertEqual(int(f10(1025)), 1) + self.assertEqual(int(f10(511)), 511) + self.assertEqual(int(f10(512)), 512) + + def test_simple_arith(self): + for f8 in [Int8, MutableInt8]: + a = f8(15) + b = f8(10) + self.assertEqual(int(a+b), 25) + self.assertEqual(int(a-b), 5) + self.assertEqual(int(a*b), (150-256)) + self.assertEqual(a.__truediv__(b), 1.5) + self.assertEqual(int(a // b), 1) + self.assertEqual(divmod(a, b), (1, 5)) + self.assertEqual(divmod(15, b), (1, 5)) + self.assertEqual(divmod(a, 10), (1, 5)) + self.assertEqual(int(a)**b, 15**10) + self.assertEqual(int(a<<8), 0) + self.assertEqual(8<<a, 8<<15) + self.assertEqual(int(~a), ~15) + self.assertEqual(int(-a), -15) + self.assertEqual(int((~a) & 0xff), ~15) + for f64 in [Int64, MutableInt64]: + a = f64(15) + b = f64(10) + self.assertEqual(int(a+b), 25) + self.assertEqual(int(a-b), 5) + self.assertEqual(int(a*b), 150) + self.assertEqual(a.__truediv__(b), 1.5) + self.assertEqual(int(a // b), 1) + self.assertEqual(divmod(a, b), (1, 5)) + self.assertEqual(divmod(15, b), (1, 5)) + self.assertEqual(divmod(a, 10), (1, 5)) + self.assertEqual(int(a)**b, 15**10) + self.assertEqual(int(a<<8), 15<<8) + self.assertEqual(8<<a, 8<<15) + self.assertEqual(int(~a), ~15) + self.assertEqual(int(-a), -15) + + def test_typecast(self): + import math + for f16 in [Int16, MutableInt16]: + x = f16(42) + self.assertEqual(int(x), 42) + self.assertEqual(float(x), 42) + self.assertEqual(complex(x), 42) + self.assertEqual(round(x), 42) + if not PY3K: + self.assertEqual(long(x), 42) + self.assertEqual(bool(x), True) + if sys.version_info[:2] >= (2,5): + self.assertEqual(list(range(100))[x], 42) + if sys.version_info[:2] >= (2,6): + self.assertEqual(math.trunc(x), 42) + + x = f16(0) + self.assertEqual(bool(x), False) + + def test_compare(self): + for f32 in [Int32, MutableInt32]: + x = f32(1000000) + self.assertEqual(x, 1000000) + self.assertNotEqual(x, 1000000 + (1<<32)) + self.assertEqual(x, f32(1000000 + (1<<32))) + self.assertNotEqual(x, 1000001) + self.assertTrue(x <= 1000000) + self.assertTrue(x >= 1000000) + self.assertTrue(x < 1000001) + self.assertTrue(x > 999999) + if not PY3K: + self.assertTrue(cmp(x, 999999) > 0) + + def test_implicit_conversion(self): + f = FixedInt(72) + x = f(32767) + y = x + self.assertEqual(x, y) + x += 100 + self.assertNotEqual(x, y) + x += FixedInt(80)(1<<79) + self.assertEqual(x.width, 80) + + def test_inplace_operators(self): + mf = MutableFixedInt(72) + x = mf(32767) + y = x + self.assertEqual(x, y) + x += 100 + self.assertEqual(x, y) + x += MutableFixedInt(80)(1<<79) + self.assertEqual(x.width, 72) + x >>= 100 + self.assertEqual(x, 0) + x += 2 + self.assertEqual(y, 2) + x **= 70 + self.assertEqual(y, 2**70) + + def test_str(self): + for ff in [FixedInt(12), MutableFixedInt(12), FixedInt(91), MutableFixedInt(91)]: + self.assertEqual(str(ff(1)), '1') + self.assertEqual(repr(ff(1)), '%s(1)' % ff.__name__) + self.assertEqual(str(ff(-1)), '-1') + self.assertEqual(hex(ff(1)), '0x1') + +tests.append(BasicTests) + +# ---------------------------------------------------------------------------- +class ExtraFunctionTests(unittest.TestCase): + def test_bytes(self): + for ff in [FixedInt(96), MutableFixedInt(96)]: + val = ff(-1) + if PY3K: + byte = lambda c: bytes([c]) + else: + byte = lambda c: chr(c) + self.assertEqual(val.to_bytes(), byte(255) * 12) + self.assertEqual(val.to_bytes(8), byte(255) * 8) + self.assertEqual(ff.from_bytes(byte(255) * 12), val) + + for ff in [FixedInt(32), MutableFixedInt(32)]: + for v in [0xdeadbeef, 0xfeedface, 0x0badf00d, 0x12345678, 0x87654321]: + for endian in ['big', 'little']: + val = ff(v) + data = val.to_bytes(byteorder=endian) + self.assertEqual(len(data), 4) + val2 = ff.from_bytes(data, byteorder=endian) + self.assertEqual(val, val2) + + for ff in [UInt32, MutableUInt32]: + for v in [0xdeadbeef, 0xfeedface, 0x0badf00d, 0x12345678, 0x87654321]: + for endian in ['big', 'little']: + val = ff(v) + data = val.to_bytes(byteorder=endian) + self.assertEqual(len(data), 4) + val2 = FixedInt.from_bytes(data, byteorder=endian, signed=False) + self.assertTrue(type(val2).__name__.endswith('UInt32')) + self.assertEqual(val, val2) + + t = UInt32(32).to_bytes() + self.assertRaises(ValueError, UInt32.from_bytes, t, signed=True) + + def test_slice_errors(self): + ff = FixedInt(24) + val = ff(1024) + # Steps unsupported + self.assertRaises(ValueError, lambda:val[::-1]) + self.assertRaises(ValueError, lambda:val[::1]) + # Mixed complex numbers unsupported + self.assertRaises(ValueError, lambda:val[:2+4j]) + # Invalid indices + self.assertRaises(IndexError, lambda:val[100:200]) + self.assertRaises(IndexError, lambda:val[5:0]) + self.assertRaises(IndexError, lambda:val[1024]) + + def test_getslice(self): + for ff in [FixedInt(48), MutableFixedInt(48)]: + testval = 0xfedcba123456 + fixed = ff(testval) + + x = testval + for i in range(48): + self.assertEqual(fixed[i], x & 1) + x >>= 1 + + x = testval + for i in range(12): + r = fixed[i*4:i*4+4] + self.assertEqual(r, x & 0xf) + self.assertEqual(r.width, 4) + self.assertEqual(r.signed, False) + x >>= 4 + + x = testval + for i in range(12): + r = fixed[i*4:4j] + self.assertEqual(r, x & 0xf) + self.assertEqual(r.width, 4) + self.assertEqual(r.signed, False) + x >>= 4 + + def test_setslice(self): + ff = MutableFixedInt(28, signed=False) + testval = 0xbadf00d + val = ff(0) + for i in range(28): + val[i] = testval & (1<<i) + self.assertEqual(val, testval) + + val = ff(0) + x = testval + for i in range(7): + val[i*4:i*4+4] = x & 0xf + x >>= 4 + self.assertEqual(val, testval) + + val = ff(0) + x = testval + for i in range(7): + val[i*4:4j] = x & 0xf + x >>= 4 + self.assertEqual(val, testval) + + val = ff(0) + val2 = val + val[:] = testval + self.assertEqual(val2, testval) + + def test_setslice_fixedint(self): + # Regression test for GitHub issue #3 + f16 = FixedInt(16, signed=False, mutable=True) + f8 = FixedInt(8, signed=False, mutable=True) + x = f16(0x0FFF) + y = f8(3) + x[0:8] = int(y) + assert repr(x) == 'MutableUInt16(3843)' + x[0:8] = y + assert repr(x) == 'MutableUInt16(3843)' + + f95 = FixedInt(95, signed=False, mutable=True) + f40 = FixedInt(40, signed=False, mutable=True) + x = f95(0x0FFFFFFFFFFFFFFF) + y = f40(0xF)[0:40] + x[0:40] = int(y) + assert bin(x) == '0b111111111111111111110000000000000000000000000000000000001111' + x[0:40] = y + assert bin(x) == '0b111111111111111111110000000000000000000000000000000000001111' + +tests.append(ExtraFunctionTests) + +# ---------------------------------------------------------------------------- +def run(verbosity=1, repeat=1): + suite = unittest.TestSuite() + for cls in tests: + for _ in range(repeat): + suite.addTest(unittest.makeSuite(cls)) + + runner = unittest.TextTestRunner(verbosity=verbosity) + return runner.run(suite) + +if __name__ == '__main__': + run() diff --git a/.venv/lib/python3.12/site-packages/fixedint/util.py b/.venv/lib/python3.12/site-packages/fixedint/util.py new file mode 100644 index 00000000..8c638a93 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/fixedint/util.py @@ -0,0 +1,8 @@ +class HexFormattingMixin(object): + def __str__(self): + n = int(self) + width = (self.width + 3) // 4 + if n < 0: + return '-0x%0*x' % (width, -n) + else: + return '0x%0*x' % (width, n) |