w177us
w177us

Reputation: 332

How to access numeric constants using the Float trait?

I want to write generic mathematical code in Rust. The types f32 and f64 already define constants. E.g. π is std::f32::consts::PI.

I understand that the Float trait provides common functions, but how about constants?

My attempt:

extern crate num;

use self::num::traits::Float;

fn f<T: Float>(t: T) -> T { 
    T::consts::PI * t 
}   

fn main() {
    let x = 5.0f32;
    println!("Result: {}", f(x));
}   

yields:

main.rs:6:5: 6:18 error: associated type `consts` not found for `T` [E0220]
main.rs:6     T::consts::PI * t
              ^~~~~~~~~~~~~

If this is not possible, then how may I access mathematical constants using a generic type T?

Upvotes: 3

Views: 655

Answers (1)

Shepmaster
Shepmaster

Reputation: 431011

This is a feature called associated constants. It doesn't appear that num 0.1.41 makes use of any such constants, but you could augment the Float trait like this:

extern crate num;

trait FloatConst: num::Float {
    const PI: Self;
    const E: Self;
}

impl FloatConst for f32 {
    const PI: f32 = 3.14;
    const E: f32 = 2.71;
}

impl FloatConst for f64 {
    const PI: f64 = 3.14159;
    const E: f64 = 2.71828;
}

fn f<T: FloatConst>(t: T) -> T {
    t + T::PI + T::E
}

fn main() {
    let x = 5.0f32;
    println!("Result: {}", f(x));
}

In previous versions of Rust, you will need to use functions:

extern crate num;

use num::traits::Float;

trait FloatConst {
    fn pi() -> Self;
}

impl FloatConst for f32 {
    fn pi() -> Self { std::f32::consts::PI }
}

impl FloatConst for f64 {
    fn pi() -> Self { std::f64::consts::PI }
}

fn f<T: Float + FloatConst>(t: T) -> T {
    T::pi() * t
}

fn main() {
    println!("Result: {}", f(5.0f32));
    println!("Result: {}", f(5.0f64));
}

I'd expect that monomorphization and compiler optimizations will make this about as fast it it could be, but profiling is always a good idea if needed.

Upvotes: 6

Related Questions