Am I testing it wrong?

Infinity values seem to pass expectApproxEqRel() tests.

test {
  const epsilon = 0.001;
  try std.testing.expectApproxEqRel(42.69, std.math.inf(f32), epsilon);
  try std.testing.expectApproxEqRel(42.69, -std.math.inf(f32), epsilon);
}

Is this a bug? Do I need to check if the number is finite first? But it does not work for comptime_float:

test {
  // error: access of union field 'float' while field 'comptime_float' is active
  try std.testing.expect(std.math.isFinite(42.69));
}
$ zig version
0.15.2

@as(f32, 42.69) to coerce it to f32.

I’m not sure if its a bug that infinity passes. they call std.math.approxEqRel under the hood, its docs state:

Returns true if the absolute difference between them is less or equal than max(|x|, |y|) * tolerance, where tolerance is a positive number greater than zero.

so the real tolerance will be infinity * tolerance which results in infinity.

It abides by the behaviour the docs state. Whether the behaviour should change is a different discussion.

So I have this function that incorrectly returns infinity:

fn half(x: anytype) @TypeOf(x) {
    // return x / 2;
    return std.math.inf(@TypeOf(x));
}

test {
    const epsilon = 0.00000000000001;
    try std.testing.expectApproxEqRel(2.0, half(@as(f32, 4.0)), epsilon);
}

How should I test it? Do I need to do both expectApproxEqRel() and isFinite()? But now I have no way to know if the function works correctly with comptime_float:

test {
    const actual = half(4.0);
    // compilation error
    try std.testing.expect(std.math.isFinite(actual));
}

use the Abs version instead of the Rel version.

1 Like