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 /internal.h | |
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 'internal.h')
-rw-r--r-- | internal.h | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/internal.h b/internal.h index 9d33ed99d1..81ecb876ad 100644 --- a/internal.h +++ b/internal.h @@ -39,6 +39,12 @@ extern "C" { # endif #endif +/* The most significant bit of the lower part of half-long integer. + * If sizeof(long) == 4, this is 0x8000. + * If sizeof(long) == 8, this is 0x80000000. + */ +#define HALF_LONG_MSB ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2)) + #define LIKELY(x) RB_LIKELY(x) #define UNLIKELY(x) RB_UNLIKELY(x) @@ -1074,6 +1080,7 @@ VALUE rb_big_gt(VALUE x, VALUE y); VALUE rb_big_ge(VALUE x, VALUE y); VALUE rb_big_lt(VALUE x, VALUE y); VALUE rb_big_le(VALUE x, VALUE y); +VALUE rb_int_powm(int const argc, VALUE * const argv, VALUE const num); /* class.c */ VALUE rb_class_boot(VALUE); @@ -1380,6 +1387,53 @@ VALUE rb_int_and(VALUE x, VALUE y); VALUE rb_int_lshift(VALUE x, VALUE y); VALUE rb_int_div(VALUE x, VALUE y); VALUE rb_int_abs(VALUE num); +VALUE rb_int_odd_p(VALUE num); + +static inline VALUE +rb_num_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 +rb_num_positive_int_p(VALUE num) +{ + const ID mid = '>'; + + if (FIXNUM_P(num)) { + if (rb_method_basic_definition_p(rb_cInteger, mid)) + return FIXNUM_POSITIVE_P(num); + } + else if (RB_TYPE_P(num, T_BIGNUM)) { + if (rb_method_basic_definition_p(rb_cInteger, mid)) + return BIGNUM_POSITIVE_P(num); + } + return RTEST(rb_num_compare_with_zero(num, mid)); +} + + +static inline int +rb_num_negative_int_p(VALUE num) +{ + const ID mid = '<'; + + if (FIXNUM_P(num)) { + if (rb_method_basic_definition_p(rb_cInteger, mid)) + return FIXNUM_NEGATIVE_P(num); + } + else if (RB_TYPE_P(num, T_BIGNUM)) { + if (rb_method_basic_definition_p(rb_cInteger, mid)) + return BIGNUM_NEGATIVE_P(num); + } + return RTEST(rb_num_compare_with_zero(num, mid)); +} + + VALUE rb_float_abs(VALUE flt); VALUE rb_float_equal(VALUE x, VALUE y); VALUE rb_float_eql(VALUE x, VALUE y); |