【发布时间】:2019-06-25 22:40:17
【问题描述】:
我有以下 C++17 代码,用于生成数组的编译时元组,其中零数组只是为了举例,在我的实现中它们将是完整的(使用 -std=c+ 编译+1z -fconcepts)。
#include <array>
#include <tuple>
#include <cmath>
template <std::size_t nrA, std::size_t ncA, std::size_t nrB, std::size_t ncB,
typename number=double>
constexpr auto operator *(const std::array<std::array<number,ncA>,nrA> & A,
const std::array<std::array<number,ncB>,nrB> & B)
{
std::array<std::array<number,ncB>,nrA> res{} ;
for (auto k=0u;k<ncB;++k)
for (auto i=0u;i<nrA;++i)
for (auto j=0u;j<nrB;++j)
res[i][k] += A[i][j]*B[j][k];
return res ;
}
constexpr auto logg2(const auto N)
{
auto res = 0;
auto n = N;
while (n != 0)
{
n /= 2;
++res;
}
return res;
}
template <std::size_t N,typename number=double>
constexpr auto create_R()
{
return std::array<std::array<double,2*N>,N>{};
}
template <std::size_t N,typename number=double>
constexpr auto create_RT()
{
return std::array<std::array<double,N>,2*N>{};
}
template <std::size_t N,std::size_t ...Is>
constexpr auto make_impl(const std::index_sequence<Is...>)
{
return std::make_tuple(std::make_tuple(create_R<(N >> Is)>()...),
std::make_tuple(create_RT<(N >> Is)>()...));
}
template <std::size_t N,typename number=double>
constexpr auto make()
{
return make_impl<N/2>(std::make_index_sequence<logg2(N/2) - 1>());
}
int main(int argc, char *argv[])
{
const auto n = 4u;
const auto A = std::array<std::array<double,2*n>,2*n>{};
const auto [R,RT] = make<2*n>();
}
我想将make<>()修改为make<>(A),并返回一个结构化绑定[R,RT,As],其中As是一个包含以下数组的元组
A,
std::get<0>(R)*A*std::get<0>(RT),
std::get<1>(R)*std::get<0>(R)*A*std::get<0>(RT)*std::get<1>(RT)
...
我尝试了一段时间,没有找到解决办法。
有什么想法吗?
编辑 1
根据@MaxLanghof 的要求,以下打印矩阵:
template <std::size_t nr, std::size_t nc, typename number=double>
constexpr auto print(const std::array<std::array<number,nc>,nr> & A)
{
for (auto i=0u;i<nr;++i)
{
for (auto j=0u;j<nc;++j)
std::cout << std::right << std::setw(12) << A[i][j];
std::cout << std::endl ;
}
std::cout << std::endl ;
}
并将以下几行添加到main()
print(A);
print(std::get<0>(R)*A*std::get<0>(RT));
print(std::get<1>(R)*std::get<0>(R)*A*std::get<0>(RT)*std::get<1>(RT));
one 获得以下输出
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0
0 0
【问题讨论】:
-
一般来说,如果您添加了一个小样本“输出”。据我了解,A 是(在这种情况下)8x8,
logg2将返回 2,因此R、RT元组中有 2 个条目,A中有 3 个条目。R将包含一个 4x8 和一个 8x16 矩阵,RT一个 8x4 和 16x8 矩阵,As将包含A(8x8),然后......然后其他乘法将不起作用。请检查您的规格/代码。 -
@MaxLanghof 感谢您的评论。我添加了检查矩阵大小是否匹配所需的代码。这个想法是让
make(A)输出一个std::tuple,其中包含打印为结构化绑定的第三个元素(名为As的元素)的矩阵。 -
哦,对了,这是右移,而不是左移。很抱歉造成混乱。
-
@MaxLanghof 感谢您的评论。没问题!我认为添加这部分代码可以大大改善帖子,以便更好地理解和测试。
标签: c++ arrays recursion c++17 compile-time