static VALUE r_gmpz_add(VALUE self, VALUE arg) { MP_INT *self_val, *arg_val, *res_val; VALUE res; mpz_get_struct(self,self_val); if (GMPZ_P(arg)) { mpz_get_struct(arg,arg_val); mpz_make_struct_init(res, res_val); mpz_add (res_val, self_val, arg_val); } else if (FIXNUM_P(arg)) { mpz_make_struct_init(res, res_val); if (FIX2INT(arg) > 0) mpz_add_ui (res_val, self_val, FIX2INT(arg)); else mpz_sub_ui (res_val, self_val, -FIX2INT(arg)); } else if (GMPQ_P(arg)) { return r_gmpq_add(arg, self); } else if (GMPF_P(arg)) { return r_gmpf_add(arg, self); } else if (BIGNUM_P(arg)) { mpz_make_struct_init(res, res_val); mpz_init (res_val); mpz_set_bignum (res_val, arg); mpz_add (res_val, res_val, self_val); } else { typeerror (ZQFXB); } return res; } static VALUE r_gmpz_add_self(VALUE self, VALUE arg) { MP_INT *self_val, *arg_val; mpz_get_struct(self,self_val); if (GMPZ_P(arg)) { mpz_get_struct(arg,arg_val); mpz_add (self_val, self_val, arg_val); } else if (FIXNUM_P(arg)) { if (FIX2INT(arg) > 0) mpz_add_ui (self_val, self_val, FIX2INT(arg)); else mpz_sub_ui (self_val, self_val, -FIX2INT(arg)); } else if (BIGNUM_P(arg)) { mpz_temp_from_bignum (arg_val, arg); mpz_add (self_val, self_val, arg_val); mpz_temp_free (arg_val); } else { typeerror (ZXB); } return Qnil; } static VALUE r_gmpz_sub(VALUE self, VALUE arg) { MP_RAT *res_val_q, *arg_val_q; MP_INT *self_val, *arg_val, *res_val; MP_FLOAT *arg_val_f, *res_val_f; VALUE res; unsigned long prec; mpz_get_struct(self,self_val); if (GMPZ_P(arg)) { mpz_make_struct_init(res, res_val); mpz_get_struct(arg,arg_val); mpz_sub (res_val, self_val, arg_val); } else if (FIXNUM_P(arg)) { mpz_make_struct_init(res, res_val); if (FIX2INT(arg) > 0) mpz_sub_ui (res_val, self_val, FIX2INT(arg)); else mpz_add_ui (res_val, self_val, -FIX2INT(arg)); } else if (GMPQ_P(arg)) { mpq_make_struct_init(res, res_val_q); mpq_get_struct(arg,arg_val_q); mpz_set (mpq_denref(res_val_q), mpq_denref(arg_val_q)); mpz_mul (mpq_numref(res_val_q), mpq_denref(arg_val_q), self_val); mpz_sub (mpq_numref(res_val_q), mpq_numref(res_val_q), mpq_numref(arg_val_q)); } else if (GMPF_P(arg)) { mpf_get_struct_prec (arg, arg_val_f, prec); mpf_make_struct_init(res, res_val_f, prec); mpf_set_z (res_val_f, self_val); mpf_sub (res_val_f, res_val_f, arg_val_f); } else if (BIGNUM_P(arg)) { mpz_make_struct_init(res, res_val); mpz_set_bignum (res_val, arg); mpz_sub (res_val, self_val, res_val); } else { typeerror (ZQFXB); } return res; } static VALUE r_gmpz_sub_self(VALUE self, VALUE arg) { MP_INT *self_val, *arg_val; mpz_get_struct(self,self_val); if (GMPZ_P(arg)) { mpz_get_struct(arg, arg_val); mpz_sub (self_val, self_val, arg_val); } else if (FIXNUM_P(arg)) { if (FIX2INT(arg) > 0) mpz_sub_ui (self_val, self_val, FIX2INT(arg)); else mpz_add_ui (self_val, self_val, -FIX2INT(arg)); } else if (BIGNUM_P(arg)) { mpz_temp_from_bignum(arg_val, arg); mpz_sub (self_val, self_val, arg_val); mpz_temp_free (arg_val); } else { typeerror (ZXB); } return Qnil; } static VALUE r_gmpz_mul(VALUE self, VALUE arg) { MP_INT *self_val, *arg_val, *res_val; VALUE res; mpz_get_struct(self,self_val); if (GMPZ_P(arg)) { mpz_make_struct_init(res, res_val); mpz_get_struct(arg,arg_val); mpz_mul (res_val, self_val, arg_val); } else if (FIXNUM_P(arg)) { mpz_make_struct_init(res, res_val); mpz_mul_si (res_val, self_val, FIX2INT(arg)); } else if (GMPQ_P(arg)) { return r_gmpq_mul(arg, self); } else if (GMPF_P(arg)) { return r_gmpf_mul(arg, self); } else if (BIGNUM_P(arg)) { mpz_make_struct_init(res, res_val); mpz_set_bignum (res_val, arg); mpz_mul (res_val, res_val, self_val); } else { typeerror (ZQFXB); } return res; } static VALUE r_gmpz_div(VALUE self, VALUE arg) { MP_INT *self_val, *arg_val_z, *tmp_z; MP_RAT *arg_val_q, *res_val_q; MP_FLOAT *arg_val_f, *res_val_f; VALUE res; unsigned int prec; mpz_get_struct(self,self_val); if (GMPZ_P(arg)) { mpz_get_struct(arg, arg_val_z); if (mpz_cmp_ui(arg_val_z, 0) == 0) rb_raise (rb_eZeroDivError, "divided by 0"); mpq_make_struct_init(res, res_val_q); mpq_set_num (res_val_q, self_val); mpq_set_den (res_val_q, arg_val_z); mpq_canonicalize (res_val_q); } else if (FIXNUM_P(arg)) { if (FIX2INT(arg) == 0) rb_raise (rb_eZeroDivError, "divided by 0"); mpq_make_struct_init(res, res_val_q); mpq_set_num (res_val_q, self_val); mpz_set_ui (mpq_denref(res_val_q), FIX2INT(arg)); mpq_canonicalize (res_val_q); } else if (GMPQ_P(arg)) { mpq_get_struct(arg, arg_val_q); if (mpz_cmp_ui(mpq_numref(arg_val_q), 0) == 0) rb_raise (rb_eZeroDivError, "divided by 0"); mpz_temp_init(tmp_z); mpq_make_struct_init(res, res_val_q); mpz_gcd (tmp_z, mpq_numref(arg_val_q), self_val); mpz_divexact (mpq_numref(res_val_q), self_val, tmp_z); mpz_divexact (mpq_denref(res_val_q), mpq_numref(arg_val_q), tmp_z); mpz_mul (mpq_numref(res_val_q), mpq_numref(res_val_q), mpq_denref(arg_val_q)); mpz_temp_free(tmp_z); } else if (GMPF_P(arg)) { mpf_get_struct_prec (arg, arg_val_f, prec); mpf_make_struct_init(res, res_val_f, prec); mpf_set_z (res_val_f, self_val); mpf_div (res_val_f, res_val_f, arg_val_f); } else if (BIGNUM_P(arg)) { mpq_make_struct_init(res, res_val_q); mpz_set_bignum (mpq_denref(res_val_q), arg); if (mpz_cmp_ui(mpq_denref(res_val_q), 0) == 0) rb_raise (rb_eZeroDivError, "divided by 0"); mpq_set_num (res_val_q, self_val); mpq_canonicalize (res_val_q); } else { typeerror (ZQFXB); } return res; } static VALUE r_gmpz_setbit(VALUE self, VALUE bitnr, VALUE set_to) { MP_INT *self_val; int bitnr_val; mpz_get_struct(self, self_val); if (FIXNUM_P(bitnr)) { bitnr_val = FIX2INT (bitnr); } else { typeerror_as(X, "index"); } if (RTEST(set_to)) { mpz_setbit (self_val, bitnr_val); } else { mpz_clrbit (self_val, bitnr_val); } return Qnil; } static VALUE r_gmpz_getbit(VALUE self, VALUE bitnr) { MP_INT *self_val; int bitnr_val; mpz_get_struct(self, self_val); if (FIXNUM_P(bitnr)) { bitnr_val = FIX2INT (bitnr); } else { typeerror_as(X, "index"); } return mpz_tstbit(self_val, bitnr_val)?Qtrue:Qfalse; } static VALUE r_gmpz_scan0(VALUE self, VALUE bitnr) { MP_INT *self_val; int bitnr_val; mpz_get_struct(self, self_val); if (FIXNUM_P(bitnr)) { bitnr_val = FIX2INT (bitnr); } else { typeerror_as(X, "index"); } return INT2FIX(mpz_scan0(self_val, bitnr_val)); } static VALUE r_gmpz_scan1(VALUE self, VALUE bitnr) { MP_INT *self_val; int bitnr_val; mpz_get_struct(self, self_val); if (FIXNUM_P(bitnr)) { bitnr_val = FIX2INT (bitnr); } else { typeerror_as(X, "index"); } return INT2FIX(mpz_scan1(self_val, bitnr_val)); } #define DEFUN_INT_COND_P(fname,mpz_fname) \ static VALUE r_gmpz_##fname(VALUE self) \ { \ MP_INT *self_val; \ mpz_get_struct(self, self_val); \ return mpz_fname(self_val)?Qtrue:Qfalse; \ } DEFUN_INT_COND_P(is_even,mpz_even_p) DEFUN_INT_COND_P(is_odd,mpz_odd_p) DEFUN_INT_COND_P(is_square,mpz_perfect_square_p) DEFUN_INT_COND_P(is_power,mpz_perfect_power_p) static VALUE r_gmpz_sgn(VALUE self) { MP_INT *self_val; mpz_get_struct(self, self_val); return INT2FIX(mpz_sgn(self_val)); } static VALUE r_gmpz_powm(VALUE self, VALUE exp, VALUE mod) { MP_INT *self_val, *res_val, *mod_val, *exp_val; VALUE res; int free_mod_val = 0; if (GMPZ_P(mod)) { mpz_get_struct(mod, mod_val); if (mpz_sgn(mod_val) <= 0) { rb_raise (rb_eRangeError, "modulus must be positive"); } } else if (FIXNUM_P(mod)) { if (FIX2INT(mod) <= 0) { rb_raise (rb_eRangeError, "modulus must be positive"); } mpz_temp_alloc (mod_val); mpz_init_set_ui(mod_val, FIX2INT(mod)); free_mod_val = 1; } else if (BIGNUM_P(mod)) { mpz_temp_from_bignum (mod_val, mod); if (mpz_sgn(mod_val) <= 0) { mpz_temp_free(mod_val); rb_raise (rb_eRangeError, "modulus must be positive"); } free_mod_val = 1; } else { typeerror_as (ZXB, "modulus"); } mpz_make_struct_init(res, res_val); mpz_get_struct(self, self_val); if (GMPZ_P(exp)) { mpz_get_struct(exp, exp_val); if (mpz_sgn(mod_val) < 0) { rb_raise (rb_eRangeError, "exponent must be nonnegative"); } mpz_powm (res_val, self_val, exp_val, mod_val); } else if (FIXNUM_P(exp)) { if (FIX2INT(exp) < 0) { if (free_mod_val) mpz_temp_free(mod_val); rb_raise (rb_eRangeError, "exponent must be nonnegative"); } mpz_powm_ui (res_val, self_val, FIX2INT(exp), mod_val); } else if (BIGNUM_P(exp)) { mpz_temp_from_bignum (exp_val, exp); mpz_powm (res_val, self_val, exp_val, mod_val); mpz_temp_free (exp_val); } else { if (free_mod_val) mpz_temp_free(mod_val); typeerror_as (ZXB, "exponent"); } if (free_mod_val) mpz_temp_free(mod_val); return res; } static VALUE r_gmpz_swap(VALUE self, VALUE arg) { MP_INT *self_val, *arg_val; if (!GMPZ_P(arg)) { rb_raise(rb_eTypeError, "Can't swap GMP::Z with object of other class"); } mpz_get_struct(self, self_val); mpz_get_struct(arg, arg_val); mpz_swap(self_val,arg_val); return Qnil; } #define DEFUN_INT_F_UL(fname,mpz_fname,argname) \ static VALUE r_gmpz_##fname(VALUE self, VALUE exp) \ { \ MP_INT *self_val, *res_val; \ VALUE res; \ unsigned long exp_val; \ \ if (FIXNUM_P(exp)) { \ if (FIX2INT (exp) < 0) \ rb_raise (rb_eRangeError, argname " out of range"); \ exp_val = FIX2INT (exp); \ } else if (GMPZ_P(exp)) {\ mpz_get_struct (exp, res_val); \ if (!mpz_fits_ulong_p (res_val)) \ rb_raise (rb_eRangeError, argname " out of range"); \ exp_val = mpz_get_ui (res_val); \ if (exp_val == 0) \ rb_raise (rb_eRangeError, argname " out of range"); \ } else { \ typeerror_as (ZX, argname); \ } \ \ mpz_make_struct_init(res, res_val); \ mpz_get_struct(self, self_val); \ mpz_fname(res_val, self_val, exp_val); \ \ return res; \ } DEFUN_INT_F_UL(pow,mpz_pow_ui,"exponent") DEFUN_INT_F_UL(shl,mpz_mul_2exp,"shift size") DEFUN_INT_F_UL(fshr,mpz_fdiv_q_2exp,"shift size") DEFUN_INT_F_UL(tshr,mpz_tdiv_q_2exp,"shift size") DEFUN_INT_F_UL(fshrm,mpz_fdiv_r_2exp,"mark size") DEFUN_INT_F_UL(tshrm,mpz_tdiv_r_2exp,"mark size") DEFUN_INT_F_UL(root,mpz_root,"root number") static int mpz_cmp_value (MP_INT *OP, VALUE arg) { MP_RAT *arg_val_q; MP_INT *arg_val_z; int res; if (GMPZ_P(arg)) { mpz_get_struct(arg,arg_val_z); return mpz_cmp (OP,arg_val_z); } else if (FIXNUM_P(arg)) { return mpz_cmp_si (OP, FIX2INT(arg)); } else if (GMPQ_P(arg)) { mpq_get_struct(arg,arg_val_q); mpz_temp_alloc (arg_val_z); mpz_init(arg_val_z); mpz_mul(arg_val_z, OP, mpq_denref(arg_val_q)); res = mpz_cmp (arg_val_z, mpq_numref(arg_val_q)); mpz_temp_free(arg_val_z); return res; } else if (GMPF_P(arg)) { not_yet; } else if (BIGNUM_P(arg)) { mpz_temp_from_bignum (arg_val_z, arg); res = mpz_cmp (OP, arg_val_z); mpz_temp_free(arg_val_z); return res; } else { typeerror_as (ZQFXB, "exponent"); } } static VALUE r_gmpz_eq(VALUE self, VALUE arg) { MP_INT *self_val, *arg_val_z; MP_RAT *arg_val_q; mpz_get_struct (self, self_val); if (GMPZ_P(arg)) { mpz_get_struct(arg, arg_val_z); return (mpz_cmp (self_val, arg_val_z)==0) ? Qtrue : Qfalse; } else if (FIXNUM_P(arg)) { return (mpz_cmp_si (self_val, INT2FIX(arg))==0) ? Qtrue : Qfalse; } else if (GMPQ_P(arg)) { mpq_get_struct(arg, arg_val_q); if (mpz_cmp_ui(mpq_denref(arg_val_q), 1)==0) return Qfalse; return (mpz_cmp (self_val, mpq_numref(arg_val_q))==0) ? Qtrue : Qfalse; } else if (BIGNUM_P(arg)) { mpz_temp_from_bignum(arg_val_z, arg); if (mpz_cmp (self_val, arg_val_z)==0) { mpz_temp_free(arg_val_z); return Qtrue; } else { mpz_temp_free(arg_val_z); return Qfalse; } } else { return Qfalse; } } static VALUE r_gmpz_cmp(VALUE self, VALUE arg) { MP_INT *self_val; int res; mpz_get_struct (self,self_val); res = mpz_cmp_value(self_val, arg); if (res > 0) return INT2FIX(1); else if (res == 0) return INT2FIX(0); else return INT2FIX(-1); } #define DEFUN_INT_CMP(name,CMP_OP) \ static VALUE r_gmpz_cmp_##name(VALUE self, VALUE arg) \ { \ MP_INT *self_val; \ mpz_get_struct (self,self_val); \ return (mpz_cmp_value(self_val, arg) CMP_OP 0)?Qtrue:Qfalse; \ } DEFUN_INT_CMP(lt,<) DEFUN_INT_CMP(le,<=) DEFUN_INT_CMP(gt,>) DEFUN_INT_CMP(ge,>=) #define DEFUN_INT_DIV(fname,gmp_fname) \ static VALUE r_gmpz_##fname(VALUE self, VALUE arg) \ { \ MP_INT *self_val, *arg_val, *res_val; \ VALUE res; \ int arg_val_i; \ \ mpz_get_struct(self, self_val); \ mpz_make_struct_init(res, res_val); \ \ if (GMPZ_P(arg)) { \ mpz_get_struct(arg,arg_val); \ if (mpz_cmp_ui(arg_val, 0) == 0) \ rb_raise (rb_eZeroDivError, "divided by 0"); \ gmp_fname (res_val, self_val, arg_val); \ } else if (FIXNUM_P(arg)) { \ arg_val_i = FIX2INT(arg); \ if (arg_val_i > 0) { \ gmp_fname##_ui (res_val, self_val, arg_val_i); \ } else if (arg_val_i == 0) { \ rb_raise (rb_eZeroDivError, "divided by 0"); \ } else { \ mpz_neg (res_val, self_val); \ gmp_fname##_ui (res_val, self_val, -arg_val_i); \ } \ } else if (BIGNUM_P(arg)) { \ mpz_set_bignum (res_val, arg); \ if (mpz_cmp_ui(res_val, 0) == 0) \ rb_raise (rb_eZeroDivError, "divided by 0"); \ gmp_fname (res_val, self_val, res_val); \ } else { \ typeerror(ZXB); \ } \ return res; \ } DEFUN_INT_DIV(tdiv, mpz_tdiv_q) DEFUN_INT_DIV(tmod, mpz_tdiv_r) DEFUN_INT_DIV(fdiv, mpz_fdiv_q) DEFUN_INT_DIV(fmod, mpz_fdiv_r) DEFUN_INT_DIV(cdiv, mpz_cdiv_q) DEFUN_INT_DIV(cmod, mpz_cdiv_r) #define DEFUN_INT2INT(fname,mpz_fname) \ static VALUE r_gmpz_##fname(VALUE self) \ {\ MP_INT *self_val, *res_val; \ VALUE res; \ mpz_get_struct(self, self_val); \ mpz_make_struct_init(res, res_val); \ mpz_fname(res_val, self_val); \ return res; \ }\ \ static VALUE r_gmpz_##fname##_self(VALUE self) \ {\ MP_INT *self_val; \ mpz_get_struct(self, self_val); \ mpz_fname(self_val, self_val); \ return Qnil; \ } DEFUN_INT2INT(abs, mpz_abs) DEFUN_INT2INT(neg, mpz_neg) DEFUN_INT2INT(com, mpz_com) DEFUN_INT2INT(sqrt, mpz_sqrt) DEFUN_INT2INT(nextprime, mpz_nextprime) static VALUE r_gmpz_jacobi(VALUE self) { MP_INT *self_val, *res_val; VALUE res; mpz_get_struct(self, self_val); if (mpz_sgn(self_val) != 1) rb_raise(rb_eRangeError, "you can take jacobi symbol only of positive value"); if (mpz_even_p(self_val)) rb_raise(rb_eRangeError, "you can't take jacobi symbol of even value"); mpz_make_struct_init(res, res_val); mpz_jacobi(res_val, self_val); return res; } static VALUE r_gmpz_legendre(VALUE self) { MP_INT *self_val, *res_val; VALUE res; mpz_get_struct(self, self_val); if (mpz_sgn(self_val) != 1) rb_raise(rb_eRangeError, "you can take legendre symbol only of positive value"); if (mpz_even_p(self_val)) rb_raise(rb_eRangeError, "you can't take legendre symbol of even value"); mpz_make_struct_init(res, res_val); mpz_legendre(res_val, self_val); return res; } #define DEFUN_INT_LOGIC(fname, mpz_fname) \ static VALUE r_gmpz_##fname(VALUE self, VALUE arg) \ { \ MP_INT *self_val, *arg_val, *res_val; \ VALUE res; \ \ mpz_get_struct(self, self_val); \ \ mpz_make_struct(res, res_val); \ if (GMPZ_P(arg)) { \ mpz_get_struct(arg,arg_val); \ mpz_init (res_val); \ mpz_fname (res_val, self_val, arg_val); \ } else if (FIXNUM_P(arg)) { \ mpz_init_set_si (res_val, FIX2INT(arg)); \ mpz_fname (res_val, self_val, res_val); \ } else if (BIGNUM_P(arg)) { \ mpz_init (res_val); \ mpz_set_bignum (res_val, arg); \ mpz_fname (res_val, self_val, res_val); \ } else { \ typeerror(ZXB); \ } \ return res; \ } DEFUN_INT_LOGIC(and, mpz_and) DEFUN_INT_LOGIC(xor, mpz_xor) DEFUN_INT_LOGIC(or, mpz_ior) static VALUE r_gmpz_sqrtrem(VALUE self) { MP_INT *self_val, *sqrt_val, *rem_val; VALUE sqrt, rem; mpz_get_struct (self, self_val); mpz_make_struct_init(sqrt, sqrt_val); mpz_make_struct_init(rem, rem_val); mpz_sqrtrem (sqrt_val, rem_val, self_val); return rb_assoc_new(sqrt, rem); } static VALUE r_gmpz_to_d(VALUE self) { MP_INT *self_val; mpz_get_struct (self, self_val); return rb_float_new(mpz_get_d(self_val)); } #define DEFUN_INT_SINGLETON_UI(fname,mpz_fname) \ static VALUE r_gmpzsg_##fname(VALUE klass, VALUE arg) \ { \ MP_INT *arg_val_z, *res_val; \ unsigned long arg_val_ul; \ VALUE res; \ \ (void)klass; \ \ if (FIXNUM_P(arg)) { \ arg_val_ul = FIX2INT (arg); \ } else if (GMPZ_P(arg)) { \ mpz_get_struct (arg, arg_val_z); \ if (!mpz_fits_ulong_p (arg_val_z)) \ rb_raise (rb_eRangeError, "argument out of range"); \ arg_val_ul = mpz_get_ui (arg_val_z); \ if (arg_val_ul == 0) \ rb_raise (rb_eRangeError, "argument out of range"); \ } else { \ typeerror_as (ZX, "argument"); \ } \ mpz_make_struct_init(res, res_val); \ mpz_fname (res_val, arg_val_ul); \ return res; \ } DEFUN_INT_SINGLETON_UI(fib,mpz_fib_ui) DEFUN_INT_SINGLETON_UI(fac,mpz_fac_ui) static VALUE r_gmpzsg_pow(VALUE klass, VALUE base, VALUE exp) { MP_INT *res_val; VALUE res; if (FIXNUM_P(base) && FIXNUM_P(exp)) { if (FIX2INT(base) < 0) rb_raise (rb_eRangeError, "base must not be negative"); if (FIX2INT(exp) < 0) rb_raise (rb_eRangeError, "exponent must not be negative"); mpz_make_struct_init (res, res_val); mpz_ui_pow_ui (res_val, base, exp); return res; } return r_gmpz_pow (r_gmpzsg_new(1, &base, klass), exp); } static VALUE r_gmpz_remove(VALUE self, VALUE arg) { MP_INT *self_val, *arg_val, *res_val; VALUE res; int free_arg_val = 0; mpz_get_struct(self,self_val); if (GMPZ_P(arg)) { mpz_get_struct(arg,arg_val); if (mpz_sgn(arg_val) != 1) rb_raise(rb_eRangeError, "argument must be positive"); } else if (FIXNUM_P(arg)) { if (FIX2INT(arg) <= 0) rb_raise(rb_eRangeError, "argument must be positive"); mpz_temp_alloc(arg_val); mpz_init_set_ui(arg_val, FIX2INT(arg)); } else if (BIGNUM_P(arg)) { mpz_temp_from_bignum(arg_val, arg); if (mpz_sgn(arg_val) != 1) { mpz_temp_free (arg_val); rb_raise(rb_eRangeError, "argument must be positive"); } } else { typeerror(ZXB); } mpz_make_struct_init (res, res_val); mpz_remove (res_val, self_val, arg_val); if (free_arg_val) mpz_temp_free(arg_val); return res; } static VALUE r_gmpz_to_i (VALUE self) { MP_INT *self_val; char *str; VALUE res; mpz_get_struct(self, self_val); if (mpz_fits_slong_p(self_val)) return rb_int2inum(mpz_get_si(self_val)); str = mpz_get_str(NULL, 0, self_val); res = rb_cstr2inum (str, 10); free (str); return res; } static VALUE r_gmpz_cmpabs (VALUE self, VALUE arg) { MP_INT *arg_val_z, *self_val; MP_RAT *arg_val_q; int res; mpz_get_struct (self, self_val); if (GMPZ_P(arg)) { mpz_get_struct(arg,arg_val_z); return INT2FIX(mpz_cmpabs (self_val, arg_val_z)); } else if (FIXNUM_P(arg)) { if (FIX2INT(arg) >= 0) return INT2FIX(mpz_cmpabs_ui (self_val, FIX2INT(arg))); else return INT2FIX(mpz_cmpabs_ui (self_val, -FIX2INT(arg))); } else if (GMPQ_P(arg)) { mpq_get_struct(arg,arg_val_q); mpz_temp_alloc (arg_val_z); mpz_init(arg_val_z); mpz_mul(arg_val_z, self_val, mpq_denref(arg_val_q)); res = mpz_cmpabs (arg_val_z, mpq_numref(arg_val_q)); mpz_temp_free(arg_val_z); return INT2FIX(res); } else if (GMPF_P(arg)) { not_yet; } else if (BIGNUM_P(arg)) { mpz_temp_from_bignum (arg_val_z, arg); res = mpz_cmpabs (self_val, arg_val_z); mpz_temp_free(arg_val_z); return INT2FIX(res); } else { typeerror(ZQFXB); } } static VALUE r_gmpz_to_s(VALUE self) { MP_INT *self_val; char *str; VALUE res; Data_Get_Struct(self, MP_INT, self_val); str = mpz_get_str(NULL, 10, self_val); res = rb_str_new2(str); free (str); return res; }