-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal for a public BigFloat::to_f64
#11
Comments
Yes, please, feel free to make this change. The reason why this function is only crate-public is exactly because it requires proper rounding and transition to subnormal. I would though consider the following signature for the function: |
I would also find such feature very usefull. For those who would need a workaround, below a snippet slightly adapted from the code mentioned above. use astro_float::{BigFloat, RoundingMode, Sign};
fn to_f64(big_float: &BigFloat, rounding_mode: RoundingMode) -> f64 {
let mut big_float = big_float.clone();
big_float.set_precision(64, rounding_mode).unwrap();
let sign = big_float.sign().unwrap();
let exponent = big_float.exponent().unwrap();
let mantissa = big_float.mantissa_digits().unwrap()[0];
if mantissa == 0 {
return 0.0;
}
let mut exponent: isize = exponent as isize + 0b1111111111;
let mut ret = 0;
if exponent >= 0b11111111111 {
match sign {
Sign::Pos => f64::INFINITY,
Sign::Neg => f64::NEG_INFINITY,
}
} else if exponent <= 0 {
let shift = -exponent;
if shift < 52 {
ret |= mantissa >> (shift + 12);
if sign == Sign::Neg {
ret |= 0x8000000000000000u64;
}
f64::from_bits(ret)
} else {
0.0
}
} else {
let mantissa = mantissa << 1;
exponent -= 1;
if sign == Sign::Neg {
ret |= 1;
}
ret <<= 11;
ret |= exponent as u64;
ret <<= 52;
ret |= mantissa >> 12;
f64::from_bits(ret)
}
} |
Actually it would be nice to have conversion for all primitives with similar behaviour as when using the impl From<BigFloat> for u64 {
fn from(value: BigFloat) -> u64 {
let sign = value.sign().unwrap();
let exponent = value.exponent().unwrap();
let mantissa = value.mantissa_digits().unwrap()[0];
match sign {
Sign::Pos => {
if exponent > 0 {
if exponent <= 64 {
let shift = (64 - exponent) as u64;
let ret = mantissa;
ret >> shift
} else {
u64::MAX
}
} else {
0
}
}
Sign::Neg => 0,
}
}
} |
Agreed that some generic way could be nice here, but I don't know if let a: f32 = 10.0f64.into(); I still think that generics are a good idea, since if we are lucky we will have impl BigFloat {
fn as_float<T: Float>(&self, rounding_mode: RoundingMode) -> T;
} |
Yes you are right using the From/Into for something that is not perfectly converted wouldn't follow rust idioms. if we can have a |
BTW: The solution I posted above only work for 64 bits architecture, I'm sure you know better than I how to fix this. Hopefully I won't encounter users that still very old computers :) (though if we can have an official well tested functions that would be better). |
Regarding implementing conversion to primitive integer types, do you have actual use cases for it? Issues that I can think of: what would be the behavior if the value exceeds the maximum allowed value for the primitive type? Return error and let client code decide, or clamp to max value? With clamping you can encounter situation when you want to know if it was clamped, and have a way to determine it somehow? Seems like a good idea to have, for example, both kinds of functions: the one that returns error and the other is saturating, e.g. |
New issue #28 has been opened. Please use it for further discussion. |
I have a use case where I need to go back and forth between
BigFloat
andf64
.fn to_f64(&self) -> f64
would be perfect.For context there is an existing pub(crate) implementation.
astro-float/astro-float-num/src/num.rs
Line 795 in 00d5150
I would like to propose cleaning up this method and tweak it to follow Rust's convention with casting between
f32
andf64
. According to the nomiconHere the same rules can be followed.
f64
(includes subnormals)I am open to working on this contribution.
The text was updated successfully, but these errors were encountered: