authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2024-11-06 19:33:52-05:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2025-03-03 15:35:07-05:00
log981f84157ce9e37cdc7ea96ea736808b1273142e
tree664763af25eda9e0c9beeddd5eb7a21086205dbf
parentedabcf61927f9699f9b869f304e9aed97f2c4a47

Value: fix comparison of NaN in compareHeteroAdvanaced

Sema: fix equality comparison of signed zeroes and NaN in compareScalar tests: add test coverage for vector float comparisons

3 files changed, 17 insertions(+), 1 deletions(-)

src/Sema.zig+5
...@@ -38137,6 +38137,11 @@ fn compareScalar(...@@ -38137,6 +38137,11 @@ fn compareScalar(
38137 const pt = sema.pt;38137 const pt = sema.pt;
38138 const coerced_lhs = try pt.getCoerced(lhs, ty);38138 const coerced_lhs = try pt.getCoerced(lhs, ty);
38139 const coerced_rhs = try pt.getCoerced(rhs, ty);38139 const coerced_rhs = try pt.getCoerced(rhs, ty);
38140
38141 // Equality comparisons of signed zero and NaN need to use floating point semantics
38142 if (coerced_lhs.isFloat(pt.zcu) or coerced_rhs.isFloat(pt.zcu))
38143 return Value.compareHeteroSema(coerced_lhs, op, coerced_rhs, pt);
38144
38140 switch (op) {38145 switch (op) {
38141 .eq => return sema.valuesEqual(coerced_lhs, coerced_rhs, ty),38146 .eq => return sema.valuesEqual(coerced_lhs, coerced_rhs, ty),
38142 .neq => return !(try sema.valuesEqual(coerced_lhs, coerced_rhs, ty)),38147 .neq => return !(try sema.valuesEqual(coerced_lhs, coerced_rhs, ty)),
src/Value.zig+2
...@@ -1132,6 +1132,8 @@ pub fn compareHeteroAdvanced(...@@ -1132,6 +1132,8 @@ pub fn compareHeteroAdvanced(
1132 else => {},1132 else => {},
1133 }1133 }
1134 }1134 }
1135
1136 if (lhs.isNan(zcu) or rhs.isNan(zcu)) return op == .neq;
1135 return (try orderAdvanced(lhs, rhs, strat, zcu, tid)).compare(op);1137 return (try orderAdvanced(lhs, rhs, strat, zcu, tid)).compare(op);
1136}1138}
11371139
test/behavior/floatop.zig+10-1
...@@ -194,7 +194,7 @@ fn testCmp(comptime T: type) !void {...@@ -194,7 +194,7 @@ fn testCmp(comptime T: type) !void {
194 try expect(x <= 2.0);194 try expect(x <= 2.0);
195 }195 }
196196
197 @setEvalBranchQuota(2_000);197 @setEvalBranchQuota(4_000);
198 var edges = [_]T{198 var edges = [_]T{
199 -math.inf(T),199 -math.inf(T),
200 -math.floatMax(T),200 -math.floatMax(T),
...@@ -210,6 +210,7 @@ fn testCmp(comptime T: type) !void {...@@ -210,6 +210,7 @@ fn testCmp(comptime T: type) !void {
210 };210 };
211 _ = &edges;211 _ = &edges;
212 for (edges, 0..) |rhs, rhs_i| {212 for (edges, 0..) |rhs, rhs_i| {
213 const rhs_v: @Vector(4, T) = @splat(rhs);
213 for (edges, 0..) |lhs, lhs_i| {214 for (edges, 0..) |lhs, lhs_i| {
214 const no_nan = lhs_i != 5 and rhs_i != 5;215 const no_nan = lhs_i != 5 and rhs_i != 5;
215 const lhs_order = if (lhs_i < 5) lhs_i else lhs_i - 2;216 const lhs_order = if (lhs_i < 5) lhs_i else lhs_i - 2;
...@@ -220,6 +221,14 @@ fn testCmp(comptime T: type) !void {...@@ -220,6 +221,14 @@ fn testCmp(comptime T: type) !void {
220 try expect((lhs > rhs) == (no_nan and lhs_order > rhs_order));221 try expect((lhs > rhs) == (no_nan and lhs_order > rhs_order));
221 try expect((lhs <= rhs) == (no_nan and lhs_order <= rhs_order));222 try expect((lhs <= rhs) == (no_nan and lhs_order <= rhs_order));
222 try expect((lhs >= rhs) == (no_nan and lhs_order >= rhs_order));223 try expect((lhs >= rhs) == (no_nan and lhs_order >= rhs_order));
224
225 const lhs_v: @Vector(4, T) = @splat(lhs);
226 try expect(@reduce(.And, (lhs_v == rhs_v)) == (no_nan and lhs_order == rhs_order));
227 try expect(@reduce(.And, (lhs_v != rhs_v)) == !(no_nan and lhs_order == rhs_order));
228 try expect(@reduce(.And, (lhs_v < rhs_v)) == (no_nan and lhs_order < rhs_order));
229 try expect(@reduce(.And, (lhs_v > rhs_v)) == (no_nan and lhs_order > rhs_order));
230 try expect(@reduce(.And, (lhs_v <= rhs_v)) == (no_nan and lhs_order <= rhs_order));
231 try expect(@reduce(.And, (lhs_v >= rhs_v)) == (no_nan and lhs_order >= rhs_order));
223 }232 }
224 }233 }
225}234}