GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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