maths_traits/algebra/
integer.rs1use 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
14pub 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
22pub 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 type Signed: Integer + IntegerSubset<Signed=Self::Signed, Unsigned=Self::Unsigned>;
52
53 type Unsigned: Natural + IntegerSubset<Signed=Self::Signed, Unsigned=Self::Unsigned>;
60
61 fn as_signed(self) -> Self::Signed;
68
69 fn as_unsigned(self) -> Self::Unsigned;
76
77 #[inline] fn abs_unsigned(self) -> Self::Unsigned { self.abs().as_unsigned() }
84
85 #[inline] fn two() -> Self { Self::one()+Self::one() }
87
88 #[inline] fn mul_two(self) -> Self { self * Self::two() }
95
96 #[inline] fn div_two(self) -> Self { self / Self::two() }
103
104 #[inline] fn even(&self) -> bool {Self::two().divides(self.clone())}
106
107 #[inline] fn odd(&self) -> bool {!self.even()}
109}
110
111pub trait Natural: IntegerSubset<Unsigned=Self> {}
113
114pub trait Integer: IntegerSubset<Signed=Self> + ArchUnitalRing {}
116
117pub struct TrialDivision<Z:IntegerSubset> {
136 x: Z,
137 f: Z,
138 mode: bool
139}
140
141impl<Z:IntegerSubset> TrialDivision<Z> {
142 pub fn factors_of(x:Z) -> Self { TrialDivision {x:x,f:Z::two(),mode:false} }
144
145 pub fn remaining(&self) -> Z { self.x.clone() }
147
148 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 { self.f = self.x.clone();
169 self.x = Z::one();
170 Some(self.f.clone())
171 } else {
172 let (q, r) = self.x.clone().div_alg(self.f.clone());
174
175 if r.is_zero() {self.x = q;
177 Some(self.f.clone())
178 } else {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() { self.x = Z::one();
194 Some(Z::zero())
195 } else if self.x.negative() { self.x = self.x.clone().abs();
197 Some(Z::zero() - Z::one())
198 } else { 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 ($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 #[inline] fn div_euc(self, rhs: Self) -> Self {self / rhs}
265
266 #[inline] fn rem_euc(self, rhs: Self) -> Self {self % rhs}
268
269 #[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);