Reputation: 332
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
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