diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2012-08-19 10:31:50 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2012-08-19 10:31:50 +0000 | 
| commit | 902a7b529820e6a0aa85f98f21afaeb1805a22f8 (patch) | |
| tree | e7da40d2f6ef824f7371860826845870e6e1dcd5 /lib/Support/APFloat.cpp | |
| parent | 58b69754af0cbff56b1cfce9be9392e4451f6628 (diff) | |
Notes
Diffstat (limited to 'lib/Support/APFloat.cpp')
| -rw-r--r-- | lib/Support/APFloat.cpp | 22 | 
1 files changed, 20 insertions, 2 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 2139df56205b..ed261a4194c9 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -1770,23 +1770,41 @@ APFloat::opStatus APFloat::roundToIntegral(roundingMode rounding_mode) {    opStatus fs;    assertArithmeticOK(*semantics); +  // If the exponent is large enough, we know that this value is already +  // integral, and the arithmetic below would potentially cause it to saturate +  // to +/-Inf.  Bail out early instead. +  if (exponent+1 >= (int)semanticsPrecision(*semantics)) +    return opOK; +    // The algorithm here is quite simple: we add 2^(p-1), where p is the    // precision of our format, and then subtract it back off again.  The choice    // of rounding modes for the addition/subtraction determines the rounding mode    // for our integral rounding as well. -  APInt IntegerConstant(NextPowerOf2(semanticsPrecision(*semantics)), -                        1 << (semanticsPrecision(*semantics)-1)); +  // NOTE: When the input value is negative, we do subtraction followed by +  // addition instead. +  APInt IntegerConstant(NextPowerOf2(semanticsPrecision(*semantics)), 1); +  IntegerConstant <<= semanticsPrecision(*semantics)-1;    APFloat MagicConstant(*semantics);    fs = MagicConstant.convertFromAPInt(IntegerConstant, false,                                        rmNearestTiesToEven); +  MagicConstant.copySign(*this); +    if (fs != opOK)      return fs; +  // Preserve the input sign so that we can handle 0.0/-0.0 cases correctly. +  bool inputSign = isNegative(); +    fs = add(MagicConstant, rounding_mode);    if (fs != opOK && fs != opInexact)      return fs;    fs = subtract(MagicConstant, rounding_mode); + +  // Restore the input sign. +  if (inputSign != isNegative()) +    changeSign(); +    return fs;  }  | 
