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
,
243 Sema
.isSigned(), /*implicitTrunc=*/true),
245 ASSERT_EQ(ValWithFract
.getIntPart(), IntPart
);
248 APFixedPoint
JustFract(APInt(Sema
.getWidth(), FullFactPart
, Sema
.isSigned(),
249 /*implicitTrunc=*/true),
251 ASSERT_EQ(JustFract
.getIntPart(), 0);
254 APFixedPoint
WholeNum(APInt(Sema
.getWidth(),
255 relativeShr(IntPart
, Sema
.getLsbWeight()),
256 Sema
.isSigned(), /*implicitTrunc=*/true),
258 ASSERT_EQ(WholeNum
.getIntPart(), IntPart
);
261 if (Sema
.isSigned()) {
262 APFixedPoint
Negative(APInt(Sema
.getWidth(),
263 relativeShr(IntPart
, Sema
.getLsbWeight()),
264 Sema
.isSigned(), /*implicitTrunc=*/true),
266 ASSERT_EQ(Negative
.getIntPart(), IntPart
);
270 void CheckIntPartMin(const FixedPointSemantics
&Sema
, int64_t Expected
) {
271 EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMin(Sema
).getIntPart(),
272 APSInt::get(Expected
)) == 0);
275 void CheckIntPartMax(const FixedPointSemantics
&Sema
, uint64_t Expected
) {
276 EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMax(Sema
).getIntPart(),
277 APSInt::getUnsigned(Expected
)) == 0);
280 void CheckIntPartRes(const FixedPointSemantics
&Sema
, int64_t Representation
,
282 APFixedPoint
Val(Representation
, Sema
);
283 ASSERT_EQ(Val
.getIntPart().getZExtValue(), Result
) ;
286 TEST(FixedPoint
, getIntPart
) {
288 CheckIntPart(getSAccumSema(), 2);
289 CheckIntPart(getAccumSema(), 2);
290 CheckIntPart(getLAccumSema(), 2);
291 CheckIntPart(getUSAccumSema(), 2);
292 CheckIntPart(getUAccumSema(), 2);
293 CheckIntPart(getULAccumSema(), 2);
294 CheckIntPart(getU8Pos4(), 32);
295 CheckIntPart(getS32Pos2(), 32);
298 CheckIntPart(getSAccumSema(), 0);
299 CheckIntPart(getAccumSema(), 0);
300 CheckIntPart(getLAccumSema(), 0);
301 CheckIntPart(getUSAccumSema(), 0);
302 CheckIntPart(getUAccumSema(), 0);
303 CheckIntPart(getULAccumSema(), 0);
305 CheckIntPart(getSFractSema(), 0);
306 CheckIntPart(getFractSema(), 0);
307 CheckIntPart(getLFractSema(), 0);
308 CheckIntPart(getUSFractSema(), 0);
309 CheckIntPart(getUFractSema(), 0);
310 CheckIntPart(getULFractSema(), 0);
312 CheckIntPart(getS16Neg18(), 0);
313 CheckIntPart(getU8Neg10(), 0);
314 CheckIntPart(getU8Pos4(), 0);
315 CheckIntPart(getS32Pos2(), 0);
318 CheckIntPartMin(getSAccumSema(), -256);
319 CheckIntPartMin(getAccumSema(), -65536);
320 CheckIntPartMin(getLAccumSema(), -4294967296);
322 CheckIntPartMin(getSFractSema(), -1);
323 CheckIntPartMin(getFractSema(), -1);
324 CheckIntPartMin(getLFractSema(), -1);
326 CheckIntPartMin(getS32Pos2(), -8589934592);
329 CheckIntPartMax(getSAccumSema(), 255);
330 CheckIntPartMax(getAccumSema(), 65535);
331 CheckIntPartMax(getLAccumSema(), 4294967295);
332 CheckIntPartMax(getUSAccumSema(), 255);
333 CheckIntPartMax(getUAccumSema(), 65535);
334 CheckIntPartMax(getULAccumSema(), 4294967295);
336 CheckIntPartMax(getU8Pos4(), 255 << 4);
337 CheckIntPartMax(getS32Pos2(), 2147483647ull << 2);
339 CheckIntPartMax(getSFractSema(), 0);
340 CheckIntPartMax(getFractSema(), 0);
341 CheckIntPartMax(getLFractSema(), 0);
342 CheckIntPartMax(getUSFractSema(), 0);
343 CheckIntPartMax(getUFractSema(), 0);
344 CheckIntPartMax(getULFractSema(), 0);
348 CheckIntPart(getPadUSAccumSema(), 2);
349 CheckIntPart(getPadUAccumSema(), 2);
350 CheckIntPart(getPadULAccumSema(), 2);
353 CheckIntPart(getPadUSAccumSema(), 0);
354 CheckIntPart(getPadUAccumSema(), 0);
355 CheckIntPart(getPadULAccumSema(), 0);
357 CheckIntPart(getPadUSFractSema(), 0);
358 CheckIntPart(getPadUFractSema(), 0);
359 CheckIntPart(getPadULFractSema(), 0);
362 CheckIntPartMax(getPadUSAccumSema(), 255);
363 CheckIntPartMax(getPadUAccumSema(), 65535);
364 CheckIntPartMax(getPadULAccumSema(), 4294967295);
366 CheckIntPartMax(getPadUSFractSema(), 0);
367 CheckIntPartMax(getPadUFractSema(), 0);
368 CheckIntPartMax(getPadULFractSema(), 0);
370 // Rounded Towards Zero
371 CheckIntPartRes(getSFractSema(), -127, 0);
372 CheckIntPartRes(getFractSema(), -32767, 0);
373 CheckIntPartRes(getLFractSema(), -2147483647, 0);
374 CheckIntPartRes(getS16Neg18(), -32768, 0);
377 TEST(FixedPoint
, compare
) {
379 // With fractional part (2.5)
381 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
382 APFixedPoint(81920, getAccumSema()));
383 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
384 APFixedPoint(5368709120, getLAccumSema()));
385 ASSERT_EQ(APFixedPoint(0, getSAccumSema()), APFixedPoint(0, getLAccumSema()));
387 ASSERT_EQ(APFixedPoint(0, getS16Neg18()), APFixedPoint(0, getU8Neg10()));
388 ASSERT_EQ(APFixedPoint(256, getS16Neg18()), APFixedPoint(1, getU8Neg10()));
389 ASSERT_EQ(APFixedPoint(32512, getS16Neg18()),
390 APFixedPoint(127, getU8Neg10()));
391 ASSERT_EQ(APFixedPoint(4, getS32Pos2()), APFixedPoint(1, getU8Pos4()));
392 ASSERT_EQ(APFixedPoint(1020, getS32Pos2()), APFixedPoint(255, getU8Pos4()));
394 // Across types (0.5)
395 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
396 APFixedPoint(64, getSFractSema()));
397 ASSERT_EQ(APFixedPoint(16384, getAccumSema()),
398 APFixedPoint(16384, getFractSema()));
399 ASSERT_EQ(APFixedPoint(1073741824, getLAccumSema()),
400 APFixedPoint(1073741824, getLFractSema()));
402 // Across widths and types (0.5)
403 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
404 APFixedPoint(16384, getFractSema()));
405 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
406 APFixedPoint(1073741824, getLFractSema()));
409 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
410 APFixedPoint(81920, Saturated(getAccumSema())));
413 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
414 APFixedPoint(640, getUSAccumSema()));
415 ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),
416 APFixedPoint(-81920, getAccumSema()));
419 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
420 APFixedPoint(320, getPadUSAccumSema()));
421 ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),
422 APFixedPoint(320, getPadUSAccumSema()));
425 ASSERT_LT(APFixedPoint(-1, getSAccumSema()), APFixedPoint(0, getAccumSema()));
426 ASSERT_LT(APFixedPoint(-1, getSAccumSema()),
427 APFixedPoint(0, getUAccumSema()));
428 ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getAccumSema()));
429 ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getUAccumSema()));
430 ASSERT_LT(APFixedPoint(0, getUSAccumSema()), APFixedPoint(1, getAccumSema()));
431 ASSERT_LT(APFixedPoint(0, getUSAccumSema()),
432 APFixedPoint(1, getUAccumSema()));
433 ASSERT_LT(APFixedPoint(65280, getS16Neg18()),
434 APFixedPoint(255, getU8Neg10()));
437 ASSERT_GT(APFixedPoint(0, getAccumSema()), APFixedPoint(-1, getSAccumSema()));
438 ASSERT_GT(APFixedPoint(0, getUAccumSema()),
439 APFixedPoint(-1, getSAccumSema()));
440 ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getSAccumSema()));
441 ASSERT_GT(APFixedPoint(1, getUAccumSema()), APFixedPoint(0, getSAccumSema()));
442 ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getUSAccumSema()));
443 ASSERT_GT(APFixedPoint(1, getUAccumSema()),
444 APFixedPoint(0, getUSAccumSema()));
447 // Check that a fixed point value in one sema is the same in another sema
448 void CheckUnsaturatedConversion(FixedPointSemantics Src
,
449 FixedPointSemantics Dst
, int64_t TestVal
) {
450 int64_t ScaledVal
= TestVal
;
451 bool IsNegative
= ScaledVal
< 0;
453 ScaledVal
= -ScaledVal
;
455 if (Dst
.getLsbWeight() < Src
.getLsbWeight()) {
456 ScaledVal
<<= (Src
.getLsbWeight() - Dst
.getLsbWeight());
458 ScaledVal
>>= (Dst
.getLsbWeight() - Src
.getLsbWeight());
462 ScaledVal
= -ScaledVal
;
464 APFixedPoint
Fixed(TestVal
, Src
);
465 APFixedPoint
Expected(ScaledVal
, Dst
);
466 ASSERT_EQ(Fixed
.convert(Dst
), Expected
);
469 // Check the value in a given fixed point sema overflows to the saturated min
471 void CheckSaturatedConversionMin(FixedPointSemantics Src
,
472 FixedPointSemantics Dst
, int64_t TestVal
) {
473 APFixedPoint
Fixed(TestVal
, Src
);
474 ASSERT_EQ(Fixed
.convert(Dst
), APFixedPoint::getMin(Dst
));
477 // Check the value in a given fixed point sema overflows to the saturated max
479 void CheckSaturatedConversionMax(FixedPointSemantics Src
,
480 FixedPointSemantics Dst
, int64_t TestVal
) {
481 APFixedPoint
Fixed(TestVal
, Src
);
482 ASSERT_EQ(Fixed
.convert(Dst
), APFixedPoint::getMax(Dst
));
485 // Check one signed _Accum sema converted to other sema for different values.
486 void CheckSignedAccumConversionsAgainstOthers(FixedPointSemantics Src
,
488 int64_t NormalVal
= (OneVal
* 2) + (OneVal
/ 2); // 2.5
489 int64_t HalfVal
= (OneVal
/ 2); // 0.5
492 CheckUnsaturatedConversion(Src
, getSAccumSema(), NormalVal
);
493 CheckUnsaturatedConversion(Src
, getAccumSema(), NormalVal
);
494 CheckUnsaturatedConversion(Src
, getLAccumSema(), NormalVal
);
495 CheckUnsaturatedConversion(Src
, getUSAccumSema(), NormalVal
);
496 CheckUnsaturatedConversion(Src
, getUAccumSema(), NormalVal
);
497 CheckUnsaturatedConversion(Src
, getULAccumSema(), NormalVal
);
498 CheckUnsaturatedConversion(Src
, getPadUSAccumSema(), NormalVal
);
499 CheckUnsaturatedConversion(Src
, getPadUAccumSema(), NormalVal
);
500 CheckUnsaturatedConversion(Src
, getPadULAccumSema(), NormalVal
);
503 CheckUnsaturatedConversion(Src
, getSAccumSema(), -NormalVal
);
504 CheckUnsaturatedConversion(Src
, getAccumSema(), -NormalVal
);
505 CheckUnsaturatedConversion(Src
, getLAccumSema(), -NormalVal
);
506 CheckSaturatedConversionMin(Src
, Saturated(getUSAccumSema()), -NormalVal
);
507 CheckSaturatedConversionMin(Src
, Saturated(getUAccumSema()), -NormalVal
);
508 CheckSaturatedConversionMin(Src
, Saturated(getULAccumSema()), -NormalVal
);
509 CheckSaturatedConversionMin(Src
, Saturated(getPadUSAccumSema()), -NormalVal
);
510 CheckSaturatedConversionMin(Src
, Saturated(getPadUAccumSema()), -NormalVal
);
511 CheckSaturatedConversionMin(Src
, Saturated(getPadULAccumSema()), -NormalVal
);
514 CheckUnsaturatedConversion(Src
, getSFractSema(), HalfVal
);
515 CheckUnsaturatedConversion(Src
, getFractSema(), HalfVal
);
516 CheckUnsaturatedConversion(Src
, getLFractSema(), HalfVal
);
517 CheckUnsaturatedConversion(Src
, getUSFractSema(), HalfVal
);
518 CheckUnsaturatedConversion(Src
, getUFractSema(), HalfVal
);
519 CheckUnsaturatedConversion(Src
, getULFractSema(), HalfVal
);
520 CheckUnsaturatedConversion(Src
, getPadUSFractSema(), HalfVal
);
521 CheckUnsaturatedConversion(Src
, getPadUFractSema(), HalfVal
);
522 CheckUnsaturatedConversion(Src
, getPadULFractSema(), HalfVal
);
525 CheckUnsaturatedConversion(Src
, getSFractSema(), -HalfVal
);
526 CheckUnsaturatedConversion(Src
, getFractSema(), -HalfVal
);
527 CheckUnsaturatedConversion(Src
, getLFractSema(), -HalfVal
);
528 CheckSaturatedConversionMin(Src
, Saturated(getUSFractSema()), -HalfVal
);
529 CheckSaturatedConversionMin(Src
, Saturated(getUFractSema()), -HalfVal
);
530 CheckSaturatedConversionMin(Src
, Saturated(getULFractSema()), -HalfVal
);
531 CheckSaturatedConversionMin(Src
, Saturated(getPadUSFractSema()), -HalfVal
);
532 CheckSaturatedConversionMin(Src
, Saturated(getPadUFractSema()), -HalfVal
);
533 CheckSaturatedConversionMin(Src
, Saturated(getPadULFractSema()), -HalfVal
);
536 CheckUnsaturatedConversion(Src
, getSAccumSema(), 0);
537 CheckUnsaturatedConversion(Src
, getAccumSema(), 0);
538 CheckUnsaturatedConversion(Src
, getLAccumSema(), 0);
539 CheckUnsaturatedConversion(Src
, getUSAccumSema(), 0);
540 CheckUnsaturatedConversion(Src
, getUAccumSema(), 0);
541 CheckUnsaturatedConversion(Src
, getULAccumSema(), 0);
542 CheckUnsaturatedConversion(Src
, getPadUSAccumSema(), 0);
543 CheckUnsaturatedConversion(Src
, getPadUAccumSema(), 0);
544 CheckUnsaturatedConversion(Src
, getPadULAccumSema(), 0);
547 CheckUnsaturatedConversion(Src
, getSFractSema(), 0);
548 CheckUnsaturatedConversion(Src
, getFractSema(), 0);
549 CheckUnsaturatedConversion(Src
, getLFractSema(), 0);
550 CheckUnsaturatedConversion(Src
, getUSFractSema(), 0);
551 CheckUnsaturatedConversion(Src
, getUFractSema(), 0);
552 CheckUnsaturatedConversion(Src
, getULFractSema(), 0);
553 CheckUnsaturatedConversion(Src
, getPadUSFractSema(), 0);
554 CheckUnsaturatedConversion(Src
, getPadUFractSema(), 0);
555 CheckUnsaturatedConversion(Src
, getPadULFractSema(), 0);
558 // Check one unsigned _Accum sema converted to other sema for different
560 void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src
,
562 int64_t NormalVal
= (OneVal
* 2) + (OneVal
/ 2); // 2.5
563 int64_t HalfVal
= (OneVal
/ 2); // 0.5
565 // +UAccums to Accums
566 CheckUnsaturatedConversion(Src
, getSAccumSema(), NormalVal
);
567 CheckUnsaturatedConversion(Src
, getAccumSema(), NormalVal
);
568 CheckUnsaturatedConversion(Src
, getLAccumSema(), NormalVal
);
569 CheckUnsaturatedConversion(Src
, getUSAccumSema(), NormalVal
);
570 CheckUnsaturatedConversion(Src
, getUAccumSema(), NormalVal
);
571 CheckUnsaturatedConversion(Src
, getULAccumSema(), NormalVal
);
572 CheckUnsaturatedConversion(Src
, getPadUSAccumSema(), NormalVal
);
573 CheckUnsaturatedConversion(Src
, getPadUAccumSema(), NormalVal
);
574 CheckUnsaturatedConversion(Src
, getPadULAccumSema(), NormalVal
);
576 // +UAccums to Fracts
577 CheckUnsaturatedConversion(Src
, getSFractSema(), HalfVal
);
578 CheckUnsaturatedConversion(Src
, getFractSema(), HalfVal
);
579 CheckUnsaturatedConversion(Src
, getLFractSema(), HalfVal
);
580 CheckUnsaturatedConversion(Src
, getUSFractSema(), HalfVal
);
581 CheckUnsaturatedConversion(Src
, getUFractSema(), HalfVal
);
582 CheckUnsaturatedConversion(Src
, getULFractSema(), HalfVal
);
583 CheckUnsaturatedConversion(Src
, getPadUSFractSema(), HalfVal
);
584 CheckUnsaturatedConversion(Src
, getPadUFractSema(), HalfVal
);
585 CheckUnsaturatedConversion(Src
, getPadULFractSema(), HalfVal
);
588 TEST(FixedPoint
, AccumConversions
) {
589 // Normal conversions
590 CheckSignedAccumConversionsAgainstOthers(getSAccumSema(), 128);
591 CheckUnsignedAccumConversionsAgainstOthers(getUSAccumSema(), 256);
592 CheckSignedAccumConversionsAgainstOthers(getAccumSema(), 32768);
593 CheckUnsignedAccumConversionsAgainstOthers(getUAccumSema(), 65536);
594 CheckSignedAccumConversionsAgainstOthers(getLAccumSema(), 2147483648);
595 CheckUnsignedAccumConversionsAgainstOthers(getULAccumSema(), 4294967296);
597 CheckUnsignedAccumConversionsAgainstOthers(getPadUSAccumSema(), 128);
598 CheckUnsignedAccumConversionsAgainstOthers(getPadUAccumSema(), 32768);
599 CheckUnsignedAccumConversionsAgainstOthers(getPadULAccumSema(), 2147483648);
602 TEST(FixedPoint
, AccumConversionOverflow
) {
603 // To SAccum max limit (65536)
604 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getAccumSema()),
606 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUAccumSema()),
608 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUAccumSema()),
610 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getAccumSema()),
612 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUAccumSema()),
614 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUAccumSema()),
617 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getAccumSema()),
619 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUAccumSema()),
621 CheckSaturatedConversionMax(getPadULAccumSema(),
622 Saturated(getPadUAccumSema()), 140737488355328);
624 // To SAccum min limit (-65536)
625 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getAccumSema()),
627 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUAccumSema()),
629 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUAccumSema()),
633 TEST(FixedPoint
, SAccumConversionOverflow
) {
634 // To SAccum max limit (256)
635 CheckSaturatedConversionMax(getAccumSema(), Saturated(getSAccumSema()),
637 CheckSaturatedConversionMax(getAccumSema(), Saturated(getUSAccumSema()),
639 CheckSaturatedConversionMax(getAccumSema(), Saturated(getPadUSAccumSema()),
641 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getSAccumSema()),
643 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getUSAccumSema()),
645 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getPadUSAccumSema()),
647 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getSAccumSema()),
649 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUSAccumSema()),
651 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUSAccumSema()),
653 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getSAccumSema()),
655 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUSAccumSema()),
657 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUSAccumSema()),
660 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getSAccumSema()),
662 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getUSAccumSema()),
664 CheckSaturatedConversionMax(getPadUAccumSema(),
665 Saturated(getPadUSAccumSema()), 8388608);
666 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getSAccumSema()),
668 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUSAccumSema()),
670 CheckSaturatedConversionMax(getPadULAccumSema(),
671 Saturated(getPadUSAccumSema()), 549755813888);
673 // To SAccum min limit (-256)
674 CheckSaturatedConversionMin(getAccumSema(), Saturated(getSAccumSema()),
676 CheckSaturatedConversionMin(getAccumSema(), Saturated(getUSAccumSema()),
678 CheckSaturatedConversionMin(getAccumSema(), Saturated(getPadUSAccumSema()),
680 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getSAccumSema()),
682 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUSAccumSema()),
684 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUSAccumSema()),
688 TEST(FixedPoint
, GetValueSignAfterConversion
) {
689 APFixedPoint
Fixed(255 << 7, getSAccumSema());
690 ASSERT_TRUE(Fixed
.getValue().isSigned());
691 APFixedPoint UFixed
= Fixed
.convert(getUSAccumSema());
692 ASSERT_TRUE(UFixed
.getValue().isUnsigned());
693 ASSERT_EQ(UFixed
.getValue(), APSInt::getUnsigned(255 << 8).extOrTrunc(16));
696 TEST(FixedPoint
, ModularWrapAround
) {
697 // Positive to negative
698 APFixedPoint Val
= APFixedPoint(1ULL << 7, getSAccumSema());
699 ASSERT_EQ(Val
.convert(getLFractSema()).getValue(), -(1ULL << 31));
701 Val
= APFixedPoint(1ULL << 23, getAccumSema());
702 ASSERT_EQ(Val
.convert(getSAccumSema()).getValue(), -(1ULL << 15));
704 Val
= APFixedPoint(1ULL << 47, getLAccumSema());
705 ASSERT_EQ(Val
.convert(getAccumSema()).getValue(), -(1ULL << 31));
707 // Negative to positive
708 Val
= APFixedPoint(/*-1.5*/ -192, getSAccumSema());
709 ASSERT_EQ(Val
.convert(getLFractSema()).getValue(), 1ULL << 30);
711 Val
= APFixedPoint(-(257 << 15), getAccumSema());
712 ASSERT_EQ(Val
.convert(getSAccumSema()).getValue(), 255 << 7);
714 Val
= APFixedPoint(-(65537ULL << 31), getLAccumSema());
715 ASSERT_EQ(Val
.convert(getAccumSema()).getValue(), 65535 << 15);
717 // Signed to unsigned
718 Val
= APFixedPoint(-(1 << 7), getSAccumSema());
719 ASSERT_EQ(Val
.convert(getUSAccumSema()).getValue(), 255 << 8);
721 Val
= APFixedPoint(-(1 << 15), getAccumSema());
722 ASSERT_EQ(Val
.convert(getUAccumSema()).getValue(), 65535ULL << 16);
724 Val
= APFixedPoint(-(1ULL << 31), getLAccumSema());
725 ASSERT_EQ(Val
.convert(getULAccumSema()).getValue().getZExtValue(),
726 4294967295ULL << 32);
729 enum OvfKind
{ MinSat
, MaxSat
};
731 void CheckFloatToFixedConversion(APFloat
&Val
, const FixedPointSemantics
&Sema
,
732 int64_t ExpectedNonSat
) {
734 ASSERT_EQ(APFixedPoint::getFromFloatValue(Val
, Sema
, &Ovf
).getValue(),
736 ASSERT_EQ(Ovf
, false);
738 APFixedPoint::getFromFloatValue(Val
, Saturated(Sema
), &Ovf
).getValue(),
740 ASSERT_EQ(Ovf
, false);
743 void CheckFloatToFixedConversion(APFloat
&Val
, const FixedPointSemantics
&Sema
,
744 OvfKind ExpectedOvf
) {
746 (void)APFixedPoint::getFromFloatValue(Val
, Sema
, &Ovf
);
747 ASSERT_EQ(Ovf
, true);
749 APFixedPoint::getFromFloatValue(Val
, Saturated(Sema
), &Ovf
).getValue(),
750 (ExpectedOvf
== MinSat
? APFixedPoint::getMin(Sema
)
751 : APFixedPoint::getMax(Sema
))
753 ASSERT_EQ(Ovf
, false);
756 TEST(FixedPoint
, toString
) {
757 ASSERT_EQ(APFixedPoint::getMax(getS16Neg18()).toString(),
758 "0.124996185302734375");
759 ASSERT_EQ(APFixedPoint::getMin(getS16Neg18())
760 .add(APFixedPoint(1, getS16Neg18()))
762 "-0.124996185302734375");
763 ASSERT_EQ(APFixedPoint::getMin(getS16Neg18()).toString(), "-0.125");
764 ASSERT_EQ(APFixedPoint::getMax(getU8Neg10()).toString(), "0.2490234375");
765 ASSERT_EQ(APFixedPoint::getMin(getU8Neg10()).toString(), "0.0");
766 ASSERT_EQ(APFixedPoint::getMax(getS32Pos2()).toString(), "8589934588.0");
767 ASSERT_EQ(APFixedPoint::getMin(getS32Pos2())
768 .add(APFixedPoint(1, getS32Pos2()))
771 ASSERT_EQ(APFixedPoint::getMin(getS32Pos2()).toString(), "-8589934592.0");
772 ASSERT_EQ(APFixedPoint::getMax(getU8Pos4()).toString(), "4080.0");
773 ASSERT_EQ(APFixedPoint::getMin(getU8Pos4()).toString(), "0.0");
776 TEST(FixedPoint
, FloatToFixed
) {
779 // Simple exact fraction
780 Val
= APFloat(0.75f
);
781 CheckFloatToFixedConversion(Val
, getSAccumSema(), 3ULL << 5);
782 CheckFloatToFixedConversion(Val
, getAccumSema(), 3ULL << 13);
783 CheckFloatToFixedConversion(Val
, getLAccumSema(), 3ULL << 29);
785 CheckFloatToFixedConversion(Val
, getUSAccumSema(), 3ULL << 6);
786 CheckFloatToFixedConversion(Val
, getUAccumSema(), 3ULL << 14);
787 CheckFloatToFixedConversion(Val
, getULAccumSema(), 3ULL << 30);
789 CheckFloatToFixedConversion(Val
, getSFractSema(), 3ULL << 5);
790 CheckFloatToFixedConversion(Val
, getFractSema(), 3ULL << 13);
791 CheckFloatToFixedConversion(Val
, getLFractSema(), 3ULL << 29);
793 CheckFloatToFixedConversion(Val
, getUSFractSema(), 3ULL << 6);
794 CheckFloatToFixedConversion(Val
, getUFractSema(), 3ULL << 14);
795 CheckFloatToFixedConversion(Val
, getULFractSema(), 3ULL << 30);
797 CheckFloatToFixedConversion(Val
, getU8Neg10(), MaxSat
);
798 CheckFloatToFixedConversion(Val
, getU8Pos4(), 0);
799 CheckFloatToFixedConversion(Val
, getS16Neg18(), MaxSat
);
800 CheckFloatToFixedConversion(Val
, getS32Pos2(), 0);
802 // Simple negative exact fraction
803 Val
= APFloat(-0.75f
);
804 CheckFloatToFixedConversion(Val
, getSAccumSema(), -3ULL << 5);
805 CheckFloatToFixedConversion(Val
, getAccumSema(), -3ULL << 13);
806 CheckFloatToFixedConversion(Val
, getLAccumSema(), -3ULL << 29);
808 CheckFloatToFixedConversion(Val
, getUSAccumSema(), MinSat
);
809 CheckFloatToFixedConversion(Val
, getUAccumSema(), MinSat
);
810 CheckFloatToFixedConversion(Val
, getULAccumSema(), MinSat
);
812 CheckFloatToFixedConversion(Val
, getSFractSema(), -3ULL << 5);
813 CheckFloatToFixedConversion(Val
, getFractSema(), -3ULL << 13);
814 CheckFloatToFixedConversion(Val
, getLFractSema(), -3ULL << 29);
816 CheckFloatToFixedConversion(Val
, getUSFractSema(), MinSat
);
817 CheckFloatToFixedConversion(Val
, getUFractSema(), MinSat
);
818 CheckFloatToFixedConversion(Val
, getULFractSema(), MinSat
);
820 CheckFloatToFixedConversion(Val
, getU8Neg10(), MinSat
);
821 CheckFloatToFixedConversion(Val
, getU8Pos4(), 0);
822 CheckFloatToFixedConversion(Val
, getS16Neg18(), MinSat
);
823 CheckFloatToFixedConversion(Val
, getS32Pos2(), 0);
825 // Highly precise fraction
826 Val
= APFloat(0.999999940395355224609375f
);
827 CheckFloatToFixedConversion(Val
, getSAccumSema(), 0x7FULL
);
828 CheckFloatToFixedConversion(Val
, getAccumSema(), 0x7FFFULL
);
829 CheckFloatToFixedConversion(Val
, getLAccumSema(), 0xFFFFFFULL
<< 7);
831 CheckFloatToFixedConversion(Val
, getUSAccumSema(), 0xFFULL
);
832 CheckFloatToFixedConversion(Val
, getUAccumSema(), 0xFFFFULL
);
833 CheckFloatToFixedConversion(Val
, getULAccumSema(), 0xFFFFFFULL
<< 8);
835 CheckFloatToFixedConversion(Val
, getSFractSema(), 0x7FULL
);
836 CheckFloatToFixedConversion(Val
, getFractSema(), 0x7FFFULL
);
837 CheckFloatToFixedConversion(Val
, getLFractSema(), 0xFFFFFFULL
<< 7);
839 CheckFloatToFixedConversion(Val
, getUSFractSema(), 0xFFULL
);
840 CheckFloatToFixedConversion(Val
, getUFractSema(), 0xFFFFULL
);
841 CheckFloatToFixedConversion(Val
, getULFractSema(), 0xFFFFFFULL
<< 8);
843 CheckFloatToFixedConversion(Val
, getU8Neg10(), MaxSat
);
844 CheckFloatToFixedConversion(Val
, getU8Pos4(), 0);
845 CheckFloatToFixedConversion(Val
, getS16Neg18(), MaxSat
);
846 CheckFloatToFixedConversion(Val
, getS32Pos2(), 0);
848 // Integral and fraction
849 Val
= APFloat(17.99609375f
);
850 CheckFloatToFixedConversion(Val
, getSAccumSema(), 0x11FFULL
>> 1);
851 CheckFloatToFixedConversion(Val
, getAccumSema(), 0x11FFULL
<< 7);
852 CheckFloatToFixedConversion(Val
, getLAccumSema(), 0x11FFULL
<< 23);
854 CheckFloatToFixedConversion(Val
, getUSAccumSema(), 0x11FFULL
);
855 CheckFloatToFixedConversion(Val
, getUAccumSema(), 0x11FFULL
<< 8);
856 CheckFloatToFixedConversion(Val
, getULAccumSema(), 0x11FFULL
<< 24);
858 CheckFloatToFixedConversion(Val
, getSFractSema(), MaxSat
);
859 CheckFloatToFixedConversion(Val
, getFractSema(), MaxSat
);
860 CheckFloatToFixedConversion(Val
, getLFractSema(), MaxSat
);
862 CheckFloatToFixedConversion(Val
, getUSFractSema(), MaxSat
);
863 CheckFloatToFixedConversion(Val
, getUFractSema(), MaxSat
);
864 CheckFloatToFixedConversion(Val
, getULFractSema(), MaxSat
);
866 CheckFloatToFixedConversion(Val
, getU8Neg10(), MaxSat
);
867 CheckFloatToFixedConversion(Val
, getU8Pos4(), 1);
868 CheckFloatToFixedConversion(Val
, getS16Neg18(), MaxSat
);
869 CheckFloatToFixedConversion(Val
, getS32Pos2(), 1 << 2);
871 // Negative integral and fraction
872 Val
= APFloat(-17.99609375f
);
873 CheckFloatToFixedConversion(Val
, getSAccumSema(), -0x11FELL
>> 1);
874 CheckFloatToFixedConversion(Val
, getAccumSema(), -0x11FFULL
<< 7);
875 CheckFloatToFixedConversion(Val
, getLAccumSema(), -0x11FFULL
<< 23);
877 CheckFloatToFixedConversion(Val
, getUSAccumSema(), MinSat
);
878 CheckFloatToFixedConversion(Val
, getUAccumSema(), MinSat
);
879 CheckFloatToFixedConversion(Val
, getULAccumSema(), MinSat
);
881 CheckFloatToFixedConversion(Val
, getSFractSema(), MinSat
);
882 CheckFloatToFixedConversion(Val
, getFractSema(), MinSat
);
883 CheckFloatToFixedConversion(Val
, getLFractSema(), MinSat
);
885 CheckFloatToFixedConversion(Val
, getUSFractSema(), MinSat
);
886 CheckFloatToFixedConversion(Val
, getUFractSema(), MinSat
);
887 CheckFloatToFixedConversion(Val
, getULFractSema(), MinSat
);
889 CheckFloatToFixedConversion(Val
, getU8Neg10(), MinSat
);
890 CheckFloatToFixedConversion(Val
, getU8Pos4(), MinSat
);
891 CheckFloatToFixedConversion(Val
, getS16Neg18(), MinSat
);
892 CheckFloatToFixedConversion(Val
, getS32Pos2(), -4);
895 Val
= APFloat(1.0e38f
);
896 CheckFloatToFixedConversion(Val
, getSAccumSema(), MaxSat
);
897 CheckFloatToFixedConversion(Val
, getAccumSema(), MaxSat
);
898 CheckFloatToFixedConversion(Val
, getLAccumSema(), MaxSat
);
900 CheckFloatToFixedConversion(Val
, getUSAccumSema(), MaxSat
);
901 CheckFloatToFixedConversion(Val
, getUAccumSema(), MaxSat
);
902 CheckFloatToFixedConversion(Val
, getULAccumSema(), MaxSat
);
904 CheckFloatToFixedConversion(Val
, getSFractSema(), MaxSat
);
905 CheckFloatToFixedConversion(Val
, getFractSema(), MaxSat
);
906 CheckFloatToFixedConversion(Val
, getLFractSema(), MaxSat
);
908 CheckFloatToFixedConversion(Val
, getUSFractSema(), MaxSat
);
909 CheckFloatToFixedConversion(Val
, getUFractSema(), MaxSat
);
910 CheckFloatToFixedConversion(Val
, getULFractSema(), MaxSat
);
912 CheckFloatToFixedConversion(Val
, getU8Neg10(), MaxSat
);
913 CheckFloatToFixedConversion(Val
, getU8Pos4(), MaxSat
);
914 CheckFloatToFixedConversion(Val
, getS16Neg18(), MaxSat
);
915 CheckFloatToFixedConversion(Val
, getS32Pos2(), MaxSat
);
918 Val
= APFloat(1.0e-38f
);
919 CheckFloatToFixedConversion(Val
, getSAccumSema(), 0);
920 CheckFloatToFixedConversion(Val
, getAccumSema(), 0);
921 CheckFloatToFixedConversion(Val
, getLAccumSema(), 0);
923 CheckFloatToFixedConversion(Val
, getUSAccumSema(), 0);
924 CheckFloatToFixedConversion(Val
, getUAccumSema(), 0);
925 CheckFloatToFixedConversion(Val
, getULAccumSema(), 0);
927 CheckFloatToFixedConversion(Val
, getSFractSema(), 0);
928 CheckFloatToFixedConversion(Val
, getFractSema(), 0);
929 CheckFloatToFixedConversion(Val
, getLFractSema(), 0);
931 CheckFloatToFixedConversion(Val
, getUSFractSema(), 0);
932 CheckFloatToFixedConversion(Val
, getUFractSema(), 0);
933 CheckFloatToFixedConversion(Val
, getULFractSema(), 0);
935 CheckFloatToFixedConversion(Val
, getU8Neg10(), 0);
936 CheckFloatToFixedConversion(Val
, getU8Pos4(), 0);
937 CheckFloatToFixedConversion(Val
, getS16Neg18(), 0);
938 CheckFloatToFixedConversion(Val
, getS32Pos2(), 0);
941 Val
= APFloat(0.99951171875f
);
943 Val
.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven
, &Ignored
);
945 CheckFloatToFixedConversion(Val
, getSAccumSema(), 0x7FULL
);
946 CheckFloatToFixedConversion(Val
, getAccumSema(), 0x7FFULL
<< 4);
947 CheckFloatToFixedConversion(Val
, getLAccumSema(), 0x7FFULL
<< 20);
949 CheckFloatToFixedConversion(Val
, getUSAccumSema(), 0xFFULL
);
950 CheckFloatToFixedConversion(Val
, getUAccumSema(), 0xFFEULL
<< 4);
951 CheckFloatToFixedConversion(Val
, getULAccumSema(), 0xFFEULL
<< 20);
953 CheckFloatToFixedConversion(Val
, getSFractSema(), 0x7FULL
);
954 CheckFloatToFixedConversion(Val
, getFractSema(), 0x7FFULL
<< 4);
955 CheckFloatToFixedConversion(Val
, getLFractSema(), 0x7FFULL
<< 20);
957 CheckFloatToFixedConversion(Val
, getUSFractSema(), 0xFFULL
);
958 CheckFloatToFixedConversion(Val
, getUFractSema(), 0xFFEULL
<< 4);
959 CheckFloatToFixedConversion(Val
, getULFractSema(), 0xFFEULL
<< 20);
961 CheckFloatToFixedConversion(Val
, getU8Neg10(), MaxSat
);
962 CheckFloatToFixedConversion(Val
, getU8Pos4(), 0);
963 CheckFloatToFixedConversion(Val
, getS16Neg18(), MaxSat
);
964 CheckFloatToFixedConversion(Val
, getS32Pos2(), 0);
966 Val
= APFloat(0.124996185302734375);
967 CheckFloatToFixedConversion(Val
, getU8Neg10(), 0x7f);
968 CheckFloatToFixedConversion(Val
, getU8Pos4(), 0);
969 CheckFloatToFixedConversion(Val
, getS16Neg18(), 0x7fff);
970 CheckFloatToFixedConversion(Val
, getS32Pos2(), 0);
972 Val
= APFloat(-0.124996185302734375);
973 CheckFloatToFixedConversion(Val
, getU8Neg10(), MinSat
);
974 CheckFloatToFixedConversion(Val
, getU8Pos4(), 0);
975 CheckFloatToFixedConversion(Val
, getS16Neg18(), -0x7fff);
976 CheckFloatToFixedConversion(Val
, getS32Pos2(), 0);
979 void CheckFixedToFloatConversion(int64_t Val
, const FixedPointSemantics
&Sema
,
981 APFixedPoint
FXVal(Val
, Sema
);
982 APFloat
APRes(Result
);
983 ASSERT_EQ(FXVal
.convertToFloat(APFloat::IEEEsingle()), APRes
);
986 void CheckFixedToHalfConversion(int64_t Val
, const FixedPointSemantics
&Sema
,
988 APFixedPoint
FXVal(Val
, Sema
);
989 APFloat
APRes(Result
);
991 APRes
.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven
, &Ignored
);
992 ASSERT_EQ(FXVal
.convertToFloat(APFloat::IEEEhalf()), APRes
);
995 TEST(FixedPoint
, FixedToFloat
) {
996 int64_t Val
= 0x1ULL
;
997 CheckFixedToFloatConversion(Val
, getSAccumSema(), 0.0078125f
);
998 CheckFixedToFloatConversion(Val
, getFractSema(), 0.000030517578125f
);
999 CheckFixedToFloatConversion(Val
, getAccumSema(), 0.000030517578125f
);
1000 CheckFixedToFloatConversion(Val
, getLFractSema(),
1001 0.0000000004656612873077392578125f
);
1003 CheckFixedToFloatConversion(Val
, getUSAccumSema(), 0.00390625f
);
1004 CheckFixedToFloatConversion(Val
, getUFractSema(), 0.0000152587890625f
);
1005 CheckFixedToFloatConversion(Val
, getUAccumSema(), 0.0000152587890625f
);
1006 CheckFixedToFloatConversion(Val
, getULFractSema(),
1007 0.00000000023283064365386962890625f
);
1009 CheckFixedToFloatConversion(Val
, getU8Neg10(), 0.0009765625f
);
1010 CheckFixedToFloatConversion(Val
, getU8Pos4(), 16.0f
);
1011 CheckFixedToFloatConversion(Val
, getS16Neg18(), 0.000003814697265625f
);
1012 CheckFixedToFloatConversion(Val
, getS32Pos2(), 4.0f
);
1015 CheckFixedToFloatConversion(Val
, getSAccumSema(), 0.9921875f
);
1016 CheckFixedToFloatConversion(Val
, getFractSema(), 0.003875732421875f
);
1017 CheckFixedToFloatConversion(Val
, getAccumSema(), 0.003875732421875f
);
1018 CheckFixedToFloatConversion(Val
, getLFractSema(),
1019 0.0000000591389834880828857421875f
);
1021 CheckFixedToFloatConversion(Val
, getUSAccumSema(), 0.49609375f
);
1022 CheckFixedToFloatConversion(Val
, getUFractSema(), 0.0019378662109375f
);
1023 CheckFixedToFloatConversion(Val
, getUAccumSema(), 0.0019378662109375f
);
1024 CheckFixedToFloatConversion(Val
, getULFractSema(),
1025 0.00000002956949174404144287109375f
);
1027 CheckFixedToFloatConversion(Val
, getU8Neg10(), 0.1240234375f
);
1028 CheckFixedToFloatConversion(Val
, getU8Pos4(), 2032.0f
);
1029 CheckFixedToFloatConversion(Val
, getS16Neg18(), 0.000484466552734375f
);
1030 CheckFixedToFloatConversion(Val
, getS32Pos2(), 508.0f
);
1033 CheckFixedToFloatConversion(Val
, getSAccumSema(), -0.0078125f
);
1034 CheckFixedToFloatConversion(Val
, getFractSema(), -0.000030517578125f
);
1035 CheckFixedToFloatConversion(Val
, getAccumSema(), -0.000030517578125f
);
1036 CheckFixedToFloatConversion(Val
, getLFractSema(),
1037 -0.0000000004656612873077392578125f
);
1039 CheckFixedToFloatConversion(Val
, getU8Neg10(), 0.249023437f
);
1040 CheckFixedToFloatConversion(Val
, getU8Pos4(), 4080.0f
);
1041 CheckFixedToFloatConversion(Val
, getS16Neg18(), -0.000003814697265625f
);
1042 CheckFixedToFloatConversion(Val
, getS32Pos2(), -4.0f
);
1044 CheckFixedToFloatConversion(-0x80ULL
, getSAccumSema(), -1.0f
);
1045 CheckFixedToFloatConversion(-0x8000ULL
, getFractSema(), -1.0f
);
1046 CheckFixedToFloatConversion(-0x8000ULL
, getAccumSema(), -1.0f
);
1047 CheckFixedToFloatConversion(-0x80000000ULL
, getLFractSema(), -1.0f
);
1050 CheckFixedToFloatConversion(Val
, getSAccumSema(), 21.953125f
);
1051 CheckFixedToFloatConversion(Val
, getFractSema(), 0.08575439453125f
);
1052 CheckFixedToFloatConversion(Val
, getAccumSema(), 0.08575439453125f
);
1053 CheckFixedToFloatConversion(Val
, getLFractSema(),
1054 0.000001308508217334747314453125f
);
1056 CheckFixedToFloatConversion(Val
, getUSAccumSema(), 10.9765625f
);
1057 CheckFixedToFloatConversion(Val
, getUFractSema(), 0.042877197265625f
);
1058 CheckFixedToFloatConversion(Val
, getUAccumSema(), 0.042877197265625f
);
1059 CheckFixedToFloatConversion(Val
, getULFractSema(),
1060 0.0000006542541086673736572265625f
);
1062 CheckFixedToFloatConversion(Val
, getS16Neg18(), 0.01071929931640625f
);
1063 CheckFixedToFloatConversion(Val
, getS32Pos2(), 11240.0f
);
1066 CheckFixedToFloatConversion(Val
, getSAccumSema(), -21.953125f
);
1067 CheckFixedToFloatConversion(Val
, getFractSema(), -0.08575439453125f
);
1068 CheckFixedToFloatConversion(Val
, getAccumSema(), -0.08575439453125f
);
1069 CheckFixedToFloatConversion(Val
, getLFractSema(),
1070 -0.000001308508217334747314453125f
);
1072 CheckFixedToFloatConversion(Val
, getS16Neg18(), -0.01071929931640625f
);
1073 CheckFixedToFloatConversion(Val
, getS32Pos2(), -11240.0f
);
1075 Val
= 0x40000080ULL
;
1076 CheckFixedToFloatConversion(Val
, getAccumSema(), 32768.00390625f
);
1077 CheckFixedToFloatConversion(Val
, getLFractSema(),
1078 0.500000059604644775390625f
);
1080 CheckFixedToFloatConversion(Val
, getUAccumSema(), 16384.001953125f
);
1081 CheckFixedToFloatConversion(Val
, getULFractSema(),
1082 0.2500000298023223876953125f
);
1084 CheckFixedToFloatConversion(Val
, getS32Pos2(), 4294967808.0f
);
1086 Val
= 0x40000040ULL
;
1087 CheckFixedToFloatConversion(Val
, getAccumSema(), 32768.0f
);
1088 CheckFixedToFloatConversion(Val
, getLFractSema(), 0.5f
);
1090 CheckFixedToFloatConversion(Val
, getUAccumSema(), 16384.0f
);
1091 CheckFixedToFloatConversion(Val
, getULFractSema(), 0.25f
);
1093 CheckFixedToFloatConversion(Val
, getS32Pos2(), 4294967552.0f
);
1096 CheckFixedToHalfConversion(Val
, getAccumSema(), 0.99951171875f
);
1097 CheckFixedToHalfConversion(Val
, getLFractSema(), 0.000015251338481903076171875f
);
1099 CheckFixedToHalfConversion(Val
, getUAccumSema(), 0.499755859375f
);
1100 CheckFixedToHalfConversion(Val
, getULFractSema(), 0.0000076256692409515380859375f
);
1102 CheckFixedToFloatConversion(Val
, getS32Pos2(), 131008.0f
);
1105 void CheckAdd(const APFixedPoint
&Lhs
, const APFixedPoint
&Rhs
,
1106 const APFixedPoint
&Res
) {
1107 bool Overflow
= false;
1108 APFixedPoint Result
= Lhs
.add(Rhs
, &Overflow
);
1109 ASSERT_FALSE(Overflow
);
1110 ASSERT_EQ(Result
.getSemantics(), Res
.getSemantics());
1111 ASSERT_EQ(Result
, Res
);
1114 void CheckAddOverflow(const APFixedPoint
&Lhs
, const APFixedPoint
&Rhs
) {
1115 bool Overflow
= false;
1116 APFixedPoint Result
= Lhs
.add(Rhs
, &Overflow
);
1117 ASSERT_TRUE(Overflow
);
1120 TEST(FixedPoint
, add
) {
1121 CheckAdd(APFixedPoint(1, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1122 APFixedPoint(2, getS32Pos2()));
1123 CheckAdd(APFixedPoint(1, getS16Neg18()), APFixedPoint(1, getS16Neg18()),
1124 APFixedPoint(2, getS16Neg18()));
1125 CheckAdd(APFixedPoint(1, getU8Neg10()), APFixedPoint(1, getU8Neg10()),
1126 APFixedPoint(2, getU8Neg10()));
1127 CheckAdd(APFixedPoint(1, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1128 APFixedPoint(2, getU8Pos4()));
1130 CheckAdd(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1131 APFixedPoint(12, getS32Pos2()));
1132 CheckAdd(APFixedPoint(11, getS16Neg18()), APFixedPoint(1, getS16Neg18()),
1133 APFixedPoint(12, getS16Neg18()));
1134 CheckAdd(APFixedPoint(11, getU8Neg10()), APFixedPoint(1, getU8Neg10()),
1135 APFixedPoint(12, getU8Neg10()));
1136 CheckAdd(APFixedPoint(11, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1137 APFixedPoint(12, getU8Pos4()));
1139 CheckAdd(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS16Neg18()),
1140 APFixedPoint(11534337,
1141 FixedPointSemantics(52, FixedPointSemantics::Lsb
{-18},
1142 true, false, false)));
1144 APFixedPoint(11, getU8Neg10()), APFixedPoint(-9472, getS16Neg18()),
1145 APFixedPoint(-6656, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1146 true, false, false)));
1148 APFixedPoint::getMax(getU8Neg10()), APFixedPoint::getMax(getS16Neg18()));
1149 CheckAdd(APFixedPoint::getMin(getU8Neg10()),
1150 APFixedPoint::getMin(getS16Neg18()),
1151 APFixedPoint::getMin(getS16Neg18())
1152 .convert(FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1153 true, false, false)));
1154 CheckAddOverflow(APFixedPoint::getMin(getS32Pos2()),
1155 APFixedPoint::getMin(getS16Neg18()));
1158 void CheckMul(const APFixedPoint
&Lhs
, const APFixedPoint
&Rhs
,
1159 const APFixedPoint
&Res
) {
1160 bool Overflow
= false;
1161 APFixedPoint Result
= Lhs
.mul(Rhs
, &Overflow
);
1162 ASSERT_FALSE(Overflow
);
1163 ASSERT_EQ(Result
.getSemantics(), Res
.getSemantics());
1164 ASSERT_EQ(Result
, Res
);
1167 void CheckMulOverflow(const APFixedPoint
&Lhs
, const APFixedPoint
&Rhs
) {
1168 bool Overflow
= false;
1169 APFixedPoint Result
= Lhs
.mul(Rhs
, &Overflow
);
1170 ASSERT_TRUE(Overflow
);
1173 TEST(FixedPoint
, mul
) {
1174 CheckMul(APFixedPoint(1, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1175 APFixedPoint(4, getS32Pos2()));
1176 CheckMul(APFixedPoint(1, getS16Neg18()), APFixedPoint(1, getS16Neg18()),
1177 APFixedPoint(0, getS16Neg18()));
1178 CheckMul(APFixedPoint(1, getU8Neg10()), APFixedPoint(1, getU8Neg10()),
1179 APFixedPoint(0, getU8Neg10()));
1180 CheckMul(APFixedPoint(1, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1181 APFixedPoint(16, getU8Pos4()));
1183 CheckMul(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1184 APFixedPoint(44, getS32Pos2()));
1185 CheckMul(APFixedPoint(11, getS16Neg18()), APFixedPoint(1, getS16Neg18()),
1186 APFixedPoint(0, getS16Neg18()));
1187 CheckMul(APFixedPoint(11, getU8Neg10()), APFixedPoint(1, getU8Neg10()),
1188 APFixedPoint(0, getU8Neg10()));
1189 CheckMul(APFixedPoint(11, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1190 APFixedPoint(176, getU8Pos4()));
1192 CheckMul(APFixedPoint(512, getS16Neg18()), APFixedPoint(512, getS16Neg18()),
1193 APFixedPoint(1, getS16Neg18()));
1194 CheckMul(APFixedPoint(32, getU8Neg10()), APFixedPoint(32, getU8Neg10()),
1195 APFixedPoint(1, getU8Neg10()));
1197 CheckMul(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS16Neg18()),
1199 FixedPointSemantics(52, FixedPointSemantics::Lsb
{-18},
1200 true, false, false)));
1202 APFixedPoint(11, getU8Neg10()), APFixedPoint(-9472, getS16Neg18()),
1203 APFixedPoint(-102, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1204 true, false, false)));
1206 APFixedPoint::getMax(getU8Neg10()), APFixedPoint::getMax(getS16Neg18()),
1207 APFixedPoint(8159, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1208 true, false, false)));
1210 APFixedPoint::getMin(getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),
1211 APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1212 true, false, false)));
1213 CheckMul(APFixedPoint::getMin(getS32Pos2()),
1214 APFixedPoint::getMin(getS16Neg18()),
1215 APFixedPoint(281474976710656,
1216 FixedPointSemantics(52, FixedPointSemantics::Lsb
{-18},
1217 true, false, false)));
1218 CheckMulOverflow(APFixedPoint::getMax(getS32Pos2()), APFixedPoint::getMax(getU8Pos4()));
1219 CheckMulOverflow(APFixedPoint::getMin(getS32Pos2()), APFixedPoint::getMax(getU8Pos4()));
1222 void CheckDiv(const APFixedPoint
&Lhs
, const APFixedPoint
&Rhs
,
1223 const APFixedPoint
&Expected
) {
1224 bool Overflow
= false;
1225 APFixedPoint Result
= Lhs
.div(Rhs
, &Overflow
);
1226 ASSERT_FALSE(Overflow
);
1227 ASSERT_EQ(Result
.getSemantics(), Expected
.getSemantics());
1228 ASSERT_EQ(Result
, Expected
);
1231 void CheckDivOverflow(const APFixedPoint
&Lhs
, const APFixedPoint
&Rhs
) {
1232 bool Overflow
= false;
1233 APFixedPoint Result
= Lhs
.div(Rhs
, &Overflow
);
1234 ASSERT_TRUE(Overflow
);
1237 TEST(FixedPoint
, div
) {
1238 CheckDiv(APFixedPoint(1, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1239 APFixedPoint(0, getS32Pos2()));
1240 CheckDivOverflow(APFixedPoint(1, getS16Neg18()), APFixedPoint(1, getS16Neg18()));
1241 CheckDivOverflow(APFixedPoint(1, getU8Neg10()), APFixedPoint(1, getU8Neg10()));
1242 CheckDiv(APFixedPoint(1, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1243 APFixedPoint(0, getU8Pos4()));
1245 CheckDiv(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS32Pos2()),
1246 APFixedPoint(2, getS32Pos2()));
1247 CheckDiv(APFixedPoint(11, getU8Pos4()), APFixedPoint(1, getU8Pos4()),
1248 APFixedPoint(0, getU8Pos4()));
1250 CheckDiv(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS16Neg18()),
1251 APFixedPoint(3023656976384,
1252 FixedPointSemantics(52, FixedPointSemantics::Lsb
{-18},
1253 true, false, false)));
1254 CheckDiv(APFixedPoint(11, getU8Neg10()), APFixedPoint(-11264, getS16Neg18()),
1255 APFixedPoint::getMin(FixedPointSemantics(
1256 17, FixedPointSemantics::Lsb
{-18}, true, false, false)));
1257 CheckDiv(APFixedPoint(11, getU8Neg10()), APFixedPoint(11265, getS16Neg18()),
1258 APFixedPoint(0xfffa,
1259 FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1260 true, false, false)));
1261 CheckDivOverflow(APFixedPoint(11, getU8Neg10()),
1262 APFixedPoint(11264, getS16Neg18()));
1264 CheckDivOverflow(APFixedPoint(11, getU8Neg10()),
1265 APFixedPoint(-9472, getS16Neg18()));
1266 CheckDivOverflow(APFixedPoint::getMax(getU8Neg10()),
1267 APFixedPoint::getMax(getS16Neg18()));
1269 APFixedPoint::getMin(getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),
1270 APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1271 true, false, false)));
1273 APFixedPoint(1, getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),
1274 APFixedPoint(-2048, FixedPointSemantics(17, FixedPointSemantics::Lsb
{-18},
1275 true, false, false)));
1278 TEST(FixedPoint
, semanticsSerialization
) {
1279 auto roundTrip
= [](FixedPointSemantics FPS
) -> bool {
1280 uint32_t I
= FPS
.toOpaqueInt();
1281 FixedPointSemantics FPS2
= FixedPointSemantics::getFromOpaqueInt(I
);
1285 ASSERT_TRUE(roundTrip(getS32Pos2()));
1286 ASSERT_TRUE(roundTrip(getU8Pos4()));
1287 ASSERT_TRUE(roundTrip(getS16Neg18()));
1288 ASSERT_TRUE(roundTrip(getU8Neg10()));
1289 ASSERT_TRUE(roundTrip(getPadULFractSema()));
1290 ASSERT_TRUE(roundTrip(getPadUFractSema()));
1291 ASSERT_TRUE(roundTrip(getPadUSFractSema()));
1292 ASSERT_TRUE(roundTrip(getPadULAccumSema()));
1293 ASSERT_TRUE(roundTrip(getPadUAccumSema()));
1294 ASSERT_TRUE(roundTrip(getPadUSAccumSema()));
1295 ASSERT_TRUE(roundTrip(getULFractSema()));
1296 ASSERT_TRUE(roundTrip(getUFractSema()));
1297 ASSERT_TRUE(roundTrip(getUSFractSema()));
1298 ASSERT_TRUE(roundTrip(getULAccumSema()));
1299 ASSERT_TRUE(roundTrip(getUAccumSema()));
1300 ASSERT_TRUE(roundTrip(getUSAccumSema()));
1301 ASSERT_TRUE(roundTrip(getLFractSema()));
1302 ASSERT_TRUE(roundTrip(getFractSema()));
1303 ASSERT_TRUE(roundTrip(getSFractSema()));
1304 ASSERT_TRUE(roundTrip(getLAccumSema()));
1305 ASSERT_TRUE(roundTrip(getAccumSema()));
1306 ASSERT_TRUE(roundTrip(getSAccumSema()));