FAILURE MAP
← Case archive

FA-91726 / Digital signal filters / Open access

Goertzel shifts s1 into s2 after overwriting it · case 01

Both states always hold the newest value and the recursion becomes first order.

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

ROOT CAUSE

s1 is overwritten with s before s2 copies it.

VERIFIED REPAIR

Copy s1 into s2 before updating s1.

Unsuccessful approach: The attempted repair assigns the tuple the wrong way round, storing the new value in s2.

Case contract

Input [N, k, samples]; samples must have length N ("length-mismatch"). Goertzel recursion s = x + c s1 - s2 with c = 2 cos(2 pi k / N) from zero state; power = s1^2 + s2^2 - c s1 s2, rounded to 6 decimals (equals |X[k]|^2 of the DFT).

Why this case matters

Goertzel filters detect single tones cheaply (DTMF, pilot tones); recursion or coefficient slips misreport bin energy.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    N, k, xs = x
    if len(xs) != N:
        return 'length-mismatch'
    w = 2 * math.pi * k / N
    coeff = 2 * math.cos(w)
    s1 = s2 = 0.0
    for v in xs:
        s = v + coeff * s1 - s2
        s1 = s
        s2 = s1
    power = s1 * s1 + s2 * s2 - coeff * s1 * s2
    return round(power, 6) + 0.0
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: dc bin', [4, 0, [1, 1, 1, 1]], 16.0], ['regression: tone on bin 1', [8, 1, [1, 0.707107, 0, -0.707107, -1, -0.707107, 0, 0.707107]], 16.000005], ['regression: random goertzel 0', [5, 3, [1.783, -0.103, 1.735, 0.172, 0.47]], 7.631659], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: nyquist bin', [4, 2, [1, -1, 1, -1]], 16.0], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049]], [['regression: random goertzel 0', [5, 3, [1.783, -0.103, 1.735, 0.172, 0.47]], 7.631659], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: nyquist bin', [4, 2, [1, -1, 1, -1]], 16.0], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049], ['regression: random goertzel 4', [5, 1, [0.277, 1.508, 1.644, 1.371, 0.902]], 2.552062]], [['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002], ['regression: random goertzel 4', [5, 1, [0.277, 1.508, 1.644, 1.371, 0.902]], 2.552062], ['regression: random goertzel 5', [16, 12, [0.484, 1.263, -0.839, 0.847, 1.38, 0.512, -1.644, -1.061, -1.041, 1.886, 1.201, 1.603, -1.82, -1.609, -1.768, -0.588]], 5.77981], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: random goertzel 0', [5, 3, [1.783, -0.103, 1.735, 0.172, 0.47]], 7.631659], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049]], [['regression: random goertzel 6', [16, 3, [-0.301, 1.167, -1.088, 1.455, 1.212, 0.703, -1.679, -0.745, -1.885, -0.092, 1.441, 0.517, 1.787, 1.007, 1.333, 0.125]], 11.236712], ['regression: random goertzel 7', [16, 12, [0.634, -0.987, 0.86, -1.732, -1.556, 1.652, 1.567, 1.68, 0.143, -1.093, 0.974, -0.392, 0.657, -0.89, -0.677, -0.216]], 8.53268], ['regression: random goertzel 5', [16, 12, [0.484, 1.263, -0.839, 0.847, 1.38, 0.512, -1.644, -1.061, -1.041, 1.886, 1.201, 1.603, -1.82, -1.609, -1.768, -0.588]], 5.77981], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049], ['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002]], [['regression: random goertzel 9', [16, 0, [1.777, -1.73, -1.599, 0.005, -0.185, 1.341, 1.416, -0.302, 1.918, -1.985, 0.787, -1.656, 0.349, -1.026, 0.686, 1.037]], 0.693889], ['regression: random goertzel 10', [8, 6, [-1.225, 0.237, -0.49, 1.181, 0.965, 0.672, -0.592, 0.35]], 1.062568], ['regression: random goertzel 7', [16, 12, [0.634, -0.987, 0.86, -1.732, -1.556, 1.652, 1.567, 1.68, 0.143, -1.093, 0.974, -0.392, 0.657, -0.89, -0.677, -0.216]], 8.53268], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049], ['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002], ['regression: random goertzel 4', [5, 1, [0.277, 1.508, 1.644, 1.371, 0.902]], 2.552062]]]
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: dc bin0.016.0Failed
regression: tone on bin 10.14619316.000005Failed
regression: random goertzel 034410.0738727.631659Failed
control: length mismatchlength-mismatchlength-mismatchPassed
regression: nyquist bin6400.016.0Failed
regression: random goertzel 1480679047173891.4481.860198Failed
regression: random goertzel 27085.26227614.115049Failed

SHA-256 / 18832886723910576a5ef5c2273559b4617d2d3b3d28b1cd44521237c79b96fe

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    N, k, xs = x
    if len(xs) != N:
        return 'length-mismatch'
    w = 2 * math.pi * k / N
    coeff = 2 * math.cos(w)
    s1 = s2 = 0.0
    for v in xs:
        s = v + coeff * s1 - s2
        s2, s1 = s, s1
    power = s1 * s1 + s2 * s2 - coeff * s1 * s2
    return round(power, 6) + 0.0
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: dc bin', [4, 0, [1, 1, 1, 1]], 16.0], ['regression: tone on bin 1', [8, 1, [1, 0.707107, 0, -0.707107, -1, -0.707107, 0, 0.707107]], 16.000005], ['regression: random goertzel 0', [5, 3, [1.783, -0.103, 1.735, 0.172, 0.47]], 7.631659], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: nyquist bin', [4, 2, [1, -1, 1, -1]], 16.0], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049]], [['regression: random goertzel 0', [5, 3, [1.783, -0.103, 1.735, 0.172, 0.47]], 7.631659], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: nyquist bin', [4, 2, [1, -1, 1, -1]], 16.0], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049], ['regression: random goertzel 4', [5, 1, [0.277, 1.508, 1.644, 1.371, 0.902]], 2.552062]], [['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002], ['regression: random goertzel 4', [5, 1, [0.277, 1.508, 1.644, 1.371, 0.902]], 2.552062], ['regression: random goertzel 5', [16, 12, [0.484, 1.263, -0.839, 0.847, 1.38, 0.512, -1.644, -1.061, -1.041, 1.886, 1.201, 1.603, -1.82, -1.609, -1.768, -0.588]], 5.77981], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: random goertzel 0', [5, 3, [1.783, -0.103, 1.735, 0.172, 0.47]], 7.631659], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049]], [['regression: random goertzel 6', [16, 3, [-0.301, 1.167, -1.088, 1.455, 1.212, 0.703, -1.679, -0.745, -1.885, -0.092, 1.441, 0.517, 1.787, 1.007, 1.333, 0.125]], 11.236712], ['regression: random goertzel 7', [16, 12, [0.634, -0.987, 0.86, -1.732, -1.556, 1.652, 1.567, 1.68, 0.143, -1.093, 0.974, -0.392, 0.657, -0.89, -0.677, -0.216]], 8.53268], ['regression: random goertzel 5', [16, 12, [0.484, 1.263, -0.839, 0.847, 1.38, 0.512, -1.644, -1.061, -1.041, 1.886, 1.201, 1.603, -1.82, -1.609, -1.768, -0.588]], 5.77981], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049], ['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002]], [['regression: random goertzel 9', [16, 0, [1.777, -1.73, -1.599, 0.005, -0.185, 1.341, 1.416, -0.302, 1.918, -1.985, 0.787, -1.656, 0.349, -1.026, 0.686, 1.037]], 0.693889], ['regression: random goertzel 10', [8, 6, [-1.225, 0.237, -0.49, 1.181, 0.965, 0.672, -0.592, 0.35]], 1.062568], ['regression: random goertzel 7', [16, 12, [0.634, -0.987, 0.86, -1.732, -1.556, 1.652, 1.567, 1.68, 0.143, -1.093, 0.974, -0.392, 0.657, -0.89, -0.677, -0.216]], 8.53268], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049], ['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002], ['regression: random goertzel 4', [5, 1, [0.277, 1.508, 1.644, 1.371, 0.902]], 2.552062]]]
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: dc bin0.016.0Failed
regression: tone on bin 10.016.000005Failed
regression: random goertzel 015.3585617.631659Failed
control: length mismatchlength-mismatchlength-mismatchPassed
regression: nyquist bin16.016.0Passed
regression: random goertzel 115.19440481.860198Failed
regression: random goertzel 214.11504914.115049Passed

SHA-256 / ae80b0ac6a91b760e8f43fe2038743a6244dfe24ee438e1697a292e80091da74

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    N, k, xs = x
    if len(xs) != N:
        return 'length-mismatch'
    w = 2 * math.pi * k / N
    coeff = 2 * math.cos(w)
    s1 = s2 = 0.0
    for v in xs:
        s = v + coeff * s1 - s2
        s2 = s1
        s1 = s
    power = s1 * s1 + s2 * s2 - coeff * s1 * s2
    return round(power, 6) + 0.0
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: dc bin', [4, 0, [1, 1, 1, 1]], 16.0], ['regression: tone on bin 1', [8, 1, [1, 0.707107, 0, -0.707107, -1, -0.707107, 0, 0.707107]], 16.000005], ['regression: random goertzel 0', [5, 3, [1.783, -0.103, 1.735, 0.172, 0.47]], 7.631659], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: nyquist bin', [4, 2, [1, -1, 1, -1]], 16.0], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049]], [['regression: random goertzel 0', [5, 3, [1.783, -0.103, 1.735, 0.172, 0.47]], 7.631659], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: nyquist bin', [4, 2, [1, -1, 1, -1]], 16.0], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049], ['regression: random goertzel 4', [5, 1, [0.277, 1.508, 1.644, 1.371, 0.902]], 2.552062]], [['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002], ['regression: random goertzel 4', [5, 1, [0.277, 1.508, 1.644, 1.371, 0.902]], 2.552062], ['regression: random goertzel 5', [16, 12, [0.484, 1.263, -0.839, 0.847, 1.38, 0.512, -1.644, -1.061, -1.041, 1.886, 1.201, 1.603, -1.82, -1.609, -1.768, -0.588]], 5.77981], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: random goertzel 0', [5, 3, [1.783, -0.103, 1.735, 0.172, 0.47]], 7.631659], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049]], [['regression: random goertzel 6', [16, 3, [-0.301, 1.167, -1.088, 1.455, 1.212, 0.703, -1.679, -0.745, -1.885, -0.092, 1.441, 0.517, 1.787, 1.007, 1.333, 0.125]], 11.236712], ['regression: random goertzel 7', [16, 12, [0.634, -0.987, 0.86, -1.732, -1.556, 1.652, 1.567, 1.68, 0.143, -1.093, 0.974, -0.392, 0.657, -0.89, -0.677, -0.216]], 8.53268], ['regression: random goertzel 5', [16, 12, [0.484, 1.263, -0.839, 0.847, 1.38, 0.512, -1.644, -1.061, -1.041, 1.886, 1.201, 1.603, -1.82, -1.609, -1.768, -0.588]], 5.77981], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: random goertzel 1', [16, 7, [1.67, -0.361, -1.179, -1.404, -0.191, 0.823, -1.353, 1.734, 0.486, 0.989, 1.205, -0.229, 1.256, -0.62, 1.422, -1.514]], 81.860198], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049], ['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002]], [['regression: random goertzel 9', [16, 0, [1.777, -1.73, -1.599, 0.005, -0.185, 1.341, 1.416, -0.302, 1.918, -1.985, 0.787, -1.656, 0.349, -1.026, 0.686, 1.037]], 0.693889], ['regression: random goertzel 10', [8, 6, [-1.225, 0.237, -0.49, 1.181, 0.965, 0.672, -0.592, 0.35]], 1.062568], ['regression: random goertzel 7', [16, 12, [0.634, -0.987, 0.86, -1.732, -1.556, 1.652, 1.567, 1.68, 0.143, -1.093, 0.974, -0.392, 0.657, -0.89, -0.677, -0.216]], 8.53268], ['control: length mismatch', [4, 1, [1, 2, 3]], 'length-mismatch'], ['regression: random goertzel 2', [4, 2, [1.006, -1.378, 0.575, -0.798]], 14.115049], ['regression: random goertzel 3', [5, 2, [0.006, 0.503, -1.021, -1.836, 1.378]], 7.416002], ['regression: random goertzel 4', [5, 1, [0.277, 1.508, 1.644, 1.371, 0.902]], 2.552062]]]
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: dc bin16.016.0Passed
regression: tone on bin 116.00000516.000005Passed
regression: random goertzel 07.6316597.631659Passed
control: length mismatchlength-mismatchlength-mismatchPassed
regression: nyquist bin16.016.0Passed
regression: random goertzel 181.86019881.860198Passed
regression: random goertzel 214.11504914.115049Passed

SHA-256 / 78c20aac2bdb57b22952f3395fbb524ef7ea742333212930ea1d7f1889bad05d

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

Case digest / c160ef19a8aca6d254824052e6c51e8fa8edea049fd0996bfe9e1589e216e3ce