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