FAILURE MAP
← Case archive

FA-91521 / Digital signal filters / Open access

Frequency response reports magnitude with the power decibel factor · case 01

A gain of 2 is reported as 3.01 dB instead of 6.02 dB.

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

ROOT CAUSE

10 log10 is applied to an amplitude ratio.

VERIFIED REPAIR

Use 20 log10 |H| for amplitude.

Unsuccessful approach: The attempted repair uses 20 log10 |H|^2, doubling the decibel values.

Case contract

Input [b, a, freqs]; coefficients and frequencies are numbers or rational strings, frequencies are fractions of Nyquist. For w = pi f evaluate H = B(e^{jw})/A(e^{jw}) with z^-k = e^{-jwk}; return per frequency [20 log10 |H| rounded to 4, phase in degrees rounded to 3], "pole" if |A| < 1e-12, "zero" if |H| < 1e-9.

Why this case matters

Magnitude and phase plots are how filters are verified; unit or sign slips misreport cutoff and delay.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
import cmath
from fractions import Fraction
N = 1
observations = []
def solve(x):
    b, a, fs = x
    b = [float(Fraction(v)) for v in b]
    a = [float(Fraction(v)) for v in a]
    out = []
    for f in fs:
        w = math.pi * float(Fraction(f))
        B = sum(c * cmath.exp(-1j * w * k) for k, c in enumerate(b))
        A = sum(c * cmath.exp(-1j * w * k) for k, c in enumerate(a))
        if abs(A) < 1e-12:
            out.append('pole')
            continue
        H = B / A
        mag = abs(H)
        if mag < 1e-9:
            out.append('zero')
            continue
        out.append([round(10 * math.log10(mag), 4) + 0.0, round(math.degrees(cmath.phase(H)), 3) + 0.0])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: first difference', [[1, -1], [1], ['0', '1/2', '1']], ['zero', [3.0103, 45.0], [6.0206, 0.0]]], ['regression: one pole', [[1], [1, '-1/2'], ['0', '1/4', '1/2']], [[6.0206, 0.0], [2.6529, -28.675], [-0.9691, -26.565]]], ['regression: deep notch', [[1, 0, 1], [1], ['1/2', '0.49']], ['zero', [-24.0378, -88.2]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: small magnitude', [[1, '-0.9999'], [1], ['0']], [[-80.0, 0.0]]], ['regression: random response 0', [['-1/4', 1], [1, 0], ['1/3', '1/8', '1/8']], [[-0.9018, -73.898], [-2.2144, -29.591], [-2.2144, -29.591]]], ['regression: deep notch', [[1, 0, 1], [1], ['1/2', '0.49']], ['zero', [-24.0378, -88.2]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: random response 2', [['1/2', '-1/4', 0, 2], [1, '1/2', '1/2'], ['1/2', '1/2', '1/2']], [[10.2633, 122.471], [10.2633, 122.471], [10.2633, 122.471]]], ['regression: random response 4', [[-1], [1, '1/2'], ['3/4', '1', '0']], [[2.6529, -151.325], [6.0206, -180.0], [-3.5218, 180.0]]], ['regression: random response 0', [['-1/4', 1], [1, 0], ['1/3', '1/8', '1/8']], [[-0.9018, -73.898], [-2.2144, -29.591], [-2.2144, -29.591]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: random response 6', [[1, -1], [1, '1/3', '1/3'], ['1/8', '1', '1/2']], [[-12.1798, 91.992], [6.0206, 0.0], [5.563, 71.565]]], ['regression: random response 7', [[2, -1], [1, '1/2'], ['3/4', '1/3', '1/3']], [[11.5896, 43.314], [2.3408, 49.107], [2.3408, 49.107]]], ['regression: random response 2', [['1/2', '-1/4', 0, 2], [1, '1/2', '1/2'], ['1/2', '1/2', '1/2']], [[10.2633, 122.471], [10.2633, 122.471], [10.2633, 122.471]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: random response 9', [[1], [1, '1/2'], ['1', '1/4', '1']], [[6.0206, 0.0], [-2.9161, 14.639], [6.0206, 0.0]]], ['regression: random response 10', [[-1, 1], [1], ['1/3', '1', '1/3']], [[0.0, -120.0], [6.0206, -180.0], [0.0, -120.0]]], ['regression: random response 5', [[1], [1, '1/2', '1/2'], ['1/4', '1', '1/8']], [[-4.0835, 32.236], [0.0, 0.0], [-5.5545, 16.706]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.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 fixtureActualExpectedOutcome
regression: first difference['zero', [1.5051, 45.0], [3.0103, 0.0]]['zero', [3.0103, 45.0], [6.0206, 0.0]]Failed
regression: one pole[[3.0103, 0.0], [1.3264, -28.675], [-0.4846, -26.565]][[6.0206, 0.0], [2.6529, -28.675], [-0.9691, -26.565]]Failed
regression: deep notch['zero', [-12.0189, -88.2]]['zero', [-24.0378, -88.2]]Failed
control: two-tap average at nyquist['zero']['zero']Passed
control: pole on unit circle['pole']['pole']Passed
control: pure delay phase[[0.0, -45.0], [0.0, -90.0]][[0.0, -45.0], [0.0, -90.0]]Passed
control: random response 3[[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]][[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]Passed

SHA-256 / 6a63025981b4ddb66d66f9af62027c723f5355e3d9538869dbfff660cb0e4a32

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
import cmath
from fractions import Fraction
N = 1
observations = []
def solve(x):
    b, a, fs = x
    b = [float(Fraction(v)) for v in b]
    a = [float(Fraction(v)) for v in a]
    out = []
    for f in fs:
        w = math.pi * float(Fraction(f))
        B = sum(c * cmath.exp(-1j * w * k) for k, c in enumerate(b))
        A = sum(c * cmath.exp(-1j * w * k) for k, c in enumerate(a))
        if abs(A) < 1e-12:
            out.append('pole')
            continue
        H = B / A
        mag = abs(H)
        if mag < 1e-9:
            out.append('zero')
            continue
        out.append([round(20 * math.log10(mag ** 2), 4) + 0.0, round(math.degrees(cmath.phase(H)), 3) + 0.0])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: first difference', [[1, -1], [1], ['0', '1/2', '1']], ['zero', [3.0103, 45.0], [6.0206, 0.0]]], ['regression: one pole', [[1], [1, '-1/2'], ['0', '1/4', '1/2']], [[6.0206, 0.0], [2.6529, -28.675], [-0.9691, -26.565]]], ['regression: deep notch', [[1, 0, 1], [1], ['1/2', '0.49']], ['zero', [-24.0378, -88.2]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: small magnitude', [[1, '-0.9999'], [1], ['0']], [[-80.0, 0.0]]], ['regression: random response 0', [['-1/4', 1], [1, 0], ['1/3', '1/8', '1/8']], [[-0.9018, -73.898], [-2.2144, -29.591], [-2.2144, -29.591]]], ['regression: deep notch', [[1, 0, 1], [1], ['1/2', '0.49']], ['zero', [-24.0378, -88.2]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: random response 2', [['1/2', '-1/4', 0, 2], [1, '1/2', '1/2'], ['1/2', '1/2', '1/2']], [[10.2633, 122.471], [10.2633, 122.471], [10.2633, 122.471]]], ['regression: random response 4', [[-1], [1, '1/2'], ['3/4', '1', '0']], [[2.6529, -151.325], [6.0206, -180.0], [-3.5218, 180.0]]], ['regression: random response 0', [['-1/4', 1], [1, 0], ['1/3', '1/8', '1/8']], [[-0.9018, -73.898], [-2.2144, -29.591], [-2.2144, -29.591]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: random response 6', [[1, -1], [1, '1/3', '1/3'], ['1/8', '1', '1/2']], [[-12.1798, 91.992], [6.0206, 0.0], [5.563, 71.565]]], ['regression: random response 7', [[2, -1], [1, '1/2'], ['3/4', '1/3', '1/3']], [[11.5896, 43.314], [2.3408, 49.107], [2.3408, 49.107]]], ['regression: random response 2', [['1/2', '-1/4', 0, 2], [1, '1/2', '1/2'], ['1/2', '1/2', '1/2']], [[10.2633, 122.471], [10.2633, 122.471], [10.2633, 122.471]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: random response 9', [[1], [1, '1/2'], ['1', '1/4', '1']], [[6.0206, 0.0], [-2.9161, 14.639], [6.0206, 0.0]]], ['regression: random response 10', [[-1, 1], [1], ['1/3', '1', '1/3']], [[0.0, -120.0], [6.0206, -180.0], [0.0, -120.0]]], ['regression: random response 5', [[1], [1, '1/2', '1/2'], ['1/4', '1', '1/8']], [[-4.0835, 32.236], [0.0, 0.0], [-5.5545, 16.706]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.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 fixtureActualExpectedOutcome
regression: first difference['zero', [6.0206, 45.0], [12.0412, 0.0]]['zero', [3.0103, 45.0], [6.0206, 0.0]]Failed
regression: one pole[[12.0412, 0.0], [5.3057, -28.675], [-1.9382, -26.565]][[6.0206, 0.0], [2.6529, -28.675], [-0.9691, -26.565]]Failed
regression: deep notch['zero', [-48.0757, -88.2]]['zero', [-24.0378, -88.2]]Failed
control: two-tap average at nyquist['zero']['zero']Passed
control: pole on unit circle['pole']['pole']Passed
control: pure delay phase[[0.0, -45.0], [0.0, -90.0]][[0.0, -45.0], [0.0, -90.0]]Passed
control: random response 3[[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]][[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]Passed

SHA-256 / 78a9309e36cf78b9e31249803eeb61616c5947de35713464cce8f1e0428bde66

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
import cmath
from fractions import Fraction
N = 1
observations = []
def solve(x):
    b, a, fs = x
    b = [float(Fraction(v)) for v in b]
    a = [float(Fraction(v)) for v in a]
    out = []
    for f in fs:
        w = math.pi * float(Fraction(f))
        B = sum(c * cmath.exp(-1j * w * k) for k, c in enumerate(b))
        A = sum(c * cmath.exp(-1j * w * k) for k, c in enumerate(a))
        if abs(A) < 1e-12:
            out.append('pole')
            continue
        H = B / A
        mag = abs(H)
        if mag < 1e-9:
            out.append('zero')
            continue
        out.append([round(20 * math.log10(mag), 4) + 0.0, round(math.degrees(cmath.phase(H)), 3) + 0.0])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: first difference', [[1, -1], [1], ['0', '1/2', '1']], ['zero', [3.0103, 45.0], [6.0206, 0.0]]], ['regression: one pole', [[1], [1, '-1/2'], ['0', '1/4', '1/2']], [[6.0206, 0.0], [2.6529, -28.675], [-0.9691, -26.565]]], ['regression: deep notch', [[1, 0, 1], [1], ['1/2', '0.49']], ['zero', [-24.0378, -88.2]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: small magnitude', [[1, '-0.9999'], [1], ['0']], [[-80.0, 0.0]]], ['regression: random response 0', [['-1/4', 1], [1, 0], ['1/3', '1/8', '1/8']], [[-0.9018, -73.898], [-2.2144, -29.591], [-2.2144, -29.591]]], ['regression: deep notch', [[1, 0, 1], [1], ['1/2', '0.49']], ['zero', [-24.0378, -88.2]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: random response 2', [['1/2', '-1/4', 0, 2], [1, '1/2', '1/2'], ['1/2', '1/2', '1/2']], [[10.2633, 122.471], [10.2633, 122.471], [10.2633, 122.471]]], ['regression: random response 4', [[-1], [1, '1/2'], ['3/4', '1', '0']], [[2.6529, -151.325], [6.0206, -180.0], [-3.5218, 180.0]]], ['regression: random response 0', [['-1/4', 1], [1, 0], ['1/3', '1/8', '1/8']], [[-0.9018, -73.898], [-2.2144, -29.591], [-2.2144, -29.591]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: random response 6', [[1, -1], [1, '1/3', '1/3'], ['1/8', '1', '1/2']], [[-12.1798, 91.992], [6.0206, 0.0], [5.563, 71.565]]], ['regression: random response 7', [[2, -1], [1, '1/2'], ['3/4', '1/3', '1/3']], [[11.5896, 43.314], [2.3408, 49.107], [2.3408, 49.107]]], ['regression: random response 2', [['1/2', '-1/4', 0, 2], [1, '1/2', '1/2'], ['1/2', '1/2', '1/2']], [[10.2633, 122.471], [10.2633, 122.471], [10.2633, 122.471]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]]], [['regression: random response 9', [[1], [1, '1/2'], ['1', '1/4', '1']], [[6.0206, 0.0], [-2.9161, 14.639], [6.0206, 0.0]]], ['regression: random response 10', [[-1, 1], [1], ['1/3', '1', '1/3']], [[0.0, -120.0], [6.0206, -180.0], [0.0, -120.0]]], ['regression: random response 5', [[1], [1, '1/2', '1/2'], ['1/4', '1', '1/8']], [[-4.0835, 32.236], [0.0, 0.0], [-5.5545, 16.706]]], ['control: two-tap average at nyquist', [[1, 1], [1], ['1']], ['zero']], ['control: pole on unit circle', [[1], [1, -1], ['0']], ['pole']], ['control: pure delay phase', [[0, 1], [1], ['1/4', '1/2']], [[0.0, -45.0], [0.0, -90.0]]], ['control: random response 3', [[0, 0, -1], [1], ['1/2', '1/8', '1']], [[0.0, 0.0], [0.0, 135.0], [0.0, -180.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 fixtureActualExpectedOutcome
regression: first difference['zero', [3.0103, 45.0], [6.0206, 0.0]]['zero', [3.0103, 45.0], [6.0206, 0.0]]Passed
regression: one pole[[6.0206, 0.0], [2.6529, -28.675], [-0.9691, -26.565]][[6.0206, 0.0], [2.6529, -28.675], [-0.9691, -26.565]]Passed
regression: deep notch['zero', [-24.0378, -88.2]]['zero', [-24.0378, -88.2]]Passed
control: two-tap average at nyquist['zero']['zero']Passed
control: pole on unit circle['pole']['pole']Passed
control: pure delay phase[[0.0, -45.0], [0.0, -90.0]][[0.0, -45.0], [0.0, -90.0]]Passed
control: random response 3[[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]][[0.0, 0.0], [0.0, 135.0], [0.0, -180.0]]Passed

SHA-256 / 86f08a8ecf434ce787c710f602d5bf5e786bc0acea7ae79cd57215e63e7a8991

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

Case digest / ebccf44172177ddab3a3dc9f4750bdbbb96bd3e409e029108265c5a43bebed1c