1//===- llvm/unittest/ADT/APFloat.cpp - APFloat unit 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/APFloat.h"
10#include "llvm/ADT/APSInt.h"
11#include "llvm/ADT/Hashing.h"
12#include "llvm/ADT/SmallString.h"
13#include "llvm/ADT/SmallVector.h"
14#include "llvm/ADT/StringExtras.h"
15#include "llvm/Support/Error.h"
16#include "llvm/Support/FormatVariadic.h"
17#include "gtest/gtest.h"
18#include <cmath>
19#include <ostream>
20#include <string>
21#include <tuple>
22
23using namespace llvm;
24
25static std::string convertToErrorFromString(StringRef Str) {
26 llvm::APFloat F(0.0);
27 auto StatusOrErr =
28 F.convertFromString(Str, llvm::APFloat::rmNearestTiesToEven);
29 EXPECT_TRUE(!StatusOrErr);
30 return toString(E: StatusOrErr.takeError());
31}
32
33static double convertToDoubleFromString(StringRef Str) {
34 llvm::APFloat F(0.0);
35 auto StatusOrErr =
36 F.convertFromString(Str, llvm::APFloat::rmNearestTiesToEven);
37 EXPECT_FALSE(!StatusOrErr);
38 consumeError(Err: StatusOrErr.takeError());
39 return F.convertToDouble();
40}
41
42static std::string convertToString(double d, unsigned Prec, unsigned Pad,
43 bool Tr = true) {
44 llvm::SmallVector<char, 100> Buffer;
45 llvm::APFloat F(d);
46 F.toString(Str&: Buffer, FormatPrecision: Prec, FormatMaxPadding: Pad, TruncateZero: Tr);
47 return std::string(Buffer.data(), Buffer.size());
48}
49
50namespace {
51
52TEST(APFloatTest, isSignaling) {
53 // We test qNaN, -qNaN, +sNaN, -sNaN with and without payloads. *NOTE* The
54 // positive/negative distinction is included only since the getQNaN/getSNaN
55 // API provides the option.
56 APInt payload = APInt::getOneBitSet(numBits: 4, BitNo: 2);
57 APFloat QNan = APFloat::getQNaN(Sem: APFloat::IEEEsingle(), Negative: false);
58 EXPECT_FALSE(QNan.isSignaling());
59 EXPECT_EQ(fcQNan, QNan.classify());
60
61 EXPECT_FALSE(APFloat::getQNaN(APFloat::IEEEsingle(), true).isSignaling());
62 EXPECT_FALSE(APFloat::getQNaN(APFloat::IEEEsingle(), false, &payload).isSignaling());
63 EXPECT_FALSE(APFloat::getQNaN(APFloat::IEEEsingle(), true, &payload).isSignaling());
64
65 APFloat SNan = APFloat::getSNaN(Sem: APFloat::IEEEsingle(), Negative: false);
66 EXPECT_TRUE(SNan.isSignaling());
67 EXPECT_EQ(fcSNan, SNan.classify());
68
69 EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), true).isSignaling());
70 EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), false, &payload).isSignaling());
71 EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), true, &payload).isSignaling());
72}
73
74TEST(APFloatTest, next) {
75
76 APFloat test(APFloat::IEEEquad(), APFloat::uninitialized);
77 APFloat expected(APFloat::IEEEquad(), APFloat::uninitialized);
78
79 // 1. Test Special Cases Values.
80 //
81 // Test all special values for nextUp and nextDown perscribed by IEEE-754R
82 // 2008. These are:
83 // 1. +inf
84 // 2. -inf
85 // 3. getLargest()
86 // 4. -getLargest()
87 // 5. getSmallest()
88 // 6. -getSmallest()
89 // 7. qNaN
90 // 8. sNaN
91 // 9. +0
92 // 10. -0
93
94 // nextUp(+inf) = +inf.
95 test = APFloat::getInf(Sem: APFloat::IEEEquad(), Negative: false);
96 expected = APFloat::getInf(Sem: APFloat::IEEEquad(), Negative: false);
97 EXPECT_EQ(test.next(false), APFloat::opOK);
98 EXPECT_TRUE(test.isInfinity());
99 EXPECT_TRUE(!test.isNegative());
100 EXPECT_TRUE(test.bitwiseIsEqual(expected));
101
102 // nextDown(+inf) = -nextUp(-inf) = -(-getLargest()) = getLargest()
103 test = APFloat::getInf(Sem: APFloat::IEEEquad(), Negative: false);
104 expected = APFloat::getLargest(Sem: APFloat::IEEEquad(), Negative: false);
105 EXPECT_EQ(test.next(true), APFloat::opOK);
106 EXPECT_TRUE(!test.isNegative());
107 EXPECT_TRUE(test.bitwiseIsEqual(expected));
108
109 // nextUp(-inf) = -getLargest()
110 test = APFloat::getInf(Sem: APFloat::IEEEquad(), Negative: true);
111 expected = APFloat::getLargest(Sem: APFloat::IEEEquad(), Negative: true);
112 EXPECT_EQ(test.next(false), APFloat::opOK);
113 EXPECT_TRUE(test.isNegative());
114 EXPECT_TRUE(test.bitwiseIsEqual(expected));
115
116 // nextDown(-inf) = -nextUp(+inf) = -(+inf) = -inf.
117 test = APFloat::getInf(Sem: APFloat::IEEEquad(), Negative: true);
118 expected = APFloat::getInf(Sem: APFloat::IEEEquad(), Negative: true);
119 EXPECT_EQ(test.next(true), APFloat::opOK);
120 EXPECT_TRUE(test.isInfinity() && test.isNegative());
121 EXPECT_TRUE(test.bitwiseIsEqual(expected));
122
123 // nextUp(getLargest()) = +inf
124 test = APFloat::getLargest(Sem: APFloat::IEEEquad(), Negative: false);
125 expected = APFloat::getInf(Sem: APFloat::IEEEquad(), Negative: false);
126 EXPECT_EQ(test.next(false), APFloat::opOK);
127 EXPECT_TRUE(test.isInfinity() && !test.isNegative());
128 EXPECT_TRUE(test.bitwiseIsEqual(expected));
129
130 // nextDown(getLargest()) = -nextUp(-getLargest())
131 // = -(-getLargest() + inc)
132 // = getLargest() - inc.
133 test = APFloat::getLargest(Sem: APFloat::IEEEquad(), Negative: false);
134 expected = APFloat(APFloat::IEEEquad(),
135 "0x1.fffffffffffffffffffffffffffep+16383");
136 EXPECT_EQ(test.next(true), APFloat::opOK);
137 EXPECT_TRUE(!test.isInfinity() && !test.isNegative());
138 EXPECT_TRUE(test.bitwiseIsEqual(expected));
139
140 // nextUp(-getLargest()) = -getLargest() + inc.
141 test = APFloat::getLargest(Sem: APFloat::IEEEquad(), Negative: true);
142 expected = APFloat(APFloat::IEEEquad(),
143 "-0x1.fffffffffffffffffffffffffffep+16383");
144 EXPECT_EQ(test.next(false), APFloat::opOK);
145 EXPECT_TRUE(test.bitwiseIsEqual(expected));
146
147 // nextDown(-getLargest()) = -nextUp(getLargest()) = -(inf) = -inf.
148 test = APFloat::getLargest(Sem: APFloat::IEEEquad(), Negative: true);
149 expected = APFloat::getInf(Sem: APFloat::IEEEquad(), Negative: true);
150 EXPECT_EQ(test.next(true), APFloat::opOK);
151 EXPECT_TRUE(test.isInfinity() && test.isNegative());
152 EXPECT_TRUE(test.bitwiseIsEqual(expected));
153
154 // nextUp(getSmallest()) = getSmallest() + inc.
155 test = APFloat(APFloat::IEEEquad(), "0x0.0000000000000000000000000001p-16382");
156 expected = APFloat(APFloat::IEEEquad(),
157 "0x0.0000000000000000000000000002p-16382");
158 EXPECT_EQ(test.next(false), APFloat::opOK);
159 EXPECT_TRUE(test.bitwiseIsEqual(expected));
160
161 // nextDown(getSmallest()) = -nextUp(-getSmallest()) = -(-0) = +0.
162 test = APFloat(APFloat::IEEEquad(), "0x0.0000000000000000000000000001p-16382");
163 expected = APFloat::getZero(Sem: APFloat::IEEEquad(), Negative: false);
164 EXPECT_EQ(test.next(true), APFloat::opOK);
165 EXPECT_TRUE(test.isPosZero());
166 EXPECT_TRUE(test.bitwiseIsEqual(expected));
167
168 // nextUp(-getSmallest()) = -0.
169 test = APFloat(APFloat::IEEEquad(), "-0x0.0000000000000000000000000001p-16382");
170 expected = APFloat::getZero(Sem: APFloat::IEEEquad(), Negative: true);
171 EXPECT_EQ(test.next(false), APFloat::opOK);
172 EXPECT_TRUE(test.isNegZero());
173 EXPECT_TRUE(test.bitwiseIsEqual(expected));
174
175 // nextDown(-getSmallest()) = -nextUp(getSmallest()) = -getSmallest() - inc.
176 test = APFloat(APFloat::IEEEquad(), "-0x0.0000000000000000000000000001p-16382");
177 expected = APFloat(APFloat::IEEEquad(),
178 "-0x0.0000000000000000000000000002p-16382");
179 EXPECT_EQ(test.next(true), APFloat::opOK);
180 EXPECT_TRUE(test.bitwiseIsEqual(expected));
181
182 // nextUp(qNaN) = qNaN
183 test = APFloat::getQNaN(Sem: APFloat::IEEEquad(), Negative: false);
184 expected = APFloat::getQNaN(Sem: APFloat::IEEEquad(), Negative: false);
185 EXPECT_EQ(test.next(false), APFloat::opOK);
186 EXPECT_TRUE(test.bitwiseIsEqual(expected));
187
188 // nextDown(qNaN) = qNaN
189 test = APFloat::getQNaN(Sem: APFloat::IEEEquad(), Negative: false);
190 expected = APFloat::getQNaN(Sem: APFloat::IEEEquad(), Negative: false);
191 EXPECT_EQ(test.next(true), APFloat::opOK);
192 EXPECT_TRUE(test.bitwiseIsEqual(expected));
193
194 // nextUp(sNaN) = qNaN
195 test = APFloat::getSNaN(Sem: APFloat::IEEEquad(), Negative: false);
196 expected = APFloat::getQNaN(Sem: APFloat::IEEEquad(), Negative: false);
197 EXPECT_EQ(test.next(false), APFloat::opInvalidOp);
198 EXPECT_TRUE(test.bitwiseIsEqual(expected));
199
200 // nextDown(sNaN) = qNaN
201 test = APFloat::getSNaN(Sem: APFloat::IEEEquad(), Negative: false);
202 expected = APFloat::getQNaN(Sem: APFloat::IEEEquad(), Negative: false);
203 EXPECT_EQ(test.next(true), APFloat::opInvalidOp);
204 EXPECT_TRUE(test.bitwiseIsEqual(expected));
205
206 // nextUp(+0) = +getSmallest()
207 test = APFloat::getZero(Sem: APFloat::IEEEquad(), Negative: false);
208 expected = APFloat::getSmallest(Sem: APFloat::IEEEquad(), Negative: false);
209 EXPECT_EQ(test.next(false), APFloat::opOK);
210 EXPECT_TRUE(test.bitwiseIsEqual(expected));
211
212 // nextDown(+0) = -nextUp(-0) = -getSmallest()
213 test = APFloat::getZero(Sem: APFloat::IEEEquad(), Negative: false);
214 expected = APFloat::getSmallest(Sem: APFloat::IEEEquad(), Negative: true);
215 EXPECT_EQ(test.next(true), APFloat::opOK);
216 EXPECT_TRUE(test.bitwiseIsEqual(expected));
217
218 // nextUp(-0) = +getSmallest()
219 test = APFloat::getZero(Sem: APFloat::IEEEquad(), Negative: true);
220 expected = APFloat::getSmallest(Sem: APFloat::IEEEquad(), Negative: false);
221 EXPECT_EQ(test.next(false), APFloat::opOK);
222 EXPECT_TRUE(test.bitwiseIsEqual(expected));
223
224 // nextDown(-0) = -nextUp(0) = -getSmallest()
225 test = APFloat::getZero(Sem: APFloat::IEEEquad(), Negative: true);
226 expected = APFloat::getSmallest(Sem: APFloat::IEEEquad(), Negative: true);
227 EXPECT_EQ(test.next(true), APFloat::opOK);
228 EXPECT_TRUE(test.bitwiseIsEqual(expected));
229
230 // 2. Binade Boundary Tests.
231
232 // 2a. Test denormal <-> normal binade boundaries.
233 // * nextUp(+Largest Denormal) -> +Smallest Normal.
234 // * nextDown(-Largest Denormal) -> -Smallest Normal.
235 // * nextUp(-Smallest Normal) -> -Largest Denormal.
236 // * nextDown(+Smallest Normal) -> +Largest Denormal.
237
238 // nextUp(+Largest Denormal) -> +Smallest Normal.
239 test = APFloat(APFloat::IEEEquad(), "0x0.ffffffffffffffffffffffffffffp-16382");
240 expected = APFloat(APFloat::IEEEquad(),
241 "0x1.0000000000000000000000000000p-16382");
242 EXPECT_EQ(test.next(false), APFloat::opOK);
243 EXPECT_FALSE(test.isDenormal());
244 EXPECT_TRUE(test.bitwiseIsEqual(expected));
245
246 // nextDown(-Largest Denormal) -> -Smallest Normal.
247 test = APFloat(APFloat::IEEEquad(),
248 "-0x0.ffffffffffffffffffffffffffffp-16382");
249 expected = APFloat(APFloat::IEEEquad(),
250 "-0x1.0000000000000000000000000000p-16382");
251 EXPECT_EQ(test.next(true), APFloat::opOK);
252 EXPECT_FALSE(test.isDenormal());
253 EXPECT_TRUE(test.bitwiseIsEqual(expected));
254
255 // nextUp(-Smallest Normal) -> -LargestDenormal.
256 test = APFloat(APFloat::IEEEquad(),
257 "-0x1.0000000000000000000000000000p-16382");
258 expected = APFloat(APFloat::IEEEquad(),
259 "-0x0.ffffffffffffffffffffffffffffp-16382");
260 EXPECT_EQ(test.next(false), APFloat::opOK);
261 EXPECT_TRUE(test.isDenormal());
262 EXPECT_TRUE(test.bitwiseIsEqual(expected));
263
264 // nextDown(+Smallest Normal) -> +Largest Denormal.
265 test = APFloat(APFloat::IEEEquad(),
266 "+0x1.0000000000000000000000000000p-16382");
267 expected = APFloat(APFloat::IEEEquad(),
268 "+0x0.ffffffffffffffffffffffffffffp-16382");
269 EXPECT_EQ(test.next(true), APFloat::opOK);
270 EXPECT_TRUE(test.isDenormal());
271 EXPECT_TRUE(test.bitwiseIsEqual(expected));
272
273 // 2b. Test normal <-> normal binade boundaries.
274 // * nextUp(-Normal Binade Boundary) -> -Normal Binade Boundary + 1.
275 // * nextDown(+Normal Binade Boundary) -> +Normal Binade Boundary - 1.
276 // * nextUp(+Normal Binade Boundary - 1) -> +Normal Binade Boundary.
277 // * nextDown(-Normal Binade Boundary + 1) -> -Normal Binade Boundary.
278
279 // nextUp(-Normal Binade Boundary) -> -Normal Binade Boundary + 1.
280 test = APFloat(APFloat::IEEEquad(), "-0x1p+1");
281 expected = APFloat(APFloat::IEEEquad(),
282 "-0x1.ffffffffffffffffffffffffffffp+0");
283 EXPECT_EQ(test.next(false), APFloat::opOK);
284 EXPECT_TRUE(test.bitwiseIsEqual(expected));
285
286 // nextDown(+Normal Binade Boundary) -> +Normal Binade Boundary - 1.
287 test = APFloat(APFloat::IEEEquad(), "0x1p+1");
288 expected = APFloat(APFloat::IEEEquad(), "0x1.ffffffffffffffffffffffffffffp+0");
289 EXPECT_EQ(test.next(true), APFloat::opOK);
290 EXPECT_TRUE(test.bitwiseIsEqual(expected));
291
292 // nextUp(+Normal Binade Boundary - 1) -> +Normal Binade Boundary.
293 test = APFloat(APFloat::IEEEquad(), "0x1.ffffffffffffffffffffffffffffp+0");
294 expected = APFloat(APFloat::IEEEquad(), "0x1p+1");
295 EXPECT_EQ(test.next(false), APFloat::opOK);
296 EXPECT_TRUE(test.bitwiseIsEqual(expected));
297
298 // nextDown(-Normal Binade Boundary + 1) -> -Normal Binade Boundary.
299 test = APFloat(APFloat::IEEEquad(), "-0x1.ffffffffffffffffffffffffffffp+0");
300 expected = APFloat(APFloat::IEEEquad(), "-0x1p+1");
301 EXPECT_EQ(test.next(true), APFloat::opOK);
302 EXPECT_TRUE(test.bitwiseIsEqual(expected));
303
304 // 2c. Test using next at binade boundaries with a direction away from the
305 // binade boundary. Away from denormal <-> normal boundaries.
306 //
307 // This is to make sure that even though we are at a binade boundary, since
308 // we are rounding away, we do not trigger the binade boundary code. Thus we
309 // test:
310 // * nextUp(-Largest Denormal) -> -Largest Denormal + inc.
311 // * nextDown(+Largest Denormal) -> +Largest Denormal - inc.
312 // * nextUp(+Smallest Normal) -> +Smallest Normal + inc.
313 // * nextDown(-Smallest Normal) -> -Smallest Normal - inc.
314
315 // nextUp(-Largest Denormal) -> -Largest Denormal + inc.
316 test = APFloat(APFloat::IEEEquad(), "-0x0.ffffffffffffffffffffffffffffp-16382");
317 expected = APFloat(APFloat::IEEEquad(),
318 "-0x0.fffffffffffffffffffffffffffep-16382");
319 EXPECT_EQ(test.next(false), APFloat::opOK);
320 EXPECT_TRUE(test.isDenormal());
321 EXPECT_TRUE(test.isNegative());
322 EXPECT_TRUE(test.bitwiseIsEqual(expected));
323
324 // nextDown(+Largest Denormal) -> +Largest Denormal - inc.
325 test = APFloat(APFloat::IEEEquad(), "0x0.ffffffffffffffffffffffffffffp-16382");
326 expected = APFloat(APFloat::IEEEquad(),
327 "0x0.fffffffffffffffffffffffffffep-16382");
328 EXPECT_EQ(test.next(true), APFloat::opOK);
329 EXPECT_TRUE(test.isDenormal());
330 EXPECT_TRUE(!test.isNegative());
331 EXPECT_TRUE(test.bitwiseIsEqual(expected));
332
333 // nextUp(+Smallest Normal) -> +Smallest Normal + inc.
334 test = APFloat(APFloat::IEEEquad(), "0x1.0000000000000000000000000000p-16382");
335 expected = APFloat(APFloat::IEEEquad(),
336 "0x1.0000000000000000000000000001p-16382");
337 EXPECT_EQ(test.next(false), APFloat::opOK);
338 EXPECT_TRUE(!test.isDenormal());
339 EXPECT_TRUE(!test.isNegative());
340 EXPECT_TRUE(test.bitwiseIsEqual(expected));
341
342 // nextDown(-Smallest Normal) -> -Smallest Normal - inc.
343 test = APFloat(APFloat::IEEEquad(), "-0x1.0000000000000000000000000000p-16382");
344 expected = APFloat(APFloat::IEEEquad(),
345 "-0x1.0000000000000000000000000001p-16382");
346 EXPECT_EQ(test.next(true), APFloat::opOK);
347 EXPECT_TRUE(!test.isDenormal());
348 EXPECT_TRUE(test.isNegative());
349 EXPECT_TRUE(test.bitwiseIsEqual(expected));
350
351 // 2d. Test values which cause our exponent to go to min exponent. This
352 // is to ensure that guards in the code to check for min exponent
353 // trigger properly.
354 // * nextUp(-0x1p-16381) -> -0x1.ffffffffffffffffffffffffffffp-16382
355 // * nextDown(-0x1.ffffffffffffffffffffffffffffp-16382) ->
356 // -0x1p-16381
357 // * nextUp(0x1.ffffffffffffffffffffffffffffp-16382) -> 0x1p-16382
358 // * nextDown(0x1p-16382) -> 0x1.ffffffffffffffffffffffffffffp-16382
359
360 // nextUp(-0x1p-16381) -> -0x1.ffffffffffffffffffffffffffffp-16382
361 test = APFloat(APFloat::IEEEquad(), "-0x1p-16381");
362 expected = APFloat(APFloat::IEEEquad(),
363 "-0x1.ffffffffffffffffffffffffffffp-16382");
364 EXPECT_EQ(test.next(false), APFloat::opOK);
365 EXPECT_TRUE(test.bitwiseIsEqual(expected));
366
367 // nextDown(-0x1.ffffffffffffffffffffffffffffp-16382) ->
368 // -0x1p-16381
369 test = APFloat(APFloat::IEEEquad(), "-0x1.ffffffffffffffffffffffffffffp-16382");
370 expected = APFloat(APFloat::IEEEquad(), "-0x1p-16381");
371 EXPECT_EQ(test.next(true), APFloat::opOK);
372 EXPECT_TRUE(test.bitwiseIsEqual(expected));
373
374 // nextUp(0x1.ffffffffffffffffffffffffffffp-16382) -> 0x1p-16381
375 test = APFloat(APFloat::IEEEquad(), "0x1.ffffffffffffffffffffffffffffp-16382");
376 expected = APFloat(APFloat::IEEEquad(), "0x1p-16381");
377 EXPECT_EQ(test.next(false), APFloat::opOK);
378 EXPECT_TRUE(test.bitwiseIsEqual(expected));
379
380 // nextDown(0x1p-16381) -> 0x1.ffffffffffffffffffffffffffffp-16382
381 test = APFloat(APFloat::IEEEquad(), "0x1p-16381");
382 expected = APFloat(APFloat::IEEEquad(),
383 "0x1.ffffffffffffffffffffffffffffp-16382");
384 EXPECT_EQ(test.next(true), APFloat::opOK);
385 EXPECT_TRUE(test.bitwiseIsEqual(expected));
386
387 // 3. Now we test both denormal/normal computation which will not cause us
388 // to go across binade boundaries. Specifically we test:
389 // * nextUp(+Denormal) -> +Denormal.
390 // * nextDown(+Denormal) -> +Denormal.
391 // * nextUp(-Denormal) -> -Denormal.
392 // * nextDown(-Denormal) -> -Denormal.
393 // * nextUp(+Normal) -> +Normal.
394 // * nextDown(+Normal) -> +Normal.
395 // * nextUp(-Normal) -> -Normal.
396 // * nextDown(-Normal) -> -Normal.
397
398 // nextUp(+Denormal) -> +Denormal.
399 test = APFloat(APFloat::IEEEquad(),
400 "0x0.ffffffffffffffffffffffff000cp-16382");
401 expected = APFloat(APFloat::IEEEquad(),
402 "0x0.ffffffffffffffffffffffff000dp-16382");
403 EXPECT_EQ(test.next(false), APFloat::opOK);
404 EXPECT_TRUE(test.isDenormal());
405 EXPECT_TRUE(!test.isNegative());
406 EXPECT_TRUE(test.bitwiseIsEqual(expected));
407
408 // nextDown(+Denormal) -> +Denormal.
409 test = APFloat(APFloat::IEEEquad(),
410 "0x0.ffffffffffffffffffffffff000cp-16382");
411 expected = APFloat(APFloat::IEEEquad(),
412 "0x0.ffffffffffffffffffffffff000bp-16382");
413 EXPECT_EQ(test.next(true), APFloat::opOK);
414 EXPECT_TRUE(test.isDenormal());
415 EXPECT_TRUE(!test.isNegative());
416 EXPECT_TRUE(test.bitwiseIsEqual(expected));
417
418 // nextUp(-Denormal) -> -Denormal.
419 test = APFloat(APFloat::IEEEquad(),
420 "-0x0.ffffffffffffffffffffffff000cp-16382");
421 expected = APFloat(APFloat::IEEEquad(),
422 "-0x0.ffffffffffffffffffffffff000bp-16382");
423 EXPECT_EQ(test.next(false), APFloat::opOK);
424 EXPECT_TRUE(test.isDenormal());
425 EXPECT_TRUE(test.isNegative());
426 EXPECT_TRUE(test.bitwiseIsEqual(expected));
427
428 // nextDown(-Denormal) -> -Denormal
429 test = APFloat(APFloat::IEEEquad(),
430 "-0x0.ffffffffffffffffffffffff000cp-16382");
431 expected = APFloat(APFloat::IEEEquad(),
432 "-0x0.ffffffffffffffffffffffff000dp-16382");
433 EXPECT_EQ(test.next(true), APFloat::opOK);
434 EXPECT_TRUE(test.isDenormal());
435 EXPECT_TRUE(test.isNegative());
436 EXPECT_TRUE(test.bitwiseIsEqual(expected));
437
438 // nextUp(+Normal) -> +Normal.
439 test = APFloat(APFloat::IEEEquad(),
440 "0x1.ffffffffffffffffffffffff000cp-16000");
441 expected = APFloat(APFloat::IEEEquad(),
442 "0x1.ffffffffffffffffffffffff000dp-16000");
443 EXPECT_EQ(test.next(false), APFloat::opOK);
444 EXPECT_TRUE(!test.isDenormal());
445 EXPECT_TRUE(!test.isNegative());
446 EXPECT_TRUE(test.bitwiseIsEqual(expected));
447
448 // nextDown(+Normal) -> +Normal.
449 test = APFloat(APFloat::IEEEquad(),
450 "0x1.ffffffffffffffffffffffff000cp-16000");
451 expected = APFloat(APFloat::IEEEquad(),
452 "0x1.ffffffffffffffffffffffff000bp-16000");
453 EXPECT_EQ(test.next(true), APFloat::opOK);
454 EXPECT_TRUE(!test.isDenormal());
455 EXPECT_TRUE(!test.isNegative());
456 EXPECT_TRUE(test.bitwiseIsEqual(expected));
457
458 // nextUp(-Normal) -> -Normal.
459 test = APFloat(APFloat::IEEEquad(),
460 "-0x1.ffffffffffffffffffffffff000cp-16000");
461 expected = APFloat(APFloat::IEEEquad(),
462 "-0x1.ffffffffffffffffffffffff000bp-16000");
463 EXPECT_EQ(test.next(false), APFloat::opOK);
464 EXPECT_TRUE(!test.isDenormal());
465 EXPECT_TRUE(test.isNegative());
466 EXPECT_TRUE(test.bitwiseIsEqual(expected));
467
468 // nextDown(-Normal) -> -Normal.
469 test = APFloat(APFloat::IEEEquad(),
470 "-0x1.ffffffffffffffffffffffff000cp-16000");
471 expected = APFloat(APFloat::IEEEquad(),
472 "-0x1.ffffffffffffffffffffffff000dp-16000");
473 EXPECT_EQ(test.next(true), APFloat::opOK);
474 EXPECT_TRUE(!test.isDenormal());
475 EXPECT_TRUE(test.isNegative());
476 EXPECT_TRUE(test.bitwiseIsEqual(expected));
477}
478
479TEST(APFloatTest, FMA) {
480 APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven;
481
482 {
483 APFloat f1(14.5f);
484 APFloat f2(-14.5f);
485 APFloat f3(225.0f);
486 f1.fusedMultiplyAdd(Multiplicand: f2, Addend: f3, RM: APFloat::rmNearestTiesToEven);
487 EXPECT_EQ(14.75f, f1.convertToFloat());
488 }
489
490 {
491 APFloat Val2(2.0f);
492 APFloat f1((float)1.17549435e-38F);
493 APFloat f2((float)1.17549435e-38F);
494 f1.divide(RHS: Val2, RM: rdmd);
495 f2.divide(RHS: Val2, RM: rdmd);
496 APFloat f3(12.0f);
497 f1.fusedMultiplyAdd(Multiplicand: f2, Addend: f3, RM: APFloat::rmNearestTiesToEven);
498 EXPECT_EQ(12.0f, f1.convertToFloat());
499 }
500
501 // Test for correct zero sign when answer is exactly zero.
502 // fma(1.0, -1.0, 1.0) -> +ve 0.
503 {
504 APFloat f1(1.0);
505 APFloat f2(-1.0);
506 APFloat f3(1.0);
507 f1.fusedMultiplyAdd(Multiplicand: f2, Addend: f3, RM: APFloat::rmNearestTiesToEven);
508 EXPECT_TRUE(!f1.isNegative() && f1.isZero());
509 }
510
511 // Test for correct zero sign when answer is exactly zero and rounding towards
512 // negative.
513 // fma(1.0, -1.0, 1.0) -> +ve 0.
514 {
515 APFloat f1(1.0);
516 APFloat f2(-1.0);
517 APFloat f3(1.0);
518 f1.fusedMultiplyAdd(Multiplicand: f2, Addend: f3, RM: APFloat::rmTowardNegative);
519 EXPECT_TRUE(f1.isNegative() && f1.isZero());
520 }
521
522 // Test for correct (in this case -ve) sign when adding like signed zeros.
523 // Test fma(0.0, -0.0, -0.0) -> -ve 0.
524 {
525 APFloat f1(0.0);
526 APFloat f2(-0.0);
527 APFloat f3(-0.0);
528 f1.fusedMultiplyAdd(Multiplicand: f2, Addend: f3, RM: APFloat::rmNearestTiesToEven);
529 EXPECT_TRUE(f1.isNegative() && f1.isZero());
530 }
531
532 // Test -ve sign preservation when small negative results underflow.
533 {
534 APFloat f1(APFloat::IEEEdouble(), "-0x1p-1074");
535 APFloat f2(APFloat::IEEEdouble(), "+0x1p-1074");
536 APFloat f3(0.0);
537 f1.fusedMultiplyAdd(Multiplicand: f2, Addend: f3, RM: APFloat::rmNearestTiesToEven);
538 EXPECT_TRUE(f1.isNegative() && f1.isZero());
539 }
540
541 // Test x87 extended precision case from http://llvm.org/PR20728.
542 {
543 APFloat M1(APFloat::x87DoubleExtended(), 1);
544 APFloat M2(APFloat::x87DoubleExtended(), 1);
545 APFloat A(APFloat::x87DoubleExtended(), 3);
546
547 bool losesInfo = false;
548 M1.fusedMultiplyAdd(Multiplicand: M1, Addend: A, RM: APFloat::rmNearestTiesToEven);
549 M1.convert(ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
550 EXPECT_FALSE(losesInfo);
551 EXPECT_EQ(4.0f, M1.convertToFloat());
552 }
553
554 // Regression test that failed an assertion.
555 {
556 APFloat f1(-8.85242279E-41f);
557 APFloat f2(2.0f);
558 APFloat f3(8.85242279E-41f);
559 f1.fusedMultiplyAdd(Multiplicand: f2, Addend: f3, RM: APFloat::rmNearestTiesToEven);
560 EXPECT_EQ(-8.85242279E-41f, f1.convertToFloat());
561 }
562
563 // Test using only a single instance of APFloat.
564 {
565 APFloat F(1.5);
566
567 F.fusedMultiplyAdd(Multiplicand: F, Addend: F, RM: APFloat::rmNearestTiesToEven);
568 EXPECT_EQ(3.75, F.convertToDouble());
569 }
570}
571
572TEST(APFloatTest, MinNum) {
573 APFloat f1(1.0);
574 APFloat f2(2.0);
575 APFloat nan = APFloat::getNaN(Sem: APFloat::IEEEdouble());
576
577 EXPECT_EQ(1.0, minnum(f1, f2).convertToDouble());
578 EXPECT_EQ(1.0, minnum(f2, f1).convertToDouble());
579 EXPECT_EQ(1.0, minnum(f1, nan).convertToDouble());
580 EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble());
581
582 APFloat zp(0.0);
583 APFloat zn(-0.0);
584 EXPECT_EQ(-0.0, minnum(zp, zn).convertToDouble());
585 EXPECT_EQ(-0.0, minnum(zn, zp).convertToDouble());
586}
587
588TEST(APFloatTest, MaxNum) {
589 APFloat f1(1.0);
590 APFloat f2(2.0);
591 APFloat nan = APFloat::getNaN(Sem: APFloat::IEEEdouble());
592
593 EXPECT_EQ(2.0, maxnum(f1, f2).convertToDouble());
594 EXPECT_EQ(2.0, maxnum(f2, f1).convertToDouble());
595 EXPECT_EQ(1.0, maxnum(f1, nan).convertToDouble());
596 EXPECT_EQ(1.0, maxnum(nan, f1).convertToDouble());
597
598 APFloat zp(0.0);
599 APFloat zn(-0.0);
600 EXPECT_EQ(0.0, maxnum(zp, zn).convertToDouble());
601 EXPECT_EQ(0.0, maxnum(zn, zp).convertToDouble());
602}
603
604TEST(APFloatTest, Minimum) {
605 APFloat f1(1.0);
606 APFloat f2(2.0);
607 APFloat zp(0.0);
608 APFloat zn(-0.0);
609 APFloat nan = APFloat::getNaN(Sem: APFloat::IEEEdouble());
610
611 EXPECT_EQ(1.0, minimum(f1, f2).convertToDouble());
612 EXPECT_EQ(1.0, minimum(f2, f1).convertToDouble());
613 EXPECT_EQ(-0.0, minimum(zp, zn).convertToDouble());
614 EXPECT_EQ(-0.0, minimum(zn, zp).convertToDouble());
615 EXPECT_TRUE(std::isnan(minimum(f1, nan).convertToDouble()));
616 EXPECT_TRUE(std::isnan(minimum(nan, f1).convertToDouble()));
617}
618
619TEST(APFloatTest, Maximum) {
620 APFloat f1(1.0);
621 APFloat f2(2.0);
622 APFloat zp(0.0);
623 APFloat zn(-0.0);
624 APFloat nan = APFloat::getNaN(Sem: APFloat::IEEEdouble());
625
626 EXPECT_EQ(2.0, maximum(f1, f2).convertToDouble());
627 EXPECT_EQ(2.0, maximum(f2, f1).convertToDouble());
628 EXPECT_EQ(0.0, maximum(zp, zn).convertToDouble());
629 EXPECT_EQ(0.0, maximum(zn, zp).convertToDouble());
630 EXPECT_TRUE(std::isnan(maximum(f1, nan).convertToDouble()));
631 EXPECT_TRUE(std::isnan(maximum(nan, f1).convertToDouble()));
632}
633
634TEST(APFloatTest, Denormal) {
635 APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven;
636
637 // Test single precision
638 {
639 const char *MinNormalStr = "1.17549435082228750797e-38";
640 EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), MinNormalStr).isDenormal());
641 EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), 0).isDenormal());
642
643 APFloat Val2(APFloat::IEEEsingle(), 2);
644 APFloat T(APFloat::IEEEsingle(), MinNormalStr);
645 T.divide(RHS: Val2, RM: rdmd);
646 EXPECT_TRUE(T.isDenormal());
647 EXPECT_EQ(fcPosSubnormal, T.classify());
648
649
650 const char *NegMinNormalStr = "-1.17549435082228750797e-38";
651 EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), NegMinNormalStr).isDenormal());
652 APFloat NegT(APFloat::IEEEsingle(), NegMinNormalStr);
653 NegT.divide(RHS: Val2, RM: rdmd);
654 EXPECT_TRUE(NegT.isDenormal());
655 EXPECT_EQ(fcNegSubnormal, NegT.classify());
656 }
657
658 // Test double precision
659 {
660 const char *MinNormalStr = "2.22507385850720138309e-308";
661 EXPECT_FALSE(APFloat(APFloat::IEEEdouble(), MinNormalStr).isDenormal());
662 EXPECT_FALSE(APFloat(APFloat::IEEEdouble(), 0).isDenormal());
663
664 APFloat Val2(APFloat::IEEEdouble(), 2);
665 APFloat T(APFloat::IEEEdouble(), MinNormalStr);
666 T.divide(RHS: Val2, RM: rdmd);
667 EXPECT_TRUE(T.isDenormal());
668 EXPECT_EQ(fcPosSubnormal, T.classify());
669 }
670
671 // Test Intel double-ext
672 {
673 const char *MinNormalStr = "3.36210314311209350626e-4932";
674 EXPECT_FALSE(APFloat(APFloat::x87DoubleExtended(), MinNormalStr).isDenormal());
675 EXPECT_FALSE(APFloat(APFloat::x87DoubleExtended(), 0).isDenormal());
676
677 APFloat Val2(APFloat::x87DoubleExtended(), 2);
678 APFloat T(APFloat::x87DoubleExtended(), MinNormalStr);
679 T.divide(RHS: Val2, RM: rdmd);
680 EXPECT_TRUE(T.isDenormal());
681 EXPECT_EQ(fcPosSubnormal, T.classify());
682 }
683
684 // Test quadruple precision
685 {
686 const char *MinNormalStr = "3.36210314311209350626267781732175260e-4932";
687 EXPECT_FALSE(APFloat(APFloat::IEEEquad(), MinNormalStr).isDenormal());
688 EXPECT_FALSE(APFloat(APFloat::IEEEquad(), 0).isDenormal());
689
690 APFloat Val2(APFloat::IEEEquad(), 2);
691 APFloat T(APFloat::IEEEquad(), MinNormalStr);
692 T.divide(RHS: Val2, RM: rdmd);
693 EXPECT_TRUE(T.isDenormal());
694 EXPECT_EQ(fcPosSubnormal, T.classify());
695 }
696
697 // Test TF32
698 {
699 const char *MinNormalStr = "1.17549435082228750797e-38";
700 EXPECT_FALSE(APFloat(APFloat::FloatTF32(), MinNormalStr).isDenormal());
701 EXPECT_FALSE(APFloat(APFloat::FloatTF32(), 0).isDenormal());
702
703 APFloat Val2(APFloat::FloatTF32(), 2);
704 APFloat T(APFloat::FloatTF32(), MinNormalStr);
705 T.divide(RHS: Val2, RM: rdmd);
706 EXPECT_TRUE(T.isDenormal());
707 EXPECT_EQ(fcPosSubnormal, T.classify());
708
709 const char *NegMinNormalStr = "-1.17549435082228750797e-38";
710 EXPECT_FALSE(APFloat(APFloat::FloatTF32(), NegMinNormalStr).isDenormal());
711 APFloat NegT(APFloat::FloatTF32(), NegMinNormalStr);
712 NegT.divide(RHS: Val2, RM: rdmd);
713 EXPECT_TRUE(NegT.isDenormal());
714 EXPECT_EQ(fcNegSubnormal, NegT.classify());
715 }
716}
717
718TEST(APFloatTest, IsSmallestNormalized) {
719 for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) {
720 const fltSemantics &Semantics =
721 APFloat::EnumToSemantics(S: static_cast<APFloat::Semantics>(I));
722
723 EXPECT_FALSE(APFloat::getZero(Semantics, false).isSmallestNormalized());
724 EXPECT_FALSE(APFloat::getZero(Semantics, true).isSmallestNormalized());
725
726 EXPECT_FALSE(APFloat::getInf(Semantics, false).isSmallestNormalized());
727 EXPECT_FALSE(APFloat::getInf(Semantics, true).isSmallestNormalized());
728
729 EXPECT_FALSE(APFloat::getQNaN(Semantics).isSmallestNormalized());
730 EXPECT_FALSE(APFloat::getSNaN(Semantics).isSmallestNormalized());
731
732 EXPECT_FALSE(APFloat::getLargest(Semantics).isSmallestNormalized());
733 EXPECT_FALSE(APFloat::getLargest(Semantics, true).isSmallestNormalized());
734
735 EXPECT_FALSE(APFloat::getSmallest(Semantics).isSmallestNormalized());
736 EXPECT_FALSE(APFloat::getSmallest(Semantics, true).isSmallestNormalized());
737
738 EXPECT_FALSE(APFloat::getAllOnesValue(Semantics).isSmallestNormalized());
739
740 APFloat PosSmallestNormalized =
741 APFloat::getSmallestNormalized(Sem: Semantics, Negative: false);
742 APFloat NegSmallestNormalized =
743 APFloat::getSmallestNormalized(Sem: Semantics, Negative: true);
744 EXPECT_TRUE(PosSmallestNormalized.isSmallestNormalized());
745 EXPECT_TRUE(NegSmallestNormalized.isSmallestNormalized());
746 EXPECT_EQ(fcPosNormal, PosSmallestNormalized.classify());
747 EXPECT_EQ(fcNegNormal, NegSmallestNormalized.classify());
748
749 for (APFloat *Val : {&PosSmallestNormalized, &NegSmallestNormalized}) {
750 bool OldSign = Val->isNegative();
751
752 // Step down, make sure it's still not smallest normalized.
753 EXPECT_EQ(APFloat::opOK, Val->next(false));
754 EXPECT_EQ(OldSign, Val->isNegative());
755 EXPECT_FALSE(Val->isSmallestNormalized());
756 EXPECT_EQ(OldSign, Val->isNegative());
757
758 // Step back up should restore it to being smallest normalized.
759 EXPECT_EQ(APFloat::opOK, Val->next(true));
760 EXPECT_TRUE(Val->isSmallestNormalized());
761 EXPECT_EQ(OldSign, Val->isNegative());
762
763 // Step beyond should no longer smallest normalized.
764 EXPECT_EQ(APFloat::opOK, Val->next(true));
765 EXPECT_FALSE(Val->isSmallestNormalized());
766 EXPECT_EQ(OldSign, Val->isNegative());
767 }
768 }
769}
770
771TEST(APFloatTest, Zero) {
772 EXPECT_EQ(0.0f, APFloat(0.0f).convertToFloat());
773 EXPECT_EQ(-0.0f, APFloat(-0.0f).convertToFloat());
774 EXPECT_TRUE(APFloat(-0.0f).isNegative());
775
776 EXPECT_EQ(0.0, APFloat(0.0).convertToDouble());
777 EXPECT_EQ(-0.0, APFloat(-0.0).convertToDouble());
778 EXPECT_TRUE(APFloat(-0.0).isNegative());
779
780 EXPECT_EQ(fcPosZero, APFloat(0.0).classify());
781 EXPECT_EQ(fcNegZero, APFloat(-0.0).classify());
782}
783
784TEST(APFloatTest, DecimalStringsWithoutNullTerminators) {
785 // Make sure that we can parse strings without null terminators.
786 // rdar://14323230.
787 EXPECT_EQ(convertToDoubleFromString(StringRef("0.00", 3)), 0.0);
788 EXPECT_EQ(convertToDoubleFromString(StringRef("0.01", 3)), 0.0);
789 EXPECT_EQ(convertToDoubleFromString(StringRef("0.09", 3)), 0.0);
790 EXPECT_EQ(convertToDoubleFromString(StringRef("0.095", 4)), 0.09);
791 EXPECT_EQ(convertToDoubleFromString(StringRef("0.00e+3", 7)), 0.00);
792 EXPECT_EQ(convertToDoubleFromString(StringRef("0e+3", 4)), 0.00);
793}
794
795TEST(APFloatTest, fromZeroDecimalString) {
796 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0").convertToDouble());
797 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0").convertToDouble());
798 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0").convertToDouble());
799
800 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.").convertToDouble());
801 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.").convertToDouble());
802 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.").convertToDouble());
803
804 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0").convertToDouble());
805 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0").convertToDouble());
806 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0").convertToDouble());
807
808 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0").convertToDouble());
809 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0").convertToDouble());
810 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0").convertToDouble());
811
812 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "00000.").convertToDouble());
813 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+00000.").convertToDouble());
814 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-00000.").convertToDouble());
815
816 EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), ".00000").convertToDouble());
817 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.00000").convertToDouble());
818 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.00000").convertToDouble());
819
820 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0000.00000").convertToDouble());
821 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0000.00000").convertToDouble());
822 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0000.00000").convertToDouble());
823}
824
825TEST(APFloatTest, fromZeroDecimalSingleExponentString) {
826 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e1").convertToDouble());
827 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e1").convertToDouble());
828 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e1").convertToDouble());
829
830 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e+1").convertToDouble());
831 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e+1").convertToDouble());
832 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e+1").convertToDouble());
833
834 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e-1").convertToDouble());
835 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e-1").convertToDouble());
836 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e-1").convertToDouble());
837
838
839 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.e1").convertToDouble());
840 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.e1").convertToDouble());
841 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.e1").convertToDouble());
842
843 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.e+1").convertToDouble());
844 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.e+1").convertToDouble());
845 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.e+1").convertToDouble());
846
847 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.e-1").convertToDouble());
848 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.e-1").convertToDouble());
849 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.e-1").convertToDouble());
850
851 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0e1").convertToDouble());
852 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0e1").convertToDouble());
853 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0e1").convertToDouble());
854
855 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0e+1").convertToDouble());
856 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0e+1").convertToDouble());
857 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0e+1").convertToDouble());
858
859 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0e-1").convertToDouble());
860 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0e-1").convertToDouble());
861 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0e-1").convertToDouble());
862
863
864 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0e1").convertToDouble());
865 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0e1").convertToDouble());
866 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0e1").convertToDouble());
867
868 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0e+1").convertToDouble());
869 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0e+1").convertToDouble());
870 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0e+1").convertToDouble());
871
872 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0e-1").convertToDouble());
873 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0e-1").convertToDouble());
874 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0e-1").convertToDouble());
875
876
877 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "000.0000e1").convertToDouble());
878 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+000.0000e+1").convertToDouble());
879 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-000.0000e+1").convertToDouble());
880}
881
882TEST(APFloatTest, fromZeroDecimalLargeExponentString) {
883 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e1234").convertToDouble());
884 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e1234").convertToDouble());
885 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e1234").convertToDouble());
886
887 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e+1234").convertToDouble());
888 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e+1234").convertToDouble());
889 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e+1234").convertToDouble());
890
891 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e-1234").convertToDouble());
892 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e-1234").convertToDouble());
893 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e-1234").convertToDouble());
894
895 EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), "000.0000e1234").convertToDouble());
896 EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), "000.0000e-1234").convertToDouble());
897
898 EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), StringRef("0e1234" "\0" "2", 6)).convertToDouble());
899}
900
901TEST(APFloatTest, fromZeroHexadecimalString) {
902 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p1").convertToDouble());
903 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0p1").convertToDouble());
904 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p1").convertToDouble());
905
906 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p+1").convertToDouble());
907 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0p+1").convertToDouble());
908 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p+1").convertToDouble());
909
910 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p-1").convertToDouble());
911 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0p-1").convertToDouble());
912 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p-1").convertToDouble());
913
914
915 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p1").convertToDouble());
916 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.p1").convertToDouble());
917 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.p1").convertToDouble());
918
919 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p+1").convertToDouble());
920 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.p+1").convertToDouble());
921 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.p+1").convertToDouble());
922
923 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p-1").convertToDouble());
924 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.p-1").convertToDouble());
925 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.p-1").convertToDouble());
926
927
928 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.0p1").convertToDouble());
929 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x.0p1").convertToDouble());
930 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x.0p1").convertToDouble());
931
932 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.0p+1").convertToDouble());
933 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x.0p+1").convertToDouble());
934 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x.0p+1").convertToDouble());
935
936 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.0p-1").convertToDouble());
937 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x.0p-1").convertToDouble());
938 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x.0p-1").convertToDouble());
939
940
941 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.0p1").convertToDouble());
942 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.0p1").convertToDouble());
943 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.0p1").convertToDouble());
944
945 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.0p+1").convertToDouble());
946 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.0p+1").convertToDouble());
947 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.0p+1").convertToDouble());
948
949 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.0p-1").convertToDouble());
950 EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.0p-1").convertToDouble());
951 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.0p-1").convertToDouble());
952
953
954 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x00000.p1").convertToDouble());
955 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0000.00000p1").convertToDouble());
956 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.00000p1").convertToDouble());
957 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p1").convertToDouble());
958 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p1234").convertToDouble());
959 EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p1234").convertToDouble());
960 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x00000.p1234").convertToDouble());
961 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0000.00000p1234").convertToDouble());
962 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.00000p1234").convertToDouble());
963 EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p1234").convertToDouble());
964}
965
966TEST(APFloatTest, fromDecimalString) {
967 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1").convertToDouble());
968 EXPECT_EQ(2.0, APFloat(APFloat::IEEEdouble(), "2.").convertToDouble());
969 EXPECT_EQ(0.5, APFloat(APFloat::IEEEdouble(), ".5").convertToDouble());
970 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0").convertToDouble());
971 EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble(), "-2").convertToDouble());
972 EXPECT_EQ(-4.0, APFloat(APFloat::IEEEdouble(), "-4.").convertToDouble());
973 EXPECT_EQ(-0.5, APFloat(APFloat::IEEEdouble(), "-.5").convertToDouble());
974 EXPECT_EQ(-1.5, APFloat(APFloat::IEEEdouble(), "-1.5").convertToDouble());
975 EXPECT_EQ(1.25e12, APFloat(APFloat::IEEEdouble(), "1.25e12").convertToDouble());
976 EXPECT_EQ(1.25e+12, APFloat(APFloat::IEEEdouble(), "1.25e+12").convertToDouble());
977 EXPECT_EQ(1.25e-12, APFloat(APFloat::IEEEdouble(), "1.25e-12").convertToDouble());
978 EXPECT_EQ(1024.0, APFloat(APFloat::IEEEdouble(), "1024.").convertToDouble());
979 EXPECT_EQ(1024.05, APFloat(APFloat::IEEEdouble(), "1024.05000").convertToDouble());
980 EXPECT_EQ(0.05, APFloat(APFloat::IEEEdouble(), ".05000").convertToDouble());
981 EXPECT_EQ(2.0, APFloat(APFloat::IEEEdouble(), "2.").convertToDouble());
982 EXPECT_EQ(2.0e2, APFloat(APFloat::IEEEdouble(), "2.e2").convertToDouble());
983 EXPECT_EQ(2.0e+2, APFloat(APFloat::IEEEdouble(), "2.e+2").convertToDouble());
984 EXPECT_EQ(2.0e-2, APFloat(APFloat::IEEEdouble(), "2.e-2").convertToDouble());
985 EXPECT_EQ(2.05e2, APFloat(APFloat::IEEEdouble(), "002.05000e2").convertToDouble());
986 EXPECT_EQ(2.05e+2, APFloat(APFloat::IEEEdouble(), "002.05000e+2").convertToDouble());
987 EXPECT_EQ(2.05e-2, APFloat(APFloat::IEEEdouble(), "002.05000e-2").convertToDouble());
988 EXPECT_EQ(2.05e12, APFloat(APFloat::IEEEdouble(), "002.05000e12").convertToDouble());
989 EXPECT_EQ(2.05e+12, APFloat(APFloat::IEEEdouble(), "002.05000e+12").convertToDouble());
990 EXPECT_EQ(2.05e-12, APFloat(APFloat::IEEEdouble(), "002.05000e-12").convertToDouble());
991
992 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1e").convertToDouble());
993 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "+1e").convertToDouble());
994 EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-1e").convertToDouble());
995
996 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.e").convertToDouble());
997 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "+1.e").convertToDouble());
998 EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-1.e").convertToDouble());
999
1000 EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e").convertToDouble());
1001 EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), "+.1e").convertToDouble());
1002 EXPECT_EQ(-0.1, APFloat(APFloat::IEEEdouble(), "-.1e").convertToDouble());
1003
1004 EXPECT_EQ(1.1, APFloat(APFloat::IEEEdouble(), "1.1e").convertToDouble());
1005 EXPECT_EQ(1.1, APFloat(APFloat::IEEEdouble(), "+1.1e").convertToDouble());
1006 EXPECT_EQ(-1.1, APFloat(APFloat::IEEEdouble(), "-1.1e").convertToDouble());
1007
1008 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1e+").convertToDouble());
1009 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1e-").convertToDouble());
1010
1011 EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e").convertToDouble());
1012 EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e+").convertToDouble());
1013 EXPECT_EQ(0.1, APFloat(APFloat::IEEEdouble(), ".1e-").convertToDouble());
1014
1015 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0e").convertToDouble());
1016 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0e+").convertToDouble());
1017 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0e-").convertToDouble());
1018
1019 // These are "carefully selected" to overflow the fast log-base
1020 // calculations in APFloat.cpp
1021 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "99e99999").isInfinity());
1022 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-99e99999").isInfinity());
1023 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "1e-99999").isPosZero());
1024 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-1e-99999").isNegZero());
1025
1026 EXPECT_EQ(2.71828, convertToDoubleFromString("2.71828"));
1027}
1028
1029TEST(APFloatTest, fromStringSpecials) {
1030 const fltSemantics &Sem = APFloat::IEEEdouble();
1031 const unsigned Precision = 53;
1032 const unsigned PayloadBits = Precision - 2;
1033 uint64_t PayloadMask = (uint64_t(1) << PayloadBits) - uint64_t(1);
1034
1035 uint64_t NaNPayloads[] = {
1036 0,
1037 1,
1038 123,
1039 0xDEADBEEF,
1040 uint64_t(-2),
1041 uint64_t(1) << PayloadBits, // overflow bit
1042 uint64_t(1) << (PayloadBits - 1), // signaling bit
1043 uint64_t(1) << (PayloadBits - 2) // highest possible bit
1044 };
1045
1046 // Convert payload integer to decimal string representation.
1047 std::string NaNPayloadDecStrings[std::size(NaNPayloads)];
1048 for (size_t I = 0; I < std::size(NaNPayloads); ++I)
1049 NaNPayloadDecStrings[I] = utostr(X: NaNPayloads[I]);
1050
1051 // Convert payload integer to hexadecimal string representation.
1052 std::string NaNPayloadHexStrings[std::size(NaNPayloads)];
1053 for (size_t I = 0; I < std::size(NaNPayloads); ++I)
1054 NaNPayloadHexStrings[I] = "0x" + utohexstr(X: NaNPayloads[I]);
1055
1056 // Fix payloads to expected result.
1057 for (uint64_t &Payload : NaNPayloads)
1058 Payload &= PayloadMask;
1059
1060 // Signaling NaN must have a non-zero payload. In case a zero payload is
1061 // requested, a default arbitrary payload is set instead. Save this payload
1062 // for testing.
1063 const uint64_t SNaNDefaultPayload =
1064 APFloat::getSNaN(Sem).bitcastToAPInt().getZExtValue() & PayloadMask;
1065
1066 // Negative sign prefix (or none - for positive).
1067 const char Signs[] = {0, '-'};
1068
1069 // "Signaling" prefix (or none - for "Quiet").
1070 const char NaNTypes[] = {0, 's', 'S'};
1071
1072 const StringRef NaNStrings[] = {"nan", "NaN"};
1073 for (StringRef NaNStr : NaNStrings)
1074 for (char TypeChar : NaNTypes) {
1075 bool Signaling = (TypeChar == 's' || TypeChar == 'S');
1076
1077 for (size_t J = 0; J < std::size(NaNPayloads); ++J) {
1078 uint64_t Payload = (Signaling && !NaNPayloads[J]) ? SNaNDefaultPayload
1079 : NaNPayloads[J];
1080 std::string &PayloadDec = NaNPayloadDecStrings[J];
1081 std::string &PayloadHex = NaNPayloadHexStrings[J];
1082
1083 for (char SignChar : Signs) {
1084 bool Negative = (SignChar == '-');
1085
1086 std::string TestStrings[5];
1087 size_t NumTestStrings = 0;
1088
1089 std::string Prefix;
1090 if (SignChar)
1091 Prefix += SignChar;
1092 if (TypeChar)
1093 Prefix += TypeChar;
1094 Prefix += NaNStr;
1095
1096 // Test without any paylod.
1097 if (!Payload)
1098 TestStrings[NumTestStrings++] = Prefix;
1099
1100 // Test with the payload as a suffix.
1101 TestStrings[NumTestStrings++] = Prefix + PayloadDec;
1102 TestStrings[NumTestStrings++] = Prefix + PayloadHex;
1103
1104 // Test with the payload inside parentheses.
1105 TestStrings[NumTestStrings++] = Prefix + '(' + PayloadDec + ')';
1106 TestStrings[NumTestStrings++] = Prefix + '(' + PayloadHex + ')';
1107
1108 for (size_t K = 0; K < NumTestStrings; ++K) {
1109 StringRef TestStr = TestStrings[K];
1110
1111 APFloat F(Sem);
1112 bool HasError = !F.convertFromString(
1113 TestStr, llvm::APFloat::rmNearestTiesToEven);
1114 EXPECT_FALSE(HasError);
1115 EXPECT_TRUE(F.isNaN());
1116 EXPECT_EQ(Signaling, F.isSignaling());
1117 EXPECT_EQ(Negative, F.isNegative());
1118 uint64_t PayloadResult =
1119 F.bitcastToAPInt().getZExtValue() & PayloadMask;
1120 EXPECT_EQ(Payload, PayloadResult);
1121 }
1122 }
1123 }
1124 }
1125
1126 const StringRef InfStrings[] = {"inf", "INFINITY", "+Inf",
1127 "-inf", "-INFINITY", "-Inf"};
1128 for (StringRef InfStr : InfStrings) {
1129 bool Negative = InfStr.front() == '-';
1130
1131 APFloat F(Sem);
1132 bool HasError =
1133 !F.convertFromString(InfStr, llvm::APFloat::rmNearestTiesToEven);
1134 EXPECT_FALSE(HasError);
1135 EXPECT_TRUE(F.isInfinity());
1136 EXPECT_EQ(Negative, F.isNegative());
1137 uint64_t PayloadResult = F.bitcastToAPInt().getZExtValue() & PayloadMask;
1138 EXPECT_EQ(UINT64_C(0), PayloadResult);
1139 }
1140}
1141
1142TEST(APFloatTest, fromToStringSpecials) {
1143 auto expects = [] (const char *first, const char *second) {
1144 std::string roundtrip = convertToString(d: convertToDoubleFromString(Str: second), Prec: 0, Pad: 3);
1145 EXPECT_STREQ(first, roundtrip.c_str());
1146 };
1147 expects("+Inf", "+Inf");
1148 expects("+Inf", "INFINITY");
1149 expects("+Inf", "inf");
1150 expects("-Inf", "-Inf");
1151 expects("-Inf", "-INFINITY");
1152 expects("-Inf", "-inf");
1153 expects("NaN", "NaN");
1154 expects("NaN", "nan");
1155 expects("NaN", "-NaN");
1156 expects("NaN", "-nan");
1157}
1158
1159TEST(APFloatTest, fromHexadecimalString) {
1160 EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble(), "0x1p0").convertToDouble());
1161 EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble(), "+0x1p0").convertToDouble());
1162 EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-0x1p0").convertToDouble());
1163
1164 EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble(), "0x1p+0").convertToDouble());
1165 EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble(), "+0x1p+0").convertToDouble());
1166 EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-0x1p+0").convertToDouble());
1167
1168 EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble(), "0x1p-0").convertToDouble());
1169 EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble(), "+0x1p-0").convertToDouble());
1170 EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-0x1p-0").convertToDouble());
1171
1172
1173 EXPECT_EQ( 2.0, APFloat(APFloat::IEEEdouble(), "0x1p1").convertToDouble());
1174 EXPECT_EQ(+2.0, APFloat(APFloat::IEEEdouble(), "+0x1p1").convertToDouble());
1175 EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble(), "-0x1p1").convertToDouble());
1176
1177 EXPECT_EQ( 2.0, APFloat(APFloat::IEEEdouble(), "0x1p+1").convertToDouble());
1178 EXPECT_EQ(+2.0, APFloat(APFloat::IEEEdouble(), "+0x1p+1").convertToDouble());
1179 EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble(), "-0x1p+1").convertToDouble());
1180
1181 EXPECT_EQ( 0.5, APFloat(APFloat::IEEEdouble(), "0x1p-1").convertToDouble());
1182 EXPECT_EQ(+0.5, APFloat(APFloat::IEEEdouble(), "+0x1p-1").convertToDouble());
1183 EXPECT_EQ(-0.5, APFloat(APFloat::IEEEdouble(), "-0x1p-1").convertToDouble());
1184
1185
1186 EXPECT_EQ( 3.0, APFloat(APFloat::IEEEdouble(), "0x1.8p1").convertToDouble());
1187 EXPECT_EQ(+3.0, APFloat(APFloat::IEEEdouble(), "+0x1.8p1").convertToDouble());
1188 EXPECT_EQ(-3.0, APFloat(APFloat::IEEEdouble(), "-0x1.8p1").convertToDouble());
1189
1190 EXPECT_EQ( 3.0, APFloat(APFloat::IEEEdouble(), "0x1.8p+1").convertToDouble());
1191 EXPECT_EQ(+3.0, APFloat(APFloat::IEEEdouble(), "+0x1.8p+1").convertToDouble());
1192 EXPECT_EQ(-3.0, APFloat(APFloat::IEEEdouble(), "-0x1.8p+1").convertToDouble());
1193
1194 EXPECT_EQ( 0.75, APFloat(APFloat::IEEEdouble(), "0x1.8p-1").convertToDouble());
1195 EXPECT_EQ(+0.75, APFloat(APFloat::IEEEdouble(), "+0x1.8p-1").convertToDouble());
1196 EXPECT_EQ(-0.75, APFloat(APFloat::IEEEdouble(), "-0x1.8p-1").convertToDouble());
1197
1198
1199 EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000.000p1").convertToDouble());
1200 EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000.000p1").convertToDouble());
1201 EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000.000p1").convertToDouble());
1202
1203 EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000.000p+1").convertToDouble());
1204 EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000.000p+1").convertToDouble());
1205 EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000.000p+1").convertToDouble());
1206
1207 EXPECT_EQ( 2048.0, APFloat(APFloat::IEEEdouble(), "0x1000.000p-1").convertToDouble());
1208 EXPECT_EQ(+2048.0, APFloat(APFloat::IEEEdouble(), "+0x1000.000p-1").convertToDouble());
1209 EXPECT_EQ(-2048.0, APFloat(APFloat::IEEEdouble(), "-0x1000.000p-1").convertToDouble());
1210
1211
1212 EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000p1").convertToDouble());
1213 EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000p1").convertToDouble());
1214 EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000p1").convertToDouble());
1215
1216 EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000p+1").convertToDouble());
1217 EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000p+1").convertToDouble());
1218 EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000p+1").convertToDouble());
1219
1220 EXPECT_EQ( 2048.0, APFloat(APFloat::IEEEdouble(), "0x1000p-1").convertToDouble());
1221 EXPECT_EQ(+2048.0, APFloat(APFloat::IEEEdouble(), "+0x1000p-1").convertToDouble());
1222 EXPECT_EQ(-2048.0, APFloat(APFloat::IEEEdouble(), "-0x1000p-1").convertToDouble());
1223
1224
1225 EXPECT_EQ( 16384.0, APFloat(APFloat::IEEEdouble(), "0x10p10").convertToDouble());
1226 EXPECT_EQ(+16384.0, APFloat(APFloat::IEEEdouble(), "+0x10p10").convertToDouble());
1227 EXPECT_EQ(-16384.0, APFloat(APFloat::IEEEdouble(), "-0x10p10").convertToDouble());
1228
1229 EXPECT_EQ( 16384.0, APFloat(APFloat::IEEEdouble(), "0x10p+10").convertToDouble());
1230 EXPECT_EQ(+16384.0, APFloat(APFloat::IEEEdouble(), "+0x10p+10").convertToDouble());
1231 EXPECT_EQ(-16384.0, APFloat(APFloat::IEEEdouble(), "-0x10p+10").convertToDouble());
1232
1233 EXPECT_EQ( 0.015625, APFloat(APFloat::IEEEdouble(), "0x10p-10").convertToDouble());
1234 EXPECT_EQ(+0.015625, APFloat(APFloat::IEEEdouble(), "+0x10p-10").convertToDouble());
1235 EXPECT_EQ(-0.015625, APFloat(APFloat::IEEEdouble(), "-0x10p-10").convertToDouble());
1236
1237 EXPECT_EQ(1.0625, APFloat(APFloat::IEEEdouble(), "0x1.1p0").convertToDouble());
1238 EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "0x1p0").convertToDouble());
1239
1240 EXPECT_EQ(convertToDoubleFromString("0x1p-150"),
1241 convertToDoubleFromString("+0x800000000000000001.p-221"));
1242 EXPECT_EQ(2251799813685248.5,
1243 convertToDoubleFromString("0x80000000000004000000.010p-28"));
1244}
1245
1246TEST(APFloatTest, toString) {
1247 ASSERT_EQ("10", convertToString(10.0, 6, 3));
1248 ASSERT_EQ("1.0E+1", convertToString(10.0, 6, 0));
1249 ASSERT_EQ("10100", convertToString(1.01E+4, 5, 2));
1250 ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 4, 2));
1251 ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 5, 1));
1252 ASSERT_EQ("0.0101", convertToString(1.01E-2, 5, 2));
1253 ASSERT_EQ("0.0101", convertToString(1.01E-2, 4, 2));
1254 ASSERT_EQ("1.01E-2", convertToString(1.01E-2, 5, 1));
1255 ASSERT_EQ("0.78539816339744828", convertToString(0.78539816339744830961, 0, 3));
1256 ASSERT_EQ("4.9406564584124654E-324", convertToString(4.9406564584124654e-324, 0, 3));
1257 ASSERT_EQ("873.18340000000001", convertToString(873.1834, 0, 1));
1258 ASSERT_EQ("8.7318340000000001E+2", convertToString(873.1834, 0, 0));
1259 ASSERT_EQ("1.7976931348623157E+308", convertToString(1.7976931348623157E+308, 0, 0));
1260 ASSERT_EQ("10", convertToString(10.0, 6, 3, false));
1261 ASSERT_EQ("1.000000e+01", convertToString(10.0, 6, 0, false));
1262 ASSERT_EQ("10100", convertToString(1.01E+4, 5, 2, false));
1263 ASSERT_EQ("1.0100e+04", convertToString(1.01E+4, 4, 2, false));
1264 ASSERT_EQ("1.01000e+04", convertToString(1.01E+4, 5, 1, false));
1265 ASSERT_EQ("0.0101", convertToString(1.01E-2, 5, 2, false));
1266 ASSERT_EQ("0.0101", convertToString(1.01E-2, 4, 2, false));
1267 ASSERT_EQ("1.01000e-02", convertToString(1.01E-2, 5, 1, false));
1268 ASSERT_EQ("0.78539816339744828",
1269 convertToString(0.78539816339744830961, 0, 3, false));
1270 ASSERT_EQ("4.94065645841246540e-324",
1271 convertToString(4.9406564584124654e-324, 0, 3, false));
1272 ASSERT_EQ("873.18340000000001", convertToString(873.1834, 0, 1, false));
1273 ASSERT_EQ("8.73183400000000010e+02", convertToString(873.1834, 0, 0, false));
1274 ASSERT_EQ("1.79769313486231570e+308",
1275 convertToString(1.7976931348623157E+308, 0, 0, false));
1276
1277 {
1278 SmallString<64> Str;
1279 APFloat UnnormalZero(APFloat::x87DoubleExtended(), APInt(80, {0, 1}));
1280 UnnormalZero.toString(Str);
1281 ASSERT_EQ("NaN", Str);
1282 }
1283}
1284
1285TEST(APFloatTest, toInteger) {
1286 bool isExact = false;
1287 APSInt result(5, /*isUnsigned=*/true);
1288
1289 EXPECT_EQ(APFloat::opOK,
1290 APFloat(APFloat::IEEEdouble(), "10")
1291 .convertToInteger(result, APFloat::rmTowardZero, &isExact));
1292 EXPECT_TRUE(isExact);
1293 EXPECT_EQ(APSInt(APInt(5, 10), true), result);
1294
1295 EXPECT_EQ(APFloat::opInvalidOp,
1296 APFloat(APFloat::IEEEdouble(), "-10")
1297 .convertToInteger(result, APFloat::rmTowardZero, &isExact));
1298 EXPECT_FALSE(isExact);
1299 EXPECT_EQ(APSInt::getMinValue(5, true), result);
1300
1301 EXPECT_EQ(APFloat::opInvalidOp,
1302 APFloat(APFloat::IEEEdouble(), "32")
1303 .convertToInteger(result, APFloat::rmTowardZero, &isExact));
1304 EXPECT_FALSE(isExact);
1305 EXPECT_EQ(APSInt::getMaxValue(5, true), result);
1306
1307 EXPECT_EQ(APFloat::opInexact,
1308 APFloat(APFloat::IEEEdouble(), "7.9")
1309 .convertToInteger(result, APFloat::rmTowardZero, &isExact));
1310 EXPECT_FALSE(isExact);
1311 EXPECT_EQ(APSInt(APInt(5, 7), true), result);
1312
1313 result.setIsUnsigned(false);
1314 EXPECT_EQ(APFloat::opOK,
1315 APFloat(APFloat::IEEEdouble(), "-10")
1316 .convertToInteger(result, APFloat::rmTowardZero, &isExact));
1317 EXPECT_TRUE(isExact);
1318 EXPECT_EQ(APSInt(APInt(5, -10, true), false), result);
1319
1320 EXPECT_EQ(APFloat::opInvalidOp,
1321 APFloat(APFloat::IEEEdouble(), "-17")
1322 .convertToInteger(result, APFloat::rmTowardZero, &isExact));
1323 EXPECT_FALSE(isExact);
1324 EXPECT_EQ(APSInt::getMinValue(5, false), result);
1325
1326 EXPECT_EQ(APFloat::opInvalidOp,
1327 APFloat(APFloat::IEEEdouble(), "16")
1328 .convertToInteger(result, APFloat::rmTowardZero, &isExact));
1329 EXPECT_FALSE(isExact);
1330 EXPECT_EQ(APSInt::getMaxValue(5, false), result);
1331}
1332
1333static APInt nanbitsFromAPInt(const fltSemantics &Sem, bool SNaN, bool Negative,
1334 uint64_t payload) {
1335 APInt appayload(64, payload);
1336 if (SNaN)
1337 return APFloat::getSNaN(Sem, Negative, payload: &appayload).bitcastToAPInt();
1338 else
1339 return APFloat::getQNaN(Sem, Negative, payload: &appayload).bitcastToAPInt();
1340}
1341
1342TEST(APFloatTest, makeNaN) {
1343 const struct {
1344 uint64_t expected;
1345 const fltSemantics &semantics;
1346 bool SNaN;
1347 bool Negative;
1348 uint64_t payload;
1349 } tests[] = {
1350 // clang-format off
1351 /* expected semantics SNaN Neg payload */
1352 { .expected: 0x7fc00000ULL, .semantics: APFloat::IEEEsingle(), .SNaN: false, .Negative: false, .payload: 0x00000000ULL },
1353 { .expected: 0xffc00000ULL, .semantics: APFloat::IEEEsingle(), .SNaN: false, .Negative: true, .payload: 0x00000000ULL },
1354 { .expected: 0x7fc0ae72ULL, .semantics: APFloat::IEEEsingle(), .SNaN: false, .Negative: false, .payload: 0x0000ae72ULL },
1355 { .expected: 0x7fffae72ULL, .semantics: APFloat::IEEEsingle(), .SNaN: false, .Negative: false, .payload: 0xffffae72ULL },
1356 { .expected: 0x7fdaae72ULL, .semantics: APFloat::IEEEsingle(), .SNaN: false, .Negative: false, .payload: 0x00daae72ULL },
1357 { .expected: 0x7fa00000ULL, .semantics: APFloat::IEEEsingle(), .SNaN: true, .Negative: false, .payload: 0x00000000ULL },
1358 { .expected: 0xffa00000ULL, .semantics: APFloat::IEEEsingle(), .SNaN: true, .Negative: true, .payload: 0x00000000ULL },
1359 { .expected: 0x7f80ae72ULL, .semantics: APFloat::IEEEsingle(), .SNaN: true, .Negative: false, .payload: 0x0000ae72ULL },
1360 { .expected: 0x7fbfae72ULL, .semantics: APFloat::IEEEsingle(), .SNaN: true, .Negative: false, .payload: 0xffffae72ULL },
1361 { .expected: 0x7f9aae72ULL, .semantics: APFloat::IEEEsingle(), .SNaN: true, .Negative: false, .payload: 0x001aae72ULL },
1362 { .expected: 0x7ff8000000000000ULL, .semantics: APFloat::IEEEdouble(), .SNaN: false, .Negative: false, .payload: 0x0000000000000000ULL },
1363 { .expected: 0xfff8000000000000ULL, .semantics: APFloat::IEEEdouble(), .SNaN: false, .Negative: true, .payload: 0x0000000000000000ULL },
1364 { .expected: 0x7ff800000000ae72ULL, .semantics: APFloat::IEEEdouble(), .SNaN: false, .Negative: false, .payload: 0x000000000000ae72ULL },
1365 { .expected: 0x7fffffffffffae72ULL, .semantics: APFloat::IEEEdouble(), .SNaN: false, .Negative: false, .payload: 0xffffffffffffae72ULL },
1366 { .expected: 0x7ffdaaaaaaaaae72ULL, .semantics: APFloat::IEEEdouble(), .SNaN: false, .Negative: false, .payload: 0x000daaaaaaaaae72ULL },
1367 { .expected: 0x7ff4000000000000ULL, .semantics: APFloat::IEEEdouble(), .SNaN: true, .Negative: false, .payload: 0x0000000000000000ULL },
1368 { .expected: 0xfff4000000000000ULL, .semantics: APFloat::IEEEdouble(), .SNaN: true, .Negative: true, .payload: 0x0000000000000000ULL },
1369 { .expected: 0x7ff000000000ae72ULL, .semantics: APFloat::IEEEdouble(), .SNaN: true, .Negative: false, .payload: 0x000000000000ae72ULL },
1370 { .expected: 0x7ff7ffffffffae72ULL, .semantics: APFloat::IEEEdouble(), .SNaN: true, .Negative: false, .payload: 0xffffffffffffae72ULL },
1371 { .expected: 0x7ff1aaaaaaaaae72ULL, .semantics: APFloat::IEEEdouble(), .SNaN: true, .Negative: false, .payload: 0x0001aaaaaaaaae72ULL },
1372 { .expected: 0x80ULL, .semantics: APFloat::Float8E5M2FNUZ(), .SNaN: false, .Negative: false, .payload: 0xaaULL },
1373 { .expected: 0x80ULL, .semantics: APFloat::Float8E5M2FNUZ(), .SNaN: false, .Negative: true, .payload: 0xaaULL },
1374 { .expected: 0x80ULL, .semantics: APFloat::Float8E5M2FNUZ(), .SNaN: true, .Negative: false, .payload: 0xaaULL },
1375 { .expected: 0x80ULL, .semantics: APFloat::Float8E5M2FNUZ(), .SNaN: true, .Negative: true, .payload: 0xaaULL },
1376 { .expected: 0x80ULL, .semantics: APFloat::Float8E4M3FNUZ(), .SNaN: false, .Negative: false, .payload: 0xaaULL },
1377 { .expected: 0x80ULL, .semantics: APFloat::Float8E4M3FNUZ(), .SNaN: false, .Negative: true, .payload: 0xaaULL },
1378 { .expected: 0x80ULL, .semantics: APFloat::Float8E4M3FNUZ(), .SNaN: true, .Negative: false, .payload: 0xaaULL },
1379 { .expected: 0x80ULL, .semantics: APFloat::Float8E4M3FNUZ(), .SNaN: true, .Negative: true, .payload: 0xaaULL },
1380 { .expected: 0x80ULL, .semantics: APFloat::Float8E4M3B11FNUZ(), .SNaN: false, .Negative: false, .payload: 0xaaULL },
1381 { .expected: 0x80ULL, .semantics: APFloat::Float8E4M3B11FNUZ(), .SNaN: false, .Negative: true, .payload: 0xaaULL },
1382 { .expected: 0x80ULL, .semantics: APFloat::Float8E4M3B11FNUZ(), .SNaN: true, .Negative: false, .payload: 0xaaULL },
1383 { .expected: 0x80ULL, .semantics: APFloat::Float8E4M3B11FNUZ(), .SNaN: true, .Negative: true, .payload: 0xaaULL },
1384 { .expected: 0x3fe00ULL, .semantics: APFloat::FloatTF32(), .SNaN: false, .Negative: false, .payload: 0x00000000ULL },
1385 { .expected: 0x7fe00ULL, .semantics: APFloat::FloatTF32(), .SNaN: false, .Negative: true, .payload: 0x00000000ULL },
1386 { .expected: 0x3feaaULL, .semantics: APFloat::FloatTF32(), .SNaN: false, .Negative: false, .payload: 0xaaULL },
1387 { .expected: 0x3ffaaULL, .semantics: APFloat::FloatTF32(), .SNaN: false, .Negative: false, .payload: 0xdaaULL },
1388 { .expected: 0x3ffaaULL, .semantics: APFloat::FloatTF32(), .SNaN: false, .Negative: false, .payload: 0xfdaaULL },
1389 { .expected: 0x3fd00ULL, .semantics: APFloat::FloatTF32(), .SNaN: true, .Negative: false, .payload: 0x00000000ULL },
1390 { .expected: 0x7fd00ULL, .semantics: APFloat::FloatTF32(), .SNaN: true, .Negative: true, .payload: 0x00000000ULL },
1391 { .expected: 0x3fcaaULL, .semantics: APFloat::FloatTF32(), .SNaN: true, .Negative: false, .payload: 0xaaULL },
1392 { .expected: 0x3fdaaULL, .semantics: APFloat::FloatTF32(), .SNaN: true, .Negative: false, .payload: 0xfaaULL },
1393 { .expected: 0x3fdaaULL, .semantics: APFloat::FloatTF32(), .SNaN: true, .Negative: false, .payload: 0x1aaULL },
1394 // clang-format on
1395 };
1396
1397 for (const auto &t : tests) {
1398 ASSERT_EQ(t.expected, nanbitsFromAPInt(t.semantics, t.SNaN, t.Negative, t.payload));
1399 }
1400}
1401
1402#ifdef GTEST_HAS_DEATH_TEST
1403#ifndef NDEBUG
1404TEST(APFloatTest, SemanticsDeath) {
1405 EXPECT_DEATH(APFloat(APFloat::IEEEquad(), 0).convertToDouble(),
1406 "Float semantics is not representable by IEEEdouble");
1407 EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), 0).convertToFloat(),
1408 "Float semantics is not representable by IEEEsingle");
1409}
1410#endif
1411#endif
1412
1413TEST(APFloatTest, StringDecimalError) {
1414 EXPECT_EQ("Invalid string length", convertToErrorFromString(""));
1415 EXPECT_EQ("String has no digits", convertToErrorFromString("+"));
1416 EXPECT_EQ("String has no digits", convertToErrorFromString("-"));
1417
1418 EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("\0", 1)));
1419 EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("1\0", 2)));
1420 EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("1" "\0" "2", 3)));
1421 EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("1" "\0" "2e1", 5)));
1422 EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("1e\0", 3)));
1423 EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("1e1\0", 4)));
1424 EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("1e1" "\0" "2", 5)));
1425
1426 EXPECT_EQ("Invalid character in significand", convertToErrorFromString("1.0f"));
1427
1428 EXPECT_EQ("String contains multiple dots", convertToErrorFromString(".."));
1429 EXPECT_EQ("String contains multiple dots", convertToErrorFromString("..0"));
1430 EXPECT_EQ("String contains multiple dots", convertToErrorFromString("1.0.0"));
1431}
1432
1433TEST(APFloatTest, StringDecimalSignificandError) {
1434 EXPECT_EQ("Significand has no digits", convertToErrorFromString( "."));
1435 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+."));
1436 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-."));
1437
1438
1439 EXPECT_EQ("Significand has no digits", convertToErrorFromString( "e"));
1440 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+e"));
1441 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-e"));
1442
1443 EXPECT_EQ("Significand has no digits", convertToErrorFromString( "e1"));
1444 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+e1"));
1445 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-e1"));
1446
1447 EXPECT_EQ("Significand has no digits", convertToErrorFromString( ".e1"));
1448 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+.e1"));
1449 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-.e1"));
1450
1451
1452 EXPECT_EQ("Significand has no digits", convertToErrorFromString( ".e"));
1453 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+.e"));
1454 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-.e"));
1455}
1456
1457TEST(APFloatTest, StringHexadecimalError) {
1458 EXPECT_EQ("Invalid string", convertToErrorFromString( "0x"));
1459 EXPECT_EQ("Invalid string", convertToErrorFromString("+0x"));
1460 EXPECT_EQ("Invalid string", convertToErrorFromString("-0x"));
1461
1462 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x0"));
1463 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x0"));
1464 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x0"));
1465
1466 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x0."));
1467 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x0."));
1468 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x0."));
1469
1470 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x.0"));
1471 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x.0"));
1472 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x.0"));
1473
1474 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString( "0x0.0"));
1475 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("+0x0.0"));
1476 EXPECT_EQ("Hex strings require an exponent", convertToErrorFromString("-0x0.0"));
1477
1478 EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x\0", 3)));
1479 EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x1\0", 4)));
1480 EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x1" "\0" "2", 5)));
1481 EXPECT_EQ("Invalid character in significand", convertToErrorFromString(StringRef("0x1" "\0" "2p1", 7)));
1482 EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("0x1p\0", 5)));
1483 EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("0x1p1\0", 6)));
1484 EXPECT_EQ("Invalid character in exponent", convertToErrorFromString(StringRef("0x1p1" "\0" "2", 7)));
1485
1486 EXPECT_EQ("Invalid character in exponent", convertToErrorFromString("0x1p0f"));
1487
1488 EXPECT_EQ("String contains multiple dots", convertToErrorFromString("0x..p1"));
1489 EXPECT_EQ("String contains multiple dots", convertToErrorFromString("0x..0p1"));
1490 EXPECT_EQ("String contains multiple dots", convertToErrorFromString("0x1.0.0p1"));
1491}
1492
1493TEST(APFloatTest, StringHexadecimalSignificandError) {
1494 EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x."));
1495 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x."));
1496 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x."));
1497
1498 EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0xp"));
1499 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0xp"));
1500 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0xp"));
1501
1502 EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0xp+"));
1503 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0xp+"));
1504 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0xp+"));
1505
1506 EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0xp-"));
1507 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0xp-"));
1508 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0xp-"));
1509
1510
1511 EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x.p"));
1512 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x.p"));
1513 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x.p"));
1514
1515 EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x.p+"));
1516 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x.p+"));
1517 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x.p+"));
1518
1519 EXPECT_EQ("Significand has no digits", convertToErrorFromString( "0x.p-"));
1520 EXPECT_EQ("Significand has no digits", convertToErrorFromString("+0x.p-"));
1521 EXPECT_EQ("Significand has no digits", convertToErrorFromString("-0x.p-"));
1522}
1523
1524TEST(APFloatTest, StringHexadecimalExponentError) {
1525 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1p"));
1526 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1p"));
1527 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1p"));
1528
1529 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1p+"));
1530 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1p+"));
1531 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1p+"));
1532
1533 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1p-"));
1534 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1p-"));
1535 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1p-"));
1536
1537
1538 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.p"));
1539 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.p"));
1540 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.p"));
1541
1542 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.p+"));
1543 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.p+"));
1544 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.p+"));
1545
1546 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.p-"));
1547 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.p-"));
1548 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.p-"));
1549
1550
1551 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x.1p"));
1552 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x.1p"));
1553 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x.1p"));
1554
1555 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x.1p+"));
1556 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x.1p+"));
1557 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x.1p+"));
1558
1559 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x.1p-"));
1560 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x.1p-"));
1561 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x.1p-"));
1562
1563
1564 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.1p"));
1565 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.1p"));
1566 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.1p"));
1567
1568 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.1p+"));
1569 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.1p+"));
1570 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.1p+"));
1571
1572 EXPECT_EQ("Exponent has no digits", convertToErrorFromString( "0x1.1p-"));
1573 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("+0x1.1p-"));
1574 EXPECT_EQ("Exponent has no digits", convertToErrorFromString("-0x1.1p-"));
1575}
1576
1577TEST(APFloatTest, exactInverse) {
1578 APFloat inv(0.0f);
1579
1580 // Trivial operation.
1581 EXPECT_TRUE(APFloat(2.0).getExactInverse(&inv));
1582 EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(0.5)));
1583 EXPECT_TRUE(APFloat(2.0f).getExactInverse(&inv));
1584 EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(0.5f)));
1585 EXPECT_TRUE(APFloat(APFloat::IEEEquad(), "2.0").getExactInverse(&inv));
1586 EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::IEEEquad(), "0.5")));
1587 EXPECT_TRUE(APFloat(APFloat::PPCDoubleDouble(), "2.0").getExactInverse(&inv));
1588 EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::PPCDoubleDouble(), "0.5")));
1589 EXPECT_TRUE(APFloat(APFloat::x87DoubleExtended(), "2.0").getExactInverse(&inv));
1590 EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::x87DoubleExtended(), "0.5")));
1591
1592 // FLT_MIN
1593 EXPECT_TRUE(APFloat(1.17549435e-38f).getExactInverse(&inv));
1594 EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(8.5070592e+37f)));
1595
1596 // Large float, inverse is a denormal.
1597 EXPECT_FALSE(APFloat(1.7014118e38f).getExactInverse(nullptr));
1598 // Zero
1599 EXPECT_FALSE(APFloat(0.0).getExactInverse(nullptr));
1600 // Denormalized float
1601 EXPECT_FALSE(APFloat(1.40129846e-45f).getExactInverse(nullptr));
1602}
1603
1604TEST(APFloatTest, roundToIntegral) {
1605 APFloat T(-0.5), S(3.14), R(APFloat::getLargest(Sem: APFloat::IEEEdouble())), P(0.0);
1606
1607 P = T;
1608 P.roundToIntegral(RM: APFloat::rmTowardZero);
1609 EXPECT_EQ(-0.0, P.convertToDouble());
1610 P = T;
1611 P.roundToIntegral(RM: APFloat::rmTowardNegative);
1612 EXPECT_EQ(-1.0, P.convertToDouble());
1613 P = T;
1614 P.roundToIntegral(RM: APFloat::rmTowardPositive);
1615 EXPECT_EQ(-0.0, P.convertToDouble());
1616 P = T;
1617 P.roundToIntegral(RM: APFloat::rmNearestTiesToEven);
1618 EXPECT_EQ(-0.0, P.convertToDouble());
1619
1620 P = S;
1621 P.roundToIntegral(RM: APFloat::rmTowardZero);
1622 EXPECT_EQ(3.0, P.convertToDouble());
1623 P = S;
1624 P.roundToIntegral(RM: APFloat::rmTowardNegative);
1625 EXPECT_EQ(3.0, P.convertToDouble());
1626 P = S;
1627 P.roundToIntegral(RM: APFloat::rmTowardPositive);
1628 EXPECT_EQ(4.0, P.convertToDouble());
1629 P = S;
1630 P.roundToIntegral(RM: APFloat::rmNearestTiesToEven);
1631 EXPECT_EQ(3.0, P.convertToDouble());
1632
1633 P = R;
1634 P.roundToIntegral(RM: APFloat::rmTowardZero);
1635 EXPECT_EQ(R.convertToDouble(), P.convertToDouble());
1636 P = R;
1637 P.roundToIntegral(RM: APFloat::rmTowardNegative);
1638 EXPECT_EQ(R.convertToDouble(), P.convertToDouble());
1639 P = R;
1640 P.roundToIntegral(RM: APFloat::rmTowardPositive);
1641 EXPECT_EQ(R.convertToDouble(), P.convertToDouble());
1642 P = R;
1643 P.roundToIntegral(RM: APFloat::rmNearestTiesToEven);
1644 EXPECT_EQ(R.convertToDouble(), P.convertToDouble());
1645
1646 P = APFloat::getZero(Sem: APFloat::IEEEdouble());
1647 P.roundToIntegral(RM: APFloat::rmTowardZero);
1648 EXPECT_EQ(0.0, P.convertToDouble());
1649 P = APFloat::getZero(Sem: APFloat::IEEEdouble(), Negative: true);
1650 P.roundToIntegral(RM: APFloat::rmTowardZero);
1651 EXPECT_EQ(-0.0, P.convertToDouble());
1652 P = APFloat::getNaN(Sem: APFloat::IEEEdouble());
1653 P.roundToIntegral(RM: APFloat::rmTowardZero);
1654 EXPECT_TRUE(std::isnan(P.convertToDouble()));
1655 P = APFloat::getInf(Sem: APFloat::IEEEdouble());
1656 P.roundToIntegral(RM: APFloat::rmTowardZero);
1657 EXPECT_TRUE(std::isinf(P.convertToDouble()) && P.convertToDouble() > 0.0);
1658 P = APFloat::getInf(Sem: APFloat::IEEEdouble(), Negative: true);
1659 P.roundToIntegral(RM: APFloat::rmTowardZero);
1660 EXPECT_TRUE(std::isinf(P.convertToDouble()) && P.convertToDouble() < 0.0);
1661
1662 APFloat::opStatus St;
1663
1664 P = APFloat::getNaN(Sem: APFloat::IEEEdouble());
1665 St = P.roundToIntegral(RM: APFloat::rmTowardZero);
1666 EXPECT_TRUE(P.isNaN());
1667 EXPECT_FALSE(P.isNegative());
1668 EXPECT_EQ(APFloat::opOK, St);
1669
1670 P = APFloat::getNaN(Sem: APFloat::IEEEdouble(), Negative: true);
1671 St = P.roundToIntegral(RM: APFloat::rmTowardZero);
1672 EXPECT_TRUE(P.isNaN());
1673 EXPECT_TRUE(P.isNegative());
1674 EXPECT_EQ(APFloat::opOK, St);
1675
1676 P = APFloat::getSNaN(Sem: APFloat::IEEEdouble());
1677 St = P.roundToIntegral(RM: APFloat::rmTowardZero);
1678 EXPECT_TRUE(P.isNaN());
1679 EXPECT_FALSE(P.isSignaling());
1680 EXPECT_FALSE(P.isNegative());
1681 EXPECT_EQ(APFloat::opInvalidOp, St);
1682
1683 P = APFloat::getSNaN(Sem: APFloat::IEEEdouble(), Negative: true);
1684 St = P.roundToIntegral(RM: APFloat::rmTowardZero);
1685 EXPECT_TRUE(P.isNaN());
1686 EXPECT_FALSE(P.isSignaling());
1687 EXPECT_TRUE(P.isNegative());
1688 EXPECT_EQ(APFloat::opInvalidOp, St);
1689
1690 P = APFloat::getInf(Sem: APFloat::IEEEdouble());
1691 St = P.roundToIntegral(RM: APFloat::rmTowardZero);
1692 EXPECT_TRUE(P.isInfinity());
1693 EXPECT_FALSE(P.isNegative());
1694 EXPECT_EQ(APFloat::opOK, St);
1695
1696 P = APFloat::getInf(Sem: APFloat::IEEEdouble(), Negative: true);
1697 St = P.roundToIntegral(RM: APFloat::rmTowardZero);
1698 EXPECT_TRUE(P.isInfinity());
1699 EXPECT_TRUE(P.isNegative());
1700 EXPECT_EQ(APFloat::opOK, St);
1701
1702 P = APFloat::getZero(Sem: APFloat::IEEEdouble(), Negative: false);
1703 St = P.roundToIntegral(RM: APFloat::rmTowardZero);
1704 EXPECT_TRUE(P.isZero());
1705 EXPECT_FALSE(P.isNegative());
1706 EXPECT_EQ(APFloat::opOK, St);
1707
1708 P = APFloat::getZero(Sem: APFloat::IEEEdouble(), Negative: false);
1709 St = P.roundToIntegral(RM: APFloat::rmTowardNegative);
1710 EXPECT_TRUE(P.isZero());
1711 EXPECT_FALSE(P.isNegative());
1712 EXPECT_EQ(APFloat::opOK, St);
1713
1714 P = APFloat::getZero(Sem: APFloat::IEEEdouble(), Negative: true);
1715 St = P.roundToIntegral(RM: APFloat::rmTowardZero);
1716 EXPECT_TRUE(P.isZero());
1717 EXPECT_TRUE(P.isNegative());
1718 EXPECT_EQ(APFloat::opOK, St);
1719
1720 P = APFloat::getZero(Sem: APFloat::IEEEdouble(), Negative: true);
1721 St = P.roundToIntegral(RM: APFloat::rmTowardNegative);
1722 EXPECT_TRUE(P.isZero());
1723 EXPECT_TRUE(P.isNegative());
1724 EXPECT_EQ(APFloat::opOK, St);
1725
1726 P = APFloat(1E-100);
1727 St = P.roundToIntegral(RM: APFloat::rmTowardNegative);
1728 EXPECT_TRUE(P.isZero());
1729 EXPECT_FALSE(P.isNegative());
1730 EXPECT_EQ(APFloat::opInexact, St);
1731
1732 P = APFloat(1E-100);
1733 St = P.roundToIntegral(RM: APFloat::rmTowardPositive);
1734 EXPECT_EQ(1.0, P.convertToDouble());
1735 EXPECT_FALSE(P.isNegative());
1736 EXPECT_EQ(APFloat::opInexact, St);
1737
1738 P = APFloat(-1E-100);
1739 St = P.roundToIntegral(RM: APFloat::rmTowardNegative);
1740 EXPECT_TRUE(P.isNegative());
1741 EXPECT_EQ(-1.0, P.convertToDouble());
1742 EXPECT_EQ(APFloat::opInexact, St);
1743
1744 P = APFloat(-1E-100);
1745 St = P.roundToIntegral(RM: APFloat::rmTowardPositive);
1746 EXPECT_TRUE(P.isZero());
1747 EXPECT_TRUE(P.isNegative());
1748 EXPECT_EQ(APFloat::opInexact, St);
1749
1750 P = APFloat(10.0);
1751 St = P.roundToIntegral(RM: APFloat::rmTowardZero);
1752 EXPECT_EQ(10.0, P.convertToDouble());
1753 EXPECT_EQ(APFloat::opOK, St);
1754
1755 P = APFloat(10.5);
1756 St = P.roundToIntegral(RM: APFloat::rmTowardZero);
1757 EXPECT_EQ(10.0, P.convertToDouble());
1758 EXPECT_EQ(APFloat::opInexact, St);
1759
1760 P = APFloat(10.5);
1761 St = P.roundToIntegral(RM: APFloat::rmTowardPositive);
1762 EXPECT_EQ(11.0, P.convertToDouble());
1763 EXPECT_EQ(APFloat::opInexact, St);
1764
1765 P = APFloat(10.5);
1766 St = P.roundToIntegral(RM: APFloat::rmTowardNegative);
1767 EXPECT_EQ(10.0, P.convertToDouble());
1768 EXPECT_EQ(APFloat::opInexact, St);
1769
1770 P = APFloat(10.5);
1771 St = P.roundToIntegral(RM: APFloat::rmNearestTiesToAway);
1772 EXPECT_EQ(11.0, P.convertToDouble());
1773 EXPECT_EQ(APFloat::opInexact, St);
1774
1775 P = APFloat(10.5);
1776 St = P.roundToIntegral(RM: APFloat::rmNearestTiesToEven);
1777 EXPECT_EQ(10.0, P.convertToDouble());
1778 EXPECT_EQ(APFloat::opInexact, St);
1779}
1780
1781TEST(APFloatTest, isInteger) {
1782 APFloat T(-0.0);
1783 EXPECT_TRUE(T.isInteger());
1784 T = APFloat(3.14159);
1785 EXPECT_FALSE(T.isInteger());
1786 T = APFloat::getNaN(Sem: APFloat::IEEEdouble());
1787 EXPECT_FALSE(T.isInteger());
1788 T = APFloat::getInf(Sem: APFloat::IEEEdouble());
1789 EXPECT_FALSE(T.isInteger());
1790 T = APFloat::getInf(Sem: APFloat::IEEEdouble(), Negative: true);
1791 EXPECT_FALSE(T.isInteger());
1792 T = APFloat::getLargest(Sem: APFloat::IEEEdouble());
1793 EXPECT_TRUE(T.isInteger());
1794}
1795
1796TEST(DoubleAPFloatTest, isInteger) {
1797 APFloat F1(-0.0);
1798 APFloat F2(-0.0);
1799 llvm::detail::DoubleAPFloat T(APFloat::PPCDoubleDouble(), std::move(F1),
1800 std::move(F2));
1801 EXPECT_TRUE(T.isInteger());
1802 APFloat F3(3.14159);
1803 APFloat F4(-0.0);
1804 llvm::detail::DoubleAPFloat T2(APFloat::PPCDoubleDouble(), std::move(F3),
1805 std::move(F4));
1806 EXPECT_FALSE(T2.isInteger());
1807 APFloat F5(-0.0);
1808 APFloat F6(3.14159);
1809 llvm::detail::DoubleAPFloat T3(APFloat::PPCDoubleDouble(), std::move(F5),
1810 std::move(F6));
1811 EXPECT_FALSE(T3.isInteger());
1812}
1813
1814TEST(APFloatTest, getLargest) {
1815 EXPECT_EQ(3.402823466e+38f, APFloat::getLargest(APFloat::IEEEsingle()).convertToFloat());
1816 EXPECT_EQ(1.7976931348623158e+308, APFloat::getLargest(APFloat::IEEEdouble()).convertToDouble());
1817 EXPECT_EQ(448, APFloat::getLargest(APFloat::Float8E4M3FN()).convertToDouble());
1818 EXPECT_EQ(240,
1819 APFloat::getLargest(APFloat::Float8E4M3FNUZ()).convertToDouble());
1820 EXPECT_EQ(57344,
1821 APFloat::getLargest(APFloat::Float8E5M2FNUZ()).convertToDouble());
1822 EXPECT_EQ(
1823 30, APFloat::getLargest(APFloat::Float8E4M3B11FNUZ()).convertToDouble());
1824 EXPECT_EQ(3.40116213421e+38f,
1825 APFloat::getLargest(APFloat::FloatTF32()).convertToFloat());
1826}
1827
1828TEST(APFloatTest, getSmallest) {
1829 APFloat test = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: false);
1830 APFloat expected = APFloat(APFloat::IEEEsingle(), "0x0.000002p-126");
1831 EXPECT_FALSE(test.isNegative());
1832 EXPECT_TRUE(test.isFiniteNonZero());
1833 EXPECT_TRUE(test.isDenormal());
1834 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1835
1836 test = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: true);
1837 expected = APFloat(APFloat::IEEEsingle(), "-0x0.000002p-126");
1838 EXPECT_TRUE(test.isNegative());
1839 EXPECT_TRUE(test.isFiniteNonZero());
1840 EXPECT_TRUE(test.isDenormal());
1841 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1842
1843 test = APFloat::getSmallest(Sem: APFloat::IEEEquad(), Negative: false);
1844 expected = APFloat(APFloat::IEEEquad(), "0x0.0000000000000000000000000001p-16382");
1845 EXPECT_FALSE(test.isNegative());
1846 EXPECT_TRUE(test.isFiniteNonZero());
1847 EXPECT_TRUE(test.isDenormal());
1848 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1849
1850 test = APFloat::getSmallest(Sem: APFloat::IEEEquad(), Negative: true);
1851 expected = APFloat(APFloat::IEEEquad(), "-0x0.0000000000000000000000000001p-16382");
1852 EXPECT_TRUE(test.isNegative());
1853 EXPECT_TRUE(test.isFiniteNonZero());
1854 EXPECT_TRUE(test.isDenormal());
1855 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1856
1857 test = APFloat::getSmallest(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
1858 expected = APFloat(APFloat::Float8E5M2FNUZ(), "0x0.4p-15");
1859 EXPECT_FALSE(test.isNegative());
1860 EXPECT_TRUE(test.isFiniteNonZero());
1861 EXPECT_TRUE(test.isDenormal());
1862 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1863
1864 test = APFloat::getSmallest(Sem: APFloat::Float8E4M3FNUZ(), Negative: false);
1865 expected = APFloat(APFloat::Float8E4M3FNUZ(), "0x0.2p-7");
1866 EXPECT_FALSE(test.isNegative());
1867 EXPECT_TRUE(test.isFiniteNonZero());
1868 EXPECT_TRUE(test.isDenormal());
1869 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1870
1871 test = APFloat::getSmallest(Sem: APFloat::Float8E4M3B11FNUZ(), Negative: false);
1872 expected = APFloat(APFloat::Float8E4M3B11FNUZ(), "0x0.2p-10");
1873 EXPECT_FALSE(test.isNegative());
1874 EXPECT_TRUE(test.isFiniteNonZero());
1875 EXPECT_TRUE(test.isDenormal());
1876 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1877
1878 test = APFloat::getSmallest(Sem: APFloat::FloatTF32(), Negative: true);
1879 expected = APFloat(APFloat::FloatTF32(), "-0x0.004p-126");
1880 EXPECT_TRUE(test.isNegative());
1881 EXPECT_TRUE(test.isFiniteNonZero());
1882 EXPECT_TRUE(test.isDenormal());
1883 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1884}
1885
1886TEST(APFloatTest, getSmallestNormalized) {
1887 APFloat test = APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: false);
1888 APFloat expected = APFloat(APFloat::IEEEsingle(), "0x1p-126");
1889 EXPECT_FALSE(test.isNegative());
1890 EXPECT_TRUE(test.isFiniteNonZero());
1891 EXPECT_FALSE(test.isDenormal());
1892 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1893 EXPECT_TRUE(test.isSmallestNormalized());
1894
1895 test = APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: true);
1896 expected = APFloat(APFloat::IEEEsingle(), "-0x1p-126");
1897 EXPECT_TRUE(test.isNegative());
1898 EXPECT_TRUE(test.isFiniteNonZero());
1899 EXPECT_FALSE(test.isDenormal());
1900 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1901 EXPECT_TRUE(test.isSmallestNormalized());
1902
1903 test = APFloat::getSmallestNormalized(Sem: APFloat::IEEEdouble(), Negative: false);
1904 expected = APFloat(APFloat::IEEEdouble(), "0x1p-1022");
1905 EXPECT_FALSE(test.isNegative());
1906 EXPECT_TRUE(test.isFiniteNonZero());
1907 EXPECT_FALSE(test.isDenormal());
1908 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1909 EXPECT_TRUE(test.isSmallestNormalized());
1910
1911 test = APFloat::getSmallestNormalized(Sem: APFloat::IEEEdouble(), Negative: true);
1912 expected = APFloat(APFloat::IEEEdouble(), "-0x1p-1022");
1913 EXPECT_TRUE(test.isNegative());
1914 EXPECT_TRUE(test.isFiniteNonZero());
1915 EXPECT_FALSE(test.isDenormal());
1916 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1917 EXPECT_TRUE(test.isSmallestNormalized());
1918
1919 test = APFloat::getSmallestNormalized(Sem: APFloat::IEEEquad(), Negative: false);
1920 expected = APFloat(APFloat::IEEEquad(), "0x1p-16382");
1921 EXPECT_FALSE(test.isNegative());
1922 EXPECT_TRUE(test.isFiniteNonZero());
1923 EXPECT_FALSE(test.isDenormal());
1924 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1925 EXPECT_TRUE(test.isSmallestNormalized());
1926
1927 test = APFloat::getSmallestNormalized(Sem: APFloat::IEEEquad(), Negative: true);
1928 expected = APFloat(APFloat::IEEEquad(), "-0x1p-16382");
1929 EXPECT_TRUE(test.isNegative());
1930 EXPECT_TRUE(test.isFiniteNonZero());
1931 EXPECT_FALSE(test.isDenormal());
1932 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1933 EXPECT_TRUE(test.isSmallestNormalized());
1934
1935 test = APFloat::getSmallestNormalized(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
1936 expected = APFloat(APFloat::Float8E5M2FNUZ(), "0x1.0p-15");
1937 EXPECT_FALSE(test.isNegative());
1938 EXPECT_TRUE(test.isFiniteNonZero());
1939 EXPECT_FALSE(test.isDenormal());
1940 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1941 EXPECT_TRUE(test.isSmallestNormalized());
1942
1943 test = APFloat::getSmallestNormalized(Sem: APFloat::Float8E4M3FNUZ(), Negative: false);
1944 expected = APFloat(APFloat::Float8E4M3FNUZ(), "0x1.0p-7");
1945 EXPECT_FALSE(test.isNegative());
1946 EXPECT_TRUE(test.isFiniteNonZero());
1947 EXPECT_FALSE(test.isDenormal());
1948 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1949 EXPECT_TRUE(test.isSmallestNormalized());
1950
1951 test = APFloat::getSmallestNormalized(Sem: APFloat::Float8E4M3B11FNUZ(), Negative: false);
1952 expected = APFloat(APFloat::Float8E4M3B11FNUZ(), "0x1.0p-10");
1953 EXPECT_FALSE(test.isNegative());
1954 EXPECT_TRUE(test.isFiniteNonZero());
1955 EXPECT_FALSE(test.isDenormal());
1956 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1957 EXPECT_TRUE(test.isSmallestNormalized());
1958
1959 test = APFloat::getSmallestNormalized(Sem: APFloat::FloatTF32(), Negative: false);
1960 expected = APFloat(APFloat::FloatTF32(), "0x1p-126");
1961 EXPECT_FALSE(test.isNegative());
1962 EXPECT_TRUE(test.isFiniteNonZero());
1963 EXPECT_FALSE(test.isDenormal());
1964 EXPECT_TRUE(test.bitwiseIsEqual(expected));
1965 EXPECT_TRUE(test.isSmallestNormalized());
1966}
1967
1968TEST(APFloatTest, getZero) {
1969 struct {
1970 const fltSemantics *semantics;
1971 const bool sign;
1972 const bool signedZero;
1973 const unsigned long long bitPattern[2];
1974 const unsigned bitPatternLength;
1975 } const GetZeroTest[] = {
1976 {.semantics: &APFloat::IEEEhalf(), .sign: false, .signedZero: true, .bitPattern: {0, 0}, .bitPatternLength: 1},
1977 {.semantics: &APFloat::IEEEhalf(), .sign: true, .signedZero: true, .bitPattern: {0x8000ULL, 0}, .bitPatternLength: 1},
1978 {.semantics: &APFloat::IEEEsingle(), .sign: false, .signedZero: true, .bitPattern: {0, 0}, .bitPatternLength: 1},
1979 {.semantics: &APFloat::IEEEsingle(), .sign: true, .signedZero: true, .bitPattern: {0x80000000ULL, 0}, .bitPatternLength: 1},
1980 {.semantics: &APFloat::IEEEdouble(), .sign: false, .signedZero: true, .bitPattern: {0, 0}, .bitPatternLength: 1},
1981 {.semantics: &APFloat::IEEEdouble(), .sign: true, .signedZero: true, .bitPattern: {0x8000000000000000ULL, 0}, .bitPatternLength: 1},
1982 {.semantics: &APFloat::IEEEquad(), .sign: false, .signedZero: true, .bitPattern: {0, 0}, .bitPatternLength: 2},
1983 {.semantics: &APFloat::IEEEquad(), .sign: true, .signedZero: true, .bitPattern: {0, 0x8000000000000000ULL}, .bitPatternLength: 2},
1984 {.semantics: &APFloat::PPCDoubleDouble(), .sign: false, .signedZero: true, .bitPattern: {0, 0}, .bitPatternLength: 2},
1985 {.semantics: &APFloat::PPCDoubleDouble(), .sign: true, .signedZero: true, .bitPattern: {0x8000000000000000ULL, 0}, .bitPatternLength: 2},
1986 {.semantics: &APFloat::x87DoubleExtended(), .sign: false, .signedZero: true, .bitPattern: {0, 0}, .bitPatternLength: 2},
1987 {.semantics: &APFloat::x87DoubleExtended(), .sign: true, .signedZero: true, .bitPattern: {0, 0x8000ULL}, .bitPatternLength: 2},
1988 {.semantics: &APFloat::Float8E5M2(), .sign: false, .signedZero: true, .bitPattern: {0, 0}, .bitPatternLength: 1},
1989 {.semantics: &APFloat::Float8E5M2(), .sign: true, .signedZero: true, .bitPattern: {0x80ULL, 0}, .bitPatternLength: 1},
1990 {.semantics: &APFloat::Float8E5M2FNUZ(), .sign: false, .signedZero: false, .bitPattern: {0, 0}, .bitPatternLength: 1},
1991 {.semantics: &APFloat::Float8E5M2FNUZ(), .sign: true, .signedZero: false, .bitPattern: {0, 0}, .bitPatternLength: 1},
1992 {.semantics: &APFloat::Float8E4M3FN(), .sign: false, .signedZero: true, .bitPattern: {0, 0}, .bitPatternLength: 1},
1993 {.semantics: &APFloat::Float8E4M3FN(), .sign: true, .signedZero: true, .bitPattern: {0x80ULL, 0}, .bitPatternLength: 1},
1994 {.semantics: &APFloat::Float8E4M3FNUZ(), .sign: false, .signedZero: false, .bitPattern: {0, 0}, .bitPatternLength: 1},
1995 {.semantics: &APFloat::Float8E4M3FNUZ(), .sign: true, .signedZero: false, .bitPattern: {0, 0}, .bitPatternLength: 1},
1996 {.semantics: &APFloat::Float8E4M3B11FNUZ(), .sign: false, .signedZero: false, .bitPattern: {0, 0}, .bitPatternLength: 1},
1997 {.semantics: &APFloat::Float8E4M3B11FNUZ(), .sign: true, .signedZero: false, .bitPattern: {0, 0}, .bitPatternLength: 1},
1998 {.semantics: &APFloat::FloatTF32(), .sign: false, .signedZero: true, .bitPattern: {0, 0}, .bitPatternLength: 1},
1999 {.semantics: &APFloat::FloatTF32(), .sign: true, .signedZero: true, .bitPattern: {0x40000ULL, 0}, .bitPatternLength: 1}};
2000 const unsigned NumGetZeroTests = std::size(GetZeroTest);
2001 for (unsigned i = 0; i < NumGetZeroTests; ++i) {
2002 APFloat test = APFloat::getZero(Sem: *GetZeroTest[i].semantics,
2003 Negative: GetZeroTest[i].sign);
2004 const char *pattern = GetZeroTest[i].sign? "-0x0p+0" : "0x0p+0";
2005 APFloat expected = APFloat(*GetZeroTest[i].semantics,
2006 pattern);
2007 EXPECT_TRUE(test.isZero());
2008 if (GetZeroTest[i].signedZero)
2009 EXPECT_TRUE(GetZeroTest[i].sign ? test.isNegative() : !test.isNegative());
2010 else
2011 EXPECT_TRUE(!test.isNegative());
2012 EXPECT_TRUE(test.bitwiseIsEqual(expected));
2013 for (unsigned j = 0, je = GetZeroTest[i].bitPatternLength; j < je; ++j) {
2014 EXPECT_EQ(GetZeroTest[i].bitPattern[j],
2015 test.bitcastToAPInt().getRawData()[j]);
2016 }
2017 }
2018}
2019
2020TEST(APFloatTest, copySign) {
2021 EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual(
2022 APFloat::copySign(APFloat(42.0), APFloat(-1.0))));
2023 EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual(
2024 APFloat::copySign(APFloat(-42.0), APFloat(1.0))));
2025 EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual(
2026 APFloat::copySign(APFloat(-42.0), APFloat(-1.0))));
2027 EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual(
2028 APFloat::copySign(APFloat(42.0), APFloat(1.0))));
2029 // For floating-point formats with unsigned 0, copySign() to a zero is a noop
2030 for (APFloat::Semantics S :
2031 {APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) {
2032 const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S);
2033 EXPECT_TRUE(APFloat::getZero(Sem).bitwiseIsEqual(
2034 APFloat::copySign(APFloat::getZero(Sem), APFloat(-1.0))));
2035 EXPECT_TRUE(APFloat::getNaN(Sem, true).bitwiseIsEqual(
2036 APFloat::copySign(APFloat::getNaN(Sem, true), APFloat(1.0))));
2037 }
2038}
2039
2040TEST(APFloatTest, convert) {
2041 bool losesInfo;
2042 APFloat test(APFloat::IEEEdouble(), "1.0");
2043 test.convert(ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2044 EXPECT_EQ(1.0f, test.convertToFloat());
2045 EXPECT_FALSE(losesInfo);
2046
2047 test = APFloat(APFloat::x87DoubleExtended(), "0x1p-53");
2048 test.add(RHS: APFloat(APFloat::x87DoubleExtended(), "1.0"), RM: APFloat::rmNearestTiesToEven);
2049 test.convert(ToSemantics: APFloat::IEEEdouble(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2050 EXPECT_EQ(1.0, test.convertToDouble());
2051 EXPECT_TRUE(losesInfo);
2052
2053 test = APFloat(APFloat::IEEEquad(), "0x1p-53");
2054 test.add(RHS: APFloat(APFloat::IEEEquad(), "1.0"), RM: APFloat::rmNearestTiesToEven);
2055 test.convert(ToSemantics: APFloat::IEEEdouble(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2056 EXPECT_EQ(1.0, test.convertToDouble());
2057 EXPECT_TRUE(losesInfo);
2058
2059 test = APFloat(APFloat::x87DoubleExtended(), "0xf.fffffffp+28");
2060 test.convert(ToSemantics: APFloat::IEEEdouble(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2061 EXPECT_EQ(4294967295.0, test.convertToDouble());
2062 EXPECT_FALSE(losesInfo);
2063
2064 test = APFloat::getSNaN(Sem: APFloat::IEEEsingle());
2065 APFloat::opStatus status = test.convert(ToSemantics: APFloat::x87DoubleExtended(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2066 // Conversion quiets the SNAN, so now 2 bits of the 64-bit significand should be set.
2067 APInt topTwoBits(64, 0x6000000000000000);
2068 EXPECT_TRUE(test.bitwiseIsEqual(APFloat::getQNaN(APFloat::x87DoubleExtended(), false, &topTwoBits)));
2069 EXPECT_FALSE(losesInfo);
2070 EXPECT_EQ(status, APFloat::opInvalidOp);
2071
2072 test = APFloat::getQNaN(Sem: APFloat::IEEEsingle());
2073 APFloat X87QNaN = APFloat::getQNaN(Sem: APFloat::x87DoubleExtended());
2074 test.convert(ToSemantics: APFloat::x87DoubleExtended(), RM: APFloat::rmNearestTiesToEven,
2075 losesInfo: &losesInfo);
2076 EXPECT_TRUE(test.bitwiseIsEqual(X87QNaN));
2077 EXPECT_FALSE(losesInfo);
2078
2079 test = APFloat::getSNaN(Sem: APFloat::x87DoubleExtended());
2080 test.convert(ToSemantics: APFloat::x87DoubleExtended(), RM: APFloat::rmNearestTiesToEven,
2081 losesInfo: &losesInfo);
2082 APFloat X87SNaN = APFloat::getSNaN(Sem: APFloat::x87DoubleExtended());
2083 EXPECT_TRUE(test.bitwiseIsEqual(X87SNaN));
2084 EXPECT_FALSE(losesInfo);
2085
2086 test = APFloat::getQNaN(Sem: APFloat::x87DoubleExtended());
2087 test.convert(ToSemantics: APFloat::x87DoubleExtended(), RM: APFloat::rmNearestTiesToEven,
2088 losesInfo: &losesInfo);
2089 EXPECT_TRUE(test.bitwiseIsEqual(X87QNaN));
2090 EXPECT_FALSE(losesInfo);
2091
2092 // The payload is lost in truncation, but we retain NaN by setting the quiet bit.
2093 APInt payload(52, 1);
2094 test = APFloat::getSNaN(Sem: APFloat::IEEEdouble(), Negative: false, payload: &payload);
2095 status = test.convert(ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2096 EXPECT_EQ(0x7fc00000, test.bitcastToAPInt());
2097 EXPECT_TRUE(losesInfo);
2098 EXPECT_EQ(status, APFloat::opInvalidOp);
2099
2100 // The payload is lost in truncation. QNaN remains QNaN.
2101 test = APFloat::getQNaN(Sem: APFloat::IEEEdouble(), Negative: false, payload: &payload);
2102 status = test.convert(ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2103 EXPECT_EQ(0x7fc00000, test.bitcastToAPInt());
2104 EXPECT_TRUE(losesInfo);
2105 EXPECT_EQ(status, APFloat::opOK);
2106
2107 // Test that subnormals are handled correctly in double to float conversion
2108 test = APFloat(APFloat::IEEEdouble(), "0x0.0000010000000p-1022");
2109 test.convert(ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2110 EXPECT_EQ(0.0f, test.convertToFloat());
2111 EXPECT_TRUE(losesInfo);
2112
2113 test = APFloat(APFloat::IEEEdouble(), "0x0.0000010000001p-1022");
2114 test.convert(ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2115 EXPECT_EQ(0.0f, test.convertToFloat());
2116 EXPECT_TRUE(losesInfo);
2117
2118 test = APFloat(APFloat::IEEEdouble(), "-0x0.0000010000001p-1022");
2119 test.convert(ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2120 EXPECT_EQ(0.0f, test.convertToFloat());
2121 EXPECT_TRUE(losesInfo);
2122
2123 test = APFloat(APFloat::IEEEdouble(), "0x0.0000020000000p-1022");
2124 test.convert(ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2125 EXPECT_EQ(0.0f, test.convertToFloat());
2126 EXPECT_TRUE(losesInfo);
2127
2128 test = APFloat(APFloat::IEEEdouble(), "0x0.0000020000001p-1022");
2129 test.convert(ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2130 EXPECT_EQ(0.0f, test.convertToFloat());
2131 EXPECT_TRUE(losesInfo);
2132
2133 // Test subnormal conversion to bfloat
2134 test = APFloat(APFloat::IEEEsingle(), "0x0.01p-126");
2135 test.convert(ToSemantics: APFloat::BFloat(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2136 EXPECT_EQ(0.0f, test.convertToFloat());
2137 EXPECT_TRUE(losesInfo);
2138
2139 test = APFloat(APFloat::IEEEsingle(), "0x0.02p-126");
2140 test.convert(ToSemantics: APFloat::BFloat(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
2141 EXPECT_EQ(0x01, test.bitcastToAPInt());
2142 EXPECT_FALSE(losesInfo);
2143
2144 test = APFloat(APFloat::IEEEsingle(), "0x0.01p-126");
2145 test.convert(ToSemantics: APFloat::BFloat(), RM: APFloat::rmNearestTiesToAway, losesInfo: &losesInfo);
2146 EXPECT_EQ(0x01, test.bitcastToAPInt());
2147 EXPECT_TRUE(losesInfo);
2148}
2149
2150TEST(APFloatTest, Float8UZConvert) {
2151 bool losesInfo = false;
2152 std::pair<APFloat, APFloat::opStatus> toNaNTests[] = {
2153 {APFloat::getQNaN(Sem: APFloat::IEEEsingle(), Negative: false), APFloat::opOK},
2154 {APFloat::getQNaN(Sem: APFloat::IEEEsingle(), Negative: true), APFloat::opOK},
2155 {APFloat::getSNaN(Sem: APFloat::IEEEsingle(), Negative: false), APFloat::opInvalidOp},
2156 {APFloat::getSNaN(Sem: APFloat::IEEEsingle(), Negative: true), APFloat::opInvalidOp},
2157 {APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false), APFloat::opInexact},
2158 {APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true), APFloat::opInexact}};
2159 for (APFloat::Semantics S :
2160 {APFloat::S_Float8E5M2FNUZ, APFloat::S_Float8E4M3FNUZ,
2161 APFloat::S_Float8E4M3B11FNUZ}) {
2162 const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S);
2163 SCOPED_TRACE("Semantics = " + std::to_string(S));
2164 for (auto [toTest, expectedRes] : toNaNTests) {
2165 llvm::SmallString<16> value;
2166 toTest.toString(Str&: value);
2167 SCOPED_TRACE("toTest = " + value);
2168 losesInfo = false;
2169 APFloat test = toTest;
2170 EXPECT_EQ(test.convert(Sem, APFloat::rmNearestTiesToAway, &losesInfo),
2171 expectedRes);
2172 EXPECT_TRUE(test.isNaN());
2173 EXPECT_TRUE(test.isNegative());
2174 EXPECT_FALSE(test.isSignaling());
2175 EXPECT_FALSE(test.isInfinity());
2176 EXPECT_EQ(0x80, test.bitcastToAPInt());
2177 EXPECT_TRUE(losesInfo);
2178 }
2179
2180 // Negative zero conversions are information losing.
2181 losesInfo = false;
2182 APFloat test = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: true);
2183 EXPECT_EQ(test.convert(Sem, APFloat::rmNearestTiesToAway, &losesInfo),
2184 APFloat::opInexact);
2185 EXPECT_TRUE(test.isZero());
2186 EXPECT_FALSE(test.isNegative());
2187 EXPECT_TRUE(losesInfo);
2188 EXPECT_EQ(0x0, test.bitcastToAPInt());
2189
2190 losesInfo = true;
2191 test = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: false);
2192 EXPECT_EQ(test.convert(Sem, APFloat::rmNearestTiesToAway, &losesInfo),
2193 APFloat::opOK);
2194 EXPECT_TRUE(test.isZero());
2195 EXPECT_FALSE(test.isNegative());
2196 EXPECT_FALSE(losesInfo);
2197 EXPECT_EQ(0x0, test.bitcastToAPInt());
2198
2199 // Except in casts between ourselves.
2200 losesInfo = true;
2201 test = APFloat::getZero(Sem);
2202 EXPECT_EQ(test.convert(Sem, APFloat::rmNearestTiesToAway, &losesInfo),
2203 APFloat::opOK);
2204 EXPECT_FALSE(losesInfo);
2205 EXPECT_EQ(0x0, test.bitcastToAPInt());
2206 }
2207}
2208
2209TEST(APFloatTest, PPCDoubleDouble) {
2210 APFloat test(APFloat::PPCDoubleDouble(), "1.0");
2211 EXPECT_EQ(0x3ff0000000000000ull, test.bitcastToAPInt().getRawData()[0]);
2212 EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]);
2213
2214 // LDBL_MAX
2215 test = APFloat(APFloat::PPCDoubleDouble(), "1.79769313486231580793728971405301e+308");
2216 EXPECT_EQ(0x7fefffffffffffffull, test.bitcastToAPInt().getRawData()[0]);
2217 EXPECT_EQ(0x7c8ffffffffffffeull, test.bitcastToAPInt().getRawData()[1]);
2218
2219 // LDBL_MIN
2220 test = APFloat(APFloat::PPCDoubleDouble(), "2.00416836000897277799610805135016e-292");
2221 EXPECT_EQ(0x0360000000000000ull, test.bitcastToAPInt().getRawData()[0]);
2222 EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]);
2223
2224 // PR30869
2225 {
2226 auto Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") +
2227 APFloat(APFloat::PPCDoubleDouble(), "1.0");
2228 EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
2229
2230 Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") -
2231 APFloat(APFloat::PPCDoubleDouble(), "1.0");
2232 EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
2233
2234 Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") *
2235 APFloat(APFloat::PPCDoubleDouble(), "1.0");
2236 EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
2237
2238 Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") /
2239 APFloat(APFloat::PPCDoubleDouble(), "1.0");
2240 EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
2241
2242 int Exp;
2243 Result = frexp(X: APFloat(APFloat::PPCDoubleDouble(), "1.0"), Exp,
2244 RM: APFloat::rmNearestTiesToEven);
2245 EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
2246
2247 Result = scalbn(X: APFloat(APFloat::PPCDoubleDouble(), "1.0"), Exp: 1,
2248 RM: APFloat::rmNearestTiesToEven);
2249 EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
2250 }
2251}
2252
2253TEST(APFloatTest, isNegative) {
2254 APFloat t(APFloat::IEEEsingle(), "0x1p+0");
2255 EXPECT_FALSE(t.isNegative());
2256 t = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
2257 EXPECT_TRUE(t.isNegative());
2258
2259 EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isNegative());
2260 EXPECT_TRUE(APFloat::getInf(APFloat::IEEEsingle(), true).isNegative());
2261
2262 EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isNegative());
2263 EXPECT_TRUE(APFloat::getZero(APFloat::IEEEsingle(), true).isNegative());
2264
2265 EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isNegative());
2266 EXPECT_TRUE(APFloat::getNaN(APFloat::IEEEsingle(), true).isNegative());
2267
2268 EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isNegative());
2269 EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), true).isNegative());
2270}
2271
2272TEST(APFloatTest, isNormal) {
2273 APFloat t(APFloat::IEEEsingle(), "0x1p+0");
2274 EXPECT_TRUE(t.isNormal());
2275
2276 EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isNormal());
2277 EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isNormal());
2278 EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isNormal());
2279 EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isNormal());
2280 EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isNormal());
2281}
2282
2283TEST(APFloatTest, isFinite) {
2284 APFloat t(APFloat::IEEEsingle(), "0x1p+0");
2285 EXPECT_TRUE(t.isFinite());
2286 EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isFinite());
2287 EXPECT_TRUE(APFloat::getZero(APFloat::IEEEsingle(), false).isFinite());
2288 EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isFinite());
2289 EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isFinite());
2290 EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isFinite());
2291}
2292
2293TEST(APFloatTest, isInfinity) {
2294 APFloat t(APFloat::IEEEsingle(), "0x1p+0");
2295 EXPECT_FALSE(t.isInfinity());
2296
2297 APFloat PosInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false);
2298 APFloat NegInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
2299
2300 EXPECT_TRUE(PosInf.isInfinity());
2301 EXPECT_TRUE(PosInf.isPosInfinity());
2302 EXPECT_FALSE(PosInf.isNegInfinity());
2303 EXPECT_EQ(fcPosInf, PosInf.classify());
2304
2305 EXPECT_TRUE(NegInf.isInfinity());
2306 EXPECT_FALSE(NegInf.isPosInfinity());
2307 EXPECT_TRUE(NegInf.isNegInfinity());
2308 EXPECT_EQ(fcNegInf, NegInf.classify());
2309
2310 EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isInfinity());
2311 EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isInfinity());
2312 EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isInfinity());
2313 EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isInfinity());
2314}
2315
2316TEST(APFloatTest, isNaN) {
2317 APFloat t(APFloat::IEEEsingle(), "0x1p+0");
2318 EXPECT_FALSE(t.isNaN());
2319 EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isNaN());
2320 EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isNaN());
2321 EXPECT_TRUE(APFloat::getNaN(APFloat::IEEEsingle(), false).isNaN());
2322 EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isNaN());
2323 EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isNaN());
2324}
2325
2326TEST(APFloatTest, isFiniteNonZero) {
2327 // Test positive/negative normal value.
2328 EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "0x1p+0").isFiniteNonZero());
2329 EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "-0x1p+0").isFiniteNonZero());
2330
2331 // Test positive/negative denormal value.
2332 EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isFiniteNonZero());
2333 EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "-0x1p-149").isFiniteNonZero());
2334
2335 // Test +/- Infinity.
2336 EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isFiniteNonZero());
2337 EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), true).isFiniteNonZero());
2338
2339 // Test +/- Zero.
2340 EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isFiniteNonZero());
2341 EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), true).isFiniteNonZero());
2342
2343 // Test +/- qNaN. +/- dont mean anything with qNaN but paranoia can't hurt in
2344 // this instance.
2345 EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isFiniteNonZero());
2346 EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), true).isFiniteNonZero());
2347
2348 // Test +/- sNaN. +/- dont mean anything with sNaN but paranoia can't hurt in
2349 // this instance.
2350 EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isFiniteNonZero());
2351 EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), true).isFiniteNonZero());
2352}
2353
2354TEST(APFloatTest, add) {
2355 // Test Special Cases against each other and normal values.
2356
2357 APFloat PInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false);
2358 APFloat MInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
2359 APFloat PZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: false);
2360 APFloat MZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: true);
2361 APFloat QNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: false);
2362 APFloat SNaN = APFloat(APFloat::IEEEsingle(), "snan123");
2363 APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
2364 APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
2365 APFloat PLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: false);
2366 APFloat MLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: true);
2367 APFloat PSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: false);
2368 APFloat MSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: true);
2369 APFloat PSmallestNormalized =
2370 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: false);
2371 APFloat MSmallestNormalized =
2372 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: true);
2373
2374 const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact;
2375
2376 struct {
2377 APFloat x;
2378 APFloat y;
2379 const char *result;
2380 int status;
2381 int category;
2382 } SpecialCaseTests[] = {
2383 { .x: PInf, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2384 { .x: PInf, .y: MInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2385 { .x: PInf, .y: PZero, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2386 { .x: PInf, .y: MZero, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2387 { .x: PInf, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2388 { .x: PInf, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2389 { .x: PInf, .y: PNormalValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2390 { .x: PInf, .y: MNormalValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2391 { .x: PInf, .y: PLargestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2392 { .x: PInf, .y: MLargestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2393 { .x: PInf, .y: PSmallestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2394 { .x: PInf, .y: MSmallestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2395 { .x: PInf, .y: PSmallestNormalized, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2396 { .x: PInf, .y: MSmallestNormalized, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2397 { .x: MInf, .y: PInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2398 { .x: MInf, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2399 { .x: MInf, .y: PZero, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2400 { .x: MInf, .y: MZero, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2401 { .x: MInf, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2402 { .x: MInf, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2403 { .x: MInf, .y: PNormalValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2404 { .x: MInf, .y: MNormalValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2405 { .x: MInf, .y: PLargestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2406 { .x: MInf, .y: MLargestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2407 { .x: MInf, .y: PSmallestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2408 { .x: MInf, .y: MSmallestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2409 { .x: MInf, .y: PSmallestNormalized, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2410 { .x: MInf, .y: MSmallestNormalized, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2411 { .x: PZero, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2412 { .x: PZero, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2413 { .x: PZero, .y: PZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2414 { .x: PZero, .y: MZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2415 { .x: PZero, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2416 { .x: PZero, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2417 { .x: PZero, .y: PNormalValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2418 { .x: PZero, .y: MNormalValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2419 { .x: PZero, .y: PLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2420 { .x: PZero, .y: MLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2421 { .x: PZero, .y: PSmallestValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2422 { .x: PZero, .y: MSmallestValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2423 { .x: PZero, .y: PSmallestNormalized, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2424 { .x: PZero, .y: MSmallestNormalized, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2425 { .x: MZero, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2426 { .x: MZero, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2427 { .x: MZero, .y: PZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2428 { .x: MZero, .y: MZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2429 { .x: MZero, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2430 { .x: MZero, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2431 { .x: MZero, .y: PNormalValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2432 { .x: MZero, .y: MNormalValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2433 { .x: MZero, .y: PLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2434 { .x: MZero, .y: MLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2435 { .x: MZero, .y: PSmallestValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2436 { .x: MZero, .y: MSmallestValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2437 { .x: MZero, .y: PSmallestNormalized, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2438 { .x: MZero, .y: MSmallestNormalized, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2439 { .x: QNaN, .y: PInf, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2440 { .x: QNaN, .y: MInf, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2441 { .x: QNaN, .y: PZero, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2442 { .x: QNaN, .y: MZero, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2443 { .x: QNaN, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2444 { .x: QNaN, .y: SNaN, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2445 { .x: QNaN, .y: PNormalValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2446 { .x: QNaN, .y: MNormalValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2447 { .x: QNaN, .y: PLargestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2448 { .x: QNaN, .y: MLargestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2449 { .x: QNaN, .y: PSmallestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2450 { .x: QNaN, .y: MSmallestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2451 { .x: QNaN, .y: PSmallestNormalized, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2452 { .x: QNaN, .y: MSmallestNormalized, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2453 { .x: SNaN, .y: PInf, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2454 { .x: SNaN, .y: MInf, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2455 { .x: SNaN, .y: PZero, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2456 { .x: SNaN, .y: MZero, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2457 { .x: SNaN, .y: QNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2458 { .x: SNaN, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2459 { .x: SNaN, .y: PNormalValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2460 { .x: SNaN, .y: MNormalValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2461 { .x: SNaN, .y: PLargestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2462 { .x: SNaN, .y: MLargestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2463 { .x: SNaN, .y: PSmallestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2464 { .x: SNaN, .y: MSmallestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2465 { .x: SNaN, .y: PSmallestNormalized, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2466 { .x: SNaN, .y: MSmallestNormalized, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2467 { .x: PNormalValue, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2468 { .x: PNormalValue, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2469 { .x: PNormalValue, .y: PZero, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2470 { .x: PNormalValue, .y: MZero, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2471 { .x: PNormalValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2472 { .x: PNormalValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2473 { .x: PNormalValue, .y: PNormalValue, .result: "0x1p+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
2474 { .x: PNormalValue, .y: MNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2475 { .x: PNormalValue, .y: PLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2476 { .x: PNormalValue, .y: MLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2477 { .x: PNormalValue, .y: PSmallestValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2478 { .x: PNormalValue, .y: MSmallestValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2479 { .x: PNormalValue, .y: PSmallestNormalized, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2480 { .x: PNormalValue, .y: MSmallestNormalized, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2481 { .x: MNormalValue, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2482 { .x: MNormalValue, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2483 { .x: MNormalValue, .y: PZero, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2484 { .x: MNormalValue, .y: MZero, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2485 { .x: MNormalValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2486 { .x: MNormalValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2487 { .x: MNormalValue, .y: PNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2488 { .x: MNormalValue, .y: MNormalValue, .result: "-0x1p+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
2489 { .x: MNormalValue, .y: PLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2490 { .x: MNormalValue, .y: MLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2491 { .x: MNormalValue, .y: PSmallestValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2492 { .x: MNormalValue, .y: MSmallestValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2493 { .x: MNormalValue, .y: PSmallestNormalized, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2494 { .x: MNormalValue, .y: MSmallestNormalized, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2495 { .x: PLargestValue, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2496 { .x: PLargestValue, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2497 { .x: PLargestValue, .y: PZero, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2498 { .x: PLargestValue, .y: MZero, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2499 { .x: PLargestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2500 { .x: PLargestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2501 { .x: PLargestValue, .y: PNormalValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2502 { .x: PLargestValue, .y: MNormalValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2503 { .x: PLargestValue, .y: PLargestValue, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
2504 { .x: PLargestValue, .y: MLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2505 { .x: PLargestValue, .y: PSmallestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2506 { .x: PLargestValue, .y: MSmallestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2507 { .x: PLargestValue, .y: PSmallestNormalized, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2508 { .x: PLargestValue, .y: MSmallestNormalized, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2509 { .x: MLargestValue, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2510 { .x: MLargestValue, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2511 { .x: MLargestValue, .y: PZero, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2512 { .x: MLargestValue, .y: MZero, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2513 { .x: MLargestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2514 { .x: MLargestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2515 { .x: MLargestValue, .y: PNormalValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2516 { .x: MLargestValue, .y: MNormalValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2517 { .x: MLargestValue, .y: PLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2518 { .x: MLargestValue, .y: MLargestValue, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
2519 { .x: MLargestValue, .y: PSmallestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2520 { .x: MLargestValue, .y: MSmallestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2521 { .x: MLargestValue, .y: PSmallestNormalized, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2522 { .x: MLargestValue, .y: MSmallestNormalized, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2523 { .x: PSmallestValue, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2524 { .x: PSmallestValue, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2525 { .x: PSmallestValue, .y: PZero, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2526 { .x: PSmallestValue, .y: MZero, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2527 { .x: PSmallestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2528 { .x: PSmallestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2529 { .x: PSmallestValue, .y: PNormalValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2530 { .x: PSmallestValue, .y: MNormalValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2531 { .x: PSmallestValue, .y: PLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2532 { .x: PSmallestValue, .y: MLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2533 { .x: PSmallestValue, .y: PSmallestValue, .result: "0x1p-148", .status: APFloat::opOK, .category: APFloat::fcNormal },
2534 { .x: PSmallestValue, .y: MSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2535 { .x: PSmallestValue, .y: PSmallestNormalized, .result: "0x1.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2536 { .x: PSmallestValue, .y: MSmallestNormalized, .result: "-0x1.fffffcp-127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2537 { .x: MSmallestValue, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2538 { .x: MSmallestValue, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2539 { .x: MSmallestValue, .y: PZero, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2540 { .x: MSmallestValue, .y: MZero, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2541 { .x: MSmallestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2542 { .x: MSmallestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2543 { .x: MSmallestValue, .y: PNormalValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2544 { .x: MSmallestValue, .y: MNormalValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2545 { .x: MSmallestValue, .y: PLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2546 { .x: MSmallestValue, .y: MLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2547 { .x: MSmallestValue, .y: PSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2548 { .x: MSmallestValue, .y: MSmallestValue, .result: "-0x1p-148", .status: APFloat::opOK, .category: APFloat::fcNormal },
2549 { .x: MSmallestValue, .y: PSmallestNormalized, .result: "0x1.fffffcp-127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2550 { .x: MSmallestValue, .y: MSmallestNormalized, .result: "-0x1.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2551 { .x: PSmallestNormalized, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2552 { .x: PSmallestNormalized, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2553 { .x: PSmallestNormalized, .y: PZero, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2554 { .x: PSmallestNormalized, .y: MZero, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2555 { .x: PSmallestNormalized, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2556 { .x: PSmallestNormalized, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2557 { .x: PSmallestNormalized, .y: PNormalValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2558 { .x: PSmallestNormalized, .y: MNormalValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2559 { .x: PSmallestNormalized, .y: PLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2560 { .x: PSmallestNormalized, .y: MLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2561 { .x: PSmallestNormalized, .y: PSmallestValue, .result: "0x1.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2562 { .x: PSmallestNormalized, .y: MSmallestValue, .result: "0x1.fffffcp-127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2563 { .x: PSmallestNormalized, .y: PSmallestNormalized, .result: "0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
2564 { .x: PSmallestNormalized, .y: MSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2565 { .x: MSmallestNormalized, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2566 { .x: MSmallestNormalized, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2567 { .x: MSmallestNormalized, .y: PZero, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2568 { .x: MSmallestNormalized, .y: MZero, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2569 { .x: MSmallestNormalized, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2570 { .x: MSmallestNormalized, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2571 { .x: MSmallestNormalized, .y: PNormalValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2572 { .x: MSmallestNormalized, .y: MNormalValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2573 { .x: MSmallestNormalized, .y: PLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2574 { .x: MSmallestNormalized, .y: MLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2575 { .x: MSmallestNormalized, .y: PSmallestValue, .result: "-0x1.fffffcp-127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2576 { .x: MSmallestNormalized, .y: MSmallestValue, .result: "-0x1.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2577 { .x: MSmallestNormalized, .y: PSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2578 { .x: MSmallestNormalized, .y: MSmallestNormalized, .result: "-0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal }
2579 };
2580
2581 for (size_t i = 0; i < std::size(SpecialCaseTests); ++i) {
2582 APFloat x(SpecialCaseTests[i].x);
2583 APFloat y(SpecialCaseTests[i].y);
2584 APFloat::opStatus status = x.add(RHS: y, RM: APFloat::rmNearestTiesToEven);
2585
2586 APFloat result(APFloat::IEEEsingle(), SpecialCaseTests[i].result);
2587
2588 EXPECT_TRUE(result.bitwiseIsEqual(x));
2589 EXPECT_EQ(SpecialCaseTests[i].status, (int)status);
2590 EXPECT_EQ(SpecialCaseTests[i].category, (int)x.getCategory());
2591 }
2592}
2593
2594TEST(APFloatTest, subtract) {
2595 // Test Special Cases against each other and normal values.
2596
2597 APFloat PInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false);
2598 APFloat MInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
2599 APFloat PZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: false);
2600 APFloat MZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: true);
2601 APFloat QNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: false);
2602 APFloat SNaN = APFloat(APFloat::IEEEsingle(), "snan123");
2603 APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
2604 APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
2605 APFloat PLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: false);
2606 APFloat MLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: true);
2607 APFloat PSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: false);
2608 APFloat MSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: true);
2609 APFloat PSmallestNormalized =
2610 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: false);
2611 APFloat MSmallestNormalized =
2612 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: true);
2613
2614 const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact;
2615
2616 struct {
2617 APFloat x;
2618 APFloat y;
2619 const char *result;
2620 int status;
2621 int category;
2622 } SpecialCaseTests[] = {
2623 { .x: PInf, .y: PInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2624 { .x: PInf, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2625 { .x: PInf, .y: PZero, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2626 { .x: PInf, .y: MZero, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2627 { .x: PInf, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2628 { .x: PInf, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2629 { .x: PInf, .y: PNormalValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2630 { .x: PInf, .y: MNormalValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2631 { .x: PInf, .y: PLargestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2632 { .x: PInf, .y: MLargestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2633 { .x: PInf, .y: PSmallestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2634 { .x: PInf, .y: MSmallestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2635 { .x: PInf, .y: PSmallestNormalized, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2636 { .x: PInf, .y: MSmallestNormalized, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2637 { .x: MInf, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2638 { .x: MInf, .y: MInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2639 { .x: MInf, .y: PZero, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2640 { .x: MInf, .y: MZero, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2641 { .x: MInf, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2642 { .x: MInf, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2643 { .x: MInf, .y: PNormalValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2644 { .x: MInf, .y: MNormalValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2645 { .x: MInf, .y: PLargestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2646 { .x: MInf, .y: MLargestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2647 { .x: MInf, .y: PSmallestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2648 { .x: MInf, .y: MSmallestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2649 { .x: MInf, .y: PSmallestNormalized, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2650 { .x: MInf, .y: MSmallestNormalized, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2651 { .x: PZero, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2652 { .x: PZero, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2653 { .x: PZero, .y: PZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2654 { .x: PZero, .y: MZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2655 { .x: PZero, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2656 { .x: PZero, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2657 { .x: PZero, .y: PNormalValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2658 { .x: PZero, .y: MNormalValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2659 { .x: PZero, .y: PLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2660 { .x: PZero, .y: MLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2661 { .x: PZero, .y: PSmallestValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2662 { .x: PZero, .y: MSmallestValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2663 { .x: PZero, .y: PSmallestNormalized, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2664 { .x: PZero, .y: MSmallestNormalized, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2665 { .x: MZero, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2666 { .x: MZero, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2667 { .x: MZero, .y: PZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2668 { .x: MZero, .y: MZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2669 { .x: MZero, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2670 { .x: MZero, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2671 { .x: MZero, .y: PNormalValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2672 { .x: MZero, .y: MNormalValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2673 { .x: MZero, .y: PLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2674 { .x: MZero, .y: MLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2675 { .x: MZero, .y: PSmallestValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2676 { .x: MZero, .y: MSmallestValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2677 { .x: MZero, .y: PSmallestNormalized, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2678 { .x: MZero, .y: MSmallestNormalized, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2679 { .x: QNaN, .y: PInf, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2680 { .x: QNaN, .y: MInf, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2681 { .x: QNaN, .y: PZero, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2682 { .x: QNaN, .y: MZero, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2683 { .x: QNaN, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2684 { .x: QNaN, .y: SNaN, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2685 { .x: QNaN, .y: PNormalValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2686 { .x: QNaN, .y: MNormalValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2687 { .x: QNaN, .y: PLargestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2688 { .x: QNaN, .y: MLargestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2689 { .x: QNaN, .y: PSmallestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2690 { .x: QNaN, .y: MSmallestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2691 { .x: QNaN, .y: PSmallestNormalized, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2692 { .x: QNaN, .y: MSmallestNormalized, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2693 { .x: SNaN, .y: PInf, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2694 { .x: SNaN, .y: MInf, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2695 { .x: SNaN, .y: PZero, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2696 { .x: SNaN, .y: MZero, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2697 { .x: SNaN, .y: QNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2698 { .x: SNaN, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2699 { .x: SNaN, .y: PNormalValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2700 { .x: SNaN, .y: MNormalValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2701 { .x: SNaN, .y: PLargestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2702 { .x: SNaN, .y: MLargestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2703 { .x: SNaN, .y: PSmallestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2704 { .x: SNaN, .y: MSmallestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2705 { .x: SNaN, .y: PSmallestNormalized, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2706 { .x: SNaN, .y: MSmallestNormalized, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2707 { .x: PNormalValue, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2708 { .x: PNormalValue, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2709 { .x: PNormalValue, .y: PZero, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2710 { .x: PNormalValue, .y: MZero, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2711 { .x: PNormalValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2712 { .x: PNormalValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2713 { .x: PNormalValue, .y: PNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2714 { .x: PNormalValue, .y: MNormalValue, .result: "0x1p+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
2715 { .x: PNormalValue, .y: PLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2716 { .x: PNormalValue, .y: MLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2717 { .x: PNormalValue, .y: PSmallestValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2718 { .x: PNormalValue, .y: MSmallestValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2719 { .x: PNormalValue, .y: PSmallestNormalized, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2720 { .x: PNormalValue, .y: MSmallestNormalized, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2721 { .x: MNormalValue, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2722 { .x: MNormalValue, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2723 { .x: MNormalValue, .y: PZero, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2724 { .x: MNormalValue, .y: MZero, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2725 { .x: MNormalValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2726 { .x: MNormalValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2727 { .x: MNormalValue, .y: PNormalValue, .result: "-0x1p+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
2728 { .x: MNormalValue, .y: MNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2729 { .x: MNormalValue, .y: PLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2730 { .x: MNormalValue, .y: MLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2731 { .x: MNormalValue, .y: PSmallestValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2732 { .x: MNormalValue, .y: MSmallestValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2733 { .x: MNormalValue, .y: PSmallestNormalized, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2734 { .x: MNormalValue, .y: MSmallestNormalized, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2735 { .x: PLargestValue, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2736 { .x: PLargestValue, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2737 { .x: PLargestValue, .y: PZero, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2738 { .x: PLargestValue, .y: MZero, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2739 { .x: PLargestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2740 { .x: PLargestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2741 { .x: PLargestValue, .y: PNormalValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2742 { .x: PLargestValue, .y: MNormalValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2743 { .x: PLargestValue, .y: PLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2744 { .x: PLargestValue, .y: MLargestValue, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
2745 { .x: PLargestValue, .y: PSmallestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2746 { .x: PLargestValue, .y: MSmallestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2747 { .x: PLargestValue, .y: PSmallestNormalized, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2748 { .x: PLargestValue, .y: MSmallestNormalized, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2749 { .x: MLargestValue, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2750 { .x: MLargestValue, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2751 { .x: MLargestValue, .y: PZero, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2752 { .x: MLargestValue, .y: MZero, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2753 { .x: MLargestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2754 { .x: MLargestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2755 { .x: MLargestValue, .y: PNormalValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2756 { .x: MLargestValue, .y: MNormalValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2757 { .x: MLargestValue, .y: PLargestValue, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
2758 { .x: MLargestValue, .y: MLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2759 { .x: MLargestValue, .y: PSmallestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2760 { .x: MLargestValue, .y: MSmallestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2761 { .x: MLargestValue, .y: PSmallestNormalized, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2762 { .x: MLargestValue, .y: MSmallestNormalized, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2763 { .x: PSmallestValue, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2764 { .x: PSmallestValue, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2765 { .x: PSmallestValue, .y: PZero, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2766 { .x: PSmallestValue, .y: MZero, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2767 { .x: PSmallestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2768 { .x: PSmallestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2769 { .x: PSmallestValue, .y: PNormalValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2770 { .x: PSmallestValue, .y: MNormalValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2771 { .x: PSmallestValue, .y: PLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2772 { .x: PSmallestValue, .y: MLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2773 { .x: PSmallestValue, .y: PSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2774 { .x: PSmallestValue, .y: MSmallestValue, .result: "0x1p-148", .status: APFloat::opOK, .category: APFloat::fcNormal },
2775 { .x: PSmallestValue, .y: PSmallestNormalized, .result: "-0x1.fffffcp-127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2776 { .x: PSmallestValue, .y: MSmallestNormalized, .result: "0x1.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2777 { .x: MSmallestValue, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2778 { .x: MSmallestValue, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2779 { .x: MSmallestValue, .y: PZero, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2780 { .x: MSmallestValue, .y: MZero, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2781 { .x: MSmallestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2782 { .x: MSmallestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2783 { .x: MSmallestValue, .y: PNormalValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2784 { .x: MSmallestValue, .y: MNormalValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2785 { .x: MSmallestValue, .y: PLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2786 { .x: MSmallestValue, .y: MLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2787 { .x: MSmallestValue, .y: PSmallestValue, .result: "-0x1p-148", .status: APFloat::opOK, .category: APFloat::fcNormal },
2788 { .x: MSmallestValue, .y: MSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2789 { .x: MSmallestValue, .y: PSmallestNormalized, .result: "-0x1.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2790 { .x: MSmallestValue, .y: MSmallestNormalized, .result: "0x1.fffffcp-127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2791 { .x: PSmallestNormalized, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2792 { .x: PSmallestNormalized, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2793 { .x: PSmallestNormalized, .y: PZero, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2794 { .x: PSmallestNormalized, .y: MZero, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2795 { .x: PSmallestNormalized, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2796 { .x: PSmallestNormalized, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2797 { .x: PSmallestNormalized, .y: PNormalValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2798 { .x: PSmallestNormalized, .y: MNormalValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2799 { .x: PSmallestNormalized, .y: PLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2800 { .x: PSmallestNormalized, .y: MLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2801 { .x: PSmallestNormalized, .y: PSmallestValue, .result: "0x1.fffffcp-127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2802 { .x: PSmallestNormalized, .y: MSmallestValue, .result: "0x1.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2803 { .x: PSmallestNormalized, .y: PSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2804 { .x: PSmallestNormalized, .y: MSmallestNormalized, .result: "0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
2805 { .x: MSmallestNormalized, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2806 { .x: MSmallestNormalized, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2807 { .x: MSmallestNormalized, .y: PZero, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2808 { .x: MSmallestNormalized, .y: MZero, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2809 { .x: MSmallestNormalized, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2810 { .x: MSmallestNormalized, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2811 { .x: MSmallestNormalized, .y: PNormalValue, .result: "-0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2812 { .x: MSmallestNormalized, .y: MNormalValue, .result: "0x1p+0", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2813 { .x: MSmallestNormalized, .y: PLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2814 { .x: MSmallestNormalized, .y: MLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opInexact, .category: APFloat::fcNormal },
2815 { .x: MSmallestNormalized, .y: PSmallestValue, .result: "-0x1.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2816 { .x: MSmallestNormalized, .y: MSmallestValue, .result: "-0x1.fffffcp-127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2817 { .x: MSmallestNormalized, .y: PSmallestNormalized, .result: "-0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
2818 { .x: MSmallestNormalized, .y: MSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero }
2819 };
2820
2821 for (size_t i = 0; i < std::size(SpecialCaseTests); ++i) {
2822 APFloat x(SpecialCaseTests[i].x);
2823 APFloat y(SpecialCaseTests[i].y);
2824 APFloat::opStatus status = x.subtract(RHS: y, RM: APFloat::rmNearestTiesToEven);
2825
2826 APFloat result(APFloat::IEEEsingle(), SpecialCaseTests[i].result);
2827
2828 EXPECT_TRUE(result.bitwiseIsEqual(x));
2829 EXPECT_EQ(SpecialCaseTests[i].status, (int)status);
2830 EXPECT_EQ(SpecialCaseTests[i].category, (int)x.getCategory());
2831 }
2832}
2833
2834TEST(APFloatTest, multiply) {
2835 // Test Special Cases against each other and normal values.
2836
2837 APFloat PInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false);
2838 APFloat MInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
2839 APFloat PZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: false);
2840 APFloat MZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: true);
2841 APFloat QNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: false);
2842 APFloat SNaN = APFloat(APFloat::IEEEsingle(), "snan123");
2843 APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
2844 APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
2845 APFloat PLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: false);
2846 APFloat MLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: true);
2847 APFloat PSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: false);
2848 APFloat MSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: true);
2849 APFloat PSmallestNormalized =
2850 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: false);
2851 APFloat MSmallestNormalized =
2852 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: true);
2853
2854 APFloat MaxQuad(APFloat::IEEEquad(),
2855 "0x1.ffffffffffffffffffffffffffffp+16383");
2856 APFloat MinQuad(APFloat::IEEEquad(),
2857 "0x0.0000000000000000000000000001p-16382");
2858 APFloat NMinQuad(APFloat::IEEEquad(),
2859 "-0x0.0000000000000000000000000001p-16382");
2860
2861 const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact;
2862 const int UnderflowStatus = APFloat::opUnderflow | APFloat::opInexact;
2863
2864 struct {
2865 APFloat x;
2866 APFloat y;
2867 const char *result;
2868 int status;
2869 int category;
2870 APFloat::roundingMode roundingMode = APFloat::rmNearestTiesToEven;
2871 } SpecialCaseTests[] = {
2872 { .x: PInf, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2873 { .x: PInf, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2874 { .x: PInf, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2875 { .x: PInf, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2876 { .x: PInf, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2877 { .x: PInf, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2878 { .x: PInf, .y: PNormalValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2879 { .x: PInf, .y: MNormalValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2880 { .x: PInf, .y: PLargestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2881 { .x: PInf, .y: MLargestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2882 { .x: PInf, .y: PSmallestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2883 { .x: PInf, .y: MSmallestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2884 { .x: PInf, .y: PSmallestNormalized, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2885 { .x: PInf, .y: MSmallestNormalized, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2886 { .x: MInf, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2887 { .x: MInf, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2888 { .x: MInf, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2889 { .x: MInf, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2890 { .x: MInf, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2891 { .x: MInf, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2892 { .x: MInf, .y: PNormalValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2893 { .x: MInf, .y: MNormalValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2894 { .x: MInf, .y: PLargestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2895 { .x: MInf, .y: MLargestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2896 { .x: MInf, .y: PSmallestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2897 { .x: MInf, .y: MSmallestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2898 { .x: MInf, .y: PSmallestNormalized, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2899 { .x: MInf, .y: MSmallestNormalized, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2900 { .x: PZero, .y: PInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2901 { .x: PZero, .y: MInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2902 { .x: PZero, .y: PZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2903 { .x: PZero, .y: MZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2904 { .x: PZero, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2905 { .x: PZero, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2906 { .x: PZero, .y: PNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2907 { .x: PZero, .y: MNormalValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2908 { .x: PZero, .y: PLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2909 { .x: PZero, .y: MLargestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2910 { .x: PZero, .y: PSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2911 { .x: PZero, .y: MSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2912 { .x: PZero, .y: PSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2913 { .x: PZero, .y: MSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2914 { .x: MZero, .y: PInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2915 { .x: MZero, .y: MInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2916 { .x: MZero, .y: PZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2917 { .x: MZero, .y: MZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2918 { .x: MZero, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2919 { .x: MZero, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2920 { .x: MZero, .y: PNormalValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2921 { .x: MZero, .y: MNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2922 { .x: MZero, .y: PLargestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2923 { .x: MZero, .y: MLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2924 { .x: MZero, .y: PSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2925 { .x: MZero, .y: MSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2926 { .x: MZero, .y: PSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2927 { .x: MZero, .y: MSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2928 { .x: QNaN, .y: PInf, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2929 { .x: QNaN, .y: MInf, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2930 { .x: QNaN, .y: PZero, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2931 { .x: QNaN, .y: MZero, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2932 { .x: QNaN, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2933 { .x: QNaN, .y: SNaN, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2934 { .x: QNaN, .y: PNormalValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2935 { .x: QNaN, .y: MNormalValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2936 { .x: QNaN, .y: PLargestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2937 { .x: QNaN, .y: MLargestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2938 { .x: QNaN, .y: PSmallestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2939 { .x: QNaN, .y: MSmallestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2940 { .x: QNaN, .y: PSmallestNormalized, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2941 { .x: QNaN, .y: MSmallestNormalized, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2942 { .x: SNaN, .y: PInf, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2943 { .x: SNaN, .y: MInf, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2944 { .x: SNaN, .y: PZero, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2945 { .x: SNaN, .y: MZero, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2946 { .x: SNaN, .y: QNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2947 { .x: SNaN, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2948 { .x: SNaN, .y: PNormalValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2949 { .x: SNaN, .y: MNormalValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2950 { .x: SNaN, .y: PLargestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2951 { .x: SNaN, .y: MLargestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2952 { .x: SNaN, .y: PSmallestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2953 { .x: SNaN, .y: MSmallestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2954 { .x: SNaN, .y: PSmallestNormalized, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2955 { .x: SNaN, .y: MSmallestNormalized, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2956 { .x: PNormalValue, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2957 { .x: PNormalValue, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2958 { .x: PNormalValue, .y: PZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2959 { .x: PNormalValue, .y: MZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2960 { .x: PNormalValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2961 { .x: PNormalValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2962 { .x: PNormalValue, .y: PNormalValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2963 { .x: PNormalValue, .y: MNormalValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2964 { .x: PNormalValue, .y: PLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2965 { .x: PNormalValue, .y: MLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2966 { .x: PNormalValue, .y: PSmallestValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2967 { .x: PNormalValue, .y: MSmallestValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2968 { .x: PNormalValue, .y: PSmallestNormalized, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2969 { .x: PNormalValue, .y: MSmallestNormalized, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2970 { .x: MNormalValue, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2971 { .x: MNormalValue, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2972 { .x: MNormalValue, .y: PZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2973 { .x: MNormalValue, .y: MZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2974 { .x: MNormalValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2975 { .x: MNormalValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2976 { .x: MNormalValue, .y: PNormalValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2977 { .x: MNormalValue, .y: MNormalValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
2978 { .x: MNormalValue, .y: PLargestValue, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2979 { .x: MNormalValue, .y: MLargestValue, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2980 { .x: MNormalValue, .y: PSmallestValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2981 { .x: MNormalValue, .y: MSmallestValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
2982 { .x: MNormalValue, .y: PSmallestNormalized, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2983 { .x: MNormalValue, .y: MSmallestNormalized, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
2984 { .x: PLargestValue, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2985 { .x: PLargestValue, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2986 { .x: PLargestValue, .y: PZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2987 { .x: PLargestValue, .y: MZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
2988 { .x: PLargestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
2989 { .x: PLargestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
2990 { .x: PLargestValue, .y: PNormalValue, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2991 { .x: PLargestValue, .y: MNormalValue, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
2992 { .x: PLargestValue, .y: PLargestValue, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
2993 { .x: PLargestValue, .y: MLargestValue, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
2994 { .x: PLargestValue, .y: PSmallestValue, .result: "0x1.fffffep-22", .status: APFloat::opOK, .category: APFloat::fcNormal },
2995 { .x: PLargestValue, .y: MSmallestValue, .result: "-0x1.fffffep-22", .status: APFloat::opOK, .category: APFloat::fcNormal },
2996 { .x: PLargestValue, .y: PSmallestNormalized, .result: "0x1.fffffep+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
2997 { .x: PLargestValue, .y: MSmallestNormalized, .result: "-0x1.fffffep+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
2998 { .x: MLargestValue, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
2999 { .x: MLargestValue, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3000 { .x: MLargestValue, .y: PZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3001 { .x: MLargestValue, .y: MZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3002 { .x: MLargestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3003 { .x: MLargestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3004 { .x: MLargestValue, .y: PNormalValue, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
3005 { .x: MLargestValue, .y: MNormalValue, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
3006 { .x: MLargestValue, .y: PLargestValue, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3007 { .x: MLargestValue, .y: MLargestValue, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3008 { .x: MLargestValue, .y: PSmallestValue, .result: "-0x1.fffffep-22", .status: APFloat::opOK, .category: APFloat::fcNormal },
3009 { .x: MLargestValue, .y: MSmallestValue, .result: "0x1.fffffep-22", .status: APFloat::opOK, .category: APFloat::fcNormal },
3010 { .x: MLargestValue, .y: PSmallestNormalized, .result: "-0x1.fffffep+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
3011 { .x: MLargestValue, .y: MSmallestNormalized, .result: "0x1.fffffep+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
3012 { .x: PSmallestValue, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3013 { .x: PSmallestValue, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3014 { .x: PSmallestValue, .y: PZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3015 { .x: PSmallestValue, .y: MZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3016 { .x: PSmallestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3017 { .x: PSmallestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3018 { .x: PSmallestValue, .y: PNormalValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
3019 { .x: PSmallestValue, .y: MNormalValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
3020 { .x: PSmallestValue, .y: PLargestValue, .result: "0x1.fffffep-22", .status: APFloat::opOK, .category: APFloat::fcNormal },
3021 { .x: PSmallestValue, .y: MLargestValue, .result: "-0x1.fffffep-22", .status: APFloat::opOK, .category: APFloat::fcNormal },
3022 { .x: PSmallestValue, .y: PSmallestValue, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3023 { .x: PSmallestValue, .y: MSmallestValue, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3024 { .x: PSmallestValue, .y: PSmallestNormalized, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3025 { .x: PSmallestValue, .y: MSmallestNormalized, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3026 { .x: MSmallestValue, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3027 { .x: MSmallestValue, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3028 { .x: MSmallestValue, .y: PZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3029 { .x: MSmallestValue, .y: MZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3030 { .x: MSmallestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3031 { .x: MSmallestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3032 { .x: MSmallestValue, .y: PNormalValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
3033 { .x: MSmallestValue, .y: MNormalValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
3034 { .x: MSmallestValue, .y: PLargestValue, .result: "-0x1.fffffep-22", .status: APFloat::opOK, .category: APFloat::fcNormal },
3035 { .x: MSmallestValue, .y: MLargestValue, .result: "0x1.fffffep-22", .status: APFloat::opOK, .category: APFloat::fcNormal },
3036 { .x: MSmallestValue, .y: PSmallestValue, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3037 { .x: MSmallestValue, .y: MSmallestValue, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3038 { .x: MSmallestValue, .y: PSmallestNormalized, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3039 { .x: MSmallestValue, .y: MSmallestNormalized, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3040 { .x: PSmallestNormalized, .y: PInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3041 { .x: PSmallestNormalized, .y: MInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3042 { .x: PSmallestNormalized, .y: PZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3043 { .x: PSmallestNormalized, .y: MZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3044 { .x: PSmallestNormalized, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3045 { .x: PSmallestNormalized, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3046 { .x: PSmallestNormalized, .y: PNormalValue, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3047 { .x: PSmallestNormalized, .y: MNormalValue, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3048 { .x: PSmallestNormalized, .y: PLargestValue, .result: "0x1.fffffep+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
3049 { .x: PSmallestNormalized, .y: MLargestValue, .result: "-0x1.fffffep+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
3050 { .x: PSmallestNormalized, .y: PSmallestValue, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3051 { .x: PSmallestNormalized, .y: MSmallestValue, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3052 { .x: PSmallestNormalized, .y: PSmallestNormalized, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3053 { .x: PSmallestNormalized, .y: MSmallestNormalized, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3054 { .x: MSmallestNormalized, .y: PInf, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3055 { .x: MSmallestNormalized, .y: MInf, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3056 { .x: MSmallestNormalized, .y: PZero, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3057 { .x: MSmallestNormalized, .y: MZero, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3058 { .x: MSmallestNormalized, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3059 { .x: MSmallestNormalized, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3060 { .x: MSmallestNormalized, .y: PNormalValue, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3061 { .x: MSmallestNormalized, .y: MNormalValue, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3062 { .x: MSmallestNormalized, .y: PLargestValue, .result: "-0x1.fffffep+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
3063 { .x: MSmallestNormalized, .y: MLargestValue, .result: "0x1.fffffep+1", .status: APFloat::opOK, .category: APFloat::fcNormal },
3064 { .x: MSmallestNormalized, .y: PSmallestValue, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3065 { .x: MSmallestNormalized, .y: MSmallestValue, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3066 { .x: MSmallestNormalized, .y: PSmallestNormalized, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3067 { .x: MSmallestNormalized, .y: MSmallestNormalized, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3068
3069 {.x: MaxQuad, .y: MinQuad, .result: "0x1.ffffffffffffffffffffffffffffp-111", .status: APFloat::opOK,
3070 .category: APFloat::fcNormal, .roundingMode: APFloat::rmNearestTiesToEven},
3071 {.x: MaxQuad, .y: MinQuad, .result: "0x1.ffffffffffffffffffffffffffffp-111", .status: APFloat::opOK,
3072 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardPositive},
3073 {.x: MaxQuad, .y: MinQuad, .result: "0x1.ffffffffffffffffffffffffffffp-111", .status: APFloat::opOK,
3074 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardNegative},
3075 {.x: MaxQuad, .y: MinQuad, .result: "0x1.ffffffffffffffffffffffffffffp-111", .status: APFloat::opOK,
3076 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardZero},
3077 {.x: MaxQuad, .y: MinQuad, .result: "0x1.ffffffffffffffffffffffffffffp-111", .status: APFloat::opOK,
3078 .category: APFloat::fcNormal, .roundingMode: APFloat::rmNearestTiesToAway},
3079
3080 {.x: MaxQuad, .y: NMinQuad, .result: "-0x1.ffffffffffffffffffffffffffffp-111", .status: APFloat::opOK,
3081 .category: APFloat::fcNormal, .roundingMode: APFloat::rmNearestTiesToEven},
3082 {.x: MaxQuad, .y: NMinQuad, .result: "-0x1.ffffffffffffffffffffffffffffp-111", .status: APFloat::opOK,
3083 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardPositive},
3084 {.x: MaxQuad, .y: NMinQuad, .result: "-0x1.ffffffffffffffffffffffffffffp-111", .status: APFloat::opOK,
3085 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardNegative},
3086 {.x: MaxQuad, .y: NMinQuad, .result: "-0x1.ffffffffffffffffffffffffffffp-111", .status: APFloat::opOK,
3087 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardZero},
3088 {.x: MaxQuad, .y: NMinQuad, .result: "-0x1.ffffffffffffffffffffffffffffp-111", .status: APFloat::opOK,
3089 .category: APFloat::fcNormal, .roundingMode: APFloat::rmNearestTiesToAway},
3090
3091 {.x: MaxQuad, .y: MaxQuad, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity,
3092 .roundingMode: APFloat::rmNearestTiesToEven},
3093 {.x: MaxQuad, .y: MaxQuad, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity,
3094 .roundingMode: APFloat::rmTowardPositive},
3095 {.x: MaxQuad, .y: MaxQuad, .result: "0x1.ffffffffffffffffffffffffffffp+16383",
3096 .status: APFloat::opInexact, .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardNegative},
3097 {.x: MaxQuad, .y: MaxQuad, .result: "0x1.ffffffffffffffffffffffffffffp+16383",
3098 .status: APFloat::opInexact, .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardZero},
3099 {.x: MaxQuad, .y: MaxQuad, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity,
3100 .roundingMode: APFloat::rmNearestTiesToAway},
3101
3102 {.x: MinQuad, .y: MinQuad, .result: "0", .status: UnderflowStatus, .category: APFloat::fcZero,
3103 .roundingMode: APFloat::rmNearestTiesToEven},
3104 {.x: MinQuad, .y: MinQuad, .result: "0x0.0000000000000000000000000001p-16382",
3105 .status: UnderflowStatus, .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardPositive},
3106 {.x: MinQuad, .y: MinQuad, .result: "0", .status: UnderflowStatus, .category: APFloat::fcZero,
3107 .roundingMode: APFloat::rmTowardNegative},
3108 {.x: MinQuad, .y: MinQuad, .result: "0", .status: UnderflowStatus, .category: APFloat::fcZero,
3109 .roundingMode: APFloat::rmTowardZero},
3110 {.x: MinQuad, .y: MinQuad, .result: "0", .status: UnderflowStatus, .category: APFloat::fcZero,
3111 .roundingMode: APFloat::rmNearestTiesToAway},
3112
3113 {.x: MinQuad, .y: NMinQuad, .result: "-0", .status: UnderflowStatus, .category: APFloat::fcZero,
3114 .roundingMode: APFloat::rmNearestTiesToEven},
3115 {.x: MinQuad, .y: NMinQuad, .result: "-0", .status: UnderflowStatus, .category: APFloat::fcZero,
3116 .roundingMode: APFloat::rmTowardPositive},
3117 {.x: MinQuad, .y: NMinQuad, .result: "-0x0.0000000000000000000000000001p-16382",
3118 .status: UnderflowStatus, .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardNegative},
3119 {.x: MinQuad, .y: NMinQuad, .result: "-0", .status: UnderflowStatus, .category: APFloat::fcZero,
3120 .roundingMode: APFloat::rmTowardZero},
3121 {.x: MinQuad, .y: NMinQuad, .result: "-0", .status: UnderflowStatus, .category: APFloat::fcZero,
3122 .roundingMode: APFloat::rmNearestTiesToAway},
3123 };
3124
3125 for (size_t i = 0; i < std::size(SpecialCaseTests); ++i) {
3126 APFloat x(SpecialCaseTests[i].x);
3127 APFloat y(SpecialCaseTests[i].y);
3128 APFloat::opStatus status = x.multiply(RHS: y, RM: SpecialCaseTests[i].roundingMode);
3129
3130 APFloat result(x.getSemantics(), SpecialCaseTests[i].result);
3131
3132 EXPECT_TRUE(result.bitwiseIsEqual(x));
3133 EXPECT_EQ(SpecialCaseTests[i].status, (int)status);
3134 EXPECT_EQ(SpecialCaseTests[i].category, (int)x.getCategory());
3135 }
3136}
3137
3138TEST(APFloatTest, divide) {
3139 // Test Special Cases against each other and normal values.
3140
3141 APFloat PInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false);
3142 APFloat MInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
3143 APFloat PZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: false);
3144 APFloat MZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: true);
3145 APFloat QNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: false);
3146 APFloat SNaN = APFloat(APFloat::IEEEsingle(), "snan123");
3147 APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
3148 APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
3149 APFloat PLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: false);
3150 APFloat MLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: true);
3151 APFloat PSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: false);
3152 APFloat MSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: true);
3153 APFloat PSmallestNormalized =
3154 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: false);
3155 APFloat MSmallestNormalized =
3156 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: true);
3157
3158 APFloat MaxQuad(APFloat::IEEEquad(),
3159 "0x1.ffffffffffffffffffffffffffffp+16383");
3160 APFloat MinQuad(APFloat::IEEEquad(),
3161 "0x0.0000000000000000000000000001p-16382");
3162 APFloat NMinQuad(APFloat::IEEEquad(),
3163 "-0x0.0000000000000000000000000001p-16382");
3164
3165 const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact;
3166 const int UnderflowStatus = APFloat::opUnderflow | APFloat::opInexact;
3167
3168 struct {
3169 APFloat x;
3170 APFloat y;
3171 const char *result;
3172 int status;
3173 int category;
3174 APFloat::roundingMode roundingMode = APFloat::rmNearestTiesToEven;
3175 } SpecialCaseTests[] = {
3176 { .x: PInf, .y: PInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3177 { .x: PInf, .y: MInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3178 { .x: PInf, .y: PZero, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3179 { .x: PInf, .y: MZero, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3180 { .x: PInf, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3181 { .x: PInf, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3182 { .x: PInf, .y: PNormalValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3183 { .x: PInf, .y: MNormalValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3184 { .x: PInf, .y: PLargestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3185 { .x: PInf, .y: MLargestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3186 { .x: PInf, .y: PSmallestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3187 { .x: PInf, .y: MSmallestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3188 { .x: PInf, .y: PSmallestNormalized, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3189 { .x: PInf, .y: MSmallestNormalized, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3190 { .x: MInf, .y: PInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3191 { .x: MInf, .y: MInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3192 { .x: MInf, .y: PZero, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3193 { .x: MInf, .y: MZero, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3194 { .x: MInf, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3195 { .x: MInf, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3196 { .x: MInf, .y: PNormalValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3197 { .x: MInf, .y: MNormalValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3198 { .x: MInf, .y: PLargestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3199 { .x: MInf, .y: MLargestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3200 { .x: MInf, .y: PSmallestValue, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3201 { .x: MInf, .y: MSmallestValue, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3202 { .x: MInf, .y: PSmallestNormalized, .result: "-inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3203 { .x: MInf, .y: MSmallestNormalized, .result: "inf", .status: APFloat::opOK, .category: APFloat::fcInfinity },
3204 { .x: PZero, .y: PInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3205 { .x: PZero, .y: MInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3206 { .x: PZero, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3207 { .x: PZero, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3208 { .x: PZero, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3209 { .x: PZero, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3210 { .x: PZero, .y: PNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3211 { .x: PZero, .y: MNormalValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3212 { .x: PZero, .y: PLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3213 { .x: PZero, .y: MLargestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3214 { .x: PZero, .y: PSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3215 { .x: PZero, .y: MSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3216 { .x: PZero, .y: PSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3217 { .x: PZero, .y: MSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3218 { .x: MZero, .y: PInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3219 { .x: MZero, .y: MInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3220 { .x: MZero, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3221 { .x: MZero, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3222 { .x: MZero, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3223 { .x: MZero, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3224 { .x: MZero, .y: PNormalValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3225 { .x: MZero, .y: MNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3226 { .x: MZero, .y: PLargestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3227 { .x: MZero, .y: MLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3228 { .x: MZero, .y: PSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3229 { .x: MZero, .y: MSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3230 { .x: MZero, .y: PSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3231 { .x: MZero, .y: MSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3232 { .x: QNaN, .y: PInf, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3233 { .x: QNaN, .y: MInf, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3234 { .x: QNaN, .y: PZero, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3235 { .x: QNaN, .y: MZero, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3236 { .x: QNaN, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3237 { .x: QNaN, .y: SNaN, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3238 { .x: QNaN, .y: PNormalValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3239 { .x: QNaN, .y: MNormalValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3240 { .x: QNaN, .y: PLargestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3241 { .x: QNaN, .y: MLargestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3242 { .x: QNaN, .y: PSmallestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3243 { .x: QNaN, .y: MSmallestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3244 { .x: QNaN, .y: PSmallestNormalized, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3245 { .x: QNaN, .y: MSmallestNormalized, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3246 { .x: SNaN, .y: PInf, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3247 { .x: SNaN, .y: MInf, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3248 { .x: SNaN, .y: PZero, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3249 { .x: SNaN, .y: MZero, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3250 { .x: SNaN, .y: QNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3251 { .x: SNaN, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3252 { .x: SNaN, .y: PNormalValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3253 { .x: SNaN, .y: MNormalValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3254 { .x: SNaN, .y: PLargestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3255 { .x: SNaN, .y: MLargestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3256 { .x: SNaN, .y: PSmallestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3257 { .x: SNaN, .y: MSmallestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3258 { .x: SNaN, .y: PSmallestNormalized, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3259 { .x: SNaN, .y: MSmallestNormalized, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3260 { .x: PNormalValue, .y: PInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3261 { .x: PNormalValue, .y: MInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3262 { .x: PNormalValue, .y: PZero, .result: "inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3263 { .x: PNormalValue, .y: MZero, .result: "-inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3264 { .x: PNormalValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3265 { .x: PNormalValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3266 { .x: PNormalValue, .y: PNormalValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3267 { .x: PNormalValue, .y: MNormalValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3268 { .x: PNormalValue, .y: PLargestValue, .result: "0x1p-128", .status: UnderflowStatus, .category: APFloat::fcNormal },
3269 { .x: PNormalValue, .y: MLargestValue, .result: "-0x1p-128", .status: UnderflowStatus, .category: APFloat::fcNormal },
3270 { .x: PNormalValue, .y: PSmallestValue, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3271 { .x: PNormalValue, .y: MSmallestValue, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3272 { .x: PNormalValue, .y: PSmallestNormalized, .result: "0x1p+126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3273 { .x: PNormalValue, .y: MSmallestNormalized, .result: "-0x1p+126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3274 { .x: MNormalValue, .y: PInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3275 { .x: MNormalValue, .y: MInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3276 { .x: MNormalValue, .y: PZero, .result: "-inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3277 { .x: MNormalValue, .y: MZero, .result: "inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3278 { .x: MNormalValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3279 { .x: MNormalValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3280 { .x: MNormalValue, .y: PNormalValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3281 { .x: MNormalValue, .y: MNormalValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3282 { .x: MNormalValue, .y: PLargestValue, .result: "-0x1p-128", .status: UnderflowStatus, .category: APFloat::fcNormal },
3283 { .x: MNormalValue, .y: MLargestValue, .result: "0x1p-128", .status: UnderflowStatus, .category: APFloat::fcNormal },
3284 { .x: MNormalValue, .y: PSmallestValue, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3285 { .x: MNormalValue, .y: MSmallestValue, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3286 { .x: MNormalValue, .y: PSmallestNormalized, .result: "-0x1p+126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3287 { .x: MNormalValue, .y: MSmallestNormalized, .result: "0x1p+126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3288 { .x: PLargestValue, .y: PInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3289 { .x: PLargestValue, .y: MInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3290 { .x: PLargestValue, .y: PZero, .result: "inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3291 { .x: PLargestValue, .y: MZero, .result: "-inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3292 { .x: PLargestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3293 { .x: PLargestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3294 { .x: PLargestValue, .y: PNormalValue, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
3295 { .x: PLargestValue, .y: MNormalValue, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
3296 { .x: PLargestValue, .y: PLargestValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3297 { .x: PLargestValue, .y: MLargestValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3298 { .x: PLargestValue, .y: PSmallestValue, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3299 { .x: PLargestValue, .y: MSmallestValue, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3300 { .x: PLargestValue, .y: PSmallestNormalized, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3301 { .x: PLargestValue, .y: MSmallestNormalized, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3302 { .x: MLargestValue, .y: PInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3303 { .x: MLargestValue, .y: MInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3304 { .x: MLargestValue, .y: PZero, .result: "-inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3305 { .x: MLargestValue, .y: MZero, .result: "inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3306 { .x: MLargestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3307 { .x: MLargestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3308 { .x: MLargestValue, .y: PNormalValue, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
3309 { .x: MLargestValue, .y: MNormalValue, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
3310 { .x: MLargestValue, .y: PLargestValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3311 { .x: MLargestValue, .y: MLargestValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3312 { .x: MLargestValue, .y: PSmallestValue, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3313 { .x: MLargestValue, .y: MSmallestValue, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3314 { .x: MLargestValue, .y: PSmallestNormalized, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3315 { .x: MLargestValue, .y: MSmallestNormalized, .result: "inf", .status: OverflowStatus, .category: APFloat::fcInfinity },
3316 { .x: PSmallestValue, .y: PInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3317 { .x: PSmallestValue, .y: MInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3318 { .x: PSmallestValue, .y: PZero, .result: "inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3319 { .x: PSmallestValue, .y: MZero, .result: "-inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3320 { .x: PSmallestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3321 { .x: PSmallestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3322 { .x: PSmallestValue, .y: PNormalValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
3323 { .x: PSmallestValue, .y: MNormalValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
3324 { .x: PSmallestValue, .y: PLargestValue, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3325 { .x: PSmallestValue, .y: MLargestValue, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3326 { .x: PSmallestValue, .y: PSmallestValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3327 { .x: PSmallestValue, .y: MSmallestValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3328 { .x: PSmallestValue, .y: PSmallestNormalized, .result: "0x1p-23", .status: APFloat::opOK, .category: APFloat::fcNormal },
3329 { .x: PSmallestValue, .y: MSmallestNormalized, .result: "-0x1p-23", .status: APFloat::opOK, .category: APFloat::fcNormal },
3330 { .x: MSmallestValue, .y: PInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3331 { .x: MSmallestValue, .y: MInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3332 { .x: MSmallestValue, .y: PZero, .result: "-inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3333 { .x: MSmallestValue, .y: MZero, .result: "inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3334 { .x: MSmallestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3335 { .x: MSmallestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3336 { .x: MSmallestValue, .y: PNormalValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
3337 { .x: MSmallestValue, .y: MNormalValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
3338 { .x: MSmallestValue, .y: PLargestValue, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3339 { .x: MSmallestValue, .y: MLargestValue, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3340 { .x: MSmallestValue, .y: PSmallestValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3341 { .x: MSmallestValue, .y: MSmallestValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3342 { .x: MSmallestValue, .y: PSmallestNormalized, .result: "-0x1p-23", .status: APFloat::opOK, .category: APFloat::fcNormal },
3343 { .x: MSmallestValue, .y: MSmallestNormalized, .result: "0x1p-23", .status: APFloat::opOK, .category: APFloat::fcNormal },
3344 { .x: PSmallestNormalized, .y: PInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3345 { .x: PSmallestNormalized, .y: MInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3346 { .x: PSmallestNormalized, .y: PZero, .result: "inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3347 { .x: PSmallestNormalized, .y: MZero, .result: "-inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3348 { .x: PSmallestNormalized, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3349 { .x: PSmallestNormalized, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3350 { .x: PSmallestNormalized, .y: PNormalValue, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3351 { .x: PSmallestNormalized, .y: MNormalValue, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3352 { .x: PSmallestNormalized, .y: PLargestValue, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3353 { .x: PSmallestNormalized, .y: MLargestValue, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3354 { .x: PSmallestNormalized, .y: PSmallestValue, .result: "0x1p+23", .status: APFloat::opOK, .category: APFloat::fcNormal },
3355 { .x: PSmallestNormalized, .y: MSmallestValue, .result: "-0x1p+23", .status: APFloat::opOK, .category: APFloat::fcNormal },
3356 { .x: PSmallestNormalized, .y: PSmallestNormalized, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3357 { .x: PSmallestNormalized, .y: MSmallestNormalized, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3358 { .x: MSmallestNormalized, .y: PInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3359 { .x: MSmallestNormalized, .y: MInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
3360 { .x: MSmallestNormalized, .y: PZero, .result: "-inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3361 { .x: MSmallestNormalized, .y: MZero, .result: "inf", .status: APFloat::opDivByZero, .category: APFloat::fcInfinity },
3362 { .x: MSmallestNormalized, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
3363 { .x: MSmallestNormalized, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
3364 { .x: MSmallestNormalized, .y: PNormalValue, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3365 { .x: MSmallestNormalized, .y: MNormalValue, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
3366 { .x: MSmallestNormalized, .y: PLargestValue, .result: "-0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3367 { .x: MSmallestNormalized, .y: MLargestValue, .result: "0x0p+0", .status: UnderflowStatus, .category: APFloat::fcZero },
3368 { .x: MSmallestNormalized, .y: PSmallestValue, .result: "-0x1p+23", .status: APFloat::opOK, .category: APFloat::fcNormal },
3369 { .x: MSmallestNormalized, .y: MSmallestValue, .result: "0x1p+23", .status: APFloat::opOK, .category: APFloat::fcNormal },
3370 { .x: MSmallestNormalized, .y: PSmallestNormalized, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3371 { .x: MSmallestNormalized, .y: MSmallestNormalized, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
3372
3373 {.x: MaxQuad, .y: NMinQuad, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity,
3374 .roundingMode: APFloat::rmNearestTiesToEven},
3375 {.x: MaxQuad, .y: NMinQuad, .result: "-0x1.ffffffffffffffffffffffffffffp+16383",
3376 .status: APFloat::opInexact, .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardPositive},
3377 {.x: MaxQuad, .y: NMinQuad, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity,
3378 .roundingMode: APFloat::rmTowardNegative},
3379 {.x: MaxQuad, .y: NMinQuad, .result: "-0x1.ffffffffffffffffffffffffffffp+16383",
3380 .status: APFloat::opInexact, .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardZero},
3381 {.x: MaxQuad, .y: NMinQuad, .result: "-inf", .status: OverflowStatus, .category: APFloat::fcInfinity,
3382 .roundingMode: APFloat::rmNearestTiesToAway},
3383
3384 {.x: MinQuad, .y: MaxQuad, .result: "0", .status: UnderflowStatus, .category: APFloat::fcZero,
3385 .roundingMode: APFloat::rmNearestTiesToEven},
3386 {.x: MinQuad, .y: MaxQuad, .result: "0x0.0000000000000000000000000001p-16382",
3387 .status: UnderflowStatus, .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardPositive},
3388 {.x: MinQuad, .y: MaxQuad, .result: "0", .status: UnderflowStatus, .category: APFloat::fcZero,
3389 .roundingMode: APFloat::rmTowardNegative},
3390 {.x: MinQuad, .y: MaxQuad, .result: "0", .status: UnderflowStatus, .category: APFloat::fcZero,
3391 .roundingMode: APFloat::rmTowardZero},
3392 {.x: MinQuad, .y: MaxQuad, .result: "0", .status: UnderflowStatus, .category: APFloat::fcZero,
3393 .roundingMode: APFloat::rmNearestTiesToAway},
3394
3395 {.x: NMinQuad, .y: MaxQuad, .result: "-0", .status: UnderflowStatus, .category: APFloat::fcZero,
3396 .roundingMode: APFloat::rmNearestTiesToEven},
3397 {.x: NMinQuad, .y: MaxQuad, .result: "-0", .status: UnderflowStatus, .category: APFloat::fcZero,
3398 .roundingMode: APFloat::rmTowardPositive},
3399 {.x: NMinQuad, .y: MaxQuad, .result: "-0x0.0000000000000000000000000001p-16382",
3400 .status: UnderflowStatus, .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardNegative},
3401 {.x: NMinQuad, .y: MaxQuad, .result: "-0", .status: UnderflowStatus, .category: APFloat::fcZero,
3402 .roundingMode: APFloat::rmTowardZero},
3403 {.x: NMinQuad, .y: MaxQuad, .result: "-0", .status: UnderflowStatus, .category: APFloat::fcZero,
3404 .roundingMode: APFloat::rmNearestTiesToAway},
3405 };
3406
3407 for (size_t i = 0; i < std::size(SpecialCaseTests); ++i) {
3408 APFloat x(SpecialCaseTests[i].x);
3409 APFloat y(SpecialCaseTests[i].y);
3410 APFloat::opStatus status = x.divide(RHS: y, RM: SpecialCaseTests[i].roundingMode);
3411
3412 APFloat result(x.getSemantics(), SpecialCaseTests[i].result);
3413
3414 EXPECT_TRUE(result.bitwiseIsEqual(x));
3415 EXPECT_EQ(SpecialCaseTests[i].status, (int)status);
3416 EXPECT_EQ(SpecialCaseTests[i].category, (int)x.getCategory());
3417 }
3418}
3419
3420TEST(APFloatTest, operatorOverloads) {
3421 // This is mostly testing that these operator overloads compile.
3422 APFloat One = APFloat(APFloat::IEEEsingle(), "0x1p+0");
3423 APFloat Two = APFloat(APFloat::IEEEsingle(), "0x2p+0");
3424 EXPECT_TRUE(Two.bitwiseIsEqual(One + One));
3425 EXPECT_TRUE(One.bitwiseIsEqual(Two - One));
3426 EXPECT_TRUE(Two.bitwiseIsEqual(One * Two));
3427 EXPECT_TRUE(One.bitwiseIsEqual(Two / Two));
3428}
3429
3430TEST(APFloatTest, Comparisons) {
3431 enum {MNan, MInf, MBig, MOne, MZer, PZer, POne, PBig, PInf, PNan, NumVals};
3432 APFloat Vals[NumVals] = {
3433 APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: true),
3434 APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true),
3435 APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: true),
3436 APFloat(APFloat::IEEEsingle(), "-0x1p+0"),
3437 APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: true),
3438 APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: false),
3439 APFloat(APFloat::IEEEsingle(), "0x1p+0"),
3440 APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: false),
3441 APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false),
3442 APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: false),
3443 };
3444 using Relation = void (*)(const APFloat &, const APFloat &);
3445 Relation LT = [](const APFloat &LHS, const APFloat &RHS) {
3446 EXPECT_FALSE(LHS == RHS);
3447 EXPECT_TRUE(LHS != RHS);
3448 EXPECT_TRUE(LHS < RHS);
3449 EXPECT_FALSE(LHS > RHS);
3450 EXPECT_TRUE(LHS <= RHS);
3451 EXPECT_FALSE(LHS >= RHS);
3452 };
3453 Relation EQ = [](const APFloat &LHS, const APFloat &RHS) {
3454 EXPECT_TRUE(LHS == RHS);
3455 EXPECT_FALSE(LHS != RHS);
3456 EXPECT_FALSE(LHS < RHS);
3457 EXPECT_FALSE(LHS > RHS);
3458 EXPECT_TRUE(LHS <= RHS);
3459 EXPECT_TRUE(LHS >= RHS);
3460 };
3461 Relation GT = [](const APFloat &LHS, const APFloat &RHS) {
3462 EXPECT_FALSE(LHS == RHS);
3463 EXPECT_TRUE(LHS != RHS);
3464 EXPECT_FALSE(LHS < RHS);
3465 EXPECT_TRUE(LHS > RHS);
3466 EXPECT_FALSE(LHS <= RHS);
3467 EXPECT_TRUE(LHS >= RHS);
3468 };
3469 Relation UN = [](const APFloat &LHS, const APFloat &RHS) {
3470 EXPECT_FALSE(LHS == RHS);
3471 EXPECT_TRUE(LHS != RHS);
3472 EXPECT_FALSE(LHS < RHS);
3473 EXPECT_FALSE(LHS > RHS);
3474 EXPECT_FALSE(LHS <= RHS);
3475 EXPECT_FALSE(LHS >= RHS);
3476 };
3477 Relation Relations[NumVals][NumVals] = {
3478 // -N -I -B -1 -0 +0 +1 +B +I +N
3479 /* MNan */ {UN, UN, UN, UN, UN, UN, UN, UN, UN, UN},
3480 /* MInf */ {UN, EQ, LT, LT, LT, LT, LT, LT, LT, UN},
3481 /* MBig */ {UN, GT, EQ, LT, LT, LT, LT, LT, LT, UN},
3482 /* MOne */ {UN, GT, GT, EQ, LT, LT, LT, LT, LT, UN},
3483 /* MZer */ {UN, GT, GT, GT, EQ, EQ, LT, LT, LT, UN},
3484 /* PZer */ {UN, GT, GT, GT, EQ, EQ, LT, LT, LT, UN},
3485 /* POne */ {UN, GT, GT, GT, GT, GT, EQ, LT, LT, UN},
3486 /* PBig */ {UN, GT, GT, GT, GT, GT, GT, EQ, LT, UN},
3487 /* PInf */ {UN, GT, GT, GT, GT, GT, GT, GT, EQ, UN},
3488 /* PNan */ {UN, UN, UN, UN, UN, UN, UN, UN, UN, UN},
3489 };
3490 for (unsigned I = 0; I < NumVals; ++I)
3491 for (unsigned J = 0; J < NumVals; ++J)
3492 Relations[I][J](Vals[I], Vals[J]);
3493}
3494
3495TEST(APFloatTest, abs) {
3496 APFloat PInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false);
3497 APFloat MInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
3498 APFloat PZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: false);
3499 APFloat MZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: true);
3500 APFloat PQNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: false);
3501 APFloat MQNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: true);
3502 APFloat PSNaN = APFloat::getSNaN(Sem: APFloat::IEEEsingle(), Negative: false);
3503 APFloat MSNaN = APFloat::getSNaN(Sem: APFloat::IEEEsingle(), Negative: true);
3504 APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
3505 APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
3506 APFloat PLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: false);
3507 APFloat MLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: true);
3508 APFloat PSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: false);
3509 APFloat MSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: true);
3510 APFloat PSmallestNormalized =
3511 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: false);
3512 APFloat MSmallestNormalized =
3513 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: true);
3514
3515 EXPECT_TRUE(PInf.bitwiseIsEqual(abs(PInf)));
3516 EXPECT_TRUE(PInf.bitwiseIsEqual(abs(MInf)));
3517 EXPECT_TRUE(PZero.bitwiseIsEqual(abs(PZero)));
3518 EXPECT_TRUE(PZero.bitwiseIsEqual(abs(MZero)));
3519 EXPECT_TRUE(PQNaN.bitwiseIsEqual(abs(PQNaN)));
3520 EXPECT_TRUE(PQNaN.bitwiseIsEqual(abs(MQNaN)));
3521 EXPECT_TRUE(PSNaN.bitwiseIsEqual(abs(PSNaN)));
3522 EXPECT_TRUE(PSNaN.bitwiseIsEqual(abs(MSNaN)));
3523 EXPECT_TRUE(PNormalValue.bitwiseIsEqual(abs(PNormalValue)));
3524 EXPECT_TRUE(PNormalValue.bitwiseIsEqual(abs(MNormalValue)));
3525 EXPECT_TRUE(PLargestValue.bitwiseIsEqual(abs(PLargestValue)));
3526 EXPECT_TRUE(PLargestValue.bitwiseIsEqual(abs(MLargestValue)));
3527 EXPECT_TRUE(PSmallestValue.bitwiseIsEqual(abs(PSmallestValue)));
3528 EXPECT_TRUE(PSmallestValue.bitwiseIsEqual(abs(MSmallestValue)));
3529 EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(PSmallestNormalized)));
3530 EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(MSmallestNormalized)));
3531}
3532
3533TEST(APFloatTest, neg) {
3534 APFloat One = APFloat(APFloat::IEEEsingle(), "1.0");
3535 APFloat NegOne = APFloat(APFloat::IEEEsingle(), "-1.0");
3536 APFloat Zero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: false);
3537 APFloat NegZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: true);
3538 APFloat Inf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false);
3539 APFloat NegInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
3540 APFloat QNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: false);
3541 APFloat NegQNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: true);
3542
3543 EXPECT_TRUE(NegOne.bitwiseIsEqual(neg(One)));
3544 EXPECT_TRUE(One.bitwiseIsEqual(neg(NegOne)));
3545 EXPECT_TRUE(NegZero.bitwiseIsEqual(neg(Zero)));
3546 EXPECT_TRUE(Zero.bitwiseIsEqual(neg(NegZero)));
3547 EXPECT_TRUE(NegInf.bitwiseIsEqual(neg(Inf)));
3548 EXPECT_TRUE(Inf.bitwiseIsEqual(neg(NegInf)));
3549 EXPECT_TRUE(NegInf.bitwiseIsEqual(neg(Inf)));
3550 EXPECT_TRUE(Inf.bitwiseIsEqual(neg(NegInf)));
3551 EXPECT_TRUE(NegQNaN.bitwiseIsEqual(neg(QNaN)));
3552 EXPECT_TRUE(QNaN.bitwiseIsEqual(neg(NegQNaN)));
3553
3554 EXPECT_TRUE(NegOne.bitwiseIsEqual(-One));
3555 EXPECT_TRUE(One.bitwiseIsEqual(-NegOne));
3556 EXPECT_TRUE(NegZero.bitwiseIsEqual(-Zero));
3557 EXPECT_TRUE(Zero.bitwiseIsEqual(-NegZero));
3558 EXPECT_TRUE(NegInf.bitwiseIsEqual(-Inf));
3559 EXPECT_TRUE(Inf.bitwiseIsEqual(-NegInf));
3560 EXPECT_TRUE(NegInf.bitwiseIsEqual(-Inf));
3561 EXPECT_TRUE(Inf.bitwiseIsEqual(-NegInf));
3562 EXPECT_TRUE(NegQNaN.bitwiseIsEqual(-QNaN));
3563 EXPECT_TRUE(QNaN.bitwiseIsEqual(-NegQNaN));
3564}
3565
3566TEST(APFloatTest, ilogb) {
3567 EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), false)));
3568 EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), true)));
3569 EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1024")));
3570 EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1023")));
3571 EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "-0x1.ffffffffffffep-1023")));
3572 EXPECT_EQ(-51, ilogb(APFloat(APFloat::IEEEdouble(), "0x1p-51")));
3573 EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1023")));
3574 EXPECT_EQ(-2, ilogb(APFloat(APFloat::IEEEdouble(), "0x0.ffffp-1")));
3575 EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.fffep-1023")));
3576 EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble(), false)));
3577 EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble(), true)));
3578
3579
3580 EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+0")));
3581 EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle(), "-0x1p+0")));
3582 EXPECT_EQ(42, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+42")));
3583 EXPECT_EQ(-42, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p-42")));
3584
3585 EXPECT_EQ(APFloat::IEK_Inf,
3586 ilogb(APFloat::getInf(APFloat::IEEEsingle(), false)));
3587 EXPECT_EQ(APFloat::IEK_Inf,
3588 ilogb(APFloat::getInf(APFloat::IEEEsingle(), true)));
3589 EXPECT_EQ(APFloat::IEK_Zero,
3590 ilogb(APFloat::getZero(APFloat::IEEEsingle(), false)));
3591 EXPECT_EQ(APFloat::IEK_Zero,
3592 ilogb(APFloat::getZero(APFloat::IEEEsingle(), true)));
3593 EXPECT_EQ(APFloat::IEK_NaN,
3594 ilogb(APFloat::getNaN(APFloat::IEEEsingle(), false)));
3595 EXPECT_EQ(APFloat::IEK_NaN,
3596 ilogb(APFloat::getSNaN(APFloat::IEEEsingle(), false)));
3597
3598 EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle(), false)));
3599 EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle(), true)));
3600
3601 EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle(), false)));
3602 EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle(), true)));
3603 EXPECT_EQ(-126,
3604 ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false)));
3605 EXPECT_EQ(-126,
3606 ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true)));
3607}
3608
3609TEST(APFloatTest, scalbn) {
3610
3611 const APFloat::roundingMode RM = APFloat::rmNearestTiesToEven;
3612 EXPECT_TRUE(
3613 APFloat(APFloat::IEEEsingle(), "0x1p+0")
3614 .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle(), "0x1p+0"), 0, RM)));
3615 EXPECT_TRUE(
3616 APFloat(APFloat::IEEEsingle(), "0x1p+42")
3617 .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle(), "0x1p+0"), 42, RM)));
3618 EXPECT_TRUE(
3619 APFloat(APFloat::IEEEsingle(), "0x1p-42")
3620 .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle(), "0x1p+0"), -42, RM)));
3621
3622 APFloat PInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false);
3623 APFloat MInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
3624 APFloat PZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: false);
3625 APFloat MZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: true);
3626 APFloat QPNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: false);
3627 APFloat QMNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: true);
3628 APFloat SNaN = APFloat::getSNaN(Sem: APFloat::IEEEsingle(), Negative: false);
3629
3630 EXPECT_TRUE(PInf.bitwiseIsEqual(scalbn(PInf, 0, RM)));
3631 EXPECT_TRUE(MInf.bitwiseIsEqual(scalbn(MInf, 0, RM)));
3632 EXPECT_TRUE(PZero.bitwiseIsEqual(scalbn(PZero, 0, RM)));
3633 EXPECT_TRUE(MZero.bitwiseIsEqual(scalbn(MZero, 0, RM)));
3634 EXPECT_TRUE(QPNaN.bitwiseIsEqual(scalbn(QPNaN, 0, RM)));
3635 EXPECT_TRUE(QMNaN.bitwiseIsEqual(scalbn(QMNaN, 0, RM)));
3636 EXPECT_FALSE(scalbn(SNaN, 0, RM).isSignaling());
3637
3638 APFloat ScalbnSNaN = scalbn(X: SNaN, Exp: 1, RM);
3639 EXPECT_TRUE(ScalbnSNaN.isNaN() && !ScalbnSNaN.isSignaling());
3640
3641 // Make sure highest bit of payload is preserved.
3642 const APInt Payload(64, (UINT64_C(1) << 50) |
3643 (UINT64_C(1) << 49) |
3644 (UINT64_C(1234) << 32) |
3645 1);
3646
3647 APFloat SNaNWithPayload = APFloat::getSNaN(Sem: APFloat::IEEEdouble(), Negative: false,
3648 payload: &Payload);
3649 APFloat QuietPayload = scalbn(X: SNaNWithPayload, Exp: 1, RM);
3650 EXPECT_TRUE(QuietPayload.isNaN() && !QuietPayload.isSignaling());
3651 EXPECT_EQ(Payload, QuietPayload.bitcastToAPInt().getLoBits(51));
3652
3653 EXPECT_TRUE(PInf.bitwiseIsEqual(
3654 scalbn(APFloat(APFloat::IEEEsingle(), "0x1p+0"), 128, RM)));
3655 EXPECT_TRUE(MInf.bitwiseIsEqual(
3656 scalbn(APFloat(APFloat::IEEEsingle(), "-0x1p+0"), 128, RM)));
3657 EXPECT_TRUE(PInf.bitwiseIsEqual(
3658 scalbn(APFloat(APFloat::IEEEsingle(), "0x1p+127"), 1, RM)));
3659 EXPECT_TRUE(PZero.bitwiseIsEqual(
3660 scalbn(APFloat(APFloat::IEEEsingle(), "0x1p-127"), -127, RM)));
3661 EXPECT_TRUE(MZero.bitwiseIsEqual(
3662 scalbn(APFloat(APFloat::IEEEsingle(), "-0x1p-127"), -127, RM)));
3663 EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "-0x1p-149").bitwiseIsEqual(
3664 scalbn(APFloat(APFloat::IEEEsingle(), "-0x1p-127"), -22, RM)));
3665 EXPECT_TRUE(PZero.bitwiseIsEqual(
3666 scalbn(APFloat(APFloat::IEEEsingle(), "0x1p-126"), -24, RM)));
3667
3668
3669 APFloat SmallestF64 = APFloat::getSmallest(Sem: APFloat::IEEEdouble(), Negative: false);
3670 APFloat NegSmallestF64 = APFloat::getSmallest(Sem: APFloat::IEEEdouble(), Negative: true);
3671
3672 APFloat LargestF64 = APFloat::getLargest(Sem: APFloat::IEEEdouble(), Negative: false);
3673 APFloat NegLargestF64 = APFloat::getLargest(Sem: APFloat::IEEEdouble(), Negative: true);
3674
3675 APFloat SmallestNormalizedF64
3676 = APFloat::getSmallestNormalized(Sem: APFloat::IEEEdouble(), Negative: false);
3677 APFloat NegSmallestNormalizedF64
3678 = APFloat::getSmallestNormalized(Sem: APFloat::IEEEdouble(), Negative: true);
3679
3680 APFloat LargestDenormalF64(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1023");
3681 APFloat NegLargestDenormalF64(APFloat::IEEEdouble(), "-0x1.ffffffffffffep-1023");
3682
3683
3684 EXPECT_TRUE(SmallestF64.bitwiseIsEqual(
3685 scalbn(APFloat(APFloat::IEEEdouble(), "0x1p-1074"), 0, RM)));
3686 EXPECT_TRUE(NegSmallestF64.bitwiseIsEqual(
3687 scalbn(APFloat(APFloat::IEEEdouble(), "-0x1p-1074"), 0, RM)));
3688
3689 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p+1023")
3690 .bitwiseIsEqual(scalbn(SmallestF64, 2097, RM)));
3691
3692 EXPECT_TRUE(scalbn(SmallestF64, -2097, RM).isPosZero());
3693 EXPECT_TRUE(scalbn(SmallestF64, -2098, RM).isPosZero());
3694 EXPECT_TRUE(scalbn(SmallestF64, -2099, RM).isPosZero());
3695 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p+1022")
3696 .bitwiseIsEqual(scalbn(SmallestF64, 2096, RM)));
3697 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p+1023")
3698 .bitwiseIsEqual(scalbn(SmallestF64, 2097, RM)));
3699 EXPECT_TRUE(scalbn(SmallestF64, 2098, RM).isInfinity());
3700 EXPECT_TRUE(scalbn(SmallestF64, 2099, RM).isInfinity());
3701
3702 // Test for integer overflows when adding to exponent.
3703 EXPECT_TRUE(scalbn(SmallestF64, -INT_MAX, RM).isPosZero());
3704 EXPECT_TRUE(scalbn(LargestF64, INT_MAX, RM).isInfinity());
3705
3706 EXPECT_TRUE(LargestDenormalF64
3707 .bitwiseIsEqual(scalbn(LargestDenormalF64, 0, RM)));
3708 EXPECT_TRUE(NegLargestDenormalF64
3709 .bitwiseIsEqual(scalbn(NegLargestDenormalF64, 0, RM)));
3710
3711 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1022")
3712 .bitwiseIsEqual(scalbn(LargestDenormalF64, 1, RM)));
3713 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1.ffffffffffffep-1021")
3714 .bitwiseIsEqual(scalbn(NegLargestDenormalF64, 2, RM)));
3715
3716 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep+1")
3717 .bitwiseIsEqual(scalbn(LargestDenormalF64, 1024, RM)));
3718 EXPECT_TRUE(scalbn(LargestDenormalF64, -1023, RM).isPosZero());
3719 EXPECT_TRUE(scalbn(LargestDenormalF64, -1024, RM).isPosZero());
3720 EXPECT_TRUE(scalbn(LargestDenormalF64, -2048, RM).isPosZero());
3721 EXPECT_TRUE(scalbn(LargestDenormalF64, 2047, RM).isInfinity());
3722 EXPECT_TRUE(scalbn(LargestDenormalF64, 2098, RM).isInfinity());
3723 EXPECT_TRUE(scalbn(LargestDenormalF64, 2099, RM).isInfinity());
3724
3725 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-2")
3726 .bitwiseIsEqual(scalbn(LargestDenormalF64, 1021, RM)));
3727 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1")
3728 .bitwiseIsEqual(scalbn(LargestDenormalF64, 1022, RM)));
3729 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep+0")
3730 .bitwiseIsEqual(scalbn(LargestDenormalF64, 1023, RM)));
3731 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep+1023")
3732 .bitwiseIsEqual(scalbn(LargestDenormalF64, 2046, RM)));
3733 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p+974")
3734 .bitwiseIsEqual(scalbn(SmallestF64, 2048, RM)));
3735
3736 APFloat RandomDenormalF64(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp+51");
3737 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-972")
3738 .bitwiseIsEqual(scalbn(RandomDenormalF64, -1023, RM)));
3739 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1")
3740 .bitwiseIsEqual(scalbn(RandomDenormalF64, -52, RM)));
3741 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-2")
3742 .bitwiseIsEqual(scalbn(RandomDenormalF64, -53, RM)));
3743 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp+0")
3744 .bitwiseIsEqual(scalbn(RandomDenormalF64, -51, RM)));
3745
3746 EXPECT_TRUE(scalbn(RandomDenormalF64, -2097, RM).isPosZero());
3747 EXPECT_TRUE(scalbn(RandomDenormalF64, -2090, RM).isPosZero());
3748
3749
3750 EXPECT_TRUE(
3751 APFloat(APFloat::IEEEdouble(), "-0x1p-1073")
3752 .bitwiseIsEqual(scalbn(NegLargestF64, -2097, RM)));
3753
3754 EXPECT_TRUE(
3755 APFloat(APFloat::IEEEdouble(), "-0x1p-1024")
3756 .bitwiseIsEqual(scalbn(NegLargestF64, -2048, RM)));
3757
3758 EXPECT_TRUE(
3759 APFloat(APFloat::IEEEdouble(), "0x1p-1073")
3760 .bitwiseIsEqual(scalbn(LargestF64, -2097, RM)));
3761
3762 EXPECT_TRUE(
3763 APFloat(APFloat::IEEEdouble(), "0x1p-1074")
3764 .bitwiseIsEqual(scalbn(LargestF64, -2098, RM)));
3765 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1p-1074")
3766 .bitwiseIsEqual(scalbn(NegLargestF64, -2098, RM)));
3767 EXPECT_TRUE(scalbn(NegLargestF64, -2099, RM).isNegZero());
3768 EXPECT_TRUE(scalbn(LargestF64, 1, RM).isInfinity());
3769
3770
3771 EXPECT_TRUE(
3772 APFloat(APFloat::IEEEdouble(), "0x1p+0")
3773 .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEdouble(), "0x1p+52"), -52, RM)));
3774
3775 EXPECT_TRUE(
3776 APFloat(APFloat::IEEEdouble(), "0x1p-103")
3777 .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEdouble(), "0x1p-51"), -52, RM)));
3778}
3779
3780TEST(APFloatTest, frexp) {
3781 const APFloat::roundingMode RM = APFloat::rmNearestTiesToEven;
3782
3783 APFloat PZero = APFloat::getZero(Sem: APFloat::IEEEdouble(), Negative: false);
3784 APFloat MZero = APFloat::getZero(Sem: APFloat::IEEEdouble(), Negative: true);
3785 APFloat One(1.0);
3786 APFloat MOne(-1.0);
3787 APFloat Two(2.0);
3788 APFloat MTwo(-2.0);
3789
3790 APFloat LargestDenormal(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1023");
3791 APFloat NegLargestDenormal(APFloat::IEEEdouble(), "-0x1.ffffffffffffep-1023");
3792
3793 APFloat Smallest = APFloat::getSmallest(Sem: APFloat::IEEEdouble(), Negative: false);
3794 APFloat NegSmallest = APFloat::getSmallest(Sem: APFloat::IEEEdouble(), Negative: true);
3795
3796 APFloat Largest = APFloat::getLargest(Sem: APFloat::IEEEdouble(), Negative: false);
3797 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::IEEEdouble(), Negative: true);
3798
3799 APFloat PInf = APFloat::getInf(Sem: APFloat::IEEEdouble(), Negative: false);
3800 APFloat MInf = APFloat::getInf(Sem: APFloat::IEEEdouble(), Negative: true);
3801
3802 APFloat QPNaN = APFloat::getNaN(Sem: APFloat::IEEEdouble(), Negative: false);
3803 APFloat QMNaN = APFloat::getNaN(Sem: APFloat::IEEEdouble(), Negative: true);
3804 APFloat SNaN = APFloat::getSNaN(Sem: APFloat::IEEEdouble(), Negative: false);
3805
3806 // Make sure highest bit of payload is preserved.
3807 const APInt Payload(64, (UINT64_C(1) << 50) |
3808 (UINT64_C(1) << 49) |
3809 (UINT64_C(1234) << 32) |
3810 1);
3811
3812 APFloat SNaNWithPayload = APFloat::getSNaN(Sem: APFloat::IEEEdouble(), Negative: false,
3813 payload: &Payload);
3814
3815 APFloat SmallestNormalized
3816 = APFloat::getSmallestNormalized(Sem: APFloat::IEEEdouble(), Negative: false);
3817 APFloat NegSmallestNormalized
3818 = APFloat::getSmallestNormalized(Sem: APFloat::IEEEdouble(), Negative: true);
3819
3820 int Exp;
3821 APFloat Frac(APFloat::IEEEdouble());
3822
3823
3824 Frac = frexp(X: PZero, Exp, RM);
3825 EXPECT_EQ(0, Exp);
3826 EXPECT_TRUE(Frac.isPosZero());
3827
3828 Frac = frexp(X: MZero, Exp, RM);
3829 EXPECT_EQ(0, Exp);
3830 EXPECT_TRUE(Frac.isNegZero());
3831
3832
3833 Frac = frexp(X: One, Exp, RM);
3834 EXPECT_EQ(1, Exp);
3835 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p-1").bitwiseIsEqual(Frac));
3836
3837 Frac = frexp(X: MOne, Exp, RM);
3838 EXPECT_EQ(1, Exp);
3839 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1p-1").bitwiseIsEqual(Frac));
3840
3841 Frac = frexp(X: LargestDenormal, Exp, RM);
3842 EXPECT_EQ(-1022, Exp);
3843 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1").bitwiseIsEqual(Frac));
3844
3845 Frac = frexp(X: NegLargestDenormal, Exp, RM);
3846 EXPECT_EQ(-1022, Exp);
3847 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1.ffffffffffffep-1").bitwiseIsEqual(Frac));
3848
3849
3850 Frac = frexp(X: Smallest, Exp, RM);
3851 EXPECT_EQ(-1073, Exp);
3852 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p-1").bitwiseIsEqual(Frac));
3853
3854 Frac = frexp(X: NegSmallest, Exp, RM);
3855 EXPECT_EQ(-1073, Exp);
3856 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1p-1").bitwiseIsEqual(Frac));
3857
3858
3859 Frac = frexp(X: Largest, Exp, RM);
3860 EXPECT_EQ(1024, Exp);
3861 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.fffffffffffffp-1").bitwiseIsEqual(Frac));
3862
3863 Frac = frexp(X: NegLargest, Exp, RM);
3864 EXPECT_EQ(1024, Exp);
3865 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1.fffffffffffffp-1").bitwiseIsEqual(Frac));
3866
3867
3868 Frac = frexp(X: PInf, Exp, RM);
3869 EXPECT_EQ(INT_MAX, Exp);
3870 EXPECT_TRUE(Frac.isInfinity() && !Frac.isNegative());
3871
3872 Frac = frexp(X: MInf, Exp, RM);
3873 EXPECT_EQ(INT_MAX, Exp);
3874 EXPECT_TRUE(Frac.isInfinity() && Frac.isNegative());
3875
3876 Frac = frexp(X: QPNaN, Exp, RM);
3877 EXPECT_EQ(INT_MIN, Exp);
3878 EXPECT_TRUE(Frac.isNaN());
3879
3880 Frac = frexp(X: QMNaN, Exp, RM);
3881 EXPECT_EQ(INT_MIN, Exp);
3882 EXPECT_TRUE(Frac.isNaN());
3883
3884 Frac = frexp(X: SNaN, Exp, RM);
3885 EXPECT_EQ(INT_MIN, Exp);
3886 EXPECT_TRUE(Frac.isNaN() && !Frac.isSignaling());
3887
3888 Frac = frexp(X: SNaNWithPayload, Exp, RM);
3889 EXPECT_EQ(INT_MIN, Exp);
3890 EXPECT_TRUE(Frac.isNaN() && !Frac.isSignaling());
3891 EXPECT_EQ(Payload, Frac.bitcastToAPInt().getLoBits(51));
3892
3893 Frac = frexp(X: APFloat(APFloat::IEEEdouble(), "0x0.ffffp-1"), Exp, RM);
3894 EXPECT_EQ(-1, Exp);
3895 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.fffep-1").bitwiseIsEqual(Frac));
3896
3897 Frac = frexp(X: APFloat(APFloat::IEEEdouble(), "0x1p-51"), Exp, RM);
3898 EXPECT_EQ(-50, Exp);
3899 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p-1").bitwiseIsEqual(Frac));
3900
3901 Frac = frexp(X: APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp+51"), Exp, RM);
3902 EXPECT_EQ(52, Exp);
3903 EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1").bitwiseIsEqual(Frac));
3904}
3905
3906TEST(APFloatTest, mod) {
3907 {
3908 APFloat f1(APFloat::IEEEdouble(), "1.5");
3909 APFloat f2(APFloat::IEEEdouble(), "1.0");
3910 APFloat expected(APFloat::IEEEdouble(), "0.5");
3911 EXPECT_EQ(f1.mod(f2), APFloat::opOK);
3912 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
3913 }
3914 {
3915 APFloat f1(APFloat::IEEEdouble(), "0.5");
3916 APFloat f2(APFloat::IEEEdouble(), "1.0");
3917 APFloat expected(APFloat::IEEEdouble(), "0.5");
3918 EXPECT_EQ(f1.mod(f2), APFloat::opOK);
3919 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
3920 }
3921 {
3922 APFloat f1(APFloat::IEEEdouble(), "0x1.3333333333333p-2"); // 0.3
3923 APFloat f2(APFloat::IEEEdouble(), "0x1.47ae147ae147bp-7"); // 0.01
3924 APFloat expected(APFloat::IEEEdouble(),
3925 "0x1.47ae147ae1471p-7"); // 0.009999999999999983
3926 EXPECT_EQ(f1.mod(f2), APFloat::opOK);
3927 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
3928 }
3929 {
3930 APFloat f1(APFloat::IEEEdouble(), "0x1p64"); // 1.8446744073709552e19
3931 APFloat f2(APFloat::IEEEdouble(), "1.5");
3932 APFloat expected(APFloat::IEEEdouble(), "1.0");
3933 EXPECT_EQ(f1.mod(f2), APFloat::opOK);
3934 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
3935 }
3936 {
3937 APFloat f1(APFloat::IEEEdouble(), "0x1p1000");
3938 APFloat f2(APFloat::IEEEdouble(), "0x1p-1000");
3939 APFloat expected(APFloat::IEEEdouble(), "0.0");
3940 EXPECT_EQ(f1.mod(f2), APFloat::opOK);
3941 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
3942 }
3943 {
3944 APFloat f1(APFloat::IEEEdouble(), "0.0");
3945 APFloat f2(APFloat::IEEEdouble(), "1.0");
3946 APFloat expected(APFloat::IEEEdouble(), "0.0");
3947 EXPECT_EQ(f1.mod(f2), APFloat::opOK);
3948 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
3949 }
3950 {
3951 APFloat f1(APFloat::IEEEdouble(), "1.0");
3952 APFloat f2(APFloat::IEEEdouble(), "0.0");
3953 EXPECT_EQ(f1.mod(f2), APFloat::opInvalidOp);
3954 EXPECT_TRUE(f1.isNaN());
3955 }
3956 {
3957 APFloat f1(APFloat::IEEEdouble(), "0.0");
3958 APFloat f2(APFloat::IEEEdouble(), "0.0");
3959 EXPECT_EQ(f1.mod(f2), APFloat::opInvalidOp);
3960 EXPECT_TRUE(f1.isNaN());
3961 }
3962 {
3963 APFloat f1 = APFloat::getInf(Sem: APFloat::IEEEdouble(), Negative: false);
3964 APFloat f2(APFloat::IEEEdouble(), "1.0");
3965 EXPECT_EQ(f1.mod(f2), APFloat::opInvalidOp);
3966 EXPECT_TRUE(f1.isNaN());
3967 }
3968 {
3969 APFloat f1(APFloat::IEEEdouble(), "-4.0");
3970 APFloat f2(APFloat::IEEEdouble(), "-2.0");
3971 APFloat expected(APFloat::IEEEdouble(), "-0.0");
3972 EXPECT_EQ(f1.mod(f2), APFloat::opOK);
3973 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
3974 }
3975 {
3976 APFloat f1(APFloat::IEEEdouble(), "-4.0");
3977 APFloat f2(APFloat::IEEEdouble(), "2.0");
3978 APFloat expected(APFloat::IEEEdouble(), "-0.0");
3979 EXPECT_EQ(f1.mod(f2), APFloat::opOK);
3980 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
3981 }
3982 {
3983 // Test E4M3FN mod where the LHS exponent is maxExponent (8) and the RHS is
3984 // the max value whose exponent is minExponent (-6). This requires special
3985 // logic in the mod implementation to prevent overflow to NaN.
3986 APFloat f1(APFloat::Float8E4M3FN(), "0x1p8"); // 256
3987 APFloat f2(APFloat::Float8E4M3FN(), "0x1.ep-6"); // 0.029296875
3988 APFloat expected(APFloat::Float8E4M3FN(), "0x1p-8"); // 0.00390625
3989 EXPECT_EQ(f1.mod(f2), APFloat::opOK);
3990 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
3991 }
3992}
3993
3994TEST(APFloatTest, remainder) {
3995 // Test Special Cases against each other and normal values.
3996
3997 APFloat PInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: false);
3998 APFloat MInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
3999 APFloat PZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: false);
4000 APFloat MZero = APFloat::getZero(Sem: APFloat::IEEEsingle(), Negative: true);
4001 APFloat QNaN = APFloat::getNaN(Sem: APFloat::IEEEsingle(), Negative: false);
4002 APFloat SNaN = APFloat(APFloat::IEEEsingle(), "snan123");
4003 APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
4004 APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
4005 APFloat PLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: false);
4006 APFloat MLargestValue = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: true);
4007 APFloat PSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: false);
4008 APFloat MSmallestValue = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: true);
4009 APFloat PSmallestNormalized =
4010 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: false);
4011 APFloat MSmallestNormalized =
4012 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: true);
4013
4014 APFloat PVal1(APFloat::IEEEsingle(), "0x1.fffffep+126");
4015 APFloat MVal1(APFloat::IEEEsingle(), "-0x1.fffffep+126");
4016 APFloat PVal2(APFloat::IEEEsingle(), "0x1.fffffep-126");
4017 APFloat MVal2(APFloat::IEEEsingle(), "-0x1.fffffep-126");
4018 APFloat PVal3(APFloat::IEEEsingle(), "0x1p-125");
4019 APFloat MVal3(APFloat::IEEEsingle(), "-0x1p-125");
4020 APFloat PVal4(APFloat::IEEEsingle(), "0x1p+127");
4021 APFloat MVal4(APFloat::IEEEsingle(), "-0x1p+127");
4022 APFloat PVal5(APFloat::IEEEsingle(), "1.5");
4023 APFloat MVal5(APFloat::IEEEsingle(), "-1.5");
4024 APFloat PVal6(APFloat::IEEEsingle(), "1");
4025 APFloat MVal6(APFloat::IEEEsingle(), "-1");
4026
4027 struct {
4028 APFloat x;
4029 APFloat y;
4030 const char *result;
4031 int status;
4032 int category;
4033 } SpecialCaseTests[] = {
4034 { .x: PInf, .y: PInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4035 { .x: PInf, .y: MInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4036 { .x: PInf, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4037 { .x: PInf, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4038 { .x: PInf, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4039 { .x: PInf, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4040 { .x: PInf, .y: PNormalValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4041 { .x: PInf, .y: MNormalValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4042 { .x: PInf, .y: PLargestValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4043 { .x: PInf, .y: MLargestValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4044 { .x: PInf, .y: PSmallestValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4045 { .x: PInf, .y: MSmallestValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4046 { .x: PInf, .y: PSmallestNormalized, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4047 { .x: PInf, .y: MSmallestNormalized, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4048 { .x: MInf, .y: PInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4049 { .x: MInf, .y: MInf, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4050 { .x: MInf, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4051 { .x: MInf, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4052 { .x: MInf, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4053 { .x: MInf, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4054 { .x: MInf, .y: PNormalValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4055 { .x: MInf, .y: MNormalValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4056 { .x: MInf, .y: PLargestValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4057 { .x: MInf, .y: MLargestValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4058 { .x: MInf, .y: PSmallestValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4059 { .x: MInf, .y: MSmallestValue, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4060 { .x: MInf, .y: PSmallestNormalized, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4061 { .x: MInf, .y: MSmallestNormalized, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4062 { .x: PZero, .y: PInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4063 { .x: PZero, .y: MInf, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4064 { .x: PZero, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4065 { .x: PZero, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4066 { .x: PZero, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4067 { .x: PZero, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4068 { .x: PZero, .y: PNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4069 { .x: PZero, .y: MNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4070 { .x: PZero, .y: PLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4071 { .x: PZero, .y: MLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4072 { .x: PZero, .y: PSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4073 { .x: PZero, .y: MSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4074 { .x: PZero, .y: PSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4075 { .x: PZero, .y: MSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4076 { .x: MZero, .y: PInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4077 { .x: MZero, .y: MInf, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4078 { .x: MZero, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4079 { .x: MZero, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4080 { .x: MZero, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4081 { .x: MZero, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4082 { .x: MZero, .y: PNormalValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4083 { .x: MZero, .y: MNormalValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4084 { .x: MZero, .y: PLargestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4085 { .x: MZero, .y: MLargestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4086 { .x: MZero, .y: PSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4087 { .x: MZero, .y: MSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4088 { .x: MZero, .y: PSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4089 { .x: MZero, .y: MSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4090 { .x: QNaN, .y: PInf, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4091 { .x: QNaN, .y: MInf, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4092 { .x: QNaN, .y: PZero, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4093 { .x: QNaN, .y: MZero, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4094 { .x: QNaN, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4095 { .x: QNaN, .y: SNaN, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4096 { .x: QNaN, .y: PNormalValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4097 { .x: QNaN, .y: MNormalValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4098 { .x: QNaN, .y: PLargestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4099 { .x: QNaN, .y: MLargestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4100 { .x: QNaN, .y: PSmallestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4101 { .x: QNaN, .y: MSmallestValue, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4102 { .x: QNaN, .y: PSmallestNormalized, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4103 { .x: QNaN, .y: MSmallestNormalized, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4104 { .x: SNaN, .y: PInf, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4105 { .x: SNaN, .y: MInf, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4106 { .x: SNaN, .y: PZero, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4107 { .x: SNaN, .y: MZero, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4108 { .x: SNaN, .y: QNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4109 { .x: SNaN, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4110 { .x: SNaN, .y: PNormalValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4111 { .x: SNaN, .y: MNormalValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4112 { .x: SNaN, .y: PLargestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4113 { .x: SNaN, .y: MLargestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4114 { .x: SNaN, .y: PSmallestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4115 { .x: SNaN, .y: MSmallestValue, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4116 { .x: SNaN, .y: PSmallestNormalized, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4117 { .x: SNaN, .y: MSmallestNormalized, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4118 { .x: PNormalValue, .y: PInf, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4119 { .x: PNormalValue, .y: MInf, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4120 { .x: PNormalValue, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4121 { .x: PNormalValue, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4122 { .x: PNormalValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4123 { .x: PNormalValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4124 { .x: PNormalValue, .y: PNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4125 { .x: PNormalValue, .y: MNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4126 { .x: PNormalValue, .y: PLargestValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4127 { .x: PNormalValue, .y: MLargestValue, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4128 { .x: PNormalValue, .y: PSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4129 { .x: PNormalValue, .y: MSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4130 { .x: PNormalValue, .y: PSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4131 { .x: PNormalValue, .y: MSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4132 { .x: MNormalValue, .y: PInf, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4133 { .x: MNormalValue, .y: MInf, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4134 { .x: MNormalValue, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4135 { .x: MNormalValue, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4136 { .x: MNormalValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4137 { .x: MNormalValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4138 { .x: MNormalValue, .y: PNormalValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4139 { .x: MNormalValue, .y: MNormalValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4140 { .x: MNormalValue, .y: PLargestValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4141 { .x: MNormalValue, .y: MLargestValue, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4142 { .x: MNormalValue, .y: PSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4143 { .x: MNormalValue, .y: MSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4144 { .x: MNormalValue, .y: PSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4145 { .x: MNormalValue, .y: MSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4146 { .x: PLargestValue, .y: PInf, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
4147 { .x: PLargestValue, .y: MInf, .result: "0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
4148 { .x: PLargestValue, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4149 { .x: PLargestValue, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4150 { .x: PLargestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4151 { .x: PLargestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4152 { .x: PLargestValue, .y: PNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4153 { .x: PLargestValue, .y: MNormalValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4154 { .x: PLargestValue, .y: PLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4155 { .x: PLargestValue, .y: MLargestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4156 { .x: PLargestValue, .y: PSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4157 { .x: PLargestValue, .y: MSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4158 { .x: PLargestValue, .y: PSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4159 { .x: PLargestValue, .y: MSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4160 { .x: MLargestValue, .y: PInf, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
4161 { .x: MLargestValue, .y: MInf, .result: "-0x1.fffffep+127", .status: APFloat::opOK, .category: APFloat::fcNormal },
4162 { .x: MLargestValue, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4163 { .x: MLargestValue, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4164 { .x: MLargestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4165 { .x: MLargestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4166 { .x: MLargestValue, .y: PNormalValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4167 { .x: MLargestValue, .y: MNormalValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4168 { .x: MLargestValue, .y: PLargestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4169 { .x: MLargestValue, .y: MLargestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4170 { .x: MLargestValue, .y: PSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4171 { .x: MLargestValue, .y: MSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4172 { .x: MLargestValue, .y: PSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4173 { .x: MLargestValue, .y: MSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4174 { .x: PSmallestValue, .y: PInf, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4175 { .x: PSmallestValue, .y: MInf, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4176 { .x: PSmallestValue, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4177 { .x: PSmallestValue, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4178 { .x: PSmallestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4179 { .x: PSmallestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4180 { .x: PSmallestValue, .y: PNormalValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4181 { .x: PSmallestValue, .y: MNormalValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4182 { .x: PSmallestValue, .y: PLargestValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4183 { .x: PSmallestValue, .y: MLargestValue, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4184 { .x: PSmallestValue, .y: PSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4185 { .x: PSmallestValue, .y: MSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4186 { .x: PSmallestValue, .y: PSmallestNormalized, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4187 { .x: PSmallestValue, .y: MSmallestNormalized, .result: "0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4188 { .x: MSmallestValue, .y: PInf, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4189 { .x: MSmallestValue, .y: MInf, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4190 { .x: MSmallestValue, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4191 { .x: MSmallestValue, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4192 { .x: MSmallestValue, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4193 { .x: MSmallestValue, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4194 { .x: MSmallestValue, .y: PNormalValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4195 { .x: MSmallestValue, .y: MNormalValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4196 { .x: MSmallestValue, .y: PLargestValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4197 { .x: MSmallestValue, .y: MLargestValue, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4198 { .x: MSmallestValue, .y: PSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4199 { .x: MSmallestValue, .y: MSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4200 { .x: MSmallestValue, .y: PSmallestNormalized, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4201 { .x: MSmallestValue, .y: MSmallestNormalized, .result: "-0x1p-149", .status: APFloat::opOK, .category: APFloat::fcNormal },
4202 { .x: PSmallestNormalized, .y: PInf, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4203 { .x: PSmallestNormalized, .y: MInf, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4204 { .x: PSmallestNormalized, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4205 { .x: PSmallestNormalized, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4206 { .x: PSmallestNormalized, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4207 { .x: PSmallestNormalized, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4208 { .x: PSmallestNormalized, .y: PNormalValue, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4209 { .x: PSmallestNormalized, .y: MNormalValue, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4210 { .x: PSmallestNormalized, .y: PLargestValue, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4211 { .x: PSmallestNormalized, .y: MLargestValue, .result: "0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4212 { .x: PSmallestNormalized, .y: PSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4213 { .x: PSmallestNormalized, .y: MSmallestValue, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4214 { .x: PSmallestNormalized, .y: PSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4215 { .x: PSmallestNormalized, .y: MSmallestNormalized, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4216 { .x: MSmallestNormalized, .y: PInf, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4217 { .x: MSmallestNormalized, .y: MInf, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4218 { .x: MSmallestNormalized, .y: PZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4219 { .x: MSmallestNormalized, .y: MZero, .result: "nan", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4220 { .x: MSmallestNormalized, .y: QNaN, .result: "nan", .status: APFloat::opOK, .category: APFloat::fcNaN },
4221 { .x: MSmallestNormalized, .y: SNaN, .result: "nan123", .status: APFloat::opInvalidOp, .category: APFloat::fcNaN },
4222 { .x: MSmallestNormalized, .y: PNormalValue, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4223 { .x: MSmallestNormalized, .y: MNormalValue, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4224 { .x: MSmallestNormalized, .y: PLargestValue, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4225 { .x: MSmallestNormalized, .y: MLargestValue, .result: "-0x1p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4226 { .x: MSmallestNormalized, .y: PSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4227 { .x: MSmallestNormalized, .y: MSmallestValue, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4228 { .x: MSmallestNormalized, .y: PSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4229 { .x: MSmallestNormalized, .y: MSmallestNormalized, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4230
4231 { .x: PVal1, .y: PVal1, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4232 { .x: PVal1, .y: MVal1, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4233 { .x: PVal1, .y: PVal2, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4234 { .x: PVal1, .y: MVal2, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4235 { .x: PVal1, .y: PVal3, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4236 { .x: PVal1, .y: MVal3, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4237 { .x: PVal1, .y: PVal4, .result: "-0x1p+103", .status: APFloat::opOK, .category: APFloat::fcNormal },
4238 { .x: PVal1, .y: MVal4, .result: "-0x1p+103", .status: APFloat::opOK, .category: APFloat::fcNormal },
4239 { .x: PVal1, .y: PVal5, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4240 { .x: PVal1, .y: MVal5, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4241 { .x: PVal1, .y: PVal6, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4242 { .x: PVal1, .y: MVal6, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4243 { .x: MVal1, .y: PVal1, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4244 { .x: MVal1, .y: MVal1, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4245 { .x: MVal1, .y: PVal2, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4246 { .x: MVal1, .y: MVal2, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4247 { .x: MVal1, .y: PVal3, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4248 { .x: MVal1, .y: MVal3, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4249 { .x: MVal1, .y: PVal4, .result: "0x1p+103", .status: APFloat::opOK, .category: APFloat::fcNormal },
4250 { .x: MVal1, .y: MVal4, .result: "0x1p+103", .status: APFloat::opOK, .category: APFloat::fcNormal },
4251 { .x: MVal1, .y: PVal5, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4252 { .x: MVal1, .y: MVal5, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4253 { .x: MVal1, .y: PVal6, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4254 { .x: MVal1, .y: MVal6, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4255 { .x: PVal2, .y: PVal1, .result: "0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4256 { .x: PVal2, .y: MVal1, .result: "0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4257 { .x: PVal2, .y: PVal2, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4258 { .x: PVal2, .y: MVal2, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4259 { .x: PVal2, .y: PVal3, .result: "-0x0.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4260 { .x: PVal2, .y: MVal3, .result: "-0x0.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4261 { .x: PVal2, .y: PVal4, .result: "0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4262 { .x: PVal2, .y: MVal4, .result: "0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4263 { .x: PVal2, .y: PVal5, .result: "0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4264 { .x: PVal2, .y: MVal5, .result: "0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4265 { .x: PVal2, .y: PVal6, .result: "0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4266 { .x: PVal2, .y: MVal6, .result: "0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4267 { .x: MVal2, .y: PVal1, .result: "-0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4268 { .x: MVal2, .y: MVal1, .result: "-0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4269 { .x: MVal2, .y: PVal2, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4270 { .x: MVal2, .y: MVal2, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4271 { .x: MVal2, .y: PVal3, .result: "0x0.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4272 { .x: MVal2, .y: MVal3, .result: "0x0.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4273 { .x: MVal2, .y: PVal4, .result: "-0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4274 { .x: MVal2, .y: MVal4, .result: "-0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4275 { .x: MVal2, .y: PVal5, .result: "-0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4276 { .x: MVal2, .y: MVal5, .result: "-0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4277 { .x: MVal2, .y: PVal6, .result: "-0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4278 { .x: MVal2, .y: MVal6, .result: "-0x1.fffffep-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4279 { .x: PVal3, .y: PVal1, .result: "0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4280 { .x: PVal3, .y: MVal1, .result: "0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4281 { .x: PVal3, .y: PVal2, .result: "0x0.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4282 { .x: PVal3, .y: MVal2, .result: "0x0.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4283 { .x: PVal3, .y: PVal3, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4284 { .x: PVal3, .y: MVal3, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4285 { .x: PVal3, .y: PVal4, .result: "0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4286 { .x: PVal3, .y: MVal4, .result: "0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4287 { .x: PVal3, .y: PVal5, .result: "0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4288 { .x: PVal3, .y: MVal5, .result: "0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4289 { .x: PVal3, .y: PVal6, .result: "0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4290 { .x: PVal3, .y: MVal6, .result: "0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4291 { .x: MVal3, .y: PVal1, .result: "-0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4292 { .x: MVal3, .y: MVal1, .result: "-0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4293 { .x: MVal3, .y: PVal2, .result: "-0x0.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4294 { .x: MVal3, .y: MVal2, .result: "-0x0.000002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4295 { .x: MVal3, .y: PVal3, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4296 { .x: MVal3, .y: MVal3, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4297 { .x: MVal3, .y: PVal4, .result: "-0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4298 { .x: MVal3, .y: MVal4, .result: "-0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4299 { .x: MVal3, .y: PVal5, .result: "-0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4300 { .x: MVal3, .y: MVal5, .result: "-0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4301 { .x: MVal3, .y: PVal6, .result: "-0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4302 { .x: MVal3, .y: MVal6, .result: "-0x1p-125", .status: APFloat::opOK, .category: APFloat::fcNormal },
4303 { .x: PVal4, .y: PVal1, .result: "0x1p+103", .status: APFloat::opOK, .category: APFloat::fcNormal },
4304 { .x: PVal4, .y: MVal1, .result: "0x1p+103", .status: APFloat::opOK, .category: APFloat::fcNormal },
4305 { .x: PVal4, .y: PVal2, .result: "0x0.002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4306 { .x: PVal4, .y: MVal2, .result: "0x0.002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4307 { .x: PVal4, .y: PVal3, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4308 { .x: PVal4, .y: MVal3, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4309 { .x: PVal4, .y: PVal4, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4310 { .x: PVal4, .y: MVal4, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4311 { .x: PVal4, .y: PVal5, .result: "0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4312 { .x: PVal4, .y: MVal5, .result: "0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4313 { .x: PVal4, .y: PVal6, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4314 { .x: PVal4, .y: MVal6, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4315 { .x: MVal4, .y: PVal1, .result: "-0x1p+103", .status: APFloat::opOK, .category: APFloat::fcNormal },
4316 { .x: MVal4, .y: MVal1, .result: "-0x1p+103", .status: APFloat::opOK, .category: APFloat::fcNormal },
4317 { .x: MVal4, .y: PVal2, .result: "-0x0.002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4318 { .x: MVal4, .y: MVal2, .result: "-0x0.002p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4319 { .x: MVal4, .y: PVal3, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4320 { .x: MVal4, .y: MVal3, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4321 { .x: MVal4, .y: PVal4, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4322 { .x: MVal4, .y: MVal4, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4323 { .x: MVal4, .y: PVal5, .result: "-0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4324 { .x: MVal4, .y: MVal5, .result: "-0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4325 { .x: MVal4, .y: PVal6, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4326 { .x: MVal4, .y: MVal6, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4327 { .x: PVal5, .y: PVal1, .result: "1.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4328 { .x: PVal5, .y: MVal1, .result: "1.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4329 { .x: PVal5, .y: PVal2, .result: "0x0.00006p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4330 { .x: PVal5, .y: MVal2, .result: "0x0.00006p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4331 { .x: PVal5, .y: PVal3, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4332 { .x: PVal5, .y: MVal3, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4333 { .x: PVal5, .y: PVal4, .result: "1.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4334 { .x: PVal5, .y: MVal4, .result: "1.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4335 { .x: PVal5, .y: PVal5, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4336 { .x: PVal5, .y: MVal5, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4337 { .x: PVal5, .y: PVal6, .result: "-0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4338 { .x: PVal5, .y: MVal6, .result: "-0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4339 { .x: MVal5, .y: PVal1, .result: "-1.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4340 { .x: MVal5, .y: MVal1, .result: "-1.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4341 { .x: MVal5, .y: PVal2, .result: "-0x0.00006p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4342 { .x: MVal5, .y: MVal2, .result: "-0x0.00006p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4343 { .x: MVal5, .y: PVal3, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4344 { .x: MVal5, .y: MVal3, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4345 { .x: MVal5, .y: PVal4, .result: "-1.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4346 { .x: MVal5, .y: MVal4, .result: "-1.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4347 { .x: MVal5, .y: PVal5, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4348 { .x: MVal5, .y: MVal5, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4349 { .x: MVal5, .y: PVal6, .result: "0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4350 { .x: MVal5, .y: MVal6, .result: "0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4351 { .x: PVal6, .y: PVal1, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4352 { .x: PVal6, .y: MVal1, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4353 { .x: PVal6, .y: PVal2, .result: "0x0.00004p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4354 { .x: PVal6, .y: MVal2, .result: "0x0.00004p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4355 { .x: PVal6, .y: PVal3, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4356 { .x: PVal6, .y: MVal3, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4357 { .x: PVal6, .y: PVal4, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4358 { .x: PVal6, .y: MVal4, .result: "0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4359 { .x: PVal6, .y: PVal5, .result: "-0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4360 { .x: PVal6, .y: MVal5, .result: "-0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4361 { .x: PVal6, .y: PVal6, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4362 { .x: PVal6, .y: MVal6, .result: "0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4363 { .x: MVal6, .y: PVal1, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4364 { .x: MVal6, .y: MVal1, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4365 { .x: MVal6, .y: PVal2, .result: "-0x0.00004p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4366 { .x: MVal6, .y: MVal2, .result: "-0x0.00004p-126", .status: APFloat::opOK, .category: APFloat::fcNormal },
4367 { .x: MVal6, .y: PVal3, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4368 { .x: MVal6, .y: MVal3, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4369 { .x: MVal6, .y: PVal4, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4370 { .x: MVal6, .y: MVal4, .result: "-0x1p+0", .status: APFloat::opOK, .category: APFloat::fcNormal },
4371 { .x: MVal6, .y: PVal5, .result: "0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4372 { .x: MVal6, .y: MVal5, .result: "0.5", .status: APFloat::opOK, .category: APFloat::fcNormal },
4373 { .x: MVal6, .y: PVal6, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4374 { .x: MVal6, .y: MVal6, .result: "-0x0p+0", .status: APFloat::opOK, .category: APFloat::fcZero },
4375 };
4376
4377 for (size_t i = 0; i < std::size(SpecialCaseTests); ++i) {
4378 APFloat x(SpecialCaseTests[i].x);
4379 APFloat y(SpecialCaseTests[i].y);
4380 APFloat::opStatus status = x.remainder(RHS: y);
4381
4382 APFloat result(x.getSemantics(), SpecialCaseTests[i].result);
4383
4384 EXPECT_TRUE(result.bitwiseIsEqual(x));
4385 EXPECT_EQ(SpecialCaseTests[i].status, (int)status);
4386 EXPECT_EQ(SpecialCaseTests[i].category, (int)x.getCategory());
4387 }
4388
4389 {
4390 APFloat f1(APFloat::IEEEdouble(), "0x1.3333333333333p-2"); // 0.3
4391 APFloat f2(APFloat::IEEEdouble(), "0x1.47ae147ae147bp-7"); // 0.01
4392 APFloat expected(APFloat::IEEEdouble(), "-0x1.4p-56");
4393 EXPECT_EQ(APFloat::opOK, f1.remainder(f2));
4394 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
4395 }
4396 {
4397 APFloat f1(APFloat::IEEEdouble(), "0x1p64"); // 1.8446744073709552e19
4398 APFloat f2(APFloat::IEEEdouble(), "1.5");
4399 APFloat expected(APFloat::IEEEdouble(), "-0.5");
4400 EXPECT_EQ(APFloat::opOK, f1.remainder(f2));
4401 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
4402 }
4403 {
4404 APFloat f1(APFloat::IEEEdouble(), "0x1p1000");
4405 APFloat f2(APFloat::IEEEdouble(), "0x1p-1000");
4406 APFloat expected(APFloat::IEEEdouble(), "0.0");
4407 EXPECT_EQ(APFloat::opOK, f1.remainder(f2));
4408 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
4409 }
4410 {
4411 APFloat f1 = APFloat::getInf(Sem: APFloat::IEEEdouble(), Negative: false);
4412 APFloat f2(APFloat::IEEEdouble(), "1.0");
4413 EXPECT_EQ(f1.remainder(f2), APFloat::opInvalidOp);
4414 EXPECT_TRUE(f1.isNaN());
4415 }
4416 {
4417 APFloat f1(APFloat::IEEEdouble(), "-4.0");
4418 APFloat f2(APFloat::IEEEdouble(), "-2.0");
4419 APFloat expected(APFloat::IEEEdouble(), "-0.0");
4420 EXPECT_EQ(APFloat::opOK, f1.remainder(f2));
4421 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
4422 }
4423 {
4424 APFloat f1(APFloat::IEEEdouble(), "-4.0");
4425 APFloat f2(APFloat::IEEEdouble(), "2.0");
4426 APFloat expected(APFloat::IEEEdouble(), "-0.0");
4427 EXPECT_EQ(APFloat::opOK, f1.remainder(f2));
4428 EXPECT_TRUE(f1.bitwiseIsEqual(expected));
4429 }
4430}
4431
4432TEST(APFloatTest, PPCDoubleDoubleAddSpecial) {
4433 using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t,
4434 APFloat::fltCategory, APFloat::roundingMode>;
4435 DataType Data[] = {
4436 // (1 + 0) + (-1 + 0) = fcZero
4437 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0xbff0000000000000ull, args: 0,
4438 args: APFloat::fcZero, args: APFloat::rmNearestTiesToEven),
4439 // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = fcInfinity
4440 std::make_tuple(args: 0x7fefffffffffffffull, args: 0x7c8ffffffffffffeull,
4441 args: 0x7948000000000000ull, args: 0ull, args: APFloat::fcInfinity,
4442 args: APFloat::rmNearestTiesToEven),
4443 // TODO: change the 4th 0x75effffffffffffe to 0x75efffffffffffff when
4444 // semPPCDoubleDoubleLegacy is gone.
4445 // LDBL_MAX + (1.011111... >> (1023 - 106) + (1.1111111...0 >> (1023 -
4446 // 160))) = fcNormal
4447 std::make_tuple(args: 0x7fefffffffffffffull, args: 0x7c8ffffffffffffeull,
4448 args: 0x7947ffffffffffffull, args: 0x75effffffffffffeull,
4449 args: APFloat::fcNormal, args: APFloat::rmNearestTiesToEven),
4450 // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = fcInfinity
4451 std::make_tuple(args: 0x7fefffffffffffffull, args: 0x7c8ffffffffffffeull,
4452 args: 0x7fefffffffffffffull, args: 0x7c8ffffffffffffeull,
4453 args: APFloat::fcInfinity, args: APFloat::rmNearestTiesToEven),
4454 // NaN + (1 + 0) = fcNaN
4455 std::make_tuple(args: 0x7ff8000000000000ull, args: 0, args: 0x3ff0000000000000ull, args: 0,
4456 args: APFloat::fcNaN, args: APFloat::rmNearestTiesToEven),
4457 };
4458
4459 for (auto Tp : Data) {
4460 uint64_t Op1[2], Op2[2];
4461 APFloat::fltCategory Expected;
4462 APFloat::roundingMode RM;
4463 std::tie(args&: Op1[0], args&: Op1[1], args&: Op2[0], args&: Op2[1], args&: Expected, args&: RM) = Tp;
4464
4465 {
4466 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4467 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4468 A1.add(RHS: A2, RM);
4469
4470 EXPECT_EQ(Expected, A1.getCategory())
4471 << formatv(Fmt: "({0:x} + {1:x}) + ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1],
4472 Vals&: Op2[0], Vals&: Op2[1])
4473 .str();
4474 }
4475 {
4476 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4477 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4478 A2.add(RHS: A1, RM);
4479
4480 EXPECT_EQ(Expected, A2.getCategory())
4481 << formatv(Fmt: "({0:x} + {1:x}) + ({2:x} + {3:x})", Vals&: Op2[0], Vals&: Op2[1],
4482 Vals&: Op1[0], Vals&: Op1[1])
4483 .str();
4484 }
4485 }
4486}
4487
4488TEST(APFloatTest, PPCDoubleDoubleAdd) {
4489 using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
4490 uint64_t, APFloat::roundingMode>;
4491 DataType Data[] = {
4492 // (1 + 0) + (1e-105 + 0) = (1 + 1e-105)
4493 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0x3960000000000000ull, args: 0,
4494 args: 0x3ff0000000000000ull, args: 0x3960000000000000ull,
4495 args: APFloat::rmNearestTiesToEven),
4496 // (1 + 0) + (1e-106 + 0) = (1 + 1e-106)
4497 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0x3950000000000000ull, args: 0,
4498 args: 0x3ff0000000000000ull, args: 0x3950000000000000ull,
4499 args: APFloat::rmNearestTiesToEven),
4500 // (1 + 1e-106) + (1e-106 + 0) = (1 + 1e-105)
4501 std::make_tuple(args: 0x3ff0000000000000ull, args: 0x3950000000000000ull,
4502 args: 0x3950000000000000ull, args: 0, args: 0x3ff0000000000000ull,
4503 args: 0x3960000000000000ull, args: APFloat::rmNearestTiesToEven),
4504 // (1 + 0) + (epsilon + 0) = (1 + epsilon)
4505 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0x0000000000000001ull, args: 0,
4506 args: 0x3ff0000000000000ull, args: 0x0000000000000001ull,
4507 args: APFloat::rmNearestTiesToEven),
4508 // TODO: change 0xf950000000000000 to 0xf940000000000000, when
4509 // semPPCDoubleDoubleLegacy is gone.
4510 // (DBL_MAX - 1 << (1023 - 105)) + (1 << (1023 - 53) + 0) = DBL_MAX +
4511 // 1.11111... << (1023 - 52)
4512 std::make_tuple(args: 0x7fefffffffffffffull, args: 0xf950000000000000ull,
4513 args: 0x7c90000000000000ull, args: 0, args: 0x7fefffffffffffffull,
4514 args: 0x7c8ffffffffffffeull, args: APFloat::rmNearestTiesToEven),
4515 // TODO: change 0xf950000000000000 to 0xf940000000000000, when
4516 // semPPCDoubleDoubleLegacy is gone.
4517 // (1 << (1023 - 53) + 0) + (DBL_MAX - 1 << (1023 - 105)) = DBL_MAX +
4518 // 1.11111... << (1023 - 52)
4519 std::make_tuple(args: 0x7c90000000000000ull, args: 0, args: 0x7fefffffffffffffull,
4520 args: 0xf950000000000000ull, args: 0x7fefffffffffffffull,
4521 args: 0x7c8ffffffffffffeull, args: APFloat::rmNearestTiesToEven),
4522 };
4523
4524 for (auto Tp : Data) {
4525 uint64_t Op1[2], Op2[2], Expected[2];
4526 APFloat::roundingMode RM;
4527 std::tie(args&: Op1[0], args&: Op1[1], args&: Op2[0], args&: Op2[1], args&: Expected[0], args&: Expected[1], args&: RM) = Tp;
4528
4529 {
4530 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4531 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4532 A1.add(RHS: A2, RM);
4533
4534 EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
4535 << formatv(Fmt: "({0:x} + {1:x}) + ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1],
4536 Vals&: Op2[0], Vals&: Op2[1])
4537 .str();
4538 EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
4539 << formatv(Fmt: "({0:x} + {1:x}) + ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1],
4540 Vals&: Op2[0], Vals&: Op2[1])
4541 .str();
4542 }
4543 {
4544 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4545 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4546 A2.add(RHS: A1, RM);
4547
4548 EXPECT_EQ(Expected[0], A2.bitcastToAPInt().getRawData()[0])
4549 << formatv(Fmt: "({0:x} + {1:x}) + ({2:x} + {3:x})", Vals&: Op2[0], Vals&: Op2[1],
4550 Vals&: Op1[0], Vals&: Op1[1])
4551 .str();
4552 EXPECT_EQ(Expected[1], A2.bitcastToAPInt().getRawData()[1])
4553 << formatv(Fmt: "({0:x} + {1:x}) + ({2:x} + {3:x})", Vals&: Op2[0], Vals&: Op2[1],
4554 Vals&: Op1[0], Vals&: Op1[1])
4555 .str();
4556 }
4557 }
4558}
4559
4560TEST(APFloatTest, PPCDoubleDoubleSubtract) {
4561 using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
4562 uint64_t, APFloat::roundingMode>;
4563 DataType Data[] = {
4564 // (1 + 0) - (-1e-105 + 0) = (1 + 1e-105)
4565 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0xb960000000000000ull, args: 0,
4566 args: 0x3ff0000000000000ull, args: 0x3960000000000000ull,
4567 args: APFloat::rmNearestTiesToEven),
4568 // (1 + 0) - (-1e-106 + 0) = (1 + 1e-106)
4569 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0xb950000000000000ull, args: 0,
4570 args: 0x3ff0000000000000ull, args: 0x3950000000000000ull,
4571 args: APFloat::rmNearestTiesToEven),
4572 };
4573
4574 for (auto Tp : Data) {
4575 uint64_t Op1[2], Op2[2], Expected[2];
4576 APFloat::roundingMode RM;
4577 std::tie(args&: Op1[0], args&: Op1[1], args&: Op2[0], args&: Op2[1], args&: Expected[0], args&: Expected[1], args&: RM) = Tp;
4578
4579 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4580 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4581 A1.subtract(RHS: A2, RM);
4582
4583 EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
4584 << formatv(Fmt: "({0:x} + {1:x}) - ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1], Vals&: Op2[0],
4585 Vals&: Op2[1])
4586 .str();
4587 EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
4588 << formatv(Fmt: "({0:x} + {1:x}) - ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1], Vals&: Op2[0],
4589 Vals&: Op2[1])
4590 .str();
4591 }
4592}
4593
4594TEST(APFloatTest, PPCDoubleDoubleMultiplySpecial) {
4595 using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t,
4596 APFloat::fltCategory, APFloat::roundingMode>;
4597 DataType Data[] = {
4598 // fcNaN * fcNaN = fcNaN
4599 std::make_tuple(args: 0x7ff8000000000000ull, args: 0, args: 0x7ff8000000000000ull, args: 0,
4600 args: APFloat::fcNaN, args: APFloat::rmNearestTiesToEven),
4601 // fcNaN * fcZero = fcNaN
4602 std::make_tuple(args: 0x7ff8000000000000ull, args: 0, args: 0, args: 0, args: APFloat::fcNaN,
4603 args: APFloat::rmNearestTiesToEven),
4604 // fcNaN * fcInfinity = fcNaN
4605 std::make_tuple(args: 0x7ff8000000000000ull, args: 0, args: 0x7ff0000000000000ull, args: 0,
4606 args: APFloat::fcNaN, args: APFloat::rmNearestTiesToEven),
4607 // fcNaN * fcNormal = fcNaN
4608 std::make_tuple(args: 0x7ff8000000000000ull, args: 0, args: 0x3ff0000000000000ull, args: 0,
4609 args: APFloat::fcNaN, args: APFloat::rmNearestTiesToEven),
4610 // fcInfinity * fcInfinity = fcInfinity
4611 std::make_tuple(args: 0x7ff0000000000000ull, args: 0, args: 0x7ff0000000000000ull, args: 0,
4612 args: APFloat::fcInfinity, args: APFloat::rmNearestTiesToEven),
4613 // fcInfinity * fcZero = fcNaN
4614 std::make_tuple(args: 0x7ff0000000000000ull, args: 0, args: 0, args: 0, args: APFloat::fcNaN,
4615 args: APFloat::rmNearestTiesToEven),
4616 // fcInfinity * fcNormal = fcInfinity
4617 std::make_tuple(args: 0x7ff0000000000000ull, args: 0, args: 0x3ff0000000000000ull, args: 0,
4618 args: APFloat::fcInfinity, args: APFloat::rmNearestTiesToEven),
4619 // fcZero * fcZero = fcZero
4620 std::make_tuple(args: 0, args: 0, args: 0, args: 0, args: APFloat::fcZero,
4621 args: APFloat::rmNearestTiesToEven),
4622 // fcZero * fcNormal = fcZero
4623 std::make_tuple(args: 0, args: 0, args: 0x3ff0000000000000ull, args: 0, args: APFloat::fcZero,
4624 args: APFloat::rmNearestTiesToEven),
4625 };
4626
4627 for (auto Tp : Data) {
4628 uint64_t Op1[2], Op2[2];
4629 APFloat::fltCategory Expected;
4630 APFloat::roundingMode RM;
4631 std::tie(args&: Op1[0], args&: Op1[1], args&: Op2[0], args&: Op2[1], args&: Expected, args&: RM) = Tp;
4632
4633 {
4634 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4635 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4636 A1.multiply(RHS: A2, RM);
4637
4638 EXPECT_EQ(Expected, A1.getCategory())
4639 << formatv(Fmt: "({0:x} + {1:x}) * ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1],
4640 Vals&: Op2[0], Vals&: Op2[1])
4641 .str();
4642 }
4643 {
4644 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4645 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4646 A2.multiply(RHS: A1, RM);
4647
4648 EXPECT_EQ(Expected, A2.getCategory())
4649 << formatv(Fmt: "({0:x} + {1:x}) * ({2:x} + {3:x})", Vals&: Op2[0], Vals&: Op2[1],
4650 Vals&: Op1[0], Vals&: Op1[1])
4651 .str();
4652 }
4653 }
4654}
4655
4656TEST(APFloatTest, PPCDoubleDoubleMultiply) {
4657 using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
4658 uint64_t, APFloat::roundingMode>;
4659 DataType Data[] = {
4660 // 1/3 * 3 = 1.0
4661 std::make_tuple(args: 0x3fd5555555555555ull, args: 0x3c75555555555556ull,
4662 args: 0x4008000000000000ull, args: 0, args: 0x3ff0000000000000ull, args: 0,
4663 args: APFloat::rmNearestTiesToEven),
4664 // (1 + epsilon) * (1 + 0) = fcZero
4665 std::make_tuple(args: 0x3ff0000000000000ull, args: 0x0000000000000001ull,
4666 args: 0x3ff0000000000000ull, args: 0, args: 0x3ff0000000000000ull,
4667 args: 0x0000000000000001ull, args: APFloat::rmNearestTiesToEven),
4668 // (1 + epsilon) * (1 + epsilon) = 1 + 2 * epsilon
4669 std::make_tuple(args: 0x3ff0000000000000ull, args: 0x0000000000000001ull,
4670 args: 0x3ff0000000000000ull, args: 0x0000000000000001ull,
4671 args: 0x3ff0000000000000ull, args: 0x0000000000000002ull,
4672 args: APFloat::rmNearestTiesToEven),
4673 // -(1 + epsilon) * (1 + epsilon) = -1
4674 std::make_tuple(args: 0xbff0000000000000ull, args: 0x0000000000000001ull,
4675 args: 0x3ff0000000000000ull, args: 0x0000000000000001ull,
4676 args: 0xbff0000000000000ull, args: 0, args: APFloat::rmNearestTiesToEven),
4677 // (0.5 + 0) * (1 + 2 * epsilon) = 0.5 + epsilon
4678 std::make_tuple(args: 0x3fe0000000000000ull, args: 0, args: 0x3ff0000000000000ull,
4679 args: 0x0000000000000002ull, args: 0x3fe0000000000000ull,
4680 args: 0x0000000000000001ull, args: APFloat::rmNearestTiesToEven),
4681 // (0.5 + 0) * (1 + epsilon) = 0.5
4682 std::make_tuple(args: 0x3fe0000000000000ull, args: 0, args: 0x3ff0000000000000ull,
4683 args: 0x0000000000000001ull, args: 0x3fe0000000000000ull, args: 0,
4684 args: APFloat::rmNearestTiesToEven),
4685 // __LDBL_MAX__ * (1 + 1 << 106) = inf
4686 std::make_tuple(args: 0x7fefffffffffffffull, args: 0x7c8ffffffffffffeull,
4687 args: 0x3ff0000000000000ull, args: 0x3950000000000000ull,
4688 args: 0x7ff0000000000000ull, args: 0, args: APFloat::rmNearestTiesToEven),
4689 // __LDBL_MAX__ * (1 + 1 << 107) > __LDBL_MAX__, but not inf, yes =_=|||
4690 std::make_tuple(args: 0x7fefffffffffffffull, args: 0x7c8ffffffffffffeull,
4691 args: 0x3ff0000000000000ull, args: 0x3940000000000000ull,
4692 args: 0x7fefffffffffffffull, args: 0x7c8fffffffffffffull,
4693 args: APFloat::rmNearestTiesToEven),
4694 // __LDBL_MAX__ * (1 + 1 << 108) = __LDBL_MAX__
4695 std::make_tuple(args: 0x7fefffffffffffffull, args: 0x7c8ffffffffffffeull,
4696 args: 0x3ff0000000000000ull, args: 0x3930000000000000ull,
4697 args: 0x7fefffffffffffffull, args: 0x7c8ffffffffffffeull,
4698 args: APFloat::rmNearestTiesToEven),
4699 };
4700
4701 for (auto Tp : Data) {
4702 uint64_t Op1[2], Op2[2], Expected[2];
4703 APFloat::roundingMode RM;
4704 std::tie(args&: Op1[0], args&: Op1[1], args&: Op2[0], args&: Op2[1], args&: Expected[0], args&: Expected[1], args&: RM) = Tp;
4705
4706 {
4707 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4708 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4709 A1.multiply(RHS: A2, RM);
4710
4711 EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
4712 << formatv(Fmt: "({0:x} + {1:x}) * ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1],
4713 Vals&: Op2[0], Vals&: Op2[1])
4714 .str();
4715 EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
4716 << formatv(Fmt: "({0:x} + {1:x}) * ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1],
4717 Vals&: Op2[0], Vals&: Op2[1])
4718 .str();
4719 }
4720 {
4721 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4722 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4723 A2.multiply(RHS: A1, RM);
4724
4725 EXPECT_EQ(Expected[0], A2.bitcastToAPInt().getRawData()[0])
4726 << formatv(Fmt: "({0:x} + {1:x}) * ({2:x} + {3:x})", Vals&: Op2[0], Vals&: Op2[1],
4727 Vals&: Op1[0], Vals&: Op1[1])
4728 .str();
4729 EXPECT_EQ(Expected[1], A2.bitcastToAPInt().getRawData()[1])
4730 << formatv(Fmt: "({0:x} + {1:x}) * ({2:x} + {3:x})", Vals&: Op2[0], Vals&: Op2[1],
4731 Vals&: Op1[0], Vals&: Op1[1])
4732 .str();
4733 }
4734 }
4735}
4736
4737TEST(APFloatTest, PPCDoubleDoubleDivide) {
4738 using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
4739 uint64_t, APFloat::roundingMode>;
4740 // TODO: Only a sanity check for now. Add more edge cases when the
4741 // double-double algorithm is implemented.
4742 DataType Data[] = {
4743 // 1 / 3 = 1/3
4744 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0x4008000000000000ull, args: 0,
4745 args: 0x3fd5555555555555ull, args: 0x3c75555555555556ull,
4746 args: APFloat::rmNearestTiesToEven),
4747 };
4748
4749 for (auto Tp : Data) {
4750 uint64_t Op1[2], Op2[2], Expected[2];
4751 APFloat::roundingMode RM;
4752 std::tie(args&: Op1[0], args&: Op1[1], args&: Op2[0], args&: Op2[1], args&: Expected[0], args&: Expected[1], args&: RM) = Tp;
4753
4754 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4755 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4756 A1.divide(RHS: A2, RM);
4757
4758 EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
4759 << formatv(Fmt: "({0:x} + {1:x}) / ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1], Vals&: Op2[0],
4760 Vals&: Op2[1])
4761 .str();
4762 EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
4763 << formatv(Fmt: "({0:x} + {1:x}) / ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1], Vals&: Op2[0],
4764 Vals&: Op2[1])
4765 .str();
4766 }
4767}
4768
4769TEST(APFloatTest, PPCDoubleDoubleRemainder) {
4770 using DataType =
4771 std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t>;
4772 DataType Data[] = {
4773 // remainder(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53)
4774 std::make_tuple(args: 0x4008000000000000ull, args: 0x3cb8000000000000ull,
4775 args: 0x3ff4000000000000ull, args: 0x3ca4000000000000ull,
4776 args: 0x3fe0000000000000ull, args: 0x3c90000000000000ull),
4777 // remainder(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (-0.5 - 0.5 << 53)
4778 std::make_tuple(args: 0x4008000000000000ull, args: 0x3cb8000000000000ull,
4779 args: 0x3ffc000000000000ull, args: 0x3cac000000000000ull,
4780 args: 0xbfe0000000000000ull, args: 0xbc90000000000000ull),
4781 };
4782
4783 for (auto Tp : Data) {
4784 uint64_t Op1[2], Op2[2], Expected[2];
4785 std::tie(args&: Op1[0], args&: Op1[1], args&: Op2[0], args&: Op2[1], args&: Expected[0], args&: Expected[1]) = Tp;
4786
4787 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4788 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4789 A1.remainder(RHS: A2);
4790
4791 EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
4792 << formatv(Fmt: "remainder({0:x} + {1:x}), ({2:x} + {3:x}))", Vals&: Op1[0], Vals&: Op1[1],
4793 Vals&: Op2[0], Vals&: Op2[1])
4794 .str();
4795 EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
4796 << formatv(Fmt: "remainder(({0:x} + {1:x}), ({2:x} + {3:x}))", Vals&: Op1[0],
4797 Vals&: Op1[1], Vals&: Op2[0], Vals&: Op2[1])
4798 .str();
4799 }
4800}
4801
4802TEST(APFloatTest, PPCDoubleDoubleMod) {
4803 using DataType =
4804 std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t>;
4805 DataType Data[] = {
4806 // mod(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53)
4807 std::make_tuple(args: 0x4008000000000000ull, args: 0x3cb8000000000000ull,
4808 args: 0x3ff4000000000000ull, args: 0x3ca4000000000000ull,
4809 args: 0x3fe0000000000000ull, args: 0x3c90000000000000ull),
4810 // mod(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (1.25 + 1.25 << 53)
4811 // 0xbc98000000000000 doesn't seem right, but it's what we currently have.
4812 // TODO: investigate
4813 std::make_tuple(args: 0x4008000000000000ull, args: 0x3cb8000000000000ull,
4814 args: 0x3ffc000000000000ull, args: 0x3cac000000000000ull,
4815 args: 0x3ff4000000000001ull, args: 0xbc98000000000000ull),
4816 };
4817
4818 for (auto Tp : Data) {
4819 uint64_t Op1[2], Op2[2], Expected[2];
4820 std::tie(args&: Op1[0], args&: Op1[1], args&: Op2[0], args&: Op2[1], args&: Expected[0], args&: Expected[1]) = Tp;
4821
4822 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4823 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4824 A1.mod(RHS: A2);
4825
4826 EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
4827 << formatv(Fmt: "fmod(({0:x} + {1:x}), ({2:x} + {3:x}))", Vals&: Op1[0], Vals&: Op1[1],
4828 Vals&: Op2[0], Vals&: Op2[1])
4829 .str();
4830 EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
4831 << formatv(Fmt: "fmod(({0:x} + {1:x}), ({2:x} + {3:x}))", Vals&: Op1[0], Vals&: Op1[1],
4832 Vals&: Op2[0], Vals&: Op2[1])
4833 .str();
4834 }
4835}
4836
4837TEST(APFloatTest, PPCDoubleDoubleFMA) {
4838 // Sanity check for now.
4839 APFloat A(APFloat::PPCDoubleDouble(), "2");
4840 A.fusedMultiplyAdd(Multiplicand: APFloat(APFloat::PPCDoubleDouble(), "3"),
4841 Addend: APFloat(APFloat::PPCDoubleDouble(), "4"),
4842 RM: APFloat::rmNearestTiesToEven);
4843 EXPECT_EQ(APFloat::cmpEqual,
4844 APFloat(APFloat::PPCDoubleDouble(), "10").compare(A));
4845}
4846
4847TEST(APFloatTest, PPCDoubleDoubleRoundToIntegral) {
4848 {
4849 APFloat A(APFloat::PPCDoubleDouble(), "1.5");
4850 A.roundToIntegral(RM: APFloat::rmNearestTiesToEven);
4851 EXPECT_EQ(APFloat::cmpEqual,
4852 APFloat(APFloat::PPCDoubleDouble(), "2").compare(A));
4853 }
4854 {
4855 APFloat A(APFloat::PPCDoubleDouble(), "2.5");
4856 A.roundToIntegral(RM: APFloat::rmNearestTiesToEven);
4857 EXPECT_EQ(APFloat::cmpEqual,
4858 APFloat(APFloat::PPCDoubleDouble(), "2").compare(A));
4859 }
4860}
4861
4862TEST(APFloatTest, PPCDoubleDoubleCompare) {
4863 using DataType =
4864 std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, APFloat::cmpResult>;
4865
4866 DataType Data[] = {
4867 // (1 + 0) = (1 + 0)
4868 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0x3ff0000000000000ull, args: 0,
4869 args: APFloat::cmpEqual),
4870 // (1 + 0) < (1.00...1 + 0)
4871 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0x3ff0000000000001ull, args: 0,
4872 args: APFloat::cmpLessThan),
4873 // (1.00...1 + 0) > (1 + 0)
4874 std::make_tuple(args: 0x3ff0000000000001ull, args: 0, args: 0x3ff0000000000000ull, args: 0,
4875 args: APFloat::cmpGreaterThan),
4876 // (1 + 0) < (1 + epsilon)
4877 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0x3ff0000000000001ull,
4878 args: 0x0000000000000001ull, args: APFloat::cmpLessThan),
4879 // NaN != NaN
4880 std::make_tuple(args: 0x7ff8000000000000ull, args: 0, args: 0x7ff8000000000000ull, args: 0,
4881 args: APFloat::cmpUnordered),
4882 // (1 + 0) != NaN
4883 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0x7ff8000000000000ull, args: 0,
4884 args: APFloat::cmpUnordered),
4885 // Inf = Inf
4886 std::make_tuple(args: 0x7ff0000000000000ull, args: 0, args: 0x7ff0000000000000ull, args: 0,
4887 args: APFloat::cmpEqual),
4888 };
4889
4890 for (auto Tp : Data) {
4891 uint64_t Op1[2], Op2[2];
4892 APFloat::cmpResult Expected;
4893 std::tie(args&: Op1[0], args&: Op1[1], args&: Op2[0], args&: Op2[1], args&: Expected) = Tp;
4894
4895 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4896 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4897 EXPECT_EQ(Expected, A1.compare(A2))
4898 << formatv(Fmt: "compare(({0:x} + {1:x}), ({2:x} + {3:x}))", Vals&: Op1[0], Vals&: Op1[1],
4899 Vals&: Op2[0], Vals&: Op2[1])
4900 .str();
4901 }
4902}
4903
4904TEST(APFloatTest, PPCDoubleDoubleBitwiseIsEqual) {
4905 using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, bool>;
4906
4907 DataType Data[] = {
4908 // (1 + 0) = (1 + 0)
4909 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0x3ff0000000000000ull, args: 0, args: true),
4910 // (1 + 0) != (1.00...1 + 0)
4911 std::make_tuple(args: 0x3ff0000000000000ull, args: 0, args: 0x3ff0000000000001ull, args: 0,
4912 args: false),
4913 // NaN = NaN
4914 std::make_tuple(args: 0x7ff8000000000000ull, args: 0, args: 0x7ff8000000000000ull, args: 0, args: true),
4915 // NaN != NaN with a different bit pattern
4916 std::make_tuple(args: 0x7ff8000000000000ull, args: 0, args: 0x7ff8000000000000ull,
4917 args: 0x3ff0000000000000ull, args: false),
4918 // Inf = Inf
4919 std::make_tuple(args: 0x7ff0000000000000ull, args: 0, args: 0x7ff0000000000000ull, args: 0, args: true),
4920 };
4921
4922 for (auto Tp : Data) {
4923 uint64_t Op1[2], Op2[2];
4924 bool Expected;
4925 std::tie(args&: Op1[0], args&: Op1[1], args&: Op2[0], args&: Op2[1], args&: Expected) = Tp;
4926
4927 APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
4928 APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
4929 EXPECT_EQ(Expected, A1.bitwiseIsEqual(A2))
4930 << formatv(Fmt: "({0:x} + {1:x}) = ({2:x} + {3:x})", Vals&: Op1[0], Vals&: Op1[1], Vals&: Op2[0],
4931 Vals&: Op2[1])
4932 .str();
4933 }
4934}
4935
4936TEST(APFloatTest, PPCDoubleDoubleHashValue) {
4937 uint64_t Data1[] = {0x3ff0000000000001ull, 0x0000000000000001ull};
4938 uint64_t Data2[] = {0x3ff0000000000001ull, 0};
4939 // The hash values are *hopefully* different.
4940 EXPECT_NE(
4941 hash_value(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data1))),
4942 hash_value(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data2))));
4943}
4944
4945TEST(APFloatTest, PPCDoubleDoubleChangeSign) {
4946 uint64_t Data[] = {
4947 0x400f000000000000ull, 0xbcb0000000000000ull,
4948 };
4949 APFloat Float(APFloat::PPCDoubleDouble(), APInt(128, 2, Data));
4950 {
4951 APFloat Actual =
4952 APFloat::copySign(Value: Float, Sign: APFloat(APFloat::IEEEdouble(), "1"));
4953 EXPECT_EQ(0x400f000000000000ull, Actual.bitcastToAPInt().getRawData()[0]);
4954 EXPECT_EQ(0xbcb0000000000000ull, Actual.bitcastToAPInt().getRawData()[1]);
4955 }
4956 {
4957 APFloat Actual =
4958 APFloat::copySign(Value: Float, Sign: APFloat(APFloat::IEEEdouble(), "-1"));
4959 EXPECT_EQ(0xc00f000000000000ull, Actual.bitcastToAPInt().getRawData()[0]);
4960 EXPECT_EQ(0x3cb0000000000000ull, Actual.bitcastToAPInt().getRawData()[1]);
4961 }
4962}
4963
4964TEST(APFloatTest, PPCDoubleDoubleFactories) {
4965 {
4966 uint64_t Data[] = {
4967 0, 0,
4968 };
4969 EXPECT_EQ(APInt(128, 2, Data),
4970 APFloat::getZero(APFloat::PPCDoubleDouble()).bitcastToAPInt());
4971 }
4972 {
4973 uint64_t Data[] = {
4974 0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
4975 };
4976 EXPECT_EQ(APInt(128, 2, Data),
4977 APFloat::getLargest(APFloat::PPCDoubleDouble()).bitcastToAPInt());
4978 }
4979 {
4980 uint64_t Data[] = {
4981 0x0000000000000001ull, 0,
4982 };
4983 EXPECT_EQ(
4984 APInt(128, 2, Data),
4985 APFloat::getSmallest(APFloat::PPCDoubleDouble()).bitcastToAPInt());
4986 }
4987 {
4988 uint64_t Data[] = {0x0360000000000000ull, 0};
4989 EXPECT_EQ(APInt(128, 2, Data),
4990 APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble())
4991 .bitcastToAPInt());
4992 }
4993 {
4994 uint64_t Data[] = {
4995 0x8000000000000000ull, 0x0000000000000000ull,
4996 };
4997 EXPECT_EQ(
4998 APInt(128, 2, Data),
4999 APFloat::getZero(APFloat::PPCDoubleDouble(), true).bitcastToAPInt());
5000 }
5001 {
5002 uint64_t Data[] = {
5003 0xffefffffffffffffull, 0xfc8ffffffffffffeull,
5004 };
5005 EXPECT_EQ(
5006 APInt(128, 2, Data),
5007 APFloat::getLargest(APFloat::PPCDoubleDouble(), true).bitcastToAPInt());
5008 }
5009 {
5010 uint64_t Data[] = {
5011 0x8000000000000001ull, 0x0000000000000000ull,
5012 };
5013 EXPECT_EQ(APInt(128, 2, Data),
5014 APFloat::getSmallest(APFloat::PPCDoubleDouble(), true)
5015 .bitcastToAPInt());
5016 }
5017 {
5018 uint64_t Data[] = {
5019 0x8360000000000000ull, 0x0000000000000000ull,
5020 };
5021 EXPECT_EQ(APInt(128, 2, Data),
5022 APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble(), true)
5023 .bitcastToAPInt());
5024 }
5025 EXPECT_TRUE(APFloat::getSmallest(APFloat::PPCDoubleDouble()).isSmallest());
5026 EXPECT_TRUE(APFloat::getLargest(APFloat::PPCDoubleDouble()).isLargest());
5027}
5028
5029TEST(APFloatTest, PPCDoubleDoubleIsDenormal) {
5030 EXPECT_TRUE(APFloat::getSmallest(APFloat::PPCDoubleDouble()).isDenormal());
5031 EXPECT_FALSE(APFloat::getLargest(APFloat::PPCDoubleDouble()).isDenormal());
5032 EXPECT_FALSE(
5033 APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble()).isDenormal());
5034 {
5035 // (4 + 3) is not normalized
5036 uint64_t Data[] = {
5037 0x4010000000000000ull, 0x4008000000000000ull,
5038 };
5039 EXPECT_TRUE(
5040 APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data)).isDenormal());
5041 }
5042}
5043
5044TEST(APFloatTest, PPCDoubleDoubleScalbn) {
5045 // 3.0 + 3.0 << 53
5046 uint64_t Input[] = {
5047 0x4008000000000000ull, 0x3cb8000000000000ull,
5048 };
5049 APFloat Result =
5050 scalbn(X: APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Input)), Exp: 1,
5051 RM: APFloat::rmNearestTiesToEven);
5052 // 6.0 + 6.0 << 53
5053 EXPECT_EQ(0x4018000000000000ull, Result.bitcastToAPInt().getRawData()[0]);
5054 EXPECT_EQ(0x3cc8000000000000ull, Result.bitcastToAPInt().getRawData()[1]);
5055}
5056
5057TEST(APFloatTest, PPCDoubleDoubleFrexp) {
5058 // 3.0 + 3.0 << 53
5059 uint64_t Input[] = {
5060 0x4008000000000000ull, 0x3cb8000000000000ull,
5061 };
5062 int Exp;
5063 // 0.75 + 0.75 << 53
5064 APFloat Result =
5065 frexp(X: APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Input)), Exp,
5066 RM: APFloat::rmNearestTiesToEven);
5067 EXPECT_EQ(2, Exp);
5068 EXPECT_EQ(0x3fe8000000000000ull, Result.bitcastToAPInt().getRawData()[0]);
5069 EXPECT_EQ(0x3c98000000000000ull, Result.bitcastToAPInt().getRawData()[1]);
5070}
5071
5072TEST(APFloatTest, x87Largest) {
5073 APFloat MaxX87Val = APFloat::getLargest(Sem: APFloat::x87DoubleExtended());
5074 EXPECT_TRUE(MaxX87Val.isLargest());
5075}
5076
5077TEST(APFloatTest, x87Next) {
5078 APFloat F(APFloat::x87DoubleExtended(), "-1.0");
5079 F.next(nextDown: false);
5080 EXPECT_TRUE(ilogb(F) == -1);
5081}
5082
5083TEST(APFloatTest, Float8ExhaustivePair) {
5084 // Test each pair of 8-bit floats with non-standard semantics
5085 for (APFloat::Semantics Sem :
5086 {APFloat::S_Float8E4M3FN, APFloat::S_Float8E5M2FNUZ,
5087 APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) {
5088 const llvm::fltSemantics &S = APFloat::EnumToSemantics(S: Sem);
5089 for (int i = 0; i < 256; i++) {
5090 for (int j = 0; j < 256; j++) {
5091 SCOPED_TRACE("sem=" + std::to_string(Sem) + ",i=" + std::to_string(i) +
5092 ",j=" + std::to_string(j));
5093 APFloat x(S, APInt(8, i));
5094 APFloat y(S, APInt(8, j));
5095
5096 bool losesInfo;
5097 APFloat x16 = x;
5098 x16.convert(ToSemantics: APFloat::IEEEhalf(), RM: APFloat::rmNearestTiesToEven,
5099 losesInfo: &losesInfo);
5100 EXPECT_FALSE(losesInfo);
5101 APFloat y16 = y;
5102 y16.convert(ToSemantics: APFloat::IEEEhalf(), RM: APFloat::rmNearestTiesToEven,
5103 losesInfo: &losesInfo);
5104 EXPECT_FALSE(losesInfo);
5105
5106 // Add
5107 APFloat z = x;
5108 z.add(RHS: y, RM: APFloat::rmNearestTiesToEven);
5109 APFloat z16 = x16;
5110 z16.add(RHS: y16, RM: APFloat::rmNearestTiesToEven);
5111 z16.convert(ToSemantics: S, RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5112 EXPECT_TRUE(z.bitwiseIsEqual(z16))
5113 << "sem=" << Sem << ", i=" << i << ", j=" << j;
5114
5115 // Subtract
5116 z = x;
5117 z.subtract(RHS: y, RM: APFloat::rmNearestTiesToEven);
5118 z16 = x16;
5119 z16.subtract(RHS: y16, RM: APFloat::rmNearestTiesToEven);
5120 z16.convert(ToSemantics: S, RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5121 EXPECT_TRUE(z.bitwiseIsEqual(z16))
5122 << "sem=" << Sem << ", i=" << i << ", j=" << j;
5123
5124 // Multiply
5125 z = x;
5126 z.multiply(RHS: y, RM: APFloat::rmNearestTiesToEven);
5127 z16 = x16;
5128 z16.multiply(RHS: y16, RM: APFloat::rmNearestTiesToEven);
5129 z16.convert(ToSemantics: S, RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5130 EXPECT_TRUE(z.bitwiseIsEqual(z16))
5131 << "sem=" << Sem << ", i=" << i << ", j=" << j;
5132
5133 // Divide
5134 z = x;
5135 z.divide(RHS: y, RM: APFloat::rmNearestTiesToEven);
5136 z16 = x16;
5137 z16.divide(RHS: y16, RM: APFloat::rmNearestTiesToEven);
5138 z16.convert(ToSemantics: S, RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5139 EXPECT_TRUE(z.bitwiseIsEqual(z16))
5140 << "sem=" << Sem << ", i=" << i << ", j=" << j;
5141
5142 // Mod
5143 z = x;
5144 z.mod(RHS: y);
5145 z16 = x16;
5146 z16.mod(RHS: y16);
5147 z16.convert(ToSemantics: S, RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5148 EXPECT_TRUE(z.bitwiseIsEqual(z16))
5149 << "sem=" << Sem << ", i=" << i << ", j=" << j;
5150
5151 // Remainder
5152 z = x;
5153 z.remainder(RHS: y);
5154 z16 = x16;
5155 z16.remainder(RHS: y16);
5156 z16.convert(ToSemantics: S, RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5157 EXPECT_TRUE(z.bitwiseIsEqual(z16))
5158 << "sem=" << Sem << ", i=" << i << ", j=" << j;
5159 }
5160 }
5161 }
5162}
5163
5164TEST(APFloatTest, ConvertE4M3FNToE5M2) {
5165 bool losesInfo;
5166 APFloat test(APFloat::Float8E4M3FN(), "1.0");
5167 APFloat::opStatus status = test.convert(
5168 ToSemantics: APFloat::Float8E5M2(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5169 EXPECT_EQ(1.0f, test.convertToFloat());
5170 EXPECT_FALSE(losesInfo);
5171 EXPECT_EQ(status, APFloat::opOK);
5172
5173 test = APFloat(APFloat::Float8E4M3FN(), "0.0");
5174 status = test.convert(ToSemantics: APFloat::Float8E5M2(), RM: APFloat::rmNearestTiesToEven,
5175 losesInfo: &losesInfo);
5176 EXPECT_EQ(0.0f, test.convertToFloat());
5177 EXPECT_FALSE(losesInfo);
5178 EXPECT_EQ(status, APFloat::opOK);
5179
5180 test = APFloat(APFloat::Float8E4M3FN(), "0x1.2p0"); // 1.125
5181 status = test.convert(ToSemantics: APFloat::Float8E5M2(), RM: APFloat::rmNearestTiesToEven,
5182 losesInfo: &losesInfo);
5183 EXPECT_EQ(0x1.0p0 /* 1.0 */, test.convertToFloat());
5184 EXPECT_TRUE(losesInfo);
5185 EXPECT_EQ(status, APFloat::opInexact);
5186
5187 test = APFloat(APFloat::Float8E4M3FN(), "0x1.6p0"); // 1.375
5188 status = test.convert(ToSemantics: APFloat::Float8E5M2(), RM: APFloat::rmNearestTiesToEven,
5189 losesInfo: &losesInfo);
5190 EXPECT_EQ(0x1.8p0 /* 1.5 */, test.convertToFloat());
5191 EXPECT_TRUE(losesInfo);
5192 EXPECT_EQ(status, APFloat::opInexact);
5193
5194 // Convert E4M3 denormal to E5M2 normal. Should not be truncated, despite the
5195 // destination format having one fewer significand bit
5196 test = APFloat(APFloat::Float8E4M3FN(), "0x1.Cp-7");
5197 status = test.convert(ToSemantics: APFloat::Float8E5M2(), RM: APFloat::rmNearestTiesToEven,
5198 losesInfo: &losesInfo);
5199 EXPECT_EQ(0x1.Cp-7, test.convertToFloat());
5200 EXPECT_FALSE(losesInfo);
5201 EXPECT_EQ(status, APFloat::opOK);
5202
5203 // Test convert from NaN
5204 test = APFloat(APFloat::Float8E4M3FN(), "nan");
5205 status = test.convert(ToSemantics: APFloat::Float8E5M2(), RM: APFloat::rmNearestTiesToEven,
5206 losesInfo: &losesInfo);
5207 EXPECT_TRUE(std::isnan(test.convertToFloat()));
5208 EXPECT_FALSE(losesInfo);
5209 EXPECT_EQ(status, APFloat::opOK);
5210}
5211
5212TEST(APFloatTest, ConvertE5M2ToE4M3FN) {
5213 bool losesInfo;
5214 APFloat test(APFloat::Float8E5M2(), "1.0");
5215 APFloat::opStatus status = test.convert(
5216 ToSemantics: APFloat::Float8E4M3FN(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5217 EXPECT_EQ(1.0f, test.convertToFloat());
5218 EXPECT_FALSE(losesInfo);
5219 EXPECT_EQ(status, APFloat::opOK);
5220
5221 test = APFloat(APFloat::Float8E5M2(), "0.0");
5222 status = test.convert(ToSemantics: APFloat::Float8E4M3FN(), RM: APFloat::rmNearestTiesToEven,
5223 losesInfo: &losesInfo);
5224 EXPECT_EQ(0.0f, test.convertToFloat());
5225 EXPECT_FALSE(losesInfo);
5226 EXPECT_EQ(status, APFloat::opOK);
5227
5228 test = APFloat(APFloat::Float8E5M2(), "0x1.Cp8"); // 448
5229 status = test.convert(ToSemantics: APFloat::Float8E4M3FN(), RM: APFloat::rmNearestTiesToEven,
5230 losesInfo: &losesInfo);
5231 EXPECT_EQ(0x1.Cp8 /* 448 */, test.convertToFloat());
5232 EXPECT_FALSE(losesInfo);
5233 EXPECT_EQ(status, APFloat::opOK);
5234
5235 // Test overflow
5236 test = APFloat(APFloat::Float8E5M2(), "0x1.0p9"); // 512
5237 status = test.convert(ToSemantics: APFloat::Float8E4M3FN(), RM: APFloat::rmNearestTiesToEven,
5238 losesInfo: &losesInfo);
5239 EXPECT_TRUE(std::isnan(test.convertToFloat()));
5240 EXPECT_TRUE(losesInfo);
5241 EXPECT_EQ(status, APFloat::opOverflow | APFloat::opInexact);
5242
5243 // Test underflow
5244 test = APFloat(APFloat::Float8E5M2(), "0x1.0p-10");
5245 status = test.convert(ToSemantics: APFloat::Float8E4M3FN(), RM: APFloat::rmNearestTiesToEven,
5246 losesInfo: &losesInfo);
5247 EXPECT_EQ(0., test.convertToFloat());
5248 EXPECT_TRUE(losesInfo);
5249 EXPECT_EQ(status, APFloat::opUnderflow | APFloat::opInexact);
5250
5251 // Test rounding up to smallest denormal number
5252 test = APFloat(APFloat::Float8E5M2(), "0x1.8p-10");
5253 status = test.convert(ToSemantics: APFloat::Float8E4M3FN(), RM: APFloat::rmNearestTiesToEven,
5254 losesInfo: &losesInfo);
5255 EXPECT_EQ(0x1.0p-9, test.convertToFloat());
5256 EXPECT_TRUE(losesInfo);
5257 EXPECT_EQ(status, APFloat::opUnderflow | APFloat::opInexact);
5258
5259 // Testing inexact rounding to denormal number
5260 test = APFloat(APFloat::Float8E5M2(), "0x1.8p-9");
5261 status = test.convert(ToSemantics: APFloat::Float8E4M3FN(), RM: APFloat::rmNearestTiesToEven,
5262 losesInfo: &losesInfo);
5263 EXPECT_EQ(0x1.0p-8, test.convertToFloat());
5264 EXPECT_TRUE(losesInfo);
5265 EXPECT_EQ(status, APFloat::opUnderflow | APFloat::opInexact);
5266
5267 APFloat nan = APFloat(APFloat::Float8E4M3FN(), "nan");
5268
5269 // Testing convert from Inf
5270 test = APFloat(APFloat::Float8E5M2(), "inf");
5271 status = test.convert(ToSemantics: APFloat::Float8E4M3FN(), RM: APFloat::rmNearestTiesToEven,
5272 losesInfo: &losesInfo);
5273 EXPECT_TRUE(std::isnan(test.convertToFloat()));
5274 EXPECT_TRUE(losesInfo);
5275 EXPECT_EQ(status, APFloat::opInexact);
5276 EXPECT_TRUE(test.bitwiseIsEqual(nan));
5277
5278 // Testing convert from quiet NaN
5279 test = APFloat(APFloat::Float8E5M2(), "nan");
5280 status = test.convert(ToSemantics: APFloat::Float8E4M3FN(), RM: APFloat::rmNearestTiesToEven,
5281 losesInfo: &losesInfo);
5282 EXPECT_TRUE(std::isnan(test.convertToFloat()));
5283 EXPECT_TRUE(losesInfo);
5284 EXPECT_EQ(status, APFloat::opOK);
5285 EXPECT_TRUE(test.bitwiseIsEqual(nan));
5286
5287 // Testing convert from signaling NaN
5288 test = APFloat(APFloat::Float8E5M2(), "snan");
5289 status = test.convert(ToSemantics: APFloat::Float8E4M3FN(), RM: APFloat::rmNearestTiesToEven,
5290 losesInfo: &losesInfo);
5291 EXPECT_TRUE(std::isnan(test.convertToFloat()));
5292 EXPECT_TRUE(losesInfo);
5293 EXPECT_EQ(status, APFloat::opInvalidOp);
5294 EXPECT_TRUE(test.bitwiseIsEqual(nan));
5295}
5296
5297TEST(APFloatTest, Float8E4M3FNGetInf) {
5298 APFloat t = APFloat::getInf(Sem: APFloat::Float8E4M3FN());
5299 EXPECT_TRUE(t.isNaN());
5300 EXPECT_FALSE(t.isInfinity());
5301}
5302
5303TEST(APFloatTest, Float8E4M3FNFromString) {
5304 // Exactly representable
5305 EXPECT_EQ(448, APFloat(APFloat::Float8E4M3FN(), "448").convertToDouble());
5306 // Round down to maximum value
5307 EXPECT_EQ(448, APFloat(APFloat::Float8E4M3FN(), "464").convertToDouble());
5308 // Round up, causing overflow to NaN
5309 EXPECT_TRUE(APFloat(APFloat::Float8E4M3FN(), "465").isNaN());
5310 // Overflow without rounding
5311 EXPECT_TRUE(APFloat(APFloat::Float8E4M3FN(), "480").isNaN());
5312 // Inf converted to NaN
5313 EXPECT_TRUE(APFloat(APFloat::Float8E4M3FN(), "inf").isNaN());
5314 // NaN converted to NaN
5315 EXPECT_TRUE(APFloat(APFloat::Float8E4M3FN(), "nan").isNaN());
5316}
5317
5318TEST(APFloatTest, Float8E4M3FNAdd) {
5319 APFloat QNaN = APFloat::getNaN(Sem: APFloat::Float8E4M3FN(), Negative: false);
5320
5321 auto FromStr = [](StringRef S) {
5322 return APFloat(APFloat::Float8E4M3FN(), S);
5323 };
5324
5325 struct {
5326 APFloat x;
5327 APFloat y;
5328 const char *result;
5329 int status;
5330 int category;
5331 APFloat::roundingMode roundingMode = APFloat::rmNearestTiesToEven;
5332 } AdditionTests[] = {
5333 // Test addition operations involving NaN, overflow, and the max E4M3
5334 // value (448) because E4M3 differs from IEEE-754 types in these regards
5335 {.x: FromStr("448"), .y: FromStr("16"), .result: "448", .status: APFloat::opInexact,
5336 .category: APFloat::fcNormal},
5337 {.x: FromStr("448"), .y: FromStr("18"), .result: "NaN",
5338 .status: APFloat::opOverflow | APFloat::opInexact, .category: APFloat::fcNaN},
5339 {.x: FromStr("448"), .y: FromStr("32"), .result: "NaN",
5340 .status: APFloat::opOverflow | APFloat::opInexact, .category: APFloat::fcNaN},
5341 {.x: FromStr("-448"), .y: FromStr("-32"), .result: "-NaN",
5342 .status: APFloat::opOverflow | APFloat::opInexact, .category: APFloat::fcNaN},
5343 {.x: QNaN, .y: FromStr("-448"), .result: "NaN", .status: APFloat::opOK, .category: APFloat::fcNaN},
5344 {.x: FromStr("448"), .y: FromStr("-32"), .result: "416", .status: APFloat::opOK, .category: APFloat::fcNormal},
5345 {.x: FromStr("448"), .y: FromStr("0"), .result: "448", .status: APFloat::opOK, .category: APFloat::fcNormal},
5346 {.x: FromStr("448"), .y: FromStr("32"), .result: "448", .status: APFloat::opInexact,
5347 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardZero},
5348 {.x: FromStr("448"), .y: FromStr("448"), .result: "448", .status: APFloat::opInexact,
5349 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardZero},
5350 };
5351
5352 for (size_t i = 0; i < std::size(AdditionTests); ++i) {
5353 APFloat x(AdditionTests[i].x);
5354 APFloat y(AdditionTests[i].y);
5355 APFloat::opStatus status = x.add(RHS: y, RM: AdditionTests[i].roundingMode);
5356
5357 APFloat result(APFloat::Float8E4M3FN(), AdditionTests[i].result);
5358
5359 EXPECT_TRUE(result.bitwiseIsEqual(x));
5360 EXPECT_EQ(AdditionTests[i].status, (int)status);
5361 EXPECT_EQ(AdditionTests[i].category, (int)x.getCategory());
5362 }
5363}
5364
5365TEST(APFloatTest, Float8E4M3FNDivideByZero) {
5366 APFloat x(APFloat::Float8E4M3FN(), "1");
5367 APFloat zero(APFloat::Float8E4M3FN(), "0");
5368 EXPECT_EQ(x.divide(zero, APFloat::rmNearestTiesToEven), APFloat::opDivByZero);
5369 EXPECT_TRUE(x.isNaN());
5370}
5371
5372TEST(APFloatTest, Float8E4M3FNNext) {
5373 APFloat test(APFloat::Float8E4M3FN(), APFloat::uninitialized);
5374 APFloat expected(APFloat::Float8E4M3FN(), APFloat::uninitialized);
5375
5376 // nextUp on positive numbers
5377 for (int i = 0; i < 127; i++) {
5378 test = APFloat(APFloat::Float8E4M3FN(), APInt(8, i));
5379 expected = APFloat(APFloat::Float8E4M3FN(), APInt(8, i + 1));
5380 EXPECT_EQ(test.next(false), APFloat::opOK);
5381 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5382 }
5383
5384 // nextUp on negative zero
5385 test = APFloat::getZero(Sem: APFloat::Float8E4M3FN(), Negative: true);
5386 expected = APFloat::getSmallest(Sem: APFloat::Float8E4M3FN(), Negative: false);
5387 EXPECT_EQ(test.next(false), APFloat::opOK);
5388 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5389
5390 // nextUp on negative nonzero numbers
5391 for (int i = 129; i < 255; i++) {
5392 test = APFloat(APFloat::Float8E4M3FN(), APInt(8, i));
5393 expected = APFloat(APFloat::Float8E4M3FN(), APInt(8, i - 1));
5394 EXPECT_EQ(test.next(false), APFloat::opOK);
5395 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5396 }
5397
5398 // nextUp on NaN
5399 test = APFloat::getQNaN(Sem: APFloat::Float8E4M3FN(), Negative: false);
5400 expected = APFloat::getQNaN(Sem: APFloat::Float8E4M3FN(), Negative: false);
5401 EXPECT_EQ(test.next(false), APFloat::opOK);
5402 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5403
5404 // nextDown on positive nonzero finite numbers
5405 for (int i = 1; i < 127; i++) {
5406 test = APFloat(APFloat::Float8E4M3FN(), APInt(8, i));
5407 expected = APFloat(APFloat::Float8E4M3FN(), APInt(8, i - 1));
5408 EXPECT_EQ(test.next(true), APFloat::opOK);
5409 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5410 }
5411
5412 // nextDown on positive zero
5413 test = APFloat::getZero(Sem: APFloat::Float8E4M3FN(), Negative: true);
5414 expected = APFloat::getSmallest(Sem: APFloat::Float8E4M3FN(), Negative: true);
5415 EXPECT_EQ(test.next(true), APFloat::opOK);
5416 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5417
5418 // nextDown on negative finite numbers
5419 for (int i = 128; i < 255; i++) {
5420 test = APFloat(APFloat::Float8E4M3FN(), APInt(8, i));
5421 expected = APFloat(APFloat::Float8E4M3FN(), APInt(8, i + 1));
5422 EXPECT_EQ(test.next(true), APFloat::opOK);
5423 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5424 }
5425
5426 // nextDown on NaN
5427 test = APFloat::getQNaN(Sem: APFloat::Float8E4M3FN(), Negative: false);
5428 expected = APFloat::getQNaN(Sem: APFloat::Float8E4M3FN(), Negative: false);
5429 EXPECT_EQ(test.next(true), APFloat::opOK);
5430 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5431}
5432
5433TEST(APFloatTest, Float8E4M3FNExhaustive) {
5434 // Test each of the 256 Float8E4M3FN values.
5435 for (int i = 0; i < 256; i++) {
5436 APFloat test(APFloat::Float8E4M3FN(), APInt(8, i));
5437 SCOPED_TRACE("i=" + std::to_string(i));
5438
5439 // isLargest
5440 if (i == 126 || i == 254) {
5441 EXPECT_TRUE(test.isLargest());
5442 EXPECT_EQ(abs(test).convertToDouble(), 448.);
5443 } else {
5444 EXPECT_FALSE(test.isLargest());
5445 }
5446
5447 // isSmallest
5448 if (i == 1 || i == 129) {
5449 EXPECT_TRUE(test.isSmallest());
5450 EXPECT_EQ(abs(test).convertToDouble(), 0x1p-9);
5451 } else {
5452 EXPECT_FALSE(test.isSmallest());
5453 }
5454
5455 // convert to BFloat
5456 APFloat test2 = test;
5457 bool losesInfo;
5458 APFloat::opStatus status = test2.convert(
5459 ToSemantics: APFloat::BFloat(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5460 EXPECT_EQ(status, APFloat::opOK);
5461 EXPECT_FALSE(losesInfo);
5462 if (i == 127 || i == 255)
5463 EXPECT_TRUE(test2.isNaN());
5464 else
5465 EXPECT_EQ(test.convertToFloat(), test2.convertToFloat());
5466
5467 // bitcastToAPInt
5468 EXPECT_EQ(i, test.bitcastToAPInt());
5469 }
5470}
5471
5472TEST(APFloatTest, Float8E5M2FNUZNext) {
5473 APFloat test(APFloat::Float8E5M2FNUZ(), APFloat::uninitialized);
5474 APFloat expected(APFloat::Float8E5M2FNUZ(), APFloat::uninitialized);
5475
5476 // 1. NextUp of largest bit pattern is nan
5477 test = APFloat::getLargest(Sem: APFloat::Float8E5M2FNUZ());
5478 expected = APFloat::getNaN(Sem: APFloat::Float8E5M2FNUZ());
5479 EXPECT_EQ(test.next(false), APFloat::opOK);
5480 EXPECT_FALSE(test.isInfinity());
5481 EXPECT_FALSE(test.isZero());
5482 EXPECT_TRUE(test.isNaN());
5483 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5484
5485 // 2. NextUp of smallest negative denormal is +0
5486 test = APFloat::getSmallest(Sem: APFloat::Float8E5M2FNUZ(), Negative: true);
5487 expected = APFloat::getZero(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
5488 EXPECT_EQ(test.next(false), APFloat::opOK);
5489 EXPECT_FALSE(test.isNegZero());
5490 EXPECT_TRUE(test.isPosZero());
5491 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5492
5493 // 3. nextDown of negative of largest value is NaN
5494 test = APFloat::getLargest(Sem: APFloat::Float8E5M2FNUZ(), Negative: true);
5495 expected = APFloat::getNaN(Sem: APFloat::Float8E5M2FNUZ());
5496 EXPECT_EQ(test.next(true), APFloat::opOK);
5497 EXPECT_FALSE(test.isInfinity());
5498 EXPECT_FALSE(test.isZero());
5499 EXPECT_TRUE(test.isNaN());
5500 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5501
5502 // 4. nextDown of +0 is smallest negative denormal
5503 test = APFloat::getZero(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
5504 expected = APFloat::getSmallest(Sem: APFloat::Float8E5M2FNUZ(), Negative: true);
5505 EXPECT_EQ(test.next(true), APFloat::opOK);
5506 EXPECT_FALSE(test.isZero());
5507 EXPECT_TRUE(test.isDenormal());
5508 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5509
5510 // 5. nextUp of NaN is NaN
5511 test = APFloat::getNaN(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
5512 expected = APFloat::getNaN(Sem: APFloat::Float8E5M2FNUZ(), Negative: true);
5513 EXPECT_EQ(test.next(false), APFloat::opOK);
5514 EXPECT_TRUE(test.isNaN());
5515
5516 // 6. nextDown of NaN is NaN
5517 test = APFloat::getNaN(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
5518 expected = APFloat::getNaN(Sem: APFloat::Float8E5M2FNUZ(), Negative: true);
5519 EXPECT_EQ(test.next(true), APFloat::opOK);
5520 EXPECT_TRUE(test.isNaN());
5521}
5522
5523TEST(APFloatTest, Float8E5M2FNUZChangeSign) {
5524 APFloat test = APFloat(APFloat::Float8E5M2FNUZ(), "1.0");
5525 APFloat expected = APFloat(APFloat::Float8E5M2FNUZ(), "-1.0");
5526 test.changeSign();
5527 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5528
5529 test = APFloat::getZero(Sem: APFloat::Float8E5M2FNUZ());
5530 expected = test;
5531 test.changeSign();
5532 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5533
5534 test = APFloat::getNaN(Sem: APFloat::Float8E5M2FNUZ());
5535 expected = test;
5536 test.changeSign();
5537 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5538}
5539
5540TEST(APFloatTest, Float8E5M2FNUZFromString) {
5541 // Exactly representable
5542 EXPECT_EQ(57344,
5543 APFloat(APFloat::Float8E5M2FNUZ(), "57344").convertToDouble());
5544 // Round down to maximum value
5545 EXPECT_EQ(57344,
5546 APFloat(APFloat::Float8E5M2FNUZ(), "59392").convertToDouble());
5547 // Round up, causing overflow to NaN
5548 EXPECT_TRUE(APFloat(APFloat::Float8E5M2FNUZ(), "61440").isNaN());
5549 // Overflow without rounding
5550 EXPECT_TRUE(APFloat(APFloat::Float8E5M2FNUZ(), "131072").isNaN());
5551 // Inf converted to NaN
5552 EXPECT_TRUE(APFloat(APFloat::Float8E5M2FNUZ(), "inf").isNaN());
5553 // NaN converted to NaN
5554 EXPECT_TRUE(APFloat(APFloat::Float8E5M2FNUZ(), "nan").isNaN());
5555 // Negative zero converted to positive zero
5556 EXPECT_TRUE(APFloat(APFloat::Float8E5M2FNUZ(), "-0").isPosZero());
5557}
5558
5559TEST(APFloatTest, UnsignedZeroArithmeticSpecial) {
5560 // Float semantics with only unsigned zero (ex. Float8E4M3FNUZ) violate the
5561 // IEEE rules about signs in arithmetic operations when producing zeros,
5562 // because they only have one zero. Most of the rest of the complexities of
5563 // arithmetic on these values are covered by the other Float8 types' test
5564 // cases and so are not repeated here.
5565
5566 // The IEEE round towards negative rule doesn't apply
5567 for (APFloat::Semantics S :
5568 {APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) {
5569 const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S);
5570 APFloat test = APFloat::getSmallest(Sem);
5571 APFloat rhs = test;
5572 EXPECT_EQ(test.subtract(rhs, APFloat::rmTowardNegative), APFloat::opOK);
5573 EXPECT_TRUE(test.isZero());
5574 EXPECT_FALSE(test.isNegative());
5575
5576 // Multiplication of (small) * (-small) is +0
5577 test = APFloat::getSmallestNormalized(Sem);
5578 rhs = -test;
5579 EXPECT_EQ(test.multiply(rhs, APFloat::rmNearestTiesToAway),
5580 APFloat::opInexact | APFloat::opUnderflow);
5581 EXPECT_TRUE(test.isZero());
5582 EXPECT_FALSE(test.isNegative());
5583
5584 // Dividing the negatize float_min by anything gives +0
5585 test = APFloat::getSmallest(Sem, Negative: true);
5586 rhs = APFloat(Sem, "2.0");
5587 EXPECT_EQ(test.divide(rhs, APFloat::rmNearestTiesToEven),
5588 APFloat::opInexact | APFloat::opUnderflow);
5589 EXPECT_TRUE(test.isZero());
5590 EXPECT_FALSE(test.isNegative());
5591
5592 // Remainder can't copy sign because there's only one zero
5593 test = APFloat(Sem, "-4.0");
5594 rhs = APFloat(Sem, "2.0");
5595 EXPECT_EQ(test.remainder(rhs), APFloat::opOK);
5596 EXPECT_TRUE(test.isZero());
5597 EXPECT_FALSE(test.isNegative());
5598
5599 // And same for mod
5600 test = APFloat(Sem, "-4.0");
5601 rhs = APFloat(Sem, "2.0");
5602 EXPECT_EQ(test.mod(rhs), APFloat::opOK);
5603 EXPECT_TRUE(test.isZero());
5604 EXPECT_FALSE(test.isNegative());
5605
5606 // FMA correctly handles both the multiply and add parts of all this
5607 test = APFloat(Sem, "2.0");
5608 rhs = test;
5609 APFloat addend = APFloat(Sem, "-4.0");
5610 EXPECT_EQ(test.fusedMultiplyAdd(rhs, addend, APFloat::rmTowardNegative),
5611 APFloat::opOK);
5612 EXPECT_TRUE(test.isZero());
5613 EXPECT_FALSE(test.isNegative());
5614 }
5615}
5616
5617TEST(APFloatTest, Float8E5M2FNUZAdd) {
5618 APFloat QNaN = APFloat::getNaN(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
5619
5620 auto FromStr = [](StringRef S) {
5621 return APFloat(APFloat::Float8E5M2FNUZ(), S);
5622 };
5623
5624 struct {
5625 APFloat x;
5626 APFloat y;
5627 const char *result;
5628 int status;
5629 int category;
5630 APFloat::roundingMode roundingMode = APFloat::rmNearestTiesToEven;
5631 } AdditionTests[] = {
5632 // Test addition operations involving NaN, overflow, and the max E5M2FNUZ
5633 // value (57344) because E5M2FNUZ differs from IEEE-754 types in these
5634 // regards
5635 {.x: FromStr("57344"), .y: FromStr("2048"), .result: "57344", .status: APFloat::opInexact,
5636 .category: APFloat::fcNormal},
5637 {.x: FromStr("57344"), .y: FromStr("4096"), .result: "NaN",
5638 .status: APFloat::opOverflow | APFloat::opInexact, .category: APFloat::fcNaN},
5639 {.x: FromStr("-57344"), .y: FromStr("-4096"), .result: "NaN",
5640 .status: APFloat::opOverflow | APFloat::opInexact, .category: APFloat::fcNaN},
5641 {.x: QNaN, .y: FromStr("-57344"), .result: "NaN", .status: APFloat::opOK, .category: APFloat::fcNaN},
5642 {.x: FromStr("57344"), .y: FromStr("-8192"), .result: "49152", .status: APFloat::opOK,
5643 .category: APFloat::fcNormal},
5644 {.x: FromStr("57344"), .y: FromStr("0"), .result: "57344", .status: APFloat::opOK,
5645 .category: APFloat::fcNormal},
5646 {.x: FromStr("57344"), .y: FromStr("4096"), .result: "57344", .status: APFloat::opInexact,
5647 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardZero},
5648 {.x: FromStr("57344"), .y: FromStr("57344"), .result: "57344", .status: APFloat::opInexact,
5649 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardZero},
5650 };
5651
5652 for (size_t i = 0; i < std::size(AdditionTests); ++i) {
5653 APFloat x(AdditionTests[i].x);
5654 APFloat y(AdditionTests[i].y);
5655 APFloat::opStatus status = x.add(RHS: y, RM: AdditionTests[i].roundingMode);
5656
5657 APFloat result(APFloat::Float8E5M2FNUZ(), AdditionTests[i].result);
5658
5659 EXPECT_TRUE(result.bitwiseIsEqual(x));
5660 EXPECT_EQ(AdditionTests[i].status, (int)status);
5661 EXPECT_EQ(AdditionTests[i].category, (int)x.getCategory());
5662 }
5663}
5664
5665TEST(APFloatTest, Float8E5M2FNUZDivideByZero) {
5666 APFloat x(APFloat::Float8E5M2FNUZ(), "1");
5667 APFloat zero(APFloat::Float8E5M2FNUZ(), "0");
5668 EXPECT_EQ(x.divide(zero, APFloat::rmNearestTiesToEven), APFloat::opDivByZero);
5669 EXPECT_TRUE(x.isNaN());
5670}
5671
5672TEST(APFloatTest, Float8UnsignedZeroExhaustive) {
5673 struct {
5674 const fltSemantics *semantics;
5675 const double largest;
5676 const double smallest;
5677 } const exhaustiveTests[] = {{.semantics: &APFloat::Float8E5M2FNUZ(), .largest: 57344., .smallest: 0x1.0p-17},
5678 {.semantics: &APFloat::Float8E4M3FNUZ(), .largest: 240., .smallest: 0x1.0p-10},
5679 {.semantics: &APFloat::Float8E4M3B11FNUZ(), .largest: 30., .smallest: 0x1.0p-13}};
5680 for (const auto &testInfo : exhaustiveTests) {
5681 const fltSemantics &sem = *testInfo.semantics;
5682 SCOPED_TRACE("Semantics=" + std::to_string(APFloat::SemanticsToEnum(sem)));
5683 // Test each of the 256 values.
5684 for (int i = 0; i < 256; i++) {
5685 SCOPED_TRACE("i=" + std::to_string(i));
5686 APFloat test(sem, APInt(8, i));
5687
5688 // isLargest
5689 if (i == 127 || i == 255) {
5690 EXPECT_TRUE(test.isLargest());
5691 EXPECT_EQ(abs(test).convertToDouble(), testInfo.largest);
5692 } else {
5693 EXPECT_FALSE(test.isLargest());
5694 }
5695
5696 // isSmallest
5697 if (i == 1 || i == 129) {
5698 EXPECT_TRUE(test.isSmallest());
5699 EXPECT_EQ(abs(test).convertToDouble(), testInfo.smallest);
5700 } else {
5701 EXPECT_FALSE(test.isSmallest());
5702 }
5703
5704 // convert to BFloat
5705 APFloat test2 = test;
5706 bool losesInfo;
5707 APFloat::opStatus status = test2.convert(
5708 ToSemantics: APFloat::BFloat(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5709 EXPECT_EQ(status, APFloat::opOK);
5710 EXPECT_FALSE(losesInfo);
5711 if (i == 128)
5712 EXPECT_TRUE(test2.isNaN());
5713 else
5714 EXPECT_EQ(test.convertToFloat(), test2.convertToFloat());
5715
5716 // bitcastToAPInt
5717 EXPECT_EQ(i, test.bitcastToAPInt());
5718 }
5719 }
5720}
5721
5722TEST(APFloatTest, Float8E4M3FNUZNext) {
5723 for (APFloat::Semantics S :
5724 {APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) {
5725 const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S);
5726 APFloat test(Sem, APFloat::uninitialized);
5727 APFloat expected(Sem, APFloat::uninitialized);
5728
5729 // 1. NextUp of largest bit pattern is nan
5730 test = APFloat::getLargest(Sem);
5731 expected = APFloat::getNaN(Sem);
5732 EXPECT_EQ(test.next(false), APFloat::opOK);
5733 EXPECT_FALSE(test.isInfinity());
5734 EXPECT_FALSE(test.isZero());
5735 EXPECT_TRUE(test.isNaN());
5736 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5737
5738 // 2. NextUp of smallest negative denormal is +0
5739 test = APFloat::getSmallest(Sem, Negative: true);
5740 expected = APFloat::getZero(Sem, Negative: false);
5741 EXPECT_EQ(test.next(false), APFloat::opOK);
5742 EXPECT_FALSE(test.isNegZero());
5743 EXPECT_TRUE(test.isPosZero());
5744 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5745
5746 // 3. nextDown of negative of largest value is NaN
5747 test = APFloat::getLargest(Sem, Negative: true);
5748 expected = APFloat::getNaN(Sem);
5749 EXPECT_EQ(test.next(true), APFloat::opOK);
5750 EXPECT_FALSE(test.isInfinity());
5751 EXPECT_FALSE(test.isZero());
5752 EXPECT_TRUE(test.isNaN());
5753 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5754
5755 // 4. nextDown of +0 is smallest negative denormal
5756 test = APFloat::getZero(Sem, Negative: false);
5757 expected = APFloat::getSmallest(Sem, Negative: true);
5758 EXPECT_EQ(test.next(true), APFloat::opOK);
5759 EXPECT_FALSE(test.isZero());
5760 EXPECT_TRUE(test.isDenormal());
5761 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5762
5763 // 5. nextUp of NaN is NaN
5764 test = APFloat::getNaN(Sem, Negative: false);
5765 expected = APFloat::getNaN(Sem, Negative: true);
5766 EXPECT_EQ(test.next(false), APFloat::opOK);
5767 EXPECT_TRUE(test.isNaN());
5768
5769 // 6. nextDown of NaN is NaN
5770 test = APFloat::getNaN(Sem, Negative: false);
5771 expected = APFloat::getNaN(Sem, Negative: true);
5772 EXPECT_EQ(test.next(true), APFloat::opOK);
5773 EXPECT_TRUE(test.isNaN());
5774 }
5775}
5776
5777TEST(APFloatTest, Float8E4M3FNUZChangeSign) {
5778 for (APFloat::Semantics S :
5779 {APFloat::S_Float8E4M3FNUZ, APFloat::S_Float8E4M3B11FNUZ}) {
5780 const llvm::fltSemantics &Sem = APFloat::EnumToSemantics(S);
5781 APFloat test = APFloat(Sem, "1.0");
5782 APFloat expected = APFloat(Sem, "-1.0");
5783 test.changeSign();
5784 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5785
5786 test = APFloat::getZero(Sem);
5787 expected = test;
5788 test.changeSign();
5789 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5790
5791 test = APFloat::getNaN(Sem);
5792 expected = test;
5793 test.changeSign();
5794 EXPECT_TRUE(test.bitwiseIsEqual(expected));
5795 }
5796}
5797
5798TEST(APFloatTest, Float8E4M3FNUZFromString) {
5799 // Exactly representable
5800 EXPECT_EQ(240, APFloat(APFloat::Float8E4M3FNUZ(), "240").convertToDouble());
5801 // Round down to maximum value
5802 EXPECT_EQ(240, APFloat(APFloat::Float8E4M3FNUZ(), "247").convertToDouble());
5803 // Round up, causing overflow to NaN
5804 EXPECT_TRUE(APFloat(APFloat::Float8E4M3FNUZ(), "248").isNaN());
5805 // Overflow without rounding
5806 EXPECT_TRUE(APFloat(APFloat::Float8E4M3FNUZ(), "480").isNaN());
5807 // Inf converted to NaN
5808 EXPECT_TRUE(APFloat(APFloat::Float8E4M3FNUZ(), "inf").isNaN());
5809 // NaN converted to NaN
5810 EXPECT_TRUE(APFloat(APFloat::Float8E4M3FNUZ(), "nan").isNaN());
5811 // Negative zero converted to positive zero
5812 EXPECT_TRUE(APFloat(APFloat::Float8E4M3FNUZ(), "-0").isPosZero());
5813}
5814
5815TEST(APFloatTest, Float8E4M3FNUZAdd) {
5816 APFloat QNaN = APFloat::getNaN(Sem: APFloat::Float8E4M3FNUZ(), Negative: false);
5817
5818 auto FromStr = [](StringRef S) {
5819 return APFloat(APFloat::Float8E4M3FNUZ(), S);
5820 };
5821
5822 struct {
5823 APFloat x;
5824 APFloat y;
5825 const char *result;
5826 int status;
5827 int category;
5828 APFloat::roundingMode roundingMode = APFloat::rmNearestTiesToEven;
5829 } AdditionTests[] = {
5830 // Test addition operations involving NaN, overflow, and the max E4M3FNUZ
5831 // value (240) because E4M3FNUZ differs from IEEE-754 types in these
5832 // regards
5833 {.x: FromStr("240"), .y: FromStr("4"), .result: "240", .status: APFloat::opInexact,
5834 .category: APFloat::fcNormal},
5835 {.x: FromStr("240"), .y: FromStr("8"), .result: "NaN",
5836 .status: APFloat::opOverflow | APFloat::opInexact, .category: APFloat::fcNaN},
5837 {.x: FromStr("240"), .y: FromStr("16"), .result: "NaN",
5838 .status: APFloat::opOverflow | APFloat::opInexact, .category: APFloat::fcNaN},
5839 {.x: FromStr("-240"), .y: FromStr("-16"), .result: "NaN",
5840 .status: APFloat::opOverflow | APFloat::opInexact, .category: APFloat::fcNaN},
5841 {.x: QNaN, .y: FromStr("-240"), .result: "NaN", .status: APFloat::opOK, .category: APFloat::fcNaN},
5842 {.x: FromStr("240"), .y: FromStr("-16"), .result: "224", .status: APFloat::opOK, .category: APFloat::fcNormal},
5843 {.x: FromStr("240"), .y: FromStr("0"), .result: "240", .status: APFloat::opOK, .category: APFloat::fcNormal},
5844 {.x: FromStr("240"), .y: FromStr("32"), .result: "240", .status: APFloat::opInexact,
5845 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardZero},
5846 {.x: FromStr("240"), .y: FromStr("240"), .result: "240", .status: APFloat::opInexact,
5847 .category: APFloat::fcNormal, .roundingMode: APFloat::rmTowardZero},
5848 };
5849
5850 for (size_t i = 0; i < std::size(AdditionTests); ++i) {
5851 APFloat x(AdditionTests[i].x);
5852 APFloat y(AdditionTests[i].y);
5853 APFloat::opStatus status = x.add(RHS: y, RM: AdditionTests[i].roundingMode);
5854
5855 APFloat result(APFloat::Float8E4M3FNUZ(), AdditionTests[i].result);
5856
5857 EXPECT_TRUE(result.bitwiseIsEqual(x));
5858 EXPECT_EQ(AdditionTests[i].status, (int)status);
5859 EXPECT_EQ(AdditionTests[i].category, (int)x.getCategory());
5860 }
5861}
5862
5863TEST(APFloatTest, Float8E4M3FNUZDivideByZero) {
5864 APFloat x(APFloat::Float8E4M3FNUZ(), "1");
5865 APFloat zero(APFloat::Float8E4M3FNUZ(), "0");
5866 EXPECT_EQ(x.divide(zero, APFloat::rmNearestTiesToEven), APFloat::opDivByZero);
5867 EXPECT_TRUE(x.isNaN());
5868}
5869
5870TEST(APFloatTest, ConvertE5M2FNUZToE4M3FNUZ) {
5871 bool losesInfo;
5872 APFloat test(APFloat::Float8E5M2FNUZ(), "1.0");
5873 APFloat::opStatus status = test.convert(
5874 ToSemantics: APFloat::Float8E4M3FNUZ(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5875 EXPECT_EQ(1.0f, test.convertToFloat());
5876 EXPECT_FALSE(losesInfo);
5877 EXPECT_EQ(status, APFloat::opOK);
5878
5879 losesInfo = true;
5880 test = APFloat(APFloat::Float8E5M2FNUZ(), "0.0");
5881 status = test.convert(ToSemantics: APFloat::Float8E4M3FNUZ(), RM: APFloat::rmNearestTiesToEven,
5882 losesInfo: &losesInfo);
5883 EXPECT_EQ(0.0f, test.convertToFloat());
5884 EXPECT_FALSE(losesInfo);
5885 EXPECT_EQ(status, APFloat::opOK);
5886
5887 losesInfo = true;
5888 test = APFloat(APFloat::Float8E5M2FNUZ(), "0x1.Cp7"); // 224
5889 status = test.convert(ToSemantics: APFloat::Float8E4M3FNUZ(), RM: APFloat::rmNearestTiesToEven,
5890 losesInfo: &losesInfo);
5891 EXPECT_EQ(0x1.Cp7 /* 224 */, test.convertToFloat());
5892 EXPECT_FALSE(losesInfo);
5893 EXPECT_EQ(status, APFloat::opOK);
5894
5895 // Test overflow
5896 losesInfo = false;
5897 test = APFloat(APFloat::Float8E5M2FNUZ(), "0x1.0p8"); // 256
5898 status = test.convert(ToSemantics: APFloat::Float8E4M3FNUZ(), RM: APFloat::rmNearestTiesToEven,
5899 losesInfo: &losesInfo);
5900 EXPECT_TRUE(std::isnan(test.convertToFloat()));
5901 EXPECT_TRUE(losesInfo);
5902 EXPECT_EQ(status, APFloat::opOverflow | APFloat::opInexact);
5903
5904 // Test underflow
5905 test = APFloat(APFloat::Float8E5M2FNUZ(), "0x1.0p-11");
5906 status = test.convert(ToSemantics: APFloat::Float8E4M3FNUZ(), RM: APFloat::rmNearestTiesToEven,
5907 losesInfo: &losesInfo);
5908 EXPECT_EQ(0., test.convertToFloat());
5909 EXPECT_TRUE(losesInfo);
5910 EXPECT_EQ(status, APFloat::opUnderflow | APFloat::opInexact);
5911
5912 // Test rounding up to smallest denormal number
5913 losesInfo = false;
5914 test = APFloat(APFloat::Float8E5M2FNUZ(), "0x1.8p-11");
5915 status = test.convert(ToSemantics: APFloat::Float8E4M3FNUZ(), RM: APFloat::rmNearestTiesToEven,
5916 losesInfo: &losesInfo);
5917 EXPECT_EQ(0x1.0p-10, test.convertToFloat());
5918 EXPECT_TRUE(losesInfo);
5919 EXPECT_EQ(status, APFloat::opUnderflow | APFloat::opInexact);
5920
5921 // Testing inexact rounding to denormal number
5922 losesInfo = false;
5923 test = APFloat(APFloat::Float8E5M2FNUZ(), "0x1.8p-10");
5924 status = test.convert(ToSemantics: APFloat::Float8E4M3FNUZ(), RM: APFloat::rmNearestTiesToEven,
5925 losesInfo: &losesInfo);
5926 EXPECT_EQ(0x1.0p-9, test.convertToFloat());
5927 EXPECT_TRUE(losesInfo);
5928 EXPECT_EQ(status, APFloat::opUnderflow | APFloat::opInexact);
5929}
5930
5931TEST(APFloatTest, ConvertE4M3FNUZToE5M2FNUZ) {
5932 bool losesInfo;
5933 APFloat test(APFloat::Float8E4M3FNUZ(), "1.0");
5934 APFloat::opStatus status = test.convert(
5935 ToSemantics: APFloat::Float8E5M2FNUZ(), RM: APFloat::rmNearestTiesToEven, losesInfo: &losesInfo);
5936 EXPECT_EQ(1.0f, test.convertToFloat());
5937 EXPECT_FALSE(losesInfo);
5938 EXPECT_EQ(status, APFloat::opOK);
5939
5940 losesInfo = true;
5941 test = APFloat(APFloat::Float8E4M3FNUZ(), "0.0");
5942 status = test.convert(ToSemantics: APFloat::Float8E5M2FNUZ(), RM: APFloat::rmNearestTiesToEven,
5943 losesInfo: &losesInfo);
5944 EXPECT_EQ(0.0f, test.convertToFloat());
5945 EXPECT_FALSE(losesInfo);
5946 EXPECT_EQ(status, APFloat::opOK);
5947
5948 losesInfo = false;
5949 test = APFloat(APFloat::Float8E4M3FNUZ(), "0x1.2p0"); // 1.125
5950 status = test.convert(ToSemantics: APFloat::Float8E5M2FNUZ(), RM: APFloat::rmNearestTiesToEven,
5951 losesInfo: &losesInfo);
5952 EXPECT_EQ(0x1.0p0 /* 1.0 */, test.convertToFloat());
5953 EXPECT_TRUE(losesInfo);
5954 EXPECT_EQ(status, APFloat::opInexact);
5955
5956 losesInfo = false;
5957 test = APFloat(APFloat::Float8E4M3FNUZ(), "0x1.6p0"); // 1.375
5958 status = test.convert(ToSemantics: APFloat::Float8E5M2FNUZ(), RM: APFloat::rmNearestTiesToEven,
5959 losesInfo: &losesInfo);
5960 EXPECT_EQ(0x1.8p0 /* 1.5 */, test.convertToFloat());
5961 EXPECT_TRUE(losesInfo);
5962 EXPECT_EQ(status, APFloat::opInexact);
5963
5964 // Convert E4M3 denormal to E5M2 normal. Should not be truncated, despite the
5965 // destination format having one fewer significand bit
5966 losesInfo = true;
5967 test = APFloat(APFloat::Float8E4M3FNUZ(), "0x1.Cp-8");
5968 status = test.convert(ToSemantics: APFloat::Float8E5M2FNUZ(), RM: APFloat::rmNearestTiesToEven,
5969 losesInfo: &losesInfo);
5970 EXPECT_EQ(0x1.Cp-8, test.convertToFloat());
5971 EXPECT_FALSE(losesInfo);
5972 EXPECT_EQ(status, APFloat::opOK);
5973}
5974
5975TEST(APFloatTest, F8ToString) {
5976 for (APFloat::Semantics S :
5977 {APFloat::S_Float8E5M2, APFloat::S_Float8E4M3FN,
5978 APFloat::S_Float8E5M2FNUZ, APFloat::S_Float8E4M3FNUZ,
5979 APFloat::S_Float8E4M3B11FNUZ}) {
5980 SCOPED_TRACE("Semantics=" + std::to_string(S));
5981 for (int i = 0; i < 256; i++) {
5982 SCOPED_TRACE("i=" + std::to_string(i));
5983 APFloat test(APFloat::EnumToSemantics(S), APInt(8, i));
5984 llvm::SmallString<128> str;
5985 test.toString(Str&: str);
5986
5987 if (test.isNaN()) {
5988 EXPECT_EQ(str, "NaN");
5989 } else {
5990 APFloat test2(APFloat::EnumToSemantics(S), str);
5991 EXPECT_TRUE(test.bitwiseIsEqual(test2));
5992 }
5993 }
5994 }
5995}
5996
5997TEST(APFloatTest, BitsToF8ToBits) {
5998 for (APFloat::Semantics S :
5999 {APFloat::S_Float8E5M2, APFloat::S_Float8E4M3FN,
6000 APFloat::S_Float8E5M2FNUZ, APFloat::S_Float8E4M3FNUZ,
6001 APFloat::S_Float8E4M3B11FNUZ}) {
6002 SCOPED_TRACE("Semantics=" + std::to_string(S));
6003 for (int i = 0; i < 256; i++) {
6004 SCOPED_TRACE("i=" + std::to_string(i));
6005 APInt bits_in = APInt(8, i);
6006 APFloat test(APFloat::EnumToSemantics(S), bits_in);
6007 APInt bits_out = test.bitcastToAPInt();
6008 EXPECT_EQ(bits_in, bits_out);
6009 }
6010 }
6011}
6012
6013TEST(APFloatTest, F8ToBitsToF8) {
6014 for (APFloat::Semantics S :
6015 {APFloat::S_Float8E5M2, APFloat::S_Float8E4M3FN,
6016 APFloat::S_Float8E5M2FNUZ, APFloat::S_Float8E4M3FNUZ,
6017 APFloat::S_Float8E4M3B11FNUZ}) {
6018 SCOPED_TRACE("Semantics=" + std::to_string(S));
6019 auto &Sem = APFloat::EnumToSemantics(S);
6020 for (bool negative : {false, true}) {
6021 SCOPED_TRACE("negative=" + std::to_string(negative));
6022 APFloat test = APFloat::getZero(Sem, /*Negative=*/negative);
6023 for (int i = 0; i < 128; i++, test.next(/*nextDown=*/negative)) {
6024 SCOPED_TRACE("i=" + std::to_string(i));
6025 APInt bits = test.bitcastToAPInt();
6026 APFloat test2 = APFloat(Sem, bits);
6027 if (test.isNaN()) {
6028 EXPECT_TRUE(test2.isNaN());
6029 } else {
6030 EXPECT_TRUE(test.bitwiseIsEqual(test2));
6031 }
6032 }
6033 }
6034 }
6035}
6036
6037TEST(APFloatTest, IEEEdoubleToDouble) {
6038 APFloat DPosZero(0.0);
6039 APFloat DPosZeroToDouble(DPosZero.convertToDouble());
6040 EXPECT_TRUE(DPosZeroToDouble.isPosZero());
6041 APFloat DNegZero(-0.0);
6042 APFloat DNegZeroToDouble(DNegZero.convertToDouble());
6043 EXPECT_TRUE(DNegZeroToDouble.isNegZero());
6044
6045 APFloat DOne(1.0);
6046 EXPECT_EQ(1.0, DOne.convertToDouble());
6047 APFloat DPosLargest = APFloat::getLargest(Sem: APFloat::IEEEdouble(), Negative: false);
6048 EXPECT_EQ(std::numeric_limits<double>::max(), DPosLargest.convertToDouble());
6049 APFloat DNegLargest = APFloat::getLargest(Sem: APFloat::IEEEdouble(), Negative: true);
6050 EXPECT_EQ(-std::numeric_limits<double>::max(), DNegLargest.convertToDouble());
6051 APFloat DPosSmallest =
6052 APFloat::getSmallestNormalized(Sem: APFloat::IEEEdouble(), Negative: false);
6053 EXPECT_EQ(std::numeric_limits<double>::min(), DPosSmallest.convertToDouble());
6054 APFloat DNegSmallest =
6055 APFloat::getSmallestNormalized(Sem: APFloat::IEEEdouble(), Negative: true);
6056 EXPECT_EQ(-std::numeric_limits<double>::min(),
6057 DNegSmallest.convertToDouble());
6058
6059 APFloat DSmallestDenorm = APFloat::getSmallest(Sem: APFloat::IEEEdouble(), Negative: false);
6060 EXPECT_EQ(std::numeric_limits<double>::denorm_min(),
6061 DSmallestDenorm.convertToDouble());
6062 APFloat DLargestDenorm(APFloat::IEEEdouble(), "0x0.FFFFFFFFFFFFFp-1022");
6063 EXPECT_EQ(/*0x0.FFFFFFFFFFFFFp-1022*/ 2.225073858507201e-308,
6064 DLargestDenorm.convertToDouble());
6065
6066 APFloat DPosInf = APFloat::getInf(Sem: APFloat::IEEEdouble());
6067 EXPECT_EQ(std::numeric_limits<double>::infinity(), DPosInf.convertToDouble());
6068 APFloat DNegInf = APFloat::getInf(Sem: APFloat::IEEEdouble(), Negative: true);
6069 EXPECT_EQ(-std::numeric_limits<double>::infinity(),
6070 DNegInf.convertToDouble());
6071 APFloat DQNaN = APFloat::getQNaN(Sem: APFloat::IEEEdouble());
6072 EXPECT_TRUE(std::isnan(DQNaN.convertToDouble()));
6073}
6074
6075TEST(APFloatTest, IEEEsingleToDouble) {
6076 APFloat FPosZero(0.0F);
6077 APFloat FPosZeroToDouble(FPosZero.convertToDouble());
6078 EXPECT_TRUE(FPosZeroToDouble.isPosZero());
6079 APFloat FNegZero(-0.0F);
6080 APFloat FNegZeroToDouble(FNegZero.convertToDouble());
6081 EXPECT_TRUE(FNegZeroToDouble.isNegZero());
6082
6083 APFloat FOne(1.0F);
6084 EXPECT_EQ(1.0, FOne.convertToDouble());
6085 APFloat FPosLargest = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: false);
6086 EXPECT_EQ(std::numeric_limits<float>::max(), FPosLargest.convertToDouble());
6087 APFloat FNegLargest = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: true);
6088 EXPECT_EQ(-std::numeric_limits<float>::max(), FNegLargest.convertToDouble());
6089 APFloat FPosSmallest =
6090 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: false);
6091 EXPECT_EQ(std::numeric_limits<float>::min(), FPosSmallest.convertToDouble());
6092 APFloat FNegSmallest =
6093 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: true);
6094 EXPECT_EQ(-std::numeric_limits<float>::min(), FNegSmallest.convertToDouble());
6095
6096 APFloat FSmallestDenorm = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: false);
6097 EXPECT_EQ(std::numeric_limits<float>::denorm_min(),
6098 FSmallestDenorm.convertToDouble());
6099 APFloat FLargestDenorm(APFloat::IEEEdouble(), "0x0.FFFFFEp-126");
6100 EXPECT_EQ(/*0x0.FFFFFEp-126*/ 1.1754942106924411e-38,
6101 FLargestDenorm.convertToDouble());
6102
6103 APFloat FPosInf = APFloat::getInf(Sem: APFloat::IEEEsingle());
6104 EXPECT_EQ(std::numeric_limits<double>::infinity(), FPosInf.convertToDouble());
6105 APFloat FNegInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
6106 EXPECT_EQ(-std::numeric_limits<double>::infinity(),
6107 FNegInf.convertToDouble());
6108 APFloat FQNaN = APFloat::getQNaN(Sem: APFloat::IEEEsingle());
6109 EXPECT_TRUE(std::isnan(FQNaN.convertToDouble()));
6110}
6111
6112TEST(APFloatTest, IEEEhalfToDouble) {
6113 APFloat HPosZero = APFloat::getZero(Sem: APFloat::IEEEhalf());
6114 APFloat HPosZeroToDouble(HPosZero.convertToDouble());
6115 EXPECT_TRUE(HPosZeroToDouble.isPosZero());
6116 APFloat HNegZero = APFloat::getZero(Sem: APFloat::IEEEhalf(), Negative: true);
6117 APFloat HNegZeroToDouble(HNegZero.convertToDouble());
6118 EXPECT_TRUE(HNegZeroToDouble.isNegZero());
6119
6120 APFloat HOne(APFloat::IEEEhalf(), "1.0");
6121 EXPECT_EQ(1.0, HOne.convertToDouble());
6122 APFloat HPosLargest = APFloat::getLargest(Sem: APFloat::IEEEhalf(), Negative: false);
6123 EXPECT_EQ(65504.0, HPosLargest.convertToDouble());
6124 APFloat HNegLargest = APFloat::getLargest(Sem: APFloat::IEEEhalf(), Negative: true);
6125 EXPECT_EQ(-65504.0, HNegLargest.convertToDouble());
6126 APFloat HPosSmallest =
6127 APFloat::getSmallestNormalized(Sem: APFloat::IEEEhalf(), Negative: false);
6128 EXPECT_EQ(/*0x1.p-14*/ 6.103515625e-05, HPosSmallest.convertToDouble());
6129 APFloat HNegSmallest =
6130 APFloat::getSmallestNormalized(Sem: APFloat::IEEEhalf(), Negative: true);
6131 EXPECT_EQ(/*-0x1.p-14*/ -6.103515625e-05, HNegSmallest.convertToDouble());
6132
6133 APFloat HSmallestDenorm = APFloat::getSmallest(Sem: APFloat::IEEEhalf(), Negative: false);
6134 EXPECT_EQ(/*0x1.p-24*/ 5.960464477539063e-08,
6135 HSmallestDenorm.convertToDouble());
6136 APFloat HLargestDenorm(APFloat::IEEEhalf(), "0x1.FFCp-14");
6137 EXPECT_EQ(/*0x1.FFCp-14*/ 0.00012201070785522461,
6138 HLargestDenorm.convertToDouble());
6139
6140 APFloat HPosInf = APFloat::getInf(Sem: APFloat::IEEEhalf());
6141 EXPECT_EQ(std::numeric_limits<double>::infinity(), HPosInf.convertToDouble());
6142 APFloat HNegInf = APFloat::getInf(Sem: APFloat::IEEEhalf(), Negative: true);
6143 EXPECT_EQ(-std::numeric_limits<double>::infinity(),
6144 HNegInf.convertToDouble());
6145 APFloat HQNaN = APFloat::getQNaN(Sem: APFloat::IEEEhalf());
6146 EXPECT_TRUE(std::isnan(HQNaN.convertToDouble()));
6147
6148 APFloat BPosZero = APFloat::getZero(Sem: APFloat::IEEEhalf());
6149 APFloat BPosZeroToDouble(BPosZero.convertToDouble());
6150 EXPECT_TRUE(BPosZeroToDouble.isPosZero());
6151 APFloat BNegZero = APFloat::getZero(Sem: APFloat::IEEEhalf(), Negative: true);
6152 APFloat BNegZeroToDouble(BNegZero.convertToDouble());
6153 EXPECT_TRUE(BNegZeroToDouble.isNegZero());
6154}
6155
6156TEST(APFloatTest, BFloatToDouble) {
6157 APFloat BOne(APFloat::BFloat(), "1.0");
6158 EXPECT_EQ(1.0, BOne.convertToDouble());
6159 APFloat BPosLargest = APFloat::getLargest(Sem: APFloat::BFloat(), Negative: false);
6160 EXPECT_EQ(/*0x1.FEp127*/ 3.3895313892515355e+38,
6161 BPosLargest.convertToDouble());
6162 APFloat BNegLargest = APFloat::getLargest(Sem: APFloat::BFloat(), Negative: true);
6163 EXPECT_EQ(/*-0x1.FEp127*/ -3.3895313892515355e+38,
6164 BNegLargest.convertToDouble());
6165 APFloat BPosSmallest =
6166 APFloat::getSmallestNormalized(Sem: APFloat::BFloat(), Negative: false);
6167 EXPECT_EQ(/*0x1.p-126*/ 1.1754943508222875e-38,
6168 BPosSmallest.convertToDouble());
6169 APFloat BNegSmallest =
6170 APFloat::getSmallestNormalized(Sem: APFloat::BFloat(), Negative: true);
6171 EXPECT_EQ(/*-0x1.p-126*/ -1.1754943508222875e-38,
6172 BNegSmallest.convertToDouble());
6173
6174 APFloat BSmallestDenorm = APFloat::getSmallest(Sem: APFloat::BFloat(), Negative: false);
6175 EXPECT_EQ(/*0x1.p-133*/ 9.183549615799121e-41,
6176 BSmallestDenorm.convertToDouble());
6177 APFloat BLargestDenorm(APFloat::BFloat(), "0x1.FCp-127");
6178 EXPECT_EQ(/*0x1.FCp-127*/ 1.1663108012064884e-38,
6179 BLargestDenorm.convertToDouble());
6180
6181 APFloat BPosInf = APFloat::getInf(Sem: APFloat::BFloat());
6182 EXPECT_EQ(std::numeric_limits<double>::infinity(), BPosInf.convertToDouble());
6183 APFloat BNegInf = APFloat::getInf(Sem: APFloat::BFloat(), Negative: true);
6184 EXPECT_EQ(-std::numeric_limits<double>::infinity(),
6185 BNegInf.convertToDouble());
6186 APFloat BQNaN = APFloat::getQNaN(Sem: APFloat::BFloat());
6187 EXPECT_TRUE(std::isnan(BQNaN.convertToDouble()));
6188}
6189
6190TEST(APFloatTest, Float8E5M2ToDouble) {
6191 APFloat One(APFloat::Float8E5M2(), "1.0");
6192 EXPECT_EQ(1.0, One.convertToDouble());
6193 APFloat Two(APFloat::Float8E5M2(), "2.0");
6194 EXPECT_EQ(2.0, Two.convertToDouble());
6195 APFloat PosLargest = APFloat::getLargest(Sem: APFloat::Float8E5M2(), Negative: false);
6196 EXPECT_EQ(5.734400e+04, PosLargest.convertToDouble());
6197 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::Float8E5M2(), Negative: true);
6198 EXPECT_EQ(-5.734400e+04, NegLargest.convertToDouble());
6199 APFloat PosSmallest =
6200 APFloat::getSmallestNormalized(Sem: APFloat::Float8E5M2(), Negative: false);
6201 EXPECT_EQ(0x1.p-14, PosSmallest.convertToDouble());
6202 APFloat NegSmallest =
6203 APFloat::getSmallestNormalized(Sem: APFloat::Float8E5M2(), Negative: true);
6204 EXPECT_EQ(-0x1.p-14, NegSmallest.convertToDouble());
6205
6206 APFloat SmallestDenorm = APFloat::getSmallest(Sem: APFloat::Float8E5M2(), Negative: false);
6207 EXPECT_TRUE(SmallestDenorm.isDenormal());
6208 EXPECT_EQ(0x1p-16, SmallestDenorm.convertToDouble());
6209
6210 APFloat PosInf = APFloat::getInf(Sem: APFloat::Float8E5M2());
6211 EXPECT_EQ(std::numeric_limits<double>::infinity(), PosInf.convertToDouble());
6212 APFloat NegInf = APFloat::getInf(Sem: APFloat::Float8E5M2(), Negative: true);
6213 EXPECT_EQ(-std::numeric_limits<double>::infinity(), NegInf.convertToDouble());
6214 APFloat QNaN = APFloat::getQNaN(Sem: APFloat::Float8E5M2());
6215 EXPECT_TRUE(std::isnan(QNaN.convertToDouble()));
6216}
6217
6218TEST(APFloatTest, Float8E4M3FNToDouble) {
6219 APFloat One(APFloat::Float8E4M3FN(), "1.0");
6220 EXPECT_EQ(1.0, One.convertToDouble());
6221 APFloat Two(APFloat::Float8E4M3FN(), "2.0");
6222 EXPECT_EQ(2.0, Two.convertToDouble());
6223 APFloat PosLargest = APFloat::getLargest(Sem: APFloat::Float8E4M3FN(), Negative: false);
6224 EXPECT_EQ(448., PosLargest.convertToDouble());
6225 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::Float8E4M3FN(), Negative: true);
6226 EXPECT_EQ(-448., NegLargest.convertToDouble());
6227 APFloat PosSmallest =
6228 APFloat::getSmallestNormalized(Sem: APFloat::Float8E4M3FN(), Negative: false);
6229 EXPECT_EQ(0x1.p-6, PosSmallest.convertToDouble());
6230 APFloat NegSmallest =
6231 APFloat::getSmallestNormalized(Sem: APFloat::Float8E4M3FN(), Negative: true);
6232 EXPECT_EQ(-0x1.p-6, NegSmallest.convertToDouble());
6233
6234 APFloat SmallestDenorm = APFloat::getSmallest(Sem: APFloat::Float8E4M3FN(), Negative: false);
6235 EXPECT_TRUE(SmallestDenorm.isDenormal());
6236 EXPECT_EQ(0x1p-9, SmallestDenorm.convertToDouble());
6237
6238 APFloat QNaN = APFloat::getQNaN(Sem: APFloat::Float8E4M3FN());
6239 EXPECT_TRUE(std::isnan(QNaN.convertToDouble()));
6240}
6241
6242TEST(APFloatTest, Float8E5M2FNUZToDouble) {
6243 APFloat One(APFloat::Float8E5M2FNUZ(), "1.0");
6244 EXPECT_EQ(1.0, One.convertToDouble());
6245 APFloat Two(APFloat::Float8E5M2FNUZ(), "2.0");
6246 EXPECT_EQ(2.0, Two.convertToDouble());
6247 APFloat PosLargest = APFloat::getLargest(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
6248 EXPECT_EQ(57344., PosLargest.convertToDouble());
6249 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::Float8E5M2FNUZ(), Negative: true);
6250 EXPECT_EQ(-57344., NegLargest.convertToDouble());
6251 APFloat PosSmallest =
6252 APFloat::getSmallestNormalized(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
6253 EXPECT_EQ(0x1.p-15, PosSmallest.convertToDouble());
6254 APFloat NegSmallest =
6255 APFloat::getSmallestNormalized(Sem: APFloat::Float8E5M2FNUZ(), Negative: true);
6256 EXPECT_EQ(-0x1.p-15, NegSmallest.convertToDouble());
6257
6258 APFloat SmallestDenorm =
6259 APFloat::getSmallest(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
6260 EXPECT_TRUE(SmallestDenorm.isDenormal());
6261 EXPECT_EQ(0x1p-17, SmallestDenorm.convertToDouble());
6262
6263 APFloat QNaN = APFloat::getQNaN(Sem: APFloat::Float8E5M2FNUZ());
6264 EXPECT_TRUE(std::isnan(QNaN.convertToDouble()));
6265}
6266
6267TEST(APFloatTest, Float8E4M3FNUZToDouble) {
6268 APFloat One(APFloat::Float8E4M3FNUZ(), "1.0");
6269 EXPECT_EQ(1.0, One.convertToDouble());
6270 APFloat Two(APFloat::Float8E4M3FNUZ(), "2.0");
6271 EXPECT_EQ(2.0, Two.convertToDouble());
6272 APFloat PosLargest = APFloat::getLargest(Sem: APFloat::Float8E4M3FNUZ(), Negative: false);
6273 EXPECT_EQ(240., PosLargest.convertToDouble());
6274 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::Float8E4M3FNUZ(), Negative: true);
6275 EXPECT_EQ(-240., NegLargest.convertToDouble());
6276 APFloat PosSmallest =
6277 APFloat::getSmallestNormalized(Sem: APFloat::Float8E4M3FNUZ(), Negative: false);
6278 EXPECT_EQ(0x1.p-7, PosSmallest.convertToDouble());
6279 APFloat NegSmallest =
6280 APFloat::getSmallestNormalized(Sem: APFloat::Float8E4M3FNUZ(), Negative: true);
6281 EXPECT_EQ(-0x1.p-7, NegSmallest.convertToDouble());
6282
6283 APFloat SmallestDenorm =
6284 APFloat::getSmallest(Sem: APFloat::Float8E4M3FNUZ(), Negative: false);
6285 EXPECT_TRUE(SmallestDenorm.isDenormal());
6286 EXPECT_EQ(0x1p-10, SmallestDenorm.convertToDouble());
6287
6288 APFloat QNaN = APFloat::getQNaN(Sem: APFloat::Float8E4M3FNUZ());
6289 EXPECT_TRUE(std::isnan(QNaN.convertToDouble()));
6290}
6291
6292TEST(APFloatTest, FloatTF32ToDouble) {
6293 APFloat One(APFloat::FloatTF32(), "1.0");
6294 EXPECT_EQ(1.0, One.convertToDouble());
6295 APFloat PosLargest = APFloat::getLargest(Sem: APFloat::FloatTF32(), Negative: false);
6296 EXPECT_EQ(3.401162134214653489792616e+38, PosLargest.convertToDouble());
6297 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::FloatTF32(), Negative: true);
6298 EXPECT_EQ(-3.401162134214653489792616e+38, NegLargest.convertToDouble());
6299 APFloat PosSmallest =
6300 APFloat::getSmallestNormalized(Sem: APFloat::FloatTF32(), Negative: false);
6301 EXPECT_EQ(1.1754943508222875079687e-38, PosSmallest.convertToDouble());
6302 APFloat NegSmallest =
6303 APFloat::getSmallestNormalized(Sem: APFloat::FloatTF32(), Negative: true);
6304 EXPECT_EQ(-1.1754943508222875079687e-38, NegSmallest.convertToDouble());
6305
6306 APFloat SmallestDenorm = APFloat::getSmallest(Sem: APFloat::FloatTF32(), Negative: false);
6307 EXPECT_EQ(1.1479437019748901445007e-41, SmallestDenorm.convertToDouble());
6308 APFloat LargestDenorm(APFloat::FloatTF32(), "0x1.FF8p-127");
6309 EXPECT_EQ(/*0x1.FF8p-127*/ 1.1743464071203126178242e-38,
6310 LargestDenorm.convertToDouble());
6311
6312 APFloat PosInf = APFloat::getInf(Sem: APFloat::FloatTF32());
6313 EXPECT_EQ(std::numeric_limits<double>::infinity(), PosInf.convertToDouble());
6314 APFloat NegInf = APFloat::getInf(Sem: APFloat::FloatTF32(), Negative: true);
6315 EXPECT_EQ(-std::numeric_limits<double>::infinity(), NegInf.convertToDouble());
6316 APFloat QNaN = APFloat::getQNaN(Sem: APFloat::FloatTF32());
6317 EXPECT_TRUE(std::isnan(QNaN.convertToDouble()));
6318}
6319
6320TEST(APFloatTest, Float8E5M2FNUZToFloat) {
6321 APFloat PosZero = APFloat::getZero(Sem: APFloat::Float8E5M2FNUZ());
6322 APFloat PosZeroToFloat(PosZero.convertToFloat());
6323 EXPECT_TRUE(PosZeroToFloat.isPosZero());
6324 // Negative zero is not supported
6325 APFloat NegZero = APFloat::getZero(Sem: APFloat::Float8E5M2FNUZ(), Negative: true);
6326 APFloat NegZeroToFloat(NegZero.convertToFloat());
6327 EXPECT_TRUE(NegZeroToFloat.isPosZero());
6328 APFloat One(APFloat::Float8E5M2FNUZ(), "1.0");
6329 EXPECT_EQ(1.0F, One.convertToFloat());
6330 APFloat Two(APFloat::Float8E5M2FNUZ(), "2.0");
6331 EXPECT_EQ(2.0F, Two.convertToFloat());
6332 APFloat PosLargest = APFloat::getLargest(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
6333 EXPECT_EQ(57344.F, PosLargest.convertToFloat());
6334 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::Float8E5M2FNUZ(), Negative: true);
6335 EXPECT_EQ(-57344.F, NegLargest.convertToFloat());
6336 APFloat PosSmallest =
6337 APFloat::getSmallestNormalized(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
6338 EXPECT_EQ(0x1.p-15F, PosSmallest.convertToFloat());
6339 APFloat NegSmallest =
6340 APFloat::getSmallestNormalized(Sem: APFloat::Float8E5M2FNUZ(), Negative: true);
6341 EXPECT_EQ(-0x1.p-15F, NegSmallest.convertToFloat());
6342
6343 APFloat SmallestDenorm =
6344 APFloat::getSmallest(Sem: APFloat::Float8E5M2FNUZ(), Negative: false);
6345 EXPECT_TRUE(SmallestDenorm.isDenormal());
6346 EXPECT_EQ(0x1p-17F, SmallestDenorm.convertToFloat());
6347
6348 APFloat QNaN = APFloat::getQNaN(Sem: APFloat::Float8E5M2FNUZ());
6349 EXPECT_TRUE(std::isnan(QNaN.convertToFloat()));
6350}
6351
6352TEST(APFloatTest, Float8E4M3FNUZToFloat) {
6353 APFloat PosZero = APFloat::getZero(Sem: APFloat::Float8E4M3FNUZ());
6354 APFloat PosZeroToFloat(PosZero.convertToFloat());
6355 EXPECT_TRUE(PosZeroToFloat.isPosZero());
6356 // Negative zero is not supported
6357 APFloat NegZero = APFloat::getZero(Sem: APFloat::Float8E4M3FNUZ(), Negative: true);
6358 APFloat NegZeroToFloat(NegZero.convertToFloat());
6359 EXPECT_TRUE(NegZeroToFloat.isPosZero());
6360 APFloat One(APFloat::Float8E4M3FNUZ(), "1.0");
6361 EXPECT_EQ(1.0F, One.convertToFloat());
6362 APFloat Two(APFloat::Float8E4M3FNUZ(), "2.0");
6363 EXPECT_EQ(2.0F, Two.convertToFloat());
6364 APFloat PosLargest = APFloat::getLargest(Sem: APFloat::Float8E4M3FNUZ(), Negative: false);
6365 EXPECT_EQ(240.F, PosLargest.convertToFloat());
6366 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::Float8E4M3FNUZ(), Negative: true);
6367 EXPECT_EQ(-240.F, NegLargest.convertToFloat());
6368 APFloat PosSmallest =
6369 APFloat::getSmallestNormalized(Sem: APFloat::Float8E4M3FNUZ(), Negative: false);
6370 EXPECT_EQ(0x1.p-7F, PosSmallest.convertToFloat());
6371 APFloat NegSmallest =
6372 APFloat::getSmallestNormalized(Sem: APFloat::Float8E4M3FNUZ(), Negative: true);
6373 EXPECT_EQ(-0x1.p-7F, NegSmallest.convertToFloat());
6374
6375 APFloat SmallestDenorm =
6376 APFloat::getSmallest(Sem: APFloat::Float8E4M3FNUZ(), Negative: false);
6377 EXPECT_TRUE(SmallestDenorm.isDenormal());
6378 EXPECT_EQ(0x1p-10F, SmallestDenorm.convertToFloat());
6379
6380 APFloat QNaN = APFloat::getQNaN(Sem: APFloat::Float8E4M3FNUZ());
6381 EXPECT_TRUE(std::isnan(QNaN.convertToFloat()));
6382}
6383
6384TEST(APFloatTest, IEEEsingleToFloat) {
6385 APFloat FPosZero(0.0F);
6386 APFloat FPosZeroToFloat(FPosZero.convertToFloat());
6387 EXPECT_TRUE(FPosZeroToFloat.isPosZero());
6388 APFloat FNegZero(-0.0F);
6389 APFloat FNegZeroToFloat(FNegZero.convertToFloat());
6390 EXPECT_TRUE(FNegZeroToFloat.isNegZero());
6391
6392 APFloat FOne(1.0F);
6393 EXPECT_EQ(1.0F, FOne.convertToFloat());
6394 APFloat FPosLargest = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: false);
6395 EXPECT_EQ(std::numeric_limits<float>::max(), FPosLargest.convertToFloat());
6396 APFloat FNegLargest = APFloat::getLargest(Sem: APFloat::IEEEsingle(), Negative: true);
6397 EXPECT_EQ(-std::numeric_limits<float>::max(), FNegLargest.convertToFloat());
6398 APFloat FPosSmallest =
6399 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: false);
6400 EXPECT_EQ(std::numeric_limits<float>::min(), FPosSmallest.convertToFloat());
6401 APFloat FNegSmallest =
6402 APFloat::getSmallestNormalized(Sem: APFloat::IEEEsingle(), Negative: true);
6403 EXPECT_EQ(-std::numeric_limits<float>::min(), FNegSmallest.convertToFloat());
6404
6405 APFloat FSmallestDenorm = APFloat::getSmallest(Sem: APFloat::IEEEsingle(), Negative: false);
6406 EXPECT_EQ(std::numeric_limits<float>::denorm_min(),
6407 FSmallestDenorm.convertToFloat());
6408 APFloat FLargestDenorm(APFloat::IEEEsingle(), "0x1.FFFFFEp-126");
6409 EXPECT_EQ(/*0x1.FFFFFEp-126*/ 2.3509885615147286e-38F,
6410 FLargestDenorm.convertToFloat());
6411
6412 APFloat FPosInf = APFloat::getInf(Sem: APFloat::IEEEsingle());
6413 EXPECT_EQ(std::numeric_limits<float>::infinity(), FPosInf.convertToFloat());
6414 APFloat FNegInf = APFloat::getInf(Sem: APFloat::IEEEsingle(), Negative: true);
6415 EXPECT_EQ(-std::numeric_limits<float>::infinity(), FNegInf.convertToFloat());
6416 APFloat FQNaN = APFloat::getQNaN(Sem: APFloat::IEEEsingle());
6417 EXPECT_TRUE(std::isnan(FQNaN.convertToFloat()));
6418}
6419
6420TEST(APFloatTest, IEEEhalfToFloat) {
6421 APFloat HPosZero = APFloat::getZero(Sem: APFloat::IEEEhalf());
6422 APFloat HPosZeroToFloat(HPosZero.convertToFloat());
6423 EXPECT_TRUE(HPosZeroToFloat.isPosZero());
6424 APFloat HNegZero = APFloat::getZero(Sem: APFloat::IEEEhalf(), Negative: true);
6425 APFloat HNegZeroToFloat(HNegZero.convertToFloat());
6426 EXPECT_TRUE(HNegZeroToFloat.isNegZero());
6427
6428 APFloat HOne(APFloat::IEEEhalf(), "1.0");
6429 EXPECT_EQ(1.0F, HOne.convertToFloat());
6430 APFloat HPosLargest = APFloat::getLargest(Sem: APFloat::IEEEhalf(), Negative: false);
6431 EXPECT_EQ(/*0x1.FFCp15*/ 65504.0F, HPosLargest.convertToFloat());
6432 APFloat HNegLargest = APFloat::getLargest(Sem: APFloat::IEEEhalf(), Negative: true);
6433 EXPECT_EQ(/*-0x1.FFCp15*/ -65504.0F, HNegLargest.convertToFloat());
6434 APFloat HPosSmallest =
6435 APFloat::getSmallestNormalized(Sem: APFloat::IEEEhalf(), Negative: false);
6436 EXPECT_EQ(/*0x1.p-14*/ 6.103515625e-05F, HPosSmallest.convertToFloat());
6437 APFloat HNegSmallest =
6438 APFloat::getSmallestNormalized(Sem: APFloat::IEEEhalf(), Negative: true);
6439 EXPECT_EQ(/*-0x1.p-14*/ -6.103515625e-05F, HNegSmallest.convertToFloat());
6440
6441 APFloat HSmallestDenorm = APFloat::getSmallest(Sem: APFloat::IEEEhalf(), Negative: false);
6442 EXPECT_EQ(/*0x1.p-24*/ 5.960464477539063e-08F,
6443 HSmallestDenorm.convertToFloat());
6444 APFloat HLargestDenorm(APFloat::IEEEhalf(), "0x1.FFCp-14");
6445 EXPECT_EQ(/*0x1.FFCp-14*/ 0.00012201070785522461F,
6446 HLargestDenorm.convertToFloat());
6447
6448 APFloat HPosInf = APFloat::getInf(Sem: APFloat::IEEEhalf());
6449 EXPECT_EQ(std::numeric_limits<float>::infinity(), HPosInf.convertToFloat());
6450 APFloat HNegInf = APFloat::getInf(Sem: APFloat::IEEEhalf(), Negative: true);
6451 EXPECT_EQ(-std::numeric_limits<float>::infinity(), HNegInf.convertToFloat());
6452 APFloat HQNaN = APFloat::getQNaN(Sem: APFloat::IEEEhalf());
6453 EXPECT_TRUE(std::isnan(HQNaN.convertToFloat()));
6454}
6455
6456TEST(APFloatTest, BFloatToFloat) {
6457 APFloat BPosZero = APFloat::getZero(Sem: APFloat::BFloat());
6458 APFloat BPosZeroToDouble(BPosZero.convertToFloat());
6459 EXPECT_TRUE(BPosZeroToDouble.isPosZero());
6460 APFloat BNegZero = APFloat::getZero(Sem: APFloat::BFloat(), Negative: true);
6461 APFloat BNegZeroToDouble(BNegZero.convertToFloat());
6462 EXPECT_TRUE(BNegZeroToDouble.isNegZero());
6463
6464 APFloat BOne(APFloat::BFloat(), "1.0");
6465 EXPECT_EQ(1.0F, BOne.convertToFloat());
6466 APFloat BPosLargest = APFloat::getLargest(Sem: APFloat::BFloat(), Negative: false);
6467 EXPECT_EQ(/*0x1.FEp127*/ 3.3895313892515355e+38F,
6468 BPosLargest.convertToFloat());
6469 APFloat BNegLargest = APFloat::getLargest(Sem: APFloat::BFloat(), Negative: true);
6470 EXPECT_EQ(/*-0x1.FEp127*/ -3.3895313892515355e+38F,
6471 BNegLargest.convertToFloat());
6472 APFloat BPosSmallest =
6473 APFloat::getSmallestNormalized(Sem: APFloat::BFloat(), Negative: false);
6474 EXPECT_EQ(/*0x1.p-126*/ 1.1754943508222875e-38F,
6475 BPosSmallest.convertToFloat());
6476 APFloat BNegSmallest =
6477 APFloat::getSmallestNormalized(Sem: APFloat::BFloat(), Negative: true);
6478 EXPECT_EQ(/*-0x1.p-126*/ -1.1754943508222875e-38F,
6479 BNegSmallest.convertToFloat());
6480
6481 APFloat BSmallestDenorm = APFloat::getSmallest(Sem: APFloat::BFloat(), Negative: false);
6482 EXPECT_EQ(/*0x1.p-133*/ 9.183549615799121e-41F,
6483 BSmallestDenorm.convertToFloat());
6484 APFloat BLargestDenorm(APFloat::BFloat(), "0x1.FCp-127");
6485 EXPECT_EQ(/*0x1.FCp-127*/ 1.1663108012064884e-38F,
6486 BLargestDenorm.convertToFloat());
6487
6488 APFloat BPosInf = APFloat::getInf(Sem: APFloat::BFloat());
6489 EXPECT_EQ(std::numeric_limits<float>::infinity(), BPosInf.convertToFloat());
6490 APFloat BNegInf = APFloat::getInf(Sem: APFloat::BFloat(), Negative: true);
6491 EXPECT_EQ(-std::numeric_limits<float>::infinity(), BNegInf.convertToFloat());
6492 APFloat BQNaN = APFloat::getQNaN(Sem: APFloat::BFloat());
6493 EXPECT_TRUE(std::isnan(BQNaN.convertToFloat()));
6494}
6495
6496TEST(APFloatTest, Float8E5M2ToFloat) {
6497 APFloat PosZero = APFloat::getZero(Sem: APFloat::Float8E5M2());
6498 APFloat PosZeroToFloat(PosZero.convertToFloat());
6499 EXPECT_TRUE(PosZeroToFloat.isPosZero());
6500 APFloat NegZero = APFloat::getZero(Sem: APFloat::Float8E5M2(), Negative: true);
6501 APFloat NegZeroToFloat(NegZero.convertToFloat());
6502 EXPECT_TRUE(NegZeroToFloat.isNegZero());
6503
6504 APFloat One(APFloat::Float8E5M2(), "1.0");
6505 EXPECT_EQ(1.0F, One.convertToFloat());
6506 APFloat Two(APFloat::Float8E5M2(), "2.0");
6507 EXPECT_EQ(2.0F, Two.convertToFloat());
6508
6509 APFloat PosLargest = APFloat::getLargest(Sem: APFloat::Float8E5M2(), Negative: false);
6510 EXPECT_EQ(5.734400e+04, PosLargest.convertToFloat());
6511 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::Float8E5M2(), Negative: true);
6512 EXPECT_EQ(-5.734400e+04, NegLargest.convertToFloat());
6513 APFloat PosSmallest =
6514 APFloat::getSmallestNormalized(Sem: APFloat::Float8E5M2(), Negative: false);
6515 EXPECT_EQ(0x1.p-14, PosSmallest.convertToFloat());
6516 APFloat NegSmallest =
6517 APFloat::getSmallestNormalized(Sem: APFloat::Float8E5M2(), Negative: true);
6518 EXPECT_EQ(-0x1.p-14, NegSmallest.convertToFloat());
6519
6520 APFloat SmallestDenorm = APFloat::getSmallest(Sem: APFloat::Float8E5M2(), Negative: false);
6521 EXPECT_TRUE(SmallestDenorm.isDenormal());
6522 EXPECT_EQ(0x1.p-16, SmallestDenorm.convertToFloat());
6523
6524 APFloat PosInf = APFloat::getInf(Sem: APFloat::Float8E5M2());
6525 EXPECT_EQ(std::numeric_limits<float>::infinity(), PosInf.convertToFloat());
6526 APFloat NegInf = APFloat::getInf(Sem: APFloat::Float8E5M2(), Negative: true);
6527 EXPECT_EQ(-std::numeric_limits<float>::infinity(), NegInf.convertToFloat());
6528 APFloat QNaN = APFloat::getQNaN(Sem: APFloat::Float8E5M2());
6529 EXPECT_TRUE(std::isnan(QNaN.convertToFloat()));
6530}
6531
6532TEST(APFloatTest, Float8E4M3FNToFloat) {
6533 APFloat PosZero = APFloat::getZero(Sem: APFloat::Float8E4M3FN());
6534 APFloat PosZeroToFloat(PosZero.convertToFloat());
6535 EXPECT_TRUE(PosZeroToFloat.isPosZero());
6536 APFloat NegZero = APFloat::getZero(Sem: APFloat::Float8E4M3FN(), Negative: true);
6537 APFloat NegZeroToFloat(NegZero.convertToFloat());
6538 EXPECT_TRUE(NegZeroToFloat.isNegZero());
6539
6540 APFloat One(APFloat::Float8E4M3FN(), "1.0");
6541 EXPECT_EQ(1.0F, One.convertToFloat());
6542 APFloat Two(APFloat::Float8E4M3FN(), "2.0");
6543 EXPECT_EQ(2.0F, Two.convertToFloat());
6544
6545 APFloat PosLargest = APFloat::getLargest(Sem: APFloat::Float8E4M3FN(), Negative: false);
6546 EXPECT_EQ(448., PosLargest.convertToFloat());
6547 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::Float8E4M3FN(), Negative: true);
6548 EXPECT_EQ(-448, NegLargest.convertToFloat());
6549 APFloat PosSmallest =
6550 APFloat::getSmallestNormalized(Sem: APFloat::Float8E4M3FN(), Negative: false);
6551 EXPECT_EQ(0x1.p-6, PosSmallest.convertToFloat());
6552 APFloat NegSmallest =
6553 APFloat::getSmallestNormalized(Sem: APFloat::Float8E4M3FN(), Negative: true);
6554 EXPECT_EQ(-0x1.p-6, NegSmallest.convertToFloat());
6555
6556 APFloat SmallestDenorm = APFloat::getSmallest(Sem: APFloat::Float8E4M3FN(), Negative: false);
6557 EXPECT_TRUE(SmallestDenorm.isDenormal());
6558 EXPECT_EQ(0x1.p-9, SmallestDenorm.convertToFloat());
6559
6560 APFloat QNaN = APFloat::getQNaN(Sem: APFloat::Float8E4M3FN());
6561 EXPECT_TRUE(std::isnan(QNaN.convertToFloat()));
6562}
6563
6564TEST(APFloatTest, FloatTF32ToFloat) {
6565 APFloat PosZero = APFloat::getZero(Sem: APFloat::FloatTF32());
6566 APFloat PosZeroToFloat(PosZero.convertToFloat());
6567 EXPECT_TRUE(PosZeroToFloat.isPosZero());
6568 APFloat NegZero = APFloat::getZero(Sem: APFloat::FloatTF32(), Negative: true);
6569 APFloat NegZeroToFloat(NegZero.convertToFloat());
6570 EXPECT_TRUE(NegZeroToFloat.isNegZero());
6571
6572 APFloat One(APFloat::FloatTF32(), "1.0");
6573 EXPECT_EQ(1.0F, One.convertToFloat());
6574 APFloat Two(APFloat::FloatTF32(), "2.0");
6575 EXPECT_EQ(2.0F, Two.convertToFloat());
6576
6577 APFloat PosLargest = APFloat::getLargest(Sem: APFloat::FloatTF32(), Negative: false);
6578 EXPECT_EQ(3.40116213421e+38F, PosLargest.convertToFloat());
6579
6580 APFloat NegLargest = APFloat::getLargest(Sem: APFloat::FloatTF32(), Negative: true);
6581 EXPECT_EQ(-3.40116213421e+38F, NegLargest.convertToFloat());
6582
6583 APFloat PosSmallest =
6584 APFloat::getSmallestNormalized(Sem: APFloat::FloatTF32(), Negative: false);
6585 EXPECT_EQ(/*0x1.p-126*/ 1.1754943508222875e-38F,
6586 PosSmallest.convertToFloat());
6587 APFloat NegSmallest =
6588 APFloat::getSmallestNormalized(Sem: APFloat::FloatTF32(), Negative: true);
6589 EXPECT_EQ(/*-0x1.p-126*/ -1.1754943508222875e-38F,
6590 NegSmallest.convertToFloat());
6591
6592 APFloat SmallestDenorm = APFloat::getSmallest(Sem: APFloat::FloatTF32(), Negative: false);
6593 EXPECT_TRUE(SmallestDenorm.isDenormal());
6594 EXPECT_EQ(0x0.004p-126, SmallestDenorm.convertToFloat());
6595
6596 APFloat QNaN = APFloat::getQNaN(Sem: APFloat::FloatTF32());
6597 EXPECT_TRUE(std::isnan(QNaN.convertToFloat()));
6598}
6599
6600TEST(APFloatTest, getExactLog2) {
6601 for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) {
6602 auto SemEnum = static_cast<APFloat::Semantics>(I);
6603 const fltSemantics &Semantics = APFloat::EnumToSemantics(S: SemEnum);
6604
6605 APFloat One(Semantics, "1.0");
6606
6607 if (I == APFloat::S_PPCDoubleDouble) {
6608 // Not implemented
6609 EXPECT_EQ(INT_MIN, One.getExactLog2());
6610 EXPECT_EQ(INT_MIN, One.getExactLog2Abs());
6611 continue;
6612 }
6613
6614 int MinExp = APFloat::semanticsMinExponent(Semantics);
6615 int MaxExp = APFloat::semanticsMaxExponent(Semantics);
6616 int Precision = APFloat::semanticsPrecision(Semantics);
6617
6618 EXPECT_EQ(0, One.getExactLog2());
6619 EXPECT_EQ(INT_MIN, APFloat(Semantics, "3.0").getExactLog2());
6620 EXPECT_EQ(INT_MIN, APFloat(Semantics, "-3.0").getExactLog2());
6621 EXPECT_EQ(INT_MIN, APFloat(Semantics, "3.0").getExactLog2Abs());
6622 EXPECT_EQ(INT_MIN, APFloat(Semantics, "-3.0").getExactLog2Abs());
6623 EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2());
6624 EXPECT_EQ(INT_MIN, APFloat(Semantics, "-8.0").getExactLog2());
6625 EXPECT_EQ(-2, APFloat(Semantics, "0.25").getExactLog2());
6626 EXPECT_EQ(-2, APFloat(Semantics, "0.25").getExactLog2Abs());
6627 EXPECT_EQ(INT_MIN, APFloat(Semantics, "-0.25").getExactLog2());
6628 EXPECT_EQ(-2, APFloat(Semantics, "-0.25").getExactLog2Abs());
6629 EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2Abs());
6630 EXPECT_EQ(3, APFloat(Semantics, "-8.0").getExactLog2Abs());
6631
6632 EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, false).getExactLog2());
6633 EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, true).getExactLog2());
6634 EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics).getExactLog2());
6635 EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics, true).getExactLog2());
6636 EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, false).getExactLog2());
6637 EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, true).getExactLog2());
6638
6639 EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, false).getExactLog2Abs());
6640 EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, true).getExactLog2Abs());
6641 EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics).getExactLog2Abs());
6642 EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics, true).getExactLog2Abs());
6643 EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, false).getExactLog2Abs());
6644 EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, true).getExactLog2Abs());
6645
6646 EXPECT_EQ(INT_MIN,
6647 scalbn(One, MinExp - Precision - 1, APFloat::rmNearestTiesToEven)
6648 .getExactLog2());
6649 EXPECT_EQ(INT_MIN,
6650 scalbn(One, MinExp - Precision, APFloat::rmNearestTiesToEven)
6651 .getExactLog2());
6652
6653 EXPECT_EQ(
6654 INT_MIN,
6655 scalbn(One, MaxExp + 1, APFloat::rmNearestTiesToEven).getExactLog2());
6656
6657 for (int i = MinExp - Precision + 1; i <= MaxExp; ++i) {
6658 EXPECT_EQ(i, scalbn(One, i, APFloat::rmNearestTiesToEven).getExactLog2());
6659 }
6660 }
6661}
6662
6663} // namespace
6664

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