2 from openpower
.decoder
.fp_working_format
import (
3 BFPState
, SelectableMSB0Fraction
)
4 from fractions
import Fraction
8 class TestSelectableMSB0Fraction(unittest
.TestCase
):
10 def check(v
, pos
, neg
):
12 with self
.subTest(v
=f
"{v.numerator:#x} / {v.denominator:#x}",
14 pos
= f
"SelectableMSB0Fraction({pos})"
15 neg
= f
"SelectableMSB0Fraction({neg})"
16 self
.assertEqual(repr(SelectableMSB0Fraction(v
)), pos
)
17 self
.assertEqual(repr(SelectableMSB0Fraction(-v
)), neg
)
18 check(0, "0x0.0", "0x0.0")
19 check(1, "0x1.0", "0x...ffff.0 (-0x1)")
20 check(0x2, "0x2.0", "0x...fffe.0 (-0x2)")
21 check(0x4, "0x4.0", "0x...fffc.0 (-0x4)")
22 check(0x8, "0x8.0", "0x...fff8.0 (-0x8)")
23 check(0x10, "0x10.0", "0x...fff0.0 (-0x10)")
24 check(0x100, "0x100.0", "0x...ff00.0 (-0x100)")
25 check(0x1000, "0x1000.0", "0x...f000.0 (-0x1 * 2**12)")
27 "0x...0000.0 (0x1 * 2**16)", "0x...0000.0 (-0x1 * 2**16)")
29 "0x...0000.0 (0x1 * 2**20)", "0x...0000.0 (-0x1 * 2**20)")
31 "0x...0000.0 (0x1 * 2**24)", "0x...0000.0 (-0x1 * 2**24)")
32 check(Fraction(1, 1 << 1), "0x0.8", "0x...ffff.8 (-0x1 / 0x2)")
33 check(Fraction(1, 1 << 2), "0x0.4", "0x...ffff.c (-0x1 / 0x4)")
34 check(Fraction(1, 1 << 3), "0x0.2", "0x...ffff.e (-0x1 / 0x8)")
35 check(Fraction(1, 1 << 4), "0x0.1", "0x...ffff.f (-0x1 / 0x10)")
36 check(Fraction(1, 1 << 8), "0x0.01", "0x...ffff.ff (-0x1 / 0x100)")
37 check(Fraction(1, 1 << 12), "0x0.001", "0x...ffff.fff (-0x1 * 2**-12)")
38 check(Fraction(1, 1 << 16),
39 "0x0.0001", "0x...ffff.ffff (-0x1 * 2**-16)")
40 check(Fraction(1, 1 << 20),
41 "0x0.0000_1", "0x...ffff.ffff_f (-0x1 * 2**-20)")
42 check(Fraction(1, 1 << 24),
43 "0x0.0000_01", "0x...ffff.ffff_ff (-0x1 * 2**-24)")
44 check(Fraction(1, 1 << 28),
45 "0x0.0000_001", "0x...ffff.ffff_fff (-0x1 * 2**-28)")
46 check(Fraction(1, 1 << 32),
47 "0x0.0000_0001", "0x...ffff.ffff_ffff (-0x1 * 2**-32)")
48 check(Fraction(1, 1 << 36),
49 "0x0.0000_0000_1", "0x...ffff.ffff_ffff_f (-0x1 * 2**-36)")
50 check(Fraction(1, 1 << 40),
51 "0x0.0000_0000_01", "0x...ffff.ffff_ffff_ff (-0x1 * 2**-40)")
52 check(Fraction(1, 1 << 44),
53 "0x0.0000_0000_001", "0x...ffff.ffff_ffff_fff (-0x1 * 2**-44)")
54 check(Fraction(1, 1 << 48),
55 "0x0.0000_0000_0001", "0x...ffff.ffff_ffff_ffff (-0x1 * 2**-48)")
56 check(Fraction(1, 1 << 52),
57 "0x0.0000_0000_0000_1",
58 "0x...ffff.ffff_ffff_ffff_f (-0x1 * 2**-52)")
59 check(Fraction(1, 1 << 56),
60 "0x0.0000_0000_0000_01",
61 "0x...ffff.ffff_ffff_ffff_ff (-0x1 * 2**-56)")
62 check(Fraction(1, 1 << 60),
63 "0x0.0000_0000_0000_001",
64 "0x...ffff.ffff_ffff_ffff_fff (-0x1 * 2**-60)")
65 check(Fraction(1, 1 << 64),
66 "0x0.0000_0000_0000_0001",
67 "0x...ffff.ffff_ffff_ffff_ffff (-0x1 * 2**-64)")
68 check(Fraction(1, 1 << 68),
69 "0x0.0000_0000_0000_0000_1",
70 "0x...ffff.ffff_ffff_ffff_ffff_f (-0x1 * 2**-68)")
71 check(Fraction(1, 1 << 72),
72 "0x0.0000_0000_0000_0000_0... (0x1 * 2**-72)",
73 "0x...ffff.ffff_ffff_ffff_ffff_f... (-0x1 * 2**-72)")
74 check(Fraction(1, 1 << 76),
75 "0x0.0000_0000_0000_0000_0... (0x1 * 2**-76)",
76 "0x...ffff.ffff_ffff_ffff_ffff_f... (-0x1 * 2**-76)")
78 "0x0.5555_5555_5555_5555_5... (0x1 / 0x3)",
79 "0x...ffff.aaaa_aaaa_aaaa_aaaa_a... (-0x1 / 0x3)")
81 "0x0.3333_3333_3333_3333_3... (0x1 / 0x5)",
82 "0x...ffff.cccc_cccc_cccc_cccc_c... (-0x1 / 0x5)")
84 "0x0.2492_4924_9249_2492_4... (0x1 / 0x7)",
85 "0x...ffff.db6d_b6db_6db6_db6d_b... (-0x1 / 0x7)")
86 check(Fraction(1234, 4567),
87 "0x0.452b_c745_e653_bec0_b... (0x4d2 / 0x11d7)",
88 "0x...ffff.bad4_38ba_19ac_413f_4... (-0x4d2 / 0x11d7)")
89 check(Fraction(0x123456789abcdef, 0x1234567),
90 "0x...0079.0000_3840_001a_9640_0... "
91 "(0x123456789abcdef / 0x1234567)",
92 "0x...ff86.ffff_c7bf_ffe5_69bf_f... "
93 "(-0x123456789abcdef / 0x1234567)")
94 # decent approximation to math.tau
95 check(Fraction(312689, 49766),
96 "0x6.487e_d511_4b5c_560c_d... (0x4c571 / 0xc266)",
97 "0x...fff9.b781_2aee_b4a3_a9f3_2... (-0x4c571 / 0xc266)")
98 check(Fraction(0xface0000, 0xffff),
99 "0xface.face_face_face_face_f... (0x539a0000 / 0x5555)",
100 "0x...0531.0531_0531_0531_0531_0... (-0x539a0000 / 0x5555)")
103 inputs
= [1, 4, 6, Fraction(1, 2), Fraction(1, 3), Fraction(2, 3)]
104 inputs
.extend([-i
for i
in inputs
])
108 with self
.subTest(a
=a
, b
=b
):
109 af
= SelectableMSB0Fraction(a
)
110 bf
= SelectableMSB0Fraction(b
)
111 self
.assertEqual(af
.value
, a
)
112 self
.assertEqual((+af
).value
, a
)
113 self
.assertEqual((-af
).value
, -a
)
114 self
.assertEqual(math
.floor(af
).value
, math
.floor(a
))
115 self
.assertEqual(math
.ceil(af
).value
, math
.ceil(a
))
116 self
.assertEqual(math
.trunc(af
).value
, math
.trunc(a
))
117 self
.assertEqual(round(af
).value
, round(a
))
118 self
.assertEqual((af
+ bf
).value
, a
+ b
)
119 self
.assertEqual((af
- bf
).value
, a
- b
)
120 self
.assertEqual((af
* bf
).value
, a
* b
)
121 self
.assertEqual(af
== bf
, a
== b
)
122 self
.assertEqual(af
!= bf
, a
!= b
)
123 self
.assertEqual(af
< bf
, a
< b
)
124 self
.assertEqual(af
<= bf
, a
<= b
)
125 self
.assertEqual(af
> bf
, a
> b
)
126 self
.assertEqual(af
>= bf
, a
>= b
)
128 self
.assertEqual((af
/ bf
).value
, a
/ Fraction(b
))
129 self
.assertEqual((af
// bf
).value
, a
// b
)
130 self
.assertEqual((af
% bf
).value
, a
% b
)
131 if isinstance(b
, int):
133 pow2_b
= Fraction(1 << b
)
135 pow2_b
= Fraction(1, 1 << -b
)
136 self
.assertEqual((af
<< b
).value
, a
* pow2_b
)
137 self
.assertEqual((af
>> b
).value
, a
/ pow2_b
)
139 def slice_helper(self
, v
, start
, length
):
140 f
= SelectableMSB0Fraction(v
)
143 # expected is 0b...XX.XXXmybitsXXX... where mybits is what we want
144 expected
*= 1 << start
145 # expected is 0b...XXm.ybitsXXX...
146 expected
*= 1 << (length
- 1)
147 # expected is 0b...XXmybits.XX...
148 expected
= math
.floor(expected
)
149 # expected is 0b...XXmybits
150 expected
%= 1 << length
151 # expected is 0bmybits
154 with self
.subTest(expected
=hex(expected
), f
=str(f
)):
155 self
.assertEqual(hex(expected
), hex(int(f
[start
:start
+length
])))
157 self
.assertEqual(hex(expected
), hex(int(f
[start
])))
158 for replace
in (0x5555, 0xffff, 0xaaaa, 0):
160 # expected is 0b...XX.XXXoldbitsYY...
161 # where oldbits is what we want to replace with newbits
163 expected
*= 1 << start
164 # expected is 0b...XXo.ldbitsYYY...
165 expected
*= 1 << (length
- 1)
166 # expected is 0b...XXoldbits.YY...
167 fraction
= expected
- math
.floor(expected
)
168 # fraction is 0b.YYY...
169 expected
= math
.floor(expected
)
170 # expected is 0b...XXoldbits
171 expected
-= expected
% (1 << length
)
172 # expected is 0b...XX0000000
173 expected |
= replace
% (1 << length
)
174 # expected is 0b...XXnewbits
176 # expected is 0b...XXnewbits.YY...
177 expected
/= 1 << (length
- 1)
178 # expected is 0b...XXn.ewbitsYYY...
179 expected
/= 1 << start
180 # expected is 0b...XX.XXXnewbitsYY...
181 expected
= SelectableMSB0Fraction(expected
)
182 with self
.subTest(expected
=str(expected
),
183 replace
=hex(replace
)):
184 f
= SelectableMSB0Fraction(v
)
185 f
[start
:start
+length
] = replace
186 self
.assertEqual(f
, expected
)
188 f
= SelectableMSB0Fraction(v
)
190 self
.assertEqual(f
, expected
)
192 def test_slice(self
):
193 for v
in [Fraction(0xface0000, 0xffff), Fraction(0x1230000, 0xffff)]:
194 for start
in range(0, 17):
195 for length
in reversed(range(0, 17)):
196 with self
.subTest(v
=v
, start
=start
, length
=length
):
197 self
.slice_helper(v
, start
, length
)
200 if __name__
== "__main__":