Fix dynamic fractional masking formula
This is the result of testing CoPilot CLI (took around 3% of premium requests).
Fix dynamic fractional masking formula (Σ(w) ≠ 1 case)
Closes #168 (closed)
Problem
When dynamic fractional masking is used with explicit interpolation weights, the formula
F_t = \frac{\sum_i F_{s,i} \cdot f_i \cdot w_i}{\sum_i f_i \cdot w_i}
produces incorrect results whenever \sum_i w_i \neq 1. The most visible symptom: when all fractional mask values are 1 (all sources fully valid), the formula reduces to
F_t = \frac{\sum_i F_{s,i} \cdot w_i}{\sum_i w_i}
instead of the expected F_t = \sum_i F_{s,i} \cdot w_i, silently rescaling the interpolation result. This affects:
- Conservative interpolation at boundary cells — partial source coverage means \sum_i w_i < 1, so the formula inflates the result relative to the no-mask case.
- Any interpolation method whose weights are not pre-normalised to sum to 1.
Fix
Multiply the result by s = \sum_i w_i:
F_t = \frac{\sum_i F_{s,i} \cdot f_i \cdot w_i}{\sum_i f_i \cdot w_i} \cdot \sum_i w_i
When all f_i = 1: \sum_i f_i w_i = \sum_i w_i = s, so
F_t = \sum_i F_{s,i} w_i — identical to the no-mask result for any
\sum_i w_i. This formula was already used in
tests/mci/test_dummy_coupling_raw_c.c as the reference, which
motivated the issue.
The fix applies only to the explicit-weights path (weights != NULL
in compute_tgt_field_wgt). The unweighted path (implicit w = 1 per
source, used for NNN-style fractional averaging) has different semantics
and is left unchanged.
Changes
| File | Description |
|---|---|
src/core/interpolation/interpolation_utils.h |
Split COMPUTE_TGT_FIELD_WGT_FRAC_ into FRAC_W_ (explicit weights, new formula with weight_sum tracking) and FRAC_NW_ (unweighted, old formula); update dispatcher |
tests/core/interpolation/test_interpolation_parallel6.c |
Update ref_tgt_data_raw[1] entries for tgt 5, 8, 10 (where \sum w_i \neq \sum f_i w_i) in both MVP-at-src and MVP-at-tgt frac test blocks |
tests/core/interpolation/test_interp_weights_parallel.c |
Update apply_interp_weights_data() reference to accumulate weight_sum and apply the corrected formula |
doc/src/fractional_mask.dox |
Update formula to include s = \sum_i w_i; add explanatory note on the all-ones frac case; update worked examples; remove outdated remark that frac masking only makes sense when weights sum to 1 |
doc/src/version_info.dox |
Add release note entry under Version 3.15.0 |
Testing
tests/mci/test_dummy_coupling_raw_c.c already used the correct
formula and required no changes — it serves as confirmation that the
new behaviour is consistent with the existing raw-exchange reference.
Checklist
- All code changes are covered by unit tests
- Code coverage did not deteriorate
- Code follows Style Guide
- Documentation updated, if necessary
- WIP: Manual running of configure/build jobs was successful
-
Update version info, if changes are worth mentioning
(
Developsection indoc/src/version_info.dox, add section if not yet included)