Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Constexpr行列式(二维std::数组)_C++_C++14_Linear Algebra_Constexpr - Fatal编程技术网

C++ Constexpr行列式(二维std::数组)

C++ Constexpr行列式(二维std::数组),c++,c++14,linear-algebra,constexpr,C++,C++14,Linear Algebra,Constexpr,我需要编写一个constexpr函数,在编译时计算行列式。最明显的解决方案是使用拉普拉斯展开。支持C++14 #include <array> #include <utility> constexpr int get_cofactor_coef(int i, int j) { return (i + j) % 2 == 0 ? 1 : -1; } template <int N> constexpr int determinant(const st

我需要编写一个constexpr函数,在编译时计算行列式。最明显的解决方案是使用拉普拉斯展开。支持C++14

#include <array>
#include <utility>

constexpr int get_cofactor_coef(int i, int j) {
    return (i + j) % 2 == 0 ? 1 : -1;
}

template <int N>
constexpr int determinant(const std::array<std::array<int, N>, N>& a) {
    int det = 0;

    for (size_t i = 0u; i < N; ++i) {
        det += get_cofactor_coef(i, 1) * a[i][0] * determinant<N-1>(GET_SUBMATRIX_OF_A<N-1, I, J>(a);
    }

    return det;
}

template <>
constexpr int determinant<2>(const std::array<std::array<int, 2>, 2>& a) {
    return a[0][0] * a[1][1] - a[0][1] * a[1][0];
}

template <>
constexpr int determinant<1>(const std::array<std::array<int, 1>, 1>& a) {
    return a[0][0];
}
#包括
#包括
constexpr int get_cofactor_coef(int i,int j){
返回(i+j)%2==0?1:-1;
}
模板
constexpr int行列式(const std::array&a){
int-det=0;
用于(尺寸i=0u;i
问题是我完全不知道如何编写
GET\u SUBMATRIX\u OF_A

我知道我需要:

  • 生成一个序列(使用
    std::integer\u序列
  • 从该序列中排除第i行
  • 复制除第一(0)列以外的所有列
  • 我的constexpr技能几乎不存在。直接尝试将
    a
    传递给另一个函数会导致奇怪的错误,如错误:“*&a”不是常量表达式


    非常感谢您的帮助!

    这里是一个示例实现。它可能会更短或更优雅,但这是一个起点。事实上,我刚刚意识到您的矩阵是正方形的,因此在下面的代码中完全可以删除一些模板参数

    正如我在评论中提到的,对于C++17及更高版本,很可能根本不需要这些

    首先,让我们定义一些样板,让我们创建并索引一个遗漏值的序列(即,要跳过的行):

    #包括
    //基于https://stackoverflow.com/a/32223343.
    模板
    结构偏移量\序列\合并;
    模板
    结构偏移量\序列\合并
    :std::索引_序列
    { };
    模板
    使用make_excluded_index_sequence=offset_sequence_merge;
    
    现在让我们用它来提取子矩阵:

    #include <array>
    template <class T, std::size_t N, std::size_t... Indices>
    constexpr std::array<T, sizeof...(Indices)> extract_columns (
        std::array<T, N> const & source, std::index_sequence<Indices...>) {
      return { source.at(Indices)... };
    }
    
    template <class T, std::size_t N>
    constexpr std::array<T, N - 1> drop_first_column (
        std::array<T, N> const & source) {
      return extract_columns(source, make_excluded_index_sequence<0, N>());
    }
    
    template <class T, std::size_t Rows, std::size_t Cols, std::size_t... RowIndices>
    constexpr auto create_sub_matrix (
        std::array<std::array<T, Cols>, Rows> const & source,
        std::index_sequence<RowIndices...>) 
        -> std::array<std::array<T, Cols - 1>, sizeof...(RowIndices)> {
      return { drop_first_column(source.at(RowIndices))... };
    }
    
    template <std::size_t ExcludedRow, class T, std::size_t Rows, std::size_t Cols>
    constexpr auto create_sub_matrix (
        std::array<std::array<T, Cols>, Rows> const & source)
        -> std::array<std::array<T, Cols - 1>, Rows - 1> {
      return create_sub_matrix(source,
        make_excluded_index_sequence<ExcludedRow, Rows>());
    }
    
    #包括:

    #包括
    #包括
    模板
    无效打印顺序(标准::整数顺序常量&/*顺序*/){
    
    std::cout问题在于
    const
    std::array::operator[]
    (返回
    T&
    )直到C++17才是constexpr,这使得设置次要元素变得困难

    但是,有一个转义图案填充,即
    std::get(std::array&)
    是constexpr,对结果执行指针算法是完全合法的,因此我们可以重写

    a[i]  // constexpr since C++17
    
    作为


    请记住,
    const
    std::array::operator[]
    已经是C++14中的
    constepr
    ,因此我们不需要重写次要结构的RHS。

    使用C++17是一个选项吗?其中还有许多函数是constepr,例如,这意味着您几乎可以编写“标准”了代码仍然是constexpr。不幸的是否:我被明确告知使用c++14标准…啊,很好,我没有意识到数组上的
    std::get
    。比我的代码短得多!非常感谢!我自己永远不会得到这个!太被c++17宠坏了
    #include <iostream>
    #include <string>
    
    template <class T>
    void print_seq (std::integer_sequence<T> const & /* seq */) {
      std::cout << '\n';
    }
    
    template <class T, T Head, T... Tail>
    void print_seq (std::integer_sequence<T, Head, Tail...> const & /* seq */) {
      std::cout << Head << ' ';
      print_seq(std::integer_sequence<T, Tail...>{});
    }
    
    template <class T, std::size_t N>
    void print_array (std::array<T, N> const & src) {
      std::string sep = "";
      for (auto const & e : src) {
        std::cout << sep << e;
        sep = " ";
      }
      std::cout << '\n';
    }
    
    template <class T, std::size_t N, std::size_t M>
    void print_matrix (std::array<std::array<T, N>, M> const & src) {
      for (auto const & row : src) { print_array(row); }
    }
    
    int main () {
      auto indexSeqA = make_excluded_index_sequence<0, 3>(); print_seq(indexSeqA);
      auto indexSeqB = make_excluded_index_sequence<1, 3>(); print_seq(indexSeqB);
      auto indexSeqC = make_excluded_index_sequence<2, 3>(); print_seq(indexSeqC);
      std::cout << '\n';
    
      std::array<int, 3> arr = { 1, 7, 9 };
      print_array(arr); std::cout << '\n';
    
      std::array<std::array<int, 3>, 3> matrix = {{
          { 0, 1, 2 }
        , { 3, 4, 5 }
        , { 6, 7, 8 }
      }};
      print_matrix(matrix); std::cout << '\n';
    
      print_matrix(create_sub_matrix<0>(matrix)); std::cout << '\n';
      print_matrix(create_sub_matrix<1>(matrix)); std::cout << '\n';
    }
    
    a[i]  // constexpr since C++17
    
    (&std::get<0>(a))[i]  // constexpr in C++14!!
    
    template<std::size_t N>
    constexpr std::array<std::array<int, N - 1>, N - 1>
    get_submatrix_of_a(const std::array<std::array<int, N>, N>& a, int i, int j) {
        std::array<std::array<int, N - 1>, N - 1> r{};
        for (int ii = 0; ii != N - 1; ++ii)
            for (int jj = 0; jj != N - 1; ++jj)
                (&std::get<0>(((&std::get<0>(r))[ii])))[jj] = a[ii + (ii >= i ? 1 : 0)][jj + (jj >= j ? 1 : 0)];
        return r;
    }