X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fmatrix.cpp;h=840dbd7c794cd639d8763497998afd2ac5aaf914;hp=dc2105ae26b85c20bdec58a95ff14bf898534898;hb=41e8c15b635c78bfbc677e7f1c00ce5f3ca97f1d;hpb=96be7a17790700998e2d071e00ad5c1ffb4a2d3e diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index dc2105ae..840dbd7c 100644 --- a/ginac/matrix.cpp +++ b/ginac/matrix.cpp @@ -3,7 +3,7 @@ * Implementation of symbolic matrices */ /* - * GiNaC Copyright (C) 1999-2018 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2020 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -140,13 +140,11 @@ void matrix::read_archive(const archive_node &n, lst &sym_lst) m.reserve(row * col); // XXX: default ctor inserts a zero element, we need to erase it here. m.pop_back(); - auto first = n.find_first("m"); - auto last = n.find_last("m"); - ++last; - for (auto i=first; i != last; ++i) { + auto range = n.find_property_range("m", "m"); + for (auto i=range.begin; i != range.end; ++i) { ex e; n.find_ex_by_loc(i, e, sym_lst); - m.push_back(e); + m.emplace_back(e); } } GINAC_BIND_UNARCHIVER(matrix); @@ -1097,17 +1095,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 +1129,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