implement Ratio::try_from(f32)
This commit is contained in:
parent
d939fbff94
commit
2f33a28c95
@ -102,6 +102,20 @@ impl Ratio64{
|
|||||||
}
|
}
|
||||||
//from num_traits crate
|
//from num_traits crate
|
||||||
#[inline]
|
#[inline]
|
||||||
|
fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
|
||||||
|
let bits: u32 = f.to_bits();
|
||||||
|
let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
|
||||||
|
let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
|
||||||
|
let mantissa = if exponent == 0 {
|
||||||
|
(bits & 0x7fffff) << 1
|
||||||
|
} else {
|
||||||
|
(bits & 0x7fffff) | 0x800000
|
||||||
|
};
|
||||||
|
// Exponent bias + mantissa shift
|
||||||
|
exponent -= 127 + 23;
|
||||||
|
(mantissa as u64, exponent, sign)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
||||||
let bits: u64 = f.to_bits();
|
let bits: u64 = f.to_bits();
|
||||||
let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
|
let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
|
||||||
@ -116,37 +130,49 @@ fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
|||||||
(mantissa, exponent, sign)
|
(mantissa, exponent, sign)
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Ratio64TryFromFloat64Error{
|
enum Ratio64TryFromFloatError{
|
||||||
Nan,
|
Nan,
|
||||||
Infinite,
|
Infinite,
|
||||||
Subnormal,
|
Subnormal,
|
||||||
HighlyNegativeExponent(i16),
|
HighlyNegativeExponent(i16),
|
||||||
HighlyPositiveExponent(i16),
|
HighlyPositiveExponent(i16),
|
||||||
}
|
}
|
||||||
|
fn ratio64_from_mes((m,e,s):(u64,i16,i8))->Result<Ratio64,Ratio64TryFromFloatError>{
|
||||||
|
if e< -127{
|
||||||
|
//bye bye
|
||||||
|
Err(Ratio64TryFromFloatError::HighlyNegativeExponent(e))
|
||||||
|
}else if e< -63{
|
||||||
|
//TODO
|
||||||
|
Err(Ratio64TryFromFloatError::HighlyNegativeExponent(e))
|
||||||
|
}else if e<0{
|
||||||
|
Ok(Ratio64::new((m as i64)*(s as i64),1<<-e).unwrap())
|
||||||
|
}else if e<62-52{
|
||||||
|
Ok(Ratio64::new((m as i64)*(s as i64)*(1<<e),1).unwrap())
|
||||||
|
}else{
|
||||||
|
Err(Ratio64TryFromFloatError::HighlyPositiveExponent(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl TryFrom<f32> for Ratio64{
|
||||||
|
type Error=Ratio64TryFromFloatError;
|
||||||
|
fn try_from(value:f32)->Result<Self,Self::Error>{
|
||||||
|
match value.classify(){
|
||||||
|
std::num::FpCategory::Nan=>Err(Self::Error::Nan),
|
||||||
|
std::num::FpCategory::Infinite=>Err(Self::Error::Infinite),
|
||||||
|
std::num::FpCategory::Zero=>Ok(Self::ZERO),
|
||||||
|
std::num::FpCategory::Subnormal=>Err(Self::Error::Subnormal),
|
||||||
|
std::num::FpCategory::Normal=>ratio64_from_mes(integer_decode_f32(value)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl TryFrom<f64> for Ratio64{
|
impl TryFrom<f64> for Ratio64{
|
||||||
type Error=Ratio64TryFromFloat64Error;
|
type Error=Ratio64TryFromFloatError;
|
||||||
fn try_from(value:f64)->Result<Self,Self::Error>{
|
fn try_from(value:f64)->Result<Self,Self::Error>{
|
||||||
match value.classify(){
|
match value.classify(){
|
||||||
std::num::FpCategory::Nan=>Err(Self::Error::Nan),
|
std::num::FpCategory::Nan=>Err(Self::Error::Nan),
|
||||||
std::num::FpCategory::Infinite=>Err(Self::Error::Infinite),
|
std::num::FpCategory::Infinite=>Err(Self::Error::Infinite),
|
||||||
std::num::FpCategory::Zero=>Ok(Self::ZERO),
|
std::num::FpCategory::Zero=>Ok(Self::ZERO),
|
||||||
std::num::FpCategory::Subnormal=>Err(Self::Error::Subnormal),
|
std::num::FpCategory::Subnormal=>Err(Self::Error::Subnormal),
|
||||||
std::num::FpCategory::Normal=>{
|
std::num::FpCategory::Normal=>ratio64_from_mes(integer_decode_f64(value)),
|
||||||
let (m,e,s)=integer_decode_f64(value);
|
|
||||||
if e< -127{
|
|
||||||
//bye bye
|
|
||||||
Err(Self::Error::HighlyNegativeExponent(e))
|
|
||||||
}else if e< -63{
|
|
||||||
//TODO
|
|
||||||
Err(Self::Error::HighlyNegativeExponent(e))
|
|
||||||
}else if e<0{
|
|
||||||
Ok(Ratio64::new((m as i64)*(s as i64),1<<-e).unwrap())
|
|
||||||
}else if e<62-52{
|
|
||||||
Ok(Ratio64::new((m as i64)*(s as i64)*(1<<e),1).unwrap())
|
|
||||||
}else{
|
|
||||||
Err(Self::Error::HighlyPositiveExponent(e))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user