blob: 6d608f1faff28155c7a43f58dc2d5aa6a75a79ae [file] [log] [blame]
Leonard Chana6779422018-08-06 16:42:37 +00001//===- unittests/Basic/FixedPointTest.cpp -- fixed point number tests -----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "clang/Basic/FixedPoint.h"
11#include "llvm/ADT/APSInt.h"
12#include "gtest/gtest.h"
13
14using clang::APFixedPoint;
15using clang::FixedPointSemantics;
16using llvm::APInt;
17using llvm::APSInt;
18
19namespace {
20
21FixedPointSemantics Saturated(FixedPointSemantics Sema) {
22 Sema.setSaturated(true);
23 return Sema;
24}
25
26FixedPointSemantics getSAccumSema() {
27 return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/true,
28 /*isSaturated=*/false,
29 /*hasUnsignedPadding=*/false);
30}
31
32FixedPointSemantics getAccumSema() {
33 return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/true,
34 /*isSaturated=*/false,
35 /*hasUnsignedPadding=*/false);
36}
37
38FixedPointSemantics getLAccumSema() {
39 return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/true,
40 /*isSaturated=*/false,
41 /*hasUnsignedPadding=*/false);
42}
43
44FixedPointSemantics getSFractSema() {
45 return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/true,
46 /*isSaturated=*/false,
47 /*hasUnsignedPadding=*/false);
48}
49
50FixedPointSemantics getFractSema() {
51 return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/true,
52 /*isSaturated=*/false,
53 /*hasUnsignedPadding=*/false);
54}
55
56FixedPointSemantics getLFractSema() {
57 return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/true,
58 /*isSaturated=*/false,
59 /*hasUnsignedPadding=*/false);
60}
61
62FixedPointSemantics getUSAccumSema() {
63 return FixedPointSemantics(/*width=*/16, /*scale=*/8, /*isSigned=*/false,
64 /*isSaturated=*/false,
65 /*hasUnsignedPadding=*/false);
66}
67
68FixedPointSemantics getUAccumSema() {
69 return FixedPointSemantics(/*width=*/32, /*scale=*/16, /*isSigned=*/false,
70 /*isSaturated=*/false,
71 /*hasUnsignedPadding=*/false);
72}
73
74FixedPointSemantics getULAccumSema() {
75 return FixedPointSemantics(/*width=*/64, /*scale=*/32, /*isSigned=*/false,
76 /*isSaturated=*/false,
77 /*hasUnsignedPadding=*/false);
78}
79
80FixedPointSemantics getUSFractSema() {
81 return FixedPointSemantics(/*width=*/8, /*scale=*/8, /*isSigned=*/false,
82 /*isSaturated=*/false,
83 /*hasUnsignedPadding=*/false);
84}
85
86FixedPointSemantics getUFractSema() {
87 return FixedPointSemantics(/*width=*/16, /*scale=*/16, /*isSigned=*/false,
88 /*isSaturated=*/false,
89 /*hasUnsignedPadding=*/false);
90}
91
92FixedPointSemantics getULFractSema() {
93 return FixedPointSemantics(/*width=*/32, /*scale=*/32, /*isSigned=*/false,
94 /*isSaturated=*/false,
95 /*hasUnsignedPadding=*/false);
96}
97
98FixedPointSemantics getPadUSAccumSema() {
99 return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/false,
100 /*isSaturated=*/false,
101 /*hasUnsignedPadding=*/true);
102}
103
104FixedPointSemantics getPadUAccumSema() {
105 return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/false,
106 /*isSaturated=*/false,
107 /*hasUnsignedPadding=*/true);
108}
109
110FixedPointSemantics getPadULAccumSema() {
111 return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/false,
112 /*isSaturated=*/false,
113 /*hasUnsignedPadding=*/true);
114}
115
116FixedPointSemantics getPadUSFractSema() {
117 return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/false,
118 /*isSaturated=*/false,
119 /*hasUnsignedPadding=*/true);
120}
121
122FixedPointSemantics getPadUFractSema() {
123 return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/false,
124 /*isSaturated=*/false,
125 /*hasUnsignedPadding=*/true);
126}
127
128FixedPointSemantics getPadULFractSema() {
129 return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/false,
130 /*isSaturated=*/false,
131 /*hasUnsignedPadding=*/true);
132}
133
134void CheckUnpaddedMax(const FixedPointSemantics &Sema) {
135 ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
136 APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()));
137}
138
139void CheckPaddedMax(const FixedPointSemantics &Sema) {
140 ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
141 APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()) >> 1);
142}
143
144void CheckMin(const FixedPointSemantics &Sema) {
145 ASSERT_EQ(APFixedPoint::getMin(Sema).getValue(),
146 APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned()));
147}
148
149TEST(FixedPointTest, getMax) {
150 CheckUnpaddedMax(getSAccumSema());
151 CheckUnpaddedMax(getAccumSema());
152 CheckUnpaddedMax(getLAccumSema());
153 CheckUnpaddedMax(getUSAccumSema());
154 CheckUnpaddedMax(getUAccumSema());
155 CheckUnpaddedMax(getULAccumSema());
156 CheckUnpaddedMax(getSFractSema());
157 CheckUnpaddedMax(getFractSema());
158 CheckUnpaddedMax(getLFractSema());
159 CheckUnpaddedMax(getUSFractSema());
160 CheckUnpaddedMax(getUFractSema());
161 CheckUnpaddedMax(getULFractSema());
162
163 CheckPaddedMax(getPadUSAccumSema());
164 CheckPaddedMax(getPadUAccumSema());
165 CheckPaddedMax(getPadULAccumSema());
166 CheckPaddedMax(getPadUSFractSema());
167 CheckPaddedMax(getPadUFractSema());
168 CheckPaddedMax(getPadULFractSema());
169}
170
171TEST(FixedPointTest, getMin) {
172 CheckMin(getSAccumSema());
173 CheckMin(getAccumSema());
174 CheckMin(getLAccumSema());
175 CheckMin(getUSAccumSema());
176 CheckMin(getUAccumSema());
177 CheckMin(getULAccumSema());
178 CheckMin(getSFractSema());
179 CheckMin(getFractSema());
180 CheckMin(getLFractSema());
181 CheckMin(getUSFractSema());
182 CheckMin(getUFractSema());
183 CheckMin(getULFractSema());
184
185 CheckMin(getPadUSAccumSema());
186 CheckMin(getPadUAccumSema());
187 CheckMin(getPadULAccumSema());
188 CheckMin(getPadUSFractSema());
189 CheckMin(getPadUFractSema());
190 CheckMin(getPadULFractSema());
191}
192
193void CheckIntPart(const FixedPointSemantics &Sema, int64_t IntPart) {
194 unsigned Scale = Sema.getScale();
195
196 // Value with a fraction
197 APFixedPoint ValWithFract(APInt(Sema.getWidth(),
198 (IntPart << Scale) + (1ULL << (Scale - 1)),
199 Sema.isSigned()),
200 Sema);
201 ASSERT_EQ(ValWithFract.getIntPart(), IntPart);
202
203 // Just fraction
204 APFixedPoint JustFract(
205 APInt(Sema.getWidth(), (1ULL << (Scale - 1)), Sema.isSigned()), Sema);
206 ASSERT_EQ(JustFract.getIntPart(), 0);
207
208 // Whole number
209 APFixedPoint WholeNum(
210 APInt(Sema.getWidth(), (IntPart << Scale), Sema.isSigned()), Sema);
211 ASSERT_EQ(WholeNum.getIntPart(), IntPart);
212
213 // Negative
214 if (Sema.isSigned()) {
215 APFixedPoint Negative(
216 APInt(Sema.getWidth(), (IntPart << Scale), Sema.isSigned()), Sema);
217 ASSERT_EQ(Negative.getIntPart(), IntPart);
218 }
219}
220
221void CheckIntPartMin(const FixedPointSemantics &Sema, int64_t Expected) {
222 ASSERT_EQ(APFixedPoint::getMin(Sema).getIntPart(), Expected);
223}
224
225void CheckIntPartMax(const FixedPointSemantics &Sema, uint64_t Expected) {
226 ASSERT_EQ(APFixedPoint::getMax(Sema).getIntPart(), Expected);
227}
228
229TEST(FixedPoint, getIntPart) {
230 // Normal values
231 CheckIntPart(getSAccumSema(), 2);
232 CheckIntPart(getAccumSema(), 2);
233 CheckIntPart(getLAccumSema(), 2);
234 CheckIntPart(getUSAccumSema(), 2);
235 CheckIntPart(getUAccumSema(), 2);
236 CheckIntPart(getULAccumSema(), 2);
237
238 // Zero
239 CheckIntPart(getSAccumSema(), 0);
240 CheckIntPart(getAccumSema(), 0);
241 CheckIntPart(getLAccumSema(), 0);
242 CheckIntPart(getUSAccumSema(), 0);
243 CheckIntPart(getUAccumSema(), 0);
244 CheckIntPart(getULAccumSema(), 0);
245
246 CheckIntPart(getSFractSema(), 0);
247 CheckIntPart(getFractSema(), 0);
248 CheckIntPart(getLFractSema(), 0);
249 CheckIntPart(getUSFractSema(), 0);
250 CheckIntPart(getUFractSema(), 0);
251 CheckIntPart(getULFractSema(), 0);
252
253 // Min
254 CheckIntPartMin(getSAccumSema(), -256);
255 CheckIntPartMin(getAccumSema(), -65536);
256 CheckIntPartMin(getLAccumSema(), -4294967296);
257
258 CheckIntPartMin(getSFractSema(), -1);
259 CheckIntPartMin(getFractSema(), -1);
260 CheckIntPartMin(getLFractSema(), -1);
261
262 // Max
263 CheckIntPartMax(getSAccumSema(), 255);
264 CheckIntPartMax(getAccumSema(), 65535);
265 CheckIntPartMax(getLAccumSema(), 4294967295);
266 CheckIntPartMax(getUSAccumSema(), 255);
267 CheckIntPartMax(getUAccumSema(), 65535);
268 CheckIntPartMax(getULAccumSema(), 4294967295);
269
270 CheckIntPartMax(getSFractSema(), 0);
271 CheckIntPartMax(getFractSema(), 0);
272 CheckIntPartMax(getLFractSema(), 0);
273 CheckIntPartMax(getUSFractSema(), 0);
274 CheckIntPartMax(getUFractSema(), 0);
275 CheckIntPartMax(getULFractSema(), 0);
276
277 // Padded
278 // Normal Values
279 CheckIntPart(getPadUSAccumSema(), 2);
280 CheckIntPart(getPadUAccumSema(), 2);
281 CheckIntPart(getPadULAccumSema(), 2);
282
283 // Zero
284 CheckIntPart(getPadUSAccumSema(), 0);
285 CheckIntPart(getPadUAccumSema(), 0);
286 CheckIntPart(getPadULAccumSema(), 0);
287
288 CheckIntPart(getPadUSFractSema(), 0);
289 CheckIntPart(getPadUFractSema(), 0);
290 CheckIntPart(getPadULFractSema(), 0);
291
292 // Max
293 CheckIntPartMax(getPadUSAccumSema(), 255);
294 CheckIntPartMax(getPadUAccumSema(), 65535);
295 CheckIntPartMax(getPadULAccumSema(), 4294967295);
296
297 CheckIntPartMax(getPadUSFractSema(), 0);
298 CheckIntPartMax(getPadUFractSema(), 0);
299 CheckIntPartMax(getPadULFractSema(), 0);
300}
301
302TEST(FixedPoint, compare) {
303 // Equality
304 // With fractional part (2.5)
305 // Across sizes
306 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
307 APFixedPoint(81920, getAccumSema()));
308 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
309 APFixedPoint(5368709120, getLAccumSema()));
310 ASSERT_EQ(APFixedPoint(0, getSAccumSema()), APFixedPoint(0, getLAccumSema()));
311
312 // Across types (0.5)
313 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
314 APFixedPoint(64, getSFractSema()));
315 ASSERT_EQ(APFixedPoint(16384, getAccumSema()),
316 APFixedPoint(16384, getFractSema()));
317 ASSERT_EQ(APFixedPoint(1073741824, getLAccumSema()),
318 APFixedPoint(1073741824, getLFractSema()));
319
320 // Across widths and types (0.5)
321 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
322 APFixedPoint(16384, getFractSema()));
323 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
324 APFixedPoint(1073741824, getLFractSema()));
325
326 // Across saturation
327 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
328 APFixedPoint(81920, Saturated(getAccumSema())));
329
330 // Across signs
331 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
332 APFixedPoint(640, getUSAccumSema()));
333 ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),
334 APFixedPoint(-81920, getAccumSema()));
335
336 // Across padding
337 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
338 APFixedPoint(320, getPadUSAccumSema()));
339 ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),
340 APFixedPoint(320, getPadUSAccumSema()));
341
342 // Less than
343 ASSERT_LT(APFixedPoint(-1, getSAccumSema()), APFixedPoint(0, getAccumSema()));
344 ASSERT_LT(APFixedPoint(-1, getSAccumSema()),
345 APFixedPoint(0, getUAccumSema()));
346 ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getAccumSema()));
347 ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getUAccumSema()));
348 ASSERT_LT(APFixedPoint(0, getUSAccumSema()), APFixedPoint(1, getAccumSema()));
349 ASSERT_LT(APFixedPoint(0, getUSAccumSema()),
350 APFixedPoint(1, getUAccumSema()));
351
352 // Greater than
353 ASSERT_GT(APFixedPoint(0, getAccumSema()), APFixedPoint(-1, getSAccumSema()));
354 ASSERT_GT(APFixedPoint(0, getUAccumSema()),
355 APFixedPoint(-1, getSAccumSema()));
356 ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getSAccumSema()));
357 ASSERT_GT(APFixedPoint(1, getUAccumSema()), APFixedPoint(0, getSAccumSema()));
358 ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getUSAccumSema()));
359 ASSERT_GT(APFixedPoint(1, getUAccumSema()),
360 APFixedPoint(0, getUSAccumSema()));
361}
362
363// Check that a fixed point value in one sema is the same in another sema
364void CheckUnsaturatedConversion(FixedPointSemantics Src,
365 FixedPointSemantics Dst, int64_t TestVal) {
366 int64_t ScaledVal = TestVal;
367 if (Dst.getScale() > Src.getScale()) {
368 ScaledVal <<= (Dst.getScale() - Src.getScale());
369 } else {
370 ScaledVal >>= (Src.getScale() - Dst.getScale());
371 }
372
373 APFixedPoint Fixed(TestVal, Src);
374 APFixedPoint Expected(ScaledVal, Dst);
375 ASSERT_EQ(Fixed.convert(Dst), Expected);
376}
377
378// Check the value in a given fixed point sema overflows to the saturated min
379// for another sema
380void CheckSaturatedConversionMin(FixedPointSemantics Src,
381 FixedPointSemantics Dst, int64_t TestVal) {
382 APFixedPoint Fixed(TestVal, Src);
383 ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMin(Dst));
384}
385
386// Check the value in a given fixed point sema overflows to the saturated max
387// for another sema
388void CheckSaturatedConversionMax(FixedPointSemantics Src,
389 FixedPointSemantics Dst, int64_t TestVal) {
390 APFixedPoint Fixed(TestVal, Src);
391 ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMax(Dst));
392}
393
394// Check one signed _Accum sema converted to other sema for different values.
395void CheckSignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
396 int64_t OneVal) {
397 int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
398 int64_t HalfVal = (OneVal / 2); // 0.5
399
400 // +Accums to Accums
401 CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);
402 CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);
403 CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);
404 CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);
405 CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);
406 CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);
407 CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);
408 CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);
409 CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);
410
411 // -Accums to Accums
412 CheckUnsaturatedConversion(Src, getSAccumSema(), -NormalVal);
413 CheckUnsaturatedConversion(Src, getAccumSema(), -NormalVal);
414 CheckUnsaturatedConversion(Src, getLAccumSema(), -NormalVal);
415 CheckSaturatedConversionMin(Src, Saturated(getUSAccumSema()), -NormalVal);
416 CheckSaturatedConversionMin(Src, Saturated(getUAccumSema()), -NormalVal);
417 CheckSaturatedConversionMin(Src, Saturated(getULAccumSema()), -NormalVal);
418 CheckSaturatedConversionMin(Src, Saturated(getPadUSAccumSema()), -NormalVal);
419 CheckSaturatedConversionMin(Src, Saturated(getPadUAccumSema()), -NormalVal);
420 CheckSaturatedConversionMin(Src, Saturated(getPadULAccumSema()), -NormalVal);
421
422 // +Accums to Fracts
423 CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);
424 CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);
425 CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);
426 CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);
427 CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);
428 CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);
429 CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);
430 CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);
431 CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);
432
433 // -Accums to Fracts
434 CheckUnsaturatedConversion(Src, getSFractSema(), -HalfVal);
435 CheckUnsaturatedConversion(Src, getFractSema(), -HalfVal);
436 CheckUnsaturatedConversion(Src, getLFractSema(), -HalfVal);
437 CheckSaturatedConversionMin(Src, Saturated(getUSFractSema()), -HalfVal);
438 CheckSaturatedConversionMin(Src, Saturated(getUFractSema()), -HalfVal);
439 CheckSaturatedConversionMin(Src, Saturated(getULFractSema()), -HalfVal);
440 CheckSaturatedConversionMin(Src, Saturated(getPadUSFractSema()), -HalfVal);
441 CheckSaturatedConversionMin(Src, Saturated(getPadUFractSema()), -HalfVal);
442 CheckSaturatedConversionMin(Src, Saturated(getPadULFractSema()), -HalfVal);
443
444 // 0 to Accums
445 CheckUnsaturatedConversion(Src, getSAccumSema(), 0);
446 CheckUnsaturatedConversion(Src, getAccumSema(), 0);
447 CheckUnsaturatedConversion(Src, getLAccumSema(), 0);
448 CheckUnsaturatedConversion(Src, getUSAccumSema(), 0);
449 CheckUnsaturatedConversion(Src, getUAccumSema(), 0);
450 CheckUnsaturatedConversion(Src, getULAccumSema(), 0);
451 CheckUnsaturatedConversion(Src, getPadUSAccumSema(), 0);
452 CheckUnsaturatedConversion(Src, getPadUAccumSema(), 0);
453 CheckUnsaturatedConversion(Src, getPadULAccumSema(), 0);
454
455 // 0 to Fracts
456 CheckUnsaturatedConversion(Src, getSFractSema(), 0);
457 CheckUnsaturatedConversion(Src, getFractSema(), 0);
458 CheckUnsaturatedConversion(Src, getLFractSema(), 0);
459 CheckUnsaturatedConversion(Src, getUSFractSema(), 0);
460 CheckUnsaturatedConversion(Src, getUFractSema(), 0);
461 CheckUnsaturatedConversion(Src, getULFractSema(), 0);
462 CheckUnsaturatedConversion(Src, getPadUSFractSema(), 0);
463 CheckUnsaturatedConversion(Src, getPadUFractSema(), 0);
464 CheckUnsaturatedConversion(Src, getPadULFractSema(), 0);
465}
466
467// Check one unsigned _Accum sema converted to other sema for different
468// values.
469void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
470 int64_t OneVal) {
471 int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
472 int64_t HalfVal = (OneVal / 2); // 0.5
473
474 // +UAccums to Accums
475 CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);
476 CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);
477 CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);
478 CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);
479 CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);
480 CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);
481 CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);
482 CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);
483 CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);
484
485 // +UAccums to Fracts
486 CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);
487 CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);
488 CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);
489 CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);
490 CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);
491 CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);
492 CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);
493 CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);
494 CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);
495}
496
497TEST(FixedPoint, AccumConversions) {
498 // Normal conversions
499 CheckSignedAccumConversionsAgainstOthers(getSAccumSema(), 128);
500 CheckUnsignedAccumConversionsAgainstOthers(getUSAccumSema(), 256);
501 CheckSignedAccumConversionsAgainstOthers(getAccumSema(), 32768);
502 CheckUnsignedAccumConversionsAgainstOthers(getUAccumSema(), 65536);
503 CheckSignedAccumConversionsAgainstOthers(getLAccumSema(), 2147483648);
504 CheckUnsignedAccumConversionsAgainstOthers(getULAccumSema(), 4294967296);
505
506 CheckUnsignedAccumConversionsAgainstOthers(getPadUSAccumSema(), 128);
507 CheckUnsignedAccumConversionsAgainstOthers(getPadUAccumSema(), 32768);
508 CheckUnsignedAccumConversionsAgainstOthers(getPadULAccumSema(), 2147483648);
509}
510
511TEST(FixedPoint, AccumConversionOverflow) {
512 // To SAccum max limit (65536)
513 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getAccumSema()),
514 140737488355328);
515 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUAccumSema()),
516 140737488355328);
517 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUAccumSema()),
518 140737488355328);
519 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getAccumSema()),
520 281474976710656);
521 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUAccumSema()),
522 281474976710656);
523 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUAccumSema()),
524 281474976710656);
525
526 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getAccumSema()),
527 140737488355328);
528 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUAccumSema()),
529 140737488355328);
530 CheckSaturatedConversionMax(getPadULAccumSema(),
531 Saturated(getPadUAccumSema()), 140737488355328);
532
533 // To SAccum min limit (-65536)
534 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getAccumSema()),
535 -140737488355328);
536 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUAccumSema()),
537 -140737488355328);
538 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUAccumSema()),
539 -140737488355328);
540}
541
542TEST(FixedPoint, SAccumConversionOverflow) {
543 // To SAccum max limit (256)
544 CheckSaturatedConversionMax(getAccumSema(), Saturated(getSAccumSema()),
545 8388608);
546 CheckSaturatedConversionMax(getAccumSema(), Saturated(getUSAccumSema()),
547 8388608);
548 CheckSaturatedConversionMax(getAccumSema(), Saturated(getPadUSAccumSema()),
549 8388608);
550 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getSAccumSema()),
551 16777216);
552 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getUSAccumSema()),
553 16777216);
554 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getPadUSAccumSema()),
555 16777216);
556 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getSAccumSema()),
557 549755813888);
558 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUSAccumSema()),
559 549755813888);
560 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUSAccumSema()),
561 549755813888);
562 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getSAccumSema()),
563 1099511627776);
564 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUSAccumSema()),
565 1099511627776);
566 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUSAccumSema()),
567 1099511627776);
568
569 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getSAccumSema()),
570 8388608);
571 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getUSAccumSema()),
572 8388608);
573 CheckSaturatedConversionMax(getPadUAccumSema(),
574 Saturated(getPadUSAccumSema()), 8388608);
575 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getSAccumSema()),
576 549755813888);
577 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUSAccumSema()),
578 549755813888);
579 CheckSaturatedConversionMax(getPadULAccumSema(),
580 Saturated(getPadUSAccumSema()), 549755813888);
581
582 // To SAccum min limit (-256)
583 CheckSaturatedConversionMin(getAccumSema(), Saturated(getSAccumSema()),
584 -8388608);
585 CheckSaturatedConversionMin(getAccumSema(), Saturated(getUSAccumSema()),
586 -8388608);
587 CheckSaturatedConversionMin(getAccumSema(), Saturated(getPadUSAccumSema()),
588 -8388608);
589 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getSAccumSema()),
590 -549755813888);
591 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUSAccumSema()),
592 -549755813888);
593 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUSAccumSema()),
594 -549755813888);
595}
596
597void CheckSaturatedConversionToFractMax(FixedPointSemantics Src,
598 int64_t OneVal) {
599 CheckSaturatedConversionMax(Src, Saturated(getSFractSema()), OneVal);
600 CheckSaturatedConversionMax(Src, Saturated(getFractSema()), OneVal);
601 CheckSaturatedConversionMax(Src, Saturated(getLFractSema()), OneVal);
602 CheckSaturatedConversionMax(Src, Saturated(getUSFractSema()), OneVal);
603 CheckSaturatedConversionMax(Src, Saturated(getUFractSema()), OneVal);
604 CheckSaturatedConversionMax(Src, Saturated(getPadULFractSema()), OneVal);
605 CheckSaturatedConversionMax(Src, Saturated(getPadUSFractSema()), OneVal);
606 CheckSaturatedConversionMax(Src, Saturated(getPadUFractSema()), OneVal);
607 CheckSaturatedConversionMax(Src, Saturated(getPadULFractSema()), OneVal);
608}
609
610void CheckSaturatedConversionToFractMin(FixedPointSemantics Src,
611 int64_t MinusOneVal) {
612 CheckSaturatedConversionMin(Src, Saturated(getSFractSema()), MinusOneVal);
613 CheckSaturatedConversionMin(Src, Saturated(getFractSema()), MinusOneVal);
614 CheckSaturatedConversionMin(Src, Saturated(getLFractSema()), MinusOneVal);
615 CheckSaturatedConversionMin(Src, Saturated(getUSFractSema()), MinusOneVal);
616 CheckSaturatedConversionMin(Src, Saturated(getUFractSema()), MinusOneVal);
617 CheckSaturatedConversionMin(Src, Saturated(getPadULFractSema()), MinusOneVal);
618 CheckSaturatedConversionMin(Src, Saturated(getPadUSFractSema()), MinusOneVal);
619 CheckSaturatedConversionMin(Src, Saturated(getPadUFractSema()), MinusOneVal);
620 CheckSaturatedConversionMin(Src, Saturated(getPadULFractSema()), MinusOneVal);
621}
622
623TEST(FixedPoint, OverflowConversionsToFract) {
624 CheckSaturatedConversionToFractMax(getSAccumSema(), 128);
625 CheckSaturatedConversionToFractMin(getSAccumSema(), -128);
626 CheckSaturatedConversionToFractMax(getAccumSema(), 32768);
627 CheckSaturatedConversionToFractMin(getAccumSema(), -32768);
628 CheckSaturatedConversionToFractMax(getLAccumSema(), 2147483648);
629 CheckSaturatedConversionToFractMin(getLAccumSema(), -2147483648);
630
631 // Unsigned
632 CheckSaturatedConversionToFractMax(getUSAccumSema(), 256);
633 CheckSaturatedConversionToFractMax(getUAccumSema(), 65536);
634 CheckSaturatedConversionToFractMax(getULAccumSema(), 4294967296);
635
636 // Padded unsigned
637 CheckSaturatedConversionToFractMax(getPadUSAccumSema(), 128);
638 CheckSaturatedConversionToFractMax(getPadUAccumSema(), 32768);
639 CheckSaturatedConversionToFractMax(getPadULAccumSema(), 2147483648);
640}
641
642TEST(FixedPoint, GetValueSignAfterConversion) {
643 APFixedPoint Fixed(255 << 7, getSAccumSema());
644 ASSERT_TRUE(Fixed.getValue().isSigned());
645 APFixedPoint UFixed = Fixed.convert(getUSAccumSema());
646 ASSERT_TRUE(UFixed.getValue().isUnsigned());
647 ASSERT_EQ(UFixed.getValue(), APSInt::getUnsigned(255 << 8).extOrTrunc(16));
648}
649
650TEST(FixedPoint, ModularWrapAround) {
651 // Positive to negative
652 APFixedPoint Val = APFixedPoint(1ULL << 7, getSAccumSema());
653 ASSERT_EQ(Val.convert(getLFractSema()).getValue(), -(1ULL << 31));
654
655 Val = APFixedPoint(1ULL << 23, getAccumSema());
656 ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), -(1ULL << 15));
657
658 Val = APFixedPoint(1ULL << 47, getLAccumSema());
659 ASSERT_EQ(Val.convert(getAccumSema()).getValue(), -(1ULL << 31));
660
661 // Negative to positive
662 Val = APFixedPoint(/*-1.5*/ -192, getSAccumSema());
663 ASSERT_EQ(Val.convert(getLFractSema()).getValue(), 1ULL << 30);
664
665 Val = APFixedPoint(-(257 << 15), getAccumSema());
666 ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), 255 << 7);
667
668 Val = APFixedPoint(-(65537ULL << 31), getLAccumSema());
669 ASSERT_EQ(Val.convert(getAccumSema()).getValue(), 65535 << 15);
670
671 // Signed to unsigned
672 Val = APFixedPoint(-(1 << 7), getSAccumSema());
673 ASSERT_EQ(Val.convert(getUSAccumSema()).getValue(), 255 << 8);
674
675 Val = APFixedPoint(-(1 << 15), getAccumSema());
676 ASSERT_EQ(Val.convert(getUAccumSema()).getValue(), 65535ULL << 16);
677
678 Val = APFixedPoint(-(1ULL << 31), getLAccumSema());
679 ASSERT_EQ(Val.convert(getULAccumSema()).getValue().getZExtValue(),
680 4294967295ULL << 32);
681}
682
683} // namespace