rust-sen/sehn-serde/src/value/real/sig_exp.rs

125 lines
2.7 KiB
Rust

use super::{
StrInt,
StringInt,
PrimitiveInt,
PrimitiveIntValue
};
pub struct StrSigExp<'a> {
sig: StrInt<'a>,
exp: StrInt<'a>
}
impl<'a> StrSigExp<'a> {
#[inline]
pub fn from_parts(sig: StrInt<'a>, exp: StrInt<'a>) -> Self {
Self {
sig,
exp
}
}
}
impl<'a> From<StrSigExp<'a>> for SigExp {
fn from(raw: StrSigExp<'a>) -> SigExp {
let raw_exp_digits = raw.exp.digits();
if raw_exp_digits.len() <= I16_MAX_DIGITS {
raw_exp_digits
}
if let PrimitiveInt(sig) = PrimitiveInt::from_str_int(raw.sig) {
let raw_exp_digits = raw.exp.digits();
if raw_exp_digits.len() <= I16_MAX_DIGITS {
raw_exp_digits
}
if let PrimitiveInt(exp) = PrimitiveInt::from_str_int() {
SigExp::Fit {
sig,
exp
}
} else {
SigExp::Fat {
sig: raw.sig.to_string_int(),
exp: raw.sig.to_string_int()
}
}
} else {
SigExp::Massive {
sig: raw.sig.to_string_int(),
exp: raw.sig.to_string_int()
}
}
}
}
#[derive(Debug, PartialEq)]
pub enum SigExp {
/// When both `sig` AND `exp` can be
/// represented by fast primitive
/// types without loss of precision.
Fit {
sig: PrimitiveIntValue,
exp: i16
},
/// When `sig` can NOT be represented
/// by a fast primitive type
/// without loss of precision.
Fat {
sig: StringInt,
exp: i16
},
/// When both `sig` OR `exp` can NOT be
/// represented by fast primitive types
/// without loss of precision.
// #[feature(massive_sig_exp)]
Massive {
sig: StringInt,
exp: StringInt
}
}
impl SigExp {
// pub fn is_fit(&self) -> f64 {
// }
// pub fn map_approx_f64(&self) -> f64 {
// match self {
// SigExp::Fit { sig, exp } => {
// }
// }
// }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_str_sig_exp_to_sig_exp_fit() {
let sig_str_int = StrInt::new("+1").unwrap();
let exp_str_int = StrInt::new("+1").unwrap();
let sig_exp = SigExp::from(StrSigExp::from_parts(sig_str_int, exp_str_int));
assert_eq!(sig_exp, SigExp::Fit{sig: 1, exp: 1});
}
#[test]
fn test_str_sig_exp_to_sig_exp_fat() {
let sig_str_int = StrInt::new("+10000000000000000000").unwrap();
let exp_str_int = StrInt::new("+1").unwrap();
let sig_exp = SigExp::from(StrSigExp::from_parts(sig_str_int, exp_str_int));
assert_eq!(sig_exp, SigExp::Fat{sig: sig_str_int.to_string_int(), exp: 1});
}
#[test]
fn test_str_sig_exp_to_sig_exp_massive() {
let sig_str_int = StrInt::new("+10000000000000000000").unwrap();
let exp_str_int = StrInt::new("+10000000000000000000").unwrap();
let sig_exp = SigExp::from(StrSigExp::from_parts(sig_str_int, exp_str_int));
assert_eq!(sig_exp, SigExp::Massive{sig: sig_str_int.to_string_int(), exp: exp_str_int.to_string_int()});
}
}