summaryrefslogtreecommitdiff
path: root/ext/gmp
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-02-16 10:13:02 +0100
committerOndřej Surý <ondrej@sury.org>2011-02-16 10:13:02 +0100
commitfd5a0b31640419ca63d1ddeaffd6d3cf2a741814 (patch)
treebfd17d84c5181d7b98d7d66f56573f4fc897e31c /ext/gmp
parent01fcdff3849c3691d9aaeaab735846ab6d8895ca (diff)
downloadphp-fd5a0b31640419ca63d1ddeaffd6d3cf2a741814.tar.gz
Imported Upstream version 5.3.5upstream/5.3.5
Diffstat (limited to 'ext/gmp')
-rw-r--r--ext/gmp/gmp.c55
-rw-r--r--ext/gmp/tests/005.phpt10
-rw-r--r--ext/gmp/tests/040.phpt2
-rw-r--r--ext/gmp/tests/bug50283.phpt9
-rw-r--r--ext/gmp/tests/bug52906.phpt46
-rw-r--r--ext/gmp/tests/gmp_nextprime.phpt2
6 files changed, 90 insertions, 34 deletions
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
index f53dcd652..8d36c7f1e 100644
--- a/ext/gmp/gmp.c
+++ b/ext/gmp/gmp.c
@@ -316,6 +316,14 @@ static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc TSRMLS_DC);
#define GMP_ROUND_PLUSINF 1
#define GMP_ROUND_MINUSINF 2
+/* The maximum base for input and output conversions is 62 from GMP 4.2
+ * onwards. */
+#if (__GNU_MP_VERSION >= 5) || (__GNU_MP_VERSION >= 4 && __GNU_MP_VERSION_MINOR >= 2)
+# define MAX_BASE 62
+#else
+# define MAX_BASE 36
+#endif
+
/* {{{ gmp_emalloc
*/
static void *gmp_emalloc(size_t size)
@@ -484,8 +492,8 @@ typedef void (*gmp_binary_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr);
typedef unsigned long (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long);
/* }}} */
-#define gmp_zval_binary_ui_op(r, a, b, o, u) gmp_zval_binary_ui_op_ex(r, a, b, o, u, 0, 0 TSRMLS_CC)
-#define gmp_zval_binary_ui_op2(r, a, b, o, u) gmp_zval_binary_ui_op2_ex(r, a, b, o, u, 0, 0 TSRMLS_CC)
+#define gmp_zval_binary_ui_op(r, a, b, o, u) gmp_zval_binary_ui_op_ex(r, a, b, o, u, 0, 0, 0 TSRMLS_CC)
+#define gmp_zval_binary_ui_op2(r, a, b, o, u) gmp_zval_binary_ui_op2_ex(r, a, b, o, u, 0, 0, 0 TSRMLS_CC)
#define gmp_binary_ui_op(op, uop) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop)
#define gmp_binary_op(op) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, NULL)
@@ -500,7 +508,7 @@ typedef unsigned long (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, unsig
Execute GMP binary operation.
May return GMP resource or long if operation allows this
*/
-static inline void gmp_zval_binary_ui_op_ex(zval *return_value, zval **a_arg, zval **b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int allow_ui_return, int check_b_zero TSRMLS_DC)
+static inline void gmp_zval_binary_ui_op_ex(zval *return_value, zval **a_arg, zval **b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int allow_ui_return, int check_b_zero, int use_sign TSRMLS_DC)
{
mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result;
unsigned long long_result = 0;
@@ -536,7 +544,7 @@ static inline void gmp_zval_binary_ui_op_ex(zval *return_value, zval **a_arg, zv
if (use_ui && gmp_ui_op) {
if (allow_ui_return) {
long_result = gmp_ui_op(*gmpnum_result, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg));
- if (mpz_sgn(*gmpnum_a) == -1) {
+ if (use_sign && mpz_sgn(*gmpnum_a) == -1) {
long_result = -long_result;
}
} else {
@@ -753,12 +761,8 @@ ZEND_FUNCTION(gmp_init)
return;
}
-#if (__GNU_MP_VERSION >= 4 && __GNU_MP_VERSION_MINOR >= 2)
- if (base && (base < 2 || base > 62)) {
-#else
- if (base && (base < 2 || base > 36)) {
-#endif
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad base for conversion: %ld (should be between 2 and 36)", base);
+ 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;
}
@@ -807,12 +811,15 @@ ZEND_FUNCTION(gmp_strval)
return;
}
-#if __GNU_MP_VERSION >= 4 && __GNU_MP_VERSION_MINOR >= 2
- if ((base < 2 && base > -2) || base > 62 || base < -36) {
+#if MAX_BASE == 62
+ /* Although the maximum base in general in GMP >= 4.2 is 62, mpz_get_str()
+ * is explicitly limited to -36 when dealing with negative bases. */
+ if ((base < 2 && base > -2) || base > MAX_BASE || base < -36) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad base for conversion: %ld (should be between 2 and %d or -2 and -36)", base, MAX_BASE);
#else
- if (base < 2 || base > 36) {
+ if (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);
#endif
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad base for conversion: %ld", base);
RETURN_FALSE;
}
@@ -907,13 +914,13 @@ ZEND_FUNCTION(gmp_div_r)
switch (round) {
case GMP_ROUND_ZERO:
- gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_tdiv_r, (gmp_binary_ui_op_t)mpz_tdiv_r_ui, 1, 1 TSRMLS_CC);
+ gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_tdiv_r, (gmp_binary_ui_op_t)mpz_tdiv_r_ui, 1, 1, 1 TSRMLS_CC);
break;
case GMP_ROUND_PLUSINF:
- gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_cdiv_r, (gmp_binary_ui_op_t)mpz_cdiv_r_ui, 1, 1 TSRMLS_CC);
+ gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_cdiv_r, (gmp_binary_ui_op_t)mpz_cdiv_r_ui, 1, 1, 1 TSRMLS_CC);
break;
case GMP_ROUND_MINUSINF:
- gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_fdiv_r, (gmp_binary_ui_op_t)mpz_fdiv_r_ui, 1, 1 TSRMLS_CC);
+ gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_fdiv_r, (gmp_binary_ui_op_t)mpz_fdiv_r_ui, 1, 1, 1 TSRMLS_CC);
break;
}
}
@@ -932,13 +939,13 @@ ZEND_FUNCTION(gmp_div_q)
switch (round) {
case GMP_ROUND_ZERO:
- gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_tdiv_q, (gmp_binary_ui_op_t)mpz_tdiv_q_ui, 0, 1 TSRMLS_CC);
+ gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_tdiv_q, (gmp_binary_ui_op_t)mpz_tdiv_q_ui, 0, 1, 1 TSRMLS_CC);
break;
case GMP_ROUND_PLUSINF:
- gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_cdiv_q, (gmp_binary_ui_op_t)mpz_cdiv_q_ui, 0, 1 TSRMLS_CC);
+ gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_cdiv_q, (gmp_binary_ui_op_t)mpz_cdiv_q_ui, 0, 1, 1 TSRMLS_CC);
break;
case GMP_ROUND_MINUSINF:
- gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_fdiv_q, (gmp_binary_ui_op_t)mpz_fdiv_q_ui, 0, 1 TSRMLS_CC);
+ gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_fdiv_q, (gmp_binary_ui_op_t)mpz_fdiv_q_ui, 0, 1, 1 TSRMLS_CC);
break;
}
@@ -950,12 +957,14 @@ ZEND_FUNCTION(gmp_div_q)
ZEND_FUNCTION(gmp_mod)
{
zval **a_arg, **b_arg;
+ zval b_copy;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
return;
}
+
- gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_mod, (gmp_binary_ui_op_t)mpz_mod_ui, 1, 1 TSRMLS_CC);
+ gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_mod, (gmp_binary_ui_op_t)mpz_mod_ui, 1, 1, 0 TSRMLS_CC);
}
/* }}} */
@@ -969,7 +978,7 @@ ZEND_FUNCTION(gmp_divexact)
return;
}
- gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_divexact, NULL, 0, 1 TSRMLS_CC);
+ gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_divexact, NULL, 0, 1, 1 TSRMLS_CC);
}
/* }}} */
@@ -1217,7 +1226,7 @@ ZEND_FUNCTION(gmp_gcd)
return;
}
- gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_gcd, (gmp_binary_ui_op_t)mpz_gcd_ui, 0, 0 TSRMLS_CC);
+ gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_gcd, (gmp_binary_ui_op_t)mpz_gcd_ui, 0, 0, 1 TSRMLS_CC);
}
/* }}} */
diff --git a/ext/gmp/tests/005.phpt b/ext/gmp/tests/005.phpt
index 806b5e6e3..7907ffbf5 100644
--- a/ext/gmp/tests/005.phpt
+++ b/ext/gmp/tests/005.phpt
@@ -41,7 +41,7 @@ bool(false)
Warning: gmp_strval() expects parameter 2 to be long, string given in %s on line %d
NULL
-Warning: gmp_strval(): Bad base for conversion: -1 in %s on line %d
+Warning: gmp_strval(): Bad base for conversion: -1 (should be between 2 and %d or -2 and -%d) in %s on line %d
bool(false)
Warning: gmp_strval() expects parameter 2 to be long, string given in %s on line %d
@@ -51,18 +51,18 @@ Warning: gmp_strval(): supplied resource is not a valid GMP integer resource in
bool(false)
string(7) "9765456"
-Warning: gmp_strval(): Bad base for conversion: -1 in %s on line %d
+Warning: gmp_strval(): Bad base for conversion: -1 (should be between 2 and %d or -2 and -%d) in %s on line %d
bool(false)
-Warning: gmp_strval(): Bad base for conversion: 100000 in %s on line %d
+Warning: gmp_strval(): Bad base for conversion: 100000 (should be between 2 and %d or -2 and -%d) in %s on line %d
bool(false)
string(7) "9765456"
string(8) "-3373333"
-Warning: gmp_strval(): Bad base for conversion: -1 in %s on line %d
+Warning: gmp_strval(): Bad base for conversion: -1 (should be between 2 and %d or -2 and -%d) in %s on line %d
bool(false)
-Warning: gmp_strval(): Bad base for conversion: 100000 in %s on line %d
+Warning: gmp_strval(): Bad base for conversion: 100000 (should be between 2 and %d or -2 and -%d) in %s on line %d
bool(false)
string(8) "-3373333"
diff --git a/ext/gmp/tests/040.phpt b/ext/gmp/tests/040.phpt
index 9864cde4c..3af18cce5 100644
--- a/ext/gmp/tests/040.phpt
+++ b/ext/gmp/tests/040.phpt
@@ -32,7 +32,7 @@ NULL
Warning: gmp_init() expects at most 2 parameters, 4 given in %s on line %d
NULL
-Warning: gmp_init(): Bad base for conversion: -1 (should be between 2 and 36) in %s on line %d
+Warning: gmp_init(): Bad base for conversion: -1 (should be between 2 and %d) in %s on line %d
bool(false)
bool(false)
bool(false)
diff --git a/ext/gmp/tests/bug50283.phpt b/ext/gmp/tests/bug50283.phpt
index e8132a78f..13eef5480 100644
--- a/ext/gmp/tests/bug50283.phpt
+++ b/ext/gmp/tests/bug50283.phpt
@@ -2,6 +2,7 @@
Feature Request #50283 (allow base in gmp_strval to use full range: 2 to 62, and -2 to -36)
--SKIPIF--
<?php if (!extension_loaded("gmp")) print "skip"; ?>
+<?php if (version_compare(GMP_VERSION, "4.2.0", "<")) print "skip"; ?>
--FILE--
<?php
$a = gmp_init("0x41682179fbf5");
@@ -19,18 +20,18 @@ printf("Base 32 and 62-based: %s\n", gmp_strval(gmp_init("gh82179fbf5", 32), 62)
Decimal: 71915494046709, -36-based: PHPISCOOL
Decimal: 71915494046709, 36-based: phpiscool
-Warning: gmp_strval(): Bad base for conversion: -1 in %s on line 5
+Warning: gmp_strval(): Bad base for conversion: -1 (should be between 2 and %d or -2 and -%d) in %s on line 5
Decimal: 71915494046709, -1-based:
-Warning: gmp_strval(): Bad base for conversion: 1 in %s on line 6
+Warning: gmp_strval(): Bad base for conversion: 1 (should be between 2 and %d or -2 and -%d) in %s on line 6
Decimal: 71915494046709, 1-based:
-Warning: gmp_strval(): Bad base for conversion: -37 in %s on line 7
+Warning: gmp_strval(): Bad base for conversion: -37 (should be between 2 and %d or -2 and -%d) in %s on line 7
Decimal: 71915494046709, -37-based:
Decimal: 71915494046709, 37-based: KHKATELJF
Decimal: 71915494046709, 62-based: KQ6yq741
-Warning: gmp_strval(): Bad base for conversion: 63 in %s on line 10
+Warning: gmp_strval(): Bad base for conversion: 63 (should be between 2 and %d or -2 and -%d) in %s on line 10
Decimal: 71915494046709, 63-based:
Base 32 and 62-based: 1NHkAcdIiD
diff --git a/ext/gmp/tests/bug52906.phpt b/ext/gmp/tests/bug52906.phpt
new file mode 100644
index 000000000..60fc7417b
--- /dev/null
+++ b/ext/gmp/tests/bug52906.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Bug #52906 gmp_mod returns negative result when non-negative is expected
+--SKIPIF--
+<?php if (!extension_loaded("gmp")) print "skip"; ?>
+--FILE--
+<?php
+
+$vals = array(
+ array(7, 3),
+ array(2, 7),
+ array(12, 7),
+ array(-2, 7),
+ array(-12, 7),
+ array(2, -7),
+ array(12, -7),
+ array(-2, -7),
+ array(-12, -7),
+);
+foreach($vals as $data) {
+ echo "{$data[0]}%{$data[1]}=".gmp_strval(gmp_mod($data[0], $data[1]));
+ echo "\n";
+ echo "{$data[0]}%{$data[1]}=".gmp_strval(gmp_mod(gmp_init($data[0]), gmp_init($data[1])));
+ echo "\n";
+}
+echo "Done\n";
+?>
+--EXPECTF--
+7%3=1
+7%3=1
+2%7=2
+2%7=2
+12%7=5
+12%7=5
+-2%7=5
+-2%7=5
+-12%7=2
+-12%7=2
+2%-7=2
+2%-7=2
+12%-7=5
+12%-7=5
+-2%-7=5
+-2%-7=5
+-12%-7=2
+-12%-7=2
+Done
diff --git a/ext/gmp/tests/gmp_nextprime.phpt b/ext/gmp/tests/gmp_nextprime.phpt
index 84d945b3f..65506ce13 100644
--- a/ext/gmp/tests/gmp_nextprime.phpt
+++ b/ext/gmp/tests/gmp_nextprime.phpt
@@ -27,7 +27,7 @@ echo "Done\n";
--EXPECTF--
string(1) "2"
string(1) "2"
-string(4) "-997"
+string(1) "2"
string(4) "1009"
string(6) "100003"