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

1import unittest 

2 

3from zserio.float import (uint16_to_float, float_to_uint16, uint32_to_float, 

4 float_to_uint32, uint64_to_float, float_to_uint64) 

5 

6class FloatUtilTest(unittest.TestCase): 

7 

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)) 

12 

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)) 

16 

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)) 

22 

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)) 

28 

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)) 

34 

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)) 

40 

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)) 

44 

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)) 

49 

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)) 

52 

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)) 

58 

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)) 

64 

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)) 

69 

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)) 

73 

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)) 

79 

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)) 

85 

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)) 

91 

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)) 

97 

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)) 

101 

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)) 

106 

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)) 

109 

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)) 

114 

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)) 

120 

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)) 

127 

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)) 

132 

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)) 

138 

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)) 

143 

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)) 

148 

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) 

154 

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) 

160 

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) 

166 

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) 

172 

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) 

176 

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) 

180 

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) 

184 

185 FLOAT16_SIGN_BIT_POSITION = 15 

186 FLOAT16_EXPONENT_BIT_POSITION = 10 

187 

188 FLOAT32_SIGN_BIT_POSITION = 31 

189 FLOAT32_EXPONENT_BIT_POSITION = 23 

190 

191 FLOAT64_SIGN_BIT_POSITION = 63 

192 FLOAT64_EXPONENT_BIT_POSITION = 52 

193 

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 ] 

204 

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 ]