📄 gmp.c
字号:
gmp_zval_unary_ui_op(return_value, a_arg, gmp_op);}/* }}} *//* {{{ _gmp_unary_op */static inline void _gmp_unary_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_op_t gmp_op) { zval **a_arg; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){ WRONG_PARAM_COUNT; } gmp_zval_unary_op(return_value, a_arg, gmp_op TSRMLS_CC);}/* }}} *//* {{{ _gmp_unary_opl */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));}/* }}} *//* {{{ _gmp_binary_opl */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));}/* }}} *//* {{{ proto resource gmp_init(mixed number [, int base]) Initializes GMP number */ZEND_FUNCTION(gmp_init){ zval **number_arg, **base_arg; mpz_t * gmpnumber; int argc; int base=0; argc = ZEND_NUM_ARGS(); if (argc < 1 || argc > 2 || zend_get_parameters_ex(argc, &number_arg, &base_arg) == FAILURE){ WRONG_PARAM_COUNT; } if (argc==2) { convert_to_long_ex(base_arg); base = Z_LVAL_PP(base_arg); if(base < 2 || base > 36) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad base for conversion: %d (should be between 2 and 36)", base); RETURN_FALSE; } } if(convert_to_gmp(&gmpnumber, number_arg, base TSRMLS_CC) == FAILURE) { RETURN_FALSE; } /* Write your own code here to handle argument number. */ ZEND_REGISTER_RESOURCE(return_value, gmpnumber, le_gmp);}/* }}} *//* {{{ proto int gmp_intval(resource gmpnumber) Gets signed long value of GMP number */ZEND_FUNCTION(gmp_intval){ zval **gmpnumber_arg; mpz_t * gmpnum; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &gmpnumber_arg) == FAILURE){ WRONG_PARAM_COUNT; } if(Z_TYPE_PP(gmpnumber_arg) == IS_RESOURCE) { ZEND_FETCH_RESOURCE(gmpnum, mpz_t *, gmpnumber_arg, -1, GMP_RESOURCE_NAME, le_gmp); RETVAL_LONG(mpz_get_si(*gmpnum)); } else { convert_to_long_ex(gmpnumber_arg); RETVAL_LONG(Z_LVAL_PP(gmpnumber_arg)); }}/* }}} *//* {{{ proto string gmp_strval(resource gmpnumber [, int base]) Gets string representation of GMP number */ZEND_FUNCTION(gmp_strval){ zval **gmpnumber_arg, **base_arg; int base=10, num_len, argc; mpz_t * gmpnum; char *out_string; argc = ZEND_NUM_ARGS(); if (argc < 1 || argc > 2 || zend_get_parameters_ex(argc, &gmpnumber_arg, &base_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum, gmpnumber_arg); switch (argc) { case 2: convert_to_long_ex(base_arg); base = Z_LVAL_PP(base_arg); break; case 1: base = 10; break; } if(base < 2 || base > 36) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad base for conversion: %d", base); RETURN_FALSE; } num_len = mpz_sizeinbase(*gmpnum, base); out_string = emalloc(num_len+2); if(mpz_sgn(*gmpnum) < 0) { num_len++; } mpz_get_str(out_string, base, *gmpnum); /* From GMP documentation for mpz_sizeinbase(): The returned value will be exact or 1 too big. If base is a power of 2, the returned value will always be exact. So let's check to see if we already have a \0 byte... */ if (out_string[num_len-1] == '\0') num_len--; else out_string[num_len] = '\0'; RETVAL_STRINGL(out_string, num_len, 0);}/* }}} *//* {{{ proto resource gmp_add(resource a, resource b) Add a and b */ZEND_FUNCTION(gmp_add){ gmp_binary_ui_op(mpz_add, (gmp_binary_ui_op_t)mpz_add_ui);}/* }}} *//* {{{ proto resource gmp_sub(resource a, resource b) Subtract b from a */ZEND_FUNCTION(gmp_sub){ gmp_binary_ui_op(mpz_sub, (gmp_binary_ui_op_t)mpz_sub_ui);}/* }}} *//* {{{ proto resource gmp_mul(resource a, resource b) Multiply a and b */ZEND_FUNCTION(gmp_mul){ gmp_binary_ui_op(mpz_mul, (gmp_binary_ui_op_t)mpz_mul_ui);}/* }}} *//* {{{ proto array gmp_div_qr(resource a, resource b [, int round]) Divide a by b, returns quotient and reminder */ZEND_FUNCTION(gmp_div_qr){ zval **a_arg, **b_arg, **round_arg; int round=GMP_ROUND_ZERO, argc; argc = ZEND_NUM_ARGS(); if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &a_arg, &b_arg, &round_arg) == FAILURE){ WRONG_PARAM_COUNT; } switch (argc) { case 3: convert_to_long_ex(round_arg); round = Z_LVAL_PP(round_arg); break; case 2: round = GMP_ROUND_ZERO; break; } switch(round) { case GMP_ROUND_ZERO: gmp_zval_binary_ui_op2_ex(return_value, a_arg, b_arg, mpz_tdiv_qr, (gmp_binary_ui_op2_t)mpz_tdiv_qr_ui, 0, 1 TSRMLS_CC); break; case GMP_ROUND_PLUSINF: gmp_zval_binary_ui_op2_ex(return_value, a_arg, b_arg, mpz_cdiv_qr, (gmp_binary_ui_op2_t)mpz_cdiv_qr_ui, 0, 1 TSRMLS_CC); break; case GMP_ROUND_MINUSINF: gmp_zval_binary_ui_op2_ex(return_value, a_arg, b_arg, mpz_fdiv_qr, (gmp_binary_ui_op2_t)mpz_fdiv_qr_ui, 0, 1 TSRMLS_CC); break; } }/* }}} *//* {{{ proto resource gmp_div_r(resource a, resource b [, int round]) Divide a by b, returns reminder only */ZEND_FUNCTION(gmp_div_r){ zval **a_arg, **b_arg, **round_arg; int round=GMP_ROUND_ZERO, argc; argc = ZEND_NUM_ARGS(); if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &a_arg, &b_arg, &round_arg) == FAILURE){ WRONG_PARAM_COUNT; } switch (argc) { case 3: convert_to_long_ex(round_arg); round = Z_LVAL_PP(round_arg); break; case 2: round = GMP_ROUND_ZERO; break; } 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); 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); 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); break; }}/* }}} *//* {{{ proto resource gmp_div_q(resource a, resource b [, int round]) Divide a by b, returns quotient only */ZEND_FUNCTION(gmp_div_q){ zval **a_arg, **b_arg, **round_arg; int round=GMP_ROUND_ZERO, argc; argc = ZEND_NUM_ARGS(); if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &a_arg, &b_arg, &round_arg) == FAILURE){ WRONG_PARAM_COUNT; } switch (argc) { case 3: convert_to_long_ex(round_arg); round = Z_LVAL_PP(round_arg); break; case 2: round = GMP_ROUND_ZERO; break; } 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); 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); 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); break; } }/* }}} *//* {{{ proto resource gmp_mod(resource a, resource b) Computes a modulo b */ZEND_FUNCTION(gmp_mod){ zval **a_arg, **b_arg; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){ WRONG_PARAM_COUNT; } 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);}/* }}} *//* {{{ proto resource gmp_divexact(resource a, resource b) Divide a by b using exact division algorithm */ZEND_FUNCTION(gmp_divexact){ gmp_binary_op(mpz_divexact);}/* }}} *//* {{{ proto resource gmp_neg(resource a) Negates a number */ZEND_FUNCTION(gmp_neg){ gmp_unary_op(mpz_neg);}/* }}} *//* {{{ proto resource gmp_abs(resource a) Calculates absolute value */ZEND_FUNCTION(gmp_abs){ gmp_unary_op(mpz_abs);}/* }}} *//* {{{ proto resource gmp_fact(int a) Calculates factorial function */ZEND_FUNCTION(gmp_fact){ zval **a_arg; mpz_t *gmpnum_tmp; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){ WRONG_PARAM_COUNT; } if (Z_TYPE_PP(a_arg) == IS_RESOURCE) { FETCH_GMP_ZVAL(gmpnum_tmp, a_arg); if (mpz_sgn(*gmpnum_tmp) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Number has to be greater than or equal to 0"); RETURN_FALSE; } } else { convert_to_long_ex(a_arg); if (Z_LVAL_PP(a_arg) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Number has to be greater than or equal to 0"); RETURN_FALSE; } } gmp_zval_unary_ui_op(return_value, a_arg, mpz_fac_ui);}/* }}} *//* {{{ proto resource gmp_pow(resource base, int exp) Raise base to power exp */ZEND_FUNCTION(gmp_pow){ zval **base_arg, **exp_arg; mpz_t *gmpnum_result, *gmpnum_base; int use_ui=0; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &base_arg, &exp_arg) == FAILURE){ WRONG_PARAM_COUNT; } if(Z_TYPE_PP(base_arg) == IS_LONG && Z_LVAL_PP(base_arg) >= 0) { use_ui=1; } else { FETCH_GMP_ZVAL(gmpnum_base, base_arg); } convert_to_long_ex(exp_arg); if(Z_LVAL_PP(exp_arg) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Negative exponent not supported"); RETURN_FALSE; } INIT_GMP_NUM(gmpnum_result); if(use_ui) { mpz_ui_pow_ui(*gmpnum_result, Z_LVAL_PP(base_arg), Z_LVAL_PP(exp_arg)); } else { mpz_pow_ui(*gmpnum_result, *gmpnum_base, Z_LVAL_PP(exp_arg)); } ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);}/* }}} *//* {{{ proto resource gmp_powm(resource base, resource exp, resource mod) Raise base to power exp and take result modulo mod */ZEND_FUNCTION(gmp_powm){ zval **base_arg, **exp_arg, **mod_arg; mpz_t *gmpnum_base, *gmpnum_exp, *gmpnum_mod, *gmpnum_result; int use_ui=0; if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &base_arg, &exp_arg, &mod_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_base, base_arg); if(Z_TYPE_PP(exp_arg) == IS_LONG && Z_LVAL_PP(exp_arg) >= 0) { use_ui=1; } else { FETCH_GMP_ZVAL(gmpnum_exp, exp_arg); if (mpz_sgn(*gmpnum_exp) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Second parameter cannot be less than 0"); RETURN_FALSE; } } FETCH_GMP_ZVAL(gmpnum_mod, mod_arg); if (!mpz_cmp_ui(*gmpnum_mod, 0)) { RETURN_FALSE; } INIT_GMP_NUM(gmpnum_result); if(use_ui) { mpz_powm_ui(*gmpnum_result, *gmpnum_base, (unsigned long)Z_LVAL_PP(exp_arg), *gmpnum_mod); } else { mpz_powm(*gmpnum_result, *gmpnum_base, *gmpnum_exp, *gmpnum_mod); } ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);}/* }}} *//* {{{ proto resource gmp_sqrt(resource a) Takes integer part of square root of a */ZEND_FUNCTION(gmp_sqrt){ zval **a_arg; mpz_t *gmpnum_a, *gmpnum_result; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, a_arg); if (mpz_sgn(*gmpnum_a) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Number has to be greater than or equal to 0"); RETURN_FALSE; } INIT_GMP_NUM(gmpnum_result);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -