Skip to main content

comnum_waveform/ofdm/
detection.rs

1//! MIMO-OFDM: per-subcarrier detection.
2//!
3//! With a cyclic prefix longer than the channel, every subcarrier $k$ of every symbol
4//! sees a flat MIMO channel, $y_{k} = H_{k} x_{k} + w_{k}$, with
5//! $H_{k} = \sum_{l} H_{l}\, e^{-j 2\pi k d_{l}/N}$. [`detect`] applies any detector of
6//! `comnum_mimo` to every resource element — a thin wrapper, as the detectors know nothing
7//! of the waveform (ADR 0009).
8//!
9//! # Examples
10//! ```
11//! use comnum_waveform::ofdm::detection::detect;
12//! use comnum_mimo::detection::Linear;
13//! use comnum_mapping::constellation::Constellation;
14//! use comnum_math::{linalg::{identity, matvec}, C64};
15//! let c = Constellation::qam(4)?.normalized();
16//! let h = vec![identity(2); 3];                             // three REs, 2 × 2
17//! let x: Vec<Vec<C64>> = (0..3).map(|i| vec![c.points()[i], c.points()[3 - i]]).collect();
18//! let y: Vec<Vec<C64>> = h.iter().zip(&x).map(|(h, x)| matvec(&h.view(), x)).collect();
19//! let d = detect(&h, &y, 0.01, &Linear::mmse(c))?;
20//! assert_eq!(d[1], vec![1, 2]);
21//! # Ok::<(), comnum_core::Error>(())
22//! ```
23//!
24//! # References
25//!
26//! 1. G. L. Stüber, J. R. Barry, S. W. McLaughlin, Y. Li, M. A. Ingram and T. G. Pratt,
27//!    "Broadband MIMO-OFDM wireless communications," *Proc. IEEE*, 92(2), 271–294, 2004.
28
29use comnum_core::{Result, same_len};
30use comnum_math::C64;
31use comnum_math::linalg::CMat;
32use comnum_mimo::detection::MimoDetector;
33
34/// Detect every resource element: `h[i]` and `y[i]` are the channel ($n_{r} \times n_{t}$)
35/// and the received vector of RE `i`. Returns the labels of every RE.
36///
37/// # Errors
38/// [`comnum_core::Error::Shape`] for inconsistent lengths, and the errors of the detector.
39pub fn detect(h: &[CMat], y: &[Vec<C64>], noise_var: f64, detector: &dyn MimoDetector) -> Result<Vec<Vec<usize>>> {
40    same_len(h.len(), y.len(), "channels and received vectors")?;
41    h.iter().zip(y).map(|(h, y)| detector.detect(&h.view(), y, noise_var)).collect()
42}