Simsys
November 15, 2016, 1:42pm
1
I'm newbe in rust. My training project is a fixedpoint arithmetic package for rust. For this, I need a macro to convert from float to u32. I managed the following code to compile:
const ONE: i32 = 1 << 16;
macro_rules! rconst {
($x:expr) => {
($x * ONE as f32) as i32
};
}
const PI: i32 = rconst!(3.14);
fn main() {
println!("{:?}", PI);
}
This works and that is fine. Better would be, to half ther rounding errors. In C the macro looks like this:
#define rconst(R) ((fixedpt)((R) * FIXEDPT_ONE + ((R) >= 0 ? 0.5 : -0.5)))
How can I do this with a rust macro?
Thanks
Simsys
Rust doesn't have the ternary operator. Instead, regular if
is just an expression.
Unfortunately , it can't currently evaluate if
s in const
contexts. So you can't do this... directly.
What you can do is abuse arithmetic shift rules:
const ONE: i32 = 1 << 16;
macro_rules! rconst {
($x:expr) => {
(
$x
* (ONE as f32)
+ ((((($x * (ONE as f32)) as i32) >> 31) as f32) + 0.5)
) as i32
};
}
const PI: i32 = rconst!(3.14);
const NOT_PI: i32 = rconst!(-1.23);
fn main() {
println!("{:?}", PI as f32 / ONE as f32);
println!("{:?}", NOT_PI as f32 / ONE as f32);
}
Just be aware: every time I tried to add rconst!(0.0)
, the playpen timed out... dunno what's up with that.
Simsys
November 15, 2016, 3:11pm
3
Thank You very much for this solution.
It's much simpler to use an array of two elements:
const CHOICE1: &'static str = "True";
const CHOICE2: &'static str = "False";
const NEG_CONDITION: usize = 0;
const SELECTED: &'static str = [CHOICE1, CHOICE2][NEG_CONDITION];
fn main() {
println!("{}", SELECTED);
}
Except you'd still have to get 0
/1
without using if
... which would be (((($x * (ONE as f32)) as i32) >> 31) + 1) as usize
in this case, and how is that any simpler?