tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

float_alignment_test.py (2306B)


      1 #!/usr/bin/env python3
      2 """Independent small-precision exhaustion and binary64 alignment boundaries."""
      3 import unittest
      4 import random
      5 import sys
      6 from float_alignment import exact_round, expected
      7 
      8 
      9 class AlignmentTests(unittest.TestCase):
     10     def test_far_threshold_exhaustive_small_precisions(self):
     11         for p in range(2,7):
     12             lo,hi = 1 << (p-1),(1 << p)-1
     13             for a in range(lo,hi+1):
     14                 for b in range(lo,hi+1):
     15                     for gap in range(p+2,p+6):
     16                         for sign in [-1,1]:
     17                             self.assertEqual(exact_round((a << gap)+sign*b,p),(gap,a,True))
     18 
     19     def test_one_less_is_not_safe_for_subtraction(self):
     20         for p in range(2,54):
     21             lo = 1 << (p-1)
     22             gap = p+1
     23             # At the binade boundary the spacing below is half that above.
     24             self.assertEqual(exact_round((lo << gap)-lo,p),(gap,lo,True))
     25             self.assertEqual(exact_round((lo << gap)-(lo+1),p),
     26                              (gap-1,(1 << p)-1,True))
     27 
     28     def test_cancellation_and_exact_add(self):
     29         lo = 1 << 52
     30         self.assertEqual(expected(lo,lo,0,True),(0,0,False))
     31         self.assertEqual(expected(lo+1,lo,0,True),(0,1,False))
     32         self.assertEqual(expected(lo,lo,0),(1,lo,False))
     33 
     34     @unittest.skipUnless(sys.float_info.radix == 2 and sys.float_info.mant_dig == 53,
     35                          'requires a binary64 Python float host')
     36     def test_oracle_against_host_integer_rounding(self):
     37         rng = random.Random(5355)
     38         for _ in range(512):
     39             a,b = sorted([rng.randrange(2**52,2**53) for _ in range(2)], reverse=True)
     40             gap = rng.randrange(61)
     41             for sign in [-1,1]:
     42                 n = (a << gap)+sign*b
     43                 cut,m,inexact = exact_round(n)
     44                 rounded = int(float(n))
     45                 self.assertEqual(m << cut, rounded)
     46                 self.assertEqual(inexact, rounded != n)
     47 
     48     def test_real_exponent_extremes(self):
     49         lo,hi = 1 << 52,(1 << 53)-1
     50         for gap in [55,56,1022,1074,2046,2097]:
     51             for a,b in [(lo,lo),(lo,hi),(hi,lo),(hi,hi)]:
     52                 for subtract in [False,True]:
     53                     self.assertEqual(expected(a,b,gap,subtract),(gap,a,True))
     54 
     55 
     56 if __name__ == '__main__':
     57     unittest.main()