**(p1)
public
Show source
static VALUE
nurat_expt(VALUE self, VALUE other)
{
if (k_numeric_p(other) && k_exact_zero_p(other))
return f_rational_new_bang1(CLASS_OF(self), ONE);
if (k_rational_p(other)) {
get_dat1(other);
if (f_one_p(dat->den))
other = dat->num; /* c14n */
}
/* Deal with special cases of 0**n and 1**n */
if (k_numeric_p(other) && k_exact_p(other)) {
get_dat1(self);
if (f_one_p(dat->den)) {
if (f_one_p(dat->num)) {
return f_rational_new_bang1(CLASS_OF(self), ONE);
}
else if (f_minus_one_p(dat->num) && RB_INTEGER_TYPE_P(other)) {
return f_rational_new_bang1(CLASS_OF(self), INT2FIX(f_odd_p(other) ? -1 : 1));
}
else if (INT_ZERO_P(dat->num)) {
if (rb_num_negative_p(other)) {
rb_num_zerodiv();
}
else {
return f_rational_new_bang1(CLASS_OF(self), ZERO);
}
}
}
}
/* General case */
if (FIXNUM_P(other)) {
{
VALUE num, den;
get_dat1(self);
if (INT_POSITIVE_P(other)) {
num = rb_int_pow(dat->num, other);
den = rb_int_pow(dat->den, other);
}
else if (INT_NEGATIVE_P(other)) {
num = rb_int_pow(dat->den, rb_int_uminus(other));
den = rb_int_pow(dat->num, rb_int_uminus(other));
}
else {
num = ONE;
den = ONE;
}
if (RB_FLOAT_TYPE_P(num)) { /* infinity due to overflow */
if (RB_FLOAT_TYPE_P(den)) return DBL2NUM(NAN);
return num;
}
if (RB_FLOAT_TYPE_P(den)) { /* infinity due to overflow */
num = ZERO;
den = ONE;
}
return f_rational_new2(CLASS_OF(self), num, den);
}
}
else if (RB_TYPE_P(other, T_BIGNUM)) {
rb_warn("in a**b, b may be too big");
return rb_float_pow(nurat_to_f(self), other);
}
else if (RB_FLOAT_TYPE_P(other) || RB_TYPE_P(other, T_RATIONAL)) {
return rb_float_pow(nurat_to_f(self), other);
}
else {
return rb_num_coerce_bin(self, other, rb_intern("**"));
}
}