Skip to content

Flatten numeric trait hierarchy and allow for user extensibility. #10387

Closed
@brendanzab

Description

@brendanzab

I am growing increasingly concerned that we are locking ourselves into a substandard numeric API heading toward 1.0 that will be hard to alter in the future without breaking a significant amount of client code.

Perhaps we could investigate simplifying the numeric trait hierarchy to be centered around built-in types. Perhaps the traits could be removed from the prelude as default instead using free, method wrapper functions as the primary form of using the numeric functions. This would make the API more amenable to being extended by users in the future. Perhaps an algebraic hierarchy could be included in extra.

For example the Round, Fractional, Algebraic, Trigonometric, Exponential, Hyperbolic, Real and Float could be consolidated into a single Float trait. Then the primary way of accessing the functions would be via the wrapper functions, eg. num::atan2(x, y).

pub trait Float {
    fn floor(x: Self) -> Self;
    fn ceil(x: Self) -> Self;
    fn round(x: Self) -> Self;
    fn trunc(x: Self) -> Self;
    fn fract(x: Self) -> Self;

    fn recip(x: Self) -> Self;

    fn pow(x: Self, n: Self) -> Self;
    fn sqrt(x: Self) -> Self;
    fn rsqrt(x: Self) -> Self;
    fn cbrt(x: Self) -> Self;
    fn hypot(x: Self, other: Self) -> Self;

    fn sin(x: Self) -> Self;
    fn cos(x: Self) -> Self;
    fn tan(x: Self) -> Self;

    fn asin(x: Self) -> Self;
    fn acos(x: Self) -> Self;
    fn atan(x: Self) -> Self;

    fn atan2(x: Self, y: Self) -> Self;
    fn sin_cos(x: Self) -> (Self, Self);

    fn sinh(x: Self) -> Self;
    fn cosh(x: Self) -> Self;
    fn tanh(x: Self) -> Self;

    fn asinh(x: Self) -> Self;
    fn acosh(x: Self) -> Self;
    fn atanh(x: Self) -> Self;

    fn exp(x: Self) -> Self;
    fn exp2(x: Self) -> Self;

    fn ln(x: Self) -> Self;
    fn log(x: Self, base: Self) -> Self;
    fn log2(x: Self) -> Self;
    fn log10(x: Self) -> Self;

    fn pi() -> Self;
    fn two_pi() -> Self;
    fn frac_pi_2() -> Self;
    fn frac_pi_3() -> Self;
    fn frac_pi_4() -> Self;
    fn frac_pi_6() -> Self;
    fn frac_pi_8() -> Self;
    fn frac_1_pi() -> Self;
    fn frac_2_pi() -> Self;
    fn frac_2_sqrtpi() -> Self;
    fn sqrt2() -> Self;
    fn frac_1_sqrt2() -> Self;
    fn e() -> Self;
    fn log2_e() -> Self;
    fn log10_e() -> Self;
    fn ln_2() -> Self;
    fn ln_10() -> Self;

    fn to_degrees(x: Self) -> Self;
    fn to_radians(x: Self) -> Self;

    fn nan() -> Self;
    fn infinity() -> Self;
    fn neg_infinity() -> Self;
    fn neg_zero() -> Self;

    fn is_nan(self) -> bool;
    fn is_infinite(self) -> bool;
    fn is_finite(self) -> bool;
    fn is_normal(self) -> bool;
    fn classify(self) -> FPCategory;

    fn mantissa_digits(_: Option<Self>) -> uint;
    fn digits(_: Option<Self>) -> uint;
    fn epsilon() -> Self;
    fn min_exp(_: Option<Self>) -> int;
    fn max_exp(_: Option<Self>) -> int;
    fn min_10_exp(_: Option<Self>) -> int;
    fn max_10_exp(_: Option<Self>) -> int;

    fn ldexp(x: Self, exp: int) -> Self;
    fn frexp(x: Self) -> (Self, int);

    fn exp_m1(x: Self) -> Self;
    fn ln_1p(x: Self) -> Self;
    fn mul_add(x: Self, a: Self, b: Self) -> Self;
    fn next_after(x: Self, other: Self) -> Self;
}

#[inline] fn floor<T:Float>(x: T) -> T { Float::floor(x) }
#[inline] fn ceil<T:Float>(x: T) -> T { Float::ceil(x) }
#[inline] fn round<T:Float>(x: T) -> T { Float::round(x) }
#[inline] fn trunc<T:Float>(x: T) -> T { Float::trunc(x) }
#[inline] fn fract<T:Float>(x: T) -> T { Float::fract(x) }

#[inline] fn recip<T:Float>(x: T) -> T { Float::recip(x) }

#[inline] fn pow<T:Float>(x: T, n: T) -> T { Float::pow(x, n) }
#[inline] fn sqrt<T:Float>(x: T) -> T { Float::sqrt(x) }
#[inline] fn rsqrt<T:Float>(x: T) -> T { Float::rsqrt(x) }
#[inline] fn cbrt<T:Float>(x: T) -> T { Float::cbrt(x) }
#[inline] fn hypot<T:Float>(x: T, y: T) -> T { Float::hypot(x, y) }

#[inline] fn sin<T:Float>(x: T) -> T { Float::sin(x) }
#[inline] fn cos<T:Float>(x: T) -> T { Float::cos(x) }
#[inline] fn tan<T:Float>(x: T) -> T { Float::tan(x) }

// ...

This is related to the numeric trait reform tracked at #4819

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions