]> granicus.if.org Git - php/commitdiff
Fix rounding of zend_dval_to_lval
authorGustavo Lopes <glopes@nebm.ist.utl.pt>
Fri, 22 Feb 2013 23:41:39 +0000 (00:41 +0100)
committerGustavo Lopes <glopes@nebm.ist.utl.pt>
Sat, 23 Feb 2013 16:55:50 +0000 (16:55 +0000)
Now rounding is always towards zero; the rounding can be though as if
occurring on the original double. Only relevant for the 32-bit long
variant.

Zend/tests/dval_to_lval_32.phpt
Zend/zend_operators.h

index ddb16ccb821a1292aca2533b552adde7be857b02..f2acc39f51ff7d3a21109cab56709d0448411823 100644 (file)
@@ -15,6 +15,8 @@ if (PHP_INT_SIZE != 4)
                -3999999999999999475712.,
                -3999999999999998951424.,
        ];
+       /* see if we're rounding negative numbers right */
+       $values[] = -2147483649.8;
 
        foreach ($values as $v) {
                var_dump((int)$v);
@@ -27,3 +29,4 @@ int(-2055733248)
 int(-2055208960)
 int(-2054684672)
 int(-2054160384)
+int(2147483647)
index a3a432ff15b2d07794d334208083040b7c84dbdd..a82c14b8c260207da5383c147a394618d6ff7e82 100644 (file)
@@ -77,7 +77,9 @@ static zend_always_inline long zend_dval_to_lval(double d)
 
                dmod = fmod(d, two_pow_32);
                if (dmod < 0) {
-                       dmod += two_pow_32;
+                       /* 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;
        }
@@ -93,6 +95,8 @@ static zend_always_inline long zend_dval_to_lval(double d)
 
                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;