Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / unittests / ADT / APFixedPointTest.cpp
blobecb89fbf76c8bb66a05ea80ff839c5eaf2e30610
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()),
244 Sema);
245 ASSERT_EQ(ValWithFract.getIntPart(), IntPart);
247 // Just fraction
248 APFixedPoint JustFract(APInt(Sema.getWidth(), FullFactPart, Sema.isSigned()),
249 Sema);
250 ASSERT_EQ(JustFract.getIntPart(), 0);
252 // Whole number
253 APFixedPoint WholeNum(APInt(Sema.getWidth(),
254 relativeShr(IntPart, Sema.getLsbWeight()),
255 Sema.isSigned()),
256 Sema);
257 ASSERT_EQ(WholeNum.getIntPart(), IntPart);
259 // Negative
260 if (Sema.isSigned()) {
261 APFixedPoint Negative(APInt(Sema.getWidth(),
262 relativeShr(IntPart, Sema.getLsbWeight()),
263 Sema.isSigned()),
264 Sema);
265 ASSERT_EQ(Negative.getIntPart(), IntPart);
269 void CheckIntPartMin(const FixedPointSemantics &Sema, int64_t Expected) {
270 EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMin(Sema).getIntPart(),
271 APSInt::get(Expected)) == 0);
274 void CheckIntPartMax(const FixedPointSemantics &Sema, uint64_t Expected) {
275 EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMax(Sema).getIntPart(),
276 APSInt::getUnsigned(Expected)) == 0);
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) ;
285 TEST(FixedPoint, getIntPart) {
286 // Normal values
287 CheckIntPart(getSAccumSema(), 2);
288 CheckIntPart(getAccumSema(), 2);
289 CheckIntPart(getLAccumSema(), 2);
290 CheckIntPart(getUSAccumSema(), 2);
291 CheckIntPart(getUAccumSema(), 2);
292 CheckIntPart(getULAccumSema(), 2);
293 CheckIntPart(getU8Pos4(), 32);
294 CheckIntPart(getS32Pos2(), 32);
296 // Zero
297 CheckIntPart(getSAccumSema(), 0);
298 CheckIntPart(getAccumSema(), 0);
299 CheckIntPart(getLAccumSema(), 0);
300 CheckIntPart(getUSAccumSema(), 0);
301 CheckIntPart(getUAccumSema(), 0);
302 CheckIntPart(getULAccumSema(), 0);
304 CheckIntPart(getSFractSema(), 0);
305 CheckIntPart(getFractSema(), 0);
306 CheckIntPart(getLFractSema(), 0);
307 CheckIntPart(getUSFractSema(), 0);
308 CheckIntPart(getUFractSema(), 0);
309 CheckIntPart(getULFractSema(), 0);
311 CheckIntPart(getS16Neg18(), 0);
312 CheckIntPart(getU8Neg10(), 0);
313 CheckIntPart(getU8Pos4(), 0);
314 CheckIntPart(getS32Pos2(), 0);
316 // Min
317 CheckIntPartMin(getSAccumSema(), -256);
318 CheckIntPartMin(getAccumSema(), -65536);
319 CheckIntPartMin(getLAccumSema(), -4294967296);
321 CheckIntPartMin(getSFractSema(), -1);
322 CheckIntPartMin(getFractSema(), -1);
323 CheckIntPartMin(getLFractSema(), -1);
325 CheckIntPartMin(getS32Pos2(), -8589934592);
327 // Max
328 CheckIntPartMax(getSAccumSema(), 255);
329 CheckIntPartMax(getAccumSema(), 65535);
330 CheckIntPartMax(getLAccumSema(), 4294967295);
331 CheckIntPartMax(getUSAccumSema(), 255);
332 CheckIntPartMax(getUAccumSema(), 65535);
333 CheckIntPartMax(getULAccumSema(), 4294967295);
335 CheckIntPartMax(getU8Pos4(), 255 << 4);
336 CheckIntPartMax(getS32Pos2(), 2147483647ull << 2);
338 CheckIntPartMax(getSFractSema(), 0);
339 CheckIntPartMax(getFractSema(), 0);
340 CheckIntPartMax(getLFractSema(), 0);
341 CheckIntPartMax(getUSFractSema(), 0);
342 CheckIntPartMax(getUFractSema(), 0);
343 CheckIntPartMax(getULFractSema(), 0);
345 // Padded
346 // Normal Values
347 CheckIntPart(getPadUSAccumSema(), 2);
348 CheckIntPart(getPadUAccumSema(), 2);
349 CheckIntPart(getPadULAccumSema(), 2);
351 // Zero
352 CheckIntPart(getPadUSAccumSema(), 0);
353 CheckIntPart(getPadUAccumSema(), 0);
354 CheckIntPart(getPadULAccumSema(), 0);
356 CheckIntPart(getPadUSFractSema(), 0);
357 CheckIntPart(getPadUFractSema(), 0);
358 CheckIntPart(getPadULFractSema(), 0);
360 // Max
361 CheckIntPartMax(getPadUSAccumSema(), 255);
362 CheckIntPartMax(getPadUAccumSema(), 65535);
363 CheckIntPartMax(getPadULAccumSema(), 4294967295);
365 CheckIntPartMax(getPadUSFractSema(), 0);
366 CheckIntPartMax(getPadUFractSema(), 0);
367 CheckIntPartMax(getPadULFractSema(), 0);
369 // Rounded Towards Zero
370 CheckIntPartRes(getSFractSema(), -127, 0);
371 CheckIntPartRes(getFractSema(), -32767, 0);
372 CheckIntPartRes(getLFractSema(), -2147483647, 0);
373 CheckIntPartRes(getS16Neg18(), -32768, 0);
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()));
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()));
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()));
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()));
407 // Across saturation
408 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
409 APFixedPoint(81920, Saturated(getAccumSema())));
411 // Across signs
412 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
413 APFixedPoint(640, getUSAccumSema()));
414 ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),
415 APFixedPoint(-81920, getAccumSema()));
417 // Across padding
418 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
419 APFixedPoint(320, getPadUSAccumSema()));
420 ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),
421 APFixedPoint(320, getPadUSAccumSema()));
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()));
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()));
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;
454 if (Dst.getLsbWeight() < Src.getLsbWeight()) {
455 ScaledVal <<= (Src.getLsbWeight() - Dst.getLsbWeight());
456 } else {
457 ScaledVal >>= (Dst.getLsbWeight() - Src.getLsbWeight());
460 if (IsNegative)
461 ScaledVal = -ScaledVal;
463 APFixedPoint Fixed(TestVal, Src);
464 APFixedPoint Expected(ScaledVal, Dst);
465 ASSERT_EQ(Fixed.convert(Dst), Expected);
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));
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));
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
490 // +Accums to Accums
491 CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);
492 CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);
493 CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);
494 CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);
495 CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);
496 CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);
497 CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);
498 CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);
499 CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);
501 // -Accums to Accums
502 CheckUnsaturatedConversion(Src, getSAccumSema(), -NormalVal);
503 CheckUnsaturatedConversion(Src, getAccumSema(), -NormalVal);
504 CheckUnsaturatedConversion(Src, getLAccumSema(), -NormalVal);
505 CheckSaturatedConversionMin(Src, Saturated(getUSAccumSema()), -NormalVal);
506 CheckSaturatedConversionMin(Src, Saturated(getUAccumSema()), -NormalVal);
507 CheckSaturatedConversionMin(Src, Saturated(getULAccumSema()), -NormalVal);
508 CheckSaturatedConversionMin(Src, Saturated(getPadUSAccumSema()), -NormalVal);
509 CheckSaturatedConversionMin(Src, Saturated(getPadUAccumSema()), -NormalVal);
510 CheckSaturatedConversionMin(Src, Saturated(getPadULAccumSema()), -NormalVal);
512 // +Accums to Fracts
513 CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);
514 CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);
515 CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);
516 CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);
517 CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);
518 CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);
519 CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);
520 CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);
521 CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);
523 // -Accums to Fracts
524 CheckUnsaturatedConversion(Src, getSFractSema(), -HalfVal);
525 CheckUnsaturatedConversion(Src, getFractSema(), -HalfVal);
526 CheckUnsaturatedConversion(Src, getLFractSema(), -HalfVal);
527 CheckSaturatedConversionMin(Src, Saturated(getUSFractSema()), -HalfVal);
528 CheckSaturatedConversionMin(Src, Saturated(getUFractSema()), -HalfVal);
529 CheckSaturatedConversionMin(Src, Saturated(getULFractSema()), -HalfVal);
530 CheckSaturatedConversionMin(Src, Saturated(getPadUSFractSema()), -HalfVal);
531 CheckSaturatedConversionMin(Src, Saturated(getPadUFractSema()), -HalfVal);
532 CheckSaturatedConversionMin(Src, Saturated(getPadULFractSema()), -HalfVal);
534 // 0 to Accums
535 CheckUnsaturatedConversion(Src, getSAccumSema(), 0);
536 CheckUnsaturatedConversion(Src, getAccumSema(), 0);
537 CheckUnsaturatedConversion(Src, getLAccumSema(), 0);
538 CheckUnsaturatedConversion(Src, getUSAccumSema(), 0);
539 CheckUnsaturatedConversion(Src, getUAccumSema(), 0);
540 CheckUnsaturatedConversion(Src, getULAccumSema(), 0);
541 CheckUnsaturatedConversion(Src, getPadUSAccumSema(), 0);
542 CheckUnsaturatedConversion(Src, getPadUAccumSema(), 0);
543 CheckUnsaturatedConversion(Src, getPadULAccumSema(), 0);
545 // 0 to Fracts
546 CheckUnsaturatedConversion(Src, getSFractSema(), 0);
547 CheckUnsaturatedConversion(Src, getFractSema(), 0);
548 CheckUnsaturatedConversion(Src, getLFractSema(), 0);
549 CheckUnsaturatedConversion(Src, getUSFractSema(), 0);
550 CheckUnsaturatedConversion(Src, getUFractSema(), 0);
551 CheckUnsaturatedConversion(Src, getULFractSema(), 0);
552 CheckUnsaturatedConversion(Src, getPadUSFractSema(), 0);
553 CheckUnsaturatedConversion(Src, getPadUFractSema(), 0);
554 CheckUnsaturatedConversion(Src, getPadULFractSema(), 0);
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
564 // +UAccums to Accums
565 CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);
566 CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);
567 CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);
568 CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);
569 CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);
570 CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);
571 CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);
572 CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);
573 CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);
575 // +UAccums to Fracts
576 CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);
577 CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);
578 CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);
579 CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);
580 CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);
581 CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);
582 CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);
583 CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);
584 CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);
587 TEST(FixedPoint, AccumConversions) {
588 // Normal conversions
589 CheckSignedAccumConversionsAgainstOthers(getSAccumSema(), 128);
590 CheckUnsignedAccumConversionsAgainstOthers(getUSAccumSema(), 256);
591 CheckSignedAccumConversionsAgainstOthers(getAccumSema(), 32768);
592 CheckUnsignedAccumConversionsAgainstOthers(getUAccumSema(), 65536);
593 CheckSignedAccumConversionsAgainstOthers(getLAccumSema(), 2147483648);
594 CheckUnsignedAccumConversionsAgainstOthers(getULAccumSema(), 4294967296);
596 CheckUnsignedAccumConversionsAgainstOthers(getPadUSAccumSema(), 128);
597 CheckUnsignedAccumConversionsAgainstOthers(getPadUAccumSema(), 32768);
598 CheckUnsignedAccumConversionsAgainstOthers(getPadULAccumSema(), 2147483648);
601 TEST(FixedPoint, AccumConversionOverflow) {
602 // To SAccum max limit (65536)
603 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getAccumSema()),
604 140737488355328);
605 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUAccumSema()),
606 140737488355328);
607 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUAccumSema()),
608 140737488355328);
609 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getAccumSema()),
610 281474976710656);
611 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUAccumSema()),
612 281474976710656);
613 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUAccumSema()),
614 281474976710656);
616 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getAccumSema()),
617 140737488355328);
618 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUAccumSema()),
619 140737488355328);
620 CheckSaturatedConversionMax(getPadULAccumSema(),
621 Saturated(getPadUAccumSema()), 140737488355328);
623 // To SAccum min limit (-65536)
624 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getAccumSema()),
625 -140737488355328);
626 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUAccumSema()),
627 -140737488355328);
628 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUAccumSema()),
629 -140737488355328);
632 TEST(FixedPoint, SAccumConversionOverflow) {
633 // To SAccum max limit (256)
634 CheckSaturatedConversionMax(getAccumSema(), Saturated(getSAccumSema()),
635 8388608);
636 CheckSaturatedConversionMax(getAccumSema(), Saturated(getUSAccumSema()),
637 8388608);
638 CheckSaturatedConversionMax(getAccumSema(), Saturated(getPadUSAccumSema()),
639 8388608);
640 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getSAccumSema()),
641 16777216);
642 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getUSAccumSema()),
643 16777216);
644 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getPadUSAccumSema()),
645 16777216);
646 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getSAccumSema()),
647 549755813888);
648 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUSAccumSema()),
649 549755813888);
650 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUSAccumSema()),
651 549755813888);
652 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getSAccumSema()),
653 1099511627776);
654 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUSAccumSema()),
655 1099511627776);
656 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUSAccumSema()),
657 1099511627776);
659 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getSAccumSema()),
660 8388608);
661 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getUSAccumSema()),
662 8388608);
663 CheckSaturatedConversionMax(getPadUAccumSema(),
664 Saturated(getPadUSAccumSema()), 8388608);
665 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getSAccumSema()),
666 549755813888);
667 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUSAccumSema()),
668 549755813888);
669 CheckSaturatedConversionMax(getPadULAccumSema(),
670 Saturated(getPadUSAccumSema()), 549755813888);
672 // To SAccum min limit (-256)
673 CheckSaturatedConversionMin(getAccumSema(), Saturated(getSAccumSema()),
674 -8388608);
675 CheckSaturatedConversionMin(getAccumSema(), Saturated(getUSAccumSema()),
676 -8388608);
677 CheckSaturatedConversionMin(getAccumSema(), Saturated(getPadUSAccumSema()),
678 -8388608);
679 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getSAccumSema()),
680 -549755813888);
681 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUSAccumSema()),
682 -549755813888);
683 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUSAccumSema()),
684 -549755813888);
687 TEST(FixedPoint, GetValueSignAfterConversion) {
688 APFixedPoint Fixed(255 << 7, getSAccumSema());
689 ASSERT_TRUE(Fixed.getValue().isSigned());
690 APFixedPoint UFixed = Fixed.convert(getUSAccumSema());
691 ASSERT_TRUE(UFixed.getValue().isUnsigned());
692 ASSERT_EQ(UFixed.getValue(), APSInt::getUnsigned(255 << 8).extOrTrunc(16));
695 TEST(FixedPoint, ModularWrapAround) {
696 // Positive to negative
697 APFixedPoint Val = APFixedPoint(1ULL << 7, getSAccumSema());
698 ASSERT_EQ(Val.convert(getLFractSema()).getValue(), -(1ULL << 31));
700 Val = APFixedPoint(1ULL << 23, getAccumSema());
701 ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), -(1ULL << 15));
703 Val = APFixedPoint(1ULL << 47, getLAccumSema());
704 ASSERT_EQ(Val.convert(getAccumSema()).getValue(), -(1ULL << 31));
706 // Negative to positive
707 Val = APFixedPoint(/*-1.5*/ -192, getSAccumSema());
708 ASSERT_EQ(Val.convert(getLFractSema()).getValue(), 1ULL << 30);
710 Val = APFixedPoint(-(257 << 15), getAccumSema());
711 ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), 255 << 7);
713 Val = APFixedPoint(-(65537ULL << 31), getLAccumSema());
714 ASSERT_EQ(Val.convert(getAccumSema()).getValue(), 65535 << 15);
716 // Signed to unsigned
717 Val = APFixedPoint(-(1 << 7), getSAccumSema());
718 ASSERT_EQ(Val.convert(getUSAccumSema()).getValue(), 255 << 8);
720 Val = APFixedPoint(-(1 << 15), getAccumSema());
721 ASSERT_EQ(Val.convert(getUAccumSema()).getValue(), 65535ULL << 16);
723 Val = APFixedPoint(-(1ULL << 31), getLAccumSema());
724 ASSERT_EQ(Val.convert(getULAccumSema()).getValue().getZExtValue(),
725 4294967295ULL << 32);
728 enum OvfKind { MinSat, MaxSat };
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);
742 void CheckFloatToFixedConversion(APFloat &Val, const FixedPointSemantics &Sema,
743 OvfKind ExpectedOvf) {
744 bool Ovf;
745 (void)APFixedPoint::getFromFloatValue(Val, Sema, &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);
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");
775 TEST(FixedPoint, FloatToFixed) {
776 APFloat Val(0.0f);
778 // Simple exact fraction
779 Val = APFloat(0.75f);
780 CheckFloatToFixedConversion(Val, getSAccumSema(), 3ULL << 5);
781 CheckFloatToFixedConversion(Val, getAccumSema(), 3ULL << 13);
782 CheckFloatToFixedConversion(Val, getLAccumSema(), 3ULL << 29);
784 CheckFloatToFixedConversion(Val, getUSAccumSema(), 3ULL << 6);
785 CheckFloatToFixedConversion(Val, getUAccumSema(), 3ULL << 14);
786 CheckFloatToFixedConversion(Val, getULAccumSema(), 3ULL << 30);
788 CheckFloatToFixedConversion(Val, getSFractSema(), 3ULL << 5);
789 CheckFloatToFixedConversion(Val, getFractSema(), 3ULL << 13);
790 CheckFloatToFixedConversion(Val, getLFractSema(), 3ULL << 29);
792 CheckFloatToFixedConversion(Val, getUSFractSema(), 3ULL << 6);
793 CheckFloatToFixedConversion(Val, getUFractSema(), 3ULL << 14);
794 CheckFloatToFixedConversion(Val, getULFractSema(), 3ULL << 30);
796 CheckFloatToFixedConversion(Val, getU8Neg10(), MaxSat);
797 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);
798 CheckFloatToFixedConversion(Val, getS16Neg18(), MaxSat);
799 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);
801 // Simple negative exact fraction
802 Val = APFloat(-0.75f);
803 CheckFloatToFixedConversion(Val, getSAccumSema(), -3ULL << 5);
804 CheckFloatToFixedConversion(Val, getAccumSema(), -3ULL << 13);
805 CheckFloatToFixedConversion(Val, getLAccumSema(), -3ULL << 29);
807 CheckFloatToFixedConversion(Val, getUSAccumSema(), MinSat);
808 CheckFloatToFixedConversion(Val, getUAccumSema(), MinSat);
809 CheckFloatToFixedConversion(Val, getULAccumSema(), MinSat);
811 CheckFloatToFixedConversion(Val, getSFractSema(), -3ULL << 5);
812 CheckFloatToFixedConversion(Val, getFractSema(), -3ULL << 13);
813 CheckFloatToFixedConversion(Val, getLFractSema(), -3ULL << 29);
815 CheckFloatToFixedConversion(Val, getUSFractSema(), MinSat);
816 CheckFloatToFixedConversion(Val, getUFractSema(), MinSat);
817 CheckFloatToFixedConversion(Val, getULFractSema(), MinSat);
819 CheckFloatToFixedConversion(Val, getU8Neg10(), MinSat);
820 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);
821 CheckFloatToFixedConversion(Val, getS16Neg18(), MinSat);
822 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);
824 // Highly precise fraction
825 Val = APFloat(0.999999940395355224609375f);
826 CheckFloatToFixedConversion(Val, getSAccumSema(), 0x7FULL);
827 CheckFloatToFixedConversion(Val, getAccumSema(), 0x7FFFULL);
828 CheckFloatToFixedConversion(Val, getLAccumSema(), 0xFFFFFFULL << 7);
830 CheckFloatToFixedConversion(Val, getUSAccumSema(), 0xFFULL);
831 CheckFloatToFixedConversion(Val, getUAccumSema(), 0xFFFFULL);
832 CheckFloatToFixedConversion(Val, getULAccumSema(), 0xFFFFFFULL << 8);
834 CheckFloatToFixedConversion(Val, getSFractSema(), 0x7FULL);
835 CheckFloatToFixedConversion(Val, getFractSema(), 0x7FFFULL);
836 CheckFloatToFixedConversion(Val, getLFractSema(), 0xFFFFFFULL << 7);
838 CheckFloatToFixedConversion(Val, getUSFractSema(), 0xFFULL);
839 CheckFloatToFixedConversion(Val, getUFractSema(), 0xFFFFULL);
840 CheckFloatToFixedConversion(Val, getULFractSema(), 0xFFFFFFULL << 8);
842 CheckFloatToFixedConversion(Val, getU8Neg10(), MaxSat);
843 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);
844 CheckFloatToFixedConversion(Val, getS16Neg18(), MaxSat);
845 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);
847 // Integral and fraction
848 Val = APFloat(17.99609375f);
849 CheckFloatToFixedConversion(Val, getSAccumSema(), 0x11FFULL >> 1);
850 CheckFloatToFixedConversion(Val, getAccumSema(), 0x11FFULL << 7);
851 CheckFloatToFixedConversion(Val, getLAccumSema(), 0x11FFULL << 23);
853 CheckFloatToFixedConversion(Val, getUSAccumSema(), 0x11FFULL);
854 CheckFloatToFixedConversion(Val, getUAccumSema(), 0x11FFULL << 8);
855 CheckFloatToFixedConversion(Val, getULAccumSema(), 0x11FFULL << 24);
857 CheckFloatToFixedConversion(Val, getSFractSema(), MaxSat);
858 CheckFloatToFixedConversion(Val, getFractSema(), MaxSat);
859 CheckFloatToFixedConversion(Val, getLFractSema(), MaxSat);
861 CheckFloatToFixedConversion(Val, getUSFractSema(), MaxSat);
862 CheckFloatToFixedConversion(Val, getUFractSema(), MaxSat);
863 CheckFloatToFixedConversion(Val, getULFractSema(), MaxSat);
865 CheckFloatToFixedConversion(Val, getU8Neg10(), MaxSat);
866 CheckFloatToFixedConversion(Val, getU8Pos4(), 1);
867 CheckFloatToFixedConversion(Val, getS16Neg18(), MaxSat);
868 CheckFloatToFixedConversion(Val, getS32Pos2(), 1 << 2);
870 // Negative integral and fraction
871 Val = APFloat(-17.99609375f);
872 CheckFloatToFixedConversion(Val, getSAccumSema(), -0x11FELL >> 1);
873 CheckFloatToFixedConversion(Val, getAccumSema(), -0x11FFULL << 7);
874 CheckFloatToFixedConversion(Val, getLAccumSema(), -0x11FFULL << 23);
876 CheckFloatToFixedConversion(Val, getUSAccumSema(), MinSat);
877 CheckFloatToFixedConversion(Val, getUAccumSema(), MinSat);
878 CheckFloatToFixedConversion(Val, getULAccumSema(), MinSat);
880 CheckFloatToFixedConversion(Val, getSFractSema(), MinSat);
881 CheckFloatToFixedConversion(Val, getFractSema(), MinSat);
882 CheckFloatToFixedConversion(Val, getLFractSema(), MinSat);
884 CheckFloatToFixedConversion(Val, getUSFractSema(), MinSat);
885 CheckFloatToFixedConversion(Val, getUFractSema(), MinSat);
886 CheckFloatToFixedConversion(Val, getULFractSema(), MinSat);
888 CheckFloatToFixedConversion(Val, getU8Neg10(), MinSat);
889 CheckFloatToFixedConversion(Val, getU8Pos4(), MinSat);
890 CheckFloatToFixedConversion(Val, getS16Neg18(), MinSat);
891 CheckFloatToFixedConversion(Val, getS32Pos2(), -4);
893 // Very large value
894 Val = APFloat(1.0e38f);
895 CheckFloatToFixedConversion(Val, getSAccumSema(), MaxSat);
896 CheckFloatToFixedConversion(Val, getAccumSema(), MaxSat);
897 CheckFloatToFixedConversion(Val, getLAccumSema(), MaxSat);
899 CheckFloatToFixedConversion(Val, getUSAccumSema(), MaxSat);
900 CheckFloatToFixedConversion(Val, getUAccumSema(), MaxSat);
901 CheckFloatToFixedConversion(Val, getULAccumSema(), MaxSat);
903 CheckFloatToFixedConversion(Val, getSFractSema(), MaxSat);
904 CheckFloatToFixedConversion(Val, getFractSema(), MaxSat);
905 CheckFloatToFixedConversion(Val, getLFractSema(), MaxSat);
907 CheckFloatToFixedConversion(Val, getUSFractSema(), MaxSat);
908 CheckFloatToFixedConversion(Val, getUFractSema(), MaxSat);
909 CheckFloatToFixedConversion(Val, getULFractSema(), MaxSat);
911 CheckFloatToFixedConversion(Val, getU8Neg10(), MaxSat);
912 CheckFloatToFixedConversion(Val, getU8Pos4(), MaxSat);
913 CheckFloatToFixedConversion(Val, getS16Neg18(), MaxSat);
914 CheckFloatToFixedConversion(Val, getS32Pos2(), MaxSat);
916 // Very small value
917 Val = APFloat(1.0e-38f);
918 CheckFloatToFixedConversion(Val, getSAccumSema(), 0);
919 CheckFloatToFixedConversion(Val, getAccumSema(), 0);
920 CheckFloatToFixedConversion(Val, getLAccumSema(), 0);
922 CheckFloatToFixedConversion(Val, getUSAccumSema(), 0);
923 CheckFloatToFixedConversion(Val, getUAccumSema(), 0);
924 CheckFloatToFixedConversion(Val, getULAccumSema(), 0);
926 CheckFloatToFixedConversion(Val, getSFractSema(), 0);
927 CheckFloatToFixedConversion(Val, getFractSema(), 0);
928 CheckFloatToFixedConversion(Val, getLFractSema(), 0);
930 CheckFloatToFixedConversion(Val, getUSFractSema(), 0);
931 CheckFloatToFixedConversion(Val, getUFractSema(), 0);
932 CheckFloatToFixedConversion(Val, getULFractSema(), 0);
934 CheckFloatToFixedConversion(Val, getU8Neg10(), 0);
935 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);
936 CheckFloatToFixedConversion(Val, getS16Neg18(), 0);
937 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);
939 // Half conversion
940 Val = APFloat(0.99951171875f);
941 bool Ignored;
942 Val.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);
944 CheckFloatToFixedConversion(Val, getSAccumSema(), 0x7FULL);
945 CheckFloatToFixedConversion(Val, getAccumSema(), 0x7FFULL << 4);
946 CheckFloatToFixedConversion(Val, getLAccumSema(), 0x7FFULL << 20);
948 CheckFloatToFixedConversion(Val, getUSAccumSema(), 0xFFULL);
949 CheckFloatToFixedConversion(Val, getUAccumSema(), 0xFFEULL << 4);
950 CheckFloatToFixedConversion(Val, getULAccumSema(), 0xFFEULL << 20);
952 CheckFloatToFixedConversion(Val, getSFractSema(), 0x7FULL);
953 CheckFloatToFixedConversion(Val, getFractSema(), 0x7FFULL << 4);
954 CheckFloatToFixedConversion(Val, getLFractSema(), 0x7FFULL << 20);
956 CheckFloatToFixedConversion(Val, getUSFractSema(), 0xFFULL);
957 CheckFloatToFixedConversion(Val, getUFractSema(), 0xFFEULL << 4);
958 CheckFloatToFixedConversion(Val, getULFractSema(), 0xFFEULL << 20);
960 CheckFloatToFixedConversion(Val, getU8Neg10(), MaxSat);
961 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);
962 CheckFloatToFixedConversion(Val, getS16Neg18(), MaxSat);
963 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);
965 Val = APFloat(0.124996185302734375);
966 CheckFloatToFixedConversion(Val, getU8Neg10(), 0x7f);
967 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);
968 CheckFloatToFixedConversion(Val, getS16Neg18(), 0x7fff);
969 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);
971 Val = APFloat(-0.124996185302734375);
972 CheckFloatToFixedConversion(Val, getU8Neg10(), MinSat);
973 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);
974 CheckFloatToFixedConversion(Val, getS16Neg18(), -0x7fff);
975 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);
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);
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(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);
991 ASSERT_EQ(FXVal.convertToFloat(APFloat::IEEEhalf()), APRes);
994 TEST(FixedPoint, FixedToFloat) {
995 int64_t Val = 0x1ULL;
996 CheckFixedToFloatConversion(Val, getSAccumSema(), 0.0078125f);
997 CheckFixedToFloatConversion(Val, getFractSema(), 0.000030517578125f);
998 CheckFixedToFloatConversion(Val, getAccumSema(), 0.000030517578125f);
999 CheckFixedToFloatConversion(Val, getLFractSema(),
1000 0.0000000004656612873077392578125f);
1002 CheckFixedToFloatConversion(Val, getUSAccumSema(), 0.00390625f);
1003 CheckFixedToFloatConversion(Val, getUFractSema(), 0.0000152587890625f);
1004 CheckFixedToFloatConversion(Val, getUAccumSema(), 0.0000152587890625f);
1005 CheckFixedToFloatConversion(Val, getULFractSema(),
1006 0.00000000023283064365386962890625f);
1008 CheckFixedToFloatConversion(Val, getU8Neg10(), 0.0009765625f);
1009 CheckFixedToFloatConversion(Val, getU8Pos4(), 16.0f);
1010 CheckFixedToFloatConversion(Val, getS16Neg18(), 0.000003814697265625f);
1011 CheckFixedToFloatConversion(Val, getS32Pos2(), 4.0f);
1013 Val = 0x7FULL;
1014 CheckFixedToFloatConversion(Val, getSAccumSema(), 0.9921875f);
1015 CheckFixedToFloatConversion(Val, getFractSema(), 0.003875732421875f);
1016 CheckFixedToFloatConversion(Val, getAccumSema(), 0.003875732421875f);
1017 CheckFixedToFloatConversion(Val, getLFractSema(),
1018 0.0000000591389834880828857421875f);
1020 CheckFixedToFloatConversion(Val, getUSAccumSema(), 0.49609375f);
1021 CheckFixedToFloatConversion(Val, getUFractSema(), 0.0019378662109375f);
1022 CheckFixedToFloatConversion(Val, getUAccumSema(), 0.0019378662109375f);
1023 CheckFixedToFloatConversion(Val, getULFractSema(),
1024 0.00000002956949174404144287109375f);
1026 CheckFixedToFloatConversion(Val, getU8Neg10(), 0.1240234375f);
1027 CheckFixedToFloatConversion(Val, getU8Pos4(), 2032.0f);
1028 CheckFixedToFloatConversion(Val, getS16Neg18(), 0.000484466552734375f);
1029 CheckFixedToFloatConversion(Val, getS32Pos2(), 508.0f);
1031 Val = -0x1ULL;
1032 CheckFixedToFloatConversion(Val, getSAccumSema(), -0.0078125f);
1033 CheckFixedToFloatConversion(Val, getFractSema(), -0.000030517578125f);
1034 CheckFixedToFloatConversion(Val, getAccumSema(), -0.000030517578125f);
1035 CheckFixedToFloatConversion(Val, getLFractSema(),
1036 -0.0000000004656612873077392578125f);
1038 CheckFixedToFloatConversion(Val, getU8Neg10(), 0.249023437f);
1039 CheckFixedToFloatConversion(Val, getU8Pos4(), 4080.0f);
1040 CheckFixedToFloatConversion(Val, getS16Neg18(), -0.000003814697265625f);
1041 CheckFixedToFloatConversion(Val, getS32Pos2(), -4.0f);
1043 CheckFixedToFloatConversion(-0x80ULL, getSAccumSema(), -1.0f);
1044 CheckFixedToFloatConversion(-0x8000ULL, getFractSema(), -1.0f);
1045 CheckFixedToFloatConversion(-0x8000ULL, getAccumSema(), -1.0f);
1046 CheckFixedToFloatConversion(-0x80000000ULL, getLFractSema(), -1.0f);
1048 Val = 0xAFAULL;
1049 CheckFixedToFloatConversion(Val, getSAccumSema(), 21.953125f);
1050 CheckFixedToFloatConversion(Val, getFractSema(), 0.08575439453125f);
1051 CheckFixedToFloatConversion(Val, getAccumSema(), 0.08575439453125f);
1052 CheckFixedToFloatConversion(Val, getLFractSema(),
1053 0.000001308508217334747314453125f);
1055 CheckFixedToFloatConversion(Val, getUSAccumSema(), 10.9765625f);
1056 CheckFixedToFloatConversion(Val, getUFractSema(), 0.042877197265625f);
1057 CheckFixedToFloatConversion(Val, getUAccumSema(), 0.042877197265625f);
1058 CheckFixedToFloatConversion(Val, getULFractSema(),
1059 0.0000006542541086673736572265625f);
1061 CheckFixedToFloatConversion(Val, getS16Neg18(), 0.01071929931640625f);
1062 CheckFixedToFloatConversion(Val, getS32Pos2(), 11240.0f);
1064 Val = -0xAFAULL;
1065 CheckFixedToFloatConversion(Val, getSAccumSema(), -21.953125f);
1066 CheckFixedToFloatConversion(Val, getFractSema(), -0.08575439453125f);
1067 CheckFixedToFloatConversion(Val, getAccumSema(), -0.08575439453125f);
1068 CheckFixedToFloatConversion(Val, getLFractSema(),
1069 -0.000001308508217334747314453125f);
1071 CheckFixedToFloatConversion(Val, getS16Neg18(), -0.01071929931640625f);
1072 CheckFixedToFloatConversion(Val, getS32Pos2(), -11240.0f);
1074 Val = 0x40000080ULL;
1075 CheckFixedToFloatConversion(Val, getAccumSema(), 32768.00390625f);
1076 CheckFixedToFloatConversion(Val, getLFractSema(),
1077 0.500000059604644775390625f);
1079 CheckFixedToFloatConversion(Val, getUAccumSema(), 16384.001953125f);
1080 CheckFixedToFloatConversion(Val, getULFractSema(),
1081 0.2500000298023223876953125f);
1083 CheckFixedToFloatConversion(Val, getS32Pos2(), 4294967808.0f);
1085 Val = 0x40000040ULL;
1086 CheckFixedToFloatConversion(Val, getAccumSema(), 32768.0f);
1087 CheckFixedToFloatConversion(Val, getLFractSema(), 0.5f);
1089 CheckFixedToFloatConversion(Val, getUAccumSema(), 16384.0f);
1090 CheckFixedToFloatConversion(Val, getULFractSema(), 0.25f);
1092 CheckFixedToFloatConversion(Val, getS32Pos2(), 4294967552.0f);
1094 Val = 0x7FF0ULL;
1095 CheckFixedToHalfConversion(Val, getAccumSema(), 0.99951171875f);
1096 CheckFixedToHalfConversion(Val, getLFractSema(), 0.000015251338481903076171875f);
1098 CheckFixedToHalfConversion(Val, getUAccumSema(), 0.499755859375f);
1099 CheckFixedToHalfConversion(Val, getULFractSema(), 0.0000076256692409515380859375f);
1101 CheckFixedToFloatConversion(Val, getS32Pos2(), 131008.0f);
1104 void CheckAdd(const APFixedPoint &Lhs, const APFixedPoint &Rhs,
1105 const APFixedPoint &Res) {
1106 bool Overflow = false;
1107 APFixedPoint Result = Lhs.add(Rhs, &Overflow);
1108 ASSERT_FALSE(Overflow);
1109 ASSERT_EQ(Result.getSemantics(), Res.getSemantics());
1110 ASSERT_EQ(Result, Res);
1113 void CheckAddOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) {
1114 bool Overflow = false;
1115 APFixedPoint Result = Lhs.add(Rhs, &Overflow);
1116 ASSERT_TRUE(Overflow);
1119 TEST(FixedPoint, add) {
1120 CheckAdd(APFixedPoint(1, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1121 APFixedPoint(2, getS32Pos2()));
1122 CheckAdd(APFixedPoint(1, getS16Neg18()), APFixedPoint(1, getS16Neg18()),
1123 APFixedPoint(2, getS16Neg18()));
1124 CheckAdd(APFixedPoint(1, getU8Neg10()), APFixedPoint(1, getU8Neg10()),
1125 APFixedPoint(2, getU8Neg10()));
1126 CheckAdd(APFixedPoint(1, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1127 APFixedPoint(2, getU8Pos4()));
1129 CheckAdd(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1130 APFixedPoint(12, getS32Pos2()));
1131 CheckAdd(APFixedPoint(11, getS16Neg18()), APFixedPoint(1, getS16Neg18()),
1132 APFixedPoint(12, getS16Neg18()));
1133 CheckAdd(APFixedPoint(11, getU8Neg10()), APFixedPoint(1, getU8Neg10()),
1134 APFixedPoint(12, getU8Neg10()));
1135 CheckAdd(APFixedPoint(11, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1136 APFixedPoint(12, getU8Pos4()));
1138 CheckAdd(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS16Neg18()),
1139 APFixedPoint(11534337,
1140 FixedPointSemantics(52, FixedPointSemantics::Lsb{-18},
1141 true, false, false)));
1142 CheckAdd(
1143 APFixedPoint(11, getU8Neg10()), APFixedPoint(-9472, getS16Neg18()),
1144 APFixedPoint(-6656, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},
1145 true, false, false)));
1146 CheckAddOverflow(
1147 APFixedPoint::getMax(getU8Neg10()), APFixedPoint::getMax(getS16Neg18()));
1148 CheckAdd(APFixedPoint::getMin(getU8Neg10()),
1149 APFixedPoint::getMin(getS16Neg18()),
1150 APFixedPoint::getMin(getS16Neg18())
1151 .convert(FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},
1152 true, false, false)));
1153 CheckAddOverflow(APFixedPoint::getMin(getS32Pos2()),
1154 APFixedPoint::getMin(getS16Neg18()));
1157 void CheckMul(const APFixedPoint &Lhs, const APFixedPoint &Rhs,
1158 const APFixedPoint &Res) {
1159 bool Overflow = false;
1160 APFixedPoint Result = Lhs.mul(Rhs, &Overflow);
1161 ASSERT_FALSE(Overflow);
1162 ASSERT_EQ(Result.getSemantics(), Res.getSemantics());
1163 ASSERT_EQ(Result, Res);
1166 void CheckMulOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) {
1167 bool Overflow = false;
1168 APFixedPoint Result = Lhs.mul(Rhs, &Overflow);
1169 ASSERT_TRUE(Overflow);
1172 TEST(FixedPoint, mul) {
1173 CheckMul(APFixedPoint(1, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1174 APFixedPoint(4, getS32Pos2()));
1175 CheckMul(APFixedPoint(1, getS16Neg18()), APFixedPoint(1, getS16Neg18()),
1176 APFixedPoint(0, getS16Neg18()));
1177 CheckMul(APFixedPoint(1, getU8Neg10()), APFixedPoint(1, getU8Neg10()),
1178 APFixedPoint(0, getU8Neg10()));
1179 CheckMul(APFixedPoint(1, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1180 APFixedPoint(16, getU8Pos4()));
1182 CheckMul(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1183 APFixedPoint(44, getS32Pos2()));
1184 CheckMul(APFixedPoint(11, getS16Neg18()), APFixedPoint(1, getS16Neg18()),
1185 APFixedPoint(0, getS16Neg18()));
1186 CheckMul(APFixedPoint(11, getU8Neg10()), APFixedPoint(1, getU8Neg10()),
1187 APFixedPoint(0, getU8Neg10()));
1188 CheckMul(APFixedPoint(11, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1189 APFixedPoint(176, getU8Pos4()));
1191 CheckMul(APFixedPoint(512, getS16Neg18()), APFixedPoint(512, getS16Neg18()),
1192 APFixedPoint(1, getS16Neg18()));
1193 CheckMul(APFixedPoint(32, getU8Neg10()), APFixedPoint(32, getU8Neg10()),
1194 APFixedPoint(1, getU8Neg10()));
1196 CheckMul(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS16Neg18()),
1197 APFixedPoint(44,
1198 FixedPointSemantics(52, FixedPointSemantics::Lsb{-18},
1199 true, false, false)));
1200 CheckMul(
1201 APFixedPoint(11, getU8Neg10()), APFixedPoint(-9472, getS16Neg18()),
1202 APFixedPoint(-102, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},
1203 true, false, false)));
1204 CheckMul(
1205 APFixedPoint::getMax(getU8Neg10()), APFixedPoint::getMax(getS16Neg18()),
1206 APFixedPoint(8159, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},
1207 true, false, false)));
1208 CheckMul(
1209 APFixedPoint::getMin(getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),
1210 APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},
1211 true, false, false)));
1212 CheckMul(APFixedPoint::getMin(getS32Pos2()),
1213 APFixedPoint::getMin(getS16Neg18()),
1214 APFixedPoint(281474976710656,
1215 FixedPointSemantics(52, FixedPointSemantics::Lsb{-18},
1216 true, false, false)));
1217 CheckMulOverflow(APFixedPoint::getMax(getS32Pos2()), APFixedPoint::getMax(getU8Pos4()));
1218 CheckMulOverflow(APFixedPoint::getMin(getS32Pos2()), APFixedPoint::getMax(getU8Pos4()));
1221 void CheckDiv(const APFixedPoint &Lhs, const APFixedPoint &Rhs,
1222 const APFixedPoint &Expected) {
1223 bool Overflow = false;
1224 APFixedPoint Result = Lhs.div(Rhs, &Overflow);
1225 ASSERT_FALSE(Overflow);
1226 ASSERT_EQ(Result.getSemantics(), Expected.getSemantics());
1227 ASSERT_EQ(Result, Expected);
1230 void CheckDivOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) {
1231 bool Overflow = false;
1232 APFixedPoint Result = Lhs.div(Rhs, &Overflow);
1233 ASSERT_TRUE(Overflow);
1236 TEST(FixedPoint, div) {
1237 CheckDiv(APFixedPoint(1, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1238 APFixedPoint(0, getS32Pos2()));
1239 CheckDivOverflow(APFixedPoint(1, getS16Neg18()), APFixedPoint(1, getS16Neg18()));
1240 CheckDivOverflow(APFixedPoint(1, getU8Neg10()), APFixedPoint(1, getU8Neg10()));
1241 CheckDiv(APFixedPoint(1, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1242 APFixedPoint(0, getU8Pos4()));
1244 CheckDiv(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1245 APFixedPoint(2, getS32Pos2()));
1246 CheckDiv(APFixedPoint(11, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1247 APFixedPoint(0, getU8Pos4()));
1249 CheckDiv(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS16Neg18()),
1250 APFixedPoint(3023656976384,
1251 FixedPointSemantics(52, FixedPointSemantics::Lsb{-18},
1252 true, false, false)));
1253 CheckDiv(APFixedPoint(11, getU8Neg10()), APFixedPoint(-11264, getS16Neg18()),
1254 APFixedPoint::getMin(FixedPointSemantics(
1255 17, FixedPointSemantics::Lsb{-18}, true, false, false)));
1256 CheckDiv(APFixedPoint(11, getU8Neg10()), APFixedPoint(11265, getS16Neg18()),
1257 APFixedPoint(0xfffa,
1258 FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},
1259 true, false, false)));
1260 CheckDivOverflow(APFixedPoint(11, getU8Neg10()),
1261 APFixedPoint(11264, getS16Neg18()));
1263 CheckDivOverflow(APFixedPoint(11, getU8Neg10()),
1264 APFixedPoint(-9472, getS16Neg18()));
1265 CheckDivOverflow(APFixedPoint::getMax(getU8Neg10()),
1266 APFixedPoint::getMax(getS16Neg18()));
1267 CheckDiv(
1268 APFixedPoint::getMin(getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),
1269 APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},
1270 true, false, false)));
1271 CheckDiv(
1272 APFixedPoint(1, getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),
1273 APFixedPoint(-2048, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},
1274 true, false, false)));
1277 } // namespace