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 void CheckUnpaddedMax(const FixedPointSemantics
&Sema
) {
136 ASSERT_EQ(APFixedPoint::getMax(Sema
).getValue(),
137 APSInt::getMaxValue(Sema
.getWidth(), !Sema
.isSigned()));
140 void CheckPaddedMax(const FixedPointSemantics
&Sema
) {
141 ASSERT_EQ(APFixedPoint::getMax(Sema
).getValue(),
142 APSInt::getMaxValue(Sema
.getWidth(), !Sema
.isSigned()) >> 1);
145 void CheckMin(const FixedPointSemantics
&Sema
) {
146 ASSERT_EQ(APFixedPoint::getMin(Sema
).getValue(),
147 APSInt::getMinValue(Sema
.getWidth(), !Sema
.isSigned()));
150 TEST(FixedPointTest
, getMax
) {
151 CheckUnpaddedMax(getSAccumSema());
152 CheckUnpaddedMax(getAccumSema());
153 CheckUnpaddedMax(getLAccumSema());
154 CheckUnpaddedMax(getUSAccumSema());
155 CheckUnpaddedMax(getUAccumSema());
156 CheckUnpaddedMax(getULAccumSema());
157 CheckUnpaddedMax(getSFractSema());
158 CheckUnpaddedMax(getFractSema());
159 CheckUnpaddedMax(getLFractSema());
160 CheckUnpaddedMax(getUSFractSema());
161 CheckUnpaddedMax(getUFractSema());
162 CheckUnpaddedMax(getULFractSema());
164 CheckPaddedMax(getPadUSAccumSema());
165 CheckPaddedMax(getPadUAccumSema());
166 CheckPaddedMax(getPadULAccumSema());
167 CheckPaddedMax(getPadUSFractSema());
168 CheckPaddedMax(getPadUFractSema());
169 CheckPaddedMax(getPadULFractSema());
172 TEST(FixedPointTest
, getMin
) {
173 CheckMin(getSAccumSema());
174 CheckMin(getAccumSema());
175 CheckMin(getLAccumSema());
176 CheckMin(getUSAccumSema());
177 CheckMin(getUAccumSema());
178 CheckMin(getULAccumSema());
179 CheckMin(getSFractSema());
180 CheckMin(getFractSema());
181 CheckMin(getLFractSema());
182 CheckMin(getUSFractSema());
183 CheckMin(getUFractSema());
184 CheckMin(getULFractSema());
186 CheckMin(getPadUSAccumSema());
187 CheckMin(getPadUAccumSema());
188 CheckMin(getPadULAccumSema());
189 CheckMin(getPadUSFractSema());
190 CheckMin(getPadUFractSema());
191 CheckMin(getPadULFractSema());
194 void CheckIntPart(const FixedPointSemantics
&Sema
, int64_t IntPart
) {
195 unsigned Scale
= Sema
.getScale();
197 // Value with a fraction
198 APFixedPoint
ValWithFract(APInt(Sema
.getWidth(),
199 (IntPart
<< Scale
) + (1ULL << (Scale
- 1)),
202 ASSERT_EQ(ValWithFract
.getIntPart(), IntPart
);
205 APFixedPoint
JustFract(
206 APInt(Sema
.getWidth(), (1ULL << (Scale
- 1)), Sema
.isSigned()), Sema
);
207 ASSERT_EQ(JustFract
.getIntPart(), 0);
210 APFixedPoint
WholeNum(
211 APInt(Sema
.getWidth(), (IntPart
<< Scale
), Sema
.isSigned()), Sema
);
212 ASSERT_EQ(WholeNum
.getIntPart(), IntPart
);
215 if (Sema
.isSigned()) {
216 APFixedPoint
Negative(
217 APInt(Sema
.getWidth(), (IntPart
<< Scale
), Sema
.isSigned()), Sema
);
218 ASSERT_EQ(Negative
.getIntPart(), IntPart
);
222 void CheckIntPartMin(const FixedPointSemantics
&Sema
, int64_t Expected
) {
223 EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMin(Sema
).getIntPart(),
224 APSInt::get(Expected
)) == 0);
227 void CheckIntPartMax(const FixedPointSemantics
&Sema
, uint64_t Expected
) {
228 EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMax(Sema
).getIntPart(),
229 APSInt::getUnsigned(Expected
)) == 0);
232 TEST(FixedPoint
, getIntPart
) {
234 CheckIntPart(getSAccumSema(), 2);
235 CheckIntPart(getAccumSema(), 2);
236 CheckIntPart(getLAccumSema(), 2);
237 CheckIntPart(getUSAccumSema(), 2);
238 CheckIntPart(getUAccumSema(), 2);
239 CheckIntPart(getULAccumSema(), 2);
242 CheckIntPart(getSAccumSema(), 0);
243 CheckIntPart(getAccumSema(), 0);
244 CheckIntPart(getLAccumSema(), 0);
245 CheckIntPart(getUSAccumSema(), 0);
246 CheckIntPart(getUAccumSema(), 0);
247 CheckIntPart(getULAccumSema(), 0);
249 CheckIntPart(getSFractSema(), 0);
250 CheckIntPart(getFractSema(), 0);
251 CheckIntPart(getLFractSema(), 0);
252 CheckIntPart(getUSFractSema(), 0);
253 CheckIntPart(getUFractSema(), 0);
254 CheckIntPart(getULFractSema(), 0);
257 CheckIntPartMin(getSAccumSema(), -256);
258 CheckIntPartMin(getAccumSema(), -65536);
259 CheckIntPartMin(getLAccumSema(), -4294967296);
261 CheckIntPartMin(getSFractSema(), -1);
262 CheckIntPartMin(getFractSema(), -1);
263 CheckIntPartMin(getLFractSema(), -1);
266 CheckIntPartMax(getSAccumSema(), 255);
267 CheckIntPartMax(getAccumSema(), 65535);
268 CheckIntPartMax(getLAccumSema(), 4294967295);
269 CheckIntPartMax(getUSAccumSema(), 255);
270 CheckIntPartMax(getUAccumSema(), 65535);
271 CheckIntPartMax(getULAccumSema(), 4294967295);
273 CheckIntPartMax(getSFractSema(), 0);
274 CheckIntPartMax(getFractSema(), 0);
275 CheckIntPartMax(getLFractSema(), 0);
276 CheckIntPartMax(getUSFractSema(), 0);
277 CheckIntPartMax(getUFractSema(), 0);
278 CheckIntPartMax(getULFractSema(), 0);
282 CheckIntPart(getPadUSAccumSema(), 2);
283 CheckIntPart(getPadUAccumSema(), 2);
284 CheckIntPart(getPadULAccumSema(), 2);
287 CheckIntPart(getPadUSAccumSema(), 0);
288 CheckIntPart(getPadUAccumSema(), 0);
289 CheckIntPart(getPadULAccumSema(), 0);
291 CheckIntPart(getPadUSFractSema(), 0);
292 CheckIntPart(getPadUFractSema(), 0);
293 CheckIntPart(getPadULFractSema(), 0);
296 CheckIntPartMax(getPadUSAccumSema(), 255);
297 CheckIntPartMax(getPadUAccumSema(), 65535);
298 CheckIntPartMax(getPadULAccumSema(), 4294967295);
300 CheckIntPartMax(getPadUSFractSema(), 0);
301 CheckIntPartMax(getPadUFractSema(), 0);
302 CheckIntPartMax(getPadULFractSema(), 0);
305 TEST(FixedPoint
, compare
) {
307 // With fractional part (2.5)
309 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
310 APFixedPoint(81920, getAccumSema()));
311 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
312 APFixedPoint(5368709120, getLAccumSema()));
313 ASSERT_EQ(APFixedPoint(0, getSAccumSema()), APFixedPoint(0, getLAccumSema()));
315 // Across types (0.5)
316 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
317 APFixedPoint(64, getSFractSema()));
318 ASSERT_EQ(APFixedPoint(16384, getAccumSema()),
319 APFixedPoint(16384, getFractSema()));
320 ASSERT_EQ(APFixedPoint(1073741824, getLAccumSema()),
321 APFixedPoint(1073741824, getLFractSema()));
323 // Across widths and types (0.5)
324 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
325 APFixedPoint(16384, getFractSema()));
326 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
327 APFixedPoint(1073741824, getLFractSema()));
330 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
331 APFixedPoint(81920, Saturated(getAccumSema())));
334 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
335 APFixedPoint(640, getUSAccumSema()));
336 ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),
337 APFixedPoint(-81920, getAccumSema()));
340 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
341 APFixedPoint(320, getPadUSAccumSema()));
342 ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),
343 APFixedPoint(320, getPadUSAccumSema()));
346 ASSERT_LT(APFixedPoint(-1, getSAccumSema()), APFixedPoint(0, getAccumSema()));
347 ASSERT_LT(APFixedPoint(-1, getSAccumSema()),
348 APFixedPoint(0, getUAccumSema()));
349 ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getAccumSema()));
350 ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getUAccumSema()));
351 ASSERT_LT(APFixedPoint(0, getUSAccumSema()), APFixedPoint(1, getAccumSema()));
352 ASSERT_LT(APFixedPoint(0, getUSAccumSema()),
353 APFixedPoint(1, getUAccumSema()));
356 ASSERT_GT(APFixedPoint(0, getAccumSema()), APFixedPoint(-1, getSAccumSema()));
357 ASSERT_GT(APFixedPoint(0, getUAccumSema()),
358 APFixedPoint(-1, getSAccumSema()));
359 ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getSAccumSema()));
360 ASSERT_GT(APFixedPoint(1, getUAccumSema()), APFixedPoint(0, getSAccumSema()));
361 ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getUSAccumSema()));
362 ASSERT_GT(APFixedPoint(1, getUAccumSema()),
363 APFixedPoint(0, getUSAccumSema()));
366 // Check that a fixed point value in one sema is the same in another sema
367 void CheckUnsaturatedConversion(FixedPointSemantics Src
,
368 FixedPointSemantics Dst
, int64_t TestVal
) {
369 int64_t ScaledVal
= TestVal
;
370 bool IsNegative
= ScaledVal
< 0;
372 ScaledVal
= -ScaledVal
;
374 if (Dst
.getScale() > Src
.getScale()) {
375 ScaledVal
<<= (Dst
.getScale() - Src
.getScale());
377 ScaledVal
>>= (Src
.getScale() - Dst
.getScale());
381 ScaledVal
= -ScaledVal
;
383 APFixedPoint
Fixed(TestVal
, Src
);
384 APFixedPoint
Expected(ScaledVal
, Dst
);
385 ASSERT_EQ(Fixed
.convert(Dst
), Expected
);
388 // Check the value in a given fixed point sema overflows to the saturated min
390 void CheckSaturatedConversionMin(FixedPointSemantics Src
,
391 FixedPointSemantics Dst
, int64_t TestVal
) {
392 APFixedPoint
Fixed(TestVal
, Src
);
393 ASSERT_EQ(Fixed
.convert(Dst
), APFixedPoint::getMin(Dst
));
396 // Check the value in a given fixed point sema overflows to the saturated max
398 void CheckSaturatedConversionMax(FixedPointSemantics Src
,
399 FixedPointSemantics Dst
, int64_t TestVal
) {
400 APFixedPoint
Fixed(TestVal
, Src
);
401 ASSERT_EQ(Fixed
.convert(Dst
), APFixedPoint::getMax(Dst
));
404 // Check one signed _Accum sema converted to other sema for different values.
405 void CheckSignedAccumConversionsAgainstOthers(FixedPointSemantics Src
,
407 int64_t NormalVal
= (OneVal
* 2) + (OneVal
/ 2); // 2.5
408 int64_t HalfVal
= (OneVal
/ 2); // 0.5
411 CheckUnsaturatedConversion(Src
, getSAccumSema(), NormalVal
);
412 CheckUnsaturatedConversion(Src
, getAccumSema(), NormalVal
);
413 CheckUnsaturatedConversion(Src
, getLAccumSema(), NormalVal
);
414 CheckUnsaturatedConversion(Src
, getUSAccumSema(), NormalVal
);
415 CheckUnsaturatedConversion(Src
, getUAccumSema(), NormalVal
);
416 CheckUnsaturatedConversion(Src
, getULAccumSema(), NormalVal
);
417 CheckUnsaturatedConversion(Src
, getPadUSAccumSema(), NormalVal
);
418 CheckUnsaturatedConversion(Src
, getPadUAccumSema(), NormalVal
);
419 CheckUnsaturatedConversion(Src
, getPadULAccumSema(), NormalVal
);
422 CheckUnsaturatedConversion(Src
, getSAccumSema(), -NormalVal
);
423 CheckUnsaturatedConversion(Src
, getAccumSema(), -NormalVal
);
424 CheckUnsaturatedConversion(Src
, getLAccumSema(), -NormalVal
);
425 CheckSaturatedConversionMin(Src
, Saturated(getUSAccumSema()), -NormalVal
);
426 CheckSaturatedConversionMin(Src
, Saturated(getUAccumSema()), -NormalVal
);
427 CheckSaturatedConversionMin(Src
, Saturated(getULAccumSema()), -NormalVal
);
428 CheckSaturatedConversionMin(Src
, Saturated(getPadUSAccumSema()), -NormalVal
);
429 CheckSaturatedConversionMin(Src
, Saturated(getPadUAccumSema()), -NormalVal
);
430 CheckSaturatedConversionMin(Src
, Saturated(getPadULAccumSema()), -NormalVal
);
433 CheckUnsaturatedConversion(Src
, getSFractSema(), HalfVal
);
434 CheckUnsaturatedConversion(Src
, getFractSema(), HalfVal
);
435 CheckUnsaturatedConversion(Src
, getLFractSema(), HalfVal
);
436 CheckUnsaturatedConversion(Src
, getUSFractSema(), HalfVal
);
437 CheckUnsaturatedConversion(Src
, getUFractSema(), HalfVal
);
438 CheckUnsaturatedConversion(Src
, getULFractSema(), HalfVal
);
439 CheckUnsaturatedConversion(Src
, getPadUSFractSema(), HalfVal
);
440 CheckUnsaturatedConversion(Src
, getPadUFractSema(), HalfVal
);
441 CheckUnsaturatedConversion(Src
, getPadULFractSema(), HalfVal
);
444 CheckUnsaturatedConversion(Src
, getSFractSema(), -HalfVal
);
445 CheckUnsaturatedConversion(Src
, getFractSema(), -HalfVal
);
446 CheckUnsaturatedConversion(Src
, getLFractSema(), -HalfVal
);
447 CheckSaturatedConversionMin(Src
, Saturated(getUSFractSema()), -HalfVal
);
448 CheckSaturatedConversionMin(Src
, Saturated(getUFractSema()), -HalfVal
);
449 CheckSaturatedConversionMin(Src
, Saturated(getULFractSema()), -HalfVal
);
450 CheckSaturatedConversionMin(Src
, Saturated(getPadUSFractSema()), -HalfVal
);
451 CheckSaturatedConversionMin(Src
, Saturated(getPadUFractSema()), -HalfVal
);
452 CheckSaturatedConversionMin(Src
, Saturated(getPadULFractSema()), -HalfVal
);
455 CheckUnsaturatedConversion(Src
, getSAccumSema(), 0);
456 CheckUnsaturatedConversion(Src
, getAccumSema(), 0);
457 CheckUnsaturatedConversion(Src
, getLAccumSema(), 0);
458 CheckUnsaturatedConversion(Src
, getUSAccumSema(), 0);
459 CheckUnsaturatedConversion(Src
, getUAccumSema(), 0);
460 CheckUnsaturatedConversion(Src
, getULAccumSema(), 0);
461 CheckUnsaturatedConversion(Src
, getPadUSAccumSema(), 0);
462 CheckUnsaturatedConversion(Src
, getPadUAccumSema(), 0);
463 CheckUnsaturatedConversion(Src
, getPadULAccumSema(), 0);
466 CheckUnsaturatedConversion(Src
, getSFractSema(), 0);
467 CheckUnsaturatedConversion(Src
, getFractSema(), 0);
468 CheckUnsaturatedConversion(Src
, getLFractSema(), 0);
469 CheckUnsaturatedConversion(Src
, getUSFractSema(), 0);
470 CheckUnsaturatedConversion(Src
, getUFractSema(), 0);
471 CheckUnsaturatedConversion(Src
, getULFractSema(), 0);
472 CheckUnsaturatedConversion(Src
, getPadUSFractSema(), 0);
473 CheckUnsaturatedConversion(Src
, getPadUFractSema(), 0);
474 CheckUnsaturatedConversion(Src
, getPadULFractSema(), 0);
477 // Check one unsigned _Accum sema converted to other sema for different
479 void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src
,
481 int64_t NormalVal
= (OneVal
* 2) + (OneVal
/ 2); // 2.5
482 int64_t HalfVal
= (OneVal
/ 2); // 0.5
484 // +UAccums to Accums
485 CheckUnsaturatedConversion(Src
, getSAccumSema(), NormalVal
);
486 CheckUnsaturatedConversion(Src
, getAccumSema(), NormalVal
);
487 CheckUnsaturatedConversion(Src
, getLAccumSema(), NormalVal
);
488 CheckUnsaturatedConversion(Src
, getUSAccumSema(), NormalVal
);
489 CheckUnsaturatedConversion(Src
, getUAccumSema(), NormalVal
);
490 CheckUnsaturatedConversion(Src
, getULAccumSema(), NormalVal
);
491 CheckUnsaturatedConversion(Src
, getPadUSAccumSema(), NormalVal
);
492 CheckUnsaturatedConversion(Src
, getPadUAccumSema(), NormalVal
);
493 CheckUnsaturatedConversion(Src
, getPadULAccumSema(), NormalVal
);
495 // +UAccums to Fracts
496 CheckUnsaturatedConversion(Src
, getSFractSema(), HalfVal
);
497 CheckUnsaturatedConversion(Src
, getFractSema(), HalfVal
);
498 CheckUnsaturatedConversion(Src
, getLFractSema(), HalfVal
);
499 CheckUnsaturatedConversion(Src
, getUSFractSema(), HalfVal
);
500 CheckUnsaturatedConversion(Src
, getUFractSema(), HalfVal
);
501 CheckUnsaturatedConversion(Src
, getULFractSema(), HalfVal
);
502 CheckUnsaturatedConversion(Src
, getPadUSFractSema(), HalfVal
);
503 CheckUnsaturatedConversion(Src
, getPadUFractSema(), HalfVal
);
504 CheckUnsaturatedConversion(Src
, getPadULFractSema(), HalfVal
);
507 TEST(FixedPoint
, AccumConversions
) {
508 // Normal conversions
509 CheckSignedAccumConversionsAgainstOthers(getSAccumSema(), 128);
510 CheckUnsignedAccumConversionsAgainstOthers(getUSAccumSema(), 256);
511 CheckSignedAccumConversionsAgainstOthers(getAccumSema(), 32768);
512 CheckUnsignedAccumConversionsAgainstOthers(getUAccumSema(), 65536);
513 CheckSignedAccumConversionsAgainstOthers(getLAccumSema(), 2147483648);
514 CheckUnsignedAccumConversionsAgainstOthers(getULAccumSema(), 4294967296);
516 CheckUnsignedAccumConversionsAgainstOthers(getPadUSAccumSema(), 128);
517 CheckUnsignedAccumConversionsAgainstOthers(getPadUAccumSema(), 32768);
518 CheckUnsignedAccumConversionsAgainstOthers(getPadULAccumSema(), 2147483648);
521 TEST(FixedPoint
, AccumConversionOverflow
) {
522 // To SAccum max limit (65536)
523 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getAccumSema()),
525 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUAccumSema()),
527 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUAccumSema()),
529 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getAccumSema()),
531 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUAccumSema()),
533 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUAccumSema()),
536 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getAccumSema()),
538 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUAccumSema()),
540 CheckSaturatedConversionMax(getPadULAccumSema(),
541 Saturated(getPadUAccumSema()), 140737488355328);
543 // To SAccum min limit (-65536)
544 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getAccumSema()),
546 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUAccumSema()),
548 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUAccumSema()),
552 TEST(FixedPoint
, SAccumConversionOverflow
) {
553 // To SAccum max limit (256)
554 CheckSaturatedConversionMax(getAccumSema(), Saturated(getSAccumSema()),
556 CheckSaturatedConversionMax(getAccumSema(), Saturated(getUSAccumSema()),
558 CheckSaturatedConversionMax(getAccumSema(), Saturated(getPadUSAccumSema()),
560 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getSAccumSema()),
562 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getUSAccumSema()),
564 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getPadUSAccumSema()),
566 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getSAccumSema()),
568 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUSAccumSema()),
570 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUSAccumSema()),
572 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getSAccumSema()),
574 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUSAccumSema()),
576 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUSAccumSema()),
579 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getSAccumSema()),
581 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getUSAccumSema()),
583 CheckSaturatedConversionMax(getPadUAccumSema(),
584 Saturated(getPadUSAccumSema()), 8388608);
585 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getSAccumSema()),
587 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUSAccumSema()),
589 CheckSaturatedConversionMax(getPadULAccumSema(),
590 Saturated(getPadUSAccumSema()), 549755813888);
592 // To SAccum min limit (-256)
593 CheckSaturatedConversionMin(getAccumSema(), Saturated(getSAccumSema()),
595 CheckSaturatedConversionMin(getAccumSema(), Saturated(getUSAccumSema()),
597 CheckSaturatedConversionMin(getAccumSema(), Saturated(getPadUSAccumSema()),
599 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getSAccumSema()),
601 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUSAccumSema()),
603 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUSAccumSema()),
607 TEST(FixedPoint
, GetValueSignAfterConversion
) {
608 APFixedPoint
Fixed(255 << 7, getSAccumSema());
609 ASSERT_TRUE(Fixed
.getValue().isSigned());
610 APFixedPoint UFixed
= Fixed
.convert(getUSAccumSema());
611 ASSERT_TRUE(UFixed
.getValue().isUnsigned());
612 ASSERT_EQ(UFixed
.getValue(), APSInt::getUnsigned(255 << 8).extOrTrunc(16));
615 TEST(FixedPoint
, ModularWrapAround
) {
616 // Positive to negative
617 APFixedPoint Val
= APFixedPoint(1ULL << 7, getSAccumSema());
618 ASSERT_EQ(Val
.convert(getLFractSema()).getValue(), -(1ULL << 31));
620 Val
= APFixedPoint(1ULL << 23, getAccumSema());
621 ASSERT_EQ(Val
.convert(getSAccumSema()).getValue(), -(1ULL << 15));
623 Val
= APFixedPoint(1ULL << 47, getLAccumSema());
624 ASSERT_EQ(Val
.convert(getAccumSema()).getValue(), -(1ULL << 31));
626 // Negative to positive
627 Val
= APFixedPoint(/*-1.5*/ -192, getSAccumSema());
628 ASSERT_EQ(Val
.convert(getLFractSema()).getValue(), 1ULL << 30);
630 Val
= APFixedPoint(-(257 << 15), getAccumSema());
631 ASSERT_EQ(Val
.convert(getSAccumSema()).getValue(), 255 << 7);
633 Val
= APFixedPoint(-(65537ULL << 31), getLAccumSema());
634 ASSERT_EQ(Val
.convert(getAccumSema()).getValue(), 65535 << 15);
636 // Signed to unsigned
637 Val
= APFixedPoint(-(1 << 7), getSAccumSema());
638 ASSERT_EQ(Val
.convert(getUSAccumSema()).getValue(), 255 << 8);
640 Val
= APFixedPoint(-(1 << 15), getAccumSema());
641 ASSERT_EQ(Val
.convert(getUAccumSema()).getValue(), 65535ULL << 16);
643 Val
= APFixedPoint(-(1ULL << 31), getLAccumSema());
644 ASSERT_EQ(Val
.convert(getULAccumSema()).getValue().getZExtValue(),
645 4294967295ULL << 32);
648 enum OvfKind
{ MinSat
, MaxSat
};
650 void CheckFloatToFixedConversion(APFloat
&Val
, const FixedPointSemantics
&Sema
,
651 int64_t ExpectedNonSat
) {
653 ASSERT_EQ(APFixedPoint::getFromFloatValue(Val
, Sema
, &Ovf
).getValue(),
655 ASSERT_EQ(Ovf
, false);
657 APFixedPoint::getFromFloatValue(Val
, Saturated(Sema
), &Ovf
).getValue(),
659 ASSERT_EQ(Ovf
, false);
662 void CheckFloatToFixedConversion(APFloat
&Val
, const FixedPointSemantics
&Sema
,
663 OvfKind ExpectedOvf
) {
665 (void)APFixedPoint::getFromFloatValue(Val
, Sema
, &Ovf
);
666 ASSERT_EQ(Ovf
, true);
668 APFixedPoint::getFromFloatValue(Val
, Saturated(Sema
), &Ovf
).getValue(),
669 (ExpectedOvf
== MinSat
? APFixedPoint::getMin(Sema
)
670 : APFixedPoint::getMax(Sema
))
672 ASSERT_EQ(Ovf
, false);
675 TEST(FixedPoint
, FloatToFixed
) {
678 // Simple exact fraction
679 Val
= APFloat(0.75f
);
680 CheckFloatToFixedConversion(Val
, getSAccumSema(), 3ULL << 5);
681 CheckFloatToFixedConversion(Val
, getAccumSema(), 3ULL << 13);
682 CheckFloatToFixedConversion(Val
, getLAccumSema(), 3ULL << 29);
684 CheckFloatToFixedConversion(Val
, getUSAccumSema(), 3ULL << 6);
685 CheckFloatToFixedConversion(Val
, getUAccumSema(), 3ULL << 14);
686 CheckFloatToFixedConversion(Val
, getULAccumSema(), 3ULL << 30);
688 CheckFloatToFixedConversion(Val
, getSFractSema(), 3ULL << 5);
689 CheckFloatToFixedConversion(Val
, getFractSema(), 3ULL << 13);
690 CheckFloatToFixedConversion(Val
, getLFractSema(), 3ULL << 29);
692 CheckFloatToFixedConversion(Val
, getUSFractSema(), 3ULL << 6);
693 CheckFloatToFixedConversion(Val
, getUFractSema(), 3ULL << 14);
694 CheckFloatToFixedConversion(Val
, getULFractSema(), 3ULL << 30);
696 // Simple negative exact fraction
697 Val
= APFloat(-0.75f
);
698 CheckFloatToFixedConversion(Val
, getSAccumSema(), -3ULL << 5);
699 CheckFloatToFixedConversion(Val
, getAccumSema(), -3ULL << 13);
700 CheckFloatToFixedConversion(Val
, getLAccumSema(), -3ULL << 29);
702 CheckFloatToFixedConversion(Val
, getUSAccumSema(), MinSat
);
703 CheckFloatToFixedConversion(Val
, getUAccumSema(), MinSat
);
704 CheckFloatToFixedConversion(Val
, getULAccumSema(), MinSat
);
706 CheckFloatToFixedConversion(Val
, getSFractSema(), -3ULL << 5);
707 CheckFloatToFixedConversion(Val
, getFractSema(), -3ULL << 13);
708 CheckFloatToFixedConversion(Val
, getLFractSema(), -3ULL << 29);
710 CheckFloatToFixedConversion(Val
, getUSFractSema(), MinSat
);
711 CheckFloatToFixedConversion(Val
, getUFractSema(), MinSat
);
712 CheckFloatToFixedConversion(Val
, getULFractSema(), MinSat
);
714 // Highly precise fraction
715 Val
= APFloat(0.999999940395355224609375f
);
716 CheckFloatToFixedConversion(Val
, getSAccumSema(), 0x7FULL
);
717 CheckFloatToFixedConversion(Val
, getAccumSema(), 0x7FFFULL
);
718 CheckFloatToFixedConversion(Val
, getLAccumSema(), 0xFFFFFFULL
<< 7);
720 CheckFloatToFixedConversion(Val
, getUSAccumSema(), 0xFFULL
);
721 CheckFloatToFixedConversion(Val
, getUAccumSema(), 0xFFFFULL
);
722 CheckFloatToFixedConversion(Val
, getULAccumSema(), 0xFFFFFFULL
<< 8);
724 CheckFloatToFixedConversion(Val
, getSFractSema(), 0x7FULL
);
725 CheckFloatToFixedConversion(Val
, getFractSema(), 0x7FFFULL
);
726 CheckFloatToFixedConversion(Val
, getLFractSema(), 0xFFFFFFULL
<< 7);
728 CheckFloatToFixedConversion(Val
, getUSFractSema(), 0xFFULL
);
729 CheckFloatToFixedConversion(Val
, getUFractSema(), 0xFFFFULL
);
730 CheckFloatToFixedConversion(Val
, getULFractSema(), 0xFFFFFFULL
<< 8);
732 // Integral and fraction
733 Val
= APFloat(17.99609375f
);
734 CheckFloatToFixedConversion(Val
, getSAccumSema(), 0x11FFULL
>> 1);
735 CheckFloatToFixedConversion(Val
, getAccumSema(), 0x11FFULL
<< 7);
736 CheckFloatToFixedConversion(Val
, getLAccumSema(), 0x11FFULL
<< 23);
738 CheckFloatToFixedConversion(Val
, getUSAccumSema(), 0x11FFULL
);
739 CheckFloatToFixedConversion(Val
, getUAccumSema(), 0x11FFULL
<< 8);
740 CheckFloatToFixedConversion(Val
, getULAccumSema(), 0x11FFULL
<< 24);
742 CheckFloatToFixedConversion(Val
, getSFractSema(), MaxSat
);
743 CheckFloatToFixedConversion(Val
, getFractSema(), MaxSat
);
744 CheckFloatToFixedConversion(Val
, getLFractSema(), MaxSat
);
746 CheckFloatToFixedConversion(Val
, getUSFractSema(), MaxSat
);
747 CheckFloatToFixedConversion(Val
, getUFractSema(), MaxSat
);
748 CheckFloatToFixedConversion(Val
, getULFractSema(), MaxSat
);
750 // Negative integral and fraction
751 Val
= APFloat(-17.99609375f
);
752 CheckFloatToFixedConversion(Val
, getSAccumSema(), -0x11FELL
>> 1);
753 CheckFloatToFixedConversion(Val
, getAccumSema(), -0x11FFULL
<< 7);
754 CheckFloatToFixedConversion(Val
, getLAccumSema(), -0x11FFULL
<< 23);
756 CheckFloatToFixedConversion(Val
, getUSAccumSema(), MinSat
);
757 CheckFloatToFixedConversion(Val
, getUAccumSema(), MinSat
);
758 CheckFloatToFixedConversion(Val
, getULAccumSema(), MinSat
);
760 CheckFloatToFixedConversion(Val
, getSFractSema(), MinSat
);
761 CheckFloatToFixedConversion(Val
, getFractSema(), MinSat
);
762 CheckFloatToFixedConversion(Val
, getLFractSema(), MinSat
);
764 CheckFloatToFixedConversion(Val
, getUSFractSema(), MinSat
);
765 CheckFloatToFixedConversion(Val
, getUFractSema(), MinSat
);
766 CheckFloatToFixedConversion(Val
, getULFractSema(), MinSat
);
769 Val
= APFloat(1.0e38f
);
770 CheckFloatToFixedConversion(Val
, getSAccumSema(), MaxSat
);
771 CheckFloatToFixedConversion(Val
, getAccumSema(), MaxSat
);
772 CheckFloatToFixedConversion(Val
, getLAccumSema(), MaxSat
);
774 CheckFloatToFixedConversion(Val
, getUSAccumSema(), MaxSat
);
775 CheckFloatToFixedConversion(Val
, getUAccumSema(), MaxSat
);
776 CheckFloatToFixedConversion(Val
, getULAccumSema(), MaxSat
);
778 CheckFloatToFixedConversion(Val
, getSFractSema(), MaxSat
);
779 CheckFloatToFixedConversion(Val
, getFractSema(), MaxSat
);
780 CheckFloatToFixedConversion(Val
, getLFractSema(), MaxSat
);
782 CheckFloatToFixedConversion(Val
, getUSFractSema(), MaxSat
);
783 CheckFloatToFixedConversion(Val
, getUFractSema(), MaxSat
);
784 CheckFloatToFixedConversion(Val
, getULFractSema(), MaxSat
);
787 Val
= APFloat(1.0e-38f
);
788 CheckFloatToFixedConversion(Val
, getSAccumSema(), 0);
789 CheckFloatToFixedConversion(Val
, getAccumSema(), 0);
790 CheckFloatToFixedConversion(Val
, getLAccumSema(), 0);
792 CheckFloatToFixedConversion(Val
, getUSAccumSema(), 0);
793 CheckFloatToFixedConversion(Val
, getUAccumSema(), 0);
794 CheckFloatToFixedConversion(Val
, getULAccumSema(), 0);
796 CheckFloatToFixedConversion(Val
, getSFractSema(), 0);
797 CheckFloatToFixedConversion(Val
, getFractSema(), 0);
798 CheckFloatToFixedConversion(Val
, getLFractSema(), 0);
800 CheckFloatToFixedConversion(Val
, getUSFractSema(), 0);
801 CheckFloatToFixedConversion(Val
, getUFractSema(), 0);
802 CheckFloatToFixedConversion(Val
, getULFractSema(), 0);
805 Val
= APFloat(0.99951171875f
);
807 Val
.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven
, &Ignored
);
809 CheckFloatToFixedConversion(Val
, getSAccumSema(), 0x7FULL
);
810 CheckFloatToFixedConversion(Val
, getAccumSema(), 0x7FFULL
<< 4);
811 CheckFloatToFixedConversion(Val
, getLAccumSema(), 0x7FFULL
<< 20);
813 CheckFloatToFixedConversion(Val
, getUSAccumSema(), 0xFFULL
);
814 CheckFloatToFixedConversion(Val
, getUAccumSema(), 0xFFEULL
<< 4);
815 CheckFloatToFixedConversion(Val
, getULAccumSema(), 0xFFEULL
<< 20);
817 CheckFloatToFixedConversion(Val
, getSFractSema(), 0x7FULL
);
818 CheckFloatToFixedConversion(Val
, getFractSema(), 0x7FFULL
<< 4);
819 CheckFloatToFixedConversion(Val
, getLFractSema(), 0x7FFULL
<< 20);
821 CheckFloatToFixedConversion(Val
, getUSFractSema(), 0xFFULL
);
822 CheckFloatToFixedConversion(Val
, getUFractSema(), 0xFFEULL
<< 4);
823 CheckFloatToFixedConversion(Val
, getULFractSema(), 0xFFEULL
<< 20);
826 void CheckFixedToFloatConversion(int64_t Val
, const FixedPointSemantics
&Sema
,
828 APFixedPoint
FXVal(Val
, Sema
);
829 APFloat
APRes(Result
);
830 ASSERT_EQ(FXVal
.convertToFloat(APFloat::IEEEsingle()), APRes
);
833 void CheckFixedToHalfConversion(int64_t Val
, const FixedPointSemantics
&Sema
,
835 APFixedPoint
FXVal(Val
, Sema
);
836 APFloat
APRes(Result
);
838 APRes
.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven
, &Ignored
);
839 ASSERT_EQ(FXVal
.convertToFloat(APFloat::IEEEhalf()), APRes
);
842 TEST(FixedPoint
, FixedToFloat
) {
843 int64_t Val
= 0x1ULL
;
844 CheckFixedToFloatConversion(Val
, getSAccumSema(), 0.0078125f
);
845 CheckFixedToFloatConversion(Val
, getFractSema(), 0.000030517578125f
);
846 CheckFixedToFloatConversion(Val
, getAccumSema(), 0.000030517578125f
);
847 CheckFixedToFloatConversion(Val
, getLFractSema(),
848 0.0000000004656612873077392578125f
);
850 CheckFixedToFloatConversion(Val
, getUSAccumSema(), 0.00390625f
);
851 CheckFixedToFloatConversion(Val
, getUFractSema(), 0.0000152587890625f
);
852 CheckFixedToFloatConversion(Val
, getUAccumSema(), 0.0000152587890625f
);
853 CheckFixedToFloatConversion(Val
, getULFractSema(),
854 0.00000000023283064365386962890625f
);
857 CheckFixedToFloatConversion(Val
, getSAccumSema(), 0.9921875f
);
858 CheckFixedToFloatConversion(Val
, getFractSema(), 0.003875732421875f
);
859 CheckFixedToFloatConversion(Val
, getAccumSema(), 0.003875732421875f
);
860 CheckFixedToFloatConversion(Val
, getLFractSema(),
861 0.0000000591389834880828857421875f
);
863 CheckFixedToFloatConversion(Val
, getUSAccumSema(), 0.49609375f
);
864 CheckFixedToFloatConversion(Val
, getUFractSema(), 0.0019378662109375f
);
865 CheckFixedToFloatConversion(Val
, getUAccumSema(), 0.0019378662109375f
);
866 CheckFixedToFloatConversion(Val
, getULFractSema(),
867 0.00000002956949174404144287109375f
);
870 CheckFixedToFloatConversion(Val
, getSAccumSema(), -0.0078125f
);
871 CheckFixedToFloatConversion(Val
, getFractSema(), -0.000030517578125f
);
872 CheckFixedToFloatConversion(Val
, getAccumSema(), -0.000030517578125f
);
873 CheckFixedToFloatConversion(Val
, getLFractSema(),
874 -0.0000000004656612873077392578125f
);
877 CheckFixedToFloatConversion(-0x80ULL
, getSAccumSema(), -1.0f
);
878 CheckFixedToFloatConversion(-0x8000ULL
, getFractSema(), -1.0f
);
879 CheckFixedToFloatConversion(-0x8000ULL
, getAccumSema(), -1.0f
);
880 CheckFixedToFloatConversion(-0x80000000ULL
, getLFractSema(), -1.0f
);
883 CheckFixedToFloatConversion(Val
, getSAccumSema(), 21.953125f
);
884 CheckFixedToFloatConversion(Val
, getFractSema(), 0.08575439453125f
);
885 CheckFixedToFloatConversion(Val
, getAccumSema(), 0.08575439453125f
);
886 CheckFixedToFloatConversion(Val
, getLFractSema(),
887 0.000001308508217334747314453125f
);
889 CheckFixedToFloatConversion(Val
, getUSAccumSema(), 10.9765625f
);
890 CheckFixedToFloatConversion(Val
, getUFractSema(), 0.042877197265625f
);
891 CheckFixedToFloatConversion(Val
, getUAccumSema(), 0.042877197265625f
);
892 CheckFixedToFloatConversion(Val
, getULFractSema(),
893 0.0000006542541086673736572265625f
);
896 CheckFixedToFloatConversion(Val
, getSAccumSema(), -21.953125f
);
897 CheckFixedToFloatConversion(Val
, getFractSema(), -0.08575439453125f
);
898 CheckFixedToFloatConversion(Val
, getAccumSema(), -0.08575439453125f
);
899 CheckFixedToFloatConversion(Val
, getLFractSema(),
900 -0.000001308508217334747314453125f
);
903 CheckFixedToFloatConversion(Val
, getAccumSema(), 32768.00390625f
);
904 CheckFixedToFloatConversion(Val
, getLFractSema(),
905 0.500000059604644775390625f
);
907 CheckFixedToFloatConversion(Val
, getUAccumSema(), 16384.001953125f
);
908 CheckFixedToFloatConversion(Val
, getULFractSema(),
909 0.2500000298023223876953125f
);
912 CheckFixedToFloatConversion(Val
, getAccumSema(), 32768.0f
);
913 CheckFixedToFloatConversion(Val
, getLFractSema(), 0.5f
);
915 CheckFixedToFloatConversion(Val
, getUAccumSema(), 16384.0f
);
916 CheckFixedToFloatConversion(Val
, getULFractSema(), 0.25f
);
919 CheckFixedToHalfConversion(Val
, getAccumSema(), 0.99951171875f
);
920 CheckFixedToHalfConversion(Val
, getLFractSema(), 0.000015251338481903076171875f
);
922 CheckFixedToHalfConversion(Val
, getUAccumSema(), 0.499755859375f
);
923 CheckFixedToHalfConversion(Val
, getULFractSema(), 0.0000076256692409515380859375f
);