maths_traits/algebra/
integer.rs

1//!
2//!Traits for integers and natural numbers
3//!
4
5use core::convert::{TryFrom};
6use core::ops::{Rem, RemAssign};
7use core::iter::Iterator;
8
9use num_traits::{ToPrimitive, FromPrimitive};
10
11use crate::analysis::ordered::*;
12use crate::algebra::*;
13
14///Aliases conversion traits to and from the primitive integer types
15pub trait CastPrimInt =
16    TryFrom<i8>   + TryFrom<u8>   +
17    TryFrom<i16>  + TryFrom<u16>  +
18    TryFrom<i32>  + TryFrom<u32>  +
19    TryFrom<i64>  + TryFrom<u64>  +
20    TryFrom<i128> + TryFrom<u128> ;
21
22///
23///A subset of the Integers that has all of the major integer operations
24///
25///This includes:
26/// * Basic ring operations
27/// * Euclidean division any everything implied by having it
28/// * Algebraic ordering properties and archimedian division
29/// * Additional operations conventionally implemented on integer types
30///
31///In practice, this means that a type implementing this trait must be either a
32///representation of the natural numbers or the integers as a whole.
33///
34///Furthermore, this trait contains associated types referring to an unsigned and signed type of
35///similar precision to make it easier to manage the broader system of types used in integer algorithms
36///
37pub trait IntegerSubset: Ord + Eq + Clone + CastPrimInt + ToPrimitive + FromPrimitive
38                        + EuclideanSemidomain
39                        + Primality
40                        + ArchSemiring + ArchimedeanDiv + Sign
41                        + Sub<Self, Output=Self> + Div<Self, Output=Self> + Rem<Self, Output=Self>
42                        + SubAssign<Self> + DivAssign<Self> + RemAssign<Self>
43{
44
45    ///
46    ///This type's corresponding signed Integer representation
47    ///
48    ///Implementors should guarantee that this type has the same theoretical bit precision as
49    ///the Unsigned type
50    ///
51    type Signed: Integer + IntegerSubset<Signed=Self::Signed, Unsigned=Self::Unsigned>;
52
53    ///
54    ///This type's corresponding unsigned Integer representation
55    ///
56    ///Implementors should guarantee that this type has the same theoretical bit precision as
57    ///the Signed type
58    ///
59    type Unsigned: Natural + IntegerSubset<Signed=Self::Signed, Unsigned=Self::Unsigned>;
60
61    ///
62    ///Converts `self` to a signed integer representation
63    ///
64    ///Note that this has the same guarantees as the primitive `as` operation
65    ///and can thus panic on overflow
66    ///
67    fn as_signed(self) -> Self::Signed;
68
69    ///
70    ///Converts `self` into an unsigned integer representation
71    ///
72    ///Note that this has the same guarantees as the primitive `as` operation
73    ///and can thus panic on underflow
74    ///
75    fn as_unsigned(self) -> Self::Unsigned;
76
77    ///
78    ///Takes the absolute value and converts into an unsigned integer representation
79    ///
80    ///Implementors should guarantee that this conversion never fails or panics since
81    ///the unsigned and signed types are assumed to be of the same theoretical bit precision
82    ///
83    #[inline] fn abs_unsigned(self) -> Self::Unsigned { self.abs().as_unsigned() }
84
85    ///A shorthand for `1+1`
86    #[inline] fn two() -> Self { Self::one()+Self::one() }
87
88    ///
89    ///Multiplies by two
90    ///
91    ///This is meant both as convenience and to expose the `<<` operator for representations that
92    ///support it. As such, this method has the _potential_ to be faster than normal multiplication
93    ///
94    #[inline] fn mul_two(self) -> Self { self * Self::two() }
95
96    ///
97    ///Divides by two
98    ///
99    ///This is meant both as convenience and to expose the `>>` operator for representations that
100    ///support it. As such, this method has the _potential_ to be faster than normal division
101    ///
102    #[inline] fn div_two(self) -> Self { self / Self::two() }
103
104    ///Determines if a number is divisible by two
105    #[inline] fn even(&self) -> bool {Self::two().divides(self.clone())}
106
107    ///Determines if a number is not divisible by two
108    #[inline] fn odd(&self) -> bool {!self.even()}
109}
110
111///An [IntegerSubset] that specifically represents an unsigned integer
112pub trait Natural: IntegerSubset<Unsigned=Self> {}
113
114///An [IntegerSubset] that specifically represents a signed integer
115pub trait Integer: IntegerSubset<Signed=Self> + ArchUnitalRing {}
116
117///
118///An iterator over the factors of an integer using the
119///[trial division](https://en.wikipedia.org/wiki/Trial_division) algorithm
120///
121///Given the nature of the algorithm, factors are guaranteed to be returned ascending order,
122///with a factor of `-1` given at the beginning if the number is negative, a single `0` given
123///if zero, and no factors returned if the original integer is `1`.
124///
125///```
126/// # use maths_traits::algebra::*;
127///let mut factors = TrialDivision::factors_of(-15);
128///
129///assert_eq!(factors.next(), Some(-1));
130///assert_eq!(factors.next(), Some(3));
131///assert_eq!(factors.next(), Some(5));
132///assert_eq!(factors.next(), None);
133///```
134///
135pub struct TrialDivision<Z:IntegerSubset> {
136    x: Z,
137    f: Z,
138    mode: bool
139}
140
141impl<Z:IntegerSubset> TrialDivision<Z> {
142    ///constructs an iterator over the factors of the argument
143    pub fn factors_of(x:Z) -> Self { TrialDivision {x:x,f:Z::two(),mode:false} }
144
145    ///the product of the remaining factors to be iterated over
146    pub fn remaining(&self) -> Z { self.x.clone() }
147
148    ///
149    ///the current factor being tested in the algorithm
150    ///
151    ///Note that there is no guarantee that this actually _is_ a factor
152    ///**or** that this function's result will change after an iterator step
153    ///
154    pub fn current_factor(&self) -> Z { self.f.clone() }
155}
156
157impl<Z:IntegerSubset> Iterator for TrialDivision<Z> {
158    type Item = Z;
159
160    fn next(&mut self) -> Option<Z> {
161
162        if self.x.is_one() {return None;}
163        let three = Z::embed_nat(3u8);
164
165        if self.f >= three {
166
167            if self.f.clone().pow_n(2u8) > self.x { //if x is prime
168                self.f = self.x.clone();
169                self.x = Z::one();
170                Some(self.f.clone())
171            } else {
172                //divide and check the remainder
173                let (q, r) = self.x.clone().div_alg(self.f.clone());
174
175                if r.is_zero() {//if the remainder is zero, we have a factor
176                    self.x = q;
177                    Some(self.f.clone())
178                } else {//else do the next loop
179                    //get the next factor
180                    if !self.mode {
181                        self.mode = if self.f == three {false} else {true};
182                        self.f += Z::two();
183                    } else {
184                        self.mode = false;
185                        self.f += Z::two() + Z::two();
186                    }
187                    self.next()
188                }
189            }
190
191        } else {
192            if self.x.is_zero() { //x is zero
193                self.x = Z::one();
194                Some(Z::zero())
195            } else if self.x.negative() { //emit a factor of -1
196                self.x = self.x.clone().abs();
197                Some(Z::zero() - Z::one())
198            } else { //if f is 2 we want to do bit-shifts and stuff for 2
199                if self.x.even() {
200                    self.x = self.x.clone().div_two();
201                    Some(Z::two())
202                } else {
203                    self.f = three;
204                    self.mode = false;
205                    self.next()
206                }
207            }
208        }
209
210    }
211
212}
213
214macro_rules! impl_int_subset {
215
216    (@unit $self:ident @unsigned) => {*$self==1};
217    (@unit $self:ident @signed) => {*$self==1 || *$self == -1 };
218
219    (@factors $factors:ident $self:ident @unsigned) => {};
220    (@factors $factors:ident $self:ident @signed) => {
221        if *$self < 0 {
222            $factors.push(-1);
223        }
224    };
225
226    (@neg $self:ident @unsigned) => {false};
227    (@neg $self:ident @signed) => {*$self < 0 };
228    (@abs $self:ident $name:ident @unsigned) => {$self};
229    (@abs $self:ident $name:ident @signed) => {Sign::abs($self) };
230
231    //base case for loop
232    ($name:ident:$signed:ident:$unsigned:ident $($tt:tt)*) => {
233
234        impl Divisibility for $name {
235            #[inline] fn unit(&self) -> bool{ impl_int_subset!(@unit self $($tt)*) }
236            #[inline] fn inverse(self) -> Option<Self>
237                {if self.unit() { Option::Some(self) }else {Option::None} }
238            #[inline] fn divides(self, rhs: Self) -> bool { (rhs % self) == 0}
239            #[inline] fn divide(self, rhs: Self) -> Option<Self> {
240                let (q, r) = self.div_alg(rhs);
241                if r==0 {Some(q)} else {None}
242            }
243        }
244
245        impl NoZeroDivisors for $name {}
246
247        impl GCD for $name {
248            #[inline] fn lcm(self, rhs: Self) -> Self { (self*rhs) / self.gcd(rhs) }
249            #[inline] fn gcd(self, rhs: Self) -> Self{ euclidean(self, rhs) }
250        }
251
252        impl UniquelyFactorizable for $name {}
253
254        impl Factorizable for $name {
255            type Factors = TrialDivision<Self>;
256            #[inline] fn factors(self) -> TrialDivision<Self> {TrialDivision::factors_of(self)}
257        }
258
259        impl EuclideanDiv for $name {
260            type Naturals = $unsigned;
261            #[inline] fn euclid_norm(&self) -> $unsigned {self.abs_unsigned()}
262
263            ///Euclidean division implemented using the `/` operator
264            #[inline] fn div_euc(self, rhs: Self) -> Self {self / rhs}
265
266            ///Euclidean remainder implemented using the `%` operator
267            #[inline] fn rem_euc(self, rhs: Self) -> Self {self % rhs}
268
269            ///
270            ///Euclidean division implemented using the `/` and `%` operators
271            ///
272            ///Note that this does mean that the remainder may be negative and this method
273            ///only guarantees that it satisfies the basic [Eucldidean division](EuclideanDiv::div_alg)
274            ///axioms
275            #[inline] fn div_alg(self, rhs: Self) -> (Self, Self) {(self / rhs, self % rhs)}
276        }
277
278        impl IntegerSubset for $name {
279            type Signed = $signed;
280            type Unsigned = $unsigned;
281            #[inline] fn as_signed(self) -> $signed { self as $signed }
282            #[inline] fn as_unsigned(self) -> $unsigned { self as $unsigned }
283
284            #[inline] fn two() -> Self { 2 }
285            #[inline] fn mul_two(self) -> Self { self << 1 }
286            #[inline] fn div_two(self) -> Self { self >> 1 }
287            #[inline] fn even(&self) -> bool { (*self & 1) == 0 }
288            #[inline] fn odd(&self) -> bool { (*self & 1) == 1 }
289        }
290
291    }
292}
293
294macro_rules! impl_int {
295    ($($s:ident:$u:ident)*) => {
296        $(
297            impl Bezout for $s {
298                #[inline]
299                fn bezout_coefficients(self, rhs: Self) -> (Self, Self) {
300                    let (x, y, _g) = extended_euclidean(self, rhs);
301                    (x, y)
302                }
303                #[inline] fn bezout_with_gcd(self, rhs: Self) -> (Self, Self, Self) { extended_euclidean(self, rhs) }
304            }
305
306            impl_int_subset!($u:$s:$u @unsigned);
307            impl_int_subset!($s:$s:$u @signed);
308            impl Natural for $u {}
309            impl Integer for $s {}
310        )*
311    };
312}
313
314macro_rules! impl_primality {
315    ($($t:ident:$hp:ident)*) => {$(
316        impl Primality for $t {
317            #[inline] fn irreducible(&self) -> bool { self.prime() }
318            #[inline] fn prime(&self) -> bool { miller_rabin(*self as $hp) }
319        }
320    )*}
321}
322
323impl_int!(i8:u8 i16:u16 i32:u32 i64:u64 i128:u128 isize:usize);
324impl_primality!(i8:u16 i16:u32 i32:u64 i64:u128 i128:u128 isize:u128);
325impl_primality!(u8:u16 u16:u32 u32:u64 u64:u128 u128:u128 usize:u128);