pub mod gcd;
pub mod modulo;
pub mod primes;
pub mod root;
use {
core::fmt::Display,
std::{
convert::From,
fmt::Debug,
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign},
str::FromStr,
},
};
pub trait Value<T>: Copy + Clone + Eq + Ord + Default {
fn value(&self) -> T;
fn set_value<V: Number + AsPrimitive<usize>>(&mut self, val: V);
fn new(val: usize) -> Self {
let mut instance = Self::default();
instance.set_value(val);
instance
}
}
#[macro_export]
macro_rules! as_value_impl {
($($t: ident)+) => {$(
impl $crate::math::Value<$t> for $t {
fn value(&self) -> $t {
*self
}
fn set_value<V: $crate::math::Number + $crate::math::AsPrimitive<usize>>(&mut self, val: V) {
*self = val.as_primitive() as $t;
}
}
)+};
}
as_value_impl!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
pub trait ConstValue<T>: Copy + Clone + Eq + Ord + Default {
const VALUE: T;
fn value() -> T {
Self::VALUE
}
}
#[macro_export]
macro_rules! value_impl {
($name:ident : $t:ty = $val:expr) => {
#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Default)]
pub struct $name {}
impl $crate::math::ConstValue<$t> for $name {
const VALUE: $t = $val;
}
};
}
pub use value_impl as value;
pub trait Zero {
fn zero() -> Self;
}
pub trait One {
fn one() -> Self;
}
#[macro_export]
macro_rules! zero_impl {
($($t: ident)+) => {$(
impl $crate::math::Zero for $t {
fn zero() -> Self {
0
}
}
)+};
}
zero_impl!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
#[macro_export]
macro_rules! one_impl {
($($t: ident)+) => {$(
impl $crate::math::One for $t {
fn one() -> Self {
1
}
}
)+};
}
one_impl!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
pub trait Pow {
fn pow(self, exp: u32) -> Self;
}
macro_rules! pow_impl {
($($t: ident)+) => {$(
impl $crate::math::Pow for $t {
fn pow(self, exp: u32) -> $t {
<$t>::pow(self, exp)
}
}
)+};
}
pow_impl!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
pub trait Powf {
fn powf(self, exp: Self) -> Self;
}
macro_rules! powf_impl {
($($t: ident)+) => {$(
impl $crate::math::Powf for $t {
fn powf(self, exp: $t) -> $t {
<$t>::powf(self, exp)
}
}
)+};
}
powf_impl!(f32 f64);
pub trait AsType<T> {
fn as_type(&self) -> T;
}
macro_rules! impl_as_type {
($from:ty => $($to:ty),*) => {
$(
impl $crate::math::AsType<$to> for $from {
fn as_type(&self) -> $to {
*self as $to
}
}
)*
};
}
impl_as_type!(u8 => u16, u32, u64, usize, i16, i32, i64, isize, f32, f64);
impl_as_type!(u16 => u16, u32, u64, usize, i16, i32, i64, isize, f32, f64);
impl_as_type!(u32 => u16, u32, u64, usize, i16, i32, i64, isize, f32, f64);
impl_as_type!(u64 => u16, u32, u64, usize, i16, i32, i64, isize, f32, f64);
impl_as_type!(usize => u16, u32, u64, usize, i16, i32, i64, isize, f32, f64);
impl_as_type!(i16 => u16, u32, u64, usize, i16, i32, i64, isize, f32, f64);
impl_as_type!(i32 => u16, u32, u64, usize, i16, i32, i64, isize, f32, f64);
impl_as_type!(i64 => u16, u32, u64, usize, i16, i32, i64, isize, f32, f64);
impl_as_type!(isize => u16, u32, u64, usize, i16, i32, i64, isize, f32, f64);
impl_as_type!(f64 => u16, u32, u64, usize, i16, i32, i64, isize, f32, f64);
pub trait Downcast: Sized {
type Source: From<Self>;
fn downcast(src: Self::Source) -> Self;
}
#[macro_export]
macro_rules! downcast_impl {
($($t: ident $w: ident),+) => {$(
impl $crate::math::Downcast for $t {
type Source = $w;
fn downcast(src: Self::Source) -> Self {
src as $t
}
}
)+};
}
downcast_impl!(i8 i16, i16 i32, i32 i64, i64 i128, u8 u16, u16 u32, u32 u64, u64 u128);
pub trait Upcast: Sized {
type Target: From<Self>;
fn upcast(self) -> Self::Target;
}
#[macro_export]
macro_rules! upcast_impl {
($($t: ident $w: ident),+) => {$(
impl $crate::math::Upcast for $t {
type Target = $w;
fn upcast(self) -> Self::Target {
$w::from(self)
}
}
)+};
}
upcast_impl!(i8 i16, i16 i32, i32 i64, i64 i128, u8 u16, u16 u32, u32 u64, u64 u128);
pub trait Integer: Number {
fn is_even(self) -> bool {
self.value() % Self::new(2) == Self::zero()
}
fn is_odd(self) -> bool {
!self.is_even()
}
}
#[macro_export]
macro_rules! integer_impl {
($($t: ident)+) => {$(
impl $crate::math::Integer for $t {}
)+};
}
integer_impl!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
pub trait Number:
Sized
+ Copy
+ FromStr
+ Default
+ Debug
+ Display
+ Value<Self>
+ Zero
+ One
+ Pow
+ Add<Output = Self>
+ AddAssign
+ Sub<Output = Self>
+ SubAssign
+ Mul<Output = Self>
+ MulAssign
+ Div<Output = Self>
+ DivAssign
+ Rem<Output = Self>
+ RemAssign
+ PartialOrd
+ PartialEq
{
}
impl<T> Number for T where
T: Sized
+ Copy
+ FromStr
+ Default
+ Debug
+ Display
+ Value<T>
+ Zero
+ One
+ Pow
+ Add<Output = Self>
+ AddAssign
+ Sub<Output = Self>
+ SubAssign
+ Mul<Output = Self>
+ MulAssign
+ Div<Output = Self>
+ DivAssign
+ Rem<Output = Self>
+ RemAssign
+ PartialOrd
+ PartialEq
{
}
pub trait Invertible {
type Output;
fn inverse(&self) -> Option<Self::Output>;
}
pub trait AsPrimitive<T> {
fn as_primitive(&self) -> T;
}
#[macro_export]
macro_rules! as_primitive_impl {
($($t: ident)+) => {$(
impl $crate::math::AsPrimitive<$t> for $t {
fn as_primitive(&self) -> $t {
*self
}
}
)+};
}
as_primitive_impl!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
#[macro_export]
macro_rules! as_primitive_unsigned_impl {
($($t: ident)+) => {$(
impl $crate::math::AsPrimitive<usize> for $t {
fn as_primitive(&self) -> usize {
*self as usize
}
}
)+};
}
as_primitive_unsigned_impl!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128);