generic exponent; tests
This commit is contained in:
18
Cargo.lock
generated
18
Cargo.lock
generated
@@ -2,6 +2,24 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "calc-math"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
@@ -4,3 +4,4 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
num-traits = { version = "0.2.19", default-features = false }
|
||||
|
||||
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