1use core::ops::Sub;
7#[cfg(not(feature = "std"))]
8use peniko::kurbo::common::FloatFuncs as _;
9
10#[inline]
12pub(crate) fn snap_up(value: f64, step: u16) -> f64 {
13 let step = f64::from(step);
14 (value / step).ceil() * step
15}
16
17pub fn compute_erf7(x: f32) -> f32 {
21 let x = x.clamp(-10., 10.);
25 let x = x * core::f32::consts::FRAC_2_SQRT_PI;
26 let xx = x * x;
27 let x = x + (0.24295 + (0.03395 + 0.0104 * xx) * xx) * (x * xx);
28 x / (1.0 + x * x).sqrt()
29}
30
31const SCALAR_NEARLY_ZERO: f32 = 1.0 / (1 << 12) as f32;
35
36pub trait FloatExt: Sized + Sub<Self, Output = Self> {
38 fn is_nearly_zero(&self) -> bool;
40
41 fn is_nearly_zero_within_tolerance(&self, tolerance: f32) -> bool;
43}
44
45impl FloatExt for f32 {
46 fn is_nearly_zero(&self) -> bool {
47 self.is_nearly_zero_within_tolerance(SCALAR_NEARLY_ZERO)
48 }
49
50 fn is_nearly_zero_within_tolerance(&self, tolerance: f32) -> bool {
51 debug_assert!(tolerance >= 0.0, "tolerance must be positive");
52
53 self.abs() <= tolerance
54 }
55}
56
57impl FloatExt for f64 {
58 fn is_nearly_zero(&self) -> bool {
59 self.is_nearly_zero_within_tolerance(SCALAR_NEARLY_ZERO)
60 }
61
62 fn is_nearly_zero_within_tolerance(&self, tolerance: f32) -> bool {
63 debug_assert!(tolerance >= 0.0, "tolerance must be positive");
64
65 self.abs() <= tolerance as Self
66 }
67}