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