@@ -900,6 +900,30 @@ writeSignedDecimal (char *dst, int value)
900900 return dst;
901901}
902902
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+
903927namespace detail {
904928/* Constructors. */
905929void IEEEFloat::initialize (const fltSemantics *ourSemantics) {
@@ -5306,12 +5330,110 @@ Expected<APFloat::opStatus> DoubleAPFloat::convertFromString(StringRef S,
53065330 return Ret;
53075331}
53085332
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.
53095339APFloat::opStatus DoubleAPFloat::next (bool nextDown) {
53105340 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;
53155437}
53165438
53175439APFloat::opStatus
0 commit comments