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-23 Instrumented lines: 511
Code covered: 94.9 % Executed lines: 485
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:30 +0000 (33 hours ago)

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