1//===- unittests/ADT/FixedPointTest.cpp -- fixed point number tests -----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ADT/APFixedPoint.h"
10#include "llvm/ADT/APFloat.h"
11#include "llvm/ADT/APSInt.h"
12#include "gtest/gtest.h"
13
14using llvm::APFixedPoint;
15using llvm::APFloat;
16using llvm::APInt;
17using llvm::APSInt;
18using llvm::FixedPointSemantics;
19
20namespace {
21
22FixedPointSemantics Saturated(FixedPointSemantics Sema) {
23 Sema.setSaturated(true);
24 return Sema;
25}
26
27FixedPointSemantics getSAccumSema() {
28 return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/true,
29 /*isSaturated=*/false,
30 /*hasUnsignedPadding=*/false);
31}
32
33FixedPointSemantics getAccumSema() {
34 return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/true,
35 /*isSaturated=*/false,
36 /*hasUnsignedPadding=*/false);
37}
38
39FixedPointSemantics getLAccumSema() {
40 return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/true,
41 /*isSaturated=*/false,
42 /*hasUnsignedPadding=*/false);
43}
44
45FixedPointSemantics getSFractSema() {
46 return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/true,
47 /*isSaturated=*/false,
48 /*hasUnsignedPadding=*/false);
49}
50
51FixedPointSemantics getFractSema() {
52 return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/true,
53 /*isSaturated=*/false,
54 /*hasUnsignedPadding=*/false);
55}
56
57FixedPointSemantics getLFractSema() {
58 return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/true,
59 /*isSaturated=*/false,
60 /*hasUnsignedPadding=*/false);
61}
62
63FixedPointSemantics getUSAccumSema() {
64 return FixedPointSemantics(/*width=*/16, /*scale=*/8, /*isSigned=*/false,
65 /*isSaturated=*/false,
66 /*hasUnsignedPadding=*/false);
67}
68
69FixedPointSemantics getUAccumSema() {
70 return FixedPointSemantics(/*width=*/32, /*scale=*/16, /*isSigned=*/false,
71 /*isSaturated=*/false,
72 /*hasUnsignedPadding=*/false);
73}
74
75FixedPointSemantics getULAccumSema() {
76 return FixedPointSemantics(/*width=*/64, /*scale=*/32, /*isSigned=*/false,
77 /*isSaturated=*/false,
78 /*hasUnsignedPadding=*/false);
79}
80
81FixedPointSemantics getUSFractSema() {
82 return FixedPointSemantics(/*width=*/8, /*scale=*/8, /*isSigned=*/false,
83 /*isSaturated=*/false,
84 /*hasUnsignedPadding=*/false);
85}
86
87FixedPointSemantics getUFractSema() {
88 return FixedPointSemantics(/*width=*/16, /*scale=*/16, /*isSigned=*/false,
89 /*isSaturated=*/false,
90 /*hasUnsignedPadding=*/false);
91}
92
93FixedPointSemantics getULFractSema() {
94 return FixedPointSemantics(/*width=*/32, /*scale=*/32, /*isSigned=*/false,
95 /*isSaturated=*/false,
96 /*hasUnsignedPadding=*/false);
97}
98
99FixedPointSemantics getPadUSAccumSema() {
100 return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/false,
101 /*isSaturated=*/false,
102 /*hasUnsignedPadding=*/true);
103}
104
105FixedPointSemantics getPadUAccumSema() {
106 return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/false,
107 /*isSaturated=*/false,
108 /*hasUnsignedPadding=*/true);
109}
110
111FixedPointSemantics getPadULAccumSema() {
112 return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/false,
113 /*isSaturated=*/false,
114 /*hasUnsignedPadding=*/true);
115}
116
117FixedPointSemantics getPadUSFractSema() {
118 return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/false,
119 /*isSaturated=*/false,
120 /*hasUnsignedPadding=*/true);
121}
122
123FixedPointSemantics getPadUFractSema() {
124 return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/false,
125 /*isSaturated=*/false,
126 /*hasUnsignedPadding=*/true);
127}
128
129FixedPointSemantics getPadULFractSema() {
130 return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/false,
131 /*isSaturated=*/false,
132 /*hasUnsignedPadding=*/true);
133}
134
135FixedPointSemantics getU8Neg10() {
136 return FixedPointSemantics(/*width=*/8, /*lsb=*/FixedPointSemantics::Lsb{.LsbWeight: -10},
137 /*isSigned=*/false,
138 /*isSaturated=*/false,
139 /*hasUnsignedPadding=*/false);
140}
141
142FixedPointSemantics getS16Neg18() {
143 return FixedPointSemantics(/*width=*/16,
144 /*lsb=*/FixedPointSemantics::Lsb{.LsbWeight: -18},
145 /*isSigned=*/true,
146 /*isSaturated=*/false,
147 /*hasUnsignedPadding=*/false);
148}
149
150FixedPointSemantics getU8Pos4() {
151 return FixedPointSemantics(/*width=*/8, /*lsb=*/FixedPointSemantics::Lsb{.LsbWeight: 4},
152 /*isSigned=*/false,
153 /*isSaturated=*/false,
154 /*hasUnsignedPadding=*/false);
155}
156
157FixedPointSemantics getS32Pos2() {
158 return FixedPointSemantics(/*width=*/32, /*lsb=*/FixedPointSemantics::Lsb{.LsbWeight: 2},
159 /*isSigned=*/true,
160 /*isSaturated=*/false,
161 /*hasUnsignedPadding=*/false);
162}
163
164void CheckUnpaddedMax(const FixedPointSemantics &Sema) {
165 ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
166 APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()));
167}
168
169void CheckPaddedMax(const FixedPointSemantics &Sema) {
170 ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
171 APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()) >> 1);
172}
173
174void CheckMin(const FixedPointSemantics &Sema) {
175 ASSERT_EQ(APFixedPoint::getMin(Sema).getValue(),
176 APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned()));
177}
178
179TEST(FixedPointTest, getMax) {
180 CheckUnpaddedMax(Sema: getSAccumSema());
181 CheckUnpaddedMax(Sema: getAccumSema());
182 CheckUnpaddedMax(Sema: getLAccumSema());
183 CheckUnpaddedMax(Sema: getUSAccumSema());
184 CheckUnpaddedMax(Sema: getUAccumSema());
185 CheckUnpaddedMax(Sema: getULAccumSema());
186 CheckUnpaddedMax(Sema: getSFractSema());
187 CheckUnpaddedMax(Sema: getFractSema());
188 CheckUnpaddedMax(Sema: getLFractSema());
189 CheckUnpaddedMax(Sema: getUSFractSema());
190 CheckUnpaddedMax(Sema: getUFractSema());
191 CheckUnpaddedMax(Sema: getULFractSema());
192 CheckUnpaddedMax(Sema: getU8Neg10());
193 CheckUnpaddedMax(Sema: getS16Neg18());
194 CheckUnpaddedMax(Sema: getU8Pos4());
195 CheckUnpaddedMax(Sema: getS32Pos2());
196
197 CheckPaddedMax(Sema: getPadUSAccumSema());
198 CheckPaddedMax(Sema: getPadUAccumSema());
199 CheckPaddedMax(Sema: getPadULAccumSema());
200 CheckPaddedMax(Sema: getPadUSFractSema());
201 CheckPaddedMax(Sema: getPadUFractSema());
202 CheckPaddedMax(Sema: getPadULFractSema());
203}
204
205TEST(FixedPointTest, getMin) {
206 CheckMin(Sema: getSAccumSema());
207 CheckMin(Sema: getAccumSema());
208 CheckMin(Sema: getLAccumSema());
209 CheckMin(Sema: getUSAccumSema());
210 CheckMin(Sema: getUAccumSema());
211 CheckMin(Sema: getULAccumSema());
212 CheckMin(Sema: getSFractSema());
213 CheckMin(Sema: getFractSema());
214 CheckMin(Sema: getLFractSema());
215 CheckMin(Sema: getUSFractSema());
216 CheckMin(Sema: getUFractSema());
217 CheckMin(Sema: getULFractSema());
218 CheckMin(Sema: getU8Neg10());
219 CheckMin(Sema: getS16Neg18());
220 CheckMin(Sema: getU8Pos4());
221 CheckMin(Sema: getS32Pos2());
222
223 CheckMin(Sema: getPadUSAccumSema());
224 CheckMin(Sema: getPadUAccumSema());
225 CheckMin(Sema: getPadULAccumSema());
226 CheckMin(Sema: getPadUSFractSema());
227 CheckMin(Sema: getPadUFractSema());
228 CheckMin(Sema: getPadULFractSema());
229}
230
231int64_t relativeShr(int64_t Int, int64_t Shift) {
232 return (Shift > 0) ? Int >> Shift : Int << -Shift;
233}
234
235void CheckIntPart(const FixedPointSemantics &Sema, int64_t IntPart) {
236 int64_t FullFactPart =
237 (Sema.getLsbWeight() > 0) ? 0 : (1ULL << (-Sema.getLsbWeight() - 1));
238
239 // Value with a fraction
240 APFixedPoint ValWithFract(
241 APInt(Sema.getWidth(),
242 relativeShr(Int: IntPart, Shift: Sema.getLsbWeight()) + FullFactPart,
243 Sema.isSigned()),
244 Sema);
245 ASSERT_EQ(ValWithFract.getIntPart(), IntPart);
246
247 // Just fraction
248 APFixedPoint JustFract(APInt(Sema.getWidth(), FullFactPart, Sema.isSigned()),
249 Sema);
250 ASSERT_EQ(JustFract.getIntPart(), 0);
251
252 // Whole number
253 APFixedPoint WholeNum(APInt(Sema.getWidth(),
254 relativeShr(Int: IntPart, Shift: Sema.getLsbWeight()),
255 Sema.isSigned()),
256 Sema);
257 ASSERT_EQ(WholeNum.getIntPart(), IntPart);
258
259 // Negative
260 if (Sema.isSigned()) {
261 APFixedPoint Negative(APInt(Sema.getWidth(),
262 relativeShr(Int: IntPart, Shift: Sema.getLsbWeight()),
263 Sema.isSigned()),
264 Sema);
265 ASSERT_EQ(Negative.getIntPart(), IntPart);
266 }
267}
268
269void CheckIntPartMin(const FixedPointSemantics &Sema, int64_t Expected) {
270 EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMin(Sema).getIntPart(),
271 APSInt::get(Expected)) == 0);
272}
273
274void CheckIntPartMax(const FixedPointSemantics &Sema, uint64_t Expected) {
275 EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMax(Sema).getIntPart(),
276 APSInt::getUnsigned(Expected)) == 0);
277}
278
279void CheckIntPartRes(const FixedPointSemantics &Sema, int64_t Representation,
280 uint64_t Result) {
281 APFixedPoint Val(Representation, Sema);
282 ASSERT_EQ(Val.getIntPart().getZExtValue(), Result) ;
283}
284
285TEST(FixedPoint, getIntPart) {
286 // Normal values
287 CheckIntPart(Sema: getSAccumSema(), IntPart: 2);
288 CheckIntPart(Sema: getAccumSema(), IntPart: 2);
289 CheckIntPart(Sema: getLAccumSema(), IntPart: 2);
290 CheckIntPart(Sema: getUSAccumSema(), IntPart: 2);
291 CheckIntPart(Sema: getUAccumSema(), IntPart: 2);
292 CheckIntPart(Sema: getULAccumSema(), IntPart: 2);
293 CheckIntPart(Sema: getU8Pos4(), IntPart: 32);
294 CheckIntPart(Sema: getS32Pos2(), IntPart: 32);
295
296 // Zero
297 CheckIntPart(Sema: getSAccumSema(), IntPart: 0);
298 CheckIntPart(Sema: getAccumSema(), IntPart: 0);
299 CheckIntPart(Sema: getLAccumSema(), IntPart: 0);
300 CheckIntPart(Sema: getUSAccumSema(), IntPart: 0);
301 CheckIntPart(Sema: getUAccumSema(), IntPart: 0);
302 CheckIntPart(Sema: getULAccumSema(), IntPart: 0);
303
304 CheckIntPart(Sema: getSFractSema(), IntPart: 0);
305 CheckIntPart(Sema: getFractSema(), IntPart: 0);
306 CheckIntPart(Sema: getLFractSema(), IntPart: 0);
307 CheckIntPart(Sema: getUSFractSema(), IntPart: 0);
308 CheckIntPart(Sema: getUFractSema(), IntPart: 0);
309 CheckIntPart(Sema: getULFractSema(), IntPart: 0);
310
311 CheckIntPart(Sema: getS16Neg18(), IntPart: 0);
312 CheckIntPart(Sema: getU8Neg10(), IntPart: 0);
313 CheckIntPart(Sema: getU8Pos4(), IntPart: 0);
314 CheckIntPart(Sema: getS32Pos2(), IntPart: 0);
315
316 // Min
317 CheckIntPartMin(Sema: getSAccumSema(), Expected: -256);
318 CheckIntPartMin(Sema: getAccumSema(), Expected: -65536);
319 CheckIntPartMin(Sema: getLAccumSema(), Expected: -4294967296);
320
321 CheckIntPartMin(Sema: getSFractSema(), Expected: -1);
322 CheckIntPartMin(Sema: getFractSema(), Expected: -1);
323 CheckIntPartMin(Sema: getLFractSema(), Expected: -1);
324
325 CheckIntPartMin(Sema: getS32Pos2(), Expected: -8589934592);
326
327 // Max
328 CheckIntPartMax(Sema: getSAccumSema(), Expected: 255);
329 CheckIntPartMax(Sema: getAccumSema(), Expected: 65535);
330 CheckIntPartMax(Sema: getLAccumSema(), Expected: 4294967295);
331 CheckIntPartMax(Sema: getUSAccumSema(), Expected: 255);
332 CheckIntPartMax(Sema: getUAccumSema(), Expected: 65535);
333 CheckIntPartMax(Sema: getULAccumSema(), Expected: 4294967295);
334
335 CheckIntPartMax(Sema: getU8Pos4(), Expected: 255 << 4);
336 CheckIntPartMax(Sema: getS32Pos2(), Expected: 2147483647ull << 2);
337
338 CheckIntPartMax(Sema: getSFractSema(), Expected: 0);
339 CheckIntPartMax(Sema: getFractSema(), Expected: 0);
340 CheckIntPartMax(Sema: getLFractSema(), Expected: 0);
341 CheckIntPartMax(Sema: getUSFractSema(), Expected: 0);
342 CheckIntPartMax(Sema: getUFractSema(), Expected: 0);
343 CheckIntPartMax(Sema: getULFractSema(), Expected: 0);
344
345 // Padded
346 // Normal Values
347 CheckIntPart(Sema: getPadUSAccumSema(), IntPart: 2);
348 CheckIntPart(Sema: getPadUAccumSema(), IntPart: 2);
349 CheckIntPart(Sema: getPadULAccumSema(), IntPart: 2);
350
351 // Zero
352 CheckIntPart(Sema: getPadUSAccumSema(), IntPart: 0);
353 CheckIntPart(Sema: getPadUAccumSema(), IntPart: 0);
354 CheckIntPart(Sema: getPadULAccumSema(), IntPart: 0);
355
356 CheckIntPart(Sema: getPadUSFractSema(), IntPart: 0);
357 CheckIntPart(Sema: getPadUFractSema(), IntPart: 0);
358 CheckIntPart(Sema: getPadULFractSema(), IntPart: 0);
359
360 // Max
361 CheckIntPartMax(Sema: getPadUSAccumSema(), Expected: 255);
362 CheckIntPartMax(Sema: getPadUAccumSema(), Expected: 65535);
363 CheckIntPartMax(Sema: getPadULAccumSema(), Expected: 4294967295);
364
365 CheckIntPartMax(Sema: getPadUSFractSema(), Expected: 0);
366 CheckIntPartMax(Sema: getPadUFractSema(), Expected: 0);
367 CheckIntPartMax(Sema: getPadULFractSema(), Expected: 0);
368
369 // Rounded Towards Zero
370 CheckIntPartRes(Sema: getSFractSema(), Representation: -127, Result: 0);
371 CheckIntPartRes(Sema: getFractSema(), Representation: -32767, Result: 0);
372 CheckIntPartRes(Sema: getLFractSema(), Representation: -2147483647, Result: 0);
373 CheckIntPartRes(Sema: getS16Neg18(), Representation: -32768, Result: 0);
374}
375
376TEST(FixedPoint, compare) {
377 // Equality
378 // With fractional part (2.5)
379 // Across sizes
380 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
381 APFixedPoint(81920, getAccumSema()));
382 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
383 APFixedPoint(5368709120, getLAccumSema()));
384 ASSERT_EQ(APFixedPoint(0, getSAccumSema()), APFixedPoint(0, getLAccumSema()));
385
386 ASSERT_EQ(APFixedPoint(0, getS16Neg18()), APFixedPoint(0, getU8Neg10()));
387 ASSERT_EQ(APFixedPoint(256, getS16Neg18()), APFixedPoint(1, getU8Neg10()));
388 ASSERT_EQ(APFixedPoint(32512, getS16Neg18()),
389 APFixedPoint(127, getU8Neg10()));
390 ASSERT_EQ(APFixedPoint(4, getS32Pos2()), APFixedPoint(1, getU8Pos4()));
391 ASSERT_EQ(APFixedPoint(1020, getS32Pos2()), APFixedPoint(255, getU8Pos4()));
392
393 // Across types (0.5)
394 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
395 APFixedPoint(64, getSFractSema()));
396 ASSERT_EQ(APFixedPoint(16384, getAccumSema()),
397 APFixedPoint(16384, getFractSema()));
398 ASSERT_EQ(APFixedPoint(1073741824, getLAccumSema()),
399 APFixedPoint(1073741824, getLFractSema()));
400
401 // Across widths and types (0.5)
402 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
403 APFixedPoint(16384, getFractSema()));
404 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
405 APFixedPoint(1073741824, getLFractSema()));
406
407 // Across saturation
408 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
409 APFixedPoint(81920, Saturated(getAccumSema())));
410
411 // Across signs
412 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
413 APFixedPoint(640, getUSAccumSema()));
414 ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),
415 APFixedPoint(-81920, getAccumSema()));
416
417 // Across padding
418 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
419 APFixedPoint(320, getPadUSAccumSema()));
420 ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),
421 APFixedPoint(320, getPadUSAccumSema()));
422
423 // Less than
424 ASSERT_LT(APFixedPoint(-1, getSAccumSema()), APFixedPoint(0, getAccumSema()));
425 ASSERT_LT(APFixedPoint(-1, getSAccumSema()),
426 APFixedPoint(0, getUAccumSema()));
427 ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getAccumSema()));
428 ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getUAccumSema()));
429 ASSERT_LT(APFixedPoint(0, getUSAccumSema()), APFixedPoint(1, getAccumSema()));
430 ASSERT_LT(APFixedPoint(0, getUSAccumSema()),
431 APFixedPoint(1, getUAccumSema()));
432 ASSERT_LT(APFixedPoint(65280, getS16Neg18()),
433 APFixedPoint(255, getU8Neg10()));
434
435 // Greater than
436 ASSERT_GT(APFixedPoint(0, getAccumSema()), APFixedPoint(-1, getSAccumSema()));
437 ASSERT_GT(APFixedPoint(0, getUAccumSema()),
438 APFixedPoint(-1, getSAccumSema()));
439 ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getSAccumSema()));
440 ASSERT_GT(APFixedPoint(1, getUAccumSema()), APFixedPoint(0, getSAccumSema()));
441 ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getUSAccumSema()));
442 ASSERT_GT(APFixedPoint(1, getUAccumSema()),
443 APFixedPoint(0, getUSAccumSema()));
444}
445
446// Check that a fixed point value in one sema is the same in another sema
447void CheckUnsaturatedConversion(FixedPointSemantics Src,
448 FixedPointSemantics Dst, int64_t TestVal) {
449 int64_t ScaledVal = TestVal;
450 bool IsNegative = ScaledVal < 0;
451 if (IsNegative)
452 ScaledVal = -ScaledVal;
453
454 if (Dst.getLsbWeight() < Src.getLsbWeight()) {
455 ScaledVal <<= (Src.getLsbWeight() - Dst.getLsbWeight());
456 } else {
457 ScaledVal >>= (Dst.getLsbWeight() - Src.getLsbWeight());
458 }
459
460 if (IsNegative)
461 ScaledVal = -ScaledVal;
462
463 APFixedPoint Fixed(TestVal, Src);
464 APFixedPoint Expected(ScaledVal, Dst);
465 ASSERT_EQ(Fixed.convert(Dst), Expected);
466}
467
468// Check the value in a given fixed point sema overflows to the saturated min
469// for another sema
470void CheckSaturatedConversionMin(FixedPointSemantics Src,
471 FixedPointSemantics Dst, int64_t TestVal) {
472 APFixedPoint Fixed(TestVal, Src);
473 ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMin(Dst));
474}
475
476// Check the value in a given fixed point sema overflows to the saturated max
477// for another sema
478void CheckSaturatedConversionMax(FixedPointSemantics Src,
479 FixedPointSemantics Dst, int64_t TestVal) {
480 APFixedPoint Fixed(TestVal, Src);
481 ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMax(Dst));
482}
483
484// Check one signed _Accum sema converted to other sema for different values.
485void CheckSignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
486 int64_t OneVal) {
487 int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
488 int64_t HalfVal = (OneVal / 2); // 0.5
489
490 // +Accums to Accums
491 CheckUnsaturatedConversion(Src, Dst: getSAccumSema(), TestVal: NormalVal);
492 CheckUnsaturatedConversion(Src, Dst: getAccumSema(), TestVal: NormalVal);
493 CheckUnsaturatedConversion(Src, Dst: getLAccumSema(), TestVal: NormalVal);
494 CheckUnsaturatedConversion(Src, Dst: getUSAccumSema(), TestVal: NormalVal);
495 CheckUnsaturatedConversion(Src, Dst: getUAccumSema(), TestVal: NormalVal);
496 CheckUnsaturatedConversion(Src, Dst: getULAccumSema(), TestVal: NormalVal);
497 CheckUnsaturatedConversion(Src, Dst: getPadUSAccumSema(), TestVal: NormalVal);
498 CheckUnsaturatedConversion(Src, Dst: getPadUAccumSema(), TestVal: NormalVal);
499 CheckUnsaturatedConversion(Src, Dst: getPadULAccumSema(), TestVal: NormalVal);
500
501 // -Accums to Accums
502 CheckUnsaturatedConversion(Src, Dst: getSAccumSema(), TestVal: -NormalVal);
503 CheckUnsaturatedConversion(Src, Dst: getAccumSema(), TestVal: -NormalVal);
504 CheckUnsaturatedConversion(Src, Dst: getLAccumSema(), TestVal: -NormalVal);
505 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getUSAccumSema()), TestVal: -NormalVal);
506 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getUAccumSema()), TestVal: -NormalVal);
507 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getULAccumSema()), TestVal: -NormalVal);
508 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadUSAccumSema()), TestVal: -NormalVal);
509 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadUAccumSema()), TestVal: -NormalVal);
510 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadULAccumSema()), TestVal: -NormalVal);
511
512 // +Accums to Fracts
513 CheckUnsaturatedConversion(Src, Dst: getSFractSema(), TestVal: HalfVal);
514 CheckUnsaturatedConversion(Src, Dst: getFractSema(), TestVal: HalfVal);
515 CheckUnsaturatedConversion(Src, Dst: getLFractSema(), TestVal: HalfVal);
516 CheckUnsaturatedConversion(Src, Dst: getUSFractSema(), TestVal: HalfVal);
517 CheckUnsaturatedConversion(Src, Dst: getUFractSema(), TestVal: HalfVal);
518 CheckUnsaturatedConversion(Src, Dst: getULFractSema(), TestVal: HalfVal);
519 CheckUnsaturatedConversion(Src, Dst: getPadUSFractSema(), TestVal: HalfVal);
520 CheckUnsaturatedConversion(Src, Dst: getPadUFractSema(), TestVal: HalfVal);
521 CheckUnsaturatedConversion(Src, Dst: getPadULFractSema(), TestVal: HalfVal);
522
523 // -Accums to Fracts
524 CheckUnsaturatedConversion(Src, Dst: getSFractSema(), TestVal: -HalfVal);
525 CheckUnsaturatedConversion(Src, Dst: getFractSema(), TestVal: -HalfVal);
526 CheckUnsaturatedConversion(Src, Dst: getLFractSema(), TestVal: -HalfVal);
527 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getUSFractSema()), TestVal: -HalfVal);
528 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getUFractSema()), TestVal: -HalfVal);
529 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getULFractSema()), TestVal: -HalfVal);
530 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadUSFractSema()), TestVal: -HalfVal);
531 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadUFractSema()), TestVal: -HalfVal);
532 CheckSaturatedConversionMin(Src, Dst: Saturated(Sema: getPadULFractSema()), TestVal: -HalfVal);
533
534 // 0 to Accums
535 CheckUnsaturatedConversion(Src, Dst: getSAccumSema(), TestVal: 0);
536 CheckUnsaturatedConversion(Src, Dst: getAccumSema(), TestVal: 0);
537 CheckUnsaturatedConversion(Src, Dst: getLAccumSema(), TestVal: 0);
538 CheckUnsaturatedConversion(Src, Dst: getUSAccumSema(), TestVal: 0);
539 CheckUnsaturatedConversion(Src, Dst: getUAccumSema(), TestVal: 0);
540 CheckUnsaturatedConversion(Src, Dst: getULAccumSema(), TestVal: 0);
541 CheckUnsaturatedConversion(Src, Dst: getPadUSAccumSema(), TestVal: 0);
542 CheckUnsaturatedConversion(Src, Dst: getPadUAccumSema(), TestVal: 0);
543 CheckUnsaturatedConversion(Src, Dst: getPadULAccumSema(), TestVal: 0);
544
545 // 0 to Fracts
546 CheckUnsaturatedConversion(Src, Dst: getSFractSema(), TestVal: 0);
547 CheckUnsaturatedConversion(Src, Dst: getFractSema(), TestVal: 0);
548 CheckUnsaturatedConversion(Src, Dst: getLFractSema(), TestVal: 0);
549 CheckUnsaturatedConversion(Src, Dst: getUSFractSema(), TestVal: 0);
550 CheckUnsaturatedConversion(Src, Dst: getUFractSema(), TestVal: 0);
551 CheckUnsaturatedConversion(Src, Dst: getULFractSema(), TestVal: 0);
552 CheckUnsaturatedConversion(Src, Dst: getPadUSFractSema(), TestVal: 0);
553 CheckUnsaturatedConversion(Src, Dst: getPadUFractSema(), TestVal: 0);
554 CheckUnsaturatedConversion(Src, Dst: getPadULFractSema(), TestVal: 0);
555}
556
557// Check one unsigned _Accum sema converted to other sema for different
558// values.
559void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
560 int64_t OneVal) {
561 int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
562 int64_t HalfVal = (OneVal / 2); // 0.5
563
564 // +UAccums to Accums
565 CheckUnsaturatedConversion(Src, Dst: getSAccumSema(), TestVal: NormalVal);
566 CheckUnsaturatedConversion(Src, Dst: getAccumSema(), TestVal: NormalVal);
567 CheckUnsaturatedConversion(Src, Dst: getLAccumSema(), TestVal: NormalVal);
568 CheckUnsaturatedConversion(Src, Dst: getUSAccumSema(), TestVal: NormalVal);
569 CheckUnsaturatedConversion(Src, Dst: getUAccumSema(), TestVal: NormalVal);
570 CheckUnsaturatedConversion(Src, Dst: getULAccumSema(), TestVal: NormalVal);
571 CheckUnsaturatedConversion(Src, Dst: getPadUSAccumSema(), TestVal: NormalVal);
572 CheckUnsaturatedConversion(Src, Dst: getPadUAccumSema(), TestVal: NormalVal);
573 CheckUnsaturatedConversion(Src, Dst: getPadULAccumSema(), TestVal: NormalVal);
574
575 // +UAccums to Fracts
576 CheckUnsaturatedConversion(Src, Dst: getSFractSema(), TestVal: HalfVal);
577 CheckUnsaturatedConversion(Src, Dst: getFractSema(), TestVal: HalfVal);
578 CheckUnsaturatedConversion(Src, Dst: getLFractSema(), TestVal: HalfVal);
579 CheckUnsaturatedConversion(Src, Dst: getUSFractSema(), TestVal: HalfVal);
580 CheckUnsaturatedConversion(Src, Dst: getUFractSema(), TestVal: HalfVal);
581 CheckUnsaturatedConversion(Src, Dst: getULFractSema(), TestVal: HalfVal);
582 CheckUnsaturatedConversion(Src, Dst: getPadUSFractSema(), TestVal: HalfVal);
583 CheckUnsaturatedConversion(Src, Dst: getPadUFractSema(), TestVal: HalfVal);
584 CheckUnsaturatedConversion(Src, Dst: getPadULFractSema(), TestVal: HalfVal);
585}
586
587TEST(FixedPoint, AccumConversions) {
588 // Normal conversions
589 CheckSignedAccumConversionsAgainstOthers(Src: getSAccumSema(), OneVal: 128);
590 CheckUnsignedAccumConversionsAgainstOthers(Src: getUSAccumSema(), OneVal: 256);
591 CheckSignedAccumConversionsAgainstOthers(Src: getAccumSema(), OneVal: 32768);
592 CheckUnsignedAccumConversionsAgainstOthers(Src: getUAccumSema(), OneVal: 65536);
593 CheckSignedAccumConversionsAgainstOthers(Src: getLAccumSema(), OneVal: 2147483648);
594 CheckUnsignedAccumConversionsAgainstOthers(Src: getULAccumSema(), OneVal: 4294967296);
595
596 CheckUnsignedAccumConversionsAgainstOthers(Src: getPadUSAccumSema(), OneVal: 128);
597 CheckUnsignedAccumConversionsAgainstOthers(Src: getPadUAccumSema(), OneVal: 32768);
598 CheckUnsignedAccumConversionsAgainstOthers(Src: getPadULAccumSema(), OneVal: 2147483648);
599}
600
601TEST(FixedPoint, AccumConversionOverflow) {
602 // To SAccum max limit (65536)
603 CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getAccumSema()),
604 TestVal: 140737488355328);
605 CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getUAccumSema()),
606 TestVal: 140737488355328);
607 CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getPadUAccumSema()),
608 TestVal: 140737488355328);
609 CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getAccumSema()),
610 TestVal: 281474976710656);
611 CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getUAccumSema()),
612 TestVal: 281474976710656);
613 CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getPadUAccumSema()),
614 TestVal: 281474976710656);
615
616 CheckSaturatedConversionMax(Src: getPadULAccumSema(), Dst: Saturated(Sema: getAccumSema()),
617 TestVal: 140737488355328);
618 CheckSaturatedConversionMax(Src: getPadULAccumSema(), Dst: Saturated(Sema: getUAccumSema()),
619 TestVal: 140737488355328);
620 CheckSaturatedConversionMax(Src: getPadULAccumSema(),
621 Dst: Saturated(Sema: getPadUAccumSema()), TestVal: 140737488355328);
622
623 // To SAccum min limit (-65536)
624 CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getAccumSema()),
625 TestVal: -140737488355328);
626 CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getUAccumSema()),
627 TestVal: -140737488355328);
628 CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getPadUAccumSema()),
629 TestVal: -140737488355328);
630}
631
632TEST(FixedPoint, SAccumConversionOverflow) {
633 // To SAccum max limit (256)
634 CheckSaturatedConversionMax(Src: getAccumSema(), Dst: Saturated(Sema: getSAccumSema()),
635 TestVal: 8388608);
636 CheckSaturatedConversionMax(Src: getAccumSema(), Dst: Saturated(Sema: getUSAccumSema()),
637 TestVal: 8388608);
638 CheckSaturatedConversionMax(Src: getAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()),
639 TestVal: 8388608);
640 CheckSaturatedConversionMax(Src: getUAccumSema(), Dst: Saturated(Sema: getSAccumSema()),
641 TestVal: 16777216);
642 CheckSaturatedConversionMax(Src: getUAccumSema(), Dst: Saturated(Sema: getUSAccumSema()),
643 TestVal: 16777216);
644 CheckSaturatedConversionMax(Src: getUAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()),
645 TestVal: 16777216);
646 CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getSAccumSema()),
647 TestVal: 549755813888);
648 CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getUSAccumSema()),
649 TestVal: 549755813888);
650 CheckSaturatedConversionMax(Src: getLAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()),
651 TestVal: 549755813888);
652 CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getSAccumSema()),
653 TestVal: 1099511627776);
654 CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getUSAccumSema()),
655 TestVal: 1099511627776);
656 CheckSaturatedConversionMax(Src: getULAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()),
657 TestVal: 1099511627776);
658
659 CheckSaturatedConversionMax(Src: getPadUAccumSema(), Dst: Saturated(Sema: getSAccumSema()),
660 TestVal: 8388608);
661 CheckSaturatedConversionMax(Src: getPadUAccumSema(), Dst: Saturated(Sema: getUSAccumSema()),
662 TestVal: 8388608);
663 CheckSaturatedConversionMax(Src: getPadUAccumSema(),
664 Dst: Saturated(Sema: getPadUSAccumSema()), TestVal: 8388608);
665 CheckSaturatedConversionMax(Src: getPadULAccumSema(), Dst: Saturated(Sema: getSAccumSema()),
666 TestVal: 549755813888);
667 CheckSaturatedConversionMax(Src: getPadULAccumSema(), Dst: Saturated(Sema: getUSAccumSema()),
668 TestVal: 549755813888);
669 CheckSaturatedConversionMax(Src: getPadULAccumSema(),
670 Dst: Saturated(Sema: getPadUSAccumSema()), TestVal: 549755813888);
671
672 // To SAccum min limit (-256)
673 CheckSaturatedConversionMin(Src: getAccumSema(), Dst: Saturated(Sema: getSAccumSema()),
674 TestVal: -8388608);
675 CheckSaturatedConversionMin(Src: getAccumSema(), Dst: Saturated(Sema: getUSAccumSema()),
676 TestVal: -8388608);
677 CheckSaturatedConversionMin(Src: getAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()),
678 TestVal: -8388608);
679 CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getSAccumSema()),
680 TestVal: -549755813888);
681 CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getUSAccumSema()),
682 TestVal: -549755813888);
683 CheckSaturatedConversionMin(Src: getLAccumSema(), Dst: Saturated(Sema: getPadUSAccumSema()),
684 TestVal: -549755813888);
685}
686
687TEST(FixedPoint, GetValueSignAfterConversion) {
688 APFixedPoint Fixed(255 << 7, getSAccumSema());
689 ASSERT_TRUE(Fixed.getValue().isSigned());
690 APFixedPoint UFixed = Fixed.convert(DstSema: getUSAccumSema());
691 ASSERT_TRUE(UFixed.getValue().isUnsigned());
692 ASSERT_EQ(UFixed.getValue(), APSInt::getUnsigned(255 << 8).extOrTrunc(16));
693}
694
695TEST(FixedPoint, ModularWrapAround) {
696 // Positive to negative
697 APFixedPoint Val = APFixedPoint(1ULL << 7, getSAccumSema());
698 ASSERT_EQ(Val.convert(getLFractSema()).getValue(), -(1ULL << 31));
699
700 Val = APFixedPoint(1ULL << 23, getAccumSema());
701 ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), -(1ULL << 15));
702
703 Val = APFixedPoint(1ULL << 47, getLAccumSema());
704 ASSERT_EQ(Val.convert(getAccumSema()).getValue(), -(1ULL << 31));
705
706 // Negative to positive
707 Val = APFixedPoint(/*-1.5*/ -192, getSAccumSema());
708 ASSERT_EQ(Val.convert(getLFractSema()).getValue(), 1ULL << 30);
709
710 Val = APFixedPoint(-(257 << 15), getAccumSema());
711 ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), 255 << 7);
712
713 Val = APFixedPoint(-(65537ULL << 31), getLAccumSema());
714 ASSERT_EQ(Val.convert(getAccumSema()).getValue(), 65535 << 15);
715
716 // Signed to unsigned
717 Val = APFixedPoint(-(1 << 7), getSAccumSema());
718 ASSERT_EQ(Val.convert(getUSAccumSema()).getValue(), 255 << 8);
719
720 Val = APFixedPoint(-(1 << 15), getAccumSema());
721 ASSERT_EQ(Val.convert(getUAccumSema()).getValue(), 65535ULL << 16);
722
723 Val = APFixedPoint(-(1ULL << 31), getLAccumSema());
724 ASSERT_EQ(Val.convert(getULAccumSema()).getValue().getZExtValue(),
725 4294967295ULL << 32);
726}
727
728enum OvfKind { MinSat, MaxSat };
729
730void CheckFloatToFixedConversion(APFloat &Val, const FixedPointSemantics &Sema,
731 int64_t ExpectedNonSat) {
732 bool Ovf;
733 ASSERT_EQ(APFixedPoint::getFromFloatValue(Val, Sema, &Ovf).getValue(),
734 ExpectedNonSat);
735 ASSERT_EQ(Ovf, false);
736 ASSERT_EQ(
737 APFixedPoint::getFromFloatValue(Val, Saturated(Sema), &Ovf).getValue(),
738 ExpectedNonSat);
739 ASSERT_EQ(Ovf, false);
740}
741
742void CheckFloatToFixedConversion(APFloat &Val, const FixedPointSemantics &Sema,
743 OvfKind ExpectedOvf) {
744 bool Ovf;
745 (void)APFixedPoint::getFromFloatValue(Value: Val, DstFXSema: Sema, Overflow: &Ovf);
746 ASSERT_EQ(Ovf, true);
747 ASSERT_EQ(
748 APFixedPoint::getFromFloatValue(Val, Saturated(Sema), &Ovf).getValue(),
749 (ExpectedOvf == MinSat ? APFixedPoint::getMin(Sema)
750 : APFixedPoint::getMax(Sema))
751 .getValue());
752 ASSERT_EQ(Ovf, false);
753}
754
755TEST(FixedPoint, toString) {
756 ASSERT_EQ(APFixedPoint::getMax(getS16Neg18()).toString(),
757 "0.124996185302734375");
758 ASSERT_EQ(APFixedPoint::getMin(getS16Neg18())
759 .add(APFixedPoint(1, getS16Neg18()))
760 .toString(),
761 "-0.124996185302734375");
762 ASSERT_EQ(APFixedPoint::getMin(getS16Neg18()).toString(), "-0.125");
763 ASSERT_EQ(APFixedPoint::getMax(getU8Neg10()).toString(), "0.2490234375");
764 ASSERT_EQ(APFixedPoint::getMin(getU8Neg10()).toString(), "0.0");
765 ASSERT_EQ(APFixedPoint::getMax(getS32Pos2()).toString(), "8589934588.0");
766 ASSERT_EQ(APFixedPoint::getMin(getS32Pos2())
767 .add(APFixedPoint(1, getS32Pos2()))
768 .toString(),
769 "-8589934588.0");
770 ASSERT_EQ(APFixedPoint::getMin(getS32Pos2()).toString(), "-8589934592.0");
771 ASSERT_EQ(APFixedPoint::getMax(getU8Pos4()).toString(), "4080.0");
772 ASSERT_EQ(APFixedPoint::getMin(getU8Pos4()).toString(), "0.0");
773}
774
775TEST(FixedPoint, FloatToFixed) {
776 APFloat Val(0.0f);
777
778 // Simple exact fraction
779 Val = APFloat(0.75f);
780 CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: 3ULL << 5);
781 CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: 3ULL << 13);
782 CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: 3ULL << 29);
783
784 CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedNonSat: 3ULL << 6);
785 CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedNonSat: 3ULL << 14);
786 CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedNonSat: 3ULL << 30);
787
788 CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedNonSat: 3ULL << 5);
789 CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedNonSat: 3ULL << 13);
790 CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedNonSat: 3ULL << 29);
791
792 CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedNonSat: 3ULL << 6);
793 CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedNonSat: 3ULL << 14);
794 CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedNonSat: 3ULL << 30);
795
796 CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MaxSat);
797 CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0);
798 CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MaxSat);
799 CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0);
800
801 // Simple negative exact fraction
802 Val = APFloat(-0.75f);
803 CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: -3ULL << 5);
804 CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: -3ULL << 13);
805 CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: -3ULL << 29);
806
807 CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedOvf: MinSat);
808 CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedOvf: MinSat);
809 CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedOvf: MinSat);
810
811 CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedNonSat: -3ULL << 5);
812 CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedNonSat: -3ULL << 13);
813 CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedNonSat: -3ULL << 29);
814
815 CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedOvf: MinSat);
816 CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedOvf: MinSat);
817 CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedOvf: MinSat);
818
819 CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MinSat);
820 CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0);
821 CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MinSat);
822 CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0);
823
824 // Highly precise fraction
825 Val = APFloat(0.999999940395355224609375f);
826 CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: 0x7FULL);
827 CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: 0x7FFFULL);
828 CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: 0xFFFFFFULL << 7);
829
830 CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedNonSat: 0xFFULL);
831 CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedNonSat: 0xFFFFULL);
832 CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedNonSat: 0xFFFFFFULL << 8);
833
834 CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedNonSat: 0x7FULL);
835 CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedNonSat: 0x7FFFULL);
836 CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedNonSat: 0xFFFFFFULL << 7);
837
838 CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedNonSat: 0xFFULL);
839 CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedNonSat: 0xFFFFULL);
840 CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedNonSat: 0xFFFFFFULL << 8);
841
842 CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MaxSat);
843 CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0);
844 CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MaxSat);
845 CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0);
846
847 // Integral and fraction
848 Val = APFloat(17.99609375f);
849 CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: 0x11FFULL >> 1);
850 CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: 0x11FFULL << 7);
851 CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: 0x11FFULL << 23);
852
853 CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedNonSat: 0x11FFULL);
854 CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedNonSat: 0x11FFULL << 8);
855 CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedNonSat: 0x11FFULL << 24);
856
857 CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedOvf: MaxSat);
858 CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedOvf: MaxSat);
859 CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedOvf: MaxSat);
860
861 CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedOvf: MaxSat);
862 CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedOvf: MaxSat);
863 CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedOvf: MaxSat);
864
865 CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MaxSat);
866 CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 1);
867 CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MaxSat);
868 CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 1 << 2);
869
870 // Negative integral and fraction
871 Val = APFloat(-17.99609375f);
872 CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: -0x11FELL >> 1);
873 CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: -0x11FFULL << 7);
874 CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: -0x11FFULL << 23);
875
876 CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedOvf: MinSat);
877 CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedOvf: MinSat);
878 CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedOvf: MinSat);
879
880 CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedOvf: MinSat);
881 CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedOvf: MinSat);
882 CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedOvf: MinSat);
883
884 CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedOvf: MinSat);
885 CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedOvf: MinSat);
886 CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedOvf: MinSat);
887
888 CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MinSat);
889 CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedOvf: MinSat);
890 CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MinSat);
891 CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: -4);
892
893 // Very large value
894 Val = APFloat(1.0e38f);
895 CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedOvf: MaxSat);
896 CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedOvf: MaxSat);
897 CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedOvf: MaxSat);
898
899 CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedOvf: MaxSat);
900 CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedOvf: MaxSat);
901 CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedOvf: MaxSat);
902
903 CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedOvf: MaxSat);
904 CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedOvf: MaxSat);
905 CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedOvf: MaxSat);
906
907 CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedOvf: MaxSat);
908 CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedOvf: MaxSat);
909 CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedOvf: MaxSat);
910
911 CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MaxSat);
912 CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedOvf: MaxSat);
913 CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MaxSat);
914 CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedOvf: MaxSat);
915
916 // Very small value
917 Val = APFloat(1.0e-38f);
918 CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: 0);
919 CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: 0);
920 CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: 0);
921
922 CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedNonSat: 0);
923 CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedNonSat: 0);
924 CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedNonSat: 0);
925
926 CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedNonSat: 0);
927 CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedNonSat: 0);
928 CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedNonSat: 0);
929
930 CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedNonSat: 0);
931 CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedNonSat: 0);
932 CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedNonSat: 0);
933
934 CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedNonSat: 0);
935 CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0);
936 CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedNonSat: 0);
937 CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0);
938
939 // Half conversion
940 Val = APFloat(0.99951171875f);
941 bool Ignored;
942 Val.convert(ToSemantics: APFloat::IEEEhalf(), RM: APFloat::rmNearestTiesToEven, losesInfo: &Ignored);
943
944 CheckFloatToFixedConversion(Val, Sema: getSAccumSema(), ExpectedNonSat: 0x7FULL);
945 CheckFloatToFixedConversion(Val, Sema: getAccumSema(), ExpectedNonSat: 0x7FFULL << 4);
946 CheckFloatToFixedConversion(Val, Sema: getLAccumSema(), ExpectedNonSat: 0x7FFULL << 20);
947
948 CheckFloatToFixedConversion(Val, Sema: getUSAccumSema(), ExpectedNonSat: 0xFFULL);
949 CheckFloatToFixedConversion(Val, Sema: getUAccumSema(), ExpectedNonSat: 0xFFEULL << 4);
950 CheckFloatToFixedConversion(Val, Sema: getULAccumSema(), ExpectedNonSat: 0xFFEULL << 20);
951
952 CheckFloatToFixedConversion(Val, Sema: getSFractSema(), ExpectedNonSat: 0x7FULL);
953 CheckFloatToFixedConversion(Val, Sema: getFractSema(), ExpectedNonSat: 0x7FFULL << 4);
954 CheckFloatToFixedConversion(Val, Sema: getLFractSema(), ExpectedNonSat: 0x7FFULL << 20);
955
956 CheckFloatToFixedConversion(Val, Sema: getUSFractSema(), ExpectedNonSat: 0xFFULL);
957 CheckFloatToFixedConversion(Val, Sema: getUFractSema(), ExpectedNonSat: 0xFFEULL << 4);
958 CheckFloatToFixedConversion(Val, Sema: getULFractSema(), ExpectedNonSat: 0xFFEULL << 20);
959
960 CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MaxSat);
961 CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0);
962 CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedOvf: MaxSat);
963 CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0);
964
965 Val = APFloat(0.124996185302734375);
966 CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedNonSat: 0x7f);
967 CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0);
968 CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedNonSat: 0x7fff);
969 CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0);
970
971 Val = APFloat(-0.124996185302734375);
972 CheckFloatToFixedConversion(Val, Sema: getU8Neg10(), ExpectedOvf: MinSat);
973 CheckFloatToFixedConversion(Val, Sema: getU8Pos4(), ExpectedNonSat: 0);
974 CheckFloatToFixedConversion(Val, Sema: getS16Neg18(), ExpectedNonSat: -0x7fff);
975 CheckFloatToFixedConversion(Val, Sema: getS32Pos2(), ExpectedNonSat: 0);
976}
977
978void CheckFixedToFloatConversion(int64_t Val, const FixedPointSemantics &Sema,
979 float Result) {
980 APFixedPoint FXVal(Val, Sema);
981 APFloat APRes(Result);
982 ASSERT_EQ(FXVal.convertToFloat(APFloat::IEEEsingle()), APRes);
983}
984
985void CheckFixedToHalfConversion(int64_t Val, const FixedPointSemantics &Sema,
986 float Result) {
987 APFixedPoint FXVal(Val, Sema);
988 APFloat APRes(Result);
989 bool Ignored;
990 APRes.convert(ToSemantics: APFloat::IEEEhalf(), RM: APFloat::rmNearestTiesToEven, losesInfo: &Ignored);
991 ASSERT_EQ(FXVal.convertToFloat(APFloat::IEEEhalf()), APRes);
992}
993
994TEST(FixedPoint, FixedToFloat) {
995 int64_t Val = 0x1ULL;
996 CheckFixedToFloatConversion(Val, Sema: getSAccumSema(), Result: 0.0078125f);
997 CheckFixedToFloatConversion(Val, Sema: getFractSema(), Result: 0.000030517578125f);
998 CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: 0.000030517578125f);
999 CheckFixedToFloatConversion(Val, Sema: getLFractSema(),
1000 Result: 0.0000000004656612873077392578125f);
1001
1002 CheckFixedToFloatConversion(Val, Sema: getUSAccumSema(), Result: 0.00390625f);
1003 CheckFixedToFloatConversion(Val, Sema: getUFractSema(), Result: 0.0000152587890625f);
1004 CheckFixedToFloatConversion(Val, Sema: getUAccumSema(), Result: 0.0000152587890625f);
1005 CheckFixedToFloatConversion(Val, Sema: getULFractSema(),
1006 Result: 0.00000000023283064365386962890625f);
1007
1008 CheckFixedToFloatConversion(Val, Sema: getU8Neg10(), Result: 0.0009765625f);
1009 CheckFixedToFloatConversion(Val, Sema: getU8Pos4(), Result: 16.0f);
1010 CheckFixedToFloatConversion(Val, Sema: getS16Neg18(), Result: 0.000003814697265625f);
1011 CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 4.0f);
1012
1013 Val = 0x7FULL;
1014 CheckFixedToFloatConversion(Val, Sema: getSAccumSema(), Result: 0.9921875f);
1015 CheckFixedToFloatConversion(Val, Sema: getFractSema(), Result: 0.003875732421875f);
1016 CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: 0.003875732421875f);
1017 CheckFixedToFloatConversion(Val, Sema: getLFractSema(),
1018 Result: 0.0000000591389834880828857421875f);
1019
1020 CheckFixedToFloatConversion(Val, Sema: getUSAccumSema(), Result: 0.49609375f);
1021 CheckFixedToFloatConversion(Val, Sema: getUFractSema(), Result: 0.0019378662109375f);
1022 CheckFixedToFloatConversion(Val, Sema: getUAccumSema(), Result: 0.0019378662109375f);
1023 CheckFixedToFloatConversion(Val, Sema: getULFractSema(),
1024 Result: 0.00000002956949174404144287109375f);
1025
1026 CheckFixedToFloatConversion(Val, Sema: getU8Neg10(), Result: 0.1240234375f);
1027 CheckFixedToFloatConversion(Val, Sema: getU8Pos4(), Result: 2032.0f);
1028 CheckFixedToFloatConversion(Val, Sema: getS16Neg18(), Result: 0.000484466552734375f);
1029 CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 508.0f);
1030
1031 Val = -0x1ULL;
1032 CheckFixedToFloatConversion(Val, Sema: getSAccumSema(), Result: -0.0078125f);
1033 CheckFixedToFloatConversion(Val, Sema: getFractSema(), Result: -0.000030517578125f);
1034 CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: -0.000030517578125f);
1035 CheckFixedToFloatConversion(Val, Sema: getLFractSema(),
1036 Result: -0.0000000004656612873077392578125f);
1037
1038 CheckFixedToFloatConversion(Val, Sema: getU8Neg10(), Result: 0.249023437f);
1039 CheckFixedToFloatConversion(Val, Sema: getU8Pos4(), Result: 4080.0f);
1040 CheckFixedToFloatConversion(Val, Sema: getS16Neg18(), Result: -0.000003814697265625f);
1041 CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: -4.0f);
1042
1043 CheckFixedToFloatConversion(Val: -0x80ULL, Sema: getSAccumSema(), Result: -1.0f);
1044 CheckFixedToFloatConversion(Val: -0x8000ULL, Sema: getFractSema(), Result: -1.0f);
1045 CheckFixedToFloatConversion(Val: -0x8000ULL, Sema: getAccumSema(), Result: -1.0f);
1046 CheckFixedToFloatConversion(Val: -0x80000000ULL, Sema: getLFractSema(), Result: -1.0f);
1047
1048 Val = 0xAFAULL;
1049 CheckFixedToFloatConversion(Val, Sema: getSAccumSema(), Result: 21.953125f);
1050 CheckFixedToFloatConversion(Val, Sema: getFractSema(), Result: 0.08575439453125f);
1051 CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: 0.08575439453125f);
1052 CheckFixedToFloatConversion(Val, Sema: getLFractSema(),
1053 Result: 0.000001308508217334747314453125f);
1054
1055 CheckFixedToFloatConversion(Val, Sema: getUSAccumSema(), Result: 10.9765625f);
1056 CheckFixedToFloatConversion(Val, Sema: getUFractSema(), Result: 0.042877197265625f);
1057 CheckFixedToFloatConversion(Val, Sema: getUAccumSema(), Result: 0.042877197265625f);
1058 CheckFixedToFloatConversion(Val, Sema: getULFractSema(),
1059 Result: 0.0000006542541086673736572265625f);
1060
1061 CheckFixedToFloatConversion(Val, Sema: getS16Neg18(), Result: 0.01071929931640625f);
1062 CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 11240.0f);
1063
1064 Val = -0xAFAULL;
1065 CheckFixedToFloatConversion(Val, Sema: getSAccumSema(), Result: -21.953125f);
1066 CheckFixedToFloatConversion(Val, Sema: getFractSema(), Result: -0.08575439453125f);
1067 CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: -0.08575439453125f);
1068 CheckFixedToFloatConversion(Val, Sema: getLFractSema(),
1069 Result: -0.000001308508217334747314453125f);
1070
1071 CheckFixedToFloatConversion(Val, Sema: getS16Neg18(), Result: -0.01071929931640625f);
1072 CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: -11240.0f);
1073
1074 Val = 0x40000080ULL;
1075 CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: 32768.00390625f);
1076 CheckFixedToFloatConversion(Val, Sema: getLFractSema(),
1077 Result: 0.500000059604644775390625f);
1078
1079 CheckFixedToFloatConversion(Val, Sema: getUAccumSema(), Result: 16384.001953125f);
1080 CheckFixedToFloatConversion(Val, Sema: getULFractSema(),
1081 Result: 0.2500000298023223876953125f);
1082
1083 CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 4294967808.0f);
1084
1085 Val = 0x40000040ULL;
1086 CheckFixedToFloatConversion(Val, Sema: getAccumSema(), Result: 32768.0f);
1087 CheckFixedToFloatConversion(Val, Sema: getLFractSema(), Result: 0.5f);
1088
1089 CheckFixedToFloatConversion(Val, Sema: getUAccumSema(), Result: 16384.0f);
1090 CheckFixedToFloatConversion(Val, Sema: getULFractSema(), Result: 0.25f);
1091
1092 CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 4294967552.0f);
1093
1094 Val = 0x7FF0ULL;
1095 CheckFixedToHalfConversion(Val, Sema: getAccumSema(), Result: 0.99951171875f);
1096 CheckFixedToHalfConversion(Val, Sema: getLFractSema(), Result: 0.000015251338481903076171875f);
1097
1098 CheckFixedToHalfConversion(Val, Sema: getUAccumSema(), Result: 0.499755859375f);
1099 CheckFixedToHalfConversion(Val, Sema: getULFractSema(), Result: 0.0000076256692409515380859375f);
1100
1101 CheckFixedToFloatConversion(Val, Sema: getS32Pos2(), Result: 131008.0f);
1102}
1103
1104void CheckAdd(const APFixedPoint &Lhs, const APFixedPoint &Rhs,
1105 const APFixedPoint &Res) {
1106 bool Overflow = false;
1107 APFixedPoint Result = Lhs.add(Other: Rhs, Overflow: &Overflow);
1108 ASSERT_FALSE(Overflow);
1109 ASSERT_EQ(Result.getSemantics(), Res.getSemantics());
1110 ASSERT_EQ(Result, Res);
1111}
1112
1113void CheckAddOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) {
1114 bool Overflow = false;
1115 APFixedPoint Result = Lhs.add(Other: Rhs, Overflow: &Overflow);
1116 ASSERT_TRUE(Overflow);
1117}
1118
1119TEST(FixedPoint, add) {
1120 CheckAdd(Lhs: APFixedPoint(1, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()),
1121 Res: APFixedPoint(2, getS32Pos2()));
1122 CheckAdd(Lhs: APFixedPoint(1, getS16Neg18()), Rhs: APFixedPoint(1, getS16Neg18()),
1123 Res: APFixedPoint(2, getS16Neg18()));
1124 CheckAdd(Lhs: APFixedPoint(1, getU8Neg10()), Rhs: APFixedPoint(1, getU8Neg10()),
1125 Res: APFixedPoint(2, getU8Neg10()));
1126 CheckAdd(Lhs: APFixedPoint(1, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()),
1127 Res: APFixedPoint(2, getU8Pos4()));
1128
1129 CheckAdd(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()),
1130 Res: APFixedPoint(12, getS32Pos2()));
1131 CheckAdd(Lhs: APFixedPoint(11, getS16Neg18()), Rhs: APFixedPoint(1, getS16Neg18()),
1132 Res: APFixedPoint(12, getS16Neg18()));
1133 CheckAdd(Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(1, getU8Neg10()),
1134 Res: APFixedPoint(12, getU8Neg10()));
1135 CheckAdd(Lhs: APFixedPoint(11, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()),
1136 Res: APFixedPoint(12, getU8Pos4()));
1137
1138 CheckAdd(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS16Neg18()),
1139 Res: APFixedPoint(11534337,
1140 FixedPointSemantics(52, FixedPointSemantics::Lsb{.LsbWeight: -18},
1141 true, false, false)));
1142 CheckAdd(
1143 Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(-9472, getS16Neg18()),
1144 Res: APFixedPoint(-6656, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18},
1145 true, false, false)));
1146 CheckAddOverflow(
1147 Lhs: APFixedPoint::getMax(Sema: getU8Neg10()), Rhs: APFixedPoint::getMax(Sema: getS16Neg18()));
1148 CheckAdd(Lhs: APFixedPoint::getMin(Sema: getU8Neg10()),
1149 Rhs: APFixedPoint::getMin(Sema: getS16Neg18()),
1150 Res: APFixedPoint::getMin(Sema: getS16Neg18())
1151 .convert(DstSema: FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18},
1152 true, false, false)));
1153 CheckAddOverflow(Lhs: APFixedPoint::getMin(Sema: getS32Pos2()),
1154 Rhs: APFixedPoint::getMin(Sema: getS16Neg18()));
1155}
1156
1157void CheckMul(const APFixedPoint &Lhs, const APFixedPoint &Rhs,
1158 const APFixedPoint &Res) {
1159 bool Overflow = false;
1160 APFixedPoint Result = Lhs.mul(Other: Rhs, Overflow: &Overflow);
1161 ASSERT_FALSE(Overflow);
1162 ASSERT_EQ(Result.getSemantics(), Res.getSemantics());
1163 ASSERT_EQ(Result, Res);
1164}
1165
1166void CheckMulOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) {
1167 bool Overflow = false;
1168 APFixedPoint Result = Lhs.mul(Other: Rhs, Overflow: &Overflow);
1169 ASSERT_TRUE(Overflow);
1170}
1171
1172TEST(FixedPoint, mul) {
1173 CheckMul(Lhs: APFixedPoint(1, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()),
1174 Res: APFixedPoint(4, getS32Pos2()));
1175 CheckMul(Lhs: APFixedPoint(1, getS16Neg18()), Rhs: APFixedPoint(1, getS16Neg18()),
1176 Res: APFixedPoint(0, getS16Neg18()));
1177 CheckMul(Lhs: APFixedPoint(1, getU8Neg10()), Rhs: APFixedPoint(1, getU8Neg10()),
1178 Res: APFixedPoint(0, getU8Neg10()));
1179 CheckMul(Lhs: APFixedPoint(1, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()),
1180 Res: APFixedPoint(16, getU8Pos4()));
1181
1182 CheckMul(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()),
1183 Res: APFixedPoint(44, getS32Pos2()));
1184 CheckMul(Lhs: APFixedPoint(11, getS16Neg18()), Rhs: APFixedPoint(1, getS16Neg18()),
1185 Res: APFixedPoint(0, getS16Neg18()));
1186 CheckMul(Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(1, getU8Neg10()),
1187 Res: APFixedPoint(0, getU8Neg10()));
1188 CheckMul(Lhs: APFixedPoint(11, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()),
1189 Res: APFixedPoint(176, getU8Pos4()));
1190
1191 CheckMul(Lhs: APFixedPoint(512, getS16Neg18()), Rhs: APFixedPoint(512, getS16Neg18()),
1192 Res: APFixedPoint(1, getS16Neg18()));
1193 CheckMul(Lhs: APFixedPoint(32, getU8Neg10()), Rhs: APFixedPoint(32, getU8Neg10()),
1194 Res: APFixedPoint(1, getU8Neg10()));
1195
1196 CheckMul(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS16Neg18()),
1197 Res: APFixedPoint(44,
1198 FixedPointSemantics(52, FixedPointSemantics::Lsb{.LsbWeight: -18},
1199 true, false, false)));
1200 CheckMul(
1201 Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(-9472, getS16Neg18()),
1202 Res: APFixedPoint(-102, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18},
1203 true, false, false)));
1204 CheckMul(
1205 Lhs: APFixedPoint::getMax(Sema: getU8Neg10()), Rhs: APFixedPoint::getMax(Sema: getS16Neg18()),
1206 Res: APFixedPoint(8159, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18},
1207 true, false, false)));
1208 CheckMul(
1209 Lhs: APFixedPoint::getMin(Sema: getU8Neg10()), Rhs: APFixedPoint::getMin(Sema: getS16Neg18()),
1210 Res: APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18},
1211 true, false, false)));
1212 CheckMul(Lhs: APFixedPoint::getMin(Sema: getS32Pos2()),
1213 Rhs: APFixedPoint::getMin(Sema: getS16Neg18()),
1214 Res: APFixedPoint(281474976710656,
1215 FixedPointSemantics(52, FixedPointSemantics::Lsb{.LsbWeight: -18},
1216 true, false, false)));
1217 CheckMulOverflow(Lhs: APFixedPoint::getMax(Sema: getS32Pos2()), Rhs: APFixedPoint::getMax(Sema: getU8Pos4()));
1218 CheckMulOverflow(Lhs: APFixedPoint::getMin(Sema: getS32Pos2()), Rhs: APFixedPoint::getMax(Sema: getU8Pos4()));
1219}
1220
1221void CheckDiv(const APFixedPoint &Lhs, const APFixedPoint &Rhs,
1222 const APFixedPoint &Expected) {
1223 bool Overflow = false;
1224 APFixedPoint Result = Lhs.div(Other: Rhs, Overflow: &Overflow);
1225 ASSERT_FALSE(Overflow);
1226 ASSERT_EQ(Result.getSemantics(), Expected.getSemantics());
1227 ASSERT_EQ(Result, Expected);
1228}
1229
1230void CheckDivOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) {
1231 bool Overflow = false;
1232 APFixedPoint Result = Lhs.div(Other: Rhs, Overflow: &Overflow);
1233 ASSERT_TRUE(Overflow);
1234}
1235
1236TEST(FixedPoint, div) {
1237 CheckDiv(Lhs: APFixedPoint(1, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()),
1238 Expected: APFixedPoint(0, getS32Pos2()));
1239 CheckDivOverflow(Lhs: APFixedPoint(1, getS16Neg18()), Rhs: APFixedPoint(1, getS16Neg18()));
1240 CheckDivOverflow(Lhs: APFixedPoint(1, getU8Neg10()), Rhs: APFixedPoint(1, getU8Neg10()));
1241 CheckDiv(Lhs: APFixedPoint(1, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()),
1242 Expected: APFixedPoint(0, getU8Pos4()));
1243
1244 CheckDiv(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS32Pos2()),
1245 Expected: APFixedPoint(2, getS32Pos2()));
1246 CheckDiv(Lhs: APFixedPoint(11, getU8Pos4()), Rhs: APFixedPoint(1, getU8Pos4()),
1247 Expected: APFixedPoint(0, getU8Pos4()));
1248
1249 CheckDiv(Lhs: APFixedPoint(11, getS32Pos2()), Rhs: APFixedPoint(1, getS16Neg18()),
1250 Expected: APFixedPoint(3023656976384,
1251 FixedPointSemantics(52, FixedPointSemantics::Lsb{.LsbWeight: -18},
1252 true, false, false)));
1253 CheckDiv(Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(-11264, getS16Neg18()),
1254 Expected: APFixedPoint::getMin(Sema: FixedPointSemantics(
1255 17, FixedPointSemantics::Lsb{.LsbWeight: -18}, true, false, false)));
1256 CheckDiv(Lhs: APFixedPoint(11, getU8Neg10()), Rhs: APFixedPoint(11265, getS16Neg18()),
1257 Expected: APFixedPoint(0xfffa,
1258 FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18},
1259 true, false, false)));
1260 CheckDivOverflow(Lhs: APFixedPoint(11, getU8Neg10()),
1261 Rhs: APFixedPoint(11264, getS16Neg18()));
1262
1263 CheckDivOverflow(Lhs: APFixedPoint(11, getU8Neg10()),
1264 Rhs: APFixedPoint(-9472, getS16Neg18()));
1265 CheckDivOverflow(Lhs: APFixedPoint::getMax(Sema: getU8Neg10()),
1266 Rhs: APFixedPoint::getMax(Sema: getS16Neg18()));
1267 CheckDiv(
1268 Lhs: APFixedPoint::getMin(Sema: getU8Neg10()), Rhs: APFixedPoint::getMin(Sema: getS16Neg18()),
1269 Expected: APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18},
1270 true, false, false)));
1271 CheckDiv(
1272 Lhs: APFixedPoint(1, getU8Neg10()), Rhs: APFixedPoint::getMin(Sema: getS16Neg18()),
1273 Expected: APFixedPoint(-2048, FixedPointSemantics(17, FixedPointSemantics::Lsb{.LsbWeight: -18},
1274 true, false, false)));
1275}
1276
1277} // namespace
1278

source code of llvm/unittests/ADT/APFixedPointTest.cpp