diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2017-12-09 21:09:27 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2017-12-11 19:25:54 +0100 |
commit | 7fea79675cfb064726f3fc7845e2c2bb1f247ea5 (patch) | |
tree | 41adc67f230e213868e797351bcb9c2c1333e588 /ext/gmp | |
parent | dc47171523b70112b14cf9144bdf223e9db550fe (diff) | |
download | php-git-7fea79675cfb064726f3fc7845e2c2bb1f247ea5.tar.gz |
Add gmp_binomial()
Adds PHP bindings for mpz_bin_ui and mpz_bin_uiui, for calculating
binomial coefficients.
Diffstat (limited to 'ext/gmp')
-rw-r--r-- | ext/gmp/gmp.c | 31 | ||||
-rw-r--r-- | ext/gmp/php_gmp.h | 1 | ||||
-rw-r--r-- | ext/gmp/tests/gmp_binomial.phpt | 67 |
3 files changed, 99 insertions, 0 deletions
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 4b4f7536f4..667df7cdad 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -188,6 +188,7 @@ const zend_function_entry gmp_functions[] = { 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 }; /* }}} */ @@ -1382,6 +1383,36 @@ ZEND_FUNCTION(gmp_fact) } /* }}} */ +/* {{{ proto GMP gmp_binomial(mixed n, int k) + * Calculates binomial coefficient */ +ZEND_FUNCTION(gmp_binomial) +{ + zval *n_arg; + zend_long k; + mpz_ptr gmpnum_result; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zl", &n_arg, &k) == FAILURE) { + return; + } + + if (k < 0) { + php_error_docref(NULL, E_WARNING, "k cannot be negative"); + RETURN_FALSE; + } + + INIT_GMP_RETVAL(gmpnum_result); + if (Z_TYPE_P(n_arg) == IS_LONG && Z_LVAL_P(n_arg) >= 0) { + mpz_bin_uiui(gmpnum_result, (gmp_ulong) Z_LVAL_P(n_arg), (gmp_ulong) k); + } else { + mpz_ptr gmpnum_n; + gmp_temp_t temp_n; + FETCH_GMP_ZVAL(gmpnum_n, n_arg, temp_n); + mpz_bin_ui(gmpnum_result, gmpnum_n, (gmp_ulong) k); + FREE_GMP_TEMP(temp_n); + } +} +/* }}} */ + /* {{{ proto GMP gmp_pow(mixed base, int exp) Raise base to power exp */ ZEND_FUNCTION(gmp_pow) diff --git a/ext/gmp/php_gmp.h b/ext/gmp/php_gmp.h index 971d6593ec..8ba4b89d5b 100644 --- a/ext/gmp/php_gmp.h +++ b/ext/gmp/php_gmp.h @@ -78,6 +78,7 @@ ZEND_FUNCTION(gmp_testbit); ZEND_FUNCTION(gmp_popcount); ZEND_FUNCTION(gmp_hamdist); ZEND_FUNCTION(gmp_nextprime); +ZEND_FUNCTION(gmp_binomial); ZEND_BEGIN_MODULE_GLOBALS(gmp) zend_bool rand_initialized; diff --git a/ext/gmp/tests/gmp_binomial.phpt b/ext/gmp/tests/gmp_binomial.phpt new file mode 100644 index 0000000000..9c280c78df --- /dev/null +++ b/ext/gmp/tests/gmp_binomial.phpt @@ -0,0 +1,67 @@ +--TEST-- +gmp_binomial(): Binomial coefficients +--FILE-- +<?php + +var_dump(gmp_binomial(10, 5)); +var_dump(gmp_binomial("10", 5)); +$n = gmp_init(10); +var_dump(gmp_binomial($n, 5)); + +var_dump(gmp_binomial(10000, 100)); + +var_dump(gmp_binomial(0, 0)); +var_dump(gmp_binomial(0, 1)); +var_dump(gmp_binomial(1, 0)); +var_dump(gmp_binomial(1, 1)); + +var_dump(gmp_binomial(-1, 5)); // == -(1 + 5 - 1 over 5) +var_dump(gmp_binomial(-2, 6)); // == (2 + 6 - 1 over 6) + +var_dump(gmp_binomial(5, -2)); + +?> +--EXPECTF-- +object(GMP)#1 (1) { + ["num"]=> + string(3) "252" +} +object(GMP)#1 (1) { + ["num"]=> + string(3) "252" +} +object(GMP)#2 (1) { + ["num"]=> + string(3) "252" +} +object(GMP)#2 (1) { + ["num"]=> + string(242) "65208469245472575695415972927215718683781335425416743372210247172869206520770178988927510291340552990847853030615947098118282371982392705479271195296127415562705948429404753632271959046657595132854990606768967505457396473467998111950929802400" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "1" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "1" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "1" +} +object(GMP)#2 (1) { + ["num"]=> + string(2) "-1" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "7" +} + +Warning: gmp_binomial(): k cannot be negative in %s on line %d +bool(false) |