【问题标题】:C++ - Function to multiply different sets of matrices with different dimensionsC ++ - 将具有不同维度的不同矩阵集相乘的函数
【发布时间】:2017-04-16 16:15:09
【问题描述】:

我有几个矩阵定义为:

array <array <float, 3>, 23> mat1;
array <array <float, 23>, 3> mat2;
array <array <float, 2>, 23> mat3;
array <array <float, 23>, 2> mat4;

我有一个矩阵乘法函数定义如下:

void mat_mult(array <array <float, 3>, 23>& a, array <array <float, 23>, 3>& b, array <array <float, 3>, 3>& c);

函数调用使得矩阵mat1 将是amat2 将是b,矩阵c 将存储a * b 的结果。

我的理解是,我需要创建一个单独的函数来乘以 mat3mat4。有没有办法避免它并为所有乘法运算创建一个函数,矩阵由std::array 对象组成?或者换句话说,是否可以在不指定任何维度的情况下传递二维数组,然后分别传递维度?

【问题讨论】:

  • 你确定 std::array 是这里首选的类型吗?看看this
  • 实际上我认为我犯了一个错误。但是,我正在学习中,我现在不能回到这个特定的项目中。你会说向量是这里的最佳选择吗?
  • 是的,在所有用例的 99.99% 中。我也不认为用向量替换这些类型需要做太多的工作。

标签: c++ function matrix matrix-multiplication


【解决方案1】:

您可以使用模板别名来减少所有麻烦array&lt;array&lt;...&gt;&gt;,然后定义另一个template &lt;M,N,P&gt; 进行矩阵乘法:

#include <iostream>
#include <array>

template <size_t M, size_t N>
using mat2f = std::array<std::array<float,N>, M>;

template <size_t M, size_t N, size_t P>
mat2f<M,P> operator*(const mat2f<M,N>& a, const mat2f<N,P>& b)
{
    mat2f<M,P> c;
    //...
    return c;
}

int main()
{
    mat2f<3,23> a;
    mat2f<23,3> b;
    auto c = a * b;
}

【讨论】:

    【解决方案2】:

    看来我迟到了几分钟。我想确保我提供的答案可以编译(g++-5,带有 -std=c++0x),并且我想在几个例子中检查它的结果与 Octave 的对比。所以本质上,我的建议与@tntxtnt 的建议非常相似:使用模板。

    #include <iostream>
    #include <array>
    
    typedef long unsigned int lui;
    template <lui N,lui M,lui K> 
    std::array<std::array<float,N>,M> mult
    (const std::array<std::array<float,N>,K>  & A, 
    const std::array<std::array<float,K>,M> & B) 
    {
      //of course you should use a more efficient algorithm, right now its     complexity is cubic
     std::array<std::array<float,N>,M> res;
     for(int i=0;i<N;++i)
     {
       for(int j=0;j<M;++j)
    
       {  
         res[i][j]=0;
         for(int k=0;k<K;++k)
           res[i][j]+=A[i][k]*B[k][j];
       }  
     } 
    return res;
    }
    
    template<lui N,lui M> 
    void print_matrix(const std::array<std::array<float,N>,M> & A) 
    {
      for(int i=0;i<N;++i)
     {  
        for(int j=0;j<M;++j)
          std::cout<<A[i][j]<<"   ";
        std::cout<<std::endl;
      }  
    }
    
    int main()
    {
    
    
      std::array<std::array<float,3>,4> A; 
      std::array<std::array<float,4>,2> B; 
    
      A[0][0]=14;A[0][1]=16;A[0][2]=2;A[0][3]=3;
      A[1][0]=12;A[1][1]=1;A[1][2]=3;A[1][3]=14;
      A[2][0]=5;A[2][1]=5;A[2][2]=31;A[2][3]=4;
    
      B[0][0]=1;B[0][1]=3;
      B[1][0]=2;B[1][1]=8;
      B[2][0]=0;B[2][1]=3;
      B[3][0]=-6;B[3][1]=3;
    
      print_matrix<3,4>(A);
      std::cout<<"*******************"<<std::endl;
      print_matrix<4,2>(B);
      std::cout<<"*******************"<<std::endl;
      print_matrix<3,2>(mult<3,2,4>(A,B));
    
      return 0; 
    }
    

    【讨论】:

    • 请原谅新手问题。我注意到template&lt;&gt; 之后没有分号。那么这些模板中的每一个都与以下功能相关联?
    • 是的。粗略地说,这里发生的是编译器将根据您在编译时提供的 N、K、M 的值为 mult 函数生成代码。
    【解决方案3】:

    我真的很喜欢 tntxtnt 的方式,但是有一个答案使用更适合您的问题的类型:

    template <int widthFinal, int sharedSize, int heightFinal> void mat_mult(array<array<float, widthFinal>,sharedSize>& a, array <array <float, sharedSize>, heightFinal>& b, array <array <float, widthFinal>, heightFinal>& c);
    

    这样您就可以一次看到所有内容:

    template <int widthFinal, int sharedSize, int heightFinal>
    void mat_mult (
                   array <array<float, widthFinal>,sharedSize>& a,
                   array <array <float, sharedSize>, heightFinal>& b,
                   array <array <float, widthFinal>, heightFinal>& c
                   );
    

    它使用称为模板的东西(那些 括号)。 用法:

    array <array <float, 2>, 3> mat1;
    array <array <float, 3>, 1> mat2;
    array <array <float, 2>, 1> matResult;
    mat_mult<2,3,1>(mat1, mat2, matResult);
    

    注意:您也可以将那些ints 替换为size_ts,这可能是更好的设计。

    另请注意:您只需要这 3 个(不是 4 个)模板参数,因为您知道(通过矩阵属性)matrix1 的宽度必须等于 matrix2 的高度。我将此属性称为“SharedSize”:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-27
      • 2020-12-06
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      相关资源
      最近更新 更多