Skip to content

Instantly share code, notes, and snippets.

@sgrif
Created April 27, 2012 02:35
Show Gist options
  • Save sgrif/2505235 to your computer and use it in GitHub Desktop.
Save sgrif/2505235 to your computer and use it in GitHub Desktop.
Sevence patch 1
--- ext/gmp/gmp.c.original 2011-07-12 21:43:51.000000000 -0600
+++ ext/gmp/gmp.c 2011-07-12 23:14:18.000000000 -0600
@@ -1396,7 +1396,11 @@
GMPG(rand_initialized) = 1;
}
- mpz_urandomb(*gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * __GMP_BITS_PER_MP_LIMB);
+
+// sevence...
+// mpz_urandomb(*gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * __GMP_BITS_PER_MP_LIMB);
+ mpz_urandomb(*gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * GMP_LIMB_BITS);
+// ...sevence
ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
}
--- ext/standard/basic_functions.c.original 2011-07-12 21:43:51.000000000 -0600
+++ ext/standard/basic_functions.c 2011-07-12 22:40:57.000000000 -0600
@@ -1868,6 +1868,9 @@
ZEND_BEGIN_ARG_INFO_EX(arginfo_round, 0, 0, 1)
ZEND_ARG_INFO(0, number)
ZEND_ARG_INFO(0, precision)
+// sevence...
+ ZEND_ARG_INFO(0, mode)
+// ...sevence
ZEND_END_ARG_INFO()
static
@@ -4023,6 +4026,13 @@
REGISTER_DOUBLE_CONSTANT("INF", php_get_inf(), CONST_CS | CONST_PERSISTENT);
REGISTER_DOUBLE_CONSTANT("NAN", php_get_nan(), CONST_CS | CONST_PERSISTENT);
+// sevence...
+ REGISTER_LONG_CONSTANT("ROUND_HALF_UP", PHP_ROUND_HALF_UP, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ROUND_HALF_DOWN", PHP_ROUND_HALF_DOWN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ROUND_HALF_EVEN", PHP_ROUND_HALF_EVEN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ROUND_HALF_ODD", PHP_ROUND_HALF_ODD, CONST_CS | CONST_PERSISTENT);
+// ...sevence
+
#if ENABLE_TEST_CLASS
test_class_startup();
#endif
--- ext/standard/formatted_print.c.original 2011-07-12 21:43:51.000000000 -0600
+++ ext/standard/formatted_print.c 2011-07-12 22:41:35.000000000 -0600
@@ -53,6 +53,14 @@
static char hexchars[] = "0123456789abcdef";
static char HEXCHARS[] = "0123456789ABCDEF";
+// sevence...
+double _php_math_round(double, int, int);
+
+#ifndef PHP_ROUND_HALF_UP
+#define PHP_ROUND_HALF_UP 0x01 /* Arithmetic rounding, up == away from zero */
+#endif
+// ...sevence
+
/* php_spintf_appendchar() {{{ */
inline static void
php_sprintf_appendchar(char **buffer, int *pos, int *size, char add TSRMLS_DC)
@@ -243,6 +251,13 @@
return;
}
+// sevence...
+if (fmt != 'e')
+{
+ number = _php_math_round(number, precision, PHP_ROUND_HALF_UP);
+}
+// ...sevence
+
switch (fmt) {
case 'e':
case 'E':
--- ext/standard/info.c.original 2011-07-12 21:43:51.000000000 -0600
+++ ext/standard/info.c 2011-07-12 22:42:14.000000000 -0600
@@ -478,11 +478,20 @@
PUTS("\" alt=\"PHP Logo\" /></a>");
}
+// sevence...
+// if (!sapi_module.phpinfo_as_text) {
+// php_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
+// } else {
+// php_info_print_table_row(2, "PHP Version", PHP_VERSION);
+// }
if (!sapi_module.phpinfo_as_text) {
- php_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
+ php_printf("<h1 class=\"p\">PHP Version %s.sevence</h1><p class=\"e\"><i>\"Because rounding should just work...\" -Benjamin Eric Morin</p>", PHP_VERSION);
} else {
- php_info_print_table_row(2, "PHP Version", PHP_VERSION);
+ php_info_print_table_row(2, "PHP Version", PHP_VERSION".sevence");
+ PUTS("\n\"Because rounding should just work...\" -Benjamin Eric Morin\n");
}
+// ...sevence
+
php_info_print_box_end();
php_info_print_table_start();
php_info_print_table_row(2, "System", php_uname );
--- ext/standard/math.c.original 2011-07-12 21:43:51.000000000 -0600
+++ ext/standard/math.c 2011-07-12 22:56:22.000000000 -0600
@@ -24,64 +24,237 @@
#include "php.h"
#include "php_math.h"
#include "zend_multiply.h"
+// sevence...
+#include "zend_strtod.h"
+// ...sevence
#include <math.h>
#include <float.h>
#include <stdlib.h>
+// sevence...
+#ifdef _MSC_VER
+/* Disable optimizations that rely on the fact that FP registers may be changed. */
+#pragma fenv_access (on)
+#endif
+
+
+/* {{{ php_intlog10abs
+ Returns floor(log10(fabs(val))), uses fast binary search */
+static inline int php_intlog10abs(double value) {
+ int result;
+ value = fabs(value);
+
+ if (value < 1e-8 || value > 1e23) {
+ result = (int)floor(log10(value));
+ } else {
+ static const double values[] = {
+ 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
+ 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
+ 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
+ // Do a binary search with 5 steps
+ result = 16;
+ if (value < values[result]) {
+ result -= 8;
+ } else {
+ result += 8;
+ }
+ if (value < values[result]) {
+ result -= 4;
+ } else {
+ result += 4;
+ }
+ if (value < values[result]) {
+ result -= 2;
+ } else {
+ result += 2;
+ }
+ if (value < values[result]) {
+ result -= 1;
+ } else {
+ result += 1;
+ }
+ if (value < values[result]) {
+ result -= 1;
+ }
+ result -= 8;
+ }
+ return result;
+}
+/* }}} */
+
+double _php_intlog10abs(double value) {
+ return php_intlog10abs(value);
+}
+
+
+/* {{{ php_intpow10
+ Returns pow(10.0, (double)power), uses fast lookup table for exact powers */
+static inline double php_intpow10(int power) {
+ static const double powers[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
+ 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
+ 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
+
+ /* Not in lookup table */
+ if (power < 0 || power > 22) {
+ return pow(10.0, (double)power);
+ }
+ return powers[power];
+}
+/* }}} */
+
+/* {{{ php_round_helper
+ Actually performs the rounding of a value to integer in a certain mode */
+static inline double php_round_helper(double value, int mode) {
+ _ZEND_FPU_CW_DECLARE
+ double tmp_value;
+
+ _ZEND_FPU_CW_SET
+ if (value >= 0.0) {
+ tmp_value = floor(value + 0.5);
+ if ((mode == PHP_ROUND_HALF_DOWN && value == (-0.5 + tmp_value)) ||
+ (mode == PHP_ROUND_HALF_EVEN && value == (0.5 + 2 * floor(tmp_value/2.0))) ||
+ (mode == PHP_ROUND_HALF_ODD && value == (0.5 + 2 * floor(tmp_value/2.0) - 1.0)))
+ {
+ tmp_value = tmp_value - 1.0;
+ }
+ } else {
+ tmp_value = ceil(value - 0.5);
+ if ((mode == PHP_ROUND_HALF_DOWN && value == (0.5 + tmp_value)) ||
+ (mode == PHP_ROUND_HALF_EVEN && value == (-0.5 + 2 * ceil(tmp_value/2.0))) ||
+ (mode == PHP_ROUND_HALF_ODD && value == (-0.5 + 2 * ceil(tmp_value/2.0) + 1.0)))
+ {
+ tmp_value = tmp_value + 1.0;
+ }
+ }
+
+ _ZEND_FPU_CW_RESTORE
+
+ return tmp_value;
+}
+/* }}} */
+
+/* {{{ _php_math_round */
/*
- * Pertains to some of the code found in the php_round() function
- * Ref: http://www.freebsd.org/cgi/query-pr.cgi?pr=59797
- *
- * Copyright (c) 2003, Steven G. Kargl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice unmodified, this list of conditions, and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Rounds a number to a certain number of decimal places in a certain rounding
+ * mode. For the specifics of the algorithm, see http://wiki.php.net/rfc/rounding
*/
-static double php_round(double val, int places) {
- double t;
- double f = pow(10.0, (double) places);
- double x = val * f;
+PHPAPI double _php_math_round(double value, int places, int mode) {
+ _ZEND_FPU_CW_DECLARE
+ double f1, f2;
+ double tmp_value;
+ int precision_places;
- if (zend_isinf(x) || zend_isnan(x)) {
- return val;
+ _ZEND_FPU_CW_SET
+
+ precision_places = 14 - php_intlog10abs(value);
+
+ f1 = php_intpow10(abs(places));
+
+ /* If the decimal precision guaranteed by FP arithmetic is higher than
+ the requested places BUT is small enough to make sure a non-zero value
+ is returned, pre-round the result to the precision */
+ if (precision_places > places && precision_places - places < 15) {
+ f2 = php_intpow10(abs(precision_places));
+ if (precision_places >= 0) {
+ tmp_value = value * f2;
+ } else {
+ tmp_value = value / f2;
}
- if (x >= 0.0) {
- t = ceil(x);
- if ((t - x) > 0.50000000001) {
- t -= 1.0;
+ /* preround the result (tmp_value will always be something * 1e14,
+ thus never larger than 1e15 here) */
+ tmp_value = php_round_helper(tmp_value, mode);
+ f2 = php_intpow10(abs(places - precision_places));
+ /* because places < precision_places */
+ tmp_value = tmp_value / f2;
+ } else {
+ if (places >= 0) {
+ tmp_value = value * f1;
+ } else {
+ tmp_value = value / f1;
+ }
+ /* This value is beyond our precision, so rounding it is pointless */
+ if (fabs(tmp_value) >= 1e15) {
+ _ZEND_FPU_CW_RESTORE
+ return value;
}
+ }
+
+ tmp_value = php_round_helper(tmp_value, mode);
+
+ /* see if it makes sense to use simple division to round the value */
+ if (abs(places) < 23) {
+ if (places > 0) {
+ tmp_value = tmp_value / f1;
} else {
- t = ceil(-x);
- if ((t + x) > 0.50000000001) {
- t -= 1.0;
+ tmp_value = tmp_value * f1;
}
- t = -t;
+ } else {
+ /* Simple division can't be used since that will cause wrong results.
+ Instead, the number is converted to a string and back again using
+ strtod(). strtod() will return the nearest possible FP value for
+ that string. */
+
+ /* 40 Bytes should be more than enough for this format string. The
+ float won't be larger than 1e15 anyway. But just in case, use
+ snprintf() and make sure the buffer is zero-terminated */
+ char buf[40];
+ snprintf(buf, 39, "%15fe%d", tmp_value, -places);
+ buf[39] = '\0';
+ tmp_value = zend_strtod(buf, NULL);
+ /* couldn't convert to string and back */
+ if (!zend_finite(tmp_value) || zend_isnan(tmp_value)) {
+ tmp_value = value;
}
- x = t / f;
+ }
+
+ _ZEND_FPU_CW_RESTORE
- return !zend_isnan(x) ? x : t;
+ return tmp_value;
}
+/* }}} */
+
+double _php_round_to_precision(double val1, double val2, double val3) {
+/*
+wrapper to round_central (qv) for arithmetic functions
+- calculates places for round_central based on 15 digits of passed value
+ - for addition/subtraction val2 and val3 should be set to original operands to prevent
+ catastrophic loss of precision on differences
+ - for multiplication/division, val2 and val3 should be zero.
+*/
+
+double tmp_val;
+int places;
+if (fabs(val1) > fabs(val2))
+{
+ if (fabs(val1)>fabs(val3))
+ {
+ tmp_val = fabs(val1);
+ } else {
+ if (fabs(val2) > fabs(val3))
+ {
+ tmp_val = fabs(val2);
+ } else {
+ tmp_val = fabs(val3);
+ }
+ }
+} else {
+ if (fabs(val2) > fabs(val3))
+ {
+ tmp_val = fabs(val2);
+ } else {
+ tmp_val = fabs(val3);
+ }
+}
+places = 14 - php_intlog10abs(tmp_val);
+return _php_math_round(val1, places, PHP_ROUND_HALF_UP);
+
+}
+// ...sevence
+
/* {{{ proto int abs(int number)
Return the absolute value of the number */
@@ -154,16 +327,27 @@
}
/* }}} */
-/* {{{ proto float round(float number [, int precision])
+// sevence...
+///* {{{ proto float round(float number [, int precision])
+// Returns the number rounded to specified precision */
+/* {{{ proto float round(float number [, int precision [, int mode]])
Returns the number rounded to specified precision */
+// ...sevence
PHP_FUNCTION(round)
{
zval **value, **precision;
int places = 0;
+// sevence...
+ long mode = PHP_ROUND_HALF_UP;
+// ...sevence
double return_val;
- if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 ||
- zend_get_parameters_ex(ZEND_NUM_ARGS(), &value, &precision) == FAILURE) {
+// sevence...
+// if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 ||
+// zend_get_parameters_ex(ZEND_NUM_ARGS(), &value, &precision) == FAILURE) {
+ if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 3 ||
+ zend_get_parameters_ex(ZEND_NUM_ARGS(), &value, &precision, &mode) == FAILURE) {
+// ...sevence
WRONG_PARAM_COUNT;
}
@@ -186,8 +370,10 @@
return_val = (Z_TYPE_PP(value) == IS_LONG) ?
(double)Z_LVAL_PP(value) : Z_DVAL_PP(value);
- return_val = php_round(return_val, places);
-
+// sevence...
+// return_val = php_round(return_val, places);
+ return_val = _php_math_round(return_val, places, mode);
+// ...sevence
RETURN_DOUBLE(return_val);
break;
@@ -1001,7 +1187,10 @@
}
dec = MAX(0, dec);
- d = php_round(d, dec);
+// sevence...
+// d = php_round(d, dec);
+ d = _php_math_round(d, dec, PHP_ROUND_HALF_UP);
+// ...sevence
tmplen = spprintf(&tmpbuf, 0, "%.*F", dec, d);
--- ext/standard/php_math.h.original 2011-07-12 21:43:51.000000000 -0600
+++ ext/standard/php_math.h 2011-07-12 22:56:40.000000000 -0600
@@ -22,6 +22,9 @@
#ifndef PHP_MATH_H
#define PHP_MATH_H
+// sevence...
+PHPAPI double _php_math_round(double value, int places, int mode);
+// ...sevence
PHPAPI char *_php_math_number_format(double, int, char , char);
PHPAPI char * _php_math_longtobase(zval *arg, int base);
PHPAPI long _php_math_basetolong(zval *arg, int base);
@@ -160,4 +163,22 @@
#define M_SQRT3 1.73205080756887729352 /* sqrt(3) */
#endif
+// sevence...
+#ifndef PHP_ROUND_HALF_UP
+#define PHP_ROUND_HALF_UP 0x01 /* Arithmetic rounding, up == away from zero */
+#endif
+
+#ifndef PHP_ROUND_HALF_DOWN
+#define PHP_ROUND_HALF_DOWN 0x02 /* Down == towards zero */
+#endif
+
+#ifndef PHP_ROUND_HALF_EVEN
+#define PHP_ROUND_HALF_EVEN 0x03 /* Banker's rounding */
+#endif
+
+#ifndef PHP_ROUND_HALF_ODD
+#define PHP_ROUND_HALF_ODD 0x04
+#endif
+// ...sevence
+
#endif /* PHP_MATH_H */
--- sapi/cli/php_cli.c.original 2011-07-12 21:43:51.000000000 -0600
+++ sapi/cli/php_cli.c 2011-07-12 22:57:07.000000000 -0600
@@ -804,7 +804,10 @@
}
request_started = 1;
- php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2010 The PHP Group\n%s",
+// sevence...
+// php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2010 The PHP Group\n%s",
+ php_printf("PHP %s.sevence (%s) (built: %s %s) %s\n\"Because rounding should just work...\" -Benjamin Eric Morin\nCopyright (c) 1997-2010 The PHP Group\n%s",
+// ...sevence
PHP_VERSION, sapi_module.name, __DATE__, __TIME__,
#if ZEND_DEBUG && defined(HAVE_GCOV)
"(DEBUG GCOV)",
--- Zend/Zend.m4.original 2011-07-12 21:43:51.000000000 -0600
+++ Zend/Zend.m4 2011-07-12 22:57:34.000000000 -0600
@@ -104,6 +104,14 @@
AC_CHECK_FUNCS(finite isfinite isinf isnan)
+dnl sevence...
+dnl
+dnl Floating point environment control
+dnl
+AC_CHECK_HEADERS(fpu_control.h)
+AC_CHECK_FUNCS(_controlfp_s _controlfp)
+dnl ...sevence
+
ZEND_FP_EXCEPT
])
--- Zend/zend_operators.c.original 2011-07-12 21:43:51.000000000 -0600
+++ Zend/zend_operators.c 2011-07-12 22:58:57.000000000 -0600
@@ -42,6 +42,15 @@
#define zend_tolower(c) tolower(c)
#endif
+// sevence...
+double _php_round_to_precision(double, double, double);
+double _php_math_round(double, int, int);
+//int _php_intlog10abs(double);
+#ifndef PHP_ROUND_HALF_UP
+#define PHP_ROUND_HALF_UP 0x01 /* Arithmetic rounding, up == away from zero */
+#endif
+// ...sevence
+
ZEND_API int zend_atoi(const char *str, int str_len)
{
int retval;
@@ -597,6 +606,12 @@
case IS_DOUBLE: {
TSRMLS_FETCH();
dval = op->value.dval;
+
+// sevence...
+//dval = _php_math_round(dval,(((int) EG(precision))-(1+_php_intlog10abs(dval))), PHP_ROUND_HALF_UP);
+dval = _php_math_round(dval,((int) EG(precision)), PHP_ROUND_HALF_UP);
+// ...sevence
+
op->value.str.len = zend_spprintf(&op->value.str.val, 0, "%.*G", (int) EG(precision), dval); /* SAFE */
/* %G already handles removing trailing zeros from the fractional part, yay */
break;
@@ -822,11 +837,21 @@
(((double) op1->value.lval) + op2->value.dval) :
(op1->value.dval + ((double) op2->value.lval)));
result->type = IS_DOUBLE;
+
+// sevence...
+result->value.dval = _php_round_to_precision(result->value.dval,op1->type == IS_LONG ?((double)op1->value.lval):op1->value.dval,op2->type == IS_LONG?((double)op2->value.lval):op2->value.dval);
+// ...sevence
+
return SUCCESS;
}
if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) {
result->type = IS_DOUBLE;
result->value.dval = op1->value.dval + op2->value.dval;
+
+// sevence...
+result->value.dval = _php_round_to_precision(result->value.dval,op1->value.dval,op2->value.dval);
+// ...sevence
+
return SUCCESS;
}
zend_error(E_ERROR, "Unsupported operand types");
@@ -862,11 +887,21 @@
(((double) op1->value.lval) - op2->value.dval) :
(op1->value.dval - ((double) op2->value.lval)));
result->type = IS_DOUBLE;
+
+// sevence...
+result->value.dval = _php_round_to_precision(result->value.dval,op1->type == IS_LONG ?((double)op1->value.lval):op1->value.dval,op2->type == IS_LONG?((double)op2->value.lval):op2->value.dval);
+// ...sevence
+
return SUCCESS;
}
if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) {
result->type = IS_DOUBLE;
result->value.dval = op1->value.dval - op2->value.dval;
+
+// sevence...
+result->value.dval = _php_round_to_precision(result->value.dval,op1->value.dval,op2->value.dval);
+// ...sevence
+
return SUCCESS;
}
zend_error(E_ERROR, "Unsupported operand types");
@@ -894,11 +929,21 @@
(((double) op1->value.lval) * op2->value.dval) :
(op1->value.dval * ((double) op2->value.lval)));
result->type = IS_DOUBLE;
+
+// sevence...
+result->value.dval = _php_round_to_precision(result->value.dval,0,0);
+// ...sevence
+
return SUCCESS;
}
if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) {
result->type = IS_DOUBLE;
result->value.dval = op1->value.dval * op2->value.dval;
+
+// sevence...
+result->value.dval = _php_round_to_precision(result->value.dval,0,0);
+// ...sevence
+
return SUCCESS;
}
zend_error(E_ERROR, "Unsupported operand types");
@@ -938,11 +983,21 @@
(((double) op1->value.lval) / op2->value.dval) :
(op1->value.dval / ((double) op2->value.lval)));
result->type = IS_DOUBLE;
+
+// sevence...
+result->value.dval = _php_round_to_precision(result->value.dval,0,0);
+// ...sevence
+
return SUCCESS;
}
if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) {
result->type = IS_DOUBLE;
result->value.dval = op1->value.dval / op2->value.dval;
+
+// sevence...
+result->value.dval = _php_round_to_precision(result->value.dval,0,0);
+// ...sevence
+
return SUCCESS;
}
zend_error(E_ERROR, "Unsupported operand types");
@@ -2083,7 +2138,16 @@
{
TSRMLS_FETCH();
- op->value.str.len = zend_spprintf(&op->value.str.val, 0, "%.*G", (int) EG(precision), (double)op->value.dval);
+// sevence...
+// op->value.str.len = zend_spprintf(&op->value.str.val, 0, "%.*G", (int) EG(precision), (double)op->value.dval);
+
+ double dval = op->value.dval;
+// dval = _php_math_round(dval,(((int) EG(precision))-(1+_php_intlog10abs(dval))), PHP_ROUND_HALF_UP);
+ dval = _php_math_round(dval,((int) EG(precision)), PHP_ROUND_HALF_UP);
+ op->value.str.len = zend_spprintf(&op->value.str.val, 0, "%.*G", (int) EG(precision), dval);
+
+// ...sevence
+
}
/*
--- Zend/zend_strtod.h.original 2011-07-12 21:43:54.000000000 -0600
+++ Zend/zend_strtod.h 2011-07-12 22:59:26.000000000 -0600
@@ -32,6 +32,41 @@
ZEND_API double zend_oct_strtod(const char *str, char **endptr);
ZEND_API int zend_startup_strtod(void);
ZEND_API int zend_shutdown_strtod(void);
+
+// sevence...
+/* Depending on system configuration, define macros that make sure the FP
+ environment is set to double precision. */
+#ifdef HAVE_FPU_CONTROL_H
+# include <fpu_control.h>
+# define _ZEND_FPU_CW_DECLARE fpu_control_t _zend_fpu_oldcw, _zend_fpu_cw;
+# define _ZEND_FPU_CW_SET _FPU_GETCW(_zend_fpu_oldcw); \
+ _zend_fpu_cw = (_zend_fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_SINGLE) | _FPU_DOUBLE; \
+ _FPU_SETCW(_zend_fpu_cw);
+# define _ZEND_FPU_CW_RESTORE _FPU_SETCW(_zend_fpu_oldcw);
+#else
+# ifdef HAVE__CONTROLFP_S
+# include <float.h>
+# define _ZEND_FPU_CW_DECLARE unsigned int _zend_fpu_oldcw, _zend_fpu_cw;
+# define _ZEND_FPU_CW_SET _controlfp_s(&_zend_fpu_cw, 0, 0); \
+ _zend_fpu_oldcw = _zend_fpu_cw; \
+ _controlfp_s(&_zend_fpu_cw, _PC_53, _MCW_PC);
+# define _ZEND_FPU_CW_RESTORE _controlfp_s(&_zend_fpu_cw, _zend_fpu_oldcw, _MCW_PC);
+# else
+# ifdef HAVE__CONTROL_FP
+# include <float.h>
+# define _ZEND_FPU_CW_DECLARE unisgned int _zend_fpu_oldcw;
+# define _ZEND_FPU_CW_SET oldcw = _controlfp(0, 0); \
+ _controlfp(_PC_53, _MCW_PC);
+# define _ZEND_FPU_CW_RESTORE _controlfp(oldcw, _MCW_PC);
+# else
+# define _ZEND_FPU_CW_DECLARE /* NOP */
+# define _ZEND_FPU_CW_SET /* NOP */
+# define _ZEND_FPU_CW_RESTORE /* NOP */
+# endif
+# endif
+#endif
+// ...sevence
+
END_EXTERN_C()
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment