def unpack_ibm_floats(data, num_items): """Unpack a series of binary-encoded big-endian single-precision IBM floats. Args: data: A sequence of bytes. num_items: The number of floats to be read. Returns: A sequence of floats. """ return [IBMFloat.from_bytes(data[i: i+4]) for i in range(0, num_items * 4, 4)]
def unpack_ibm_floats(data, count): """Unpack a series of binary-encoded big-endian single-precision IBM floats. Args: data: A sequence of bytes. (Python 2 - a str object, Python 3 - a bytes object) count: The number of floats to be read. Returns: A sequence of floats. """ return [IBMFloat.from_bytes(data[i: i+4]) for i in range(0, count * 4, 4)]
def test_rfloordiv_ibm(self, a, b): ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) assume(not ibm_b.is_zero()) ieee_a = float(ibm_a) ieee_b = float(ibm_b) assert ieee_a // ibm_b == ieee_a // ieee_b
def test_rfloordiv_ibm_division_by_zero_raises_zero_division_error( self, a, b): ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(0.0) ieee_a = float(ibm_a) with raises(ZeroDivisionError): _ = ieee_a // ibm_b
def test_sub(self, a, b): ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ibm_c = ibm_a - ibm_b ieee_a = float(ibm_a) ieee_b = float(ibm_b) ieee_c = ieee_a - ieee_b self.assertTrue(almost_equal(ieee_c, ibm_c, epsilon=EPSILON_IBM_FLOAT))
def test_mul_ibm(self, a, b): ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ieee_a = float(ibm_a) ieee_b = float(ibm_b) try: ibm_c = ibm_a * ibm_b except OverflowError: raise UnsatisfiedAssumption ieee_c = ieee_a * ieee_b assert almost_equal(ibm_c, ieee_c, epsilon=EPSILON_IBM_FLOAT)
def test_rpow_ibm_ieee_results(self, a, b): assume(a != 0.0) ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ieee_a = float(ibm_a) ieee_b = float(ibm_b) try: ieee_c1 = ieee_a**ibm_b except OverflowError: raise UnsatisfiedAssumption ieee_c2 = ieee_a**ieee_b assert almost_equal(ieee_c1, ieee_c2, epsilon=EPSILON_IBM_FLOAT)
def test_rpow_ibm_ieee_results(self, a, b): assume(a != 0.0) ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ieee_a = float(ibm_a) ieee_b = float(ibm_b) try: ieee_c1 = ieee_a ** ibm_b except OverflowError: raise UnsatisfiedAssumption ieee_c2 = ieee_a ** ieee_b assert almost_equal(ieee_c1, ieee_c2, epsilon=EPSILON_IBM_FLOAT)
def test_rmod_ibm(self, a, b): ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) assume(not ibm_b.is_zero()) ieee_a = float(ibm_a) ieee_b = float(ibm_b) try: ieee_c1 = ieee_a % ibm_b except OverflowError: raise UnsatisfiedAssumption ieee_c2 = ieee_a % ieee_b assert almost_equal(ieee_c1, ieee_c2, epsilon=EPSILON_IBM_FLOAT)
def test_pow_ibm_complex_result(self, a, b): assume(a != 0.0) assume(b != 0.0 and b != 1.0) ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ieee_a = float(ibm_a) ieee_b = float(ibm_b) try: ibm_c = ibm_a ** ibm_b except OverflowError: raise UnsatisfiedAssumption ieee_c = ieee_a ** ieee_b assert almost_equal(ibm_c, ieee_c, epsilon=EPSILON_IBM_FLOAT)
def test_sub(self, a, b): try: ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ibm_c = ibm_a - ibm_b except FloatingPointError: raise UnsatisfiedAssumption ieee_a = float(ibm_a) ieee_b = float(ibm_b) ieee_c = ieee_a - ieee_b self.assertTrue(almost_equal(ieee_c, ibm_c, epsilon=EPSILON_IBM_FLOAT))
def test_add(self, f, p): a = f * p b = f - a ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ibm_c = ibm_a + ibm_b ieee_a = float(ibm_a) ieee_b = float(ibm_b) ieee_c = ieee_a + ieee_b self.assertTrue(almost_equal(ieee_c, ibm_c, epsilon=EPSILON_IBM_FLOAT * 4))
def test_sub(self, a, b): ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) try: ibm_c = ibm_a - ibm_b except FloatingPointError: raise UnsatisfiedAssumption ieee_a = float(ibm_a) ieee_b = float(ibm_b) ieee_c = ieee_a - ieee_b assert almost_equal(ieee_c, ibm_c, epsilon=EPSILON_IBM_FLOAT)
def test_pow_ibm_complex_result(self, a, b): assume(a != 0.0) assume(b != 0.0 and b != 1.0) ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ieee_a = float(ibm_a) ieee_b = float(ibm_b) try: ibm_c = ibm_a**ibm_b except OverflowError: raise UnsatisfiedAssumption ieee_c = ieee_a**ieee_b assert almost_equal(ibm_c, ieee_c, epsilon=EPSILON_IBM_FLOAT)
def test_add(self, f, p): a = f * p b = f - a ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ibm_c = ibm_a + ibm_b ieee_a = float(ibm_a) ieee_b = float(ibm_b) ieee_c = ieee_a + ieee_b self.assertTrue( almost_equal(ieee_c, ibm_c, epsilon=EPSILON_IBM_FLOAT * 4))
def test_add(self, f, p): a = f * p b = f - a try: ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ibm_c = ibm_a + ibm_b except FloatingPointError: raise UnsatisfiedAssumption ieee_a = float(ibm_a) ieee_b = float(ibm_b) ieee_c = ieee_a + ieee_b assert almost_equal(ieee_c, ibm_c, epsilon=EPSILON_IBM_FLOAT * 4)
def test_add(self, f, p): a = f * p b = f - a try: ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ibm_c = ibm_a + ibm_b except FloatingPointError: raise UnsatisfiedAssumption ieee_a = float(ibm_a) ieee_b = float(ibm_b) ieee_c = ieee_a + ieee_b self.assertTrue(almost_equal(ieee_c, ibm_c, epsilon=EPSILON_IBM_FLOAT * 4))
def test_ldexp_frexp(self, fraction, exponent): try: ibm = IBMFloat.ldexp(fraction, exponent) except OverflowError: assume(False) else: f, e = ibm.frexp() self.assertTrue(almost_equal(fraction * 2**exponent, f * 2**e, epsilon=EPSILON_IBM_FLOAT))
def test_ldexp_frexp(self, fraction, exponent): try: ibm = IBMFloat.ldexp(fraction, exponent) except (OverflowError, FloatingPointError): raise UnsatisfiedAssumption else: f, e = ibm.frexp() self.assertTrue(almost_equal(fraction * 2**exponent, f * 2**e, epsilon=EPSILON_IBM_FLOAT))
def pack_ibm_floats(values): """Pack floats into binary-encoded big-endian single-precision IBM floats. Args: values: An iterable series of numeric values. Returns: A sequence of bytes. """ return EMPTY_BYTE_STRING.join(bytes(IBMFloat.from_real(value)) for value in values)
def test_ldexp_frexp(self, fraction, exponent): try: ibm = IBMFloat.ldexp(fraction, exponent) except (OverflowError, FloatingPointError): raise UnsatisfiedAssumption else: f, e = ibm.frexp() assert almost_equal(fraction * 2**exponent, f * 2**e, epsilon=EPSILON_IBM_FLOAT)
def test_ldexp_frexp(self, fraction, exponent): try: ibm = IBMFloat.ldexp(fraction, exponent) except OverflowError: assume(False) else: f, e = ibm.frexp() self.assertTrue( almost_equal(fraction * 2**exponent, f * 2**e, epsilon=EPSILON_IBM_FLOAT))
def test_normalise_subnormal(self, b, c, d, shift): mantissa = (b << 16) | (c << 8) | d assume(mantissa != 0) mantissa >>= shift assert mantissa != 0 sa = EXPONENT_BIAS sb = (mantissa >> 16) & 0xff sc = (mantissa >> 8) & 0xff sd = mantissa & 0xff ibm = IBMFloat.from_bytes((sa, sb, sc, sd)) assert ibm.is_subnormal() normalized = ibm.normalize() self.assertFalse(normalized.is_subnormal())
def test_zero_subnormal(self, b, c, d, shift): mantissa = (b << 16) | (c << 8) | d assume(mantissa != 0) mantissa >>= shift assert mantissa != 0 sa = EXPONENT_BIAS sb = (mantissa >> 16) & 0xff sc = (mantissa >> 8) & 0xff sd = mantissa & 0xff ibm = IBMFloat.from_bytes((sa, sb, sc, sd)) assert ibm.is_subnormal() z = ibm.zero_subnormal() self.assertTrue(z.is_zero())
def test_zero_subnormal(self, b, c, d, shift): mantissa = (b << 16) | (c << 8) | d assume(mantissa != 0) mantissa >>= shift assert mantissa != 0 sa = EXPONENT_BIAS sb = (mantissa >> 16) & 0xff sc = (mantissa >> 8) & 0xff sd = mantissa & 0xff ibm = IBMFloat.from_bytes((sa, sb, sc, sd)) assert ibm.is_subnormal() z = ibm.zero_subnormal() assert z.is_zero()
def pack(self, values): return EMPTY_BYTE_STRING.join( bytes(IBMFloat.from_real(value)) for value in values)
def test_le_ibm(self, a, b): ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(b) ieee_a = float(ibm_a) ieee_b = float(ibm_b) assert (ibm_a <= ibm_b) == (ieee_a <= ieee_b)
def test_mod_ibm_division_by_zero_raises_zero_division_error(self, a): ibm_a = IBMFloat.from_float(a) ibm_b = IBMFloat.from_float(0.0) with raises(ZeroDivisionError): _ = ibm_a % ibm_b
def test_bool(self, f): self.assertEqual(bool(IBMFloat.from_float(f)), bool(f))
def test_floats_roundtrip(self, f): ibm = IBMFloat.from_float(f) self.assertTrue(almost_equal(f, float(ibm), epsilon=EPSILON_IBM_FLOAT))
def test_conversion_to_int(self, f): ibm = IBMFloat.from_float(f) assert int(ibm) == int(f)
def test_trunc_below_zero(self, i, f): assume(f != 1.0) ieee = i - f ibm = IBMFloat.from_float(ieee) self.assertEqual(trunc(ibm), i)
def test_normalise_subnormal1(self): ibm = IBMFloat.from_bytes((0b01000000, 0b00000000, 0b11111111, 0b00000000)) assert ibm.is_subnormal() normalized = ibm.normalize() self.assertFalse(normalized.is_subnormal())
def test_normalise_subnormal2(self): ibm = IBMFloat.from_bytes((64, 1, 0, 0)) assert ibm.is_subnormal() normalized = ibm.normalize() self.assertFalse(normalized.is_subnormal())
def test_abs(self, a, b, c, d): ibm = IBMFloat.from_bytes((a, b, c, d)) abs_ibm = abs(ibm) self.assertGreaterEqual(abs_ibm.signbit, 0)
def test_equality_normalizable_subnormal(self): p = IBMFloat(bytes((0x10, 0x04, 0x00, 0x00))) assert p.is_subnormal() q = IBMFloat(bytes((0x10, 0x05, 0x00, 0x00))) assert q.is_subnormal() assert p != q
def test_floor(self, i, f): assume(f != 1.0) ieee = i + f ibm = IBMFloat.from_float(ieee) self.assertEqual(math.floor(ibm), i)
def test_normalise_subnormal_expect_failure(self): # This float has an base-16 exponent of -64 (the minimum) and cannot be normalised ibm = IBMFloat.from_float(1.6472184286297693e-83) assert ibm.is_subnormal() with self.assertRaises(FloatingPointError): ibm.normalize()
def test_repr(self, f): ibm = IBMFloat.from_float(f) r = repr(ibm) assert check_balanced(r)
def test_equality_with_infinite_float_negative(self): p = IBMFloat.from_float(+1.5) q = float("+inf") assert p != q
def test_round(self, f): ibm = IBMFloat.from_float(f) g = float(ibm) assert round(ibm) == round(g)
def test_equality_with_nan_negative(self): p = IBMFloat.from_float(+1.5) q = float("nan") assert p != q
def test_bytes_roundtrip(self, a, b, c, d): b = bytes((a, b, c, d)) ibm = IBMFloat.from_bytes(b) self.assertEqual(bytes(ibm), b)
def test_equality_with_int_positive(self): p = IBMFloat.from_float(1234.0) q = 1234 assert p == q
def test_too_small(self): with self.assertRaises(OverflowError): IBMFloat.from_float(MIN_IBM_FLOAT * 10)
def test_equality_with_int_negative(self): p = IBMFloat.from_float(1234.0) q = 4321 assert p != q
def test_too_large(self): with self.assertRaises(OverflowError): IBMFloat.from_float(MAX_IBM_FLOAT * 10)
def test_equality_with_non_comparable_type_is_false(self): p = IBMFloat.from_float(1234.0) q = None assert p != q
def test_negate_zero(self): zero = IBMFloat.from_float(0.0) negated = -zero self.assertTrue(negated.is_zero())
def test_negate_non_zero(self, a, b, c, d): ibm = IBMFloat.from_bytes((a, b, c, d)) assume(not ibm.is_zero()) negated = -ibm self.assertNotEqual(ibm.signbit, negated.signbit)
def unpack(self, data, num_items): return [ IBMFloat.from_bytes(data[i:i + 4]) for i in range(0, num_items * 4, 4) ]
def test_signbit(self, f): ltz = f < 0 ibm = IBMFloat.from_float(f) self.assertEqual(ltz, ibm.signbit)