summaryrefslogtreecommitdiff
path: root/ext/gmp/gmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/gmp/gmp.c')
-rw-r--r--ext/gmp/gmp.c316
1 files changed, 163 insertions, 153 deletions
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
index ceaf49b8bc..855513bf39 100644
--- a/ext/gmp/gmp.c
+++ b/ext/gmp/gmp.c
@@ -109,7 +109,7 @@ typedef struct _gmp_temp {
* gmp_temp_t. This temporary value needs to be freed lateron using the
* FREE_GMP_TEMP macro.
*
- * If the conversion to a gmp number fails, the macros return false.
+ * If the conversion to a gmp number fails, the macros RETURN_THROWS() due to TypeError.
* The _DEP / _DEP_DEP variants additionally free the temporary values
* passed in the last / last two arguments.
*
@@ -126,46 +126,46 @@ typedef struct _gmp_temp {
mpz_clear(temp.num); \
}
-#define FETCH_GMP_ZVAL_DEP_DEP(gmpnumber, zval, temp, dep1, dep2) \
+#define FETCH_GMP_ZVAL_DEP_DEP(gmpnumber, zval, temp, dep1, dep2, arg_pos) \
if (IS_GMP(zval)) { \
gmpnumber = GET_GMP_FROM_ZVAL(zval); \
temp.is_used = 0; \
} else { \
mpz_init(temp.num); \
- if (convert_to_gmp(temp.num, zval, 0) == FAILURE) { \
+ if (convert_to_gmp(temp.num, zval, 0, arg_pos) == FAILURE) { \
mpz_clear(temp.num); \
FREE_GMP_TEMP(dep1); \
FREE_GMP_TEMP(dep2); \
- RETURN_FALSE; \
+ RETURN_THROWS(); \
} \
temp.is_used = 1; \
gmpnumber = temp.num; \
}
-#define FETCH_GMP_ZVAL_DEP(gmpnumber, zval, temp, dep) \
+#define FETCH_GMP_ZVAL_DEP(gmpnumber, zval, temp, dep, arg_pos) \
if (IS_GMP(zval)) { \
gmpnumber = GET_GMP_FROM_ZVAL(zval); \
temp.is_used = 0; \
} else { \
mpz_init(temp.num); \
- if (convert_to_gmp(temp.num, zval, 0) == FAILURE) { \
+ if (convert_to_gmp(temp.num, zval, 0, arg_pos) == FAILURE) { \
mpz_clear(temp.num); \
FREE_GMP_TEMP(dep); \
- RETURN_FALSE; \
+ RETURN_THROWS(); \
} \
temp.is_used = 1; \
gmpnumber = temp.num; \
}
-#define FETCH_GMP_ZVAL(gmpnumber, zval, temp) \
+#define FETCH_GMP_ZVAL(gmpnumber, zval, temp, arg_pos) \
if (IS_GMP(zval)) { \
gmpnumber = GET_GMP_FROM_ZVAL(zval); \
temp.is_used = 0; \
} else { \
mpz_init(temp.num); \
- if (convert_to_gmp(temp.num, zval, 0) == FAILURE) { \
+ if (convert_to_gmp(temp.num, zval, 0, arg_pos) == FAILURE) { \
mpz_clear(temp.num); \
- RETURN_FALSE; \
+ RETURN_THROWS(); \
} \
temp.is_used = 1; \
gmpnumber = temp.num; \
@@ -175,7 +175,7 @@ if (IS_GMP(zval)) { \
gmp_create(return_value, &gmpnumber)
static void gmp_strval(zval *result, mpz_t gmpnum, int base);
-static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base);
+static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos);
static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg);
/*
@@ -198,7 +198,6 @@ 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);
@@ -345,7 +344,7 @@ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zva
mpz_ptr gmpnum_op, gmpnum_result;
gmp_temp_t temp;
- FETCH_GMP_ZVAL(gmpnum_op, op1, temp);
+ FETCH_GMP_ZVAL(gmpnum_op, op1, temp, 1);
INIT_GMP_RETVAL(gmpnum_result);
op(gmpnum_result, gmpnum_op, (gmp_ulong) shift);
FREE_GMP_TEMP(temp);
@@ -356,13 +355,17 @@ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zva
gmp_zval_binary_ui_op( \
result, op1, op2, op, uop, check_b_zero \
); \
+ if (UNEXPECTED(EG(exception))) { return FAILURE; } \
return SUCCESS;
#define DO_BINARY_UI_OP(op) DO_BINARY_UI_OP_EX(op, op ## _ui, 0)
#define DO_BINARY_OP(op) DO_BINARY_UI_OP_EX(op, NULL, 0)
-#define DO_UNARY_OP(op) \
+#define DO_UNARY_OP(op) \
gmp_zval_unary_op(result, op1, op); \
+ if (UNEXPECTED(EG(exception))) { \
+ return FAILURE; \
+ } \
return SUCCESS;
static int gmp_do_operation_ex(zend_uchar opcode, zval *result, zval *op1, zval *op2) /* {{{ */
@@ -479,7 +482,7 @@ static int gmp_unserialize(zval *object, zend_class_entry *ce, const unsigned ch
zv = var_tmp_var(&unserialize_data);
if (!php_var_unserialize(zv, &p, max, &unserialize_data)
|| Z_TYPE_P(zv) != IS_STRING
- || convert_to_gmp(gmpnum, zv, 10) == FAILURE
+ || convert_to_gmp(gmpnum, zv, 10, 0) == FAILURE
) {
zend_throw_exception(NULL, "Could not unserialize number", 0);
goto exit;
@@ -583,7 +586,7 @@ ZEND_MODULE_INFO_D(gmp)
/* {{{ convert_to_gmp
* Convert zval to be gmp number */
-static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base)
+static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos)
{
switch (Z_TYPE_P(val)) {
case IS_LONG:
@@ -609,16 +612,25 @@ static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base)
ret = mpz_set_str(gmpnumber, (skip_lead ? &numstr[2] : numstr), (int) base);
if (-1 == ret) {
- php_error_docref(NULL, E_WARNING,
- "Unable to convert variable to GMP - string is not an integer");
+ /* if unserializing */
+ if (arg_pos == 0) {
+ php_error_docref(NULL, E_WARNING,
+ "Cannot convert variable to GMP, it is not an integer string");
+ return FAILURE;
+ }
+ zend_argument_type_error(arg_pos, "is not an integer string");
return FAILURE;
}
return SUCCESS;
}
default:
- php_error_docref(NULL, E_WARNING,
- "Unable to convert variable to GMP - wrong type");
+ /* if unserializing */
+ if (arg_pos == 0) {
+ php_error_docref(NULL, E_WARNING, "Cannot convert variable of type %s to GMP", zend_zval_type_name(val));
+ return FAILURE;
+ }
+ zend_argument_type_error(arg_pos, "must be of type GMP|string|int|bool, %s given", zend_zval_type_name(val));
return FAILURE;
}
}
@@ -662,13 +674,13 @@ static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg) /* {{{ */
zend_bool use_si = 0;
zend_long res;
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
if (Z_TYPE_P(b_arg) == IS_LONG) {
use_si = 1;
temp_b.is_used = 0;
} else {
- FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+ FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
}
if (use_si) {
@@ -692,13 +704,13 @@ static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *
mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result;
gmp_temp_t temp_a, temp_b;
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
if (gmp_ui_op && Z_TYPE_P(b_arg) == IS_LONG && Z_LVAL_P(b_arg) >= 0) {
gmpnum_b = NULL;
temp_b.is_used = 0;
} else {
- FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+ FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
}
if (check_b_zero) {
@@ -710,10 +722,14 @@ static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *
}
if (b_is_zero) {
- php_error_docref(NULL, E_WARNING, "Zero operand not allowed");
+ if ((gmp_binary_op_t) mpz_mod == gmp_op) {
+ zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
+ } else {
+ zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Division by zero");
+ }
FREE_GMP_TEMP(temp_a);
FREE_GMP_TEMP(temp_b);
- RETURN_FALSE;
+ RETURN_THROWS();
}
}
@@ -739,13 +755,13 @@ static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval
gmp_temp_t temp_a, temp_b;
zval result1, result2;
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
if (gmp_ui_op && Z_TYPE_P(b_arg) == IS_LONG && Z_LVAL_P(b_arg) >= 0) {
gmpnum_b = NULL;
temp_b.is_used = 0;
} else {
- FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+ FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
}
if (check_b_zero) {
@@ -757,10 +773,10 @@ static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval
}
if (b_is_zero) {
- php_error_docref(NULL, E_WARNING, "Zero operand not allowed");
+ zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Division by zero");
FREE_GMP_TEMP(temp_a);
FREE_GMP_TEMP(temp_b);
- RETURN_FALSE;
+ RETURN_THROWS();
}
}
@@ -803,7 +819,7 @@ static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_
mpz_ptr gmpnum_a, gmpnum_result;
gmp_temp_t temp_a;
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
INIT_GMP_RETVAL(gmpnum_result);
gmp_op(gmpnum_result, gmpnum_a);
@@ -812,16 +828,6 @@ static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_
}
/* }}} */
-/* {{{ 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;
-
- INIT_GMP_RETVAL(gmpnum_result);
- gmp_op(gmpnum_result, zval_get_long(a_arg));
-}
-/* }}} */
-
/* {{{ _gmp_unary_op */
static inline void _gmp_unary_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_op_t gmp_op)
{
@@ -846,7 +852,7 @@ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
RETVAL_LONG(gmp_op(gmpnum_a));
FREE_GMP_TEMP(temp_a);
}
@@ -864,14 +870,13 @@ ZEND_FUNCTION(gmp_init)
}
if (base && (base < 2 || base > GMP_MAX_BASE)) {
- php_error_docref(NULL, E_WARNING, "Bad base for conversion: " ZEND_LONG_FMT " (should be between 2 and %d)", base, GMP_MAX_BASE);
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be between 2 and %d", GMP_MAX_BASE);
+ RETURN_THROWS();
}
INIT_GMP_RETVAL(gmpnumber);
- if (convert_to_gmp(gmpnumber, number_arg, base) == FAILURE) {
- zval_ptr_dtor(return_value);
- RETURN_FALSE;
+ if (convert_to_gmp(gmpnumber, number_arg, base, 1) == FAILURE) {
+ RETURN_THROWS();
}
}
/* }}} */
@@ -879,8 +884,8 @@ ZEND_FUNCTION(gmp_init)
int gmp_import_export_validate(zend_long size, zend_long options, int *order, int *endian)
{
if (size < 1) {
- php_error_docref(NULL, E_WARNING,
- "Word size must be positive, " ZEND_LONG_FMT " given", size);
+ /* size argument is in second position */
+ zend_argument_value_error(2, "must be greater than or equal to 1");
return FAILURE;
}
@@ -893,8 +898,8 @@ int gmp_import_export_validate(zend_long size, zend_long options, int *order, in
*order = 1;
break;
default:
- php_error_docref(NULL, E_WARNING,
- "Invalid options: Conflicting word orders");
+ /* options argument is in second position */
+ zend_argument_value_error(3, "cannot use multiple word order options");
return FAILURE;
}
@@ -910,8 +915,8 @@ int gmp_import_export_validate(zend_long size, zend_long options, int *order, in
*endian = 0;
break;
default:
- php_error_docref(NULL, E_WARNING,
- "Invalid options: Conflicting word endianness");
+ /* options argument is in second position */
+ zend_argument_value_error(3, "cannot use multiple endian options");
return FAILURE;
}
@@ -933,13 +938,12 @@ ZEND_FUNCTION(gmp_import)
}
if (gmp_import_export_validate(size, options, &order, &endian) == FAILURE) {
- RETURN_FALSE;
+ RETURN_THROWS();
}
if ((data_len % size) != 0) {
- php_error_docref(NULL, E_WARNING,
- "Input length must be a multiple of word size");
- RETURN_FALSE;
+ zend_argument_value_error(1, "must be a multiple of argument #2 ($word_size)");
+ RETURN_THROWS();
}
INIT_GMP_RETVAL(gmpnumber);
@@ -963,10 +967,10 @@ ZEND_FUNCTION(gmp_export)
}
if (gmp_import_export_validate(size, options, &order, &endian) == FAILURE) {
- RETURN_FALSE;
+ RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnumber, gmpnumber_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnumber, gmpnumber_arg, temp_a, 1);
if (mpz_sgn(gmpnumber) == 0) {
RETURN_EMPTY_STRING();
@@ -1017,11 +1021,11 @@ ZEND_FUNCTION(gmp_strval)
/* Although the maximum base in general in GMP is 62, mpz_get_str()
* is explicitly limited to -36 when dealing with negative bases. */
if ((base < 2 && base > -2) || base > GMP_MAX_BASE || base < -36) {
- php_error_docref(NULL, E_WARNING, "Bad base for conversion: " ZEND_LONG_FMT " (should be between 2 and %d or -2 and -36)", base, GMP_MAX_BASE);
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be between 2 and %d, or -2 and -36", GMP_MAX_BASE);
+ RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum, gmpnumber_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum, gmpnumber_arg, temp_a, 1);
gmp_strval(return_value, gmpnum, (int)base);
@@ -1071,8 +1075,8 @@ ZEND_FUNCTION(gmp_div_qr)
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");
- RETURN_FALSE;
+ zend_argument_value_error(3, "must be one of GMP_ROUND_ZERO, GMP_ROUND_PLUSINF, or GMP_ROUND_MINUSINF");
+ RETURN_THROWS();
}
}
/* }}} */
@@ -1098,8 +1102,8 @@ ZEND_FUNCTION(gmp_div_r)
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");
- RETURN_FALSE;
+ zend_argument_value_error(3, "must be one of GMP_ROUND_ZERO, GMP_ROUND_PLUSINF, or GMP_ROUND_MINUSINF");
+ RETURN_THROWS();
}
}
/* }}} */
@@ -1125,8 +1129,8 @@ ZEND_FUNCTION(gmp_div_q)
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");
- RETURN_FALSE;
+ zend_argument_value_error(3, "must be one of GMP_ROUND_ZERO, GMP_ROUND_PLUSINF, or GMP_ROUND_MINUSINF");
+ RETURN_THROWS();
}
}
@@ -1164,34 +1168,32 @@ ZEND_FUNCTION(gmp_abs)
ZEND_FUNCTION(gmp_fact)
{
zval *a_arg;
+ mpz_ptr gmpnum_result;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &a_arg) == FAILURE){
RETURN_THROWS();
}
- if (IS_GMP(a_arg)) {
- mpz_ptr gmpnum_tmp = GET_GMP_FROM_ZVAL(a_arg);
- if (mpz_sgn(gmpnum_tmp) < 0) {
- php_error_docref(NULL, E_WARNING, "Number has to be greater than or equal to 0");
- RETURN_FALSE;
+ if (Z_TYPE_P(a_arg) == IS_LONG) {
+ if (Z_LVAL_P(a_arg) < 0) {
+ zend_argument_value_error(1, "must be greater than or equal to 0");
+ RETURN_THROWS();
}
} else {
- /* Use convert_to_number first to detect getting non-integer */
- convert_scalar_to_number(a_arg);
- if (Z_TYPE_P(a_arg) != IS_LONG) {
- convert_to_long(a_arg);
- if (Z_LVAL_P(a_arg) >= 0) {
- /* Only warn if we'll make it past the non-negative check */
- php_error_docref(NULL, E_WARNING, "Number has to be an integer");
- }
- }
- if (Z_LVAL_P(a_arg) < 0) {
- php_error_docref(NULL, E_WARNING, "Number has to be greater than or equal to 0");
- RETURN_FALSE;
+ mpz_ptr gmpnum;
+ gmp_temp_t temp_a;
+
+ FETCH_GMP_ZVAL(gmpnum, a_arg, temp_a, 1);
+ FREE_GMP_TEMP(temp_a);
+
+ if (mpz_sgn(gmpnum) < 0) {
+ zend_argument_value_error(1, "must be greater than or equal to 0");
+ RETURN_THROWS();
}
}
- gmp_zval_unary_ui_op(return_value, a_arg, mpz_fac_ui);
+ INIT_GMP_RETVAL(gmpnum_result);
+ mpz_fac_ui(gmpnum_result, zval_get_long(a_arg));
}
/* }}} */
@@ -1207,8 +1209,8 @@ ZEND_FUNCTION(gmp_binomial)
}
if (k < 0) {
- php_error_docref(NULL, E_WARNING, "k cannot be negative");
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be greater than or equal to 0");
+ RETURN_THROWS();
}
INIT_GMP_RETVAL(gmpnum_result);
@@ -1217,7 +1219,7 @@ ZEND_FUNCTION(gmp_binomial)
} else {
mpz_ptr gmpnum_n;
gmp_temp_t temp_n;
- FETCH_GMP_ZVAL(gmpnum_n, n_arg, temp_n);
+ FETCH_GMP_ZVAL(gmpnum_n, n_arg, temp_n, 1);
mpz_bin_ui(gmpnum_result, gmpnum_n, (gmp_ulong) k);
FREE_GMP_TEMP(temp_n);
}
@@ -1246,7 +1248,7 @@ ZEND_FUNCTION(gmp_pow)
mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp);
} else {
mpz_ptr gmpnum_base;
- FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base);
+ FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base, 1);
INIT_GMP_RETVAL(gmpnum_result);
mpz_pow_ui(gmpnum_result, gmpnum_base, exp);
FREE_GMP_TEMP(temp_base);
@@ -1266,28 +1268,28 @@ ZEND_FUNCTION(gmp_powm)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base);
+ FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base, 1);
if (Z_TYPE_P(exp_arg) == IS_LONG && Z_LVAL_P(exp_arg) >= 0) {
use_ui = 1;
temp_exp.is_used = 0;
} else {
- FETCH_GMP_ZVAL_DEP(gmpnum_exp, exp_arg, temp_exp, temp_base);
+ FETCH_GMP_ZVAL_DEP(gmpnum_exp, exp_arg, temp_exp, temp_base, 2);
if (mpz_sgn(gmpnum_exp) < 0) {
- php_error_docref(NULL, E_WARNING, "Second parameter cannot be less than 0");
+ zend_argument_value_error(2, "must be greater than or equal to 0");
FREE_GMP_TEMP(temp_base);
FREE_GMP_TEMP(temp_exp);
- RETURN_FALSE;
+ RETURN_THROWS();
}
}
- FETCH_GMP_ZVAL_DEP_DEP(gmpnum_mod, mod_arg, temp_mod, temp_exp, temp_base);
+ FETCH_GMP_ZVAL_DEP_DEP(gmpnum_mod, mod_arg, temp_mod, temp_exp, temp_base, 3);
if (!mpz_cmp_ui(gmpnum_mod, 0)) {
- php_error_docref(NULL, E_WARNING, "Modulus may not be zero");
+ zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
FREE_GMP_TEMP(temp_base);
FREE_GMP_TEMP(temp_exp);
FREE_GMP_TEMP(temp_mod);
- RETURN_FALSE;
+ RETURN_THROWS();
}
INIT_GMP_RETVAL(gmpnum_result);
@@ -1314,12 +1316,12 @@ ZEND_FUNCTION(gmp_sqrt)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
if (mpz_sgn(gmpnum_a) < 0) {
- php_error_docref(NULL, E_WARNING, "Number has to be greater than or equal to 0");
+ zend_argument_value_error(1, "must be greater than or equal to 0");
FREE_GMP_TEMP(temp_a);
- RETURN_FALSE;
+ RETURN_THROWS();
}
INIT_GMP_RETVAL(gmpnum_result);
@@ -1340,12 +1342,12 @@ ZEND_FUNCTION(gmp_sqrtrem)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
if (mpz_sgn(gmpnum_a) < 0) {
- php_error_docref(NULL, E_WARNING, "Number has to be greater than or equal to 0");
+ zend_argument_value_error(1, "must be greater than or equal to 0");
FREE_GMP_TEMP(temp_a);
- RETURN_FALSE;
+ RETURN_THROWS();
}
gmp_create(&result1, &gmpnum_result1);
@@ -1373,16 +1375,16 @@ ZEND_FUNCTION(gmp_root)
}
if (nth <= 0) {
- php_error_docref(NULL, E_WARNING, "The root must be positive");
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be greater than 0");
+ RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
if (nth % 2 == 0 && mpz_sgn(gmpnum_a) < 0) {
- php_error_docref(NULL, E_WARNING, "Can't take even root of negative number");
+ zend_argument_value_error(2, "must be odd if argument #1 ($a) is negative");
FREE_GMP_TEMP(temp_a);
- RETURN_FALSE;
+ RETURN_THROWS();
}
INIT_GMP_RETVAL(gmpnum_result);
@@ -1405,16 +1407,16 @@ ZEND_FUNCTION(gmp_rootrem)
}
if (nth <= 0) {
- php_error_docref(NULL, E_WARNING, "The root must be positive");
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be greater than or equal to 1");
+ RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
if (nth % 2 == 0 && mpz_sgn(gmpnum_a) < 0) {
- php_error_docref(NULL, E_WARNING, "Can't take even root of negative number");
+ zend_argument_value_error(2, "must be odd if argument #1 ($a) is negative");
FREE_GMP_TEMP(temp_a);
- RETURN_FALSE;
+ RETURN_THROWS();
}
gmp_create(&result1, &gmpnum_result1);
@@ -1449,7 +1451,7 @@ ZEND_FUNCTION(gmp_perfect_square)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
RETVAL_BOOL((mpz_perfect_square_p(gmpnum_a) != 0));
FREE_GMP_TEMP(temp_a);
@@ -1467,7 +1469,7 @@ ZEND_FUNCTION(gmp_perfect_power)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
RETVAL_BOOL((mpz_perfect_power_p(gmpnum_a) != 0));
FREE_GMP_TEMP(temp_a);
@@ -1486,7 +1488,7 @@ ZEND_FUNCTION(gmp_prob_prime)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, gmpnumber_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, gmpnumber_arg, temp_a, 1);
RETVAL_LONG(mpz_probab_prime_p(gmpnum_a, (int)reps));
FREE_GMP_TEMP(temp_a);
@@ -1519,8 +1521,8 @@ ZEND_FUNCTION(gmp_gcdext)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
- FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
+ FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
gmp_create(&result_g, &gmpnum_g);
gmp_create(&result_s, &gmpnum_s);
@@ -1549,8 +1551,16 @@ ZEND_FUNCTION(gmp_invert)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
- FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
+ FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
+
+ // TODO Early check if b_arg IS_LONG?
+ if (0 == mpz_cmp_ui(gmpnum_b, 0)) {
+ zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Division by zero");
+ FREE_GMP_TEMP(temp_a);
+ FREE_GMP_TEMP(temp_b);
+ RETURN_THROWS();
+ }
INIT_GMP_RETVAL(gmpnum_result);
res = mpz_invert(gmpnum_result, gmpnum_a, gmpnum_b);
@@ -1574,8 +1584,8 @@ ZEND_FUNCTION(gmp_jacobi)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
- FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
+ FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
RETVAL_LONG(mpz_jacobi(gmpnum_a, gmpnum_b));
@@ -1595,8 +1605,8 @@ ZEND_FUNCTION(gmp_legendre)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
- FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
+ FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
RETVAL_LONG(mpz_legendre(gmpnum_a, gmpnum_b));
@@ -1622,14 +1632,14 @@ ZEND_FUNCTION(gmp_kronecker)
use_a_si = 1;
temp_a.is_used = 0;
} else {
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
}
if (Z_TYPE_P(b_arg) == IS_LONG) {
use_b_si = 1;
temp_b.is_used = 0;
} else {
- FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+ FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
}
if (use_a_si) {
@@ -1673,7 +1683,7 @@ ZEND_FUNCTION(gmp_sign)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
RETVAL_LONG(mpz_sgn(gmpnum_a));
FREE_GMP_TEMP(temp_a);
@@ -1710,7 +1720,7 @@ ZEND_FUNCTION(gmp_random_seed)
else {
mpz_ptr gmpnum_seed;
- FETCH_GMP_ZVAL(gmpnum_seed, seed, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_seed, seed, temp_a, 1);
gmp_randseed(GMPG(rand_state), gmpnum_seed);
@@ -1730,8 +1740,8 @@ ZEND_FUNCTION(gmp_random_bits)
}
if (bits <= 0) {
- php_error_docref(NULL, E_WARNING, "The number of bits must be positive");
- RETURN_FALSE;
+ zend_argument_value_error(1, "must be greater than or equal to 1");
+ RETURN_THROWS();
}
INIT_GMP_RETVAL(gmpnum_result);
@@ -1755,13 +1765,13 @@ ZEND_FUNCTION(gmp_random_range)
gmp_init_random();
- FETCH_GMP_ZVAL(gmpnum_max, max_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_max, max_arg, temp_a, 2);
if (Z_TYPE_P(min_arg) == IS_LONG && Z_LVAL_P(min_arg) >= 0) {
if (mpz_cmp_ui(gmpnum_max, Z_LVAL_P(min_arg)) <= 0) {
FREE_GMP_TEMP(temp_a);
- php_error_docref(NULL, E_WARNING, "The minimum value must be less than the maximum value");
- RETURN_FALSE;
+ zend_argument_value_error(1, "must be less than argument #2 ($maximum)");
+ RETURN_THROWS();
}
INIT_GMP_RETVAL(gmpnum_result);
@@ -1784,13 +1794,13 @@ ZEND_FUNCTION(gmp_random_range)
} else {
mpz_ptr gmpnum_min;
- FETCH_GMP_ZVAL_DEP(gmpnum_min, min_arg, temp_b, temp_a);
+ FETCH_GMP_ZVAL_DEP(gmpnum_min, min_arg, temp_b, temp_a, 1);
if (mpz_cmp(gmpnum_max, gmpnum_min) <= 0) {
FREE_GMP_TEMP(temp_b);
FREE_GMP_TEMP(temp_a);
- php_error_docref(NULL, E_WARNING, "The minimum value must be less than the maximum value");
- RETURN_FALSE;
+ zend_argument_value_error(1, "must be less than argument #2 ($maximum)");
+ RETURN_THROWS();
}
INIT_GMP_RETVAL(gmpnum_result);
@@ -1856,12 +1866,12 @@ ZEND_FUNCTION(gmp_setbit)
}
if (index < 0) {
- php_error_docref(NULL, E_WARNING, "Index must be greater than or equal to zero");
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be greater than or equal to 0");
+ RETURN_THROWS();
}
if (index / GMP_NUMB_BITS >= INT_MAX) {
- php_error_docref(NULL, E_WARNING, "Index must be less than %d * %d", INT_MAX, GMP_NUMB_BITS);
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be less than %d * %d", INT_MAX, GMP_NUMB_BITS);
+ RETURN_THROWS();
}
gmpnum_a = GET_GMP_FROM_ZVAL(a_arg);
@@ -1886,8 +1896,8 @@ ZEND_FUNCTION(gmp_clrbit)
}
if (index < 0) {
- php_error_docref(NULL, E_WARNING, "Index must be greater than or equal to zero");
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be greater than or equal to 0");
+ RETURN_THROWS();
}
gmpnum_a = GET_GMP_FROM_ZVAL(a_arg);
@@ -1908,11 +1918,11 @@ ZEND_FUNCTION(gmp_testbit)
}
if (index < 0) {
- php_error_docref(NULL, E_WARNING, "Index must be greater than or equal to zero");
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be greater than or equal to 0");
+ RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
RETVAL_BOOL(mpz_tstbit(gmpnum_a, index));
FREE_GMP_TEMP(temp_a);
}
@@ -1936,8 +1946,8 @@ ZEND_FUNCTION(gmp_hamdist)
RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
- FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
+ FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
RETVAL_LONG(mpz_hamdist(gmpnum_a, gmpnum_b));
@@ -1959,11 +1969,11 @@ ZEND_FUNCTION(gmp_scan0)
}
if (start < 0) {
- php_error_docref(NULL, E_WARNING, "Starting index must be greater than or equal to zero");
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be greater than or equal to 0");
+ RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
RETVAL_LONG(mpz_scan0(gmpnum_a, start));
FREE_GMP_TEMP(temp_a);
@@ -1983,11 +1993,11 @@ ZEND_FUNCTION(gmp_scan1)
}
if (start < 0) {
- php_error_docref(NULL, E_WARNING, "Starting index must be greater than or equal to zero");
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be greater than or equal to 0");
+ RETURN_THROWS();
}
- FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+ FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
RETVAL_LONG(mpz_scan1(gmpnum_a, start));
FREE_GMP_TEMP(temp_a);