Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:65750 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 28207 invoked from network); 10 Feb 2013 07:09:15 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 10 Feb 2013 07:09:15 -0000 Authentication-Results: pb1.pair.com header.from=remi@fedoraproject.org; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=remi@fedoraproject.org; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain fedoraproject.org from 212.27.42.5 cause and error) X-PHP-List-Original-Sender: remi@fedoraproject.org X-Host-Fingerprint: 212.27.42.5 smtp5-g21.free.fr Linux 2.6 Received: from [212.27.42.5] ([212.27.42.5:47287] helo=smtp5-g21.free.fr) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 01/71-20900-89747115 for ; Sun, 10 Feb 2013 02:09:14 -0500 Received: from dixsept.famillecollet.com (unknown [82.241.130.121]) by smtp5-g21.free.fr (Postfix) with ESMTP id EE1FDD480C3 for ; Sun, 10 Feb 2013 08:09:05 +0100 (CET) Message-ID: <51174790.8040805@fedoraproject.org> Date: Sun, 10 Feb 2013 08:09:04 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130110 Thunderbird/17.0.2 MIME-Version: 1.0 To: PHP Internals References: <511666DE.8080809@fedoraproject.org> <51172819.4000806@sugarcrm.com> In-Reply-To: <51172819.4000806@sugarcrm.com> X-Enigmail-Version: 1.5.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subject: Re: [PHP-DEV] double val to long val conversion issue From: remi@fedoraproject.org (Remi Collet) Le 10/02/2013 05:54, Stas Malyshev a écrit : > Hi! > >> About >> http://git.php.net/?p=php-src.git;a=commitdiff;h=79956330fe17cfd5f60de456497541b21a89bddf >> (For now, I have reverted this fix) >> >> Here some explanations. >> >> LONG_MAX is 9223372036854775807 (0x7fffffffffffffff) >> double representation of LONG_MAX is 9223372036854775808 > > I see what's going on here. We have precision loss due to the fact that > the range of double (53 bits) is smaller than the range of long (63 > bits) on 64-bit system. When it's converted back to long, I guess it has > to be expanded back to 63 bits. > >> 9223372036854775807 on ppc64 >> 9223372036854775808 on x86_64 (gcc without optimization) >> 9223372036854775807 on x86_64 (gcc -O2) >> >> PHP expected value is 9223372036854775808 > > Not sure how value of long can be expected to be 9223372036854775808 - > 9223372036854775808 is not representable in signed long. If you do > (long)(unsigned long), you'd get -9223372036854775808. Yes; I mean -9223372036854775808 (0x8000000000000000) (sorry, I have use %lu format instead of %ld in my tests) > >> (Btw, I don't understand why PHP, build on x86_64, with -O2, gives the >> good result, some environment mystery) > > With -O2, gcc probably pre-calculates the result of the operation if you > use simple test program. So, if I write: > > double b = LONG_MAX; > printf("%ld", (long)b); > > Then without -O2, I'm getting: > > movsd -16(%rbp), %xmm0 > cvttsd2siq %xmm0, %rsi > > But with -O2, it's just: > > movabsq $9223372036854775807, %rsi > > So the difference in results may stem from the fact that the > calculations go in different way here. > >> Obviously, we could have different result on different platform, >> compiler, architecture. >> >> I will be very interested by result on other platform (mac, windows), >> compiler (Visual C), architecture. >> >> If we switch to the unsigned cast: >> (long)(unsigned long)d; >> >> The result is always 9223372036854775808 (which is expected) > > Wait, long can not be 9223372036854775808, how the result of long > conversion can be that? Yes, -9223372036854775808 (0x8000000000000000) >> From my tests, this doesn't change anything on x86_64, and improves > > Well, for the value of (double)LONG_MAX the code actually changes > substantially, and if I test this code: > > double b = LONG_MAX; > printf("%ld %ld", (long)(unsigned long)b, (long)b); > > Then with -O2 I get different results: > > -9223372036854775808 9223372036854775807 > > But that may be an optimization artifact. Yes I also think. But is this couldn't occurs in real PHP, with another compiler or another gcc version ? > With real PHP, the result of > converting 9223372036854775807 to double and then back to int seems to > always be -9223372036854775808 on Intel, with or without the patch. I > don't have access to ppc64 machine so no idea what's going on there. > That's exactly the problem. On Intel, we always get -9223372036854775808 (when 9223372036854775807 could be expected, with -O2, from you previous test) On ppc64, we always get 9223372036854775807. This is exactly what I'd like to fix. And, as you said, the patch doesn't change result on Intel. I could make this change conditionnal on PPC, but I think it will also protect us from any compiler optimization change. Remi