Coverage for /home/jenkins/workspace/NDS/Zserio/NDS_ZSERIO-linux-build/compiler/extensions/python/runtime/tests/test_float.py: 100%
127 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-12-13 15:12 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-12-13 15:12 +0000
1import unittest
3from zserio.float import (uint16_to_float, float_to_uint16, uint32_to_float,
4 float_to_uint32, uint64_to_float, float_to_uint64)
6class FloatUtilTest(unittest.TestCase):
8 def test_uint16_to_float(self):
9 # plus zero
10 float16_value_plus_zero = self._create_float16_value(0, 0, 0) # +0.0
11 self.assertEqual(0.0, uint16_to_float(float16_value_plus_zero))
13 # minus zero
14 float16_value_minus_zero = self._create_float16_value(1, 0, 0) # -0.0
15 self.assertEqual(-0.0, uint16_to_float(float16_value_minus_zero))
17 # plus infinity
18 float16_value_plus_infinity = self._create_float16_value(0, 0x1F, 0) # +INF
19 float64_value_plus_infinity = self._create_float64_value(0, 0x7FF, 0) # +INF
20 converted_float = uint16_to_float(float16_value_plus_infinity)
21 self.assertEqual(float64_value_plus_infinity, float_to_uint64(converted_float))
23 # minus infinity
24 float16_value_minus_infinity = self._create_float16_value(1, 0x1F, 0) # -INF
25 float64_value_minus_infinity = self._create_float64_value(1, 0x7FF, 0) # -INF
26 converted_float = uint16_to_float(float16_value_minus_infinity)
27 self.assertEqual(float64_value_minus_infinity, float_to_uint64(converted_float))
29 # quiet NaN
30 float16_value_quiet_nan = self._create_float16_value(0, 0x1F, 0x3FF) # +NaN
31 float64_value_quiet_nan = self._create_float64_value(0, 0x7FF, 0xFFC0000000000) # +NaN
32 converted_float = uint16_to_float(float16_value_quiet_nan)
33 self.assertEqual(float64_value_quiet_nan, float_to_uint64(converted_float))
35 # signaling NaN
36 float16_value_signaling_nan = self._create_float16_value(1, 0x1F, 0x3FF) # -NaN
37 float64_value_signaling_nan = self._create_float64_value(1, 0x7FF, 0xFFC0000000000) # -NaN
38 converted_float = uint16_to_float(float16_value_signaling_nan)
39 self.assertEqual(float64_value_signaling_nan, float_to_uint64(converted_float))
41 # normal numbers
42 float16_value_one = self._create_float16_value(0, 15, 0) # 1.0
43 self.assertEqual(1.0, uint16_to_float(float16_value_one))
45 float16_value_one_plus = self._create_float16_value(0, 15, 0x01) # 1.0 + 2^-10
46 float64_value_one_plus = self._create_float64_value(0, 0x3FF, 0x40000000000) # 1.0 + 2^-10
47 converted_float = uint16_to_float(float16_value_one_plus)
48 self.assertEqual(float64_value_one_plus, float_to_uint64(converted_float))
50 float16_value_max = self._create_float16_value(0, 30, 0x3FF) # 2^15 (1 + 2^-1 + ... + 2^-10)
51 self.assertEqual(65504.0, uint16_to_float(float16_value_max))
53 # subnormal numbers
54 float16_value_min_subnormal = self._create_float16_value(0, 0, 1) # 2^-14 (2^-10)
55 float64_value_min_subnormal = self._create_float64_value(0, 999, 0) # 2^-24
56 converted_float = uint16_to_float(float16_value_min_subnormal)
57 self.assertEqual(float64_value_min_subnormal, float_to_uint64(converted_float))
59 float16_value_max_subnormal = self._create_float16_value(0, 0, 0x3FF) # 2^-14 (2^-1 + ... + 2^-10)
60 float64_value_max_subnormal = self._create_float64_value(0, 1008,
61 0xFF80000000000)# 2^-15 (1 + 2^-1 + ... + 2^-9)
62 converted_float = uint16_to_float(float16_value_max_subnormal)
63 self.assertEqual(float64_value_max_subnormal, float_to_uint64(converted_float))
65 def test_float_to_uint16(self):
66 # plus zero
67 float16_value_plus_zero = self._create_float16_value(0, 0, 0) # +0.0
68 self.assertEqual(float16_value_plus_zero, float_to_uint16(0.0))
70 # minus zero
71 float16_value_minus_zero = self._create_float16_value(1, 0, 0) # -0.0
72 self.assertEqual(float16_value_minus_zero, float_to_uint16(-0.0))
74 # plus infinity
75 float64_value_plus_infinity = self._create_float64_value(0, 0x7FF, 0) # +INF
76 float16_value_plus_infinity = self._create_float16_value(0, 0x1F, 0) # +INF
77 converted_float = uint64_to_float(float64_value_plus_infinity)
78 self.assertEqual(float16_value_plus_infinity, float_to_uint16(converted_float))
80 # minus infinity
81 float64_value_minus_infinity = self._create_float64_value(1, 0x7FF, 0) # -INF
82 float16_value_minus_infinity = self._create_float16_value(1, 0x1F, 0) # -INF
83 converted_float = uint64_to_float(float64_value_minus_infinity)
84 self.assertEqual(float16_value_minus_infinity, float_to_uint16(converted_float))
86 # quiet NaN
87 float64_value_quiet_nan = self._create_float64_value(0, 0x7FF, 0xFFC0000000000) # +NaN
88 float16_value_quiet_nan = self._create_float16_value(0, 0x1F, 0x3FF) # +NaN
89 converted_float = uint64_to_float(float64_value_quiet_nan)
90 self.assertEqual(float16_value_quiet_nan, float_to_uint16(converted_float))
92 # signaling NaN
93 float64_value_signaling_nan = self._create_float64_value(1, 0x7FF, 0xFFC0000000000) # -NaN
94 float16_value_signaling_nan = self._create_float16_value(1, 0x1F, 0x3FF) # -NaN
95 converted_float = uint64_to_float(float64_value_signaling_nan)
96 self.assertEqual(float16_value_signaling_nan, float_to_uint16(converted_float))
98 # normal numbers
99 float16_value_one = self._create_float16_value(0, 15, 0) # 1.0
100 self.assertEqual(float16_value_one, float_to_uint16(1.0))
102 float64_value_one_plus = self._create_float64_value(0, 0x3FF, 0x40000000000) # 1.0 + 2^-10
103 float16_value_one_plus = self._create_float16_value(0, 15, 0x01) # 1.0 + 2^-10
104 converted_float = uint64_to_float(float64_value_one_plus)
105 self.assertEqual(float16_value_one_plus, float_to_uint16(converted_float))
107 float16_value_max = self._create_float16_value(0, 30, 0x3FF) # 2^15 (1 + 2^-1 + ... + 2^-10)
108 self.assertEqual(float16_value_max, float_to_uint16(65504.0))
110 # normal numbers converted to zero
111 float64_value_underflow = self._create_float64_value(0, 998, 0) # 2^-25
112 converted_float = uint64_to_float(float64_value_underflow)
113 self.assertEqual(float16_value_plus_zero, float_to_uint16(converted_float))
115 # normal numbers converted to subnormal numbers
116 float64_value_min_underflow = self._create_float64_value(0, 999, 1) # 2^-24 (1 + 2^-52)
117 float16_value_min_subnormal = self._create_float16_value(0, 0, 1) # 2^-24
118 converted_float = uint64_to_float(float64_value_min_underflow)
119 self.assertEqual(float16_value_min_subnormal, float_to_uint16(converted_float))
121 # normal numbers converted to subnormal numbers with rounding
122 float64_value_min_underflow_rounding = self._create_float64_value(0, 1000,
123 0x4000000000000) # 2^-23 (1 + 2^-2)
124 float16_value_min_subnormal_rounding = self._create_float16_value(0, 0, 0x3) # 2^-14 (2^-9 + 2^-10)
125 converted_float = uint64_to_float(float64_value_min_underflow_rounding)
126 self.assertEqual(float16_value_min_subnormal_rounding, float_to_uint16(converted_float))
128 # normal numbers converted to infinity
129 float64_value_overflow = self._create_float64_value(0, 1040, 0) # 2^17
130 converted_float = uint64_to_float(float64_value_overflow)
131 self.assertEqual(float16_value_plus_infinity, float_to_uint16(converted_float))
133 # normal numbers converted with rounding
134 float64_value_rounding = self._create_float64_value(0, 1023, 0x8040000000000) # 1 + 2^-1 + 2^-11
135 float16_value_rounding = self._create_float16_value(0, 15, 0x201) # 1 + 2^-1 + 2^-10
136 converted_float = uint64_to_float(float64_value_rounding)
137 self.assertEqual(float16_value_rounding, float_to_uint16(converted_float))
139 # subnormal numbers
140 float64_value_min32_subnormal = self._create_float64_value(0, 874, 0) # 2^-126 (2^-23)
141 converted_float = uint64_to_float(float64_value_min32_subnormal)
142 self.assertEqual(float16_value_plus_zero, float_to_uint16(converted_float))
144 float64_value_max32_subnormal = self._create_float64_value(0, 896,
145 0xFFFFFC0000000)# 2^-126 (2^-1 + ... + 2^-23)
146 converted_float = uint64_to_float(float64_value_max32_subnormal)
147 self.assertEqual(float16_value_plus_zero, float_to_uint16(converted_float))
149 def test_uint32_to_float(self):
150 for data_row in self.TEST_FLOAT32_DATA:
151 float32_value = self._create_float32_value(data_row[0], data_row[1], data_row[2])
152 converted_float = uint32_to_float(float32_value)
153 self.assertEqual(data_row[3], converted_float)
155 def test_float_to_uint32(self):
156 for data_row in self.TEST_FLOAT32_DATA:
157 converted_float32_value = float_to_uint32(data_row[3])
158 float32_value = self._create_float32_value(data_row[0], data_row[1], data_row[2])
159 self.assertEqual(float32_value, converted_float32_value)
161 def test_uint64_to_float(self):
162 for data_row in self.TEST_FLOAT64_DATA:
163 float64_value = self._create_float64_value(data_row[0], data_row[1], data_row[2])
164 converted_float = uint64_to_float(float64_value)
165 self.assertEqual(data_row[3], converted_float)
167 def test_float_to_uint64(self):
168 for data_row in self.TEST_FLOAT64_DATA:
169 converted_float64_value = float_to_uint64(data_row[3])
170 float64_value = self._create_float64_value(data_row[0], data_row[1], data_row[2])
171 self.assertEqual(float64_value, converted_float64_value)
173 def _create_float16_value(self, sign, exponent, significand):
174 return ((sign << self.FLOAT16_SIGN_BIT_POSITION) | (exponent << self.FLOAT16_EXPONENT_BIT_POSITION) |
175 significand)
177 def _create_float32_value(self, sign, exponent, significand):
178 return ((sign << self.FLOAT32_SIGN_BIT_POSITION) | (exponent << self.FLOAT32_EXPONENT_BIT_POSITION) |
179 significand)
181 def _create_float64_value(self, sign, exponent, significand):
182 return ((sign << self.FLOAT64_SIGN_BIT_POSITION) | (exponent << self.FLOAT64_EXPONENT_BIT_POSITION) |
183 significand)
185 FLOAT16_SIGN_BIT_POSITION = 15
186 FLOAT16_EXPONENT_BIT_POSITION = 10
188 FLOAT32_SIGN_BIT_POSITION = 31
189 FLOAT32_EXPONENT_BIT_POSITION = 23
191 FLOAT64_SIGN_BIT_POSITION = 63
192 FLOAT64_EXPONENT_BIT_POSITION = 52
194 TEST_FLOAT32_DATA = [
195 [0, 0, 0, 0.0],
196 [1, 0, 0, -0.0],
197 [0, 127, 0, +1.0],
198 [1, 127, 0, -1.0],
199 [0, 128, 0x600000, 3.5], # 2^1 (1 + 2^-1 + 2^-2)
200 [0, 126, 0x600000, 0.875], # 2^-1 (1 + 2^-1 + 2^-2)
201 [0, 130, 0x1E0000, 9.875], # 2^3 (1 + 2^-3 + 2^-4 + 2^-5 + 2^-6)
202 [0, 126, 0x1E0000, 0.6171875] # 2^-3 (1 + 2^-3 + 2^-4 + 2^-5 + 2^-6)
203 ]
205 TEST_FLOAT64_DATA = [
206 [0, 0, 0, 0.0],
207 [1, 0, 0, -0.0],
208 [0, 1023, 0, +1.0],
209 [1, 1023, 0, -1.0],
210 [0, 1024, 0xC000000000000, 3.5], # 2^1 (1 + 2^-1 + 2^-2)
211 [0, 1022, 0xC000000000000, 0.875], # 2^-1 (1 + 2^-1 + 2^-2)
212 [0, 1026, 0x3C00000000000, 9.875], # 2^3 (1 + 2^-3 + 2^-4 + 2^-5 + 2^-6)
213 [0, 1022, 0x3C00000000000, 0.6171875] # 2^-3 (1 + 2^-3 + 2^-4 + 2^-5 + 2^-6)
214 ]