C ++ - 用于将不同维矩集的矩阵相乘的函数

时间:2017-04-16 16:15:10

标签: c++ function matrix matrix-multiplication

我有几个矩阵定义为:

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);

函数调用使矩阵mat1amat2b,矩阵c将存储{{1}的结果}}

我的理解是,我需要创建一个单独的函数来乘以a * bmat3。有没有办法避免它并为所有乘法运算创建单个函数,矩阵由mat4对象组成?或者换句话说,是否可以传递2d数组而不指定任何维度,然后分别传递维度?

3 个答案:

答案 0 :(得分:3)

您可以使用模板别名来减少所有麻烦array<array<...>>,然后为矩阵乘法定义另一个template <M,N,P>

#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;
}

答案 1 :(得分: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; 
}

答案 2 :(得分:1)

我真的很喜欢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
               );

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

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);

注意:您也可以将这些int替换为size_t s,这可能是更好的设计。

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