When a weak station goes undecoded, the last word doesn't belong to the antenna or the DSP: it belongs to the error-correction decoder. FT2, FT8 and FT4 all share the same LDPC(174,91) code with a CRC-14, and the decoder handling it has stayed essentially unchanged for years. Today we present fastldpc, a decoder written from scratch for that code, integrated into Decodium 4.0 “Core Shannon” and released under GPL-3.0.
Let's say upfront what fastldpc is not: it is not a new algorithm, nor a theoretical discovery. LDPC codes are Robert Gallager's (1962), normalized min-sum is Chen and Fossorier's, ordered statistics decoding is Fossorier and Lin's. What fastldpc does is make practical what existed on paper but cost too much — and in weak-signal decoding, what is practical decides what gets decoded.
The results, in two numbers
On the bench (AWGN, 20,000 codewords per point, details below): +1.3 dB of sensitivity over plain min-sum and +0.35 dB over the classic WSJT-X-style OSD-2 compromise, at equal false-decode rates — with a chain roughly 16 times faster. The two numbers are linked: the gain comes from using a search order (OSD-3, tens of thousands of candidates per word) that nobody uses because it's too expensive. It became usable because the cost per candidate collapsed.
The key insight: the CRC-14 is linear
The OSD decoder generates candidates and checks them against the CRC-14. Normally, checking a candidate means rebuilding all 174 bits and re-running the LFSR — expensive, and done per candidate. But the CRC-14's LFSR starts from zero and has no final XOR, so its syndrome is a linear function of the 91 information bits: each bit-flip's contribution is precomputed once per word, and from then on testing a candidate costs a single XOR on a 16-bit integer.
The practical consequence flips the architecture: the most selective filter (the CRC accepts 1 candidate in 16,384) becomes the cheapest one, so it goes first, and everything else is paid only on the very few candidates that pass it. Measured: going from OSD-0 to OSD-2 used to cost 13×; now it costs 3%. At that point, using “unreasonable” search orders and spans becomes the obvious choice.
Around this insight sit the other optimizations: the min-sum hand-written in AVX2 intrinsics (compilers refuse to vectorize it — a measured 30× difference), branchless Gaussian elimination on 256-bit rows, and a normalized soft-distance “gate” that keeps false decodes in check — because trying 21,000 candidates without a strict gate would mean accepting ghosts. Words closed by min-sum+CRC alone never produced a single false decode at any measured point.
A bug found along the way (affecting FT8 and FT4 too)
Benchmarking fastldpc head-to-head against the existing decoder exposed an anomaly: the existing decoder's BP closed zero words. The cause: the min-sum branch of FtxLdpc.cpp — a branch added in Decodium's C++ port, which exists neither in WSJT-X's original Fortran nor in ft8_lib, both unaffected — was missing a sign negation in the check→variable message (the exact branch computes 2*platanh(-tmn); the min-sum branch omitted the minus). Every parity equation pushed bits the wrong way, BP never converged, and every decode was silently coming from the OSD alone. Fixed with a single negation (release 1.0.590): at 1 dB on 1,000 words, decodes go from 713 to 834. Within Decodium the branch is shared with FT8 and FT4, so the fix benefits all three modes.
Verify it yourselves: how to reproduce every number
This is the most important section of this post. No number above requires an act of faith:
git clone https://github.com/iu8lmc/Decodium-4.0-Core-Shannon
cd Decodium-4.0-Core-Shannon/Detector/fastldpc
make test # CRC, bit-for-bit equivalence with the reference, the three presets
make sweep # the full FER/false/µs table from the README
make gate # the false-decode gate calibration
You need a C++17 compiler and an x86-64 CPU; with AVX2 you get the stated timings, without AVX2 everything still works (just slower). verify.cpp compares the optimized implementation against the reference word by word: zero differences over 21,492 words. If you find a number that doesn't add up, opening an issue is the best contribution you can make.
The stated limitation, and the ask
All measurements are on an AWGN channel with ideal LLRs. The real 4-GFSK demodulator won't produce them that way, and the roadmap says so explicitly: the gate and the anti-impulse clip need re-calibration on real LLRs. This is why we're looking for testers: operators willing to run the fastldpc build in real conditions — crowded bands, QRM, static crashes — and report results, good or bad. It's the step that decides how much of the lab gain makes it on the air, and we can't do it alone.
Transparency
fastldpc was developed with AI-assisted tooling. The design decisions, constraints, measurements, discarded experiments and verification are the author's, and every result is reproducible with the benchmarks included in the repo. The code is GPL-3.0, like WSJT-X and ft8_lib, from which the code tables originate — kept bit-identical for full compatibility with any other station.
The LDPC(174,91) and the CRC-14 belong to the FT8 protocol by Steve Franke K9AN and Joe Taylor K1JT; to them, as always, the greatest debt.
73 de Martino IU8LMC