1 //===- unittests/ADT/FixedPointTest.cpp -- fixed point number tests -----===//
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
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
;
18 using llvm::FixedPointSemantics
;
22 FixedPointSemantics
Saturated(FixedPointSemantics Sema
) {
23 Sema
.setSaturated(true);
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},
138 /*isSaturated=*/false,
139 /*hasUnsignedPadding=*/false);
142 FixedPointSemantics
getS16Neg18() {
143 return FixedPointSemantics(/*width=*/16,
144 /*lsb=*/FixedPointSemantics::Lsb
{-18},
146 /*isSaturated=*/false,
147 /*hasUnsignedPadding=*/false);
150 FixedPointSemantics
getU8Pos4() {
151 return FixedPointSemantics(/*width=*/8, /*lsb=*/FixedPointSemantics::Lsb
{4},
153 /*isSaturated=*/false,
154 /*hasUnsignedPadding=*/false);
157 FixedPointSemantics
getS32Pos2() {
158 return FixedPointSemantics(/*width=*/32, /*lsb=*/FixedPointSemantics::Lsb
{2},
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
,
245 ASSERT_EQ(ValWithFract
.getIntPart(), IntPart
);
248 APFixedPoint
JustFract(APInt(Sema
.getWidth(), FullFactPart
, Sema
.isSigned()),
250 ASSERT_EQ(JustFract
.getIntPart(), 0);
253 APFixedPoint
WholeNum(APInt(Sema
.getWidth(),
254 relativeShr(IntPart
, Sema
.getLsbWeight()),
257 ASSERT_EQ(WholeNum
.getIntPart(), IntPart
);
260 if (Sema
.isSigned()) {
261 APFixedPoint
Negative(APInt(Sema
.getWidth(),
262 relativeShr(IntPart
, Sema
.getLsbWeight()),
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
,
281 APFixedPoint
Val(Representation
, Sema
);
282 ASSERT_EQ(Val
.getIntPart().getZExtValue(), Result
) ;
285 TEST(FixedPoint
, getIntPart
) {
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);
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);
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);
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);
347 CheckIntPart(getPadUSAccumSema(), 2);
348 CheckIntPart(getPadUAccumSema(), 2);
349 CheckIntPart(getPadULAccumSema(), 2);
352 CheckIntPart(getPadUSAccumSema(), 0);
353 CheckIntPart(getPadUAccumSema(), 0);
354 CheckIntPart(getPadULAccumSema(), 0);
356 CheckIntPart(getPadUSFractSema(), 0);
357 CheckIntPart(getPadUFractSema(), 0);
358 CheckIntPart(getPadULFractSema(), 0);
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
) {
378 // With fractional part (2.5)
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()));
408 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
409 APFixedPoint(81920, Saturated(getAccumSema())));
412 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
413 APFixedPoint(640, getUSAccumSema()));
414 ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),
415 APFixedPoint(-81920, getAccumSema()));
418 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
419 APFixedPoint(320, getPadUSAccumSema()));
420 ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),
421 APFixedPoint(320, getPadUSAccumSema()));
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()));
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;
452 ScaledVal
= -ScaledVal
;
454 if (Dst
.getLsbWeight() < Src
.getLsbWeight()) {
455 ScaledVal
<<= (Src
.getLsbWeight() - Dst
.getLsbWeight());
457 ScaledVal
>>= (Dst
.getLsbWeight() - Src
.getLsbWeight());
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
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
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
,
487 int64_t NormalVal
= (OneVal
* 2) + (OneVal
/ 2); // 2.5
488 int64_t HalfVal
= (OneVal
/ 2); // 0.5
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
);
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
);
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
);
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
);
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);
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
559 void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src
,
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()),
605 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUAccumSema()),
607 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUAccumSema()),
609 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getAccumSema()),
611 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUAccumSema()),
613 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUAccumSema()),
616 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getAccumSema()),
618 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUAccumSema()),
620 CheckSaturatedConversionMax(getPadULAccumSema(),
621 Saturated(getPadUAccumSema()), 140737488355328);
623 // To SAccum min limit (-65536)
624 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getAccumSema()),
626 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUAccumSema()),
628 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUAccumSema()),
632 TEST(FixedPoint
, SAccumConversionOverflow
) {
633 // To SAccum max limit (256)
634 CheckSaturatedConversionMax(getAccumSema(), Saturated(getSAccumSema()),
636 CheckSaturatedConversionMax(getAccumSema(), Saturated(getUSAccumSema()),
638 CheckSaturatedConversionMax(getAccumSema(), Saturated(getPadUSAccumSema()),
640 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getSAccumSema()),
642 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getUSAccumSema()),
644 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getPadUSAccumSema()),
646 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getSAccumSema()),
648 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUSAccumSema()),
650 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUSAccumSema()),
652 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getSAccumSema()),
654 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUSAccumSema()),
656 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUSAccumSema()),
659 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getSAccumSema()),
661 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getUSAccumSema()),
663 CheckSaturatedConversionMax(getPadUAccumSema(),
664 Saturated(getPadUSAccumSema()), 8388608);
665 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getSAccumSema()),
667 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUSAccumSema()),
669 CheckSaturatedConversionMax(getPadULAccumSema(),
670 Saturated(getPadUSAccumSema()), 549755813888);
672 // To SAccum min limit (-256)
673 CheckSaturatedConversionMin(getAccumSema(), Saturated(getSAccumSema()),
675 CheckSaturatedConversionMin(getAccumSema(), Saturated(getUSAccumSema()),
677 CheckSaturatedConversionMin(getAccumSema(), Saturated(getPadUSAccumSema()),
679 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getSAccumSema()),
681 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUSAccumSema()),
683 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUSAccumSema()),
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
) {
733 ASSERT_EQ(APFixedPoint::getFromFloatValue(Val
, Sema
, &Ovf
).getValue(),
735 ASSERT_EQ(Ovf
, false);
737 APFixedPoint::getFromFloatValue(Val
, Saturated(Sema
), &Ovf
).getValue(),
739 ASSERT_EQ(Ovf
, false);
742 void CheckFloatToFixedConversion(APFloat
&Val
, const FixedPointSemantics
&Sema
,
743 OvfKind ExpectedOvf
) {
745 (void)APFixedPoint::getFromFloatValue(Val
, Sema
, &Ovf
);
746 ASSERT_EQ(Ovf
, true);
748 APFixedPoint::getFromFloatValue(Val
, Saturated(Sema
), &Ovf
).getValue(),
749 (ExpectedOvf
== MinSat
? APFixedPoint::getMin(Sema
)
750 : APFixedPoint::getMax(Sema
))
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()))
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()))
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
) {
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);
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
);
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);
940 Val
= APFloat(0.99951171875f
);
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
,
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
,
987 APFixedPoint
FXVal(Val
, Sema
);
988 APFloat
APRes(Result
);
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
);
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
);
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
);
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
);
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
);
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)));
1143 APFixedPoint(11, getU8Neg10()), APFixedPoint(-9472, getS16Neg18()),
1144 APFixedPoint(-6656, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1145 true, false, false)));
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()),
1198 FixedPointSemantics(52, FixedPointSemantics::Lsb
{-18},
1199 true, false, false)));
1201 APFixedPoint(11, getU8Neg10()), APFixedPoint(-9472, getS16Neg18()),
1202 APFixedPoint(-102, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1203 true, false, false)));
1205 APFixedPoint::getMax(getU8Neg10()), APFixedPoint::getMax(getS16Neg18()),
1206 APFixedPoint(8159, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1207 true, false, false)));
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()));
1268 APFixedPoint::getMin(getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),
1269 APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1270 true, false, false)));
1272 APFixedPoint(1, getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),
1273 APFixedPoint(-2048, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1274 true, false, false)));