@@ -5519,13 +5519,127 @@ APFloat::opStatus DoubleAPFloat::next(bool nextDown) {
5519
5519
return opOK;
5520
5520
}
5521
5521
5522
+ APFloat::opStatus DoubleAPFloat::convertToSignExtendedInteger (
5523
+ MutableArrayRef<integerPart> Input, unsigned int Width, bool IsSigned,
5524
+ roundingMode RM, bool *IsExact) const {
5525
+ assert (Semantics == &semPPCDoubleDouble && " Unexpected Semantics" );
5526
+
5527
+ // If Hi is not finite, or Lo is zero, the value is entirely represented
5528
+ // by Hi. Delegate to the simpler single-APFloat conversion.
5529
+ if (!getFirst ().isFiniteNonZero () || getSecond ().isZero ())
5530
+ return getFirst ().convertToInteger (Input, Width, IsSigned, RM, IsExact);
5531
+
5532
+ // First, round the full double-double value to an integral value. This
5533
+ // simplifies the rest of the function, as we no longer need to consider
5534
+ // fractional parts.
5535
+ *IsExact = false ;
5536
+ DoubleAPFloat Integral = *this ;
5537
+ const opStatus RoundStatus = Integral.roundToIntegral (RM);
5538
+ if (RoundStatus == opInvalidOp)
5539
+ return RoundStatus;
5540
+ const APFloat &IntegralHi = Integral.getFirst ();
5541
+ const APFloat &IntegralLo = Integral.getSecond ();
5542
+
5543
+ // If rounding results in either component being zero, the sum is trivial.
5544
+ // Delegate to the simpler single-APFloat conversion.
5545
+ bool HiIsExact;
5546
+ if (IntegralHi.isZero () || IntegralLo.isZero ()) {
5547
+ const opStatus HiStatus =
5548
+ IntegralHi.convertToInteger (Input, Width, IsSigned, RM, &HiIsExact);
5549
+ // The conversion from an integer-valued float to an APInt may fail if the
5550
+ // result would be out of range. Regardless, taking this path is only
5551
+ // possible if rounding occured during the initial `roundToIntegral`.
5552
+ return HiStatus == opOK ? opInexact : HiStatus;
5553
+ }
5554
+
5555
+ // A negative number cannot be represented by an unsigned integer.
5556
+ // Since a double-double is canonical, if Hi is negative, the sum is negative.
5557
+ if (!IsSigned && IntegralHi.isNegative ())
5558
+ return opInvalidOp;
5559
+
5560
+ // Handle the special boundary case where |Hi| is exactly the power of two
5561
+ // that marks the edge of the integer's range (e.g., 2^63 for int64_t). In
5562
+ // this situation, Hi itself won't fit, but the sum Hi + Lo might.
5563
+ // `PositiveOverflowWidth` is the bit number for this boundary (N-1 for
5564
+ // signed, N for unsigned).
5565
+ bool LoIsExact;
5566
+ const int HiExactLog2 = IntegralHi.getExactLog2Abs ();
5567
+ const unsigned PositiveOverflowWidth = IsSigned ? Width - 1 : Width;
5568
+ if (HiExactLog2 >= 0 &&
5569
+ static_cast <unsigned >(HiExactLog2) == PositiveOverflowWidth) {
5570
+ // If Hi and Lo have the same sign, |Hi + Lo| > |Hi|, so the sum is
5571
+ // guaranteed to overflow. E.g., for uint128_t, (2^128, 1) overflows.
5572
+ if (IntegralHi.isNegative () == IntegralLo.isNegative ())
5573
+ return opInvalidOp;
5574
+
5575
+ // If the signs differ, the sum will fit. We can compute the result using
5576
+ // properties of two's complement arithmetic without a wide intermediate
5577
+ // integer. E.g., for uint128_t, (2^128, -1) should be 2^128 - 1.
5578
+ [[maybe_unused]] opStatus LoStatus = IntegralLo.convertToInteger (
5579
+ Input, Width, /* IsSigned=*/ true , RM, &LoIsExact);
5580
+ assert (LoStatus == opOK && " Unexpected failure" );
5581
+
5582
+ // Adjust the bit pattern of Lo to account for Hi's value:
5583
+ // - For unsigned (Hi=2^Width): `2^Width + Lo` in `Width`-bit
5584
+ // arithmetic is equivalent to just `Lo`. The conversion of `Lo` above
5585
+ // already produced the correct final bit pattern.
5586
+ // - For signed (Hi=2^(Width-1)): The sum `2^(Width-1) + Lo` (where Lo<0)
5587
+ // can be computed by taking the two's complement pattern for `Lo` and
5588
+ // clearing the sign bit.
5589
+ if (IsSigned && !IntegralHi.isNegative ())
5590
+ APInt::tcClearBit (Input.data (), PositiveOverflowWidth);
5591
+ *IsExact = RoundStatus == opOK;
5592
+ return RoundStatus;
5593
+ }
5594
+
5595
+ // General case: Hi is not a power-of-two boundary, so we know it fits.
5596
+ // Since we already rounded the full value, we now just need to convert the
5597
+ // components to integers. The rounding mode should not matter.
5598
+ [[maybe_unused]] opStatus HiStatus = IntegralHi.convertToInteger (
5599
+ Input, Width, IsSigned, rmTowardZero, &HiIsExact);
5600
+ assert (HiStatus == opOK && " Unexpected failure" );
5601
+
5602
+ // Convert Lo into a temporary integer of the same width.
5603
+ APSInt LoResult{Width, /* isUnsigned=*/ !IsSigned};
5604
+ [[maybe_unused]] opStatus LoStatus =
5605
+ IntegralLo.convertToInteger (LoResult, rmTowardZero, &LoIsExact);
5606
+ assert (LoStatus == opOK && " Unexpected failure" );
5607
+
5608
+ // Add Lo to Hi. This addition is guaranteed not to overflow because of the
5609
+ // double-double canonicalization rule (`|Lo| <= ulp(Hi)/2`). The only case
5610
+ // where the sum could cross the integer type's boundary is when Hi is a
5611
+ // power of two, which is handled by the special case block above.
5612
+ APInt::tcAdd (Input.data (), LoResult.getRawData (), /* carry=*/ 0 , Input.size ());
5613
+
5614
+ *IsExact = RoundStatus == opOK;
5615
+ return RoundStatus;
5616
+ }
5617
+
5522
5618
APFloat::opStatus
5523
5619
DoubleAPFloat::convertToInteger (MutableArrayRef<integerPart> Input,
5524
5620
unsigned int Width, bool IsSigned,
5525
5621
roundingMode RM, bool *IsExact) const {
5526
- assert (Semantics == &semPPCDoubleDouble && " Unexpected Semantics" );
5527
- return APFloat (semPPCDoubleDoubleLegacy, bitcastToAPInt ())
5528
- .convertToInteger (Input, Width, IsSigned, RM, IsExact);
5622
+ opStatus FS =
5623
+ convertToSignExtendedInteger (Input, Width, IsSigned, RM, IsExact);
5624
+
5625
+ if (FS == opInvalidOp) {
5626
+ const unsigned DstPartsCount = partCountForBits (Width);
5627
+ assert (DstPartsCount <= Parts.size () && " Integer too big" );
5628
+
5629
+ unsigned Bits;
5630
+ if (getCategory () == fcNaN)
5631
+ Bits = 0 ;
5632
+ else if (isNegative ())
5633
+ Bits = IsSigned;
5634
+ else
5635
+ Bits = Width - IsSigned;
5636
+
5637
+ tcSetLeastSignificantBits (Input.data (), DstPartsCount, Bits);
5638
+ if (isNegative () && IsSigned)
5639
+ APInt::tcShiftLeft (Input.data (), DstPartsCount, Width - 1 );
5640
+ }
5641
+
5642
+ return FS;
5529
5643
}
5530
5644
5531
5645
APFloat::opStatus DoubleAPFloat::convertFromAPInt (const APInt &Input,
@@ -5626,14 +5740,31 @@ bool DoubleAPFloat::getExactInverse(APFloat *inv) const {
5626
5740
return Ret;
5627
5741
}
5628
5742
5629
- int DoubleAPFloat::getExactLog2 () const {
5630
- // TODO: Implement me
5631
- return INT_MIN;
5632
- }
5633
-
5634
5743
int DoubleAPFloat::getExactLog2Abs () const {
5635
- // TODO: Implement me
5636
- return INT_MIN;
5744
+ // In order for Hi + Lo to be a power of two, the following must be true:
5745
+ // 1. Hi must be a power of two.
5746
+ // 2. Lo must be zero.
5747
+ if (getSecond ().isNonZero ())
5748
+ return INT_MIN;
5749
+ return getFirst ().getExactLog2Abs ();
5750
+ }
5751
+
5752
+ int ilogb (const DoubleAPFloat& Arg) {
5753
+ const APFloat& Hi = Arg.getFirst ();
5754
+ const APFloat& Lo = Arg.getSecond ();
5755
+ int IlogbResult = ilogb (Hi);
5756
+ // Zero and non-finite values can delegate to ilogb(Hi).
5757
+ if (Arg.getCategory () != fcNormal)
5758
+ return IlogbResult;
5759
+ // If Lo can't change the binade, we can delegate to ilogb(Hi).
5760
+ if (Lo.isZero () ||
5761
+ Hi.isNegative () == Lo.isNegative ())
5762
+ return IlogbResult;
5763
+ if (Hi.getExactLog2Abs () == INT_MIN)
5764
+ return IlogbResult;
5765
+ // Numbers of the form 2^a - 2^b or -2^a + 2^b are almost powers of two but
5766
+ // get nudged out of the binade by the low component.
5767
+ return IlogbResult - 1 ;
5637
5768
}
5638
5769
5639
5770
DoubleAPFloat scalbn (const DoubleAPFloat &Arg, int Exp,
@@ -5749,10 +5880,6 @@ void APFloat::Profile(FoldingSetNodeID &NID) const {
5749
5880
NID.Add (bitcastToAPInt ());
5750
5881
}
5751
5882
5752
- /* Same as convertToInteger(integerPart*, ...), except the result is returned in
5753
- an APSInt, whose initial bit-width and signed-ness are used to determine the
5754
- precision of the conversion.
5755
- */
5756
5883
APFloat::opStatus APFloat::convertToInteger (APSInt &result,
5757
5884
roundingMode rounding_mode,
5758
5885
bool *isExact) const {
0 commit comments