Add an IEEE remainder function, which is not
authorDale Johannesen <dalej@apple.com>
Tue, 20 Jan 2009 18:35:05 +0000 (18:35 +0000)
committerDale Johannesen <dalej@apple.com>
Tue, 20 Jan 2009 18:35:05 +0000 (18:35 +0000)
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

include/llvm/ADT/APFloat.h
lib/Support/APFloat.cpp

index d51bcf5cc5eccd19105c63ac249acb8964232c51..5b09d48b0f05a21bb14c87d1bdf582ed54214ab5 100644 (file)
@@ -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);
 
index fde157d60fc0bb229d09c1620d411a3109a1ee13..151f9d5b392649ad76f4b67317cdf4ee039bde3d 100644 (file)
@@ -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)
 {