This commit is contained in:
2025-07-18 21:19:30 +01:00
parent 028e85b0bf
commit 164c5df92b
3 changed files with 78 additions and 12 deletions

7
Cargo.lock generated
View File

@@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "autocfg"
version = "1.4.0"
@@ -12,6 +18,7 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
name = "calc-math"
version = "0.1.0"
dependencies = [
"arrayvec",
"num-traits",
]

View File

@@ -5,3 +5,6 @@ edition = "2021"
[dependencies]
num-traits = { version = "0.2.19", default-features = false }
[dev-dependencies]
arrayvec = { version = "0.7.6", default-features = false }

View File

@@ -1,10 +1,26 @@
// #![no_std]
#![no_std]
use core::{error::Error, fmt::Display};
#[cfg(not(test))]
use num_traits::float::FloatCore;
use num_traits::{one, zero, PrimInt, Unsigned};
#[derive(Debug)]
pub enum DecimalError {
ExponentOverflow,
NotANumber,
}
impl Error for DecimalError {}
impl Display for DecimalError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
DecimalError::ExponentOverflow => f.write_str("Exponent overflow"),
DecimalError::NotANumber => f.write_str("Not a number"),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Decimal<const S: usize = 5, E = u16> {
pub minus: bool,
@@ -24,19 +40,22 @@ impl<const S: usize, E: PrimInt> Default for Decimal<S, E> {
}
}
#[derive(Debug)]
pub enum DecimalError {
ExponentOverflow,
NotANumber,
}
impl Error for DecimalError {}
impl Display for DecimalError {
impl<const S: usize, E: Display> Display for Decimal<S, E> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
DecimalError::ExponentOverflow => f.write_str("Exponent overflow"),
DecimalError::NotANumber => f.write_str("Not a number"),
if self.minus {
write!(f, "-")?;
}
for i in 0..S {
write!(f, "{}", self.significant[i])?;
if i == 0 {
write!(f, ".")?;
}
}
write!(f, "e")?;
if self.minus_exponent {
write!(f, "-")?;
}
write!(f, "{}", self.exponent)
}
}
@@ -120,6 +139,7 @@ impl<const S: usize, E: PrimInt + Unsigned> TryFrom<Decimal<S, E>> for f64 {
#[cfg(test)]
mod tests {
use super::*;
use arrayvec::ArrayString;
#[test]
fn float_to_decimal_zero() {
@@ -259,4 +279,40 @@ mod tests {
let dec = Decimal::<16>::try_from(f64::MAX).unwrap();
assert_eq!(f64::try_from(dec).unwrap(), f64::MAX);
}
#[test]
fn decimal_display_zero() {
use core::fmt::Write;
let dec = Decimal::<7>::try_from(0.0).unwrap();
let mut str: ArrayString<100> = ArrayString::new();
write!(str, "{}", dec).unwrap();
assert_eq!("0.000000e0", str.as_str());
}
#[test]
fn decimal_display_pos_big() {
use core::fmt::Write;
let dec = Decimal::<7>::try_from(1337.42).unwrap();
let mut str: ArrayString<100> = ArrayString::new();
write!(str, "{}", dec).unwrap();
assert_eq!("1.337420e3", str.as_str());
}
#[test]
fn decimal_display_neg_big() {
use core::fmt::Write;
let dec = Decimal::<7>::try_from(-1337.42).unwrap();
let mut str: ArrayString<100> = ArrayString::new();
write!(str, "{}", dec).unwrap();
assert_eq!("-1.337420e3", str.as_str());
}
#[test]
fn decimal_display_neg_small() {
use core::fmt::Write;
let dec = Decimal::<7>::try_from(-0.0133742).unwrap();
let mut str: ArrayString<100> = ArrayString::new();
write!(str, "{}", dec).unwrap();
assert_eq!("-1.337420e-2", str.as_str());
}
}