From 310e0d3a4c498b16ab7f790e99bbf6cf06e87a43 Mon Sep 17 00:00:00 2001 From: clangenb <37865735+clangenb@users.noreply.github.com> Date: Fri, 22 Jan 2021 10:58:59 +0100 Subject: [PATCH] [transcendental] sqrt: change error type from () to &'static str. (#7) * Closes #6: Resolve this by printing an error if an overflow occurs in `sqrt`due to small numbers. * Add test that shows the approximate lower bound of working values for I32F32 * version bump: v0.5.5 --- Cargo.toml | 2 +- src/transcendental.rs | 27 +++++++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ff0f113..09afe60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ [package] name = "substrate-fixed" -version = "0.5.4" +version = "0.5.5" authors = ["Trevor Spiteri "] description = "Fixed-point numbers" documentation = "https://docs.rs/fixed" diff --git a/src/transcendental.rs b/src/transcendental.rs index 15b8764..bfd7a34 100644 --- a/src/transcendental.rs +++ b/src/transcendental.rs @@ -17,7 +17,7 @@ This module contains transcendental functions. */ use crate::consts; use crate::traits::{Fixed, FixedSigned, LossyFrom, ToFixed}; -use crate::types::{I9F23, I9F55, U0F128, U64F64}; +use crate::types::{I9F23, I9F55, U0F128}; use core::ops::{AddAssign, BitOrAssign, ShlAssign}; type ConstType = I9F23; @@ -129,14 +129,14 @@ where } /// square root -pub fn sqrt(operand: S) -> Result +pub fn sqrt(operand: S) -> Result where S: Fixed + PartialOrd, D: Fixed + PartialOrd + From, { let mut invert = false; if operand < ZERO { - return Err(()); + return Err("Can't calculate sqrt from negative numbers."); }; let mut operand = D::from(operand); @@ -148,7 +148,7 @@ where operand = if let Some(r) = D::from_num(1).checked_div(operand) { r } else { - return Err(()); + return Err("Overflow inverting operand."); }; } // Newton iterations @@ -160,7 +160,7 @@ where l = if let Some(r) = D::from_num(1).checked_div(l) { r } else { - return Err(()); + return Err("Overflow un-inverting operand."); }; } Ok(l) @@ -448,7 +448,7 @@ pub fn asin(angle: T) -> T { mod tests { use super::*; use crate::traits::LossyInto; - use crate::types::{I32F32, I64F64}; + use crate::types::{I32F32, I64F64, U64F64}; #[test] fn sqrt_works() { @@ -475,6 +475,21 @@ mod tests { } } + #[test] + fn sqrt_check_lower_bound_of_working_values() { + // Todo: This could be done for other types too. + type S = I32F32; + type D = I32F32; + + // this works + let result: f64 = sqrt::(S::from_num(5.8208e-10)).unwrap().lossy_into(); + assert_relative_eq!(result, 0.0000261, epsilon = 1.0e-6); + + // slightly below lower bound that produces an overflow + let res = sqrt::(S::from_num(5.8205e-10)); + assert_eq!(res.unwrap_err(), "Overflow inverting operand.") + } + #[test] fn rs_works() { let result: f64 = rs(I9F23::from_num(0)).lossy_into();