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