Clang Project

clang_source_code/unittests/Basic/FixedPointTest.cpp
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
13using clang::APFixedPoint;
14using clang::FixedPointSemantics;
15using llvm::APInt;
16using llvm::APSInt;
17
18namespace {
19
20FixedPointSemantics Saturated(FixedPointSemantics Sema) {
21  Sema.setSaturated(true);
22  return Sema;
23}
24
25FixedPointSemantics getSAccumSema() {
26  return FixedPointSemantics(/*width=*/16/*scale=*/7/*isSigned=*/true,
27                             /*isSaturated=*/false,
28                             /*hasUnsignedPadding=*/false);
29}
30
31FixedPointSemantics getAccumSema() {
32  return FixedPointSemantics(/*width=*/32/*scale=*/15/*isSigned=*/true,
33                             /*isSaturated=*/false,
34                             /*hasUnsignedPadding=*/false);
35}
36
37FixedPointSemantics getLAccumSema() {
38  return FixedPointSemantics(/*width=*/64/*scale=*/31/*isSigned=*/true,
39                             /*isSaturated=*/false,
40                             /*hasUnsignedPadding=*/false);
41}
42
43FixedPointSemantics getSFractSema() {
44  return FixedPointSemantics(/*width=*/8/*scale=*/7/*isSigned=*/true,
45                             /*isSaturated=*/false,
46                             /*hasUnsignedPadding=*/false);
47}
48
49FixedPointSemantics getFractSema() {
50  return FixedPointSemantics(/*width=*/16/*scale=*/15/*isSigned=*/true,
51                             /*isSaturated=*/false,
52                             /*hasUnsignedPadding=*/false);
53}
54
55FixedPointSemantics getLFractSema() {
56  return FixedPointSemantics(/*width=*/32/*scale=*/31/*isSigned=*/true,
57                             /*isSaturated=*/false,
58                             /*hasUnsignedPadding=*/false);
59}
60
61FixedPointSemantics getUSAccumSema() {
62  return FixedPointSemantics(/*width=*/16/*scale=*/8/*isSigned=*/false,
63                             /*isSaturated=*/false,
64                             /*hasUnsignedPadding=*/false);
65}
66
67FixedPointSemantics getUAccumSema() {
68  return FixedPointSemantics(/*width=*/32/*scale=*/16/*isSigned=*/false,
69                             /*isSaturated=*/false,
70                             /*hasUnsignedPadding=*/false);
71}
72
73FixedPointSemantics getULAccumSema() {
74  return FixedPointSemantics(/*width=*/64/*scale=*/32/*isSigned=*/false,
75                             /*isSaturated=*/false,
76                             /*hasUnsignedPadding=*/false);
77}
78
79FixedPointSemantics getUSFractSema() {
80  return FixedPointSemantics(/*width=*/8/*scale=*/8/*isSigned=*/false,
81                             /*isSaturated=*/false,
82                             /*hasUnsignedPadding=*/false);
83}
84
85FixedPointSemantics getUFractSema() {
86  return FixedPointSemantics(/*width=*/16/*scale=*/16/*isSigned=*/false,
87                             /*isSaturated=*/false,
88                             /*hasUnsignedPadding=*/false);
89}
90
91FixedPointSemantics getULFractSema() {
92  return FixedPointSemantics(/*width=*/32/*scale=*/32/*isSigned=*/false,
93                             /*isSaturated=*/false,
94                             /*hasUnsignedPadding=*/false);
95}
96
97FixedPointSemantics getPadUSAccumSema() {
98  return FixedPointSemantics(/*width=*/16/*scale=*/7/*isSigned=*/false,
99                             /*isSaturated=*/false,
100                             /*hasUnsignedPadding=*/true);
101}
102
103FixedPointSemantics getPadUAccumSema() {
104  return FixedPointSemantics(/*width=*/32/*scale=*/15/*isSigned=*/false,
105                             /*isSaturated=*/false,
106                             /*hasUnsignedPadding=*/true);
107}
108
109FixedPointSemantics getPadULAccumSema() {
110  return FixedPointSemantics(/*width=*/64/*scale=*/31/*isSigned=*/false,
111                             /*isSaturated=*/false,
112                             /*hasUnsignedPadding=*/true);
113}
114
115FixedPointSemantics getPadUSFractSema() {
116  return FixedPointSemantics(/*width=*/8/*scale=*/7/*isSigned=*/false,
117                             /*isSaturated=*/false,
118                             /*hasUnsignedPadding=*/true);
119}
120
121FixedPointSemantics getPadUFractSema() {
122  return FixedPointSemantics(/*width=*/16/*scale=*/15/*isSigned=*/false,
123                             /*isSaturated=*/false,
124                             /*hasUnsignedPadding=*/true);
125}
126
127FixedPointSemantics getPadULFractSema() {
128  return FixedPointSemantics(/*width=*/32/*scale=*/31/*isSigned=*/false,
129                             /*isSaturated=*/false,
130                             /*hasUnsignedPadding=*/true);
131}
132
133void CheckUnpaddedMax(const FixedPointSemantics &Sema) {
134  ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
135            APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()));
136}
137
138void CheckPaddedMax(const FixedPointSemantics &Sema) {
139  ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
140            APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()) >> 1);
141}
142
143void CheckMin(const FixedPointSemantics &Sema) {
144  ASSERT_EQ(APFixedPoint::getMin(Sema).getValue(),
145            APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned()));
146}
147
148TEST(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
170TEST(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
192void 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
220void CheckIntPartMin(const FixedPointSemantics &Sema, int64_t Expected) {
221  ASSERT_EQ(APFixedPoint::getMin(Sema).getIntPart(), Expected);
222}
223
224void CheckIntPartMax(const FixedPointSemantics &Sema, uint64_t Expected) {
225  ASSERT_EQ(APFixedPoint::getMax(Sema).getIntPart(), Expected);
226}
227
228TEST(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
301TEST(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
363void 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
386void 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
394void 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.
401void 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.
475void 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
503TEST(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
517TEST(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
548TEST(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
603TEST(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
611TEST(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