rutil 0.2.0

A library containing utilities for creating programs in rust.
Documentation
use std::ops::*;

// ========================== //
// ========= NUMBER ========= //
// ========================== //

mod number_ops;
use number_ops::*;

/// A number.
pub trait Number:
    Sized + Copy + Clone + PartialEq + PartialOrd +
    Add<Output = Self> + AddAssign +
    Sub<Output = Self> + SubAssign +
    Mul<Output = Self> + MulAssign +
    Div<Output = Self> + DivAssign +
    Rem<Output = Self> + RemAssign +
    ConvertOps +
    SizeOps +
    SignOps +
    ClampOps +
    EuclidOps +
{}

/// Implements [`Number`].
macro_rules! impl_number {
    ($($t:ty),*) => {
        $(impl Number for $t {})*
    };
}

impl_number!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64);

// ============================ //
// ========= UNSIGNED ========= //
// ============================ //

/// An unsigned number.
pub trait Unsigned: Number {}

/// Implements [`Unsigned`].
macro_rules! impl_unsigned {
    ($($t:ty),*) => {
        $(impl Unsigned for $t {})*
    };
}

impl_unsigned!(u8, u16, u32, u64, u128, usize);

// ========================== //
// ========= SIGNED ========= //
// ========================== //

/// A signed number.
pub trait Signed:
    Number +
    Neg<Output = Self> +
{}

/// Implements [`Signed`].
macro_rules! impl_signed {
    ($($t:ty),*) => {
        $(impl Signed for $t {})*
    };
}

impl_signed!(i8, i16, i32, i64, i128, isize, f32, f64);

// =========================== //
// ========= INTEGER ========= //
// =========================== //

mod integer_ops;
use std::num::ParseIntError;
use integer_ops::*;

/// An integer.
pub trait Integer:
    Number +
    BitOps +
    BitCountingOps +
    BitConversionOps +
    IntSignOps +
    CheckedOps +
    SaturatingOps +
    WrappingOps +
    OverflowingOps +
    IntEuclidOps +
    PowOps +
{
    /// Converts a string slice in a given base to an integer.
    ///
    /// The string is expected to be an optional `+` or `-` sign (for signed) followed by digits.
    /// Leading and trailing whitespace represent an error. Digits are a subset of these characters,
    /// depending on `radix`:
    ///
    ///  * `0-9`
    ///  * `a-z`
    ///  * `A-Z`
    ///
    /// # Panics
    ///
    /// This function panics if `radix` is not in the range from 2 to 36.
    fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError>;
}

/// Implements [`Integer`].
macro_rules! impl_integer {
    ($($t:ty),*) => {
        $(impl Integer for $t {
            #[inline]
            fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
                Self::from_str_radix(src, radix)
            }
        })*
    };
}

impl_integer!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);

// ==================================== //
// ========= UNSIGNED INTEGER ========= //
// ==================================== //

/// An unsigned integer.
pub trait UnsignedInteger: Unsigned {
    /// Returns `true` if and only if `self == 2^k` for some `k`.
    fn is_power_of_two(self) -> bool;

    /// Returns the smallest power of two greater than or equal to `self`.
    ///
    /// When return value overflows (i.e., `self > (1 << (N-1))` for type
    /// `uN`), it panics in debug mode and the return value is wrapped to 0 in
    /// release mode (the only situation in which method can return 0).
    fn next_power_of_two(self) -> Self;

    /// Returns the smallest power of two greater than or equal to `n`. If
    /// the next power of two is greater than the type's maximum value,
    /// `None` is returned, otherwise the power of two is wrapped in `Some`.
    fn checked_next_power_of_two(self) -> Option<Self>;
}

/// Implements [`UnsignedInteger`].
macro_rules! impl_unsigned_integer {
    ($($t:ty),*) => {
        $(impl UnsignedInteger for $t {
            #[inline] fn is_power_of_two(self) -> bool { self.is_power_of_two() }
            #[inline] fn next_power_of_two(self) -> Self { self.next_power_of_two() }
            #[inline] fn checked_next_power_of_two(self) -> Option<Self> { self.checked_next_power_of_two() }
        })*
    };
}

impl_unsigned_integer!(u8, u16, u32, u64, u128, usize);

// ================================== //
// ========= SIGNED INTEGER ========= //
// ================================== //

/// A signed integer.
pub trait SignedInteger: Signed {}

/// Implements [`SignedInteger`].
macro_rules! impl_signed_integer {
    ($($t:ty),*) => {
        $(impl SignedInteger for $t {})*
    };
}

impl_signed_integer!(i8, i16, i32, i64, i128, isize);

// ============================== //
// ========= CORE FLOAT ========= //
// ============================== //

mod core_float_ops;
use core_float_ops::*;

/// A core floating point number.
pub trait CoreFloat:
    Signed +
    FloatConstants +
    ClassificationOps +
{
    /// Takes the reciprocal (inverse) of a number, `1/x`.
    fn recip(self) -> Self;

    /// Converts radians to degrees.
    fn to_degrees(self) -> Self;

    /// Converts degrees to radians.
    fn to_radians(self) -> Self;
}

/// Implements [`CoreFloat`].
macro_rules! impl_core_float {
    ($($t:ty),*) => {
        $(impl CoreFloat for $t {
            #[inline] fn recip(self) -> Self { self.recip() }
            #[inline] fn to_degrees(self) -> Self { self.to_degrees() }
            #[inline] fn to_radians(self) -> Self { self.to_radians() }
        })*
    };
}

impl_core_float!(f32, f64);

// ========================= //
// ========= FLOAT ========= //
// ========================= //

mod float_ops;
use float_ops::*;

/// A floating point number.
pub trait Float:
    CoreFloat +
    FloatRoundOps +
    TrigonometricOps +
    LogarithmOps +
    HyperbolicOps +
{
    /// Returns a number composed of the magnitude of `self` and the sign of
    /// `sign`.
    ///
    /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
    /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
    /// `sign` is returned.
    fn copysign(self, sign: Self) -> Self;

    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
    /// error, yielding a more accurate result than an unfused multiply-add.
    ///
    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
    /// the target architecture has a dedicated `fma` CPU instruction. However,
    /// this is not always true, and will be heavily dependant on designing
    /// algorithms with specific target hardware in mind.
    fn mul_add(self, a: Self, b: Self) -> Self;

    /// Raises a number to an integer power.
    ///
    /// Using this function is generally faster than using `powf`
    fn powi(self, n: i32) -> Self;

    /// Raises a number to a floating point power.
    fn powf(self, n: Self) -> Self;

    /// Returns the square root of a number.
    ///
    /// Returns NaN if `self` is a negative number other than `-0.0`.
    fn sqrt(self) -> Self;

    /// Returns `e^(self)`, (the exponential function).
    fn exp(self) -> Self;

    /// Returns `2^(self)`.
    fn exp2(self) -> Self;

    /// Returns the cube root of a number.
    fn cbrt(self) -> Self;

    /// Returns `e^(self) - 1` in a way that is accurate even if the
    /// number is close to zero.
    fn exp_m1(self) -> Self;

    /// Returns `ln(1+n)` (natural logarithm) more accurately than if
    /// the operations were performed separately.
    fn ln_1p(self) -> Self;
}

/// Implements [`Float`].
macro_rules! impl_float {
    ($($t:ty),*) => {
        $(impl Float for $t {
            #[inline] fn copysign(self, sign: Self) -> Self { self.copysign(sign) }
            #[inline] fn mul_add(self, a: Self, b: Self) -> Self { self.mul_add(a, b) }
            #[inline] fn powi(self, n: i32) -> Self { self.powi(n) }
            #[inline] fn powf(self, n: Self) -> Self { self.powf(n) }
            #[inline] fn sqrt(self) -> Self { self.sqrt() }
            #[inline] fn exp(self) -> Self { self.exp() }
            #[inline] fn exp2(self) -> Self { self.exp2() }
            #[inline] fn cbrt(self) -> Self { self.cbrt() }
            #[inline] fn exp_m1(self) -> Self { self.exp_m1() }
            #[inline] fn ln_1p(self) -> Self { self.ln_1p() }
        })*
    };
}

impl_float!(f32, f64);