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