cvs: php4 /ext/gmp Makefile.in README TODO config.m4 gmp.c php_gmp.h

From: Date: Sun, 26 Nov 2000 18:36:17 +0000
Subject: cvs: php4 /ext/gmp Makefile.in README TODO config.m4 gmp.c php_gmp.h
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-2797@lists.php.net to get a copy of this message
stas Sun Nov 26 10:36:17 2000 EDT Added files: /php4/ext/gmp Makefile.in README TODO config.m4 gmp.c php_gmp.h Log: GNU GMP - arbitrary precision nubers library

Index: php4/ext/gmp/Makefile.in +++ php4/ext/gmp/Makefile.in # $Id: Makefile.in,v 1.1 2000/11/26 18:36:16 stas Exp $ LTLIBRARY_NAME = libgmp.la LTLIBRARY_SOURCES = gmp.c LTLIBRARY_SHARED_NAME = gmp.la LTLIBRARY_LIBADD = $(GMP_LIBADD) LTLIBRARY_SHARED_LIBADD = $(GMP_SHARED_LIBADD) include $(top_srcdir)/build/dynlib.mk Index: php4/ext/gmp/config.m4 +++ php4/ext/gmp/config.m4 dnl $Id: config.m4,v 1.1 2000/11/26 18:36:16 stas Exp $ dnl config.m4 for extension gmp dnl If your extension references something external, use with: PHP_ARG_WITH(gmp, for gmp support, dnl Make sure that the comment is aligned: [ --with-gmp Include gmp support]) if test "$PHP_GMP" != "no"; then for i in /usr/local /usr $PHP_GMP; do if test -f $i/include/gmp.h; then GMP_DIR=$i fi done if test -z "$GMP_DIR"; then AC_MSG_ERROR(Unable to locate gmp.h) fi AC_ADD_INCLUDE($GMP_DIR/include) PHP_EXTENSION(gmp, $ext_shared) AC_DEFINE(HAVE_GMP, 1, [ ]) AC_ADD_LIBRARY_WITH_PATH(gmp, $GMP_DIR/lib) fi Index: php4/ext/gmp/gmp.c +++ php4/ext/gmp/gmp.c /* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Stanislav Malyshev <stas@php.net> | +----------------------------------------------------------------------+ */ #include "php.h" #include "php_ini.h" #include "php_gmp.h" #include "ext/standard/info.h" /* You should tweak config.m4 so this symbol (or some else suitable) gets defined. */ #if HAVE_GMP #include <gmp.h> /* If you declare any globals in php_gmp.h uncomment this: ZEND_DECLARE_MODULE_GLOBALS(gmp) */ /* True global resources - no need for thread safety here */ static int le_gmp; static unsigned char first_of_two_force_ref[] = { 2, BYREF_FORCE, BYREF_NONE }; /* Every user visible function must have an entry in gmp_functions[]. */ function_entry gmp_functions[] = { ZEND_FE(gmp_init, NULL) ZEND_FE(gmp_intval, NULL) ZEND_FE(gmp_strval, NULL) ZEND_FE(gmp_add, NULL) ZEND_FE(gmp_sub, NULL) ZEND_FE(gmp_mul, NULL) ZEND_FE(gmp_div_qr, NULL) ZEND_FE(gmp_div_q, NULL) ZEND_FE(gmp_div_r, NULL) ZEND_FALIAS(gmp_div, gmp_div_q, NULL) ZEND_FE(gmp_mod, NULL) ZEND_FE(gmp_divexact, NULL) ZEND_FE(gmp_neg, NULL) ZEND_FE(gmp_abs, NULL) ZEND_FE(gmp_fact, NULL) ZEND_FE(gmp_sqrt, NULL) ZEND_FE(gmp_sqrtrem, NULL) ZEND_FE(gmp_pow, NULL) ZEND_FE(gmp_powm, NULL) ZEND_FE(gmp_perfect_square, NULL) ZEND_FE(gmp_prob_prime, NULL) ZEND_FE(gmp_gcd, NULL) ZEND_FE(gmp_gcdext, NULL) ZEND_FE(gmp_invert, NULL) ZEND_FE(gmp_jacobi, NULL) ZEND_FE(gmp_legendre, NULL) ZEND_FE(gmp_cmp, NULL) ZEND_FE(gmp_sign, NULL) ZEND_FE(gmp_random, NULL) ZEND_FE(gmp_and, NULL) ZEND_FE(gmp_or, NULL) ZEND_FE(gmp_com, NULL) ZEND_FE(gmp_xor, NULL) ZEND_FE(gmp_setbit, first_of_two_force_ref) ZEND_FE(gmp_clrbit, first_of_two_force_ref) {NULL, NULL, NULL} /* Must be the last line in gmp_functions[] */ }; zend_module_entry gmp_module_entry = { "gmp", gmp_functions, ZEND_MINIT(gmp), ZEND_MSHUTDOWN(gmp), NULL, /* Replace with NULL if there's nothing to do at request start */ NULL, /* Replace with NULL if there's nothing to do at request end */ ZEND_MINFO(gmp), STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_GMP ZEND_GET_MODULE(gmp) #endif static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc); #define GMP_RESOURCE_NAME "GMP integer" #define GMP_ROUND_ZERO 0 #define GMP_ROUND_PLUSINF 1 #define GMP_ROUND_MINUSINF 2 ZEND_MINIT_FUNCTION(gmp) { /* Remove comments if you have entries in php.ini REGISTER_INI_ENTRIES(); */ le_gmp = zend_register_list_destructors_ex(_php_gmpnum_free, NULL, GMP_RESOURCE_NAME, module_number); REGISTER_LONG_CONSTANT("GMP_ROUND_ZERO", GMP_ROUND_ZERO, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("GMP_ROUND_PLUSINF", GMP_ROUND_PLUSINF, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("GMP_ROUND_MINUSINF", GMP_ROUND_MINUSINF, CONST_CS | CONST_PERSISTENT); return SUCCESS; } ZEND_MSHUTDOWN_FUNCTION(gmp) { /* Remove comments if you have entries in php.ini UNREGISTER_INI_ENTRIES(); */ return SUCCESS; } ZEND_MINFO_FUNCTION(gmp) { php_info_print_table_start(); php_info_print_table_header(2, "gmp support", "enabled"); php_info_print_table_end(); /* Remove comments if you have entries in php.ini DISPLAY_INI_ENTRIES(); */ } /* Fetch zval to be GMP number. Initially, zval can be also number or string */ #define FETCH_GMP_ZVAL(gmpnumber, zval) \ if(Z_TYPE_PP(zval) == IS_RESOURCE) { \ ZEND_FETCH_RESOURCE(gmpnumber, mpz_t *, zval, -1, GMP_RESOURCE_NAME, le_gmp);\ } else {\ convert_to_gmp(&gmpnumber,zval);\ ZEND_REGISTER_RESOURCE(NULL, gmpnumber, le_gmp);\ } /* create a new initialized GMP number */ #define INIT_GMP_NUM(gmpnumber) { gmpnumber=emalloc(sizeof(mpz_t)); mpz_init(*gmpnumber); } #define FREE_GMP_NUM(gmpnumber) { mpz_clear(*gmpnumber); efree(gmpnumber); } /* Convert zval to be gmp number */ static int convert_to_gmp(mpz_t * *gmpnumber, zval **val) { int ret = 0; *gmpnumber = emalloc(sizeof(mpz_t)); switch(Z_TYPE_PP(val)) { case IS_LONG: case IS_BOOL: case IS_CONSTANT: { convert_to_long_ex(val); mpz_init_set_si(**gmpnumber, Z_LVAL_PP(val)); } break; case IS_STRING: { char *numstr = Z_STRVAL_PP(val); if(numstr[0] == '0' && (numstr[1] == 'x' || numstr[1] == 'X')) { ret = mpz_init_set_str(**gmpnumber, numstr+2, 16); } else { ret = mpz_init_set_str(**gmpnumber, numstr, 10); } } break; default: zend_error(E_WARNING,"Unable to convert variable to GMP - wrong type"); return FAILURE; } return ret?FAILURE:SUCCESS; } typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr); typedef void (*gmp_unary_ui_op_t)(mpz_ptr, unsigned long); typedef void (*gmp_binary_op_t)(mpz_ptr, mpz_srcptr, mpz_srcptr); typedef unsigned long (*gmp_binary_ui_op_t)(mpz_ptr, mpz_srcptr, unsigned long); typedef void (*gmp_binary_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); typedef unsigned long (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long); #define gmp_zval_binary_ui_op(r,a,b,o,u) gmp_zval_binary_ui_op_ex(r,a,b,o,u,0) #define gmp_zval_binary_ui_op2(r,a,b,o,u) gmp_zval_binary_ui_op2_ex(r,a,b,o,u,0) #define gmp_binary_ui_op(op,uop) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop) #define gmp_binary_op(op) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, NULL) /* Unary operations */ #define gmp_unary_op(op) _gmp_unary_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) #define gmp_unary_ui_op(op) _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) /* Execute GMP binary operation. May return GMP resource or long if operation allows this */ 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) { mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result; unsigned long long_result; int use_ui=0; FETCH_GMP_ZVAL(gmpnum_a, a_arg); if(gmp_ui_op && Z_TYPE_PP(b_arg) == IS_LONG && Z_LVAL_PP(b_arg) >= 0) { use_ui=1; } else { FETCH_GMP_ZVAL(gmpnum_b, b_arg); } INIT_GMP_NUM(gmpnum_result); if(use_ui && gmp_ui_op) { if(allow_ui_return) { long_result = gmp_ui_op(*gmpnum_result, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg)); } else { gmp_ui_op(*gmpnum_result, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg)); } } else { gmp_op(*gmpnum_result, *gmpnum_a, *gmpnum_b); } if(use_ui && allow_ui_return) { FREE_GMP_NUM(gmpnum_result); RETURN_LONG((long)long_result); } else { ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } } /* Execute GMP binary operation which returns 2 values. May return GMP resources or longs if operation allows this. */ 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) { mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result1, *gmpnum_result2; zval r; int use_ui=0; unsigned long long_result; FETCH_GMP_ZVAL(gmpnum_a, a_arg); if(gmp_ui_op && Z_TYPE_PP(b_arg) == IS_LONG && Z_LVAL_PP(b_arg) >= 0) { /* use _ui function */ use_ui=1; } else { FETCH_GMP_ZVAL(gmpnum_b, b_arg); } INIT_GMP_NUM(gmpnum_result1); INIT_GMP_NUM(gmpnum_result2); if(use_ui && gmp_ui_op) { if(allow_ui_return) { long_result = gmp_ui_op(*gmpnum_result1, *gmpnum_result2, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg)); } else { gmp_ui_op(*gmpnum_result1, *gmpnum_result2, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg)); } } else { gmp_op(*gmpnum_result1, *gmpnum_result2, *gmpnum_a, *gmpnum_b); } array_init(return_value); ZEND_REGISTER_RESOURCE(&r, gmpnum_result1, le_gmp); add_index_resource(return_value, 0, Z_LVAL(r)); if(use_ui && allow_ui_return) { mpz_clear(*gmpnum_result2); add_index_long(return_value, 1, long_result); } else { ZEND_REGISTER_RESOURCE(&r, gmpnum_result2, le_gmp); add_index_resource(return_value, 1, Z_LVAL(r)); } } static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op) { zval **a_arg, **b_arg; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){ WRONG_PARAM_COUNT; } gmp_zval_binary_ui_op(return_value,a_arg,b_arg,gmp_op,gmp_ui_op); } /* Unary operations */ static inline void gmp_zval_unary_op(zval *return_value, zval **a_arg, gmp_unary_op_t gmp_op) { mpz_t *gmpnum_a, *gmpnum_result; FETCH_GMP_ZVAL(gmpnum_a, a_arg); INIT_GMP_NUM(gmpnum_result); gmp_op(*gmpnum_result, *gmpnum_a); ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } static inline void gmp_zval_unary_ui_op(zval *return_value, zval **a_arg, gmp_unary_ui_op_t gmp_op) { mpz_t *gmpnum_result; convert_to_long_ex(a_arg); INIT_GMP_NUM(gmpnum_result); gmp_op(*gmpnum_result, Z_LVAL_PP(a_arg)); ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } /* Execute GMP unary operation. */ static inline void _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_ui_op_t gmp_op) { zval **a_arg; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){ WRONG_PARAM_COUNT; } gmp_zval_unary_ui_op(return_value,a_arg,gmp_op); } static inline void _gmp_unary_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_op_t gmp_op) { zval **a_arg; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){ WRONG_PARAM_COUNT; } gmp_zval_unary_op(return_value,a_arg,gmp_op); } /* Remove the following function when you have succesfully modified config.m4 so that your module can be compiled into PHP, it exists only for testing purposes. */ /* {{{ proto resource gmp_init(mixed number) Initialize GMP number */ ZEND_FUNCTION(gmp_init) { zval **number_arg; mpz_t * gmpnumber; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &number_arg) == FAILURE){ WRONG_PARAM_COUNT; } if(convert_to_gmp(&gmpnumber,number_arg) == FAILURE) { RETURN_FALSE; } /* Write your own code here to handle argument number. */ ZEND_REGISTER_RESOURCE(return_value, gmpnumber, le_gmp); } /* }}} */ /* {{{ proto int gmp_intval(resource gmpnumber) Get signed long value of GMP number */ ZEND_FUNCTION(gmp_intval) { zval **gmpnumber_arg; mpz_t * gmpnum; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &gmpnumber_arg) == FAILURE){ WRONG_PARAM_COUNT; } if(Z_TYPE_PP(gmpnumber_arg) == IS_RESOURCE) { ZEND_FETCH_RESOURCE(gmpnum, mpz_t *, gmpnumber_arg, -1, GMP_RESOURCE_NAME, le_gmp); RETVAL_LONG(mpz_get_si(*gmpnum)); } else { convert_to_long_ex(gmpnumber_arg); RETVAL_LONG(Z_LVAL_PP(gmpnumber_arg)); } } /* }}} */ /* {{{ proto string gmp_strval(resource gmpnumber [, int base]) Get string representation of GMP number */ ZEND_FUNCTION(gmp_strval) { zval **gmpnumber_arg, **base_arg; int base, num_len, argc; mpz_t * gmpnum; char *out_string; argc = ZEND_NUM_ARGS(); if (argc < 1 || argc > 2 || zend_get_parameters_ex(argc, &gmpnumber_arg, &base_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum, gmpnumber_arg); switch (argc) { case 2: convert_to_long_ex(base_arg); base = Z_LVAL_PP(base_arg); break; case 1: base = 10; break; } num_len = mpz_sizeinbase(*gmpnum, base); out_string = emalloc(num_len+2); if(mpz_sgn(*gmpnum) < 0) { num_len++; } mpz_get_str(out_string, base, *gmpnum); RETVAL_STRINGL(out_string, num_len, 0); } /* }}} */ /* {{{ proto resource gmp_add(resource a, resource b) Add a and b */ ZEND_FUNCTION(gmp_add) { gmp_binary_ui_op(mpz_add, (gmp_binary_ui_op_t)mpz_add_ui); } /* }}} */ /* {{{ proto resource gmp_sub(resource a, resource b) Subtract b from a */ ZEND_FUNCTION(gmp_sub) { gmp_binary_ui_op(mpz_sub, (gmp_binary_ui_op_t)mpz_sub_ui); } /* }}} */ /* {{{ proto resource gmp_mul(resource a, resource b) Multiply a and b */ ZEND_FUNCTION(gmp_mul) { gmp_binary_ui_op(mpz_mul, (gmp_binary_ui_op_t)mpz_mul_ui); } /* }}} */ /* {{{ proto array gmp_div_qr(resource a, resource b [, int round]) Divide a by b, return quotient and reminder. */ ZEND_FUNCTION(gmp_div_qr) { zval **a_arg, **b_arg, **round_arg; int round, argc; argc = ZEND_NUM_ARGS(); if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &a_arg, &b_arg, &round_arg) == FAILURE){ WRONG_PARAM_COUNT; } switch (argc) { case 3: convert_to_long_ex(round_arg); round = Z_LVAL_PP(round_arg); break; case 2: round = GMP_ROUND_ZERO; break; } switch(round) { case GMP_ROUND_ZERO: gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_tdiv_qr, (gmp_binary_ui_op2_t)mpz_tdiv_qr_ui); break; case GMP_ROUND_PLUSINF: gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_cdiv_qr, (gmp_binary_ui_op2_t)mpz_cdiv_qr_ui); break; case GMP_ROUND_MINUSINF: gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_fdiv_qr, (gmp_binary_ui_op2_t)mpz_fdiv_qr_ui); break; } } /* }}} */ /* {{{ proto array gmp_div_r(resource a, resource b [, int round]) Divide a by b, return reminder only */ ZEND_FUNCTION(gmp_div_r) { zval **a_arg, **b_arg, **round_arg; int round, argc; argc = ZEND_NUM_ARGS(); if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &a_arg, &b_arg, &round_arg) == FAILURE){ WRONG_PARAM_COUNT; } switch (argc) { case 3: convert_to_long_ex(round_arg); round = Z_LVAL_PP(round_arg); break; case 2: round = GMP_ROUND_ZERO; break; } switch(round) { case GMP_ROUND_ZERO: 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); break; case GMP_ROUND_PLUSINF: 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); break; case GMP_ROUND_MINUSINF: 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); break; } } /* }}} */ /* {{{ proto array gmp_div_q(resource a, resource b [, int round]) Divide a by b, return quotient only */ ZEND_FUNCTION(gmp_div_q) { zval **a_arg, **b_arg, **round_arg; int round, argc; argc = ZEND_NUM_ARGS(); if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &a_arg, &b_arg, &round_arg) == FAILURE){ WRONG_PARAM_COUNT; } switch (argc) { case 3: convert_to_long_ex(round_arg); round = Z_LVAL_PP(round_arg); break; case 2: round = GMP_ROUND_ZERO; break; } switch(round) { case GMP_ROUND_ZERO: gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_q, (gmp_binary_ui_op_t)mpz_tdiv_q_ui); break; case GMP_ROUND_PLUSINF: gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_q, (gmp_binary_ui_op_t)mpz_cdiv_q_ui); break; case GMP_ROUND_MINUSINF: gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_q, (gmp_binary_ui_op_t)mpz_fdiv_q_ui); break; } } /* }}} */ /* {{{ proto resource gmp_mod(resource a, resource b) Compute a modulo b */ ZEND_FUNCTION(gmp_mod) { zval **a_arg, **b_arg; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){ WRONG_PARAM_COUNT; } gmp_zval_binary_ui_op_ex(return_value,a_arg,b_arg,mpz_mod,(gmp_binary_ui_op_t)mpz_mod_ui,1); } /* }}} */ /* {{{ proto resource gmp_divexact(resource a, resource b) Divide a by b using exact division algorithm */ ZEND_FUNCTION(gmp_divexact) { gmp_binary_op(mpz_divexact); } /* }}} */ /* {{{ proto resource gmp_neg(resource a) Negate a number */ ZEND_FUNCTION(gmp_neg) { gmp_unary_op(mpz_neg); } /* }}} */ /* {{{ proto resource gmp_abs(resource a) Calculate absolute value */ ZEND_FUNCTION(gmp_abs) { gmp_unary_op(mpz_abs); } /* }}} */ /* {{{ proto resource gmp_fact(int a) Calculata factorial function */ ZEND_FUNCTION(gmp_fact) { gmp_unary_ui_op(mpz_fac_ui); } /* }}} */ /* {{{ proto resource gmp_powm(resource base, int exp) Raise base to power exp */ ZEND_FUNCTION(gmp_pow) { zval **base_arg, **exp_arg; mpz_t *gmpnum_result, *gmpnum_base; int use_ui=0; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &base_arg, &exp_arg) == FAILURE){ WRONG_PARAM_COUNT; } if(Z_TYPE_PP(base_arg) == IS_LONG && Z_LVAL_PP(base_arg) >= 0) { use_ui=1; } else { FETCH_GMP_ZVAL(gmpnum_base, base_arg); } convert_to_long_ex(exp_arg); if(Z_LVAL_PP(exp_arg) < 0) { zend_error(E_WARNING,"Negative exponent not supported"); RETURN_FALSE; } INIT_GMP_NUM(gmpnum_result); if(use_ui) { mpz_ui_pow_ui(*gmpnum_result, Z_LVAL_PP(base_arg), Z_LVAL_PP(exp_arg)); } else { mpz_pow_ui(*gmpnum_result, *gmpnum_base, Z_LVAL_PP(exp_arg)); } ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } /* }}} */ /* {{{ proto resource gmp_powm(resource base, resource exp, resource mod) Raise base to power exp and take result modulo mod */ ZEND_FUNCTION(gmp_powm) { zval **base_arg, **exp_arg, **mod_arg; mpz_t *gmpnum_base, *gmpnum_exp, *gmpnum_mod, *gmpnum_result; int use_ui=0; if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &base_arg, &exp_arg, &mod_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_base, base_arg); if(Z_TYPE_PP(exp_arg) == IS_LONG && Z_LVAL_PP(exp_arg) >= 0) { use_ui=1; } else { FETCH_GMP_ZVAL(gmpnum_exp, exp_arg); } FETCH_GMP_ZVAL(gmpnum_mod, mod_arg); INIT_GMP_NUM(gmpnum_result); if(use_ui) { mpz_powm_ui(*gmpnum_result, *gmpnum_base, (unsigned long)Z_LVAL_PP(exp_arg), *gmpnum_mod); } else { mpz_powm(*gmpnum_result, *gmpnum_base, *gmpnum_exp, *gmpnum_mod); } ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } /* }}} */ /* {{{ proto resource gmp_sqrt(resource a) Take integer part of square root of a */ ZEND_FUNCTION(gmp_sqrt) { gmp_unary_op(mpz_sqrt); } /* }}} */ /* {{{ proto array gmp_sqrtrem(resource a) Take integer part of square root of a */ ZEND_FUNCTION(gmp_sqrtrem) { zval **a_arg; mpz_t *gmpnum_a, *gmpnum_result1, *gmpnum_result2; zval r; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, a_arg); INIT_GMP_NUM(gmpnum_result1); INIT_GMP_NUM(gmpnum_result2); mpz_sqrtrem(*gmpnum_result1, *gmpnum_result2, *gmpnum_a); array_init(return_value); ZEND_REGISTER_RESOURCE(&r, gmpnum_result1, le_gmp); add_index_resource(return_value, 0, Z_LVAL(r)); ZEND_REGISTER_RESOURCE(&r, gmpnum_result2, le_gmp); add_index_resource(return_value, 1, Z_LVAL(r)); } /* }}} */ /* {{{ proto bool gmp_perfect_square(resource a) Check if a is an exact square */ ZEND_FUNCTION(gmp_perfect_square) { zval **a_arg; mpz_t *gmpnum_a; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, a_arg); RETURN_BOOL(mpz_perfect_square_p(*gmpnum_a)); } /* }}} */ /* {{{ proto bool gmp_prob_prime(resource a[, int reps]) Check if a is a "probably prime" */ ZEND_FUNCTION(gmp_prob_prime) { zval **gmpnumber_arg, **reps_arg; mpz_t *gmpnum_a; int argc, reps; argc = ZEND_NUM_ARGS(); if (argc < 1 || argc > 2 || zend_get_parameters_ex(argc, &gmpnumber_arg, &reps_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, gmpnumber_arg); switch (argc) { case 2: convert_to_long_ex(reps_arg); reps = Z_LVAL_PP(reps_arg); break; case 1: reps = 25; break; } RETURN_BOOL(mpz_probab_prime_p(*gmpnum_a, reps)); } /* }}} */ /* {{{ proto resource gmp_gcd(resource a, resource b) Compute greatest common denominator (gcd) of a and b */ ZEND_FUNCTION(gmp_gcd) { zval **a_arg, **b_arg; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){ WRONG_PARAM_COUNT; } gmp_zval_binary_ui_op_ex(return_value,a_arg,b_arg,mpz_gcd,(gmp_binary_ui_op_t)mpz_gcd_ui,1); } /* }}} */ /* {{{ proto array gmp_gcdext(resource a, resource b) Compute G, S, and T, such that AS + BT = G = `gcd' (A, B) */ ZEND_FUNCTION(gmp_gcdext) { zval **a_arg, **b_arg; mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_t, *gmpnum_s, *gmpnum_g; zval r; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, a_arg); FETCH_GMP_ZVAL(gmpnum_b, a_arg); INIT_GMP_NUM(gmpnum_g); INIT_GMP_NUM(gmpnum_s); INIT_GMP_NUM(gmpnum_t); mpz_gcdext(*gmpnum_g, *gmpnum_s, *gmpnum_t, *gmpnum_a, *gmpnum_b); array_init(return_value); ZEND_REGISTER_RESOURCE(&r, gmpnum_g, le_gmp); add_assoc_resource(return_value, "g", Z_LVAL(r)); ZEND_REGISTER_RESOURCE(&r, gmpnum_s, le_gmp); add_assoc_resource(return_value, "s", Z_LVAL(r)); ZEND_REGISTER_RESOURCE(&r, gmpnum_t, le_gmp); add_assoc_resource(return_value, "t", Z_LVAL(r)); } /* }}} */ /* {{{ proto resource gmp_invert(resource a, resource b) Compute the inverse of a modulo b */ ZEND_FUNCTION(gmp_invert) { zval **a_arg, **b_arg; mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, a_arg); FETCH_GMP_ZVAL(gmpnum_b, a_arg); INIT_GMP_NUM(gmpnum_result); if(mpz_invert(*gmpnum_result,*gmpnum_a, *gmpnum_b)) { ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } else { FREE_GMP_NUM(gmpnum_result); RETURN_FALSE; } } /* }}} */ /* {{{ proto resource gmp_jacobi(resource a, resource b) Compute Jacobi symbol */ ZEND_FUNCTION(gmp_jacobi) { zval **a_arg, **b_arg; mpz_t *gmpnum_a, *gmpnum_b; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, a_arg); FETCH_GMP_ZVAL(gmpnum_b, a_arg); RETURN_LONG(mpz_jacobi(*gmpnum_a, *gmpnum_b)); } /* }}} */ /* {{{ proto resource gmp_legendre(resource a, resource b) Compute Legendre symbol */ ZEND_FUNCTION(gmp_legendre) { zval **a_arg, **b_arg; mpz_t *gmpnum_a, *gmpnum_b; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, a_arg); FETCH_GMP_ZVAL(gmpnum_b, a_arg); RETURN_LONG(mpz_legendre(*gmpnum_a, *gmpnum_b)); } /* }}} */ /* {{{ proto int gmp_cmp(resource a, resource b) */ ZEND_FUNCTION(gmp_cmp) { zval **a_arg, **b_arg; mpz_t *gmpnum_a, *gmpnum_b; int use_si=0, res; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, a_arg); if(Z_TYPE_PP(b_arg) == IS_LONG) { use_si=1; } else { FETCH_GMP_ZVAL(gmpnum_b, b_arg); } if(use_si) { res = mpz_cmp_si(*gmpnum_a, Z_LVAL_PP(b_arg)); } else { res = mpz_cmp(*gmpnum_a, *gmpnum_b); } RETURN_LONG(res); } /* }}} */ /* {{{ proto int gmp_sign(resource a) */ ZEND_FUNCTION(gmp_sign) { zval **a_arg; mpz_t *gmpnum_a; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, a_arg); RETURN_LONG(mpz_sgn(*gmpnum_a)); } /* }}} */ /* {{{ proto resource gmp_random([int limiter]) */ ZEND_FUNCTION(gmp_random) { zval **limiter_arg; int limiter, argc; mpz_t *gmpnum_result; argc = ZEND_NUM_ARGS(); if (argc < 0 || argc > 1 || zend_get_parameters_ex(1, &limiter_arg) == FAILURE){ WRONG_PARAM_COUNT; } if(argc) { convert_to_long_ex(limiter_arg); limiter = Z_LVAL_PP(limiter_arg); } else { limiter = 20; } INIT_GMP_NUM(gmpnum_result); mpz_random(*gmpnum_result, limiter); ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } /* }}} */ /* {{{ proto resource gmp_and(resource a, resource b) Calculate logical AND of a and b */ ZEND_FUNCTION(gmp_and) { gmp_binary_op(mpz_and); } /* }}} */ /* {{{ proto resource gmp_or(resource a, resource b) Calculate logical OR of a and b */ ZEND_FUNCTION(gmp_or) { gmp_binary_op(mpz_ior); } /* }}} */ /* {{{ proto resource gmp_or(resource a) Calculate one's complement of a */ ZEND_FUNCTION(gmp_com) { gmp_unary_op(mpz_com); } /* }}} */ /* {{{ proto resource gmp_xor(resource a, resource b) Calculate logical exclusive OR of a and b */ ZEND_FUNCTION(gmp_xor) { /* use formula: a^b = (a|b)&^(a&b) */ zval **a_arg, **b_arg; mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result, *gmpnum_t; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &b_arg) == FAILURE){ WRONG_PARAM_COUNT; } FETCH_GMP_ZVAL(gmpnum_a, a_arg); FETCH_GMP_ZVAL(gmpnum_b, b_arg); INIT_GMP_NUM(gmpnum_result); INIT_GMP_NUM(gmpnum_t); mpz_and(*gmpnum_t, *gmpnum_a, *gmpnum_b); mpz_com(*gmpnum_t, *gmpnum_t); mpz_ior(*gmpnum_result, *gmpnum_a, *gmpnum_b); mpz_and(*gmpnum_result, *gmpnum_result, *gmpnum_t); FREE_GMP_NUM(gmpnum_t); ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } /* }}} */ /* {{{ proto void gmp_setbit(resource &a, int index[, bool set_clear]) Set or clear bit in a */ ZEND_FUNCTION(gmp_setbit) { zval **a_arg, **ind_arg, **sc_arg; int argc, index, set; mpz_t *gmpnum_a; argc = ZEND_NUM_ARGS(); if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &a_arg, &ind_arg, &sc_arg) == FAILURE){ WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp); convert_to_long_ex(ind_arg); index = Z_LVAL_PP(ind_arg); switch (argc) { case 3: convert_to_long_ex(sc_arg); set = Z_LVAL_PP(sc_arg); break; case 2: set = 1; break; } if(set) { mpz_setbit(*gmpnum_a, index); } else { mpz_clrbit(*gmpnum_a, index); } } /* }}} */ /* {{{ proto void gmp_clrbit(resource &a, int index) Clear bit in a */ ZEND_FUNCTION(gmp_clrbit) { zval **a_arg, **ind_arg; int index; mpz_t *gmpnum_a; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &a_arg, &ind_arg) == FAILURE){ WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp); convert_to_long_ex(ind_arg); index = Z_LVAL_PP(ind_arg); mpz_clrbit(*gmpnum_a, index); } /* }}} */ static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc) { mpz_t *gmpnum = (mpz_t *)rsrc->ptr; FREE_GMP_NUM(gmpnum); } #endif /* HAVE_GMP */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */ Index: php4/ext/gmp/php_gmp.h +++ php4/ext/gmp/php_gmp.h /* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Stanislav Malyshev <stas@php.net> | +----------------------------------------------------------------------+ */ #ifndef PHP_GMP_H #define PHP_GMP_H /* You should tweak config.m4 so this symbol (or some else suitable) gets defined. */ #if HAVE_GMP extern zend_module_entry gmp_module_entry; #define phpext_gmp_ptr &gmp_module_entry #ifdef ZEND_WIN32 #define GMP_API __declspec(dllexport) #else #define GMP_API #endif ZEND_MINIT_FUNCTION(gmp); ZEND_MSHUTDOWN_FUNCTION(gmp); ZEND_MINFO_FUNCTION(gmp); ZEND_FUNCTION(gmp_init); ZEND_FUNCTION(gmp_intval); ZEND_FUNCTION(gmp_strval); ZEND_FUNCTION(gmp_add); ZEND_FUNCTION(gmp_sub); ZEND_FUNCTION(gmp_mul); ZEND_FUNCTION(gmp_div_qr); ZEND_FUNCTION(gmp_div_q); ZEND_FUNCTION(gmp_div_r); ZEND_FUNCTION(gmp_mod); ZEND_FUNCTION(gmp_divexact); ZEND_FUNCTION(gmp_neg); ZEND_FUNCTION(gmp_abs); ZEND_FUNCTION(gmp_fact); ZEND_FUNCTION(gmp_sqrt); ZEND_FUNCTION(gmp_pow); ZEND_FUNCTION(gmp_powm); ZEND_FUNCTION(gmp_sqrtrem); ZEND_FUNCTION(gmp_perfect_square); ZEND_FUNCTION(gmp_prob_prime); ZEND_FUNCTION(gmp_gcd); ZEND_FUNCTION(gmp_gcdext); ZEND_FUNCTION(gmp_invert); ZEND_FUNCTION(gmp_jacobi); ZEND_FUNCTION(gmp_legendre); ZEND_FUNCTION(gmp_cmp); ZEND_FUNCTION(gmp_sign); ZEND_FUNCTION(gmp_and); ZEND_FUNCTION(gmp_or); ZEND_FUNCTION(gmp_com); ZEND_FUNCTION(gmp_xor); ZEND_FUNCTION(gmp_random); ZEND_FUNCTION(gmp_setbit); ZEND_FUNCTION(gmp_clrbit); /* Declare any global variables you may need between the BEGIN and END macros here: ZEND_BEGIN_MODULE_GLOBALS(gmp) int global_variable; ZEND_END_MODULE_GLOBALS(gmp) */ /* In every function that needs to use variables in php_gmp_globals, do call GMPLS_FETCH(); after declaring other variables used by that function, and always refer to them as GMPG(variable). You are encouraged to rename these macros something shorter, see examples in any other php module directory. */ #ifdef ZTS #define GMPG(v) (gmp_globals->v) #define GMPLS_FETCH() php_gmp_globals *gmp_globals = ts_resource(gmp_globals_id) #else #define GMPG(v) (gmp_globals.v) #define GMPLS_FETCH() #endif #else #define phpext_gmp_ptr NULL #endif #endif /* PHP_GMP_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */
« previous php.cvs (#2797) next »