我们试图理解MATLAB的准确函数,想为我们的理解编写C / C ++代码。 有人可以用样本/伪代码帮助我们吗?
根据文件 ,
该函数处理输入如下:
那么,转换为C ++(这是未经测试的代码),
template< typename sub_it, typename val_it, typename out_it, typename fun = std::plus< typename std::iterator_traits< val_it >::value_type >, typename T = typename fun::result_type > out_it accumarray( sub_it first_index, sub_it last_index, val_it first_value, // val_it last_value, -- 1 value per index out_it first_out, fun f = fun(), T fillval = T() ) { std::size_t sz = std::max_element( first_index, last_index ); // 1. Get size. std::vector< bool > used_indexes; // 2-3. remember which indexes are used std::fill_n( first_out, sz, T() ); // 4. initialize output while ( first_index != last_index ) { std::size_t index = * first_index; used_indexes[ index ] = true; // 2-3. remember that this index was used first_out[ index ] = f( first_out[ index ], * first_value ); // 5. accumulate ++ first_value; ++ first_index; } // If fill is different from zero, reinitialize untouched values if ( fillval != T() ) { out_it fill_it = first_out; for ( std::vector< bool >::iterator used_it = used_indexes.begin(); used_it != used_indexes.end(); ++ used_it ) { if ( * used_it ) * fill_it = fillval; } } return first_out + sz; }
这有一些缺点,例如,对整个列向量重复调用累加函数而不是一次。 输出放在first_out
引用的预分配存储中。 索引向量必须与值向量的大小相同。 但是应该很好地捕获大多数function。
非常感谢您的回复。 我们能够在C ++中完全理解和实现它(我们使用armadillo )。 这是代码:
colvec TestProcessing::accumarray(icolvec cf, colvec T, double nf, int p) { /* ******* Description ******* here cf is the matrix of indices T is the values whose data is to be accumulted in the output array S. if T is not given (or is scaler)then accumarray simply converts to calculation of histogram of the input data nf is the the size of output Array nf >= max(cf) so pass the argument accordingly p is not used in the function ********************************/ colvec S; // output Array S.set_size(int(nf)); // preallocate the output array for(int i = 0 ; i < (int)nf ; i++) { // find the indices in cf corresponding to 1 to nf // and store in unsigned integer array q1 uvec q1 = find(cf == (i+1)); vec q ; double sum1 = 0 ; if(!q1.is_empty()) { q = T.elem(q1) ; // find the elements in T having indices in q1 // make sure q1 is not empty sum1 = arma::sum(q); // calculate the sum and store in output array S(i) = sum1; } // if q1 is empty array just put 0 at that particular location else { S(i) = 0 ; } } return S; }
希望这对其他人也有帮助! 再次感谢所有贡献的人:)
这就是我想出的。 注意:我追求可读性(因为你想要最好地理解),而不是进行优化。 哦,我从来没有使用过MATLAB,我刚才看到了这个样本:
val = 101:105; subs = [1; 2; 4; 2; 4] subs = 1 2 4 2 4 A = accumarray(subs, val) A = 101 % A(1) = val(1) = 101 206 % A(2) = val(2)+val(4) = 102+104 = 206 0 % A(3) = 0 208 % A(4) = val(3)+val(5) = 103+105 = 208
无论如何,这是代码示例:
#include #include #include #include
除了Vicky Budhiraja“犰狳”的例子,这个是一个2D版本的accumarray使用类似语义而不是matlab函数:
arma::mat accumarray (arma::mat& subs, arma::vec& val, arma::rowvec& sz) { arma::u32 ar = sz.col(0)(0); arma::u32 ac = sz.col(1)(0); arma::mat A; A.set_size(ar, ac); for (arma::u32 r = 0; r < ar; ++r) { for (arma::u32 c = 0; c < ac; ++c) { arma::uvec idx = arma::find(subs.col(0) == r && subs.col(1) == c); if (!idx.is_empty()) A(r, c) = arma::sum(val.elem(idx)); else A(r, c) = 0; } } return A; }
sz输入是一个两列向量,包含:输出矩阵A的num rows / num cols。子矩阵是2列,具有相同的num行val。 num行的val基本上是sz.rows由sz.cols。
sz(大小)输入不是必需的,可以通过搜索子列中的max来轻松推断。
arma::u32 sz_rows = arma::max(subs.col(0)) + 1; arma::u32 sz_cols = arma::max(subs.col(1)) + 1;
要么
arma::u32 sz_rows = arma::max(subs.col(0)) + 1; arma::u32 sz_cols = val.n_elem / sz_rows;
输出矩阵现在是:
arma::mat A (sz_rows, sz_cols);
准确的function变成:
arma::mat accumarray (arma::mat& subs, arma::vec& val) { arma::u32 sz_rows = arma::max(subs.col(0)) + 1; arma::u32 sz_cols = arma::max(subs.col(1)) + 1; arma::mat A (sz_rows, sz_cols); for (arma::u32 r = 0; r < sz_rows; ++r) { for (arma::u32 c = 0; c < sz_cols; ++c) { arma::uvec idx = arma::find(subs.col(0) == r && subs.col(1) == c); if (!idx.is_empty()) A(r, c) = arma::sum(val.elem(idx)); else A(r, c) = 0; } } return A; }
例如 :
arma::vec val = arma::regspace(101, 106); arma::mat subs; subs << 0 << 0 << arma::endr << 1 << 1 << arma::endr << 2 << 1 << arma::endr << 0 << 0 << arma::endr << 1 << 1 << arma::endr << 3 << 0 << arma::endr; arma::mat A = accumarray (subs, val); A.raw_print("A =");
产生这个结果:
A = 205 0 0 207 0 103 106 0
这个例子可以在这里找到: http ://fr.mathworks.com/help/matlab/ref/accumarray.html?requestedDomain = indice,其中matlab是1基。
不幸的是,以前的代码不适合大矩阵。 两个for-loop在中间的向量中找到是非常糟糕的事情。 代码很好理解这个概念,但可以像这样一个单循环优化:
arma::mat accumarray(arma::mat& subs, arma::vec& val) { arma::u32 ar = arma::max(subs.col(0)) + 1; arma::u32 ac = arma::max(subs.col(1)) + 1; arma::mat A(ar, ac); A.zeros(); for (arma::u32 r = 0; r < subs.n_rows; ++r) A(subs(r, 0), subs(r, 1)) += val(r); return A; }
唯一的变化是:
函数的一维版本(向量)可以是:
arma::vec accumarray (arma::ivec& subs, arma::vec& val) { arma::u32 num_elems = arma::max(subs) + 1; arma::vec A (num_elems); A.zeros(); for (arma::u32 r = 0; r < subs.n_rows; ++r) A(subs(r)) += val(r); return A; }
用于测试1D版本:
arma::vec val = arma::regspace(101, 105); arma::ivec subs; subs << 0 << 2 << 3 << 2 << 3; arma::vec A = accumarray(subs, val); A.raw_print("A =");
结果符合matlab示例(参见上一个链接)
A = 101 0 206 208
这不是matlab accumarray函数的严格副本。 例如,matlab函数允许输出尺寸由sz定义的vec / mat,该尺寸大于sub / val duo的intrinsec尺寸。
也许这可以成为添加到犰狳api的想法。 允许单个界面用于不同的维度和类型。
以上就是c/c++开发分享在C / C ++中是否有一个accumarray()的例子相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/559921.html