Hi all,
GMP '0' object does not evaluated as empty()
$ ./php-bin -r '$v = gmp_init("0"); var_dump(empty($v), $v == 0);'
bool(false)
bool(true)
This may cause confusion and bugs in user scripts.
Most math functions does not work with GMP object neither.
We might be better to raise warning for math functions that
do not support GMP object.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Nikita,
GMP '0' object does not evaluated as empty()
$ ./php-bin -r '$v = gmp_init("0"); var_dump(empty($v), $v == 0);'
bool(false)
bool(true)This may cause confusion and bugs in user scripts.
Most math functions does not work with GMP object neither.
We might be better to raise warning for math functions that
do not support GMP object.
I'm concerned about GMP objects handling in functions.
It would be nicer if we treat GMP objects as special data type, IMHO.
Something like autoboxing or handle it as special case.
https://wiki.php.net/rfc/autoboxing
What do you think?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
I thought GMP object does not work with math functions, but some of them
work.
Apparently, I was only testing with function that does not work with GMP.
Some math function
works. e.g. pow()
with small value. min()
/max() seems ok.
Not only empty(), but there are number of wired behavior with GMP and
functions.
I haven't tried them all, but we need to work more for these.
It seems time to write more tests and fix issues.
=== pow()
===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("2"); var_dump(pow($v, 10));'
int(1024)
This works fine.
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("223423"); var_dump(pow($v, 234242));'
float(INF)
This returns float(INF). It may be acceptable. Returning GMP object with
correct value is better.
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("223423423423423423423422342342342342.234234234");
var_dump(pow($v, 234242));'
int(0)
but this returns int(0).
=== round()
/floor()/ceil()===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("25.234242342"); var_dump(round($v));'
float(0)
It should be 25. floor()
/ceil() is the same.
===abs()===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("25.234242342"); var_dump(abs($v));'
int(0)
It returns int(0).
===acos()===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("25.234242342"); var_dump(acos($v), acos(25.234242342));'
float(1.5707963267949)
float(NAN)
Something wrong.
===cos()===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("25.234242342"); var_dump(cos($v), cos(25.234242342));'
float(1)
float(0.99485318302495)
Almost correct, but it's not.
If GMP integer is passed, it raises E_WARNING.
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("2"); var_dump(cos($v), cos(2));'
Warning: cos()
expects parameter 1 to be double, object given in Command
line code on line 1
NULL
float(-0.41614683654714)
===log===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("2"); var_dump(log($v), log(2));'
Warning: log()
expects parameter 1 to be double, object given in Command
line code on line 1
NULL
float(0.69314718055995)
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("2.2"); var_dump(log($v), log(2.2));'
float(-INF)
float(0.78845736036427)
Something wrong.
Hi,
Hi all,
I thought GMP object does not work with math functions, but some of them
work.
Apparently, I was only testing with function that does not work with GMP.
Some math function
works. e.g.pow()
with small value.min()
/max() seems ok.Not only empty(), but there are number of wired behavior with GMP and
functions.I haven't tried them all, but we need to work more for these.
It seems time to write more tests and fix issues.===
pow()
===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("2"); var_dump(pow($v, 10));'
int(1024)This works fine.
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("223423"); var_dump(pow($v, 234242));'
float(INF)This returns float(INF). It may be acceptable. Returning GMP object with
correct value is better.[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("223423423423423423423422342342342342.234234234");
var_dump(pow($v, 234242));'
int(0)but this returns int(0).
===
round()
/floor()/ceil()===[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("25.234242342"); var_dump(round($v));'
float(0)It should be 25.
floor()
/ceil() is the same.===abs()===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("25.234242342"); var_dump(abs($v));'
int(0)It returns int(0).
===acos()===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("25.234242342"); var_dump(acos($v), acos(25.234242342));'
float(1.5707963267949)
float(NAN)Something wrong.
===cos()===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("25.234242342"); var_dump(cos($v), cos(25.234242342));'
float(1)
float(0.99485318302495)Almost correct, but it's not.
This is because gmp_init() yields bool(false) if you pass a floating point
value, as it should because it's meant for arbitrary-length integers ;-)
If GMP integer is passed, it raises E_WARNING.
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("2"); var_dump(cos($v), cos(2));'
Warning:cos()
expects parameter 1 to be double, object given in Command
line code on line 1
NULL
float(-0.41614683654714)===log===
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("2"); var_dump(log($v), log(2));'
Warning:log()
expects parameter 1 to be double, object given in Command
line code on line 1
NULL
float(0.69314718055995)[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r '$v =
gmp_init("2.2"); var_dump(log($v), log(2.2));'
float(-INF)
float(0.78845736036427)Something wrong.
You could argue that it would make sense to cast GMP to a native integer or
float type, but it will most likely lose precision; otherwise, what would
be the point of using GMP in the first place?
--
Tjerk
Hi Tjerk,
On Mon, Dec 30, 2013 at 3:42 PM, Tjerk Meesters tjerk.meesters@gmail.comwrote:
This is because gmp_init() yields bool(false) if you pass a floating point
value, as it should because it's meant for arbitrary-length integers ;-)
I forgot PHP's GMP implementation does not support float. Thanks.
And I was expecting
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r
'$f=2.2;$v=gmp_init($f); var_dump($v);'
Warning: gmp_init(): Unable to convert variable to GMP - wrong type in
Command line code on line 1
bool(false)
this kind of behavior for literal, too. ;)
Why is PHP not raising error for float literal?
--
Yasuo Ohgaki
yohgaki@ohgaki.net
And I was expecting
[yohgaki@dev php-src]$ ./php-bin -d error_reporting=-1 -r
'$f=2.2;$v=gmp_init($f); var_dump($v);'Warning: gmp_init(): Unable to convert variable to GMP - wrong type in
Command line code on line 1
bool(false)this kind of behavior for literal, too. ;)
Why is PHP not raising error for float literal?
ZEND_FUNCTION(gmp_init)
{
zval *number_arg;
mpz_ptr gmpnumber;
long base = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l",
&number_arg, &base) == FAILURE) {
return;
}
if (base && (base < 2 || base > MAX_BASE)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad base for
conversion: %ld (should be between 2 and %d)", base, MAX_BASE);
RETURN_FALSE;
}
INIT_GMP_RETVAL(gmpnumber);
if (convert_to_gmp(gmpnumber, number_arg, base TSRMLS_CC) == FAILURE) {
zval_dtor(return_value);
RETURN_FALSE;
}
}
Apparently, we need type check and/or float support in GMP.
Are there any technical reasons not to support GMP float?
https://gmplib.org/manual/Initializing-Floats.html#Initializing-Floats
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
Apparently, we need type check and/or float support in GMP.
We need error instead of type check.
Possible patch is
[yohgaki@dev php-src]$ git diff ext/gmp/
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
index 8835f05..a64e486 100644
--- a/ext/gmp/gmp.c
+++ b/ext/gmp/gmp.c
@@ -1036,6 +1036,7 @@ ZEND_FUNCTION(gmp_init)
INIT_GMP_RETVAL(gmpnumber);
if (convert_to_gmp(gmpnumber, number_arg, base TSRMLS_CC) ==
FAILURE) {
-
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad number
supplied");
zval_dtor(return_value);
RETURN_FALSE;
}
Any comments?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
Apparently, we need type check and/or float support in GMP.
We need error instead of type check.
Possible patch is[yohgaki@dev php-src]$ git diff ext/gmp/
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
index 8835f05..a64e486 100644
--- a/ext/gmp/gmp.c
+++ b/ext/gmp/gmp.c
@@ -1036,6 +1036,7 @@ ZEND_FUNCTION(gmp_init)INIT_GMP_RETVAL(gmpnumber); if (convert_to_gmp(gmpnumber, number_arg, base TSRMLS_CC) ==
FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad number
supplied");
zval_dtor(return_value);
RETURN_FALSE;
}Any comments?
I would like to have float support rather than this dirty patch.
We may implement GMP float support. It would be easier with object.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
I would like to have float support rather than this dirty patch.
We may implement GMP float support. It would be easier with object.Regards,
Current GMP ext exposes mpz functionality. It can be used for discrete
mathematics, e.g. modular arithmetic in the context of asymmetric crypto.
The mpq and mpf functionality also provided by gmp/mpir are something
completely separate. If you like, you can expose them to PHP as GmpRational
and GmpFloat, but you must keep them separate, otherwise you'll render the
gmp ext useless for the purposes it is currently used for. Before doing
that I would recommend to think about whether you really want bignum
rationals and floats or whether you are looking for decimals (something
traditionally provided by bcmath, but could also be implemented on top of
mpz).
Nikita
Hi Nikita,
I would like to have float support rather than this dirty patch.
We may implement GMP float support. It would be easier with object.Regards,
Current GMP ext exposes mpz functionality. It can be used for discrete
mathematics, e.g. modular arithmetic in the context of asymmetric crypto.
The mpq and mpf functionality also provided by gmp/mpir are something
completely separate. If you like, you can expose them to PHP as GmpRational
and GmpFloat, but you must keep them separate, otherwise you'll render the
gmp ext useless for the purposes it is currently used for. Before doing
that I would recommend to think about whether you really want bignum
rationals and floats or whether you are looking for decimals (something
traditionally provided by bcmath, but could also be implemented on top of
mpz).
I agree most of your argument.
GMP int and GMP float/rational have different purpose and usage.
However, users can use them separately even if we add float support in GMP.
For example, when arithmetic contains with GMP int or int, then GMP int
should use
GMP int only. When arithmetic contains GMP float, then GMP int/PHP float
may be
promoted to GMP float, like PHP int is promoted to GMP int.
If users are careful about data types in arithmetic, they can do GMP int
math as
it is now.
For math functions, we may implement GMP float support, but we may down
grade
GMP float to PHP float. (for the time being)
PHP is weakly typed language and promoting/converting value to other types
is
nature of PHP.
Therefore, adding GMP float/rational to current GMP module is natural to
me. IMHO.
I might misreading your sentence "but you must keep them separate".
Does "separate" mean what I wrote here?
I have to work on session module with limited amount of time.
If anyone is willing to work on GMP float support, I appreciate it. If
nobody is willing
to do, I may work on this.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
However, users can use them separately even if we add float support in GMP.
For example, when arithmetic contains with GMP int or int, then GMP int
should use
GMP int only. When arithmetic contains GMP float, then GMP int/PHP float
may be
promoted to GMP float, like PHP int is promoted to GMP int.
If we do this, GMP numbers work like Ruby numbers.
[yohgaki@dev php-src]$ irb
2.0.0p247 :001 > 10 / 3
=> 3
2.0.0p247 :002 > 10.0 / 3
=> 3.3333333333333335
2.0.0p247 :003 >
[yohgaki@dev php-src]$ php -a
Interactive shell
php > $g = gmp_init('10');
php > echo $g / 3;
3
php > echo 10 / 3;
3.3333333333333
It may be better to stick with PHP way, since we will have both Ruby like
arithmetic and
PHP arithmetic.
Any comments?
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
Apparently, we need type check and/or float support in GMP.
We need error instead of type check.
Possible patch is[yohgaki@dev php-src]$ git diff ext/gmp/
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
index 8835f05..a64e486 100644
--- a/ext/gmp/gmp.c
+++ b/ext/gmp/gmp.c
@@ -1036,6 +1036,7 @@ ZEND_FUNCTION(gmp_init)INIT_GMP_RETVAL(gmpnumber); if (convert_to_gmp(gmpnumber, number_arg, base TSRMLS_CC) ==
FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad number
supplied");
zval_dtor(return_value);
RETURN_FALSE;
}Any comments?
I added an error check for the 5.6 branch (
http://git.php.net/?p=php-src.git;a=commitdiff;h=5408f1e5a68fead0057c95df57cfb1ff0cc3fe81).
Don't know why this particular branch was was not checked previously.
Nikita
Hi,
because in my world the following operations should be the same:
(expect that "empty" doesn't trigger a warning in an unknown variable)
$v = gmp_init("0");
if (!$v) {}
if ($v != true) {}
if ($v == false) {}
if (empty($v)) {}
... so in my world "empty" should be handled the same as "$v == false"
and such comparison operation is possible to define by the GMP object if
it's not already.
Thoughts?
Marc
Am 29.12.2013 09:04, schrieb Yasuo Ohgaki:
Hi all,
GMP '0' object does not evaluated as empty()
$ ./php-bin -r '$v = gmp_init("0"); var_dump(empty($v), $v == 0);'
bool(false)
bool(true)This may cause confusion and bugs in user scripts.
Most math functions does not work with GMP object neither.
We might be better to raise warning for math functions that
do not support GMP object.Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net