Commit 6f3d6c1f45

LemonBoy <thatlemon@gmail.com>
2020-11-01 18:35:19
std: Fix expectWithinEpsilon with negative values
1 parent 2957433
Changed files (1)
lib
lib/std/testing.zig
@@ -4,6 +4,7 @@
 // The MIT license requires this copyright notice to be included in all copies
 // and substantial portions of the software.
 const std = @import("std.zig");
+const math = std.math;
 const print = std.debug.print;
 
 pub const FailingAllocator = @import("testing/failing_allocator.zig").FailingAllocator;
@@ -198,11 +199,16 @@ pub fn expectWithinMargin(expected: anytype, actual: @TypeOf(expected), margin:
     }
 }
 
-test "expectWithinMargin.f32" {
-    const x: f32 = 12.0;
-    const y: f32 = 12.06;
+test "expectWithinMargin" {
+    inline for ([_]type{ f16, f32, f64, f128 }) |T| {
+        const pos_x: T = 12.0;
+        const pos_y: T = 12.06;
+        const neg_x: T = -12.0;
+        const neg_y: T = -12.06;
 
-    expectWithinMargin(x, y, 0.1);
+        expectWithinMargin(pos_x, pos_y, 0.1);
+        expectWithinMargin(neg_x, neg_y, 0.1);
+    }
 }
 
 /// This function is intended to be used only in tests. When the actual value is not
@@ -212,7 +218,8 @@ test "expectWithinMargin.f32" {
 pub fn expectWithinEpsilon(expected: anytype, actual: @TypeOf(expected), epsilon: @TypeOf(expected)) void {
     std.debug.assert(epsilon >= 0.0 and epsilon <= 1.0);
 
-    const margin = epsilon * expected;
+    // Relative epsilon test.
+    const margin = math.max(math.fabs(expected), math.fabs(actual)) * epsilon;
     switch (@typeInfo(@TypeOf(actual))) {
         .Float,
         .ComptimeFloat,
@@ -225,11 +232,16 @@ pub fn expectWithinEpsilon(expected: anytype, actual: @TypeOf(expected), epsilon
     }
 }
 
-test "expectWithinEpsilon.f32" {
-    const x: f32 = 12.0;
-    const y: f32 = 13.2;
+test "expectWithinEpsilon" {
+    inline for ([_]type{ f16, f32, f64, f128 }) |T| {
+        const pos_x: T = 12.0;
+        const pos_y: T = 13.2;
+        const neg_x: T = -12.0;
+        const neg_y: T = -13.2;
 
-    expectWithinEpsilon(x, y, 0.1);
+        expectWithinEpsilon(pos_x, pos_y, 0.1);
+        expectWithinEpsilon(neg_x, neg_y, 0.1);
+    }
 }
 
 /// This function is intended to be used only in tests. When the two slices are not