GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
sparse-xpow.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1998-2025 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 "oct-cmplx.h"
34#include "quit.h"
35
36#include "error.h"
37#include "ovl.h"
38#include "utils.h"
39
40#include "dSparse.h"
41#include "CSparse.h"
42#include "ov-re-sparse.h"
43#include "ov-cx-sparse.h"
44#include "sparse-xpow.h"
45
47
48static inline bool
49xisint (double x)
50{
51 return (octave::math::x_nint (x) == x
52 && ((x >= 0 && x < std::numeric_limits<int>::max ())
53 || (x <= 0 && x > std::numeric_limits<int>::min ())));
54}
55
56// Safer pow functions. Only two make sense for sparse matrices, the
57// others should all promote to full matrices.
58
60xpow (const SparseMatrix& a, double b)
61{
62 octave_value retval;
63
64 octave_idx_type nr = a.rows ();
65 octave_idx_type nc = a.cols ();
66
67 if (nr == 0 || nc == 0)
68 return SparseMatrix ();
69
70 // If we are here, A is not empty ==> A needs to be square.
71 if (nr != nc)
72 error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
73
74 if (! xisint (b))
75 error ("use full(a) ^ full(b)");
76
77 int btmp = static_cast<int> (b);
78 if (btmp == 0)
79 {
80 SparseMatrix tmp = SparseMatrix (nr, nr, nr);
81 for (octave_idx_type i = 0; i < nr; i++)
82 {
83 tmp.data (i) = 1.0;
84 tmp.ridx (i) = i;
85 }
86 for (octave_idx_type i = 0; i < nr + 1; i++)
87 tmp.cidx (i) = i;
88
89 retval = tmp;
90 }
91 else
92 {
93 SparseMatrix atmp;
94 if (btmp < 0)
95 {
96 btmp = -btmp;
97
98 octave_idx_type info;
99 double rcond = 0.0;
100 MatrixType mattyp (a);
101
102 // FIXME: This causes an error if the input sparse matrix is all-zeros.
103 // That behavior is inconsistent with A ^ b when A is a full all-zeros
104 // matrix, which just returns Inf of the same size with a warning.
105 atmp = a.inverse (mattyp, info, rcond, 1);
106
107 if (info == -1)
108 warning ("inverse: matrix singular to machine precision, rcond = %g", rcond);
109 }
110 else
111 atmp = a;
112
113 if (atmp.nnz () == 0) // Fast return for all-zeros matrix
114 return atmp;
115
116 SparseMatrix result (atmp);
117
118 btmp--;
119
120 // There are two approaches to the actual exponentiation.
121 // Exponentiation by squaring uses only a logarithmic number
122 // of multiplications but the matrices it multiplies tend to be dense
123 // towards the end.
124 // Linear multiplication uses a linear number of multiplications
125 // but one of the matrices it uses will be as sparse as the original
126 // matrix.
127 //
128 // The time to multiply fixed-size matrices is strongly affected by their
129 // sparsity. Denser matrices take much longer to multiply together.
130 // See this URL for a worked-through example:
131 // https://octave.discourse.group/t/3216/4
132 //
133 // The tradeoff is between many fast multiplications or a few slow ones.
134 //
135 // Large exponents favor the squaring technique, and sparse matrices
136 // favor linear multiplication.
137 //
138 // We calculate a threshold based on the sparsity of the input
139 // and use squaring for exponents larger than that.
140 //
141 // FIXME: Improve this threshold calculation.
142
143 uint64_t sparsity = atmp.numel () / atmp.nnz (); // reciprocal of density
144 int threshold = (sparsity >= 1000) ? 40
145 : (sparsity >= 100) ? 20
146 : 3;
147
148 if (btmp > threshold) // use squaring technique
149 {
150 while (btmp > 0)
151 {
152 if (btmp & 1)
153 result = result * atmp;
154
155 btmp >>= 1;
156
157 if (btmp > 0)
158 atmp = atmp * atmp;
159 }
160 }
161 else // use linear multiplication
162 {
163 for (int i = 0; i < btmp; i++)
164 result = result * atmp;
165 }
166
167 retval = result;
168 }
169
170 return retval;
171}
172
174xpow (const SparseComplexMatrix& a, double b)
175{
176 octave_value retval;
177
178 octave_idx_type nr = a.rows ();
179 octave_idx_type nc = a.cols ();
180
181 if (nr == 0 || nc == 0)
182 return SparseMatrix ();
183
184 // If we are here, A is not empty ==> A needs to be square.
185 if (nr != nc)
186 error ("for A^b, A must be a square matrix. Use .^ for elementwise power.");
187
188 if (! xisint (b))
189 error ("use full(a) ^ full(b)");
190
191 int btmp = static_cast<int> (b);
192 if (btmp == 0)
193 {
194 SparseMatrix tmp = SparseMatrix (nr, nr, nr);
195 for (octave_idx_type i = 0; i < nr; i++)
196 {
197 tmp.data (i) = 1.0;
198 tmp.ridx (i) = i;
199 }
200 for (octave_idx_type i = 0; i < nr + 1; i++)
201 tmp.cidx (i) = i;
202
203 retval = tmp;
204 }
205 else
206 {
208 if (btmp < 0)
209 {
210 btmp = -btmp;
211
212 octave_idx_type info;
213 double rcond = 0.0;
214 MatrixType mattyp (a);
215
216 atmp = a.inverse (mattyp, info, rcond, 1);
217
218 if (info == -1)
219 warning ("inverse: matrix singular to machine precision, rcond = %g", rcond);
220 }
221 else
222 atmp = a;
223
224 if (atmp.nnz () == 0) // Fast return for all-zeros matrix
225 return atmp;
226
227 SparseComplexMatrix result (atmp);
228
229 btmp--;
230
231 // Select multiplication sequence based on sparsity of atmp.
232 // See the long comment in xpow (const SparseMatrix& a, double b)
233 // for more details.
234 //
235 // FIXME: Improve this threshold calculation.
236
237 uint64_t sparsity = atmp.numel () / atmp.nnz (); // reciprocal of density
238 int threshold = (sparsity >= 1000) ? 40
239 : (sparsity >= 100) ? 20
240 : 3;
241
242 if (btmp > threshold) // use squaring technique
243 {
244 while (btmp > 0)
245 {
246 if (btmp & 1)
247 result = result * atmp;
248
249 btmp >>= 1;
250
251 if (btmp > 0)
252 atmp = atmp * atmp;
253 }
254 }
255 else // use linear multiplication
256 {
257 for (int i = 0; i < btmp; i++)
258 result = result * atmp;
259 }
260
261 retval = result;
262 }
263
264 return retval;
265}
266
267// Safer pow functions that work elementwise for matrices.
268//
269// op2 \ op1: s m cs cm
270// +-- +---+---+----+----+
271// scalar | | * | 3 | * | 9 |
272// +---+---+----+----+
273// matrix | 1 | 4 | 7 | 10 |
274// +---+---+----+----+
275// complex_scalar | * | 5 | * | 11 |
276// +---+---+----+----+
277// complex_matrix | 2 | 6 | 8 | 12 |
278// +---+---+----+----+
279//
280// * -> not needed.
281
282// FIXME: these functions need to be fixed so that things
283// like
284//
285// a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
286//
287// and
288//
289// a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
290//
291// produce identical results. Also, it would be nice if -1^0.5
292// produced a pure imaginary result instead of a complex number with a
293// small real part. But perhaps that's really a problem with the math
294// library...
295
296// Handle special case of scalar-sparse-matrix .^ sparse-matrix.
297// Forwarding to the scalar elem_xpow function and then converting the
298// result back to a sparse matrix is a bit wasteful but it does not
299// seem worth the effort to optimize -- how often does this case come up
300// in practice?
301
302template <typename S, typename SM>
303inline octave_value
304scalar_xpow (const S& a, const SM& b)
305{
306 octave_value val = elem_xpow (a, b);
307
308 if (val.iscomplex ())
310 else
311 return SparseMatrix (val.matrix_value ());
312}
313
314/*
315%!assert (sparse (2) .^ [3, 4], sparse ([8, 16]))
316%!assert <47775> (sparse (2i) .^ [3, 4], sparse ([-0-8i, 16]))
317
318%!test <*63080>
319%! Z = sparse ([]);
320%! A = sparse (zeros (0, 2));
321%! B = sparse (zeros (2, 0));
322%! assert (Z ^ 1, Z);
323%! assert (Z ^ 0, Z);
324%! assert (Z ^ -1, Z);
325%! assert (A ^ 1, Z);
326%! assert (A ^ 0, Z);
327%! assert (A ^ -1, Z);
328%! assert (B ^ 1, Z);
329%! assert (B ^ 0, Z);
330%! assert (B ^ -1, Z);
331
332%!test <*63080>
333%! A = sparse (zeros (2, 2));
334%! assert (A ^ 1, A);
335%! assert (A ^ 0, sparse (eye (2, 2)));
336
337%!test <63080>
338%! A = sparse (zeros (2, 2));
339%! assert (A ^ -1, sparse (inf (2, 2)));
340
341*/
342
343// -*- 1 -*-
345elem_xpow (double a, const SparseMatrix& b)
346{
347 octave_value retval;
348
349 octave_idx_type nr = b.rows ();
350 octave_idx_type nc = b.cols ();
351
352 double d1, d2;
353
354 if (a < 0.0 && ! b.all_integers (d1, d2))
355 {
356 Complex atmp (a);
357 ComplexMatrix result (nr, nc);
358
359 for (octave_idx_type j = 0; j < nc; j++)
360 {
361 for (octave_idx_type i = 0; i < nr; i++)
362 {
363 octave_quit ();
364 result(i, j) = std::pow (atmp, b(i, j));
365 }
366 }
367
368 retval = result;
369 }
370 else
371 {
372 Matrix result (nr, nc);
373
374 for (octave_idx_type j = 0; j < nc; j++)
375 {
376 for (octave_idx_type i = 0; i < nr; i++)
377 {
378 octave_quit ();
379 result(i, j) = std::pow (a, b(i, j));
380 }
381 }
382
383 retval = result;
384 }
385
386 return retval;
387}
388
389// -*- 2 -*-
391elem_xpow (double a, const SparseComplexMatrix& b)
392{
393 octave_idx_type nr = b.rows ();
394 octave_idx_type nc = b.cols ();
395
396 Complex atmp (a);
397 ComplexMatrix result (nr, nc);
398
399 for (octave_idx_type j = 0; j < nc; j++)
400 {
401 for (octave_idx_type i = 0; i < nr; i++)
402 {
403 octave_quit ();
404 result(i, j) = std::pow (atmp, b(i, j));
405 }
406 }
407
408 return result;
409}
410
411// -*- 3 -*-
413elem_xpow (const SparseMatrix& a, double b)
414{
415 // FIXME: What should a .^ 0 give? Matlab gives a
416 // sparse matrix with same structure as a, which is strictly
417 // incorrect. Keep compatibility.
418
419 octave_value retval;
420
421 octave_idx_type nz = a.nnz ();
422
423 if (b <= 0.0)
424 {
425 octave_idx_type nr = a.rows ();
426 octave_idx_type nc = a.cols ();
427
428 if (! xisint (b) && a.any_element_is_negative ())
429 {
430 ComplexMatrix result (nr, nc, Complex (std::pow (0.0, b)));
431
432 // FIXME: avoid apparent GNU libm bug by
433 // converting A and B to complex instead of just A.
434 Complex btmp (b);
435
436 for (octave_idx_type j = 0; j < nc; j++)
437 for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
438 {
439 octave_quit ();
440
441 Complex atmp (a.data (i));
442
443 result(a.ridx (i), j) = std::pow (atmp, btmp);
444 }
445
446 retval = octave_value (result);
447 }
448 else
449 {
450 Matrix result (nr, nc, (std::pow (0.0, b)));
451
452 for (octave_idx_type j = 0; j < nc; j++)
453 for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
454 {
455 octave_quit ();
456 result(a.ridx (i), j) = std::pow (a.data (i), b);
457 }
458
459 retval = octave_value (result);
460 }
461 }
462 else if (! xisint (b) && a.any_element_is_negative ())
463 {
464 SparseComplexMatrix result (a);
465
466 for (octave_idx_type i = 0; i < nz; i++)
467 {
468 octave_quit ();
469
470 // FIXME: avoid apparent GNU libm bug by
471 // converting A and B to complex instead of just A.
472
473 Complex atmp (a.data (i));
474 Complex btmp (b);
475
476 result.data (i) = std::pow (atmp, btmp);
477 }
478
479 result.maybe_compress (true);
480
481 retval = result;
482 }
483 else
484 {
485 SparseMatrix result (a);
486
487 for (octave_idx_type i = 0; i < nz; i++)
488 {
489 octave_quit ();
490 result.data (i) = std::pow (a.data (i), b);
491 }
492
493 result.maybe_compress (true);
494
495 retval = result;
496 }
497
498 return retval;
499}
500
501// -*- 4 -*-
504{
505 octave_value retval;
506
507 octave_idx_type nr = a.rows ();
508 octave_idx_type nc = a.cols ();
509
510 octave_idx_type b_nr = b.rows ();
511 octave_idx_type b_nc = b.cols ();
512
513 if (a.numel () == 1 && b.numel () > 1)
514 return scalar_xpow (a(0), b);
515
516 if (nr != b_nr || nc != b_nc)
517 octave::err_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
518
519 int convert_to_complex = 0;
520 for (octave_idx_type j = 0; j < nc; j++)
521 for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
522 {
523 if (a.data(i) < 0.0)
524 {
525 double btmp = b (a.ridx (i), j);
526 if (! xisint (btmp))
527 {
528 convert_to_complex = 1;
529 goto done;
530 }
531 }
532 }
533
534done:
535
536 // This is a dumb operator for sparse matrices anyway, and there is
537 // no sensible way to handle the 0.^0 versus the 0.^x cases. Therefore
538 // allocate a full matrix filled for the 0.^0 case and shrink it later
539 // as needed.
540
541 if (convert_to_complex)
542 {
543 SparseComplexMatrix complex_result (nr, nc, Complex (1.0, 0.0));
544
545 for (octave_idx_type j = 0; j < nc; j++)
546 {
547 for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
548 {
549 octave_quit ();
550 complex_result.xelem (a.ridx (i), j)
551 = std::pow (Complex (a.data (i)), Complex (b(a.ridx (i), j)));
552 }
553 }
554 complex_result.maybe_compress (true);
555 retval = complex_result;
556 }
557 else
558 {
559 SparseMatrix result (nr, nc, 1.0);
560
561 for (octave_idx_type j = 0; j < nc; j++)
562 {
563 for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
564 {
565 octave_quit ();
566 result.xelem (a.ridx (i), j) = std::pow (a.data (i),
567 b(a.ridx (i), j));
568 }
569 }
570 result.maybe_compress (true);
571 retval = result;
572 }
573
574 return retval;
575}
576
577// -*- 5 -*-
579elem_xpow (const SparseMatrix& a, const Complex& b)
580{
581 octave_value retval;
582
583 if (b == 0.0)
584 // Can this case ever happen, due to automatic retyping with maybe_mutate?
585 retval = octave_value (NDArray (a.dims (), 1));
586 else
587 {
588 octave_idx_type nz = a.nnz ();
589 SparseComplexMatrix result (a);
590
591 for (octave_idx_type i = 0; i < nz; i++)
592 {
593 octave_quit ();
594 result.data (i) = std::pow (Complex (a.data (i)), b);
595 }
596
597 result.maybe_compress (true);
598
599 retval = result;
600 }
601
602 return retval;
603}
604
605// -*- 6 -*-
608{
609 octave_idx_type nr = a.rows ();
610 octave_idx_type nc = a.cols ();
611
612 octave_idx_type b_nr = b.rows ();
613 octave_idx_type b_nc = b.cols ();
614
615 if (a.numel () == 1 && b.numel () > 1)
616 return scalar_xpow (a(0), b);
617
618 if (nr != b_nr || nc != b_nc)
619 octave::err_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
620
621 SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));
622 for (octave_idx_type j = 0; j < nc; j++)
623 {
624 for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
625 {
626 octave_quit ();
627 result.xelem (a.ridx(i), j) = std::pow (a.data (i), b(a.ridx (i), j));
628 }
629 }
630
631 result.maybe_compress (true);
632
633 return result;
634}
635
636// -*- 7 -*-
638elem_xpow (const Complex& a, const SparseMatrix& b)
639{
640 octave_idx_type nr = b.rows ();
641 octave_idx_type nc = b.cols ();
642
643 ComplexMatrix result (nr, nc);
644
645 for (octave_idx_type j = 0; j < nc; j++)
646 {
647 for (octave_idx_type i = 0; i < nr; i++)
648 {
649 octave_quit ();
650 double btmp = b (i, j);
651 if (xisint (btmp))
652 result (i, j) = std::pow (a, static_cast<int> (btmp));
653 else
654 result (i, j) = std::pow (a, btmp);
655 }
656 }
657
658 return result;
659}
660
661// -*- 8 -*-
664{
665 octave_idx_type nr = b.rows ();
666 octave_idx_type nc = b.cols ();
667
668 ComplexMatrix result (nr, nc);
669 for (octave_idx_type j = 0; j < nc; j++)
670 for (octave_idx_type i = 0; i < nr; i++)
671 {
672 octave_quit ();
673 result (i, j) = std::pow (a, b (i, j));
674 }
675
676 return result;
677}
678
679// -*- 9 -*-
681elem_xpow (const SparseComplexMatrix& a, double b)
682{
683 octave_value retval;
684
685 if (b <= 0)
686 {
687 octave_idx_type nr = a.rows ();
688 octave_idx_type nc = a.cols ();
689
690 ComplexMatrix result (nr, nc, Complex (std::pow (0.0, b)));
691
692 if (xisint (b))
693 {
694 for (octave_idx_type j = 0; j < nc; j++)
695 for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
696 {
697 octave_quit ();
698 result (a.ridx (i), j)
699 = std::pow (a.data (i), static_cast<int> (b));
700 }
701 }
702 else
703 {
704 for (octave_idx_type j = 0; j < nc; j++)
705 for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
706 {
707 octave_quit ();
708 result (a.ridx (i), j) = std::pow (a.data (i), b);
709 }
710 }
711
712 retval = result;
713 }
714 else
715 {
716 octave_idx_type nz = a.nnz ();
717
718 SparseComplexMatrix result (a);
719
720 if (xisint (b))
721 {
722 for (octave_idx_type i = 0; i < nz; i++)
723 {
724 octave_quit ();
725 result.data (i) = std::pow (a.data (i), static_cast<int> (b));
726 }
727 }
728 else
729 {
730 for (octave_idx_type i = 0; i < nz; i++)
731 {
732 octave_quit ();
733 result.data (i) = std::pow (a.data (i), b);
734 }
735 }
736
737 result.maybe_compress (true);
738
739 retval = result;
740 }
741
742 return retval;
743}
744
745// -*- 10 -*-
748{
749 octave_idx_type nr = a.rows ();
750 octave_idx_type nc = a.cols ();
751
752 octave_idx_type b_nr = b.rows ();
753 octave_idx_type b_nc = b.cols ();
754
755 if (a.numel () == 1 && b.numel () > 1)
756 return scalar_xpow (a(0), b);
757
758 if (nr != b_nr || nc != b_nc)
759 octave::err_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
760
761 SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));
762 for (octave_idx_type j = 0; j < nc; j++)
763 {
764 for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
765 {
766 octave_quit ();
767 double btmp = b(a.ridx (i), j);
768
769 if (xisint (btmp))
770 result.xelem (a.ridx (i), j) = std::pow (a.data (i),
771 static_cast<int> (btmp));
772 else
773 result.xelem (a.ridx (i), j) = std::pow (a.data (i), btmp);
774 }
775 }
776
777 result.maybe_compress (true);
778
779 return result;
780}
781
782// -*- 11 -*-
785{
786 octave_value retval;
787
788 if (b == 0.0)
789 // Can this case ever happen, due to automatic retyping with maybe_mutate?
790 retval = octave_value (NDArray (a.dims (), 1));
791 else
792 {
793
794 octave_idx_type nz = a.nnz ();
795
796 SparseComplexMatrix result (a);
797
798 for (octave_idx_type i = 0; i < nz; i++)
799 {
800 octave_quit ();
801 result.data (i) = std::pow (a.data (i), b);
802 }
803
804 result.maybe_compress (true);
805
806 retval = result;
807 }
808
809 return retval;
810}
811
812// -*- 12 -*-
815{
816 octave_idx_type nr = a.rows ();
817 octave_idx_type nc = a.cols ();
818
819 octave_idx_type b_nr = b.rows ();
820 octave_idx_type b_nc = b.cols ();
821
822 if (a.numel () == 1 && b.numel () > 1)
823 return scalar_xpow (a(0), b);
824
825 if (nr != b_nr || nc != b_nc)
826 octave::err_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
827
828 SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));
829 for (octave_idx_type j = 0; j < nc; j++)
830 {
831 for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
832 {
833 octave_quit ();
834 result.xelem (a.ridx (i), j) = std::pow (a.data (i),
835 b(a.ridx (i), j));
836 }
837 }
838 result.maybe_compress (true);
839
840 return result;
841}
842
843
844OCTAVE_END_NAMESPACE(octave)
SparseComplexMatrix inverse() const
Definition CSparse.cc:666
bool all_integers(double &max_val, double &min_val) const
Definition dSparse.cc:7249
SparseMatrix inverse() const
Definition dSparse.cc:608
bool any_element_is_negative(bool=false) const
Definition dSparse.cc:7151
octave_idx_type cols() const
Definition Sparse.h:349
octave_idx_type * cidx()
Definition Sparse.h:593
T * data()
Definition Sparse.h:571
octave_idx_type * ridx()
Definition Sparse.h:580
octave_idx_type numel() const
Definition Sparse.h:340
Sparse< T, Alloc > maybe_compress(bool remove_zeros=false)
Definition Sparse.h:528
octave_idx_type nnz() const
Actual number of nonzero terms.
Definition Sparse.h:336
octave_idx_type rows() const
Definition Sparse.h:348
T & xelem(octave_idx_type n)
Definition Sparse.h:392
dim_vector dims() const
Definition Sparse.h:368
ComplexMatrix complex_matrix_value(bool frc_str_conv=false) const
Definition ov.h:877
bool iscomplex() const
Definition ov.h:741
Matrix matrix_value(bool frc_str_conv=false) const
Definition ov.h:859
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void warning(const char *fmt,...)
Definition error.cc:1078
void error(const char *fmt,...)
Definition error.cc:1003
F77_RET_T const F77_DBLE * x
std::complex< double > Complex
Definition oct-cmplx.h:33
octave_value xpow(const SparseMatrix &a, double b)
octave_value elem_xpow(double a, const SparseMatrix &b)
octave_value scalar_xpow(const S &a, const SM &b)