GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
xpow.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2013 John W. Eaton
4 Copyright (C) 2009-2010 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <cassert>
29 
30 #include <limits>
31 
32 #include "Array-util.h"
33 #include "CColVector.h"
34 #include "CDiagMatrix.h"
35 #include "fCDiagMatrix.h"
36 #include "CMatrix.h"
37 #include "EIG.h"
38 #include "fEIG.h"
39 #include "dDiagMatrix.h"
40 #include "fDiagMatrix.h"
41 #include "dMatrix.h"
42 #include "PermMatrix.h"
43 #include "mx-cm-cdm.h"
44 #include "oct-cmplx.h"
45 #include "Range.h"
46 #include "quit.h"
47 
48 #include "error.h"
49 #include "oct-obj.h"
50 #include "utils.h"
51 #include "xpow.h"
52 
53 #include "bsxfun.h"
54 
55 #ifdef _OPENMP
56 #include <omp.h>
57 #endif
58 
59 static inline int
60 xisint (double x)
61 {
62  return (D_NINT (x) == x
63  && ((x >= 0 && x < std::numeric_limits<int>::max ())
64  || (x <= 0 && x > std::numeric_limits<int>::min ())));
65 }
66 
67 // Safer pow functions.
68 //
69 // op2 \ op1: s m cs cm
70 // +-- +---+---+----+----+
71 // scalar | | 1 | 5 | 7 | 11 |
72 // +---+---+----+----+
73 // matrix | 2 | * | 8 | * |
74 // +---+---+----+----+
75 // complex_scalar | 3 | 6 | 9 | 12 |
76 // +---+---+----+----+
77 // complex_matrix | 4 | * | 10 | * |
78 // +---+---+----+----+
79 
80 // -*- 1 -*-
82 xpow (double a, double b)
83 {
84  double retval;
85 
86  if (a < 0.0 && ! xisint (b))
87  {
88  Complex atmp (a);
89 
90  return std::pow (atmp, b);
91  }
92  else
93  retval = std::pow (a, b);
94 
95  return retval;
96 }
97 
98 // -*- 2 -*-
100 xpow (double a, const Matrix& b)
101 {
102  octave_value retval;
103 
104  octave_idx_type nr = b.rows ();
105  octave_idx_type nc = b.cols ();
106 
107  if (nr == 0 || nc == 0 || nr != nc)
108  error ("for x^A, A must be a square matrix. Use .^ for elementwise power.");
109  else
110  {
111  EIG b_eig (b);
112 
113  if (! error_state)
114  {
115  ComplexColumnVector lambda (b_eig.eigenvalues ());
116  ComplexMatrix Q (b_eig.eigenvectors ());
117 
118  for (octave_idx_type i = 0; i < nr; i++)
119  {
120  Complex elt = lambda(i);
121  if (std::imag (elt) == 0.0)
122  lambda(i) = std::pow (a, std::real (elt));
123  else
124  lambda(i) = std::pow (a, elt);
125  }
126  ComplexDiagMatrix D (lambda);
127 
128  ComplexMatrix C = Q * D * Q.inverse ();
129  if (a > 0)
130  retval = real (C);
131  else
132  retval = C;
133  }
134  else
135  error ("xpow: matrix diagonalization failed");
136  }
137 
138  return retval;
139 }
140 
141 // -*- 3 -*-
143 xpow (double a, const Complex& b)
144 {
145  Complex result = std::pow (a, b);
146  return result;
147 }
148 
149 // -*- 4 -*-
151 xpow (double a, const ComplexMatrix& b)
152 {
153  octave_value retval;
154 
155  octave_idx_type nr = b.rows ();
156  octave_idx_type nc = b.cols ();
157 
158  if (nr == 0 || nc == 0 || nr != nc)
159  error ("for x^A, A must be a square matrix. Use .^ for elementwise power.");
160  else
161  {
162  EIG b_eig (b);
163 
164  if (! error_state)
165  {
166  ComplexColumnVector lambda (b_eig.eigenvalues ());
167  ComplexMatrix Q (b_eig.eigenvectors ());
168 
169  for (octave_idx_type i = 0; i < nr; i++)
170  {
171  Complex elt = lambda(i);
172  if (std::imag (elt) == 0.0)
173  lambda(i) = std::pow (a, std::real (elt));
174  else
175  lambda(i) = std::pow (a, elt);
176  }
177  ComplexDiagMatrix D (lambda);
178 
179  retval = ComplexMatrix (Q * D * Q.inverse ());
180  }
181  else
182  error ("xpow: matrix diagonalization failed");
183  }
184 
185  return retval;
186 }
187 
188 // -*- 5 -*-
190 xpow (const Matrix& a, double b)
191 {
192  octave_value retval;
193 
194  octave_idx_type nr = a.rows ();
195  octave_idx_type nc = a.cols ();
196 
197  if (nr == 0 || nc == 0 || nr != nc)
198  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
199  else
200  {
201  if (static_cast<int> (b) == b)
202  {
203  int btmp = static_cast<int> (b);
204  if (btmp == 0)
205  {
206  retval = DiagMatrix (nr, nr, 1.0);
207  }
208  else
209  {
210  // Too much copying?
211  // FIXME: we shouldn't do this if the exponent is large...
212 
213  Matrix atmp;
214  if (btmp < 0)
215  {
216  btmp = -btmp;
217 
218  octave_idx_type info;
219  double rcond = 0.0;
220  MatrixType mattype (a);
221 
222  atmp = a.inverse (mattype, info, rcond, 1);
223 
224  if (info == -1)
225  warning ("inverse: matrix singular to machine\
226  precision, rcond = %g", rcond);
227  }
228  else
229  atmp = a;
230 
231  Matrix result (atmp);
232 
233  btmp--;
234 
235  while (btmp > 0)
236  {
237  if (btmp & 1)
238  result = result * atmp;
239 
240  btmp >>= 1;
241 
242  if (btmp > 0)
243  atmp = atmp * atmp;
244  }
245 
246  retval = result;
247  }
248  }
249  else
250  {
251  EIG a_eig (a);
252 
253  if (! error_state)
254  {
255  ComplexColumnVector lambda (a_eig.eigenvalues ());
256  ComplexMatrix Q (a_eig.eigenvectors ());
257 
258  for (octave_idx_type i = 0; i < nr; i++)
259  lambda(i) = std::pow (lambda(i), b);
260 
261  ComplexDiagMatrix D (lambda);
262 
263  retval = ComplexMatrix (Q * D * Q.inverse ());
264  }
265  else
266  error ("xpow: matrix diagonalization failed");
267  }
268  }
269 
270  return retval;
271 }
272 
273 // -*- 5d -*-
275 xpow (const DiagMatrix& a, double b)
276 {
277  octave_value retval;
278 
279  octave_idx_type nr = a.rows ();
280  octave_idx_type nc = a.cols ();
281 
282  if (nr == 0 || nc == 0 || nr != nc)
283  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
284  else
285  {
286  if (static_cast<int> (b) == b)
287  {
288  DiagMatrix r (nr, nc);
289  for (octave_idx_type i = 0; i < nc; i++)
290  r.dgelem (i) = std::pow (a.dgelem (i), b);
291  retval = r;
292  }
293  else
294  {
295  ComplexDiagMatrix r (nr, nc);
296  for (octave_idx_type i = 0; i < nc; i++)
297  r.dgelem (i) = std::pow (static_cast<Complex> (a.dgelem (i)), b);
298  retval = r;
299  }
300  }
301 
302  return retval;
303 }
304 
305 // -*- 5p -*-
307 xpow (const PermMatrix& a, double b)
308 {
309  octave_value retval;
310  int btmp = static_cast<int> (b);
311  if (btmp == b)
312  return a.power (btmp);
313  else
314  return xpow (Matrix (a), b);
315 }
316 
317 // -*- 6 -*-
319 xpow (const Matrix& a, const Complex& b)
320 {
321  octave_value retval;
322 
323  octave_idx_type nr = a.rows ();
324  octave_idx_type nc = a.cols ();
325 
326  if (nr == 0 || nc == 0 || nr != nc)
327  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
328  else
329  {
330  EIG a_eig (a);
331 
332  if (! error_state)
333  {
334  ComplexColumnVector lambda (a_eig.eigenvalues ());
335  ComplexMatrix Q (a_eig.eigenvectors ());
336 
337  for (octave_idx_type i = 0; i < nr; i++)
338  lambda(i) = std::pow (lambda(i), b);
339 
340  ComplexDiagMatrix D (lambda);
341 
342  retval = ComplexMatrix (Q * D * Q.inverse ());
343  }
344  else
345  error ("xpow: matrix diagonalization failed");
346  }
347 
348  return retval;
349 }
350 
351 // -*- 7 -*-
353 xpow (const Complex& a, double b)
354 {
355  Complex result;
356 
357  if (xisint (b))
358  result = std::pow (a, static_cast<int> (b));
359  else
360  result = std::pow (a, b);
361 
362  return result;
363 }
364 
365 // -*- 8 -*-
367 xpow (const Complex& a, const Matrix& b)
368 {
369  octave_value retval;
370 
371  octave_idx_type nr = b.rows ();
372  octave_idx_type nc = b.cols ();
373 
374  if (nr == 0 || nc == 0 || nr != nc)
375  error ("for x^A, A must be a square matrix. Use .^ for elementwise power.");
376  else
377  {
378  EIG b_eig (b);
379 
380  if (! error_state)
381  {
382  ComplexColumnVector lambda (b_eig.eigenvalues ());
383  ComplexMatrix Q (b_eig.eigenvectors ());
384 
385  for (octave_idx_type i = 0; i < nr; i++)
386  {
387  Complex elt = lambda(i);
388  if (std::imag (elt) == 0.0)
389  lambda(i) = std::pow (a, std::real (elt));
390  else
391  lambda(i) = std::pow (a, elt);
392  }
393  ComplexDiagMatrix D (lambda);
394 
395  retval = ComplexMatrix (Q * D * Q.inverse ());
396  }
397  else
398  error ("xpow: matrix diagonalization failed");
399  }
400 
401  return retval;
402 }
403 
404 // -*- 9 -*-
406 xpow (const Complex& a, const Complex& b)
407 {
408  Complex result;
409  result = std::pow (a, b);
410  return result;
411 }
412 
413 // -*- 10 -*-
415 xpow (const Complex& a, const ComplexMatrix& b)
416 {
417  octave_value retval;
418 
419  octave_idx_type nr = b.rows ();
420  octave_idx_type nc = b.cols ();
421 
422  if (nr == 0 || nc == 0 || nr != nc)
423  error ("for x^A, A must be a square matrix. Use .^ for elementwise power.");
424  else
425  {
426  EIG b_eig (b);
427 
428  if (! error_state)
429  {
430  ComplexColumnVector lambda (b_eig.eigenvalues ());
431  ComplexMatrix Q (b_eig.eigenvectors ());
432 
433  for (octave_idx_type i = 0; i < nr; i++)
434  {
435  Complex elt = lambda(i);
436  if (std::imag (elt) == 0.0)
437  lambda(i) = std::pow (a, std::real (elt));
438  else
439  lambda(i) = std::pow (a, elt);
440  }
441  ComplexDiagMatrix D (lambda);
442 
443  retval = ComplexMatrix (Q * D * Q.inverse ());
444  }
445  else
446  error ("xpow: matrix diagonalization failed");
447  }
448 
449  return retval;
450 }
451 
452 // -*- 11 -*-
454 xpow (const ComplexMatrix& a, double b)
455 {
456  octave_value retval;
457 
458  octave_idx_type nr = a.rows ();
459  octave_idx_type nc = a.cols ();
460 
461  if (nr == 0 || nc == 0 || nr != nc)
462  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
463  else
464  {
465  if (static_cast<int> (b) == b)
466  {
467  int btmp = static_cast<int> (b);
468  if (btmp == 0)
469  {
470  retval = DiagMatrix (nr, nr, 1.0);
471  }
472  else
473  {
474  // Too much copying?
475  // FIXME: we shouldn't do this if the exponent is large...
476 
477  ComplexMatrix atmp;
478  if (btmp < 0)
479  {
480  btmp = -btmp;
481 
482  octave_idx_type info;
483  double rcond = 0.0;
484  MatrixType mattype (a);
485 
486  atmp = a.inverse (mattype, info, rcond, 1);
487 
488  if (info == -1)
489  warning ("inverse: matrix singular to machine\
490  precision, rcond = %g", rcond);
491  }
492  else
493  atmp = a;
494 
495  ComplexMatrix result (atmp);
496 
497  btmp--;
498 
499  while (btmp > 0)
500  {
501  if (btmp & 1)
502  result = result * atmp;
503 
504  btmp >>= 1;
505 
506  if (btmp > 0)
507  atmp = atmp * atmp;
508  }
509 
510  retval = result;
511  }
512  }
513  else
514  {
515  EIG a_eig (a);
516 
517  if (! error_state)
518  {
519  ComplexColumnVector lambda (a_eig.eigenvalues ());
520  ComplexMatrix Q (a_eig.eigenvectors ());
521 
522  for (octave_idx_type i = 0; i < nr; i++)
523  lambda(i) = std::pow (lambda(i), b);
524 
525  ComplexDiagMatrix D (lambda);
526 
527  retval = ComplexMatrix (Q * D * Q.inverse ());
528  }
529  else
530  error ("xpow: matrix diagonalization failed");
531  }
532  }
533 
534  return retval;
535 }
536 
537 // -*- 12 -*-
539 xpow (const ComplexMatrix& a, const Complex& b)
540 {
541  octave_value retval;
542 
543  octave_idx_type nr = a.rows ();
544  octave_idx_type nc = a.cols ();
545 
546  if (nr == 0 || nc == 0 || nr != nc)
547  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
548  else
549  {
550  EIG a_eig (a);
551 
552  if (! error_state)
553  {
554  ComplexColumnVector lambda (a_eig.eigenvalues ());
555  ComplexMatrix Q (a_eig.eigenvectors ());
556 
557  for (octave_idx_type i = 0; i < nr; i++)
558  lambda(i) = std::pow (lambda(i), b);
559 
560  ComplexDiagMatrix D (lambda);
561 
562  retval = ComplexMatrix (Q * D * Q.inverse ());
563  }
564  else
565  error ("xpow: matrix diagonalization failed");
566  }
567 
568  return retval;
569 }
570 
571 // -*- 12d -*-
573 xpow (const ComplexDiagMatrix& a, const Complex& b)
574 {
575  octave_value retval;
576 
577  octave_idx_type nr = a.rows ();
578  octave_idx_type nc = a.cols ();
579 
580  if (nr == 0 || nc == 0 || nr != nc)
581  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
582  else
583  {
584  ComplexDiagMatrix r (nr, nc);
585  for (octave_idx_type i = 0; i < nc; i++)
586  r(i, i) = std::pow (a(i, i), b);
587  retval = r;
588  }
589 
590  return retval;
591 }
592 
593 // mixed
595 xpow (const ComplexDiagMatrix& a, double b)
596 {
597  return xpow (a, static_cast<Complex> (b));
598 }
599 
601 xpow (const DiagMatrix& a, const Complex& b)
602 {
603  return xpow (ComplexDiagMatrix (a), b);
604 }
605 
606 
607 // Safer pow functions that work elementwise for matrices.
608 //
609 // op2 \ op1: s m cs cm
610 // +-- +---+---+----+----+
611 // scalar | | * | 3 | * | 9 |
612 // +---+---+----+----+
613 // matrix | 1 | 4 | 7 | 10 |
614 // +---+---+----+----+
615 // complex_scalar | * | 5 | * | 11 |
616 // +---+---+----+----+
617 // complex_matrix | 2 | 6 | 8 | 12 |
618 // +---+---+----+----+
619 //
620 // * -> not needed.
621 
622 // FIXME: these functions need to be fixed so that things like
623 //
624 // a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
625 //
626 // and
627 //
628 // a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
629 //
630 // produce identical results. Also, it would be nice if -1^0.5
631 // produced a pure imaginary result instead of a complex number with a
632 // small real part. But perhaps that's really a problem with the math
633 // library...
634 
635 // -*- 1 -*-
637 elem_xpow (double a, const Matrix& b)
638 {
639  octave_value retval;
640 
641  octave_idx_type nr = b.rows ();
642  octave_idx_type nc = b.cols ();
643 
644  double d1, d2;
645 
646  if (a < 0.0 && ! b.all_integers (d1, d2))
647  {
648  Complex atmp (a);
649  ComplexMatrix result (nr, nc);
650 
651  for (octave_idx_type j = 0; j < nc; j++)
652  for (octave_idx_type i = 0; i < nr; i++)
653  {
654  octave_quit ();
655  result (i, j) = std::pow (atmp, b (i, j));
656  }
657 
658  retval = result;
659  }
660  else
661  {
662  Matrix result (nr, nc);
663 
664  for (octave_idx_type j = 0; j < nc; j++)
665  for (octave_idx_type i = 0; i < nr; i++)
666  {
667  octave_quit ();
668  result (i, j) = std::pow (a, b (i, j));
669  }
670 
671  retval = result;
672  }
673 
674  return retval;
675 }
676 
677 // -*- 2 -*-
679 elem_xpow (double a, const ComplexMatrix& b)
680 {
681  octave_idx_type nr = b.rows ();
682  octave_idx_type nc = b.cols ();
683 
684  ComplexMatrix result (nr, nc);
685  Complex atmp (a);
686 
687  for (octave_idx_type j = 0; j < nc; j++)
688  for (octave_idx_type i = 0; i < nr; i++)
689  {
690  octave_quit ();
691  result (i, j) = std::pow (atmp, b (i, j));
692  }
693 
694  return result;
695 }
696 
697 static inline bool
698 same_sign (double a, double b)
699 {
700  return (a >= 0 && b >= 0) || (a <= 0 && b <= 0);
701 }
702 
704 elem_xpow (double a, const Range& r)
705 {
706  octave_value retval;
707 
708  // Only optimize powers with ranges that are integer and monotonic in
709  // magnitude.
710  if (r.nelem () > 1 && r.all_elements_are_ints ()
711  && same_sign (r.base (), r.limit ()))
712  {
713  octave_idx_type n = r.nelem ();
714  Matrix result (1, n);
715  if (same_sign (r.base (), r.inc ()))
716  {
717  double base = std::pow (a, r.base ());
718  double inc = std::pow (a, r.inc ());
719  result(0) = base;
720  for (octave_idx_type i = 1; i < n; i++)
721  result(i) = (base *= inc);
722  }
723  else
724  {
725  // Don't use Range::limit () here.
726  double limit = std::pow (a, r.base () + (n-1) * r.inc ());
727  double inc = std::pow (a, -r.inc ());
728  result(n-1) = limit;
729  for (octave_idx_type i = n-2; i >= 0; i--)
730  result(i) = (limit *= inc);
731  }
732 
733  retval = result;
734  }
735  else
736  retval = elem_xpow (a, r.matrix_value ());
737 
738  return retval;
739 }
740 
741 // -*- 3 -*-
743 elem_xpow (const Matrix& a, double b)
744 {
745  octave_value retval;
746 
747  octave_idx_type nr = a.rows ();
748  octave_idx_type nc = a.cols ();
749 
750  if (! xisint (b) && a.any_element_is_negative ())
751  {
752  ComplexMatrix result (nr, nc);
753 
754  for (octave_idx_type j = 0; j < nc; j++)
755  for (octave_idx_type i = 0; i < nr; i++)
756  {
757  octave_quit ();
758 
759  Complex atmp (a (i, j));
760 
761  result (i, j) = std::pow (atmp, b);
762  }
763 
764  retval = result;
765  }
766  else
767  {
768  Matrix result (nr, nc);
769 
770  for (octave_idx_type j = 0; j < nc; j++)
771  for (octave_idx_type i = 0; i < nr; i++)
772  {
773  octave_quit ();
774  result (i, j) = std::pow (a (i, j), b);
775  }
776 
777  retval = result;
778  }
779 
780  return retval;
781 }
782 
783 // -*- 4 -*-
785 elem_xpow (const Matrix& a, const Matrix& b)
786 {
787  octave_value retval;
788 
789  octave_idx_type nr = a.rows ();
790  octave_idx_type nc = a.cols ();
791 
792  octave_idx_type b_nr = b.rows ();
793  octave_idx_type b_nc = b.cols ();
794 
795  if (nr != b_nr || nc != b_nc)
796  {
797  gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
798  return octave_value ();
799  }
800 
801  int convert_to_complex = 0;
802  for (octave_idx_type j = 0; j < nc; j++)
803  for (octave_idx_type i = 0; i < nr; i++)
804  {
805  octave_quit ();
806  double atmp = a (i, j);
807  double btmp = b (i, j);
808  if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
809  {
810  convert_to_complex = 1;
811  goto done;
812  }
813  }
814 
815 done:
816 
817  if (convert_to_complex)
818  {
819  ComplexMatrix complex_result (nr, nc);
820 
821  for (octave_idx_type j = 0; j < nc; j++)
822  for (octave_idx_type i = 0; i < nr; i++)
823  {
824  octave_quit ();
825  Complex atmp (a (i, j));
826  Complex btmp (b (i, j));
827  complex_result (i, j) = std::pow (atmp, btmp);
828  }
829 
830  retval = complex_result;
831  }
832  else
833  {
834  Matrix result (nr, nc);
835 
836  for (octave_idx_type j = 0; j < nc; j++)
837  for (octave_idx_type i = 0; i < nr; i++)
838  {
839  octave_quit ();
840  result (i, j) = std::pow (a (i, j), b (i, j));
841  }
842 
843  retval = result;
844  }
845 
846  return retval;
847 }
848 
849 // -*- 5 -*-
851 elem_xpow (const Matrix& a, const Complex& b)
852 {
853  octave_idx_type nr = a.rows ();
854  octave_idx_type nc = a.cols ();
855 
856  ComplexMatrix result (nr, nc);
857 
858  for (octave_idx_type j = 0; j < nc; j++)
859  for (octave_idx_type i = 0; i < nr; i++)
860  {
861  octave_quit ();
862  result (i, j) = std::pow (Complex (a (i, j)), b);
863  }
864 
865  return result;
866 }
867 
868 // -*- 6 -*-
870 elem_xpow (const Matrix& a, const ComplexMatrix& b)
871 {
872  octave_idx_type nr = a.rows ();
873  octave_idx_type nc = a.cols ();
874 
875  octave_idx_type b_nr = b.rows ();
876  octave_idx_type b_nc = b.cols ();
877 
878  if (nr != b_nr || nc != b_nc)
879  {
880  gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
881  return octave_value ();
882  }
883 
884  ComplexMatrix result (nr, nc);
885 
886  for (octave_idx_type j = 0; j < nc; j++)
887  for (octave_idx_type i = 0; i < nr; i++)
888  {
889  octave_quit ();
890  result (i, j) = std::pow (Complex (a (i, j)), b (i, j));
891  }
892 
893  return result;
894 }
895 
896 // -*- 7 -*-
898 elem_xpow (const Complex& a, const Matrix& b)
899 {
900  octave_idx_type nr = b.rows ();
901  octave_idx_type nc = b.cols ();
902 
903  ComplexMatrix result (nr, nc);
904 
905  for (octave_idx_type j = 0; j < nc; j++)
906  for (octave_idx_type i = 0; i < nr; i++)
907  {
908  octave_quit ();
909  double btmp = b (i, j);
910  if (xisint (btmp))
911  result (i, j) = std::pow (a, static_cast<int> (btmp));
912  else
913  result (i, j) = std::pow (a, btmp);
914  }
915 
916  return result;
917 }
918 
919 // -*- 8 -*-
921 elem_xpow (const Complex& a, const ComplexMatrix& b)
922 {
923  octave_idx_type nr = b.rows ();
924  octave_idx_type nc = b.cols ();
925 
926  ComplexMatrix result (nr, nc);
927 
928  for (octave_idx_type j = 0; j < nc; j++)
929  for (octave_idx_type i = 0; i < nr; i++)
930  {
931  octave_quit ();
932  result (i, j) = std::pow (a, b (i, j));
933  }
934 
935  return result;
936 }
937 
939 elem_xpow (const Complex& a, const Range& r)
940 {
941  octave_value retval;
942 
943  // Only optimize powers with ranges that are integer and monotonic in
944  // magnitude.
945  if (r.nelem () > 1 && r.all_elements_are_ints ()
946  && same_sign (r.base (), r.limit ()))
947  {
948  octave_idx_type n = r.nelem ();
949  ComplexMatrix result (1, n);
950 
951  if (same_sign (r.base (), r.inc ()))
952  {
953  Complex base = std::pow (a, r.base ());
954  Complex inc = std::pow (a, r.inc ());
955  result(0) = base;
956  for (octave_idx_type i = 1; i < n; i++)
957  result(i) = (base *= inc);
958  }
959  else
960  {
961  // Don't use Range::limit () here.
962  Complex limit = std::pow (a, r.base () + (n-1) * r.inc ());
963  Complex inc = std::pow (a, -r.inc ());
964  result(n-1) = limit;
965  for (octave_idx_type i = n-2; i >= 0; i--)
966  result(i) = (limit *= inc);
967  }
968 
969  retval = result;
970  }
971  else
972  retval = elem_xpow (a, r.matrix_value ());
973 
974 
975  return retval;
976 }
977 
978 // -*- 9 -*-
980 elem_xpow (const ComplexMatrix& a, double b)
981 {
982  octave_idx_type nr = a.rows ();
983  octave_idx_type nc = a.cols ();
984 
985  ComplexMatrix result (nr, nc);
986 
987  if (xisint (b))
988  {
989  for (octave_idx_type j = 0; j < nc; j++)
990  for (octave_idx_type i = 0; i < nr; i++)
991  {
992  octave_quit ();
993  result (i, j) = std::pow (a (i, j), static_cast<int> (b));
994  }
995  }
996  else
997  {
998  for (octave_idx_type j = 0; j < nc; j++)
999  for (octave_idx_type i = 0; i < nr; i++)
1000  {
1001  octave_quit ();
1002  result (i, j) = std::pow (a (i, j), b);
1003  }
1004  }
1005 
1006  return result;
1007 }
1008 
1009 // -*- 10 -*-
1011 elem_xpow (const ComplexMatrix& a, const Matrix& b)
1012 {
1013  octave_idx_type nr = a.rows ();
1014  octave_idx_type nc = a.cols ();
1015 
1016  octave_idx_type b_nr = b.rows ();
1017  octave_idx_type b_nc = b.cols ();
1018 
1019  if (nr != b_nr || nc != b_nc)
1020  {
1021  gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
1022  return octave_value ();
1023  }
1024 
1025  ComplexMatrix result (nr, nc);
1026 
1027  for (octave_idx_type j = 0; j < nc; j++)
1028  for (octave_idx_type i = 0; i < nr; i++)
1029  {
1030  octave_quit ();
1031  double btmp = b (i, j);
1032  if (xisint (btmp))
1033  result (i, j) = std::pow (a (i, j), static_cast<int> (btmp));
1034  else
1035  result (i, j) = std::pow (a (i, j), btmp);
1036  }
1037 
1038  return result;
1039 }
1040 
1041 // -*- 11 -*-
1043 elem_xpow (const ComplexMatrix& a, const Complex& b)
1044 {
1045  octave_idx_type nr = a.rows ();
1046  octave_idx_type nc = a.cols ();
1047 
1048  ComplexMatrix result (nr, nc);
1049 
1050  for (octave_idx_type j = 0; j < nc; j++)
1051  for (octave_idx_type i = 0; i < nr; i++)
1052  {
1053  octave_quit ();
1054  result (i, j) = std::pow (a (i, j), b);
1055  }
1056 
1057  return result;
1058 }
1059 
1060 // -*- 12 -*-
1063 {
1064  octave_idx_type nr = a.rows ();
1065  octave_idx_type nc = a.cols ();
1066 
1067  octave_idx_type b_nr = b.rows ();
1068  octave_idx_type b_nc = b.cols ();
1069 
1070  if (nr != b_nr || nc != b_nc)
1071  {
1072  gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
1073  return octave_value ();
1074  }
1075 
1076  ComplexMatrix result (nr, nc);
1077 
1078  for (octave_idx_type j = 0; j < nc; j++)
1079  for (octave_idx_type i = 0; i < nr; i++)
1080  {
1081  octave_quit ();
1082  result (i, j) = std::pow (a (i, j), b (i, j));
1083  }
1084 
1085  return result;
1086 }
1087 
1088 // Safer pow functions that work elementwise for N-d arrays.
1089 //
1090 // op2 \ op1: s nd cs cnd
1091 // +-- +---+---+----+----+
1092 // scalar | | * | 3 | * | 9 |
1093 // +---+---+----+----+
1094 // N_d | 1 | 4 | 7 | 10 |
1095 // +---+---+----+----+
1096 // complex_scalar | * | 5 | * | 11 |
1097 // +---+---+----+----+
1098 // complex_N_d | 2 | 6 | 8 | 12 |
1099 // +---+---+----+----+
1100 //
1101 // * -> not needed.
1102 
1103 // FIXME: these functions need to be fixed so that things like
1104 //
1105 // a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
1106 //
1107 // and
1108 //
1109 // a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
1110 //
1111 // produce identical results. Also, it would be nice if -1^0.5
1112 // produced a pure imaginary result instead of a complex number with a
1113 // small real part. But perhaps that's really a problem with the math
1114 // library...
1115 
1116 // -*- 1 -*-
1118 elem_xpow (double a, const NDArray& b)
1119 {
1120  octave_value retval;
1121 
1122  if (a < 0.0 && ! b.all_integers ())
1123  {
1124  Complex atmp (a);
1125  ComplexNDArray result (b.dims ());
1126  for (octave_idx_type i = 0; i < b.length (); i++)
1127  {
1128  octave_quit ();
1129  result(i) = std::pow (atmp, b(i));
1130  }
1131 
1132  retval = result;
1133  }
1134  else
1135  {
1136  NDArray result (b.dims ());
1137  for (octave_idx_type i = 0; i < b.length (); i++)
1138  {
1139  octave_quit ();
1140  result (i) = std::pow (a, b(i));
1141  }
1142 
1143  retval = result;
1144  }
1145 
1146  return retval;
1147 }
1148 
1149 // -*- 2 -*-
1151 elem_xpow (double a, const ComplexNDArray& b)
1152 {
1153  ComplexNDArray result (b.dims ());
1154 
1155  for (octave_idx_type i = 0; i < b.length (); i++)
1156  {
1157  octave_quit ();
1158  result(i) = std::pow (a, b(i));
1159  }
1160 
1161  return result;
1162 }
1163 
1164 // -*- 3 -*-
1166 elem_xpow (const NDArray& a, double b)
1167 {
1168  octave_value retval;
1169 
1170  if (! xisint (b))
1171  {
1172  if (a.any_element_is_negative ())
1173  {
1174  ComplexNDArray result (a.dims ());
1175 
1176  for (octave_idx_type i = 0; i < a.length (); i++)
1177  {
1178  octave_quit ();
1179 
1180  Complex atmp (a (i));
1181 
1182  result(i) = std::pow (atmp, b);
1183  }
1184 
1185  retval = result;
1186  }
1187  else
1188  {
1189  NDArray result (a.dims ());
1190  for (octave_idx_type i = 0; i < a.length (); i++)
1191  {
1192  octave_quit ();
1193  result(i) = std::pow (a(i), b);
1194  }
1195 
1196  retval = result;
1197  }
1198  }
1199  else
1200  {
1201  NoAlias<NDArray> result (a.dims ());
1202 
1203  int ib = static_cast<int> (b);
1204  if (ib == 2)
1205  {
1206  for (octave_idx_type i = 0; i < a.length (); i++)
1207  result(i) = a(i) * a(i);
1208  }
1209  else if (ib == 3)
1210  {
1211  for (octave_idx_type i = 0; i < a.length (); i++)
1212  result(i) = a(i) * a(i) * a(i);
1213  }
1214  else if (ib == -1)
1215  {
1216  for (octave_idx_type i = 0; i < a.length (); i++)
1217  result(i) = 1.0 / a(i);
1218  }
1219  else
1220  {
1221  for (octave_idx_type i = 0; i < a.length (); i++)
1222  {
1223  octave_quit ();
1224  result(i) = std::pow (a(i), ib);
1225  }
1226  }
1227 
1228  retval = result;
1229  }
1230 
1231  return retval;
1232 }
1233 
1234 // -*- 4 -*-
1236 elem_xpow (const NDArray& a, const NDArray& b)
1237 {
1238  octave_value retval;
1239 
1240  dim_vector a_dims = a.dims ();
1241  dim_vector b_dims = b.dims ();
1242 
1243  if (a_dims != b_dims)
1244  {
1245  if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
1246  {
1247  //Potentially complex results
1250  if (! xb.all_integers () && xa.any_element_is_negative ())
1251  return octave_value (bsxfun_pow (ComplexNDArray (xa), xb));
1252  else
1253  return octave_value (bsxfun_pow (xa, xb));
1254  }
1255  else
1256  {
1257  gripe_nonconformant ("operator .^", a_dims, b_dims);
1258  return octave_value ();
1259  }
1260  }
1261 
1262  int len = a.length ();
1263 
1264  bool convert_to_complex = false;
1265 
1266  for (octave_idx_type i = 0; i < len; i++)
1267  {
1268  octave_quit ();
1269  double atmp = a(i);
1270  double btmp = b(i);
1271  if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
1272  {
1273  convert_to_complex = true;
1274  goto done;
1275  }
1276  }
1277 
1278 done:
1279 
1280  if (convert_to_complex)
1281  {
1282  ComplexNDArray complex_result (a_dims);
1283 
1284  for (octave_idx_type i = 0; i < len; i++)
1285  {
1286  octave_quit ();
1287  Complex atmp (a(i));
1288  complex_result(i) = std::pow (atmp, b(i));
1289  }
1290 
1291  retval = complex_result;
1292  }
1293  else
1294  {
1295  NDArray result (a_dims);
1296 
1297  for (octave_idx_type i = 0; i < len; i++)
1298  {
1299  octave_quit ();
1300  result(i) = std::pow (a(i), b(i));
1301  }
1302 
1303  retval = result;
1304  }
1305 
1306  return retval;
1307 }
1308 
1309 // -*- 5 -*-
1311 elem_xpow (const NDArray& a, const Complex& b)
1312 {
1313  ComplexNDArray result (a.dims ());
1314 
1315  for (octave_idx_type i = 0; i < a.length (); i++)
1316  {
1317  octave_quit ();
1318  result(i) = std::pow (a(i), b);
1319  }
1320 
1321  return result;
1322 }
1323 
1324 // -*- 6 -*-
1326 elem_xpow (const NDArray& a, const ComplexNDArray& b)
1327 {
1328  dim_vector a_dims = a.dims ();
1329  dim_vector b_dims = b.dims ();
1330 
1331  if (a_dims != b_dims)
1332  {
1333  if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
1334  {
1335  return bsxfun_pow (a, b);
1336  }
1337  else
1338  {
1339  gripe_nonconformant ("operator .^", a_dims, b_dims);
1340  return octave_value ();
1341  }
1342  }
1343 
1344  ComplexNDArray result (a_dims);
1345 
1346  for (octave_idx_type i = 0; i < a.length (); i++)
1347  {
1348  octave_quit ();
1349  result(i) = std::pow (a(i), b(i));
1350  }
1351 
1352  return result;
1353 }
1354 
1355 // -*- 7 -*-
1357 elem_xpow (const Complex& a, const NDArray& b)
1358 {
1359  ComplexNDArray result (b.dims ());
1360 
1361  for (octave_idx_type i = 0; i < b.length (); i++)
1362  {
1363  octave_quit ();
1364  double btmp = b(i);
1365  if (xisint (btmp))
1366  result(i) = std::pow (a, static_cast<int> (btmp));
1367  else
1368  result(i) = std::pow (a, btmp);
1369  }
1370 
1371  return result;
1372 }
1373 
1374 // -*- 8 -*-
1376 elem_xpow (const Complex& a, const ComplexNDArray& b)
1377 {
1378  ComplexNDArray result (b.dims ());
1379 
1380  for (octave_idx_type i = 0; i < b.length (); i++)
1381  {
1382  octave_quit ();
1383  result(i) = std::pow (a, b(i));
1384  }
1385 
1386  return result;
1387 }
1388 
1389 // -*- 9 -*-
1391 elem_xpow (const ComplexNDArray& a, double b)
1392 {
1393  ComplexNDArray result (a.dims ());
1394 
1395  if (xisint (b))
1396  {
1397  if (b == -1)
1398  {
1399  for (octave_idx_type i = 0; i < a.length (); i++)
1400  result.xelem (i) = 1.0 / a(i);
1401  }
1402  else
1403  {
1404  for (octave_idx_type i = 0; i < a.length (); i++)
1405  {
1406  octave_quit ();
1407  result(i) = std::pow (a(i), static_cast<int> (b));
1408  }
1409  }
1410  }
1411  else
1412  {
1413  for (octave_idx_type i = 0; i < a.length (); i++)
1414  {
1415  octave_quit ();
1416  result(i) = std::pow (a(i), b);
1417  }
1418  }
1419 
1420  return result;
1421 }
1422 
1423 // -*- 10 -*-
1425 elem_xpow (const ComplexNDArray& a, const NDArray& b)
1426 {
1427  dim_vector a_dims = a.dims ();
1428  dim_vector b_dims = b.dims ();
1429 
1430  if (a_dims != b_dims)
1431  {
1432  if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
1433  {
1434  return bsxfun_pow (a, b);
1435  }
1436  else
1437  {
1438  gripe_nonconformant ("operator .^", a_dims, b_dims);
1439  return octave_value ();
1440  }
1441  }
1442 
1443  ComplexNDArray result (a_dims);
1444 
1445  for (octave_idx_type i = 0; i < a.length (); i++)
1446  {
1447  octave_quit ();
1448  double btmp = b(i);
1449  if (xisint (btmp))
1450  result(i) = std::pow (a(i), static_cast<int> (btmp));
1451  else
1452  result(i) = std::pow (a(i), btmp);
1453  }
1454 
1455  return result;
1456 }
1457 
1458 // -*- 11 -*-
1460 elem_xpow (const ComplexNDArray& a, const Complex& b)
1461 {
1462  ComplexNDArray result (a.dims ());
1463 
1464  for (octave_idx_type i = 0; i < a.length (); i++)
1465  {
1466  octave_quit ();
1467  result(i) = std::pow (a(i), b);
1468  }
1469 
1470  return result;
1471 }
1472 
1473 // -*- 12 -*-
1476 {
1477  dim_vector a_dims = a.dims ();
1478  dim_vector b_dims = b.dims ();
1479 
1480  if (a_dims != b_dims)
1481  {
1482  if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
1483  {
1484  return bsxfun_pow (a, b);
1485  }
1486  else
1487  {
1488  gripe_nonconformant ("operator .^", a_dims, b_dims);
1489  return octave_value ();
1490  }
1491  }
1492 
1493  ComplexNDArray result (a_dims);
1494 
1495  for (octave_idx_type i = 0; i < a.length (); i++)
1496  {
1497  octave_quit ();
1498  result(i) = std::pow (a(i), b(i));
1499  }
1500 
1501  return result;
1502 }
1503 
1504 static inline int
1505 xisint (float x)
1506 {
1507  return (D_NINT (x) == x
1508  && ((x >= 0 && x < std::numeric_limits<int>::max ())
1509  || (x <= 0 && x > std::numeric_limits<int>::min ())));
1510 }
1511 
1512 // Safer pow functions.
1513 //
1514 // op2 \ op1: s m cs cm
1515 // +-- +---+---+----+----+
1516 // scalar | | 1 | 5 | 7 | 11 |
1517 // +---+---+----+----+
1518 // matrix | 2 | * | 8 | * |
1519 // +---+---+----+----+
1520 // complex_scalar | 3 | 6 | 9 | 12 |
1521 // +---+---+----+----+
1522 // complex_matrix | 4 | * | 10 | * |
1523 // +---+---+----+----+
1524 
1525 // -*- 1 -*-
1527 xpow (float a, float b)
1528 {
1529  float retval;
1530 
1531  if (a < 0.0 && ! xisint (b))
1532  {
1533  FloatComplex atmp (a);
1534 
1535  return std::pow (atmp, b);
1536  }
1537  else
1538  retval = std::pow (a, b);
1539 
1540  return retval;
1541 }
1542 
1543 // -*- 2 -*-
1545 xpow (float a, const FloatMatrix& b)
1546 {
1547  octave_value retval;
1548 
1549  octave_idx_type nr = b.rows ();
1550  octave_idx_type nc = b.cols ();
1551 
1552  if (nr == 0 || nc == 0 || nr != nc)
1553  error ("for x^A, A must be a square matrix. Use .^ for elementwise power.");
1554  else
1555  {
1556  FloatEIG b_eig (b);
1557 
1558  if (! error_state)
1559  {
1560  FloatComplexColumnVector lambda (b_eig.eigenvalues ());
1561  FloatComplexMatrix Q (b_eig.eigenvectors ());
1562 
1563  for (octave_idx_type i = 0; i < nr; i++)
1564  {
1565  FloatComplex elt = lambda(i);
1566  if (std::imag (elt) == 0.0)
1567  lambda(i) = std::pow (a, std::real (elt));
1568  else
1569  lambda(i) = std::pow (a, elt);
1570  }
1571  FloatComplexDiagMatrix D (lambda);
1572 
1573  FloatComplexMatrix C = Q * D * Q.inverse ();
1574 
1575  if (a > 0)
1576  retval = real (C);
1577  else
1578  retval = C;
1579  }
1580  else
1581  error ("xpow: matrix diagonalization failed");
1582  }
1583 
1584  return retval;
1585 }
1586 
1587 // -*- 3 -*-
1589 xpow (float a, const FloatComplex& b)
1590 {
1591  FloatComplex result = std::pow (a, b);
1592  return result;
1593 }
1594 
1595 // -*- 4 -*-
1597 xpow (float a, const FloatComplexMatrix& b)
1598 {
1599  octave_value retval;
1600 
1601  octave_idx_type nr = b.rows ();
1602  octave_idx_type nc = b.cols ();
1603 
1604  if (nr == 0 || nc == 0 || nr != nc)
1605  error ("for x^A, A must be a square matrix. Use .^ for elementwise power.");
1606  else
1607  {
1608  FloatEIG b_eig (b);
1609 
1610  if (! error_state)
1611  {
1612  FloatComplexColumnVector lambda (b_eig.eigenvalues ());
1613  FloatComplexMatrix Q (b_eig.eigenvectors ());
1614 
1615  for (octave_idx_type i = 0; i < nr; i++)
1616  {
1617  FloatComplex elt = lambda(i);
1618  if (std::imag (elt) == 0.0)
1619  lambda(i) = std::pow (a, std::real (elt));
1620  else
1621  lambda(i) = std::pow (a, elt);
1622  }
1623  FloatComplexDiagMatrix D (lambda);
1624 
1625  retval = FloatComplexMatrix (Q * D * Q.inverse ());
1626  }
1627  else
1628  error ("xpow: matrix diagonalization failed");
1629  }
1630 
1631  return retval;
1632 }
1633 
1634 // -*- 5 -*-
1636 xpow (const FloatMatrix& a, float b)
1637 {
1638  octave_value retval;
1639 
1640  octave_idx_type nr = a.rows ();
1641  octave_idx_type nc = a.cols ();
1642 
1643  if (nr == 0 || nc == 0 || nr != nc)
1644  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
1645  else
1646  {
1647  if (static_cast<int> (b) == b)
1648  {
1649  int btmp = static_cast<int> (b);
1650  if (btmp == 0)
1651  {
1652  retval = FloatDiagMatrix (nr, nr, 1.0);
1653  }
1654  else
1655  {
1656  // Too much copying?
1657  // FIXME: we shouldn't do this if the exponent is large...
1658 
1659  FloatMatrix atmp;
1660  if (btmp < 0)
1661  {
1662  btmp = -btmp;
1663 
1664  octave_idx_type info;
1665  float rcond = 0.0;
1666  MatrixType mattype (a);
1667 
1668  atmp = a.inverse (mattype, info, rcond, 1);
1669 
1670  if (info == -1)
1671  warning ("inverse: matrix singular to machine\
1672  precision, rcond = %g", rcond);
1673  }
1674  else
1675  atmp = a;
1676 
1677  FloatMatrix result (atmp);
1678 
1679  btmp--;
1680 
1681  while (btmp > 0)
1682  {
1683  if (btmp & 1)
1684  result = result * atmp;
1685 
1686  btmp >>= 1;
1687 
1688  if (btmp > 0)
1689  atmp = atmp * atmp;
1690  }
1691 
1692  retval = result;
1693  }
1694  }
1695  else
1696  {
1697  FloatEIG a_eig (a);
1698 
1699  if (! error_state)
1700  {
1701  FloatComplexColumnVector lambda (a_eig.eigenvalues ());
1702  FloatComplexMatrix Q (a_eig.eigenvectors ());
1703 
1704  for (octave_idx_type i = 0; i < nr; i++)
1705  lambda(i) = std::pow (lambda(i), b);
1706 
1707  FloatComplexDiagMatrix D (lambda);
1708 
1709  retval = FloatComplexMatrix (Q * D * Q.inverse ());
1710  }
1711  else
1712  error ("xpow: matrix diagonalization failed");
1713  }
1714  }
1715 
1716  return retval;
1717 }
1718 
1719 // -*- 5d -*-
1721 xpow (const FloatDiagMatrix& a, float b)
1722 {
1723  octave_value retval;
1724 
1725  octave_idx_type nr = a.rows ();
1726  octave_idx_type nc = a.cols ();
1727 
1728  if (nr == 0 || nc == 0 || nr != nc)
1729  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
1730  else
1731  {
1732  if (static_cast<int> (b) == b)
1733  {
1734  FloatDiagMatrix r (nr, nc);
1735  for (octave_idx_type i = 0; i < nc; i++)
1736  r.dgelem (i) = std::pow (a.dgelem (i), b);
1737  retval = r;
1738  }
1739  else
1740  {
1741  FloatComplexDiagMatrix r (nr, nc);
1742  for (octave_idx_type i = 0; i < nc; i++)
1743  r.dgelem (i) = std::pow (static_cast<FloatComplex> (a.dgelem (i)),
1744  b);
1745  retval = r;
1746  }
1747  }
1748 
1749  return retval;
1750 }
1751 
1752 // -*- 6 -*-
1754 xpow (const FloatMatrix& a, const FloatComplex& b)
1755 {
1756  octave_value retval;
1757 
1758  octave_idx_type nr = a.rows ();
1759  octave_idx_type nc = a.cols ();
1760 
1761  if (nr == 0 || nc == 0 || nr != nc)
1762  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
1763  else
1764  {
1765  FloatEIG a_eig (a);
1766 
1767  if (! error_state)
1768  {
1769  FloatComplexColumnVector lambda (a_eig.eigenvalues ());
1770  FloatComplexMatrix Q (a_eig.eigenvectors ());
1771 
1772  for (octave_idx_type i = 0; i < nr; i++)
1773  lambda(i) = std::pow (lambda(i), b);
1774 
1775  FloatComplexDiagMatrix D (lambda);
1776 
1777  retval = FloatComplexMatrix (Q * D * Q.inverse ());
1778  }
1779  else
1780  error ("xpow: matrix diagonalization failed");
1781  }
1782 
1783  return retval;
1784 }
1785 
1786 // -*- 7 -*-
1788 xpow (const FloatComplex& a, float b)
1789 {
1790  FloatComplex result;
1791 
1792  if (xisint (b))
1793  result = std::pow (a, static_cast<int> (b));
1794  else
1795  result = std::pow (a, b);
1796 
1797  return result;
1798 }
1799 
1800 // -*- 8 -*-
1802 xpow (const FloatComplex& a, const FloatMatrix& b)
1803 {
1804  octave_value retval;
1805 
1806  octave_idx_type nr = b.rows ();
1807  octave_idx_type nc = b.cols ();
1808 
1809  if (nr == 0 || nc == 0 || nr != nc)
1810  error ("for x^A, A must be a square matrix. Use .^ for elementwise power.");
1811  else
1812  {
1813  FloatEIG b_eig (b);
1814 
1815  if (! error_state)
1816  {
1817  FloatComplexColumnVector lambda (b_eig.eigenvalues ());
1818  FloatComplexMatrix Q (b_eig.eigenvectors ());
1819 
1820  for (octave_idx_type i = 0; i < nr; i++)
1821  {
1822  FloatComplex elt = lambda(i);
1823  if (std::imag (elt) == 0.0)
1824  lambda(i) = std::pow (a, std::real (elt));
1825  else
1826  lambda(i) = std::pow (a, elt);
1827  }
1828  FloatComplexDiagMatrix D (lambda);
1829 
1830  retval = FloatComplexMatrix (Q * D * Q.inverse ());
1831  }
1832  else
1833  error ("xpow: matrix diagonalization failed");
1834  }
1835 
1836  return retval;
1837 }
1838 
1839 // -*- 9 -*-
1841 xpow (const FloatComplex& a, const FloatComplex& b)
1842 {
1843  FloatComplex result;
1844  result = std::pow (a, b);
1845  return result;
1846 }
1847 
1848 // -*- 10 -*-
1851 {
1852  octave_value retval;
1853 
1854  octave_idx_type nr = b.rows ();
1855  octave_idx_type nc = b.cols ();
1856 
1857  if (nr == 0 || nc == 0 || nr != nc)
1858  error ("for x^A, A must be a square matrix. Use .^ for elementwise power.");
1859  else
1860  {
1861  FloatEIG b_eig (b);
1862 
1863  if (! error_state)
1864  {
1865  FloatComplexColumnVector lambda (b_eig.eigenvalues ());
1866  FloatComplexMatrix Q (b_eig.eigenvectors ());
1867 
1868  for (octave_idx_type i = 0; i < nr; i++)
1869  {
1870  FloatComplex elt = lambda(i);
1871  if (std::imag (elt) == 0.0)
1872  lambda(i) = std::pow (a, std::real (elt));
1873  else
1874  lambda(i) = std::pow (a, elt);
1875  }
1876  FloatComplexDiagMatrix D (lambda);
1877 
1878  retval = FloatComplexMatrix (Q * D * Q.inverse ());
1879  }
1880  else
1881  error ("xpow: matrix diagonalization failed");
1882  }
1883 
1884  return retval;
1885 }
1886 
1887 // -*- 11 -*-
1889 xpow (const FloatComplexMatrix& a, float b)
1890 {
1891  octave_value retval;
1892 
1893  octave_idx_type nr = a.rows ();
1894  octave_idx_type nc = a.cols ();
1895 
1896  if (nr == 0 || nc == 0 || nr != nc)
1897  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
1898  else
1899  {
1900  if (static_cast<int> (b) == b)
1901  {
1902  int btmp = static_cast<int> (b);
1903  if (btmp == 0)
1904  {
1905  retval = FloatDiagMatrix (nr, nr, 1.0);
1906  }
1907  else
1908  {
1909  // Too much copying?
1910  // FIXME: we shouldn't do this if the exponent is large...
1911 
1912  FloatComplexMatrix atmp;
1913  if (btmp < 0)
1914  {
1915  btmp = -btmp;
1916 
1917  octave_idx_type info;
1918  float rcond = 0.0;
1919  MatrixType mattype (a);
1920 
1921  atmp = a.inverse (mattype, info, rcond, 1);
1922 
1923  if (info == -1)
1924  warning ("inverse: matrix singular to machine\
1925  precision, rcond = %g", rcond);
1926  }
1927  else
1928  atmp = a;
1929 
1930  FloatComplexMatrix result (atmp);
1931 
1932  btmp--;
1933 
1934  while (btmp > 0)
1935  {
1936  if (btmp & 1)
1937  result = result * atmp;
1938 
1939  btmp >>= 1;
1940 
1941  if (btmp > 0)
1942  atmp = atmp * atmp;
1943  }
1944 
1945  retval = result;
1946  }
1947  }
1948  else
1949  {
1950  FloatEIG a_eig (a);
1951 
1952  if (! error_state)
1953  {
1954  FloatComplexColumnVector lambda (a_eig.eigenvalues ());
1955  FloatComplexMatrix Q (a_eig.eigenvectors ());
1956 
1957  for (octave_idx_type i = 0; i < nr; i++)
1958  lambda(i) = std::pow (lambda(i), b);
1959 
1960  FloatComplexDiagMatrix D (lambda);
1961 
1962  retval = FloatComplexMatrix (Q * D * Q.inverse ());
1963  }
1964  else
1965  error ("xpow: matrix diagonalization failed");
1966  }
1967  }
1968 
1969  return retval;
1970 }
1971 
1972 // -*- 12 -*-
1975 {
1976  octave_value retval;
1977 
1978  octave_idx_type nr = a.rows ();
1979  octave_idx_type nc = a.cols ();
1980 
1981  if (nr == 0 || nc == 0 || nr != nc)
1982  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
1983  else
1984  {
1985  FloatEIG a_eig (a);
1986 
1987  if (! error_state)
1988  {
1989  FloatComplexColumnVector lambda (a_eig.eigenvalues ());
1990  FloatComplexMatrix Q (a_eig.eigenvectors ());
1991 
1992  for (octave_idx_type i = 0; i < nr; i++)
1993  lambda(i) = std::pow (lambda(i), b);
1994 
1995  FloatComplexDiagMatrix D (lambda);
1996 
1997  retval = FloatComplexMatrix (Q * D * Q.inverse ());
1998  }
1999  else
2000  error ("xpow: matrix diagonalization failed");
2001  }
2002 
2003  return retval;
2004 }
2005 
2006 // -*- 12d -*-
2009 {
2010  octave_value retval;
2011 
2012  octave_idx_type nr = a.rows ();
2013  octave_idx_type nc = a.cols ();
2014 
2015  if (nr == 0 || nc == 0 || nr != nc)
2016  error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
2017  else
2018  {
2019  FloatComplexDiagMatrix r (nr, nc);
2020  for (octave_idx_type i = 0; i < nc; i++)
2021  r(i, i) = std::pow (a(i, i), b);
2022  retval = r;
2023  }
2024 
2025  return retval;
2026 }
2027 
2028 // mixed
2030 xpow (const FloatComplexDiagMatrix& a, float b)
2031 {
2032  return xpow (a, static_cast<FloatComplex> (b));
2033 }
2034 
2036 xpow (const FloatDiagMatrix& a, const FloatComplex& b)
2037 {
2038  return xpow (FloatComplexDiagMatrix (a), b);
2039 }
2040 
2041 // Safer pow functions that work elementwise for matrices.
2042 //
2043 // op2 \ op1: s m cs cm
2044 // +-- +---+---+----+----+
2045 // scalar | | * | 3 | * | 9 |
2046 // +---+---+----+----+
2047 // matrix | 1 | 4 | 7 | 10 |
2048 // +---+---+----+----+
2049 // complex_scalar | * | 5 | * | 11 |
2050 // +---+---+----+----+
2051 // complex_matrix | 2 | 6 | 8 | 12 |
2052 // +---+---+----+----+
2053 //
2054 // * -> not needed.
2055 
2056 // FIXME: these functions need to be fixed so that things like
2057 //
2058 // a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
2059 //
2060 // and
2061 //
2062 // a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
2063 //
2064 // produce identical results. Also, it would be nice if -1^0.5
2065 // produced a pure imaginary result instead of a complex number with a
2066 // small real part. But perhaps that's really a problem with the math
2067 // library...
2068 
2069 // -*- 1 -*-
2071 elem_xpow (float a, const FloatMatrix& b)
2072 {
2073  octave_value retval;
2074 
2075  octave_idx_type nr = b.rows ();
2076  octave_idx_type nc = b.cols ();
2077 
2078  float d1, d2;
2079 
2080  if (a < 0.0 && ! b.all_integers (d1, d2))
2081  {
2082  FloatComplex atmp (a);
2083  FloatComplexMatrix result (nr, nc);
2084 
2085  for (octave_idx_type j = 0; j < nc; j++)
2086  for (octave_idx_type i = 0; i < nr; i++)
2087  {
2088  octave_quit ();
2089  result (i, j) = std::pow (atmp, b (i, j));
2090  }
2091 
2092  retval = result;
2093  }
2094  else
2095  {
2096  FloatMatrix result (nr, nc);
2097 
2098  for (octave_idx_type j = 0; j < nc; j++)
2099  for (octave_idx_type i = 0; i < nr; i++)
2100  {
2101  octave_quit ();
2102  result (i, j) = std::pow (a, b (i, j));
2103  }
2104 
2105  retval = result;
2106  }
2107 
2108  return retval;
2109 }
2110 
2111 // -*- 2 -*-
2113 elem_xpow (float a, const FloatComplexMatrix& b)
2114 {
2115  octave_idx_type nr = b.rows ();
2116  octave_idx_type nc = b.cols ();
2117 
2118  FloatComplexMatrix result (nr, nc);
2119  FloatComplex atmp (a);
2120 
2121  for (octave_idx_type j = 0; j < nc; j++)
2122  for (octave_idx_type i = 0; i < nr; i++)
2123  {
2124  octave_quit ();
2125  result (i, j) = std::pow (atmp, b (i, j));
2126  }
2127 
2128  return result;
2129 }
2130 
2131 // -*- 3 -*-
2133 elem_xpow (const FloatMatrix& a, float b)
2134 {
2135  octave_value retval;
2136 
2137  octave_idx_type nr = a.rows ();
2138  octave_idx_type nc = a.cols ();
2139 
2140  if (! xisint (b) && a.any_element_is_negative ())
2141  {
2142  FloatComplexMatrix result (nr, nc);
2143 
2144  for (octave_idx_type j = 0; j < nc; j++)
2145  for (octave_idx_type i = 0; i < nr; i++)
2146  {
2147  octave_quit ();
2148 
2149  FloatComplex atmp (a (i, j));
2150 
2151  result (i, j) = std::pow (atmp, b);
2152  }
2153 
2154  retval = result;
2155  }
2156  else
2157  {
2158  FloatMatrix result (nr, nc);
2159 
2160  for (octave_idx_type j = 0; j < nc; j++)
2161  for (octave_idx_type i = 0; i < nr; i++)
2162  {
2163  octave_quit ();
2164  result (i, j) = std::pow (a (i, j), b);
2165  }
2166 
2167  retval = result;
2168  }
2169 
2170  return retval;
2171 }
2172 
2173 // -*- 4 -*-
2175 elem_xpow (const FloatMatrix& a, const FloatMatrix& b)
2176 {
2177  octave_value retval;
2178 
2179  octave_idx_type nr = a.rows ();
2180  octave_idx_type nc = a.cols ();
2181 
2182  octave_idx_type b_nr = b.rows ();
2183  octave_idx_type b_nc = b.cols ();
2184 
2185  if (nr != b_nr || nc != b_nc)
2186  {
2187  gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
2188  return octave_value ();
2189  }
2190 
2191  int convert_to_complex = 0;
2192  for (octave_idx_type j = 0; j < nc; j++)
2193  for (octave_idx_type i = 0; i < nr; i++)
2194  {
2195  octave_quit ();
2196  float atmp = a (i, j);
2197  float btmp = b (i, j);
2198  if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
2199  {
2200  convert_to_complex = 1;
2201  goto done;
2202  }
2203  }
2204 
2205 done:
2206 
2207  if (convert_to_complex)
2208  {
2209  FloatComplexMatrix complex_result (nr, nc);
2210 
2211  for (octave_idx_type j = 0; j < nc; j++)
2212  for (octave_idx_type i = 0; i < nr; i++)
2213  {
2214  octave_quit ();
2215  FloatComplex atmp (a (i, j));
2216  FloatComplex btmp (b (i, j));
2217  complex_result (i, j) = std::pow (atmp, btmp);
2218  }
2219 
2220  retval = complex_result;
2221  }
2222  else
2223  {
2224  FloatMatrix result (nr, nc);
2225 
2226  for (octave_idx_type j = 0; j < nc; j++)
2227  for (octave_idx_type i = 0; i < nr; i++)
2228  {
2229  octave_quit ();
2230  result (i, j) = std::pow (a (i, j), b (i, j));
2231  }
2232 
2233  retval = result;
2234  }
2235 
2236  return retval;
2237 }
2238 
2239 // -*- 5 -*-
2241 elem_xpow (const FloatMatrix& a, const FloatComplex& b)
2242 {
2243  octave_idx_type nr = a.rows ();
2244  octave_idx_type nc = a.cols ();
2245 
2246  FloatComplexMatrix result (nr, nc);
2247 
2248  for (octave_idx_type j = 0; j < nc; j++)
2249  for (octave_idx_type i = 0; i < nr; i++)
2250  {
2251  octave_quit ();
2252  result (i, j) = std::pow (FloatComplex (a (i, j)), b);
2253  }
2254 
2255  return result;
2256 }
2257 
2258 // -*- 6 -*-
2261 {
2262  octave_idx_type nr = a.rows ();
2263  octave_idx_type nc = a.cols ();
2264 
2265  octave_idx_type b_nr = b.rows ();
2266  octave_idx_type b_nc = b.cols ();
2267 
2268  if (nr != b_nr || nc != b_nc)
2269  {
2270  gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
2271  return octave_value ();
2272  }
2273 
2274  FloatComplexMatrix result (nr, nc);
2275 
2276  for (octave_idx_type j = 0; j < nc; j++)
2277  for (octave_idx_type i = 0; i < nr; i++)
2278  {
2279  octave_quit ();
2280  result (i, j) = std::pow (FloatComplex (a (i, j)), b (i, j));
2281  }
2282 
2283  return result;
2284 }
2285 
2286 // -*- 7 -*-
2288 elem_xpow (const FloatComplex& a, const FloatMatrix& b)
2289 {
2290  octave_idx_type nr = b.rows ();
2291  octave_idx_type nc = b.cols ();
2292 
2293  FloatComplexMatrix result (nr, nc);
2294 
2295  for (octave_idx_type j = 0; j < nc; j++)
2296  for (octave_idx_type i = 0; i < nr; i++)
2297  {
2298  octave_quit ();
2299  float btmp = b (i, j);
2300  if (xisint (btmp))
2301  result (i, j) = std::pow (a, static_cast<int> (btmp));
2302  else
2303  result (i, j) = std::pow (a, btmp);
2304  }
2305 
2306  return result;
2307 }
2308 
2309 // -*- 8 -*-
2312 {
2313  octave_idx_type nr = b.rows ();
2314  octave_idx_type nc = b.cols ();
2315 
2316  FloatComplexMatrix result (nr, nc);
2317 
2318  for (octave_idx_type j = 0; j < nc; j++)
2319  for (octave_idx_type i = 0; i < nr; i++)
2320  {
2321  octave_quit ();
2322  result (i, j) = std::pow (a, b (i, j));
2323  }
2324 
2325  return result;
2326 }
2327 
2328 // -*- 9 -*-
2330 elem_xpow (const FloatComplexMatrix& a, float b)
2331 {
2332  octave_idx_type nr = a.rows ();
2333  octave_idx_type nc = a.cols ();
2334 
2335  FloatComplexMatrix result (nr, nc);
2336 
2337  if (xisint (b))
2338  {
2339  for (octave_idx_type j = 0; j < nc; j++)
2340  for (octave_idx_type i = 0; i < nr; i++)
2341  {
2342  octave_quit ();
2343  result (i, j) = std::pow (a (i, j), static_cast<int> (b));
2344  }
2345  }
2346  else
2347  {
2348  for (octave_idx_type j = 0; j < nc; j++)
2349  for (octave_idx_type i = 0; i < nr; i++)
2350  {
2351  octave_quit ();
2352  result (i, j) = std::pow (a (i, j), b);
2353  }
2354  }
2355 
2356  return result;
2357 }
2358 
2359 // -*- 10 -*-
2362 {
2363  octave_idx_type nr = a.rows ();
2364  octave_idx_type nc = a.cols ();
2365 
2366  octave_idx_type b_nr = b.rows ();
2367  octave_idx_type b_nc = b.cols ();
2368 
2369  if (nr != b_nr || nc != b_nc)
2370  {
2371  gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
2372  return octave_value ();
2373  }
2374 
2375  FloatComplexMatrix result (nr, nc);
2376 
2377  for (octave_idx_type j = 0; j < nc; j++)
2378  for (octave_idx_type i = 0; i < nr; i++)
2379  {
2380  octave_quit ();
2381  float btmp = b (i, j);
2382  if (xisint (btmp))
2383  result (i, j) = std::pow (a (i, j), static_cast<int> (btmp));
2384  else
2385  result (i, j) = std::pow (a (i, j), btmp);
2386  }
2387 
2388  return result;
2389 }
2390 
2391 // -*- 11 -*-
2394 {
2395  octave_idx_type nr = a.rows ();
2396  octave_idx_type nc = a.cols ();
2397 
2398  FloatComplexMatrix result (nr, nc);
2399 
2400  for (octave_idx_type j = 0; j < nc; j++)
2401  for (octave_idx_type i = 0; i < nr; i++)
2402  {
2403  octave_quit ();
2404  result (i, j) = std::pow (a (i, j), b);
2405  }
2406 
2407  return result;
2408 }
2409 
2410 // -*- 12 -*-
2413 {
2414  octave_idx_type nr = a.rows ();
2415  octave_idx_type nc = a.cols ();
2416 
2417  octave_idx_type b_nr = b.rows ();
2418  octave_idx_type b_nc = b.cols ();
2419 
2420  if (nr != b_nr || nc != b_nc)
2421  {
2422  gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
2423  return octave_value ();
2424  }
2425 
2426  FloatComplexMatrix result (nr, nc);
2427 
2428  for (octave_idx_type j = 0; j < nc; j++)
2429  for (octave_idx_type i = 0; i < nr; i++)
2430  {
2431  octave_quit ();
2432  result (i, j) = std::pow (a (i, j), b (i, j));
2433  }
2434 
2435  return result;
2436 }
2437 
2438 // Safer pow functions that work elementwise for N-d arrays.
2439 //
2440 // op2 \ op1: s nd cs cnd
2441 // +-- +---+---+----+----+
2442 // scalar | | * | 3 | * | 9 |
2443 // +---+---+----+----+
2444 // N_d | 1 | 4 | 7 | 10 |
2445 // +---+---+----+----+
2446 // complex_scalar | * | 5 | * | 11 |
2447 // +---+---+----+----+
2448 // complex_N_d | 2 | 6 | 8 | 12 |
2449 // +---+---+----+----+
2450 //
2451 // * -> not needed.
2452 
2453 // FIXME: these functions need to be fixed so that things like
2454 //
2455 // a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
2456 //
2457 // and
2458 //
2459 // a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
2460 //
2461 // produce identical results. Also, it would be nice if -1^0.5
2462 // produced a pure imaginary result instead of a complex number with a
2463 // small real part. But perhaps that's really a problem with the math
2464 // library...
2465 
2466 // -*- 1 -*-
2468 elem_xpow (float a, const FloatNDArray& b)
2469 {
2470  octave_value retval;
2471 
2472  if (a < 0.0 && ! b.all_integers ())
2473  {
2474  FloatComplex atmp (a);
2475  FloatComplexNDArray result (b.dims ());
2476  for (octave_idx_type i = 0; i < b.length (); i++)
2477  {
2478  octave_quit ();
2479  result(i) = std::pow (atmp, b(i));
2480  }
2481 
2482  retval = result;
2483  }
2484  else
2485  {
2486  FloatNDArray result (b.dims ());
2487  for (octave_idx_type i = 0; i < b.length (); i++)
2488  {
2489  octave_quit ();
2490  result (i) = std::pow (a, b(i));
2491  }
2492 
2493  retval = result;
2494  }
2495 
2496  return retval;
2497 }
2498 
2499 // -*- 2 -*-
2501 elem_xpow (float a, const FloatComplexNDArray& b)
2502 {
2503  FloatComplexNDArray result (b.dims ());
2504 
2505  for (octave_idx_type i = 0; i < b.length (); i++)
2506  {
2507  octave_quit ();
2508  result(i) = std::pow (a, b(i));
2509  }
2510 
2511  return result;
2512 }
2513 
2514 // -*- 3 -*-
2516 elem_xpow (const FloatNDArray& a, float b)
2517 {
2518  octave_value retval;
2519 
2520  if (! xisint (b))
2521  {
2522  if (a.any_element_is_negative ())
2523  {
2524  FloatComplexNDArray result (a.dims ());
2525 
2526  for (octave_idx_type i = 0; i < a.length (); i++)
2527  {
2528  octave_quit ();
2529 
2530  FloatComplex atmp (a (i));
2531 
2532  result(i) = std::pow (atmp, b);
2533  }
2534 
2535  retval = result;
2536  }
2537  else
2538  {
2539  FloatNDArray result (a.dims ());
2540  for (octave_idx_type i = 0; i < a.length (); i++)
2541  {
2542  octave_quit ();
2543  result(i) = std::pow (a(i), b);
2544  }
2545 
2546  retval = result;
2547  }
2548  }
2549  else
2550  {
2551  NoAlias<FloatNDArray> result (a.dims ());
2552 
2553  int ib = static_cast<int> (b);
2554  if (ib == 2)
2555  {
2556  for (octave_idx_type i = 0; i < a.length (); i++)
2557  result(i) = a(i) * a(i);
2558  }
2559  else if (ib == 3)
2560  {
2561  for (octave_idx_type i = 0; i < a.length (); i++)
2562  result(i) = a(i) * a(i) * a(i);
2563  }
2564  else if (ib == -1)
2565  {
2566  for (octave_idx_type i = 0; i < a.length (); i++)
2567  result(i) = 1.0f / a(i);
2568  }
2569  else
2570  {
2571  for (octave_idx_type i = 0; i < a.length (); i++)
2572  {
2573  octave_quit ();
2574  result(i) = std::pow (a(i), ib);
2575  }
2576  }
2577 
2578  retval = result;
2579  }
2580 
2581  return retval;
2582 }
2583 
2584 // -*- 4 -*-
2587 {
2588  octave_value retval;
2589 
2590  dim_vector a_dims = a.dims ();
2591  dim_vector b_dims = b.dims ();
2592 
2593  if (a_dims != b_dims)
2594  {
2595  if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
2596  {
2597  //Potentially complex results
2600  if (! xb.all_integers () && xa.any_element_is_negative ())
2601  return octave_value (bsxfun_pow (FloatComplexNDArray (xa), xb));
2602  else
2603  return octave_value (bsxfun_pow (xa, xb));
2604  }
2605  else
2606  {
2607  gripe_nonconformant ("operator .^", a_dims, b_dims);
2608  return octave_value ();
2609  }
2610  }
2611 
2612  int len = a.length ();
2613 
2614  bool convert_to_complex = false;
2615 
2616  for (octave_idx_type i = 0; i < len; i++)
2617  {
2618  octave_quit ();
2619  float atmp = a(i);
2620  float btmp = b(i);
2621  if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
2622  {
2623  convert_to_complex = true;
2624  goto done;
2625  }
2626  }
2627 
2628 done:
2629 
2630  if (convert_to_complex)
2631  {
2632  FloatComplexNDArray complex_result (a_dims);
2633 
2634  for (octave_idx_type i = 0; i < len; i++)
2635  {
2636  octave_quit ();
2637  FloatComplex atmp (a(i));
2638  complex_result(i) = std::pow (atmp, b(i));
2639  }
2640 
2641  retval = complex_result;
2642  }
2643  else
2644  {
2645  FloatNDArray result (a_dims);
2646 
2647  for (octave_idx_type i = 0; i < len; i++)
2648  {
2649  octave_quit ();
2650  result(i) = std::pow (a(i), b(i));
2651  }
2652 
2653  retval = result;
2654  }
2655 
2656  return retval;
2657 }
2658 
2659 // -*- 5 -*-
2662 {
2663  FloatComplexNDArray result (a.dims ());
2664 
2665  for (octave_idx_type i = 0; i < a.length (); i++)
2666  {
2667  octave_quit ();
2668  result(i) = std::pow (a(i), b);
2669  }
2670 
2671  return result;
2672 }
2673 
2674 // -*- 6 -*-
2677 {
2678  dim_vector a_dims = a.dims ();
2679  dim_vector b_dims = b.dims ();
2680 
2681  if (a_dims != b_dims)
2682  {
2683  if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
2684  {
2685  return bsxfun_pow (a, b);
2686  }
2687  else
2688  {
2689  gripe_nonconformant ("operator .^", a_dims, b_dims);
2690  return octave_value ();
2691  }
2692  }
2693 
2694  FloatComplexNDArray result (a_dims);
2695 
2696  for (octave_idx_type i = 0; i < a.length (); i++)
2697  {
2698  octave_quit ();
2699  result(i) = std::pow (a(i), b(i));
2700  }
2701 
2702  return result;
2703 }
2704 
2705 // -*- 7 -*-
2708 {
2709  FloatComplexNDArray result (b.dims ());
2710 
2711  for (octave_idx_type i = 0; i < b.length (); i++)
2712  {
2713  octave_quit ();
2714  float btmp = b(i);
2715  if (xisint (btmp))
2716  result(i) = std::pow (a, static_cast<int> (btmp));
2717  else
2718  result(i) = std::pow (a, btmp);
2719  }
2720 
2721  return result;
2722 }
2723 
2724 // -*- 8 -*-
2727 {
2728  FloatComplexNDArray result (b.dims ());
2729 
2730  for (octave_idx_type i = 0; i < b.length (); i++)
2731  {
2732  octave_quit ();
2733  result(i) = std::pow (a, b(i));
2734  }
2735 
2736  return result;
2737 }
2738 
2739 // -*- 9 -*-
2741 elem_xpow (const FloatComplexNDArray& a, float b)
2742 {
2743  FloatComplexNDArray result (a.dims ());
2744 
2745  if (xisint (b))
2746  {
2747  if (b == -1)
2748  {
2749  for (octave_idx_type i = 0; i < a.length (); i++)
2750  result.xelem (i) = 1.0f / a(i);
2751  }
2752  else
2753  {
2754  for (octave_idx_type i = 0; i < a.length (); i++)
2755  {
2756  octave_quit ();
2757  result(i) = std::pow (a(i), static_cast<int> (b));
2758  }
2759  }
2760  }
2761  else
2762  {
2763  for (octave_idx_type i = 0; i < a.length (); i++)
2764  {
2765  octave_quit ();
2766  result(i) = std::pow (a(i), b);
2767  }
2768  }
2769 
2770  return result;
2771 }
2772 
2773 // -*- 10 -*-
2776 {
2777  dim_vector a_dims = a.dims ();
2778  dim_vector b_dims = b.dims ();
2779 
2780  if (a_dims != b_dims)
2781  {
2782  if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
2783  {
2784  return bsxfun_pow (a, b);
2785  }
2786  else
2787  {
2788  gripe_nonconformant ("operator .^", a_dims, b_dims);
2789  return octave_value ();
2790  }
2791  }
2792 
2793  FloatComplexNDArray result (a_dims);
2794 
2795  for (octave_idx_type i = 0; i < a.length (); i++)
2796  {
2797  octave_quit ();
2798  float btmp = b(i);
2799  if (xisint (btmp))
2800  result(i) = std::pow (a(i), static_cast<int> (btmp));
2801  else
2802  result(i) = std::pow (a(i), btmp);
2803  }
2804 
2805  return result;
2806 }
2807 
2808 // -*- 11 -*-
2811 {
2812  FloatComplexNDArray result (a.dims ());
2813 
2814  for (octave_idx_type i = 0; i < a.length (); i++)
2815  {
2816  octave_quit ();
2817  result(i) = std::pow (a(i), b);
2818  }
2819 
2820  return result;
2821 }
2822 
2823 // -*- 12 -*-
2826 {
2827  dim_vector a_dims = a.dims ();
2828  dim_vector b_dims = b.dims ();
2829 
2830  if (a_dims != b_dims)
2831  {
2832  if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
2833  {
2834  return bsxfun_pow (a, b);
2835  }
2836  else
2837  {
2838  gripe_nonconformant ("operator .^", a_dims, b_dims);
2839  return octave_value ();
2840  }
2841  }
2842 
2843  FloatComplexNDArray result (a_dims);
2844 
2845  for (octave_idx_type i = 0; i < a.length (); i++)
2846  {
2847  octave_quit ();
2848  result(i) = std::pow (a(i), b(i));
2849  }
2850 
2851  return result;
2852 }