float_quantize_test.py (2460B)
1 #!/usr/bin/env python3 2 import math 3 import struct 4 import sys 5 import unittest 6 7 from float_alignment import exact_round 8 from float_quantize import BIAS, INF, MAX, cases, near_cases, dyadic, oracle, value 9 10 11 class QuantizerTests(unittest.TestCase): 12 def test_zero_and_subnormal_halfway(self): 13 self.assertEqual(oracle(0,0),(0,False,False)) 14 self.assertEqual(oracle(1,BIAS-1075),(0,True,True)) 15 self.assertEqual(oracle(3,BIAS-1075),(2,True,True)) 16 self.assertEqual(oracle(1,BIAS-1074),(1,False,False)) 17 18 def test_transition_uses_tininess_after_rounding(self): 19 self.assertEqual(oracle(2**53-1,BIAS-1075),(2**52,True,False)) 20 self.assertEqual(oracle(2**52-1,BIAS-1074),(2**52-1,False,False)) 21 22 def test_overflow_halfway(self): 23 self.assertEqual(oracle(2**53-1,BIAS+971),(MAX,False,False)) 24 self.assertEqual(oracle(2**54-1,BIAS+970),(INF,True,False)) 25 self.assertEqual(oracle((2**54-1)*2-1,BIAS+969),(MAX,True,False)) 26 27 def test_double_rounding_in_both_directions(self): 28 for n,wrong in [(2**54+5,2**51),(2**54+11,2**51+2)]: 29 scale=BIAS-1077 30 self.assertEqual(oracle(n,scale),(2**51+1,True,True)) 31 cut,m,_=exact_round(n) 32 self.assertEqual(oracle(m,scale+cut)[0],wrong) 33 34 def test_cancellation_normalization(self): 35 self.assertEqual(oracle(1,BIAS-52),(971 << 52,False,False)) 36 self.assertEqual(oracle(1,BIAS-1074),(1,False,False)) 37 self.assertEqual(oracle(2**52,BIAS-1074),(1 << 52,False,False)) 38 39 def test_equivalent_exact_coordinates(self): 40 for n,scale in cases()[::13]: 41 for shift in [1,52,107]: 42 if scale >= shift: 43 self.assertEqual(oracle(n,scale),oracle(n << shift,scale-shift)) 44 45 @unittest.skipUnless(sys.float_info.radix==2 and sys.float_info.mant_dig==53, 46 'requires binary64 Python floats') 47 def test_exact_fraction_conversion_and_flags(self): 48 rows=cases()+[((a << gap)+sign*b,scale) for scale,gap,a,b in near_cases() for sign in [-1,1]] 49 for n,scale in rows: 50 x=dyadic(n,scale-BIAS) 51 try: f=float(x) 52 except OverflowError: f=math.inf 53 bits=int.from_bytes(struct.pack('>d',f),'big') 54 inexact=math.isinf(f) or value(bits)!=x 55 self.assertEqual(oracle(n,scale),(bits,inexact,inexact and bits < 2**52)) 56 57 58 if __name__=='__main__': unittest.main()