@@ -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
@@ -1171,4 +1172,32 @@ mod tests {
11711172 let y = ModInt :: new ( 123 ) . pow ( 0 ) ;
11721173 assert_eq ! ( y. val( ) , 0 ) ;
11731174 }
1175+
1176+ // test `2^31 < modulus < 2^32` case
1177+ // https://github.com/rust-lang-ja/ac-library-rs/issues/111
1178+ // https://github.com/atcoder/ac-library/issues/149
1179+ // https://github.com/atcoder/ac-library/pull/163
1180+ // https://github.com/atcoder/ac-library/issues/164
1181+ #[ test]
1182+ fn dynamic_modint_m32 ( ) {
1183+ let m = 3221225471 ;
1184+ ModInt :: set_modulus ( m) ;
1185+ let f = ModInt :: new :: < u32 > ;
1186+ assert_eq ! ( f( 1398188832 ) + f( 3184083880 ) , f( 1361047241 ) ) ;
1187+ assert_eq ! ( f( 3013899062 ) + f( 2238406135 ) , f( 2031079726 ) ) ;
1188+ assert_eq ! ( f( 2699997885 ) + f( 2745140255 ) , f( 2223912669 ) ) ;
1189+ assert_eq ! ( f( 2824399978 ) + f( 2531872141 ) , f( 2135046648 ) ) ;
1190+ assert_eq ! ( f( 36496612 ) - f( 2039504668 ) , f( 1218217415 ) ) ;
1191+ assert_eq ! ( f( 266176802 ) - f( 1609833977 ) , f( 1877568296 ) ) ;
1192+ assert_eq ! ( f( 713535382 ) - f( 2153383999 ) , f( 1781376854 ) ) ;
1193+ assert_eq ! ( f( 1249965147 ) - f( 3144251805 ) , f( 1326938813 ) ) ;
1194+ assert_eq ! ( f( 2692223381 ) * f( 2935379475 ) , f( 2084179397 ) ) ;
1195+ assert_eq ! ( f( 2800462205 ) * f( 2822998916 ) , f( 2089431198 ) ) ;
1196+ assert_eq ! ( f( 3061947734 ) * f( 3210920667 ) , f( 1962208034 ) ) ;
1197+ assert_eq ! ( f( 3138997926 ) * f( 2994465129 ) , f( 1772479317 ) ) ;
1198+ assert_eq ! ( f( 2947552629 ) / f( 576466398 ) , f( 2041593039 ) ) ;
1199+ assert_eq ! ( f( 2914694891 ) / f( 399734126 ) , f( 1983162347 ) ) ;
1200+ assert_eq ! ( f( 2202862138 ) / f( 1154428799 ) , f( 2139936238 ) ) ;
1201+ assert_eq ! ( f( 3037207894 ) / f( 2865447143 ) , f( 1894581230 ) ) ;
1202+ }
11741203}
0 commit comments