rfc:rounding

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
Last revisionBoth sides next revision
rfc:rounding [2008/08/23 20:43] – created cseilerrfc:rounding [2008/12/02 16:45] – changed status, link updates cseiler
Line 3: Line 3:
   * Date: 2008-08-23   * Date: 2008-08-23
   * Author: Christian Seiler <chris_se@gmx.net>   * Author: Christian Seiler <chris_se@gmx.net>
-  * Status: Under Discussion+  * Status: Implemented
   * First Published at: http://wiki.php.net/rfc/rounding   * First Published at: http://wiki.php.net/rfc/rounding
  
Line 173: Line 173:
 discussion. discussion.
  
-=== Frist version of math.c in CVS ===+=== First version of math.c in CVS ===
  
    * Signature: round($float), rounds to integer, no precision argument    * Signature: round($float), rounds to integer, no precision argument
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: Every other language supporting printf() or similar format strings portability: Every other language supporting printf() or similar format strings
-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("%.2f", round($float, 2)); if one really It is always possible to do printf("%.2f", round($float, 2)); if one really
 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 may have adverse effects when debugging floating +printf() bigint algorithm will have adverse effects on the fact that printf 
-point algorithms where a extremely high precision is wanted.+is often used with very high precision (> 20) to debug floating point algorithms.
  
 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://www.christian-seiler.de/projekte/fpmath/ for further information 
 +on how to ensure double precision on different architectures, operating 
 +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; +
-+
-</code> +
- +
-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 macros in order to ensure double+The round function uses the new ZEND_FLOAT macros in order to ensure double
 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 to PHP_5_3 and HEAD.
-[[http://www.christian-seiler.de/temp/php/2008-08-23-rounding/rounding-5.3-1.patch]]. +
-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.hbut there may +I tested the patch under Linux 32 bit x86Linux 64 bit x86_64, Windows 
-be a better place for thatAlso, the configure checks for those makros are +32 bit x86 and FreeBSD 32 bit x86Additionally, the macros themselves were 
-currently in ext/standard/config.{m4,w32} while they are probably better +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