@@ -4575,35 +4575,6 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
4575
4575
4576
4576
}
4577
4577
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
-
4607
4578
int IEEEFloat::getExactLog2Abs () const {
4608
4579
if (!isFinite () || isZero ())
4609
4580
return INT_MIN;
@@ -5731,17 +5702,6 @@ void DoubleAPFloat::toString(SmallVectorImpl<char> &Str,
5731
5702
.toString (Str, FormatPrecision, FormatMaxPadding, TruncateZero);
5732
5703
}
5733
5704
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
-
5745
5705
int DoubleAPFloat::getExactLog2Abs () const {
5746
5706
// In order for Hi + Lo to be a power of two, the following must be true:
5747
5707
// 1. Hi must be a power of two.
@@ -5926,6 +5886,58 @@ FPClassTest APFloat::classify() const {
5926
5886
return isSignaling () ? fcSNan : fcQNan;
5927
5887
}
5928
5888
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
+
5929
5941
APFloat::opStatus APFloat::convert (const fltSemantics &ToSemantics,
5930
5942
roundingMode RM, bool *losesInfo) {
5931
5943
if (&getSemantics () == &ToSemantics) {
0 commit comments