基于Eigen库将Matlab转C++:三维矩阵初始化与逐元素乘法问题
Hey there! Let's break down your Eigen-to-Matlab conversion problems one by one—they're common pitfalls when switching between the two, so you're not alone here.
1. Initializing a 3D Tensor (SMat) from a 2D Matrix (S)
First, keep in mind that Eigen's Matrix type is strictly for 2D data. For 3D arrays, you'll need to use Eigen's Tensor module (don't forget to include <Eigen/Tensor> in your code, and link against Tensor components if your build setup requires it).
Your S is a 10×181 matrix, and you want to create a 26×10×181 3D tensor SMat. Depending on how you want to populate SMat (e.g., copying S into every slice along the 26-length dimension), here are two straightforward approaches:
Option 1: Explicit slice loop (readable and flexible)
If you need to set each 10×181 slice of SMat to the value of S:
#include <Eigen/Core> #include <Eigen/Tensor> // Assume your 2D matrix is already defined and populated Eigen::Matrix<double, 10, 181> S; // Initialize the 3D tensor (dimensions ordered as: [26, 10, 181]) Eigen::Tensor<double, 3> SMat(26, 10, 181); for (int iFreq = 0; iFreq < 26; ++iFreq) { // Get a reference to the iFreq-th 2D slice of SMat auto slice = SMat.chip(iFreq, 0); // chip(target_index, axis_to_chop) // Map the 2D matrix S to a tensor and assign it to the slice slice = Eigen::TensorMap<Eigen::Tensor<double, 2>>(S.data(), 10, 181); }
Option 2: Broadcast the 2D matrix (concise)
If you want to "broadcast" S across the first dimension to fill all 26 slices in one go, use Eigen's built-in broadcast method:
// Convert your 2D matrix S to a 2D tensor first Eigen::Tensor<double, 2> S_tensor(S.data(), 10, 181); // Broadcast along the first dimension (26 copies), keep the other two dimensions unchanged Eigen::Tensor<double, 3> SMat = S_tensor.broadcast(Eigen::array<long, 3>{26, 1, 1});
2. Indexing & Element-wise Multiplication Issues
A key difference to remember: Eigen uses 0-based indexing, while Matlab uses 1-based. You'll need to subtract 1 from any indices you used in Matlab to match Eigen's system. Let's map each Matlab index to its Eigen equivalent:
Matlab → Eigen Index Mapping
| Matlab Syntax | Eigen Equivalent (0-adjusted) |
|---|---|
delay(angle,:) | If delay is a Matrix<double, 181, 10>: delay.row(angle - 1) (returns a 1×10 row vector) |
S(:,angle) | If S is a Matrix<double, 10, 181>: S.col(angle - 1) (returns a 10×1 column vector) |
StMat(iFreq,:,angle) | If StMat is a Tensor<double, 3> (dimensions [26,10,181]): StMat.chip(iFreq, 0).chip(angle, 1) (returns a 10-element tensor, which you can convert to a vector if needed) |
Fixing Element-wise Multiplication Errors
Your error likely comes from dimension mismatches—Eigen requires explicit broadcasting (unlike Matlab's implicit behavior). Let's address the two common scenarios:
Scenario 1: Scalar × Vector multiplication
If your Matlab code is doing something like Freq(iFreq) .* delay(angle,:) (multiplying a single element of Freq with an entire row of delay), this is a simple scalar-vector operation in Eigen:
// Assume Freq is a Matrix<double, 26, 1> and delay is Matrix<double, 181, 10> int iFreq = ...; // your original 1-based index minus 1 (0-based) int angle = ...; // your original 1-based index minus 1 (0-based) Eigen::RowVectorXd result = Freq(iFreq) * delay.row(angle);
Scenario 2: Broadcasting for full element-wise multiplication
If you need to broadcast Freq (26×1) to match delay's dimensions (181×10) for element-wise multiplication, you'll need to use Tensor broadcasting (since Eigen's Matrix doesn't support arbitrary broadcasting):
Eigen::Tensor<double, 1> Freq_tensor(Freq.data(), 26); Eigen::Tensor<double, 2> delay_tensor(delay.data(), 181, 10); // Broadcast Freq to 26×181×10 and delay to 26×181×10, then multiply element-wise auto broadcasted_freq = Freq_tensor.broadcast(Eigen::array<long, 3>{1, 181, 10}); auto broadcasted_delay = delay_tensor.broadcast(Eigen::array<long, 3>{26, 1, 1}); Eigen::Tensor<double, 3> elementwise_product = broadcasted_freq * broadcasted_delay;
Stick to Matrix for 2D data and Tensor for 3D data to avoid confusion with indexing and operations!
内容的提问来源于stack exchange,提问作者Ema

