mirror of
https://github.com/ruby/ruby.git
synced 2026-01-26 12:14:51 +00:00
[Bug #21814] Fix negative bignum modulo
If modulo is zero, do not apply bias even if the divisor is zero. `BIGNUM_POSITIVE_P` is true even on bignum zero.
This commit is contained in:
parent
966dbba8db
commit
19e539c9ee
Notes:
git
2025-12-30 14:45:56 +00:00
9
bignum.c
9
bignum.c
@ -7070,7 +7070,7 @@ int_pow_tmp3(VALUE x, VALUE y, VALUE m, int nega_flg)
|
|||||||
zn = mn;
|
zn = mn;
|
||||||
z = bignew(zn, 1);
|
z = bignew(zn, 1);
|
||||||
bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
|
bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
|
||||||
if (nega_flg & BIGNUM_POSITIVE_P(z)) {
|
if (nega_flg && BIGNUM_POSITIVE_P(z) && !BIGZEROP(z)) {
|
||||||
z = rb_big_minus(z, m);
|
z = rb_big_minus(z, m);
|
||||||
}
|
}
|
||||||
RB_GC_GUARD(x);
|
RB_GC_GUARD(x);
|
||||||
@ -7098,7 +7098,7 @@ int_pow_tmp3(VALUE x, VALUE y, VALUE m, int nega_flg)
|
|||||||
x = rb_int_modulo(x, m);
|
x = rb_int_modulo(x, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nega_flg && rb_int_positive_p(tmp)) {
|
if (nega_flg && rb_int_positive_p(tmp) && !rb_int_zero_p(tmp)) {
|
||||||
tmp = rb_int_minus(tmp, m);
|
tmp = rb_int_minus(tmp, m);
|
||||||
}
|
}
|
||||||
return tmp;
|
return tmp;
|
||||||
@ -7210,6 +7210,11 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
|
|||||||
rb_raise(rb_eTypeError, "Integer#pow() 2nd argument not allowed unless all arguments are integers");
|
rb_raise(rb_eTypeError, "Integer#pow() 2nd argument not allowed unless all arguments are integers");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rb_int_zero_p(a) && !rb_int_zero_p(b)) {
|
||||||
|
/* shortcut; 0**x => 0 except for x == 0 */
|
||||||
|
return INT2FIX(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (rb_int_negative_p(m)) {
|
if (rb_int_negative_p(m)) {
|
||||||
m = rb_int_uminus(m);
|
m = rb_int_uminus(m);
|
||||||
nega_flg = 1;
|
nega_flg = 1;
|
||||||
|
|||||||
@ -489,6 +489,10 @@ class TestNumeric < Test::Unit::TestCase
|
|||||||
assert_equal(0, 0.pow(3, 1))
|
assert_equal(0, 0.pow(3, 1))
|
||||||
assert_equal(0, 2.pow(3, 1))
|
assert_equal(0, 2.pow(3, 1))
|
||||||
assert_equal(0, -2.pow(3, 1))
|
assert_equal(0, -2.pow(3, 1))
|
||||||
|
|
||||||
|
min, max = RbConfig::LIMITS.values_at("FIXNUM_MIN", "FIXNUM_MAX")
|
||||||
|
assert_equal(0, 0.pow(2, min))
|
||||||
|
assert_equal(0, Integer.sqrt(max+1).pow(2, min))
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user