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

LTP GCOV extension - code coverage report
Current view: directory - gmp - gmp.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 508
Code covered: 94.7 % Executed lines: 481
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:00 +0000 (3 days ago)

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