【发布时间】:2016-12-13 14:31:07
【问题描述】:
有没有办法使用矩阵的非连续视图
即就像在
arma::mat A = arma::zeros(3,3);
arma::uvec idx = {0,2};
A(idx,idx) += 2;
但是使用矩阵 A 的子视图?
即
arma::subview<double> swA = A.submat(0,0,2,2);
swA(idx,idx) += 2.5;
最后一点不会编译为
error: no match for call to ‘(arma::subview<double>) (arma::uvec&, arma::uvec&)’
swA(idx,idx) += 2.5;
只是为了提供一些可以帮助我使用arma::subviewcs 作为函数参数的上下文。由于A.submat(0,0,2,2) 是rtype,我不能将它作为非常量参数传递给函数,并且在函数内部我需要能够以非连续方式访问元素。
一个最小(不工作)的例子也明白我的意思可能是以下
#include <iostream>
#include <armadillo>
void f(arma::subview<double> x)
{
arma::uvec i = {0,2};
arma::uvec j = {1,2};
x(i,j) += 2.5;
}
int main ()
{
arma::mat A = arma::zeros(5,5);
std::cout << A << std::endl;
f(A.submat(0,0,2,2));
std::cout << A << std::endl;
return 0;
}
gcc 再次返回的地方
error: no match for call to ‘(arma::subview<double>) (arma::uvec&, arma::uvec&)’
解决这个问题的傻事是复制矩阵,将其作为引用传递,然后复制回 A:
#include <iostream>
#include <armadillo>
void f(arma::mat& x)
{
arma::uvec i = {0,2};
arma::uvec j = {1,2};
x(i,j) += 2.5;
}
int main ()
{
arma::mat A = arma::zeros(5,5);
std::cout << A << std::endl;
arma::mat B = A.submat(0,0,2,2);
f(B);
A.submat(0,0,2,2) = B;
std::cout << A << std::endl;
return 0;
}
编译和运行完美,但我需要不惜一切代价避免复制矩阵(A 比 5x5 大得多!)
再次明确,我无法执行以下操作
[...]
void f(arma::mat& x)
{
arma::uvec i = {0,2};
arma::uvec j = {1,2};
x(i,j) += 2.5;
}
[...]
f(A.submat(0,0,2,2));
因为子视图是rtype,我会从 gcc 获得
invalid initialization of non-const reference of type ‘arma::mat& {aka arma::Mat<double>&}’ from an rvalue of type ‘arma::mat {aka arma::Mat<double>}
我遇到了麻烦(只是一个实现问题,不在开发人员的 TODO 列表中)还是有比我更聪明的人提供的优雅解决方案?
谢谢!
旁注:
- 如果在那里做这样的事情是微不足道的,我愿意将线性代数库更改为其他人(例如 Eigen 或其他),但我宁愿不这样做,因为我已经使用犰狳多年而且我一直很满意...
- 我知道使用循环和更简单的子视图在我展示的更简单的代码中获得相同结果的可能性,但实际代码更复杂,并且此子视图将用于矩阵运算,所以我必须循环并复制临时对象中的子矩阵,我想避免这种情况
【问题讨论】:
-
也许写一个实现该功能的补丁并发送给犰狳开发者?
-
我也需要这样的功能。我避免这种情况的唯一方法是做一些讨厌的指针算术并直接修改值。但这不如重新排序值和进行矩阵运算快。有没有其他人有更好的方法?