00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <cassert>
00029 #include <climits>
00030
00031 #include "Array-util.h"
00032 #include "oct-cmplx.h"
00033 #include "quit.h"
00034
00035 #include "error.h"
00036 #include "oct-obj.h"
00037 #include "utils.h"
00038
00039 #include "dSparse.h"
00040 #include "CSparse.h"
00041 #include "ov-re-sparse.h"
00042 #include "ov-cx-sparse.h"
00043 #include "sparse-xpow.h"
00044
00045 static inline int
00046 xisint (double x)
00047 {
00048 return (D_NINT (x) == x
00049 && ((x >= 0 && x < INT_MAX)
00050 || (x <= 0 && x > INT_MIN)));
00051 }
00052
00053
00054
00055
00056
00057 octave_value
00058 xpow (const SparseMatrix& a, double b)
00059 {
00060 octave_value retval;
00061
00062 octave_idx_type nr = a.rows ();
00063 octave_idx_type nc = a.cols ();
00064
00065 if (nr == 0 || nc == 0 || nr != nc)
00066 error ("for A^b, A must be a square matrix");
00067 else
00068 {
00069 if (static_cast<int> (b) == b)
00070 {
00071 int btmp = static_cast<int> (b);
00072 if (btmp == 0)
00073 {
00074 SparseMatrix tmp = SparseMatrix (nr, nr, nr);
00075 for (octave_idx_type i = 0; i < nr; i++)
00076 {
00077 tmp.data (i) = 1.0;
00078 tmp.ridx (i) = i;
00079 }
00080 for (octave_idx_type i = 0; i < nr + 1; i++)
00081 tmp.cidx (i) = i;
00082
00083 retval = tmp;
00084 }
00085 else
00086 {
00087 SparseMatrix atmp;
00088 if (btmp < 0)
00089 {
00090 btmp = -btmp;
00091
00092 octave_idx_type info;
00093 double rcond = 0.0;
00094 MatrixType mattyp (a);
00095
00096 atmp = a.inverse (mattyp, info, rcond, 1);
00097
00098 if (info == -1)
00099 warning ("inverse: matrix singular to machine\
00100 precision, rcond = %g", rcond);
00101 }
00102 else
00103 atmp = a;
00104
00105 SparseMatrix result (atmp);
00106
00107 btmp--;
00108
00109 while (btmp > 0)
00110 {
00111 if (btmp & 1)
00112 result = result * atmp;
00113
00114 btmp >>= 1;
00115
00116 if (btmp > 0)
00117 atmp = atmp * atmp;
00118 }
00119
00120 retval = result;
00121 }
00122 }
00123 else
00124 error ("use full(a) ^ full(b)");
00125 }
00126
00127 return retval;
00128 }
00129
00130 octave_value
00131 xpow (const SparseComplexMatrix& a, double b)
00132 {
00133 octave_value retval;
00134
00135 octave_idx_type nr = a.rows ();
00136 octave_idx_type nc = a.cols ();
00137
00138 if (nr == 0 || nc == 0 || nr != nc)
00139 error ("for A^b, A must be a square matrix");
00140 else
00141 {
00142 if (static_cast<int> (b) == b)
00143 {
00144 int btmp = static_cast<int> (b);
00145 if (btmp == 0)
00146 {
00147 SparseMatrix tmp = SparseMatrix (nr, nr, nr);
00148 for (octave_idx_type i = 0; i < nr; i++)
00149 {
00150 tmp.data (i) = 1.0;
00151 tmp.ridx (i) = i;
00152 }
00153 for (octave_idx_type i = 0; i < nr + 1; i++)
00154 tmp.cidx (i) = i;
00155
00156 retval = tmp;
00157 }
00158 else
00159 {
00160 SparseComplexMatrix atmp;
00161 if (btmp < 0)
00162 {
00163 btmp = -btmp;
00164
00165 octave_idx_type info;
00166 double rcond = 0.0;
00167 MatrixType mattyp (a);
00168
00169 atmp = a.inverse (mattyp, info, rcond, 1);
00170
00171 if (info == -1)
00172 warning ("inverse: matrix singular to machine\
00173 precision, rcond = %g", rcond);
00174 }
00175 else
00176 atmp = a;
00177
00178 SparseComplexMatrix result (atmp);
00179
00180 btmp--;
00181
00182 while (btmp > 0)
00183 {
00184 if (btmp & 1)
00185 result = result * atmp;
00186
00187 btmp >>= 1;
00188
00189 if (btmp > 0)
00190 atmp = atmp * atmp;
00191 }
00192
00193 retval = result;
00194 }
00195 }
00196 else
00197 error ("use full(a) ^ full(b)");
00198 }
00199
00200 return retval;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 template <class S, class SM>
00239 inline octave_value
00240 scalar_xpow (const S& a, const SM& b)
00241 {
00242 octave_value val = elem_xpow (a, b);
00243
00244 if (val.is_complex_type ())
00245 return SparseComplexMatrix (val.complex_matrix_value ());
00246 else
00247 return SparseMatrix (val.matrix_value ());
00248 }
00249
00250
00251
00252
00253
00254
00255
00256 octave_value
00257 elem_xpow (double a, const SparseMatrix& b)
00258 {
00259 octave_value retval;
00260
00261 octave_idx_type nr = b.rows ();
00262 octave_idx_type nc = b.cols ();
00263
00264 double d1, d2;
00265
00266 if (a < 0.0 && ! b.all_integers (d1, d2))
00267 {
00268 Complex atmp (a);
00269 ComplexMatrix result (nr, nc);
00270
00271 for (octave_idx_type j = 0; j < nc; j++)
00272 {
00273 for (octave_idx_type i = 0; i < nr; i++)
00274 {
00275 octave_quit ();
00276 result (i, j) = std::pow (atmp, b(i,j));
00277 }
00278 }
00279
00280 retval = result;
00281 }
00282 else
00283 {
00284 Matrix result (nr, nc);
00285
00286 for (octave_idx_type j = 0; j < nc; j++)
00287 {
00288 for (octave_idx_type i = 0; i < nr; i++)
00289 {
00290 octave_quit ();
00291 result (i, j) = std::pow (a, b(i,j));
00292 }
00293 }
00294
00295 retval = result;
00296 }
00297
00298 return retval;
00299 }
00300
00301
00302 octave_value
00303 elem_xpow (double a, const SparseComplexMatrix& b)
00304 {
00305 octave_idx_type nr = b.rows ();
00306 octave_idx_type nc = b.cols ();
00307
00308 Complex atmp (a);
00309 ComplexMatrix result (nr, nc);
00310
00311 for (octave_idx_type j = 0; j < nc; j++)
00312 {
00313 for (octave_idx_type i = 0; i < nr; i++)
00314 {
00315 octave_quit ();
00316 result (i, j) = std::pow (atmp, b(i,j));
00317 }
00318 }
00319
00320 return result;
00321 }
00322
00323
00324 octave_value
00325 elem_xpow (const SparseMatrix& a, double b)
00326 {
00327
00328
00329
00330
00331 octave_value retval;
00332
00333 octave_idx_type nz = a.nnz ();
00334
00335 if (b <= 0.0)
00336 {
00337 octave_idx_type nr = a.rows ();
00338 octave_idx_type nc = a.cols ();
00339
00340 if (static_cast<int> (b) != b && a.any_element_is_negative ())
00341 {
00342 ComplexMatrix result (nr, nc, Complex (std::pow (0.0, b)));
00343
00344
00345
00346 Complex btmp (b);
00347
00348 for (octave_idx_type j = 0; j < nc; j++)
00349 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00350 {
00351 octave_quit ();
00352
00353 Complex atmp (a.data (i));
00354
00355 result (a.ridx(i), j) = std::pow (atmp, btmp);
00356 }
00357
00358 retval = octave_value (result);
00359 }
00360 else
00361 {
00362 Matrix result (nr, nc, (std::pow (0.0, b)));
00363
00364 for (octave_idx_type j = 0; j < nc; j++)
00365 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00366 {
00367 octave_quit ();
00368 result (a.ridx(i), j) = std::pow (a.data (i), b);
00369 }
00370
00371 retval = octave_value (result);
00372 }
00373 }
00374 else if (static_cast<int> (b) != b && a.any_element_is_negative ())
00375 {
00376 SparseComplexMatrix result (a);
00377
00378 for (octave_idx_type i = 0; i < nz; i++)
00379 {
00380 octave_quit ();
00381
00382
00383
00384
00385 Complex atmp (a.data (i));
00386 Complex btmp (b);
00387
00388 result.data (i) = std::pow (atmp, btmp);
00389 }
00390
00391 result.maybe_compress (true);
00392
00393 retval = result;
00394 }
00395 else
00396 {
00397 SparseMatrix result (a);
00398
00399 for (octave_idx_type i = 0; i < nz; i++)
00400 {
00401 octave_quit ();
00402 result.data (i) = std::pow (a.data (i), b);
00403 }
00404
00405 result.maybe_compress (true);
00406
00407 retval = result;
00408 }
00409
00410 return retval;
00411 }
00412
00413
00414 octave_value
00415 elem_xpow (const SparseMatrix& a, const SparseMatrix& b)
00416 {
00417 octave_value retval;
00418
00419 octave_idx_type nr = a.rows ();
00420 octave_idx_type nc = a.cols ();
00421
00422 octave_idx_type b_nr = b.rows ();
00423 octave_idx_type b_nc = b.cols ();
00424
00425 if (a.numel () == 1 && b.numel () > 1)
00426 return scalar_xpow (a(0), b);
00427
00428 if (nr != b_nr || nc != b_nc)
00429 {
00430 gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
00431 return octave_value ();
00432 }
00433
00434 int convert_to_complex = 0;
00435 for (octave_idx_type j = 0; j < nc; j++)
00436 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00437 {
00438 if (a.data(i) < 0.0)
00439 {
00440 double btmp = b (a.ridx(i), j);
00441 if (static_cast<int> (btmp) != btmp)
00442 {
00443 convert_to_complex = 1;
00444 goto done;
00445 }
00446 }
00447 }
00448
00449 done:
00450
00451
00452
00453
00454
00455
00456 if (convert_to_complex)
00457 {
00458 SparseComplexMatrix complex_result (nr, nc, Complex(1.0, 0.0));
00459
00460 for (octave_idx_type j = 0; j < nc; j++)
00461 {
00462 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00463 {
00464 octave_quit ();
00465 complex_result.xelem(a.ridx(i), j) =
00466 std::pow (Complex(a.data(i)), Complex(b(a.ridx(i), j)));
00467 }
00468 }
00469 complex_result.maybe_compress (true);
00470 retval = complex_result;
00471 }
00472 else
00473 {
00474 SparseMatrix result (nr, nc, 1.0);
00475
00476 for (octave_idx_type j = 0; j < nc; j++)
00477 {
00478 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00479 {
00480 octave_quit ();
00481 result.xelem(a.ridx(i), j) = std::pow (a.data(i),
00482 b (a.ridx(i), j));
00483 }
00484 }
00485 result.maybe_compress (true);
00486 retval = result;
00487 }
00488
00489 return retval;
00490 }
00491
00492
00493 octave_value
00494 elem_xpow (const SparseMatrix& a, const Complex& b)
00495 {
00496 octave_value retval;
00497
00498 if (b == 0.0)
00499
00500 retval = octave_value (NDArray (a.dims (), 1));
00501 else
00502 {
00503 octave_idx_type nz = a.nnz ();
00504 SparseComplexMatrix result (a);
00505
00506 for (octave_idx_type i = 0; i < nz; i++)
00507 {
00508 octave_quit ();
00509 result.data (i) = std::pow (Complex (a.data (i)), b);
00510 }
00511
00512 result.maybe_compress (true);
00513
00514 retval = result;
00515 }
00516
00517 return retval;
00518 }
00519
00520
00521 octave_value
00522 elem_xpow (const SparseMatrix& a, const SparseComplexMatrix& b)
00523 {
00524 octave_idx_type nr = a.rows ();
00525 octave_idx_type nc = a.cols ();
00526
00527 octave_idx_type b_nr = b.rows ();
00528 octave_idx_type b_nc = b.cols ();
00529
00530 if (a.numel () == 1 && b.numel () > 1)
00531 return scalar_xpow (a(0), b);
00532
00533 if (nr != b_nr || nc != b_nc)
00534 {
00535 gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
00536 return octave_value ();
00537 }
00538
00539 SparseComplexMatrix result (nr, nc, Complex(1.0, 0.0));
00540 for (octave_idx_type j = 0; j < nc; j++)
00541 {
00542 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00543 {
00544 octave_quit ();
00545 result.xelem(a.ridx(i), j) = std::pow (a.data(i), b (a.ridx(i), j));
00546 }
00547 }
00548
00549 result.maybe_compress (true);
00550
00551 return result;
00552 }
00553
00554
00555 octave_value
00556 elem_xpow (const Complex& a, const SparseMatrix& b)
00557 {
00558 octave_idx_type nr = b.rows ();
00559 octave_idx_type nc = b.cols ();
00560
00561 ComplexMatrix result (nr, nc);
00562
00563 for (octave_idx_type j = 0; j < nc; j++)
00564 {
00565 for (octave_idx_type i = 0; i < nr; i++)
00566 {
00567 octave_quit ();
00568 double btmp = b (i, j);
00569 if (xisint (btmp))
00570 result (i, j) = std::pow (a, static_cast<int> (btmp));
00571 else
00572 result (i, j) = std::pow (a, btmp);
00573 }
00574 }
00575
00576 return result;
00577 }
00578
00579
00580 octave_value
00581 elem_xpow (const Complex& a, const SparseComplexMatrix& b)
00582 {
00583 octave_idx_type nr = b.rows ();
00584 octave_idx_type nc = b.cols ();
00585
00586 ComplexMatrix result (nr, nc);
00587 for (octave_idx_type j = 0; j < nc; j++)
00588 for (octave_idx_type i = 0; i < nr; i++)
00589 {
00590 octave_quit ();
00591 result (i, j) = std::pow (a, b (i, j));
00592 }
00593
00594 return result;
00595 }
00596
00597
00598 octave_value
00599 elem_xpow (const SparseComplexMatrix& a, double b)
00600 {
00601 octave_value retval;
00602
00603 if (b <= 0)
00604 {
00605 octave_idx_type nr = a.rows ();
00606 octave_idx_type nc = a.cols ();
00607
00608 ComplexMatrix result (nr, nc, Complex (std::pow (0.0, b)));
00609
00610 if (xisint (b))
00611 {
00612 for (octave_idx_type j = 0; j < nc; j++)
00613 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00614 {
00615 octave_quit ();
00616 result (a.ridx(i), j) =
00617 std::pow (a.data (i), static_cast<int> (b));
00618 }
00619 }
00620 else
00621 {
00622 for (octave_idx_type j = 0; j < nc; j++)
00623 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00624 {
00625 octave_quit ();
00626 result (a.ridx(i), j) = std::pow (a.data (i), b);
00627 }
00628 }
00629
00630 retval = result;
00631 }
00632 else
00633 {
00634 octave_idx_type nz = a.nnz ();
00635
00636 SparseComplexMatrix result (a);
00637
00638 if (xisint (b))
00639 {
00640 for (octave_idx_type i = 0; i < nz; i++)
00641 {
00642 octave_quit ();
00643 result.data (i) = std::pow (a.data (i), static_cast<int> (b));
00644 }
00645 }
00646 else
00647 {
00648 for (octave_idx_type i = 0; i < nz; i++)
00649 {
00650 octave_quit ();
00651 result.data (i) = std::pow (a.data (i), b);
00652 }
00653 }
00654
00655 result.maybe_compress (true);
00656
00657 retval = result;
00658 }
00659
00660 return retval;
00661 }
00662
00663
00664 octave_value
00665 elem_xpow (const SparseComplexMatrix& a, const SparseMatrix& b)
00666 {
00667 octave_idx_type nr = a.rows ();
00668 octave_idx_type nc = a.cols ();
00669
00670 octave_idx_type b_nr = b.rows ();
00671 octave_idx_type b_nc = b.cols ();
00672
00673 if (a.numel () == 1 && b.numel () > 1)
00674 return scalar_xpow (a(0), b);
00675
00676 if (nr != b_nr || nc != b_nc)
00677 {
00678 gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
00679 return octave_value ();
00680 }
00681
00682 SparseComplexMatrix result (nr, nc, Complex(1.0, 0.0));
00683 for (octave_idx_type j = 0; j < nc; j++)
00684 {
00685 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00686 {
00687 octave_quit ();
00688 double btmp = b (a.ridx(i), j);
00689 Complex tmp;
00690
00691 if (xisint (btmp))
00692 result.xelem(a.ridx(i), j) = std::pow (a.data (i),
00693 static_cast<int> (btmp));
00694 else
00695 result.xelem(a.ridx(i), j) = std::pow (a.data (i), btmp);
00696 }
00697 }
00698
00699 result.maybe_compress (true);
00700
00701 return result;
00702 }
00703
00704
00705 octave_value
00706 elem_xpow (const SparseComplexMatrix& a, const Complex& b)
00707 {
00708 octave_value retval;
00709
00710 if (b == 0.0)
00711
00712 retval = octave_value (NDArray (a.dims (), 1));
00713 else
00714 {
00715
00716 octave_idx_type nz = a.nnz ();
00717
00718 SparseComplexMatrix result (a);
00719
00720 for (octave_idx_type i = 0; i < nz; i++)
00721 {
00722 octave_quit ();
00723 result.data (i) = std::pow (a.data (i), b);
00724 }
00725
00726 result.maybe_compress (true);
00727
00728 retval = result;
00729 }
00730
00731 return retval;
00732 }
00733
00734
00735 octave_value
00736 elem_xpow (const SparseComplexMatrix& a, const SparseComplexMatrix& b)
00737 {
00738 octave_idx_type nr = a.rows ();
00739 octave_idx_type nc = a.cols ();
00740
00741 octave_idx_type b_nr = b.rows ();
00742 octave_idx_type b_nc = b.cols ();
00743
00744 if (a.numel () == 1 && b.numel () > 1)
00745 return scalar_xpow (a(0), b);
00746
00747 if (nr != b_nr || nc != b_nc)
00748 {
00749 gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
00750 return octave_value ();
00751 }
00752
00753 SparseComplexMatrix result (nr, nc, Complex(1.0, 0.0));
00754 for (octave_idx_type j = 0; j < nc; j++)
00755 {
00756 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00757 {
00758 octave_quit ();
00759 result.xelem(a.ridx(i), j) = std::pow (a.data (i), b (a.ridx(i), j));
00760 }
00761 }
00762 result.maybe_compress (true);
00763
00764 return result;
00765 }