Index: lib/Support/APFloat.cpp =================================================================== --- lib/Support/APFloat.cpp +++ lib/Support/APFloat.cpp @@ -1739,43 +1739,28 @@ return fs; } -/* Normalized llvm frem (C fmod). - This is not currently correct in all cases. */ +/* Normalized llvm frem (C fmod). */ IEEEFloat::opStatus IEEEFloat::mod(const IEEEFloat &rhs) { opStatus fs; fs = modSpecials(rhs); if (isFiniteNonZero() && rhs.isFiniteNonZero()) { - IEEEFloat V = *this; - unsigned int origSign = sign; - - fs = V.divide(rhs, rmNearestTiesToEven); - if (fs == opDivByZero) - return fs; - - int parts = partCount(); - integerPart *x = new integerPart[parts]; - bool ignored; - fs = V.convertToInteger(x, parts * integerPartWidth, true, - rmTowardZero, &ignored); - if (fs==opInvalidOp) { - delete[] x; - return fs; - } - - fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true, - rmNearestTiesToEven); - assert(fs==opOK); // should always work - - fs = V.multiply(rhs, rmNearestTiesToEven); - assert(fs==opOK || fs==opInexact); // should not overflow or underflow + while (true) { + IEEEFloat V = *this; - fs = subtract(V, rmNearestTiesToEven); - assert(fs==opOK || fs==opInexact); // likewise + fs = V.divide(rhs, rmTowardZero); + if (fs == opDivByZero) + return fs; + V.roundToIntegral(rmTowardZero); + if (V.isZero()) + break; - if (isZero()) - sign = origSign; // IEEE754 requires this - delete[] x; + /* *this = *this - V*rhs */ + V.sign = !V.sign; + fs = V.fusedMultiplyAdd(rhs, *this, rmTowardZero); + assert(fs==opOK); // should always be exact + *this = V; + } } return fs; }