1use std::fmt::Debug;
4use std::iter::{Product, Sum};
5use std::ops::{
6 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
7 Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
8};
9
10pub trait Number:
12 Copy
13 + Debug
14 + Default
15 + PartialEq
16 + PartialOrd
17 + Add<Output = Self>
18 + AddAssign
19 + Div<Output = Self>
20 + DivAssign
21 + Mul<Output = Self>
22 + MulAssign
23 + Rem<Output = Self>
24 + RemAssign
25 + Sub<Output = Self>
26 + SubAssign
27 + Sum<Self>
28 + for<'a> Sum<&'a Self>
29 + Product<Self>
30 + for<'a> Product<&'a Self>
31{
32 const ZERO: Self;
33 const ONE: Self;
34 const MIN: Self;
35 const MAX: Self;
36
37 #[must_use]
38 fn abs(self) -> Self;
39 #[must_use]
40 fn rem_euclid(self, rhs: Self) -> Self;
41}
42
43pub trait Signed: Number + Neg<Output = Self> + From<i8> {
45 const MINUS_ONE: Self;
46}
47
48pub trait Integer:
50 Number
51 + Not<Output = Self>
52 + BitAnd<Output = Self>
53 + BitAndAssign
54 + BitOr<Output = Self>
55 + BitOrAssign
56 + BitXor<Output = Self>
57 + BitXorAssign
58 + Shl<Output = Self>
59 + Shl<u32, Output = Self>
60 + ShlAssign
61 + ShlAssign<u32>
62 + Shr<Output = Self>
63 + Shr<u32, Output = Self>
64 + ShrAssign
65 + ShrAssign<u32>
66 + TryInto<i128>
67{
68 type Unsigned: UnsignedInteger;
69 type Signed: SignedInteger;
70
71 #[must_use]
72 fn abs_diff(self, rhs: Self) -> Self::Unsigned;
73 #[must_use]
74 fn checked_add(self, rhs: Self) -> Option<Self>;
75 #[must_use]
76 fn checked_sub(self, rhs: Self) -> Option<Self>;
77 #[must_use]
78 fn checked_mul(self, rhs: Self) -> Option<Self>;
79 #[must_use]
80 fn trailing_ones(self) -> u32;
81 #[must_use]
82 fn trailing_zeros(self) -> u32;
83 #[must_use]
84 fn unsigned_abs(self) -> Self::Unsigned;
85 #[must_use]
86 fn saturating_sub_0(self, rhs: Self) -> Self::Unsigned;
87}
88
89pub trait UnsignedInteger: Integer<Unsigned = Self> + From<u8> {
91 #[must_use]
92 fn wrapping_add_signed(self, rhs: Self::Signed) -> Self;
93}
94
95pub trait SignedInteger: Integer<Signed = Self> + Signed {}
97
98macro_rules! number_impl {
99 (int => $($u:ident: $s:ident ),+) => {
100 $(impl Number for $u {
101 const ZERO: Self = 0;
102 const ONE: Self = 1;
103 const MIN: Self = Self::MIN;
104 const MAX: Self = Self::MAX;
105
106 #[inline]
107 fn abs(self) -> Self {
108 self }
110
111 #[inline]
112 fn rem_euclid(self, rhs: Self) -> Self {
113 self.rem_euclid(rhs)
114 }
115 })+
116
117 $(impl Integer for $u {
118 type Unsigned = $u;
119 type Signed = $s;
120
121 #[inline]
122 fn abs_diff(self, rhs: Self) -> Self::Unsigned {
123 self.abs_diff(rhs)
124 }
125 #[inline]
126 fn checked_add(self, rhs: Self) -> Option<Self> {
127 self.checked_add(rhs)
128 }
129 #[inline]
130 fn checked_sub(self, rhs: Self) -> Option<Self> {
131 self.checked_sub(rhs)
132 }
133 #[inline]
134 fn checked_mul(self, rhs: Self) -> Option<Self> {
135 self.checked_mul(rhs)
136 }
137 #[inline]
138 fn trailing_ones(self) -> u32 {
139 self.trailing_ones()
140 }
141 #[inline]
142 fn trailing_zeros(self) -> u32 {
143 self.trailing_zeros()
144 }
145 #[inline]
146 fn unsigned_abs(self) -> Self::Unsigned {
147 self }
149 #[inline]
150 fn saturating_sub_0(self, rhs: Self) -> Self::Unsigned {
151 self.saturating_sub(rhs)
152 }
153 })+
154
155 $(impl UnsignedInteger for $u {
156 #[inline]
157 fn wrapping_add_signed(self, rhs: Self::Signed) -> Self {
158 self.wrapping_add_signed(rhs)
159 }
160 })+
161
162 $(impl Number for $s {
163 const ZERO: Self = 0;
164 const ONE: Self = 1;
165 const MIN: Self = Self::MIN;
166 const MAX: Self = Self::MAX;
167
168 #[inline]
169 fn abs(self) -> Self {
170 self.abs()
171 }
172
173 #[inline]
174 fn rem_euclid(self, rhs: Self) -> Self {
175 self.rem_euclid(rhs)
176 }
177 })+
178
179 $(impl Signed for $s {
180 const MINUS_ONE: Self = -Self::ONE;
181 })+
182
183 $(impl Integer for $s {
184 type Unsigned = $u;
185 type Signed = $s;
186
187 #[inline]
188 fn abs_diff(self, rhs: Self) -> Self::Unsigned {
189 self.abs_diff(rhs)
190 }
191 #[inline]
192 fn checked_add(self, rhs: Self) -> Option<Self> {
193 self.checked_add(rhs)
194 }
195 #[inline]
196 fn checked_sub(self, rhs: Self) -> Option<Self> {
197 self.checked_sub(rhs)
198 }
199 #[inline]
200 fn checked_mul(self, rhs: Self) -> Option<Self> {
201 self.checked_mul(rhs)
202 }
203 #[inline]
204 fn trailing_ones(self) -> u32 {
205 self.trailing_ones()
206 }
207 #[inline]
208 fn trailing_zeros(self) -> u32 {
209 self.trailing_zeros()
210 }
211 #[inline]
212 fn unsigned_abs(self) -> Self::Unsigned {
213 self.unsigned_abs()
214 }
215 #[inline]
216 #[expect(clippy::cast_sign_loss)]
217 fn saturating_sub_0(self, rhs: Self) -> Self::Unsigned {
218 let diff = (self as $u).wrapping_sub(rhs as $u);
221 let mask = (0 as $u).wrapping_sub($u::from(self >= rhs));
222 diff & mask
223 }
224 })+
225
226 $(impl SignedInteger for $s {})+
227 };
228 (float => $($t:ident),+) => {$(
229 impl Number for $t {
230 const ZERO: Self = 0.0;
231 const ONE: Self = 1.0;
232 const MIN: Self = Self::NEG_INFINITY;
233 const MAX: Self = Self::INFINITY;
234
235 #[inline]
236 fn abs(self) -> Self {
237 self.abs()
238 }
239
240 #[inline]
241 fn rem_euclid(self, rhs: Self) -> Self {
242 self.rem_euclid(rhs)
243 }
244 }
245
246 impl Signed for $t {
247 const MINUS_ONE: Self = -Self::ONE;
248 }
249 )+};
250}
251number_impl! {int => u8: i8, u16: i16, u32: i32, u64: i64, u128: i128, usize: isize}
252number_impl! {float => f32, f64}
253
254#[inline]
266#[must_use]
267pub fn is_prime<T: UnsignedInteger>(n: T) -> bool {
268 if n <= T::ONE {
269 return false;
270 }
271 if n == T::from(2) || n == T::from(3) {
272 return true;
273 }
274 if n % T::from(2) == T::ZERO || n % T::from(3) == T::ZERO {
275 return false;
276 }
277
278 let mut i = T::from(5);
279 while let Some(square) = i.checked_mul(i)
280 && square <= n
281 {
282 if n % i == T::ZERO || n % (i + T::from(2)) == T::ZERO {
283 return false;
284 }
285
286 if let Some(next) = i.checked_add(T::from(6)) {
287 i = next;
288 } else {
289 break;
290 }
291 }
292
293 true
294}
295
296#[inline]
310#[must_use]
311pub fn sum_of_divisors<T: UnsignedInteger>(n: T) -> Option<T> {
312 if n <= T::ONE {
313 return Some(n);
314 }
315
316 let mut sum = T::ZERO;
317 let mut d = T::ONE;
318 while let Some(square) = d.checked_mul(d)
319 && square <= n
320 {
321 if n % d == T::ZERO {
322 if let Some(s) = sum.checked_add(d) {
323 sum = s;
324 } else {
325 return None;
326 }
327
328 let q = n / d;
329 if q != d {
330 if let Some(s) = sum.checked_add(q) {
331 sum = s;
332 } else {
333 return None;
334 }
335 }
336 }
337
338 d += T::ONE;
339 }
340
341 Some(sum)
342}
343
344#[inline]
358#[must_use]
359pub fn egcd<T: SignedInteger>(mut a: T, mut b: T) -> (T, T, T) {
360 let (mut x0, mut x1, mut y0, mut y1) = (T::ONE, T::ZERO, T::ZERO, T::ONE);
361
362 while b != T::ZERO {
363 let q = a / b;
364 (a, b) = (b, a % b);
365 (x0, x1) = (x1, x0 - q * x1);
366 (y0, y1) = (y1, y0 - q * y1);
367 }
368
369 (a, x0, y0)
370}
371
372#[inline]
381#[must_use]
382pub fn lcm<T: SignedInteger>(a: T, b: T) -> T {
383 if a == T::ZERO || b == T::ZERO {
384 return T::ZERO;
385 }
386
387 let (gcd, ..) = egcd(a, b);
388 (a / gcd).abs() * b.abs()
389}
390
391#[inline]
405#[must_use]
406pub fn mod_inverse<T: SignedInteger>(a: T, b: T) -> Option<T> {
407 let (gcd, x, _) = egcd(a, b);
408 if gcd == T::ONE {
409 Some(x.rem_euclid(b))
410 } else {
411 None
412 }
413}
414
415#[inline]
429#[must_use]
430pub fn chinese_remainder<T: SignedInteger>(
431 residues: impl IntoIterator<Item = T>,
432 moduli: impl IntoIterator<Item = T, IntoIter: Clone>,
433) -> Option<T> {
434 let moduli = moduli.into_iter();
435 let product = moduli.clone().product();
436
437 let mut sum = T::ZERO;
438 for (residue, modulus) in residues.into_iter().zip(moduli) {
439 let p = product / modulus;
440 sum += residue * mod_inverse(p, modulus)? * p;
441 }
442
443 Some(sum.rem_euclid(product))
444}
445
446#[inline]
455#[must_use]
456pub fn mod_pow<T: UnsignedInteger>(base: T, exponent: T, modulus: T) -> T {
457 let mut result = T::ONE;
458 let mut base = base % modulus;
459 let mut exponent = exponent;
460
461 while exponent > T::ZERO {
462 if exponent % T::from(2) == T::ONE {
463 result = (result * base) % modulus;
464 }
465 exponent >>= 1;
466 base = (base * base) % modulus;
467 }
468
469 result
470}