summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
authormrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-04 02:35:40 +0000
committermrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-04 02:35:40 +0000
commit9b09cc8a37ca80c7126bfc4ffc39ce9dddcdb1d8 (patch)
tree077a5bcc275ca50f1588428b384e742f8366f43a /numeric.c
parent58b3f3654634e86a3d89c74294b8356008ae8597 (diff)
bignum.c, numeric.c: add Integer#pow(b, m)
This commit is based on the pull-request #1320 created by Makoto Kishimoto. [Feature #12508] [Feature #11003] [close GH-1320] * bignum.c (rb_int_powm): Added for Integer#pow(b, m). * internal.h (rb_int_powm): Declared to refer in numeric.c. * bignum.c (bary_powm_gmp): Added for Integer#pow(b, m) using GMP. * bignum.c (int_pow_tmp1): Added for implementing Integer#pow(b, m). * bignum.c (int_pow_tmp2, int_pow_tmp3): ditto. * internal.h (rb_num_positive_int_p): Moved from numeric.c for sharing the definition with bignum.c. * internal.h (rb_num_negative_int_p, rb_num_compare_with_zero): ditto. * numeric.c(negative_int_p): Moved to internal.h for sharing the definition with bignum.c. * numeric.c (positive_int_p, compare_with_zero): ditto. * numeric.c (rb_int_odd_p): Exported (renamed from int_odd_p). * internal.h (rb_int_odd_p): ditto. * internal.h (HALF_LONG_MSB): Added. * numeric.c (SQRT_LONG_MAX): Redefined by using HALF_LONG_MSB. * test/ruby/test_numeric.rb (test_pow): Added for Integer#pow(b, m). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61003 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c78
1 files changed, 18 insertions, 60 deletions
diff --git a/numeric.c b/numeric.c
index 1858113c09..1639787154 100644
--- a/numeric.c
+++ b/numeric.c
@@ -162,7 +162,6 @@ static VALUE fix_mul(VALUE x, VALUE y);
static VALUE fix_lshift(long, unsigned long);
static VALUE fix_rshift(long, unsigned long);
static VALUE int_pow(long x, unsigned long y);
-static VALUE int_odd_p(VALUE x);
static VALUE int_even_p(VALUE x);
static int int_round_zero_p(VALUE num, int ndigits);
VALUE rb_int_floor(VALUE num, int ndigits);
@@ -271,17 +270,6 @@ rb_num_to_uint(VALUE val, unsigned int *ret)
#define method_basic_p(klass) rb_method_basic_definition_p(klass, mid)
-static VALUE
-compare_with_zero(VALUE num, ID mid)
-{
- VALUE zero = INT2FIX(0);
- VALUE r = rb_check_funcall(num, mid, 1, &zero);
- if (r == Qundef) {
- rb_cmperr(num, zero);
- }
- return r;
-}
-
static inline int
int_pos_p(VALUE num)
{
@@ -306,42 +294,10 @@ int_neg_p(VALUE num)
rb_raise(rb_eTypeError, "not an Integer");
}
-static inline int
-positive_int_p(VALUE num)
-{
- const ID mid = '>';
-
- if (FIXNUM_P(num)) {
- if (method_basic_p(rb_cInteger))
- return FIXNUM_POSITIVE_P(num);
- }
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- if (method_basic_p(rb_cInteger))
- return BIGNUM_POSITIVE_P(num);
- }
- return RTEST(compare_with_zero(num, mid));
-}
-
-static inline int
-negative_int_p(VALUE num)
-{
- const ID mid = '<';
-
- if (FIXNUM_P(num)) {
- if (method_basic_p(rb_cInteger))
- return FIXNUM_NEGATIVE_P(num);
- }
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- if (method_basic_p(rb_cInteger))
- return BIGNUM_NEGATIVE_P(num);
- }
- return RTEST(compare_with_zero(num, mid));
-}
-
int
rb_num_negative_p(VALUE num)
{
- return negative_int_p(num);
+ return rb_num_negative_int_p(num);
}
static VALUE
@@ -665,10 +621,10 @@ num_remainder(VALUE x, VALUE y)
VALUE z = num_funcall1(x, '%', y);
if ((!rb_equal(z, INT2FIX(0))) &&
- ((negative_int_p(x) &&
- positive_int_p(y)) ||
- (positive_int_p(x) &&
- negative_int_p(y)))) {
+ ((rb_num_negative_int_p(x) &&
+ rb_num_positive_int_p(y)) ||
+ (rb_num_positive_int_p(x) &&
+ rb_num_negative_int_p(y)))) {
return rb_funcall(z, '-', 1, y);
}
return z;
@@ -769,7 +725,7 @@ num_int_p(VALUE num)
static VALUE
num_abs(VALUE num)
{
- if (negative_int_p(num)) {
+ if (rb_num_negative_int_p(num)) {
return num_funcall0(num, idUMinus);
}
return num;
@@ -886,7 +842,7 @@ num_positive_p(VALUE num)
if (method_basic_p(rb_cInteger))
return BIGNUM_POSITIVE_P(num) && !rb_bigzero_p(num) ? Qtrue : Qfalse;
}
- return compare_with_zero(num, mid);
+ return rb_num_compare_with_zero(num, mid);
}
/*
@@ -899,7 +855,7 @@ num_positive_p(VALUE num)
static VALUE
num_negative_p(VALUE num)
{
- return negative_int_p(num) ? Qtrue : Qfalse;
+ return rb_num_negative_int_p(num) ? Qtrue : Qfalse;
}
@@ -2072,7 +2028,7 @@ int_round_half_down(SIGNED_VALUE x, SIGNED_VALUE y)
static int
int_half_p_half_even(VALUE num, VALUE n, VALUE f)
{
- return (int)int_odd_p(rb_int_idiv(n, f));
+ return (int)rb_int_odd_p(rb_int_idiv(n, f));
}
static int
@@ -2939,7 +2895,7 @@ rb_fix2uint(VALUE val)
}
num = FIX2ULONG(val);
- check_uint(num, negative_int_p(val));
+ check_uint(num, rb_num_negative_int_p(val));
return num;
}
#else
@@ -3025,7 +2981,7 @@ rb_fix2ushort(VALUE val)
}
num = FIX2ULONG(val);
- check_ushort(num, negative_int_p(val));
+ check_ushort(num, rb_num_negative_int_p(val));
return num;
}
@@ -3168,8 +3124,8 @@ int_int_p(VALUE num)
* Returns +true+ if +int+ is an odd number.
*/
-static VALUE
-int_odd_p(VALUE num)
+VALUE
+rb_int_odd_p(VALUE num)
{
if (FIXNUM_P(num)) {
if (num & 2) {
@@ -3567,7 +3523,7 @@ rb_int_minus(VALUE x, VALUE y)
}
-#define SQRT_LONG_MAX ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2))
+#define SQRT_LONG_MAX HALF_LONG_MSB
/*tests if N*N would overflow*/
#define FIT_SQRT_LONG(n) (((n)<SQRT_LONG_MAX)&&((n)>=-SQRT_LONG_MAX))
@@ -3976,7 +3932,7 @@ fix_pow(VALUE x, VALUE y)
if (int_even_p(y)) return INT2FIX(1);
else return INT2FIX(-1);
}
- if (negative_int_p(y))
+ if (rb_num_negative_int_p(y))
return num_funcall1(rb_rational_raw1(x), idPow, y);
if (a == 0) return INT2FIX(0);
x = rb_int2big(FIX2LONG(x));
@@ -5394,7 +5350,7 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "to_s", int_to_s, -1);
rb_define_alias(rb_cInteger, "inspect", "to_s");
rb_define_method(rb_cInteger, "integer?", int_int_p, 0);
- rb_define_method(rb_cInteger, "odd?", int_odd_p, 0);
+ rb_define_method(rb_cInteger, "odd?", rb_int_odd_p, 0);
rb_define_method(rb_cInteger, "even?", int_even_p, 0);
rb_define_method(rb_cInteger, "upto", int_upto, 1);
rb_define_method(rb_cInteger, "downto", int_downto, 1);
@@ -5426,6 +5382,8 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "fdiv", rb_int_fdiv, 1);
rb_define_method(rb_cInteger, "**", rb_int_pow, 1);
+ rb_define_method(rb_cInteger, "pow", rb_int_powm, -1);
+
rb_define_method(rb_cInteger, "abs", rb_int_abs, 0);
rb_define_method(rb_cInteger, "magnitude", rb_int_abs, 0);