<html>
<head>
<base href="https://llvm.org/bugs/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW --- - Conversion of APFloat and string and back can change value"
href="https://llvm.org/bugs/show_bug.cgi?id=24539">24539</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Conversion of APFloat and string and back can change value
</td>
</tr>
<tr>
<th>Product</th>
<td>libraries
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>Support Libraries
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>dan@su-root.co.uk
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>This was discussed on mailing list [1].
The bug seems to be that the conversion of an APFloat to a string (using the
"natural precision") and then converting that back into an APFloat can result
in a different value when not using ``APFloat::rmNearestTiesToEven``.
In the implementation of ``APFloat::toString(...)`` you can
specify ``FormatPrecision`` as 0. The method comments state that this
will use the "natural precision" of the number. In the actual
implementation the comments say that when FormatPrecision is 0 that
```
// We use enough digits so the number can be round-tripped back to an
// APFloat. The formula comes from "How to Print Floating-Point Numbers
// Accurately" by Steele and White.
```
Based on the above comments I expected to be able to convert an
APFloat to a string and back again when ``FormatPrecision`` is set to
zero. However this does not seem to hold. Here's some example code
that demonstrates this.
```
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/APFloat.h"
#include <string>
using namespace llvm;
std::string getString(APFloat f) {
SmallVector<char,10> strRep;
// FormatPrecision=0 means that the "natural precision" of the number is used
f.toString(strRep,/*FormatPrecision=*/0, /*FormatMaxPadding=*/0);
return std::string(strRep.begin(), strRep.end());
}
uint16_t getBits(APFloat f) {
APInt bits = f.bitcastToAPInt();
assert(bits.getActiveBits() <= 16);
return (uint16_t) (bits.getZExtValue() & 0xffff);
}
int main(int argc, char** argv) {
APFloat f(APFloat::IEEEhalf);
APFloat newF(APFloat::IEEEhalf);
f.convertFromString("0.3", APFloat::rmTowardZero);
outs() << "f bits: 0x";
outs().write_hex(getBits(f));
outs() << "\n";
assert(getBits(f) == 0x34cc);
// Check that if we get the string using FormatPrecision=0
// that this can be used to construct another APFloat of the
// same value.
std::string fAsString = getString(f);
outs() << "f as string: \"" << fAsString << "\"\n";
newF.convertFromString(fAsString, APFloat::rmTowardZero);
outs() << "newF as string: \"" << getString(newF) << "\"\n";
outs() << "newF bits: 0x";
outs().write_hex(getBits(newF));
outs() << "\n";
// BUG This assert fails
assert(getBits(newF) == 0x34cc);
return 0;
}
```
The output I see is
```
f bits: 0x34cc
f as string: "2.998E-1"
newF as string: "2.9956E-1"
newF bits: 0x34cb
... Assertion `getBits(newF) == 0x34cc' failed.
```
As you can see when we create a new APFloat from the string we get a
slightly smaller number. I have observed that if I use
``APFloat::rmNearestTiesToEven`` when creating ``newF`` that I do get
an APFloat instance which has the same value as the original APFloat.
[1] <a href="http://lists.llvm.org/pipermail/llvm-dev/2015-August/089085.html">http://lists.llvm.org/pipermail/llvm-dev/2015-August/089085.html</a></pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>