PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/gmp - gmp.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 487 500 97.4 %
Date: 2014-09-13 Functions: 56 56 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Author: Stanislav Malyshev <stas@php.net>                            |
      16             :    +----------------------------------------------------------------------+
      17             :  */
      18             : 
      19             : #ifdef HAVE_CONFIG_H
      20             : #include "config.h"
      21             : #endif
      22             : 
      23             : #include "php.h"
      24             : #include "php_ini.h"
      25             : #include "php_gmp.h"
      26             : #include "ext/standard/info.h"
      27             : 
      28             : #if HAVE_GMP
      29             : 
      30             : #include <gmp.h>
      31             : 
      32             : /* Needed for gmp_random() */
      33             : #include "ext/standard/php_rand.h"
      34             : #include "ext/standard/php_lcg.h"
      35             : #define GMP_ABS(x) ((x) >= 0 ? (x) : -(x))
      36             : 
      37             : /* True global resources - no need for thread safety here */
      38             : static int le_gmp;
      39             : 
      40             : /* {{{ arginfo */
      41             : ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_init, 0, 0, 1)
      42             :         ZEND_ARG_INFO(0, number)
      43             :         ZEND_ARG_INFO(0, base)
      44             : ZEND_END_ARG_INFO()
      45             : 
      46             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_intval, 0)
      47             :         ZEND_ARG_INFO(0, gmpnumber)
      48             : ZEND_END_ARG_INFO()
      49             : 
      50             : ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_strval, 0, 0, 1)
      51             :         ZEND_ARG_INFO(0, gmpnumber)
      52             :         ZEND_ARG_INFO(0, base)
      53             : ZEND_END_ARG_INFO()
      54             : 
      55             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_add, 0)
      56             :         ZEND_ARG_INFO(0, a)
      57             :         ZEND_ARG_INFO(0, b)
      58             : ZEND_END_ARG_INFO()
      59             : 
      60             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_sub, 0)
      61             :         ZEND_ARG_INFO(0, a)
      62             :         ZEND_ARG_INFO(0, b)
      63             : ZEND_END_ARG_INFO()
      64             : 
      65             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_mul, 0)
      66             :         ZEND_ARG_INFO(0, a)
      67             :         ZEND_ARG_INFO(0, b)
      68             : ZEND_END_ARG_INFO()
      69             : 
      70             : ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_div_qr, 0, 0, 2)
      71             :         ZEND_ARG_INFO(0, a)
      72             :         ZEND_ARG_INFO(0, b)
      73             :         ZEND_ARG_INFO(0, round)
      74             : ZEND_END_ARG_INFO()
      75             : 
      76             : ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_div_r, 0, 0, 2)
      77             :         ZEND_ARG_INFO(0, a)
      78             :         ZEND_ARG_INFO(0, b)
      79             :         ZEND_ARG_INFO(0, round)
      80             : ZEND_END_ARG_INFO()
      81             : 
      82             : ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_div_q, 0, 0, 2)
      83             :         ZEND_ARG_INFO(0, a)
      84             :         ZEND_ARG_INFO(0, b)
      85             :         ZEND_ARG_INFO(0, round)
      86             : ZEND_END_ARG_INFO()
      87             : 
      88             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_mod, 0)
      89             :         ZEND_ARG_INFO(0, a)
      90             :         ZEND_ARG_INFO(0, b)
      91             : ZEND_END_ARG_INFO()
      92             : 
      93             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_divexact, 0)
      94             :         ZEND_ARG_INFO(0, a)
      95             :         ZEND_ARG_INFO(0, b)
      96             : ZEND_END_ARG_INFO()
      97             : 
      98             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_neg, 0)
      99             :         ZEND_ARG_INFO(0, a)
     100             : ZEND_END_ARG_INFO()
     101             : 
     102             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_abs, 0)
     103             :         ZEND_ARG_INFO(0, a)
     104             : ZEND_END_ARG_INFO()
     105             : 
     106             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_fact, 0)
     107             :         ZEND_ARG_INFO(0, a)
     108             : ZEND_END_ARG_INFO()
     109             : 
     110             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_pow, 0)
     111             :         ZEND_ARG_INFO(0, base)
     112             :         ZEND_ARG_INFO(0, exp)
     113             : ZEND_END_ARG_INFO()
     114             : 
     115             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_powm, 0)
     116             :         ZEND_ARG_INFO(0, base)
     117             :         ZEND_ARG_INFO(0, exp)
     118             :         ZEND_ARG_INFO(0, mod)
     119             : ZEND_END_ARG_INFO()
     120             : 
     121             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_sqrt, 0)
     122             :         ZEND_ARG_INFO(0, a)
     123             : ZEND_END_ARG_INFO()
     124             : 
     125             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_sqrtrem, 0)
     126             :         ZEND_ARG_INFO(0, a)
     127             : ZEND_END_ARG_INFO()
     128             : 
     129             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_perfect_square, 0)
     130             :         ZEND_ARG_INFO(0, a)
     131             : ZEND_END_ARG_INFO()
     132             : 
     133             : ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_prob_prime, 0, 0, 1)
     134             :         ZEND_ARG_INFO(0, a)
     135             :         ZEND_ARG_INFO(0, reps)
     136             : ZEND_END_ARG_INFO()
     137             : 
     138             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_gcd, 0)
     139             :         ZEND_ARG_INFO(0, a)
     140             :         ZEND_ARG_INFO(0, b)
     141             : ZEND_END_ARG_INFO()
     142             : 
     143             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_gcdext, 0)
     144             :         ZEND_ARG_INFO(0, a)
     145             :         ZEND_ARG_INFO(0, b)
     146             : ZEND_END_ARG_INFO()
     147             : 
     148             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_invert, 0)
     149             :         ZEND_ARG_INFO(0, a)
     150             :         ZEND_ARG_INFO(0, b)
     151             : ZEND_END_ARG_INFO()
     152             : 
     153             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_jacobi, 0)
     154             :         ZEND_ARG_INFO(0, a)
     155             :         ZEND_ARG_INFO(0, b)
     156             : ZEND_END_ARG_INFO()
     157             : 
     158             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_legendre, 0)
     159             :         ZEND_ARG_INFO(0, a)
     160             :         ZEND_ARG_INFO(0, b)
     161             : ZEND_END_ARG_INFO()
     162             : 
     163             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_cmp, 0)
     164             :         ZEND_ARG_INFO(0, a)
     165             :         ZEND_ARG_INFO(0, b)
     166             : ZEND_END_ARG_INFO()
     167             : 
     168             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_sign, 0)
     169             :         ZEND_ARG_INFO(0, a)
     170             : ZEND_END_ARG_INFO()
     171             : 
     172             : ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random, 0, 0, 0)
     173             :         ZEND_ARG_INFO(0, limiter)
     174             : ZEND_END_ARG_INFO()
     175             : 
     176             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_and, 0)
     177             :         ZEND_ARG_INFO(0, a)
     178             :         ZEND_ARG_INFO(0, b)
     179             : ZEND_END_ARG_INFO()
     180             : 
     181             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_or, 0)
     182             :         ZEND_ARG_INFO(0, a)
     183             :         ZEND_ARG_INFO(0, b)
     184             : ZEND_END_ARG_INFO()
     185             : 
     186             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_com, 0)
     187             :         ZEND_ARG_INFO(0, a)
     188             : ZEND_END_ARG_INFO()
     189             : 
     190             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_xor, 0)
     191             :         ZEND_ARG_INFO(0, a)
     192             :         ZEND_ARG_INFO(0, b)
     193             : ZEND_END_ARG_INFO()
     194             : 
     195             : ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_setbit, 0, 0, 2)
     196             :         ZEND_ARG_INFO(1, a)
     197             :         ZEND_ARG_INFO(0, index)
     198             :         ZEND_ARG_INFO(0, set_clear)
     199             : ZEND_END_ARG_INFO()
     200             : 
     201             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_clrbit, 0)
     202             :         ZEND_ARG_INFO(1, a)
     203             :         ZEND_ARG_INFO(0, index)
     204             : ZEND_END_ARG_INFO()
     205             : 
     206             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_testbit, 0)
     207             :         ZEND_ARG_INFO(0, a)
     208             :         ZEND_ARG_INFO(0, index)
     209             : ZEND_END_ARG_INFO()
     210             : 
     211             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_popcount, 0)
     212             :         ZEND_ARG_INFO(0, a)
     213             : ZEND_END_ARG_INFO()
     214             : 
     215             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_hamdist, 0)
     216             :         ZEND_ARG_INFO(0, a)
     217             :         ZEND_ARG_INFO(0, b)
     218             : ZEND_END_ARG_INFO()
     219             : 
     220             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_scan0, 0)
     221             :         ZEND_ARG_INFO(0, a)
     222             :         ZEND_ARG_INFO(0, start)
     223             : ZEND_END_ARG_INFO()
     224             : 
     225             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_scan1, 0)
     226             :         ZEND_ARG_INFO(0, a)
     227             :         ZEND_ARG_INFO(0, start)
     228             : ZEND_END_ARG_INFO()
     229             : 
     230             : ZEND_BEGIN_ARG_INFO(arginfo_gmp_nextprime, 0)
     231             :         ZEND_ARG_INFO(0, a)
     232             : ZEND_END_ARG_INFO()
     233             : 
     234             : /* }}} */
     235             : 
     236             : ZEND_DECLARE_MODULE_GLOBALS(gmp)
     237             : static ZEND_GINIT_FUNCTION(gmp);
     238             : 
     239             : /* {{{ gmp_functions[]
     240             :  */
     241             : const zend_function_entry gmp_functions[] = {
     242             :         ZEND_FE(gmp_init,       arginfo_gmp_init)
     243             :         ZEND_FE(gmp_intval,     arginfo_gmp_intval)
     244             :         ZEND_FE(gmp_strval,     arginfo_gmp_strval)
     245             :         ZEND_FE(gmp_add,            arginfo_gmp_add)
     246             :         ZEND_FE(gmp_sub,            arginfo_gmp_sub)
     247             :         ZEND_FE(gmp_mul,            arginfo_gmp_mul)
     248             :         ZEND_FE(gmp_div_qr,     arginfo_gmp_div_qr)
     249             :         ZEND_FE(gmp_div_q,      arginfo_gmp_div_q)
     250             :         ZEND_FE(gmp_div_r,      arginfo_gmp_div_r)
     251             :         ZEND_FALIAS(gmp_div,    gmp_div_q, arginfo_gmp_div_q)
     252             :         ZEND_FE(gmp_mod,        arginfo_gmp_mod)
     253             :         ZEND_FE(gmp_divexact,   arginfo_gmp_divexact)
     254             :         ZEND_FE(gmp_neg,        arginfo_gmp_neg)
     255             :         ZEND_FE(gmp_abs,        arginfo_gmp_abs)
     256             :         ZEND_FE(gmp_fact,       arginfo_gmp_fact)
     257             :         ZEND_FE(gmp_sqrt,       arginfo_gmp_sqrt)
     258             :         ZEND_FE(gmp_sqrtrem,    arginfo_gmp_sqrtrem)
     259             :         ZEND_FE(gmp_pow,        arginfo_gmp_pow)
     260             :         ZEND_FE(gmp_powm,       arginfo_gmp_powm)
     261             :         ZEND_FE(gmp_perfect_square,     arginfo_gmp_perfect_square)
     262             :         ZEND_FE(gmp_prob_prime, arginfo_gmp_prob_prime)
     263             :         ZEND_FE(gmp_gcd,        arginfo_gmp_gcd)
     264             :         ZEND_FE(gmp_gcdext,     arginfo_gmp_gcdext)
     265             :         ZEND_FE(gmp_invert,     arginfo_gmp_invert)
     266             :         ZEND_FE(gmp_jacobi,     arginfo_gmp_jacobi)
     267             :         ZEND_FE(gmp_legendre,   arginfo_gmp_legendre)
     268             :         ZEND_FE(gmp_cmp,        arginfo_gmp_cmp)
     269             :         ZEND_FE(gmp_sign,       arginfo_gmp_sign)
     270             :         ZEND_FE(gmp_random,     arginfo_gmp_random)
     271             :         ZEND_FE(gmp_and,        arginfo_gmp_and)
     272             :         ZEND_FE(gmp_or, arginfo_gmp_or)
     273             :         ZEND_FE(gmp_com,        arginfo_gmp_com)
     274             :         ZEND_FE(gmp_xor,        arginfo_gmp_xor)
     275             :         ZEND_FE(gmp_setbit,     arginfo_gmp_setbit)
     276             :         ZEND_FE(gmp_clrbit,     arginfo_gmp_clrbit)
     277             :         ZEND_FE(gmp_scan0,  arginfo_gmp_scan0)
     278             :         ZEND_FE(gmp_scan1,  arginfo_gmp_scan1)
     279             :         ZEND_FE(gmp_testbit,arginfo_gmp_testbit)
     280             :         ZEND_FE(gmp_popcount, arginfo_gmp_popcount)
     281             :         ZEND_FE(gmp_hamdist, arginfo_gmp_hamdist)
     282             :         ZEND_FE(gmp_nextprime, arginfo_gmp_nextprime)
     283             :         PHP_FE_END
     284             : };
     285             : /* }}} */
     286             : 
     287             : /* {{{ gmp_module_entry
     288             :  */
     289             : zend_module_entry gmp_module_entry = {
     290             :         STANDARD_MODULE_HEADER,
     291             :         "gmp",
     292             :         gmp_functions,
     293             :         ZEND_MODULE_STARTUP_N(gmp),
     294             :         NULL,
     295             :         NULL,
     296             :         ZEND_MODULE_DEACTIVATE_N(gmp),
     297             :         ZEND_MODULE_INFO_N(gmp),
     298             :         NO_VERSION_YET,
     299             :         ZEND_MODULE_GLOBALS(gmp),
     300             :         ZEND_GINIT(gmp),
     301             :         NULL,
     302             :         NULL,
     303             :         STANDARD_MODULE_PROPERTIES_EX
     304             : };
     305             : /* }}} */
     306             : 
     307             : #ifdef COMPILE_DL_GMP
     308             : ZEND_GET_MODULE(gmp)
     309             : #endif
     310             : 
     311             : static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc TSRMLS_DC);
     312             : 
     313             : #define GMP_RESOURCE_NAME "GMP integer"
     314             : 
     315             : #define GMP_ROUND_ZERO      0
     316             : #define GMP_ROUND_PLUSINF   1
     317             : #define GMP_ROUND_MINUSINF  2
     318             : 
     319             : /* The maximum base for input and output conversions is 62 from GMP 4.2
     320             :  * onwards. */
     321             : #if (__GNU_MP_VERSION >= 5) || (__GNU_MP_VERSION >= 4 && __GNU_MP_VERSION_MINOR >= 2)
     322             : #       define MAX_BASE 62
     323             : #else
     324             : #       define MAX_BASE 36
     325             : #endif
     326             : 
     327             : /* {{{ gmp_emalloc
     328             :  */
     329        2829 : static void *gmp_emalloc(size_t size)
     330             : {
     331        2829 :         return emalloc(size);
     332             : }
     333             : /* }}} */
     334             : 
     335             : /* {{{ gmp_erealloc
     336             :  */
     337        1221 : static void *gmp_erealloc(void *ptr, size_t old_size, size_t new_size)
     338             : {
     339        1221 :         return erealloc(ptr, new_size);
     340             : }
     341             : /* }}} */
     342             : 
     343             : /* {{{ gmp_efree
     344             :  */
     345        2829 : static void gmp_efree(void *ptr, size_t size)
     346             : {
     347        2829 :         efree(ptr);
     348        2829 : }
     349             : /* }}} */
     350             : 
     351             : /* {{{ ZEND_GINIT_FUNCTION
     352             :  */
     353       20225 : static ZEND_GINIT_FUNCTION(gmp)
     354             : {
     355       20225 :         gmp_globals->rand_initialized = 0;
     356       20225 : }
     357             : /* }}} */
     358             : 
     359             : /* {{{ ZEND_MINIT_FUNCTION
     360             :  */
     361       20225 : ZEND_MODULE_STARTUP_D(gmp)
     362             : {
     363       20225 :         le_gmp = zend_register_list_destructors_ex(_php_gmpnum_free, NULL, GMP_RESOURCE_NAME, module_number);
     364       20225 :         REGISTER_LONG_CONSTANT("GMP_ROUND_ZERO", GMP_ROUND_ZERO, CONST_CS | CONST_PERSISTENT);
     365       20225 :         REGISTER_LONG_CONSTANT("GMP_ROUND_PLUSINF", GMP_ROUND_PLUSINF, CONST_CS | CONST_PERSISTENT);
     366       20225 :         REGISTER_LONG_CONSTANT("GMP_ROUND_MINUSINF", GMP_ROUND_MINUSINF, CONST_CS | CONST_PERSISTENT);
     367             : #ifdef mpir_version
     368             :         REGISTER_STRING_CONSTANT("GMP_MPIR_VERSION", (char *)mpir_version, CONST_CS | CONST_PERSISTENT);
     369             : #endif
     370       20225 :         REGISTER_STRING_CONSTANT("GMP_VERSION", (char *)gmp_version, CONST_CS | CONST_PERSISTENT);
     371             : 
     372       20225 :         mp_set_memory_functions(gmp_emalloc, gmp_erealloc, gmp_efree);
     373             : 
     374       20225 :         return SUCCESS;
     375             : }
     376             : /* }}} */
     377             : 
     378             : /* {{{ ZEND_RSHUTDOWN_FUNCTION
     379             :  */
     380       20220 : ZEND_MODULE_DEACTIVATE_D(gmp)
     381             : {
     382       20220 :         if (GMPG(rand_initialized)) {
     383           1 :                 gmp_randclear(GMPG(rand_state));
     384           1 :                 GMPG(rand_initialized) = 0;
     385             :         }
     386             : 
     387       20220 :         return SUCCESS;
     388             : }
     389             : /* }}} */
     390             : 
     391             : /* {{{ ZEND_MINFO_FUNCTION
     392             :  */
     393         148 : ZEND_MODULE_INFO_D(gmp)
     394             : {
     395         148 :         php_info_print_table_start();
     396         148 :         php_info_print_table_row(2, "gmp support", "enabled");
     397             : #ifdef mpir_version
     398             :         php_info_print_table_row(2, "MPIR version", mpir_version);
     399             : #else
     400         148 :         php_info_print_table_row(2, "GMP version", gmp_version);
     401             : #endif
     402         148 :         php_info_print_table_end();
     403         148 : }
     404             : /* }}} */
     405             : 
     406             : /* Fetch zval to be GMP number.
     407             :    Initially, zval can be also number or string */
     408             : #define FETCH_GMP_ZVAL(gmpnumber, zval, tmp_resource)                                                           \
     409             : if (Z_TYPE_PP(zval) == IS_RESOURCE) {                                                                                           \
     410             :         ZEND_FETCH_RESOURCE(gmpnumber, mpz_t *, zval, -1, GMP_RESOURCE_NAME, le_gmp);   \
     411             :         tmp_resource = 0;                                                                                                                               \
     412             : } else {                                                                                                                                                        \
     413             :         if (convert_to_gmp(&gmpnumber, zval, 0 TSRMLS_CC) == FAILURE) {                                     \
     414             :                 RETURN_FALSE;                                                                                                                           \
     415             :         }                                                                                                                                                               \
     416             :         tmp_resource = ZEND_REGISTER_RESOURCE(NULL, gmpnumber, le_gmp);                                 \
     417             : }
     418             : 
     419             : #define FREE_GMP_TEMP(tmp_resource)                     \
     420             :         if(tmp_resource) {                                              \
     421             :                 zend_list_delete(tmp_resource);         \
     422             :         }
     423             : 
     424             : 
     425             : /* create a new initialized GMP number */
     426             : #define INIT_GMP_NUM(gmpnumber) { gmpnumber=emalloc(sizeof(mpz_t)); mpz_init(*gmpnumber); }
     427             : #define FREE_GMP_NUM(gmpnumber) { mpz_clear(*gmpnumber); efree(gmpnumber); }
     428             : 
     429             : /* {{{ convert_to_gmp
     430             :  * Convert zval to be gmp number */
     431        1614 : static int convert_to_gmp(mpz_t * *gmpnumber, zval **val, int base TSRMLS_DC) 
     432             : {
     433        1614 :         int ret = 0;
     434        1614 :         int skip_lead = 0;
     435             : 
     436        1614 :         *gmpnumber = emalloc(sizeof(mpz_t));
     437             : 
     438        1614 :         switch (Z_TYPE_PP(val)) {
     439             :         case IS_LONG:
     440             :         case IS_BOOL:
     441             :         case IS_CONSTANT:
     442             :                 {
     443        1480 :                         convert_to_long_ex(val);
     444        1365 :                         mpz_init_set_si(**gmpnumber, Z_LVAL_PP(val));
     445             :                 }
     446        1365 :                 break;
     447             :         case IS_STRING:
     448             :                 {
     449         187 :                         char *numstr = Z_STRVAL_PP(val);
     450             : 
     451         187 :                         if (Z_STRLEN_PP(val) > 2) {
     452         154 :                                 if (numstr[0] == '0') {
     453          13 :                                         if (numstr[1] == 'x' || numstr[1] == 'X') {
     454           3 :                                                 base = 16;
     455           3 :                                                 skip_lead = 1;
     456           7 :                                         } else if (base != 16 && (numstr[1] == 'b' || numstr[1] == 'B')) {
     457           2 :                                                 base = 2;
     458           2 :                                                 skip_lead = 1;
     459             :                                         }
     460             :                                 }
     461             :                         }
     462         187 :                         ret = mpz_init_set_str(**gmpnumber, (skip_lead ? &numstr[2] : numstr), base);
     463             :                 }
     464         187 :                 break;
     465             :         default:
     466          62 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING,"Unable to convert variable to GMP - wrong type");
     467          62 :                 efree(*gmpnumber);
     468          62 :                 return FAILURE;
     469             :         }
     470             : 
     471        1552 :         if (ret) {
     472          18 :                 FREE_GMP_NUM(*gmpnumber);
     473          18 :                 return FAILURE;
     474             :         }
     475             :         
     476        1534 :         return SUCCESS;
     477             : }
     478             : /* }}} */
     479             : 
     480             : /* {{{ typedefs
     481             :  */
     482             : typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr);
     483             : typedef int (*gmp_unary_opl_t)(mpz_srcptr);
     484             : 
     485             : typedef void (*gmp_unary_ui_op_t)(mpz_ptr, unsigned long);
     486             : 
     487             : typedef void (*gmp_binary_op_t)(mpz_ptr, mpz_srcptr, mpz_srcptr);
     488             : typedef int (*gmp_binary_opl_t)(mpz_srcptr, mpz_srcptr);
     489             : 
     490             : typedef unsigned long (*gmp_binary_ui_op_t)(mpz_ptr, mpz_srcptr, unsigned long);
     491             : typedef void (*gmp_binary_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr);
     492             : typedef unsigned long (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long);
     493             : /* }}} */
     494             : 
     495             : #define gmp_zval_binary_ui_op(r, a, b, o, u) gmp_zval_binary_ui_op_ex(r, a, b, o, u, 0, 0, 0 TSRMLS_CC)
     496             : #define gmp_zval_binary_ui_op2(r, a, b, o, u) gmp_zval_binary_ui_op2_ex(r, a, b, o, u, 0, 0, 0 TSRMLS_CC)
     497             : 
     498             : #define gmp_binary_ui_op(op, uop) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop)
     499             : #define gmp_binary_op(op)         _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, NULL)
     500             : #define gmp_binary_opl(op) _gmp_binary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
     501             : 
     502             : /* Unary operations */
     503             : #define gmp_unary_op(op)         _gmp_unary_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
     504             : #define gmp_unary_opl(op)         _gmp_unary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
     505             : #define gmp_unary_ui_op(op)      _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
     506             : 
     507             : /* {{{ gmp_zval_binary_ui_op_ex
     508             :    Execute GMP binary operation.
     509             :    May return GMP resource or long if operation allows this
     510             : */
     511        1107 : static inline void gmp_zval_binary_ui_op_ex(zval *return_value, zval **a_arg, zval **b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int allow_ui_return, int check_b_zero, int use_sign TSRMLS_DC) 
     512             : {
     513             :         mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result;
     514        1107 :         unsigned long long_result = 0;
     515        1107 :         int use_ui = 0;
     516        1107 :         int arga_tmp = 0, argb_tmp = 0;
     517             : 
     518        1107 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, arga_tmp);
     519             :         
     520        1138 :         if (gmp_ui_op && Z_TYPE_PP(b_arg) == IS_LONG && Z_LVAL_PP(b_arg) >= 0) {
     521          46 :                 use_ui = 1;
     522             :         } else {
     523        1046 :                 FETCH_GMP_ZVAL(gmpnum_b, b_arg, argb_tmp);
     524             :         }
     525             : 
     526        1089 :         if(check_b_zero) {
     527          48 :                 int b_is_zero = 0;
     528          48 :                 if(use_ui) {
     529          26 :                         b_is_zero = (Z_LVAL_PP(b_arg) == 0);
     530             :                 } else {
     531          22 :                         b_is_zero = !mpz_cmp_ui(*gmpnum_b, 0);
     532             :                 }
     533             : 
     534          48 :                 if(b_is_zero) {
     535           5 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero operand not allowed");
     536           5 :                         FREE_GMP_TEMP(arga_tmp);
     537           5 :                         FREE_GMP_TEMP(argb_tmp);
     538           5 :                         RETURN_FALSE;
     539             :                 }
     540             :         }
     541             : 
     542        1084 :         INIT_GMP_NUM(gmpnum_result);
     543             : 
     544        1126 :         if (use_ui && gmp_ui_op) {
     545          42 :                 if (allow_ui_return) {
     546          14 :                         long_result = gmp_ui_op(*gmpnum_result, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg));
     547          14 :                         if (use_sign && mpz_sgn(*gmpnum_a) == -1) {
     548           0 :                                 long_result = -long_result;
     549             :                         }
     550             :                 } else {
     551          28 :                         gmp_ui_op(*gmpnum_result, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg));
     552             :                 }
     553             :         } else {
     554        1042 :                 gmp_op(*gmpnum_result, *gmpnum_a, *gmpnum_b);
     555             :         }
     556             : 
     557        1084 :         FREE_GMP_TEMP(arga_tmp);
     558        1084 :         FREE_GMP_TEMP(argb_tmp);
     559             : 
     560        1084 :         if (use_ui && allow_ui_return) {
     561          14 :                 FREE_GMP_NUM(gmpnum_result);
     562          14 :                 RETURN_LONG((long)long_result);
     563             :         } else {
     564        1070 :                 ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
     565             :         }
     566             : }
     567             : /* }}} */
     568             : 
     569             : /* {{{ gmp_zval_binary_ui_op2_ex
     570             :    Execute GMP binary operation which returns 2 values.
     571             :    May return GMP resources or longs if operation allows this.
     572             : */
     573          12 : static inline void gmp_zval_binary_ui_op2_ex(zval *return_value, zval **a_arg, zval **b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int allow_ui_return, int check_b_zero TSRMLS_DC)
     574             : {
     575             :         mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result1, *gmpnum_result2;
     576             :         zval r;
     577          12 :         int use_ui = 0;
     578          12 :         unsigned long long_result = 0;
     579          12 :         int arga_tmp = 0, argb_tmp = 0;
     580             : 
     581          12 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, arga_tmp);
     582             : 
     583          20 :         if (gmp_ui_op && Z_TYPE_PP(b_arg) == IS_LONG && Z_LVAL_PP(b_arg) >= 0) {
     584             :                 /* use _ui function */
     585          10 :                 use_ui = 1;
     586             :         } else {
     587           0 :                 FETCH_GMP_ZVAL(gmpnum_b, b_arg, argb_tmp);
     588             :         }
     589             : 
     590          10 :         if(check_b_zero) {
     591          10 :                 int b_is_zero = 0;
     592          10 :                 if(use_ui) {
     593          10 :                         b_is_zero = (Z_LVAL_PP(b_arg) == 0);
     594             :                 } else {
     595           0 :                         b_is_zero = !mpz_cmp_ui(*gmpnum_b, 0);
     596             :                 }
     597             : 
     598          10 :                 if(b_is_zero) {
     599           2 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero operand not allowed");
     600           2 :                         FREE_GMP_TEMP(arga_tmp);
     601           2 :                         FREE_GMP_TEMP(argb_tmp);
     602           2 :                         RETURN_FALSE;
     603             :                 }
     604             :         }
     605             : 
     606           8 :         INIT_GMP_NUM(gmpnum_result1);
     607           8 :         INIT_GMP_NUM(gmpnum_result2);
     608             : 
     609          16 :         if (use_ui && gmp_ui_op) {
     610           8 :                 if (allow_ui_return) {
     611           0 :                         long_result = gmp_ui_op(*gmpnum_result1, *gmpnum_result2, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg));
     612             :                 } else {
     613           8 :                         gmp_ui_op(*gmpnum_result1, *gmpnum_result2, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg));
     614             :                 }
     615             :         } else {
     616           0 :                 gmp_op(*gmpnum_result1, *gmpnum_result2, *gmpnum_a, *gmpnum_b);
     617             :         }
     618             : 
     619           8 :         FREE_GMP_TEMP(arga_tmp);
     620           8 :         FREE_GMP_TEMP(argb_tmp);
     621             : 
     622           8 :         array_init(return_value);
     623           8 :         ZEND_REGISTER_RESOURCE(&r, gmpnum_result1, le_gmp);
     624           8 :         add_index_resource(return_value, 0, Z_LVAL(r));
     625           8 :         if (use_ui && allow_ui_return) {
     626           0 :                 mpz_clear(*gmpnum_result2);
     627           0 :                 add_index_long(return_value, 1, long_result);
     628             :         } else {
     629           8 :                 ZEND_REGISTER_RESOURCE(&r, gmpnum_result2, le_gmp);
     630           8 :                 add_index_resource(return_value, 1, Z_LVAL(r));
     631             :         }
     632             : }
     633             : /* }}} */
     634             : 
     635             : /* {{{ _gmp_binary_ui_op
     636             :  */
     637        1049 : static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op)
     638             : {
     639             :         zval **a_arg, **b_arg;
     640             : 
     641        1049 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
     642           7 :                 return;
     643             :         }
     644             :         
     645        1042 :         gmp_zval_binary_ui_op(return_value, a_arg, b_arg, gmp_op, gmp_ui_op);
     646             : }
     647             : /* }}} */
     648             : 
     649             : /* Unary operations */
     650             : 
     651             : /* {{{ gmp_zval_unary_op
     652             :  */
     653          37 : static inline void gmp_zval_unary_op(zval *return_value, zval **a_arg, gmp_unary_op_t gmp_op TSRMLS_DC) 
     654             : {
     655             :         mpz_t *gmpnum_a, *gmpnum_result;
     656             :         int temp_a;
     657             :         
     658          37 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
     659             : 
     660          25 :         INIT_GMP_NUM(gmpnum_result);
     661          25 :         gmp_op(*gmpnum_result, *gmpnum_a);
     662             : 
     663          25 :         FREE_GMP_TEMP(temp_a);
     664          25 :         ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
     665             : }
     666             : /* }}} */
     667             : 
     668             : /* {{{ gmp_zval_unary_ui_op
     669             :  */
     670          11 : static inline void gmp_zval_unary_ui_op(zval *return_value, zval **a_arg, gmp_unary_ui_op_t gmp_op TSRMLS_DC)
     671             : {
     672             :         mpz_t *gmpnum_result;
     673             : 
     674          16 :         convert_to_long_ex(a_arg);
     675             : 
     676          11 :         INIT_GMP_NUM(gmpnum_result);
     677          11 :         gmp_op(*gmpnum_result, Z_LVAL_PP(a_arg));
     678             : 
     679          11 :         ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
     680          11 : }
     681             : /* }}} */
     682             : 
     683             : /* {{{ _gmp_unary_ui_op
     684             :    Execute GMP unary operation.
     685             : */
     686             : static inline void _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_ui_op_t gmp_op)
     687             : {
     688             :         zval **a_arg;
     689             : 
     690             :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
     691             :                 return;
     692             :         }
     693             : 
     694             :         gmp_zval_unary_ui_op(return_value, a_arg, gmp_op TSRMLS_CC);
     695             : }
     696             : /* }}} */
     697             : 
     698             : /* {{{ _gmp_unary_op
     699             :  */
     700          42 : static inline void _gmp_unary_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_op_t gmp_op)
     701             : {
     702             :         zval **a_arg;
     703             : 
     704          42 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
     705           5 :                 return;
     706             :         }
     707             :         
     708          37 :         gmp_zval_unary_op(return_value, a_arg, gmp_op TSRMLS_CC);
     709             : }
     710             : /* }}} */
     711             : 
     712             : /* {{{ _gmp_unary_opl
     713             :  */
     714             : static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t gmp_op)
     715             : {
     716             :         zval **a_arg;
     717             :         mpz_t *gmpnum_a;
     718             :         int temp_a;
     719             : 
     720             :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
     721             :                 return;
     722             :         }
     723             :         
     724             :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
     725             :         RETVAL_LONG(gmp_op(*gmpnum_a));
     726             :         FREE_GMP_TEMP(temp_a);
     727             : }
     728             : /* }}} */
     729             : 
     730             : /* {{{ _gmp_binary_opl
     731             :  */
     732          46 : static inline void _gmp_binary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_opl_t gmp_op)
     733             : {
     734             :         zval **a_arg, **b_arg;
     735             :         mpz_t *gmpnum_a, *gmpnum_b;
     736             :         int temp_a, temp_b;
     737             : 
     738          46 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
     739           6 :                 return;
     740             :         }
     741             : 
     742          40 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
     743          36 :         FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
     744             : 
     745          34 :         RETVAL_LONG(gmp_op(*gmpnum_a, *gmpnum_b));
     746             : 
     747          34 :         FREE_GMP_TEMP(temp_a);
     748          34 :         FREE_GMP_TEMP(temp_b);
     749             : }
     750             : /* }}} */
     751             : 
     752             : /* {{{ proto resource gmp_init(mixed number [, int base])
     753             :    Initializes GMP number */
     754         122 : ZEND_FUNCTION(gmp_init)
     755             : {
     756             :         zval **number_arg;
     757             :         mpz_t * gmpnumber;
     758         122 :         long base=0;
     759             : 
     760         122 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|l", &number_arg, &base) == FAILURE) {
     761           3 :                 return;
     762             :         }
     763             : 
     764         119 :         if (base && (base < 2 || base > MAX_BASE)) {
     765           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad base for conversion: %ld (should be between 2 and %d)", base, MAX_BASE);
     766           1 :                 RETURN_FALSE;
     767             :         }
     768             : 
     769         118 :         if (convert_to_gmp(&gmpnumber, number_arg, base TSRMLS_CC) == FAILURE) {
     770           5 :                 RETURN_FALSE;
     771             :         }
     772             : 
     773             :         /* Write your own code here to handle argument number. */
     774         113 :         ZEND_REGISTER_RESOURCE(return_value, gmpnumber, le_gmp);
     775             : }
     776             : /* }}} */
     777             : 
     778             : /* {{{ proto int gmp_intval(resource gmpnumber)
     779             :    Gets signed long value of GMP number */
     780          19 : ZEND_FUNCTION(gmp_intval)
     781             : {
     782             :         zval **gmpnumber_arg;
     783             :         mpz_t * gmpnum;
     784             : 
     785          19 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &gmpnumber_arg) == FAILURE){
     786           1 :                 return;
     787             :         }
     788             :         
     789          18 :         if (Z_TYPE_PP(gmpnumber_arg) == IS_RESOURCE) {
     790           8 :                 ZEND_FETCH_RESOURCE(gmpnum, mpz_t *, gmpnumber_arg, -1, GMP_RESOURCE_NAME, le_gmp);
     791           7 :                 RETVAL_LONG(mpz_get_si(*gmpnum));
     792             :         } else {
     793          31 :                 convert_to_long_ex(gmpnumber_arg);
     794          10 :                 RETVAL_LONG(Z_LVAL_PP(gmpnumber_arg));
     795             :         }
     796             : }
     797             : /* }}} */
     798             : 
     799             : /* {{{ proto string gmp_strval(resource gmpnumber [, int base])
     800             :    Gets string representation of GMP number  */
     801         345 : ZEND_FUNCTION(gmp_strval)
     802             : {
     803             :         zval **gmpnumber_arg;
     804             :         int num_len;
     805         345 :         long base = 10;
     806             :         mpz_t * gmpnum;
     807             :         char *out_string;
     808             :         int temp_a;
     809             : 
     810         345 :         if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "Z|l", &gmpnumber_arg, &base ) == FAILURE ) {
     811           5 :                 return;
     812             :         }
     813             : 
     814             : #if MAX_BASE == 62
     815             :         /* Although the maximum base in general in GMP >= 4.2 is 62, mpz_get_str()
     816             :          * is explicitly limited to -36 when dealing with negative bases. */
     817         340 :         if ((base < 2 && base > -2) || base > MAX_BASE || base < -36) {
     818           9 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad base for conversion: %ld (should be between 2 and %d or -2 and -36)", base, MAX_BASE);
     819             : #else
     820             :         if (base < 2 || base > MAX_BASE) {
     821             :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad base for conversion: %ld (should be between 2 and %d)", base, MAX_BASE);
     822             : #endif
     823           9 :                 RETURN_FALSE;
     824             :         }
     825             : 
     826         331 :         FETCH_GMP_ZVAL(gmpnum, gmpnumber_arg, temp_a);
     827             : 
     828         317 :         num_len = mpz_sizeinbase(*gmpnum, abs(base));
     829         317 :         out_string = emalloc(num_len+2);
     830         317 :         if (mpz_sgn(*gmpnum) < 0) {
     831          43 :                 num_len++;
     832             :         }
     833         317 :         mpz_get_str(out_string, base, *gmpnum);
     834             :         
     835         317 :         FREE_GMP_TEMP(temp_a);
     836             :         
     837             :         /* 
     838             :         From GMP documentation for mpz_sizeinbase():
     839             :         The returned value will be exact or 1 too big.  If base is a power of
     840             :         2, the returned value will always be exact.
     841             : 
     842             :         So let's check to see if we already have a \0 byte...
     843             :         */
     844             : 
     845         317 :         if (out_string[num_len-1] == '\0') {
     846          45 :                 num_len--;
     847             :         } else {
     848         272 :                 out_string[num_len] = '\0';
     849             :         }
     850         317 :         RETVAL_STRINGL(out_string, num_len, 0);
     851             : }
     852             : /* }}} */
     853             : 
     854             : /* {{{ proto resource gmp_add(resource a, resource b)
     855             :    Add a and b */
     856          15 : ZEND_FUNCTION(gmp_add)
     857             : {
     858          15 :         gmp_binary_ui_op(mpz_add, (gmp_binary_ui_op_t)mpz_add_ui);
     859          15 : }
     860             : /* }}} */
     861             : 
     862             : /* {{{ proto resource gmp_sub(resource a, resource b)
     863             :    Subtract b from a */
     864           9 : ZEND_FUNCTION(gmp_sub)
     865             : {
     866           9 :         gmp_binary_ui_op(mpz_sub, (gmp_binary_ui_op_t)mpz_sub_ui);
     867           9 : }
     868             : /* }}} */
     869             : 
     870             : /* {{{ proto resource gmp_mul(resource a, resource b)
     871             :    Multiply a and b */
     872         999 : ZEND_FUNCTION(gmp_mul)
     873             : {
     874         999 :         gmp_binary_ui_op(mpz_mul, (gmp_binary_ui_op_t)mpz_mul_ui);
     875         999 : }
     876             : /* }}} */
     877             : 
     878             : /* {{{ proto array gmp_div_qr(resource a, resource b [, int round])
     879             :    Divide a by b, returns quotient and reminder */
     880          15 : ZEND_FUNCTION(gmp_div_qr)
     881             : {
     882             :         zval **a_arg, **b_arg;
     883          15 :         long round = GMP_ROUND_ZERO;
     884             : 
     885          15 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|l", &a_arg, &b_arg, &round) == FAILURE) {
     886           2 :                 return;
     887             :         }
     888             : 
     889          13 :         switch (round) {
     890             :         case GMP_ROUND_ZERO:
     891           8 :                 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);
     892           8 :                 break;
     893             :         case GMP_ROUND_PLUSINF:
     894           2 :                 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);
     895           2 :                 break;
     896             :         case GMP_ROUND_MINUSINF:
     897           2 :                 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);
     898             :                 break;
     899             :         }
     900             :                                                            
     901             : }
     902             : /* }}} */
     903             : 
     904             : /* {{{ proto resource gmp_div_r(resource a, resource b [, int round])
     905             :    Divide a by b, returns reminder only */
     906          14 : ZEND_FUNCTION(gmp_div_r)
     907             : {
     908             :         zval **a_arg, **b_arg;
     909          14 :         long round = GMP_ROUND_ZERO;
     910             : 
     911          14 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|l", &a_arg, &b_arg, &round) == FAILURE) {
     912           2 :                 return;
     913             :         }
     914             : 
     915          12 :         switch (round) {
     916             :         case GMP_ROUND_ZERO:
     917           7 :                 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, 1 TSRMLS_CC);
     918           7 :                 break;
     919             :         case GMP_ROUND_PLUSINF:
     920           2 :                 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, 1 TSRMLS_CC);
     921           2 :                 break;
     922             :         case GMP_ROUND_MINUSINF:
     923           2 :                 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, 1 TSRMLS_CC);
     924             :                 break;
     925             :         }
     926             : }
     927             : /* }}} */
     928             : 
     929             : /* {{{ proto resource gmp_div_q(resource a, resource b [, int round])
     930             :    Divide a by b, returns quotient only */
     931          15 : ZEND_FUNCTION(gmp_div_q)
     932             : {
     933             :         zval **a_arg, **b_arg;
     934          15 :         long round = GMP_ROUND_ZERO;
     935             : 
     936          15 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|l", &a_arg, &b_arg, &round) == FAILURE) {
     937           2 :                 return;
     938             :         }
     939             : 
     940          13 :         switch (round) {
     941             :         case GMP_ROUND_ZERO:
     942           8 :                 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, 1 TSRMLS_CC);
     943           8 :                 break;
     944             :         case GMP_ROUND_PLUSINF:
     945           2 :                 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, 1 TSRMLS_CC);
     946           2 :                 break;
     947             :         case GMP_ROUND_MINUSINF:
     948           2 :                 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, 1 TSRMLS_CC);
     949             :                 break;
     950             :         }
     951             :                                                            
     952             : }
     953             : /* }}} */
     954             : 
     955             : /* {{{ proto resource gmp_mod(resource a, resource b)
     956             :    Computes a modulo b */
     957          26 : ZEND_FUNCTION(gmp_mod)
     958             : {
     959             :         zval **a_arg, **b_arg;
     960             : 
     961          26 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
     962           2 :                 return;
     963             :         }       
     964             : 
     965          24 :         gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_mod, (gmp_binary_ui_op_t)mpz_mod_ui, 1, 1, 0 TSRMLS_CC);
     966             : }
     967             : /* }}} */
     968             : 
     969             : /* {{{ proto resource gmp_divexact(resource a, resource b)
     970             :    Divide a by b using exact division algorithm */
     971           9 : ZEND_FUNCTION(gmp_divexact)
     972             : {
     973             :         zval **a_arg, **b_arg;
     974             : 
     975           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
     976           2 :                 return;
     977             :         }
     978             :         
     979           7 :         gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_divexact, NULL, 0, 1, 1 TSRMLS_CC);
     980             : }
     981             : /* }}} */
     982             : 
     983             : /* {{{ proto resource gmp_neg(resource a)
     984             :    Negates a number */
     985          11 : ZEND_FUNCTION(gmp_neg)
     986             : {
     987          11 :         gmp_unary_op(mpz_neg);
     988          11 : }
     989             : /* }}} */
     990             : 
     991             : /* {{{ proto resource gmp_abs(resource a)
     992             :    Calculates absolute value */
     993          12 : ZEND_FUNCTION(gmp_abs)
     994             : {
     995          12 :         gmp_unary_op(mpz_abs);
     996          12 : }
     997             : /* }}} */
     998             : 
     999             : /* {{{ proto resource gmp_fact(int a)
    1000             :    Calculates factorial function */
    1001          16 : ZEND_FUNCTION(gmp_fact)
    1002             : {
    1003             :         zval **a_arg;
    1004             :         mpz_t *gmpnum_tmp;
    1005             :         int temp_a;
    1006             : 
    1007          16 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
    1008           2 :                 return;
    1009             :         }
    1010             : 
    1011          14 :         if (Z_TYPE_PP(a_arg) == IS_RESOURCE) {
    1012           2 :                 FETCH_GMP_ZVAL(gmpnum_tmp, a_arg, temp_a);      /* no need to free this since it's IS_RESOURCE */
    1013           2 :                 if (mpz_sgn(*gmpnum_tmp) < 0) {
    1014           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0");
    1015           1 :                         RETURN_FALSE;
    1016             :                 }
    1017             :         } else {
    1018          39 :                 convert_to_long_ex(a_arg);
    1019          12 :                 if (Z_LVAL_PP(a_arg) < 0) {
    1020           2 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0");
    1021           2 :                         RETURN_FALSE;
    1022             :                 }
    1023             :         }
    1024             :                 
    1025          11 :         gmp_zval_unary_ui_op(return_value, a_arg, mpz_fac_ui TSRMLS_CC);
    1026             : }
    1027             : /* }}} */
    1028             : 
    1029             : /* {{{ proto resource gmp_pow(resource base, int exp)
    1030             :    Raise base to power exp */
    1031          18 : ZEND_FUNCTION(gmp_pow)
    1032             : {
    1033             :         zval **base_arg;
    1034             :         mpz_t *gmpnum_result, *gmpnum_base;
    1035          18 :         int use_ui = 0;
    1036             :         int temp_base;
    1037             :         long exp;
    1038             : 
    1039          18 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &base_arg, &exp) == FAILURE) {
    1040           5 :                 return;
    1041             :         }
    1042             : 
    1043          17 :         if (Z_TYPE_PP(base_arg) == IS_LONG && Z_LVAL_PP(base_arg) >= 0) {
    1044           4 :                 use_ui = 1;
    1045             :         } else {
    1046           9 :                 FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base);
    1047             :         }
    1048             : 
    1049          12 :         if (exp < 0) {
    1050           2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Negative exponent not supported");
    1051           2 :                 RETURN_FALSE;
    1052             :         }
    1053             :         
    1054          10 :         INIT_GMP_NUM(gmpnum_result);
    1055          10 :         if (use_ui) {
    1056           3 :                 mpz_ui_pow_ui(*gmpnum_result, Z_LVAL_PP(base_arg), exp);
    1057             :         } else {
    1058           7 :                 mpz_pow_ui(*gmpnum_result, *gmpnum_base, exp);
    1059           7 :                 FREE_GMP_TEMP(temp_base);
    1060             :         }
    1061          10 :         ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
    1062             : }
    1063             : /* }}} */
    1064             : 
    1065             : /* {{{ proto resource gmp_powm(resource base, resource exp, resource mod)
    1066             :    Raise base to power exp and take result modulo mod */
    1067          18 : ZEND_FUNCTION(gmp_powm)
    1068             : {
    1069             :         zval **base_arg, **exp_arg, **mod_arg;
    1070             :         mpz_t *gmpnum_base, *gmpnum_exp, *gmpnum_mod, *gmpnum_result;
    1071          18 :         int use_ui = 0;
    1072          18 :         int temp_base = 0, temp_exp = 0, temp_mod;
    1073             : 
    1074          18 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ", &base_arg, &exp_arg, &mod_arg) == FAILURE){
    1075           3 :                 return;
    1076             :         }
    1077             : 
    1078          15 :         FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base);
    1079             : 
    1080          20 :         if (Z_TYPE_PP(exp_arg) == IS_LONG && Z_LVAL_PP(exp_arg) >= 0) {
    1081           7 :                 use_ui = 1;
    1082             :         } else {
    1083           6 :                 FETCH_GMP_ZVAL(gmpnum_exp, exp_arg, temp_exp);
    1084           5 :                 if (mpz_sgn(*gmpnum_exp) < 0) {
    1085           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING,"Second parameter cannot be less than 0");
    1086           1 :                         RETURN_FALSE;
    1087             :                 }
    1088             :         }
    1089          11 :         FETCH_GMP_ZVAL(gmpnum_mod, mod_arg, temp_mod);
    1090             : 
    1091          10 :         if (!mpz_cmp_ui(*gmpnum_mod, 0)) {
    1092           0 :                 FREE_GMP_TEMP(temp_base);
    1093           0 :                 if (use_ui) {
    1094           0 :                         FREE_GMP_TEMP(temp_exp);
    1095             :                 }
    1096           0 :                 FREE_GMP_TEMP(temp_mod);
    1097           0 :                 RETURN_FALSE;
    1098             :         }
    1099             : 
    1100          10 :         INIT_GMP_NUM(gmpnum_result);
    1101          10 :         if (use_ui) {
    1102           7 :                 mpz_powm_ui(*gmpnum_result, *gmpnum_base, (unsigned long)Z_LVAL_PP(exp_arg), *gmpnum_mod);
    1103             :         } else {
    1104           3 :                 mpz_powm(*gmpnum_result, *gmpnum_base, *gmpnum_exp, *gmpnum_mod);
    1105           3 :                 FREE_GMP_TEMP(temp_exp);
    1106             :         }
    1107             : 
    1108          10 :         FREE_GMP_TEMP(temp_base);
    1109          10 :         FREE_GMP_TEMP(temp_mod);
    1110             : 
    1111          10 :         ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
    1112             : 
    1113             : }
    1114             : /* }}} */
    1115             : 
    1116             : /* {{{ proto resource gmp_sqrt(resource a)
    1117             :    Takes integer part of square root of a */
    1118          11 : ZEND_FUNCTION(gmp_sqrt)
    1119             : {
    1120             :         zval **a_arg;
    1121             :         mpz_t *gmpnum_a, *gmpnum_result;
    1122             :         int temp_a;
    1123             : 
    1124          11 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
    1125           2 :                 return;
    1126             :         }
    1127             :         
    1128           9 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1129             : 
    1130           8 :         if (mpz_sgn(*gmpnum_a) < 0) {
    1131           3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0");
    1132           3 :                 FREE_GMP_TEMP(temp_a);
    1133           3 :                 RETURN_FALSE;
    1134             :         }       
    1135             :         
    1136           5 :         INIT_GMP_NUM(gmpnum_result);
    1137           5 :         mpz_sqrt(*gmpnum_result, *gmpnum_a);
    1138           5 :         FREE_GMP_TEMP(temp_a);
    1139             : 
    1140           5 :         ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
    1141             : }
    1142             : /* }}} */
    1143             : 
    1144             : /* {{{ proto array gmp_sqrtrem(resource a)
    1145             :    Square root with remainder */
    1146          13 : ZEND_FUNCTION(gmp_sqrtrem)
    1147             : {
    1148             :         zval **a_arg;
    1149             :         mpz_t *gmpnum_a, *gmpnum_result1, *gmpnum_result2;
    1150             :         zval r;
    1151             :         int temp_a;
    1152             : 
    1153          13 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
    1154           1 :                 return;
    1155             :         }
    1156             : 
    1157          12 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1158             :         
    1159          11 :         if (mpz_sgn(*gmpnum_a) < 0) {
    1160           2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING,"Number has to be greater than or equal to 0");
    1161           2 :                 RETURN_FALSE;
    1162             :         }
    1163             :         
    1164           9 :         INIT_GMP_NUM(gmpnum_result1);
    1165           9 :         INIT_GMP_NUM(gmpnum_result2);
    1166             : 
    1167           9 :         mpz_sqrtrem(*gmpnum_result1, *gmpnum_result2, *gmpnum_a);
    1168           9 :         FREE_GMP_TEMP(temp_a);
    1169             : 
    1170           9 :         array_init(return_value);
    1171           9 :         ZEND_REGISTER_RESOURCE(&r, gmpnum_result1, le_gmp);
    1172           9 :         add_index_resource(return_value, 0, Z_LVAL(r));
    1173           9 :         ZEND_REGISTER_RESOURCE(&r, gmpnum_result2, le_gmp);
    1174           9 :         add_index_resource(return_value, 1, Z_LVAL(r));
    1175             : }
    1176             : /* }}} */
    1177             : 
    1178             : /* {{{ proto bool gmp_perfect_square(resource a)
    1179             :    Checks if a is an exact square */
    1180          13 : ZEND_FUNCTION(gmp_perfect_square)
    1181             : {
    1182             :         zval **a_arg;
    1183             :         mpz_t *gmpnum_a;
    1184             :         int temp_a;
    1185             : 
    1186          13 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
    1187           1 :                 return;
    1188             :         }
    1189             : 
    1190          12 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1191             : 
    1192          11 :         RETVAL_BOOL((mpz_perfect_square_p(*gmpnum_a)!=0));
    1193          11 :         FREE_GMP_TEMP(temp_a);
    1194             : }
    1195             : /* }}} */
    1196             : 
    1197             : /* {{{ proto int gmp_prob_prime(resource a[, int reps])
    1198             :    Checks if a is "probably prime" */
    1199          40 : ZEND_FUNCTION(gmp_prob_prime)
    1200             : {
    1201             :         zval **gmpnumber_arg;
    1202             :         mpz_t *gmpnum_a;
    1203          40 :         long reps = 10;
    1204             :         int temp_a;
    1205             : 
    1206          40 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|l", &gmpnumber_arg, &reps) == FAILURE) {
    1207           1 :                 return;
    1208             :         }
    1209             : 
    1210          39 :         FETCH_GMP_ZVAL(gmpnum_a, gmpnumber_arg, temp_a);
    1211             : 
    1212          38 :         RETVAL_LONG(mpz_probab_prime_p(*gmpnum_a, reps));
    1213          38 :         FREE_GMP_TEMP(temp_a);
    1214             : }
    1215             : /* }}} */
    1216             : 
    1217             : /* {{{ proto resource gmp_gcd(resource a, resource b)
    1218             :    Computes greatest common denominator (gcd) of a and b */
    1219          14 : ZEND_FUNCTION(gmp_gcd)
    1220             : {
    1221             :         zval **a_arg, **b_arg;
    1222             : 
    1223          14 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
    1224           3 :                 return;
    1225             :         }
    1226             : 
    1227          11 :         gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_gcd, (gmp_binary_ui_op_t)mpz_gcd_ui, 0, 0, 1 TSRMLS_CC);
    1228             : }
    1229             : /* }}} */
    1230             : 
    1231             : /* {{{ proto array gmp_gcdext(resource a, resource b)
    1232             :    Computes G, S, and T, such that AS + BT = G = `gcd' (A, B) */
    1233          15 : ZEND_FUNCTION(gmp_gcdext)
    1234             : {
    1235             :         zval **a_arg, **b_arg;
    1236             :         mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_t, *gmpnum_s, *gmpnum_g;
    1237             :         zval r;
    1238             :         int temp_a, temp_b;
    1239             : 
    1240          15 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
    1241           3 :                 return;
    1242             :         }
    1243             : 
    1244          12 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1245          11 :         FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
    1246             : 
    1247          10 :         INIT_GMP_NUM(gmpnum_g);
    1248          10 :         INIT_GMP_NUM(gmpnum_s);
    1249          10 :         INIT_GMP_NUM(gmpnum_t);
    1250             : 
    1251          10 :         mpz_gcdext(*gmpnum_g, *gmpnum_s, *gmpnum_t, *gmpnum_a, *gmpnum_b);
    1252          10 :         FREE_GMP_TEMP(temp_a);
    1253          10 :         FREE_GMP_TEMP(temp_b);
    1254             : 
    1255          10 :         array_init(return_value);
    1256             : 
    1257          10 :         ZEND_REGISTER_RESOURCE(&r, gmpnum_g, le_gmp);
    1258          10 :         add_assoc_resource(return_value, "g", Z_LVAL(r));
    1259          10 :         ZEND_REGISTER_RESOURCE(&r, gmpnum_s, le_gmp);
    1260          10 :         add_assoc_resource(return_value, "s", Z_LVAL(r));
    1261          10 :         ZEND_REGISTER_RESOURCE(&r, gmpnum_t, le_gmp);
    1262          10 :         add_assoc_resource(return_value, "t", Z_LVAL(r));
    1263             : }
    1264             : /* }}} */
    1265             : 
    1266             : /* {{{ proto resource gmp_invert(resource a, resource b)
    1267             :    Computes the inverse of a modulo b */
    1268          14 : ZEND_FUNCTION(gmp_invert)
    1269             : {
    1270             :         zval **a_arg, **b_arg;
    1271             :         mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result;
    1272             :         int temp_a, temp_b;
    1273             :         int res;
    1274             : 
    1275          14 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
    1276           2 :                 return;
    1277             :         }
    1278             : 
    1279          12 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1280          10 :         FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
    1281             : 
    1282           9 :         INIT_GMP_NUM(gmpnum_result);
    1283           9 :         res=mpz_invert(*gmpnum_result, *gmpnum_a, *gmpnum_b);
    1284           9 :         FREE_GMP_TEMP(temp_a);
    1285           9 :         FREE_GMP_TEMP(temp_b);
    1286           9 :         if (res) {
    1287           4 :                 ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
    1288             :         } else {
    1289           5 :                 FREE_GMP_NUM(gmpnum_result);
    1290           5 :                 RETURN_FALSE;
    1291             :         }
    1292             : }
    1293             : /* }}} */
    1294             : 
    1295             : /* {{{ proto int gmp_jacobi(resource a, resource b)
    1296             :    Computes Jacobi symbol */
    1297          23 : ZEND_FUNCTION(gmp_jacobi)
    1298             : {
    1299          23 :         gmp_binary_opl(mpz_jacobi);
    1300          23 : }
    1301             : /* }}} */
    1302             : 
    1303             : /* {{{ proto int gmp_legendre(resource a, resource b)
    1304             :    Computes Legendre symbol */
    1305          23 : ZEND_FUNCTION(gmp_legendre)
    1306             : {
    1307          23 :         gmp_binary_opl(mpz_legendre);
    1308          23 : }
    1309             : /* }}} */
    1310             : 
    1311             : /* {{{ proto int gmp_cmp(resource a, resource b)
    1312             :    Compares two numbers */
    1313          12 : ZEND_FUNCTION(gmp_cmp)
    1314             : {
    1315             :         zval **a_arg, **b_arg;
    1316             :         mpz_t *gmpnum_a, *gmpnum_b;
    1317          12 :         int use_si = 0, res;
    1318             :         int temp_a, temp_b;
    1319             : 
    1320          12 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
    1321           3 :                 return;
    1322             :         }
    1323             : 
    1324           9 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1325             : 
    1326           8 :         if (Z_TYPE_PP(b_arg) == IS_LONG) {
    1327           4 :                 use_si = 1;
    1328             :         } else {
    1329           4 :                 FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
    1330             :         }
    1331             : 
    1332           8 :         if (use_si) {
    1333           4 :                 res = mpz_cmp_si(*gmpnum_a, Z_LVAL_PP(b_arg));
    1334             :         } else {
    1335           4 :                 res = mpz_cmp(*gmpnum_a, *gmpnum_b);
    1336           4 :                 FREE_GMP_TEMP(temp_b);
    1337             :         }
    1338           8 :         FREE_GMP_TEMP(temp_a);
    1339             :         
    1340           8 :         RETURN_LONG(res);
    1341             : }
    1342             : /* }}} */
    1343             : 
    1344             : /* {{{ proto int gmp_sign(resource a)
    1345             :    Gets the sign of the number */
    1346          10 : ZEND_FUNCTION(gmp_sign)
    1347             : {
    1348             :         zval **a_arg;
    1349             :         mpz_t *gmpnum_a;
    1350             :         int temp_a;
    1351             : 
    1352          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
    1353           2 :                 return;
    1354             :         }
    1355             :         
    1356           8 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1357             : 
    1358           6 :         RETVAL_LONG(mpz_sgn(*gmpnum_a));
    1359           6 :         FREE_GMP_TEMP(temp_a);
    1360             : }
    1361             : /* }}} */
    1362             : 
    1363             : /* {{{ proto resource gmp_random([int limiter])
    1364             :    Gets random number */
    1365          10 : ZEND_FUNCTION(gmp_random)
    1366             : {
    1367          10 :         long limiter = 20;
    1368             :         mpz_t *gmpnum_result;
    1369             : 
    1370          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &limiter) == FAILURE) {
    1371           4 :                 return;
    1372             :         }
    1373             : 
    1374           6 :         INIT_GMP_NUM(gmpnum_result);
    1375             : 
    1376           6 :         if (!GMPG(rand_initialized)) {
    1377             :                 /* Initialize */
    1378           1 :                 gmp_randinit_lc_2exp_size(GMPG(rand_state), 32L);
    1379             : 
    1380             :                 /* Seed */
    1381           1 :                 gmp_randseed_ui(GMPG(rand_state), GENERATE_SEED());
    1382             : 
    1383           1 :                 GMPG(rand_initialized) = 1;
    1384             :         }
    1385             : #ifdef GMP_LIMB_BITS
    1386           6 :         mpz_urandomb(*gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * GMP_LIMB_BITS);
    1387             : #else
    1388             :         mpz_urandomb(*gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * __GMP_BITS_PER_MP_LIMB);
    1389             : #endif
    1390           6 :         ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
    1391             : }
    1392             : /* }}} */
    1393             : 
    1394             : /* {{{ proto resource gmp_and(resource a, resource b)
    1395             :    Calculates logical AND of a and b */
    1396          13 : ZEND_FUNCTION(gmp_and)
    1397             : {
    1398          13 :         gmp_binary_op(mpz_and);
    1399          13 : }
    1400             : /* }}} */
    1401             : 
    1402             : /* {{{ proto resource gmp_or(resource a, resource b)
    1403             :    Calculates logical OR of a and b */
    1404          13 : ZEND_FUNCTION(gmp_or)
    1405             : {
    1406          13 :         gmp_binary_op(mpz_ior);
    1407          13 : }
    1408             : /* }}} */
    1409             : 
    1410             : /* {{{ proto resource gmp_com(resource a)
    1411             :    Calculates one's complement of a */
    1412          11 : ZEND_FUNCTION(gmp_com)
    1413             : {
    1414          11 :         gmp_unary_op(mpz_com);
    1415          11 : }
    1416             : /* }}} */
    1417             : 
    1418             : /* {{{ proto resource gmp_nextprime(resource a)
    1419             :    Finds next prime of a */
    1420           8 : ZEND_FUNCTION(gmp_nextprime)
    1421             : {
    1422           8 :    gmp_unary_op(mpz_nextprime);
    1423           8 : }
    1424             : /* }}} */
    1425             : 
    1426             : /* {{{ proto resource gmp_xor(resource a, resource b)
    1427             :    Calculates logical exclusive OR of a and b */
    1428          13 : ZEND_FUNCTION(gmp_xor)
    1429             : {
    1430             :         /* use formula: a^b = (a|b)&^(a&b) */
    1431             :         zval **a_arg, **b_arg;
    1432             :         mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result, *gmpnum_t;
    1433             :         int temp_a, temp_b;
    1434             : 
    1435          13 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
    1436           2 :                 return;
    1437             :         }
    1438             : 
    1439          11 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1440           8 :         FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
    1441             : 
    1442           7 :         INIT_GMP_NUM(gmpnum_result);
    1443           7 :         INIT_GMP_NUM(gmpnum_t);
    1444             : 
    1445           7 :         mpz_and(*gmpnum_t, *gmpnum_a, *gmpnum_b);
    1446           7 :         mpz_com(*gmpnum_t, *gmpnum_t);
    1447             : 
    1448           7 :         mpz_ior(*gmpnum_result, *gmpnum_a, *gmpnum_b);
    1449           7 :         mpz_and(*gmpnum_result, *gmpnum_result, *gmpnum_t);
    1450             : 
    1451           7 :         FREE_GMP_NUM(gmpnum_t);
    1452             : 
    1453           7 :         FREE_GMP_TEMP(temp_a);
    1454           7 :         FREE_GMP_TEMP(temp_b);
    1455           7 :         ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
    1456             : }
    1457             : /* }}} */
    1458             : 
    1459             : /* {{{ proto void gmp_setbit(resource &a, int index[, bool set_clear])
    1460             :    Sets or clear bit in a */
    1461          15 : ZEND_FUNCTION(gmp_setbit)
    1462             : {
    1463             :         zval **a_arg;
    1464             :         long index;
    1465          15 :         zend_bool set = 1;
    1466             :         mpz_t *gmpnum_a;
    1467             : 
    1468          15 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl|b", &a_arg, &index, &set) == FAILURE) {
    1469           4 :                 return;
    1470             :         }
    1471             : 
    1472          11 :         ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp);
    1473             : 
    1474          10 :         if (index < 0) {
    1475           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Index must be greater than or equal to zero");
    1476           1 :                 return;
    1477             :         }
    1478             : 
    1479           9 :         if (set) {
    1480           7 :                 mpz_setbit(*gmpnum_a, index);
    1481             :         } else {
    1482           2 :                 mpz_clrbit(*gmpnum_a, index);
    1483             :         }
    1484             : }
    1485             : /* }}} */
    1486             : 
    1487             : /* {{{ proto void gmp_clrbit(resource &a, int index)
    1488             :    Clears bit in a */
    1489          12 : ZEND_FUNCTION(gmp_clrbit)
    1490             : {
    1491             :         zval **a_arg;
    1492             :         long index;
    1493             :         mpz_t *gmpnum_a;
    1494             : 
    1495          12 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &index) == FAILURE){
    1496           3 :                 return;
    1497             :         }
    1498             : 
    1499           9 :         ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp);
    1500             : 
    1501           8 :         if (index < 0) {
    1502           2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Index must be greater than or equal to zero");
    1503           2 :                 return;
    1504             :         }
    1505             : 
    1506           6 :         mpz_clrbit(*gmpnum_a, index);
    1507             : }
    1508             : /* }}} */
    1509             : 
    1510             : /* {{{ proto bool gmp_testbit(resource a, int index)
    1511             :    Tests if bit is set in a */
    1512          12 : ZEND_FUNCTION(gmp_testbit)
    1513             : {
    1514             :         zval **a_arg;
    1515             :         long index;
    1516             :         mpz_t *gmpnum_a;
    1517             : 
    1518          12 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &index) == FAILURE){
    1519           0 :                 return;
    1520             :         }
    1521             : 
    1522          12 :         ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp);
    1523             : 
    1524          12 :         if (index < 0) {
    1525           2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Index must be greater than or equal to zero");
    1526           2 :                 RETURN_FALSE;
    1527             :         }
    1528             : 
    1529          10 :         if (mpz_tstbit(*gmpnum_a, index)) {
    1530           4 :                 RETURN_TRUE;
    1531             :         }
    1532             : 
    1533           6 :         RETURN_FALSE;
    1534             : }
    1535             : /* }}} */
    1536             : 
    1537             : /* {{{ proto int gmp_popcount(resource a)
    1538             :    Calculates the population count of a */
    1539           8 : ZEND_FUNCTION(gmp_popcount)
    1540             : {
    1541             :         zval **a_arg;
    1542             :         mpz_t *gmpnum_a;
    1543             :         int temp_a;
    1544             : 
    1545           8 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
    1546           1 :                 return;
    1547             :         }
    1548             :         
    1549           7 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1550             : 
    1551           6 :         RETVAL_LONG(mpz_popcount(*gmpnum_a));
    1552           6 :         FREE_GMP_TEMP(temp_a);
    1553             : }
    1554             : /* }}} */
    1555             : 
    1556             : /* {{{ proto int gmp_hamdist(resource a, resource b)
    1557             :    Calculates hamming distance between a and b */
    1558          12 : ZEND_FUNCTION(gmp_hamdist)
    1559             : {
    1560             :         zval **a_arg, **b_arg;
    1561             :         mpz_t *gmpnum_a, *gmpnum_b;
    1562             :         int temp_a, temp_b;
    1563             : 
    1564          12 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
    1565           2 :                 return;
    1566             :         }
    1567             : 
    1568          10 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1569           8 :         FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
    1570             : 
    1571           7 :         RETVAL_LONG(mpz_hamdist(*gmpnum_a, *gmpnum_b));
    1572           7 :         FREE_GMP_TEMP(temp_a);
    1573           7 :         FREE_GMP_TEMP(temp_b);
    1574             : }
    1575             : /* }}} */
    1576             : 
    1577             : /* {{{ proto int gmp_scan0(resource a, int start)
    1578             :    Finds first zero bit */
    1579           9 : ZEND_FUNCTION(gmp_scan0)
    1580             : {
    1581             :         zval **a_arg;
    1582             :         mpz_t *gmpnum_a;
    1583             :         int temp_a;
    1584             :         long start;
    1585             : 
    1586           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &start) == FAILURE){
    1587           2 :                 return;
    1588             :         }
    1589             : 
    1590           7 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1591             : 
    1592           6 :         if (start < 0) {
    1593           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Starting index must be greater than or equal to zero");
    1594           1 :                 RETURN_FALSE;
    1595             :         }
    1596             : 
    1597           5 :         RETVAL_LONG(mpz_scan0(*gmpnum_a, start));
    1598           5 :         FREE_GMP_TEMP(temp_a);
    1599             : }
    1600             : /* }}} */
    1601             : 
    1602             : /* {{{ proto int gmp_scan1(resource a, int start)
    1603             :    Finds first non-zero bit */
    1604           9 : ZEND_FUNCTION(gmp_scan1)
    1605             : {
    1606             :         zval **a_arg;
    1607             :         mpz_t *gmpnum_a;
    1608             :         int temp_a;
    1609             :         long start;
    1610             : 
    1611           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &start) == FAILURE){
    1612           2 :                 return;
    1613             :         }
    1614             : 
    1615           7 :         FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
    1616           6 :         if (start < 0) {
    1617           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Starting index must be greater than or equal to zero");
    1618           1 :                 RETURN_FALSE;
    1619             :         }
    1620             : 
    1621           5 :         RETVAL_LONG(mpz_scan1(*gmpnum_a, start));
    1622           5 :         FREE_GMP_TEMP(temp_a);
    1623             : }
    1624             : /* }}} */
    1625             : 
    1626             : /* {{{ _php_gmpnum_free
    1627             :  */
    1628        2746 : static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc TSRMLS_DC)
    1629             : {
    1630        2746 :         mpz_t *gmpnum = (mpz_t *)rsrc->ptr;
    1631             : 
    1632        2746 :         FREE_GMP_NUM(gmpnum);
    1633        2746 : }
    1634             : /* }}} */
    1635             : 
    1636             : #endif  /* HAVE_GMP */
    1637             : 
    1638             : /*
    1639             :  * Local variables:
    1640             :  * tab-width: 4
    1641             :  * c-basic-offset: 4
    1642             :  * End:
    1643             :  * vim600: noet sw=4 ts=4 fdm=marker
    1644             :  * vim<600: noet sw=4 ts=4
    1645             :  */

Generated by: LCOV version 1.10

Generated at Sat, 13 Sep 2014 16:24:25 +0000 (5 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.