rmath 0.1.5

A rust math library
Documentation

macro_rules! nat_from_basic {
    ($type: ty) => {
        impl From<$type> for Nat {
            fn from(x: $type) -> Self {
                if std::mem::size_of::<$type>() <= std::mem::size_of::<u32>() {
                    Nat {nat: Rc::new(Cell::new(vec![x as u32]))}
                } else {
                    Nat::from(x.to_le_bytes().as_ref())
                }
            }
        }
    };
    
    ($type0: ty, $($type1: ty),+) => {
        nat_from_basic!($type0);
        nat_from_basic!($($type1),+);
    }
}

macro_rules! nat_fmt {
    (($trait_name: ident, $fmt_str: literal, $prefix: literal)) => {
        impl $trait_name for Nat {
            fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
                if self.is_nan() {
                    return write!(f, "{}", "NaN");
                }
                
                let mut nat: Vec<String> = self.iter().rev().map(|&x| {format!($fmt_str, x)}).collect();
                let len = nat.len();
                match nat.first_mut() {
                    Some(x) => {
                        let mut y = String::with_capacity(x.len());
                        y.push_str(x.trim_start_matches('0'));
                        x.clear();
                        if y.is_empty() && len == 1 {
                            x.push('0');
                        } else {
                            x.push_str(y.as_str());
                        }
                    }
                    None => {},
                }
                if f.alternate() {
                    nat.insert(0, $prefix.to_string());
                }
                write!(f, "{}", nat.join(""))
            }
        }
    };
    
    (($trait_name0: ident, $fmt_str0: literal, $prefix0: literal), $(($trait_name1: ident, $fmt_str1: literal, $prefix1: literal)),+) => {
        nat_fmt!(($trait_name0, $fmt_str0, $prefix0));
        nat_fmt!($(($trait_name1, $fmt_str1, $prefix1)),+);
    }
}

macro_rules! nat_eq_basic {
    ($type0: ty) => {
        impl PartialEq<$type0> for Nat {
            fn eq(&self, other: &$type0) -> bool {
                if self.is_nan() {false}
                else {
                    let x = Nat::from(*other);
                    self.as_vec() == x.as_vec()
                }
            }
        }
    };
    ($type0: ty, $($type1: ty),+) => {
        nat_eq_basic!($type0);
        nat_eq_basic!($($type1),+);
    }
}

macro_rules! nat_ord_basic {
    ($type0: ty) => {
        impl PartialOrd<$type0> for Nat {
            fn partial_cmp(&self, other: &$type0) -> Option<Ordering> {
                let x = Nat::from(*other);
                self.partial_cmp(&x)
            }
        }
    };
    ($type0: ty, $($type1: ty),+) => {
        nat_ord_basic!($type0);
        nat_ord_basic!($($type1),+);
    }
}

macro_rules! nat_arith_ops1 {
    (($Rhs: ty, $trait_name: ident, $trait_assign_name: ident, $fn_name: ident, $fn_assign_name: ident, $fn_inner_name: ident, $rhs_is_nan: expr)) => {
        impl $trait_name<$Rhs> for Nat {
            type Output = Nat;
            fn $fn_name(self, rhs: $Rhs) -> Self::Output {
                if self.is_nan() || $rhs_is_nan(&rhs) {
                    Self::default()
                } else {
                    let mut lhs = self.deep_clone();
                    lhs.$fn_inner_name(&rhs);
                    lhs
                }
            }
        }
        
        impl $trait_assign_name<$Rhs> for Nat {
            fn $fn_assign_name(&mut self, rhs: $Rhs) {
                if self.is_nan() || $rhs_is_nan(&rhs) {
                    self.clear();
                } else {
                    self.$fn_inner_name(&rhs);
                }
            }
        }
    };
    
    (($Rhs: ty, $trait_name: ident, $trait_assign_name: ident, $fn_name: ident, $fn_assign_name: ident, $fn_inner_name: ident, $rhs_is_nan: expr),
        $(($Rhs1: ty, $trait_name1: ident, $trait_assign_name1: ident, $fn_name1: ident, $fn_assign_name1: ident, $fn_inner_name1: ident, $rhs_is_nan1: expr)),+) => {
        nat_arith_ops1!(($Rhs, $trait_name, $trait_assign_name, $fn_name, $fn_assign_name, $fn_inner_name, $rhs_is_nan));
        nat_arith_ops1!($(($Rhs1, $trait_name1, $trait_assign_name1, $fn_name1, $fn_assign_name1, $fn_inner_name1, $rhs_is_nan1)),+);
    }
}