From f243b5cccfd8ff57115f0b0d5ade20bcca23ae1f Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Sat, 9 Mar 2019 18:40:32 +0100 Subject: [PATCH] Refactor matrix::determinant_minor() a bit. Remove special cases for small matrices and for for last column minor computation. Add early return for the case that all minors relevant for one column turn out to be zero. Improve some comments. --- ginac/matrix.cpp | 89 ++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 49 deletions(-) diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index 299cacfc..fb675060 100644 --- a/ginac/matrix.cpp +++ b/ginac/matrix.cpp @@ -1097,17 +1097,8 @@ unsigned matrix::rank(unsigned solve_algo) const * @see matrix::determinant() */ ex matrix::determinant_minor() const { - // for small matrices the algorithm does not make any sense: const unsigned n = this->cols(); - if (n==1) - return m[0].expand(); - if (n==2) - return (m[0]*m[3]-m[2]*m[1]).expand(); - if (n==3) - return (m[0]*m[4]*m[8]-m[0]*m[5]*m[7]- - m[1]*m[3]*m[8]+m[2]*m[3]*m[7]+ - m[1]*m[5]*m[6]-m[2]*m[4]*m[6]).expand(); - + // This algorithm can best be understood by looking at a naive // implementation of Laplace-expansion, like this one: // ex det; @@ -1140,65 +1131,65 @@ ex matrix::determinant_minor() const // calculated in step c-1. We therefore only have to store at most // 2*binomial(n,n/2) minors. - // Unique flipper counter for partitioning into minors - std::vector Pkey; - Pkey.reserve(n); - // key for minor determinant (a subpartition of Pkey) - std::vector Mkey; + // we store the minors in maps, keyed by the rows they arise from + typedef std::vector keyseq; + typedef std::map Rmap; + + Rmap M, N; // minors used in current and next column, respectively + // populate M with dummy unit, to be used as factor in rightmost column + M[keyseq{}] = _ex1; + + // keys to identify minor of M and N (Mkey is a subsequence of Nkey) + keyseq Mkey, Nkey; Mkey.reserve(n-1); - // we store our subminors in maps, keys being the rows they arise from - typedef std::map,class ex> Rmap; - typedef std::map,class ex>::value_type Rmap_value; - Rmap A; - Rmap B; + Nkey.reserve(n); + ex det; - // initialize A with last column: - for (unsigned r=0; r=0; --c) { - Pkey.erase(Pkey.begin(),Pkey.end()); // don't change capacity - Mkey.erase(Mkey.begin(),Mkey.end()); + for (int c=n-1; c>=0; --c) { + Nkey.clear(); + Mkey.clear(); for (unsigned i=0; i0; --fc) { - ++Pkey[fc-1]; - if (Pkey[fc-1]0) for (unsigned j=fc; j