devela/num/int/num_trait/mod.rs
1// devela::num::int::num_trait
2//
3//! Defines the `NumInt` trait.
4//
5// TOC
6// - trait NumInt
7// - base
8// - core
9// - combinatorics
10// - division
11// - factors
12// - primes
13// - roots
14// - macro helpers
15// - link_impls
16// - ref_fn
17
18use super::shared_docs::*;
19#[cfg(feature = "alloc")]
20use crate::Vec;
21use crate::{GcdReturn, Num, NumError as E, NumResult as Result, ValueQuant};
22#[cfg(doc)]
23use E::{
24 MismatchedSizes, NoInverse, NonNegativeRequired, NonZeroRequired, NotImplemented, NotSupported,
25 Overflow,
26};
27
28#[cfg(_int··)]
29mod impls;
30mod r#ref;
31pub use r#ref::NumRefInt;
32
33mod auto_impls {
34 use super::{NumInt, NumRefInt};
35
36 #[rustfmt::skip]
37 impl<T: NumInt> NumRefInt<'_> for &T {}
38 #[rustfmt::skip]
39 impl<T: NumInt> NumRefInt<'_> for &mut T {}
40}
41
42/// Common trait for integer types.
43///
44/// See also [`NumRefInt`] which is automatically implemented for `NumInt` references.
45///
46/// # Notes
47/// - We use `n` to refer to the `self` argument in all method descriptions and formulations.
48/// - Every method in this trait returns [`NotImplemented`] by default.
49/// - Any concrete implementation must define the operations it wants to support.
50/// - Unsupported operations should ideally return [`NotSupported`].
51/// - This trait only includes checked methods, which return a `Result` to handle errors explicitly.
52/// - It aims to provide the same methods across all implementations, returning a result when possible.
53/// - Operations are generally supported if they are valid for some input values.
54/// - Most methods come in two variants, distinguished by their prefixes:
55/// - `int_*` methods take arguments by value.
56/// - `int_ref_*` methods take arguments by reference.
57///
58/// # Methods
59/// - base:
60/// [`digital_root`][Self::int_digital_root],
61/// [`digital_root_base`][Self::int_digital_root_base],
62/// [`digits`][Self::int_digits],
63/// [`digits_sign`][Self::int_digits_sign],
64/// [`digits_base`][Self::int_digits_base],
65/// [`digits_base_sign`][Self::int_digits_base_sign].
66/// - core:
67/// [`abs`][Self::int_abs],
68/// [`is_even`][Self::int_is_even],
69/// [`is_odd`][Self::int_is_odd],
70/// [`gcd`][Self::int_gcd],
71/// [`gcd_ext`][Self::int_gcd_ext],
72/// [`lcm`][Self::int_lcm],
73/// [`scale`][Self::int_scale].
74/// [`midpoint`][Self::int_midpoint].
75/// - combinatorics:
76/// [`factorial`][Self::int_factorial],
77/// [`subfactorial`][Self::int_subfactorial],
78/// [`permute`][Self::int_permute],
79/// [`permute_rep`][Self::int_permute_rep],
80/// [`combine`][Self::int_combine],
81/// [`combine_rep`][Self::int_combine_rep].
82/// - division:
83/// [`div_rem`][Self::int_div_rem],
84/// [`div_ceil`][Self::int_div_ceil],
85/// [`div_floor`][Self::int_div_floor],
86/// [`div_ties_away`][Self::int_div_ties_away],
87/// [`div_ties_towards`][Self::int_div_ties_towards]
88/// [`div_ties_even`][Self::int_div_ties_even],
89/// [`div_ties_odd`][Self::int_div_ties_odd].
90/// - factors:
91/// [`factors`][Self::int_factors],
92/// [`factors_proper`][Self::int_factors_proper],
93/// [`factors_prime`][Self::int_factors_prime],
94/// [`factors_prime_unique`][Self::int_factors_prime_unique],
95/// [`factors_buf`][Self::int_factors_buf`],
96/// [`factors_proper_buf`][Self::int_factors_proper_buf`],
97/// [`factors_prime_buf`][Self::int_factors_prime_buf`],
98/// [`factors_prime_unique_buf`][Self::int_factors_prime_unique_buf`].
99/// - modulo:
100/// [`modulo`][Self::int_modulo],
101/// [`modulo_cycles`][Self::int_modulo_cycles],
102/// [`modulo_add`][Self::int_modulo_add],
103/// [`modulo_add_cycles`][Self::int_modulo_add_cycles],
104/// [`modulo_add_inv`][Self::int_modulo_add_inv],
105/// [`modulo_sub`][Self::int_modulo_sub],
106/// [`modulo_sub_cycles`][Self::int_modulo_sub_cycles],
107/// [`modulo_mul`][Self::int_modulo_mul],
108/// [`modulo_mul_cycles`][Self::int_modulo_mul_cycles],
109/// [`modulo_mul_inv`][Self::int_modulo_mul_inv],
110/// [`modulo_div`][Self::int_modulo_div].
111/// - primes:
112/// [`is_prime`][Self::int_is_prime],
113/// [`prime_nth`][Self::int_prime_nth],
114/// [`prime_pi`][Self::int_prime_pi],
115/// [`totient`][Self::int_totient].
116/// - roots:
117/// [`is_square`][Self::int_is_square],
118// [`is_power`][Self::int_is_power], TODO
119/// [`sqrt_ceil`][Self::int_sqrt_ceil],
120/// [`sqrt_floor`][Self::int_sqrt_floor],
121/// [`sqrt_round`][Self::int_sqrt_round],
122/// [`root_ceil`][Self::int_root_ceil],
123/// [`root_floor`][Self::int_root_floor].
124// [`root_round`][Self::int_root_round], TODO
125//
126// In sync with src/num/int/num_trait/ref.rs (int_ref_* methods)
127#[cfg_attr(feature = "nightly_doc", doc(notable_trait))]
128#[expect(unused_variables, reason = "pretty signatures")]
129#[rustfmt::skip]
130pub trait NumInt: Num {
131 /// Specifically signed output type for some operations (â–¶ `int_gcd_ext`).
132 type OutI;
133
134 /* base */
135
136 /// Returns the digital root in base 10.
137 #[doc = link_impls!["digital_root"]]
138 fn int_digital_root(self) -> Result<Self::Out> where Self: Sized { E::ni() }
139 #[doc = ref_fn!["int_digital_root"]]
140 fn int_ref_digital_root(&self) -> Result<Self::Out> { E::ni() }
141
142 /// Returns the digital root in the given `base`.
143 #[doc = link_impls!["digital_root_base"]]
144 fn int_digital_root_base(self, base: Self::Rhs) -> Result<Self::Out>
145 where Self: Sized { E::ni() }
146 #[doc = ref_fn!["int_digital_root_base"]]
147 fn int_ref_digital_root_base(&self, base: &Self::Rhs) -> Result<Self::Out> { E::ni() }
148
149 /// Returns the number of digits in base 10.
150 #[doc = link_impls!["digits"]]
151 fn int_digits(self) -> Result<Self::Out> where Self: Sized { E::ni() }
152 #[doc = ref_fn!["int_digits"]]
153 fn int_ref_digits(&self) -> Result<Self::Out> { E::ni() }
154
155 /// Returns the number of digits in base 10 including the negative sign.
156 #[doc = link_impls!["digits_sign"]]
157 fn int_digits_sign(self) -> Result<Self::Out> where Self: Sized { E::ni() }
158 #[doc = ref_fn!["int_digits_sign"]]
159 fn int_ref_digits_sign(&self) -> Result<Self::Out> { E::ni() }
160
161 /// Returns the number of digits in the given `base`.
162 #[doc = link_impls!["digits_base"]]
163 fn int_digits_base(self, base: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
164 #[doc = ref_fn!["int_digits_base"]]
165 fn int_ref_digits_base(&self, base: &Self::Rhs) -> Result<Self::Out> { E::ni() }
166
167 /// Returns the number of digits in the given `base`.
168 #[doc = link_impls!["digits_base_sign"]]
169 fn int_digits_base_sign(self, base: Self::Rhs)
170 -> Result<Self::Out> where Self: Sized { E::ni() }
171 #[doc = ref_fn!["int_digits_base_sign"]]
172 fn int_ref_digits_base_sign(&self, base: &Self::Rhs) -> Result<Self::Out> { E::ni() }
173
174 /* core */
175
176 /// Returns the absolute value.
177 #[doc = link_impls!["abs"]]
178 fn int_abs(self) -> Result<Self::Out> where Self: Sized { E::ni() }
179 #[doc = ref_fn!["int_abs"]]
180 fn int_ref_abs(&self) -> Result<Self::Out> { E::ni() }
181
182 /// Returns `true` if `self` is even.
183 #[doc = link_impls!["is_even"]]
184 fn int_is_even(self) -> Result<bool> where Self: Sized { E::ni() }
185 #[doc = ref_fn!["int_is_even"]]
186 fn int_ref_is_even(&self) -> Result<bool> { E::ni() }
187
188 /// Returns `true` if `self` is odd.
189 #[doc = link_impls!["is_odd"]]
190 fn int_is_odd(self) -> Result<bool> where Self: Sized { E::ni() }
191 #[doc = ref_fn!["int_is_odd"]]
192 fn int_ref_is_odd(&self) -> Result<bool> { E::ni() }
193
194 /// Returns the <abbr title="Greatest Common Divisor">GCD</abbr>.
195 #[doc = link_impls!["gcd"]]
196 fn int_gcd(self, other: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
197 #[doc = ref_fn!["int_gcd"]]
198 fn int_ref_gcd(&self, other: &Self::Rhs) -> Result<Self::Out> { E::ni() }
199
200 /// Returns the <abbr title="Greatest Common Divisor">GCD</abbr> and the Bézout coeficients.
201 #[doc = link_impls!["gcd_ext"]]
202 fn int_gcd_ext(self, other: Self::Rhs)
203 -> Result<GcdReturn<Self::Out, Self::OutI>> where Self: Sized { E::ni() }
204 #[doc = ref_fn!["int_gcd_ext"]]
205 fn int_ref_gcd_ext(&self, other: &Self::Rhs)
206 -> Result<GcdReturn<Self::Out, Self::OutI>> { E::ni() }
207
208 /// Returns the <abbr title="Least Common Multiple">LCM</abbr>.
209 #[doc = link_impls!["lcm"]]
210 fn int_lcm(self, other: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
211 #[doc = ref_fn!["int_lcm"]]
212 fn int_ref_lcm(&self, other: &Self::Rhs) -> Result<Self::Out> { E::ni() }
213
214 /// Returns a scaled value in `[min..=max]` to a new range `[a..=b]`.
215 /// If the value lies outside of `[min..=max]` it will result in extrapolation.
216 ///
217 /// # Errors
218 /// Can [`Overflow`] for extrapolated values that can't fit the type,
219 /// and for overflowing arithmetic operations in the following formula:
220 ///
221 /// # Formulation
222 #[doc = FORMULA_SCALE!()]
223 #[doc = link_impls!["scale"]]
224 fn int_scale(self, min: Self::Rhs, max: Self::Rhs, a: Self::Rhs, b: Self::Rhs)
225 -> Result<Self::Out> where Self: Sized { E::ni() }
226 #[doc = ref_fn!["int_scale"]]
227 fn int_ref_scale(&self, min: &Self::Rhs, max: &Self::Rhs, a: &Self::Rhs, b: &Self::Rhs)
228 -> Result<Self::Out> { E::ni() }
229
230 /// Returns a scaled value between `[min..=max]` to a new range `[a..=b]`.
231 ///
232 /// If the value lies outside of `[min..=max]` it will result in extrapolation, and
233 /// if the value doesn't fit in the type it will wrap around its boundaries.
234 ///
235 /// # Panics
236 /// Could panic for very large values on some implementations.
237 ///
238 /// # Formulation
239 #[doc = FORMULA_SCALE!()] // (same as scale)
240 #[doc = link_impls!["scale_wrap"]]
241 fn int_scale_wrap(self, min: Self::Rhs, max: Self::Rhs, a: Self::Rhs, b: Self::Rhs)
242 -> Result<Self::Out> where Self: Sized { E::ni() }
243 #[doc = ref_fn!["int_scale_wrap"]]
244 fn int_ref_scale_wrap(&self, min: &Self::Rhs, max: &Self::Rhs, a: &Self::Rhs, b: &Self::Rhs)
245 -> Result<Self::Out> { E::ni() }
246
247 /// Returns the midpoint of `self` and `other`.
248 #[doc = link_impls!["midpoint"]]
249 fn int_midpoint(self, other: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
250 #[doc = ref_fn!["int_midpoint"]]
251 fn int_ref_midpoint(&self, other: &Self::Rhs) -> Result<Self::Out> { E::ni() }
252
253 /* combinatorics */
254
255 /// Returns the factorial.
256 ///
257 /// Permutations of *n* items, ordered, where $n = r$.
258 ///
259 /// # Formulation
260 #[doc = FORMULA_FACTORIAL!()]
261 ///
262 /// These are the maximum numbers whose factorials can fit within
263 /// standard signed integer types:
264 /// - 5 for `i8`, 7 for `i16`, 12 for `i32`, 20 for `i64` and 33 for `i128`.
265 /// - 5 for `u8`, 8 for `u16`, 12 for `u32`, 20 for `u64` and 34 for `u128`.
266 /// # Errors
267 /// Returns [`NonNegativeRequired`] if $n<0$ and [`Overflow`] if the result can't fit the type.
268 #[doc = link_impls!["factorial"]]
269 fn int_factorial(self) -> Result<Self::Out> where Self: Sized { E::ni() }
270 #[doc = ref_fn!["int_factorial"]]
271 fn int_ref_factorial(&self) -> Result<Self::Out> { E::ni() }
272
273 /// Returns the subfactorial, or the number of derangements.
274 ///
275 /// Permutations of *n* items which no element appears in its original position.
276 ///
277 /// # Formulation
278 /// The subfactorial $!n$ is defined recursively as:
279 #[doc = FORMULA_SUBFACTORIAL_RECURSIVE!()]
280 ///
281 /// These are the maximum numbers whose subfactorials can fit within
282 /// standard signed integer types:
283 /// - 5 for `i8`, 8 for `i16`, 12 for `i32`, 20 for `i64` and 35 for `i128`.
284 /// - 5 for `u8`, 8 for `u16`, 13 for `u32`, 20 for `u64` and 35 for `u128`.
285 ///
286 /// # Errors
287 /// Returns [`NonNegativeRequired`] if $n<0$,
288 /// and [`Overflow`] if the result can't fit the type.
289 /// # Links
290 /// - The list of subfactorials is available in <https://oeis.org/A000166>.
291 #[doc = link_impls!["subfactorial"]]
292 fn int_subfactorial(self) -> Result<Self::Out> where Self: Sized { E::ni() }
293 #[doc = ref_fn!["int_subfactorial"]]
294 fn int_ref_subfactorial(&self) -> Result<Self::Out> { E::ni() }
295
296 /// Returns the number of combinations of `n` items taken `r` at a time, unordered.
297 ///
298 /// # Formulation
299 #[doc = FORMULA_COMBINE_REP!()]
300 ///
301 /// # Errors
302 /// Returns [`MismatchedSizes`] if $r > n$ and [`Overflow`] if the result cant't fit the type.
303 #[doc = link_impls!["combine"]]
304 fn int_combine(self, r: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
305 #[doc = ref_fn!["int_combine"]]
306 fn int_ref_combine(&self, r: &Self::Rhs) -> Result<Self::Out> { E::ni() }
307
308 /// Returns the number of permutations of `n` items taken `r` at a time with repetitions,
309 /// unordered.
310 ///
311 /// Also known as *multichoose*.
312 ///
313 /// # Formulation
314 #[doc = FORMULA_COMBINE_REP!()]
315 ///
316 /// # Errors
317 /// Returns [`Overflow`] if the result cant't fit the type.
318 #[doc = link_impls!["combine_rep"]]
319 fn int_combine_rep(self, r: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
320 #[doc = ref_fn!["int_combine_rep"]]
321 fn int_ref_combine_rep(&self, r: &Self::Rhs) -> Result<Self::Out> { E::ni() }
322
323 /// Returns the number of permutations of `n` items taken `r` at a time, ordered.
324 ///
325 /// When $n=r$ or $n=r-1$ the result is the same as calculating the factorial $n!$.
326 ///
327 /// # Formulation
328 #[doc = FORMULA_PERMUTE!()]
329 ///
330 /// # Errors
331 /// Returns [`MismatchedSizes`] if $r > n$ and [`Overflow`] if the result cant't fit the type.
332 #[doc = link_impls!["permute"]]
333 fn int_permute(self, r: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
334 #[doc = ref_fn!["int_permute"]]
335 fn int_ref_permute(&self, r: &Self::Rhs) -> Result<Self::Out> { E::ni() }
336
337 /// Returns the number of permutations of n` items taken `r` at a time with repetitions,
338 /// ordered.
339 ///
340 /// # Formulation
341 #[doc = FORMULA_PERMUTE_REP!()]
342 ///
343 /// # Errors
344 /// Returns [`Overflow`] if the result cant't fit the type.
345 #[doc = link_impls!["permute_rep"]]
346 fn int_permute_rep(self, r: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
347 #[doc = ref_fn!["int_permute_rep"]]
348 fn int_ref_permute_rep(&self, r: &Self::Rhs) -> Result<Self::Out> { E::ni() }
349
350 /* division */
351
352 /// Returns the truncated quotient and the remainder.
353 #[doc = link_impls!["div_rem"]]
354 fn int_div_rem(self, b: Self::Rhs) -> Result<[Self::Out; 2]> where Self: Sized { E::ni() }
355 #[doc = ref_fn!["int_div_rem"]]
356 fn int_ref_div_rem(&self, b: &Self::Rhs) -> Result<[Self::Out; 2]> { E::ni() }
357
358 /// Returns the quotient, rounding the result towards positive infinity.
359 ///
360 /// # Formulation
361 #[doc = NOTATION_DIV_CEIL!()]
362 #[doc = link_impls!["div_ceil"]]
363 fn int_div_ceil(self, b: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
364 #[doc = ref_fn!["int_div_ceil"]]
365 fn int_ref_div_ceil(&self, b: &Self::Rhs) -> Result<Self::Out> { E::ni() }
366
367 /// Returns the quotient, rounding the result towards negative infinity.
368 ///
369 #[doc = NOTATION_DIV_FLOOR!()]
370 #[doc = link_impls!["div_floor"]]
371 fn int_div_floor(self, b: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
372 #[doc = ref_fn!["int_div_floor"]]
373 fn int_ref_div_floor(&self, b: &Self::Rhs) -> Result<Self::Out> { E::ni() }
374
375 /// Returns the quotient, rounding ties away from zero.
376 #[doc = link_impls!["div_ties_away"]]
377 fn int_div_ties_away(self, b: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
378 #[doc = ref_fn!["int_div_ties_away"]]
379 fn int_ref_div_ties_away(&self, b: &Self::Rhs) -> Result<Self::Out> { E::ni() }
380
381 /// Returns the quotient, rounding ties towards from zero.
382 #[doc = link_impls!["div_ties_towards"]]
383 fn int_div_ties_towards(self, b: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
384 #[doc = ref_fn!["int_div_ties_towards"]]
385 fn int_ref_div_ties_towards(&self, b: &Self::Rhs) -> Result<Self::Out> { E::ni() }
386
387 /// Returns the quotient, rounding ties to the nearest even number.
388 #[doc = link_impls!["div_ties_even"]]
389 fn int_div_ties_even(self, b: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
390 #[doc = ref_fn!["int_div_ties_even"]]
391 fn int_ref_div_ties_even(&self, b: &Self::Rhs) -> Result<Self::Out> { E::ni() }
392
393 /// Returns the quotient, rounding ties to the nearest odd number.
394 #[doc = link_impls!["div_ties_odd"]]
395 fn int_div_ties_odd(self, b: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
396 #[doc = ref_fn!["int_div_ties_odd"]]
397 fn int_ref_div_ties_odd(&self, b: &Self::Rhs) -> Result<Self::Out> { E::ni() }
398
399 /* factors (allocating) */
400
401 /// Returns the factors (including 1 and self).
402 ///
403 /// This is the allocating version of [`int_factors_buf`][Self::int_factors_buf].
404 ///
405 /// # Examples
406 /// ```
407 /// # use devela::NumInt;
408 /// assert_eq![24_i64.int_factors(), Ok(vec![1, 2, 3, 4, 6, 8, 12, 24])];
409 /// assert_eq![(-24_i64).int_factors(), Ok(vec![1, 2, 3, 4, 6, 8, 12, 24])];
410 /// assert_eq![0_i64.int_factors(), Ok(vec![])];
411 /// assert_eq![1_i64.int_factors(), Ok(vec![1])];
412 /// assert_eq![7_i64.int_factors(), Ok(vec![1, 7])];
413 /// ```
414 #[cfg(feature = "alloc")]
415 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
416 #[doc = link_impls!["factors"]]
417 fn int_factors(self) -> Result<Vec<Self::Out>> where Self: Sized { E::ni() }
418 #[cfg(feature = "alloc")]
419 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
420 #[doc = ref_fn!["int_factors"]]
421 fn int_ref_factors(&self) -> Result<Vec<Self::Out>> { E::ni() }
422
423 /// Returns the proper factors.
424 ///
425 /// This is the allocating version of [`int_factors_proper_buf`][Self::int_factors_proper_buf].
426 ///
427 /// # Examples
428 /// ```
429 /// # use devela::NumInt;
430 /// assert_eq![24_i64.int_factors_proper(), Ok(vec![2, 3, 4, 6, 8, 12])];
431 /// assert_eq![(-24_i64).int_factors_proper(), Ok(vec![2, 3, 4, 6, 8, 12])];
432 /// assert_eq![0_i64.int_factors_proper(), Ok(vec![])];
433 /// assert_eq![1_i64.int_factors_proper(), Ok(vec![])];
434 /// assert_eq![7_i64.int_factors_proper(), Ok(vec![])];
435 /// ```
436 #[cfg(feature = "alloc")]
437 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
438 #[doc = link_impls!["factors_proper"]]
439 fn int_factors_proper(self) -> Result<Vec<Self::Out>> where Self: Sized { E::ni() }
440 #[cfg(feature = "alloc")]
441 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
442 #[doc = ref_fn!["int_factors_proper"]]
443 fn int_ref_factors_proper(&self) -> Result<Vec<Self::Out>> { E::ni() }
444
445 /// Returns the prime factors.
446 ///
447 /// This is the allocating version of [`int_factors_prime_buf`][Self::int_factors_prime_buf].
448 ///
449 /// # Examples
450 /// ```
451 /// # use devela::NumInt;
452 /// assert_eq![24_i64.int_factors_prime(), Ok(vec![2, 2, 2, 3])];
453 /// assert_eq![(-24_i64).int_factors_prime(), Ok(vec![2, 2, 2, 3])];
454 /// assert_eq![0_i64.int_factors_prime(), Ok(vec![])];
455 /// assert_eq![1_i64.int_factors_prime(), Ok(vec![])];
456 /// assert_eq![7_i64.int_factors_prime(), Ok(vec![7])];
457 /// ```
458 #[cfg(feature = "alloc")]
459 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
460 #[doc = link_impls!["factors_prime"]]
461 fn int_factors_prime(self) -> Result<Vec<Self::Out>> where Self: Sized { E::ni() }
462 #[cfg(feature = "alloc")]
463 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
464 #[doc = ref_fn!["int_factors_prime"]]
465 fn int_ref_factors_prime(&self) -> Result<Vec<Self::Out>> { E::ni() }
466
467 /// Returns the unique prime factors.
468 ///
469 /// This is the allocating version of
470 /// [`int_factors_prime_unique_buf`][Self::int_factors_prime_unique_buf].
471 ///
472 /// # Examples
473 /// ```
474 /// # use devela::NumInt;
475 /// assert_eq![24_i64.int_factors_prime_unique(), Ok(vec![2, 3])];
476 /// ```
477 #[cfg(feature = "alloc")]
478 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
479 #[doc = link_impls!["factors_prime_unique"]]
480 fn int_factors_prime_unique(self) -> Result<Vec<Self::Out>> where Self: Sized { E::ni() }
481 #[cfg(feature = "alloc")]
482 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
483 #[doc = ref_fn!["int_factors_prime_unique"]]
484 fn int_ref_factors_prime_unique(&self) -> Result<Vec<Self::Out>> { E::ni() }
485
486 /* factors (non-allocating) */
487
488 /// Writes the factors in `fbuf`, and the unique prime factors in `upfbuf`.
489 ///
490 /// This is the non-allocating version of [`int_factors`][Self::int_factors].
491 ///
492 /// Returns a tuple with the number of factors and unique prime factors found.
493 ///
494 /// # Errors
495 /// Returns [`MismatchedSizes`] if the total number of factors is greater
496 /// than the length of any buffer.
497 ///
498 /// # Examples
499 /// ```
500 /// # use devela::NumInt;
501 /// let (mut fbuf, mut upbuf) = ([0; 20], [0; 20]);
502 /// assert_eq![24_i64.int_factors_buf(&mut fbuf, &mut upbuf), Ok((8, 2))];
503 ///
504 /// assert_eq![fbuf[..8], [1, 2, 3, 4, 6, 8, 12, 24]];
505 /// assert_eq![upbuf[..2], [2, 3]];
506 /// ```
507 #[doc = link_impls!["factors_buf"]]
508 fn int_factors_buf(self, fbuf: &mut [Self::Out], upfbuf: &mut [Self::Out])
509 -> Result<(usize, usize)> where Self: Sized { E::ni() }
510 #[doc = ref_fn!["int_factors_buf"]]
511 fn int_ref_factors_buf(&self, fbuf: &mut [Self::Out], upfbuf: &mut [Self::Out])
512 -> Result<(usize, usize)> { E::ni() }
513
514 /// Writes the proper factors in `fbuf`, and the unique prime factors in `upfbuf`.
515 ///
516 /// This is the non-allocating version of [`int_factors_proper`][Self::int_factors_proper].
517 ///
518 /// Returns a tuple with the number of factors and unique prime factors found.
519 ///
520 /// # Errors
521 /// Returns [`MismatchedSizes`] if the total number of factors is greater
522 /// than the length of any buffer.
523 ///
524 /// # Examples
525 /// ```
526 /// # use devela::NumInt;
527 /// let (mut fbuf, mut upbuf) = ([0; 20], [0; 20]);
528 /// assert_eq![24_i64.int_factors_proper_buf(&mut fbuf, &mut upbuf), Ok((6, 2))];
529 ///
530 /// assert_eq![fbuf[..6], [2, 3, 4, 6, 8, 12,]];
531 /// assert_eq![upbuf[..2], [2, 3]];
532 /// ```
533 #[doc = link_impls!["factors_proper_buf"]]
534 fn int_factors_proper_buf(self, fbuf: &mut [Self], upfbuf: &mut [Self])
535 -> Result<(usize, usize)> where Self: Sized { E::ni() }
536 #[doc = ref_fn!["int_factors_proper_buf"]]
537 fn int_ref_factors_proper_buf(&self, fbuf: &mut [Self::Out], upfbuf: &mut [Self::Out])
538 -> Result<(usize, usize)> { E::ni() }
539
540 /// Writes the prime factors in the given `buffer`.
541 ///
542 /// This is the non-allocating version of [`int_factors_prime`][Self::int_factors_prime].
543 ///
544 /// Returns the number of factors found.
545 ///
546 /// # Errors
547 /// Returns [`MismatchedSizes`] if the total number of factors is greater
548 /// than the length of the `buffer`.
549 ///
550 /// # Examples
551 /// ```
552 /// # use devela::NumInt;
553 /// let mut buf = [0; 5];
554 /// assert_eq![24_i64.int_factors_prime_buf(&mut buf), Ok(4)];
555 ///
556 /// assert_eq![buf[..4], [2, 2, 2, 3]];
557 /// assert![(24_i64 * 4).int_factors_prime_buf(&mut buf).is_err()];
558 /// assert_eq![buf, [2, 2, 2, 2, 2]]; // the 3 didn't fit
559 ///
560 /// assert_eq![0_i64.int_factors_prime_buf(&mut buf), Ok(0)];
561 /// assert_eq![1_i64.int_factors_prime_buf(&mut buf), Ok(0)];
562 /// assert_eq![7_i64.int_factors_prime_buf(&mut buf), Ok(1)];
563 /// assert_eq![buf[..1], [7]];
564 /// ```
565 #[doc = link_impls!["factors_prime_buf"]]
566 fn int_factors_prime_buf(self, buffer: &mut [Self])
567 -> Result<usize> where Self: Sized { E::ni() }
568 #[doc = ref_fn!["int_factors_prime_buf"]]
569 fn int_ref_factors_prime_buf(&self, buffer: &mut [Self::Out]) -> Result<usize> { E::ni() }
570
571 /// Writes the prime factors in the given `buffer`.
572 ///
573 /// This is the non-allocating version of
574 /// [`int_factors_prime_unique`][Self::int_factors_prime_unique].
575 ///
576 /// The buffer must be large enough to hold all the non-unique factors of `n`.
577 /// In that case the function will return the number of unique factors found.
578 ///
579 /// # Errors
580 /// Returns [`MismatchedSizes`] if the unique number of factors is greater than the
581 /// length of the `buffer`. In that case the buffer will only contain the non-unique
582 /// factors that can fit, like [`int_factors_prime_buf`][Self::int_factors_prime_buf].
583 ///
584 /// # Examples
585 /// ```
586 /// # use devela::NumInt;
587 /// let mut uniq = [0; 5];
588 /// assert_eq![24_i64.int_factors_prime_unique_buf(&mut uniq), Ok(2)];
589 /// assert_eq![uniq, [2, 3, 2, 3, 0]];
590 /// ```
591 #[doc = link_impls!["factors_prime_unique_buf"]]
592 fn int_factors_prime_unique_buf(self, buffer: &mut [Self])
593 -> Result<usize> where Self: Sized { E::ni() }
594 #[doc = ref_fn!["int_factors_prime_unique_buf"]]
595 fn int_ref_factors_prime_unique_buf(&self, buffer: &mut [Self::Out])
596 -> Result<usize> { E::ni() }
597
598 /* primes */
599
600 /// Returns `true` if `n` is prime.
601 #[doc = link_impls!["is_prime"]]
602 fn int_is_prime(self) -> Result<bool> where Self: Sized { E::ni() }
603 #[doc = ref_fn!["int_is_prime"]]
604 fn int_ref_is_prime(&self) -> Result<bool> { E::ni() }
605
606 /// Finds the 0-indexed `nth` prime number.
607 ///
608 /// Note: If `nth` is negative, this function should treat it as its absolute value.
609 ///
610 /// # Errors
611 /// Returns [`Overflow`] if the result can't fit the type.
612 #[doc = link_impls!["prime_nth"]]
613 fn int_prime_nth(self) -> Result<Self::Out> where Self: Sized { E::ni() }
614 #[doc = ref_fn!["int_prime_nth"]]
615 fn int_ref_prime_nth(&self) -> Result<Self::Out> { E::ni() }
616
617 /// Counts the number of primes upto and including `n`.
618 ///
619 #[doc = NOTATION_PI!()]
620 #[doc = link_impls!["prime_pi"]]
621 fn int_prime_pi(self) -> Result<usize> where Self: Sized { E::ni() }
622 #[doc = ref_fn!["int_prime_pi"]]
623 fn int_ref_prime_pi(&self) -> Result<usize> { E::ni() }
624
625 /// Counts the number of integers $<|n|$ that are relatively prime to `n`.
626 ///
627 /// Note: If `n` is negative, this function should treat it as its absolute value.
628 #[doc = link_impls!["totient"]]
629 fn int_totient(self) -> Result<Self::Out> where Self: Sized { E::ni() }
630 #[doc = ref_fn!["int_totient"]]
631 fn int_ref_totient(&self) -> Result<Self::Out> { E::ni() }
632
633 /* roots (square) */
634
635 /// Returns `true` if it's a perfect square.
636 ///
637 /// Returns `false` otherwise, which includes all possible negative values.
638 ///
639 /// # Errors
640 /// Returns [`NonNegativeRequired`] if $n<0$ and [`Overflow`] if the result can't fit the type.
641 ///
642 /// # Formulation
643 #[doc = FORMULA_IS_SQUARE!()]
644 #[doc = link_impls!["is_square"]]
645 fn int_is_square(self) -> Result<bool> where Self: Sized { E::ni() }
646 #[doc = ref_fn!["int_is_square"]]
647 fn int_ref_is_square(&self) -> Result<bool> { E::ni() }
648
649 /// Returns the ceiled integer square root.
650 ///
651 /// # Errors
652 /// Returns [`NonNegativeRequired`] if `self` is negative.
653 ///
654 /// # Formulation
655 #[doc = ALGORITHM_SQRT_CEIL!()]
656 #[doc = link_impls!["sqrt_ceil"]]
657 fn int_sqrt_ceil(self) -> Result<Self::Out> where Self: Sized { E::ni() }
658 #[doc = ref_fn!["int_sqrt_ceil"]]
659 fn int_ref_sqrt_ceil(&self) -> Result<Self::Out> { E::ni() }
660
661 /// Returns the floored integer square root.
662 ///
663 /// # Errors
664 /// Returns [`NonNegativeRequired`] if `self` is negative.
665 ///
666 /// # Formulation
667 /// ## Algorithm
668 #[doc = ALGORITHM_SQRT_FLOOR!()]
669 #[doc = link_impls!["sqrt_floor"]]
670 fn int_sqrt_floor(self) -> Result<Self::Out> where Self: Sized { E::ni() }
671 #[doc = ref_fn!["int_sqrt_floor"]]
672 fn int_ref_sqrt_floor(&self) -> Result<Self::Out> { E::ni() }
673
674 /// Returns the rounded integer square root.
675 ///
676 /// # Formulation
677 /// ## Algorithm
678 #[doc = ALGORITHM_SQRT_ROUND!()]
679 #[doc = link_impls!["sqrt_round"]]
680 fn int_sqrt_round(self) -> Result<Self::Out> where Self: Sized { E::ni() }
681 #[doc = ref_fn!["int_sqrt_round"]]
682 fn int_ref_sqrt_round(&self) -> Result<Self::Out> { E::ni() }
683
684 /* roots */
685
686 /// Returns the ceiled integer `nth` root.
687 ///
688 #[doc = FORMULA_ROOT_CEIL_SIGNED!()]
689 ///
690 /// # Errors
691 /// Returns [`NonZeroRequired`] if `nth` is 0, or
692 /// [`NonNegativeRequired`] if `self` is negative and `nth` is even.
693 #[doc = link_impls!["root_ceil"]]
694 fn int_root_ceil(self, nth: u32) -> Result<Self::Out> where Self: Sized { E::ni() }
695 #[doc = ref_fn!["int_root_ceil"]]
696 fn int_ref_root_ceil(&self, nth: u32) -> Result<Self::Out> { E::ni() }
697
698 /// Returns the floored integer `nth` root.
699 ///
700 #[doc = FORMULA_ROOT_FLOOR_SIGNED!()]
701 ///
702 /// # Errors
703 /// Returns [`NonZeroRequired`] if `nth` is 0, or
704 /// [`NonNegativeRequired`] if `self` is negative and `nth` is even.
705 #[doc = link_impls!["root_floor"]]
706 fn int_root_floor(self, nth: u32) -> Result<Self::Out> where Self: Sized { E::ni() }
707 #[doc = ref_fn!["int_root_floor"]]
708 fn int_ref_root_floor(&self, nth: u32) -> Result<Self::Out> { E::ni() }
709
710 /* modulo */
711
712 /// Computes the non-negative modulo of `self` over |`modulus`|.
713 ///
714 /// The result is non-negative and less than the absolute value of `modulus`,
715 /// i.e., in the range $ [0, |\text{modulus}|) $.
716 ///
717 /// # Errors
718 /// Returns [`NonZeroRequired`] if `modulus == 0`,
719 /// and it could also return [`Overflow`].
720 #[doc = link_impls!["modulo"]]
721 fn int_modulo(self, modulus: Self::Rhs) -> Result<Self::Out> where Self: Sized { E::ni() }
722 #[doc = ref_fn!["int_modulo"]]
723 fn int_ref_modulo(&self, modulus: &Self::Rhs) -> Result<Self::Out> { E::ni() }
724
725 /// Computes the non-negative modulo of `self` over |`modulus`|,
726 /// and the number of cycles it is reduced.
727 ///
728 /// # Errors
729 /// Returns [`NonZeroRequired`] if `modulus == 0`,
730 /// and it could also return [`Overflow`].
731 #[doc = link_impls!["modulo_cycles"]]
732 fn int_modulo_cycles(self, modulus: Self::Rhs)
733 -> Result<ValueQuant<Self::Out, Self::Out>> where Self: Sized { E::ni() }
734 #[doc = ref_fn!["int_modulo_cycles"]]
735 fn int_ref_modulo_cycles(&self, modulus: &Self::Rhs)
736 -> Result<ValueQuant<Self::Out, Self::Out>> where Self: Sized { E::ni() }
737
738 /// Computes the modulo of `self + other` over |`modulus`|.
739 ///
740 /// # Errors
741 /// Returns [`NonZeroRequired`] if `modulus == 0`,
742 /// and it could also return [`Overflow`].
743 #[doc = link_impls!["modulo_add"]]
744 fn int_modulo_add(self, other: Self::Rhs, modulus: Self::Rhs)
745 -> Result<Self::Out> where Self: Sized { E::ni() }
746 #[doc = ref_fn!["int_modulo_add"]]
747 fn int_ref_modulo_add(&self, other: &Self::Rhs, modulus: &Self::Rhs)
748 -> Result<Self::Out> { E::ni() }
749
750 /// Computes the modulo of `self + other` over |`modulus`|,
751 /// and the number of cycles the result is reduced.
752 ///
753 /// # Errors
754 /// Returns [`NonZeroRequired`] if `modulus == 0`,
755 /// and it could also return [`Overflow`].
756 #[doc = link_impls!["modulo_add_cycles"]]
757 fn int_modulo_add_cycles(self, other: Self::Rhs, modulus: Self::Rhs)
758 -> Result<ValueQuant<Self::Out, Self::Out>> where Self: Sized { E::ni() }
759 #[doc = ref_fn!["int_modulo_add_cycles"]]
760 fn int_ref_modulo_add_cycles(&self, other: &Self::Rhs, modulus: &Self::Rhs)
761 -> Result<ValueQuant<Self::Out, Self::Out>> where Self: Sized { E::ni() }
762
763 /// Calculates the modular additive inverse.
764 ///
765 /// The modular additive inverse of *self* modulo *modulus*
766 /// is an integer *b* such that $ a+b \equiv 0 (\mod m) $.
767 ///
768 /// The modular multiplicative inverse always exists and is simply
769 /// `modulus - self` if `self != 0`, or 0 otherwise.
770 ///
771 /// # Errors
772 /// Returns [`NonZeroRequired`] if `modulus == 0`.
773 #[doc = link_impls!["modulo_add_inv"]]
774 fn int_modulo_add_inv(self, modulus: Self::Rhs)
775 -> Result<Self::Out> where Self: Sized { E::ni() }
776 #[doc = ref_fn!["int_modulo_add_inv"]]
777 fn int_ref_modulo_add_inv(&self, modulus: &Self::Rhs)
778 -> Result<Self::Out> { E::ni() }
779
780 /// Computes the modulo of `self - other` over |`modulus`|.
781 ///
782 /// # Errors
783 /// Returns [`NonZeroRequired`] if `modulus == 0`,
784 /// and [`Overflow`] if the result would be a negative value.
785 #[doc = link_impls!["modulo_sub"]]
786 fn int_modulo_sub(self, other: Self::Rhs, modulus: Self::Rhs)
787 -> Result<Self::Out> where Self: Sized { E::ni() }
788 #[doc = ref_fn!["int_modulo_sub"]]
789 fn int_ref_modulo_sub(&self, other: &Self::Rhs, modulus: &Self::Rhs)
790 -> Result<Self::Out> { E::ni() }
791
792 /// Computes the modulo of `self - other` over |`modulus`|,
793 /// and the number of cycles the result is reduced.
794 ///
795 /// # Errors
796 /// Returns [`NonZeroRequired`] if `modulus == 0`,
797 /// and [`Overflow`] if the result would be a negative value.
798 #[doc = link_impls!["modulo_sub_cycles"]]
799 fn int_modulo_sub_cycles(self, other: Self::Rhs, modulus: Self::Rhs)
800 -> Result<ValueQuant<Self::Out, Self::Out>> where Self: Sized { E::ni() }
801 #[doc = ref_fn!["int_modulo_sub_cycles"]]
802 fn int_ref_modulo_sub_cycles(&self, other: &Self::Rhs, modulus: &Self::Rhs)
803 -> Result<ValueQuant<Self::Out, Self::Out>> where Self: Sized { E::ni() }
804
805 /// Computes the modulo of `self + other` over |`modulus`|.
806 ///
807 /// # Errors
808 /// Returns [`NonZeroRequired`] if `modulus == 0`,
809 /// and it could also return [`Overflow`].
810 #[doc = link_impls!["modulo_mul"]]
811 fn int_modulo_mul(self, other: Self::Rhs, modulus: Self::Rhs)
812 -> Result<Self::Out> where Self: Sized { E::ni() }
813 #[doc = ref_fn!["int_modulo_mul"]]
814 fn int_ref_modulo_mul(&self, other: &Self::Rhs, modulus: &Self::Rhs)
815 -> Result<Self::Out> { E::ni() }
816
817 /// Computes the modulo of `self + other` over |`modulus`|,
818 /// and the number of cycles the result is reduced.
819 ///
820 /// # Errors
821 /// Returns [`NonZeroRequired`] if `modulus == 0`,
822 /// and it could also return [`Overflow`].
823 #[doc = link_impls!["modulo_mul_cycles"]]
824 fn int_modulo_mul_cycles(self, other: Self::Rhs, modulus: Self::Rhs)
825 -> Result<ValueQuant<Self::Out, Self::Out>> where Self: Sized { E::ni() }
826 #[doc = ref_fn!["int_modulo_mul_cycles"]]
827 fn int_ref_modulo_mul_cycles(&self, other: &Self::Rhs, modulus: &Self::Rhs)
828 -> Result<ValueQuant<Self::Out, Self::Out>> where Self: Sized { E::ni() }
829
830 /// Calculates the modular multiplicative inverse.
831 ///
832 /// The modular multiplicative inverse of *a* modulo *m*
833 /// is an integer *b* such that $ ab \equiv 1 (\mod m) $.
834 ///
835 /// The modular multiplicative inverse exists only if `self` and
836 /// `modulus` are coprime, meaning their greatest common divisor is 1.
837 ///
838 /// # Errors
839 /// Returns [`NonZeroRequired`] if `modulus == 0`,
840 /// [`NoInverse`] if there's no inverse,
841 /// and it could also return [`Overflow`].
842 #[doc = link_impls!["modulo_mul_inv"]]
843 fn int_modulo_mul_inv(self, modulus: Self::Rhs)
844 -> Result<Self::Out> where Self: Sized { E::ni() }
845 #[doc = ref_fn!["int_modulo_mul_inv"]]
846 fn int_ref_modulo_mul_inv(&self, modulus: &Self::Rhs)
847 -> Result<Self::Out> { E::ni() }
848
849 /// Computes `self / other` over |`modulus`|.
850 ///
851 /// $a / b \mod m$ is equivalent to $a * b^{-1} \mod m$,
852 /// where $b^{-1}$ is the modular multiplicative inverse
853 /// of $b$ modulo $m$.
854 /// # Errors
855 /// Returns [`NonZeroRequired`] if `modulus == 0`,
856 /// [`NoInverse`] if there's no multiplicative inverse of `other`,
857 /// and it could also return [`Overflow`].
858 #[doc = link_impls!["modulo_div"]]
859 fn int_modulo_div(self, other: Self::Rhs, modulus: Self::Rhs)
860 -> Result<Self::Out> where Self: Sized { E::ni() }
861 #[doc = ref_fn!["int_modulo_div"]]
862 fn int_ref_modulo_div(&self, other: &Self::Rhs, modulus: &Self::Rhs)
863 -> Result<Self::Out> { E::ni() }
864}
865
866/* macro helpers */
867
868/// Links to the implementation for primitive integers.
869macro_rules! link_impls {
870 ($fn:literal) => {
871 concat! {
872 "\n\n # Implementations\n\nSee an implementation for primitive integers: [`Int::`",
873 $fn, "][crate::Int::", $fn, "]." }
874 };
875}
876use link_impls;
877
878/// Links to the version that operates on references.
879macro_rules! ref_fn {
880 ($fn:literal) => {
881 concat! { "Similar to [", $fn, "][Self::",
882 $fn, "], but operates on references instead of values." }
883 };
884}
885use ref_fn;