comparison liboctave/CMatrix.cc @ 8336:9813c07ca946

make det take advantage of matrix type
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 19 Nov 2008 15:26:39 +0100
parents 64cf956a109c
children e02242c54c49
comparison
equal deleted inserted replaced
8335:64cf956a109c 8336:9813c07ca946
54 #include "mx-cm-dm.h" 54 #include "mx-cm-dm.h"
55 #include "mx-dm-cm.h" 55 #include "mx-dm-cm.h"
56 #include "mx-cm-s.h" 56 #include "mx-cm-s.h"
57 #include "mx-inlines.cc" 57 #include "mx-inlines.cc"
58 #include "oct-cmplx.h" 58 #include "oct-cmplx.h"
59 #include "oct-norm.h"
59 60
60 #if defined (HAVE_FFTW3) 61 #if defined (HAVE_FFTW3)
61 #include "oct-fftw.h" 62 #include "oct-fftw.h"
62 #endif 63 #endif
63 64
1572 } 1573 }
1573 1574
1574 ComplexDET 1575 ComplexDET
1575 ComplexMatrix::determinant (octave_idx_type& info, double& rcon, int calc_cond) const 1576 ComplexMatrix::determinant (octave_idx_type& info, double& rcon, int calc_cond) const
1576 { 1577 {
1577 ComplexDET retval; 1578 MatrixType mattype (*this);
1578 1579 return determinant (mattype, info, rcon, calc_cond);
1579 octave_idx_type nr = rows (); 1580 }
1580 octave_idx_type nc = cols (); 1581
1581 1582 ComplexDET
1582 if (nr == 0 || nc == 0) 1583 ComplexMatrix::determinant (MatrixType& mattype,
1583 { 1584 octave_idx_type& info, double& rcon, int calc_cond) const
1584 retval = ComplexDET (1.0, 0); 1585 {
1585 } 1586 ComplexDET retval (1.0);
1587
1588 octave_idx_type nr = rows ();
1589 octave_idx_type nc = cols ();
1590
1591 if (nr != nc)
1592 (*current_liboctave_error_handler) ("matrix must be square");
1586 else 1593 else
1587 { 1594 {
1588 Array<octave_idx_type> ipvt (nr); 1595 int typ = mattype.type ();
1589 octave_idx_type *pipvt = ipvt.fortran_vec (); 1596
1590 1597 if (typ == MatrixType::Lower || typ == MatrixType::Upper)
1591 ComplexMatrix atmp = *this; 1598 {
1592 Complex *tmp_data = atmp.fortran_vec (); 1599 for (octave_idx_type i = 0; i < nc; i++)
1593 1600 retval *= elem (i,i);
1594 info = 0; 1601 }
1595 1602 else if (typ == MatrixType::Hermitian)
1596 // Calculate the norm of the matrix, for later use. 1603 {
1597 double anorm = 0; 1604 ComplexMatrix atmp = *this;
1598 if (calc_cond) 1605 Complex *tmp_data = atmp.fortran_vec ();
1599 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); 1606
1600 1607 info = 0;
1601 F77_XFCN (zgetrf, ZGETRF, (nr, nc, tmp_data, nr, pipvt, info)); 1608 double anorm = 0;
1602 1609 if (calc_cond) anorm = xnorm (*this, 1);
1603 // Throw-away extra info LAPACK gives so as to not change output. 1610
1604 rcon = 0.0; 1611
1605 if (info != 0) 1612 char job = 'L';
1606 { 1613 F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
1607 info = -1; 1614 tmp_data, nr, info
1608 retval = ComplexDET (); 1615 F77_CHAR_ARG_LEN (1)));
1609 } 1616
1610 else 1617 if (info != 0)
1611 { 1618 {
1612 if (calc_cond) 1619 rcon = 0.0;
1613 { 1620 mattype.mark_as_unsymmetric ();
1614 // Now calc the condition number for non-singular matrix. 1621 typ = MatrixType::Full;
1615 char job = '1'; 1622 }
1616 Array<Complex> z (2*nr); 1623 else
1617 Complex *pz = z.fortran_vec (); 1624 {
1618 Array<double> rz (2*nr); 1625 Array<Complex> z (2 * nc);
1619 double *prz = rz.fortran_vec (); 1626 Complex *pz = z.fortran_vec ();
1620 1627 Array<double> rz (nc);
1621 F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1), 1628 double *prz = rz.fortran_vec ();
1622 nc, tmp_data, nr, anorm, 1629
1623 rcon, pz, prz, info 1630 F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
1624 F77_CHAR_ARG_LEN (1))); 1631 nr, tmp_data, nr, anorm,
1625 } 1632 rcon, pz, prz, info
1626 1633 F77_CHAR_ARG_LEN (1)));
1627 if (info != 0) 1634
1628 { 1635 if (info != 0)
1629 info = -1; 1636 rcon = 0.0;
1630 retval = ComplexDET (); 1637
1631 } 1638 for (octave_idx_type i = 0; i < nc; i++)
1632 else 1639 retval *= elem (i,i);
1633 { 1640
1634 retval = ComplexDET (1.0); 1641 retval = retval.square ();
1635 1642 }
1636 for (octave_idx_type i = 0; i < nc; i++) 1643 }
1637 { 1644 else if (typ != MatrixType::Full)
1638 Complex c = atmp(i,i); 1645 (*current_liboctave_error_handler) ("det: invalid dense matrix type");
1639 retval *= (ipvt(i) != (i+1)) ? -c : c; 1646
1647 if (typ == MatrixType::Full)
1648 {
1649 Array<octave_idx_type> ipvt (nr);
1650 octave_idx_type *pipvt = ipvt.fortran_vec ();
1651
1652 ComplexMatrix atmp = *this;
1653 Complex *tmp_data = atmp.fortran_vec ();
1654
1655 info = 0;
1656
1657 // Calculate the norm of the matrix, for later use.
1658 double anorm = 0;
1659 if (calc_cond) anorm = xnorm (*this, 1);
1660
1661 F77_XFCN (zgetrf, ZGETRF, (nr, nr, tmp_data, nr, pipvt, info));
1662
1663 // Throw-away extra info LAPACK gives so as to not change output.
1664 rcon = 0.0;
1665 if (info != 0)
1666 {
1667 info = -1;
1668 retval = ComplexDET ();
1669 }
1670 else
1671 {
1672 if (calc_cond)
1673 {
1674 // Now calc the condition number for non-singular matrix.
1675 char job = '1';
1676 Array<Complex> z (2 * nc);
1677 Complex *pz = z.fortran_vec ();
1678 Array<double> rz (2 * nc);
1679 double *prz = rz.fortran_vec ();
1680
1681 F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
1682 nc, tmp_data, nr, anorm,
1683 rcon, pz, prz, info
1684 F77_CHAR_ARG_LEN (1)));
1640 } 1685 }
1641 } 1686
1642 } 1687 if (info != 0)
1643 } 1688 {
1644 1689 info = -1;
1690 retval = ComplexDET ();
1691 }
1692 else
1693 {
1694 for (octave_idx_type i = 0; i < nc; i++)
1695 {
1696 Complex c = atmp(i,i);
1697 retval *= (ipvt(i) != (i+1)) ? -c : c;
1698 }
1699 }
1700 }
1701 }
1702 }
1703
1645 return retval; 1704 return retval;
1646 } 1705 }
1647 1706
1648 double 1707 double
1649 ComplexMatrix::rcond (void) const 1708 ComplexMatrix::rcond (void) const