Skip to content

Commit e31d6a0

Browse files
Dimitrios AdamDimitrios Adam
authored andcommitted
Print Maximum Absolute and Relative Error
1 parent 88c0a11 commit e31d6a0

File tree

1 file changed

+78
-18
lines changed

1 file changed

+78
-18
lines changed

toolchain/mfc/packer/tol.py

Lines changed: 78 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,46 +22,106 @@ def is_close(error: Error, tolerance: Tolerance) -> bool:
2222
def compare(candidate: Pack, golden: Pack, tol: Tolerance) -> typing.Tuple[Error, str]:
2323
# Keep track of the average error
2424
avg_err = AverageError()
25-
25+
2626
# Compare entry-count
2727
if len(candidate.entries) != len(golden.entries):
2828
return None, "Line count does not match."
29-
29+
3030
# For every entry in the golden's pack
3131
for gFilepath, gEntry in golden.entries.items():
3232
# Find the corresponding entry in the candidate's pack
3333
cEntry = candidate.find(gFilepath)
34-
3534
if cEntry is None:
3635
return None, f"No reference to {gFilepath} in the candidate's pack."
37-
36+
3837
# Compare variable-count
3938
if len(gEntry.doubles) != len(cEntry.doubles):
4039
return None, f"Variable count didn't match for {gFilepath}."
41-
40+
4241
# Check if each variable is within tolerance
4342
for valIndex, (gVal, cVal) in enumerate(zip(gEntry.doubles, cEntry.doubles)):
4443
# Keep track of the error and average errors
4544
error = compute_error(cVal, gVal)
4645
avg_err.push(error)
47-
48-
def raise_err(msg: str):
46+
47+
def raise_err_with_max_diagnostics(msg: str):
48+
# Find maximum errors across ALL files for diagnostics
49+
max_abs_info, max_rel_info = find_maximum_errors(candidate, golden)
50+
51+
diagnostic_msg = ""
52+
if max_abs_info:
53+
max_abs_filepath, max_abs_valIndex, max_abs_gVal, max_abs_cVal, max_abs_error, max_abs_rel_error = max_abs_info
54+
rel_error_str = f"{max_abs_rel_error:.2E}" if not math.isnan(max_abs_rel_error) else "NaN"
55+
diagnostic_msg += f"\n\nDiagnostics - Maximum absolute error across ALL files:\n" \
56+
f" - File: {max_abs_filepath}\n" \
57+
f" - Variable n°{max_abs_valIndex+1}\n" \
58+
f" - Candidate: {max_abs_cVal}\n" \
59+
f" - Golden: {max_abs_gVal}\n" \
60+
f" - Absolute Error: {max_abs_error:.2E}\n" \
61+
f" - Relative Error: {rel_error_str}"
62+
63+
if max_rel_info:
64+
max_rel_filepath, max_rel_valIndex, max_rel_gVal, max_rel_cVal, max_rel_error, max_rel_abs_error = max_rel_info
65+
diagnostic_msg += f"\n\nDiagnostics - Maximum relative error across ALL files:\n" \
66+
f" - File: {max_rel_filepath}\n" \
67+
f" - Variable n°{max_rel_valIndex+1}\n" \
68+
f" - Candidate: {max_rel_cVal}\n" \
69+
f" - Golden: {max_rel_gVal}\n" \
70+
f" - Relative Error: {max_rel_error:.2E}\n" \
71+
f" - Absolute Error: {max_rel_abs_error:.2E}"
72+
4973
return None, f"""\
5074
Variable n°{valIndex+1} (1-indexed) in {gFilepath} {msg}:
51-
- Candidate: {cVal}
52-
- Golden: {gVal}
53-
- Error: {error}
54-
- Tolerance: {tol}
75+
- Candidate: {cVal}
76+
- Golden: {gVal}
77+
- Error: {error}
78+
- Tolerance: {tol}{diagnostic_msg}
5579
"""
56-
80+
5781
if math.isnan(gVal):
58-
return raise_err("is NaN in the golden file")
59-
82+
return raise_err_with_max_diagnostics("is NaN in the golden file")
6083
if math.isnan(cVal):
61-
return raise_err("is NaN in the pack file")
62-
84+
return raise_err_with_max_diagnostics("is NaN in the pack file")
6385
if not is_close(error, tol):
64-
return raise_err("is not within tolerance")
65-
86+
return raise_err_with_max_diagnostics("is not within tolerance")
87+
6688
# Return the average relative error
6789
return avg_err.get(), None
90+
91+
92+
def find_maximum_errors(candidate: Pack, golden: Pack) -> typing.Tuple[typing.Optional[typing.Tuple[str, int, float, float, float, float]], typing.Optional[typing.Tuple[str, int, float, float, float, float]]]:
93+
"""
94+
Scan all files to find the maximum absolute and relative errors.
95+
Returns tuple of:
96+
- max_abs_info: (filepath, var_index, golden_val, candidate_val, absolute_error, relative_error)
97+
- max_rel_info: (filepath, var_index, golden_val, candidate_val, relative_error, absolute_error)
98+
"""
99+
max_abs_error = -1.0
100+
max_abs_info = None
101+
102+
max_rel_error = -1.0
103+
max_rel_info = None
104+
105+
for gFilepath, gEntry in golden.entries.items():
106+
cEntry = candidate.find(gFilepath)
107+
if cEntry is None:
108+
continue
109+
110+
for valIndex, (gVal, cVal) in enumerate(zip(gEntry.doubles, cEntry.doubles)):
111+
# Skip NaN values in golden or candidate
112+
if math.isnan(gVal) or math.isnan(cVal):
113+
continue
114+
115+
error = compute_error(cVal, gVal)
116+
117+
# Track maximum absolute error
118+
if error.absolute > max_abs_error:
119+
max_abs_error = error.absolute
120+
max_abs_info = (gFilepath, valIndex, gVal, cVal, error.absolute, error.relative)
121+
122+
# Track maximum relative error (only if it's not NaN)
123+
if not math.isnan(error.relative) and error.relative > max_rel_error:
124+
max_rel_error = error.relative
125+
max_rel_info = (gFilepath, valIndex, gVal, cVal, error.relative, error.absolute)
126+
127+
return max_abs_info, max_rel_info

0 commit comments

Comments
 (0)