@@ -4575,35 +4575,6 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
45754575
45764576}
45774577
4578- bool IEEEFloat::getExactInverse (APFloat *inv) const {
4579- // Special floats and denormals have no exact inverse.
4580- if (!isFiniteNonZero ())
4581- return false ;
4582-
4583- // Check that the number is a power of two by making sure that only the
4584- // integer bit is set in the significand.
4585- if (significandLSB () != semantics->precision - 1 )
4586- return false ;
4587-
4588- // Get the inverse.
4589- IEEEFloat reciprocal (*semantics, 1ULL );
4590- if (reciprocal.divide (*this , rmNearestTiesToEven) != opOK)
4591- return false ;
4592-
4593- // Avoid multiplication with a denormal, it is not safe on all platforms and
4594- // may be slower than a normal division.
4595- if (reciprocal.isDenormal ())
4596- return false ;
4597-
4598- assert (reciprocal.isFiniteNonZero () &&
4599- reciprocal.significandLSB () == reciprocal.semantics ->precision - 1 );
4600-
4601- if (inv)
4602- *inv = APFloat (reciprocal, *semantics);
4603-
4604- return true ;
4605- }
4606-
46074578int IEEEFloat::getExactLog2Abs () const {
46084579 if (!isFinite () || isZero ())
46094580 return INT_MIN;
@@ -5731,17 +5702,6 @@ void DoubleAPFloat::toString(SmallVectorImpl<char> &Str,
57315702 .toString (Str, FormatPrecision, FormatMaxPadding, TruncateZero);
57325703}
57335704
5734- bool DoubleAPFloat::getExactInverse (APFloat *inv) const {
5735- assert (Semantics == &semPPCDoubleDouble && " Unexpected Semantics" );
5736- APFloat Tmp (semPPCDoubleDoubleLegacy, bitcastToAPInt ());
5737- if (!inv)
5738- return Tmp.getExactInverse (nullptr );
5739- APFloat Inv (semPPCDoubleDoubleLegacy);
5740- auto Ret = Tmp.getExactInverse (&Inv);
5741- *inv = APFloat (semPPCDoubleDouble, Inv.bitcastToAPInt ());
5742- return Ret;
5743- }
5744-
57455705int DoubleAPFloat::getExactLog2Abs () const {
57465706 // In order for Hi + Lo to be a power of two, the following must be true:
57475707 // 1. Hi must be a power of two.
@@ -5926,6 +5886,58 @@ FPClassTest APFloat::classify() const {
59265886 return isSignaling () ? fcSNan : fcQNan;
59275887}
59285888
5889+ bool APFloat::getExactInverse (APFloat *Inv) const {
5890+ // Only finite, non-zero numbers can have a useful, representable inverse.
5891+ // This check filters out +/- zero, +/- infinity, and NaN.
5892+ if (!isFiniteNonZero ())
5893+ return false ;
5894+
5895+ // A number has an exact, representable inverse if and only if it is a power
5896+ // of two.
5897+ //
5898+ // Mathematical Rationale:
5899+ // 1. A binary floating-point number x is a dyadic rational, meaning it can
5900+ // be written as x = M / 2^k for integers M (the significand) and k.
5901+ // 2. The inverse is 1/x = 2^k / M.
5902+ // 3. For 1/x to also be a dyadic rational (and thus exactly representable
5903+ // in binary), its denominator M must also be a power of two.
5904+ // Let's say M = 2^m.
5905+ // 4. Substituting this back into the formula for x, we get
5906+ // x = (2^m) / (2^k) = 2^(m-k).
5907+ //
5908+ // This proves that x must be a power of two.
5909+
5910+ // getExactLog2Abs() returns the integer exponent if the number is a power of
5911+ // two or INT_MIN if it is not.
5912+ const int Exp = getExactLog2Abs ();
5913+ if (Exp == INT_MIN)
5914+ return false ;
5915+
5916+ // The inverse of +/- 2^Exp is +/- 2^(-Exp). We can compute this by
5917+ // scaling 1.0 by the negated exponent.
5918+ APFloat Reciprocal =
5919+ scalbn (APFloat::getOne (getSemantics (), /* Negative=*/ isNegative ()), -Exp,
5920+ rmTowardZero);
5921+
5922+ // scalbn might round if the resulting exponent -Exp is outside the
5923+ // representable range, causing overflow (to infinity) or underflow. We
5924+ // must verify that the result is still the exact power of two we expect.
5925+ if (Reciprocal.getExactLog2Abs () != -Exp)
5926+ return false ;
5927+
5928+ // Avoid multiplication with a subnormal, it is not safe on all platforms and
5929+ // may be slower than a normal division.
5930+ if (Reciprocal.isDenormal ())
5931+ return false ;
5932+
5933+ assert (Reciprocal.isFiniteNonZero ());
5934+
5935+ if (Inv)
5936+ *Inv = std::move (Reciprocal);
5937+
5938+ return true ;
5939+ }
5940+
59295941APFloat::opStatus APFloat::convert (const fltSemantics &ToSemantics,
59305942 roundingMode RM, bool *losesInfo) {
59315943 if (&getSemantics () == &ToSemantics) {
0 commit comments