https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17097754782016-03-24T04:20:46ZRuby Issue Tracking SystemRuby master - Bug #12209: Array#pack("G") problemhttps://bugs.ruby-lang.org/issues/12209?journal_id=576242016-03-24T04:20:46Znaruse (Yui NARUSE)naruse@airemix.jp
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Feedback</i></li></ul><p>It looks because of x87 FPU's internal calculation behavior.</p>
<p>x87 always calculates floating points with 80bit precision on their register, even if the number is 64bit double.<br>
And only when the number is assigned to a 64bit double variable, the number is rounded into 64bit.</p>
<p>It seems the reason why when you use ';' instead of ',', the issue disappear.</p>
<p>You may force FPU to always round in 64bit by following ways:<br>
(1) assign the number to a variable<br>
(2) specify -ffloat-store for gcc/clang, -Op for VC6, -fp:precise for VC8+.<br>
(3) specify -msse2 -mfpmath=sse or similar one</p>
<p>(1) is the one Vit suggested and marcandre commited.<br>
It is still problematic because a smart C compiler will optimize out a variable.<br>
Failed test results I showed in are because of it.<br>
So you must add volatile to guard the variable from such optimization.<br>
But it is barrier for optimization on non x87 FPU.</p>
<p>(2) is not so good because it effects above volatile effect all over the code.<br>
It degrade the speed.</p>
<p>(3) uses SSE2 to calculate floating point numbers.<br>
This doesn't have such speed penalty, but it is less portable for CPUs.</p> Ruby master - Bug #12209: Array#pack("G") problemhttps://bugs.ruby-lang.org/issues/12209?journal_id=576252016-03-24T06:08:50Zjohan556 (Johan Holmberg)johan556@gmail.com
<ul></ul><p>I am aware of the x87 vs. SSE2 differences, but I don't think this issue has anything to do with that.</p>
<p>Note that my example demonstrated that a given Float, when processed by pack("G") + unpack("G") is changed into another bit pattern. No floating point calculation is involved. Also note that when pack("D") + unpack("D") is used, I get back the bit pattern I started with. That should have happened with "G" too.</p>
<p>The difference between these two cases is that conversions with "D" uses "native format", but "G" uses "network (big-endian) byte order". And for "network byte order", the macro HTOND used in "pack.c" was supposed to rearrange the bytes in the correct order.</p>
<p>In both 32-bit and 64-bit Ruby, a Float is a "double" at C level and has size 64-bit.</p> Ruby master - Bug #12209: Array#pack("G") problemhttps://bugs.ruby-lang.org/issues/12209?journal_id=576522016-03-24T09:00:58Zkazuho (Kazuho Oku)
<ul></ul><p>This is obviously a bug in the Ruby-side.</p>
<p>The original code, after swapping the bytes of a double, assigns it to a double.</p>
<pre><code>d = (..., d);
</code></pre>
<p>At this point, bit pattern of the right-hand expression ends with f67f, which is a signalling NAN for x87.</p>
<p>However, there is no guarantee that the bit pattern of a NAN is retained after being assigned. In this case, I assume x87 is converting the value to quiet NAN, as discussed in <a href="http://stackoverflow.com/questions/22816095/signalling-nan-was-corrupted-when-returning-from-x86-function-flds-fstps-of-x87" class="external">http://stackoverflow.com/questions/22816095/signalling-nan-was-corrupted-when-returning-from-x86-function-flds-fstps-of-x87</a>.</p>
<p>That is why the bit pattern changes to fe7f.</p> Ruby master - Bug #12209: Array#pack("G") problemhttps://bugs.ruby-lang.org/issues/12209?journal_id=594962016-07-05T02:09:00Znaruse (Yui NARUSE)naruse@airemix.jp
<ul><li><strong>Status</strong> changed from <i>Feedback</i> to <i>Closed</i></li></ul><p>Applied in changeset r55573.</p>
<hr>
<ul>
<li>
<p>pack.c (pack_pack): use union instead of bare variable to ease<br>
optimizations and avoid assigning x87 floating point number.<br>
<a href="/issues/12209">[ruby-core:74496]</a> [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Array#pack("G") problem (Closed)" href="https://bugs.ruby-lang.org/issues/12209">#12209</a>]</p>
</li>
<li>
<p>pack.c (pack_unpack): ditto.</p>
</li>
</ul> Ruby master - Bug #12209: Array#pack("G") problemhttps://bugs.ruby-lang.org/issues/12209?journal_id=599372016-08-04T07:37:00Zusa (Usaku NAKAMURA)usa@garbagecollect.jp
<ul><li><strong>Backport</strong> changed from <i>2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN</i> to <i>2.1: WONTFIX, 2.2: REQUIRED, 2.3: REQUIRED</i></li></ul> Ruby master - Bug #12209: Array#pack("G") problemhttps://bugs.ruby-lang.org/issues/12209?journal_id=600512016-08-10T16:19:55Znagachika (Tomoyuki Chikanaga)nagachika00@gmail.com
<ul><li><strong>Backport</strong> changed from <i>2.1: WONTFIX, 2.2: REQUIRED, 2.3: REQUIRED</i> to <i>2.1: WONTFIX, 2.2: REQUIRED, 2.3: DONE</i></li></ul><p>ruby_2_3 r55854 merged revision(s) 55573.</p> Ruby master - Bug #12209: Array#pack("G") problemhttps://bugs.ruby-lang.org/issues/12209?journal_id=601442016-08-16T05:06:41Zusa (Usaku NAKAMURA)usa@garbagecollect.jp
<ul><li><strong>Backport</strong> changed from <i>2.1: WONTFIX, 2.2: REQUIRED, 2.3: DONE</i> to <i>2.1: WONTFIX, 2.2: DONE, 2.3: DONE</i></li></ul><p>ruby_2_2 r55927 merged revision(s) 55573.</p>