Handle storage complications of float->float conversions.
authorNeil Booth <neil@daikokuya.co.uk>
Sat, 22 Sep 2007 02:56:19 +0000 (02:56 +0000)
committerNeil Booth <neil@daikokuya.co.uk>
Sat, 22 Sep 2007 02:56:19 +0000 (02:56 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42220 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/APFloat.cpp

index 1fab6cae47e8039c431b8f7675c58e06083f3fcb..2b9930cad6b404d25916634b94753e62cdae14cd 100644 (file)
@@ -1318,39 +1318,44 @@ APFloat::opStatus
 APFloat::convert(const fltSemantics &toSemantics,
                 roundingMode rounding_mode)
 {
-  unsigned int newPartCount;
+  lostFraction lostFraction;
+  unsigned int newPartCount, oldPartCount;
   opStatus fs;
-
+  
+  lostFraction = lfExactlyZero;
   newPartCount = partCountForBits(toSemantics.precision + 1);
+  oldPartCount = partCount();
 
-  /* If our new form is wider, re-allocate our bit pattern into wider
-     storage.
-     If we're narrowing from multiple words to 1 words, copy to the single
-     word.  If we are losing information by doing this, we would have to
-     worry about rounding; right now the only case is f80 -> shorter
-     conversion, and we are keeping all 64 significant bits, so it's OK. */
-  if(newPartCount > partCount()) {
+  /* Handle storage complications.  If our new form is wider,
+     re-allocate our bit pattern into wider storage.  If it is
+     narrower, we ignore the excess parts, but if narrowing to a
+     single part we need to free the old storage.  */
+  if (newPartCount > oldPartCount) {
     integerPart *newParts;
 
     newParts = new integerPart[newPartCount];
     APInt::tcSet(newParts, 0, newPartCount);
-    APInt::tcAssign(newParts, significandParts(), partCount());
+    APInt::tcAssign(newParts, significandParts(), oldPartCount);
     freeSignificand();
     significand.parts = newParts;
-  } else if (newPartCount==1 && newPartCount < partCount()) {
-    integerPart newPart;
-
-    APInt::tcSet(&newPart, 0, newPartCount);
-    APInt::tcAssign(&newPart, significandParts(), partCount());
-    freeSignificand();
-    significand.part = newPart;
+  } else if (newPartCount < oldPartCount) {
+    /* Capture any lost fraction through truncation of parts so we get
+       correct rounding whilst normalizing.  */
+    lostFraction = lostFractionThroughTruncation
+      (significandParts(), oldPartCount, toSemantics.precision);
+    if (newPartCount == 1)
+      {
+       integerPart newPart = significandParts()[0];
+       freeSignificand();
+       significand.part = newPart;
+      }
   }
 
   if(category == fcNormal) {
     /* Re-interpret our bit-pattern.  */
     exponent += toSemantics.precision - semantics->precision;
     semantics = &toSemantics;
-    fs = normalize(rounding_mode, lfExactlyZero);
+    fs = normalize(rounding_mode, lostFraction);
   } else {
     semantics = &toSemantics;
     fs = opOK;