generic exponent; tests

This commit is contained in:
2025-07-18 21:19:30 +01:00
parent 55c2ebadce
commit f9b8215596
3 changed files with 66 additions and 7 deletions

18
Cargo.lock generated
View File

@@ -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",
]

View File

@@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
num-traits = { version = "0.2.19", default-features = false }

View File

@@ -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)
}
}