Mercurial > hg > octave-lyh
view libinterp/corefcn/xpow.cc @ 17289:bc924baa2c4e
doc: Add new @qcode macro for code samples which are quoted.
Macro handles options ("on") or properties ("position") more elegantly
than @code{"text"}.
* doc/interpreter/macros.texi: Add new @qcode macro.
* doc/interpreter/tips.txi: Add documentation about @qcode macro.
* doc/interpreter/basics.txi, doc/interpreter/container.txi,
doc/interpreter/emacs.txi, doc/interpreter/errors.txi,
doc/interpreter/eval.txi, doc/interpreter/expr.txi,
doc/interpreter/external.txi, doc/interpreter/func.txi,
doc/interpreter/grammar.txi, doc/interpreter/image.txi,
doc/interpreter/install.txi, doc/interpreter/interp.txi,
doc/interpreter/io.txi, doc/interpreter/matrix.txi,
doc/interpreter/numbers.txi, doc/interpreter/oop.txi,
doc/interpreter/package.txi, doc/interpreter/plot.txi,
doc/interpreter/quad.txi, doc/interpreter/sparse.txi,
doc/interpreter/strings.txi, doc/interpreter/system.txi,
doc/interpreter/vectorize.txi, libinterp/corefcn/balance.cc,
libinterp/corefcn/bitfcns.cc, libinterp/corefcn/cellfun.cc,
libinterp/corefcn/conv2.cc, libinterp/corefcn/data.cc,
libinterp/corefcn/debug.cc, libinterp/corefcn/defaults.cc,
libinterp/corefcn/dirfns.cc, libinterp/corefcn/dlmread.cc,
libinterp/corefcn/error.cc, libinterp/corefcn/file-io.cc,
libinterp/corefcn/find.cc, libinterp/corefcn/gammainc.cc,
libinterp/corefcn/graphics.cc, libinterp/corefcn/help.cc,
libinterp/corefcn/hex2num.cc, libinterp/corefcn/input.cc,
libinterp/corefcn/load-path.cc, libinterp/corefcn/load-save.cc,
libinterp/corefcn/ls-oct-ascii.cc, libinterp/corefcn/lu.cc,
libinterp/corefcn/luinc.cc, libinterp/corefcn/matrix_type.cc,
libinterp/corefcn/oct-hist.cc, libinterp/corefcn/pager.cc,
libinterp/corefcn/pr-output.cc, libinterp/corefcn/pt-jit.cc,
libinterp/corefcn/qz.cc, libinterp/corefcn/rand.cc,
libinterp/corefcn/regexp.cc, libinterp/corefcn/schur.cc,
libinterp/corefcn/sighandlers.cc, libinterp/corefcn/sparse.cc,
libinterp/corefcn/spparms.cc, libinterp/corefcn/str2double.cc,
libinterp/corefcn/svd.cc, libinterp/corefcn/symtab.cc,
libinterp/corefcn/syscalls.cc, libinterp/corefcn/toplev.cc,
libinterp/corefcn/tril.cc, libinterp/corefcn/typecast.cc,
libinterp/corefcn/utils.cc, libinterp/corefcn/variables.cc,
libinterp/dldfcn/__init_fltk__.cc, libinterp/dldfcn/chol.cc,
libinterp/dldfcn/colamd.cc, libinterp/dldfcn/fftw.cc, libinterp/dldfcn/qr.cc,
libinterp/dldfcn/symbfact.cc, libinterp/octave-value/ov-base.cc,
libinterp/octave-value/ov-fcn-handle.cc,
libinterp/octave-value/ov-fcn-inline.cc, libinterp/octave-value/ov-java.cc,
libinterp/octave-value/ov-range.cc, libinterp/octave-value/ov-struct.cc,
libinterp/octave-value/ov-usr-fcn.cc, libinterp/parse-tree/oct-parse.in.yy,
libinterp/parse-tree/pt-binop.cc, libinterp/parse-tree/pt-eval.cc,
libinterp/parse-tree/pt-mat.cc, scripts/@ftp/ftp.m,
scripts/deprecated/java_convert_matrix.m, scripts/deprecated/java_debug.m,
scripts/deprecated/java_unsigned_conversion.m, scripts/deprecated/shell_cmd.m,
scripts/general/dblquad.m, scripts/general/display.m,
scripts/general/genvarname.m, scripts/general/idivide.m,
scripts/general/interp1.m, scripts/general/interp2.m,
scripts/general/interp3.m, scripts/general/interpn.m, scripts/general/isa.m,
scripts/general/profexplore.m, scripts/general/profile.m,
scripts/general/quadgk.m, scripts/general/randi.m, scripts/general/structfun.m,
scripts/general/subsindex.m, scripts/general/triplequad.m,
scripts/geometry/griddata.m, scripts/geometry/griddata3.m,
scripts/geometry/griddatan.m, scripts/geometry/voronoi.m, scripts/help/help.m,
scripts/help/lookfor.m, scripts/image/cmpermute.m, scripts/image/colormap.m,
scripts/image/image.m, scripts/image/imagesc.m, scripts/image/imfinfo.m,
scripts/image/imformats.m, scripts/image/imread.m, scripts/image/imshow.m,
scripts/image/imwrite.m, scripts/image/ind2gray.m, scripts/image/lines.m,
scripts/image/rgb2ind.m, scripts/image/spinmap.m, scripts/io/dlmwrite.m,
scripts/io/strread.m, scripts/io/textread.m, scripts/io/textscan.m,
scripts/java/javaclasspath.m, scripts/java/usejava.m,
scripts/miscellaneous/bzip2.m, scripts/miscellaneous/computer.m,
scripts/miscellaneous/copyfile.m, scripts/miscellaneous/debug.m,
scripts/miscellaneous/dos.m, scripts/miscellaneous/edit.m,
scripts/miscellaneous/gzip.m, scripts/miscellaneous/license.m,
scripts/miscellaneous/mkoctfile.m, scripts/miscellaneous/movefile.m,
scripts/miscellaneous/parseparams.m, scripts/miscellaneous/unix.m,
scripts/optimization/fminbnd.m, scripts/optimization/fminsearch.m,
scripts/optimization/fminunc.m, scripts/optimization/fsolve.m,
scripts/optimization/fzero.m, scripts/optimization/glpk.m,
scripts/optimization/lsqnonneg.m, scripts/optimization/optimset.m,
scripts/optimization/pqpnonneg.m, scripts/pkg/pkg.m, scripts/plot/allchild.m,
scripts/plot/ancestor.m, scripts/plot/area.m, scripts/plot/axis.m,
scripts/plot/bar.m, scripts/plot/barh.m, scripts/plot/box.m,
scripts/plot/caxis.m, scripts/plot/cla.m, scripts/plot/clabel.m,
scripts/plot/clf.m, scripts/plot/close.m, scripts/plot/colorbar.m,
scripts/plot/daspect.m, scripts/plot/ezmesh.m, scripts/plot/ezmeshc.m,
scripts/plot/ezsurf.m, scripts/plot/ezsurfc.m, scripts/plot/findall.m,
scripts/plot/findobj.m, scripts/plot/gcbo.m, scripts/plot/gcf.m,
scripts/plot/gco.m, scripts/plot/grid.m, scripts/plot/guihandles.m,
scripts/plot/hdl2struct.m, scripts/plot/hidden.m, scripts/plot/hold.m,
scripts/plot/isonormals.m, scripts/plot/isosurface.m, scripts/plot/legend.m,
scripts/plot/mesh.m, scripts/plot/meshc.m, scripts/plot/meshz.m,
scripts/plot/newplot.m, scripts/plot/orient.m, scripts/plot/pareto.m,
scripts/plot/patch.m, scripts/plot/pbaspect.m, scripts/plot/pcolor.m,
scripts/plot/plot.m, scripts/plot/print.m,
scripts/plot/private/__add_default_menu__.m, scripts/plot/quiver.m,
scripts/plot/quiver3.m, scripts/plot/refreshdata.m, scripts/plot/saveas.m,
scripts/plot/scatter.m, scripts/plot/scatter3.m, scripts/plot/shading.m,
scripts/plot/shrinkfaces.m, scripts/plot/slice.m, scripts/plot/stem.m,
scripts/plot/stem3.m, scripts/plot/struct2hdl.m, scripts/plot/subplot.m,
scripts/plot/surf.m, scripts/plot/surfc.m, scripts/plot/surfl.m,
scripts/plot/tetramesh.m, scripts/plot/uigetfile.m, scripts/plot/uimenu.m,
scripts/plot/uiputfile.m, scripts/plot/waterfall.m, scripts/plot/whitebg.m,
scripts/plot/xlim.m, scripts/plot/ylim.m, scripts/plot/zlim.m,
scripts/polynomial/conv.m, scripts/polynomial/polyout.m,
scripts/polynomial/splinefit.m, scripts/set/ismember.m, scripts/set/powerset.m,
scripts/set/setdiff.m, scripts/set/union.m, scripts/set/unique.m,
scripts/signal/detrend.m, scripts/signal/filter2.m, scripts/signal/freqz.m,
scripts/signal/periodogram.m, scripts/signal/spectral_adf.m,
scripts/signal/spectral_xdf.m, scripts/sparse/eigs.m, scripts/sparse/svds.m,
scripts/specfun/legendre.m, scripts/special-matrix/gallery.m,
scripts/statistics/base/mean.m, scripts/statistics/base/moment.m,
scripts/statistics/tests/cor_test.m,
scripts/statistics/tests/kolmogorov_smirnov_test.m,
scripts/statistics/tests/kolmogorov_smirnov_test_2.m,
scripts/statistics/tests/kruskal_wallis_test.m,
scripts/statistics/tests/prop_test_2.m, scripts/statistics/tests/sign_test.m,
scripts/statistics/tests/t_test.m, scripts/statistics/tests/t_test_2.m,
scripts/statistics/tests/t_test_regression.m,
scripts/statistics/tests/u_test.m, scripts/statistics/tests/var_test.m,
scripts/statistics/tests/welch_test.m,
scripts/statistics/tests/wilcoxon_test.m, scripts/statistics/tests/z_test.m,
scripts/statistics/tests/z_test_2.m, scripts/strings/base2dec.m,
scripts/strings/index.m, scripts/strings/isstrprop.m,
scripts/strings/mat2str.m, scripts/strings/regexptranslate.m,
scripts/strings/rindex.m, scripts/strings/str2num.m, scripts/strings/strcat.m,
scripts/strings/strjust.m, scripts/strings/strmatch.m,
scripts/strings/validatestring.m, scripts/testfun/demo.m,
scripts/testfun/example.m, scripts/testfun/test.m, scripts/time/addtodate.m,
scripts/time/asctime.m, scripts/time/datestr.m, scripts/time/datetick.m,
scripts/time/weekday.m, scripts/ui/errordlg.m, scripts/ui/helpdlg.m,
scripts/ui/inputdlg.m, scripts/ui/listdlg.m, scripts/ui/msgbox.m,
scripts/ui/questdlg.m, scripts/ui/warndlg.m: Use new @qcode macro.
author | Rik <rik@octave.org> |
---|---|
date | Mon, 19 Aug 2013 20:46:38 -0700 |
parents | 68fc671a9339 |
children |
line wrap: on
line source
/* Copyright (C) 1993-2012 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 "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 "oct-cmplx.h" #include "Range.h" #include "quit.h" #include "error.h" #include "oct-obj.h" #include "utils.h" #include "xpow.h" #include "bsxfun.h" #ifdef _OPENMP #include <omp.h> #endif 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"); else { EIG b_eig (b); if (! error_state) { 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; } else error ("xpow: matrix diagonalization failed"); } 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"); else { EIG b_eig (b); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } 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"); else { 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); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } } 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"); else { 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"); else { EIG a_eig (a); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } 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"); else { EIG b_eig (b); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } 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"); else { EIG b_eig (b); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } 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"); else { 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); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } } 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"); else { EIG a_eig (a); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } 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"); else { 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.nelem () > 1 && r.all_elements_are_ints () && same_sign (r.base (), r.limit ())) { octave_idx_type n = r.nelem (); 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) { gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); return octave_value (); } 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) { gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); return octave_value (); } 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.nelem () > 1 && r.all_elements_are_ints () && same_sign (r.base (), r.limit ())) { octave_idx_type n = r.nelem (); 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) { gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); return octave_value (); } 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) { gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); return octave_value (); } 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.length (); 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.length (); 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.length (); 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.length (); 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.length (); 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.length (); i++) result(i) = a(i) * a(i); } else if (ib == 3) { for (octave_idx_type i = 0; i < a.length (); i++) result(i) = a(i) * a(i) * a(i); } else if (ib == -1) { for (octave_idx_type i = 0; i < a.length (); i++) result(i) = 1.0 / a(i); } else { for (octave_idx_type i = 0; i < a.length (); 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 { gripe_nonconformant ("operator .^", a_dims, b_dims); return octave_value (); } } int len = a.length (); 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.length (); 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 { gripe_nonconformant ("operator .^", a_dims, b_dims); return octave_value (); } } ComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.length (); 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.length (); 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.length (); 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.length (); i++) result.xelem (i) = 1.0 / a(i); } else { for (octave_idx_type i = 0; i < a.length (); i++) { octave_quit (); result(i) = std::pow (a(i), static_cast<int> (b)); } } } else { for (octave_idx_type i = 0; i < a.length (); 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 { gripe_nonconformant ("operator .^", a_dims, b_dims); return octave_value (); } } ComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.length (); 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.length (); 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 { gripe_nonconformant ("operator .^", a_dims, b_dims); return octave_value (); } } ComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.length (); 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"); else { FloatEIG b_eig (b); if (! error_state) { 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; } else error ("xpow: matrix diagonalization failed"); } 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"); else { FloatEIG b_eig (b); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } 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"); else { 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); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } } 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"); else { 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"); else { FloatEIG a_eig (a); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } 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"); else { FloatEIG b_eig (b); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } 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"); else { FloatEIG b_eig (b); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } 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"); else { 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); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } } 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"); else { FloatEIG a_eig (a); if (! error_state) { 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 ()); } else error ("xpow: matrix diagonalization failed"); } 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"); else { 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) { gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); return octave_value (); } 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) { gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); return octave_value (); } 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) { gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); return octave_value (); } 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) { gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); return octave_value (); } 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.length (); 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.length (); 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.length (); 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.length (); 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.length (); 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.length (); i++) result(i) = a(i) * a(i); } else if (ib == 3) { for (octave_idx_type i = 0; i < a.length (); i++) result(i) = a(i) * a(i) * a(i); } else if (ib == -1) { for (octave_idx_type i = 0; i < a.length (); i++) result(i) = 1.0f / a(i); } else { for (octave_idx_type i = 0; i < a.length (); 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 { gripe_nonconformant ("operator .^", a_dims, b_dims); return octave_value (); } } int len = a.length (); 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.length (); 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 { gripe_nonconformant ("operator .^", a_dims, b_dims); return octave_value (); } } FloatComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.length (); 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.length (); 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.length (); 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.length (); i++) result.xelem (i) = 1.0f / a(i); } else { for (octave_idx_type i = 0; i < a.length (); i++) { octave_quit (); result(i) = std::pow (a(i), static_cast<int> (b)); } } } else { for (octave_idx_type i = 0; i < a.length (); 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 { gripe_nonconformant ("operator .^", a_dims, b_dims); return octave_value (); } } FloatComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.length (); 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.length (); 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 { gripe_nonconformant ("operator .^", a_dims, b_dims); return octave_value (); } } FloatComplexNDArray result (a_dims); for (octave_idx_type i = 0; i < a.length (); i++) { octave_quit (); result(i) = std::pow (a(i), b(i)); } return result; }