diff options
author | mrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-04 02:35:40 +0000 |
---|---|---|
committer | mrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-04 02:35:40 +0000 |
commit | 9b09cc8a37ca80c7126bfc4ffc39ce9dddcdb1d8 (patch) | |
tree | 077a5bcc275ca50f1588428b384e742f8366f43a /numeric.c | |
parent | 58b3f3654634e86a3d89c74294b8356008ae8597 (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.c | 78 |
1 files changed, 18 insertions, 60 deletions
@@ -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); |