Mercurial > hg > octave-avbm
view src/xpow.cc @ 1740:fe9d3b2ded26
[project @ 1996-01-12 11:03:26 by jwe]
author | jwe |
---|---|
date | Fri, 12 Jan 1996 11:04:49 +0000 |
parents | 5a8ad3d12304 |
children | a02f140ed897 |
line wrap: on
line source
// xpow.cc -*- C++ -*- /* Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton This file is part of Octave. Octave is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <cassert> #include <climits> #include "CColVector.h" #include "CDiagMatrix.h" #include "CMatrix.h" #include "EIG.h" #include "dDiagMatrix.h" #include "dMatrix.h" #include "oct-cmplx.h" #include "error.h" #include "tree-const.h" #include "utils.h" #include "xpow.h" // This function also appears in tree-const.cc. Maybe it should be a // member function of the Matrix class. static int any_element_is_negative (const Matrix& a) { int nr = a.rows (); int nc = a.columns (); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) if (a.elem (i, j) < 0.0) return 1; return 0; } static inline int xisint (double x) { return (D_NINT (x) == x && ((x >= 0 && x < INT_MAX) || (x <= 0 && x > INT_MIN))); } // Safer pow functions. // // op2 \ op1: s m cs cm // +-- +---+---+----+----+ // scalar | | 1 | 5 | 7 | 11 | // +---+---+----+----+ // matrix | 2 | E | 8 | E | // +---+---+----+----+ // complex_scalar | 3 | 6 | 9 | 12 | // +---+---+----+----+ // complex_matrix | 4 | E | 10 | E | // +---+---+----+----+ // // E -> error, trapped in arith-ops.cc. // -*- 1 -*- tree_constant xpow (double a, double b) { if (a < 0.0 && (int) b != b) { Complex atmp (a); return pow (atmp, b); } else return pow (a, b); } // -*- 2 -*- tree_constant xpow (double a, const Matrix& b) { tree_constant retval; int nr = b.rows (); int nc = b.columns (); if (nr == 0 || nc == 0 || nr != nc) error ("for x^A, A must be square"); else { EIG b_eig (b); ComplexColumnVector lambda (b_eig.eigenvalues ()); ComplexMatrix Q (b_eig.eigenvectors ()); for (int i = 0; i < nr; i++) { Complex elt = lambda.elem (i); if (imag (elt) == 0.0) lambda.elem (i) = pow (a, real (elt)); else lambda.elem (i) = pow (a, elt); } ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } return retval; } // -*- 3 -*- tree_constant xpow (double a, const Complex& b) { Complex result; Complex atmp (a); result = pow (atmp, b); return result; } // -*- 4 -*- tree_constant xpow (double a, const ComplexMatrix& b) { tree_constant retval; int nr = b.rows (); int nc = b.columns (); if (nr == 0 || nc == 0 || nr != nc) { error ("for x^A, A must be square"); } else { EIG b_eig (b); ComplexColumnVector lambda (b_eig.eigenvalues ()); ComplexMatrix Q (b_eig.eigenvectors ()); for (int i = 0; i < nr; i++) { Complex elt = lambda.elem (i); if (imag (elt) == 0.0) lambda.elem (i) = pow (a, real (elt)); else lambda.elem (i) = pow (a, elt); } ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } return retval; } // -*- 5 -*- tree_constant xpow (const Matrix& a, double b) { tree_constant retval; int nr = a.rows (); int nc = a.columns (); if (nr == 0 || nc == 0 || nr != nc) { error ("for A^b, A must be square"); } else { if ((int) b == b) { int btmp = (int) b; if (btmp == 0) { retval = DiagMatrix (nr, nr, 1.0); } else { // Too much copying? // XXX FIXME XXX -- we shouldn't do this if the exponent is // large... Matrix atmp; if (btmp < 0) { btmp = -btmp; int info; double rcond = 0.0; atmp = a.inverse (info, rcond, 1); if (info == -1) warning ("inverse: matrix singular to machine\ precision, rcond = %g", rcond); } else atmp = a; Matrix result (atmp); for (int i = 1; i < btmp; i++) result = result * atmp; retval = result; } } else { EIG a_eig (a); ComplexColumnVector lambda (a_eig.eigenvalues ()); ComplexMatrix Q (a_eig.eigenvectors ()); for (int i = 0; i < nr; i++) lambda.elem (i) = pow (lambda.elem (i), b); ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } } return retval; } // -*- 6 -*- tree_constant xpow (const Matrix& a, const Complex& b) { tree_constant retval; int nr = a.rows (); int nc = a.columns (); if (nr == 0 || nc == 0 || nr != nc) { error ("for A^b, A must be square"); } else { EIG a_eig (a); ComplexColumnVector lambda (a_eig.eigenvalues ()); ComplexMatrix Q (a_eig.eigenvectors ()); for (int i = 0; i < nr; i++) lambda.elem (i) = pow (lambda.elem (i), b); ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } return retval; } // -*- 7 -*- tree_constant xpow (const Complex& a, double b) { Complex result; if (xisint (b)) result = pow (a, (int) b); else result = pow (a, b); return result; } // -*- 8 -*- tree_constant xpow (const Complex& a, const Matrix& b) { tree_constant retval; int nr = b.rows (); int nc = b.columns (); if (nr == 0 || nc == 0 || nr != nc) { error ("for x^A, A must be square"); } else { EIG b_eig (b); ComplexColumnVector lambda (b_eig.eigenvalues ()); ComplexMatrix Q (b_eig.eigenvectors ()); for (int i = 0; i < nr; i++) { Complex elt = lambda.elem (i); if (imag (elt) == 0.0) lambda.elem (i) = pow (a, real (elt)); else lambda.elem (i) = pow (a, elt); } ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } return retval; } // -*- 9 -*- tree_constant xpow (const Complex& a, const Complex& b) { Complex result; result = pow (a, b); return result; } // -*- 10 -*- tree_constant xpow (const Complex& a, const ComplexMatrix& b) { tree_constant retval; int nr = b.rows (); int nc = b.columns (); if (nr == 0 || nc == 0 || nr != nc) { error ("for x^A, A must be square"); } else { EIG b_eig (b); ComplexColumnVector lambda (b_eig.eigenvalues ()); ComplexMatrix Q (b_eig.eigenvectors ()); for (int i = 0; i < nr; i++) { Complex elt = lambda.elem (i); if (imag (elt) == 0.0) lambda.elem (i) = pow (a, real (elt)); else lambda.elem (i) = pow (a, elt); } ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } return retval; } // -*- 11 -*- tree_constant xpow (const ComplexMatrix& a, double b) { tree_constant retval; int nr = a.rows (); int nc = a.columns (); if (nr == 0 || nc == 0 || nr != nc) { error ("for A^b, A must be square"); } else { if ((int) b == b) { int btmp = (int) b; if (btmp == 0) { retval = DiagMatrix (nr, nr, 1.0); } else { // Too much copying? // XXX FIXME XXX -- we shouldn't do this if the exponent is // large... ComplexMatrix atmp; if (btmp < 0) { btmp = -btmp; int info; double rcond = 0.0; atmp = a.inverse (info, rcond, 1); if (info == -1) warning ("inverse: matrix singular to machine\ precision, rcond = %g", rcond); } else atmp = a; ComplexMatrix result (atmp); for (int i = 1; i < btmp; i++) result = result * atmp; retval = result; } } else { EIG a_eig (a); ComplexColumnVector lambda (a_eig.eigenvalues ()); ComplexMatrix Q (a_eig.eigenvectors ()); for (int i = 0; i < nr; i++) lambda.elem (i) = pow (lambda.elem (i), b); ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } } return retval; } // -*- 12 -*- tree_constant xpow (const ComplexMatrix& a, const Complex& b) { tree_constant retval; int nr = a.rows (); int nc = a.columns (); if (nr == 0 || nc == 0 || nr != nc) { error ("for A^b, A must be square"); } else { EIG a_eig (a); ComplexColumnVector lambda (a_eig.eigenvalues ()); ComplexMatrix Q (a_eig.eigenvectors ()); for (int i = 0; i < nr; i++) lambda.elem (i) = pow (lambda.elem (i), b); ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } return retval; } // Safer pow functions that work elementwise for matrices. // // op2 \ op1: s m cs cm // +-- +---+---+----+----+ // scalar | | * | 3 | * | 9 | // +---+---+----+----+ // matrix | 1 | 4 | 7 | 10 | // +---+---+----+----+ // complex_scalar | * | 5 | * | 11 | // +---+---+----+----+ // complex_matrix | 2 | 6 | 8 | 12 | // +---+---+----+----+ // // * -> not needed. // -*- 1 -*- tree_constant elem_xpow (double a, const Matrix& b) { tree_constant retval; int nr = b.rows (); int nc = b.columns (); // For now, assume the worst. if (a < 0.0) { Complex atmp (a); ComplexMatrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (atmp, b.elem (i, j)); retval = result; } else { Matrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a, b.elem (i, j)); retval = result; } return retval; } // -*- 2 -*- tree_constant elem_xpow (double a, const ComplexMatrix& b) { int nr = b.rows (); int nc = b.columns (); ComplexMatrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a, b.elem (i, j)); return result; } // -*- 3 -*- tree_constant elem_xpow (const Matrix& a, double b) { tree_constant retval; int nr = a.rows (); int nc = a.columns (); if ((int) b != b && any_element_is_negative (a)) { ComplexMatrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) { Complex atmp (a.elem (i, j)); result.elem (i, j) = pow (atmp, b); } retval = result; } else { Matrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a.elem (i, j), b); retval = result; } return retval; } // -*- 4 -*- tree_constant elem_xpow (const Matrix& a, const Matrix& b) { tree_constant retval; int nr = a.rows (); int nc = a.columns (); assert (nr == b.rows () && nc == b.columns ()); int convert_to_complex = 0; for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) { double atmp = a.elem (i, j); double btmp = b.elem (i, j); if (atmp < 0.0 && (int) btmp != btmp) { convert_to_complex = 1; goto done; } } done: if (convert_to_complex) { ComplexMatrix complex_result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) { Complex atmp (a.elem (i, j)); Complex btmp (b.elem (i, j)); complex_result.elem (i, j) = pow (atmp, btmp); } retval = complex_result; } else { Matrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a.elem (i, j), b.elem (i, j)); retval = result; } return retval; } // -*- 5 -*- tree_constant elem_xpow (const Matrix& a, const Complex& b) { int nr = a.rows (); int nc = a.columns (); ComplexMatrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a.elem (i, j), b); return result; } // -*- 6 -*- tree_constant elem_xpow (const Matrix& a, const ComplexMatrix& b) { int nr = a.rows (); int nc = a.columns (); assert (nr == b.rows () && nc == b.columns ()); ComplexMatrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a.elem (i, j), b.elem (i, j)); return result; } // -*- 7 -*- tree_constant elem_xpow (const Complex& a, const Matrix& b) { int nr = b.rows (); int nc = b.columns (); ComplexMatrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) { double btmp = b.elem (i, j); if (xisint (btmp)) result.elem (i, j) = pow (a, (int) btmp); else result.elem (i, j) = pow (a, btmp); } return result; } // -*- 8 -*- tree_constant elem_xpow (const Complex& a, const ComplexMatrix& b) { int nr = b.rows (); int nc = b.columns (); ComplexMatrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a, b.elem (i, j)); return result; } // -*- 9 -*- tree_constant elem_xpow (const ComplexMatrix& a, double b) { int nr = a.rows (); int nc = a.columns (); ComplexMatrix result (nr, nc); if (xisint (b)) { for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a.elem (i, j), (int) b); } else { for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a.elem (i, j), b); } return result; } // -*- 10 -*- tree_constant elem_xpow (const ComplexMatrix& a, const Matrix& b) { int nr = a.rows (); int nc = a.columns (); assert (nr == b.rows () && nc == b.columns ()); ComplexMatrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) { double btmp = b.elem (i, j); if (xisint (btmp)) result.elem (i, j) = pow (a.elem (i, j), (int) btmp); else result.elem (i, j) = pow (a.elem (i, j), btmp); } return result; } // -*- 11 -*- tree_constant elem_xpow (const ComplexMatrix& a, const Complex& b) { int nr = a.rows (); int nc = a.columns (); ComplexMatrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a.elem (i, j), b); return result; } // -*- 12 -*- tree_constant elem_xpow (const ComplexMatrix& a, const ComplexMatrix& b) { int nr = a.rows (); int nc = a.columns (); ComplexMatrix result (nr, nc); for (int j = 0; j < nc; j++) for (int i = 0; i < nr; i++) result.elem (i, j) = pow (a.elem (i, j), b.elem (i, j)); return result; } /* ;;; Local Variables: *** ;;; mode: C++ *** ;;; page-delimiter: "^/\\*" *** ;;; End: *** */