@@ -36,7 +36,7 @@ static inline int php_intlog10abs(double value) {
36
36
value = fabs (value );
37
37
38
38
if (value < 1e-8 || value > 1e22 ) {
39
- return (int ) floor (log10 (value ));
39
+ return (int )floor (log10 (value ));
40
40
} else {
41
41
/* Do a binary search with 5 steps */
42
42
int result = 15 ;
@@ -79,7 +79,7 @@ static inline int php_intlog10abs(double value) {
79
79
static inline double php_intpow10 (int power ) {
80
80
/* Not in lookup table */
81
81
if (power < 0 || power > 22 ) {
82
- return pow (10.0 , (double ) power );
82
+ return pow (10.0 , (double )power );
83
83
}
84
84
85
85
static const double powers [] = {
@@ -197,7 +197,7 @@ PHPAPI double _php_math_round(double value, int places, int mode) {
197
197
return value ;
198
198
}
199
199
200
- places = places < INT_MIN + 1 ? INT_MIN + 1 : places ;
200
+ places = places < INT_MIN + 1 ? INT_MIN + 1 : places ;
201
201
precision_places = 14 - php_intlog10abs (value );
202
202
203
203
f1 = php_intpow10 (abs (places ));
@@ -206,9 +206,9 @@ PHPAPI double _php_math_round(double value, int places, int mode) {
206
206
the requested places BUT is small enough to make sure a non-zero value
207
207
is returned, pre-round the result to the precision */
208
208
if (precision_places > places && precision_places - 15 < places ) {
209
- int64_t use_precision = precision_places < INT_MIN + 1 ? INT_MIN + 1 : precision_places ;
209
+ int64_t use_precision = precision_places < INT_MIN + 1 ? INT_MIN + 1 : precision_places ;
210
210
211
- f2 = php_intpow10 (abs ((int ) use_precision ));
211
+ f2 = php_intpow10 (abs ((int )use_precision ));
212
212
if (use_precision >= 0 ) {
213
213
tmp_value = value * f2 ;
214
214
} else {
@@ -219,9 +219,9 @@ PHPAPI double _php_math_round(double value, int places, int mode) {
219
219
tmp_value = php_round_helper (tmp_value , mode );
220
220
221
221
use_precision = places - precision_places ;
222
- use_precision = use_precision < INT_MIN + 1 ? INT_MIN + 1 : use_precision ;
222
+ use_precision = use_precision < INT_MIN + 1 ? INT_MIN + 1 : use_precision ;
223
223
/* now correctly move the decimal point */
224
- f2 = php_intpow10 (abs ((int ) use_precision ));
224
+ f2 = php_intpow10 (abs ((int )use_precision ));
225
225
/* because places < precision_places */
226
226
tmp_value = tmp_value / f2 ;
227
227
} else {
@@ -1353,6 +1353,16 @@ PHP_FUNCTION(number_format)
1353
1353
break ;
1354
1354
1355
1355
case IS_DOUBLE :
1356
+ // double values of >= 2^52 can not have fractional digits anymore
1357
+ // Casting to long on 64bit will not loose precision on rounding
1358
+ if (UNEXPECTED (
1359
+ (Z_DVAL_P (num ) >= 4503599627370496.0 || Z_DVAL_P (num ) <= -4503599627370496.0 )
1360
+ && ZEND_DOUBLE_FITS_LONG (Z_DVAL_P (num ))
1361
+ )) {
1362
+ RETURN_STR (_php_math_number_format_long ((zend_long )Z_DVAL_P (num ), dec , dec_point , dec_point_len , thousand_sep , thousand_sep_len ));
1363
+ break ;
1364
+ }
1365
+
1356
1366
if (dec >= 0 ) {
1357
1367
dec_int = ZEND_LONG_INT_OVFL (dec ) ? INT_MAX : (int )dec ;
1358
1368
} else {
0 commit comments