]> www.ginac.de Git - ginac.git/blob - ginac/matrix.cpp
* bernoulli(): Add Markus Nullmeier's new implementation.
[ginac.git] / ginac / matrix.cpp
1 /** @file matrix.cpp
2  *
3  *  Implementation of symbolic matrices */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <iostream>
24 #include <algorithm>
25 #include <map>
26 #include <stdexcept>
27
28 #include "matrix.h"
29 #include "numeric.h"
30 #include "lst.h"
31 #include "idx.h"
32 #include "indexed.h"
33 #include "power.h"
34 #include "symbol.h"
35 #include "normal.h"
36 #include "print.h"
37 #include "archive.h"
38 #include "utils.h"
39
40 namespace GiNaC {
41
42 GINAC_IMPLEMENT_REGISTERED_CLASS(matrix, basic)
43
44 //////////
45 // default ctor, dtor, copy ctor, assignment operator and helpers:
46 //////////
47
48 /** Default ctor.  Initializes to 1 x 1-dimensional zero-matrix. */
49 matrix::matrix() : inherited(TINFO_matrix), row(1), col(1)
50 {
51         m.push_back(_ex0);
52 }
53
54 void matrix::copy(const matrix & other)
55 {
56         inherited::copy(other);
57         row = other.row;
58         col = other.col;
59         m = other.m;  // STL's vector copying invoked here
60 }
61
62 DEFAULT_DESTROY(matrix)
63
64 //////////
65 // other ctors
66 //////////
67
68 // public
69
70 /** Very common ctor.  Initializes to r x c-dimensional zero-matrix.
71  *
72  *  @param r number of rows
73  *  @param c number of cols */
74 matrix::matrix(unsigned r, unsigned c)
75   : inherited(TINFO_matrix), row(r), col(c)
76 {
77         m.resize(r*c, _ex0);
78 }
79
80 // protected
81
82 /** Ctor from representation, for internal use only. */
83 matrix::matrix(unsigned r, unsigned c, const exvector & m2)
84   : inherited(TINFO_matrix), row(r), col(c), m(m2) {}
85
86 /** Construct matrix from (flat) list of elements. If the list has fewer
87  *  elements than the matrix, the remaining matrix elements are set to zero.
88  *  If the list has more elements than the matrix, the excessive elements are
89  *  thrown away. */
90 matrix::matrix(unsigned r, unsigned c, const lst & l)
91   : inherited(TINFO_matrix), row(r), col(c)
92 {
93         m.resize(r*c, _ex0);
94
95         for (unsigned i=0; i<l.nops(); i++) {
96                 unsigned x = i % c;
97                 unsigned y = i / c;
98                 if (y >= r)
99                         break; // matrix smaller than list: throw away excessive elements
100                 m[y*c+x] = l.op(i);
101         }
102 }
103
104 //////////
105 // archiving
106 //////////
107
108 matrix::matrix(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
109 {
110         if (!(n.find_unsigned("row", row)) || !(n.find_unsigned("col", col)))
111                 throw (std::runtime_error("unknown matrix dimensions in archive"));
112         m.reserve(row * col);
113         for (unsigned int i=0; true; i++) {
114                 ex e;
115                 if (n.find_ex("m", e, sym_lst, i))
116                         m.push_back(e);
117                 else
118                         break;
119         }
120 }
121
122 void matrix::archive(archive_node &n) const
123 {
124         inherited::archive(n);
125         n.add_unsigned("row", row);
126         n.add_unsigned("col", col);
127         exvector::const_iterator i = m.begin(), iend = m.end();
128         while (i != iend) {
129                 n.add_ex("m", *i);
130                 ++i;
131         }
132 }
133
134 DEFAULT_UNARCHIVE(matrix)
135
136 //////////
137 // functions overriding virtual functions from base classes
138 //////////
139
140 // public
141
142 void matrix::print(const print_context & c, unsigned level) const
143 {
144         if (is_a<print_tree>(c)) {
145
146                 inherited::print(c, level);
147
148         } else {
149
150                 if (is_a<print_python_repr>(c))
151                         c.s << class_name() << '(';
152
153                 c.s << "[";
154                 for (unsigned y=0; y<row-1; ++y) {
155                         c.s << "[";
156                         for (unsigned x=0; x<col-1; ++x) {
157                                 m[y*col+x].print(c);
158                                 c.s << ",";
159                         }
160                         m[col*(y+1)-1].print(c);
161                         c.s << "],";
162                 }
163                 c.s << "[";
164                 for (unsigned x=0; x<col-1; ++x) {
165                         m[(row-1)*col+x].print(c);
166                         c.s << ",";
167                 }
168                 m[row*col-1].print(c);
169                 c.s << "]]";
170
171                 if (is_a<print_python_repr>(c))
172                         c.s << ')';
173
174         }
175 }
176
177 /** nops is defined to be rows x columns. */
178 unsigned matrix::nops() const
179 {
180         return row*col;
181 }
182
183 /** returns matrix entry at position (i/col, i%col). */
184 ex matrix::op(int i) const
185 {
186         return m[i];
187 }
188
189 /** returns matrix entry at position (i/col, i%col). */
190 ex & matrix::let_op(int i)
191 {
192         GINAC_ASSERT(i>=0);
193         GINAC_ASSERT(i<nops());
194         
195         return m[i];
196 }
197
198 /** Evaluate matrix entry by entry. */
199 ex matrix::eval(int level) const
200 {
201         // check if we have to do anything at all
202         if ((level==1)&&(flags & status_flags::evaluated))
203                 return *this;
204         
205         // emergency break
206         if (level == -max_recursion_level)
207                 throw (std::runtime_error("matrix::eval(): recursion limit exceeded"));
208         
209         // eval() entry by entry
210         exvector m2(row*col);
211         --level;
212         for (unsigned r=0; r<row; ++r)
213                 for (unsigned c=0; c<col; ++c)
214                         m2[r*col+c] = m[r*col+c].eval(level);
215         
216         return (new matrix(row, col, m2))->setflag(status_flags::dynallocated |
217                                                                                            status_flags::evaluated );
218 }
219
220 ex matrix::subs(const lst & ls, const lst & lr, bool no_pattern) const
221 {
222         exvector m2(row * col);
223         for (unsigned r=0; r<row; ++r)
224                 for (unsigned c=0; c<col; ++c)
225                         m2[r*col+c] = m[r*col+c].subs(ls, lr, no_pattern);
226
227         return matrix(row, col, m2).basic::subs(ls, lr, no_pattern);
228 }
229
230 // protected
231
232 int matrix::compare_same_type(const basic & other) const
233 {
234         GINAC_ASSERT(is_exactly_a<matrix>(other));
235         const matrix &o = static_cast<const matrix &>(other);
236         
237         // compare number of rows
238         if (row != o.rows())
239                 return row < o.rows() ? -1 : 1;
240         
241         // compare number of columns
242         if (col != o.cols())
243                 return col < o.cols() ? -1 : 1;
244         
245         // equal number of rows and columns, compare individual elements
246         int cmpval;
247         for (unsigned r=0; r<row; ++r) {
248                 for (unsigned c=0; c<col; ++c) {
249                         cmpval = ((*this)(r,c)).compare(o(r,c));
250                         if (cmpval!=0) return cmpval;
251                 }
252         }
253         // all elements are equal => matrices are equal;
254         return 0;
255 }
256
257 bool matrix::match_same_type(const basic & other) const
258 {
259         GINAC_ASSERT(is_exactly_a<matrix>(other));
260         const matrix & o = static_cast<const matrix &>(other);
261         
262         // The number of rows and columns must be the same. This is necessary to
263         // prevent a 2x3 matrix from matching a 3x2 one.
264         return row == o.rows() && col == o.cols();
265 }
266
267 /** Automatic symbolic evaluation of an indexed matrix. */
268 ex matrix::eval_indexed(const basic & i) const
269 {
270         GINAC_ASSERT(is_a<indexed>(i));
271         GINAC_ASSERT(is_a<matrix>(i.op(0)));
272
273         bool all_indices_unsigned = static_cast<const indexed &>(i).all_index_values_are(info_flags::nonnegint);
274
275         // Check indices
276         if (i.nops() == 2) {
277
278                 // One index, must be one-dimensional vector
279                 if (row != 1 && col != 1)
280                         throw (std::runtime_error("matrix::eval_indexed(): vector must have exactly 1 index"));
281
282                 const idx & i1 = ex_to<idx>(i.op(1));
283
284                 if (col == 1) {
285
286                         // Column vector
287                         if (!i1.get_dim().is_equal(row))
288                                 throw (std::runtime_error("matrix::eval_indexed(): dimension of index must match number of vector elements"));
289
290                         // Index numeric -> return vector element
291                         if (all_indices_unsigned) {
292                                 unsigned n1 = ex_to<numeric>(i1.get_value()).to_int();
293                                 if (n1 >= row)
294                                         throw (std::runtime_error("matrix::eval_indexed(): value of index exceeds number of vector elements"));
295                                 return (*this)(n1, 0);
296                         }
297
298                 } else {
299
300                         // Row vector
301                         if (!i1.get_dim().is_equal(col))
302                                 throw (std::runtime_error("matrix::eval_indexed(): dimension of index must match number of vector elements"));
303
304                         // Index numeric -> return vector element
305                         if (all_indices_unsigned) {
306                                 unsigned n1 = ex_to<numeric>(i1.get_value()).to_int();
307                                 if (n1 >= col)
308                                         throw (std::runtime_error("matrix::eval_indexed(): value of index exceeds number of vector elements"));
309                                 return (*this)(0, n1);
310                         }
311                 }
312
313         } else if (i.nops() == 3) {
314
315                 // Two indices
316                 const idx & i1 = ex_to<idx>(i.op(1));
317                 const idx & i2 = ex_to<idx>(i.op(2));
318
319                 if (!i1.get_dim().is_equal(row))
320                         throw (std::runtime_error("matrix::eval_indexed(): dimension of first index must match number of rows"));
321                 if (!i2.get_dim().is_equal(col))
322                         throw (std::runtime_error("matrix::eval_indexed(): dimension of second index must match number of columns"));
323
324                 // Pair of dummy indices -> compute trace
325                 if (is_dummy_pair(i1, i2))
326                         return trace();
327
328                 // Both indices numeric -> return matrix element
329                 if (all_indices_unsigned) {
330                         unsigned n1 = ex_to<numeric>(i1.get_value()).to_int(), n2 = ex_to<numeric>(i2.get_value()).to_int();
331                         if (n1 >= row)
332                                 throw (std::runtime_error("matrix::eval_indexed(): value of first index exceeds number of rows"));
333                         if (n2 >= col)
334                                 throw (std::runtime_error("matrix::eval_indexed(): value of second index exceeds number of columns"));
335                         return (*this)(n1, n2);
336                 }
337
338         } else
339                 throw (std::runtime_error("matrix::eval_indexed(): matrix must have exactly 2 indices"));
340
341         return i.hold();
342 }
343
344 /** Sum of two indexed matrices. */
345 ex matrix::add_indexed(const ex & self, const ex & other) const
346 {
347         GINAC_ASSERT(is_a<indexed>(self));
348         GINAC_ASSERT(is_a<matrix>(self.op(0)));
349         GINAC_ASSERT(is_a<indexed>(other));
350         GINAC_ASSERT(self.nops() == 2 || self.nops() == 3);
351
352         // Only add two matrices
353         if (is_ex_of_type(other.op(0), matrix)) {
354                 GINAC_ASSERT(other.nops() == 2 || other.nops() == 3);
355
356                 const matrix &self_matrix = ex_to<matrix>(self.op(0));
357                 const matrix &other_matrix = ex_to<matrix>(other.op(0));
358
359                 if (self.nops() == 2 && other.nops() == 2) { // vector + vector
360
361                         if (self_matrix.row == other_matrix.row)
362                                 return indexed(self_matrix.add(other_matrix), self.op(1));
363                         else if (self_matrix.row == other_matrix.col)
364                                 return indexed(self_matrix.add(other_matrix.transpose()), self.op(1));
365
366                 } else if (self.nops() == 3 && other.nops() == 3) { // matrix + matrix
367
368                         if (self.op(1).is_equal(other.op(1)) && self.op(2).is_equal(other.op(2)))
369                                 return indexed(self_matrix.add(other_matrix), self.op(1), self.op(2));
370                         else if (self.op(1).is_equal(other.op(2)) && self.op(2).is_equal(other.op(1)))
371                                 return indexed(self_matrix.add(other_matrix.transpose()), self.op(1), self.op(2));
372
373                 }
374         }
375
376         // Don't know what to do, return unevaluated sum
377         return self + other;
378 }
379
380 /** Product of an indexed matrix with a number. */
381 ex matrix::scalar_mul_indexed(const ex & self, const numeric & other) const
382 {
383         GINAC_ASSERT(is_a<indexed>(self));
384         GINAC_ASSERT(is_a<matrix>(self.op(0)));
385         GINAC_ASSERT(self.nops() == 2 || self.nops() == 3);
386
387         const matrix &self_matrix = ex_to<matrix>(self.op(0));
388
389         if (self.nops() == 2)
390                 return indexed(self_matrix.mul(other), self.op(1));
391         else // self.nops() == 3
392                 return indexed(self_matrix.mul(other), self.op(1), self.op(2));
393 }
394
395 /** Contraction of an indexed matrix with something else. */
396 bool matrix::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
397 {
398         GINAC_ASSERT(is_a<indexed>(*self));
399         GINAC_ASSERT(is_a<indexed>(*other));
400         GINAC_ASSERT(self->nops() == 2 || self->nops() == 3);
401         GINAC_ASSERT(is_a<matrix>(self->op(0)));
402
403         // Only contract with other matrices
404         if (!is_ex_of_type(other->op(0), matrix))
405                 return false;
406
407         GINAC_ASSERT(other->nops() == 2 || other->nops() == 3);
408
409         const matrix &self_matrix = ex_to<matrix>(self->op(0));
410         const matrix &other_matrix = ex_to<matrix>(other->op(0));
411
412         if (self->nops() == 2) {
413
414                 if (other->nops() == 2) { // vector * vector (scalar product)
415
416                         if (self_matrix.col == 1) {
417                                 if (other_matrix.col == 1) {
418                                         // Column vector * column vector, transpose first vector
419                                         *self = self_matrix.transpose().mul(other_matrix)(0, 0);
420                                 } else {
421                                         // Column vector * row vector, swap factors
422                                         *self = other_matrix.mul(self_matrix)(0, 0);
423                                 }
424                         } else {
425                                 if (other_matrix.col == 1) {
426                                         // Row vector * column vector, perfect
427                                         *self = self_matrix.mul(other_matrix)(0, 0);
428                                 } else {
429                                         // Row vector * row vector, transpose second vector
430                                         *self = self_matrix.mul(other_matrix.transpose())(0, 0);
431                                 }
432                         }
433                         *other = _ex1;
434                         return true;
435
436                 } else { // vector * matrix
437
438                         // B_i * A_ij = (B*A)_j (B is row vector)
439                         if (is_dummy_pair(self->op(1), other->op(1))) {
440                                 if (self_matrix.row == 1)
441                                         *self = indexed(self_matrix.mul(other_matrix), other->op(2));
442                                 else
443                                         *self = indexed(self_matrix.transpose().mul(other_matrix), other->op(2));
444                                 *other = _ex1;
445                                 return true;
446                         }
447
448                         // B_j * A_ij = (A*B)_i (B is column vector)
449                         if (is_dummy_pair(self->op(1), other->op(2))) {
450                                 if (self_matrix.col == 1)
451                                         *self = indexed(other_matrix.mul(self_matrix), other->op(1));
452                                 else
453                                         *self = indexed(other_matrix.mul(self_matrix.transpose()), other->op(1));
454                                 *other = _ex1;
455                                 return true;
456                         }
457                 }
458
459         } else if (other->nops() == 3) { // matrix * matrix
460
461                 // A_ij * B_jk = (A*B)_ik
462                 if (is_dummy_pair(self->op(2), other->op(1))) {
463                         *self = indexed(self_matrix.mul(other_matrix), self->op(1), other->op(2));
464                         *other = _ex1;
465                         return true;
466                 }
467
468                 // A_ij * B_kj = (A*Btrans)_ik
469                 if (is_dummy_pair(self->op(2), other->op(2))) {
470                         *self = indexed(self_matrix.mul(other_matrix.transpose()), self->op(1), other->op(1));
471                         *other = _ex1;
472                         return true;
473                 }
474
475                 // A_ji * B_jk = (Atrans*B)_ik
476                 if (is_dummy_pair(self->op(1), other->op(1))) {
477                         *self = indexed(self_matrix.transpose().mul(other_matrix), self->op(2), other->op(2));
478                         *other = _ex1;
479                         return true;
480                 }
481
482                 // A_ji * B_kj = (B*A)_ki
483                 if (is_dummy_pair(self->op(1), other->op(2))) {
484                         *self = indexed(other_matrix.mul(self_matrix), other->op(1), self->op(2));
485                         *other = _ex1;
486                         return true;
487                 }
488         }
489
490         return false;
491 }
492
493
494 //////////
495 // non-virtual functions in this class
496 //////////
497
498 // public
499
500 /** Sum of matrices.
501  *
502  *  @exception logic_error (incompatible matrices) */
503 matrix matrix::add(const matrix & other) const
504 {
505         if (col != other.col || row != other.row)
506                 throw std::logic_error("matrix::add(): incompatible matrices");
507         
508         exvector sum(this->m);
509         exvector::iterator i = sum.begin(), end = sum.end();
510         exvector::const_iterator ci = other.m.begin();
511         while (i != end)
512                 *i++ += *ci++;
513         
514         return matrix(row,col,sum);
515 }
516
517
518 /** Difference of matrices.
519  *
520  *  @exception logic_error (incompatible matrices) */
521 matrix matrix::sub(const matrix & other) const
522 {
523         if (col != other.col || row != other.row)
524                 throw std::logic_error("matrix::sub(): incompatible matrices");
525         
526         exvector dif(this->m);
527         exvector::iterator i = dif.begin(), end = dif.end();
528         exvector::const_iterator ci = other.m.begin();
529         while (i != end)
530                 *i++ -= *ci++;
531         
532         return matrix(row,col,dif);
533 }
534
535
536 /** Product of matrices.
537  *
538  *  @exception logic_error (incompatible matrices) */
539 matrix matrix::mul(const matrix & other) const
540 {
541         if (this->cols() != other.rows())
542                 throw std::logic_error("matrix::mul(): incompatible matrices");
543         
544         exvector prod(this->rows()*other.cols());
545         
546         for (unsigned r1=0; r1<this->rows(); ++r1) {
547                 for (unsigned c=0; c<this->cols(); ++c) {
548                         if (m[r1*col+c].is_zero())
549                                 continue;
550                         for (unsigned r2=0; r2<other.cols(); ++r2)
551                                 prod[r1*other.col+r2] += (m[r1*col+c] * other.m[c*other.col+r2]).expand();
552                 }
553         }
554         return matrix(row, other.col, prod);
555 }
556
557
558 /** Product of matrix and scalar. */
559 matrix matrix::mul(const numeric & other) const
560 {
561         exvector prod(row * col);
562
563         for (unsigned r=0; r<row; ++r)
564                 for (unsigned c=0; c<col; ++c)
565                         prod[r*col+c] = m[r*col+c] * other;
566
567         return matrix(row, col, prod);
568 }
569
570
571 /** Product of matrix and scalar expression. */
572 matrix matrix::mul_scalar(const ex & other) const
573 {
574         if (other.return_type() != return_types::commutative)
575                 throw std::runtime_error("matrix::mul_scalar(): non-commutative scalar");
576
577         exvector prod(row * col);
578
579         for (unsigned r=0; r<row; ++r)
580                 for (unsigned c=0; c<col; ++c)
581                         prod[r*col+c] = m[r*col+c] * other;
582
583         return matrix(row, col, prod);
584 }
585
586
587 /** Power of a matrix.  Currently handles integer exponents only. */
588 matrix matrix::pow(const ex & expn) const
589 {
590         if (col!=row)
591                 throw (std::logic_error("matrix::pow(): matrix not square"));
592         
593         if (is_ex_exactly_of_type(expn, numeric)) {
594                 // Integer cases are computed by successive multiplication, using the
595                 // obvious shortcut of storing temporaries, like A^4 == (A*A)*(A*A).
596                 if (expn.info(info_flags::integer)) {
597                         numeric b = ex_to<numeric>(expn);
598                         matrix A(row,col);
599                         if (expn.info(info_flags::negative)) {
600                                 b *= -1;
601                                 A = this->inverse();
602                         } else {
603                                 A = *this;
604                         }
605                         matrix C(row,col);
606                         for (unsigned r=0; r<row; ++r)
607                                 C(r,r) = _ex1;
608                         // This loop computes the representation of b in base 2 from right
609                         // to left and multiplies the factors whenever needed.  Note
610                         // that this is not entirely optimal but close to optimal and
611                         // "better" algorithms are much harder to implement.  (See Knuth,
612                         // TAoCP2, section "Evaluation of Powers" for a good discussion.)
613                         while (b!=1) {
614                                 if (b.is_odd()) {
615                                         C = C.mul(A);
616                                         b -= 1;
617                                 }
618                                 b *= _num1_2;  // b /= 2, still integer.
619                                 A = A.mul(A);
620                         }
621                         return A.mul(C);
622                 }
623         }
624         throw (std::runtime_error("matrix::pow(): don't know how to handle exponent"));
625 }
626
627
628 /** operator() to access elements for reading.
629  *
630  *  @param ro row of element
631  *  @param co column of element
632  *  @exception range_error (index out of range) */
633 const ex & matrix::operator() (unsigned ro, unsigned co) const
634 {
635         if (ro>=row || co>=col)
636                 throw (std::range_error("matrix::operator(): index out of range"));
637
638         return m[ro*col+co];
639 }
640
641
642 /** operator() to access elements for writing.
643  *
644  *  @param ro row of element
645  *  @param co column of element
646  *  @exception range_error (index out of range) */
647 ex & matrix::operator() (unsigned ro, unsigned co)
648 {
649         if (ro>=row || co>=col)
650                 throw (std::range_error("matrix::operator(): index out of range"));
651
652         ensure_if_modifiable();
653         return m[ro*col+co];
654 }
655
656
657 /** Transposed of an m x n matrix, producing a new n x m matrix object that
658  *  represents the transposed. */
659 matrix matrix::transpose(void) const
660 {
661         exvector trans(this->cols()*this->rows());
662         
663         for (unsigned r=0; r<this->cols(); ++r)
664                 for (unsigned c=0; c<this->rows(); ++c)
665                         trans[r*this->rows()+c] = m[c*this->cols()+r];
666         
667         return matrix(this->cols(),this->rows(),trans);
668 }
669
670 /** Determinant of square matrix.  This routine doesn't actually calculate the
671  *  determinant, it only implements some heuristics about which algorithm to
672  *  run.  If all the elements of the matrix are elements of an integral domain
673  *  the determinant is also in that integral domain and the result is expanded
674  *  only.  If one or more elements are from a quotient field the determinant is
675  *  usually also in that quotient field and the result is normalized before it
676  *  is returned.  This implies that the determinant of the symbolic 2x2 matrix
677  *  [[a/(a-b),1],[b/(a-b),1]] is returned as unity.  (In this respect, it
678  *  behaves like MapleV and unlike Mathematica.)
679  *
680  *  @param     algo allows to chose an algorithm
681  *  @return    the determinant as a new expression
682  *  @exception logic_error (matrix not square)
683  *  @see       determinant_algo */
684 ex matrix::determinant(unsigned algo) const
685 {
686         if (row!=col)
687                 throw (std::logic_error("matrix::determinant(): matrix not square"));
688         GINAC_ASSERT(row*col==m.capacity());
689         
690         // Gather some statistical information about this matrix:
691         bool numeric_flag = true;
692         bool normal_flag = false;
693         unsigned sparse_count = 0;  // counts non-zero elements
694         exvector::const_iterator r = m.begin(), rend = m.end();
695         while (r != rend) {
696                 lst srl;  // symbol replacement list
697                 ex rtest = r->to_rational(srl);
698                 if (!rtest.is_zero())
699                         ++sparse_count;
700                 if (!rtest.info(info_flags::numeric))
701                         numeric_flag = false;
702                 if (!rtest.info(info_flags::crational_polynomial) &&
703                          rtest.info(info_flags::rational_function))
704                         normal_flag = true;
705                 ++r;
706         }
707         
708         // Here is the heuristics in case this routine has to decide:
709         if (algo == determinant_algo::automatic) {
710                 // Minor expansion is generally a good guess:
711                 algo = determinant_algo::laplace;
712                 // Does anybody know when a matrix is really sparse?
713                 // Maybe <~row/2.236 nonzero elements average in a row?
714                 if (row>3 && 5*sparse_count<=row*col)
715                         algo = determinant_algo::bareiss;
716                 // Purely numeric matrix can be handled by Gauss elimination.
717                 // This overrides any prior decisions.
718                 if (numeric_flag)
719                         algo = determinant_algo::gauss;
720         }
721         
722         // Trap the trivial case here, since some algorithms don't like it
723         if (this->row==1) {
724                 // for consistency with non-trivial determinants...
725                 if (normal_flag)
726                         return m[0].normal();
727                 else
728                         return m[0].expand();
729         }
730         
731         // Compute the determinant
732         switch(algo) {
733                 case determinant_algo::gauss: {
734                         ex det = 1;
735                         matrix tmp(*this);
736                         int sign = tmp.gauss_elimination(true);
737                         for (unsigned d=0; d<row; ++d)
738                                 det *= tmp.m[d*col+d];
739                         if (normal_flag)
740                                 return (sign*det).normal();
741                         else
742                                 return (sign*det).normal().expand();
743                 }
744                 case determinant_algo::bareiss: {
745                         matrix tmp(*this);
746                         int sign;
747                         sign = tmp.fraction_free_elimination(true);
748                         if (normal_flag)
749                                 return (sign*tmp.m[row*col-1]).normal();
750                         else
751                                 return (sign*tmp.m[row*col-1]).expand();
752                 }
753                 case determinant_algo::divfree: {
754                         matrix tmp(*this);
755                         int sign;
756                         sign = tmp.division_free_elimination(true);
757                         if (sign==0)
758                                 return _ex0;
759                         ex det = tmp.m[row*col-1];
760                         // factor out accumulated bogus slag
761                         for (unsigned d=0; d<row-2; ++d)
762                                 for (unsigned j=0; j<row-d-2; ++j)
763                                         det = (det/tmp.m[d*col+d]).normal();
764                         return (sign*det);
765                 }
766                 case determinant_algo::laplace:
767                 default: {
768                         // This is the minor expansion scheme.  We always develop such
769                         // that the smallest minors (i.e, the trivial 1x1 ones) are on the
770                         // rightmost column.  For this to be efficient, empirical tests
771                         // have shown that the emptiest columns (i.e. the ones with most
772                         // zeros) should be the ones on the right hand side -- although
773                         // this might seem counter-intuitive (and in contradiction to some
774                         // literature like the FORM manual).  Please go ahead and test it
775                         // if you don't believe me!  Therefore we presort the columns of
776                         // the matrix:
777                         typedef std::pair<unsigned,unsigned> uintpair;
778                         std::vector<uintpair> c_zeros;  // number of zeros in column
779                         for (unsigned c=0; c<col; ++c) {
780                                 unsigned acc = 0;
781                                 for (unsigned r=0; r<row; ++r)
782                                         if (m[r*col+c].is_zero())
783                                                 ++acc;
784                                 c_zeros.push_back(uintpair(acc,c));
785                         }
786                         std::sort(c_zeros.begin(),c_zeros.end());
787                         std::vector<unsigned> pre_sort;
788                         for (std::vector<uintpair>::const_iterator i=c_zeros.begin(); i!=c_zeros.end(); ++i)
789                                 pre_sort.push_back(i->second);
790                         std::vector<unsigned> pre_sort_test(pre_sort); // permutation_sign() modifies the vector so we make a copy here
791                         int sign = permutation_sign(pre_sort_test.begin(), pre_sort_test.end());
792                         exvector result(row*col);  // represents sorted matrix
793                         unsigned c = 0;
794                         for (std::vector<unsigned>::const_iterator i=pre_sort.begin();
795                                  i!=pre_sort.end();
796                                  ++i,++c) {
797                                 for (unsigned r=0; r<row; ++r)
798                                         result[r*col+c] = m[r*col+(*i)];
799                         }
800                         
801                         if (normal_flag)
802                                 return (sign*matrix(row,col,result).determinant_minor()).normal();
803                         else
804                                 return sign*matrix(row,col,result).determinant_minor();
805                 }
806         }
807 }
808
809
810 /** Trace of a matrix.  The result is normalized if it is in some quotient
811  *  field and expanded only otherwise.  This implies that the trace of the
812  *  symbolic 2x2 matrix [[a/(a-b),x],[y,b/(b-a)]] is recognized to be unity.
813  *
814  *  @return    the sum of diagonal elements
815  *  @exception logic_error (matrix not square) */
816 ex matrix::trace(void) const
817 {
818         if (row != col)
819                 throw (std::logic_error("matrix::trace(): matrix not square"));
820         
821         ex tr;
822         for (unsigned r=0; r<col; ++r)
823                 tr += m[r*col+r];
824         
825         if (tr.info(info_flags::rational_function) &&
826                 !tr.info(info_flags::crational_polynomial))
827                 return tr.normal();
828         else
829                 return tr.expand();
830 }
831
832
833 /** Characteristic Polynomial.  Following mathematica notation the
834  *  characteristic polynomial of a matrix M is defined as the determiant of
835  *  (M - lambda * 1) where 1 stands for the unit matrix of the same dimension
836  *  as M.  Note that some CASs define it with a sign inside the determinant
837  *  which gives rise to an overall sign if the dimension is odd.  This method
838  *  returns the characteristic polynomial collected in powers of lambda as a
839  *  new expression.
840  *
841  *  @return    characteristic polynomial as new expression
842  *  @exception logic_error (matrix not square)
843  *  @see       matrix::determinant() */
844 ex matrix::charpoly(const symbol & lambda) const
845 {
846         if (row != col)
847                 throw (std::logic_error("matrix::charpoly(): matrix not square"));
848         
849         bool numeric_flag = true;
850         exvector::const_iterator r = m.begin(), rend = m.end();
851         while (r!=rend && numeric_flag==true) {
852                 if (!r->info(info_flags::numeric))
853                         numeric_flag = false;
854                 ++r;
855         }
856         
857         // The pure numeric case is traditionally rather common.  Hence, it is
858         // trapped and we use Leverrier's algorithm which goes as row^3 for
859         // every coefficient.  The expensive part is the matrix multiplication.
860         if (numeric_flag) {
861                 matrix B(*this);
862                 ex c = B.trace();
863                 ex poly = power(lambda,row)-c*power(lambda,row-1);
864                 for (unsigned i=1; i<row; ++i) {
865                         for (unsigned j=0; j<row; ++j)
866                                 B.m[j*col+j] -= c;
867                         B = this->mul(B);
868                         c = B.trace()/ex(i+1);
869                         poly -= c*power(lambda,row-i-1);
870                 }
871                 if (row%2)
872                         return -poly;
873                 else
874                         return poly;
875         }
876         
877         matrix M(*this);
878         for (unsigned r=0; r<col; ++r)
879                 M.m[r*col+r] -= lambda;
880         
881         return M.determinant().collect(lambda);
882 }
883
884
885 /** Inverse of this matrix.
886  *
887  *  @return    the inverted matrix
888  *  @exception logic_error (matrix not square)
889  *  @exception runtime_error (singular matrix) */
890 matrix matrix::inverse(void) const
891 {
892         if (row != col)
893                 throw (std::logic_error("matrix::inverse(): matrix not square"));
894         
895         // This routine actually doesn't do anything fancy at all.  We compute the
896         // inverse of the matrix A by solving the system A * A^{-1} == Id.
897         
898         // First populate the identity matrix supposed to become the right hand side.
899         matrix identity(row,col);
900         for (unsigned i=0; i<row; ++i)
901                 identity(i,i) = _ex1;
902         
903         // Populate a dummy matrix of variables, just because of compatibility with
904         // matrix::solve() which wants this (for compatibility with under-determined
905         // systems of equations).
906         matrix vars(row,col);
907         for (unsigned r=0; r<row; ++r)
908                 for (unsigned c=0; c<col; ++c)
909                         vars(r,c) = symbol();
910         
911         matrix sol(row,col);
912         try {
913                 sol = this->solve(vars,identity);
914         } catch (const std::runtime_error & e) {
915             if (e.what()==std::string("matrix::solve(): inconsistent linear system"))
916                         throw (std::runtime_error("matrix::inverse(): singular matrix"));
917                 else
918                         throw;
919         }
920         return sol;
921 }
922
923
924 /** Solve a linear system consisting of a m x n matrix and a m x p right hand
925  *  side by applying an elimination scheme to the augmented matrix.
926  *
927  *  @param vars n x p matrix, all elements must be symbols 
928  *  @param rhs m x p matrix
929  *  @return n x p solution matrix
930  *  @exception logic_error (incompatible matrices)
931  *  @exception invalid_argument (1st argument must be matrix of symbols)
932  *  @exception runtime_error (inconsistent linear system)
933  *  @see       solve_algo */
934 matrix matrix::solve(const matrix & vars,
935                                          const matrix & rhs,
936                                          unsigned algo) const
937 {
938         const unsigned m = this->rows();
939         const unsigned n = this->cols();
940         const unsigned p = rhs.cols();
941         
942         // syntax checks    
943         if ((rhs.rows() != m) || (vars.rows() != n) || (vars.col != p))
944                 throw (std::logic_error("matrix::solve(): incompatible matrices"));
945         for (unsigned ro=0; ro<n; ++ro)
946                 for (unsigned co=0; co<p; ++co)
947                         if (!vars(ro,co).info(info_flags::symbol))
948                                 throw (std::invalid_argument("matrix::solve(): 1st argument must be matrix of symbols"));
949         
950         // build the augmented matrix of *this with rhs attached to the right
951         matrix aug(m,n+p);
952         for (unsigned r=0; r<m; ++r) {
953                 for (unsigned c=0; c<n; ++c)
954                         aug.m[r*(n+p)+c] = this->m[r*n+c];
955                 for (unsigned c=0; c<p; ++c)
956                         aug.m[r*(n+p)+c+n] = rhs.m[r*p+c];
957         }
958         
959         // Gather some statistical information about the augmented matrix:
960         bool numeric_flag = true;
961         exvector::const_iterator r = aug.m.begin(), rend = aug.m.end();
962         while (r!=rend && numeric_flag==true) {
963                 if (!r->info(info_flags::numeric))
964                         numeric_flag = false;
965                 ++r;
966         }
967         
968         // Here is the heuristics in case this routine has to decide:
969         if (algo == solve_algo::automatic) {
970                 // Bareiss (fraction-free) elimination is generally a good guess:
971                 algo = solve_algo::bareiss;
972                 // For m<3, Bareiss elimination is equivalent to division free
973                 // elimination but has more logistic overhead
974                 if (m<3)
975                         algo = solve_algo::divfree;
976                 // This overrides any prior decisions.
977                 if (numeric_flag)
978                         algo = solve_algo::gauss;
979         }
980         
981         // Eliminate the augmented matrix:
982         switch(algo) {
983                 case solve_algo::gauss:
984                         aug.gauss_elimination();
985                         break;
986                 case solve_algo::divfree:
987                         aug.division_free_elimination();
988                         break;
989                 case solve_algo::bareiss:
990                 default:
991                         aug.fraction_free_elimination();
992         }
993         
994         // assemble the solution matrix:
995         matrix sol(n,p);
996         for (unsigned co=0; co<p; ++co) {
997                 unsigned last_assigned_sol = n+1;
998                 for (int r=m-1; r>=0; --r) {
999                         unsigned fnz = 1;    // first non-zero in row
1000                         while ((fnz<=n) && (aug.m[r*(n+p)+(fnz-1)].is_zero()))
1001                                 ++fnz;
1002                         if (fnz>n) {
1003                                 // row consists only of zeros, corresponding rhs must be 0, too
1004                                 if (!aug.m[r*(n+p)+n+co].is_zero()) {
1005                                         throw (std::runtime_error("matrix::solve(): inconsistent linear system"));
1006                                 }
1007                         } else {
1008                                 // assign solutions for vars between fnz+1 and
1009                                 // last_assigned_sol-1: free parameters
1010                                 for (unsigned c=fnz; c<last_assigned_sol-1; ++c)
1011                                         sol(c,co) = vars.m[c*p+co];
1012                                 ex e = aug.m[r*(n+p)+n+co];
1013                                 for (unsigned c=fnz; c<n; ++c)
1014                                         e -= aug.m[r*(n+p)+c]*sol.m[c*p+co];
1015                                 sol(fnz-1,co) = (e/(aug.m[r*(n+p)+(fnz-1)])).normal();
1016                                 last_assigned_sol = fnz;
1017                         }
1018                 }
1019                 // assign solutions for vars between 1 and
1020                 // last_assigned_sol-1: free parameters
1021                 for (unsigned ro=0; ro<last_assigned_sol-1; ++ro)
1022                         sol(ro,co) = vars(ro,co);
1023         }
1024         
1025         return sol;
1026 }
1027
1028
1029 // protected
1030
1031 /** Recursive determinant for small matrices having at least one symbolic
1032  *  entry.  The basic algorithm, known as Laplace-expansion, is enhanced by
1033  *  some bookkeeping to avoid calculation of the same submatrices ("minors")
1034  *  more than once.  According to W.M.Gentleman and S.C.Johnson this algorithm
1035  *  is better than elimination schemes for matrices of sparse multivariate
1036  *  polynomials and also for matrices of dense univariate polynomials if the
1037  *  matrix' dimesion is larger than 7.
1038  *
1039  *  @return the determinant as a new expression (in expanded form)
1040  *  @see matrix::determinant() */
1041 ex matrix::determinant_minor(void) const
1042 {
1043         // for small matrices the algorithm does not make any sense:
1044         const unsigned n = this->cols();
1045         if (n==1)
1046                 return m[0].expand();
1047         if (n==2)
1048                 return (m[0]*m[3]-m[2]*m[1]).expand();
1049         if (n==3)
1050                 return (m[0]*m[4]*m[8]-m[0]*m[5]*m[7]-
1051                         m[1]*m[3]*m[8]+m[2]*m[3]*m[7]+
1052                         m[1]*m[5]*m[6]-m[2]*m[4]*m[6]).expand();
1053         
1054         // This algorithm can best be understood by looking at a naive
1055         // implementation of Laplace-expansion, like this one:
1056         // ex det;
1057         // matrix minorM(this->rows()-1,this->cols()-1);
1058         // for (unsigned r1=0; r1<this->rows(); ++r1) {
1059         //     // shortcut if element(r1,0) vanishes
1060         //     if (m[r1*col].is_zero())
1061         //         continue;
1062         //     // assemble the minor matrix
1063         //     for (unsigned r=0; r<minorM.rows(); ++r) {
1064         //         for (unsigned c=0; c<minorM.cols(); ++c) {
1065         //             if (r<r1)
1066         //                 minorM(r,c) = m[r*col+c+1];
1067         //             else
1068         //                 minorM(r,c) = m[(r+1)*col+c+1];
1069         //         }
1070         //     }
1071         //     // recurse down and care for sign:
1072         //     if (r1%2)
1073         //         det -= m[r1*col] * minorM.determinant_minor();
1074         //     else
1075         //         det += m[r1*col] * minorM.determinant_minor();
1076         // }
1077         // return det.expand();
1078         // What happens is that while proceeding down many of the minors are
1079         // computed more than once.  In particular, there are binomial(n,k)
1080         // kxk minors and each one is computed factorial(n-k) times.  Therefore
1081         // it is reasonable to store the results of the minors.  We proceed from
1082         // right to left.  At each column c we only need to retrieve the minors
1083         // calculated in step c-1.  We therefore only have to store at most 
1084         // 2*binomial(n,n/2) minors.
1085         
1086         // Unique flipper counter for partitioning into minors
1087         std::vector<unsigned> Pkey;
1088         Pkey.reserve(n);
1089         // key for minor determinant (a subpartition of Pkey)
1090         std::vector<unsigned> Mkey;
1091         Mkey.reserve(n-1);
1092         // we store our subminors in maps, keys being the rows they arise from
1093         typedef std::map<std::vector<unsigned>,class ex> Rmap;
1094         typedef std::map<std::vector<unsigned>,class ex>::value_type Rmap_value;
1095         Rmap A;
1096         Rmap B;
1097         ex det;
1098         // initialize A with last column:
1099         for (unsigned r=0; r<n; ++r) {
1100                 Pkey.erase(Pkey.begin(),Pkey.end());
1101                 Pkey.push_back(r);
1102                 A.insert(Rmap_value(Pkey,m[n*(r+1)-1]));
1103         }
1104         // proceed from right to left through matrix
1105         for (int c=n-2; c>=0; --c) {
1106                 Pkey.erase(Pkey.begin(),Pkey.end());  // don't change capacity
1107                 Mkey.erase(Mkey.begin(),Mkey.end());
1108                 for (unsigned i=0; i<n-c; ++i)
1109                         Pkey.push_back(i);
1110                 unsigned fc = 0;  // controls logic for our strange flipper counter
1111                 do {
1112                         det = _ex0;
1113                         for (unsigned r=0; r<n-c; ++r) {
1114                                 // maybe there is nothing to do?
1115                                 if (m[Pkey[r]*n+c].is_zero())
1116                                         continue;
1117                                 // create the sorted key for all possible minors
1118                                 Mkey.erase(Mkey.begin(),Mkey.end());
1119                                 for (unsigned i=0; i<n-c; ++i)
1120                                         if (i!=r)
1121                                                 Mkey.push_back(Pkey[i]);
1122                                 // Fetch the minors and compute the new determinant
1123                                 if (r%2)
1124                                         det -= m[Pkey[r]*n+c]*A[Mkey];
1125                                 else
1126                                         det += m[Pkey[r]*n+c]*A[Mkey];
1127                         }
1128                         // prevent build-up of deep nesting of expressions saves time:
1129                         det = det.expand();
1130                         // store the new determinant at its place in B:
1131                         if (!det.is_zero())
1132                                 B.insert(Rmap_value(Pkey,det));
1133                         // increment our strange flipper counter
1134                         for (fc=n-c; fc>0; --fc) {
1135                                 ++Pkey[fc-1];
1136                                 if (Pkey[fc-1]<fc+c)
1137                                         break;
1138                         }
1139                         if (fc<n-c && fc>0)
1140                                 for (unsigned j=fc; j<n-c; ++j)
1141                                         Pkey[j] = Pkey[j-1]+1;
1142                 } while(fc);
1143                 // next column, so change the role of A and B:
1144                 A = B;
1145                 B.clear();
1146         }
1147         
1148         return det;
1149 }
1150
1151
1152 /** Perform the steps of an ordinary Gaussian elimination to bring the m x n
1153  *  matrix into an upper echelon form.  The algorithm is ok for matrices
1154  *  with numeric coefficients but quite unsuited for symbolic matrices.
1155  *
1156  *  @param det may be set to true to save a lot of space if one is only
1157  *  interested in the diagonal elements (i.e. for calculating determinants).
1158  *  The others are set to zero in this case.
1159  *  @return sign is 1 if an even number of rows was swapped, -1 if an odd
1160  *  number of rows was swapped and 0 if the matrix is singular. */
1161 int matrix::gauss_elimination(const bool det)
1162 {
1163         ensure_if_modifiable();
1164         const unsigned m = this->rows();
1165         const unsigned n = this->cols();
1166         GINAC_ASSERT(!det || n==m);
1167         int sign = 1;
1168         
1169         unsigned r0 = 0;
1170         for (unsigned r1=0; (r1<n-1)&&(r0<m-1); ++r1) {
1171                 int indx = pivot(r0, r1, true);
1172                 if (indx == -1) {
1173                         sign = 0;
1174                         if (det)
1175                                 return 0;  // leaves *this in a messy state
1176                 }
1177                 if (indx>=0) {
1178                         if (indx > 0)
1179                                 sign = -sign;
1180                         for (unsigned r2=r0+1; r2<m; ++r2) {
1181                                 if (!this->m[r2*n+r1].is_zero()) {
1182                                         // yes, there is something to do in this row
1183                                         ex piv = this->m[r2*n+r1] / this->m[r0*n+r1];
1184                                         for (unsigned c=r1+1; c<n; ++c) {
1185                                                 this->m[r2*n+c] -= piv * this->m[r0*n+c];
1186                                                 if (!this->m[r2*n+c].info(info_flags::numeric))
1187                                                         this->m[r2*n+c] = this->m[r2*n+c].normal();
1188                                         }
1189                                 }
1190                                 // fill up left hand side with zeros
1191                                 for (unsigned c=0; c<=r1; ++c)
1192                                         this->m[r2*n+c] = _ex0;
1193                         }
1194                         if (det) {
1195                                 // save space by deleting no longer needed elements
1196                                 for (unsigned c=r0+1; c<n; ++c)
1197                                         this->m[r0*n+c] = _ex0;
1198                         }
1199                         ++r0;
1200                 }
1201         }
1202         
1203         return sign;
1204 }
1205
1206
1207 /** Perform the steps of division free elimination to bring the m x n matrix
1208  *  into an upper echelon form.
1209  *
1210  *  @param det may be set to true to save a lot of space if one is only
1211  *  interested in the diagonal elements (i.e. for calculating determinants).
1212  *  The others are set to zero in this case.
1213  *  @return sign is 1 if an even number of rows was swapped, -1 if an odd
1214  *  number of rows was swapped and 0 if the matrix is singular. */
1215 int matrix::division_free_elimination(const bool det)
1216 {
1217         ensure_if_modifiable();
1218         const unsigned m = this->rows();
1219         const unsigned n = this->cols();
1220         GINAC_ASSERT(!det || n==m);
1221         int sign = 1;
1222         
1223         unsigned r0 = 0;
1224         for (unsigned r1=0; (r1<n-1)&&(r0<m-1); ++r1) {
1225                 int indx = pivot(r0, r1, true);
1226                 if (indx==-1) {
1227                         sign = 0;
1228                         if (det)
1229                                 return 0;  // leaves *this in a messy state
1230                 }
1231                 if (indx>=0) {
1232                         if (indx>0)
1233                                 sign = -sign;
1234                         for (unsigned r2=r0+1; r2<m; ++r2) {
1235                                 for (unsigned c=r1+1; c<n; ++c)
1236                                         this->m[r2*n+c] = (this->m[r0*n+r1]*this->m[r2*n+c] - this->m[r2*n+r1]*this->m[r0*n+c]).expand();
1237                                 // fill up left hand side with zeros
1238                                 for (unsigned c=0; c<=r1; ++c)
1239                                         this->m[r2*n+c] = _ex0;
1240                         }
1241                         if (det) {
1242                                 // save space by deleting no longer needed elements
1243                                 for (unsigned c=r0+1; c<n; ++c)
1244                                         this->m[r0*n+c] = _ex0;
1245                         }
1246                         ++r0;
1247                 }
1248         }
1249         
1250         return sign;
1251 }
1252
1253
1254 /** Perform the steps of Bareiss' one-step fraction free elimination to bring
1255  *  the matrix into an upper echelon form.  Fraction free elimination means
1256  *  that divide is used straightforwardly, without computing GCDs first.  This
1257  *  is possible, since we know the divisor at each step.
1258  *  
1259  *  @param det may be set to true to save a lot of space if one is only
1260  *  interested in the last element (i.e. for calculating determinants). The
1261  *  others are set to zero in this case.
1262  *  @return sign is 1 if an even number of rows was swapped, -1 if an odd
1263  *  number of rows was swapped and 0 if the matrix is singular. */
1264 int matrix::fraction_free_elimination(const bool det)
1265 {
1266         // Method:
1267         // (single-step fraction free elimination scheme, already known to Jordan)
1268         //
1269         // Usual division-free elimination sets m[0](r,c) = m(r,c) and then sets
1270         //     m[k+1](r,c) = m[k](k,k) * m[k](r,c) - m[k](r,k) * m[k](k,c).
1271         //
1272         // Bareiss (fraction-free) elimination in addition divides that element
1273         // by m[k-1](k-1,k-1) for k>1, where it can be shown by means of the
1274         // Sylvester determinant that this really divides m[k+1](r,c).
1275         //
1276         // We also allow rational functions where the original prove still holds.
1277         // However, we must care for numerator and denominator separately and
1278         // "manually" work in the integral domains because of subtle cancellations
1279         // (see below).  This blows up the bookkeeping a bit and the formula has
1280         // to be modified to expand like this (N{x} stands for numerator of x,
1281         // D{x} for denominator of x):
1282         //     N{m[k+1](r,c)} = N{m[k](k,k)}*N{m[k](r,c)}*D{m[k](r,k)}*D{m[k](k,c)}
1283         //                     -N{m[k](r,k)}*N{m[k](k,c)}*D{m[k](k,k)}*D{m[k](r,c)}
1284         //     D{m[k+1](r,c)} = D{m[k](k,k)}*D{m[k](r,c)}*D{m[k](r,k)}*D{m[k](k,c)}
1285         // where for k>1 we now divide N{m[k+1](r,c)} by
1286         //     N{m[k-1](k-1,k-1)}
1287         // and D{m[k+1](r,c)} by
1288         //     D{m[k-1](k-1,k-1)}.
1289         
1290         ensure_if_modifiable();
1291         const unsigned m = this->rows();
1292         const unsigned n = this->cols();
1293         GINAC_ASSERT(!det || n==m);
1294         int sign = 1;
1295         if (m==1)
1296                 return 1;
1297         ex divisor_n = 1;
1298         ex divisor_d = 1;
1299         ex dividend_n;
1300         ex dividend_d;
1301         
1302         // We populate temporary matrices to subsequently operate on.  There is
1303         // one holding numerators and another holding denominators of entries.
1304         // This is a must since the evaluator (or even earlier mul's constructor)
1305         // might cancel some trivial element which causes divide() to fail.  The
1306         // elements are normalized first (yes, even though this algorithm doesn't
1307         // need GCDs) since the elements of *this might be unnormalized, which
1308         // makes things more complicated than they need to be.
1309         matrix tmp_n(*this);
1310         matrix tmp_d(m,n);  // for denominators, if needed
1311         lst srl;  // symbol replacement list
1312         exvector::const_iterator cit = this->m.begin(), citend = this->m.end();
1313         exvector::iterator tmp_n_it = tmp_n.m.begin(), tmp_d_it = tmp_d.m.begin();
1314         while (cit != citend) {
1315                 ex nd = cit->normal().to_rational(srl).numer_denom();
1316                 ++cit;
1317                 *tmp_n_it++ = nd.op(0);
1318                 *tmp_d_it++ = nd.op(1);
1319         }
1320         
1321         unsigned r0 = 0;
1322         for (unsigned r1=0; (r1<n-1)&&(r0<m-1); ++r1) {
1323                 int indx = tmp_n.pivot(r0, r1, true);
1324                 if (indx==-1) {
1325                         sign = 0;
1326                         if (det)
1327                                 return 0;
1328                 }
1329                 if (indx>=0) {
1330                         if (indx>0) {
1331                                 sign = -sign;
1332                                 // tmp_n's rows r0 and indx were swapped, do the same in tmp_d:
1333                                 for (unsigned c=r1; c<n; ++c)
1334                                         tmp_d.m[n*indx+c].swap(tmp_d.m[n*r0+c]);
1335                         }
1336                         for (unsigned r2=r0+1; r2<m; ++r2) {
1337                                 for (unsigned c=r1+1; c<n; ++c) {
1338                                         dividend_n = (tmp_n.m[r0*n+r1]*tmp_n.m[r2*n+c]*
1339                                                       tmp_d.m[r2*n+r1]*tmp_d.m[r0*n+c]
1340                                                      -tmp_n.m[r2*n+r1]*tmp_n.m[r0*n+c]*
1341                                                       tmp_d.m[r0*n+r1]*tmp_d.m[r2*n+c]).expand();
1342                                         dividend_d = (tmp_d.m[r2*n+r1]*tmp_d.m[r0*n+c]*
1343                                                       tmp_d.m[r0*n+r1]*tmp_d.m[r2*n+c]).expand();
1344                                         bool check = divide(dividend_n, divisor_n,
1345                                                             tmp_n.m[r2*n+c], true);
1346                                         check &= divide(dividend_d, divisor_d,
1347                                                         tmp_d.m[r2*n+c], true);
1348                                         GINAC_ASSERT(check);
1349                                 }
1350                                 // fill up left hand side with zeros
1351                                 for (unsigned c=0; c<=r1; ++c)
1352                                         tmp_n.m[r2*n+c] = _ex0;
1353                         }
1354                         if ((r1<n-1)&&(r0<m-1)) {
1355                                 // compute next iteration's divisor
1356                                 divisor_n = tmp_n.m[r0*n+r1].expand();
1357                                 divisor_d = tmp_d.m[r0*n+r1].expand();
1358                                 if (det) {
1359                                         // save space by deleting no longer needed elements
1360                                         for (unsigned c=0; c<n; ++c) {
1361                                                 tmp_n.m[r0*n+c] = _ex0;
1362                                                 tmp_d.m[r0*n+c] = _ex1;
1363                                         }
1364                                 }
1365                         }
1366                         ++r0;
1367                 }
1368         }
1369         // repopulate *this matrix:
1370         exvector::iterator it = this->m.begin(), itend = this->m.end();
1371         tmp_n_it = tmp_n.m.begin();
1372         tmp_d_it = tmp_d.m.begin();
1373         while (it != itend)
1374                 *it++ = ((*tmp_n_it++)/(*tmp_d_it++)).subs(srl);
1375         
1376         return sign;
1377 }
1378
1379
1380 /** Partial pivoting method for matrix elimination schemes.
1381  *  Usual pivoting (symbolic==false) returns the index to the element with the
1382  *  largest absolute value in column ro and swaps the current row with the one
1383  *  where the element was found.  With (symbolic==true) it does the same thing
1384  *  with the first non-zero element.
1385  *
1386  *  @param ro is the row from where to begin
1387  *  @param co is the column to be inspected
1388  *  @param symbolic signal if we want the first non-zero element to be pivoted
1389  *  (true) or the one with the largest absolute value (false).
1390  *  @return 0 if no interchange occured, -1 if all are zero (usually signaling
1391  *  a degeneracy) and positive integer k means that rows ro and k were swapped.
1392  */
1393 int matrix::pivot(unsigned ro, unsigned co, bool symbolic)
1394 {
1395         unsigned k = ro;
1396         if (symbolic) {
1397                 // search first non-zero element in column co beginning at row ro
1398                 while ((k<row) && (this->m[k*col+co].expand().is_zero()))
1399                         ++k;
1400         } else {
1401                 // search largest element in column co beginning at row ro
1402                 GINAC_ASSERT(is_a<numeric>(this->m[k*col+co]));
1403                 unsigned kmax = k+1;
1404                 numeric mmax = abs(ex_to<numeric>(m[kmax*col+co]));
1405                 while (kmax<row) {
1406                         GINAC_ASSERT(is_a<numeric>(this->m[kmax*col+co]));
1407                         numeric tmp = ex_to<numeric>(this->m[kmax*col+co]);
1408                         if (abs(tmp) > mmax) {
1409                                 mmax = tmp;
1410                                 k = kmax;
1411                         }
1412                         ++kmax;
1413                 }
1414                 if (!mmax.is_zero())
1415                         k = kmax;
1416         }
1417         if (k==row)
1418                 // all elements in column co below row ro vanish
1419                 return -1;
1420         if (k==ro)
1421                 // matrix needs no pivoting
1422                 return 0;
1423         // matrix needs pivoting, so swap rows k and ro
1424         ensure_if_modifiable();
1425         for (unsigned c=0; c<col; ++c)
1426                 this->m[k*col+c].swap(this->m[ro*col+c]);
1427         
1428         return k;
1429 }
1430
1431 ex lst_to_matrix(const lst & l)
1432 {
1433         // Find number of rows and columns
1434         unsigned rows = l.nops(), cols = 0, i, j;
1435         for (i=0; i<rows; i++)
1436                 if (l.op(i).nops() > cols)
1437                         cols = l.op(i).nops();
1438
1439         // Allocate and fill matrix
1440         matrix &m = *new matrix(rows, cols);
1441         m.setflag(status_flags::dynallocated);
1442         for (i=0; i<rows; i++)
1443                 for (j=0; j<cols; j++)
1444                         if (l.op(i).nops() > j)
1445                                 m(i, j) = l.op(i).op(j);
1446                         else
1447                                 m(i, j) = _ex0;
1448         return m;
1449 }
1450
1451 ex diag_matrix(const lst & l)
1452 {
1453         unsigned dim = l.nops();
1454
1455         matrix &m = *new matrix(dim, dim);
1456         m.setflag(status_flags::dynallocated);
1457         for (unsigned i=0; i<dim; i++)
1458                 m(i, i) = l.op(i);
1459
1460         return m;
1461 }
1462
1463 } // namespace GiNaC