From 9b49d8c41882792cb97d6faba646e89eff0d7549 Mon Sep 17 00:00:00 2001 From: Kasper Date: Tue, 3 Jun 2025 01:29:22 +0200 Subject: [PATCH] Remove pow accuracy workaround https://github.com/neogenie/fastnum/issues/28 --- Cargo.lock | 4 ++-- src/evaluator.rs | 2 ++ src/units.rs | 18 +++++------------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index accac65..912322e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,9 +60,9 @@ dependencies = [ [[package]] name = "fastnum" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86cde0c9334bfed5ced962bd7acc266e02e254d71494787e4255d8ec4f7296d4" +checksum = "b875e26379edd7866a74cec720c6ae7bea3107aaf9fd3b14d7449d87d4c1986b" dependencies = [ "autocfg", "bnum", diff --git a/src/evaluator.rs b/src/evaluator.rs index eb17b73..6212469 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -299,6 +299,8 @@ mod tests { assert_eq!(eval_default("-1km to m"), Number::new(d!(-1000), Unit::Meter)); assert_eq!(eval_num("2*-3*0.5"), "-3"); assert_eq!(eval_num("-3^2"), "-9"); + assert_eq!(eval_num("e^2"), "7.3890560989306502272304274605750078132"); + assert_eq!(eval_num("e^2.5"), "12.1824939607034734380701759511679661832"); assert_eq!(eval_num("-1+2"), "1"); } diff --git a/src/units.rs b/src/units.rs index c8fa132..d095cad 100644 --- a/src/units.rs +++ b/src/units.rs @@ -1,4 +1,4 @@ -use fastnum::{dec128 as d, D128, D256}; +use fastnum::{dec128 as d, D128}; use crate::Number; #[derive(Clone, Copy, PartialEq, Debug)] @@ -754,15 +754,6 @@ pub fn modulo(left: Number, right: Number) -> Result { } } -fn do_pow(left: D128, right: D128) -> D128 { - // Do pow with d256 for higher accuracy - let left = D256::try_from(left.transmute()).unwrap(); - let right = D256::try_from(right.transmute()).unwrap(); - let result = left.pow(right); - let result_d128: D128 = result.transmute(); - result_d128 -} - /// Returns a [`Number`] to the power of another [`Number`] /// /// - If you take [`Length`] to the power of [`NoType`], the result has a unit of [`Area`]. @@ -770,20 +761,21 @@ fn do_pow(left: D128, right: D128) -> D128 { /// - If you take [`Length`] to the power of [`Area`], the result has a unit of [`Volume`] /// - etc. pub fn pow(left: Number, right: Number) -> Result { + // I tried converting `right` to use powi, but somehow that was slower let lcat = left.unit.category(); let rcat = left.unit.category(); if left.unit == NoUnit && right.unit == NoUnit { // 3 ^ 2 - Ok(Number::new(do_pow(left.value, right.value), left.unit)) + Ok(Number::new(left.value.pow(right.value), left.unit)) } else if right.value == d!(1) && right.unit == NoUnit { Ok(left) } else if lcat == Length && right.unit == NoUnit && right.value == d!(2) { // x km ^ 2 - let result = do_pow(left.value * left.unit.weight(), right.value); + let result = (left.value * left.unit.weight()).pow(right.value); Ok(to_ideal_unit(Number::new(result, SquareMillimeter))) } else if lcat == Length && right.unit == NoUnit && right.value == d!(3) { // x km ^ 3 - let result = do_pow(left.value * left.unit.weight(), right.value); + let result = (left.value * left.unit.weight()).pow(right.value); Ok(to_ideal_unit(Number::new(result, CubicMillimeter))) } else if lcat == Length && rcat == Length && right.value == d!(1) { // x km ^ 1 km