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.

> (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?

> 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. 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.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to