Mercurial > octave
view libinterp/corefcn/xpow.cc @ 21100:e39e05d90788
Switch gripe_XXX to either err_XXX or warn_XXX naming scheme.
* libinterp/corefcn/errwarn.h, libinterp/corefcn/errwarn.cc: New header and .cc
file with common errors and warnings for libinterp.
* libinterp/corefcn/module.mk: Add errwarn.h, errwarn.cc to build system.
* liboctave/util/lo-array-errwarn.h, liboctave/util/lo-array-errwarn.cc: New
header and .cc file with common errors and warnings for liboctave.
* liboctave/util/module.mk: Add lo-array-errwarn.h, lo-array-errwarn.cc to
build system.
* lo-array-gripes.h: #include "lo-array-errwarn.h" for access to class
index_exception. Remove const char *error_id_XXX prototypes.
* lo-array-gripes.cc: Remove const char *error_id_XXX initializations.
Remove index_exception method definitions.
* Cell.cc, __pchip_deriv__.cc, __qp__.cc, balance.cc, betainc.cc, cellfun.cc,
daspk.cc, dasrt.cc, dassl.cc, data.cc, debug.cc, defaults.cc, det.cc,
dirfns.cc, eig.cc, fft.cc, fft2.cc, fftn.cc, find.cc, gammainc.cc, gcd.cc,
getgrent.cc, getpwent.cc, graphics.in.h, help.cc, hess.cc, hex2num.cc,
input.cc, inv.cc, jit-typeinfo.cc, load-save.cc, lookup.cc, ls-hdf5.cc,
ls-mat-ascii.cc, ls-mat4.cc, ls-mat5.cc, ls-oct-binary.cc, ls-oct-text.cc,
lsode.cc, lu.cc, luinc.cc, max.cc, mgorth.cc, oct-hist.cc, oct-procbuf.cc,
oct-stream.cc, oct.h, pager.cc, pinv.cc, pr-output.cc, quad.cc, qz.cc, rand.cc,
rcond.cc, regexp.cc, schur.cc, sparse-xdiv.cc, sparse-xpow.cc, sparse.cc,
spparms.cc, sqrtm.cc, str2double.cc, strfind.cc, strfns.cc, sub2ind.cc, svd.cc,
sylvester.cc, syscalls.cc, typecast.cc, utils.cc, variables.cc, xdiv.cc,
xnorm.cc, xpow.cc, __eigs__.cc, __glpk__.cc, __magick_read__.cc,
__osmesa_print__.cc, audiodevinfo.cc, audioread.cc, chol.cc, dmperm.cc,
fftw.cc, qr.cc, symbfact.cc, symrcm.cc, ov-base-diag.cc, ov-base-int.cc,
ov-base-mat.cc, ov-base-scalar.cc, ov-base-sparse.cc, ov-base.cc,
ov-bool-mat.cc, ov-bool-sparse.cc, ov-bool.cc, ov-builtin.cc, ov-cell.cc,
ov-ch-mat.cc, ov-class.cc, ov-complex.cc, ov-complex.h, ov-cs-list.cc,
ov-cx-diag.cc, ov-cx-mat.cc, ov-cx-sparse.cc, ov-fcn-handle.cc,
ov-fcn-inline.cc, ov-float.cc, ov-float.h, ov-flt-complex.cc, ov-flt-complex.h,
ov-flt-cx-diag.cc, ov-flt-cx-mat.cc, ov-flt-re-mat.cc, ov-int16.cc,
ov-int32.cc, ov-int64.cc, ov-int8.cc, ov-intx.h, ov-mex-fcn.cc, ov-perm.cc,
ov-range.cc, ov-re-mat.cc, ov-re-sparse.cc, ov-scalar.cc, ov-scalar.h,
ov-str-mat.cc, ov-struct.cc, ov-type-conv.h, ov-uint16.cc, ov-uint32.cc,
ov-uint64.cc, ov-uint8.cc, ov-usr-fcn.cc, ov.cc, op-b-b.cc, op-b-bm.cc,
op-b-sbm.cc, op-bm-b.cc, op-bm-bm.cc, op-bm-sbm.cc, op-cdm-cdm.cc, op-cell.cc,
op-chm.cc, op-class.cc, op-cm-cm.cc, op-cm-cs.cc, op-cm-m.cc, op-cm-s.cc,
op-cm-scm.cc, op-cm-sm.cc, op-cs-cm.cc, op-cs-cs.cc, op-cs-m.cc, op-cs-s.cc,
op-cs-scm.cc, op-cs-sm.cc, op-dm-dm.cc, op-dm-scm.cc, op-dm-sm.cc,
op-dms-template.cc, op-double-conv.cc, op-fcdm-fcdm.cc, op-fcdm-fdm.cc,
op-fcm-fcm.cc, op-fcm-fcs.cc, op-fcm-fm.cc, op-fcm-fs.cc, op-fcn.cc,
op-fcs-fcm.cc, op-fcs-fcs.cc, op-fcs-fm.cc, op-fcs-fs.cc, op-fdm-fdm.cc,
op-float-conv.cc, op-fm-fcm.cc, op-fm-fcs.cc, op-fm-fm.cc, op-fm-fs.cc,
op-fs-fcm.cc, op-fs-fcs.cc, op-fs-fm.cc, op-fs-fs.cc, op-i16-i16.cc,
op-i32-i32.cc, op-i64-i64.cc, op-i8-i8.cc, op-int-concat.cc, op-int-conv.cc,
op-int.h, op-m-cm.cc, op-m-cs.cc, op-m-m.cc, op-m-s.cc, op-m-scm.cc,
op-m-sm.cc, op-pm-pm.cc, op-pm-scm.cc, op-pm-sm.cc, op-range.cc, op-s-cm.cc,
op-s-cs.cc, op-s-m.cc, op-s-s.cc, op-s-scm.cc, op-s-sm.cc, op-sbm-b.cc,
op-sbm-bm.cc, op-sbm-sbm.cc, op-scm-cm.cc, op-scm-cs.cc, op-scm-m.cc,
op-scm-s.cc, op-scm-scm.cc, op-scm-sm.cc, op-sm-cm.cc, op-sm-cs.cc, op-sm-m.cc,
op-sm-s.cc, op-sm-scm.cc, op-sm-sm.cc, op-str-m.cc, op-str-s.cc, op-str-str.cc,
op-struct.cc, op-ui16-ui16.cc, op-ui32-ui32.cc, op-ui64-ui64.cc, op-ui8-ui8.cc,
ops.h, lex.ll, pt-assign.cc, pt-eval.cc, pt-idx.cc, pt-loop.cc, pt-mat.cc,
pt-stmt.cc, Array-util.cc, Array-util.h, Array.cc, CColVector.cc,
CDiagMatrix.cc, CMatrix.cc, CNDArray.cc, CRowVector.cc, CSparse.cc,
DiagArray2.cc, MDiagArray2.cc, MSparse.cc, PermMatrix.cc, Range.cc, Sparse.cc,
dColVector.cc, dDiagMatrix.cc, dMatrix.cc, dNDArray.cc, dRowVector.cc,
dSparse.cc, fCColVector.cc, fCDiagMatrix.cc, fCMatrix.cc, fCNDArray.cc,
fCRowVector.cc, fColVector.cc, fDiagMatrix.cc, fMatrix.cc, fNDArray.cc,
fRowVector.cc, idx-vector.cc, CmplxGEPBAL.cc, dbleGEPBAL.cc, fCmplxGEPBAL.cc,
floatGEPBAL.cc, Sparse-diag-op-defs.h, Sparse-op-defs.h, Sparse-perm-op-defs.h,
mx-inlines.cc, mx-op-defs.h, oct-binmap.h:
Replace 'include "gripes.h"' with 'include "errwarn.h". Change all gripe_XXX
to err_XXX or warn_XXX or errwarn_XXX.
author | Rik <rik@octave.org> |
---|---|
date | Mon, 18 Jan 2016 18:28:06 -0800 |
parents | 5e00ed38a58b |
children | dfcb9d74b253 |
line wrap: on
line source
/* Copyright (C) 1993-2015 John W. Eaton Copyright (C) 2009-2010 VZLU Prague 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <cassert> #include <limits> #include "Array-util.h" #include "CColVector.h" #include "CDiagMatrix.h" #include "fCDiagMatrix.h" #include "fCMatrix.h" #include "CMatrix.h" #include "EIG.h" #include "fEIG.h" #include "dDiagMatrix.h" #include "fDiagMatrix.h" #include "dMatrix.h" #include "PermMatrix.h" #include "mx-cm-cdm.h" #include "mx-fcm-fcdm.h" #include "oct-cmplx.h" #include "Range.h" #include "quit.h" #include "error.h" #include "ovl.h" #include "utils.h" #include "xpow.h" #include "bsxfun.h" static void gripe_failed_diagonalization (void) { gripe_failed_diagonalization (); } static inline int xisint (double x) { return (D_NINT (x) == x && ((x >= 0 && x < std::numeric_limits<int>::max ()) || (x <= 0 && x > std::numeric_limits<int>::min ()))); } // Safer pow functions. // // op2 \ op1: s m cs cm // +-- +---+---+----+----+ // scalar | | 1 | 5 | 7 | 11 | // +---+---+----+----+ // matrix | 2 | * | 8 | * | // +---+---+----+----+ // complex_scalar | 3 | 6 | 9 | 12 | // +---+---+----+----+ // complex_matrix | 4 | * | 10 | * | // +---+---+----+----+ // -*- 1 -*- octave_value xpow (double a, double b) { double retval; if (a < 0.0 && ! xisint (b)) { Complex atmp (a); return std::pow (atmp, b); } else retval = std::pow (a, b); return retval; } // -*- 2 -*- octave_value xpow (double a, const Matrix& b) { octave_value retval; octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for x^A, A must be a square matrix. Use .^ for elementwise power."); try { EIG b_eig (b); ComplexColumnVector lambda (b_eig.eigenvalues ()); ComplexMatrix Q (b_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) { Complex elt = lambda(i); if (std::imag (elt) == 0.0) lambda(i) = std::pow (a, std::real (elt)); else lambda(i) = std::pow (a, elt); } ComplexDiagMatrix D (lambda); ComplexMatrix C = Q * D * Q.inverse (); if (a > 0) retval = real (C); else retval = C; } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 3 -*- octave_value xpow (double a, const Complex& b) { Complex result = std::pow (a, b); return result; } // -*- 4 -*- octave_value xpow (double a, const ComplexMatrix& b) { octave_value retval; octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for x^A, A must be a square matrix. Use .^ for elementwise power."); EIG b_eig (b); try { ComplexColumnVector lambda (b_eig.eigenvalues ()); ComplexMatrix Q (b_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) { Complex elt = lambda(i); if (std::imag (elt) == 0.0) lambda(i) = std::pow (a, std::real (elt)); else lambda(i) = std::pow (a, elt); } ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 5 -*- octave_value xpow (const Matrix& a, double b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); if (static_cast<int> (b) == b) { int btmp = static_cast<int> (b); if (btmp == 0) { retval = DiagMatrix (nr, nr, 1.0); } else { // Too much copying? // FIXME: we shouldn't do this if the exponent is large... Matrix atmp; if (btmp < 0) { btmp = -btmp; octave_idx_type info; double rcond = 0.0; MatrixType mattype (a); atmp = a.inverse (mattype, info, rcond, 1); if (info == -1) warning ("inverse: matrix singular to machine\ precision, rcond = %g", rcond); } else atmp = a; Matrix result (atmp); btmp--; while (btmp > 0) { if (btmp & 1) result = result * atmp; btmp >>= 1; if (btmp > 0) atmp = atmp * atmp; } retval = result; } } else { EIG a_eig (a); try { ComplexColumnVector lambda (a_eig.eigenvalues ()); ComplexMatrix Q (a_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) lambda(i) = std::pow (lambda(i), b); ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } } return retval; } // -*- 5d -*- octave_value xpow (const DiagMatrix& a, double b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); if (static_cast<int> (b) == b) { DiagMatrix r (nr, nc); for (octave_idx_type i = 0; i < nc; i++) r.dgelem (i) = std::pow (a.dgelem (i), b); retval = r; } else { ComplexDiagMatrix r (nr, nc); for (octave_idx_type i = 0; i < nc; i++) r.dgelem (i) = std::pow (static_cast<Complex> (a.dgelem (i)), b); retval = r; } return retval; } // -*- 5p -*- octave_value xpow (const PermMatrix& a, double b) { octave_value retval; int btmp = static_cast<int> (b); if (btmp == b) return a.power (btmp); else return xpow (Matrix (a), b); } // -*- 6 -*- octave_value xpow (const Matrix& a, const Complex& b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); EIG a_eig (a); try { ComplexColumnVector lambda (a_eig.eigenvalues ()); ComplexMatrix Q (a_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) lambda(i) = std::pow (lambda(i), b); ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 7 -*- octave_value xpow (const Complex& a, double b) { Complex result; if (xisint (b)) result = std::pow (a, static_cast<int> (b)); else result = std::pow (a, b); return result; } // -*- 8 -*- octave_value xpow (const Complex& a, const Matrix& b) { octave_value retval; octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for x^A, A must be a square matrix. Use .^ for elementwise power."); EIG b_eig (b); try { ComplexColumnVector lambda (b_eig.eigenvalues ()); ComplexMatrix Q (b_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) { Complex elt = lambda(i); if (std::imag (elt) == 0.0) lambda(i) = std::pow (a, std::real (elt)); else lambda(i) = std::pow (a, elt); } ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 9 -*- octave_value xpow (const Complex& a, const Complex& b) { Complex result; result = std::pow (a, b); return result; } // -*- 10 -*- octave_value xpow (const Complex& a, const ComplexMatrix& b) { octave_value retval; octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for x^A, A must be a square matrix. Use .^ for elementwise power."); EIG b_eig (b); try { ComplexColumnVector lambda (b_eig.eigenvalues ()); ComplexMatrix Q (b_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) { Complex elt = lambda(i); if (std::imag (elt) == 0.0) lambda(i) = std::pow (a, std::real (elt)); else lambda(i) = std::pow (a, elt); } ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 11 -*- octave_value xpow (const ComplexMatrix& a, double b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); if (static_cast<int> (b) == b) { int btmp = static_cast<int> (b); if (btmp == 0) { retval = DiagMatrix (nr, nr, 1.0); } else { // Too much copying? // FIXME: we shouldn't do this if the exponent is large... ComplexMatrix atmp; if (btmp < 0) { btmp = -btmp; octave_idx_type info; double rcond = 0.0; MatrixType mattype (a); atmp = a.inverse (mattype, info, rcond, 1); if (info == -1) warning ("inverse: matrix singular to machine\ precision, rcond = %g", rcond); } else atmp = a; ComplexMatrix result (atmp); btmp--; while (btmp > 0) { if (btmp & 1) result = result * atmp; btmp >>= 1; if (btmp > 0) atmp = atmp * atmp; } retval = result; } } else { EIG a_eig (a); try { ComplexColumnVector lambda (a_eig.eigenvalues ()); ComplexMatrix Q (a_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) lambda(i) = std::pow (lambda(i), b); ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } } return retval; } // -*- 12 -*- octave_value xpow (const ComplexMatrix& a, const Complex& b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); EIG a_eig (a); try { ComplexColumnVector lambda (a_eig.eigenvalues ()); ComplexMatrix Q (a_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) lambda(i) = std::pow (lambda(i), b); ComplexDiagMatrix D (lambda); retval = ComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 12d -*- octave_value xpow (const ComplexDiagMatrix& a, const Complex& b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); ComplexDiagMatrix r (nr, nc); for (octave_idx_type i = 0; i < nc; i++) r(i, i) = std::pow (a(i, i), b); retval = r; return retval; } // mixed octave_value xpow (const ComplexDiagMatrix& a, double b) { return xpow (a, static_cast<Complex> (b)); } octave_value xpow (const DiagMatrix& a, const Complex& b) { return xpow (ComplexDiagMatrix (a), b); } // 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. // FIXME: these functions need to be fixed so that things like // // a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b // // and // // a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end // // produce identical results. Also, it would be nice if -1^0.5 // produced a pure imaginary result instead of a complex number with a // small real part. But perhaps that's really a problem with the math // library... // -*- 1 -*- octave_value elem_xpow (double a, const Matrix& b) { octave_value retval; octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); double d1, d2; if (a < 0.0 && ! b.all_integers (d1, d2)) { Complex atmp (a); ComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (atmp, b (i, j)); } retval = result; } else { Matrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a, b (i, j)); } retval = result; } return retval; } // -*- 2 -*- octave_value elem_xpow (double a, const ComplexMatrix& b) { octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); ComplexMatrix result (nr, nc); Complex atmp (a); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (atmp, b (i, j)); } return result; } static inline bool same_sign (double a, double b) { return (a >= 0 && b >= 0) || (a <= 0 && b <= 0); } octave_value elem_xpow (double a, const Range& r) { octave_value retval; // Only optimize powers with ranges that are integer and monotonic in // magnitude. if (r.numel () > 1 && r.all_elements_are_ints () && same_sign (r.base (), r.limit ())) { octave_idx_type n = r.numel (); Matrix result (1, n); if (same_sign (r.base (), r.inc ())) { double base = std::pow (a, r.base ()); double inc = std::pow (a, r.inc ()); result(0) = base; for (octave_idx_type i = 1; i < n; i++) result(i) = (base *= inc); } else { // Don't use Range::limit () here. double limit = std::pow (a, r.base () + (n-1) * r.inc ()); double inc = std::pow (a, -r.inc ()); result(n-1) = limit; for (octave_idx_type i = n-2; i >= 0; i--) result(i) = (limit *= inc); } retval = result; } else retval = elem_xpow (a, r.matrix_value ()); return retval; } // -*- 3 -*- octave_value elem_xpow (const Matrix& a, double b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (! xisint (b) && a.any_element_is_negative ()) { ComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); Complex atmp (a (i, j)); result (i, j) = std::pow (atmp, b); } retval = result; } else { Matrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), b); } retval = result; } return retval; } // -*- 4 -*- octave_value elem_xpow (const Matrix& a, const Matrix& b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); octave_idx_type b_nr = b.rows (); octave_idx_type b_nc = b.cols (); if (nr != b_nr || nc != b_nc) err_nonconformant ("operator .^", nr, nc, b_nr, b_nc); int convert_to_complex = 0; for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); double atmp = a (i, j); double btmp = b (i, j); if (atmp < 0.0 && static_cast<int> (btmp) != btmp) { convert_to_complex = 1; goto done; } } done: if (convert_to_complex) { ComplexMatrix complex_result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); Complex atmp (a (i, j)); Complex btmp (b (i, j)); complex_result (i, j) = std::pow (atmp, btmp); } retval = complex_result; } else { Matrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), b (i, j)); } retval = result; } return retval; } // -*- 5 -*- octave_value elem_xpow (const Matrix& a, const Complex& b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); ComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (Complex (a (i, j)), b); } return result; } // -*- 6 -*- octave_value elem_xpow (const Matrix& a, const ComplexMatrix& b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); octave_idx_type b_nr = b.rows (); octave_idx_type b_nc = b.cols (); if (nr != b_nr || nc != b_nc) err_nonconformant ("operator .^", nr, nc, b_nr, b_nc); ComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (Complex (a (i, j)), b (i, j)); } return result; } // -*- 7 -*- octave_value elem_xpow (const Complex& a, const Matrix& b) { octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); ComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); double btmp = b (i, j); if (xisint (btmp)) result (i, j) = std::pow (a, static_cast<int> (btmp)); else result (i, j) = std::pow (a, btmp); } return result; } // -*- 8 -*- octave_value elem_xpow (const Complex& a, const ComplexMatrix& b) { octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); ComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a, b (i, j)); } return result; } octave_value elem_xpow (const Complex& a, const Range& r) { octave_value retval; // Only optimize powers with ranges that are integer and monotonic in // magnitude. if (r.numel () > 1 && r.all_elements_are_ints () && same_sign (r.base (), r.limit ())) { octave_idx_type n = r.numel (); ComplexMatrix result (1, n); if (same_sign (r.base (), r.inc ())) { Complex base = std::pow (a, r.base ()); Complex inc = std::pow (a, r.inc ()); result(0) = base; for (octave_idx_type i = 1; i < n; i++) result(i) = (base *= inc); } else { // Don't use Range::limit () here. Complex limit = std::pow (a, r.base () + (n-1) * r.inc ()); Complex inc = std::pow (a, -r.inc ()); result(n-1) = limit; for (octave_idx_type i = n-2; i >= 0; i--) result(i) = (limit *= inc); } retval = result; } else retval = elem_xpow (a, r.matrix_value ()); return retval; } // -*- 9 -*- octave_value elem_xpow (const ComplexMatrix& a, double b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); ComplexMatrix result (nr, nc); if (xisint (b)) { for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), static_cast<int> (b)); } } else { for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), b); } } return result; } // -*- 10 -*- octave_value elem_xpow (const ComplexMatrix& a, const Matrix& b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); octave_idx_type b_nr = b.rows (); octave_idx_type b_nc = b.cols (); if (nr != b_nr || nc != b_nc) err_nonconformant ("operator .^", nr, nc, b_nr, b_nc); ComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); double btmp = b (i, j); if (xisint (btmp)) result (i, j) = std::pow (a (i, j), static_cast<int> (btmp)); else result (i, j) = std::pow (a (i, j), btmp); } return result; } // -*- 11 -*- octave_value elem_xpow (const ComplexMatrix& a, const Complex& b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); ComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), b); } return result; } // -*- 12 -*- octave_value elem_xpow (const ComplexMatrix& a, const ComplexMatrix& b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); octave_idx_type b_nr = b.rows (); octave_idx_type b_nc = b.cols (); if (nr != b_nr || nc != b_nc) err_nonconformant ("operator .^", nr, nc, b_nr, b_nc); ComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), b (i, j)); } return result; } // Safer pow functions that work elementwise for N-D arrays. // // op2 \ op1: s nd cs cnd // +-- +---+---+----+----+ // scalar | | * | 3 | * | 9 | // +---+---+----+----+ // N_d | 1 | 4 | 7 | 10 | // +---+---+----+----+ // complex_scalar | * | 5 | * | 11 | // +---+---+----+----+ // complex_N_d | 2 | 6 | 8 | 12 | // +---+---+----+----+ // // * -> not needed. // FIXME: these functions need to be fixed so that things like // // a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b // // and // // a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end // // produce identical results. Also, it would be nice if -1^0.5 // produced a pure imaginary result instead of a complex number with a // small real part. But perhaps that's really a problem with the math // library... // -*- 1 -*- octave_value elem_xpow (double a, const NDArray& b) { octave_value retval; if (a < 0.0 && ! b.all_integers ()) { Complex atmp (a); ComplexNDArray result (b.dims ()); for (octave_idx_type i = 0; i < b.numel (); i++) { octave_quit (); result(i) = std::pow (atmp, b(i)); } retval = result; } else { NDArray result (b.dims ()); for (octave_idx_type i = 0; i < b.numel (); i++) { octave_quit (); result (i) = std::pow (a, b(i)); } retval = result; } return retval; } // -*- 2 -*- octave_value elem_xpow (double a, const ComplexNDArray& b) { ComplexNDArray result (b.dims ()); for (octave_idx_type i = 0; i < b.numel (); i++) { octave_quit (); result(i) = std::pow (a, b(i)); } return result; } // -*- 3 -*- octave_value elem_xpow (const NDArray& a, double b) { octave_value retval; if (! xisint (b)) { if (a.any_element_is_negative ()) { ComplexNDArray result (a.dims ()); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); Complex atmp (a (i)); result(i) = std::pow (atmp, b); } retval = result; } else { NDArray result (a.dims ()); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b); } retval = result; } } else { NoAlias<NDArray> result (a.dims ()); int ib = static_cast<int> (b); if (ib == 2) { for (octave_idx_type i = 0; i < a.numel (); i++) result(i) = a(i) * a(i); } else if (ib == 3) { for (octave_idx_type i = 0; i < a.numel (); i++) result(i) = a(i) * a(i) * a(i); } else if (ib == -1) { for (octave_idx_type i = 0; i < a.numel (); i++) result(i) = 1.0 / a(i); } else { for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), ib); } } retval = result; } return retval; } // -*- 4 -*- octave_value elem_xpow (const NDArray& a, const NDArray& b) { octave_value retval; dim_vector a_dims = a.dims (); dim_vector b_dims = b.dims (); if (a_dims != b_dims) { if (is_valid_bsxfun ("operator .^", a_dims, b_dims)) { //Potentially complex results NDArray xa = octave_value_extract<NDArray> (a); NDArray xb = octave_value_extract<NDArray> (b); if (! xb.all_integers () && xa.any_element_is_negative ()) return octave_value (bsxfun_pow (ComplexNDArray (xa), xb)); else return octave_value (bsxfun_pow (xa, xb)); } else err_nonconformant ("operator .^", a_dims, b_dims); } int len = a.numel (); bool convert_to_complex = false; for (octave_idx_type i = 0; i < len; i++) { octave_quit (); double atmp = a(i); double btmp = b(i); if (atmp < 0.0 && static_cast<int> (btmp) != btmp) { convert_to_complex = true; goto done; } } done: if (convert_to_complex) { ComplexNDArray complex_result (a_dims); for (octave_idx_type i = 0; i < len; i++) { octave_quit (); Complex atmp (a(i)); complex_result(i) = std::pow (atmp, b(i)); } retval = complex_result; } else { NDArray result (a_dims); for (octave_idx_type i = 0; i < len; i++) { octave_quit (); result(i) = std::pow (a(i), b(i)); } retval = result; } return retval; } // -*- 5 -*- octave_value elem_xpow (const NDArray& a, const Complex& b) { ComplexNDArray result (a.dims ()); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b); } return result; } // -*- 6 -*- octave_value elem_xpow (const NDArray& a, const ComplexNDArray& b) { dim_vector a_dims = a.dims (); dim_vector b_dims = b.dims (); if (a_dims != b_dims) { if (is_valid_bsxfun ("operator .^", a_dims, b_dims)) { return bsxfun_pow (a, b); } else err_nonconformant ("operator .^", a_dims, b_dims); } ComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b(i)); } return result; } // -*- 7 -*- octave_value elem_xpow (const Complex& a, const NDArray& b) { ComplexNDArray result (b.dims ()); for (octave_idx_type i = 0; i < b.numel (); i++) { octave_quit (); double btmp = b(i); if (xisint (btmp)) result(i) = std::pow (a, static_cast<int> (btmp)); else result(i) = std::pow (a, btmp); } return result; } // -*- 8 -*- octave_value elem_xpow (const Complex& a, const ComplexNDArray& b) { ComplexNDArray result (b.dims ()); for (octave_idx_type i = 0; i < b.numel (); i++) { octave_quit (); result(i) = std::pow (a, b(i)); } return result; } // -*- 9 -*- octave_value elem_xpow (const ComplexNDArray& a, double b) { ComplexNDArray result (a.dims ()); if (xisint (b)) { if (b == -1) { for (octave_idx_type i = 0; i < a.numel (); i++) result.xelem (i) = 1.0 / a(i); } else { for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), static_cast<int> (b)); } } } else { for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b); } } return result; } // -*- 10 -*- octave_value elem_xpow (const ComplexNDArray& a, const NDArray& b) { dim_vector a_dims = a.dims (); dim_vector b_dims = b.dims (); if (a_dims != b_dims) { if (is_valid_bsxfun ("operator .^", a_dims, b_dims)) { return bsxfun_pow (a, b); } else err_nonconformant ("operator .^", a_dims, b_dims); } ComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); double btmp = b(i); if (xisint (btmp)) result(i) = std::pow (a(i), static_cast<int> (btmp)); else result(i) = std::pow (a(i), btmp); } return result; } // -*- 11 -*- octave_value elem_xpow (const ComplexNDArray& a, const Complex& b) { ComplexNDArray result (a.dims ()); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b); } return result; } // -*- 12 -*- octave_value elem_xpow (const ComplexNDArray& a, const ComplexNDArray& b) { dim_vector a_dims = a.dims (); dim_vector b_dims = b.dims (); if (a_dims != b_dims) { if (is_valid_bsxfun ("operator .^", a_dims, b_dims)) { return bsxfun_pow (a, b); } else err_nonconformant ("operator .^", a_dims, b_dims); } ComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b(i)); } return result; } static inline int xisint (float x) { return (D_NINT (x) == x && ((x >= 0 && x < std::numeric_limits<int>::max ()) || (x <= 0 && x > std::numeric_limits<int>::min ()))); } // Safer pow functions. // // op2 \ op1: s m cs cm // +-- +---+---+----+----+ // scalar | | 1 | 5 | 7 | 11 | // +---+---+----+----+ // matrix | 2 | * | 8 | * | // +---+---+----+----+ // complex_scalar | 3 | 6 | 9 | 12 | // +---+---+----+----+ // complex_matrix | 4 | * | 10 | * | // +---+---+----+----+ // -*- 1 -*- octave_value xpow (float a, float b) { float retval; if (a < 0.0 && ! xisint (b)) { FloatComplex atmp (a); return std::pow (atmp, b); } else retval = std::pow (a, b); return retval; } // -*- 2 -*- octave_value xpow (float a, const FloatMatrix& b) { octave_value retval; octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for x^A, A must be a square matrix. Use .^ for elementwise power."); FloatEIG b_eig (b); try { FloatComplexColumnVector lambda (b_eig.eigenvalues ()); FloatComplexMatrix Q (b_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) { FloatComplex elt = lambda(i); if (std::imag (elt) == 0.0) lambda(i) = std::pow (a, std::real (elt)); else lambda(i) = std::pow (a, elt); } FloatComplexDiagMatrix D (lambda); FloatComplexMatrix C = Q * D * Q.inverse (); if (a > 0) retval = real (C); else retval = C; } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 3 -*- octave_value xpow (float a, const FloatComplex& b) { FloatComplex result = std::pow (a, b); return result; } // -*- 4 -*- octave_value xpow (float a, const FloatComplexMatrix& b) { octave_value retval; octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for x^A, A must be a square matrix. Use .^ for elementwise power."); FloatEIG b_eig (b); try { FloatComplexColumnVector lambda (b_eig.eigenvalues ()); FloatComplexMatrix Q (b_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) { FloatComplex elt = lambda(i); if (std::imag (elt) == 0.0) lambda(i) = std::pow (a, std::real (elt)); else lambda(i) = std::pow (a, elt); } FloatComplexDiagMatrix D (lambda); retval = FloatComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 5 -*- octave_value xpow (const FloatMatrix& a, float b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); if (static_cast<int> (b) == b) { int btmp = static_cast<int> (b); if (btmp == 0) { retval = FloatDiagMatrix (nr, nr, 1.0); } else { // Too much copying? // FIXME: we shouldn't do this if the exponent is large... FloatMatrix atmp; if (btmp < 0) { btmp = -btmp; octave_idx_type info; float rcond = 0.0; MatrixType mattype (a); atmp = a.inverse (mattype, info, rcond, 1); if (info == -1) warning ("inverse: matrix singular to machine\ precision, rcond = %g", rcond); } else atmp = a; FloatMatrix result (atmp); btmp--; while (btmp > 0) { if (btmp & 1) result = result * atmp; btmp >>= 1; if (btmp > 0) atmp = atmp * atmp; } retval = result; } } else { FloatEIG a_eig (a); try { FloatComplexColumnVector lambda (a_eig.eigenvalues ()); FloatComplexMatrix Q (a_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) lambda(i) = std::pow (lambda(i), b); FloatComplexDiagMatrix D (lambda); retval = FloatComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } } return retval; } // -*- 5d -*- octave_value xpow (const FloatDiagMatrix& a, float b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); if (static_cast<int> (b) == b) { FloatDiagMatrix r (nr, nc); for (octave_idx_type i = 0; i < nc; i++) r.dgelem (i) = std::pow (a.dgelem (i), b); retval = r; } else { FloatComplexDiagMatrix r (nr, nc); for (octave_idx_type i = 0; i < nc; i++) r.dgelem (i) = std::pow (static_cast<FloatComplex> (a.dgelem (i)), b); retval = r; } return retval; } // -*- 6 -*- octave_value xpow (const FloatMatrix& a, const FloatComplex& b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); FloatEIG a_eig (a); try { FloatComplexColumnVector lambda (a_eig.eigenvalues ()); FloatComplexMatrix Q (a_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) lambda(i) = std::pow (lambda(i), b); FloatComplexDiagMatrix D (lambda); retval = FloatComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 7 -*- octave_value xpow (const FloatComplex& a, float b) { FloatComplex result; if (xisint (b)) result = std::pow (a, static_cast<int> (b)); else result = std::pow (a, b); return result; } // -*- 8 -*- octave_value xpow (const FloatComplex& a, const FloatMatrix& b) { octave_value retval; octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for x^A, A must be a square matrix. Use .^ for elementwise power."); FloatEIG b_eig (b); try { FloatComplexColumnVector lambda (b_eig.eigenvalues ()); FloatComplexMatrix Q (b_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) { FloatComplex elt = lambda(i); if (std::imag (elt) == 0.0) lambda(i) = std::pow (a, std::real (elt)); else lambda(i) = std::pow (a, elt); } FloatComplexDiagMatrix D (lambda); retval = FloatComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 9 -*- octave_value xpow (const FloatComplex& a, const FloatComplex& b) { FloatComplex result; result = std::pow (a, b); return result; } // -*- 10 -*- octave_value xpow (const FloatComplex& a, const FloatComplexMatrix& b) { octave_value retval; octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for x^A, A must be a square matrix. Use .^ for elementwise power."); FloatEIG b_eig (b); try { FloatComplexColumnVector lambda (b_eig.eigenvalues ()); FloatComplexMatrix Q (b_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) { FloatComplex elt = lambda(i); if (std::imag (elt) == 0.0) lambda(i) = std::pow (a, std::real (elt)); else lambda(i) = std::pow (a, elt); } FloatComplexDiagMatrix D (lambda); retval = FloatComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 11 -*- octave_value xpow (const FloatComplexMatrix& a, float b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); if (static_cast<int> (b) == b) { int btmp = static_cast<int> (b); if (btmp == 0) { retval = FloatDiagMatrix (nr, nr, 1.0); } else { // Too much copying? // FIXME: we shouldn't do this if the exponent is large... FloatComplexMatrix atmp; if (btmp < 0) { btmp = -btmp; octave_idx_type info; float rcond = 0.0; MatrixType mattype (a); atmp = a.inverse (mattype, info, rcond, 1); if (info == -1) warning ("inverse: matrix singular to machine\ precision, rcond = %g", rcond); } else atmp = a; FloatComplexMatrix result (atmp); btmp--; while (btmp > 0) { if (btmp & 1) result = result * atmp; btmp >>= 1; if (btmp > 0) atmp = atmp * atmp; } retval = result; } } else { FloatEIG a_eig (a); try { FloatComplexColumnVector lambda (a_eig.eigenvalues ()); FloatComplexMatrix Q (a_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) lambda(i) = std::pow (lambda(i), b); FloatComplexDiagMatrix D (lambda); retval = FloatComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } } return retval; } // -*- 12 -*- octave_value xpow (const FloatComplexMatrix& a, const FloatComplex& b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); FloatEIG a_eig (a); try { FloatComplexColumnVector lambda (a_eig.eigenvalues ()); FloatComplexMatrix Q (a_eig.eigenvectors ()); for (octave_idx_type i = 0; i < nr; i++) lambda(i) = std::pow (lambda(i), b); FloatComplexDiagMatrix D (lambda); retval = FloatComplexMatrix (Q * D * Q.inverse ()); } catch (const octave_execution_exception&) { gripe_failed_diagonalization (); } return retval; } // -*- 12d -*- octave_value xpow (const FloatComplexDiagMatrix& a, const FloatComplex& b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (nr == 0 || nc == 0 || nr != nc) error ("for A^b, A must be a square matrix. Use .^ for elementwise power."); FloatComplexDiagMatrix r (nr, nc); for (octave_idx_type i = 0; i < nc; i++) r(i, i) = std::pow (a(i, i), b); retval = r; return retval; } // mixed octave_value xpow (const FloatComplexDiagMatrix& a, float b) { return xpow (a, static_cast<FloatComplex> (b)); } octave_value xpow (const FloatDiagMatrix& a, const FloatComplex& b) { return xpow (FloatComplexDiagMatrix (a), b); } // 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. // FIXME: these functions need to be fixed so that things like // // a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b // // and // // a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end // // produce identical results. Also, it would be nice if -1^0.5 // produced a pure imaginary result instead of a complex number with a // small real part. But perhaps that's really a problem with the math // library... // -*- 1 -*- octave_value elem_xpow (float a, const FloatMatrix& b) { octave_value retval; octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); float d1, d2; if (a < 0.0 && ! b.all_integers (d1, d2)) { FloatComplex atmp (a); FloatComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (atmp, b (i, j)); } retval = result; } else { FloatMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a, b (i, j)); } retval = result; } return retval; } // -*- 2 -*- octave_value elem_xpow (float a, const FloatComplexMatrix& b) { octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); FloatComplexMatrix result (nr, nc); FloatComplex atmp (a); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (atmp, b (i, j)); } return result; } // -*- 3 -*- octave_value elem_xpow (const FloatMatrix& a, float b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); if (! xisint (b) && a.any_element_is_negative ()) { FloatComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); FloatComplex atmp (a (i, j)); result (i, j) = std::pow (atmp, b); } retval = result; } else { FloatMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), b); } retval = result; } return retval; } // -*- 4 -*- octave_value elem_xpow (const FloatMatrix& a, const FloatMatrix& b) { octave_value retval; octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); octave_idx_type b_nr = b.rows (); octave_idx_type b_nc = b.cols (); if (nr != b_nr || nc != b_nc) err_nonconformant ("operator .^", nr, nc, b_nr, b_nc); int convert_to_complex = 0; for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); float atmp = a (i, j); float btmp = b (i, j); if (atmp < 0.0 && static_cast<int> (btmp) != btmp) { convert_to_complex = 1; goto done; } } done: if (convert_to_complex) { FloatComplexMatrix complex_result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); FloatComplex atmp (a (i, j)); FloatComplex btmp (b (i, j)); complex_result (i, j) = std::pow (atmp, btmp); } retval = complex_result; } else { FloatMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), b (i, j)); } retval = result; } return retval; } // -*- 5 -*- octave_value elem_xpow (const FloatMatrix& a, const FloatComplex& b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); FloatComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (FloatComplex (a (i, j)), b); } return result; } // -*- 6 -*- octave_value elem_xpow (const FloatMatrix& a, const FloatComplexMatrix& b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); octave_idx_type b_nr = b.rows (); octave_idx_type b_nc = b.cols (); if (nr != b_nr || nc != b_nc) err_nonconformant ("operator .^", nr, nc, b_nr, b_nc); FloatComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (FloatComplex (a (i, j)), b (i, j)); } return result; } // -*- 7 -*- octave_value elem_xpow (const FloatComplex& a, const FloatMatrix& b) { octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); FloatComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); float btmp = b (i, j); if (xisint (btmp)) result (i, j) = std::pow (a, static_cast<int> (btmp)); else result (i, j) = std::pow (a, btmp); } return result; } // -*- 8 -*- octave_value elem_xpow (const FloatComplex& a, const FloatComplexMatrix& b) { octave_idx_type nr = b.rows (); octave_idx_type nc = b.cols (); FloatComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a, b (i, j)); } return result; } // -*- 9 -*- octave_value elem_xpow (const FloatComplexMatrix& a, float b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); FloatComplexMatrix result (nr, nc); if (xisint (b)) { for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), static_cast<int> (b)); } } else { for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), b); } } return result; } // -*- 10 -*- octave_value elem_xpow (const FloatComplexMatrix& a, const FloatMatrix& b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); octave_idx_type b_nr = b.rows (); octave_idx_type b_nc = b.cols (); if (nr != b_nr || nc != b_nc) err_nonconformant ("operator .^", nr, nc, b_nr, b_nc); FloatComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); float btmp = b (i, j); if (xisint (btmp)) result (i, j) = std::pow (a (i, j), static_cast<int> (btmp)); else result (i, j) = std::pow (a (i, j), btmp); } return result; } // -*- 11 -*- octave_value elem_xpow (const FloatComplexMatrix& a, const FloatComplex& b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); FloatComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), b); } return result; } // -*- 12 -*- octave_value elem_xpow (const FloatComplexMatrix& a, const FloatComplexMatrix& b) { octave_idx_type nr = a.rows (); octave_idx_type nc = a.cols (); octave_idx_type b_nr = b.rows (); octave_idx_type b_nc = b.cols (); if (nr != b_nr || nc != b_nc) err_nonconformant ("operator .^", nr, nc, b_nr, b_nc); FloatComplexMatrix result (nr, nc); for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) { octave_quit (); result (i, j) = std::pow (a (i, j), b (i, j)); } return result; } // Safer pow functions that work elementwise for N-D arrays. // // op2 \ op1: s nd cs cnd // +-- +---+---+----+----+ // scalar | | * | 3 | * | 9 | // +---+---+----+----+ // N_d | 1 | 4 | 7 | 10 | // +---+---+----+----+ // complex_scalar | * | 5 | * | 11 | // +---+---+----+----+ // complex_N_d | 2 | 6 | 8 | 12 | // +---+---+----+----+ // // * -> not needed. // FIXME: these functions need to be fixed so that things like // // a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b // // and // // a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end // // produce identical results. Also, it would be nice if -1^0.5 // produced a pure imaginary result instead of a complex number with a // small real part. But perhaps that's really a problem with the math // library... // -*- 1 -*- octave_value elem_xpow (float a, const FloatNDArray& b) { octave_value retval; if (a < 0.0 && ! b.all_integers ()) { FloatComplex atmp (a); FloatComplexNDArray result (b.dims ()); for (octave_idx_type i = 0; i < b.numel (); i++) { octave_quit (); result(i) = std::pow (atmp, b(i)); } retval = result; } else { FloatNDArray result (b.dims ()); for (octave_idx_type i = 0; i < b.numel (); i++) { octave_quit (); result (i) = std::pow (a, b(i)); } retval = result; } return retval; } // -*- 2 -*- octave_value elem_xpow (float a, const FloatComplexNDArray& b) { FloatComplexNDArray result (b.dims ()); for (octave_idx_type i = 0; i < b.numel (); i++) { octave_quit (); result(i) = std::pow (a, b(i)); } return result; } // -*- 3 -*- octave_value elem_xpow (const FloatNDArray& a, float b) { octave_value retval; if (! xisint (b)) { if (a.any_element_is_negative ()) { FloatComplexNDArray result (a.dims ()); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); FloatComplex atmp (a (i)); result(i) = std::pow (atmp, b); } retval = result; } else { FloatNDArray result (a.dims ()); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b); } retval = result; } } else { NoAlias<FloatNDArray> result (a.dims ()); int ib = static_cast<int> (b); if (ib == 2) { for (octave_idx_type i = 0; i < a.numel (); i++) result(i) = a(i) * a(i); } else if (ib == 3) { for (octave_idx_type i = 0; i < a.numel (); i++) result(i) = a(i) * a(i) * a(i); } else if (ib == -1) { for (octave_idx_type i = 0; i < a.numel (); i++) result(i) = 1.0f / a(i); } else { for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), ib); } } retval = result; } return retval; } // -*- 4 -*- octave_value elem_xpow (const FloatNDArray& a, const FloatNDArray& b) { octave_value retval; dim_vector a_dims = a.dims (); dim_vector b_dims = b.dims (); if (a_dims != b_dims) { if (is_valid_bsxfun ("operator .^", a_dims, b_dims)) { //Potentially complex results FloatNDArray xa = octave_value_extract<FloatNDArray> (a); FloatNDArray xb = octave_value_extract<FloatNDArray> (b); if (! xb.all_integers () && xa.any_element_is_negative ()) return octave_value (bsxfun_pow (FloatComplexNDArray (xa), xb)); else return octave_value (bsxfun_pow (xa, xb)); } else err_nonconformant ("operator .^", a_dims, b_dims); } int len = a.numel (); bool convert_to_complex = false; for (octave_idx_type i = 0; i < len; i++) { octave_quit (); float atmp = a(i); float btmp = b(i); if (atmp < 0.0 && static_cast<int> (btmp) != btmp) { convert_to_complex = true; goto done; } } done: if (convert_to_complex) { FloatComplexNDArray complex_result (a_dims); for (octave_idx_type i = 0; i < len; i++) { octave_quit (); FloatComplex atmp (a(i)); complex_result(i) = std::pow (atmp, b(i)); } retval = complex_result; } else { FloatNDArray result (a_dims); for (octave_idx_type i = 0; i < len; i++) { octave_quit (); result(i) = std::pow (a(i), b(i)); } retval = result; } return retval; } // -*- 5 -*- octave_value elem_xpow (const FloatNDArray& a, const FloatComplex& b) { FloatComplexNDArray result (a.dims ()); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b); } return result; } // -*- 6 -*- octave_value elem_xpow (const FloatNDArray& a, const FloatComplexNDArray& b) { dim_vector a_dims = a.dims (); dim_vector b_dims = b.dims (); if (a_dims != b_dims) { if (is_valid_bsxfun ("operator .^", a_dims, b_dims)) { return bsxfun_pow (a, b); } else err_nonconformant ("operator .^", a_dims, b_dims); } FloatComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b(i)); } return result; } // -*- 7 -*- octave_value elem_xpow (const FloatComplex& a, const FloatNDArray& b) { FloatComplexNDArray result (b.dims ()); for (octave_idx_type i = 0; i < b.numel (); i++) { octave_quit (); float btmp = b(i); if (xisint (btmp)) result(i) = std::pow (a, static_cast<int> (btmp)); else result(i) = std::pow (a, btmp); } return result; } // -*- 8 -*- octave_value elem_xpow (const FloatComplex& a, const FloatComplexNDArray& b) { FloatComplexNDArray result (b.dims ()); for (octave_idx_type i = 0; i < b.numel (); i++) { octave_quit (); result(i) = std::pow (a, b(i)); } return result; } // -*- 9 -*- octave_value elem_xpow (const FloatComplexNDArray& a, float b) { FloatComplexNDArray result (a.dims ()); if (xisint (b)) { if (b == -1) { for (octave_idx_type i = 0; i < a.numel (); i++) result.xelem (i) = 1.0f / a(i); } else { for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), static_cast<int> (b)); } } } else { for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b); } } return result; } // -*- 10 -*- octave_value elem_xpow (const FloatComplexNDArray& a, const FloatNDArray& b) { dim_vector a_dims = a.dims (); dim_vector b_dims = b.dims (); if (a_dims != b_dims) { if (is_valid_bsxfun ("operator .^", a_dims, b_dims)) { return bsxfun_pow (a, b); } else err_nonconformant ("operator .^", a_dims, b_dims); } FloatComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); float btmp = b(i); if (xisint (btmp)) result(i) = std::pow (a(i), static_cast<int> (btmp)); else result(i) = std::pow (a(i), btmp); } return result; } // -*- 11 -*- octave_value elem_xpow (const FloatComplexNDArray& a, const FloatComplex& b) { FloatComplexNDArray result (a.dims ()); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b); } return result; } // -*- 12 -*- octave_value elem_xpow (const FloatComplexNDArray& a, const FloatComplexNDArray& b) { dim_vector a_dims = a.dims (); dim_vector b_dims = b.dims (); if (a_dims != b_dims) { if (is_valid_bsxfun ("operator .^", a_dims, b_dims)) { return bsxfun_pow (a, b); } else err_nonconformant ("operator .^", a_dims, b_dims); } FloatComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.numel (); i++) { octave_quit (); result(i) = std::pow (a(i), b(i)); } return result; }