From fcbd4ae5f0180f9cc8efe472ce278c69c59a61f7 Mon Sep 17 00:00:00 2001 From: Nail Sharipov Date: Fri, 19 Jun 2026 21:25:52 +0300 Subject: [PATCH 1/3] add four --- src/float/number.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/float/number.rs b/src/float/number.rs index 0bee7af..425b25c 100644 --- a/src/float/number.rs +++ b/src/float/number.rs @@ -21,6 +21,7 @@ where const ONE: Self; const TWO: Self; const THREE: Self; + const FOUR: Self; const HALF: Self; // Construction. @@ -66,6 +67,7 @@ impl FloatNumber for f32 { const ONE: Self = 1.0; const TWO: Self = 2.0; const THREE: Self = 3.0; + const FOUR: Self = 4.0; const HALF: Self = 0.5; // Construction. @@ -216,6 +218,7 @@ impl FloatNumber for f64 { const ONE: Self = 1.0; const TWO: Self = 2.0; const THREE: Self = 3.0; + const FOUR: Self = 4.0; const HALF: Self = 0.5; // Construction. #[inline(always)] From e8d7e9e57a310f6e5d20569ef01a8b97851be76a Mon Sep 17 00:00:00 2001 From: Nail Sharipov Date: Tue, 7 Jul 2026 17:19:50 +0300 Subject: [PATCH 2/3] add is_finite api --- Cargo.toml | 2 +- src/adapter.rs | 30 ++++++++++++++++++++++-------- src/float/compatible.rs | 12 ++++++++++++ src/float/number.rs | 11 +++++++++++ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 513aa15..e0efbc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "i_float" -version = "3.0.0" +version = "4.0.0" authors = ["Nail Sharipov "] edition = "2024" description = "This fixed float math library provides an efficient and deterministic solution for arithmetic and geometric operations." diff --git a/src/adapter.rs b/src/adapter.rs index 2a3cde1..b929e34 100644 --- a/src/adapter.rs +++ b/src/adapter.rs @@ -115,7 +115,7 @@ impl FloatPointAdapter { rect: FloatRect, scale: P::Scalar, ) -> Result { - let scale_f64 = Self::validate_scale(scale)?; + let scale = Self::validate_scale(scale)?; let mut adapter = Self::new(rect); let zero = P::Scalar::ZERO; @@ -125,7 +125,7 @@ impl FloatPointAdapter { } adapter.dir_scale = scale; - adapter.inv_scale = P::Scalar::from_float(1.0 / scale_f64); + adapter.inv_scale = P::Scalar::ONE / scale; Ok(adapter) } @@ -157,15 +157,14 @@ impl FloatPointAdapter { } #[inline] - fn validate_scale(scale: P::Scalar) -> Result { - let scale_f64 = scale.to_f64(); - if !scale_f64.is_finite() { + fn validate_scale(scale: P::Scalar) -> Result { + if !scale.is_finite() { return Err(FloatPointAdapterScaleError::ScaleNotFinite); } - if scale_f64 <= 0.0 { + if scale <= P::Scalar::ZERO { return Err(FloatPointAdapterScaleError::ScaleNonPositive); } - Ok(scale_f64) + Ok(scale) } #[inline(always)] @@ -248,7 +247,7 @@ impl FloatPointAdapter { #[inline(always)] pub fn try_float_to_int(&self, point: &P) -> Result, FloatPointAdapterRangeError> { - if !self.rect.contains(point) { + if !point.is_finite() || !self.rect.contains(point) { return Err(FloatPointAdapterRangeError::PointOutOfRange); } @@ -444,6 +443,21 @@ mod tests { ); } + #[test] + fn test_try_float_to_int_not_finite() { + let adapter = + FloatPointAdapter::<[f64; 2], i32>::with_scale(FloatRect::new(-1.0, 1.0, -1.0, 1.0), 10.0); + + assert_eq!( + adapter.try_float_to_int(&[f64::NAN, 0.0]).err().unwrap(), + FloatPointAdapterRangeError::PointOutOfRange + ); + assert_eq!( + adapter.try_float_to_int(&[0.0, f64::INFINITY]).err().unwrap(), + FloatPointAdapterRangeError::PointOutOfRange + ); + } + #[test] fn test_try_int_to_float_range() { let adapter = diff --git a/src/float/compatible.rs b/src/float/compatible.rs index dfbd0e1..1889060 100644 --- a/src/float/compatible.rs +++ b/src/float/compatible.rs @@ -5,6 +5,11 @@ pub trait FloatPointCompatible: Copy { fn from_xy(x: Self::Scalar, y: Self::Scalar) -> Self; fn x(&self) -> Self::Scalar; fn y(&self) -> Self::Scalar; + + #[inline(always)] + fn is_finite(&self) -> bool { + self.x().is_finite() && self.y().is_finite() + } } impl FloatPointCompatible for [T; 2] { @@ -39,4 +44,11 @@ mod tests { assert_eq!(a0, a1); } + + #[test] + fn test_is_finite() { + assert!([2.0, 5.0].is_finite()); + assert!(![f64::NAN, 5.0].is_finite()); + assert!(![2.0, f64::INFINITY].is_finite()); + } } diff --git a/src/float/number.rs b/src/float/number.rs index 425b25c..6320397 100644 --- a/src/float/number.rs +++ b/src/float/number.rs @@ -43,6 +43,7 @@ where fn acos(self) -> Self; fn asin(self) -> Self; fn signum(self) -> Self; + fn is_finite(self) -> bool; // Truncating casts. fn to_i16(self) -> i16; fn to_i32(self) -> i32; @@ -152,6 +153,11 @@ impl FloatNumber for f32 { self.signum() } + #[inline(always)] + fn is_finite(self) -> bool { + self.is_finite() + } + // Truncating casts. #[inline(always)] fn to_i16(self) -> i16 { @@ -302,6 +308,11 @@ impl FloatNumber for f64 { self.signum() } + #[inline(always)] + fn is_finite(self) -> bool { + self.is_finite() + } + // Truncating casts. #[inline(always)] fn to_i16(self) -> i16 { From 62f7ec30d4666f77a8494dd218bf64016d684bc8 Mon Sep 17 00:00:00 2001 From: Nail Sharipov Date: Tue, 7 Jul 2026 17:23:43 +0300 Subject: [PATCH 3/3] zero fix --- src/adapter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapter.rs b/src/adapter.rs index b929e34..7a130e4 100644 --- a/src/adapter.rs +++ b/src/adapter.rs @@ -118,8 +118,8 @@ impl FloatPointAdapter { let scale = Self::validate_scale(scale)?; let mut adapter = Self::new(rect); - let zero = P::Scalar::ZERO; - let is_degenerate = adapter.rect.width() == zero && adapter.rect.height() == zero; + let is_degenerate = + adapter.rect.width() == P::Scalar::ZERO && adapter.rect.height() == P::Scalar::ZERO; if !is_degenerate && adapter.dir_scale < scale { return Err(FloatPointAdapterScaleError::ScaleTooLarge); }