Skip to content

Commit ab2c3ed

Browse files
committed
modint: add/sub impl fix for 2^31<modulus<2^32
1 parent 64163e1 commit ab2c3ed

File tree

1 file changed

+36
-8
lines changed

1 file changed

+36
-8
lines changed

src/modint.rs

+36-8
Original file line numberDiff line numberDiff line change
@@ -793,20 +793,21 @@ trait InternalImplementations: ModIntBase {
793793
#[inline]
794794
fn add_impl(lhs: Self, rhs: Self) -> Self {
795795
let modulus = Self::modulus();
796-
let mut val = lhs.val() + rhs.val();
797-
if val >= modulus {
798-
val -= modulus;
799-
}
796+
let v = u64::from(lhs.val()) + u64::from(rhs.val());
797+
let val = match v.overflowing_sub(u64::from(modulus)) {
798+
(_, true) => v as u32,
799+
(w, false) => w as u32,
800+
};
800801
Self::raw(val)
801802
}
802803

803804
#[inline]
804805
fn sub_impl(lhs: Self, rhs: Self) -> Self {
805806
let modulus = Self::modulus();
806-
let mut val = lhs.val().wrapping_sub(rhs.val());
807-
if val >= modulus {
808-
val = val.wrapping_add(modulus)
809-
}
807+
let val = match lhs.val().overflowing_sub(rhs.val()) {
808+
(v, true) => v.wrapping_add(modulus),
809+
(v, false) => v,
810+
};
810811
Self::raw(val)
811812
}
812813

@@ -1050,6 +1051,8 @@ impl_folding! {
10501051

10511052
#[cfg(test)]
10521053
mod tests {
1054+
#![allow(clippy::unreadable_literal)]
1055+
use crate::modint::ModInt;
10531056
use crate::modint::ModInt1000000007;
10541057

10551058
#[test]
@@ -1157,4 +1160,29 @@ mod tests {
11571160
c /= b;
11581161
assert_eq!(expected, c);
11591162
}
1163+
1164+
// test `2^31 < modulus < 2^32` case
1165+
// https://github.com/rust-lang-ja/ac-library-rs/issues/111
1166+
#[test]
1167+
fn dynamic_modint_m32() {
1168+
let m = 3221225471;
1169+
ModInt::set_modulus(m);
1170+
let f = ModInt::new::<u32>;
1171+
assert_eq!(f(1398188832) + f(3184083880), f(1361047241));
1172+
assert_eq!(f(3013899062) + f(2238406135), f(2031079726));
1173+
assert_eq!(f(2699997885) + f(2745140255), f(2223912669));
1174+
assert_eq!(f(2824399978) + f(2531872141), f(2135046648));
1175+
assert_eq!(f(36496612) - f(2039504668), f(1218217415));
1176+
assert_eq!(f(266176802) - f(1609833977), f(1877568296));
1177+
assert_eq!(f(713535382) - f(2153383999), f(1781376854));
1178+
assert_eq!(f(1249965147) - f(3144251805), f(1326938813));
1179+
assert_eq!(f(2692223381) * f(2935379475), f(2084179397));
1180+
assert_eq!(f(2800462205) * f(2822998916), f(2089431198));
1181+
assert_eq!(f(3061947734) * f(3210920667), f(1962208034));
1182+
assert_eq!(f(3138997926) * f(2994465129), f(1772479317));
1183+
assert_eq!(f(2947552629) / f(576466398), f(2041593039));
1184+
assert_eq!(f(2914694891) / f(399734126), f(1983162347));
1185+
assert_eq!(f(2202862138) / f(1154428799), f(2139936238));
1186+
assert_eq!(f(3037207894) / f(2865447143), f(1894581230));
1187+
}
11601188
}

0 commit comments

Comments
 (0)