use num::Integer;
use crate::divisible::{Composite, Prime, PrimePower};
pub trait Modulus where Self: Clone + Into<u32> {
fn modding(&self, d: u32) -> u32 {
let uself: u32 = self.clone().into();
d % uself
}
fn mod_neg(&self, d: u32) -> u32 {
let uself: u32 = self.clone().into();
let dmod = d % uself;
if dmod == 0 {
0
} else {
uself - dmod
}
}
fn mod_sub(&self, d0: u32, d1: u32) -> u32 {
let uself: u32 = self.clone().into();
let d0mod = d0 % uself;
let d1mod = d1 % uself;
if d0mod >= d1mod {
d0mod - d1mod
} else {
uself + d0mod - d1mod
}
}
fn mod_exp(&self, d: u32, x: u32) -> u32 {
if d == 0 {
return 0;
} else if x == 0 {
return 1;
}
let uself: u32 = self.clone().into();
let (mut mult, mut ans, mut pow) = (d, 1, x);
while pow > 1 {
if pow.is_odd() {
ans = ans * mult % uself;
pow = pow - 1;
}
mult = mult * mult % uself;
pow = pow / 2;
}
(ans * mult) % uself
}
}
impl Modulus for Prime { }
impl Modulus for PrimePower { }
impl Modulus for Composite { }