FA-91556 / Digital signal filters / Open access
Polyphase interpolator omits the L gain · case 01
The interpolated signal is L times too quiet because zero-stuffing removed energy.
ROOT CAUSE
Outputs are appended without multiplying by L.
VERIFIED REPAIR
Scale every output by L.
Unsuccessful approach: The attempted repair scales only phase 0 outputs.
Case contract
Input [h, L, samples] (integers). Zero-stuff by L and filter with h, scaled by gain L: y[mL + p] = L sum_j h[jL + p] x[m - j]; return len(samples) * L outputs in time order.
Why this case matters
Interpolators feed DACs and sample-rate converters; gain and phase-indexing slips cause level errors and imaging.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
h, L, xs = x
out = []
for m in range(len(xs)):
for p in range(L):
acc = 0
j = 0
while j * L + p < len(h):
if m - j >= 0:
acc += h[j * L + p] * xs[m - j]
j += 1
out.append(acc)
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: impulse L=2', [[1, 2, 3, 4], 2, [1, 0, 0]], [2, 4, 6, 8, 0, 0]], ['regression: partial phase tail', [[1, 2, 3], 2, [1, 1]], [2, 4, 8, 4]], ['regression: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]]], [['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['regression: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]], ['regression: random interpolator 3', [[-3], 4, [2, 2, 4, -3, -2]], [-24, 0, 0, 0, -24, 0, 0, 0, -48, 0, 0, 0, 36, 0, 0, 0, 24, 0, 0, 0]]], [['regression: random interpolator 3', [[-3], 4, [2, 2, 4, -3, -2]], [-24, 0, 0, 0, -24, 0, 0, 0, -48, 0, 0, 0, 36, 0, 0, 0, 24, 0, 0, 0]], ['regression: random interpolator 4', [[-3, 3, 2, -1, 1], 4, [1]], [-12, 12, 8, -4]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]]], [['regression: random interpolator 7', [[-3, 4, -3, -1, -2, -3, -1, 1], 4, [-3, 1, 2, 5, 0]], [36, -48, 36, 12, 12, 52, 0, -16, -32, 20, -28, -4, -76, 56, -68, -12, -40, -60, -20, 20]], ['regression: random interpolator 8', [[0, -2, 3, 3, -2, 4, -3], 3, [4, 2]], [0, -24, 36, 36, -36, 66]], ['regression: random interpolator 4', [[-3, 3, 2, -1, 1], 4, [1]], [-12, 12, 8, -4]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]]], [['regression: random interpolator 10', [[-3, -2, 1], 3, [-4]], [36, 24, -12]], ['regression: random interpolator 11', [[2, 4, -1, -3], 4, [0, -4, 1]], [0, 0, 0, 0, -32, -64, 16, 48, 8, 16, -4, -12]], ['regression: random interpolator 7', [[-3, 4, -3, -1, -2, -3, -1, 1], 4, [-3, 1, 2, 5, 0]], [36, -48, 36, 12, 12, 52, 0, -16, -32, 20, -28, -4, -76, 56, -68, -12, -40, -60, -20, 20]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]], ['regression: random interpolator 3', [[-3], 4, [2, 2, 4, -3, -2]], [-24, 0, 0, 0, -24, 0, 0, 0, -48, 0, 0, 0, 36, 0, 0, 0, 24, 0, 0, 0]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: impulse L=2 | [1, 2, 3, 4, 0, 0] | [2, 4, 6, 8, 0, 0] | Failed |
| regression: partial phase tail | [1, 2, 4, 2] | [2, 4, 8, 4] | Failed |
| regression: L=3 taps 7 | [1, 1, 1, 3, 3, 3] | [3, 3, 3, 9, 9, 9] | Failed |
| control: random interpolator 5 | [0, 0, 0, 0, 0, 0] | [0, 0, 0, 0, 0, 0] | Passed |
| control: random interpolator 36 | [0, 0] | [0, 0] | Passed |
| regression: random interpolator 0 | [-12, 4, 4, -20, -8, 4, -2, -14, -2] | [-36, 12, 12, -60, -24, 12, -6, -42, -6] | Failed |
| regression: random interpolator 1 | [9, -6, 9, -9] | [36, -24, 36, -36] | Failed |
SHA-256 / ba04b62b9655e6b254260694bb2785164f353438b88704d96b8579fd05c61da1
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
h, L, xs = x
out = []
for m in range(len(xs)):
for p in range(L):
acc = 0
j = 0
while j * L + p < len(h):
if m - j >= 0:
acc += h[j * L + p] * xs[m - j]
j += 1
out.append(L * acc if p == 0 else acc)
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: impulse L=2', [[1, 2, 3, 4], 2, [1, 0, 0]], [2, 4, 6, 8, 0, 0]], ['regression: partial phase tail', [[1, 2, 3], 2, [1, 1]], [2, 4, 8, 4]], ['regression: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]]], [['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['regression: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]], ['regression: random interpolator 3', [[-3], 4, [2, 2, 4, -3, -2]], [-24, 0, 0, 0, -24, 0, 0, 0, -48, 0, 0, 0, 36, 0, 0, 0, 24, 0, 0, 0]]], [['regression: random interpolator 3', [[-3], 4, [2, 2, 4, -3, -2]], [-24, 0, 0, 0, -24, 0, 0, 0, -48, 0, 0, 0, 36, 0, 0, 0, 24, 0, 0, 0]], ['regression: random interpolator 4', [[-3, 3, 2, -1, 1], 4, [1]], [-12, 12, 8, -4]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]]], [['regression: random interpolator 7', [[-3, 4, -3, -1, -2, -3, -1, 1], 4, [-3, 1, 2, 5, 0]], [36, -48, 36, 12, 12, 52, 0, -16, -32, 20, -28, -4, -76, 56, -68, -12, -40, -60, -20, 20]], ['regression: random interpolator 8', [[0, -2, 3, 3, -2, 4, -3], 3, [4, 2]], [0, -24, 36, 36, -36, 66]], ['regression: random interpolator 4', [[-3, 3, 2, -1, 1], 4, [1]], [-12, 12, 8, -4]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]]], [['regression: random interpolator 10', [[-3, -2, 1], 3, [-4]], [36, 24, -12]], ['regression: random interpolator 11', [[2, 4, -1, -3], 4, [0, -4, 1]], [0, 0, 0, 0, -32, -64, 16, 48, 8, 16, -4, -12]], ['regression: random interpolator 7', [[-3, 4, -3, -1, -2, -3, -1, 1], 4, [-3, 1, 2, 5, 0]], [36, -48, 36, 12, 12, 52, 0, -16, -32, 20, -28, -4, -76, 56, -68, -12, -40, -60, -20, 20]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]], ['regression: random interpolator 3', [[-3], 4, [2, 2, 4, -3, -2]], [-24, 0, 0, 0, -24, 0, 0, 0, -48, 0, 0, 0, 36, 0, 0, 0, 24, 0, 0, 0]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: impulse L=2 | [2, 2, 6, 4, 0, 0] | [2, 4, 6, 8, 0, 0] | Failed |
| regression: partial phase tail | [2, 2, 8, 2] | [2, 4, 8, 4] | Failed |
| regression: L=3 taps 7 | [3, 1, 1, 9, 3, 3] | [3, 3, 3, 9, 9, 9] | Failed |
| control: random interpolator 5 | [0, 0, 0, 0, 0, 0] | [0, 0, 0, 0, 0, 0] | Passed |
| control: random interpolator 36 | [0, 0] | [0, 0] | Passed |
| regression: random interpolator 0 | [-36, 4, 4, -60, -8, 4, -6, -14, -2] | [-36, 12, 12, -60, -24, 12, -6, -42, -6] | Failed |
| regression: random interpolator 1 | [36, -6, 9, -9] | [36, -24, 36, -36] | Failed |
SHA-256 / 55a07bb0ba18d5a44f857a0ceed0542d3b9df6829355961d86cfb59c55a3b4d2
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
h, L, xs = x
out = []
for m in range(len(xs)):
for p in range(L):
acc = 0
j = 0
while j * L + p < len(h):
if m - j >= 0:
acc += h[j * L + p] * xs[m - j]
j += 1
out.append(L * acc)
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: impulse L=2', [[1, 2, 3, 4], 2, [1, 0, 0]], [2, 4, 6, 8, 0, 0]], ['regression: partial phase tail', [[1, 2, 3], 2, [1, 1]], [2, 4, 8, 4]], ['regression: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]]], [['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['regression: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]], ['regression: random interpolator 3', [[-3], 4, [2, 2, 4, -3, -2]], [-24, 0, 0, 0, -24, 0, 0, 0, -48, 0, 0, 0, 36, 0, 0, 0, 24, 0, 0, 0]]], [['regression: random interpolator 3', [[-3], 4, [2, 2, 4, -3, -2]], [-24, 0, 0, 0, -24, 0, 0, 0, -48, 0, 0, 0, 36, 0, 0, 0, 24, 0, 0, 0]], ['regression: random interpolator 4', [[-3, 3, 2, -1, 1], 4, [1]], [-12, 12, 8, -4]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]]], [['regression: random interpolator 7', [[-3, 4, -3, -1, -2, -3, -1, 1], 4, [-3, 1, 2, 5, 0]], [36, -48, 36, 12, 12, 52, 0, -16, -32, 20, -28, -4, -76, 56, -68, -12, -40, -60, -20, 20]], ['regression: random interpolator 8', [[0, -2, 3, 3, -2, 4, -3], 3, [4, 2]], [0, -24, 36, 36, -36, 66]], ['regression: random interpolator 4', [[-3, 3, 2, -1, 1], 4, [1]], [-12, 12, 8, -4]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]]], [['regression: random interpolator 10', [[-3, -2, 1], 3, [-4]], [36, 24, -12]], ['regression: random interpolator 11', [[2, 4, -1, -3], 4, [0, -4, 1]], [0, 0, 0, 0, -32, -64, 16, 48, 8, 16, -4, -12]], ['regression: random interpolator 7', [[-3, 4, -3, -1, -2, -3, -1, 1], 4, [-3, 1, 2, 5, 0]], [36, -48, 36, 12, 12, 52, 0, -16, -32, 20, -28, -4, -76, 56, -68, -12, -40, -60, -20, 20]], ['control: random interpolator 5', [[0], 3, [2, 0]], [0, 0, 0, 0, 0, 0]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['regression: random interpolator 2', [[-3, -2], 2, [4, 2, -2, 3]], [-24, -16, -12, -8, 12, 8, -18, -12]], ['regression: random interpolator 3', [[-3], 4, [2, 2, 4, -3, -2]], [-24, 0, 0, 0, -24, 0, 0, 0, -48, 0, 0, 0, 36, 0, 0, 0, 24, 0, 0, 0]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: impulse L=2 | [2, 4, 6, 8, 0, 0] | [2, 4, 6, 8, 0, 0] | Passed |
| regression: partial phase tail | [2, 4, 8, 4] | [2, 4, 8, 4] | Passed |
| regression: L=3 taps 7 | [3, 3, 3, 9, 9, 9] | [3, 3, 3, 9, 9, 9] | Passed |
| control: random interpolator 5 | [0, 0, 0, 0, 0, 0] | [0, 0, 0, 0, 0, 0] | Passed |
| control: random interpolator 36 | [0, 0] | [0, 0] | Passed |
| regression: random interpolator 0 | [-36, 12, 12, -60, -24, 12, -6, -42, -6] | [-36, 12, 12, -60, -24, 12, -6, -42, -6] | Passed |
| regression: random interpolator 1 | [36, -24, 36, -36] | [36, -24, 36, -36] | Passed |
SHA-256 / 25e55ba0c2a5331cf010d6f9ef78ee9ea95665bef6b94853cc10a7398deba8dc
Verification & scope
A deterministic bounded teaching model with a stipulated toy contract; exact rational arithmetic or fixed-decimal rounding keeps outputs strict JSON. It is not a production DSP library and claims no standards conformance. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:36.961495+00:00.
Case digest / 64b72caf259d1805b50accbb65ba431cb09b152b48d2c6165e3d5926eff8fcd8