Created
April 27, 2012 02:35
-
-
Save sgrif/2505235 to your computer and use it in GitHub Desktop.
Sevence patch 1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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': |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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 ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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)", |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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 | |
]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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 | |
+ | |
} | |
/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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