| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | // The MIT license requires this copyright notice to be included in all copies | 4 | // The MIT license requires this copyright notice to be included in all copies |
| 5 | // and substantial portions of the software. | 5 | // and substantial portions of the software. |
| 6 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| | 7 | const math = std.math; |
| 7 | const print = std.debug.print; | 8 | const print = std.debug.print; |
| 8 | | 9 | |
| 9 | pub const FailingAllocator = @import("testing/failing_allocator.zig").FailingAllocator; | 10 | pub const FailingAllocator = @import("testing/failing_allocator.zig").FailingAllocator; |
| ... | @@ -198,11 +199,16 @@ pub fn expectWithinMargin(expected: anytype, actual: @TypeOf(expected), margin: | ... | @@ -198,11 +199,16 @@ pub fn expectWithinMargin(expected: anytype, actual: @TypeOf(expected), margin: |
| 198 | } | 199 | } |
| 199 | } | 200 | } |
| 200 | | 201 | |
| 201 | test "expectWithinMargin.f32" { | 202 | test "expectWithinMargin" { |
| 202 | const x: f32 = 12.0; | 203 | inline for ([_]type{ f16, f32, f64, f128 }) |T| { |
| 203 | const y: f32 = 12.06; | 204 | const pos_x: T = 12.0; |
| | 205 | const pos_y: T = 12.06; |
| | 206 | const neg_x: T = -12.0; |
| | 207 | const neg_y: T = -12.06; |
| 204 | | 208 | |
| 205 | expectWithinMargin(x, y, 0.1); | 209 | expectWithinMargin(pos_x, pos_y, 0.1); |
| | 210 | expectWithinMargin(neg_x, neg_y, 0.1); |
| | 211 | } |
| 206 | } | 212 | } |
| 207 | | 213 | |
| 208 | /// This function is intended to be used only in tests. When the actual value is not | 214 | /// This function is intended to be used only in tests. When the actual value is not |
| ... | @@ -212,7 +218,8 @@ test "expectWithinMargin.f32" { | ... | @@ -212,7 +218,8 @@ test "expectWithinMargin.f32" { |
| 212 | pub fn expectWithinEpsilon(expected: anytype, actual: @TypeOf(expected), epsilon: @TypeOf(expected)) void { | 218 | pub fn expectWithinEpsilon(expected: anytype, actual: @TypeOf(expected), epsilon: @TypeOf(expected)) void { |
| 213 | std.debug.assert(epsilon >= 0.0 and epsilon <= 1.0); | 219 | std.debug.assert(epsilon >= 0.0 and epsilon <= 1.0); |
| 214 | | 220 | |
| 215 | const margin = epsilon * expected; | 221 | // Relative epsilon test. |
| | 222 | const margin = math.max(math.fabs(expected), math.fabs(actual)) * epsilon; |
| 216 | switch (@typeInfo(@TypeOf(actual))) { | 223 | switch (@typeInfo(@TypeOf(actual))) { |
| 217 | .Float, | 224 | .Float, |
| 218 | .ComptimeFloat, | 225 | .ComptimeFloat, |
| ... | @@ -225,11 +232,16 @@ pub fn expectWithinEpsilon(expected: anytype, actual: @TypeOf(expected), epsilon | ... | @@ -225,11 +232,16 @@ pub fn expectWithinEpsilon(expected: anytype, actual: @TypeOf(expected), epsilon |
| 225 | } | 232 | } |
| 226 | } | 233 | } |
| 227 | | 234 | |
| 228 | test "expectWithinEpsilon.f32" { | 235 | test "expectWithinEpsilon" { |
| 229 | const x: f32 = 12.0; | 236 | inline for ([_]type{ f16, f32, f64, f128 }) |T| { |
| 230 | const y: f32 = 13.2; | 237 | const pos_x: T = 12.0; |
| | 238 | const pos_y: T = 13.2; |
| | 239 | const neg_x: T = -12.0; |
| | 240 | const neg_y: T = -13.2; |
| 231 | | 241 | |
| 232 | expectWithinEpsilon(x, y, 0.1); | 242 | expectWithinEpsilon(pos_x, pos_y, 0.1); |
| | 243 | expectWithinEpsilon(neg_x, neg_y, 0.1); |
| | 244 | } |
| 233 | } | 245 | } |
| 234 | | 246 | |
| 235 | /// This function is intended to be used only in tests. When the two slices are not | 247 | /// This function is intended to be used only in tests. When the two slices are not |