diff options
Diffstat (limited to 'ext/gmp/gmp.c')
-rw-r--r-- | ext/gmp/gmp.c | 634 |
1 files changed, 220 insertions, 414 deletions
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index c2ac6d0a1e..ceaf49b8bc 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | @@ -30,178 +28,21 @@ #include "zend_exceptions.h" #include <gmp.h> +#include "gmp_arginfo.h" /* Needed for gmp_random() */ #include "ext/standard/php_rand.h" #include "ext/standard/php_lcg.h" #define GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) -/* {{{ arginfo */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_init, 0, 0, 1) - ZEND_ARG_INFO(0, number) - ZEND_ARG_INFO(0, base) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_import, 0, 0, 1) - ZEND_ARG_INFO(0, data) - ZEND_ARG_INFO(0, word_size) - ZEND_ARG_INFO(0, options) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_export, 0, 0, 1) - ZEND_ARG_INFO(0, gmpnumber) - ZEND_ARG_INFO(0, word_size) - ZEND_ARG_INFO(0, options) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_intval, 0, 0, 1) - ZEND_ARG_INFO(0, gmpnumber) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_strval, 0, 0, 1) - ZEND_ARG_INFO(0, gmpnumber) - ZEND_ARG_INFO(0, base) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_unary, 0, 0, 1) - ZEND_ARG_INFO(0, a) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_binary, 0, 0, 2) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_div, 0, 0, 2) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) - ZEND_ARG_INFO(0, round) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_pow, 0, 0, 2) - ZEND_ARG_INFO(0, base) - ZEND_ARG_INFO(0, exp) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_powm, 0, 0, 3) - ZEND_ARG_INFO(0, base) - ZEND_ARG_INFO(0, exp) - ZEND_ARG_INFO(0, mod) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_root, 0, 0, 2) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, nth) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_prob_prime, 0, 0, 1) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, reps) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random, 0, 0, 0) - ZEND_ARG_INFO(0, limiter) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random_seed, 0, 0, 1) - ZEND_ARG_INFO(0, seed) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random_bits, 0, 0, 1) - ZEND_ARG_INFO(0, bits) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random_range, 0, 0, 2) - ZEND_ARG_INFO(0, min) - ZEND_ARG_INFO(0, max) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_setbit, 0, 0, 2) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, index) - ZEND_ARG_INFO(0, set_clear) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_bit, 0, 0, 2) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, index) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_scan, 0, 0, 2) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, start) -ZEND_END_ARG_INFO() - -/* }}} */ - ZEND_DECLARE_MODULE_GLOBALS(gmp) static ZEND_GINIT_FUNCTION(gmp); -/* {{{ gmp_functions[] - */ -static const zend_function_entry gmp_functions[] = { - ZEND_FE(gmp_init, arginfo_gmp_init) - ZEND_FE(gmp_import, arginfo_gmp_import) - ZEND_FE(gmp_export, arginfo_gmp_export) - ZEND_FE(gmp_intval, arginfo_gmp_intval) - ZEND_FE(gmp_strval, arginfo_gmp_strval) - ZEND_FE(gmp_add, arginfo_gmp_binary) - ZEND_FE(gmp_sub, arginfo_gmp_binary) - ZEND_FE(gmp_mul, arginfo_gmp_binary) - ZEND_FE(gmp_div_qr, arginfo_gmp_div) - ZEND_FE(gmp_div_q, arginfo_gmp_div) - ZEND_FE(gmp_div_r, arginfo_gmp_div) - ZEND_FALIAS(gmp_div, gmp_div_q, arginfo_gmp_div) - ZEND_FE(gmp_mod, arginfo_gmp_binary) - ZEND_FE(gmp_divexact, arginfo_gmp_binary) - ZEND_FE(gmp_neg, arginfo_gmp_unary) - ZEND_FE(gmp_abs, arginfo_gmp_unary) - ZEND_FE(gmp_fact, arginfo_gmp_unary) - ZEND_FE(gmp_sqrt, arginfo_gmp_unary) - ZEND_FE(gmp_sqrtrem, arginfo_gmp_unary) - ZEND_FE(gmp_root, arginfo_gmp_root) - ZEND_FE(gmp_rootrem, arginfo_gmp_root) - ZEND_FE(gmp_pow, arginfo_gmp_pow) - ZEND_FE(gmp_powm, arginfo_gmp_powm) - ZEND_FE(gmp_perfect_square, arginfo_gmp_unary) - ZEND_FE(gmp_perfect_power, arginfo_gmp_unary) - ZEND_FE(gmp_prob_prime, arginfo_gmp_prob_prime) - ZEND_FE(gmp_gcd, arginfo_gmp_binary) - ZEND_FE(gmp_gcdext, arginfo_gmp_binary) - ZEND_FE(gmp_lcm, arginfo_gmp_binary) - ZEND_FE(gmp_invert, arginfo_gmp_binary) - ZEND_FE(gmp_jacobi, arginfo_gmp_binary) - ZEND_FE(gmp_legendre, arginfo_gmp_binary) - ZEND_FE(gmp_kronecker, arginfo_gmp_binary) - ZEND_FE(gmp_cmp, arginfo_gmp_binary) - ZEND_FE(gmp_sign, arginfo_gmp_unary) - ZEND_DEP_FE(gmp_random, arginfo_gmp_random) - ZEND_FE(gmp_random_seed, arginfo_gmp_random_seed) - ZEND_FE(gmp_random_bits, arginfo_gmp_random_bits) - ZEND_FE(gmp_random_range, arginfo_gmp_random_range) - ZEND_FE(gmp_and, arginfo_gmp_binary) - ZEND_FE(gmp_or, arginfo_gmp_binary) - ZEND_FE(gmp_com, arginfo_gmp_unary) - ZEND_FE(gmp_xor, arginfo_gmp_binary) - ZEND_FE(gmp_setbit, arginfo_gmp_setbit) - ZEND_FE(gmp_clrbit, arginfo_gmp_bit) - ZEND_FE(gmp_testbit, arginfo_gmp_bit) - ZEND_FE(gmp_scan0, arginfo_gmp_scan) - ZEND_FE(gmp_scan1, arginfo_gmp_scan) - ZEND_FE(gmp_popcount, arginfo_gmp_unary) - ZEND_FE(gmp_hamdist, arginfo_gmp_binary) - ZEND_FE(gmp_nextprime, arginfo_gmp_unary) - ZEND_FE(gmp_binomial, arginfo_gmp_binary) - PHP_FE_END -}; -/* }}} */ - -/* {{{ gmp_module_entry - */ +/* {{{ gmp_module_entry */ zend_module_entry gmp_module_entry = { STANDARD_MODULE_HEADER, "gmp", - gmp_functions, + ext_functions, ZEND_MODULE_STARTUP_N(gmp), NULL, NULL, @@ -226,7 +67,7 @@ ZEND_GET_MODULE(gmp) static zend_class_entry *gmp_ce; static zend_object_handlers gmp_object_handlers; -PHP_GMP_API zend_class_entry *php_gmp_class_entry() { +PHP_GMP_API zend_class_entry *php_gmp_class_entry(void) { return gmp_ce; } @@ -344,26 +185,49 @@ static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg); * include parameter parsing. */ typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr); -typedef int (*gmp_unary_opl_t)(mpz_srcptr); +typedef mp_bitcnt_t (*gmp_unary_opl_t)(mpz_srcptr); typedef void (*gmp_unary_ui_op_t)(mpz_ptr, gmp_ulong); typedef void (*gmp_binary_op_t)(mpz_ptr, mpz_srcptr, mpz_srcptr); -typedef int (*gmp_binary_opl_t)(mpz_srcptr, mpz_srcptr); typedef void (*gmp_binary_ui_op_t)(mpz_ptr, mpz_srcptr, gmp_ulong); typedef void (*gmp_binary_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); -typedef void (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, gmp_ulong); +typedef gmp_ulong (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, gmp_ulong); static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int check_b_zero); static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int check_b_zero); static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_op_t gmp_op); static inline void gmp_zval_unary_ui_op(zval *return_value, zval *a_arg, gmp_unary_ui_op_t gmp_op); +static void gmp_mpz_tdiv_q_ui(mpz_ptr a, mpz_srcptr b, gmp_ulong c) { + mpz_tdiv_q_ui(a, b, c); +} +static void gmp_mpz_tdiv_r_ui(mpz_ptr a, mpz_srcptr b, gmp_ulong c) { + mpz_tdiv_r_ui(a, b, c); +} +static void gmp_mpz_fdiv_q_ui(mpz_ptr a, mpz_srcptr b, gmp_ulong c) { + mpz_fdiv_q_ui(a, b, c); +} +static void gmp_mpz_fdiv_r_ui(mpz_ptr a, mpz_srcptr b, gmp_ulong c) { + mpz_fdiv_r_ui(a, b, c); +} +static void gmp_mpz_cdiv_r_ui(mpz_ptr a, mpz_srcptr b, gmp_ulong c) { + mpz_cdiv_r_ui(a, b, c); +} +static void gmp_mpz_cdiv_q_ui(mpz_ptr a, mpz_srcptr b, gmp_ulong c) { + mpz_cdiv_q_ui(a, b, c); +} +static void gmp_mpz_mod_ui(mpz_ptr a, mpz_srcptr b, gmp_ulong c) { + mpz_mod_ui(a, b, c); +} +static void gmp_mpz_gcd_ui(mpz_ptr a, mpz_srcptr b, gmp_ulong c) { + mpz_gcd_ui(a, b, c); +} + /* Binary operations */ #define gmp_binary_ui_op(op, uop) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop, 0) #define gmp_binary_op(op) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, NULL, 0) -#define gmp_binary_opl(op) _gmp_binary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) #define gmp_binary_ui_op_no_zero(op, uop) \ _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop, 1) @@ -408,24 +272,24 @@ static inline void gmp_create(zval *target, mpz_ptr *gmpnum_target) /* {{{ */ } /* }}} */ -static int gmp_cast_object(zval *readobj, zval *writeobj, int type) /* {{{ */ +static int gmp_cast_object(zend_object *readobj, zval *writeobj, int type) /* {{{ */ { mpz_ptr gmpnum; switch (type) { case IS_STRING: - gmpnum = GET_GMP_FROM_ZVAL(readobj); + gmpnum = GET_GMP_OBJECT_FROM_OBJ(readobj)->num; gmp_strval(writeobj, gmpnum, 10); return SUCCESS; case IS_LONG: - gmpnum = GET_GMP_FROM_ZVAL(readobj); + gmpnum = GET_GMP_OBJECT_FROM_OBJ(readobj)->num; ZVAL_LONG(writeobj, mpz_get_si(gmpnum)); return SUCCESS; case IS_DOUBLE: - gmpnum = GET_GMP_FROM_ZVAL(readobj); + gmpnum = GET_GMP_OBJECT_FROM_OBJ(readobj)->num; ZVAL_DOUBLE(writeobj, mpz_get_d(gmpnum)); return SUCCESS; case _IS_NUMBER: - gmpnum = GET_GMP_FROM_ZVAL(readobj); + gmpnum = GET_GMP_OBJECT_FROM_OBJ(readobj)->num; if (mpz_fits_slong_p(gmpnum)) { ZVAL_LONG(writeobj, mpz_get_si(gmpnum)); } else { @@ -438,10 +302,10 @@ static int gmp_cast_object(zval *readobj, zval *writeobj, int type) /* {{{ */ } /* }}} */ -static HashTable *gmp_get_debug_info(zval *obj, int *is_temp) /* {{{ */ +static HashTable *gmp_get_debug_info(zend_object *obj, int *is_temp) /* {{{ */ { HashTable *ht, *props = zend_std_get_properties(obj); - mpz_ptr gmpnum = GET_GMP_FROM_ZVAL(obj); + mpz_ptr gmpnum = GET_GMP_OBJECT_FROM_OBJ(obj)->num; zval zv; *is_temp = 1; @@ -454,10 +318,10 @@ static HashTable *gmp_get_debug_info(zval *obj, int *is_temp) /* {{{ */ } /* }}} */ -static zend_object *gmp_clone_obj(zval *obj) /* {{{ */ +static zend_object *gmp_clone_obj(zend_object *obj) /* {{{ */ { - gmp_object *old_object = GET_GMP_OBJECT_FROM_ZVAL(obj); - gmp_object *new_object = GET_GMP_OBJECT_FROM_OBJ(gmp_create_object(Z_OBJCE_P(obj))); + gmp_object *old_object = GET_GMP_OBJECT_FROM_OBJ(obj); + gmp_object *new_object = GET_GMP_OBJECT_FROM_OBJ(gmp_create_object(obj->ce)); zend_objects_clone_members( &new_object->std, &old_object->std); @@ -467,12 +331,16 @@ static zend_object *gmp_clone_obj(zval *obj) /* {{{ */ } /* }}} */ -static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zval *op1, zval *op2) { +static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zval *op1, zval *op2, zend_uchar opcode) { zend_long shift = zval_get_long(op2); if (shift < 0) { - php_error_docref(NULL, E_WARNING, "Shift cannot be negative"); - RETVAL_FALSE; + zend_throw_error( + zend_ce_value_error, "%s must be greater than or equal to 0", + opcode == ZEND_POW ? "Exponent" : "Shift" + ); + ZVAL_UNDEF(return_value); + return; } else { mpz_ptr gmpnum_op, gmpnum_result; gmp_temp_t temp; @@ -486,8 +354,7 @@ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zva #define DO_BINARY_UI_OP_EX(op, uop, check_b_zero) \ gmp_zval_binary_ui_op( \ - result, op1, op2, op, (gmp_binary_ui_op_t) uop, \ - check_b_zero \ + result, op1, op2, op, uop, check_b_zero \ ); \ return SUCCESS; @@ -508,17 +375,17 @@ static int gmp_do_operation_ex(zend_uchar opcode, zval *result, zval *op1, zval case ZEND_MUL: DO_BINARY_UI_OP(mpz_mul); case ZEND_POW: - shift_operator_helper(mpz_pow_ui, result, op1, op2); + shift_operator_helper(mpz_pow_ui, result, op1, op2, opcode); return SUCCESS; case ZEND_DIV: - DO_BINARY_UI_OP_EX(mpz_tdiv_q, mpz_tdiv_q_ui, 1); + DO_BINARY_UI_OP_EX(mpz_tdiv_q, gmp_mpz_tdiv_q_ui, 1); case ZEND_MOD: - DO_BINARY_UI_OP_EX(mpz_mod, mpz_mod_ui, 1); + DO_BINARY_UI_OP_EX(mpz_mod, gmp_mpz_mod_ui, 1); case ZEND_SL: - shift_operator_helper(mpz_mul_2exp, result, op1, op2); + shift_operator_helper(mpz_mul_2exp, result, op1, op2, opcode); return SUCCESS; case ZEND_SR: - shift_operator_helper(mpz_fdiv_q_2exp, result, op1, op2); + shift_operator_helper(mpz_fdiv_q_2exp, result, op1, op2, opcode); return SUCCESS; case ZEND_BW_OR: DO_BINARY_OP(mpz_ior); @@ -555,13 +422,15 @@ static int gmp_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op } /* }}} */ -static int gmp_compare(zval *result, zval *op1, zval *op2) /* {{{ */ +static int gmp_compare(zval *op1, zval *op2) /* {{{ */ { - gmp_cmp(result, op1, op2); - if (Z_TYPE_P(result) == IS_FALSE) { - ZVAL_LONG(result, 1); + zval result; + + gmp_cmp(&result, op1, op2); + if (Z_TYPE(result) == IS_FALSE) { + return 1; } - return SUCCESS; + return Z_LVAL(result); } /* }}} */ @@ -578,7 +447,7 @@ static int gmp_serialize(zval *object, unsigned char **buffer, size_t *buf_len, php_var_serialize(&buf, &zv, &serialize_data); zval_ptr_dtor_str(&zv); - ZVAL_ARR(&zv, zend_std_get_properties(object)); + ZVAL_ARR(&zv, zend_std_get_properties(Z_OBJ_P(object))); php_var_serialize(&buf, &zv, &serialize_data); PHP_VAR_SERIALIZE_DESTROY(serialize_data); @@ -597,14 +466,12 @@ static int gmp_unserialize(zval *object, zend_class_entry *ce, const unsigned ch zval *zv; int retval = FAILURE; php_unserialize_data_t unserialize_data; - zval object_copy; + zend_object *zobj; PHP_VAR_UNSERIALIZE_INIT(unserialize_data); gmp_create(object, &gmpnum); - /* The "object" variable may be modified during the execution of this unserialize handler - * (it may turn into a reference). Keep the original object around for further operations. */ - ZVAL_OBJ(&object_copy, Z_OBJ_P(object)); + zobj = Z_OBJ_P(object); p = buf; max = buf + buf_len; @@ -628,7 +495,7 @@ static int gmp_unserialize(zval *object, zend_class_entry *ce, const unsigned ch if (zend_hash_num_elements(Z_ARRVAL_P(zv)) != 0) { zend_hash_copy( - zend_std_get_properties(&object_copy), Z_ARRVAL_P(zv), + zend_std_get_properties(zobj), Z_ARRVAL_P(zv), (copy_ctor_func_t) zval_add_ref ); } @@ -640,8 +507,7 @@ exit: } /* }}} */ -/* {{{ ZEND_GINIT_FUNCTION - */ +/* {{{ ZEND_GINIT_FUNCTION */ static ZEND_GINIT_FUNCTION(gmp) { #if defined(COMPILE_DL_GMP) && defined(ZTS) @@ -651,12 +517,11 @@ static ZEND_GINIT_FUNCTION(gmp) } /* }}} */ -/* {{{ ZEND_MINIT_FUNCTION - */ +/* {{{ ZEND_MINIT_FUNCTION */ ZEND_MINIT_FUNCTION(gmp) { zend_class_entry tmp_ce; - INIT_CLASS_ENTRY(tmp_ce, "GMP", NULL); + INIT_CLASS_ENTRY(tmp_ce, "GMP", class_GMP_methods); gmp_ce = zend_register_internal_class(&tmp_ce); gmp_ce->create_object = gmp_create_object; gmp_ce->serialize = gmp_serialize; @@ -689,8 +554,7 @@ ZEND_MINIT_FUNCTION(gmp) } /* }}} */ -/* {{{ ZEND_RSHUTDOWN_FUNCTION - */ +/* {{{ ZEND_RSHUTDOWN_FUNCTION */ ZEND_MODULE_DEACTIVATE_D(gmp) { if (GMPG(rand_initialized)) { @@ -702,8 +566,7 @@ ZEND_MODULE_DEACTIVATE_D(gmp) } /* }}} */ -/* {{{ ZEND_MINFO_FUNCTION - */ +/* {{{ ZEND_MINFO_FUNCTION */ ZEND_MODULE_INFO_D(gmp) { php_info_print_table_start(); @@ -919,14 +782,13 @@ static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval } /* }}} */ -/* {{{ _gmp_binary_ui_op - */ +/* {{{ _gmp_binary_ui_op */ static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int check_b_zero) { zval *a_arg, *b_arg; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a_arg, &b_arg) == FAILURE){ - return; + RETURN_THROWS(); } gmp_zval_binary_ui_op(return_value, a_arg, b_arg, gmp_op, gmp_ui_op, check_b_zero); @@ -935,8 +797,7 @@ static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op /* Unary operations */ -/* {{{ gmp_zval_unary_op - */ +/* {{{ gmp_zval_unary_op */ static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_op_t gmp_op) { mpz_ptr gmpnum_a, gmpnum_result; @@ -951,8 +812,7 @@ static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_ } /* }}} */ -/* {{{ gmp_zval_unary_ui_op - */ +/* {{{ gmp_zval_unary_ui_op */ static inline void gmp_zval_unary_ui_op(zval *return_value, zval *a_arg, gmp_unary_ui_op_t gmp_op) { mpz_ptr gmpnum_result; @@ -962,22 +822,20 @@ static inline void gmp_zval_unary_ui_op(zval *return_value, zval *a_arg, gmp_una } /* }}} */ -/* {{{ _gmp_unary_op - */ +/* {{{ _gmp_unary_op */ static inline void _gmp_unary_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_op_t gmp_op) { zval *a_arg; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &a_arg) == FAILURE){ - return; + RETURN_THROWS(); } gmp_zval_unary_op(return_value, a_arg, gmp_op); } /* }}} */ -/* {{{ _gmp_unary_opl - */ +/* {{{ _gmp_unary_opl */ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t gmp_op) { zval *a_arg; @@ -985,7 +843,7 @@ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &a_arg) == FAILURE){ - return; + RETURN_THROWS(); } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); @@ -994,30 +852,7 @@ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t } /* }}} */ -/* {{{ _gmp_binary_opl - */ -static inline void _gmp_binary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_opl_t gmp_op) -{ - zval *a_arg, *b_arg; - mpz_ptr gmpnum_a, gmpnum_b; - gmp_temp_t temp_a, temp_b; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a_arg, &b_arg) == FAILURE){ - return; - } - - FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); - - RETVAL_LONG(gmp_op(gmpnum_a, gmpnum_b)); - - FREE_GMP_TEMP(temp_a); - FREE_GMP_TEMP(temp_b); -} -/* }}} */ - -/* {{{ proto GMP gmp_init(mixed number [, int base]) - Initializes GMP number */ +/* {{{ Initializes GMP number */ ZEND_FUNCTION(gmp_init) { zval *number_arg; @@ -1025,7 +860,7 @@ ZEND_FUNCTION(gmp_init) zend_long base = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &number_arg, &base) == FAILURE) { - return; + RETURN_THROWS(); } if (base && (base < 2 || base > GMP_MAX_BASE)) { @@ -1083,8 +918,7 @@ int gmp_import_export_validate(zend_long size, zend_long options, int *order, in return SUCCESS; } -/* {{{ proto GMP gmp_import(string data [, int word_size = 1, int options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN]) - Imports a GMP number from a binary string */ +/* {{{ Imports a GMP number from a binary string */ ZEND_FUNCTION(gmp_import) { char *data; @@ -1095,7 +929,7 @@ ZEND_FUNCTION(gmp_import) mpz_ptr gmpnumber; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ll", &data, &data_len, &size, &options) == FAILURE) { - return; + RETURN_THROWS(); } if (gmp_import_export_validate(size, options, &order, &endian) == FAILURE) { @@ -1114,8 +948,7 @@ ZEND_FUNCTION(gmp_import) } /* }}} */ -/* {{{ proto string gmp_export(GMP gmpnumber [, int word_size = 1, int options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN]) - Exports a GMP number to a binary string */ +/* {{{ Exports a GMP number to a binary string */ ZEND_FUNCTION(gmp_export) { zval *gmpnumber_arg; @@ -1126,7 +959,7 @@ ZEND_FUNCTION(gmp_export) gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|ll", &gmpnumber_arg, &size, &options) == FAILURE) { - return; + RETURN_THROWS(); } if (gmp_import_export_validate(size, options, &order, &endian) == FAILURE) { @@ -1152,14 +985,13 @@ ZEND_FUNCTION(gmp_export) } /* }}} */ -/* {{{ proto int gmp_intval(mixed gmpnumber) - Gets signed long value of GMP number */ +/* {{{ Gets signed long value of GMP number */ ZEND_FUNCTION(gmp_intval) { zval *gmpnumber_arg; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &gmpnumber_arg) == FAILURE){ - return; + RETURN_THROWS(); } if (IS_GMP(gmpnumber_arg)) { @@ -1170,8 +1002,7 @@ ZEND_FUNCTION(gmp_intval) } /* }}} */ -/* {{{ proto string gmp_strval(mixed gmpnumber [, int base]) - Gets string representation of GMP number */ +/* {{{ Gets string representation of GMP number */ ZEND_FUNCTION(gmp_strval) { zval *gmpnumber_arg; @@ -1180,7 +1011,7 @@ ZEND_FUNCTION(gmp_strval) gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &gmpnumber_arg, &base) == FAILURE) { - return; + RETURN_THROWS(); } /* Although the maximum base in general in GMP is 62, mpz_get_str() @@ -1198,50 +1029,46 @@ ZEND_FUNCTION(gmp_strval) } /* }}} */ -/* {{{ proto GMP gmp_add(mixed a, mixed b) - Add a and b */ +/* {{{ Add a and b */ ZEND_FUNCTION(gmp_add) { gmp_binary_ui_op(mpz_add, mpz_add_ui); } /* }}} */ -/* {{{ proto GMP gmp_sub(mixed a, mixed b) - Subtract b from a */ +/* {{{ Subtract b from a */ ZEND_FUNCTION(gmp_sub) { gmp_binary_ui_op(mpz_sub, mpz_sub_ui); } /* }}} */ -/* {{{ proto GMP gmp_mul(mixed a, mixed b) - Multiply a and b */ +/* {{{ Multiply a and b */ ZEND_FUNCTION(gmp_mul) { gmp_binary_ui_op(mpz_mul, mpz_mul_ui); } /* }}} */ -/* {{{ proto array gmp_div_qr(mixed a, mixed b [, int round]) - Divide a by b, returns quotient and reminder */ +/* {{{ Divide a by b, returns quotient and reminder */ ZEND_FUNCTION(gmp_div_qr) { zval *a_arg, *b_arg; zend_long round = GMP_ROUND_ZERO; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|l", &a_arg, &b_arg, &round) == FAILURE) { - return; + RETURN_THROWS(); } switch (round) { case GMP_ROUND_ZERO: - gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_tdiv_qr, (gmp_binary_ui_op2_t) mpz_tdiv_qr_ui, 1); + gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_tdiv_qr, mpz_tdiv_qr_ui, 1); break; case GMP_ROUND_PLUSINF: - gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_cdiv_qr, (gmp_binary_ui_op2_t) mpz_cdiv_qr_ui, 1); + gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_cdiv_qr, mpz_cdiv_qr_ui, 1); break; case GMP_ROUND_MINUSINF: - gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_fdiv_qr, (gmp_binary_ui_op2_t) mpz_fdiv_qr_ui, 1); + gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_fdiv_qr, mpz_fdiv_qr_ui, 1); break; default: php_error_docref(NULL, E_WARNING, "Invalid rounding mode"); @@ -1250,26 +1077,25 @@ ZEND_FUNCTION(gmp_div_qr) } /* }}} */ -/* {{{ proto GMP gmp_div_r(mixed a, mixed b [, int round]) - Divide a by b, returns reminder only */ +/* {{{ Divide a by b, returns reminder only */ ZEND_FUNCTION(gmp_div_r) { zval *a_arg, *b_arg; zend_long round = GMP_ROUND_ZERO; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|l", &a_arg, &b_arg, &round) == FAILURE) { - return; + RETURN_THROWS(); } switch (round) { case GMP_ROUND_ZERO: - gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_r, (gmp_binary_ui_op_t) mpz_tdiv_r_ui, 1); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_r, gmp_mpz_tdiv_r_ui, 1); break; case GMP_ROUND_PLUSINF: - gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_r, (gmp_binary_ui_op_t) mpz_cdiv_r_ui, 1); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_r, gmp_mpz_cdiv_r_ui, 1); break; case GMP_ROUND_MINUSINF: - gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_r, (gmp_binary_ui_op_t) mpz_fdiv_r_ui, 1); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_r, gmp_mpz_fdiv_r_ui, 1); break; default: php_error_docref(NULL, E_WARNING, "Invalid rounding mode"); @@ -1278,26 +1104,25 @@ ZEND_FUNCTION(gmp_div_r) } /* }}} */ -/* {{{ proto GMP gmp_div_q(mixed a, mixed b [, int round]) - Divide a by b, returns quotient only */ +/* {{{ Divide a by b, returns quotient only */ ZEND_FUNCTION(gmp_div_q) { zval *a_arg, *b_arg; zend_long round = GMP_ROUND_ZERO; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|l", &a_arg, &b_arg, &round) == FAILURE) { - return; + RETURN_THROWS(); } switch (round) { case GMP_ROUND_ZERO: - gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_q, (gmp_binary_ui_op_t) mpz_tdiv_q_ui, 1); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_q, gmp_mpz_tdiv_q_ui, 1); break; case GMP_ROUND_PLUSINF: - gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_q, (gmp_binary_ui_op_t) mpz_cdiv_q_ui, 1); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_q, gmp_mpz_cdiv_q_ui, 1); break; case GMP_ROUND_MINUSINF: - gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_q, (gmp_binary_ui_op_t) mpz_fdiv_q_ui, 1); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_q, gmp_mpz_fdiv_q_ui, 1); break; default: php_error_docref(NULL, E_WARNING, "Invalid rounding mode"); @@ -1307,46 +1132,41 @@ ZEND_FUNCTION(gmp_div_q) } /* }}} */ -/* {{{ proto GMP gmp_mod(mixed a, mixed b) - Computes a modulo b */ +/* {{{ Computes a modulo b */ ZEND_FUNCTION(gmp_mod) { - gmp_binary_ui_op_no_zero(mpz_mod, (gmp_binary_ui_op_t) mpz_mod_ui); + gmp_binary_ui_op_no_zero(mpz_mod, gmp_mpz_mod_ui); } /* }}} */ -/* {{{ proto GMP gmp_divexact(mixed a, mixed b) - Divide a by b using exact division algorithm */ +/* {{{ Divide a by b using exact division algorithm */ ZEND_FUNCTION(gmp_divexact) { gmp_binary_ui_op_no_zero(mpz_divexact, NULL); } /* }}} */ -/* {{{ proto GMP gmp_neg(mixed a) - Negates a number */ +/* {{{ Negates a number */ ZEND_FUNCTION(gmp_neg) { gmp_unary_op(mpz_neg); } /* }}} */ -/* {{{ proto GMP gmp_abs(mixed a) - Calculates absolute value */ +/* {{{ Calculates absolute value */ ZEND_FUNCTION(gmp_abs) { gmp_unary_op(mpz_abs); } /* }}} */ -/* {{{ proto GMP gmp_fact(int a) - Calculates factorial function */ +/* {{{ Calculates factorial function */ ZEND_FUNCTION(gmp_fact) { zval *a_arg; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &a_arg) == FAILURE){ - return; + RETURN_THROWS(); } if (IS_GMP(a_arg)) { @@ -1375,8 +1195,7 @@ ZEND_FUNCTION(gmp_fact) } /* }}} */ -/* {{{ proto GMP gmp_binomial(mixed n, int k) - * Calculates binomial coefficient */ +/* {{{ Calculates binomial coefficient */ ZEND_FUNCTION(gmp_binomial) { zval *n_arg; @@ -1384,7 +1203,7 @@ ZEND_FUNCTION(gmp_binomial) mpz_ptr gmpnum_result; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zl", &n_arg, &k) == FAILURE) { - return; + RETURN_THROWS(); } if (k < 0) { @@ -1405,8 +1224,7 @@ ZEND_FUNCTION(gmp_binomial) } /* }}} */ -/* {{{ proto GMP gmp_pow(mixed base, int exp) - Raise base to power exp */ +/* {{{ Raise base to power exp */ ZEND_FUNCTION(gmp_pow) { zval *base_arg; @@ -1415,12 +1233,12 @@ ZEND_FUNCTION(gmp_pow) zend_long exp; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zl", &base_arg, &exp) == FAILURE) { - return; + RETURN_THROWS(); } if (exp < 0) { - php_error_docref(NULL, E_WARNING, "Negative exponent not supported"); - RETURN_FALSE; + zend_argument_value_error(2, "must be greater than or equal to 0"); + RETURN_THROWS(); } if (Z_TYPE_P(base_arg) == IS_LONG && Z_LVAL_P(base_arg) >= 0) { @@ -1436,8 +1254,7 @@ ZEND_FUNCTION(gmp_pow) } /* }}} */ -/* {{{ proto GMP gmp_powm(mixed base, mixed exp, mixed mod) - Raise base to power exp and take result modulo mod */ +/* {{{ Raise base to power exp and take result modulo mod */ ZEND_FUNCTION(gmp_powm) { zval *base_arg, *exp_arg, *mod_arg; @@ -1446,7 +1263,7 @@ ZEND_FUNCTION(gmp_powm) gmp_temp_t temp_base, temp_exp, temp_mod; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz", &base_arg, &exp_arg, &mod_arg) == FAILURE){ - return; + RETURN_THROWS(); } FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base); @@ -1486,8 +1303,7 @@ ZEND_FUNCTION(gmp_powm) } /* }}} */ -/* {{{ proto GMP gmp_sqrt(mixed a) - Takes integer part of square root of a */ +/* {{{ Takes integer part of square root of a */ ZEND_FUNCTION(gmp_sqrt) { zval *a_arg; @@ -1495,7 +1311,7 @@ ZEND_FUNCTION(gmp_sqrt) gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &a_arg) == FAILURE){ - return; + RETURN_THROWS(); } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); @@ -1512,8 +1328,7 @@ ZEND_FUNCTION(gmp_sqrt) } /* }}} */ -/* {{{ proto array gmp_sqrtrem(mixed a) - Square root with remainder */ +/* {{{ Square root with remainder */ ZEND_FUNCTION(gmp_sqrtrem) { zval *a_arg; @@ -1522,7 +1337,7 @@ ZEND_FUNCTION(gmp_sqrtrem) zval result1, result2; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &a_arg) == FAILURE){ - return; + RETURN_THROWS(); } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); @@ -1545,8 +1360,7 @@ ZEND_FUNCTION(gmp_sqrtrem) } /* }}} */ -/* {{{ proto GMP gmp_root(mixed a, int nth) - Takes integer part of nth root */ +/* {{{ Takes integer part of nth root */ ZEND_FUNCTION(gmp_root) { zval *a_arg; @@ -1555,7 +1369,7 @@ ZEND_FUNCTION(gmp_root) gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zl", &a_arg, &nth) == FAILURE) { - return; + RETURN_THROWS(); } if (nth <= 0) { @@ -1577,8 +1391,7 @@ ZEND_FUNCTION(gmp_root) } /* }}} */ -/* {{{ proto GMP gmp_rootrem(mixed a, int nth) - Calculates integer part of nth root and remainder */ +/* {{{ Calculates integer part of nth root and remainder */ ZEND_FUNCTION(gmp_rootrem) { zval *a_arg; @@ -1588,7 +1401,7 @@ ZEND_FUNCTION(gmp_rootrem) zval result1, result2; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zl", &a_arg, &nth) == FAILURE) { - return; + RETURN_THROWS(); } if (nth <= 0) { @@ -1625,8 +1438,7 @@ ZEND_FUNCTION(gmp_rootrem) } /* }}} */ -/* {{{ proto bool gmp_perfect_square(mixed a) - Checks if a is an exact square */ +/* {{{ Checks if a is an exact square */ ZEND_FUNCTION(gmp_perfect_square) { zval *a_arg; @@ -1634,7 +1446,7 @@ ZEND_FUNCTION(gmp_perfect_square) gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &a_arg) == FAILURE){ - return; + RETURN_THROWS(); } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); @@ -1644,8 +1456,7 @@ ZEND_FUNCTION(gmp_perfect_square) } /* }}} */ -/* {{{ proto bool gmp_perfect_power(mixed a) - Checks if a is a perfect power */ +/* {{{ Checks if a is a perfect power */ ZEND_FUNCTION(gmp_perfect_power) { zval *a_arg; @@ -1653,7 +1464,7 @@ ZEND_FUNCTION(gmp_perfect_power) gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &a_arg) == FAILURE){ - return; + RETURN_THROWS(); } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); @@ -1663,8 +1474,7 @@ ZEND_FUNCTION(gmp_perfect_power) } /* }}} */ -/* {{{ proto int gmp_prob_prime(mixed a[, int reps]) - Checks if a is "probably prime" */ +/* {{{ Checks if a is "probably prime" */ ZEND_FUNCTION(gmp_prob_prime) { zval *gmpnumber_arg; @@ -1673,7 +1483,7 @@ ZEND_FUNCTION(gmp_prob_prime) gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &gmpnumber_arg, &reps) == FAILURE) { - return; + RETURN_THROWS(); } FETCH_GMP_ZVAL(gmpnum_a, gmpnumber_arg, temp_a); @@ -1683,24 +1493,21 @@ ZEND_FUNCTION(gmp_prob_prime) } /* }}} */ -/* {{{ proto GMP gmp_gcd(mixed a, mixed b) - Computes greatest common denominator (gcd) of a and b */ +/* {{{ Computes greatest common denominator (gcd) of a and b */ ZEND_FUNCTION(gmp_gcd) { - gmp_binary_ui_op(mpz_gcd, (gmp_binary_ui_op_t) mpz_gcd_ui); + gmp_binary_ui_op(mpz_gcd, gmp_mpz_gcd_ui); } /* }}} */ -/* {{{ proto GMP gmp_lcm(mixed a, mixed b) - Computes least common multiple (lcm) of a and b */ +/* {{{ Computes least common multiple (lcm) of a and b */ ZEND_FUNCTION(gmp_lcm) { - gmp_binary_ui_op(mpz_lcm, (gmp_binary_ui_op_t) mpz_lcm_ui); + gmp_binary_ui_op(mpz_lcm, mpz_lcm_ui); } /* }}} */ -/* {{{ proto array gmp_gcdext(mixed a, mixed b) - Computes G, S, and T, such that AS + BT = G = `gcd' (A, B) */ +/* {{{ Computes G, S, and T, such that AS + BT = G = `gcd' (A, B) */ ZEND_FUNCTION(gmp_gcdext) { zval *a_arg, *b_arg; @@ -1709,7 +1516,7 @@ ZEND_FUNCTION(gmp_gcdext) zval result_g, result_s, result_t; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a_arg, &b_arg) == FAILURE){ - return; + RETURN_THROWS(); } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); @@ -1730,8 +1537,7 @@ ZEND_FUNCTION(gmp_gcdext) } /* }}} */ -/* {{{ proto GMP gmp_invert(mixed a, mixed b) - Computes the inverse of a modulo b */ +/* {{{ Computes the inverse of a modulo b */ ZEND_FUNCTION(gmp_invert) { zval *a_arg, *b_arg; @@ -1740,7 +1546,7 @@ ZEND_FUNCTION(gmp_invert) int res; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a_arg, &b_arg) == FAILURE){ - return; + RETURN_THROWS(); } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); @@ -1757,24 +1563,49 @@ ZEND_FUNCTION(gmp_invert) } /* }}} */ -/* {{{ proto int gmp_jacobi(mixed a, mixed b) - Computes Jacobi symbol */ +/* {{{ Computes Jacobi symbol */ ZEND_FUNCTION(gmp_jacobi) { - gmp_binary_opl(mpz_jacobi); + zval *a_arg, *b_arg; + mpz_ptr gmpnum_a, gmpnum_b; + gmp_temp_t temp_a, temp_b; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a_arg, &b_arg) == FAILURE){ + RETURN_THROWS(); + } + + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); + FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); + + RETVAL_LONG(mpz_jacobi(gmpnum_a, gmpnum_b)); + + FREE_GMP_TEMP(temp_a); + FREE_GMP_TEMP(temp_b); } /* }}} */ -/* {{{ proto int gmp_legendre(mixed a, mixed b) - Computes Legendre symbol */ +/* {{{ Computes Legendre symbol */ ZEND_FUNCTION(gmp_legendre) { - gmp_binary_opl(mpz_legendre); + zval *a_arg, *b_arg; + mpz_ptr gmpnum_a, gmpnum_b; + gmp_temp_t temp_a, temp_b; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a_arg, &b_arg) == FAILURE){ + RETURN_THROWS(); + } + + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); + FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); + + RETVAL_LONG(mpz_legendre(gmpnum_a, gmpnum_b)); + + FREE_GMP_TEMP(temp_a); + FREE_GMP_TEMP(temp_b); } /* }}} */ -/* {{{ proto int gmp_kronecker(mixed a, mixed b) - Computes the Kronecker symbol */ +/* {{{ Computes the Kronecker symbol */ ZEND_FUNCTION(gmp_kronecker) { zval *a_arg, *b_arg; @@ -1784,7 +1615,7 @@ ZEND_FUNCTION(gmp_kronecker) int result; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a_arg, &b_arg) == FAILURE){ - return; + RETURN_THROWS(); } if (Z_TYPE_P(a_arg) == IS_LONG && Z_TYPE_P(b_arg) != IS_LONG) { @@ -1817,22 +1648,20 @@ ZEND_FUNCTION(gmp_kronecker) } /* }}} */ -/* {{{ proto int gmp_cmp(mixed a, mixed b) - Compares two numbers */ +/* {{{ Compares two numbers */ ZEND_FUNCTION(gmp_cmp) { zval *a_arg, *b_arg; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a_arg, &b_arg) == FAILURE){ - return; + RETURN_THROWS(); } gmp_cmp(return_value, a_arg, b_arg); } /* }}} */ -/* {{{ proto int gmp_sign(mixed a) - Gets the sign of the number */ +/* {{{ Gets the sign of the number */ ZEND_FUNCTION(gmp_sign) { /* Can't use gmp_unary_opl here, because mpz_sgn is a macro */ @@ -1841,7 +1670,7 @@ ZEND_FUNCTION(gmp_sign) gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &a_arg) == FAILURE){ - return; + RETURN_THROWS(); } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); @@ -1863,37 +1692,14 @@ static void gmp_init_random(void) } } -/* {{{ proto GMP gmp_random([int limiter]) - Gets random number */ -ZEND_FUNCTION(gmp_random) -{ - zend_long limiter = 20; - mpz_ptr gmpnum_result; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &limiter) == FAILURE) { - return; - } - - INIT_GMP_RETVAL(gmpnum_result); - gmp_init_random(); - -#ifdef GMP_LIMB_BITS - mpz_urandomb(gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * GMP_LIMB_BITS); -#else - mpz_urandomb(gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * __GMP_BITS_PER_MP_LIMB); -#endif -} -/* }}} */ - -/* {{{ proto GMP gmp_random_seed(mixed seed) - Seed the RNG */ +/* {{{ Seed the RNG */ ZEND_FUNCTION(gmp_random_seed) { zval *seed; gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &seed) == FAILURE) { - return; + RETURN_THROWS(); } gmp_init_random(); @@ -1913,15 +1719,14 @@ ZEND_FUNCTION(gmp_random_seed) } /* }}} */ -/* {{{ proto GMP gmp_random_bits(int bits) - Gets a random number in the range 0 to (2 ** n) - 1 */ +/* {{{ Gets a random number in the range 0 to (2 ** n) - 1 */ ZEND_FUNCTION(gmp_random_bits) { zend_long bits; mpz_ptr gmpnum_result; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &bits) == FAILURE) { - return; + RETURN_THROWS(); } if (bits <= 0) { @@ -1936,8 +1741,7 @@ ZEND_FUNCTION(gmp_random_bits) } /* }}} */ -/* {{{ proto GMP gmp_random_range(mixed min, mixed max) - Gets a random number in the range min to max */ +/* {{{ Gets a random number in the range min to max */ ZEND_FUNCTION(gmp_random_range) { zval *min_arg, *max_arg; @@ -1946,7 +1750,7 @@ ZEND_FUNCTION(gmp_random_range) gmp_temp_t temp_a, temp_b; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &min_arg, &max_arg) == FAILURE) { - return; + RETURN_THROWS(); } gmp_init_random(); @@ -2004,48 +1808,42 @@ ZEND_FUNCTION(gmp_random_range) } /* }}} */ -/* {{{ proto GMP gmp_and(mixed a, mixed b) - Calculates logical AND of a and b */ +/* {{{ Calculates logical AND of a and b */ ZEND_FUNCTION(gmp_and) { gmp_binary_op(mpz_and); } /* }}} */ -/* {{{ proto GMP gmp_or(mixed a, mixed b) - Calculates logical OR of a and b */ +/* {{{ Calculates logical OR of a and b */ ZEND_FUNCTION(gmp_or) { gmp_binary_op(mpz_ior); } /* }}} */ -/* {{{ proto GMP gmp_com(mixed a) - Calculates one's complement of a */ +/* {{{ Calculates one's complement of a */ ZEND_FUNCTION(gmp_com) { gmp_unary_op(mpz_com); } /* }}} */ -/* {{{ proto GMP gmp_nextprime(mixed a) - Finds next prime of a */ +/* {{{ Finds next prime of a */ ZEND_FUNCTION(gmp_nextprime) { gmp_unary_op(mpz_nextprime); } /* }}} */ -/* {{{ proto GMP gmp_xor(mixed a, mixed b) - Calculates logical exclusive OR of a and b */ +/* {{{ Calculates logical exclusive OR of a and b */ ZEND_FUNCTION(gmp_xor) { gmp_binary_op(mpz_xor); } /* }}} */ -/* {{{ proto void gmp_setbit(GMP a, int index[, bool set_clear]) - Sets or clear bit in a */ +/* {{{ Sets or clear bit in a */ ZEND_FUNCTION(gmp_setbit) { zval *a_arg; @@ -2054,7 +1852,7 @@ ZEND_FUNCTION(gmp_setbit) mpz_ptr gmpnum_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|b", &a_arg, gmp_ce, &index, &set) == FAILURE) { - return; + RETURN_THROWS(); } if (index < 0) { @@ -2076,8 +1874,7 @@ ZEND_FUNCTION(gmp_setbit) } /* }}} */ -/* {{{ proto void gmp_clrbit(GMP a, int index) - Clears bit in a */ +/* {{{ Clears bit in a */ ZEND_FUNCTION(gmp_clrbit) { zval *a_arg; @@ -2085,7 +1882,7 @@ ZEND_FUNCTION(gmp_clrbit) mpz_ptr gmpnum_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &a_arg, gmp_ce, &index) == FAILURE){ - return; + RETURN_THROWS(); } if (index < 0) { @@ -2098,8 +1895,7 @@ ZEND_FUNCTION(gmp_clrbit) } /* }}} */ -/* {{{ proto bool gmp_testbit(mixed a, int index) - Tests if bit is set in a */ +/* {{{ Tests if bit is set in a */ ZEND_FUNCTION(gmp_testbit) { zval *a_arg; @@ -2108,7 +1904,7 @@ ZEND_FUNCTION(gmp_testbit) gmp_temp_t temp_a; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zl", &a_arg, &index) == FAILURE){ - return; + RETURN_THROWS(); } if (index < 0) { @@ -2122,24 +1918,35 @@ ZEND_FUNCTION(gmp_testbit) } /* }}} */ -/* {{{ proto int gmp_popcount(mixed a) - Calculates the population count of a */ +/* {{{ Calculates the population count of a */ ZEND_FUNCTION(gmp_popcount) { - gmp_unary_opl((gmp_unary_opl_t) mpz_popcount); + gmp_unary_opl(mpz_popcount); } /* }}} */ -/* {{{ proto int gmp_hamdist(mixed a, mixed b) - Calculates hamming distance between a and b */ +/* {{{ Calculates hamming distance between a and b */ ZEND_FUNCTION(gmp_hamdist) { - gmp_binary_opl((gmp_binary_opl_t) mpz_hamdist); + zval *a_arg, *b_arg; + mpz_ptr gmpnum_a, gmpnum_b; + gmp_temp_t temp_a, temp_b; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a_arg, &b_arg) == FAILURE){ + RETURN_THROWS(); + } + + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); + FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); + + RETVAL_LONG(mpz_hamdist(gmpnum_a, gmpnum_b)); + + FREE_GMP_TEMP(temp_a); + FREE_GMP_TEMP(temp_b); } /* }}} */ -/* {{{ proto int gmp_scan0(mixed a, int start) - Finds first zero bit */ +/* {{{ Finds first zero bit */ ZEND_FUNCTION(gmp_scan0) { zval *a_arg; @@ -2148,7 +1955,7 @@ ZEND_FUNCTION(gmp_scan0) zend_long start; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zl", &a_arg, &start) == FAILURE){ - return; + RETURN_THROWS(); } if (start < 0) { @@ -2163,8 +1970,7 @@ ZEND_FUNCTION(gmp_scan0) } /* }}} */ -/* {{{ proto int gmp_scan1(mixed a, int start) - Finds first non-zero bit */ +/* {{{ Finds first non-zero bit */ ZEND_FUNCTION(gmp_scan1) { zval *a_arg; @@ -2173,7 +1979,7 @@ ZEND_FUNCTION(gmp_scan1) zend_long start; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zl", &a_arg, &start) == FAILURE){ - return; + RETURN_THROWS(); } if (start < 0) { |