====== PHP RFC: GMP Floating Point Support ====== * Version: 1.1 * Date: 2014-01-04 * Author: Sara Golemon, pollita@php.net * Status: Under Discussion * First Published at: http://wiki.php.net/rfc/gmp-floating-point ===== Introduction ===== @yohgaki suggested adding support for libgmp's arbitrary precision floating point numbers to the PHP extension, and I offered to implement it, so here's my proposal. ===== Proposal #1 ===== Extend `gmp_object` struct to the following: #define PHP_GMP_TYPE_INT 0 #define PHP_GMP_TYPE_FLOAT 1 typedef struct _gmp_object { zend_object std; char type; union { mpz_t inum; mpf_t fnum; } } gmp_object; The existing gmp_init() function will create a gmp_object with type == PHP_GMP_TYPE_INT. Add gmp_init_float(int|string $number[, $base = 0]) to create a gmp_object with type == PHP_GMP_TYPE_FLOAT Extend all other gmp_*() functions (and overload operators) to check type on the input object(s) and call the appropriate libgmp function and return the appropriate gmp_object type. Add gmp_floatval(), gmp_isint(), gmp_isfloat(), and similar introspection functions. ===== Proposal #2 ===== Rather than overload the GMP class for integer/float representations, organize Integer and Floating-Point GMP objects into a class heirarchy as so: abstract class GMPNumber {} class GMPInt extends GMPNumber {} class GMPFloat extends GMPNumber {} The same open questions exist for this approach (i.e. should int/int yield float?) ===== Backward Incompatible Changes ===== gmp_init_float() is being added to specifically avoid breakage in code currently supplying numbers which may (or may not) have decimal separators in them. Note that overloading gmp_init() to detect floating point numbers would also present a challenge as GMP parses numbers based on system locale which may use '.', ',', or other separators. Having a unique initializer avoids that problem. Actor functions and operator overloads should remain unaffected (with one exception, below) as code producing gmp_objects now will continue to do so, with the single (invisible) addition of the type byte. gmp_div() (aka gmp_div_q()), may result in a non-integer result. This function currently has three modes: GMP_ROUND_ZERO, GMP_ROUND_PLUSINF, GMP_ROUND_MINUSINF which define what to do with the leftover fractional portion. This proposal suggests adding GMP_ROUND_NONE which will produce a floating point GMP object. The existing three modes will continue to produce integer results. gmp_div_qr() would not be modified to handle GMP_ROUND_NONE as it is specifically designed to return a remainder. It would, however, still need to be extended to handle division of floating point numbers with integer 'q' and floating point 'r' results. **Open Question**: The division operator overload uses the default division mode of GMP_ROUND_ZERO. It may coincide with "The PHP Way" to change to GMP_ROUND_NONE so that floating-point results may be produced from expressions such as: gmp_init(3) / gmp_init(2) This has limited BC issues since operator overloading for GMP is very new. ===== Proposed PHP Version(s) ===== 5.next (master branch) ===== php.ini Defaults ===== Add INI setting: gmp.default_precision=(libgmp-initial-default-precision) ===== History ===== * Version 1.0: 2014-01-04 Initial Draft * Version 1.1: 2014-01-05 Added proposal #2 ===== Implementation ===== Pending discussion to decide what direction we should go.