From: Dale Johannesen Date: Tue, 20 Jan 2009 18:35:05 +0000 (+0000) Subject: Add an IEEE remainder function, which is not X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=24b66a83ca8c80417ad7523c35ece709a7e6599c;p=oota-llvm.git Add an IEEE remainder function, which is not fully implemented yet and not used. This is mainly to clarify that APFloat::mod implements C fmod, not remainder. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62593 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index d51bcf5cc5e..5b09d48b0f0 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -207,6 +207,9 @@ namespace llvm { opStatus subtract(const APFloat &, roundingMode); opStatus multiply(const APFloat &, roundingMode); opStatus divide(const APFloat &, roundingMode); + /* IEEE remainder. */ + opStatus remainder(const APFloat &); + /* C fmod, or llvm frem. */ opStatus mod(const APFloat &, roundingMode); opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode); diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index fde157d60fc..151f9d5b392 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -1514,7 +1514,45 @@ APFloat::divide(const APFloat &rhs, roundingMode rounding_mode) return fs; } -/* Normalized remainder. This is not currently doing TRT. */ +/* Normalized remainder. This is not currently correct in all cases. */ +APFloat::opStatus +APFloat::remainder(const APFloat &rhs) +{ + opStatus fs; + APFloat V = *this; + unsigned int origSign = sign; + + assertArithmeticOK(*semantics); + 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, + rmNearestTiesToEven, &ignored); + if (fs==opInvalidOp) + 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 + + fs = subtract(V, rmNearestTiesToEven); + assert(fs==opOK || fs==opInexact); // likewise + + if (isZero()) + sign = origSign; // IEEE754 requires this + delete[] x; + return fs; +} + +/* Normalized llvm frem (C fmod). + This is not currently correct in all cases. */ APFloat::opStatus APFloat::mod(const APFloat &rhs, roundingMode rounding_mode) {