authorgravatar for madlittlemods@gmail.comEric Eastwood <madlittlemods@gmail.com> 2024-01-06 04:36:47-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-07 22:23:06-08:00
log2115d7d1beeba32f975d8a032e5f5068e96e74f4
treee812f89a245ba353bd2897ca8a98f1781285af82
parentfaeb0ef032cbe941d5593c9e72ebfefaa994f70b

Add approxEqAbs support for comptime_float


1 files changed, 20 insertions(+), 2 deletions(-)

lib/std/math.zig+20-2
...@@ -120,7 +120,7 @@ pub const epsilon = @compileError("Deprecated: use `floatEps` instead");...@@ -120,7 +120,7 @@ pub const epsilon = @compileError("Deprecated: use `floatEps` instead");
120///120///
121/// NaN values are never considered equal to any value.121/// NaN values are never considered equal to any value.
122pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {122pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {
123 assert(@typeInfo(T) == .Float);123 assert(@typeInfo(T) == .Float or @typeInfo(T) == .ComptimeFloat);
124 assert(tolerance >= 0);124 assert(tolerance >= 0);
125125
126 // Fast path for equal values (and signed zeros and infinites).126 // Fast path for equal values (and signed zeros and infinites).
...@@ -148,7 +148,7 @@ pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {...@@ -148,7 +148,7 @@ pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {
148///148///
149/// NaN values are never considered equal to any value.149/// NaN values are never considered equal to any value.
150pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool {150pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool {
151 assert(@typeInfo(T) == .Float);151 assert(@typeInfo(T) == .Float or @typeInfo(T) == .ComptimeFloat);
152 assert(tolerance > 0);152 assert(tolerance > 0);
153153
154 // Fast path for equal values (and signed zeros and infinites).154 // Fast path for equal values (and signed zeros and infinites).
...@@ -184,6 +184,24 @@ test "approxEqAbs and approxEqRel" {...@@ -184,6 +184,24 @@ test "approxEqAbs and approxEqRel" {
184 try testing.expect(approxEqAbs(T, min_value, 0.0, eps_value * 2));184 try testing.expect(approxEqAbs(T, min_value, 0.0, eps_value * 2));
185 try testing.expect(approxEqAbs(T, -min_value, 0.0, eps_value * 2));185 try testing.expect(approxEqAbs(T, -min_value, 0.0, eps_value * 2));
186 }186 }
187
188 comptime {
189 // `comptime_float` is guaranteed to have the same precision and operations of
190 // the largest other floating point type, which is f128 but it doesn't have a
191 // defined layout so we can't rely on `@bitCast` to construct the smallest
192 // possible epsilon value like we do in the tests above. In the same vein, we
193 // also can't represent a max/min, `NaN` or `Inf` values.
194 const eps_value = 1e-4;
195 const sqrt_eps_value = sqrt(eps_value);
196
197 try testing.expect(approxEqAbs(comptime_float, 0.0, 0.0, eps_value));
198 try testing.expect(approxEqAbs(comptime_float, -0.0, -0.0, eps_value));
199 try testing.expect(approxEqAbs(comptime_float, 0.0, -0.0, eps_value));
200 try testing.expect(approxEqRel(comptime_float, 1.0, 1.0, sqrt_eps_value));
201 try testing.expect(!approxEqRel(comptime_float, 1.0, 0.0, sqrt_eps_value));
202 try testing.expect(!approxEqAbs(comptime_float, 1.0 + 2 * eps_value, 1.0, eps_value));
203 try testing.expect(approxEqAbs(comptime_float, 1.0 + 1 * eps_value, 1.0, eps_value));
204 }
187}205}
188206
189pub const doNotOptimizeAway = @compileError("Deprecated: use `std.mem.doNotOptimizeAway` instead");207pub const doNotOptimizeAway = @compileError("Deprecated: use `std.mem.doNotOptimizeAway` instead");