2020-02-12 22:29:57 -05:00
|
|
|
#![forbid(unsafe_code)]
|
|
|
|
|
2020-02-13 17:13:25 -05:00
|
|
|
use std::ops::{
|
|
|
|
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
|
|
|
|
Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
|
|
|
|
};
|
2020-02-12 23:10:08 -05:00
|
|
|
|
2020-02-12 22:29:57 -05:00
|
|
|
pub mod bigint;
|
|
|
|
pub mod rational;
|
|
|
|
pub mod seq;
|
|
|
|
|
2020-02-13 17:13:25 -05:00
|
|
|
/// A Trait representing unsigned integer primitives
|
|
|
|
pub trait Unsigned:
|
|
|
|
Add
|
|
|
|
+ AddAssign
|
|
|
|
+ BitAnd
|
|
|
|
+ BitAndAssign
|
|
|
|
+ BitOr
|
|
|
|
+ BitOrAssign
|
|
|
|
+ BitXor
|
|
|
|
+ BitXorAssign
|
|
|
|
+ Div
|
|
|
|
+ DivAssign
|
|
|
|
+ Mul
|
|
|
|
+ MulAssign
|
|
|
|
+ Rem
|
|
|
|
+ RemAssign
|
|
|
|
+ Copy
|
|
|
|
+ Shl
|
|
|
|
+ ShlAssign
|
|
|
|
+ Shr
|
|
|
|
+ ShrAssign
|
|
|
|
+ Sub
|
|
|
|
+ SubAssign
|
|
|
|
+ Eq
|
|
|
|
+ Ord
|
|
|
|
+ Not
|
|
|
|
{
|
|
|
|
/// Find the greatest common denominator of two numbers
|
|
|
|
fn gcd(a: Self, b: Self) -> Self;
|
2020-02-12 22:29:57 -05:00
|
|
|
|
2020-02-13 17:13:25 -05:00
|
|
|
/// Find the least common multiple of two numbers
|
|
|
|
fn lcm(a: Self, b: Self) -> Self;
|
2020-02-12 22:29:57 -05:00
|
|
|
|
2020-02-13 17:13:25 -05:00
|
|
|
/// The maximum value of the type
|
|
|
|
fn max_value() -> Self;
|
|
|
|
|
|
|
|
/// Is this a zero value?
|
|
|
|
fn is_zero(self) -> bool;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
2020-02-12 23:10:08 -05:00
|
|
|
pub enum Sign {
|
|
|
|
Positive,
|
2020-02-13 17:13:25 -05:00
|
|
|
Negative,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Sign {
|
|
|
|
fn default() -> Self {
|
|
|
|
Sign::Positive
|
|
|
|
}
|
2020-02-12 23:10:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Not for Sign {
|
|
|
|
type Output = Sign;
|
|
|
|
|
|
|
|
fn not(self) -> Self::Output {
|
|
|
|
match self {
|
|
|
|
Self::Positive => Self::Negative,
|
|
|
|
Self::Negative => Self::Positive,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-13 17:13:25 -05:00
|
|
|
macro_rules! impl_unsigned {
|
|
|
|
($Type: ty) => {
|
|
|
|
impl Unsigned for $Type {
|
|
|
|
fn gcd(a: $Type, b: $Type) -> $Type {
|
|
|
|
if a == b {
|
|
|
|
return a;
|
|
|
|
} else if a == 0 {
|
|
|
|
return b;
|
|
|
|
} else if b == 0 {
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
|
|
|
let a_even = a % 2 == 0;
|
|
|
|
let b_even = b % 2 == 0;
|
|
|
|
|
|
|
|
if a_even {
|
|
|
|
if b_even {
|
|
|
|
// Both a & b are even
|
|
|
|
return Self::gcd(a >> 1, b >> 1) << 1;
|
|
|
|
} else if !b_even {
|
|
|
|
// b is odd
|
|
|
|
return Self::gcd(a >> 1, b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// a is odd, b is even
|
|
|
|
if (!a_even) && b_even {
|
|
|
|
return Self::gcd(a, b >> 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if a > b {
|
|
|
|
return Self::gcd((a - b) >> 1, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
Self::gcd((b - a) >> 1, a)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn lcm(a: $Type, b: $Type) -> $Type {
|
|
|
|
if (a == 0 && b == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
a * b / Self::gcd(a, b)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn max_value() -> $Type {
|
|
|
|
<$Type>::max_value()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_zero(self) -> bool {
|
|
|
|
self == 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
impl_unsigned!(u8);
|
|
|
|
impl_unsigned!(u16);
|
|
|
|
impl_unsigned!(u32);
|
|
|
|
impl_unsigned!(u64);
|
|
|
|
impl_unsigned!(u128);
|
|
|
|
impl_unsigned!(usize);
|
|
|
|
|
2020-02-12 22:29:57 -05:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2020-02-13 17:13:25 -05:00
|
|
|
use super::*;
|
|
|
|
|
2020-02-12 22:29:57 -05:00
|
|
|
#[test]
|
2020-02-13 17:13:25 -05:00
|
|
|
fn test_gcd() {
|
|
|
|
assert_eq!(u8::gcd(2, 2), 2);
|
|
|
|
assert_eq!(u16::gcd(36, 48), 12);
|
2020-02-12 22:29:57 -05:00
|
|
|
}
|
|
|
|
}
|