1 | //===- unittests/ADT/FixedPointTest.cpp -- fixed point number tests -----===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/ADT/APFixedPoint.h" |
10 | #include "llvm/ADT/APFloat.h" |
11 | #include "llvm/ADT/APSInt.h" |
12 | #include "gtest/gtest.h" |
13 | |
14 | using llvm::APFixedPoint; |
15 | using llvm::APFloat; |
16 | using llvm::APInt; |
17 | using llvm::APSInt; |
18 | using llvm::FixedPointSemantics; |
19 | |
20 | namespace { |
21 | |
22 | FixedPointSemantics Saturated(FixedPointSemantics Sema) { |
23 | Sema.setSaturated(true); |
24 | return Sema; |
25 | } |
26 | |
27 | FixedPointSemantics getSAccumSema() { |
28 | return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/true, |
29 | /*isSaturated=*/false, |
30 | /*hasUnsignedPadding=*/false); |
31 | } |
32 | |
33 | FixedPointSemantics getAccumSema() { |
34 | return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/true, |
35 | /*isSaturated=*/false, |
36 | /*hasUnsignedPadding=*/false); |
37 | } |
38 | |
39 | FixedPointSemantics getLAccumSema() { |
40 | return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/true, |
41 | /*isSaturated=*/false, |
42 | /*hasUnsignedPadding=*/false); |
43 | } |
44 | |
45 | FixedPointSemantics getSFractSema() { |
46 | return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/true, |
47 | /*isSaturated=*/false, |
48 | /*hasUnsignedPadding=*/false); |
49 | } |
50 | |
51 | FixedPointSemantics getFractSema() { |
52 | return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/true, |
53 | /*isSaturated=*/false, |
54 | /*hasUnsignedPadding=*/false); |
55 | } |
56 | |
57 | FixedPointSemantics getLFractSema() { |
58 | return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/true, |
59 | /*isSaturated=*/false, |
60 | /*hasUnsignedPadding=*/false); |
61 | } |
62 | |
63 | FixedPointSemantics getUSAccumSema() { |
64 | return FixedPointSemantics(/*width=*/16, /*scale=*/8, /*isSigned=*/false, |
65 | /*isSaturated=*/false, |
66 | /*hasUnsignedPadding=*/false); |
67 | } |
68 | |
69 | FixedPointSemantics getUAccumSema() { |
70 | return FixedPointSemantics(/*width=*/32, /*scale=*/16, /*isSigned=*/false, |
71 | /*isSaturated=*/false, |
72 | /*hasUnsignedPadding=*/false); |
73 | } |
74 | |
75 | FixedPointSemantics getULAccumSema() { |
76 | return FixedPointSemantics(/*width=*/64, /*scale=*/32, /*isSigned=*/false, |
77 | /*isSaturated=*/false, |
78 | /*hasUnsignedPadding=*/false); |
79 | } |
80 | |
81 | FixedPointSemantics getUSFractSema() { |
82 | return FixedPointSemantics(/*width=*/8, /*scale=*/8, /*isSigned=*/false, |
83 | /*isSaturated=*/false, |
84 | /*hasUnsignedPadding=*/false); |
85 | } |
86 | |
87 | FixedPointSemantics getUFractSema() { |
88 | return FixedPointSemantics(/*width=*/16, /*scale=*/16, /*isSigned=*/false, |
89 | /*isSaturated=*/false, |
90 | /*hasUnsignedPadding=*/false); |
91 | } |
92 | |
93 | FixedPointSemantics getULFractSema() { |
94 | return FixedPointSemantics(/*width=*/32, /*scale=*/32, /*isSigned=*/false, |
95 | /*isSaturated=*/false, |
96 | /*hasUnsignedPadding=*/false); |
97 | } |
98 | |
99 | FixedPointSemantics getPadUSAccumSema() { |
100 | return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/false, |
101 | /*isSaturated=*/false, |
102 | /*hasUnsignedPadding=*/true); |
103 | } |
104 | |
105 | FixedPointSemantics getPadUAccumSema() { |
106 | return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/false, |
107 | /*isSaturated=*/false, |
108 | /*hasUnsignedPadding=*/true); |
109 | } |
110 | |
111 | FixedPointSemantics getPadULAccumSema() { |
112 | return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/false, |
113 | /*isSaturated=*/false, |
114 | /*hasUnsignedPadding=*/true); |
115 | } |
116 | |
117 | FixedPointSemantics getPadUSFractSema() { |
118 | return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/false, |
119 | /*isSaturated=*/false, |
120 | /*hasUnsignedPadding=*/true); |
121 | } |
122 | |
123 | FixedPointSemantics getPadUFractSema() { |
124 | return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/false, |
125 | /*isSaturated=*/false, |
126 | /*hasUnsignedPadding=*/true); |
127 | } |
128 | |
129 | FixedPointSemantics getPadULFractSema() { |
130 | return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/false, |
131 | /*isSaturated=*/false, |
132 | /*hasUnsignedPadding=*/true); |
133 | } |
134 | |
135 | FixedPointSemantics getU8Neg10() { |
136 | return FixedPointSemantics(/*width=*/8, /*lsb=*/FixedPointSemantics::Lsb{.LsbWeight: -10}, |
137 | /*isSigned=*/false, |
138 | /*isSaturated=*/false, |
139 | /*hasUnsignedPadding=*/false); |
140 | } |
141 | |
142 | FixedPointSemantics getS16Neg18() { |
143 | return FixedPointSemantics(/*width=*/16, |
144 | /*lsb=*/FixedPointSemantics::Lsb{.LsbWeight: -18}, |
145 | /*isSigned=*/true, |
146 | /*isSaturated=*/false, |
147 | /*hasUnsignedPadding=*/false); |
148 | } |
149 | |
150 | FixedPointSemantics getU8Pos4() { |
151 | return FixedPointSemantics(/*width=*/8, /*lsb=*/FixedPointSemantics::Lsb{.LsbWeight: 4}, |
152 | /*isSigned=*/false, |
153 | /*isSaturated=*/false, |
154 | /*hasUnsignedPadding=*/false); |
155 | } |
156 | |
157 | FixedPointSemantics getS32Pos2() { |
158 | return FixedPointSemantics(/*width=*/32, /*lsb=*/FixedPointSemantics::Lsb{.LsbWeight: 2}, |
159 | /*isSigned=*/true, |
160 | /*isSaturated=*/false, |
161 | /*hasUnsignedPadding=*/false); |
162 | } |
163 | |
164 | void CheckUnpaddedMax(const FixedPointSemantics &Sema) { |
165 | ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(), |
166 | APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned())); |
167 | } |
168 | |
169 | void CheckPaddedMax(const FixedPointSemantics &Sema) { |
170 | ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(), |
171 | APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()) >> 1); |
172 | } |
173 | |
174 | void CheckMin(const FixedPointSemantics &Sema) { |
175 | ASSERT_EQ(APFixedPoint::getMin(Sema).getValue(), |
176 | APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned())); |
177 | } |
178 | |
179 | TEST(FixedPointTest, getMax) { |
180 | CheckUnpaddedMax(Sema: getSAccumSema()); |
181 | CheckUnpaddedMax(Sema: getAccumSema()); |
182 | CheckUnpaddedMax(Sema: getLAccumSema()); |
183 | CheckUnpaddedMax(Sema: getUSAccumSema()); |
184 | CheckUnpaddedMax(Sema: getUAccumSema()); |
185 | CheckUnpaddedMax(Sema: getULAccumSema()); |
186 | CheckUnpaddedMax(Sema: getSFractSema()); |
187 | CheckUnpaddedMax(Sema: getFractSema()); |
188 | CheckUnpaddedMax(Sema: getLFractSema()); |
189 | CheckUnpaddedMax(Sema: getUSFractSema()); |
190 | CheckUnpaddedMax(Sema: getUFractSema()); |
191 | CheckUnpaddedMax(Sema: getULFractSema()); |
192 | CheckUnpaddedMax(Sema: getU8Neg10()); |
193 | CheckUnpaddedMax(Sema: getS16Neg18()); |
194 | CheckUnpaddedMax(Sema: getU8Pos4()); |
195 | CheckUnpaddedMax(Sema: getS32Pos2()); |
196 | |
197 | CheckPaddedMax(Sema: getPadUSAccumSema()); |
198 | CheckPaddedMax(Sema: getPadUAccumSema()); |
199 | CheckPaddedMax(Sema: getPadULAccumSema()); |
200 | CheckPaddedMax(Sema: getPadUSFractSema()); |
201 | CheckPaddedMax(Sema: getPadUFractSema()); |
202 | CheckPaddedMax(Sema: getPadULFractSema()); |
203 | } |
204 | |
205 | TEST(FixedPointTest, getMin) { |
206 | CheckMin(Sema: getSAccumSema()); |
207 | CheckMin(Sema: getAccumSema()); |
208 | CheckMin(Sema: getLAccumSema()); |
209 | CheckMin(Sema: getUSAccumSema()); |
210 | CheckMin(Sema: getUAccumSema()); |
211 | CheckMin(Sema: getULAccumSema()); |
212 | CheckMin(Sema: getSFractSema()); |
213 | CheckMin(Sema: getFractSema()); |
214 | CheckMin(Sema: getLFractSema()); |
215 | CheckMin(Sema: getUSFractSema()); |
216 | CheckMin(Sema: getUFractSema()); |
217 | CheckMin(Sema: getULFractSema()); |
218 | CheckMin(Sema: getU8Neg10()); |
219 | CheckMin(Sema: getS16Neg18()); |
220 | CheckMin(Sema: getU8Pos4()); |
221 | CheckMin(Sema: getS32Pos2()); |
222 | |
223 | CheckMin(Sema: getPadUSAccumSema()); |
224 | CheckMin(Sema: getPadUAccumSema()); |
225 | CheckMin(Sema: getPadULAccumSema()); |
226 | CheckMin(Sema: getPadUSFractSema()); |
227 | CheckMin(Sema: getPadUFractSema()); |
228 | CheckMin(Sema: getPadULFractSema()); |
229 | } |
230 | |
231 | int64_t relativeShr(int64_t Int, int64_t Shift) { |
232 | return (Shift > 0) ? Int >> Shift : Int << -Shift; |
233 | } |
234 | |
235 | void CheckIntPart(const FixedPointSemantics &Sema, int64_t IntPart) { |
236 | int64_t FullFactPart = |
237 | (Sema.getLsbWeight() > 0) ? 0 : (1ULL << (-Sema.getLsbWeight() - 1)); |
238 | |
239 | // Value with a fraction |
240 | APFixedPoint ValWithFract( |
241 | APInt(Sema.getWidth(), |
242 | relativeShr(Int: IntPart, Shift: Sema.getLsbWeight()) + FullFactPart, |
243 | Sema.isSigned()), |
244 | Sema); |
245 | ASSERT_EQ(ValWithFract.getIntPart(), IntPart); |
246 | |
247 | // Just fraction |
248 | APFixedPoint JustFract(APInt(Sema.getWidth(), FullFactPart, Sema.isSigned()), |
249 | Sema); |
250 | ASSERT_EQ(JustFract.getIntPart(), 0); |
251 | |
252 | // Whole number |
253 | APFixedPoint WholeNum(APInt(Sema.getWidth(), |
254 | relativeShr(Int: IntPart, Shift: Sema.getLsbWeight()), |
255 | Sema.isSigned()), |
256 | Sema); |
257 | ASSERT_EQ(WholeNum.getIntPart(), IntPart); |
258 | |
259 | // Negative |
260 | if (Sema.isSigned()) { |
261 | APFixedPoint Negative(APInt(Sema.getWidth(), |
262 | relativeShr(Int: IntPart, Shift: Sema.getLsbWeight()), |
263 | Sema.isSigned()), |
264 | Sema); |
265 | ASSERT_EQ(Negative.getIntPart(), IntPart); |
266 | } |
267 | } |
268 | |
269 | void CheckIntPartMin(const FixedPointSemantics &Sema, int64_t Expected) { |
270 | EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMin(Sema).getIntPart(), |
271 | APSInt::get(Expected)) == 0); |
272 | } |
273 | |
274 | void CheckIntPartMax(const FixedPointSemantics &Sema, uint64_t Expected) { |
275 | EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMax(Sema).getIntPart(), |
276 | APSInt::getUnsigned(Expected)) == 0); |
277 | } |
278 | |
279 | void CheckIntPartRes(const FixedPointSemantics &Sema, int64_t Representation, |
280 | uint64_t Result) { |
281 | APFixedPoint Val(Representation, Sema); |
282 | ASSERT_EQ(Val.getIntPart().getZExtValue(), Result) ; |
283 | } |
284 | |
285 | TEST(FixedPoint, getIntPart) { |
286 | // Normal values |
287 | CheckIntPart(Sema: getSAccumSema(), IntPart: 2); |
288 | CheckIntPart(Sema: getAccumSema(), IntPart: 2); |
289 | CheckIntPart(Sema: getLAccumSema(), IntPart: 2); |
290 | CheckIntPart(Sema: getUSAccumSema(), IntPart: 2); |
291 | CheckIntPart(Sema: getUAccumSema(), IntPart: 2); |
292 | CheckIntPart(Sema: getULAccumSema(), IntPart: 2); |
293 | CheckIntPart(Sema: getU8Pos4(), IntPart: 32); |
294 | CheckIntPart(Sema: getS32Pos2(), IntPart: 32); |
295 | |
296 | // Zero |
297 | CheckIntPart(Sema: getSAccumSema(), IntPart: 0); |
298 | CheckIntPart(Sema: getAccumSema(), IntPart: 0); |
299 | CheckIntPart(Sema: getLAccumSema(), IntPart: 0); |
300 | CheckIntPart(Sema: getUSAccumSema(), IntPart: 0); |
301 | CheckIntPart(Sema: getUAccumSema(), IntPart: 0); |
302 | CheckIntPart(Sema: getULAccumSema(), IntPart: 0); |
303 | |
304 | CheckIntPart(Sema: getSFractSema(), IntPart: 0); |
305 | CheckIntPart(Sema: getFractSema(), IntPart: 0); |
306 | CheckIntPart(Sema: getLFractSema(), IntPart: 0); |
307 | CheckIntPart(Sema: getUSFractSema(), IntPart: 0); |
308 | CheckIntPart(Sema: getUFractSema(), IntPart: 0); |
309 | CheckIntPart(Sema: getULFractSema(), IntPart: 0); |
310 | |
311 | CheckIntPart(Sema: getS16Neg18(), IntPart: 0); |
312 | CheckIntPart(Sema: getU8Neg10(), IntPart: 0); |
313 | CheckIntPart(Sema: getU8Pos4(), IntPart: 0); |
314 | CheckIntPart(Sema: getS32Pos2(), IntPart: 0); |
315 | |
316 | // Min |
317 | CheckIntPartMin(Sema: getSAccumSema(), Expected: -256); |
318 | CheckIntPartMin(Sema: getAccumSema(), Expected: -65536); |
319 | CheckIntPartMin(Sema: getLAccumSema(), Expected: -4294967296); |
320 | |
321 | CheckIntPartMin(Sema: getSFractSema(), Expected: -1); |
322 | CheckIntPartMin(Sema: getFractSema(), Expected: -1); |
323 | CheckIntPartMin(Sema: getLFractSema(), Expected: -1); |
324 | |
325 | CheckIntPartMin(Sema: getS32Pos2(), Expected: -8589934592); |
326 | |
327 | // Max |
328 | CheckIntPartMax(Sema: getSAccumSema(), Expected: 255); |
329 | CheckIntPartMax(Sema: getAccumSema(), Expected: 65535); |
330 | CheckIntPartMax(Sema: getLAccumSema(), Expected: 4294967295); |
331 | CheckIntPartMax(Sema: getUSAccumSema(), Expected: 255); |
332 | CheckIntPartMax(Sema: getUAccumSema(), Expected: 65535); |
333 | CheckIntPartMax(Sema: getULAccumSema(), Expected: 4294967295); |
334 | |
335 | CheckIntPartMax(Sema: getU8Pos4(), Expected: 255 << 4); |
336 | CheckIntPartMax(Sema: getS32Pos2(), Expected: 2147483647ull << 2); |
337 | |
338 | CheckIntPartMax(Sema: getSFractSema(), Expected: 0); |
339 | CheckIntPartMax(Sema: getFractSema(), Expected: 0); |
340 | CheckIntPartMax(Sema: getLFractSema(), Expected: 0); |
341 | CheckIntPartMax(Sema: getUSFractSema(), Expected: 0); |
342 | CheckIntPartMax(Sema: getUFractSema(), Expected: 0); |
343 | CheckIntPartMax(Sema: getULFractSema(), Expected: 0); |
344 | |
345 | // Padded |
346 | // Normal Values |
347 | CheckIntPart(Sema: getPadUSAccumSema(), IntPart: 2); |
348 | CheckIntPart(Sema: getPadUAccumSema(), IntPart: 2); |
349 | CheckIntPart(Sema: getPadULAccumSema(), IntPart: 2); |
350 | |
351 | // Zero |
352 | CheckIntPart(Sema: getPadUSAccumSema(), IntPart: 0); |
353 | CheckIntPart(Sema: getPadUAccumSema(), IntPart: 0); |
354 | CheckIntPart(Sema: getPadULAccumSema(), IntPart: 0); |
355 | |
356 | CheckIntPart(Sema: getPadUSFractSema(), IntPart: 0); |
357 | CheckIntPart(Sema: getPadUFractSema(), IntPart: 0); |
358 | CheckIntPart(Sema: getPadULFractSema(), IntPart: 0); |
359 | |
360 | // Max |
361 | CheckIntPartMax(Sema: getPadUSAccumSema(), Expected: 255); |
362 | CheckIntPartMax(Sema: getPadUAccumSema(), Expected: 65535); |
363 | CheckIntPartMax(Sema: getPadULAccumSema(), Expected: 4294967295); |
364 | |
365 | CheckIntPartMax(Sema: getPadUSFractSema(), Expected: 0); |
366 | CheckIntPartMax(Sema: getPadUFractSema(), Expected: 0); |
367 | CheckIntPartMax(Sema: getPadULFractSema(), Expected: 0); |
368 | |
369 | // Rounded Towards Zero |
370 | CheckIntPartRes(Sema: getSFractSema(), Representation: -127, Result: 0); |
371 | CheckIntPartRes(Sema: getFractSema(), Representation: -32767, Result: 0); |
372 | CheckIntPartRes(Sema: getLFractSema(), Representation: -2147483647, Result: 0); |
373 | CheckIntPartRes(Sema: getS16Neg18(), Representation: -32768, Result: 0); |
374 | } |
375 | |
376 | TEST(FixedPoint, compare) { |
377 | // Equality |
378 | // With fractional part (2.5) |
379 | // Across sizes |
380 | ASSERT_EQ(APFixedPoint(320, getSAccumSema()), |
381 | APFixedPoint(81920, getAccumSema())); |
382 | ASSERT_EQ(APFixedPoint(320, getSAccumSema()), |
383 | APFixedPoint(5368709120, getLAccumSema())); |
384 | ASSERT_EQ(APFixedPoint(0, getSAccumSema()), APFixedPoint(0, getLAccumSema())); |
385 | |
386 | ASSERT_EQ(APFixedPoint(0, getS16Neg18()), APFixedPoint(0, getU8Neg10())); |
387 | ASSERT_EQ(APFixedPoint(256, getS16Neg18()), APFixedPoint(1, getU8Neg10())); |
388 | ASSERT_EQ(APFixedPoint(32512, getS16Neg18()), |
389 | APFixedPoint(127, getU8Neg10())); |
390 | ASSERT_EQ(APFixedPoint(4, getS32Pos2()), APFixedPoint(1, getU8Pos4())); |
391 | ASSERT_EQ(APFixedPoint(1020, getS32Pos2()), APFixedPoint(255, getU8Pos4())); |
392 | |
393 | // Across types (0.5) |
394 | ASSERT_EQ(APFixedPoint(64, getSAccumSema()), |
395 | APFixedPoint(64, getSFractSema())); |
396 | ASSERT_EQ(APFixedPoint(16384, getAccumSema()), |
397 | APFixedPoint(16384, getFractSema())); |
398 | ASSERT_EQ(APFixedPoint(1073741824, getLAccumSema()), |
399 | APFixedPoint(1073741824, getLFractSema())); |
400 | |
401 | // Across widths and types (0.5) |
402 | ASSERT_EQ(APFixedPoint(64, getSAccumSema()), |
403 | APFixedPoint(16384, getFractSema())); |
404 | ASSERT_EQ(APFixedPoint(64, getSAccumSema()), |
405 | APFixedPoint(1073741824, getLFractSema())); |
406 | |
407 | // Across saturation |
408 | ASSERT_EQ(APFixedPoint(320, getSAccumSema()), |
409 | APFixedPoint(81920, Saturated(getAccumSema()))); |
410 | |
411 | // Across signs |
412 | ASSERT_EQ(APFixedPoint(320, getSAccumSema()), |
413 | APFixedPoint(640, getUSAccumSema())); |
414 | ASSERT_EQ(APFixedPoint(-320, getSAccumSema()), |
415 | APFixedPoint(-81920, getAccumSema())); |
416 | |
417 | // Across padding |
418 | ASSERT_EQ(APFixedPoint(320, getSAccumSema()), |
419 | APFixedPoint(320, getPadUSAccumSema())); |
420 | ASSERT_EQ(APFixedPoint(640, getUSAccumSema()), |
421 | APFixedPoint(320, getPadUSAccumSema())); |
422 | |
423 | // Less than |
424 | ASSERT_LT(APFixedPoint(-1, getSAccumSema()), APFixedPoint(0, getAccumSema())); |
425 | ASSERT_LT(APFixedPoint(-1, getSAccumSema()), |
426 | APFixedPoint(0, getUAccumSema())); |
427 | ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getAccumSema())); |
428 | ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getUAccumSema())); |
429 | ASSERT_LT(APFixedPoint(0, getUSAccumSema()), APFixedPoint(1, getAccumSema())); |
430 | ASSERT_LT(APFixedPoint(0, getUSAccumSema()), |
431 | APFixedPoint(1, getUAccumSema())); |
432 | ASSERT_LT(APFixedPoint(65280, getS16Neg18()), |
433 | APFixedPoint(255, getU8Neg10())); |
434 | |
435 | // Greater than |
436 | ASSERT_GT(APFixedPoint(0, getAccumSema()), APFixedPoint(-1, getSAccumSema())); |
437 | ASSERT_GT(APFixedPoint(0, getUAccumSema()), |
438 | APFixedPoint(-1, getSAccumSema())); |
439 | ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getSAccumSema())); |
440 | ASSERT_GT(APFixedPoint(1, getUAccumSema()), APFixedPoint(0, getSAccumSema())); |
441 | ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getUSAccumSema())); |
442 | ASSERT_GT(APFixedPoint(1, getUAccumSema()), |
443 | APFixedPoint(0, getUSAccumSema())); |
444 | } |
445 | |
446 | // Check that a fixed point value in one sema is the same in another sema |
447 | void CheckUnsaturatedConversion(FixedPointSemantics Src, |
448 | FixedPointSemantics Dst, int64_t TestVal) { |
449 | int64_t ScaledVal = TestVal; |
450 | bool IsNegative = ScaledVal < 0; |
451 | if (IsNegative) |
452 | ScaledVal = -ScaledVal; |
453 | |
454 | if (Dst.getLsbWeight() < Src.getLsbWeight()) { |
455 | ScaledVal <<= (Src.getLsbWeight() - Dst.getLsbWeight()); |
456 | } else { |
457 | ScaledVal >>= (Dst.getLsbWeight() - Src.getLsbWeight()); |
458 | } |
459 | |
460 | if (IsNegative) |
461 | ScaledVal = -ScaledVal; |
462 | |
463 | APFixedPoint Fixed(TestVal, Src); |
464 | APFixedPoint Expected(ScaledVal, Dst); |
465 | ASSERT_EQ(Fixed.convert(Dst), Expected); |
466 | } |
467 | |
468 | // Check the value in a given fixed point sema overflows to the saturated min |
469 | // for another sema |
470 | void CheckSaturatedConversionMin(FixedPointSemantics Src, |
471 | FixedPointSemantics Dst, int64_t TestVal) { |
472 | APFixedPoint Fixed(TestVal, Src); |
473 | ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMin(Dst)); |
474 | } |
475 | |
476 | // Check the value in a given fixed point sema overflows to the saturated max |
477 | // for another sema |
478 | void CheckSaturatedConversionMax(FixedPointSemantics Src, |
479 | FixedPointSemantics Dst, int64_t TestVal) { |
480 | APFixedPoint Fixed(TestVal, Src); |
481 | ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMax(Dst)); |
482 | } |
483 | |
484 | // Check one signed _Accum sema converted to other sema for different values. |
485 | void CheckSignedAccumConversionsAgainstOthers(FixedPointSemantics Src, |
486 | int64_t OneVal) { |
487 | int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5 |
488 | int64_t HalfVal = (OneVal / 2); // 0.5 |
489 | |
490 | // +Accums to Accums |
491 | CheckUnsaturatedConversion(Src, Dst: getSAccumSema(), TestVal: NormalVal); |
492 | CheckUnsaturatedConversion(Src, Dst: getAccumSema(), TestVal: NormalVal); |
493 | CheckUnsaturatedConversion(Src, Dst: getLAccumSema(), TestVal: NormalVal); |
494 | CheckUnsaturatedConversion(Src, Dst: getUSAccumSema(), TestVal: NormalVal); |
495 | CheckUnsaturatedConversion(Src, Dst: getUAccumSema(), TestVal: NormalVal); |
496 | CheckUnsaturatedConversion(Src, Dst: getULAccumSema(), TestVal: NormalVal); |
497 | CheckUnsaturatedConversion(Src, Dst: getPadUSAccumSema(), TestVal: NormalVal); |
498 | CheckUnsaturatedConversion(Src, Dst: getPadUAccumSema(), TestVal: NormalVal); |
499 | CheckUnsaturatedConversion(Src, Dst: getPadULAccumSema(), TestVal: NormalVal); |
500 | |
501 | // -Accums to Accums |
502 | CheckUnsaturatedConversion(Src, Dst: getSAccumSema(), TestVal: -NormalVal); |
503 | CheckUnsaturatedConversion(Src, Dst: getAccumSema(), TestVal: -NormalVal); |
504 | CheckUnsaturatedConversion(Src, Dst: getLAccumSema(), TestVal: -NormalVal); |
505 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getUSAccumSema()), TestVal: -NormalVal); |
506 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getUAccumSema()), TestVal: -NormalVal); |
507 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getULAccumSema()), TestVal: -NormalVal); |
508 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadUSAccumSema()), TestVal: -NormalVal); |
509 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadUAccumSema()), TestVal: -NormalVal); |
510 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadULAccumSema()), TestVal: -NormalVal); |
511 | |
512 | // +Accums to Fracts |
513 | CheckUnsaturatedConversion(Src, Dst: getSFractSema(), TestVal: HalfVal); |
514 | CheckUnsaturatedConversion(Src, Dst: getFractSema(), TestVal: HalfVal); |
515 | CheckUnsaturatedConversion(Src, Dst: getLFractSema(), TestVal: HalfVal); |
516 | CheckUnsaturatedConversion(Src, Dst: getUSFractSema(), TestVal: HalfVal); |
517 | CheckUnsaturatedConversion(Src, Dst: getUFractSema(), TestVal: HalfVal); |
518 | CheckUnsaturatedConversion(Src, Dst: getULFractSema(), TestVal: HalfVal); |
519 | CheckUnsaturatedConversion(Src, Dst: getPadUSFractSema(), TestVal: HalfVal); |
520 | CheckUnsaturatedConversion(Src, Dst: getPadUFractSema(), TestVal: HalfVal); |
521 | CheckUnsaturatedConversion(Src, Dst: getPadULFractSema(), TestVal: HalfVal); |
522 | |
523 | // -Accums to Fracts |
524 | CheckUnsaturatedConversion(Src, Dst: getSFractSema(), TestVal: -HalfVal); |
525 | CheckUnsaturatedConversion(Src, Dst: getFractSema(), TestVal: -HalfVal); |
526 | CheckUnsaturatedConversion(Src, Dst: getLFractSema(), TestVal: -HalfVal); |
527 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getUSFractSema()), TestVal: -HalfVal); |
528 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getUFractSema()), TestVal: -HalfVal); |
529 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getULFractSema()), TestVal: -HalfVal); |
530 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadUSFractSema()), TestVal: -HalfVal); |
531 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadUFractSema()), TestVal: -HalfVal); |
532 | CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadULFractSema()), TestVal: -HalfVal); |
533 | |
534 | // 0 to Accums |
535 | CheckUnsaturatedConversion(Src, Dst: getSAccumSema(), TestVal: 0); |
536 | CheckUnsaturatedConversion(Src, Dst: getAccumSema(), TestVal: 0); |
537 | CheckUnsaturatedConversion(Src, Dst: getLAccumSema(), TestVal: 0); |
538 | CheckUnsaturatedConversion(Src, Dst: getUSAccumSema(), TestVal: 0); |
539 | CheckUnsaturatedConversion(Src, Dst: getUAccumSema(), TestVal: 0); |
540 | CheckUnsaturatedConversion(Src, Dst: getULAccumSema(), TestVal: 0); |
541 | CheckUnsaturatedConversion(Src, Dst: getPadUSAccumSema(), TestVal: 0); |
542 | CheckUnsaturatedConversion(Src, Dst: getPadUAccumSema(), TestVal: 0); |
543 | CheckUnsaturatedConversion(Src, Dst: getPadULAccumSema(), TestVal: 0); |
544 | |
545 | // 0 to Fracts |
546 | CheckUnsaturatedConversion(Src, Dst: getSFractSema(), TestVal: 0); |
547 | CheckUnsaturatedConversion(Src, Dst: getFractSema(), TestVal: 0); |
548 | CheckUnsaturatedConversion(Src, Dst: getLFractSema(), TestVal: 0); |
549 | CheckUnsaturatedConversion(Src, Dst: getUSFractSema(), TestVal: 0); |
550 | CheckUnsaturatedConversion(Src, Dst: getUFractSema(), TestVal: 0); |
551 | CheckUnsaturatedConversion(Src, Dst: getULFractSema(), TestVal: 0); |
552 | CheckUnsaturatedConversion(Src, Dst: getPadUSFractSema(), TestVal: 0); |
553 | CheckUnsaturatedConversion(Src, Dst: getPadUFractSema(), TestVal: 0); |
554 | CheckUnsaturatedConversion(Src, Dst: getPadULFractSema(), TestVal: 0); |
555 | } |
556 | |
557 | // Check one unsigned _Accum sema converted to other sema for different |
558 | // values. |
559 | void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src, |
560 | int64_t OneVal) { |
561 | int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5 |
562 | int64_t HalfVal = (OneVal / 2); // 0.5 |
563 | |
564 | // +UAccums to Accums |
565 | CheckUnsaturatedConversion(Src, Dst: getSAccumSema(), TestVal: NormalVal); |
566 | CheckUnsaturatedConversion(Src, Dst: getAccumSema(), TestVal: NormalVal); |
567 | CheckUnsaturatedConversion(Src, Dst: getLAccumSema(), TestVal: NormalVal); |
568 | CheckUnsaturatedConversion(Src, Dst: getUSAccumSema(), TestVal: NormalVal); |
569 | CheckUnsaturatedConversion(Src, Dst: getUAccumSema(), TestVal: NormalVal); |
570 | CheckUnsaturatedConversion(Src, Dst: getULAccumSema(), TestVal: NormalVal); |
571 | CheckUnsaturatedConversion(Src, Dst: getPadUSAccumSema(), TestVal: NormalVal); |
572 | CheckUnsaturatedConversion(Src, Dst: getPadUAccumSema(), TestVal: NormalVal); |
573 | CheckUnsaturatedConversion(Src, Dst: getPadULAccumSema(), TestVal: NormalVal); |
574 | |
575 | // +UAccums to Fracts |
576 | CheckUnsaturatedConversion(Src, Dst: getSFractSema(), TestVal: HalfVal); |
577 | CheckUnsaturatedConversion(Src, Dst: getFractSema(), TestVal: HalfVal); |
578 | CheckUnsaturatedConversion(Src, Dst: getLFractSema(), TestVal: HalfVal); |
579 | CheckUnsaturatedConversion(Src, Dst: getUSFractSema(), TestVal: HalfVal); |
580 | CheckUnsaturatedConversion(Src, Dst: getUFractSema(), TestVal: HalfVal); |
581 | CheckUnsaturatedConversion(Src, Dst: getULFractSema(), TestVal: HalfVal); |
582 | CheckUnsaturatedConversion(Src, Dst: getPadUSFractSema(), TestVal: HalfVal); |
583 | CheckUnsaturatedConversion(Src, Dst: getPadUFractSema(), TestVal: HalfVal); |
584 | CheckUnsaturatedConversion(Src, Dst: getPadULFractSema(), TestVal: HalfVal); |
585 | } |
586 | |
587 | TEST(FixedPoint, AccumConversions) { |
588 | // Normal conversions |
589 | CheckSignedAccumConversionsAgainstOthers(Src: getSAccumSema(), OneVal: 128); |
590 | CheckUnsignedAccumConversionsAgainstOthers(Src: getUSAccumSema(), OneVal: 256); |
591 | CheckSignedAccumConversionsAgainstOthers(Src: getAccumSema(), OneVal: 32768); |
592 | CheckUnsignedAccumConversionsAgainstOthers(Src: getUAccumSema(), OneVal: 65536); |
593 | CheckSignedAccumConversionsAgainstOthers(Src: getLAccumSema(), OneVal: 2147483648); |
594 | CheckUnsignedAccumConversionsAgainstOthers(Src: getULAccumSema(), OneVal: 4294967296); |
595 | |
596 | CheckUnsignedAccumConversionsAgainstOthers(Src: getPadUSAccumSema(), OneVal: 128); |
597 | CheckUnsignedAccumConversionsAgainstOthers(Src: getPadUAccumSema(), OneVal: 32768); |
598 | CheckUnsignedAccumConversionsAgainstOthers(Src: getPadULAccumSema(), OneVal: 2147483648); |
599 | } |
600 | |
601 | TEST(FixedPoint, AccumConversionOverflow) { |
602 | // To SAccum max limit (65536) |
603 | CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getAccumSema()), |
604 | TestVal: 140737488355328); |
605 | CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getUAccumSema()), |
606 | TestVal: 140737488355328); |
607 | CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getPadUAccumSema()), |
608 | TestVal: 140737488355328); |
609 | CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getAccumSema()), |
610 | TestVal: 281474976710656); |
611 | CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getUAccumSema()), |
612 | TestVal: 281474976710656); |
613 | CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getPadUAccumSema()), |
614 | TestVal: 281474976710656); |
615 | |
616 | CheckSaturatedConversionMax(Src: getPadULAccumSema(), Dst: Saturated(Sema: getAccumSema()), |
617 | TestVal: 140737488355328); |
618 | CheckSaturatedConversionMax(Src: getPadULAccumSema(), Dst: Saturated(Sema: getUAccumSema()), |
619 | TestVal: 140737488355328); |
620 | CheckSaturatedConversionMax(Src: getPadULAccumSema(), |
621 | Dst: Saturated(Sema: getPadUAccumSema()), TestVal: 140737488355328); |
622 | |
623 | // To SAccum min limit (-65536) |
624 | CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getAccumSema()), |
625 | TestVal: -140737488355328); |
626 | CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getUAccumSema()), |
627 | TestVal: -140737488355328); |
628 | CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getPadUAccumSema()), |
629 | TestVal: -140737488355328); |
630 | } |
631 | |
632 | TEST(FixedPoint, SAccumConversionOverflow) { |
633 | // To SAccum max limit (256) |
634 | CheckSaturatedConversionMax(Src: getAccumSema(), Dst: Saturated(Sema: getSAccumSema()), |
635 | TestVal: 8388608); |
636 | CheckSaturatedConversionMax(Src: getAccumSema(), Dst: Saturated(Sema: getUSAccumSema()), |
637 | TestVal: 8388608); |
638 | CheckSaturatedConversionMax(Src: getAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()), |
639 | TestVal: 8388608); |
640 | CheckSaturatedConversionMax(Src: getUAccumSema(), Dst: Saturated(Sema: getSAccumSema()), |
641 | TestVal: 16777216); |
642 | CheckSaturatedConversionMax(Src: getUAccumSema(), Dst: Saturated(Sema: getUSAccumSema()), |
643 | TestVal: 16777216); |
644 | CheckSaturatedConversionMax(Src: getUAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()), |
645 | TestVal: 16777216); |
646 | CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getSAccumSema()), |
647 | TestVal: 549755813888); |
648 | CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getUSAccumSema()), |
649 | TestVal: 549755813888); |
650 | CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()), |
651 | TestVal: 549755813888); |
652 | CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getSAccumSema()), |
653 | TestVal: 1099511627776); |
654 | CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getUSAccumSema()), |
655 | TestVal: 1099511627776); |
656 | CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()), |
657 | TestVal: 1099511627776); |
658 | |
659 | CheckSaturatedConversionMax(Src: getPadUAccumSema(), Dst: Saturated(Sema: getSAccumSema()), |
660 | TestVal: 8388608); |
661 | CheckSaturatedConversionMax(Src: getPadUAccumSema(), Dst: Saturated(Sema: getUSAccumSema()), |
662 | TestVal: 8388608); |
663 | CheckSaturatedConversionMax(Src: getPadUAccumSema(), |
664 | Dst: Saturated(Sema: getPadUSAccumSema()), TestVal: 8388608); |
665 | CheckSaturatedConversionMax(Src: getPadULAccumSema(), Dst: Saturated(Sema: getSAccumSema()), |
666 | TestVal: 549755813888); |
667 | CheckSaturatedConversionMax(Src: getPadULAccumSema(), Dst: Saturated(Sema: getUSAccumSema()), |
668 | TestVal: 549755813888); |
669 | CheckSaturatedConversionMax(Src: getPadULAccumSema(), |
670 | Dst: Saturated(Sema: getPadUSAccumSema()), TestVal: 549755813888); |
671 | |
672 | // To SAccum min limit (-256) |
673 | CheckSaturatedConversionMin(Src: getAccumSema(), Dst: Saturated(Sema: getSAccumSema()), |
674 | TestVal: -8388608); |
675 | CheckSaturatedConversionMin(Src: getAccumSema(), Dst: Saturated(Sema: getUSAccumSema()), |
676 | TestVal: -8388608); |
677 | CheckSaturatedConversionMin(Src: getAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()), |
678 | TestVal: -8388608); |
679 | CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getSAccumSema()), |
680 | TestVal: -549755813888); |
681 | CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getUSAccumSema()), |
682 | TestVal: -549755813888); |
683 | CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()), |
684 | TestVal: -549755813888); |
685 | } |
686 | |
687 | TEST(FixedPoint, GetValueSignAfterConversion) { |
688 | APFixedPoint Fixed(255 << 7, getSAccumSema()); |
689 | ASSERT_TRUE(Fixed.getValue().isSigned()); |
690 | APFixedPoint UFixed = Fixed.convert(DstSema: getUSAccumSema()); |
691 | ASSERT_TRUE(UFixed.getValue().isUnsigned()); |
692 | ASSERT_EQ(UFixed.getValue(), APSInt::getUnsigned(255 << 8).extOrTrunc(16)); |
693 | } |
694 | |
695 | TEST(FixedPoint, ModularWrapAround) { |
696 | // Positive to negative |
697 | APFixedPoint Val = APFixedPoint(1ULL << 7, getSAccumSema()); |
698 | ASSERT_EQ(Val.convert(getLFractSema()).getValue(), -(1ULL << 31)); |
699 | |
700 | Val = APFixedPoint(1ULL << 23, getAccumSema()); |
701 | ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), -(1ULL << 15)); |
702 | |
703 | Val = APFixedPoint(1ULL << 47, getLAccumSema()); |
704 | ASSERT_EQ(Val.convert(getAccumSema()).getValue(), -(1ULL << 31)); |
705 | |
706 | // Negative to positive |
707 | Val = APFixedPoint(/*-1.5*/ -192, getSAccumSema()); |
708 | ASSERT_EQ(Val.convert(getLFractSema()).getValue(), 1ULL << 30); |
709 | |
710 | Val = APFixedPoint(-(257 << 15), getAccumSema()); |
711 | ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), 255 << 7); |
712 | |
713 | Val = APFixedPoint(-(65537ULL << 31), getLAccumSema()); |
714 | ASSERT_EQ(Val.convert(getAccumSema()).getValue(), 65535 << 15); |
715 | |
716 | // Signed to unsigned |
717 | Val = APFixedPoint(-(1 << 7), getSAccumSema()); |
718 | ASSERT_EQ(Val.convert(getUSAccumSema()).getValue(), 255 << 8); |
719 | |
720 | Val = APFixedPoint(-(1 << 15), getAccumSema()); |
721 | ASSERT_EQ(Val.convert(getUAccumSema()).getValue(), 65535ULL << 16); |
722 | |
723 | Val = APFixedPoint(-(1ULL << 31), getLAccumSema()); |
724 | ASSERT_EQ(Val.convert(getULAccumSema()).getValue().getZExtValue(), |
725 | 4294967295ULL << 32); |
726 | } |
727 | |
728 | enum OvfKind { MinSat, MaxSat }; |
729 | |
730 | void CheckFloatToFixedConversion(APFloat &Val, const FixedPointSemantics &Sema, |
731 | int64_t ExpectedNonSat) { |
732 | bool Ovf; |
733 | ASSERT_EQ(APFixedPoint::getFromFloatValue(Val, Sema, &Ovf).getValue(), |
734 | ExpectedNonSat); |
735 | ASSERT_EQ(Ovf, false); |
736 | ASSERT_EQ( |
737 | APFixedPoint::getFromFloatValue(Val, Saturated(Sema), &Ovf).getValue(), |
738 | ExpectedNonSat); |
739 | ASSERT_EQ(Ovf, false); |
740 | } |
741 | |
742 | void CheckFloatToFixedConversion(APFloat &Val, const FixedPointSemantics &Sema, |
743 | OvfKind ExpectedOvf) { |
744 | bool Ovf; |
745 | (void)APFixedPoint::getFromFloatValue(Value: Val, DstFXSema: Sema, Overflow: &Ovf); |
746 | ASSERT_EQ(Ovf, true); |
747 | ASSERT_EQ( |
748 | APFixedPoint::getFromFloatValue(Val, Saturated(Sema), &Ovf).getValue(), |
749 | (ExpectedOvf == MinSat ? APFixedPoint::getMin(Sema) |
750 | : APFixedPoint::getMax(Sema)) |
751 | .getValue()); |
752 | ASSERT_EQ(Ovf, false); |
753 | } |
754 | |
755 | TEST(FixedPoint, toString) { |
756 | ASSERT_EQ(APFixedPoint::getMax(getS16Neg18()).toString(), |
757 | "0.124996185302734375" ); |
758 | ASSERT_EQ(APFixedPoint::getMin(getS16Neg18()) |
759 | .add(APFixedPoint(1, getS16Neg18())) |
760 | .toString(), |
761 | "-0.124996185302734375" ); |
762 | ASSERT_EQ(APFixedPoint::getMin(getS16Neg18()).toString(), "-0.125" ); |
763 | ASSERT_EQ(APFixedPoint::getMax(getU8Neg10()).toString(), "0.2490234375" ); |
764 | ASSERT_EQ(APFixedPoint::getMin(getU8Neg10()).toString(), "0.0" ); |
765 | ASSERT_EQ(APFixedPoint::getMax(getS32Pos2()).toString(), "8589934588.0" ); |
766 | ASSERT_EQ(APFixedPoint::getMin(getS32Pos2()) |
767 | .add(APFixedPoint(1, getS32Pos2())) |
768 | .toString(), |
769 | "-8589934588.0" ); |
770 | ASSERT_EQ(APFixedPoint::getMin(getS32Pos2()).toString(), "-8589934592.0" ); |
771 | ASSERT_EQ(APFixedPoint::getMax(getU8Pos4()).toString(), "4080.0" ); |
772 | ASSERT_EQ(APFixedPoint::getMin(getU8Pos4()).toString(), "0.0" ); |
773 | } |
774 | |
775 | TEST(FixedPoint, FloatToFixed) { |
776 | APFloat Val(0.0f); |
777 | |
778 | // Simple exact fraction |
779 | Val = APFloat(0.75f); |
780 | CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: 3ULL << 5); |
781 | CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: 3ULL << 13); |
782 | CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: 3ULL << 29); |
783 | |
784 | CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedNonSat: 3ULL << 6); |
785 | CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedNonSat: 3ULL << 14); |
786 | CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedNonSat: 3ULL << 30); |
787 | |
788 | CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedNonSat: 3ULL << 5); |
789 | CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedNonSat: 3ULL << 13); |
790 | CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedNonSat: 3ULL << 29); |
791 | |
792 | CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedNonSat: 3ULL << 6); |
793 | CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedNonSat: 3ULL << 14); |
794 | CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedNonSat: 3ULL << 30); |
795 | |
796 | CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MaxSat); |
797 | CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0); |
798 | CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MaxSat); |
799 | CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0); |
800 | |
801 | // Simple negative exact fraction |
802 | Val = APFloat(-0.75f); |
803 | CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: -3ULL << 5); |
804 | CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: -3ULL << 13); |
805 | CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: -3ULL << 29); |
806 | |
807 | CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedOvf: MinSat); |
808 | CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedOvf: MinSat); |
809 | CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedOvf: MinSat); |
810 | |
811 | CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedNonSat: -3ULL << 5); |
812 | CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedNonSat: -3ULL << 13); |
813 | CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedNonSat: -3ULL << 29); |
814 | |
815 | CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedOvf: MinSat); |
816 | CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedOvf: MinSat); |
817 | CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedOvf: MinSat); |
818 | |
819 | CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MinSat); |
820 | CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0); |
821 | CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MinSat); |
822 | CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0); |
823 | |
824 | // Highly precise fraction |
825 | Val = APFloat(0.999999940395355224609375f); |
826 | CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: 0x7FULL); |
827 | CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: 0x7FFFULL); |
828 | CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: 0xFFFFFFULL << 7); |
829 | |
830 | CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedNonSat: 0xFFULL); |
831 | CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedNonSat: 0xFFFFULL); |
832 | CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedNonSat: 0xFFFFFFULL << 8); |
833 | |
834 | CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedNonSat: 0x7FULL); |
835 | CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedNonSat: 0x7FFFULL); |
836 | CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedNonSat: 0xFFFFFFULL << 7); |
837 | |
838 | CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedNonSat: 0xFFULL); |
839 | CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedNonSat: 0xFFFFULL); |
840 | CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedNonSat: 0xFFFFFFULL << 8); |
841 | |
842 | CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MaxSat); |
843 | CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0); |
844 | CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MaxSat); |
845 | CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0); |
846 | |
847 | // Integral and fraction |
848 | Val = APFloat(17.99609375f); |
849 | CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: 0x11FFULL >> 1); |
850 | CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: 0x11FFULL << 7); |
851 | CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: 0x11FFULL << 23); |
852 | |
853 | CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedNonSat: 0x11FFULL); |
854 | CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedNonSat: 0x11FFULL << 8); |
855 | CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedNonSat: 0x11FFULL << 24); |
856 | |
857 | CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedOvf: MaxSat); |
858 | CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedOvf: MaxSat); |
859 | CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedOvf: MaxSat); |
860 | |
861 | CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedOvf: MaxSat); |
862 | CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedOvf: MaxSat); |
863 | CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedOvf: MaxSat); |
864 | |
865 | CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MaxSat); |
866 | CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 1); |
867 | CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MaxSat); |
868 | CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 1 << 2); |
869 | |
870 | // Negative integral and fraction |
871 | Val = APFloat(-17.99609375f); |
872 | CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: -0x11FELL >> 1); |
873 | CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: -0x11FFULL << 7); |
874 | CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: -0x11FFULL << 23); |
875 | |
876 | CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedOvf: MinSat); |
877 | CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedOvf: MinSat); |
878 | CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedOvf: MinSat); |
879 | |
880 | CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedOvf: MinSat); |
881 | CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedOvf: MinSat); |
882 | CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedOvf: MinSat); |
883 | |
884 | CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedOvf: MinSat); |
885 | CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedOvf: MinSat); |
886 | CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedOvf: MinSat); |
887 | |
888 | CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MinSat); |
889 | CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedOvf: MinSat); |
890 | CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MinSat); |
891 | CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: -4); |
892 | |
893 | // Very large value |
894 | Val = APFloat(1.0e38f); |
895 | CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedOvf: MaxSat); |
896 | CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedOvf: MaxSat); |
897 | CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedOvf: MaxSat); |
898 | |
899 | CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedOvf: MaxSat); |
900 | CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedOvf: MaxSat); |
901 | CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedOvf: MaxSat); |
902 | |
903 | CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedOvf: MaxSat); |
904 | CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedOvf: MaxSat); |
905 | CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedOvf: MaxSat); |
906 | |
907 | CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedOvf: MaxSat); |
908 | CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedOvf: MaxSat); |
909 | CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedOvf: MaxSat); |
910 | |
911 | CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MaxSat); |
912 | CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedOvf: MaxSat); |
913 | CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MaxSat); |
914 | CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedOvf: MaxSat); |
915 | |
916 | // Very small value |
917 | Val = APFloat(1.0e-38f); |
918 | CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: 0); |
919 | CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: 0); |
920 | CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: 0); |
921 | |
922 | CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedNonSat: 0); |
923 | CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedNonSat: 0); |
924 | CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedNonSat: 0); |
925 | |
926 | CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedNonSat: 0); |
927 | CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedNonSat: 0); |
928 | CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedNonSat: 0); |
929 | |
930 | CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedNonSat: 0); |
931 | CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedNonSat: 0); |
932 | CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedNonSat: 0); |
933 | |
934 | CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedNonSat: 0); |
935 | CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0); |
936 | CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedNonSat: 0); |
937 | CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0); |
938 | |
939 | // Half conversion |
940 | Val = APFloat(0.99951171875f); |
941 | bool Ignored; |
942 | Val.convert(ToSemantics: APFloat::IEEEhalf(), RM: APFloat::rmNearestTiesToEven, losesInfo: &Ignored); |
943 | |
944 | CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: 0x7FULL); |
945 | CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: 0x7FFULL << 4); |
946 | CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: 0x7FFULL << 20); |
947 | |
948 | CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedNonSat: 0xFFULL); |
949 | CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedNonSat: 0xFFEULL << 4); |
950 | CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedNonSat: 0xFFEULL << 20); |
951 | |
952 | CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedNonSat: 0x7FULL); |
953 | CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedNonSat: 0x7FFULL << 4); |
954 | CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedNonSat: 0x7FFULL << 20); |
955 | |
956 | CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedNonSat: 0xFFULL); |
957 | CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedNonSat: 0xFFEULL << 4); |
958 | CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedNonSat: 0xFFEULL << 20); |
959 | |
960 | CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MaxSat); |
961 | CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0); |
962 | CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MaxSat); |
963 | CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0); |
964 | |
965 | Val = APFloat(0.124996185302734375); |
966 | CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedNonSat: 0x7f); |
967 | CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0); |
968 | CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedNonSat: 0x7fff); |
969 | CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0); |
970 | |
971 | Val = APFloat(-0.124996185302734375); |
972 | CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MinSat); |
973 | CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0); |
974 | CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedNonSat: -0x7fff); |
975 | CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0); |
976 | } |
977 | |
978 | void CheckFixedToFloatConversion(int64_t Val, const FixedPointSemantics &Sema, |
979 | float Result) { |
980 | APFixedPoint FXVal(Val, Sema); |
981 | APFloat APRes(Result); |
982 | ASSERT_EQ(FXVal.convertToFloat(APFloat::IEEEsingle()), APRes); |
983 | } |
984 | |
985 | void CheckFixedToHalfConversion(int64_t Val, const FixedPointSemantics &Sema, |
986 | float Result) { |
987 | APFixedPoint FXVal(Val, Sema); |
988 | APFloat APRes(Result); |
989 | bool Ignored; |
990 | APRes.convert(ToSemantics: APFloat::IEEEhalf(), RM: APFloat::rmNearestTiesToEven, losesInfo: &Ignored); |
991 | ASSERT_EQ(FXVal.convertToFloat(APFloat::IEEEhalf()), APRes); |
992 | } |
993 | |
994 | TEST(FixedPoint, FixedToFloat) { |
995 | int64_t Val = 0x1ULL; |
996 | CheckFixedToFloatConversion(Val, Sema: getSAccumSema(), Result: 0.0078125f); |
997 | CheckFixedToFloatConversion(Val, Sema: getFractSema(), Result: 0.000030517578125f); |
998 | CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: 0.000030517578125f); |
999 | CheckFixedToFloatConversion(Val, Sema: getLFractSema(), |
1000 | Result: 0.0000000004656612873077392578125f); |
1001 | |
1002 | CheckFixedToFloatConversion(Val, Sema: getUSAccumSema(), Result: 0.00390625f); |
1003 | CheckFixedToFloatConversion(Val, Sema: getUFractSema(), Result: 0.0000152587890625f); |
1004 | CheckFixedToFloatConversion(Val, Sema: getUAccumSema(), Result: 0.0000152587890625f); |
1005 | CheckFixedToFloatConversion(Val, Sema: getULFractSema(), |
1006 | Result: 0.00000000023283064365386962890625f); |
1007 | |
1008 | CheckFixedToFloatConversion(Val, Sema: getU8Neg10(), Result: 0.0009765625f); |
1009 | CheckFixedToFloatConversion(Val, Sema: getU8Pos4(), Result: 16.0f); |
1010 | CheckFixedToFloatConversion(Val, Sema: getS16Neg18(), Result: 0.000003814697265625f); |
1011 | CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 4.0f); |
1012 | |
1013 | Val = 0x7FULL; |
1014 | CheckFixedToFloatConversion(Val, Sema: getSAccumSema(), Result: 0.9921875f); |
1015 | CheckFixedToFloatConversion(Val, Sema: getFractSema(), Result: 0.003875732421875f); |
1016 | CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: 0.003875732421875f); |
1017 | CheckFixedToFloatConversion(Val, Sema: getLFractSema(), |
1018 | Result: 0.0000000591389834880828857421875f); |
1019 | |
1020 | CheckFixedToFloatConversion(Val, Sema: getUSAccumSema(), Result: 0.49609375f); |
1021 | CheckFixedToFloatConversion(Val, Sema: getUFractSema(), Result: 0.0019378662109375f); |
1022 | CheckFixedToFloatConversion(Val, Sema: getUAccumSema(), Result: 0.0019378662109375f); |
1023 | CheckFixedToFloatConversion(Val, Sema: getULFractSema(), |
1024 | Result: 0.00000002956949174404144287109375f); |
1025 | |
1026 | CheckFixedToFloatConversion(Val, Sema: getU8Neg10(), Result: 0.1240234375f); |
1027 | CheckFixedToFloatConversion(Val, Sema: getU8Pos4(), Result: 2032.0f); |
1028 | CheckFixedToFloatConversion(Val, Sema: getS16Neg18(), Result: 0.000484466552734375f); |
1029 | CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 508.0f); |
1030 | |
1031 | Val = -0x1ULL; |
1032 | CheckFixedToFloatConversion(Val, Sema: getSAccumSema(), Result: -0.0078125f); |
1033 | CheckFixedToFloatConversion(Val, Sema: getFractSema(), Result: -0.000030517578125f); |
1034 | CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: -0.000030517578125f); |
1035 | CheckFixedToFloatConversion(Val, Sema: getLFractSema(), |
1036 | Result: -0.0000000004656612873077392578125f); |
1037 | |
1038 | CheckFixedToFloatConversion(Val, Sema: getU8Neg10(), Result: 0.249023437f); |
1039 | CheckFixedToFloatConversion(Val, Sema: getU8Pos4(), Result: 4080.0f); |
1040 | CheckFixedToFloatConversion(Val, Sema: getS16Neg18(), Result: -0.000003814697265625f); |
1041 | CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: -4.0f); |
1042 | |
1043 | CheckFixedToFloatConversion(Val: -0x80ULL, Sema: getSAccumSema(), Result: -1.0f); |
1044 | CheckFixedToFloatConversion(Val: -0x8000ULL, Sema: getFractSema(), Result: -1.0f); |
1045 | CheckFixedToFloatConversion(Val: -0x8000ULL, Sema: getAccumSema(), Result: -1.0f); |
1046 | CheckFixedToFloatConversion(Val: -0x80000000ULL, Sema: getLFractSema(), Result: -1.0f); |
1047 | |
1048 | Val = 0xAFAULL; |
1049 | CheckFixedToFloatConversion(Val, Sema: getSAccumSema(), Result: 21.953125f); |
1050 | CheckFixedToFloatConversion(Val, Sema: getFractSema(), Result: 0.08575439453125f); |
1051 | CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: 0.08575439453125f); |
1052 | CheckFixedToFloatConversion(Val, Sema: getLFractSema(), |
1053 | Result: 0.000001308508217334747314453125f); |
1054 | |
1055 | CheckFixedToFloatConversion(Val, Sema: getUSAccumSema(), Result: 10.9765625f); |
1056 | CheckFixedToFloatConversion(Val, Sema: getUFractSema(), Result: 0.042877197265625f); |
1057 | CheckFixedToFloatConversion(Val, Sema: getUAccumSema(), Result: 0.042877197265625f); |
1058 | CheckFixedToFloatConversion(Val, Sema: getULFractSema(), |
1059 | Result: 0.0000006542541086673736572265625f); |
1060 | |
1061 | CheckFixedToFloatConversion(Val, Sema: getS16Neg18(), Result: 0.01071929931640625f); |
1062 | CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 11240.0f); |
1063 | |
1064 | Val = -0xAFAULL; |
1065 | CheckFixedToFloatConversion(Val, Sema: getSAccumSema(), Result: -21.953125f); |
1066 | CheckFixedToFloatConversion(Val, Sema: getFractSema(), Result: -0.08575439453125f); |
1067 | CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: -0.08575439453125f); |
1068 | CheckFixedToFloatConversion(Val, Sema: getLFractSema(), |
1069 | Result: -0.000001308508217334747314453125f); |
1070 | |
1071 | CheckFixedToFloatConversion(Val, Sema: getS16Neg18(), Result: -0.01071929931640625f); |
1072 | CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: -11240.0f); |
1073 | |
1074 | Val = 0x40000080ULL; |
1075 | CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: 32768.00390625f); |
1076 | CheckFixedToFloatConversion(Val, Sema: getLFractSema(), |
1077 | Result: 0.500000059604644775390625f); |
1078 | |
1079 | CheckFixedToFloatConversion(Val, Sema: getUAccumSema(), Result: 16384.001953125f); |
1080 | CheckFixedToFloatConversion(Val, Sema: getULFractSema(), |
1081 | Result: 0.2500000298023223876953125f); |
1082 | |
1083 | CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 4294967808.0f); |
1084 | |
1085 | Val = 0x40000040ULL; |
1086 | CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: 32768.0f); |
1087 | CheckFixedToFloatConversion(Val, Sema: getLFractSema(), Result: 0.5f); |
1088 | |
1089 | CheckFixedToFloatConversion(Val, Sema: getUAccumSema(), Result: 16384.0f); |
1090 | CheckFixedToFloatConversion(Val, Sema: getULFractSema(), Result: 0.25f); |
1091 | |
1092 | CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 4294967552.0f); |
1093 | |
1094 | Val = 0x7FF0ULL; |
1095 | CheckFixedToHalfConversion(Val, Sema: getAccumSema(), Result: 0.99951171875f); |
1096 | CheckFixedToHalfConversion(Val, Sema: getLFractSema(), Result: 0.000015251338481903076171875f); |
1097 | |
1098 | CheckFixedToHalfConversion(Val, Sema: getUAccumSema(), Result: 0.499755859375f); |
1099 | CheckFixedToHalfConversion(Val, Sema: getULFractSema(), Result: 0.0000076256692409515380859375f); |
1100 | |
1101 | CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 131008.0f); |
1102 | } |
1103 | |
1104 | void CheckAdd(const APFixedPoint &Lhs, const APFixedPoint &Rhs, |
1105 | const APFixedPoint &Res) { |
1106 | bool Overflow = false; |
1107 | APFixedPoint Result = Lhs.add(Other: Rhs, Overflow: &Overflow); |
1108 | ASSERT_FALSE(Overflow); |
1109 | ASSERT_EQ(Result.getSemantics(), Res.getSemantics()); |
1110 | ASSERT_EQ(Result, Res); |
1111 | } |
1112 | |
1113 | void CheckAddOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) { |
1114 | bool Overflow = false; |
1115 | APFixedPoint Result = Lhs.add(Other: Rhs, Overflow: &Overflow); |
1116 | ASSERT_TRUE(Overflow); |
1117 | } |
1118 | |
1119 | TEST(FixedPoint, add) { |
1120 | CheckAdd(Lhs: APFixedPoint(1, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()), |
1121 | Res: APFixedPoint(2, getS32Pos2())); |
1122 | CheckAdd(Lhs: APFixedPoint(1, getS16Neg18()), Rhs: APFixedPoint(1, getS16Neg18()), |
1123 | Res: APFixedPoint(2, getS16Neg18())); |
1124 | CheckAdd(Lhs: APFixedPoint(1, getU8Neg10()), Rhs: APFixedPoint(1, getU8Neg10()), |
1125 | Res: APFixedPoint(2, getU8Neg10())); |
1126 | CheckAdd(Lhs: APFixedPoint(1, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()), |
1127 | Res: APFixedPoint(2, getU8Pos4())); |
1128 | |
1129 | CheckAdd(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()), |
1130 | Res: APFixedPoint(12, getS32Pos2())); |
1131 | CheckAdd(Lhs: APFixedPoint(11, getS16Neg18()), Rhs: APFixedPoint(1, getS16Neg18()), |
1132 | Res: APFixedPoint(12, getS16Neg18())); |
1133 | CheckAdd(Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(1, getU8Neg10()), |
1134 | Res: APFixedPoint(12, getU8Neg10())); |
1135 | CheckAdd(Lhs: APFixedPoint(11, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()), |
1136 | Res: APFixedPoint(12, getU8Pos4())); |
1137 | |
1138 | CheckAdd(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS16Neg18()), |
1139 | Res: APFixedPoint(11534337, |
1140 | FixedPointSemantics(52, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1141 | true, false, false))); |
1142 | CheckAdd( |
1143 | Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(-9472, getS16Neg18()), |
1144 | Res: APFixedPoint(-6656, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1145 | true, false, false))); |
1146 | CheckAddOverflow( |
1147 | Lhs: APFixedPoint::getMax(Sema: getU8Neg10()), Rhs: APFixedPoint::getMax(Sema: getS16Neg18())); |
1148 | CheckAdd(Lhs: APFixedPoint::getMin(Sema: getU8Neg10()), |
1149 | Rhs: APFixedPoint::getMin(Sema: getS16Neg18()), |
1150 | Res: APFixedPoint::getMin(Sema: getS16Neg18()) |
1151 | .convert(DstSema: FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1152 | true, false, false))); |
1153 | CheckAddOverflow(Lhs: APFixedPoint::getMin(Sema: getS32Pos2()), |
1154 | Rhs: APFixedPoint::getMin(Sema: getS16Neg18())); |
1155 | } |
1156 | |
1157 | void CheckMul(const APFixedPoint &Lhs, const APFixedPoint &Rhs, |
1158 | const APFixedPoint &Res) { |
1159 | bool Overflow = false; |
1160 | APFixedPoint Result = Lhs.mul(Other: Rhs, Overflow: &Overflow); |
1161 | ASSERT_FALSE(Overflow); |
1162 | ASSERT_EQ(Result.getSemantics(), Res.getSemantics()); |
1163 | ASSERT_EQ(Result, Res); |
1164 | } |
1165 | |
1166 | void CheckMulOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) { |
1167 | bool Overflow = false; |
1168 | APFixedPoint Result = Lhs.mul(Other: Rhs, Overflow: &Overflow); |
1169 | ASSERT_TRUE(Overflow); |
1170 | } |
1171 | |
1172 | TEST(FixedPoint, mul) { |
1173 | CheckMul(Lhs: APFixedPoint(1, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()), |
1174 | Res: APFixedPoint(4, getS32Pos2())); |
1175 | CheckMul(Lhs: APFixedPoint(1, getS16Neg18()), Rhs: APFixedPoint(1, getS16Neg18()), |
1176 | Res: APFixedPoint(0, getS16Neg18())); |
1177 | CheckMul(Lhs: APFixedPoint(1, getU8Neg10()), Rhs: APFixedPoint(1, getU8Neg10()), |
1178 | Res: APFixedPoint(0, getU8Neg10())); |
1179 | CheckMul(Lhs: APFixedPoint(1, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()), |
1180 | Res: APFixedPoint(16, getU8Pos4())); |
1181 | |
1182 | CheckMul(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()), |
1183 | Res: APFixedPoint(44, getS32Pos2())); |
1184 | CheckMul(Lhs: APFixedPoint(11, getS16Neg18()), Rhs: APFixedPoint(1, getS16Neg18()), |
1185 | Res: APFixedPoint(0, getS16Neg18())); |
1186 | CheckMul(Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(1, getU8Neg10()), |
1187 | Res: APFixedPoint(0, getU8Neg10())); |
1188 | CheckMul(Lhs: APFixedPoint(11, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()), |
1189 | Res: APFixedPoint(176, getU8Pos4())); |
1190 | |
1191 | CheckMul(Lhs: APFixedPoint(512, getS16Neg18()), Rhs: APFixedPoint(512, getS16Neg18()), |
1192 | Res: APFixedPoint(1, getS16Neg18())); |
1193 | CheckMul(Lhs: APFixedPoint(32, getU8Neg10()), Rhs: APFixedPoint(32, getU8Neg10()), |
1194 | Res: APFixedPoint(1, getU8Neg10())); |
1195 | |
1196 | CheckMul(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS16Neg18()), |
1197 | Res: APFixedPoint(44, |
1198 | FixedPointSemantics(52, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1199 | true, false, false))); |
1200 | CheckMul( |
1201 | Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(-9472, getS16Neg18()), |
1202 | Res: APFixedPoint(-102, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1203 | true, false, false))); |
1204 | CheckMul( |
1205 | Lhs: APFixedPoint::getMax(Sema: getU8Neg10()), Rhs: APFixedPoint::getMax(Sema: getS16Neg18()), |
1206 | Res: APFixedPoint(8159, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1207 | true, false, false))); |
1208 | CheckMul( |
1209 | Lhs: APFixedPoint::getMin(Sema: getU8Neg10()), Rhs: APFixedPoint::getMin(Sema: getS16Neg18()), |
1210 | Res: APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1211 | true, false, false))); |
1212 | CheckMul(Lhs: APFixedPoint::getMin(Sema: getS32Pos2()), |
1213 | Rhs: APFixedPoint::getMin(Sema: getS16Neg18()), |
1214 | Res: APFixedPoint(281474976710656, |
1215 | FixedPointSemantics(52, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1216 | true, false, false))); |
1217 | CheckMulOverflow(Lhs: APFixedPoint::getMax(Sema: getS32Pos2()), Rhs: APFixedPoint::getMax(Sema: getU8Pos4())); |
1218 | CheckMulOverflow(Lhs: APFixedPoint::getMin(Sema: getS32Pos2()), Rhs: APFixedPoint::getMax(Sema: getU8Pos4())); |
1219 | } |
1220 | |
1221 | void CheckDiv(const APFixedPoint &Lhs, const APFixedPoint &Rhs, |
1222 | const APFixedPoint &Expected) { |
1223 | bool Overflow = false; |
1224 | APFixedPoint Result = Lhs.div(Other: Rhs, Overflow: &Overflow); |
1225 | ASSERT_FALSE(Overflow); |
1226 | ASSERT_EQ(Result.getSemantics(), Expected.getSemantics()); |
1227 | ASSERT_EQ(Result, Expected); |
1228 | } |
1229 | |
1230 | void CheckDivOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) { |
1231 | bool Overflow = false; |
1232 | APFixedPoint Result = Lhs.div(Other: Rhs, Overflow: &Overflow); |
1233 | ASSERT_TRUE(Overflow); |
1234 | } |
1235 | |
1236 | TEST(FixedPoint, div) { |
1237 | CheckDiv(Lhs: APFixedPoint(1, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()), |
1238 | Expected: APFixedPoint(0, getS32Pos2())); |
1239 | CheckDivOverflow(Lhs: APFixedPoint(1, getS16Neg18()), Rhs: APFixedPoint(1, getS16Neg18())); |
1240 | CheckDivOverflow(Lhs: APFixedPoint(1, getU8Neg10()), Rhs: APFixedPoint(1, getU8Neg10())); |
1241 | CheckDiv(Lhs: APFixedPoint(1, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()), |
1242 | Expected: APFixedPoint(0, getU8Pos4())); |
1243 | |
1244 | CheckDiv(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()), |
1245 | Expected: APFixedPoint(2, getS32Pos2())); |
1246 | CheckDiv(Lhs: APFixedPoint(11, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()), |
1247 | Expected: APFixedPoint(0, getU8Pos4())); |
1248 | |
1249 | CheckDiv(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS16Neg18()), |
1250 | Expected: APFixedPoint(3023656976384, |
1251 | FixedPointSemantics(52, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1252 | true, false, false))); |
1253 | CheckDiv(Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(-11264, getS16Neg18()), |
1254 | Expected: APFixedPoint::getMin(Sema: FixedPointSemantics( |
1255 | 17, FixedPointSemantics::Lsb{.LsbWeight: -18}, true, false, false))); |
1256 | CheckDiv(Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(11265, getS16Neg18()), |
1257 | Expected: APFixedPoint(0xfffa, |
1258 | FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1259 | true, false, false))); |
1260 | CheckDivOverflow(Lhs: APFixedPoint(11, getU8Neg10()), |
1261 | Rhs: APFixedPoint(11264, getS16Neg18())); |
1262 | |
1263 | CheckDivOverflow(Lhs: APFixedPoint(11, getU8Neg10()), |
1264 | Rhs: APFixedPoint(-9472, getS16Neg18())); |
1265 | CheckDivOverflow(Lhs: APFixedPoint::getMax(Sema: getU8Neg10()), |
1266 | Rhs: APFixedPoint::getMax(Sema: getS16Neg18())); |
1267 | CheckDiv( |
1268 | Lhs: APFixedPoint::getMin(Sema: getU8Neg10()), Rhs: APFixedPoint::getMin(Sema: getS16Neg18()), |
1269 | Expected: APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1270 | true, false, false))); |
1271 | CheckDiv( |
1272 | Lhs: APFixedPoint(1, getU8Neg10()), Rhs: APFixedPoint::getMin(Sema: getS16Neg18()), |
1273 | Expected: APFixedPoint(-2048, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18}, |
1274 | true, false, false))); |
1275 | } |
1276 | |
1277 | } // namespace |
1278 | |