def test_unsigned_scaled_integer_formats(): format_ = Format(msb=8, lsb=2, signed=False) assert format_.msb == 8 assert format_.lsb == 2 assert not format_.signed assert format_.wordlength == 6 assert format_.mantissa_interval == interval(0, 63) assert format_.value_interval == interval(0, 252) assert format_.value_epsilon == 4 assert format_.to_qnotation() == 'uQ8.-2' assert format_.to_pnotation() == 'u(8,2)' with pytest.raises(ValueError): format_.represent(-1) mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(128) assert mantissa == 32 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(256) assert not underflow assert overflow
def test_unsigned_fixed_point_formats(): format_ = Format(msb=4, lsb=-4, signed=False) assert format_.msb == 4 assert format_.lsb == -4 assert not format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(0, 255) assert format_.value_interval == interval(0.0, 15.9375) assert format_.value_epsilon == 0.0625 assert format_.to_qnotation() == 'uQ4.4' assert format_.to_pnotation() == 'u(4,-4)' with pytest.raises(ValueError): format_.represent(-1) mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1e-6) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(8) assert mantissa == 128 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(16) assert not underflow assert overflow
def test_unsigned_fractional_formats(): format_ = Format(msb=0, lsb=-8, signed=False) assert format_.msb == 0 assert format_.lsb == -8 assert not format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(0, 255) assert format_.value_interval == interval(0.0, 0.99609375) assert format_.value_epsilon == 0.00390625 assert format_.to_qnotation() == 'uQ0.8' assert format_.to_pnotation() == 'u(0,-8)' with pytest.raises(ValueError): format_.represent(-0.1) mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1e-6) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0.5) assert mantissa == 128 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1) assert not underflow assert overflow
def test_signed_fixed_point_formats(): format_ = Format(msb=3, lsb=-4, signed=True) assert format_.msb == 3 assert format_.lsb == -4 assert format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(-128, 127) assert format_.value_interval == interval(-8.0, 7.9375) assert format_.value_epsilon == 0.0625 assert format_.to_qnotation() == 'Q4.4' assert format_.to_pnotation() == '(3,-4)' mantissa, (underflow, overflow) = format_.represent(-2.25) assert mantissa == -36 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1e-6) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0.5) assert mantissa == 8 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(8) assert not underflow assert overflow
def test_signed_scaled_integer_formats(): format_ = Format(msb=7, lsb=2, signed=True) assert format_.msb == 7 assert format_.lsb == 2 assert format_.signed assert format_.wordlength == 6 assert format_.mantissa_interval == interval(-32, 31) assert format_.value_interval == interval(-128, 124) assert format_.value_epsilon == 4 assert format_.to_qnotation() == 'Q8.-2' assert format_.to_pnotation() == '(7,2)' mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent( -17, rounding_method=rounding.nearest_integer ) assert mantissa == -4 # i.e. -16 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(128) assert not underflow assert overflow
def test_signed_fractional_formats(): format_ = Format(msb=0, lsb=-7, signed=True) assert format_.msb == 0 assert format_.lsb == -7 assert format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(-128, 127) assert format_.value_interval == interval(-1.0, 0.9921875) assert format_.value_epsilon == 0.0078125 assert format_.to_qnotation() == 'Q1.7' assert format_.to_pnotation() == '(0,-7)' mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1e-6) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0.5) assert mantissa == 64 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1) assert not underflow assert overflow
def multiply(self, x, y): # Use 2x wordlength multipliers, adjust format signed = x.format_.signed lsb = x.format_.lsb + y.format_.lsb msb = x.format_.msb + y.format_.msb format_z = Format(msb, lsb, signed) mantissa_z = x.mantissa * y.mantissa if format_z.wordlength > self.wordlength: mantissa_z, format_z = Format.best( Representation(mantissa_z, format_z), wordlength=self.wordlength, rounding_method=self.rounding_method, signed=signed ) return type(x)(mantissa_z, format_z)
def _handle_overflow(self, operation, mantissa, format_, off_by): if not operation.allows_overflow: signed = format_.signed msb = format_.msb + off_by extended_format = Format(msb, format_.lsb, signed) lsb = msb - self.wordlength + int(signed) format_ = Format(msb, lsb, signed) mantissa, (underflow, overflow) = format_.represent( Representation(mantissa, extended_format), rounding_method=self.rounding_method ) assert not underflow assert not overflow else: mantissa, _ = self.overflow_behavior( mantissa, range_=format_.mantissa_interval ) return mantissa, format_
def _find_common_format(self, format_x, format_y): if format_x == format_y: return format_x assert format_x.signed == format_y.signed signed = format_x.signed msb = max(format_x.msb, format_y.msb) lsb = min(format_x.lsb, format_y.lsb) wordlength = msb - lsb + int(signed) if wordlength > self.wordlength: lsb = msb - self.wordlength + int(signed) return Format(msb, lsb, signed)
def rshift(self, x, n): if x.format_.wordlength > self.wordlength: raise ValueError(f'{self} cannot handle {x}') if n < 0: raise ValueError(f'negative shift count {n}') n = int(n) return type(x)(x.mantissa, Format( msb=x.format_.msb - n, lsb=x.format_.lsb - n, signed=x.format_.signed ))
def test_best_formats(): mantissa, format_ = Format.best( 0, wordlength=8, signed=True ) assert mantissa == 0 assert format_.msb == 0 assert format_.lsb == -7 assert format_.signed mantissa, format_ = Format.best( 0.5, wordlength=8, signed=True ) assert mantissa == 64 assert format_.msb == 0 assert format_.lsb == -7 assert format_.signed mantissa, format_ = Format.best( 1.0, wordlength=8, signed=True ) assert mantissa == 64 assert format_.msb == 1 assert format_.lsb == -6 assert format_.signed mantissa, format_ = Format.best( -1.0, wordlength=8, signed=True ) assert mantissa == -128 assert format_.msb == 0 assert format_.lsb == -7 assert format_.signed mantissa, format_ = Format.best( 12.0, wordlength=8, signed=True ) assert mantissa == 96 assert format_.msb == 4 assert format_.lsb == -3 assert format_.signed mantissa, format_ = Format.best( 1200.0, wordlength=8, signed=True ) assert mantissa == 75 assert format_.msb == 11 assert format_.lsb == 4 assert format_.signed mantissa, format_ = Format.best( interval(-16, 16), wordlength=8, signed=True ) assert mantissa == interval(-64, 64) assert format_.msb == 5 assert format_.lsb == -2 assert format_.signed
def test_signed_integer_formats(): format_ = Format(msb=7, lsb=0, signed=True) assert format_.msb == 7 assert format_.lsb == 0 assert format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(-128, 127) assert format_.value_interval == interval(-128, 127) assert format_.value_epsilon == 1 assert format_.to_qnotation() == 'Q8.0' assert format_.to_pnotation() == '(7,0)' mantissa, (underflow, overflow) = format_.represent( -127.5, rounding_method=rounding.nearest_integer ) assert mantissa == -128 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent( -127.5, rounding_method=rounding.ceil ) assert mantissa == -127 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0.1) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(256) assert not underflow assert overflow
def multiply(self, x, y): # Use 2 * wordlength long multipliers z = Representation(mantissa=x.mantissa * y.mantissa, format_=Format(msb=self.format_.msb * 2 + 1, lsb=self.format_.lsb * 2, signed=self.format_.signed)) mantissa, (underflow, overflow) = self.format_.represent( z, rounding_method=self.rounding_method) if underflow and not self.multiply.allows_underflow: raise UnderflowError(f'{x} * {y} underflows in {self.format_}', mpfloat(z), self.format_.value_epsilon) if overflow: if not self.multiply.allows_overflow: raise OverflowError(f'{x} * {y} overflows in {self.format_}', mpfloat(z), self.format_.value_interval) mantissa, _ = self.overflow_behavior( mantissa, range_=self.format_.mantissa_interval) return type(x)(mantissa, self.format_)
def represent(self, value, rtype=Representation, format_=None): if format_ is not None: if format_.wordlength > self.wordlength: raise ValueError(f'{format_} wordlength is too large') mantissa, (underflow, overflow) = format_.represent( value, rounding_method=self.rounding_method ) if underflow and not self.represent.allows_underflow: raise UnderflowError(f'{value} in {format_} underflows') if overflow: if not self.represent.allows_overflow: raise OverflowError(f'{value} in {format_} overflows') mantissa, _ = self.overflow_behavior( mantissa, range_=format_.mantissa_interval ) else: if isinstance(value, rtype): if value.format_.wordlength <= self.wordlength: return value mantissa, format_ = Format.best(value, wordlength=self.wordlength) return rtype(mantissa, format_)
def test_invalid_formats(): with pytest.raises(ValueError): Format(msb=0, lsb=2)