[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / llvm / unittests / ADT / APFixedPointTest.cpp
blobf54df99446d8f74375e8166049c9a16cbccc18e4
1 //===- unittests/ADT/FixedPointTest.cpp -- fixed point number tests -----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/APFixedPoint.h"
10 #include "llvm/ADT/APFloat.h"
11 #include "llvm/ADT/APSInt.h"
12 #include "gtest/gtest.h"
14 using llvm::APFixedPoint;
15 using llvm::APFloat;
16 using llvm::APInt;
17 using llvm::APSInt;
18 using llvm::FixedPointSemantics;
20 namespace {
22 FixedPointSemantics Saturated(FixedPointSemantics Sema) {
23 Sema.setSaturated(true);
24 return Sema;
27 FixedPointSemantics getSAccumSema() {
28 return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/true,
29 /*isSaturated=*/false,
30 /*hasUnsignedPadding=*/false);
33 FixedPointSemantics getAccumSema() {
34 return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/true,
35 /*isSaturated=*/false,
36 /*hasUnsignedPadding=*/false);
39 FixedPointSemantics getLAccumSema() {
40 return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/true,
41 /*isSaturated=*/false,
42 /*hasUnsignedPadding=*/false);
45 FixedPointSemantics getSFractSema() {
46 return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/true,
47 /*isSaturated=*/false,
48 /*hasUnsignedPadding=*/false);
51 FixedPointSemantics getFractSema() {
52 return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/true,
53 /*isSaturated=*/false,
54 /*hasUnsignedPadding=*/false);
57 FixedPointSemantics getLFractSema() {
58 return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/true,
59 /*isSaturated=*/false,
60 /*hasUnsignedPadding=*/false);
63 FixedPointSemantics getUSAccumSema() {
64 return FixedPointSemantics(/*width=*/16, /*scale=*/8, /*isSigned=*/false,
65 /*isSaturated=*/false,
66 /*hasUnsignedPadding=*/false);
69 FixedPointSemantics getUAccumSema() {
70 return FixedPointSemantics(/*width=*/32, /*scale=*/16, /*isSigned=*/false,
71 /*isSaturated=*/false,
72 /*hasUnsignedPadding=*/false);
75 FixedPointSemantics getULAccumSema() {
76 return FixedPointSemantics(/*width=*/64, /*scale=*/32, /*isSigned=*/false,
77 /*isSaturated=*/false,
78 /*hasUnsignedPadding=*/false);
81 FixedPointSemantics getUSFractSema() {
82 return FixedPointSemantics(/*width=*/8, /*scale=*/8, /*isSigned=*/false,
83 /*isSaturated=*/false,
84 /*hasUnsignedPadding=*/false);
87 FixedPointSemantics getUFractSema() {
88 return FixedPointSemantics(/*width=*/16, /*scale=*/16, /*isSigned=*/false,
89 /*isSaturated=*/false,
90 /*hasUnsignedPadding=*/false);
93 FixedPointSemantics getULFractSema() {
94 return FixedPointSemantics(/*width=*/32, /*scale=*/32, /*isSigned=*/false,
95 /*isSaturated=*/false,
96 /*hasUnsignedPadding=*/false);
99 FixedPointSemantics getPadUSAccumSema() {
100 return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/false,
101 /*isSaturated=*/false,
102 /*hasUnsignedPadding=*/true);
105 FixedPointSemantics getPadUAccumSema() {
106 return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/false,
107 /*isSaturated=*/false,
108 /*hasUnsignedPadding=*/true);
111 FixedPointSemantics getPadULAccumSema() {
112 return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/false,
113 /*isSaturated=*/false,
114 /*hasUnsignedPadding=*/true);
117 FixedPointSemantics getPadUSFractSema() {
118 return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/false,
119 /*isSaturated=*/false,
120 /*hasUnsignedPadding=*/true);
123 FixedPointSemantics getPadUFractSema() {
124 return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/false,
125 /*isSaturated=*/false,
126 /*hasUnsignedPadding=*/true);
129 FixedPointSemantics getPadULFractSema() {
130 return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/false,
131 /*isSaturated=*/false,
132 /*hasUnsignedPadding=*/true);
135 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)),
200 Sema.isSigned()),
201 Sema);
202 ASSERT_EQ(ValWithFract.getIntPart(), IntPart);
204 // Just fraction
205 APFixedPoint JustFract(
206 APInt(Sema.getWidth(), (1ULL << (Scale - 1)), Sema.isSigned()), Sema);
207 ASSERT_EQ(JustFract.getIntPart(), 0);
209 // Whole number
210 APFixedPoint WholeNum(
211 APInt(Sema.getWidth(), (IntPart << Scale), Sema.isSigned()), Sema);
212 ASSERT_EQ(WholeNum.getIntPart(), IntPart);
214 // Negative
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) {
233 // Normal values
234 CheckIntPart(getSAccumSema(), 2);
235 CheckIntPart(getAccumSema(), 2);
236 CheckIntPart(getLAccumSema(), 2);
237 CheckIntPart(getUSAccumSema(), 2);
238 CheckIntPart(getUAccumSema(), 2);
239 CheckIntPart(getULAccumSema(), 2);
241 // Zero
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);
256 // Min
257 CheckIntPartMin(getSAccumSema(), -256);
258 CheckIntPartMin(getAccumSema(), -65536);
259 CheckIntPartMin(getLAccumSema(), -4294967296);
261 CheckIntPartMin(getSFractSema(), -1);
262 CheckIntPartMin(getFractSema(), -1);
263 CheckIntPartMin(getLFractSema(), -1);
265 // Max
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);
280 // Padded
281 // Normal Values
282 CheckIntPart(getPadUSAccumSema(), 2);
283 CheckIntPart(getPadUAccumSema(), 2);
284 CheckIntPart(getPadULAccumSema(), 2);
286 // Zero
287 CheckIntPart(getPadUSAccumSema(), 0);
288 CheckIntPart(getPadUAccumSema(), 0);
289 CheckIntPart(getPadULAccumSema(), 0);
291 CheckIntPart(getPadUSFractSema(), 0);
292 CheckIntPart(getPadUFractSema(), 0);
293 CheckIntPart(getPadULFractSema(), 0);
295 // Max
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) {
306 // Equality
307 // With fractional part (2.5)
308 // Across sizes
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()));
329 // Across saturation
330 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
331 APFixedPoint(81920, Saturated(getAccumSema())));
333 // Across signs
334 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
335 APFixedPoint(640, getUSAccumSema()));
336 ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),
337 APFixedPoint(-81920, getAccumSema()));
339 // Across padding
340 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
341 APFixedPoint(320, getPadUSAccumSema()));
342 ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),
343 APFixedPoint(320, getPadUSAccumSema()));
345 // Less than
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()));
355 // Greater than
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;
371 if (IsNegative)
372 ScaledVal = -ScaledVal;
374 if (Dst.getScale() > Src.getScale()) {
375 ScaledVal <<= (Dst.getScale() - Src.getScale());
376 } else {
377 ScaledVal >>= (Src.getScale() - Dst.getScale());
380 if (IsNegative)
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
389 // for another sema
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
397 // for another sema
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,
406 int64_t OneVal) {
407 int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
408 int64_t HalfVal = (OneVal / 2); // 0.5
410 // +Accums to Accums
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);
421 // -Accums to Accums
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);
432 // +Accums to Fracts
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);
443 // -Accums to Fracts
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);
454 // 0 to Accums
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);
465 // 0 to Fracts
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
478 // values.
479 void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
480 int64_t OneVal) {
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()),
524 140737488355328);
525 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUAccumSema()),
526 140737488355328);
527 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUAccumSema()),
528 140737488355328);
529 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getAccumSema()),
530 281474976710656);
531 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUAccumSema()),
532 281474976710656);
533 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUAccumSema()),
534 281474976710656);
536 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getAccumSema()),
537 140737488355328);
538 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUAccumSema()),
539 140737488355328);
540 CheckSaturatedConversionMax(getPadULAccumSema(),
541 Saturated(getPadUAccumSema()), 140737488355328);
543 // To SAccum min limit (-65536)
544 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getAccumSema()),
545 -140737488355328);
546 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUAccumSema()),
547 -140737488355328);
548 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUAccumSema()),
549 -140737488355328);
552 TEST(FixedPoint, SAccumConversionOverflow) {
553 // To SAccum max limit (256)
554 CheckSaturatedConversionMax(getAccumSema(), Saturated(getSAccumSema()),
555 8388608);
556 CheckSaturatedConversionMax(getAccumSema(), Saturated(getUSAccumSema()),
557 8388608);
558 CheckSaturatedConversionMax(getAccumSema(), Saturated(getPadUSAccumSema()),
559 8388608);
560 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getSAccumSema()),
561 16777216);
562 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getUSAccumSema()),
563 16777216);
564 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getPadUSAccumSema()),
565 16777216);
566 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getSAccumSema()),
567 549755813888);
568 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUSAccumSema()),
569 549755813888);
570 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUSAccumSema()),
571 549755813888);
572 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getSAccumSema()),
573 1099511627776);
574 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUSAccumSema()),
575 1099511627776);
576 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUSAccumSema()),
577 1099511627776);
579 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getSAccumSema()),
580 8388608);
581 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getUSAccumSema()),
582 8388608);
583 CheckSaturatedConversionMax(getPadUAccumSema(),
584 Saturated(getPadUSAccumSema()), 8388608);
585 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getSAccumSema()),
586 549755813888);
587 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUSAccumSema()),
588 549755813888);
589 CheckSaturatedConversionMax(getPadULAccumSema(),
590 Saturated(getPadUSAccumSema()), 549755813888);
592 // To SAccum min limit (-256)
593 CheckSaturatedConversionMin(getAccumSema(), Saturated(getSAccumSema()),
594 -8388608);
595 CheckSaturatedConversionMin(getAccumSema(), Saturated(getUSAccumSema()),
596 -8388608);
597 CheckSaturatedConversionMin(getAccumSema(), Saturated(getPadUSAccumSema()),
598 -8388608);
599 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getSAccumSema()),
600 -549755813888);
601 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUSAccumSema()),
602 -549755813888);
603 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUSAccumSema()),
604 -549755813888);
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) {
652 bool Ovf;
653 ASSERT_EQ(APFixedPoint::getFromFloatValue(Val, Sema, &Ovf).getValue(),
654 ExpectedNonSat);
655 ASSERT_EQ(Ovf, false);
656 ASSERT_EQ(
657 APFixedPoint::getFromFloatValue(Val, Saturated(Sema), &Ovf).getValue(),
658 ExpectedNonSat);
659 ASSERT_EQ(Ovf, false);
662 void CheckFloatToFixedConversion(APFloat &Val, const FixedPointSemantics &Sema,
663 OvfKind ExpectedOvf) {
664 bool Ovf;
665 (void)APFixedPoint::getFromFloatValue(Val, Sema, &Ovf);
666 ASSERT_EQ(Ovf, true);
667 ASSERT_EQ(
668 APFixedPoint::getFromFloatValue(Val, Saturated(Sema), &Ovf).getValue(),
669 (ExpectedOvf == MinSat ? APFixedPoint::getMin(Sema)
670 : APFixedPoint::getMax(Sema))
671 .getValue());
672 ASSERT_EQ(Ovf, false);
675 TEST(FixedPoint, FloatToFixed) {
676 APFloat Val(0.0f);
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);
768 // Very large value
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);
786 // Very small value
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);
804 // Half conversion
805 Val = APFloat(0.99951171875f);
806 bool Ignored;
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,
827 float Result) {
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,
834 float Result) {
835 APFixedPoint FXVal(Val, Sema);
836 APFloat APRes(Result);
837 bool Ignored;
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);
856 Val = 0x7FULL;
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);
869 Val = -0x1ULL;
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);
882 Val = 0xAFAULL;
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);
895 Val = -0xAFAULL;
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);
902 Val = 0x40000080ULL;
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);
911 Val = 0x40000040ULL;
912 CheckFixedToFloatConversion(Val, getAccumSema(), 32768.0f);
913 CheckFixedToFloatConversion(Val, getLFractSema(), 0.5f);
915 CheckFixedToFloatConversion(Val, getUAccumSema(), 16384.0f);
916 CheckFixedToFloatConversion(Val, getULFractSema(), 0.25f);
918 Val = 0x7FF0ULL;
919 CheckFixedToHalfConversion(Val, getAccumSema(), 0.99951171875f);
920 CheckFixedToHalfConversion(Val, getLFractSema(), 0.000015251338481903076171875f);
922 CheckFixedToHalfConversion(Val, getUAccumSema(), 0.499755859375f);
923 CheckFixedToHalfConversion(Val, getULFractSema(), 0.0000076256692409515380859375f);
926 } // namespace