tricu

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

float_working_test.py (3509B)


      1 #!/usr/bin/env python3
      2 import hashlib
      3 import os
      4 from pathlib import Path
      5 import subprocess
      6 import unittest
      7 
      8 from float_working import cases, groups, chain_oracle, working_parts
      9 from float_finite import finite_value, special_words
     10 from float_ieee import SIGN, INF, QNAN, QUIET, OPS, oracle, nan, class_words, dyadic
     11 
     12 
     13 def reconstruct(parts):
     14     kind,negative,scale,m=parts
     15     if kind==0:word=0
     16     elif kind==2:word=INF
     17     elif kind==3:word=INF|m
     18     elif scale>=1230:word=((scale-1229)<<52)|(m-2**52)
     19     else:word=m>>(1230-scale)
     20     return word|(SIGN if negative else 0)
     21 
     22 
     23 def host_trace(reference):
     24     rows=[];expected=[]
     25     for initial,pool,steps in cases():
     26         word=initial
     27         for op,index in steps:
     28             rows.append(f'{op} {word:016x} {pool[index]:016x}\n')
     29             ok,(word,flags)=oracle(word,pool[index],OPS[op]);assert ok
     30             expected.append((word,flags))
     31     raw=''.join(rows).encode()
     32     result=subprocess.run([str(reference)],input=raw,capture_output=True,check=True,timeout=60)
     33     lines=result.stdout.splitlines();assert len(lines)==len(expected)
     34     for line,(word,flags) in zip(lines,expected):
     35         actual,raised=line.split();actual=int(actual,16);raised=int(raised)
     36         assert raised==sum(int(f)<<i for i,f in enumerate(flags))
     37         if nan(word):assert nan(actual) and actual&QUIET
     38         else:assert actual==word
     39     return dict(checked_steps=len(expected),input_sha256=hashlib.sha256(raw).hexdigest(),
     40                 output_sha256=hashlib.sha256(result.stdout).hexdigest(),
     41                 reference_sha256=hashlib.sha256(Path(reference).read_bytes()).hexdigest())
     42 
     43 
     44 class WorkingTests(unittest.TestCase):
     45     def test_decode_encode_and_finite_invariant(self):
     46         words=special_words()+class_words()+[chain_oracle(row)[0] for row in cases()]
     47         for word in words:
     48             parts=working_parts(word);kind,sign,s,m=parts
     49             self.assertEqual(reconstruct(parts),word)
     50             if kind==1:
     51                 self.assertEqual(m.bit_length(),53)
     52                 self.assertTrue(1178<=s<=3275)
     53                 self.assertEqual((-1 if sign else 1)*dyadic(m,s-2304),finite_value(word))
     54                 if s<1230:self.assertEqual(m%(1<<(1230-s)),0)
     55             elif kind in [0,2]:self.assertEqual((s,m),(0,0))
     56             else:self.assertTrue(0<m<2**52)
     57 
     58     def test_far_branch_bound(self):
     59         for lower in range(1178,3276):
     60             for gap in [55,56,127,2097]:
     61                 dominant=lower+gap
     62                 if dominant<=3275:self.assertGreaterEqual(dominant,1233)
     63 
     64     def test_no_fused_precision(self):
     65         row=(0x3ff0000000000000,[0x3ca0000000000000],[(0,0)]*2)
     66         self.assertEqual(chain_oracle(row),(0x3ff0000000000000,(False,False,False,False,True)))
     67 
     68     def test_empty_preserves_signaling_payload(self):
     69         for word in [SIGN,INF|1,SIGN|QNAN|123]:
     70             self.assertEqual(chain_oracle((word,[],[])),(word,(False,)*5))
     71             self.assertEqual(reconstruct(working_parts(word)),word)
     72 
     73     def test_pool_reuse_is_not_numeric_change(self):
     74         g=groups()
     75         self.assertEqual([chain_oracle(r) for r in g['affine-reuse-16']],
     76                          [chain_oracle(r) for r in g['affine-unique-16']])
     77 
     78     @unittest.skipUnless(os.environ.get('TRICU_FLOAT_HOST'),'set TRICU_FLOAT_HOST to C fenv reference')
     79     def test_steps_against_c_fenv(self):
     80         self.assertGreater(host_trace(os.environ['TRICU_FLOAT_HOST'])['checked_steps'],14000)
     81 
     82 
     83 if __name__=='__main__':unittest.main()