rfc:rounding
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
rfc:rounding [2008/08/23 20:43] – created cseiler | rfc:rounding [2017/09/22 13:28] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 3: | Line 3: | ||
* Date: 2008-08-23 | * Date: 2008-08-23 | ||
* Author: Christian Seiler < | * Author: Christian Seiler < | ||
- | * Status: | + | * Status: |
* First Published at: http:// | * First Published at: http:// | ||
Line 173: | Line 173: | ||
discussion. | discussion. | ||
- | === Frist version of math.c in CVS === | + | === First version of math.c in CVS === |
* Signature: round($float), | * Signature: round($float), | ||
Line 274: | Line 274: | ||
in a platform-independent way. The GNU C library offers the _FPU_SETCW and | in a platform-independent way. The GNU C library offers the _FPU_SETCW and | ||
_FPU_GETCW macros in fpu_control.h while on Windows Systems a function named | _FPU_GETCW macros in fpu_control.h while on Windows Systems a function named | ||
- | _controlfp is available for this job. | + | _controlfp is available for this job. FreeBSD provides fpsetprec() and other |
+ | Operating Systems that run on x86 require inline assembly. | ||
Please note that zend_strtod() is also affected by this problem: On systems | Please note that zend_strtod() is also affected by this problem: On systems | ||
Line 373: | Line 374: | ||
0.29 if used with %2f as format string. But the problem with fixing printf() is | 0.29 if used with %2f as format string. But the problem with fixing printf() is | ||
portability: | portability: | ||
- | do it wrong in the exact same way, PHP should not deviate from that (in my yes). | + | do it wrong in the exact same way, PHP should not deviate from that (in my eyes). |
It is always possible to do printf(" | It is always possible to do printf(" | ||
wants correct results, as long as round() works properly. Also, changing the | wants correct results, as long as round() works properly. Also, changing the | ||
- | printf() bigint algorithm | + | printf() bigint algorithm |
- | point algorithms where a extremely | + | is often used with very high precision |
However, the PHP manual should contain a warning for printf() that rounding may | However, the PHP manual should contain a warning for printf() that rounding may | ||
Line 394: | Line 395: | ||
==== Building an abstraction layer for FP control register manipulation ==== | ==== Building an abstraction layer for FP control register manipulation ==== | ||
- | In a first step, my patch introduces 3 macros: | + | See http:// |
+ | on how to ensure double precision on different architectures, | ||
+ | systems and with different compilers. | ||
- | * _ZEND_FPU_CW_DECLARE | + | This proposal proposes to wrap the above abstraction into the following |
- | * _ZEND_FPU_CW_SET | + | macros: |
- | * _ZEND_FPU_CW_RESTORE | + | |
- | The DECLARE macro declares certain necessary variables, the SET macro modifies | + | * ZEND_FLOAT_DECLARE |
- | the FPU control word so that double precision is used for calculation and | + | * ZEND_FLOAT_ENSURE() |
- | RESTORE restores the previous state of the control word. The following example | + | * ZEND_FLOAT_RESTORE() |
- | illustrates how these macros are to be used: | + | * ZEND_FLOAT_RETURN(val) |
- | <code c> | + | These will be defined in Zend/zend_float.h. |
- | double somefunction (double val) | + | |
- | { | + | |
- | _ZEND_FPU_CW_DECLARE; | + | |
- | double foo; | + | |
- | + | ||
- | _ZEND_FPU_CW_SET; | + | |
- | + | ||
- | /* some calculations... */ | + | |
- | foo = val / 100.0; | + | |
- | + | ||
- | /* ... */ | + | |
- | + | ||
- | _ZEND_FPU_CW_RESTORE; | + | |
- | return foo; | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | These macros expand to the correct versions for each platform or to NOPs if | + | |
- | the method for the corresponding platform could not be determined. | + | |
==== Fix of zend_strtod ==== | ==== Fix of zend_strtod ==== | ||
Line 440: | Line 423: | ||
different results. | different results. | ||
- | For this reason, my patch also fixes zend_strtod() by adding the _ZEND_FPU_CW | + | For this reason, my patch also fixes zend_strtod() by adding the proposed |
macros to the function. Then, C and PHP will yield the same results on all | macros to the function. Then, C and PHP will yield the same results on all | ||
platforms (that support IEEE 754 arithmetics anyway). | platforms (that support IEEE 754 arithmetics anyway). | ||
Line 451: | Line 434: | ||
=== Usage of FP control word manipulation === | === Usage of FP control word manipulation === | ||
- | The round function uses the new _ZEND_FPU_CW | + | The round function uses the new ZEND_FLOAT |
precision arithmetics within the function body. This will make sure the final | precision arithmetics within the function body. This will make sure the final | ||
division works properly. | division works properly. | ||
Line 525: | Line 508: | ||
==== Patch ===== | ==== Patch ===== | ||
- | The patch is available under | + | The patch was already applied |
- | [[http:// | + | |
- | It applies against the current CVS branch of 5.3, porting it to HEAD should | + | |
- | be extremely trivial (since this only affects math-related stuff). | + | |
- | + | ||
- | I tested the patch under Linux 32 bit x86, Linux 64 bit x86_64 and Windows | + | |
- | 32 bit x86. Please note that MinGW does not define _controlfp_s but does | + | |
- | define _controlfp. Thus I added a conditional ifdef to use _controlfp instead | + | |
- | if _controlfp_s is not present. This is not relevant now but may be relevant | + | |
- | when CMake is used as build system for PHP and thus PHP starts to support | + | |
- | MinGW. | + | |
- | The _ZEND_FPU_CW macros are currently defined in zend_strtod.h, but there may | + | I tested the patch under Linux 32 bit x86, Linux 64 bit x86_64, Windows |
- | be a better place for that. Also, the configure checks | + | 32 bit x86 and FreeBSD 32 bit x86. Additionally, the macros themselves were |
- | currently in ext/ | + | tested on various platforms (see the above link for details). |
- | located somewhere else. | + | |
===== Comparison with the 2004 proposal ===== | ===== Comparison with the 2004 proposal ===== | ||
Line 599: | Line 571: | ||
===== Changelog ===== | ===== Changelog ===== | ||
+ | * 2008-12-02 Christian Seiler: Updated to current situation | ||
* 2008-08-23 Christian Seiler: Created RFC | * 2008-08-23 Christian Seiler: Created RFC | ||
rfc/rounding.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1