numerous 0.1.0

A set of tools to finding and classifying special numbers
Documentation
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
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
#![allow(clippy::cast_sign_loss)] // For is_unusual
#![allow(clippy::cast_possible_truncation)] //For is_unusual

use gcd::Gcd;
use prime_factorization::Factorization;
use integer_sqrt::IntegerSquareRoot;

pub const TEST_POWERFUL:[i32; 30] = [1, 4, 8, 9, 16, 25, 27, 32, 36, 49,
                                     64, 72, 81, 100, 108, 121, 125, 128, 144, 169,
                                     196, 200, 216, 225, 243, 256, 288, 289, 324, 343];
pub const TEST_ACHILLES:[i32; 30] = [72, 108, 200, 288, 392, 500, 648, 675, 800, 968,
                                    972, 1125, 1323, 1352, 1568, 1800, 1944, 2000, 2700, 2888,
                                     3087, 3200, 3267, 3528, 4000, 4232, 4500, 4563, 4608, 5000];
pub const TEST_PERFECT:[i32; 30] = [4, 8, 9, 16, 25, 27, 32, 36, 49, 64,
                                    81, 100, 121, 125, 128, 144, 169, 196, 216, 225, 
                                    243, 256, 289, 324, 343, 361, 400, 441, 484, 512];
pub const TEST_SEMIPRIME:[i32; 30] = [4, 6, 9, 10, 14, 15, 21, 22, 25, 26,
                                      33, 34, 35, 38, 39, 46, 49, 51, 55, 57,
                                      58, 62, 65, 69, 74, 77, 82, 85, 86, 87];
pub const TEST_SPHENIC: [i32; 30] = [30, 42, 66, 70, 78, 102, 105, 110, 114, 130,
                                    138, 154, 165, 170, 174, 182, 186, 190, 195, 222,
                                    230, 231, 238, 246, 255, 258, 266, 273, 282, 285];
pub const TEST_SQUAREFREE: [i32; 30] = [1, 2, 3, 5, 6, 7, 10, 11, 13, 14, 
                                        15, 17, 19, 21, 22, 23, 26, 29, 30, 31, 
                                        33, 34, 35, 37, 38, 39, 41, 42, 43, 46];
pub const TEST_PRONIC: [i32; 30] = [2, 6, 12, 20, 30, 42, 56, 72, 90,
                                    110, 132, 156, 182, 210, 240, 272, 306, 342, 380,
                                    420, 462, 506, 552, 600, 650, 702, 756, 812, 870, 930];
///
/// A powerful number is a positive integer m such that for every prime number p dividing m, p2 also divides m. 
/// Behavior described in OEIS A001694. s
/// 
/// For this test we take the informal definition of a powerful number as described on wikipedia: 
/// Informally, given the prime factorization of m, take b to be the product of the prime factors of m that have an odd exponent
/// (if there are none, then take b to be 1). Because m is powerful, each prime factor with an odd exponent has an exponent that 
/// is at least 3, so m/b^3 is an integer. In addition, each prime factor of m/b^3 has an even exponent, so m/b^3 is a perfect square, 
/// so call this a^2; then m = a^2b^3
/// 
///  # Arguements
/// 
///  * `testee` - An i32 number to be tested 
/// 
///  # Example
///  ``` rust
/// let powerful_num: i32 = 200;
/// let not_powerful_num: i32 = 19;
/// assert!(is_powerful(powerful_num);
/// assert!(!is_powerful(not_powerful_num));
/// ```    
/// 
///  # Todo
///  Upper limit catch, currently panics as i32:MAX integers
/// 
pub fn is_powerful(testee: i32) -> bool {
    if testee < 0 {return false;}
    let unsigned_testee:u64 = u64::from(testee.unsigned_abs());
    let factor_factory: Factorization<u64> = Factorization::run(unsigned_testee);
    let prime_factors:Vec<(u64, u32)> = factor_factory.prime_factor_repr();
    let mut b;
    let mut odd_factors = vec![];
    // prime_factors
    //     .into_par_iter()
    //     .for_each(|prime:(u64,u32)|{
    //         if prime.1 % 2 == 1 {odd_factors.push(prime.0);}
    //     });
    for prime in prime_factors{
        if prime.1 % 2 == 1 {odd_factors.push(prime.0);}
    }
    if odd_factors.is_empty() {
        b = 1;
    }
    else {
        b = odd_factors[0];
        odd_factors.remove(0);
        for odd in odd_factors {
            b *= odd;
        }
    };
    let radicand_of_a: u64 = unsigned_testee / b.pow(3);
    let test: u64 = radicand_of_a * b.pow(3); // IS THIS USELESS CODE?
    if unsigned_testee == test {return true;}
    false
}

#[test]
fn test_is_powerful(){
    for &i in &TEST_POWERFUL {
        assert!(is_powerful(i));
    }
    assert!(!is_powerful(19));
    assert!(!is_powerful(-20));
    assert!(!is_powerful(-25));
}

///
/// An achilles number is a powerful number which is not a perfect power. 
/// Behavior described in OEIS A052486. 
/// 
/// From Wikipedia:  positive integer n is a powerful number if, for every prime factor p of n, p2 is also a divisor. In other words, every prime factor appears at least squared in the factorization. All Achilles numbers are powerful. However, not all powerful numbers are Achilles numbers: only those that cannot be represented as mk, where m and k are positive integers greater than 1.
/// 
///  # Arguements
/// 
///  * `testee` - An i32 number to be tested 
/// 
///  # Example
///  ``` rust
/// let achilles_num: i32 = 500;
/// let not_achilles_num: i32 = 784;
/// assert!(is_achilles(achilles_num);
/// assert!(!is_achilles(not_achilles_num));
/// ```    
/// 
///  # Todo
///  Upper limit catch, currently panics as i32:MAX integers
/// 
pub fn is_achilles(testee: i32) -> bool {
    if is_perfect_power(testee) {return false;}
    if is_powerful(testee){
        if is_perfect_power(testee) {return false;}
        let unsigned_testee:u64 = u64::from(testee.unsigned_abs());
        let factor_factory: Factorization<u64> = Factorization::run(unsigned_testee);
        let prime_factors:Vec<(u64, u32)> = factor_factory.prime_factor_repr();
        for factor in prime_factors{
            let factor_squared = factor.0.pow(2);
            if unsigned_testee % factor_squared != 0 {return false;} // if any factor squared does not divide testee, f
        }
        return  true;
    };
    false
}

#[test]
fn test_is_achilles(){
    for &i in &TEST_ACHILLES {
        assert!(is_achilles(i));
    }
    assert!(!is_achilles(360));
    assert!(!is_achilles(784));
    assert!(!is_achilles(-72));
}

///
/// An pefect power is a is a natural number that can be described as a n-th power of a single natural number
/// Behavior described in OEIS A052486. 
/// 
/// From Wikipedia: n is a perfect power if there exist natural numbers m > 1, and k > 1 such that mk = n. In this case, n may be called a perfect kth power. If k = 2 or k = 3, then n is called a perfect square or perfect cube, respectively. Sometimes 0 and 1 are also considered perfect powers (0k = 0 for any k > 0, 1k = 1 for any k). 
/// 
///  # Arguements
/// 
///  * `testee` - An i32 number to be tested 
/// 
///  # Example
///  ``` rust
/// let perfect: i32 = 500;
/// let not_perfect: i32 = 500;
/// assert!(is_perfect_power(perfect));
/// assert!(!is_perfect_power(not_perfect));
/// ```    
/// 
///  # Todo
///  Upper limit catch, currently panics as i32:MAX integers
/// 
pub fn is_perfect_power(testee: i32) -> bool {
    if !is_powerful(testee) {return false;};
    let unsigned_testee: u64 = u64::from(testee.unsigned_abs());
    let factor_factory: Factorization<u64> = Factorization::run(unsigned_testee);
    let prime_factors:Vec<(u64, u32)> = factor_factory.prime_factor_repr();
    let mut gcd_of_prime_powers = prime_factors[0].1;
    for prime_power in &prime_factors[1..] {
        gcd_of_prime_powers = gcd_of_prime_powers.gcd(prime_power.1);
    }
    if gcd_of_prime_powers > 1 {
        return true;
    }
false
}

#[test]
fn test_is_perfect_power(){
    for &i in &TEST_PERFECT {
        assert!(is_perfect_power(i));
    }
    assert!(!is_perfect_power(360));
    assert!(!is_perfect_power(785));
    assert!(!is_perfect_power(-72));    

}

///
/// A semiprime is the product of exactly two primes
/// Behavior described in OEIS A001358. 
/// 
///  # Arguements
/// 
///  * `testee` - An i32 number to be tested 
/// 
///  # Example
///  ``` rust
/// let semiprime: i32 = 9;
/// let not_semiprime: i32 = 500;
/// assert!(is_semiprime(semiprime));
/// assert!(!is_semiprime(not_semiprime));
/// ```    
/// 
///  # Todo
///  Upper limit catch, currently panics as i32:MAX integers
/// 
pub fn is_semiprime(testee: i32) -> bool{
    if testee < 4 {return false;}
    let unsigned_testee:u64 = u64::from(testee.unsigned_abs());
    let factor_factory: Factorization<u64> = Factorization::run(unsigned_testee);
    let prime_factors:Vec<(u64, u32)> = factor_factory.prime_factor_repr();
    if prime_factors.len() == 2{
        return true;
    }
    if prime_factors.len() == 1 && prime_factors[0].1 == 2 {
        return true;
    }    
false
}

#[test]
fn test_is_semiprime(){
    for &i in &TEST_SEMIPRIME {
    assert!(is_semiprime(i));
    assert!(!is_semiprime(19));
assert!(!is_semiprime(786));
assert!(!is_semiprime(-72));   
}
}


///
/// A sphenic integer is the product of three distince primes
/// Behavior described in OEIS A007304. 
/// 
///  # Arguements
/// 
///  * `testee` - An i32 number to be tested 
/// 
///  # Example
///  ``` rust
/// let sphenic: i32 = 30;
/// let not_sphenic: i32 = 24;
/// assert!(is_sphenic(sphenic));
/// assert!(!is_shphenic(not_sphenic));
/// ```    
/// 
///  # Todo
///  Upper limit catch, currently panics as i32:MAX integers
pub fn is_sphenic(testee: i32) -> bool {
    if testee < 4 {return false;}
    let unsigned_testee:u64 = u64::from(testee.unsigned_abs());
    let factor_factory: Factorization<u64> = Factorization::run(unsigned_testee);
    let prime_factors:Vec<(u64, u32)> = factor_factory.prime_factor_repr();
    if prime_factors.len() == 3{
        return true;
    } 
false   
}

#[test]
fn test_is_sphenic(){
    for &borrow_i in &(TEST_SPHENIC) {
    let i: i32 = borrow_i;
    assert!(is_sphenic(i));
    assert!(!is_sphenic(19));
    assert!(is_sphenic(786));
    assert!(!is_sphenic(788));
    assert!(!is_sphenic(72));   
}}
//
/// A sqaurefree integer is the product of unique prime factors, no prime factor has a power greater than one 
/// Behavior described in OEIS A005117. 
/// 
///  # Arguements
/// 
///  * `testee` - An i32 number to be tested 
/// 
///  # Example
///  ``` rust
/// let squarefree: i32 = 10;
/// let not_squarefree: i32 = 18;
/// assert!(is_squarefree(squarefree));
/// assert!(!is_squarefree(not_squarefree));
/// ```    
/// 
///  # Todo
///  Upper limit catch, currently panics as i32:MAX integers
/// 
///  I do not like how the tail for this function returns true, while all other test functions' tails return false.
/// 
pub fn is_squarefree(testee: i32) -> bool {
    let unsigned_testee:u64 = u64::from(testee.unsigned_abs());
    let factor_factory: Factorization<u64> = Factorization::run(unsigned_testee);
    let prime_factors:Vec<(u64, u32)> = factor_factory.prime_factor_repr();
    for prime in prime_factors{
        if prime.1 > 1 {return false;}
    }
    true
}

#[test]
fn test_is_squarefree(){
    for i in &TEST_SQUAREFREE {
        assert!(is_squarefree(*i));
        assert!(!is_squarefree(8));
        assert!(!is_squarefree(9));
}
}

/// Checks if a number is a pronic number.
///
/// A pronic number, also known as an oblong number or rectangular number,
/// is a number that is the product of two consecutive integers.
/// Described in OEIS A002378
/// 
/// # Arguments
///
/// * `testee` - An i32 number to be tested.
///
/// # Example
///
/// ``` rust
/// let pronic: i32 = 6;
/// let not_pronic: i32 = 10;
/// assert!(is_pronic(pronic));
/// assert!(!is_pronic(not_pronic));
/// ```
///
pub fn is_pronic(testee: i32) -> bool {
    let mut sqrt: i32 = 2;
    if testee < 0 {return false;}
    if testee == 0 {return true;}
    if testee > 0 {sqrt = testee.integer_sqrt();}

    for i in 0..=sqrt {
        if i * (i + 1) == testee {
            return true;
        }
    }
    false
}

#[test]
fn test_is_pronic(){
    for i in &TEST_PRONIC {
        assert!(is_pronic(*i));}
        assert!(!is_pronic(8));
        assert!(!is_pronic(10));
}


/// Checks if a number is a smooth number to the n-th degree.
/// 
/// # Arguments
///
/// * `testee` - An i32 number to be tested.
/// * `smooth` - The factor by which the smoothness is to be tested, cannot be negative
///
/// # Example
///
/// ``` rust
/// let five_smooth: i32 = 384;
/// let three_smooth: i32 = 240;
/// assert!(is_smooth(five_smooth, 5));
/// assert!(!is_smooth(three_smooth, 5));
/// assert!(is_smooth(three_smooth, 3));
/// ```
///
pub fn is_smooth(testee: i32, smoothing: u32) -> bool {
    let unsigned_testee:u64 = u64::from(testee.unsigned_abs());
    let factor_factory: Factorization<u64> = Factorization::run(unsigned_testee);
    let prime_factors:Vec<(u64, u32)> = factor_factory.prime_factor_repr();
    let max_factor: u64 = prime_factors.last().unwrap().0;
    if u64::from(smoothing) <= max_factor{
        return true;
    }
    false
}

/// Checks if a number is a rough number to the n-th degree.
/// 
/// # Arguments
///
/// * `testee` - An i32 number to be tested.
/// * `rough` - The factor by which the roughness is to be tested
///
/// # Example
///
/// ``` rust
//
/// ```
///
pub fn is_rough(testee: i32, rough: u32) -> bool {
        let unsigned_testee:u64 = u64::from(testee.unsigned_abs());
        let factor_factory: Factorization<u64> = Factorization::run(unsigned_testee);
        let prime_factors:Vec<(u64, u32)> = factor_factory.prime_factor_repr();
    let least_factor: u64 = prime_factors.first().unwrap().0;
    if least_factor > u64::from(rough){
        return true;
    }
    false
}


pub fn is_unusual(testee: i32) -> bool {
    let unsigned_testee:u64 = u64::from(testee.unsigned_abs());
    let factor_factory: Factorization<u64> = Factorization::run(unsigned_testee);
    let prime_factors:Vec<(u64, u32)> = factor_factory.prime_factor_repr();
    let max_factor: u64 = prime_factors.last().unwrap().0;
    let sqrt = f64::from(testee).sqrt();    
    if max_factor >= sqrt.floor() as u64 {
        return true;
    }
    if max_factor == sqrt.floor() as u64 && sqrt.fract() > 0.0{
        return true;
    }
    false
}