C ++ - 将具有不同维度的不同矩阵集相乘的函数
C++ - Function to multiply different sets of matrices with different dimensions
我有几个矩阵定义为:
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
将是 a
,mat2
将是 b
,矩阵 c
将存储 [的结果=17=].
我的理解是我需要创建一个单独的函数来乘以 mat3
和 mat4
。有没有办法避免它并为所有乘法运算创建一个函数,矩阵由 std::array
对象组成?或者换句话说,是否可以在不指定任何维度的情况下传递二维数组,然后单独传递维度?
你可以使用模板别名来减少所有的麻烦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;
}
看来我迟到了几分钟。我想确保我提供的答案可以编译(g++-5,with-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;
}
我真的很喜欢 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);
注意:您也可以将那些 int
替换为 size_t
,这可能是更好的设计。
另请注意:您只需要这 3 个(而不是 4 个)模板参数,因为您知道(通过矩阵属性)matrix1 的宽度必须等于 matrix2 的高度。我称这个 属性 "SharedSize":
我有几个矩阵定义为:
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
将是 a
,mat2
将是 b
,矩阵 c
将存储 [的结果=17=].
我的理解是我需要创建一个单独的函数来乘以 mat3
和 mat4
。有没有办法避免它并为所有乘法运算创建一个函数,矩阵由 std::array
对象组成?或者换句话说,是否可以在不指定任何维度的情况下传递二维数组,然后单独传递维度?
你可以使用模板别名来减少所有的麻烦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;
}
看来我迟到了几分钟。我想确保我提供的答案可以编译(g++-5,with-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;
}
我真的很喜欢 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);
注意:您也可以将那些 int
替换为 size_t
,这可能是更好的设计。
另请注意:您只需要这 3 个(而不是 4 个)模板参数,因为您知道(通过矩阵属性)matrix1 的宽度必须等于 matrix2 的高度。我称这个 属性 "SharedSize":