@@ -4575,6 +4575,35 @@ 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+
45784607int IEEEFloat::getExactLog2Abs () const {
45794608 if (!isFinite () || isZero ())
45804609 return INT_MIN;
@@ -5702,6 +5731,17 @@ void DoubleAPFloat::toString(SmallVectorImpl<char> &Str,
57025731 .toString (Str, FormatPrecision, FormatMaxPadding, TruncateZero);
57035732}
57045733
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+
57055745int DoubleAPFloat::getExactLog2Abs () const {
57065746 // In order for Hi + Lo to be a power of two, the following must be true:
57075747 // 1. Hi must be a power of two.
@@ -5886,58 +5926,6 @@ FPClassTest APFloat::classify() const {
58865926 return isSignaling () ? fcSNan : fcQNan;
58875927}
58885928
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-
59415929APFloat::opStatus APFloat::convert (const fltSemantics &ToSemantics,
59425930 roundingMode RM, bool *losesInfo) {
59435931 if (&getSemantics () == &ToSemantics) {
0 commit comments