1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
//!
//!Traits for integers and natural numbers
//!

use core::convert::{TryFrom};
use core::ops::{Rem, RemAssign};
use core::iter::Iterator;

use num_traits::{ToPrimitive, FromPrimitive};

use crate::analysis::ordered::*;
use crate::algebra::*;

///Aliases conversion traits to and from the primitive integer types
pub trait CastPrimInt =
    TryFrom<i8>   + TryFrom<u8>   +
    TryFrom<i16>  + TryFrom<u16>  +
    TryFrom<i32>  + TryFrom<u32>  +
    TryFrom<i64>  + TryFrom<u64>  +
    TryFrom<i128> + TryFrom<u128> ;

///
///A subset of the Integers that has all of the major integer operations
///
///This includes:
/// * Basic ring operations
/// * Euclidean division any everything implied by having it
/// * Algebraic ordering properties and archimedian division
/// * Additional operations conventionally implemented on integer types
///
///In practice, this means that a type implementing this trait must be either a
///representation of the natural numbers or the integers as a whole.
///
///Furthermore, this trait contains associated types referring to an unsigned and signed type of
///similar precision to make it easier to manage the broader system of types used in integer algorithms
///
pub trait IntegerSubset: Ord + Eq + Clone + CastPrimInt + ToPrimitive + FromPrimitive
                        + EuclideanSemidomain
                        + Primality
                        + ArchSemiring + ArchimedeanDiv + Sign
                        + Sub<Self, Output=Self> + Div<Self, Output=Self> + Rem<Self, Output=Self>
                        + SubAssign<Self> + DivAssign<Self> + RemAssign<Self>
{

    ///
    ///This type's corresponding signed Integer representation
    ///
    ///Implementors should guarantee that this type has the same theoretical bit precision as
    ///the Unsigned type
    ///
    type Signed: Integer + IntegerSubset<Signed=Self::Signed, Unsigned=Self::Unsigned>;

    ///
    ///This type's corresponding unsigned Integer representation
    ///
    ///Implementors should guarantee that this type has the same theoretical bit precision as
    ///the Signed type
    ///
    type Unsigned: Natural + IntegerSubset<Signed=Self::Signed, Unsigned=Self::Unsigned>;

    ///
    ///Converts `self` to a signed integer representation
    ///
    ///Note that this has the same guarantees as the primitive `as` operation
    ///and can thus panic on overflow
    ///
    fn as_signed(self) -> Self::Signed;

    ///
    ///Converts `self` into an unsigned integer representation
    ///
    ///Note that this has the same guarantees as the primitive `as` operation
    ///and can thus panic on underflow
    ///
    fn as_unsigned(self) -> Self::Unsigned;

    ///
    ///Takes the absolute value and converts into an unsigned integer representation
    ///
    ///Implementors should guarantee that this conversion never fails or panics since
    ///the unsigned and signed types are assumed to be of the same theoretical bit precision
    ///
    #[inline] fn abs_unsigned(self) -> Self::Unsigned { self.abs().as_unsigned() }

    ///A shorthand for `1+1`
    #[inline] fn two() -> Self { Self::one()+Self::one() }

    ///
    ///Multiplies by two
    ///
    ///This is meant both as convenience and to expose the `<<` operator for representations that
    ///support it. As such, this method has the _potential_ to be faster than normal multiplication
    ///
    #[inline] fn mul_two(self) -> Self { self * Self::two() }

    ///
    ///Divides by two
    ///
    ///This is meant both as convenience and to expose the `>>` operator for representations that
    ///support it. As such, this method has the _potential_ to be faster than normal division
    ///
    #[inline] fn div_two(self) -> Self { self / Self::two() }

    ///Determines if a number is divisible by two
    #[inline] fn even(&self) -> bool {Self::two().divides(self.clone())}

    ///Determines if a number is not divisible by two
    #[inline] fn odd(&self) -> bool {!self.even()}
}

///An [IntegerSubset] that specifically represents an unsigned integer
pub trait Natural: IntegerSubset<Unsigned=Self> {}

///An [IntegerSubset] that specifically represents a signed integer
pub trait Integer: IntegerSubset<Signed=Self> + ArchUnitalRing {}

///
///An iterator over the factors of an integer using the
///[trial division](https://en.wikipedia.org/wiki/Trial_division) algorithm
///
///Given the nature of the algorithm, factors are guaranteed to be returned ascending order,
///with a factor of `-1` given at the beginning if the number is negative, a single `0` given
///if zero, and no factors returned if the original integer is `1`.
///
///```
/// # use maths_traits::algebra::*;
///let mut factors = TrialDivision::factors_of(-15);
///
///assert_eq!(factors.next(), Some(-1));
///assert_eq!(factors.next(), Some(3));
///assert_eq!(factors.next(), Some(5));
///assert_eq!(factors.next(), None);
///```
///
pub struct TrialDivision<Z:IntegerSubset> {
    x: Z,
    f: Z,
    mode: bool
}

impl<Z:IntegerSubset> TrialDivision<Z> {
    ///constructs an iterator over the factors of the argument
    pub fn factors_of(x:Z) -> Self { TrialDivision {x:x,f:Z::two(),mode:false} }

    ///the product of the remaining factors to be iterated over
    pub fn remaining(&self) -> Z { self.x.clone() }

    ///
    ///the current factor being tested in the algorithm
    ///
    ///Note that there is no guarantee that this actually _is_ a factor
    ///**or** that this function's result will change after an iterator step
    ///
    pub fn current_factor(&self) -> Z { self.f.clone() }
}

impl<Z:IntegerSubset> Iterator for TrialDivision<Z> {
    type Item = Z;

    fn next(&mut self) -> Option<Z> {

        if self.x.is_one() {return None;}
        let three = Z::embed_nat(3u8);

        if self.f >= three {

            if self.f.clone().pow_n(2u8) > self.x { //if x is prime
                self.f = self.x.clone();
                self.x = Z::one();
                Some(self.f.clone())
            } else {
                //divide and check the remainder
                let (q, r) = self.x.clone().div_alg(self.f.clone());

                if r.is_zero() {//if the remainder is zero, we have a factor
                    self.x = q;
                    Some(self.f.clone())
                } else {//else do the next loop
                    //get the next factor
                    if !self.mode {
                        self.mode = if self.f == three {false} else {true};
                        self.f += Z::two();
                    } else {
                        self.mode = false;
                        self.f += Z::two() + Z::two();
                    }
                    self.next()
                }
            }

        } else {
            if self.x.is_zero() { //x is zero
                self.x = Z::one();
                Some(Z::zero())
            } else if self.x.negative() { //emit a factor of -1
                self.x = self.x.clone().abs();
                Some(Z::zero() - Z::one())
            } else { //if f is 2 we want to do bit-shifts and stuff for 2
                if self.x.even() {
                    self.x = self.x.clone().div_two();
                    Some(Z::two())
                } else {
                    self.f = three;
                    self.mode = false;
                    self.next()
                }
            }
        }

    }

}

macro_rules! impl_int_subset {

    (@unit $self:ident @unsigned) => {*$self==1};
    (@unit $self:ident @signed) => {*$self==1 || *$self == -1 };

    (@factors $factors:ident $self:ident @unsigned) => {};
    (@factors $factors:ident $self:ident @signed) => {
        if *$self < 0 {
            $factors.push(-1);
        }
    };

    (@neg $self:ident @unsigned) => {false};
    (@neg $self:ident @signed) => {*$self < 0 };
    (@abs $self:ident $name:ident @unsigned) => {$self};
    (@abs $self:ident $name:ident @signed) => {Sign::abs($self) };

    //base case for loop
    ($name:ident:$signed:ident:$unsigned:ident $($tt:tt)*) => {

        impl Divisibility for $name {
            #[inline] fn unit(&self) -> bool{ impl_int_subset!(@unit self $($tt)*) }
            #[inline] fn inverse(self) -> Option<Self>
                {if self.unit() { Option::Some(self) }else {Option::None} }
            #[inline] fn divides(self, rhs: Self) -> bool { (rhs % self) == 0}
            #[inline] fn divide(self, rhs: Self) -> Option<Self> {
                let (q, r) = self.div_alg(rhs);
                if r==0 {Some(q)} else {None}
            }
        }

        impl NoZeroDivisors for $name {}

        impl GCD for $name {
            #[inline] fn lcm(self, rhs: Self) -> Self { (self*rhs) / self.gcd(rhs) }
            #[inline] fn gcd(self, rhs: Self) -> Self{ euclidean(self, rhs) }
        }

        impl UniquelyFactorizable for $name {}

        impl Factorizable for $name {
            type Factors = TrialDivision<Self>;
            #[inline] fn factors(self) -> TrialDivision<Self> {TrialDivision::factors_of(self)}
        }

        impl EuclideanDiv for $name {
            type Naturals = $unsigned;
            #[inline] fn euclid_norm(&self) -> $unsigned {self.abs_unsigned()}

            ///Euclidean division implemented using the `/` operator
            #[inline] fn div_euc(self, rhs: Self) -> Self {self / rhs}

            ///Euclidean remainder implemented using the `%` operator
            #[inline] fn rem_euc(self, rhs: Self) -> Self {self % rhs}

            ///
            ///Euclidean division implemented using the `/` and `%` operators
            ///
            ///Note that this does mean that the remainder may be negative and this method
            ///only guarantees that it satisfies the basic [Eucldidean division](EuclideanDiv::div_alg)
            ///axioms
            #[inline] fn div_alg(self, rhs: Self) -> (Self, Self) {(self / rhs, self % rhs)}
        }

        impl IntegerSubset for $name {
            type Signed = $signed;
            type Unsigned = $unsigned;
            #[inline] fn as_signed(self) -> $signed { self as $signed }
            #[inline] fn as_unsigned(self) -> $unsigned { self as $unsigned }

            #[inline] fn two() -> Self { 2 }
            #[inline] fn mul_two(self) -> Self { self << 1 }
            #[inline] fn div_two(self) -> Self { self >> 1 }
            #[inline] fn even(&self) -> bool { (*self & 1) == 0 }
            #[inline] fn odd(&self) -> bool { (*self & 1) == 1 }
        }

    }
}

macro_rules! impl_int {
    ($($s:ident:$u:ident)*) => {
        $(
            impl Bezout for $s {
                #[inline]
                fn bezout_coefficients(self, rhs: Self) -> (Self, Self) {
                    let (x, y, _g) = extended_euclidean(self, rhs);
                    (x, y)
                }
                #[inline] fn bezout_with_gcd(self, rhs: Self) -> (Self, Self, Self) { extended_euclidean(self, rhs) }
            }

            impl_int_subset!($u:$s:$u @unsigned);
            impl_int_subset!($s:$s:$u @signed);
            impl Natural for $u {}
            impl Integer for $s {}
        )*
    };
}

macro_rules! impl_primality {
    ($($t:ident:$hp:ident)*) => {$(
        impl Primality for $t {
            #[inline] fn irreducible(&self) -> bool { self.prime() }
            #[inline] fn prime(&self) -> bool { miller_rabin(*self as $hp) }
        }
    )*}
}

impl_int!(i8:u8 i16:u16 i32:u32 i64:u64 i128:u128 isize:usize);
impl_primality!(i8:u16 i16:u32 i32:u64 i64:u128 i128:u128 isize:u128);
impl_primality!(u8:u16 u16:u32 u32:u64 u64:u128 u128:u128 usize:u128);