@@ -900,6 +900,30 @@ writeSignedDecimal (char *dst, int value)
900
900
return dst;
901
901
}
902
902
903
+ // Compute the ULP of the input using a definition from:
904
+ // Jean-Michel Muller. On the definition of ulp(x). [Research Report] RR-5504,
905
+ // LIP RR-2005-09, INRIA, LIP. 2005, pp.16. inria-00070503
906
+ static APFloat harrisonUlp (const APFloat &X) {
907
+ const fltSemantics &Sem = X.getSemantics ();
908
+ switch (X.getCategory ()) {
909
+ case APFloat::fcNaN:
910
+ return APFloat::getQNaN (Sem);
911
+ case APFloat::fcInfinity:
912
+ return APFloat::getInf (Sem);
913
+ case APFloat::fcZero:
914
+ return APFloat::getSmallest (Sem);
915
+ case APFloat::fcNormal:
916
+ break ;
917
+ }
918
+ if (X.isDenormal () || X.isSmallestNormalized ())
919
+ return APFloat::getSmallest (Sem);
920
+ int Exp = ilogb (X);
921
+ if (X.getExactLog2 () != INT_MIN)
922
+ Exp -= 1 ;
923
+ return scalbn (APFloat::getOne (Sem), Exp - (Sem.precision - 1 ),
924
+ APFloat::rmNearestTiesToEven);
925
+ }
926
+
903
927
namespace detail {
904
928
/* Constructors. */
905
929
void IEEEFloat::initialize (const fltSemantics *ourSemantics) {
@@ -5306,12 +5330,110 @@ Expected<APFloat::opStatus> DoubleAPFloat::convertFromString(StringRef S,
5306
5330
return Ret;
5307
5331
}
5308
5332
5333
+ // The double-double lattice of values corresponds to numbers which obey:
5334
+ // - abs(lo) <= 1/2 * ulp(hi)
5335
+ // - roundTiesToEven(hi + lo) == hi
5336
+ //
5337
+ // nextUp must choose the smallest output > input that follows these rules.
5338
+ // nexDown must choose the largest output < input that follows these rules.
5309
5339
APFloat::opStatus DoubleAPFloat::next (bool nextDown) {
5310
5340
assert (Semantics == &semPPCDoubleDouble && " Unexpected Semantics" );
5311
- APFloat Tmp (semPPCDoubleDoubleLegacy, bitcastToAPInt ());
5312
- auto Ret = Tmp.next (nextDown);
5313
- *this = DoubleAPFloat (semPPCDoubleDouble, Tmp.bitcastToAPInt ());
5314
- return Ret;
5341
+ // nextDown(x) = -nextUp(-x)
5342
+ if (nextDown) {
5343
+ changeSign ();
5344
+ APFloat::opStatus Result = next (/* nextDown=*/ false );
5345
+ changeSign ();
5346
+ return Result;
5347
+ }
5348
+ switch (getCategory ()) {
5349
+ case fcInfinity:
5350
+ // nextUp(+inf) = +inf
5351
+ // nextUp(-inf) = -getLargest()
5352
+ if (isNegative ())
5353
+ makeLargest (true );
5354
+ return opOK;
5355
+
5356
+ case fcNaN:
5357
+ // IEEE-754R 2008 6.2 Par 2: nextUp(sNaN) = qNaN. Set Invalid flag.
5358
+ // IEEE-754R 2008 6.2: nextUp(qNaN) = qNaN. Must be identity so we do not
5359
+ // change the payload.
5360
+ if (getFirst ().isSignaling ()) {
5361
+ // For consistency, propagate the sign of the sNaN to the qNaN.
5362
+ makeNaN (false , isNegative (), nullptr );
5363
+ return opInvalidOp;
5364
+ }
5365
+ return opOK;
5366
+
5367
+ case fcZero:
5368
+ // nextUp(pm 0) = +getSmallest()
5369
+ makeSmallest (false );
5370
+ return opOK;
5371
+
5372
+ case fcNormal:
5373
+ break ;
5374
+ }
5375
+
5376
+ const APFloat &HiOld = getFirst ();
5377
+ const APFloat &LoOld = getSecond ();
5378
+
5379
+ APFloat NextLo = LoOld;
5380
+ NextLo.next (/* nextDown=*/ false );
5381
+
5382
+ // We want to admit values where:
5383
+ // 1. abs(Lo) <= ulp(Hi)/2
5384
+ // 2. Hi == RTNE(Hi + lo)
5385
+ auto InLattice = [](const APFloat &Hi, const APFloat &Lo) {
5386
+ return Hi + Lo == Hi;
5387
+ };
5388
+
5389
+ // Check if (HiOld, nextUp(LoOld) is in the lattice.
5390
+ if (InLattice (HiOld, NextLo)) {
5391
+ // Yes, the result is (HiOld, nextUp(LoOld)).
5392
+ Floats[1 ] = std::move (NextLo);
5393
+
5394
+ // TODO: Because we currently rely on semPPCDoubleDoubleLegacy, our maximum
5395
+ // value is defined to have exactly 106 bits of precision. This limitation
5396
+ // results in semPPCDoubleDouble being unable to reach its maximum canonical
5397
+ // value.
5398
+ DoubleAPFloat Largest{*Semantics, uninitialized};
5399
+ Largest.makeLargest (/* Neg=*/ false );
5400
+ if (compare (Largest) == cmpGreaterThan)
5401
+ makeInf (/* Neg=*/ false );
5402
+
5403
+ return opOK;
5404
+ }
5405
+
5406
+ // Now we need to handle the cases where (HiOld, nextUp(LoOld)) is not the
5407
+ // correct result. We know the new hi component will be nextUp(HiOld) but our
5408
+ // lattice rules make it a little ambiguous what the correct NextLo must be.
5409
+ APFloat NextHi = HiOld;
5410
+ NextHi.next (/* nextDown=*/ false );
5411
+
5412
+ // nextUp(getLargest()) == INFINITY
5413
+ if (NextHi.isInfinity ()) {
5414
+ makeInf (/* Neg=*/ false );
5415
+ return opOK;
5416
+ }
5417
+
5418
+ // IEEE 754-2019 5.3.1:
5419
+ // "If x is the negative number of least magnitude in x's format, nextUp(x) is
5420
+ // -0."
5421
+ if (NextHi.isZero ()) {
5422
+ makeZero (/* Neg=*/ true );
5423
+ return opOK;
5424
+ }
5425
+
5426
+ // abs(NextLo) must be <= ulp(NextHi)/2. We want NextLo to be as close to
5427
+ // negative infinity as possible.
5428
+ NextLo = neg (scalbn (harrisonUlp (NextHi), -1 , rmTowardZero));
5429
+ if (!InLattice (NextHi, NextLo))
5430
+ // RTNE may mean that Lo must be < ulp(NextHi) / 2 so we bump NextLo.
5431
+ NextLo.next (/* nextDown=*/ false );
5432
+
5433
+ Floats[0 ] = std::move (NextHi);
5434
+ Floats[1 ] = std::move (NextLo);
5435
+
5436
+ return opOK;
5315
5437
}
5316
5438
5317
5439
APFloat::opStatus
0 commit comments