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;