51 nTapers =
static_cast<int>(std::floor(2.0 * halfBandwidth - 1.0));
53 const int N = sym ? nSamples : nSamples + 1;
55 const double W = halfBandwidth /
static_cast<double>(N);
61 VectorXd offdiag(N > 1 ? N - 1 : 0);
63 const double cosW = std::cos(2.0 * DPSS_PI * W);
65 for (
int i = 0; i < N; ++i) {
66 const double val = (
static_cast<double>(N - 1) - 2.0 *
static_cast<double>(i)) / 2.0;
67 diag[i] = val * val * cosW;
70 for (
int i = 0; i < N - 1; ++i) {
71 offdiag[i] =
static_cast<double>(i + 1) *
static_cast<double>(N - i - 1) / 2.0;
75 MatrixXd T = MatrixXd::Zero(N, N);
76 for (
int i = 0; i < N; ++i)
78 for (
int i = 0; i < N - 1; ++i) {
79 T(i, i + 1) = offdiag[i];
80 T(i + 1, i) = offdiag[i];
83 SelfAdjointEigenSolver<MatrixXd> solver(T);
86 const MatrixXd& allEigenvectors = solver.eigenvectors();
95 for (
int m = 1; m < N; ++m)
96 kernel[m] = std::sin(2.0 * DPSS_PI * W * m) / (DPSS_PI * m);
98 for (
int k = 0; k < nTapers; ++k) {
99 const int idx = N - 1 - k;
102 VectorXd taper = allEigenvectors.col(idx);
103 const double norm = taper.norm();
111 result.
matTapers.row(k) = taper.transpose();
114 double ratio = kernel[0] * taper.squaredNorm();
115 for (
int m = 1; m < N; ++m)
116 ratio += 2.0 * kernel[m] * taper.head(N - m).dot(taper.tail(N - m));
124 result.
matTapers.conservativeResize(nKeep, Eigen::NoChange);
128 result.
matTapers.conservativeResize(Eigen::NoChange, nSamples);