]> granicus.if.org Git - php/commitdiff
GMP improvements
authorNikita Popov <nikic@php.net>
Mon, 17 Jun 2013 15:49:24 +0000 (17:49 +0200)
committerNikita Popov <nikic@php.net>
Mon, 17 Jun 2013 15:59:12 +0000 (17:59 +0200)
As per RFC https://wiki.php.net/rfc/operator_overloading_gmp

18 files changed:
ext/gmp/gmp.c
ext/gmp/tests/004.phpt
ext/gmp/tests/005.phpt
ext/gmp/tests/006.phpt
ext/gmp/tests/007.phpt
ext/gmp/tests/008.phpt
ext/gmp/tests/009.phpt
ext/gmp/tests/010.phpt
ext/gmp/tests/014.phpt
ext/gmp/tests/016.phpt
ext/gmp/tests/033.phpt
ext/gmp/tests/034.phpt
ext/gmp/tests/040.phpt
ext/gmp/tests/cast.phpt [new file with mode: 0644]
ext/gmp/tests/clone.phpt [new file with mode: 0644]
ext/gmp/tests/comparison.phpt [new file with mode: 0644]
ext/gmp/tests/overloading.phpt [new file with mode: 0644]
ext/gmp/tests/serialize.phpt [new file with mode: 0644]

index c9da09b230bb4c82591337c015fb37a59d6cea2c..6b3dadf40576f4b748c8747107dd6d663af75efb 100644 (file)
@@ -24,6 +24,7 @@
 #include "php_ini.h"
 #include "php_gmp.h"
 #include "ext/standard/info.h"
+#include "zend_exceptions.h"
 
 #if HAVE_GMP
 
@@ -34,9 +35,6 @@
 #include "ext/standard/php_lcg.h"
 #define GMP_ABS(x) ((x) >= 0 ? (x) : -(x))
 
-/* True global resources - no need for thread safety here */
-static int le_gmp;
-
 /* {{{ arginfo */
 ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_init, 0, 0, 1)
        ZEND_ARG_INFO(0, number)
@@ -308,9 +306,18 @@ zend_module_entry gmp_module_entry = {
 ZEND_GET_MODULE(gmp)
 #endif
 
-static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc TSRMLS_DC);
+zend_class_entry *gmp_ce;
+static zend_object_handlers gmp_object_handlers;
+
+typedef struct _gmp_object {
+       zend_object std;
+       mpz_t num;
+} gmp_object;
 
-#define GMP_RESOURCE_NAME "GMP integer"
+typedef struct _gmp_temp {
+       mpz_t num;
+       zend_bool is_used;
+} gmp_temp_t;
 
 #define GMP_ROUND_ZERO      0
 #define GMP_ROUND_PLUSINF   1
@@ -324,6 +331,123 @@ static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc TSRMLS_DC);
 #      define MAX_BASE 36
 #endif
 
+#define IS_GMP(zval) \
+       (Z_TYPE_P(zval) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zval), gmp_ce TSRMLS_CC))
+
+#define GET_GMP_FROM_ZVAL(zval) \
+       (((gmp_object *) zend_object_store_get_object((zval) TSRMLS_CC))->num)
+
+/* The FETCH_GMP_ZVAL_* family of macros is used to fetch a gmp number
+ * (mpz_ptr) from a zval. If the zval is not a GMP instance, then we
+ * try to convert the value to a temporary gmp number using convert_to_gmp.
+ * This temporary number is stored in the temp argument, which is of type
+ * gmp_temp_t. This temporary value needs to be freed lateron using the
+ * FREE_GMP_TEMP macro.
+ *
+ * If the conversion to a gmp number fails, the macros return false.
+ * The _DEP / _DEP_DEP variants additionally free the temporary values
+ * passed in the last / last two arguments.
+ *
+ * If one zval can sometimes be fetched as a long you have to set the
+ * is_used member of the corresponding gmp_temp_t value to 0, otherwise
+ * the FREE_GMP_TEMP and *_DEP macros will not work properly.
+ *
+ * The three FETCH_GMP_ZVAL_* macros below are mostly copy & paste code
+ * as I couldn't find a way to combine them.
+ */
+
+#define FREE_GMP_TEMP(temp)  \
+       if (temp.is_used) {      \
+               mpz_clear(temp.num); \
+       }
+
+#define FETCH_GMP_ZVAL_DEP_DEP(gmpnumber, zval, temp, dep1, dep2) \
+if (IS_GMP(zval)) {                                               \
+       gmpnumber = GET_GMP_FROM_ZVAL(zval);                          \
+       temp.is_used = 0;                                             \
+} else {                                                          \
+       mpz_init(temp.num);                                           \
+       if (convert_to_gmp(temp.num, zval, 0 TSRMLS_CC) == FAILURE) { \
+               mpz_clear(temp.num);                                      \
+               FREE_GMP_TEMP(dep1);                                      \
+               FREE_GMP_TEMP(dep2);                                      \
+               RETURN_FALSE;                                             \
+       }                                                             \
+       temp.is_used = 1;                                             \
+       gmpnumber = temp.num;                                         \
+}
+
+#define FETCH_GMP_ZVAL_DEP(gmpnumber, zval, temp, dep)            \
+if (IS_GMP(zval)) {                                               \
+       gmpnumber = GET_GMP_FROM_ZVAL(zval);                          \
+       temp.is_used = 0;                                             \
+} else {                                                          \
+       mpz_init(temp.num);                                           \
+       if (convert_to_gmp(temp.num, zval, 0 TSRMLS_CC) == FAILURE) { \
+               mpz_clear(temp.num);                                      \
+               FREE_GMP_TEMP(dep);                                       \
+               RETURN_FALSE;                                             \
+       }                                                             \
+       temp.is_used = 1;                                             \
+       gmpnumber = temp.num;                                         \
+}
+
+#define FETCH_GMP_ZVAL(gmpnumber, zval, temp)                     \
+if (IS_GMP(zval)) {                                               \
+       gmpnumber = GET_GMP_FROM_ZVAL(zval);                          \
+       temp.is_used = 0;                                             \
+} else {                                                          \
+       mpz_init(temp.num);                                           \
+       if (convert_to_gmp(temp.num, zval, 0 TSRMLS_CC) == FAILURE) { \
+               mpz_clear(temp.num);                                      \
+               RETURN_FALSE;                                             \
+       }                                                             \
+       temp.is_used = 1;                                             \
+       gmpnumber = temp.num;                                         \
+}
+
+#define INIT_GMP_RETVAL(gmpnumber) \
+       gmp_create_ex(return_value, &gmpnumber TSRMLS_CC)
+
+static void gmp_strval(zval *result, mpz_t gmpnum, long base);
+static int convert_to_gmp(mpz_t gmpnumber, zval *val, int base TSRMLS_DC);
+static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg TSRMLS_DC);
+
+/* 
+ * The gmp_*_op functions provide an implementation for several common types
+ * of GMP functions. The gmp_zval_(unary|binary)_*_op functions have to be manually
+ * passed zvals to work on, whereas the gmp_(unary|binary)_*_op macros already
+ * include parameter parsing.
+ */
+typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr);
+typedef int (*gmp_unary_opl_t)(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 int (*gmp_binary_opl_t)(mpz_srcptr, mpz_srcptr);
+
+typedef void (*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 void (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long);
+
+static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int check_b_zero TSRMLS_DC);
+static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int check_b_zero TSRMLS_DC);
+static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_op_t gmp_op TSRMLS_DC);
+static inline void gmp_zval_unary_ui_op(zval *return_value, zval *a_arg, gmp_unary_ui_op_t gmp_op TSRMLS_DC);
+
+/* Binary operations */
+#define gmp_binary_ui_op(op, uop) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop, 0)
+#define gmp_binary_op(op)         _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, NULL, 0)
+#define gmp_binary_opl(op) _gmp_binary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
+#define gmp_binary_ui_op_no_zero(op, uop) \
+       _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop, 1)
+
+/* Unary operations */
+#define gmp_unary_op(op)         _gmp_unary_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
+#define gmp_unary_opl(op)         _gmp_unary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
+#define gmp_unary_ui_op(op)      _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
+
 /* {{{ gmp_emalloc
  */
 static void *gmp_emalloc(size_t size)
@@ -348,6 +472,245 @@ static void gmp_efree(void *ptr, size_t size)
 }
 /* }}} */
 
+static inline long gmp_get_long(zval *zv) /* {{{ */
+{
+       if (Z_TYPE_P(zv) == IS_LONG) {
+               return Z_LVAL_P(zv);
+       } else {
+               zval tmp_zv;
+               MAKE_COPY_ZVAL(&zv, &tmp_zv);
+               convert_to_long(&tmp_zv);
+               return Z_LVAL(tmp_zv);
+       }
+}
+/* }}} */
+
+static void gmp_free_object_storage(gmp_object *intern TSRMLS_DC) /* {{{ */
+{
+       mpz_clear(intern->num);
+
+       zend_object_std_dtor(&intern->std TSRMLS_CC);
+       efree(intern);
+}
+/* }}} */
+
+static inline zend_object_value gmp_create_object_ex(zend_class_entry *ce, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */
+{
+       zend_object_value retval;
+       gmp_object *intern = emalloc(sizeof(gmp_object));
+
+       zend_object_std_init(&intern->std, ce TSRMLS_CC);
+       object_properties_init(&intern->std, ce);
+
+       mpz_init(intern->num);
+       *gmpnum_target = intern->num;
+
+       retval.handle = zend_objects_store_put(
+               intern, (zend_objects_store_dtor_t) zend_objects_destroy_object,
+               (zend_objects_free_object_storage_t) gmp_free_object_storage,
+               NULL TSRMLS_CC
+       );
+       retval.handlers = &gmp_object_handlers;
+
+       return retval;
+}
+/* }}} */
+
+static zend_object_value gmp_create_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */
+{
+       mpz_ptr gmpnum_dummy;
+       return gmp_create_object_ex(ce, &gmpnum_dummy TSRMLS_CC);
+}
+/* }}} */
+
+static inline void gmp_create_ex(zval *target, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */
+{
+       Z_TYPE_P(target) = IS_OBJECT;
+       Z_OBJVAL_P(target) = gmp_create_object_ex(gmp_ce, gmpnum_target TSRMLS_CC);
+}
+/* }}} */
+
+static zval *gmp_create(mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */
+{
+       zval *obj;
+       MAKE_STD_ZVAL(obj);
+       gmp_create_ex(obj, gmpnum_target TSRMLS_CC);
+       return obj;
+}
+/* }}} */
+
+static int gmp_cast_object(zval *readobj, zval *writeobj, int type TSRMLS_DC) /* {{{ */
+{
+       mpz_ptr gmpnum;
+       switch (type) {
+       case IS_STRING:
+               gmpnum = GET_GMP_FROM_ZVAL(readobj);
+               INIT_PZVAL(writeobj);
+               gmp_strval(writeobj, gmpnum, 10);
+               return SUCCESS;
+       case IS_LONG:
+               gmpnum = GET_GMP_FROM_ZVAL(readobj);
+               INIT_PZVAL(writeobj);
+               ZVAL_LONG(writeobj, mpz_get_si(gmpnum));
+               return SUCCESS;
+       case IS_DOUBLE:
+               gmpnum = GET_GMP_FROM_ZVAL(readobj);
+               INIT_PZVAL(writeobj);
+               ZVAL_DOUBLE(writeobj, mpz_get_d(gmpnum));
+               return SUCCESS;
+       default:
+               return FAILURE;
+       }
+}
+/* }}} */
+
+static HashTable *gmp_get_properties(zval *obj TSRMLS_DC) /* {{{ */
+{
+       HashTable *ht = zend_std_get_properties(obj TSRMLS_CC);
+       mpz_ptr gmpnum = GET_GMP_FROM_ZVAL(obj);
+       zval *zv;
+
+       MAKE_STD_ZVAL(zv);
+       gmp_strval(zv, gmpnum, 10);
+       zend_hash_update(ht, "num", sizeof("num"), &zv, sizeof(zval *), NULL);
+
+       return ht;
+}
+/* }}} */
+
+static zend_object_value gmp_clone_obj(zval *obj TSRMLS_DC) /* {{{ */
+{
+       gmp_object *old_object = zend_object_store_get_object(obj TSRMLS_CC);
+       zend_object_value new_object_val = gmp_create_object(Z_OBJCE_P(obj) TSRMLS_CC);
+       gmp_object *new_object = zend_object_store_get_object_by_handle(
+               new_object_val.handle TSRMLS_CC
+       );
+
+       zend_objects_clone_members(
+               &new_object->std, new_object_val,
+               &old_object->std, Z_OBJ_HANDLE_P(obj) TSRMLS_CC
+       );
+
+       mpz_set(new_object->num, old_object->num);
+
+       return new_object_val;
+}
+/* }}} */
+
+static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zval *op1, zval *op2 TSRMLS_DC) {
+       zval op2_copy;
+       if (Z_TYPE_P(op2) != IS_LONG) {
+               op2_copy = *op2;
+               zval_copy_ctor(&op2_copy);
+               convert_to_long(&op2_copy);
+               op2 = &op2_copy;
+       }
+
+       if (Z_LVAL_P(op2) < 0) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Shift cannot be negative");
+               RETVAL_FALSE;
+       } else {
+               mpz_ptr gmpnum_op, gmpnum_result;
+               gmp_temp_t temp;
+
+               FETCH_GMP_ZVAL(gmpnum_op, op1, temp);
+               INIT_GMP_RETVAL(gmpnum_result);
+               op(gmpnum_result, gmpnum_op, (unsigned long) Z_LVAL_P(op2));
+               FREE_GMP_TEMP(temp);
+       }
+}
+
+#define DO_BINARY_UI_OP_EX(op, uop, check_b_zero)       \
+       gmp_zval_binary_ui_op(                              \
+               result, op1, op2, op, (gmp_binary_ui_op_t) uop, \
+               check_b_zero TSRMLS_CC                          \
+       );                                                  \
+       return SUCCESS;
+
+#define DO_BINARY_UI_OP(op) DO_BINARY_UI_OP_EX(op, op ## _ui, 0)
+#define DO_BINARY_OP(op) DO_BINARY_UI_OP_EX(op, NULL, 0)
+
+#define DO_UNARY_OP(op) \
+       gmp_zval_unary_op(result, op1, op TSRMLS_CC); \
+       return SUCCESS;
+
+static int gmp_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+       switch (opcode) {
+       case ZEND_ADD:
+               DO_BINARY_UI_OP(mpz_add);
+       case ZEND_SUB:
+               DO_BINARY_UI_OP(mpz_sub);
+       case ZEND_MUL:
+               DO_BINARY_UI_OP(mpz_mul);
+       case ZEND_DIV:
+               DO_BINARY_UI_OP_EX(mpz_tdiv_q, mpz_tdiv_q_ui, 1);
+       case ZEND_MOD:
+               DO_BINARY_UI_OP_EX(mpz_mod, mpz_mod_ui, 1);
+       case ZEND_SL:
+               shift_operator_helper(mpz_mul_2exp, result, op1, op2 TSRMLS_CC);
+               return SUCCESS;
+       case ZEND_SR:
+               shift_operator_helper(mpz_fdiv_q_2exp, result, op1, op2 TSRMLS_CC);
+               return SUCCESS;
+       case ZEND_BW_OR:
+               DO_BINARY_OP(mpz_ior);
+       case ZEND_BW_AND:
+               DO_BINARY_OP(mpz_and);
+       case ZEND_BW_XOR:
+               DO_BINARY_OP(mpz_xor);
+       case ZEND_BW_NOT:
+               DO_UNARY_OP(mpz_com);
+
+       default:
+               return FAILURE;
+       }
+}
+/* }}} */
+
+static int gmp_compare(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+       gmp_cmp(result, op1, op2 TSRMLS_CC);
+       if (Z_TYPE_P(result) == IS_BOOL) {
+               ZVAL_LONG(result, 1);
+       }
+       return SUCCESS;
+}
+/* }}} */
+
+PHP_METHOD(GMP, __wakeup) /* {{{ */
+{
+       HashTable *props;
+       zval **num_zv;
+
+       if (zend_parse_parameters_none() == FAILURE) {
+               return;
+       }
+
+       props = zend_std_get_properties(getThis() TSRMLS_CC);
+       if (zend_hash_find(props, "num", sizeof("num"), (void **) &num_zv) == SUCCESS
+           && Z_TYPE_PP(num_zv) == IS_STRING && Z_STRLEN_PP(num_zv) > 0
+       ) {
+               mpz_ptr gmpnumber = GET_GMP_FROM_ZVAL(getThis());
+               if (convert_to_gmp(gmpnumber, *num_zv, 10 TSRMLS_CC) == SUCCESS) {
+                       return;
+               }
+       }
+
+       zend_throw_exception(
+               NULL, "Invalid serialization data", 0 TSRMLS_CC 
+       );
+}
+/* }}} */
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_wakeup, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+const zend_function_entry gmp_methods[] = {
+       PHP_ME(GMP, __wakeup, arginfo_wakeup, ZEND_ACC_PUBLIC)
+       PHP_FE_END
+};
+
 /* {{{ ZEND_GINIT_FUNCTION
  */
 static ZEND_GINIT_FUNCTION(gmp)
@@ -358,9 +721,20 @@ static ZEND_GINIT_FUNCTION(gmp)
 
 /* {{{ ZEND_MINIT_FUNCTION
  */
-ZEND_MODULE_STARTUP_D(gmp)
+ZEND_MINIT_FUNCTION(gmp)
 {
-       le_gmp = zend_register_list_destructors_ex(_php_gmpnum_free, NULL, GMP_RESOURCE_NAME, module_number);
+       zend_class_entry tmp_ce;
+       INIT_CLASS_ENTRY(tmp_ce, "GMP", gmp_methods); /* No methods on the class for now */
+       gmp_ce = zend_register_internal_class(&tmp_ce TSRMLS_CC);
+       gmp_ce->create_object = gmp_create_object;
+
+       memcpy(&gmp_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+       gmp_object_handlers.cast_object = gmp_cast_object;
+       gmp_object_handlers.get_properties = gmp_get_properties;
+       gmp_object_handlers.clone_obj = gmp_clone_obj;
+       gmp_object_handlers.do_operation = gmp_do_operation;
+       gmp_object_handlers.compare = gmp_compare;
+
        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);
@@ -403,246 +777,211 @@ ZEND_MODULE_INFO_D(gmp)
 }
 /* }}} */
 
-/* Fetch zval to be GMP number.
-   Initially, zval can be also number or string */
-#define FETCH_GMP_ZVAL(gmpnumber, zval, tmp_resource)                                                          \
-if (Z_TYPE_PP(zval) == IS_RESOURCE) {                                                                                          \
-       ZEND_FETCH_RESOURCE(gmpnumber, mpz_t *, zval, -1, GMP_RESOURCE_NAME, le_gmp);   \
-       tmp_resource = 0;                                                                                                                               \
-} else {                                                                                                                                                       \
-       if (convert_to_gmp(&gmpnumber, zval, 0 TSRMLS_CC) == FAILURE) {                                 \
-               RETURN_FALSE;                                                                                                                           \
-       }                                                                                                                                                               \
-       tmp_resource = ZEND_REGISTER_RESOURCE(NULL, gmpnumber, le_gmp);                                 \
-}
-
-#define FREE_GMP_TEMP(tmp_resource)                    \
-       if(tmp_resource) {                                              \
-               zend_list_delete(tmp_resource);         \
-       }
-
-
-/* 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_to_gmp
  * Convert zval to be gmp number */
-static int convert_to_gmp(mpz_t * *gmpnumber, zval **val, int base TSRMLS_DC) 
+static int convert_to_gmp(mpz_t gmpnumber, zval *val, int base TSRMLS_DC) 
 {
-       int ret = 0;
-       int skip_lead = 0;
-
-       *gmpnumber = emalloc(sizeof(mpz_t));
-
-       switch (Z_TYPE_PP(val)) {
+       switch (Z_TYPE_P(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 (Z_STRLEN_PP(val) > 2) {
-                               if (numstr[0] == '0') {
-                                       if (numstr[1] == 'x' || numstr[1] == 'X') {
-                                               base = 16;
-                                               skip_lead = 1;
-                                       } else if (base != 16 && (numstr[1] == 'b' || numstr[1] == 'B')) {
-                                               base = 2;
-                                               skip_lead = 1;
-                                       }
+       case IS_CONSTANT: {
+               mpz_set_si(gmpnumber, gmp_get_long(val));
+               return SUCCESS;
+       }
+       case IS_STRING: {
+               char *numstr = Z_STRVAL_P(val);
+               int skip_lead = 0;
+
+               if (Z_STRLEN_P(val) > 2) {
+                       if (numstr[0] == '0') {
+                               if (numstr[1] == 'x' || numstr[1] == 'X') {
+                                       base = 16;
+                                       skip_lead = 1;
+                               } else if (base != 16 && (numstr[1] == 'b' || numstr[1] == 'B')) {
+                                       base = 2;
+                                       skip_lead = 1;
                                }
                        }
-                       ret = mpz_init_set_str(**gmpnumber, (skip_lead ? &numstr[2] : numstr), base);
                }
-               break;
-       default:
-               php_error_docref(NULL TSRMLS_CC, E_WARNING,"Unable to convert variable to GMP - wrong type");
-               efree(*gmpnumber);
-               return FAILURE;
-       }
 
-       if (ret) {
-               FREE_GMP_NUM(*gmpnumber);
+               return mpz_set_str(gmpnumber, (skip_lead ? &numstr[2] : numstr), base);
+       }
+       default:
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to convert variable to GMP - wrong type");
                return FAILURE;
        }
-       
-       return SUCCESS;
 }
 /* }}} */
 
-/* {{{ typedefs
- */
-typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr);
-typedef int (*gmp_unary_opl_t)(mpz_srcptr);
+static void gmp_strval(zval *result, mpz_t gmpnum, long base) /* {{{ */
+{
+       int num_len;
+       char *out_string;
 
-typedef void (*gmp_unary_ui_op_t)(mpz_ptr, unsigned long);
+       num_len = mpz_sizeinbase(gmpnum, abs(base));
+       if (mpz_sgn(gmpnum) < 0) {
+               num_len++;
+       }
 
-typedef void (*gmp_binary_op_t)(mpz_ptr, mpz_srcptr, mpz_srcptr);
-typedef int (*gmp_binary_opl_t)(mpz_srcptr, mpz_srcptr);
+       out_string = emalloc(num_len + 1);
+       mpz_get_str(out_string, base, gmpnum);
+       
+       /* 
+        * From GMP documentation for mpz_sizeinbase():
+        * The returned value will be exact or 1 too big.  If base is a power of
+        * 2, the returned value will always be exact.
+        *
+        * So let's check to see if we already have a \0 byte...
+        */
+
+       if (out_string[num_len - 1] == '\0') {
+               num_len--;
+       } else {
+               out_string[num_len] = '\0';
+       }
 
-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);
+       ZVAL_STRINGL(result, out_string, num_len, 0);
+}
 /* }}} */
 
-#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)
-#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)
+static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg TSRMLS_DC) /* {{{ */
+{
+       mpz_ptr gmpnum_a, gmpnum_b;
+       gmp_temp_t temp_a, temp_b;
+       zend_bool use_si = 0;
+       long res;
 
-#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)
-#define gmp_binary_opl(op) _gmp_binary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
+       FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
 
-/* Unary operations */
-#define gmp_unary_op(op)         _gmp_unary_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
-#define gmp_unary_opl(op)         _gmp_unary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
-#define gmp_unary_ui_op(op)      _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op)
+       if (Z_TYPE_P(b_arg) == IS_LONG) {
+               use_si = 1;
+               temp_b.is_used = 0;
+       } else {
+               FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+       }
+
+       if (use_si) {
+               res = mpz_cmp_si(gmpnum_a, Z_LVAL_P(b_arg));
+       } else {
+               res = mpz_cmp(gmpnum_a, gmpnum_b);
+       }
+
+       FREE_GMP_TEMP(temp_a);
+       FREE_GMP_TEMP(temp_b);
+       
+       RETURN_LONG(res);
+}
+/* }}} */
 
-/* {{{ gmp_zval_binary_ui_op_ex
+/* {{{ gmp_zval_binary_ui_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, int check_b_zero, int use_sign TSRMLS_DC) 
+static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int check_b_zero TSRMLS_DC) 
 {
-       mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result;
-       unsigned long long_result = 0;
+       mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result;
        int use_ui = 0;
-       int arga_tmp = 0, argb_tmp = 0;
+       gmp_temp_t temp_a, temp_b;
 
-       FETCH_GMP_ZVAL(gmpnum_a, a_arg, arga_tmp);
+       FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
        
-       if (gmp_ui_op && Z_TYPE_PP(b_arg) == IS_LONG && Z_LVAL_PP(b_arg) >= 0) {
+       if (gmp_ui_op && Z_TYPE_P(b_arg) == IS_LONG && Z_LVAL_P(b_arg) >= 0) {
                use_ui = 1;
+               temp_b.is_used = 0;
        } else {
-               FETCH_GMP_ZVAL(gmpnum_b, b_arg, argb_tmp);
+               FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
        }
 
-       if(check_b_zero) {
+       if (check_b_zero) {
                int b_is_zero = 0;
-               if(use_ui) {
-                       b_is_zero = (Z_LVAL_PP(b_arg) == 0);
+               if (use_ui) {
+                       b_is_zero = (Z_LVAL_P(b_arg) == 0);
                } else {
-                       b_is_zero = !mpz_cmp_ui(*gmpnum_b, 0);
+                       b_is_zero = !mpz_cmp_ui(gmpnum_b, 0);
                }
 
-               if(b_is_zero) {
+               if (b_is_zero) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero operand not allowed");
-                       FREE_GMP_TEMP(arga_tmp);
-                       FREE_GMP_TEMP(argb_tmp);
+                       FREE_GMP_TEMP(temp_a);
+                       FREE_GMP_TEMP(temp_b);
                        RETURN_FALSE;
                }
        }
 
-       INIT_GMP_NUM(gmpnum_result);
+       INIT_GMP_RETVAL(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));
-                       if (use_sign && mpz_sgn(*gmpnum_a) == -1) {
-                               long_result = -long_result;
-                       }
-               } else {
-                       gmp_ui_op(*gmpnum_result, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg));
-               }
+       if (use_ui) {
+               gmp_ui_op(gmpnum_result, gmpnum_a, (unsigned long) Z_LVAL_P(b_arg));
        } else {
-               gmp_op(*gmpnum_result, *gmpnum_a, *gmpnum_b);
+               gmp_op(gmpnum_result, gmpnum_a, gmpnum_b);
        }
 
-       FREE_GMP_TEMP(arga_tmp);
-       FREE_GMP_TEMP(argb_tmp);
-
-       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);
-       }
+       FREE_GMP_TEMP(temp_a);
+       FREE_GMP_TEMP(temp_b);
 }
 /* }}} */
 
-/* {{{ gmp_zval_binary_ui_op2_ex
+/* {{{ gmp_zval_binary_ui_op2
    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, int check_b_zero TSRMLS_DC)
+static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int check_b_zero TSRMLS_DC)
 {
-       mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result1, *gmpnum_result2;
-       zval r;
+       mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result1, gmpnum_result2;
        int use_ui = 0;
-       unsigned long long_result = 0;
-       int arga_tmp = 0, argb_tmp = 0;
+       gmp_temp_t temp_a, temp_b;
 
-       FETCH_GMP_ZVAL(gmpnum_a, a_arg, arga_tmp);
+       FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
 
-       if (gmp_ui_op && Z_TYPE_PP(b_arg) == IS_LONG && Z_LVAL_PP(b_arg) >= 0) {
+       if (gmp_ui_op && Z_TYPE_P(b_arg) == IS_LONG && Z_LVAL_P(b_arg) >= 0) {
                /* use _ui function */
                use_ui = 1;
+               temp_b.is_used = 0;
        } else {
-               FETCH_GMP_ZVAL(gmpnum_b, b_arg, argb_tmp);
+               FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
        }
 
-       if(check_b_zero) {
+       if (check_b_zero) {
                int b_is_zero = 0;
-               if(use_ui) {
-                       b_is_zero = (Z_LVAL_PP(b_arg) == 0);
+               if (use_ui) {
+                       b_is_zero = (Z_LVAL_P(b_arg) == 0);
                } else {
-                       b_is_zero = !mpz_cmp_ui(*gmpnum_b, 0);
+                       b_is_zero = !mpz_cmp_ui(gmpnum_b, 0);
                }
 
-               if(b_is_zero) {
+               if (b_is_zero) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero operand not allowed");
-                       FREE_GMP_TEMP(arga_tmp);
-                       FREE_GMP_TEMP(argb_tmp);
+                       FREE_GMP_TEMP(temp_a);
+                       FREE_GMP_TEMP(temp_b);
                        RETURN_FALSE;
                }
        }
 
-       INIT_GMP_NUM(gmpnum_result1);
-       INIT_GMP_NUM(gmpnum_result2);
+       array_init(return_value);
+       add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC));
+       add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC));
 
-       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));
-               }
+       if (use_ui) {
+               gmp_ui_op(gmpnum_result1, gmpnum_result2, gmpnum_a, (unsigned long) Z_LVAL_P(b_arg));
        } else {
-               gmp_op(*gmpnum_result1, *gmpnum_result2, *gmpnum_a, *gmpnum_b);
+               gmp_op(gmpnum_result1, gmpnum_result2, gmpnum_a, gmpnum_b);
        }
 
-       FREE_GMP_TEMP(arga_tmp);
-       FREE_GMP_TEMP(argb_tmp);
-
-       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));
-       }
+       FREE_GMP_TEMP(temp_a);
+       FREE_GMP_TEMP(temp_b);
 }
 /* }}} */
 
 /* {{{ _gmp_binary_ui_op
  */
-static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op)
+static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int check_b_zero)
 {
-       zval **a_arg, **b_arg;
+       zval *a_arg, *b_arg;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){
                return;
        }
        
-       gmp_zval_binary_ui_op(return_value, a_arg, b_arg, gmp_op, gmp_ui_op);
+       gmp_zval_binary_ui_op(return_value, a_arg, b_arg, gmp_op, gmp_ui_op, check_b_zero TSRMLS_CC);
 }
 /* }}} */
 
@@ -650,33 +989,28 @@ static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op
 
 /* {{{ gmp_zval_unary_op
  */
-static inline void gmp_zval_unary_op(zval *return_value, zval **a_arg, gmp_unary_op_t gmp_op TSRMLS_DC) 
+static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_op_t gmp_op TSRMLS_DC) 
 {
-       mpz_t *gmpnum_a, *gmpnum_result;
-       int temp_a;
+       mpz_ptr gmpnum_a, gmpnum_result;
+       gmp_temp_t temp_a;
        
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
 
-       INIT_GMP_NUM(gmpnum_result);
-       gmp_op(*gmpnum_result, *gmpnum_a);
+       INIT_GMP_RETVAL(gmpnum_result);
+       gmp_op(gmpnum_result, gmpnum_a);
 
        FREE_GMP_TEMP(temp_a);
-       ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
 }
 /* }}} */
 
 /* {{{ gmp_zval_unary_ui_op
  */
-static inline void gmp_zval_unary_ui_op(zval *return_value, zval **a_arg, gmp_unary_ui_op_t gmp_op TSRMLS_DC)
+static inline void gmp_zval_unary_ui_op(zval *return_value, zval *a_arg, gmp_unary_ui_op_t gmp_op TSRMLS_DC)
 {
-       mpz_t *gmpnum_result;
-
-       convert_to_long_ex(a_arg);
+       mpz_ptr gmpnum_result;
 
-       INIT_GMP_NUM(gmpnum_result);
-       gmp_op(*gmpnum_result, Z_LVAL_PP(a_arg));
-
-       ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
+       INIT_GMP_RETVAL(gmpnum_result);
+       gmp_op(gmpnum_result, gmp_get_long(a_arg));
 }
 /* }}} */
 
@@ -685,9 +1019,9 @@ static inline void gmp_zval_unary_ui_op(zval *return_value, zval **a_arg, gmp_un
 */
 static inline void _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_ui_op_t gmp_op)
 {
-       zval **a_arg;
+       zval *a_arg;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){
                return;
        }
 
@@ -699,9 +1033,9 @@ static inline void _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_ui_o
  */
 static inline void _gmp_unary_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_op_t gmp_op)
 {
-       zval **a_arg;
+       zval *a_arg;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){
                return;
        }
        
@@ -713,16 +1047,16 @@ static inline void _gmp_unary_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_op_t gm
  */
 static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t gmp_op)
 {
-       zval **a_arg;
-       mpz_t *gmpnum_a;
-       int temp_a;
+       zval *a_arg;
+       mpz_ptr gmpnum_a;
+       gmp_temp_t temp_a;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){
                return;
        }
        
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
-       RETVAL_LONG(gmp_op(*gmpnum_a));
+       RETVAL_LONG(gmp_op(gmpnum_a));
        FREE_GMP_TEMP(temp_a);
 }
 /* }}} */
@@ -731,33 +1065,33 @@ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t
  */
 static inline void _gmp_binary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_opl_t gmp_op)
 {
-       zval **a_arg, **b_arg;
-       mpz_t *gmpnum_a, *gmpnum_b;
-       int temp_a, temp_b;
+       zval *a_arg, *b_arg;
+       mpz_ptr gmpnum_a, gmpnum_b;
+       gmp_temp_t temp_a, temp_b;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){
                return;
        }
 
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
-       FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
+       FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
 
-       RETVAL_LONG(gmp_op(*gmpnum_a, *gmpnum_b));
+       RETVAL_LONG(gmp_op(gmpnum_a, gmpnum_b));
 
        FREE_GMP_TEMP(temp_a);
        FREE_GMP_TEMP(temp_b);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_init(mixed number [, int base])
+/* {{{ proto GMP gmp_init(mixed number [, int base])
    Initializes GMP number */
 ZEND_FUNCTION(gmp_init)
 {
-       zval **number_arg;
-       mpz_t * gmpnumber;
-       long base=0;
+       zval *number_arg;
+       mpz_ptr gmpnumber;
+       long base = 0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|l", &number_arg, &base) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &number_arg, &base) == FAILURE) {
                return;
        }
 
@@ -766,48 +1100,42 @@ ZEND_FUNCTION(gmp_init)
                RETURN_FALSE;
        }
 
-       if (convert_to_gmp(&gmpnumber, number_arg, base TSRMLS_CC) == FAILURE) {
+       INIT_GMP_RETVAL(gmpnumber);
+       if (convert_to_gmp(gmpnumber, number_arg, base TSRMLS_CC) == FAILURE) {
+               zval_dtor(return_value);
                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)
+/* {{{ proto int gmp_intval(mixed gmpnumber)
    Gets signed long value of GMP number */
 ZEND_FUNCTION(gmp_intval)
 {
-       zval **gmpnumber_arg;
-       mpz_t * gmpnum;
+       zval *gmpnumber_arg;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &gmpnumber_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &gmpnumber_arg) == FAILURE){
                return;
        }
        
-       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));
+       if (IS_GMP(gmpnumber_arg)) {
+               RETVAL_LONG(mpz_get_si(GET_GMP_FROM_ZVAL(gmpnumber_arg)));
        } else {
-               convert_to_long_ex(gmpnumber_arg);
-               RETVAL_LONG(Z_LVAL_PP(gmpnumber_arg));
+               RETVAL_LONG(gmp_get_long(gmpnumber_arg));
        }
 }
 /* }}} */
 
-/* {{{ proto string gmp_strval(resource gmpnumber [, int base])
+/* {{{ proto string gmp_strval(mixed gmpnumber [, int base])
    Gets string representation of GMP number  */
 ZEND_FUNCTION(gmp_strval)
 {
-       zval **gmpnumber_arg;
-       int num_len;
+       zval *gmpnumber_arg;
        long base = 10;
-       mpz_t * gmpnum;
-       char *out_string;
-       int temp_a;
+       mpz_ptr gmpnum;
+       gmp_temp_t temp_a;
 
-       if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "Z|l", &gmpnumber_arg, &base ) == FAILURE ) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &gmpnumber_arg, &base) == FAILURE) {
                return;
        }
 
@@ -825,162 +1153,138 @@ ZEND_FUNCTION(gmp_strval)
 
        FETCH_GMP_ZVAL(gmpnum, gmpnumber_arg, temp_a);
 
-       num_len = mpz_sizeinbase(*gmpnum, abs(base));
-       out_string = emalloc(num_len+2);
-       if (mpz_sgn(*gmpnum) < 0) {
-               num_len++;
-       }
-       mpz_get_str(out_string, base, *gmpnum);
-       
-       FREE_GMP_TEMP(temp_a);
-       
-       /* 
-       From GMP documentation for mpz_sizeinbase():
-       The returned value will be exact or 1 too big.  If base is a power of
-       2, the returned value will always be exact.
-
-       So let's check to see if we already have a \0 byte...
-       */
+       gmp_strval(return_value, gmpnum, base);
 
-       if (out_string[num_len-1] == '\0') {
-               num_len--;
-       } else {
-               out_string[num_len] = '\0';
-       }
-       RETVAL_STRINGL(out_string, num_len, 0);
+       FREE_GMP_TEMP(temp_a);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_add(resource a, resource b)
+/* {{{ proto GMP gmp_add(mixed a, mixed b)
    Add a and b */
 ZEND_FUNCTION(gmp_add)
 {
-       gmp_binary_ui_op(mpz_add, (gmp_binary_ui_op_t)mpz_add_ui);
+       gmp_binary_ui_op(mpz_add, mpz_add_ui);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_sub(resource a, resource b)
+/* {{{ proto GMP gmp_sub(mixed a, mixed b)
    Subtract b from a */
 ZEND_FUNCTION(gmp_sub)
 {
-       gmp_binary_ui_op(mpz_sub, (gmp_binary_ui_op_t)mpz_sub_ui);
+       gmp_binary_ui_op(mpz_sub, mpz_sub_ui);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_mul(resource a, resource b)
+/* {{{ proto GMP gmp_mul(mixed a, mixed b)
    Multiply a and b */
 ZEND_FUNCTION(gmp_mul)
 {
-       gmp_binary_ui_op(mpz_mul, (gmp_binary_ui_op_t)mpz_mul_ui);
+       gmp_binary_ui_op(mpz_mul, mpz_mul_ui);
 }
 /* }}} */
 
-/* {{{ proto array gmp_div_qr(resource a, resource b [, int round])
+/* {{{ proto array gmp_div_qr(mixed a, mixed b [, int round])
    Divide a by b, returns quotient and reminder */
 ZEND_FUNCTION(gmp_div_qr)
 {
-       zval **a_arg, **b_arg;
+       zval *a_arg, *b_arg;
        long round = GMP_ROUND_ZERO;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|l", &a_arg, &b_arg, &round) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &a_arg, &b_arg, &round) == FAILURE) {
                return;
        }
 
        switch (round) {
        case GMP_ROUND_ZERO:
-               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);
+               gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_tdiv_qr, (gmp_binary_ui_op2_t) mpz_tdiv_qr_ui, 1 TSRMLS_CC);
                break;
        case GMP_ROUND_PLUSINF:
-               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);
+               gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_cdiv_qr, (gmp_binary_ui_op2_t) mpz_cdiv_qr_ui, 1 TSRMLS_CC);
                break;
        case GMP_ROUND_MINUSINF:
-               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);
+               gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_fdiv_qr, (gmp_binary_ui_op2_t) mpz_fdiv_qr_ui, 1 TSRMLS_CC);
                break;
+       default:
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid rounding mode");
+               RETURN_FALSE;
        }
-                                                          
 }
 /* }}} */
 
-/* {{{ proto resource gmp_div_r(resource a, resource b [, int round])
+/* {{{ proto GMP gmp_div_r(mixed a, mixed b [, int round])
    Divide a by b, returns reminder only */
 ZEND_FUNCTION(gmp_div_r)
 {
-       zval **a_arg, **b_arg;
+       zval *a_arg, *b_arg;
        long round = GMP_ROUND_ZERO;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|l", &a_arg, &b_arg, &round) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &a_arg, &b_arg, &round) == FAILURE) {
                return;
        }
 
        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, 1, 1 TSRMLS_CC);
+               gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_r, (gmp_binary_ui_op_t) mpz_tdiv_r_ui, 1 TSRMLS_CC);
                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, 1, 1 TSRMLS_CC);
+               gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_r, (gmp_binary_ui_op_t) mpz_cdiv_r_ui, 1 TSRMLS_CC);
                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, 1, 1 TSRMLS_CC);
+               gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_r, (gmp_binary_ui_op_t) mpz_fdiv_r_ui, 1 TSRMLS_CC);
                break;
+       default:
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid rounding mode");
+               RETURN_FALSE;
        }
 }
 /* }}} */
 
-/* {{{ proto resource gmp_div_q(resource a, resource b [, int round])
+/* {{{ proto GMP gmp_div_q(mixed a, mixed b [, int round])
    Divide a by b, returns quotient only */
 ZEND_FUNCTION(gmp_div_q)
 {
-       zval **a_arg, **b_arg;
+       zval *a_arg, *b_arg;
        long round = GMP_ROUND_ZERO;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|l", &a_arg, &b_arg, &round) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &a_arg, &b_arg, &round) == FAILURE) {
                return;
        }
 
        switch (round) {
        case GMP_ROUND_ZERO:
-               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);
+               gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_q, (gmp_binary_ui_op_t) mpz_tdiv_q_ui, 1 TSRMLS_CC);
                break;
        case GMP_ROUND_PLUSINF:
-               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);
+               gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_q, (gmp_binary_ui_op_t) mpz_cdiv_q_ui, 1 TSRMLS_CC);
                break;
        case GMP_ROUND_MINUSINF:
-               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);
+               gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_q, (gmp_binary_ui_op_t) mpz_fdiv_q_ui, 1 TSRMLS_CC);
                break;
+       default:
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid rounding mode");
+               RETURN_FALSE;
        }
                                                           
 }
 /* }}} */
 
-/* {{{ proto resource gmp_mod(resource a, resource b)
+/* {{{ proto GMP gmp_mod(mixed a, mixed b)
    Computes a modulo b */
 ZEND_FUNCTION(gmp_mod)
 {
-       zval **a_arg, **b_arg;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
-               return;
-       }       
-
-       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);
+       gmp_binary_ui_op_no_zero(mpz_mod, (gmp_binary_ui_op_t) mpz_mod_ui);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_divexact(resource a, resource b)
+/* {{{ proto GMP gmp_divexact(mixed a, mixed b)
    Divide a by b using exact division algorithm */
 ZEND_FUNCTION(gmp_divexact)
 {
-       zval **a_arg, **b_arg;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
-               return;
-       }
-       
-       gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_divexact, NULL, 0, 1, 1 TSRMLS_CC);
+       gmp_binary_ui_op_no_zero(mpz_divexact, NULL);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_neg(resource a)
+/* {{{ proto GMP gmp_neg(mixed a)
    Negates a number */
 ZEND_FUNCTION(gmp_neg)
 {
@@ -988,7 +1292,7 @@ ZEND_FUNCTION(gmp_neg)
 }
 /* }}} */
 
-/* {{{ proto resource gmp_abs(resource a)
+/* {{{ proto GMP gmp_abs(mixed a)
    Calculates absolute value */
 ZEND_FUNCTION(gmp_abs)
 {
@@ -996,99 +1300,92 @@ ZEND_FUNCTION(gmp_abs)
 }
 /* }}} */
 
-/* {{{ proto resource gmp_fact(int a)
+/* {{{ proto GMP gmp_fact(int a)
    Calculates factorial function */
 ZEND_FUNCTION(gmp_fact)
 {
-       zval **a_arg;
-       mpz_t *gmpnum_tmp;
-       int temp_a;
+       zval *a_arg;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){
                return;
        }
 
-       if (Z_TYPE_PP(a_arg) == IS_RESOURCE) {
-               FETCH_GMP_ZVAL(gmpnum_tmp, a_arg, temp_a);      /* no need to free this since it's IS_RESOURCE */
-               if (mpz_sgn(*gmpnum_tmp) < 0) {
+       if (IS_GMP(a_arg)) {
+               mpz_ptr gmpnum_tmp = GET_GMP_FROM_ZVAL(a_arg);
+               if (mpz_sgn(gmpnum_tmp) < 0) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0");
                        RETURN_FALSE;
                }
        } else {
-               convert_to_long_ex(a_arg);
-               if (Z_LVAL_PP(a_arg) < 0) {
+               if (gmp_get_long(a_arg) < 0) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0");
                        RETURN_FALSE;
                }
        }
-               
+
        gmp_zval_unary_ui_op(return_value, a_arg, mpz_fac_ui TSRMLS_CC);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_pow(resource base, int exp)
+/* {{{ proto GMP gmp_pow(mixed base, int exp)
    Raise base to power exp */
 ZEND_FUNCTION(gmp_pow)
 {
-       zval **base_arg;
-       mpz_t *gmpnum_result, *gmpnum_base;
-       int use_ui = 0;
-       int temp_base;
+       zval *base_arg;
+       mpz_ptr gmpnum_result, gmpnum_base;
+       gmp_temp_t temp_base;
        long exp;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &base_arg, &exp) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &base_arg, &exp) == FAILURE) {
                return;
        }
 
-       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, temp_base);
-       }
-
        if (exp < 0) {
                php_error_docref(NULL TSRMLS_CC, 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), exp);
+       INIT_GMP_RETVAL(gmpnum_result);
+       if (Z_TYPE_P(base_arg) == IS_LONG && Z_LVAL_P(base_arg) >= 0) {
+               mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp);
        } else {
-               mpz_pow_ui(*gmpnum_result, *gmpnum_base, exp);
+               FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base);
+               mpz_pow_ui(gmpnum_result, gmpnum_base, exp);
                FREE_GMP_TEMP(temp_base);
        }
-       ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_powm(resource base, resource exp, resource mod)
+/* {{{ proto GMP gmp_powm(mixed base, mixed exp, mixed 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;
+       zval *base_arg, *exp_arg, *mod_arg;
+       mpz_ptr gmpnum_base, gmpnum_exp, gmpnum_mod, gmpnum_result;
        int use_ui = 0;
-       int temp_base, temp_exp, temp_mod;
+       gmp_temp_t temp_base, temp_exp, temp_mod;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ", &base_arg, &exp_arg, &mod_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzz", &base_arg, &exp_arg, &mod_arg) == FAILURE){
                return;
        }
 
        FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base);
 
-       if (Z_TYPE_PP(exp_arg) == IS_LONG && Z_LVAL_PP(exp_arg) >= 0) {
+       if (Z_TYPE_P(exp_arg) == IS_LONG && Z_LVAL_P(exp_arg) >= 0) {
                use_ui = 1;
+               temp_exp.is_used = 0;
        } else {
-               FETCH_GMP_ZVAL(gmpnum_exp, exp_arg, temp_exp);
-               if (mpz_sgn(*gmpnum_exp) < 0) {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING,"Second parameter cannot be less than 0");
+               FETCH_GMP_ZVAL_DEP(gmpnum_exp, exp_arg, temp_exp, temp_base);
+               if (mpz_sgn(gmpnum_exp) < 0) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Second parameter cannot be less than 0");
+                       FREE_GMP_TEMP(temp_base);
+                       FREE_GMP_TEMP(temp_exp);
                        RETURN_FALSE;
                }
        }
-       FETCH_GMP_ZVAL(gmpnum_mod, mod_arg, temp_mod);
+       FETCH_GMP_ZVAL_DEP_DEP(gmpnum_mod, mod_arg, temp_mod, temp_exp, temp_base);
 
-       if (!mpz_cmp_ui(*gmpnum_mod, 0)) {
+       if (!mpz_cmp_ui(gmpnum_mod, 0)) {
                FREE_GMP_TEMP(temp_base);
                if (use_ui) {
                        FREE_GMP_TEMP(temp_exp);
@@ -1097,202 +1394,175 @@ ZEND_FUNCTION(gmp_powm)
                RETURN_FALSE;
        }
 
-       INIT_GMP_NUM(gmpnum_result);
+       INIT_GMP_RETVAL(gmpnum_result);
        if (use_ui) {
-               mpz_powm_ui(*gmpnum_result, *gmpnum_base, (unsigned long)Z_LVAL_PP(exp_arg), *gmpnum_mod);
+               mpz_powm_ui(gmpnum_result, gmpnum_base, (unsigned long) Z_LVAL_P(exp_arg), gmpnum_mod);
        } else {
-               mpz_powm(*gmpnum_result, *gmpnum_base, *gmpnum_exp, *gmpnum_mod);
+               mpz_powm(gmpnum_result, gmpnum_base, gmpnum_exp, gmpnum_mod);
                FREE_GMP_TEMP(temp_exp);
        }
 
        FREE_GMP_TEMP(temp_base);
        FREE_GMP_TEMP(temp_mod);
-
-       ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
-
 }
 /* }}} */
 
-/* {{{ proto resource gmp_sqrt(resource a)
+/* {{{ proto GMP gmp_sqrt(mixed a)
    Takes integer part of square root of a */
 ZEND_FUNCTION(gmp_sqrt)
 {
-       zval **a_arg;
-       mpz_t *gmpnum_a, *gmpnum_result;
-       int temp_a;
+       zval *a_arg;
+       mpz_ptr gmpnum_a, gmpnum_result;
+       gmp_temp_t temp_a;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){
                return;
        }
        
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
 
-       if (mpz_sgn(*gmpnum_a) < 0) {
+       if (mpz_sgn(gmpnum_a) < 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0");
                FREE_GMP_TEMP(temp_a);
                RETURN_FALSE;
        }       
-       
-       INIT_GMP_NUM(gmpnum_result);
-       mpz_sqrt(*gmpnum_result, *gmpnum_a);
-       FREE_GMP_TEMP(temp_a);
 
-       ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
+       INIT_GMP_RETVAL(gmpnum_result);
+       mpz_sqrt(gmpnum_result, gmpnum_a);
+       FREE_GMP_TEMP(temp_a);
 }
 /* }}} */
 
-/* {{{ proto array gmp_sqrtrem(resource a)
+/* {{{ proto array gmp_sqrtrem(mixed a)
    Square root with remainder */
 ZEND_FUNCTION(gmp_sqrtrem)
 {
-       zval **a_arg;
-       mpz_t *gmpnum_a, *gmpnum_result1, *gmpnum_result2;
-       zval r;
-       int temp_a;
+       zval *a_arg;
+       mpz_ptr gmpnum_a, gmpnum_result1, gmpnum_result2;
+       gmp_temp_t temp_a;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){
                return;
        }
 
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
-       
-       if (mpz_sgn(*gmpnum_a) < 0) {
-               php_error_docref(NULL TSRMLS_CC, E_WARNING,"Number has to be greater than or equal to 0");
+
+       if (mpz_sgn(gmpnum_a) < 0) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0");
+               FREE_GMP_TEMP(temp_a);
                RETURN_FALSE;
        }
        
-       INIT_GMP_NUM(gmpnum_result1);
-       INIT_GMP_NUM(gmpnum_result2);
+       array_init(return_value);
+       add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC));
+       add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC));
 
-       mpz_sqrtrem(*gmpnum_result1, *gmpnum_result2, *gmpnum_a);
+       mpz_sqrtrem(gmpnum_result1, gmpnum_result2, gmpnum_a);
        FREE_GMP_TEMP(temp_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)
+/* {{{ proto bool gmp_perfect_square(mixed a)
    Checks if a is an exact square */
 ZEND_FUNCTION(gmp_perfect_square)
 {
-       zval **a_arg;
-       mpz_t *gmpnum_a;
-       int temp_a;
+       zval *a_arg;
+       mpz_ptr gmpnum_a;
+       gmp_temp_t temp_a;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){
                return;
        }
 
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
 
-       RETVAL_BOOL((mpz_perfect_square_p(*gmpnum_a)!=0));
+       RETVAL_BOOL((mpz_perfect_square_p(gmpnum_a) != 0));
        FREE_GMP_TEMP(temp_a);
 }
 /* }}} */
 
-/* {{{ proto int gmp_prob_prime(resource a[, int reps])
+/* {{{ proto int gmp_prob_prime(mixed a[, int reps])
    Checks if a is "probably prime" */
 ZEND_FUNCTION(gmp_prob_prime)
 {
-       zval **gmpnumber_arg;
-       mpz_t *gmpnum_a;
+       zval *gmpnumber_arg;
+       mpz_ptr gmpnum_a;
        long reps = 10;
-       int temp_a;
+       gmp_temp_t temp_a;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|l", &gmpnumber_arg, &reps) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &gmpnumber_arg, &reps) == FAILURE) {
                return;
        }
 
        FETCH_GMP_ZVAL(gmpnum_a, gmpnumber_arg, temp_a);
 
-       RETVAL_LONG(mpz_probab_prime_p(*gmpnum_a, reps));
+       RETVAL_LONG(mpz_probab_prime_p(gmpnum_a, reps));
        FREE_GMP_TEMP(temp_a);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_gcd(resource a, resource b)
+/* {{{ proto GMP gmp_gcd(mixed a, mixed b)
    Computes greatest common denominator (gcd) of a and b */
 ZEND_FUNCTION(gmp_gcd)
 {
-       zval **a_arg, **b_arg;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
-               return;
-       }
-
-       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);
+       gmp_binary_ui_op(mpz_gcd, (gmp_binary_ui_op_t) mpz_gcd_ui);
 }
 /* }}} */
 
-/* {{{ proto array gmp_gcdext(resource a, resource b)
+/* {{{ proto array gmp_gcdext(mixed a, mixed b)
    Computes 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;
-       int temp_a, temp_b;
+       zval *a_arg, *b_arg;
+       mpz_ptr gmpnum_a, gmpnum_b, gmpnum_t, gmpnum_s, gmpnum_g;
+       gmp_temp_t temp_a, temp_b;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){
                return;
        }
 
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
-       FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
+       FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
 
-       INIT_GMP_NUM(gmpnum_g);
-       INIT_GMP_NUM(gmpnum_s);
-       INIT_GMP_NUM(gmpnum_t);
+       array_init(return_value);
+       add_assoc_zval(return_value, "g", gmp_create(&gmpnum_g TSRMLS_CC));
+       add_assoc_zval(return_value, "s", gmp_create(&gmpnum_s TSRMLS_CC));
+       add_assoc_zval(return_value, "t", gmp_create(&gmpnum_t TSRMLS_CC));
 
-       mpz_gcdext(*gmpnum_g, *gmpnum_s, *gmpnum_t, *gmpnum_a, *gmpnum_b);
+       mpz_gcdext(gmpnum_g, gmpnum_s, gmpnum_t, gmpnum_a, gmpnum_b);
        FREE_GMP_TEMP(temp_a);
        FREE_GMP_TEMP(temp_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)
+/* {{{ proto GMP gmp_invert(mixed a, mixed b)
    Computes the inverse of a modulo b */
 ZEND_FUNCTION(gmp_invert)
 {
-       zval **a_arg, **b_arg;
-       mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result;
-       int temp_a, temp_b;
+       zval *a_arg, *b_arg;
+       mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result;
+       gmp_temp_t temp_a, temp_b;
        int res;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){
                return;
        }
 
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
-       FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
+       FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
 
-       INIT_GMP_NUM(gmpnum_result);
-       res=mpz_invert(*gmpnum_result, *gmpnum_a, *gmpnum_b);
+       INIT_GMP_RETVAL(gmpnum_result);
+       res = mpz_invert(gmpnum_result, gmpnum_a, gmpnum_b);
        FREE_GMP_TEMP(temp_a);
        FREE_GMP_TEMP(temp_b);
-       if (res) {
-               ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
-       } else {
-               FREE_GMP_NUM(gmpnum_result);
+       if (!res) {
+               zval_dtor(return_value);
                RETURN_FALSE;
        }
 }
 /* }}} */
 
-/* {{{ proto int gmp_jacobi(resource a, resource b)
+/* {{{ proto int gmp_jacobi(mixed a, mixed b)
    Computes Jacobi symbol */
 ZEND_FUNCTION(gmp_jacobi)
 {
@@ -1300,7 +1570,7 @@ ZEND_FUNCTION(gmp_jacobi)
 }
 /* }}} */
 
-/* {{{ proto int gmp_legendre(resource a, resource b)
+/* {{{ proto int gmp_legendre(mixed a, mixed b)
    Computes Legendre symbol */
 ZEND_FUNCTION(gmp_legendre)
 {
@@ -1308,69 +1578,51 @@ ZEND_FUNCTION(gmp_legendre)
 }
 /* }}} */
 
-/* {{{ proto int gmp_cmp(resource a, resource b)
+/* {{{ proto int gmp_cmp(mixed a, mixed b)
    Compares two numbers */
 ZEND_FUNCTION(gmp_cmp)
 {
-       zval **a_arg, **b_arg;
-       mpz_t *gmpnum_a, *gmpnum_b;
-       int use_si = 0, res;
-       int temp_a, temp_b;
+       zval *a_arg, *b_arg;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){
                return;
        }
 
-       FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
-
-       if (Z_TYPE_PP(b_arg) == IS_LONG) {
-               use_si = 1;
-       } else {
-               FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
-       }
-
-       if (use_si) {
-               res = mpz_cmp_si(*gmpnum_a, Z_LVAL_PP(b_arg));
-       } else {
-               res = mpz_cmp(*gmpnum_a, *gmpnum_b);
-       }
-       FREE_GMP_TEMP(temp_a);
-       
-       RETURN_LONG(res);
+       gmp_cmp(return_value, a_arg, b_arg TSRMLS_CC);
 }
 /* }}} */
 
-/* {{{ proto int gmp_sign(resource a)
+/* {{{ proto int gmp_sign(mixed a)
    Gets the sign of the number */
 ZEND_FUNCTION(gmp_sign)
 {
-       zval **a_arg;
-       mpz_t *gmpnum_a;
-       int temp_a;
+       zval *a_arg;
+       mpz_ptr gmpnum_a;
+       gmp_temp_t temp_a;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){
                return;
        }
        
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
 
-       RETVAL_LONG(mpz_sgn(*gmpnum_a));
+       RETVAL_LONG(mpz_sgn(gmpnum_a));
        FREE_GMP_TEMP(temp_a);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_random([int limiter])
+/* {{{ proto GMP gmp_random([int limiter])
    Gets random number */
 ZEND_FUNCTION(gmp_random)
 {
        long limiter = 20;
-       mpz_t *gmpnum_result;
+       mpz_ptr gmpnum_result;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &limiter) == FAILURE) {
                return;
        }
 
-       INIT_GMP_NUM(gmpnum_result);
+       INIT_GMP_RETVAL(gmpnum_result);
 
        if (!GMPG(rand_initialized)) {
                /* Initialize */
@@ -1382,15 +1634,14 @@ ZEND_FUNCTION(gmp_random)
                GMPG(rand_initialized) = 1;
        }
 #ifdef GMP_LIMB_BITS
-       mpz_urandomb(*gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * GMP_LIMB_BITS);
+       mpz_urandomb(gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * GMP_LIMB_BITS);
 #else
-       mpz_urandomb(*gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * __GMP_BITS_PER_MP_LIMB);
+       mpz_urandomb(gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * __GMP_BITS_PER_MP_LIMB);
 #endif
-       ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
 }
 /* }}} */
 
-/* {{{ proto resource gmp_and(resource a, resource b)
+/* {{{ proto GMP gmp_and(mixed a, mixed b)
    Calculates logical AND of a and b */
 ZEND_FUNCTION(gmp_and)
 {
@@ -1398,7 +1649,7 @@ ZEND_FUNCTION(gmp_and)
 }
 /* }}} */
 
-/* {{{ proto resource gmp_or(resource a, resource b)
+/* {{{ proto GMP gmp_or(mixed a, mixed b)
    Calculates logical OR of a and b */
 ZEND_FUNCTION(gmp_or)
 {
@@ -1406,7 +1657,7 @@ ZEND_FUNCTION(gmp_or)
 }
 /* }}} */
 
-/* {{{ proto resource gmp_com(resource a)
+/* {{{ proto GMP gmp_com(mixed a)
    Calculates one's complement of a */
 ZEND_FUNCTION(gmp_com)
 {
@@ -1414,7 +1665,7 @@ ZEND_FUNCTION(gmp_com)
 }
 /* }}} */
 
-/* {{{ proto resource gmp_nextprime(resource a)
+/* {{{ proto GMP gmp_nextprime(mixed a)
    Finds next prime of a */
 ZEND_FUNCTION(gmp_nextprime)
 {
@@ -1422,21 +1673,22 @@ ZEND_FUNCTION(gmp_nextprime)
 }
 /* }}} */
 
-/* {{{ proto resource gmp_xor(resource a, resource b)
+/* {{{ proto GMP gmp_xor(mixed a, mixed b)
    Calculates logical exclusive OR of a and b */
 ZEND_FUNCTION(gmp_xor)
 {
-       /* use formula: a^b = (a|b)&^(a&b) */
-       zval **a_arg, **b_arg;
+       gmp_binary_op(mpz_xor);
+       /* use formula: a^b = (a|b)&~(a&b) */
+       /*zval **a_arg, **b_arg;
        mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result, *gmpnum_t;
-       int temp_a, temp_b;
+       gmp_temp_t temp_a, temp_b;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
                return;
        }
 
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
-       FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
+       FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
 
        INIT_GMP_NUM(gmpnum_result);
        INIT_GMP_NUM(gmpnum_t);
@@ -1451,183 +1703,169 @@ ZEND_FUNCTION(gmp_xor)
 
        FREE_GMP_TEMP(temp_a);
        FREE_GMP_TEMP(temp_b);
-       ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp);
+       RETVAL_GMP(gmpnum_result);*/
 }
 /* }}} */
 
-/* {{{ proto void gmp_setbit(resource &a, int index[, bool set_clear])
+/* {{{ proto void gmp_setbit(GMP &a, int index[, bool set_clear])
    Sets or clear bit in a */
 ZEND_FUNCTION(gmp_setbit)
 {
-       zval **a_arg;
+       zval *a_arg;
        long index;
        zend_bool set = 1;
-       mpz_t *gmpnum_a;
+       mpz_ptr gmpnum_a;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl|b", &a_arg, &index, &set) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|b", &a_arg, gmp_ce, &index, &set) == FAILURE) {
                return;
        }
 
-       ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp);
-
        if (index < 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Index must be greater than or equal to zero");
                return;
        }
 
+       gmpnum_a = GET_GMP_FROM_ZVAL(a_arg);
+
        if (set) {
-               mpz_setbit(*gmpnum_a, index);
+               mpz_setbit(gmpnum_a, index);
        } else {
-               mpz_clrbit(*gmpnum_a, index);
+               mpz_clrbit(gmpnum_a, index);
        }
 }
 /* }}} */
 
-/* {{{ proto void gmp_clrbit(resource &a, int index)
+/* {{{ proto void gmp_clrbit(GMP &a, int index)
    Clears bit in a */
 ZEND_FUNCTION(gmp_clrbit)
 {
-       zval **a_arg;
+       zval *a_arg;
        long index;
-       mpz_t *gmpnum_a;
+       mpz_ptr gmpnum_a;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &index) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &a_arg, gmp_ce, &index) == FAILURE){
                return;
        }
 
-       ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp);
-
        if (index < 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Index must be greater than or equal to zero");
                return;
        }
 
-       mpz_clrbit(*gmpnum_a, index);
+       gmpnum_a = GET_GMP_FROM_ZVAL(a_arg);
+       mpz_clrbit(gmpnum_a, index);
 }
 /* }}} */
 
-/* {{{ proto bool gmp_testbit(resource a, int index)
+/* {{{ proto bool gmp_testbit(mixed a, int index)
    Tests if bit is set in a */
 ZEND_FUNCTION(gmp_testbit)
 {
-       zval **a_arg;
+       zval *a_arg;
        long index;
-       mpz_t *gmpnum_a;
+       mpz_ptr gmpnum_a;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &index) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &index) == FAILURE){
                return;
        }
 
-       ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp);
-
        if (index < 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Index must be greater than or equal to zero");
                RETURN_FALSE;
        }
 
-       if (mpz_tstbit(*gmpnum_a, index)) {
-               RETURN_TRUE;
-       }
-       RETURN_FALSE;
+       gmpnum_a = GET_GMP_FROM_ZVAL(a_arg);
+       RETURN_BOOL(mpz_tstbit(gmpnum_a, index));
 }
 /* }}} */
 
-/* {{{ proto int gmp_popcount(resource a)
+/* {{{ proto int gmp_popcount(mixed a)
    Calculates the population count of a */
 ZEND_FUNCTION(gmp_popcount)
 {
-       zval **a_arg;
-       mpz_t *gmpnum_a;
-       int temp_a;
+       zval *a_arg;
+       mpz_ptr gmpnum_a;
+       gmp_temp_t temp_a;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){
                return;
        }
        
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
 
-       RETVAL_LONG(mpz_popcount(*gmpnum_a));
+       RETVAL_LONG(mpz_popcount(gmpnum_a));
        FREE_GMP_TEMP(temp_a);
 }
 /* }}} */
 
-/* {{{ proto int gmp_hamdist(resource a, resource b)
+/* {{{ proto int gmp_hamdist(mixed a, mixed b)
    Calculates hamming distance between a and b */
 ZEND_FUNCTION(gmp_hamdist)
 {
-       zval **a_arg, **b_arg;
-       mpz_t *gmpnum_a, *gmpnum_b;
-       int temp_a, temp_b;
+       zval *a_arg, *b_arg;
+       mpz_ptr gmpnum_a, gmpnum_b;
+       gmp_temp_t temp_a, temp_b;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){
                return;
        }
 
        FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
-       FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b);
+       FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
 
-       RETVAL_LONG(mpz_hamdist(*gmpnum_a, *gmpnum_b));
+       RETVAL_LONG(mpz_hamdist(gmpnum_a, gmpnum_b));
        FREE_GMP_TEMP(temp_a);
        FREE_GMP_TEMP(temp_b);
 }
 /* }}} */
 
-/* {{{ proto int gmp_scan0(resource a, int start)
+/* {{{ proto int gmp_scan0(mixed a, int start)
    Finds first zero bit */
 ZEND_FUNCTION(gmp_scan0)
 {
-       zval **a_arg;
-       mpz_t *gmpnum_a;
-       int temp_a;
+       zval *a_arg;
+       mpz_ptr gmpnum_a;
+       gmp_temp_t temp_a;
        long start;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &start) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &start) == FAILURE){
                return;
        }
 
-       FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
-
        if (start < 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Starting index must be greater than or equal to zero");
                RETURN_FALSE;
        }
 
-       RETVAL_LONG(mpz_scan0(*gmpnum_a, start));
+       FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
+
+       RETVAL_LONG(mpz_scan0(gmpnum_a, start));
        FREE_GMP_TEMP(temp_a);
 }
 /* }}} */
 
-/* {{{ proto int gmp_scan1(resource a, int start)
+/* {{{ proto int gmp_scan1(mixed a, int start)
    Finds first non-zero bit */
 ZEND_FUNCTION(gmp_scan1)
 {
-       zval **a_arg;
-       mpz_t *gmpnum_a;
-       int temp_a;
+       zval *a_arg;
+       mpz_ptr gmpnum_a;
+       gmp_temp_t temp_a;
        long start;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &start) == FAILURE){
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &start) == FAILURE){
                return;
        }
 
-       FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
        if (start < 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Starting index must be greater than or equal to zero");
                RETURN_FALSE;
        }
 
-       RETVAL_LONG(mpz_scan1(*gmpnum_a, start));
-       FREE_GMP_TEMP(temp_a);
-}
-/* }}} */
-
-/* {{{ _php_gmpnum_free
- */
-static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
-       mpz_t *gmpnum = (mpz_t *)rsrc->ptr;
+       FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
 
-       FREE_GMP_NUM(gmpnum);
+       RETVAL_LONG(mpz_scan1(gmpnum_a, start));
+       FREE_GMP_TEMP(temp_a);
 }
 /* }}} */
 
index a0fa1cd133c91f55274bea18fe9128512ef3bdcb..088dd08fd8ee40ad3efa4a74fd089aa453c348c4 100644 (file)
@@ -38,8 +38,6 @@ int(2342344)
 Notice: Object of class stdClass could not be converted to int in %s on line %d
 int(1)
 int(0)
-
-Warning: gmp_intval(): supplied resource is not a valid GMP integer resource in %s on line %d
-bool(false)
+int(%d)
 int(12345678)
 Done
index 7907ffbf53e940c663a07b43894cd8f570fd5a39..4ae0cb750a4155092ca0763d7bcd647393659063 100644 (file)
@@ -47,7 +47,7 @@ bool(false)
 Warning: gmp_strval() expects parameter 2 to be long, string given in %s on line %d
 NULL
 
-Warning: gmp_strval(): supplied resource is not a valid GMP integer resource in %s on line %d
+Warning: gmp_strval(): Unable to convert variable to GMP - wrong type in %s on line %d
 bool(false)
 string(7) "9765456"
 
index dedbcd04726a639e34078d2f57a918a6216dfc5b..740760631d4e652b8b87ea148340de32aa79beaf 100644 (file)
@@ -35,9 +35,15 @@ NULL
 
 Warning: gmp_sub(): Unable to convert variable to GMP - wrong type in %s on line %d
 bool(false)
-resource(%d) of type (GMP integer)
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "-1"
+}
 string(2) "-1"
-resource(%d) of type (GMP integer)
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(5) "10001"
+}
 string(5) "10001"
 
 Warning: gmp_sub(): Unable to convert variable to GMP - wrong type in %s on line %d
index 4d4a993a1729af1e93cfffe93ccf1e152bbc03f1..e391c121f8d1d3fad96d58da98c39956918536f5 100644 (file)
@@ -8,34 +8,16 @@ gmp_div_qr() tests
 var_dump(gmp_div_qr());
 var_dump(gmp_div_qr(""));
 
-var_dump($r = gmp_div_qr(0,1));
-var_dump(gmp_strval($r[0]));
-var_dump(gmp_strval($r[1]));
-var_dump($r = gmp_div_qr(1,0));
-var_dump($r = gmp_div_qr(12653,23482734));
-var_dump(gmp_strval($r[0]));
-var_dump(gmp_strval($r[1]));
-var_dump($r = gmp_div_qr(12653,23482734, 10));
-var_dump(gmp_strval($r[0]));
-var_dump(gmp_strval($r[1]));
-var_dump($r = gmp_div_qr(1123123,123));
-var_dump(gmp_strval($r[0]));
-var_dump(gmp_strval($r[1]));
-var_dump($r = gmp_div_qr(1123123,123, 1));
-var_dump(gmp_strval($r[0]));
-var_dump(gmp_strval($r[1]));
-var_dump($r = gmp_div_qr(1123123,123, 2));
-var_dump(gmp_strval($r[0]));
-var_dump(gmp_strval($r[1]));
-var_dump($r = gmp_div_qr(1123123,123, GMP_ROUND_ZERO));
-var_dump(gmp_strval($r[0]));
-var_dump(gmp_strval($r[1]));
-var_dump($r = gmp_div_qr(1123123,123, GMP_ROUND_PLUSINF));
-var_dump(gmp_strval($r[0]));
-var_dump(gmp_strval($r[1]));
-var_dump($r = gmp_div_qr(1123123,123, GMP_ROUND_MINUSINF));
-var_dump(gmp_strval($r[0]));
-var_dump(gmp_strval($r[1]));
+var_dump(gmp_div_qr(0,1));
+var_dump(gmp_div_qr(1,0));
+var_dump(gmp_div_qr(12653,23482734));
+var_dump(gmp_div_qr(12653,23482734, 10));
+var_dump(gmp_div_qr(1123123,123));
+var_dump(gmp_div_qr(1123123,123, 1));
+var_dump(gmp_div_qr(1123123,123, 2));
+var_dump(gmp_div_qr(1123123,123, GMP_ROUND_ZERO));
+var_dump(gmp_div_qr(1123123,123, GMP_ROUND_PLUSINF));
+var_dump(gmp_div_qr(1123123,123, GMP_ROUND_MINUSINF));
 
 $fp = fopen(__FILE__, 'r');
 
@@ -52,80 +34,108 @@ Warning: gmp_div_qr() expects at least 2 parameters, 1 given in %s on line %d
 NULL
 array(2) {
   [0]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(1) "0"
+  }
   [1]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(1) "0"
+  }
 }
-string(1) "0"
-string(1) "0"
 
 Warning: gmp_div_qr(): Zero operand not allowed in %s on line %d
 bool(false)
 array(2) {
   [0]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(1) "0"
+  }
   [1]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(5) "12653"
+  }
 }
-string(1) "0"
-string(5) "12653"
-NULL
-
-Warning: gmp_strval(): Unable to convert variable to GMP - wrong type in %s on line %d
-bool(false)
 
-Warning: gmp_strval(): Unable to convert variable to GMP - wrong type in %s on line %d
+Warning: gmp_div_qr(): Invalid rounding mode in %s on line %d
 bool(false)
 array(2) {
   [0]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(4) "9131"
+  }
   [1]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(2) "10"
+  }
 }
-string(4) "9131"
-string(2) "10"
 array(2) {
   [0]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(4) "9132"
+  }
   [1]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(4) "-113"
+  }
 }
-string(4) "9132"
-string(4) "-113"
 array(2) {
   [0]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(4) "9131"
+  }
   [1]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(2) "10"
+  }
 }
-string(4) "9131"
-string(2) "10"
 array(2) {
   [0]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(4) "9131"
+  }
   [1]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(2) "10"
+  }
 }
-string(4) "9131"
-string(2) "10"
 array(2) {
   [0]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(4) "9132"
+  }
   [1]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(4) "-113"
+  }
 }
-string(4) "9132"
-string(4) "-113"
 array(2) {
   [0]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(4) "9131"
+  }
   [1]=>
-  resource(%d) of type (GMP integer)
+  object(GMP)#%d (1) {
+    ["num"]=>
+    string(2) "10"
+  }
 }
-string(4) "9131"
-string(2) "10"
 
-Warning: gmp_div_qr(): supplied resource is not a valid GMP integer resource in %s on line %d
+Warning: gmp_div_qr(): Unable to convert variable to GMP - wrong type in %s on line %d
 bool(false)
 
 Warning: gmp_div_qr(): Unable to convert variable to GMP - wrong type in %s on line %d
index 4e44ec10bf88446c6d1d4fb83b74aeb9f7d1eaff..c1874c86f901fa5a67774328ea7147baee46c074 100644 (file)
@@ -9,24 +9,15 @@ var_dump(gmp_div_r());
 var_dump(gmp_div_r(""));
 
 var_dump($r = gmp_div_r(0,1));
-var_dump(gmp_strval($r));
 var_dump($r = gmp_div_r(1,0));
 var_dump($r = gmp_div_r(12653,23482734));
-var_dump(gmp_strval($r));
 var_dump($r = gmp_div_r(12653,23482734, 10));
-var_dump(gmp_strval($r));
 var_dump($r = gmp_div_r(1123123,123));
-var_dump(gmp_strval($r));
 var_dump($r = gmp_div_r(1123123,123, 1));
-var_dump(gmp_strval($r));
 var_dump($r = gmp_div_r(1123123,123, 2));
-var_dump(gmp_strval($r));
 var_dump($r = gmp_div_r(1123123,123, GMP_ROUND_ZERO));
-var_dump(gmp_strval($r));
 var_dump($r = gmp_div_r(1123123,123, GMP_ROUND_PLUSINF));
-var_dump(gmp_strval($r));
 var_dump($r = gmp_div_r(1123123,123, GMP_ROUND_MINUSINF));
-var_dump(gmp_strval($r));
 
 $fp = fopen(__FILE__, 'r');
 
@@ -41,31 +32,46 @@ NULL
 
 Warning: gmp_div_r() expects at least 2 parameters, 1 given in %s on line %d
 NULL
-int(0)
-string(1) "0"
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "0"
+}
 
 Warning: gmp_div_r(): Zero operand not allowed in %s on line %d
 bool(false)
-int(12653)
-string(5) "12653"
-NULL
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(5) "12653"
+}
 
-Warning: gmp_strval(): Unable to convert variable to GMP - wrong type in %s on line %d
+Warning: gmp_div_r(): Invalid rounding mode in %s on line %d
 bool(false)
-int(10)
-string(2) "10"
-int(113)
-string(3) "113"
-int(10)
-string(2) "10"
-int(10)
-string(2) "10"
-int(113)
-string(3) "113"
-int(10)
-string(2) "10"
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "10"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(4) "-113"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "10"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "10"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(4) "-113"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "10"
+}
 
-Warning: gmp_div_r(): supplied resource is not a valid GMP integer resource in %s on line %d
+Warning: gmp_div_r(): Unable to convert variable to GMP - wrong type in %s on line %d
 bool(false)
 
 Warning: gmp_div_r(): Unable to convert variable to GMP - wrong type in %s on line %d
index 745a4ef63841922e7c3bbc06082a4c5622e92fd1..3b75a48e1825b4ed55a014ffb7a97d2cb25bd881 100644 (file)
@@ -8,25 +8,16 @@ gmp_div_q() tests
 var_dump(gmp_div_q());
 var_dump(gmp_div_q(""));
 
-var_dump($r = gmp_div_q(0,1));
-var_dump(gmp_strval($r));
-var_dump($r = gmp_div_q(1,0));
-var_dump($r = gmp_div_q(12653,23482734));
-var_dump(gmp_strval($r));
-var_dump($r = gmp_div_q(12653,23482734, 10));
-var_dump(gmp_strval($r));
-var_dump($r = gmp_div_q(1123123,123));
-var_dump(gmp_strval($r));
-var_dump($r = gmp_div_q(1123123,123, 1));
-var_dump(gmp_strval($r));
-var_dump($r = gmp_div_q(1123123,123, 2));
-var_dump(gmp_strval($r));
-var_dump($r = gmp_div_q(1123123,123, GMP_ROUND_ZERO));
-var_dump(gmp_strval($r));
-var_dump($r = gmp_div_q(1123123,123, GMP_ROUND_PLUSINF));
-var_dump(gmp_strval($r));
-var_dump($r = gmp_div_q(1123123,123, GMP_ROUND_MINUSINF));
-var_dump(gmp_strval($r));
+var_dump(gmp_div_q(0,1));
+var_dump(gmp_div_q(1,0));
+var_dump(gmp_div_q(12653,23482734));
+var_dump(gmp_div_q(12653,23482734, 10));
+var_dump(gmp_div_q(1123123,123));
+var_dump(gmp_div_q(1123123,123, 1));
+var_dump(gmp_div_q(1123123,123, 2));
+var_dump(gmp_div_q(1123123,123, GMP_ROUND_ZERO));
+var_dump(gmp_div_q(1123123,123, GMP_ROUND_PLUSINF));
+var_dump(gmp_div_q(1123123,123, GMP_ROUND_MINUSINF));
 
 $fp = fopen(__FILE__, 'r');
 
@@ -41,31 +32,46 @@ NULL
 
 Warning: gmp_div_q() expects at least 2 parameters, 1 given in %s on line %d
 NULL
-resource(%d) of type (GMP integer)
-string(1) "0"
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "0"
+}
 
 Warning: gmp_div_q(): Zero operand not allowed in %s on line %d
 bool(false)
-resource(%d) of type (GMP integer)
-string(1) "0"
-NULL
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "0"
+}
 
-Warning: gmp_strval(): Unable to convert variable to GMP - wrong type in %s on line %d
+Warning: gmp_div_q(): Invalid rounding mode %s on line %d
 bool(false)
-resource(%d) of type (GMP integer)
-string(4) "9131"
-resource(%d) of type (GMP integer)
-string(4) "9132"
-resource(%d) of type (GMP integer)
-string(4) "9131"
-resource(%d) of type (GMP integer)
-string(4) "9131"
-resource(%d) of type (GMP integer)
-string(4) "9132"
-resource(%d) of type (GMP integer)
-string(4) "9131"
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(4) "9131"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(4) "9132"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(4) "9131"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(4) "9131"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(4) "9132"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(4) "9131"
+}
 
-Warning: gmp_div_q(): supplied resource is not a valid GMP integer resource in %s on line %d
+Warning: gmp_div_q(): Unable to convert variable to GMP - wrong type in %s on line %d
 bool(false)
 
 Warning: gmp_div_q(): Unable to convert variable to GMP - wrong type in %s on line %d
index 293a2a0bf20cea27ab94898375b42b4aacbf8478..e3f85ec44f1ecd6da4f3cb9cf15bb79dce3cd203 100644 (file)
@@ -28,13 +28,22 @@ NULL
 Warning: gmp_mod() expects exactly 2 parameters, 1 given in %s on line %d
 NULL
 bool(false)
-int(0)
-resource(%d) of type (GMP integer)
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "0"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "0"
+}
 
 Warning: gmp_mod(): Zero operand not allowed in %s on line %d
 bool(false)
 
 Warning: gmp_mod(): Unable to convert variable to GMP - wrong type in %s on line %d
 bool(false)
-resource(%d) of type (GMP integer)
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(5) "31161"
+}
 Done
index 40e10c6fbe031fb50fb49fa95451613a892d5d31..6afccaf936cc01d33dee06f808d7801b4779516d 100644 (file)
@@ -43,7 +43,7 @@ string(19) "2432902008176640000"
 string(65) "30414093201713378043612608166064768844377641568960512000000000000"
 string(7) "3628800"
 string(1) "1"
-string(11) "87178291200"
+string(9) "479001600"
 
 Warning: gmp_fact(): Number has to be greater than or equal to 0 in %s on line %d
 string(1) "0"
@@ -53,6 +53,9 @@ NULL
 
 Warning: gmp_fact() expects exactly 1 parameter, 2 given in %s on line %d
 NULL
-resource(%d) of type (GMP integer)
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "1"
+}
 string(1) "1"
 Done
index 44360865ca8abcd3aefce4ba630ff06e4f0dbb5c..8a0b34458fe39c99d1fc4e2df71cfef882f61cd1 100644 (file)
@@ -69,5 +69,8 @@ NULL
 
 Warning: gmp_powm(): Second parameter cannot be less than 0 in %s on line %d
 bool(false)
-resource(%d) of type (GMP integer)
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "1"
+}
 Done
index 38ff5be5bf94720177e57d8f4c6ca88b85312620..99848959d52df006f9f59e6ff84d424803c96340 100644 (file)
@@ -52,13 +52,13 @@ string(12) "100008388608"
 string(12) "100000000000"
 string(12) "100000000008"
 
-Warning: gmp_setbit(): supplied argument is not a valid GMP integer resource in %s on line %d
+Warning: gmp_setbit() expects parameter 1 to be GMP, string given in %s on line %d
 
 Warning: gmp_setbit() expects at least 2 parameters, 1 given in %s on line %d
 
 Warning: gmp_setbit() expects at most 3 parameters, 4 given in %s on line %d
 
-Warning: gmp_setbit() expects parameter 2 to be long, array given in %s on line %d
+Warning: gmp_setbit() expects parameter 1 to be GMP, string given in %s on line %d
 
-Warning: gmp_setbit() expects parameter 2 to be long, array given in %s on line %d
+Warning: gmp_setbit() expects parameter 1 to be GMP, array given in %s on line %d
 Done
index 601102990557984d059a2aaf12b2eff4d9a13e02..079d5d669f37b54b0385f70bca10814ce289eab4 100644 (file)
@@ -46,7 +46,7 @@ string(7) "1000000"
 string(7) "1000000"
 string(30) "238462734628347239571822592658"
 
-Warning: gmp_clrbit(): supplied argument is not a valid GMP integer resource in %s on line %d
+Warning: gmp_clrbit() expects parameter 1 to be GMP, array given in %s on line %d
 
 Warning: gmp_clrbit() expects exactly 2 parameters, 3 given in %s on line %d
 
index 3af18cce59aaf13fb77e388ce45d5a654a5a6de3..9cc497edc6c1dbd2c3c501ce9bdb02ac67397aea 100644 (file)
@@ -18,7 +18,10 @@ var_dump(gmp_strval(gmp_init("993247326237679187178",3)));
 echo "Done\n";
 ?>
 --EXPECTF--    
-resource(%d) of type (GMP integer)
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(8) "98765678"
+}
 string(8) "98765678"
 
 Warning: gmp_init() expects at least 1 parameter, 0 given in %s on line %d
diff --git a/ext/gmp/tests/cast.phpt b/ext/gmp/tests/cast.phpt
new file mode 100644 (file)
index 0000000..eb1832c
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+GMP casting using casting operators
+--SKIPIF--
+<?php if (!extension_loaded("gmp")) print "skip"; ?>
+--FILE--
+<?php
+
+$n = gmp_init(42);
+echo $n, "\n";
+var_dump((string) $n);
+var_dump((int) $n);
+var_dump((float) $n);
+var_dump((bool) $n);
+
+?>
+--EXPECTF--    
+42
+string(2) "42"
+int(42)
+float(42)
+
+Catchable fatal error: Object of class GMP could not be converted to boolean in %s on line %d
diff --git a/ext/gmp/tests/clone.phpt b/ext/gmp/tests/clone.phpt
new file mode 100644 (file)
index 0000000..56b5ca3
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Cloning GMP instances
+--SKIPIF--
+<?php if (!extension_loaded("gmp")) print "skip"; ?>
+--FILE--
+<?php
+
+$a = gmp_init(3);
+$b = clone $a;
+gmp_clrbit($a, 0);
+var_dump($a, $b); // $b should be unaffected
+
+?>
+--EXPECTF--    
+object(GMP)#1 (1) {
+  ["num"]=>
+  string(1) "2"
+}
+object(GMP)#2 (1) {
+  ["num"]=>
+  string(1) "3"
+}
diff --git a/ext/gmp/tests/comparison.phpt b/ext/gmp/tests/comparison.phpt
new file mode 100644 (file)
index 0000000..1f3a423
--- /dev/null
@@ -0,0 +1,37 @@
+--TEST--
+Overloaded GMP comparison in sort() etc
+--SKIPIF--
+<?php if (!extension_loaded("gmp")) print "skip"; ?>
+--FILE--
+<?php
+
+$arr = [gmp_init(0), -3, gmp_init(2), 1];
+sort($arr);
+var_dump($arr);
+
+var_dump(min(gmp_init(3), 4));
+var_dump(max(gmp_init(3), 4));
+
+?>
+--EXPECT--
+array(4) {
+  [0]=>
+  int(-3)
+  [1]=>
+  object(GMP)#1 (1) {
+    ["num"]=>
+    string(1) "0"
+  }
+  [2]=>
+  int(1)
+  [3]=>
+  object(GMP)#2 (1) {
+    ["num"]=>
+    string(1) "2"
+  }
+}
+object(GMP)#3 (1) {
+  ["num"]=>
+  string(1) "3"
+}
+int(4)
diff --git a/ext/gmp/tests/overloading.phpt b/ext/gmp/tests/overloading.phpt
new file mode 100644 (file)
index 0000000..18e0bb2
--- /dev/null
@@ -0,0 +1,259 @@
+--TEST--
+GMP operator overloading
+--SKIPIF--
+<?php if (!extension_loaded("gmp")) print "skip"; ?>
+--FILE--
+<?php
+
+$a = gmp_init(42);
+$b = gmp_init(17);
+
+var_dump($a + $b);
+var_dump($a + 17);
+var_dump(42 + $b);
+
+var_dump($a - $b);
+var_dump($a - 17);
+var_dump(42 - $b);
+
+var_dump($a / $b);
+var_dump($a / 17);
+var_dump(42 / $b);
+var_dump($a / 0);
+
+var_dump($a % $b);
+var_dump($a % 17);
+var_dump(42 % $b);
+var_dump($a % 0);
+
+// sl, sr
+
+var_dump($a | $b);
+var_dump($a | 17);
+var_dump(42 | $b);
+
+var_dump($a & $b);
+var_dump($a & 17);
+var_dump(42 & $b);
+
+var_dump($a ^ $b);
+var_dump($a ^ 17);
+var_dump(42 ^ $b);
+
+var_dump($a << $b);
+var_dump($a << 17);
+var_dump(42 << $b);
+
+var_dump($a >> 2);
+var_dump(-$a >> 2);
+
+var_dump(~$a);
+var_dump(-$a);
+var_dump(+$a);
+
+var_dump($a == $b);
+var_dump($a != $b);
+var_dump($a < $b);
+var_dump($a <= $b);
+var_dump($a > $b);
+var_dump($a >= $b);
+
+var_dump($a == $a);
+var_dump($a != $a);
+
+var_dump($a == 42);
+var_dump($a != 42);
+var_dump($a < 42);
+var_dump($a <= 42);
+var_dump($a > 42);
+var_dump($a >= 42);
+
+var_dump($a == new stdClass);
+
+$a += 1;
+var_dump($a);
+$a -= 1;
+var_dump($a);
+
+var_dump(++$a);
+var_dump($a++);
+var_dump($a);
+
+var_dump(--$a);
+var_dump($a--);
+var_dump($a);
+
+?>
+--EXPECTF--
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "59"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "59"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "59"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "25"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "25"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "25"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "2"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "2"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "2"
+}
+
+Warning: main(): Zero operand not allowed in %s on line %d
+bool(false)
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "8"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "8"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "8"
+}
+
+Warning: main(): Zero operand not allowed in %s on line %d
+bool(false)
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "59"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "59"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "59"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "0"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "0"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(1) "0"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "59"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "59"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "59"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(7) "5505024"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(7) "5505024"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(7) "5505024"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "10"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(3) "-11"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(3) "-43"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(3) "-42"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "42"
+}
+bool(false)
+bool(true)
+bool(false)
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(false)
+bool(true)
+bool(false)
+bool(false)
+bool(true)
+bool(false)
+bool(true)
+
+Warning: main(): Unable to convert variable to GMP - wrong type in %s on line %d
+bool(false)
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "43"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "42"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "43"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "43"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "44"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "43"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "43"
+}
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "42"
+}
+
diff --git a/ext/gmp/tests/serialize.phpt b/ext/gmp/tests/serialize.phpt
new file mode 100644 (file)
index 0000000..26716b6
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+GMP serialization and unserialization
+--SKIPIF--
+<?php if (!extension_loaded("gmp")) print "skip"; ?>
+--FILE--
+<?php
+
+var_dump($n = gmp_init(42));
+var_dump($s = serialize($n));
+var_dump(unserialize($s));
+
+?>
+--EXPECTF--    
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "42"
+}
+string(33) "O:3:"GMP":1:{s:3:"num";s:2:"42";}"
+object(GMP)#%d (1) {
+  ["num"]=>
+  string(2) "42"
+}