generic exponent; tests
This commit is contained in:
54
src/lib.rs
54
src/lib.rs
@@ -1,13 +1,14 @@
|
||||
#![no_std]
|
||||
|
||||
use core::{error::Error, fmt::Display};
|
||||
use num_traits::{one, zero, PrimInt, Unsigned};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Decimal<const S: usize = 5> {
|
||||
pub struct Decimal<const S: usize = 5, E: PrimInt + Unsigned = u16> {
|
||||
pub minus: bool,
|
||||
pub significant: [u8; S],
|
||||
pub minus_exponent: bool,
|
||||
pub exponent: u8,
|
||||
pub exponent: E,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -53,7 +54,7 @@ impl From<f64> for Float {
|
||||
}
|
||||
}
|
||||
|
||||
impl<const S: usize> TryFrom<Float> for Decimal<S> {
|
||||
impl<const S: usize, E: PrimInt + Unsigned> TryFrom<Float> for Decimal<S, E> {
|
||||
type Error = DecimalError;
|
||||
|
||||
fn try_from(val: Float) -> Result<Self, Self::Error> {
|
||||
@@ -65,12 +66,12 @@ impl<const S: usize> TryFrom<Float> for Decimal<S> {
|
||||
if minus {
|
||||
f *= -1.0;
|
||||
}
|
||||
let mut exponent: u8 = 0;
|
||||
let mut exponent: E = zero();
|
||||
let minus_exponent = f < 1.0 && f > 0.0;
|
||||
while f > 10.0 {
|
||||
f /= 10.0;
|
||||
exponent = exponent
|
||||
.checked_add(1u8)
|
||||
.checked_add(&one())
|
||||
.ok_or(DecimalError::ExponentOverflow)?;
|
||||
}
|
||||
while f < 1.0 {
|
||||
@@ -79,7 +80,7 @@ impl<const S: usize> TryFrom<Float> for Decimal<S> {
|
||||
}
|
||||
f *= 10.0;
|
||||
exponent = exponent
|
||||
.checked_add(1u8)
|
||||
.checked_add(&one())
|
||||
.ok_or(DecimalError::ExponentOverflow)?;
|
||||
}
|
||||
let mut significant = [0; S];
|
||||
@@ -183,7 +184,46 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn float_to_decimal_nan() {
|
||||
let err = Decimal::<7>::try_from(Float::from(0.0 / 0.0)).unwrap_err();
|
||||
let err = Decimal::<7>::try_from(Float::from(f64::NAN)).unwrap_err();
|
||||
assert!(matches!(err, DecimalError::NotANumber));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_to_decimal_max() {
|
||||
let dec = Decimal::<7>::try_from(Float::from(f64::MAX)).unwrap();
|
||||
assert!(!dec.minus);
|
||||
assert_eq!(dec.significant, [1, 7, 9, 7, 6, 9, 3]);
|
||||
assert!(!dec.minus_exponent);
|
||||
assert_eq!(dec.exponent, 308)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_to_decimal_max_overflow() {
|
||||
let err = Decimal::<7, u8>::try_from(Float::from(f64::MAX)).unwrap_err();
|
||||
assert!(matches!(err, DecimalError::ExponentOverflow));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_to_decimal_min() {
|
||||
let dec = Decimal::<7>::try_from(Float::from(f64::MIN)).unwrap();
|
||||
assert!(dec.minus);
|
||||
assert_eq!(dec.significant, [1, 7, 9, 7, 6, 9, 3]);
|
||||
assert!(!dec.minus_exponent);
|
||||
assert_eq!(dec.exponent, 308)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_to_decimal_min_overflow() {
|
||||
let err = Decimal::<7, u8>::try_from(Float::from(f64::MIN)).unwrap_err();
|
||||
assert!(matches!(err, DecimalError::ExponentOverflow));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_to_decimal_epsilon() {
|
||||
let dec = Decimal::<7>::try_from(Float::from(f64::EPSILON)).unwrap();
|
||||
assert!(!dec.minus);
|
||||
assert_eq!(dec.significant, [2, 2, 2, 0, 4, 4, 6]);
|
||||
assert!(dec.minus_exponent);
|
||||
assert_eq!(dec.exponent, 16)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user