static VALUE r_gmpq_add(VALUE self, VALUE arg)
{
MP_RAT *self_val, *arg_val_q, *res_val;
MP_INT *arg_val_z, *res_val_num;
VALUE res;
mpq_get_struct(self, self_val);
mpq_make_struct_init(res, res_val);
if (GMPQ_P(arg)) {
mpq_get_struct(arg,arg_val_q);
mpq_add (res_val, self_val, arg_val_q);
} else if (GMPZ_P(arg)) {
res_val_num = mpq_numref(res_val);
mpz_set (mpq_denref(res_val), mpq_denref(self_val));
mpz_get_struct(arg, arg_val_z);
mpz_mul (res_val_num, mpq_denref(self_val), arg_val_z);
mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
} else if (FIXNUM_P(arg)) {
res_val_num = mpq_numref(res_val);
mpz_set (mpq_denref(res_val), mpq_denref(self_val));
mpz_mul_si (res_val_num, mpq_denref(self_val), FIX2INT(arg));
mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
} else if (GMPF_P(arg)) {
return r_gmpf_add(arg,self);
} else if (BIGNUM_P(arg)) {
res_val_num = mpq_numref(res_val);
mpz_set (mpq_denref(res_val), mpq_denref(self_val));
mpz_set_bignum (res_val_num, arg);
mpz_mul (res_val_num, res_val_num, mpq_denref(self_val));
mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
} else {
typeerror (ZQFXB);
}
return res;
}
static VALUE r_gmpq_sub(VALUE self, VALUE arg)
{
MP_RAT *self_val, *arg_val_q, *res_val;
MP_INT *arg_val_z, *res_val_num;
MP_FLOAT *arg_val_f, *res_val_f;
VALUE res;
unsigned int prec;
mpq_get_struct(self, self_val);
mpq_make_struct_init(res, res_val);
if (GMPQ_P(arg)) {
mpq_get_struct(arg,arg_val_q);
mpq_sub (res_val, self_val, arg_val_q);
} else if (GMPZ_P(arg)) {
res_val_num = mpq_numref(res_val);
mpz_set (mpq_denref(res_val), mpq_denref(self_val));
mpz_get_struct(arg, arg_val_z);
mpz_mul (res_val_num, mpq_denref(self_val), arg_val_z);
mpz_neg (res_val_num, res_val_num);
mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
} else if (FIXNUM_P(arg)) {
res_val_num = mpq_numref(res_val);
mpz_set (mpq_denref(res_val), mpq_denref(self_val));
mpz_mul_si (res_val_num, mpq_denref(self_val), -FIX2INT(arg));
mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
} 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_q (res_val_f, self_val);
mpf_sub (res_val_f, res_val_f, arg_val_f);
} else if (BIGNUM_P(arg)) {
res_val_num = mpq_numref(res_val);
mpz_set (mpq_denref(res_val), mpq_denref(self_val));
mpz_set_bignum (res_val_num, arg);
mpz_mul (res_val_num, res_val_num, mpq_denref(self_val));
mpz_neg (res_val_num, res_val_num);
mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
} else {
typeerror (ZQFXB);
}
return res;
}
static VALUE r_gmpq_mul(VALUE self, VALUE arg)
{
MP_RAT *self_val, *arg_val_q, *res_val;
MP_INT *arg_val_z, *tmp_z;
VALUE res;
#if GMP >= 4
unsigned long tmp_ui;
#endif
mpq_get_struct(self, self_val);
mpq_make_struct_init(res, res_val);
if (GMPQ_P(arg)) {
mpq_get_struct(arg,arg_val_q);
mpq_mul (res_val, self_val, arg_val_q);
} else if (GMPZ_P(arg)) {
mpz_get_struct(arg,arg_val_z);
mpz_temp_init(tmp_z);
mpz_gcd (tmp_z, mpq_denref(self_val), arg_val_z);
mpz_divexact (mpq_denref(res_val), mpq_denref(self_val), tmp_z);
mpz_divexact (mpq_numref(res_val), arg_val_z, tmp_z);
mpz_mul (mpq_numref(res_val), mpq_numref(res_val), mpq_numref(self_val));
mpz_temp_free(tmp_z);
} else if (FIXNUM_P(arg)) {
#if GMP >= 4
if (FIX2INT(arg) > 0) {
tmp_ui = mpz_gcd_ui (0, mpq_denref(self_val), FIX2INT(arg));
} else if (FIX2INT(arg) < 0) {
tmp_ui = mpz_gcd_ui (0, mpq_denref(self_val), -FIX2INT(arg));
} else {
mpz_set_ui(mpq_numref(res_val), 0);
mpz_set_ui(mpq_denref(res_val), 1);
return res;
}
mpz_divexact_ui (mpq_denref(res_val), mpq_denref(self_val), tmp_ui);
mpz_mul_ui (mpq_numref(res_val), mpq_numref(self_val), FIX2INT(arg)/tmp_ui);
#else
mpz_set (mpq_denref(res_val), mpq_denref(self_val));
mpz_mul_si (mpq_numref(res_val), mpq_numref(self_val), FIX2INT(arg));
mpq_canonicalize (res_val);
#endif
} else if (GMPF_P(arg)) {
return r_gmpf_mul (arg, self);
} else if (BIGNUM_P(arg)) {
mpz_temp_alloc(tmp_z);
mpz_set_bignum(tmp_z, arg);
mpz_gcd(mpq_denref(res_val), mpq_denref(self_val), tmp_z);
mpz_divexact(mpq_numref(res_val), tmp_z, mpq_denref(res_val));
mpz_divexact(mpq_denref(res_val), mpq_denref(self_val), mpq_denref(res_val));
mpz_mul(mpq_numref(res_val), mpq_numref(res_val), mpq_numref(self_val));
mpz_temp_free(tmp_z);
} else {
typeerror (ZQFXB);
}
return res;
}
static VALUE r_gmpq_div(VALUE self, VALUE arg)
{
MP_RAT *self_val, *arg_val_q, *res_val;
MP_INT *arg_val_z, *tmp_z;
MP_FLOAT *arg_val_f, *res_val_f;
VALUE res;
unsigned long tmp_ui, prec;
mpq_get_struct(self, self_val);
mpq_make_struct_init(res, res_val);
if (GMPQ_P(arg)) {
mpq_get_struct(arg,arg_val_q);
if (mpz_sgn(mpq_numref(arg_val_q)) == 0)
rb_raise (rb_eZeroDivError, "divided by 0");
mpq_div (res_val, self_val, arg_val_q);
} else if (GMPZ_P(arg)) {
mpz_get_struct(arg,arg_val_z);
mpz_temp_init(tmp_z);
mpz_gcd (tmp_z, mpq_numref(self_val), arg_val_z);
mpz_divexact (mpq_numref(res_val), mpq_numref(self_val), tmp_z);
mpz_divexact (mpq_denref(res_val), arg_val_z, tmp_z);
mpz_mul (mpq_denref(res_val), mpq_denref(res_val), mpq_denref(self_val));
mpz_temp_free(tmp_z);
} else if (FIXNUM_P(arg)) {
if (FIX2INT(arg) == 0)
rb_raise (rb_eZeroDivError, "divided by 0");
if (FIX2INT(arg) > 0) {
tmp_ui = mpz_gcd_ui (0, mpq_numref(self_val), FIX2INT(arg));
} else {
tmp_ui = mpz_gcd_ui (0, mpq_numref(self_val), -FIX2INT(arg));
}
mpz_divexact_ui (mpq_numref(res_val), mpq_numref(self_val), tmp_ui);
mpz_mul_ui (mpq_denref(res_val), mpq_denref(self_val), FIX2INT(arg)/tmp_ui);
} 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_q (res_val_f, self_val);
mpf_div (res_val_f, res_val_f, arg_val_f);
} else if (BIGNUM_P(arg)) {
mpz_temp_alloc(tmp_z);
mpz_set_bignum(tmp_z, arg);
mpz_gcd(mpq_numref(res_val), mpq_numref(self_val), tmp_z);
mpz_divexact(mpq_denref(res_val), tmp_z, mpq_numref(res_val));
mpz_divexact(mpq_numref(res_val), mpq_numref(self_val), mpq_numref(res_val));
mpz_mul(mpq_denref(res_val), mpq_denref(res_val), mpq_denref(self_val));
mpz_temp_free(tmp_z);
} else {
typeerror (ZQFXB);
}
return res;
}
static VALUE r_gmpq_neg(VALUE self)
{
MP_RAT *self_val, *res_val;
VALUE res;
mpq_get_struct(self, self_val);
mpq_make_struct_init(res, res_val);
mpq_neg (res_val, self_val);
return res;
}
static VALUE r_gmpq_neg_self(VALUE self)
{
MP_RAT *self_val;
mpq_get_struct(self, self_val);
mpz_neg (mpq_numref(self_val), mpq_numref(self_val));
return Qnil;
}
static VALUE r_gmpq_abs(VALUE self)
{
MP_RAT *self_val, *res_val;
VALUE res;
mpq_get_struct(self, self_val);
mpq_make_struct_init(res, res_val);
mpz_abs (mpq_numref(res_val), mpq_numref(self_val));
mpz_set (mpq_denref(res_val), mpq_denref(self_val));
return res;
}
static VALUE r_gmpq_abs_self(VALUE self)
{
MP_RAT *self_val;
mpq_get_struct(self, self_val);
mpz_abs (mpq_numref(self_val), mpq_numref(self_val));
return Qnil;
}
static VALUE r_gmpq_inv(VALUE self)
{
MP_RAT *self_val, *res_val;
VALUE res;
mpq_get_struct(self, self_val);
if (mpq_sgn(self_val) == 0)
rb_raise (rb_eZeroDivError, "divided by 0");
mpq_make_struct_init(res, res_val);
mpq_inv (res_val, self_val);
return res;
}
static VALUE r_gmpq_inv_self(VALUE self)
{
MP_RAT *self_val;
mpq_get_struct(self, self_val);
if (mpq_sgn(self_val) == 0)
rb_raise (rb_eZeroDivError, "divided by 0");
mpq_inv (self_val, self_val);
return Qnil;
}
static VALUE r_gmpq_sgn(VALUE self)
{
MP_RAT *self_val;
mpq_get_struct(self, self_val);
return INT2FIX(mpq_sgn(self_val));
}
static int mpq_cmp_value (MP_RAT *OP, VALUE arg)
{
MP_INT *arg_val_z, *tmp_z;
MP_RAT *arg_val_q;
int res;
if (GMPQ_P(arg)) {
mpq_get_struct(arg,arg_val_q);
return mpq_cmp (OP,arg_val_q);
} else if (GMPZ_P(arg)) {
mpz_get_struct(arg, arg_val_z);
mpz_temp_alloc (tmp_z);
mpz_init (tmp_z);
mpz_mul (tmp_z, mpq_denref(OP), arg_val_z);
res = mpz_cmp (mpq_numref(OP),tmp_z);
mpz_temp_free (tmp_z);
return res;
} else if (FIXNUM_P(arg)) {
mpz_temp_alloc (tmp_z);
mpz_init (tmp_z);
mpz_mul_si (tmp_z, mpq_denref(OP), FIX2INT(arg));
res = mpz_cmp (mpq_numref(OP), tmp_z);
mpz_temp_free (tmp_z);
return res;
} else if (GMPF_P(arg)) {
not_yet;
} else if (BIGNUM_P(arg)) {
mpz_temp_from_bignum (tmp_z, arg);
mpz_mul (tmp_z, tmp_z, mpq_denref(OP));
res = mpz_cmp (mpq_numref(OP), tmp_z);
mpz_temp_free (tmp_z);
return res;
} else {
typeerror (ZQFXB);
}
}
static VALUE r_gmpq_eq(VALUE self, VALUE arg)
{
MP_RAT *self_val, *arg_val_q;
MP_INT *arg_val_z;
mpq_get_struct(self,self_val);
if (GMPQ_P(arg)) {
mpq_get_struct(arg,arg_val_q);
return mpq_equal(self_val,arg_val_q)?Qtrue:Qfalse;
} else if (GMPZ_P(arg)) {
if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
return Qfalse;
mpz_get_struct (arg, arg_val_z);
return (mpz_cmp(mpq_numref(self_val),arg_val_z)==0)?Qtrue:Qfalse;
} else if (FIXNUM_P(arg)) {
if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
return Qfalse;
return (mpz_cmp_ui(mpq_numref(self_val),FIX2INT(arg))==0)?Qtrue:Qfalse;
} else if (BIGNUM_P(arg)) {
if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
return Qfalse;
mpz_temp_from_bignum(arg_val_z, arg);
if (mpz_cmp (mpq_numref(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_gmpq_cmp(VALUE self, VALUE arg)
{
MP_RAT *self_val;
int res;
mpq_get_struct (self,self_val);
res = mpq_cmp_value(self_val, arg);
if (res > 0)
return INT2FIX(1);
else if (res == 0)
return INT2FIX(0);
else
return INT2FIX(-1);
}
#define DEFUN_RAT_CMP(name,CMP_OP) \
static VALUE r_gmpq_cmp_##name(VALUE self, VALUE arg) \
{ \
MP_RAT *self_val; \
mpq_get_struct (self,self_val); \
return (mpq_cmp_value(self_val, arg) CMP_OP 0)?Qtrue:Qfalse; \
}
DEFUN_RAT_CMP(lt,<)
DEFUN_RAT_CMP(le,<=)
DEFUN_RAT_CMP(gt,>)
DEFUN_RAT_CMP(ge,>=)
static VALUE r_gmpq_swap(VALUE self, VALUE arg)
{
MP_RAT *self_val, *arg_val;
if (!GMPQ_P(arg)) {
rb_raise(rb_eTypeError, "Can't swap GMP::Q with object of other class");
}
mpq_get_struct(self, self_val);
mpq_get_struct(arg, arg_val);
mpq_swap(self_val,arg_val);
return Qnil;
}
#define DEFUN_RAT2INT(fname,mpz_fname) \
static VALUE r_gmpq_##fname(VALUE self) \
{ \
MP_RAT *self_val; \
MP_INT *res_val; \
VALUE res; \
\
mpq_get_struct(self, self_val); \
mpz_make_struct_init (res, res_val) \
mpz_fname (res_val, mpq_numref(self_val), mpq_denref(self_val)); \
return res; \
}
DEFUN_RAT2INT(floor,mpz_fdiv_q)
DEFUN_RAT2INT(trunc,mpz_tdiv_q)
DEFUN_RAT2INT(ceil,mpz_cdiv_q)
static VALUE r_gmpq_to_d(VALUE self)
{
MP_RAT *self_val;
mpq_get_struct (self, self_val);
return rb_float_new(mpq_get_d(self_val));
}
static VALUE r_gmpq_cmpabs (VALUE self, VALUE arg)
{
MP_RAT *arg_val_q, *self_val;
MP_INT *arg_val_z, *tmp_z;
int res;
int sgnt;
mpq_get_struct(self, self_val);
if (GMPQ_P(arg)) {
mpq_get_struct(arg,arg_val_q);
sgnt = 3*mpz_sgn(mpq_numref(self_val)) + mpz_sgn(mpq_numref(arg_val_q));
switch (sgnt)
{
default:
case 0:
return INT2FIX(0);
case 1:
case -1:
return INT2FIX(-1);
case 2:
tmp_z = mpq_numref(arg_val_q);
mpz_neg (tmp_z, tmp_z);
res = mpq_cmp (self_val, arg_val_q);
mpz_neg (tmp_z, tmp_z);
return res;
case -2:
tmp_z = mpq_numref(arg_val_q);
mpz_neg (tmp_z, tmp_z);
res = mpq_cmp (self_val, arg_val_q);
mpz_neg (tmp_z, tmp_z);
return res;
case 3:
case -3:
return INT2FIX(1);
case 4:
case -4:
return INT2FIX(mpq_cmp (self_val,arg_val_q));
}
} else if (GMPZ_P(arg)) {
mpz_get_struct(arg, arg_val_z);
mpz_temp_alloc (tmp_z);
mpz_init (tmp_z);
mpz_mul (tmp_z, mpq_denref(self_val), arg_val_z);
res = mpz_cmpabs (mpq_numref(self_val),tmp_z);
mpz_temp_free (tmp_z);
return res;
} else if (FIXNUM_P(arg)) {
mpz_temp_alloc (tmp_z);
mpz_init (tmp_z);
mpz_mul_si (tmp_z, mpq_denref(self_val), FIX2INT(arg));
res = mpz_cmpabs (mpq_numref(self_val), tmp_z);
mpz_temp_free (tmp_z);
return res;
} else if (GMPF_P(arg)) {
not_yet;
} else if (BIGNUM_P(arg)) {
mpz_temp_from_bignum (tmp_z, arg);
mpz_mul (tmp_z, tmp_z, mpq_denref(self_val));
res = mpz_cmpabs (mpq_numref(self_val), tmp_z);
mpz_temp_free (tmp_z);
return res;
} else {
typeerror (ZQFXB);
}
}
static VALUE r_gmpq_num(VALUE self)
{
MP_RAT *self_val;
MP_INT *res_val;
VALUE res;
mpq_get_struct(self,self_val);
mpz_make_struct(res, res_val);
mpz_init_set (res_val, mpq_numref (self_val));
return res;
}
static VALUE r_gmpq_den(VALUE self)
{
MP_RAT *self_val;
MP_INT *res_val;
VALUE res;
mpq_get_struct(self,self_val);
mpz_make_struct(res, res_val);
mpz_init_set (res_val, mpq_denref (self_val));
return res;
}
syntax highlighted by Code2HTML, v. 0.9.1