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