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.