#include #include template using vec = std::array; template using mat = std::array,M>; /* generalized Kronecker delta - antisymmetrizer */ template constexpr int8_t gkd(const std::array& v, const std::array& orig) { bool trans = 0; for(size_t i = 0; i < orig.size(); i++) { size_t cnt = 0; for(size_t j = 0; j < std::min(i + 1,v.size()); j++) if(orig[i] == v[j]) ++cnt; for(size_t j = i + 1; j < v.size(); j++) { if(orig[i] == v[j]) ++cnt; if( v[i] > v[j]) trans += -1; } if(cnt != 1) return 0; } return trans ? -1 : 1; } /* generalized permanent delta - complete symmetrizer * * equivalent to abs(gKd(v,orig)) or is_index_sequence */ template inline constexpr int8_t gpd(const std::array& v, const std::array& orig) { for(auto& i : orig) if(std::count(v.begin(), v.end(), i) != 1) return 0; return 1; } template constexpr auto minor(const mat& a, size_t x, size_t y)->mat requires(N > 0) { mat result; for (size_t i = 0; i < N-1; i++) for (size_t j = 0; j < N-1; j++) result[i][j] = (i < x && j < y) ? a[i ][j ] : (i >= x && j < y) ? a[i + 1][j ] : (i < x && j >= y) ? a[i ][j + 1] : a[i + 1][j + 1] ; return result; } template constexpr double det(const mat& a) requires(N == 1) { return double(a[0][0]); } template constexpr double det(const mat& a) requires(N > 1) { double sum = 0; bool sign = true; for (size_t i = 0; i < a.size(); i++) sum += double((sign += -1) && SIGN ? -1 : 1) * double(a[0][i]) * det(minor(a,0,i)); return sum; } template inline constexpr double perm(const mat& a) requires(N > 0) { return det(a); } template std::ostream &operator<<(std::ostream &os, const mat &v) { for(size_t i = 0; i < N; i++) { os << '['; for(size_t j = 0; j < M; j++) { printf("%+e", (double)v[i][j]); if( j < (M - 1)) os << ", "; } os << ']' << std::endl; } return os; } template void test(const mat& m) { std::cout << m; printf("Permanent: %+f Determinant: %+f\n", perm(m), det(m)); } int main() { mat A = { vec{1,2}, vec{3,4} }; mat B = { vec{-2, 2, -3}, vec{-1, 1, 3}, vec{ 2, 0, -1} }; mat C = { vec{ 1, 2, 3, 4}, vec{ 4, 5, 6, 7}, vec{ 7, 8, 9,10}, vec{10,11,12,13} }; mat D = { vec{ 0, 1, 2, 3, 4}, vec{ 5, 6, 7, 8, 9}, vec{10, 11, 12, 13, 14}, vec{15, 16, 17, 18, 19}, vec{20, 21, 22, 23, 24} }; test(A); std::cout << std::endl; test(B); std::cout << std::endl; test(C); std::cout << std::endl; test(D); return 0; }