summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2000-11-29 15:49:18 +0000
committerStanislav Malyshev <stas@php.net>2000-11-29 15:49:18 +0000
commitebffa649c363f3d58bc0c0b653e9861ca7b76bc9 (patch)
tree64acf4f2ea3823172f940dce6daf963d055e68d6
parent2cc8e2f8c79b4ca00c2e4ef953c12ea1ef6588d4 (diff)
downloadphp-git-ebffa649c363f3d58bc0c0b653e9861ca7b76bc9.tar.gz
Add more GMP functions, fix a couple of bugs
-rw-r--r--ext/gmp/TODO6
-rw-r--r--ext/gmp/config.m42
-rw-r--r--ext/gmp/gmp.c152
-rw-r--r--ext/gmp/php_gmp.h4
4 files changed, 129 insertions, 35 deletions
diff --git a/ext/gmp/TODO b/ext/gmp/TODO
index faa1008577..81098a9cc1 100644
--- a/ext/gmp/TODO
+++ b/ext/gmp/TODO
@@ -1,9 +1,5 @@
mpz_mul_2exp
mpz_[ft]div_[qr]_2exp
-mpz_popcount
-mpz_hamdist
-mpz_scan0
-mpz_scan1
V 3:
mpz_nextprime
@@ -23,4 +19,4 @@ mpz_urandom[bm]
mpz_fits_slong_p
mpz_mul_si
mpz_odd_p
-mpz_even_p \ No newline at end of file
+mpz_even_p
diff --git a/ext/gmp/config.m4 b/ext/gmp/config.m4
index 245c7e3503..d7b54e495c 100644
--- a/ext/gmp/config.m4
+++ b/ext/gmp/config.m4
@@ -5,7 +5,7 @@ dnl If your extension references something external, use with:
PHP_ARG_WITH(gmp, for gmp support,
dnl Make sure that the comment is aligned:
-[ --with-gmp Include gmp support])
+[ --with-gmp Include gmp support])
if test "$PHP_GMP" != "no"; then
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
index a148ff4e24..f57fa49e85 100644
--- a/ext/gmp/gmp.c
+++ b/ext/gmp/gmp.c
@@ -21,9 +21,6 @@
#include "php_gmp.h"
#include "ext/standard/info.h"
-/* You should tweak config.m4 so this symbol (or some else suitable)
- gets defined.
-*/
#if HAVE_GMP
#include <gmp.h>
@@ -36,8 +33,6 @@ static int le_gmp;
static unsigned char first_of_two_force_ref[] = { 2, BYREF_FORCE, BYREF_NONE };
-/* Every user visible function must have an entry in gmp_functions[].
-*/
function_entry gmp_functions[] = {
ZEND_FE(gmp_init, NULL)
ZEND_FE(gmp_intval, NULL)
@@ -74,6 +69,10 @@ function_entry gmp_functions[] = {
ZEND_FE(gmp_xor, NULL)
ZEND_FE(gmp_setbit, first_of_two_force_ref)
ZEND_FE(gmp_clrbit, first_of_two_force_ref)
+ ZEND_FE(gmp_scan0, NULL)
+ ZEND_FE(gmp_scan1, NULL)
+ ZEND_FE(gmp_popcount, NULL)
+ ZEND_FE(gmp_hamdist, NULL)
{NULL, NULL, NULL} /* Must be the last line in gmp_functions[] */
};
@@ -139,7 +138,9 @@ ZEND_MINFO_FUNCTION(gmp)
if(Z_TYPE_PP(zval) == IS_RESOURCE) { \
ZEND_FETCH_RESOURCE(gmpnumber, mpz_t *, zval, -1, GMP_RESOURCE_NAME, le_gmp);\
} else {\
- convert_to_gmp(&gmpnumber,zval);\
+ if(convert_to_gmp(&gmpnumber,zval) == FAILURE) {\
+ RETURN_FALSE;\
+ }\
ZEND_REGISTER_RESOURCE(NULL, gmpnumber, le_gmp);\
}
@@ -174,6 +175,7 @@ static int convert_to_gmp(mpz_t * *gmpnumber, zval **val)
break;
default:
zend_error(E_WARNING,"Unable to convert variable to GMP - wrong type");
+ efree(*gmpnumber);
return FAILURE;
}
@@ -181,9 +183,13 @@ static int convert_to_gmp(mpz_t * *gmpnumber, zval **val)
}
typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr);
+typedef int (*gmp_unary_opl_t)(mpz_srcptr);
+
typedef void (*gmp_unary_ui_op_t)(mpz_ptr, unsigned long);
typedef void (*gmp_binary_op_t)(mpz_ptr, mpz_srcptr, mpz_srcptr);
+typedef int (*gmp_binary_opl_t)(mpz_srcptr, mpz_srcptr);
+
typedef unsigned long (*gmp_binary_ui_op_t)(mpz_ptr, mpz_srcptr, unsigned long);
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);
@@ -192,9 +198,11 @@ typedef unsigned long (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, unsig
#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)
+#define gmp_binary_opl(op) _gmp_binary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
/* Unary operations */
#define gmp_unary_op(op) _gmp_unary_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
+#define gmp_unary_opl(op) _gmp_unary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
#define gmp_unary_ui_op(op) _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
/*
@@ -333,6 +341,33 @@ static inline void _gmp_unary_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_op_t gm
gmp_zval_unary_op(return_value,a_arg,gmp_op);
}
+static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t gmp_op) {
+ zval **a_arg;
+ mpz_t *gmpnum_a;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){
+ WRONG_PARAM_COUNT;
+ }
+
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg);
+
+ RETURN_LONG(gmp_op(*gmpnum_a));
+}
+
+static inline void _gmp_binary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_opl_t gmp_op) {
+ zval **a_arg, **b_arg;
+ mpz_t *gmpnum_a, *gmpnum_b;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){
+ WRONG_PARAM_COUNT;
+ }
+
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg);
+ FETCH_GMP_ZVAL(gmpnum_b, a_arg);
+
+ RETURN_LONG(gmp_op(*gmpnum_a, *gmpnum_b));
+}
+
/* Remove the following function when you have succesfully modified config.m4
so that your module can be compiled into PHP, it exists only for testing
@@ -844,17 +879,7 @@ ZEND_FUNCTION(gmp_invert)
*/
ZEND_FUNCTION(gmp_jacobi)
{
- zval **a_arg, **b_arg;
- mpz_t *gmpnum_a, *gmpnum_b;
-
- if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){
- WRONG_PARAM_COUNT;
- }
-
- FETCH_GMP_ZVAL(gmpnum_a, a_arg);
- FETCH_GMP_ZVAL(gmpnum_b, a_arg);
-
- RETURN_LONG(mpz_jacobi(*gmpnum_a, *gmpnum_b));
+ gmp_binary_opl(mpz_jacobi);
}
/* }}} */
@@ -863,21 +888,12 @@ ZEND_FUNCTION(gmp_jacobi)
*/
ZEND_FUNCTION(gmp_legendre)
{
- zval **a_arg, **b_arg;
- mpz_t *gmpnum_a, *gmpnum_b;
-
- if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){
- WRONG_PARAM_COUNT;
- }
-
- FETCH_GMP_ZVAL(gmpnum_a, a_arg);
- FETCH_GMP_ZVAL(gmpnum_b, a_arg);
-
- RETURN_LONG(mpz_legendre(*gmpnum_a, *gmpnum_b));
+ gmp_binary_opl(mpz_legendre);
}
/* }}} */
/* {{{ proto int gmp_cmp(resource a, resource b)
+ Compare two numbers
*/
ZEND_FUNCTION(gmp_cmp)
{
@@ -908,6 +924,7 @@ ZEND_FUNCTION(gmp_cmp)
/* }}} */
/* {{{ proto int gmp_sign(resource a)
+ Get the sign of the number
*/
ZEND_FUNCTION(gmp_sign)
{
@@ -917,7 +934,7 @@ ZEND_FUNCTION(gmp_sign)
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){
WRONG_PARAM_COUNT;
}
-
+
FETCH_GMP_ZVAL(gmpnum_a, a_arg);
RETURN_LONG(mpz_sgn(*gmpnum_a));
@@ -925,6 +942,7 @@ ZEND_FUNCTION(gmp_sign)
/* }}} */
/* {{{ proto resource gmp_random([int limiter])
+ Get random number
*/
ZEND_FUNCTION(gmp_random)
{
@@ -1069,6 +1087,82 @@ ZEND_FUNCTION(gmp_clrbit)
}
/* }}} */
+/* {{{ proto int gmp_popcount(resource a)
+ Calculate the population count of a
+ */
+ZEND_FUNCTION(gmp_popcount)
+{
+ zval **a_arg;
+ mpz_t *gmpnum_a;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){
+ WRONG_PARAM_COUNT;
+ }
+
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg);
+
+ RETURN_LONG(mpz_popcount(*gmpnum_a));
+}
+/* }}} */
+
+/* {{{ proto int gmp_hamdist(resource a, resource b)
+ Calculate hamming distance between a and b
+ */
+ZEND_FUNCTION(gmp_hamdist)
+{
+ zval **a_arg, **b_arg;
+ mpz_t *gmpnum_a, *gmpnum_b;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(1, &a_arg, &b_arg) == FAILURE){
+ WRONG_PARAM_COUNT;
+ }
+
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg);
+ FETCH_GMP_ZVAL(gmpnum_b, b_arg);
+
+ RETURN_LONG(mpz_hamdist(*gmpnum_a, *gmpnum_b));
+}
+/* }}} */
+
+/* {{{ proto int gmp_scan0(resource a, int start)
+ Find first zero bit
+ */
+ZEND_FUNCTION(gmp_scan0)
+{
+ zval **a_arg, **start_arg;
+ mpz_t *gmpnum_a;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &start_arg) == FAILURE){
+ WRONG_PARAM_COUNT;
+ }
+
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg);
+ convert_to_long_ex(start_arg);
+
+ RETURN_LONG(mpz_scan0(*gmpnum_a, Z_LVAL_PP(start_arg)));
+}
+/* }}} */
+
+/* {{{ proto int gmp_scan1(resource a, int start)
+ Find first non-zero bit
+ */
+ZEND_FUNCTION(gmp_scan1)
+{
+ zval **a_arg, **start_arg;
+ mpz_t *gmpnum_a;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &start_arg) == FAILURE){
+ WRONG_PARAM_COUNT;
+ }
+
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg);
+ convert_to_long_ex(start_arg);
+
+ RETURN_LONG(mpz_scan1(*gmpnum_a, Z_LVAL_PP(start_arg)));
+}
+/* }}} */
+
+
static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc)
{
mpz_t *gmpnum = (mpz_t *)rsrc->ptr;
diff --git a/ext/gmp/php_gmp.h b/ext/gmp/php_gmp.h
index 519a70757b..5f8c2350a0 100644
--- a/ext/gmp/php_gmp.h
+++ b/ext/gmp/php_gmp.h
@@ -71,6 +71,10 @@ ZEND_FUNCTION(gmp_xor);
ZEND_FUNCTION(gmp_random);
ZEND_FUNCTION(gmp_setbit);
ZEND_FUNCTION(gmp_clrbit);
+ZEND_FUNCTION(gmp_scan0);
+ZEND_FUNCTION(gmp_scan1);
+ZEND_FUNCTION(gmp_popcount);
+ZEND_FUNCTION(gmp_hamdist);
/*
Declare any global variables you may need between the BEGIN