Skip to content

Commit 65eb598

Browse files
DimAdam-01Dimitrios Adamsbryngelson
authored
Improved error reporting for failed tolerance checks (#988)
Co-authored-by: Dimitrios Adam <[email protected]> Co-authored-by: Spencer Bryngelson <[email protected]> Co-authored-by: Spencer Bryngelson <[email protected]>
1 parent e966781 commit 65eb598

File tree

1 file changed

+81
-7
lines changed

1 file changed

+81
-7
lines changed

toolchain/mfc/packer/tol.py

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,34 @@ def is_close(error: Error, tolerance: Tolerance) -> bool:
1818
return False
1919

2020

21+
def _format_error_diagnostics(max_abs_info, max_rel_info) -> str:
22+
"""Format diagnostic information for maximum errors among failing variables."""
23+
diagnostic_msg = ""
24+
25+
if max_abs_info:
26+
filepath, val_idx, g_val, c_val, abs_err, rel_err = max_abs_info
27+
rel_error_str = f"{rel_err:.2E}" if not math.isnan(rel_err) else "NaN"
28+
diagnostic_msg += f"\n\nDiagnostics - Maximum absolute error among FAILING variables:\n" \
29+
f" - File: {filepath}\n" \
30+
f" - Variable n°{val_idx+1}\n" \
31+
f" - Candidate: {c_val}\n" \
32+
f" - Golden: {g_val}\n" \
33+
f" - Absolute Error: {abs_err:.2E}\n" \
34+
f" - Relative Error: {rel_error_str}"
35+
36+
if max_rel_info:
37+
filepath, val_idx, g_val, c_val, rel_err, abs_err = max_rel_info
38+
diagnostic_msg += f"\n\nDiagnostics - Maximum relative error among FAILING variables:\n" \
39+
f" - File: {filepath}\n" \
40+
f" - Variable n°{val_idx+1}\n" \
41+
f" - Candidate: {c_val}\n" \
42+
f" - Golden: {g_val}\n" \
43+
f" - Relative Error: {rel_err:.2E}\n" \
44+
f" - Absolute Error: {abs_err:.2E}"
45+
46+
return diagnostic_msg
47+
48+
2149
# pylint: disable=too-many-return-statements
2250
def compare(candidate: Pack, golden: Pack, tol: Tolerance) -> typing.Tuple[Error, str]:
2351
# Keep track of the average error
@@ -45,23 +73,69 @@ def compare(candidate: Pack, golden: Pack, tol: Tolerance) -> typing.Tuple[Error
4573
error = compute_error(cVal, gVal)
4674
avg_err.push(error)
4775

48-
def raise_err(msg: str):
76+
def raise_err_with_failing_diagnostics(msg: str):
77+
# Find maximum errors among FAILING variables only
78+
max_abs_info, max_rel_info = find_maximum_errors_among_failing(candidate, golden, tol)
79+
diagnostic_msg = _format_error_diagnostics(max_abs_info, max_rel_info)
80+
4981
return None, f"""\
5082
Variable n°{valIndex+1} (1-indexed) in {gFilepath} {msg}:
5183
- Candidate: {cVal}
5284
- Golden: {gVal}
5385
- Error: {error}
54-
- Tolerance: {tol}
86+
- Tolerance: {tol}{diagnostic_msg}
5587
"""
5688

5789
if math.isnan(gVal):
58-
return raise_err("is NaN in the golden file")
59-
90+
return raise_err_with_failing_diagnostics("is NaN in the golden file")
6091
if math.isnan(cVal):
61-
return raise_err("is NaN in the pack file")
62-
92+
return raise_err_with_failing_diagnostics("is NaN in the pack file")
6393
if not is_close(error, tol):
64-
return raise_err("is not within tolerance")
94+
return raise_err_with_failing_diagnostics("is not within tolerance")
6595

6696
# Return the average relative error
6797
return avg_err.get(), None
98+
99+
100+
def find_maximum_errors_among_failing(candidate: Pack, golden: Pack, tol: Tolerance) -> typing.Tuple[typing.Optional[typing.Tuple[str, int, float, float, float, float]], typing.Optional[typing.Tuple[str, int, float, float, float, float]]]:
101+
"""
102+
Scan all files to find the maximum absolute and relative errors among FAILING variables only.
103+
A variable fails if is_close(error, tol) returns False.
104+
105+
Returns tuple of:
106+
- max_abs_info: (filepath, var_index, golden_val, candidate_val, absolute_error, relative_error)
107+
- max_rel_info: (filepath, var_index, golden_val, candidate_val, relative_error, absolute_error)
108+
"""
109+
max_abs_error = -1.0
110+
max_abs_info = None
111+
112+
max_rel_error = -1.0
113+
max_rel_info = None
114+
115+
for gFilepath, gEntry in golden.entries.items():
116+
cEntry = candidate.find(gFilepath)
117+
if cEntry is None:
118+
continue
119+
120+
for valIndex, (gVal, cVal) in enumerate(zip(gEntry.doubles, cEntry.doubles)):
121+
# Skip NaN values in golden or candidate
122+
if math.isnan(gVal) or math.isnan(cVal):
123+
continue
124+
125+
error = compute_error(cVal, gVal)
126+
127+
# Only consider variables that FAIL tolerance
128+
if is_close(error, tol):
129+
continue # Skip variables that pass tolerance
130+
131+
# Track maximum absolute error among failing variables
132+
if error.absolute > max_abs_error:
133+
max_abs_error = error.absolute
134+
max_abs_info = (gFilepath, valIndex, gVal, cVal, error.absolute, error.relative)
135+
136+
# Track maximum relative error among failing variables (only if it's not NaN)
137+
if not math.isnan(error.relative) and error.relative > max_rel_error:
138+
max_rel_error = error.relative
139+
max_rel_info = (gFilepath, valIndex, gVal, cVal, error.relative, error.absolute)
140+
141+
return max_abs_info, max_rel_info

0 commit comments

Comments
 (0)