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