1
0
Fork
You've already forked turbo_codes
0
Naive attempt at turbo_codes
  • Rust 59.6%
  • Python 14%
  • Shell 12.8%
  • C++ 11.7%
  • CMake 1.9%
Find a file
2026年06月06日 13:12:12 +10:00
bench init 2026年06月03日 16:37:13 +10:00
examples init 2026年06月03日 16:37:13 +10:00
scripts fix: readme numbers to latest, update script to not crash on linux. 2026年06月06日 13:12:12 +10:00
src init 2026年06月03日 16:37:13 +10:00
tests init 2026年06月03日 16:37:13 +10:00
.gitignore init 2026年06月03日 16:37:13 +10:00
.gitmodules init 2026年06月03日 16:37:13 +10:00
Cargo.lock init 2026年06月03日 16:37:13 +10:00
Cargo.toml init 2026年06月03日 16:37:13 +10:00
mac_results.txt init 2026年06月03日 16:37:13 +10:00
popbox_results.txt init 2026年06月03日 16:37:13 +10:00
README.md fix: readme numbers to latest, update script to not crash on linux. 2026年06月06日 13:12:12 +10:00

turbo_codes

Turbo codes (CCSDS 131.0-B-3, 3GPP LTE, generic RSC g=13/15).

I've tried to make this output Bit-exact against AFF3CT, which is the last library I used when I last played with these... many moons ago.

The no_std + simd + libm is my usecase.

I am not an expert in this sorta thing, just wanted to learn-by-porting.

Features

  • no_std - for, what should be obivous reasons
  • std (default) — uses std::f32 for transcendental ops
  • libm — route maths through libm regardless of std;
  • simdwide-backed BCJR for 8-state codes (no_std-friendly)
  • rayon — what it says on the tin

Usage

Encode, then fuck with ~5% of data, then decode for full recovery:

useturbo_codes::{Spec,TurboCode};letcode=TurboCode::new(&Spec::Lte,512)?;letmsg: Vec<u8>=(0..512).map(|i|u8::from(i%3==0)).collect();letencoded=code.encode_bits(&msg)?;// BPSK LLRs (bit 0 → +8, bit 1 → -8), then flip every 20th symbol.
letmutllr: Vec<f32>=encoded.iter().map(|&b|ifb==0{8.0}else{-8.0}).collect();foriin(0..llr.len()).step_by(20){llr[i]=-llr[i];}letdecoded=code.decode_bits(&llr)?;assert_eq!(decoded,msg);// FEC recovers every bit

See examples/fec_demo.rs.

Building the C++ reference + benchmarks

bash scripts/build_cpp.sh # vendor AFF3CT (pinned v4.4.0) and build the harness
bash scripts/gen_fixtures.sh # regenerate test_data/ for `cargo test`
python3 scripts/vs_cpp.py # benchmark Rust vs AFF3CT, prints prints a pretty(ish) table

Benchmark snapshot

AMD 5950x
=== std (scalar, system libm) (exec=serial) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 22.07 ms 10.31 ms 2.14x | 1.33 s 3.50 s 0.38x
lte 6144 maxlog 500 375.0 KiB | 27.62 ms 12.41 ms 2.22x | 1.62 s 4.56 s 0.36x
lte 512 logmap 2000 125.0 KiB | 8.07 ms 3.90 ms 2.07x | 4.65 s 5.23 s 0.89x
ccsds 1784 maxlog 1000 217.8 KiB | 13.70 ms 7.76 ms 1.77x | 1.65 s 5.16 s 0.32x
ccsds 8920 maxlog 200 217.8 KiB | 15.39 ms 7.46 ms 2.06x | 1.68 s 5.00 s 0.34x
ccsds 1784 logmap 400 87.1 KiB | 5.47 ms 2.87 ms 1.91x | 6.84 s 7.78 s 0.88x
rsc1315 1024 maxlog 2000 250.0 KiB | 21.45 ms 8.51 ms 2.52x | 1.06 s 3.03 s 0.35x
=== std + libm (portable maths) (exec=serial) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 22.61 ms 11.43 ms 1.98x | 1.35 s 3.83 s 0.35x
lte 6144 maxlog 500 375.0 KiB | 24.41 ms 11.50 ms 2.12x | 1.46 s 4.27 s 0.34x
lte 512 logmap 2000 125.0 KiB | 9.94 ms 3.96 ms 2.51x | 4.71 s 5.87 s 0.80x
ccsds 1784 maxlog 1000 217.8 KiB | 13.82 ms 6.59 ms 2.10x | 1.56 s 4.80 s 0.32x
ccsds 8920 maxlog 200 217.8 KiB | 13.53 ms 7.30 ms 1.85x | 1.57 s 4.95 s 0.32x
ccsds 1784 logmap 400 87.1 KiB | 6.19 ms 2.80 ms 2.21x | 6.86 s 8.56 s 0.80x
rsc1315 1024 maxlog 2000 250.0 KiB | 16.22 ms 8.26 ms 1.96x | 960.23 ms 2.87 s 0.33x
=== std + simd (exec=serial) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 19.99 ms 10.05 ms 1.99x | 1.23 s 2.02 s 0.61x
lte 6144 maxlog 500 375.0 KiB | 27.89 ms 12.71 ms 2.19x | 1.61 s 2.66 s 0.60x
lte 512 logmap 2000 125.0 KiB | 9.39 ms 4.00 ms 2.34x | 4.69 s 5.44 s 0.86x
ccsds 1784 maxlog 1000 217.8 KiB | 15.79 ms 6.59 ms 2.40x | 1.59 s 4.90 s 0.32x
ccsds 8920 maxlog 200 217.8 KiB | 14.77 ms 7.42 ms 1.99x | 1.63 s 5.19 s 0.31x
ccsds 1784 logmap 400 87.1 KiB | 5.69 ms 2.60 ms 2.19x | 7.11 s 7.63 s 0.93x
rsc1315 1024 maxlog 2000 250.0 KiB | 18.37 ms 8.89 ms 2.07x | 1.07 s 1.81 s 0.59x
=== no_std + libm (scalar) (exec=serial) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 22.68 ms 10.89 ms 2.08x | 1.31 s 3.92 s 0.33x
lte 6144 maxlog 500 375.0 KiB | 27.46 ms 12.31 ms 2.23x | 1.63 s 4.55 s 0.36x
lte 512 logmap 2000 125.0 KiB | 9.11 ms 4.30 ms 2.12x | 5.07 s 6.16 s 0.82x
ccsds 1784 maxlog 1000 217.8 KiB | 15.41 ms 7.62 ms 2.02x | 1.73 s 5.31 s 0.33x
ccsds 8920 maxlog 200 217.8 KiB | 15.08 ms 7.09 ms 2.13x | 1.70 s 5.29 s 0.32x
ccsds 1784 logmap 400 87.1 KiB | 6.51 ms 2.59 ms 2.51x | 7.38 s 8.94 s 0.82x
rsc1315 1024 maxlog 2000 250.0 KiB | 18.31 ms 8.54 ms 2.14x | 1.10 s 3.12 s 0.35x
=== no_std + libm + simd (exec=serial) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 22.74 ms 11.11 ms 2.05x | 1.35 s 2.26 s 0.60x
lte 6144 maxlog 500 375.0 KiB | 27.45 ms 12.33 ms 2.23x | 1.67 s 2.70 s 0.62x
lte 512 logmap 2000 125.0 KiB | 7.94 ms 4.33 ms 1.83x | 5.08 s 6.22 s 0.82x
ccsds 1784 maxlog 1000 217.8 KiB | 14.19 ms 6.44 ms 2.21x | 1.54 s 4.91 s 0.31x
ccsds 8920 maxlog 200 217.8 KiB | 15.41 ms 7.28 ms 2.12x | 1.74 s 5.34 s 0.33x
ccsds 1784 logmap 400 87.1 KiB | 6.42 ms 2.88 ms 2.23x | 7.60 s 8.79 s 0.86x
rsc1315 1024 maxlog 2000 250.0 KiB | 18.00 ms 8.50 ms 2.12x | 1.08 s 1.71 s 0.63x
=== no_std + libm + simd + scoped (exec=scoped) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 23.05 ms 10.98 ms 2.10x | 1.42 s 116.64 ms 12.19x
lte 6144 maxlog 500 375.0 KiB | 27.25 ms 12.41 ms 2.20x | 1.60 s 255.74 ms 6.25x
lte 512 logmap 2000 125.0 KiB | 8.77 ms 4.35 ms 2.02x | 5.27 s 291.26 ms 18.10x
ccsds 1784 maxlog 1000 217.8 KiB | 15.54 ms 7.31 ms 2.12x | 1.75 s 391.15 ms 4.48x
ccsds 8920 maxlog 200 217.8 KiB | 15.04 ms 6.35 ms 2.37x | 1.75 s 401.03 ms 4.35x
ccsds 1784 logmap 400 87.1 KiB | 6.02 ms 2.91 ms 2.07x | 7.37 s 459.94 ms 16.02x
rsc1315 1024 maxlog 2000 250.0 KiB | 17.87 ms 8.76 ms 2.04x | 1.08 s 115.48 ms 9.32x
=== std + simd + rayon (exec=rayon) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 22.29 ms 11.32 ms 1.97x | 1.35 s 114.55 ms 11.81x
lte 6144 maxlog 500 375.0 KiB | 27.78 ms 12.99 ms 2.14x | 1.61 s 258.23 ms 6.25x
lte 512 logmap 2000 125.0 KiB | 12.88 ms 4.47 ms 2.88x | 5.18 s 272.76 ms 18.99x
ccsds 1784 maxlog 1000 217.8 KiB | 14.14 ms 7.41 ms 1.91x | 1.71 s 361.76 ms 4.71x
ccsds 8920 maxlog 200 217.8 KiB | 15.46 ms 7.42 ms 2.08x | 1.74 s 374.36 ms 4.64x
ccsds 1784 logmap 400 87.1 KiB | 6.00 ms 2.94 ms 2.04x | 7.24 s 396.70 ms 18.25x
rsc1315 1024 maxlog 2000 250.0 KiB | 18.09 ms 8.83 ms 2.05x | 1.08 s 97.35 ms 11.08x
M5 macbook pro
host:
 cpu : Apple M5 Pro (18c/18t)
 memory : 64.0 GiB
 os : macOS 26.4.1
 rustc : rustc 1.96.0 (ac68faa20 2026年05月25日)
 rust_opt: opt-level=3, lto=false, codegen-units=16 (default release)
 cpp_cc : Apple clang version 21.0.0 (clang-2100年1月1日.101)
 cpp_opt : -O3 -DNDEBUG -Wall -Wextra -Wno-unused-parameter -Wno-zero-length-array (plus AFF3CT static-lib flags)
building rust [std (scalar, system libm)]
 $ cargo build --release --example bench
building rust [std + libm (portable maths)]
 $ cargo build --release --example bench --features libm
building rust [std + simd]
 $ cargo build --release --example bench --features simd
building rust [std + simd + rayon]
 $ cargo build --release --example bench --features simd rayon
building rust [no_std + libm (scalar)]
 $ cargo build --release --example bench --no-default-features --features no_std
building rust [no_std + libm + simd]
 $ cargo build --release --example bench --no-default-features --features no_std simd
building rust [no_std + libm + simd + scoped]
 $ cargo build --release --example bench --no-default-features --features no_std simd
==========================================================================================
benchmarks
==========================================================================================
=== std (scalar, system libm) (exec=serial) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 10.75 ms 8.58 ms 1.25x | 918.96 ms 1.72 s 0.53x
lte 6144 maxlog 500 375.0 KiB | 12.73 ms 9.93 ms 1.28x | 1.12 s 2.09 s 0.54x
lte 512 logmap 2000 125.0 KiB | 4.30 ms 3.43 ms 1.25x | 935.09 ms 1.29 s 0.72x
ccsds 1784 maxlog 1000 217.8 KiB | 7.22 ms 5.79 ms 1.25x | 1.25 s 2.34 s 0.54x
ccsds 8920 maxlog 200 217.8 KiB | 7.38 ms 5.83 ms 1.27x | 3.79 s 3.19 s 1.19x
ccsds 1784 logmap 400 87.1 KiB | 2.89 ms 2.31 ms 1.25x | 1.32 s 1.90 s 0.69x
rsc1315 1024 maxlog 2000 250.0 KiB | 8.38 ms 6.83 ms 1.23x | 743.65 ms 1.38 s 0.54x
=== std + libm (portable maths) (exec=serial) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 10.78 ms 8.46 ms 1.28x | 916.25 ms 1.91 s 0.48x
lte 6144 maxlog 500 375.0 KiB | 12.61 ms 9.92 ms 1.27x | 1.12 s 2.25 s 0.50x
lte 512 logmap 2000 125.0 KiB | 4.31 ms 3.38 ms 1.28x | 919.31 ms 1.54 s 0.60x
ccsds 1784 maxlog 1000 217.8 KiB | 7.23 ms 5.87 ms 1.23x | 1.25 s 2.62 s 0.48x
ccsds 8920 maxlog 200 217.8 KiB | 7.38 ms 5.79 ms 1.28x | 3.78 s 3.11 s 1.22x
ccsds 1784 logmap 400 87.1 KiB | 2.89 ms 2.39 ms 1.21x | 1.31 s 2.28 s 0.58x
rsc1315 1024 maxlog 2000 250.0 KiB | 8.46 ms 6.67 ms 1.27x | 742.50 ms 1.50 s 0.49x
=== std + simd (exec=serial) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 10.84 ms 8.47 ms 1.28x | 918.32 ms 1.01 s 0.91x
lte 6144 maxlog 500 375.0 KiB | 12.67 ms 9.92 ms 1.28x | 1.12 s 1.21 s 0.92x
lte 512 logmap 2000 125.0 KiB | 4.29 ms 3.38 ms 1.27x | 965.25 ms 1.29 s 0.75x
ccsds 1784 maxlog 1000 217.8 KiB | 7.21 ms 5.80 ms 1.24x | 1.25 s 2.35 s 0.53x
ccsds 8920 maxlog 200 217.8 KiB | 7.38 ms 5.81 ms 1.27x | 3.73 s 3.18 s 1.17x
ccsds 1784 logmap 400 87.1 KiB | 2.89 ms 2.32 ms 1.25x | 1.34 s 1.91 s 0.70x
rsc1315 1024 maxlog 2000 250.0 KiB | 8.48 ms 6.85 ms 1.24x | 741.17 ms 811.34 ms 0.91x
=== std + simd + rayon (exec=rayon) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 10.80 ms 8.46 ms 1.28x | 917.70 ms 73.74 ms 12.44x
lte 6144 maxlog 500 375.0 KiB | 12.69 ms 9.97 ms 1.27x | 1.12 s 84.06 ms 13.35x
lte 512 logmap 2000 125.0 KiB | 4.34 ms 3.37 ms 1.29x | 930.09 ms 109.15 ms 8.52x
ccsds 1784 maxlog 1000 217.8 KiB | 7.58 ms 5.85 ms 1.30x | 1.25 s 196.49 ms 6.38x
ccsds 8920 maxlog 200 217.8 KiB | 7.39 ms 5.80 ms 1.27x | 3.77 s 249.00 ms 15.13x
ccsds 1784 logmap 400 87.1 KiB | 2.90 ms 2.32 ms 1.25x | 1.36 s 148.06 ms 9.22x
rsc1315 1024 maxlog 2000 250.0 KiB | 8.44 ms 6.84 ms 1.23x | 742.06 ms 58.21 ms 12.75x
=== no_std + libm (scalar) (exec=serial) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 10.73 ms 8.65 ms 1.24x | 921.32 ms 1.89 s 0.49x
lte 6144 maxlog 500 375.0 KiB | 12.75 ms 10.15 ms 1.26x | 1.12 s 2.25 s 0.50x
lte 512 logmap 2000 125.0 KiB | 4.35 ms 3.46 ms 1.26x | 969.18 ms 1.54 s 0.63x
ccsds 1784 maxlog 1000 217.8 KiB | 7.21 ms 5.94 ms 1.21x | 1.25 s 2.61 s 0.48x
ccsds 8920 maxlog 200 217.8 KiB | 7.39 ms 5.82 ms 1.27x | 3.80 s 3.12 s 1.22x
ccsds 1784 logmap 400 87.1 KiB | 2.88 ms 2.38 ms 1.21x | 1.40 s 2.19 s 0.64x
rsc1315 1024 maxlog 2000 250.0 KiB | 8.44 ms 6.80 ms 1.24x | 743.21 ms 1.50 s 0.50x
=== no_std + libm + simd (exec=serial) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 10.79 ms 8.43 ms 1.28x | 922.88 ms 1.01 s 0.91x
lte 6144 maxlog 500 375.0 KiB | 12.63 ms 9.92 ms 1.27x | 1.12 s 1.21 s 0.92x
lte 512 logmap 2000 125.0 KiB | 4.31 ms 3.41 ms 1.26x | 958.97 ms 1.50 s 0.64x
ccsds 1784 maxlog 1000 217.8 KiB | 7.28 ms 5.77 ms 1.26x | 1.25 s 2.60 s 0.48x
ccsds 8920 maxlog 200 217.8 KiB | 7.43 ms 5.78 ms 1.28x | 3.73 s 3.88 s 0.96x
ccsds 1784 logmap 400 87.1 KiB | 2.88 ms 2.39 ms 1.20x | 1.35 s 2.27 s 0.60x
rsc1315 1024 maxlog 2000 250.0 KiB | 8.40 ms 6.64 ms 1.26x | 742.17 ms 812.34 ms 0.91x
=== no_std + libm + simd + scoped (exec=scoped) ===
spec K algo frames payload | enc cpp enc rust enc Δ | dec cpp dec rust dec Δ
----------------------------------------------------------------------------------------------------------
lte 512 maxlog 5000 312.5 KiB | 10.78 ms 8.43 ms 1.28x | 918.67 ms 81.06 ms 11.33x
lte 6144 maxlog 500 375.0 KiB | 12.62 ms 9.91 ms 1.27x | 1.12 s 89.19 ms 12.52x
lte 512 logmap 2000 125.0 KiB | 4.29 ms 3.37 ms 1.28x | 1.02 s 139.94 ms 7.30x
ccsds 1784 maxlog 1000 217.8 KiB | 7.20 ms 5.79 ms 1.24x | 1.25 s 219.96 ms 5.68x
ccsds 8920 maxlog 200 217.8 KiB | 7.39 ms 5.93 ms 1.25x | 3.80 s 254.71 ms 14.91x
ccsds 1784 logmap 400 87.1 KiB | 2.90 ms 2.38 ms 1.22x | 1.37 s 167.90 ms 8.14x
rsc1315 1024 maxlog 2000 250.0 KiB | 8.45 ms 6.65 ms 1.27x | 742.73 ms 63.47 ms 11.70x
note: the no_std + scoped row uses a hand-rolled `FrameExecutor`
 backed by `std::thread::scope` declared *inside* the bench
 harness — the library itself is built no_std and spawns
 nothing. Same pattern wraps embassy / RTIC / WASM workers on
 real no_std targets; see examples/custom_executor.rs.
Δ = cpp_us / rust_us (green = Rust >5% faster, red = Rust >5% slower, plain = within noise)