From: Nikita Popov Date: Sat, 9 Dec 2017 20:57:41 +0000 (+0100) Subject: Add gmp_kronecker() X-Git-Tag: php-7.3.0alpha1~822 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fc80114a481e1e7fc8c7be775a2cce683db9c107;p=php Add gmp_kronecker() Exposes the mpz_kronecker(), mpz_si_kronecker() and mpz_kronecher_si() for computing the Kronecker symbol. --- diff --git a/NEWS b/NEWS index 533f0d4514..258446fcc5 100644 --- a/NEWS +++ b/NEWS @@ -51,6 +51,7 @@ PHP NEWS . Added gmp_binomial(n, k). (Nikita) . Added gmp_lcm(a, b). (Nikita) . Added gmp_perfect_power(a). (Nikita) + . Added gmp_kronecker(a, b). (Nikita) - intl: . Fixed bug #75317 (UConverter::setDestinationEncoding changes source instead diff --git a/UPGRADING b/UPGRADING index 955b53ce1c..96c5583bec 100644 --- a/UPGRADING +++ b/UPGRADING @@ -89,6 +89,7 @@ GMP: . Added gmp_binomial(n, k) for calculating binomial coefficients. . Added gmp_lcm(a, b) for calculating the least common multiple. . Added gmp_perfect_power(a) to check if number is a perfect power. + . Added gmp_kronecker(a, b) to compute the Kronecker symbol. Intl: . Added void Spoofchecker::setRestrictionLevel(int $level) method, available diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 7453b85ba9..ef9f070f49 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -172,6 +172,7 @@ const zend_function_entry gmp_functions[] = { 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) @@ -1782,6 +1783,50 @@ ZEND_FUNCTION(gmp_legendre) } /* }}} */ +/* {{{ proto int gmp_kronecker(mixed a, mixed b) + Computes the Kronecker symbol */ +ZEND_FUNCTION(gmp_kronecker) +{ + zval *a_arg, *b_arg; + mpz_ptr gmpnum_a, gmpnum_b; + gmp_temp_t temp_a, temp_b; + zend_bool use_a_si = 0, use_b_si = 0; + int result; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a_arg, &b_arg) == FAILURE){ + return; + } + + if (Z_TYPE_P(a_arg) == IS_LONG && Z_TYPE_P(b_arg) != IS_LONG) { + use_a_si = 1; + temp_a.is_used = 0; + } else { + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); + } + + 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); + } + + if (use_a_si) { + ZEND_ASSERT(use_b_si == 0); + result = mpz_si_kronecker((gmp_long) Z_LVAL_P(a_arg), gmpnum_b); + } else if (use_b_si) { + result = mpz_kronecker_si(gmpnum_a, (gmp_long) Z_LVAL_P(b_arg)); + } else { + result = mpz_kronecker(gmpnum_a, gmpnum_b); + } + + FREE_GMP_TEMP(temp_a); + FREE_GMP_TEMP(temp_b); + + RETURN_LONG(result); +} +/* }}} */ + /* {{{ proto int gmp_cmp(mixed a, mixed b) Compares two numbers */ ZEND_FUNCTION(gmp_cmp) diff --git a/ext/gmp/php_gmp.h b/ext/gmp/php_gmp.h index 99dfe476d0..0148e488f5 100644 --- a/ext/gmp/php_gmp.h +++ b/ext/gmp/php_gmp.h @@ -61,6 +61,7 @@ ZEND_FUNCTION(gmp_gcdext); ZEND_FUNCTION(gmp_invert); ZEND_FUNCTION(gmp_jacobi); ZEND_FUNCTION(gmp_legendre); +ZEND_FUNCTION(gmp_kronecker); ZEND_FUNCTION(gmp_cmp); ZEND_FUNCTION(gmp_sign); ZEND_FUNCTION(gmp_and); diff --git a/ext/gmp/tests/gmp_kronecker.phpt b/ext/gmp/tests/gmp_kronecker.phpt new file mode 100644 index 0000000000..8bfa876ee1 --- /dev/null +++ b/ext/gmp/tests/gmp_kronecker.phpt @@ -0,0 +1,31 @@ +--TEST-- +gmp_kronecker(): Kronecker symbol +--FILE-- + +--EXPECT-- +int(-1) +int(-1) +int(-1) +int(-1) +int(-1) +int(-1) +int(-1) + +int(-1) +int(1) +int(-1)