]> granicus.if.org Git - php/commitdiff
Add gmp_root() and gmp_rootrem() functions
authorNikita Popov <nikic@php.net>
Thu, 28 Nov 2013 22:42:23 +0000 (23:42 +0100)
committerNikita Popov <nikic@php.net>
Thu, 28 Nov 2013 23:01:59 +0000 (00:01 +0100)
NEWS
UPGRADING
ext/gmp/gmp.c
ext/gmp/php_gmp.h

diff --git a/NEWS b/NEWS
index 29dd740646f0f167afa756de48eca2c8d2b88585..dabe0cf1370706632dea94bcdf0dee6118f33b06 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,8 @@ PHP                                                                        NEWS
   . Moved GMP to use object as the underlying structure and implemented various
     improvements based on this.
     (RFC: https://wiki.php.net/rfc/operator_overloading_gmp). (Nikita)
+  . Added gmp_root() and gmp_rootrem() functions for calculating nth roots.
+    (Nikita)
 
 - Hash:
   . Added gost-crypto (CryptoPro S-box) GOST hash algo. (Manuel Mausz)
index b680a9fbe5f9719a1c797cb6683df0aaec89a441..6392c5fa762d66e78b5135c8b59d36ef496994a5 100755 (executable)
--- a/UPGRADING
+++ b/UPGRADING
@@ -88,6 +88,9 @@ PHP X.Y UPGRADE NOTES
 5. New Functions
 ========================================
 
+- GMP:
+  Added gmp_root($a, $nth) and gmp_rootrem($a, $nth) for calculating nth roots.
+
 - Openssl:
   Added string openssl_x509_fingerprint($x509, $type, $binary).
 
index d3b618910d6181686eaede7a140f0d4bbd0008ba..e64acf92addff37bbff363a9a3318bf784962776 100644 (file)
@@ -126,6 +126,16 @@ ZEND_BEGIN_ARG_INFO(arginfo_gmp_sqrtrem, 0)
        ZEND_ARG_INFO(0, a)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_INFO(arginfo_gmp_root, 0)
+       ZEND_ARG_INFO(0, a)
+       ZEND_ARG_INFO(0, nth)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_gmp_rootrem, 0)
+       ZEND_ARG_INFO(0, a)
+       ZEND_ARG_INFO(0, nth)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO(arginfo_gmp_perfect_square, 0)
        ZEND_ARG_INFO(0, a)
 ZEND_END_ARG_INFO()
@@ -256,6 +266,8 @@ const zend_function_entry gmp_functions[] = {
        ZEND_FE(gmp_fact,       arginfo_gmp_fact)
        ZEND_FE(gmp_sqrt,       arginfo_gmp_sqrt)
        ZEND_FE(gmp_sqrtrem,    arginfo_gmp_sqrtrem)
+       ZEND_FE(gmp_root,       arginfo_gmp_root)
+       ZEND_FE(gmp_rootrem,    arginfo_gmp_rootrem)
        ZEND_FE(gmp_pow,        arginfo_gmp_pow)
        ZEND_FE(gmp_powm,       arginfo_gmp_powm)
        ZEND_FE(gmp_perfect_square,     arginfo_gmp_perfect_square)
@@ -1514,6 +1526,73 @@ ZEND_FUNCTION(gmp_sqrtrem)
 }
 /* }}} */
 
+/* {{{ proto GMP gmp_root(mixed a, int nth)
+   Takes integer part of nth root */
+ZEND_FUNCTION(gmp_root)
+{
+       zval *a_arg;
+       long nth;
+       mpz_ptr gmpnum_a, gmpnum_result;
+       gmp_temp_t temp_a;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &nth) == FAILURE) {
+               return;
+       }
+
+       if (nth <= 0) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "The root must be positive");
+               RETURN_FALSE;
+       }
+
+       FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+
+       if (nth % 2 == 0 && mpz_sgn(gmpnum_a) < 0) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't take even root of negative number");
+               FREE_GMP_TEMP(temp_a);
+               RETURN_FALSE;
+       }
+
+       INIT_GMP_RETVAL(gmpnum_result);
+       mpz_root(gmpnum_result, gmpnum_a, (unsigned long) nth);
+       FREE_GMP_TEMP(temp_a);
+}
+/* }}} */
+
+/* {{{ proto GMP gmp_rootrem(mixed a, int nth)
+   Calculates integer part of nth root and remainder */
+ZEND_FUNCTION(gmp_rootrem)
+{
+       zval *a_arg;
+       long nth;
+       mpz_ptr gmpnum_a, gmpnum_result1, gmpnum_result2;
+       gmp_temp_t temp_a;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &nth) == FAILURE) {
+               return;
+       }
+
+       if (nth <= 0) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "The root must be positive");
+               RETURN_FALSE;
+       }
+
+       FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+
+       if (nth % 2 == 0 && mpz_sgn(gmpnum_a) < 0) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't take even root of negative number");
+               FREE_GMP_TEMP(temp_a);
+               RETURN_FALSE;
+       }
+
+       array_init(return_value);
+       add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC));
+       add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC));
+
+       mpz_rootrem(gmpnum_result1, gmpnum_result2, gmpnum_a, (unsigned long) nth);
+       FREE_GMP_TEMP(temp_a);
+}
+/* }}} */
+
 /* {{{ proto bool gmp_perfect_square(mixed a)
    Checks if a is an exact square */
 ZEND_FUNCTION(gmp_perfect_square)
index e1aaef886d277692a7e693b93803ac363cfe0b54..902c3ac0bbd6fa5703bf816bdb6f930dc13a9e43 100644 (file)
@@ -45,9 +45,11 @@ ZEND_FUNCTION(gmp_neg);
 ZEND_FUNCTION(gmp_abs);
 ZEND_FUNCTION(gmp_fact);
 ZEND_FUNCTION(gmp_sqrt);
+ZEND_FUNCTION(gmp_sqrtrem);
+ZEND_FUNCTION(gmp_root);
+ZEND_FUNCTION(gmp_rootrem);
 ZEND_FUNCTION(gmp_pow);
 ZEND_FUNCTION(gmp_powm);
-ZEND_FUNCTION(gmp_sqrtrem);
 ZEND_FUNCTION(gmp_perfect_square);
 ZEND_FUNCTION(gmp_prob_prime);
 ZEND_FUNCTION(gmp_gcd);