devela/num/int/num_trait/
ref.rs

1// devela::num::int::num_trait::ref
2//
3//! Defines the `NumRefInt` trait and auto-implements it.
4//
5// TOC
6// - trait NumRefInt
7//   - base
8//   - core
9//   - combinatorics
10//   - division
11//   - factors
12//   - primes
13//   - modulo
14//   - roots
15// - macro helpers
16//   - impl_int_ref
17//   - own_fn
18
19#[cfg(feature = "alloc")]
20use crate::Vec;
21use crate::{Deref, GcdReturn, Num, NumInt, NumRef, NumResult as Result, ValueQuant};
22
23/// Common auto-trait for referenced integer types.
24///
25/// # Notes
26/// - This is automatically implemented for references of types implementing [`NumInt`].
27/// - Mutable operations are only available for exclusive (`&mut`) references.
28//
29// In sync with src/num/int/num_trait/mod.rs (int_ref_* methods)
30#[cfg_attr(feature = "nightly_doc", doc(notable_trait))]
31#[rustfmt::skip]
32pub trait NumRefInt<'a>: NumRef<'a>
33where
34    Self: Deref<Target = <Self as NumRef<'a>>::Own>,
35    <Self as NumRef<'a>>::Own: NumInt
36{
37    /* base */
38
39    impl_int_ref![int_ref_digital_root(&self) -> Out];
40    impl_int_ref![int_ref_digital_root_base(&self, base: &Rhs) -> Out];
41
42    impl_int_ref![int_ref_digits(&self) -> Out];
43    impl_int_ref![int_ref_digits_sign(&self) -> Out];
44    impl_int_ref![int_ref_digits_base(&self, base: &Rhs) -> Out];
45    impl_int_ref![int_ref_digits_base_sign(&self, base: &Rhs) -> Out];
46
47    /* core */
48
49    impl_int_ref![int_ref_abs(&self) -> Out];
50    impl_int_ref![int_ref_is_even(&self) -> bool];
51    impl_int_ref![int_ref_is_odd(&self) -> bool];
52
53    impl_int_ref![int_ref_gcd(&self, other: &Rhs) -> Out];
54
55    #[doc = own_fn!["int_ref_gcd_ext"]]
56    #[allow(clippy::type_complexity, reason = "unavoidable")]
57    fn int_ref_gcd_ext(&self, other: &<Self::Own as Num>::Rhs)
58        -> Result<GcdReturn<<Self::Own as Num>::Out, <Self::Own as NumInt>::OutI>> {
59            self.deref().int_ref_gcd_ext(other) }
60    // impl_int_ref![int_ref_gcd_ext(&self, other: &Rhs) -> GcdReturn<Out, OutI>]; MAYBE
61
62    impl_int_ref![int_ref_lcm(&self, other: &Rhs) -> Out];
63    impl_int_ref![int_ref_scale(&self, min: &Rhs, max: &Rhs, a: &Rhs, b: &Rhs) -> Out];
64    impl_int_ref![int_ref_scale_wrap(&self, min: &Rhs, max: &Rhs, a: &Rhs, b: &Rhs) -> Out];
65    impl_int_ref![int_ref_midpoint(&self, other: &Rhs) -> Out];
66
67    /* combinatorics */
68
69    impl_int_ref![int_ref_factorial(&self) -> Out];
70    impl_int_ref![int_ref_subfactorial(&self) -> Out];
71    impl_int_ref![int_ref_permute(&self, r: &Rhs) -> Out];
72    impl_int_ref![int_ref_permute_rep(&self, r: &Rhs) -> Out];
73    impl_int_ref![int_ref_combine(&self, r: &Rhs) -> Out];
74    impl_int_ref![int_ref_combine_rep(&self, r: &Rhs) -> Out];
75
76    /* division */
77
78    impl_int_ref![int_ref_div_rem(&self, r: &Rhs) -> [Out; 2]];
79    impl_int_ref![int_ref_div_ceil(&self, r: &Rhs) -> Out];
80    impl_int_ref![int_ref_div_floor(&self, r: &Rhs) -> Out];
81    impl_int_ref![int_ref_div_ties_away(&self, r: &Rhs) -> Out];
82    impl_int_ref![int_ref_div_ties_towards(&self, r: &Rhs) -> Out];
83    impl_int_ref![int_ref_div_ties_even(&self, r: &Rhs) -> Out];
84    impl_int_ref![int_ref_div_ties_odd(&self, r: &Rhs) -> Out];
85
86    /* factors (allocating) */
87
88    #[doc = own_fn!["int_ref_factors"]]
89    #[cfg(feature = "alloc")] #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
90    fn int_ref_factors(&self) -> Result<Vec<<Self::Own as Num>::Out>> {
91            self.deref().int_ref_factors() }
92    #[doc = own_fn!["int_ref_factors_proper"]]
93    #[cfg(feature = "alloc")] #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
94    fn int_ref_factors_proper(&self) -> Result<Vec<<Self::Own as Num>::Out>> {
95            self.deref().int_ref_factors_proper() }
96    #[doc = own_fn!["int_ref_factors_prime"]]
97    #[cfg(feature = "alloc")] #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
98    fn int_ref_factors_prime(&self) -> Result<Vec<<Self::Own as Num>::Out>> {
99            self.deref().int_ref_factors_prime() }
100    #[doc = own_fn!["int_ref_factors_prime_unique"]]
101    #[cfg(feature = "alloc")] #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
102    fn int_ref_factors_prime_unique(&self) -> Result<Vec<<Self::Own as Num>::Out>> {
103            self.deref().int_ref_factors_prime_unique() }
104
105    /* factors (non-allocating) */
106
107    #[doc = own_fn!["int_ref_factors_buf"]]
108    fn int_ref_factors_buf(&self,
109        fbuf: &mut [<Self::Own as Num>::Out], upfbuf: &mut [<Self::Own as Num>::Out])
110        -> Result<(usize, usize)> {
111            self.deref().int_ref_factors_buf(fbuf, upfbuf) }
112    #[doc = own_fn!["int_ref_factors_proper_buf"]]
113    fn int_ref_factors_proper_buf(&self,
114        fbuf: &mut [<Self::Own as Num>::Out], upfbuf: &mut [<Self::Own as Num>::Out])
115        -> Result<(usize, usize)> {
116            self.deref().int_ref_factors_proper_buf(fbuf, upfbuf) }
117    #[doc = own_fn!["int_ref_factors_prime_buf"]]
118    fn int_ref_factors_prime_buf(&self, buffer: &mut [<Self::Own as Num>::Out]) -> Result<usize> {
119            self.deref().int_ref_factors_prime_buf(buffer) }
120    #[doc = own_fn!["int_ref_factors_prime_unique_buf"]]
121    fn int_ref_factors_prime_unique_buf(&self, buffer: &mut [<Self::Own as Num>::Out])
122        -> Result<usize> {
123            self.deref().int_ref_factors_prime_unique_buf(buffer) }
124
125    /* primes */
126
127    impl_int_ref![int_ref_is_prime(&self) -> bool];
128    impl_int_ref![int_ref_prime_nth(&self) -> Out];
129    impl_int_ref![int_ref_prime_pi(&self) -> usize];
130    impl_int_ref![int_ref_totient(&self) -> Out];
131
132    /* roots (square) */
133
134    impl_int_ref![int_ref_is_square(&self) -> bool];
135    impl_int_ref![int_ref_sqrt_ceil(&self) -> Out];
136    impl_int_ref![int_ref_sqrt_floor(&self) -> Out];
137    impl_int_ref![int_ref_sqrt_round(&self) -> Out];
138
139    /* modulo */
140
141    impl_int_ref![int_ref_modulo(&self, modulus: &Rhs) -> Out];
142    impl_int_ref![int_ref_modulo_cycles(&self, modulus: &Rhs) -> ValueQuant<Out, Out>];
143
144    impl_int_ref![int_ref_modulo_add(&self, other: &Rhs, modulus: &Rhs) -> Out];
145    impl_int_ref![int_ref_modulo_add_cycles(&self, other: &Rhs, modulus: &Rhs)
146        -> ValueQuant<Out, Out>];
147    impl_int_ref![int_ref_modulo_add_inv(&self, modulus: &Rhs) -> Out];
148    impl_int_ref![int_ref_modulo_sub(&self, other: &Rhs, modulus: &Rhs) -> Out];
149    impl_int_ref![int_ref_modulo_sub_cycles(&self, other: &Rhs, modulus: &Rhs)
150        -> ValueQuant<Out, Out>];
151    impl_int_ref![int_ref_modulo_mul(&self, other: &Rhs, modulus: &Rhs) -> Out];
152    impl_int_ref![int_ref_modulo_mul_cycles(&self, other: &Rhs, modulus: &Rhs)
153        -> ValueQuant<Out, Out>];
154    impl_int_ref![int_ref_modulo_mul_inv(&self, modulus: &Rhs) -> Out];
155    impl_int_ref![int_ref_modulo_div(&self, other: &Rhs, modulus: &Rhs) -> Out];
156
157    /* roots */
158
159    impl_int_ref![int_ref_root_ceil(&self, nth: u32) -> Out];
160    impl_int_ref![int_ref_root_floor(&self, nth: u32) -> Out];
161}
162
163/// Implements the given method.
164macro_rules! impl_int_ref {
165    (
166    // >=0 Num::Rhs args, returns Self::Out
167    $fn:ident(&$self:ident $(, $arg:ident: &Rhs)*) -> Out) => { $crate::paste! {
168        #[doc = own_fn![$fn]]
169        fn $fn(&$self $(, $arg: &<Self::Own as Num>::Rhs)*)
170            -> Result<<Self::Own as Num>::Out> {
171            $self.deref().$fn($($arg),*) }
172    }};
173    (
174    // >=0 Num::Rhs args, returns an array of Self::Out
175    $fn:ident(&$self:ident $(, $arg:ident: &Rhs)*)
176     -> [Out; $LEN:literal]) => { $crate::paste! {
177        #[doc = own_fn![$fn]]
178        fn $fn(&$self $(, $arg: &<Self::Own as Num>::Rhs)*)
179            -> Result<[<Self::Own as Num>::Out; $LEN]> {
180            $self.deref().$fn($($arg),*) }
181    }};
182    (
183    // >=0 Num::Rhs args, returns Valuequant<Self::Out, Self::Out>
184    $fn:ident(&$self:ident $(, $arg:ident: &Rhs)*)
185    -> ValueQuant<Out, Out>) => { $crate::paste! {
186        #[doc = own_fn![$fn]]
187        fn $fn(&$self $(, $arg: &<Self::Own as Num>::Rhs)*)
188            -> Result<ValueQuant<<Self::Own as Num>::Out, <Self::Own as Num>::Out>> {
189            $self.deref().$fn($($arg),*) }
190    }};
191    (
192    // >=0 ty args, returns Self::Out
193    $fn:ident(&$self:ident $(, $arg:ident: $arg_ty:ty)*) -> Out) => { $crate::paste! {
194        #[doc = own_fn![$fn]]
195        fn $fn(&$self $(, $arg: $arg_ty)*) -> Result<<Self::Own as Num>::Out> {
196            $self.deref().$fn($($arg),*) }
197    }};
198    (
199    // 0 args returns ty (bool, usize…)
200    $fn:ident(&$self:ident) -> $out:ty) => { $crate::paste! {
201        #[doc = own_fn![$fn]]
202        fn $fn(&$self) -> Result<$out> {
203            $self.deref().$fn() }
204    }};
205}
206use impl_int_ref;
207
208/// Links to the version that operates on values.
209macro_rules! own_fn {
210    ($fn:ident) => { own_fn!(@stringify!($fn)) };
211    ($fn:literal) => { own_fn!(@$fn) };
212    (@$fn_str:expr) => {
213        concat! { "Calls [`NumInt::", $fn_str, "][NumInt::", $fn_str, "]." }
214    };
215}
216use own_fn;