mirror of
https://github.com/php/php-src.git
synced 2026-04-05 15:12:39 +02:00
Merge branch 'dval_to_lval' into PHP-5.5
* dval_to_lval: Fix rounding of zend_dval_to_lval Fix zend_dval_to_lval outside 64bit integers range
This commit is contained in:
@@ -64,6 +64,8 @@ print "\nDone\n";
|
||||
--EXPECTF--
|
||||
Notice: String offset cast occurred in %s on line %d
|
||||
|
||||
Notice: Uninitialized string offset: %s in %s on line 6
|
||||
|
||||
Notice: Uninitialized string offset: 0 in %s on line %d
|
||||
|
||||
Notice: Uninitialized string offset: 0 in %s on line %d
|
||||
|
||||
32
Zend/tests/dval_to_lval_32.phpt
Normal file
32
Zend/tests/dval_to_lval_32.phpt
Normal file
@@ -0,0 +1,32 @@
|
||||
--TEST--
|
||||
zend_dval_to_lval preserves low bits (32 bit long)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (PHP_INT_SIZE != 4)
|
||||
die("skip for machines with 32-bit longs");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
/* test doubles around -4e21 */
|
||||
$values = [
|
||||
-4000000000000001048576.,
|
||||
-4000000000000000524288.,
|
||||
-4000000000000000000000.,
|
||||
-3999999999999999475712.,
|
||||
-3999999999999998951424.,
|
||||
];
|
||||
/* see if we're rounding negative numbers right */
|
||||
$values[] = -2147483649.8;
|
||||
|
||||
foreach ($values as $v) {
|
||||
var_dump((int)$v);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(-2056257536)
|
||||
int(-2055733248)
|
||||
int(-2055208960)
|
||||
int(-2054684672)
|
||||
int(-2054160384)
|
||||
int(2147483647)
|
||||
29
Zend/tests/dval_to_lval_64.phpt
Normal file
29
Zend/tests/dval_to_lval_64.phpt
Normal file
@@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
zend_dval_to_lval preserves low bits (64 bit long)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (PHP_INT_SIZE != 8)
|
||||
die("skip for machines with 64-bit longs");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
/* test doubles around -4e21 */
|
||||
$values = [
|
||||
-4000000000000001048576.,
|
||||
-4000000000000000524288.,
|
||||
-4000000000000000000000.,
|
||||
-3999999999999999475712.,
|
||||
-3999999999999998951424.,
|
||||
];
|
||||
|
||||
foreach ($values as $v) {
|
||||
var_dump((int)$v);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2943463994971652096)
|
||||
int(2943463994972176384)
|
||||
int(2943463994972700672)
|
||||
int(2943463994973224960)
|
||||
int(2943463994973749248)
|
||||
@@ -68,22 +68,40 @@ END_EXTERN_C()
|
||||
|
||||
#if ZEND_DVAL_TO_LVAL_CAST_OK
|
||||
# define zend_dval_to_lval(d) ((long) (d))
|
||||
#elif SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64)
|
||||
#elif SIZEOF_LONG == 4
|
||||
static zend_always_inline long zend_dval_to_lval(double d)
|
||||
{
|
||||
if (d > LONG_MAX || d < LONG_MIN) {
|
||||
return (long)(unsigned long)(zend_long64) d;
|
||||
double two_pow_32 = pow(2., 32.),
|
||||
dmod;
|
||||
|
||||
dmod = fmod(d, two_pow_32);
|
||||
if (dmod < 0) {
|
||||
/* we're going to make this number positive; call ceil()
|
||||
* to simulate rounding towards 0 of the negative number */
|
||||
dmod = ceil(dmod) + two_pow_32;
|
||||
}
|
||||
return (long)(unsigned long)dmod;
|
||||
}
|
||||
return (long) d;
|
||||
return (long)d;
|
||||
}
|
||||
#else
|
||||
static zend_always_inline long zend_dval_to_lval(double d)
|
||||
{
|
||||
/* >= as (double)LONG_MAX is outside signed range */
|
||||
if (d >= LONG_MAX) {
|
||||
return (long)(unsigned long) d;
|
||||
if (d >= LONG_MAX || d < LONG_MIN) {
|
||||
double two_pow_64 = pow(2., 64.),
|
||||
dmod;
|
||||
|
||||
dmod = fmod(d, two_pow_64);
|
||||
if (dmod < 0) {
|
||||
/* no need to call ceil; original double must have had no
|
||||
* fractional part, hence dmod does not have one either */
|
||||
dmod += two_pow_64;
|
||||
}
|
||||
return (long)(unsigned long)dmod;
|
||||
}
|
||||
return (long) d;
|
||||
return (long)d;
|
||||
}
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
Reference in New Issue
Block a user