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;
}
syntax highlighted by Code2HTML, v. 0.9.1