FAILURE MAP
← Case archive

FA-91566 / Digital signal filters / Open access

Polyphase interpolator drops trailing taps of shorter phases · case 01

When the filter length is not a multiple of L the last taps are never applied.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

Each branch iterates j < len(h) // L instead of while jL + p < len(h).

VERIFIED REPAIR

Iterate while j L + p < len(h).

Unsuccessful approach: The attempted repair stops one tap before the end of the filter.

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 < len(h) // L:
                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: partial phase tail', [[1, 2, 3], 2, [1, 1]], [2, 4, 8, 4]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['repair check: impulse L=2', [[1, 2, 3, 4], 2, [1, 0, 0]], [2, 4, 6, 8, 0, 0]], ['control: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['control: 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]]], [['regression: random interpolator 9', [[-2, 4], 3, [-1, -1]], [6, -12, 0, 6, -12, 0]], ['regression: random interpolator 12', [[3, -1], 4, [1, 4, -2]], [12, -4, 0, 0, 48, -16, 0, 0, -24, 8, 0, 0]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['control: random interpolator 8', [[0, -2, 3, 3, -2, 4, -3], 3, [4, 2]], [0, -24, 36, 36, -36, 66]], ['control: random interpolator 17', [[4, 4, 3, 1, -3, 2, 1], 4, [4]], [64, 64, 48, 16]], ['control: random interpolator 21', [[2, -3, 0], 3, [-4, 3, 2, -2, -2]], [-24, 36, 0, 18, -27, 0, 12, -18, 0, -12, 18, 0, -12, 18, 0]], ['control: random interpolator 23', [[3, 2, 1, -1, 3, -1], 2, [-3, -1]], [-18, -12, -12, 2]]], [['regression: random interpolator 14', [[4, -1, 3, -1, 0, -2, 4], 3, [1, 3, 5]], [12, -3, 9, 33, -9, 21, 63, -15, 27]], ['regression: random interpolator 15', [[4, 2, 3], 2, [-2, -2, 2, 0, -1]], [-16, -8, -28, -8, 4, 8, 12, 0, -8, -4]], ['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]], ['control: random interpolator 24', [[-2, -1, 3, 0, -2, -2, 2], 2, [-2]], [8, 4]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['control: random interpolator 44', [[-2, -1, 1, -2, -3, -1], 4, [2]], [-16, -8, 8, -16]], ['control: random interpolator 46', [[0, -3, 2, 2, 0, 1, 3, 1], 2, [-3]], [0, 18]]], [['regression: random interpolator 18', [[-2, -1, -2, 0, 2], 2, [-4, 3, 1, 5, 1]], [16, 8, 4, -6, -32, -2, -12, -10, -20, -2]], ['regression: random interpolator 20', [[0, 1, 4, 1, -3, 2], 4, [-3, 2, -2, 0, 4]], [0, -12, -48, -12, 36, -16, 32, 8, -24, 8, -32, -8, 24, -16, 0, 0, 0, 16, 64, 16]], ['repair check: 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: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['control: 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]]], [['regression: random interpolator 25', [[-2], 3, [3, 2, 3, -1, -1]], [-18, 0, 0, -12, 0, 0, -18, 0, 0, 6, 0, 0, 6, 0, 0]], ['regression: random interpolator 26', [[4, -3, 2, -2], 3, [2, -4, 0, 4, -3]], [24, -18, 12, -60, 36, -24, 24, 0, 0, 48, -36, 24, -60, 27, -18]], ['repair check: random interpolator 10', [[-3, -2, 1], 3, [-4]], [36, 24, -12]], ['control: random interpolator 8', [[0, -2, 3, 3, -2, 4, -3], 3, [4, 2]], [0, -24, 36, 36, -36, 66]], ['control: random interpolator 17', [[4, 4, 3, 1, -3, 2, 1], 4, [4]], [64, 64, 48, 16]], ['control: random interpolator 21', [[2, -3, 0], 3, [-4, 3, 2, -2, -2]], [-24, 36, 0, 18, -27, 0, 12, -18, 0, -12, 18, 0, -12, 18, 0]], ['control: random interpolator 23', [[3, 2, 1, -1, 3, -1], 2, [-3, -1]], [-18, -12, -12, 2]]]]
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 fixtureActualExpectedOutcome
regression: partial phase tail[2, 4, 2, 4][2, 4, 8, 4]Failed
regression: random interpolator 0[-36, 12, 12, -36, 12, 12, 18, -6, -6][-36, 12, 12, -60, -24, 12, -6, -42, -6]Failed
repair check: impulse L=2[2, 4, 6, 8, 0, 0][2, 4, 6, 8, 0, 0]Passed
control: L=3 taps 7[3, 3, 3, 9, 9, 9][3, 3, 3, 9, 9, 9]Passed
control: random interpolator 1[36, -24, 36, -36][36, -24, 36, -36]Passed
control: random interpolator 4[-12, 12, 8, -4][-12, 12, 8, -4]Passed
control: random interpolator 5[0, 0, 0, 0, 0, 0][0, 0, 0, 0, 0, 0]Passed

SHA-256 / 21ca6a0383e7a573f3a7708f24d732e61fca7f20969e915c1bb539b92302451f

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) - 1:
                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: partial phase tail', [[1, 2, 3], 2, [1, 1]], [2, 4, 8, 4]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['repair check: impulse L=2', [[1, 2, 3, 4], 2, [1, 0, 0]], [2, 4, 6, 8, 0, 0]], ['control: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['control: 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]]], [['regression: random interpolator 9', [[-2, 4], 3, [-1, -1]], [6, -12, 0, 6, -12, 0]], ['regression: random interpolator 12', [[3, -1], 4, [1, 4, -2]], [12, -4, 0, 0, 48, -16, 0, 0, -24, 8, 0, 0]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['control: random interpolator 8', [[0, -2, 3, 3, -2, 4, -3], 3, [4, 2]], [0, -24, 36, 36, -36, 66]], ['control: random interpolator 17', [[4, 4, 3, 1, -3, 2, 1], 4, [4]], [64, 64, 48, 16]], ['control: random interpolator 21', [[2, -3, 0], 3, [-4, 3, 2, -2, -2]], [-24, 36, 0, 18, -27, 0, 12, -18, 0, -12, 18, 0, -12, 18, 0]], ['control: random interpolator 23', [[3, 2, 1, -1, 3, -1], 2, [-3, -1]], [-18, -12, -12, 2]]], [['regression: random interpolator 14', [[4, -1, 3, -1, 0, -2, 4], 3, [1, 3, 5]], [12, -3, 9, 33, -9, 21, 63, -15, 27]], ['regression: random interpolator 15', [[4, 2, 3], 2, [-2, -2, 2, 0, -1]], [-16, -8, -28, -8, 4, 8, 12, 0, -8, -4]], ['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]], ['control: random interpolator 24', [[-2, -1, 3, 0, -2, -2, 2], 2, [-2]], [8, 4]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['control: random interpolator 44', [[-2, -1, 1, -2, -3, -1], 4, [2]], [-16, -8, 8, -16]], ['control: random interpolator 46', [[0, -3, 2, 2, 0, 1, 3, 1], 2, [-3]], [0, 18]]], [['regression: random interpolator 18', [[-2, -1, -2, 0, 2], 2, [-4, 3, 1, 5, 1]], [16, 8, 4, -6, -32, -2, -12, -10, -20, -2]], ['regression: random interpolator 20', [[0, 1, 4, 1, -3, 2], 4, [-3, 2, -2, 0, 4]], [0, -12, -48, -12, 36, -16, 32, 8, -24, 8, -32, -8, 24, -16, 0, 0, 0, 16, 64, 16]], ['repair check: 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: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['control: 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]]], [['regression: random interpolator 25', [[-2], 3, [3, 2, 3, -1, -1]], [-18, 0, 0, -12, 0, 0, -18, 0, 0, 6, 0, 0, 6, 0, 0]], ['regression: random interpolator 26', [[4, -3, 2, -2], 3, [2, -4, 0, 4, -3]], [24, -18, 12, -60, 36, -24, 24, 0, 0, 48, -36, 24, -60, 27, -18]], ['repair check: random interpolator 10', [[-3, -2, 1], 3, [-4]], [36, 24, -12]], ['control: random interpolator 8', [[0, -2, 3, 3, -2, 4, -3], 3, [4, 2]], [0, -24, 36, 36, -36, 66]], ['control: random interpolator 17', [[4, 4, 3, 1, -3, 2, 1], 4, [4]], [64, 64, 48, 16]], ['control: random interpolator 21', [[2, -3, 0], 3, [-4, 3, 2, -2, -2]], [-24, 36, 0, 18, -27, 0, 12, -18, 0, -12, 18, 0, -12, 18, 0]], ['control: random interpolator 23', [[3, 2, 1, -1, 3, -1], 2, [-3, -1]], [-18, -12, -12, 2]]]]
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 fixtureActualExpectedOutcome
regression: partial phase tail[2, 4, 2, 4][2, 4, 8, 4]Failed
regression: random interpolator 0[-36, 12, 12, -60, 12, 12, -6, -6, -6][-36, 12, 12, -60, -24, 12, -6, -42, -6]Failed
repair check: impulse L=2[2, 4, 6, 0, 0, 0][2, 4, 6, 8, 0, 0]Failed
control: L=3 taps 7[3, 3, 3, 9, 9, 9][3, 3, 3, 9, 9, 9]Passed
control: random interpolator 1[36, -24, 36, -36][36, -24, 36, -36]Passed
control: random interpolator 4[-12, 12, 8, -4][-12, 12, 8, -4]Passed
control: random interpolator 5[0, 0, 0, 0, 0, 0][0, 0, 0, 0, 0, 0]Passed

SHA-256 / eb892901267f9e67a555f3b9edbd0fe6ad5fa754b23e16c5df5d3bdf00fe1ee8

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: partial phase tail', [[1, 2, 3], 2, [1, 1]], [2, 4, 8, 4]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['repair check: impulse L=2', [[1, 2, 3, 4], 2, [1, 0, 0]], [2, 4, 6, 8, 0, 0]], ['control: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['control: 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]]], [['regression: random interpolator 9', [[-2, 4], 3, [-1, -1]], [6, -12, 0, 6, -12, 0]], ['regression: random interpolator 12', [[3, -1], 4, [1, 4, -2]], [12, -4, 0, 0, 48, -16, 0, 0, -24, 8, 0, 0]], ['regression: random interpolator 0', [[3, -1, -1, 2, 3], 3, [-4, -4, 2]], [-36, 12, 12, -60, -24, 12, -6, -42, -6]], ['control: random interpolator 8', [[0, -2, 3, 3, -2, 4, -3], 3, [4, 2]], [0, -24, 36, 36, -36, 66]], ['control: random interpolator 17', [[4, 4, 3, 1, -3, 2, 1], 4, [4]], [64, 64, 48, 16]], ['control: random interpolator 21', [[2, -3, 0], 3, [-4, 3, 2, -2, -2]], [-24, 36, 0, 18, -27, 0, 12, -18, 0, -12, 18, 0, -12, 18, 0]], ['control: random interpolator 23', [[3, 2, 1, -1, 3, -1], 2, [-3, -1]], [-18, -12, -12, 2]]], [['regression: random interpolator 14', [[4, -1, 3, -1, 0, -2, 4], 3, [1, 3, 5]], [12, -3, 9, 33, -9, 21, 63, -15, 27]], ['regression: random interpolator 15', [[4, 2, 3], 2, [-2, -2, 2, 0, -1]], [-16, -8, -28, -8, 4, 8, 12, 0, -8, -4]], ['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]], ['control: random interpolator 24', [[-2, -1, 3, 0, -2, -2, 2], 2, [-2]], [8, 4]], ['control: random interpolator 36', [[2, 2, 0, 1, -3, -2], 2, [0]], [0, 0]], ['control: random interpolator 44', [[-2, -1, 1, -2, -3, -1], 4, [2]], [-16, -8, 8, -16]], ['control: random interpolator 46', [[0, -3, 2, 2, 0, 1, 3, 1], 2, [-3]], [0, 18]]], [['regression: random interpolator 18', [[-2, -1, -2, 0, 2], 2, [-4, 3, 1, 5, 1]], [16, 8, 4, -6, -32, -2, -12, -10, -20, -2]], ['regression: random interpolator 20', [[0, 1, 4, 1, -3, 2], 4, [-3, 2, -2, 0, 4]], [0, -12, -48, -12, 36, -16, 32, 8, -24, 8, -32, -8, 24, -16, 0, 0, 0, 16, 64, 16]], ['repair check: 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: L=3 taps 7', [[1, 1, 1, 1, 1, 1, 1], 3, [1, 2]], [3, 3, 3, 9, 9, 9]], ['control: random interpolator 1', [[3, -2, 3, -3, 2, 2], 4, [3]], [36, -24, 36, -36]], ['control: 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]]], [['regression: random interpolator 25', [[-2], 3, [3, 2, 3, -1, -1]], [-18, 0, 0, -12, 0, 0, -18, 0, 0, 6, 0, 0, 6, 0, 0]], ['regression: random interpolator 26', [[4, -3, 2, -2], 3, [2, -4, 0, 4, -3]], [24, -18, 12, -60, 36, -24, 24, 0, 0, 48, -36, 24, -60, 27, -18]], ['repair check: random interpolator 10', [[-3, -2, 1], 3, [-4]], [36, 24, -12]], ['control: random interpolator 8', [[0, -2, 3, 3, -2, 4, -3], 3, [4, 2]], [0, -24, 36, 36, -36, 66]], ['control: random interpolator 17', [[4, 4, 3, 1, -3, 2, 1], 4, [4]], [64, 64, 48, 16]], ['control: random interpolator 21', [[2, -3, 0], 3, [-4, 3, 2, -2, -2]], [-24, 36, 0, 18, -27, 0, 12, -18, 0, -12, 18, 0, -12, 18, 0]], ['control: random interpolator 23', [[3, 2, 1, -1, 3, -1], 2, [-3, -1]], [-18, -12, -12, 2]]]]
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 fixtureActualExpectedOutcome
regression: partial phase tail[2, 4, 8, 4][2, 4, 8, 4]Passed
regression: random interpolator 0[-36, 12, 12, -60, -24, 12, -6, -42, -6][-36, 12, 12, -60, -24, 12, -6, -42, -6]Passed
repair check: impulse L=2[2, 4, 6, 8, 0, 0][2, 4, 6, 8, 0, 0]Passed
control: L=3 taps 7[3, 3, 3, 9, 9, 9][3, 3, 3, 9, 9, 9]Passed
control: random interpolator 1[36, -24, 36, -36][36, -24, 36, -36]Passed
control: random interpolator 4[-12, 12, 8, -4][-12, 12, 8, -4]Passed
control: random interpolator 5[0, 0, 0, 0, 0, 0][0, 0, 0, 0, 0, 0]Passed

SHA-256 / f8f3d20651a1407781f36b279ca89393bff401df20eb1ebde22e673950988a31

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:37.138829+00:00.

Case digest / b7546ebd99ad394acb10685a472cf199c32dad4506009366615bbe0fe82a1223