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