@@ -2927,51 +2927,6 @@ APFloat::opStatus IEEEFloat::convertFromAPInt(const APInt &Val, bool isSigned,
29272927 return convertFromUnsignedParts (api.getRawData (), partCount, rounding_mode);
29282928}
29292929
2930- /* Convert a two's complement integer SRC to a floating point number,
2931- rounding according to ROUNDING_MODE. ISSIGNED is true if the
2932- integer is signed, in which case it must be sign-extended. */
2933- APFloat::opStatus
2934- IEEEFloat::convertFromSignExtendedInteger (const integerPart *src,
2935- unsigned int srcCount, bool isSigned,
2936- roundingMode rounding_mode) {
2937- opStatus status;
2938-
2939- if (isSigned &&
2940- APInt::tcExtractBit (src, srcCount * integerPartWidth - 1 )) {
2941- integerPart *copy;
2942-
2943- /* If we're signed and negative negate a copy. */
2944- sign = true ;
2945- copy = new integerPart[srcCount];
2946- APInt::tcAssign (copy, src, srcCount);
2947- APInt::tcNegate (copy, srcCount);
2948- status = convertFromUnsignedParts (copy, srcCount, rounding_mode);
2949- delete [] copy;
2950- } else {
2951- sign = false ;
2952- status = convertFromUnsignedParts (src, srcCount, rounding_mode);
2953- }
2954-
2955- return status;
2956- }
2957-
2958- /* FIXME: should this just take a const APInt reference? */
2959- APFloat::opStatus
2960- IEEEFloat::convertFromZeroExtendedInteger (const integerPart *parts,
2961- unsigned int width, bool isSigned,
2962- roundingMode rounding_mode) {
2963- unsigned int partCount = partCountForBits (width);
2964- APInt api = APInt (width, ArrayRef (parts, partCount));
2965-
2966- sign = false ;
2967- if (isSigned && APInt::tcExtractBit (parts, width - 1 )) {
2968- sign = true ;
2969- api = -api;
2970- }
2971-
2972- return convertFromUnsignedParts (api.getRawData (), partCount, rounding_mode);
2973- }
2974-
29752930Expected<APFloat::opStatus>
29762931IEEEFloat::convertFromHexadecimalString (StringRef s,
29772932 roundingMode rounding_mode) {
@@ -5648,36 +5603,158 @@ DoubleAPFloat::convertToInteger(MutableArrayRef<integerPart> Input,
56485603 return FS;
56495604}
56505605
5651- APFloat::opStatus DoubleAPFloat::convertFromAPInt (const APInt &Input,
5652- bool IsSigned,
5653- roundingMode RM) {
5654- assert (Semantics == &semPPCDoubleDouble && " Unexpected Semantics" );
5655- APFloat Tmp (semPPCDoubleDoubleLegacy);
5656- auto Ret = Tmp.convertFromAPInt (Input, IsSigned, RM);
5657- *this = DoubleAPFloat (semPPCDoubleDouble, Tmp.bitcastToAPInt ());
5658- return Ret;
5659- }
5606+ APFloat::opStatus DoubleAPFloat::handleOverflow (roundingMode RM) {
5607+ switch (RM) {
5608+ case APFloat::rmTowardZero:
5609+ makeLargest (/* Neg=*/ isNegative ());
5610+ break ;
5611+ case APFloat::rmTowardNegative:
5612+ if (isNegative ())
5613+ makeInf (/* Neg=*/ true );
5614+ else
5615+ makeLargest (/* Neg=*/ false );
5616+ break ;
5617+ case APFloat::rmTowardPositive:
5618+ if (isNegative ())
5619+ makeLargest (/* Neg=*/ true );
5620+ else
5621+ makeInf (/* Neg=*/ false );
5622+ break ;
5623+ case APFloat::rmNearestTiesToAway:
5624+ case APFloat::rmNearestTiesToEven:
5625+ makeInf (/* Neg=*/ isNegative ());
5626+ break ;
5627+ default :
5628+ llvm_unreachable (" Invalid rounding mode found" );
5629+ }
5630+ opStatus S = opInexact;
5631+ if (!getFirst ().isFinite ())
5632+ S = static_cast <opStatus>(S | opOverflow);
5633+ return S;
5634+ }
5635+
5636+ APFloat::opStatus DoubleAPFloat::convertFromUnsignedParts (
5637+ const integerPart *Src, unsigned int SrcCount, roundingMode RM) {
5638+ // Find the most significant bit of the source integer. APInt::tcMSB returns
5639+ // UINT_MAX for a zero value.
5640+ const unsigned SrcMSB = APInt::tcMSB (Src, SrcCount);
5641+ if (SrcMSB == UINT_MAX) {
5642+ // The source integer is 0.
5643+ makeZero (/* Neg=*/ false );
5644+ return opOK;
5645+ }
56605646
5661- APFloat::opStatus
5662- DoubleAPFloat::convertFromSignExtendedInteger (const integerPart *Input,
5663- unsigned int InputSize,
5664- bool IsSigned, roundingMode RM) {
5665- assert (Semantics == &semPPCDoubleDouble && " Unexpected Semantics" );
5666- APFloat Tmp (semPPCDoubleDoubleLegacy);
5667- auto Ret = Tmp.convertFromSignExtendedInteger (Input, InputSize, IsSigned, RM);
5668- *this = DoubleAPFloat (semPPCDoubleDouble, Tmp.bitcastToAPInt ());
5669- return Ret;
5647+ // Create a minimally-sized APInt to represent the source value.
5648+ const unsigned SrcBitWidth = SrcMSB + 1 ;
5649+ APSInt SrcInt{APInt{/* numBits=*/ SrcBitWidth,
5650+ /* numWords=*/ SrcCount, Src},
5651+ /* isUnsigned=*/ true };
5652+
5653+ // Stage 1: Initial Approximation.
5654+ // Convert the source integer SrcInt to the Hi part of the DoubleAPFloat.
5655+ // We use round-to-nearest because it minimizes the initial error, which is
5656+ // crucial for the subsequent steps.
5657+ APFloat Hi{getFirst ().getSemantics ()};
5658+ Hi.convertFromAPInt (SrcInt, /* IsSigned=*/ false , rmNearestTiesToEven);
5659+
5660+ // If the first approximation already overflows, the number is too large.
5661+ // NOTE: The underlying semantics are *more* conservative when choosing to
5662+ // overflow because their notion of ULP is much larger. As such, it is always
5663+ // safe to overflow at the DoubleAPFloat level if the APFloat overflows.
5664+ if (!Hi.isFinite ())
5665+ return handleOverflow (RM);
5666+
5667+ // Stage 2: Exact Error Calculation.
5668+ // Calculate the exact error of the first approximation: Error = SrcInt - Hi.
5669+ // This is done by converting Hi back to an integer and subtracting it from
5670+ // the original source.
5671+ bool HiAsIntIsExact;
5672+ // Create an integer representation of Hi. Its width is determined by the
5673+ // exponent of Hi, ensuring it's just large enough. This width can exceed
5674+ // SrcBitWidth if the conversion to Hi rounded up to a power of two.
5675+ // accurately when converted back to an integer.
5676+ APSInt HiAsInt{static_cast <uint32_t >(ilogb (Hi) + 1 ), /* isUnsigned=*/ true };
5677+ Hi.convertToInteger (HiAsInt, rmNearestTiesToEven, &HiAsIntIsExact);
5678+ const APInt Error = SrcInt.zext (HiAsInt.getBitWidth ()) - HiAsInt;
5679+
5680+ // Stage 3: Error Approximation and Rounding.
5681+ // Convert the integer error into the Lo part of the DoubleAPFloat. This step
5682+ // captures the remainder of the original number. The rounding mode for this
5683+ // conversion (LoRM) may need to be adjusted from the user-requested RM to
5684+ // ensure the final sum (Hi + Lo) rounds correctly.
5685+ roundingMode LoRM = RM;
5686+ // Adjustments are only necessary when the initial approximation Hi was an
5687+ // overestimate, making the Error negative.
5688+ if (Error.isNegative ()) {
5689+ if (RM == rmNearestTiesToAway) {
5690+ // For rmNearestTiesToAway, a tie should round away from zero. Since
5691+ // SrcInt is positive, this means rounding toward +infinity.
5692+ // A standard conversion of a negative Error would round ties toward
5693+ // -infinity, causing the final sum Hi + Lo to be smaller. To
5694+ // counteract this, we detect the tie case and override the rounding
5695+ // mode for Lo to rmTowardPositive.
5696+ const unsigned ErrorActiveBits = Error.getSignificantBits () - 1 ;
5697+ const unsigned LoPrecision = getSecond ().getSemantics ().precision ;
5698+ if (ErrorActiveBits > LoPrecision) {
5699+ const unsigned RoundingBoundary = ErrorActiveBits - LoPrecision;
5700+ // A tie occurs when the bits to be truncated are of the form 100...0.
5701+ // This is detected by checking if the number of trailing zeros is
5702+ // exactly one less than the number of bits being truncated.
5703+ if (Error.countTrailingZeros () == RoundingBoundary - 1 )
5704+ LoRM = rmTowardPositive;
5705+ }
5706+ } else if (RM == rmTowardZero) {
5707+ // For rmTowardZero, the final positive result must be truncated (rounded
5708+ // down). When Hi is an overestimate, Error is negative. A standard
5709+ // rmTowardZero conversion of Error would make it *less* negative,
5710+ // effectively rounding the final sum Hi + Lo *up*. To ensure the sum
5711+ // rounds down correctly, we force Lo to round toward -infinity.
5712+ LoRM = rmTowardNegative;
5713+ }
5714+ }
5715+
5716+ APFloat Lo{getSecond ().getSemantics ()};
5717+ opStatus Status = Lo.convertFromAPInt (Error, /* IsSigned=*/ true , LoRM);
5718+
5719+ // Renormalize the pair (Hi, Lo) into a canonical DoubleAPFloat form where the
5720+ // components do not overlap. fastTwoSum performs this operation.
5721+ std::tie (Hi, Lo) = fastTwoSum (Hi, Lo);
5722+ Floats[0 ] = std::move (Hi);
5723+ Floats[1 ] = std::move (Lo);
5724+
5725+ // A final check for overflow is needed because fastTwoSum can cause a
5726+ // carry-out from Lo that pushes Hi to infinity.
5727+ if (!getFirst ().isFinite ())
5728+ return handleOverflow (RM);
5729+
5730+ // The largest DoubleAPFloat must be canonical. Values which are larger are
5731+ // not canonical and are equivalent to overflow.
5732+ if (getFirst ().isFiniteNonZero () && Floats[0 ].isLargest ()) {
5733+ DoubleAPFloat Largest{*Semantics};
5734+ Largest.makeLargest (/* Neg=*/ false );
5735+ if (compare (Largest) == APFloat::cmpGreaterThan)
5736+ return handleOverflow (RM);
5737+ }
5738+
5739+ // The final status of the operation is determined by the conversion of the
5740+ // error term. If Lo could represent Error exactly, the entire conversion
5741+ // is exact. Otherwise, it's inexact.
5742+ return Status;
56705743}
56715744
5672- APFloat::opStatus
5673- DoubleAPFloat::convertFromZeroExtendedInteger (const integerPart *Input,
5674- unsigned int InputSize,
5675- bool IsSigned, roundingMode RM) {
5676- assert (Semantics == &semPPCDoubleDouble && " Unexpected Semantics" );
5677- APFloat Tmp (semPPCDoubleDoubleLegacy);
5678- auto Ret = Tmp.convertFromZeroExtendedInteger (Input, InputSize, IsSigned, RM);
5679- *this = DoubleAPFloat (semPPCDoubleDouble, Tmp.bitcastToAPInt ());
5680- return Ret;
5745+ APFloat::opStatus DoubleAPFloat::convertFromAPInt (const APInt &Input,
5746+ bool IsSigned,
5747+ roundingMode RM) {
5748+ const bool NegateInput = IsSigned && Input.isNegative ();
5749+ APInt API = Input;
5750+ if (NegateInput)
5751+ API.negate ();
5752+
5753+ const APFloat::opStatus Status =
5754+ convertFromUnsignedParts (API.getRawData (), API.getNumWords (), RM);
5755+ if (NegateInput)
5756+ changeSign ();
5757+ return Status;
56815758}
56825759
56835760unsigned int DoubleAPFloat::convertToHexString (char *DST,
0 commit comments