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
00030 #include "Array-util.h"
00031 #include "oct-cmplx.h"
00032 #include "quit.h"
00033 #include "error.h"
00034 #include "lo-ieee.h"
00035
00036 #include "dSparse.h"
00037 #include "dDiagMatrix.h"
00038 #include "CSparse.h"
00039 #include "CDiagMatrix.h"
00040 #include "oct-spparms.h"
00041 #include "sparse-xdiv.h"
00042
00043 static void
00044 solve_singularity_warning (double rcond)
00045 {
00046 warning ("matrix singular to machine precision, rcond = %g", rcond);
00047 warning ("attempting to find minimum norm solution");
00048 }
00049
00050 template <class T1, class T2>
00051 bool
00052 mx_leftdiv_conform (const T1& a, const T2& b)
00053 {
00054 octave_idx_type a_nr = a.rows ();
00055 octave_idx_type b_nr = b.rows ();
00056
00057 if (a_nr != b_nr)
00058 {
00059 octave_idx_type a_nc = a.cols ();
00060 octave_idx_type b_nc = b.cols ();
00061
00062 gripe_nonconformant ("operator \\", a_nr, a_nc, b_nr, b_nc);
00063 return false;
00064 }
00065
00066 return true;
00067 }
00068
00069 #define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2) \
00070 template bool mx_leftdiv_conform (const T1&, const T2&)
00071
00072 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseMatrix);
00073 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseComplexMatrix);
00074 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseMatrix);
00075 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix);
00076 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, Matrix);
00077 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, ComplexMatrix);
00078 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, Matrix);
00079 INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, ComplexMatrix);
00080 INSTANTIATE_MX_LEFTDIV_CONFORM (DiagMatrix, SparseMatrix);
00081 INSTANTIATE_MX_LEFTDIV_CONFORM (DiagMatrix, SparseComplexMatrix);
00082 INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexDiagMatrix, SparseMatrix);
00083 INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexDiagMatrix, SparseComplexMatrix);
00084
00085 template <class T1, class T2>
00086 bool
00087 mx_div_conform (const T1& a, const T2& b)
00088 {
00089 octave_idx_type a_nc = a.cols ();
00090 octave_idx_type b_nc = b.cols ();
00091
00092 if (a_nc != b_nc)
00093 {
00094 octave_idx_type a_nr = a.rows ();
00095 octave_idx_type b_nr = b.rows ();
00096
00097 gripe_nonconformant ("operator /", a_nr, a_nc, b_nr, b_nc);
00098 return false;
00099 }
00100
00101 return true;
00102 }
00103
00104 #define INSTANTIATE_MX_DIV_CONFORM(T1, T2) \
00105 template bool mx_div_conform (const T1&, const T2&)
00106
00107 INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseMatrix);
00108 INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseComplexMatrix);
00109 INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseMatrix);
00110 INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix);
00111 INSTANTIATE_MX_DIV_CONFORM (Matrix, SparseMatrix);
00112 INSTANTIATE_MX_DIV_CONFORM (Matrix, SparseComplexMatrix);
00113 INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseMatrix);
00114 INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseComplexMatrix);
00115 INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, DiagMatrix);
00116 INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, ComplexDiagMatrix);
00117 INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, DiagMatrix);
00118 INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, ComplexDiagMatrix);
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 Matrix
00135 xdiv (const Matrix& a, const SparseMatrix& b, MatrixType &typ)
00136 {
00137 if (! mx_div_conform (a, b))
00138 return Matrix ();
00139
00140 Matrix atmp = a.transpose ();
00141 SparseMatrix btmp = b.transpose ();
00142 MatrixType btyp = typ.transpose ();
00143
00144 octave_idx_type info;
00145 double rcond = 0.0;
00146 Matrix result = btmp.solve (btyp, atmp, info, rcond,
00147 solve_singularity_warning);
00148
00149 typ = btyp.transpose ();
00150 return result.transpose ();
00151 }
00152
00153
00154 ComplexMatrix
00155 xdiv (const Matrix& a, const SparseComplexMatrix& b, MatrixType &typ)
00156 {
00157 if (! mx_div_conform (a, b))
00158 return ComplexMatrix ();
00159
00160 Matrix atmp = a.transpose ();
00161 SparseComplexMatrix btmp = b.hermitian ();
00162 MatrixType btyp = typ.transpose ();
00163
00164 octave_idx_type info;
00165 double rcond = 0.0;
00166 ComplexMatrix result
00167 = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00168
00169 typ = btyp.transpose ();
00170 return result.hermitian ();
00171 }
00172
00173
00174 ComplexMatrix
00175 xdiv (const ComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
00176 {
00177 if (! mx_div_conform (a, b))
00178 return ComplexMatrix ();
00179
00180 ComplexMatrix atmp = a.hermitian ();
00181 SparseMatrix btmp = b.transpose ();
00182 MatrixType btyp = typ.transpose ();
00183
00184 octave_idx_type info;
00185 double rcond = 0.0;
00186 ComplexMatrix result
00187 = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00188
00189 typ = btyp.transpose ();
00190 return result.hermitian ();
00191 }
00192
00193
00194 ComplexMatrix
00195 xdiv (const ComplexMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
00196 {
00197 if (! mx_div_conform (a, b))
00198 return ComplexMatrix ();
00199
00200 ComplexMatrix atmp = a.hermitian ();
00201 SparseComplexMatrix btmp = b.hermitian ();
00202 MatrixType btyp = typ.transpose ();
00203
00204 octave_idx_type info;
00205 double rcond = 0.0;
00206 ComplexMatrix result
00207 = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00208
00209 typ = btyp.transpose ();
00210 return result.hermitian ();
00211 }
00212
00213
00214 SparseMatrix
00215 xdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType &typ)
00216 {
00217 if (! mx_div_conform (a, b))
00218 return SparseMatrix ();
00219
00220 SparseMatrix atmp = a.transpose ();
00221 SparseMatrix btmp = b.transpose ();
00222 MatrixType btyp = typ.transpose ();
00223
00224 octave_idx_type info;
00225 double rcond = 0.0;
00226 SparseMatrix result = btmp.solve (btyp, atmp, info, rcond,
00227 solve_singularity_warning);
00228
00229 typ = btyp.transpose ();
00230 return result.transpose ();
00231 }
00232
00233
00234 SparseComplexMatrix
00235 xdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
00236 {
00237 if (! mx_div_conform (a, b))
00238 return SparseComplexMatrix ();
00239
00240 SparseMatrix atmp = a.transpose ();
00241 SparseComplexMatrix btmp = b.hermitian ();
00242 MatrixType btyp = typ.transpose ();
00243
00244 octave_idx_type info;
00245 double rcond = 0.0;
00246 SparseComplexMatrix result
00247 = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00248
00249 typ = btyp.transpose ();
00250 return result.hermitian ();
00251 }
00252
00253
00254 SparseComplexMatrix
00255 xdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
00256 {
00257 if (! mx_div_conform (a, b))
00258 return SparseComplexMatrix ();
00259
00260 SparseComplexMatrix atmp = a.hermitian ();
00261 SparseMatrix btmp = b.transpose ();
00262 MatrixType btyp = typ.transpose ();
00263
00264 octave_idx_type info;
00265 double rcond = 0.0;
00266 SparseComplexMatrix result
00267 = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00268
00269 typ = btyp.transpose ();
00270 return result.hermitian ();
00271 }
00272
00273
00274 SparseComplexMatrix
00275 xdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
00276 {
00277 if (! mx_div_conform (a, b))
00278 return SparseComplexMatrix ();
00279
00280 SparseComplexMatrix atmp = a.hermitian ();
00281 SparseComplexMatrix btmp = b.hermitian ();
00282 MatrixType btyp = typ.transpose ();
00283
00284 octave_idx_type info;
00285 double rcond = 0.0;
00286 SparseComplexMatrix result
00287 = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
00288
00289 typ = btyp.transpose ();
00290 return result.hermitian ();
00291 }
00292
00293 template <typename RT, typename SM, typename DM>
00294 RT do_rightdiv_sm_dm (const SM& a, const DM& d)
00295 {
00296 const octave_idx_type d_nr = d.rows ();
00297
00298 const octave_idx_type a_nr = a.rows ();
00299 const octave_idx_type a_nc = a.cols ();
00300
00301 using std::min;
00302 const octave_idx_type nc = min (d_nr, a_nc);
00303
00304 if ( ! mx_div_conform (a, d))
00305 return RT ();
00306
00307 const octave_idx_type nz = a.nnz ();
00308 RT r (a_nr, nc, nz);
00309
00310 typedef typename DM::element_type DM_elt_type;
00311 const DM_elt_type zero = DM_elt_type ();
00312
00313 octave_idx_type k_result = 0;
00314 for (octave_idx_type j = 0; j < nc; ++j)
00315 {
00316 octave_quit ();
00317 const DM_elt_type s = d.dgelem (j);
00318 const octave_idx_type colend = a.cidx (j+1);
00319 r.xcidx (j) = k_result;
00320 if (s != zero)
00321 for (octave_idx_type k = a.cidx (j); k < colend; ++k)
00322 {
00323 r.xdata (k_result) = a.data (k) / s;
00324 r.xridx (k_result) = a.ridx (k);
00325 ++k_result;
00326 }
00327 }
00328 r.xcidx (nc) = k_result;
00329
00330 r.maybe_compress (true);
00331 return r;
00332 }
00333
00334
00335 SparseMatrix
00336 xdiv (const SparseMatrix& a, const DiagMatrix& b, MatrixType &)
00337 {
00338 return do_rightdiv_sm_dm<SparseMatrix> (a, b);
00339 }
00340
00341
00342 SparseComplexMatrix
00343 xdiv (const SparseMatrix& a, const ComplexDiagMatrix& b, MatrixType &)
00344 {
00345 return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
00346 }
00347
00348
00349 SparseComplexMatrix
00350 xdiv (const SparseComplexMatrix& a, const DiagMatrix& b, MatrixType &)
00351 {
00352 return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
00353 }
00354
00355
00356 SparseComplexMatrix
00357 xdiv (const SparseComplexMatrix& a, const ComplexDiagMatrix& b, MatrixType &)
00358 {
00359 return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 Matrix
00372 x_el_div (double a, const SparseMatrix& b)
00373 {
00374 octave_idx_type nr = b.rows ();
00375 octave_idx_type nc = b.cols ();
00376
00377 Matrix result;
00378 if (a == 0.)
00379 result = Matrix (nr, nc, octave_NaN);
00380 else if (a > 0.)
00381 result = Matrix (nr, nc, octave_Inf);
00382 else
00383 result = Matrix (nr, nc, -octave_Inf);
00384
00385
00386 for (octave_idx_type j = 0; j < nc; j++)
00387 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
00388 {
00389 octave_quit ();
00390 result.elem (b.ridx(i), j) = a / b.data (i);
00391 }
00392
00393 return result;
00394 }
00395
00396 ComplexMatrix
00397 x_el_div (double a, const SparseComplexMatrix& b)
00398 {
00399 octave_idx_type nr = b.rows ();
00400 octave_idx_type nc = b.cols ();
00401
00402 ComplexMatrix result (nr, nc, Complex(octave_NaN, octave_NaN));
00403
00404 for (octave_idx_type j = 0; j < nc; j++)
00405 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
00406 {
00407 octave_quit ();
00408 result.elem (b.ridx(i), j) = a / b.data (i);
00409 }
00410
00411 return result;
00412 }
00413
00414 ComplexMatrix
00415 x_el_div (const Complex a, const SparseMatrix& b)
00416 {
00417 octave_idx_type nr = b.rows ();
00418 octave_idx_type nc = b.cols ();
00419
00420 ComplexMatrix result (nr, nc, (a / 0.0));
00421
00422 for (octave_idx_type j = 0; j < nc; j++)
00423 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
00424 {
00425 octave_quit ();
00426 result.elem (b.ridx(i), j) = a / b.data (i);
00427 }
00428
00429 return result;
00430 }
00431
00432 ComplexMatrix
00433 x_el_div (const Complex a, const SparseComplexMatrix& b)
00434 {
00435 octave_idx_type nr = b.rows ();
00436 octave_idx_type nc = b.cols ();
00437
00438 ComplexMatrix result (nr, nc, (a / 0.0));
00439
00440 for (octave_idx_type j = 0; j < nc; j++)
00441 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
00442 {
00443 octave_quit ();
00444 result.elem (b.ridx(i), j) = a / b.data (i);
00445 }
00446
00447 return result;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 Matrix
00465 xleftdiv (const SparseMatrix& a, const Matrix& b, MatrixType &typ)
00466 {
00467 if (! mx_leftdiv_conform (a, b))
00468 return Matrix ();
00469
00470 octave_idx_type info;
00471 double rcond = 0.0;
00472 return a.solve (typ, b, info, rcond, solve_singularity_warning);
00473 }
00474
00475
00476 ComplexMatrix
00477 xleftdiv (const SparseMatrix& a, const ComplexMatrix& b, MatrixType &typ)
00478 {
00479 if (! mx_leftdiv_conform (a, b))
00480 return ComplexMatrix ();
00481
00482 octave_idx_type info;
00483 double rcond = 0.0;
00484 return a.solve (typ, b, info, rcond, solve_singularity_warning);
00485 }
00486
00487
00488 SparseMatrix
00489 xleftdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType &typ)
00490 {
00491 if (! mx_leftdiv_conform (a, b))
00492 return SparseMatrix ();
00493
00494 octave_idx_type info;
00495 double rcond = 0.0;
00496 return a.solve (typ, b, info, rcond, solve_singularity_warning);
00497 }
00498
00499
00500 SparseComplexMatrix
00501 xleftdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
00502 {
00503 if (! mx_leftdiv_conform (a, b))
00504 return SparseComplexMatrix ();
00505
00506 octave_idx_type info;
00507 double rcond = 0.0;
00508 return a.solve (typ, b, info, rcond, solve_singularity_warning);
00509 }
00510
00511
00512 ComplexMatrix
00513 xleftdiv (const SparseComplexMatrix& a, const Matrix& b, MatrixType &typ)
00514 {
00515 if (! mx_leftdiv_conform (a, b))
00516 return ComplexMatrix ();
00517
00518 octave_idx_type info;
00519 double rcond = 0.0;
00520 return a.solve (typ, b, info, rcond, solve_singularity_warning);
00521 }
00522
00523
00524 ComplexMatrix
00525 xleftdiv (const SparseComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ)
00526 {
00527 if (! mx_leftdiv_conform (a, b))
00528 return ComplexMatrix ();
00529
00530 octave_idx_type info;
00531 double rcond = 0.0;
00532 return a.solve (typ, b, info, rcond, solve_singularity_warning);
00533 }
00534
00535
00536 SparseComplexMatrix
00537 xleftdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
00538 {
00539 if (! mx_leftdiv_conform (a, b))
00540 return SparseComplexMatrix ();
00541
00542 octave_idx_type info;
00543 double rcond = 0.0;
00544 return a.solve (typ, b, info, rcond, solve_singularity_warning);
00545 }
00546
00547
00548 SparseComplexMatrix
00549 xleftdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b,
00550 MatrixType &typ)
00551 {
00552 if (! mx_leftdiv_conform (a, b))
00553 return SparseComplexMatrix ();
00554
00555 octave_idx_type info;
00556 double rcond = 0.0;
00557 return a.solve (typ, b, info, rcond, solve_singularity_warning);
00558 }
00559
00560 template <typename RT, typename DM, typename SM>
00561 RT do_leftdiv_dm_sm (const DM& d, const SM& a)
00562 {
00563 const octave_idx_type a_nr = a.rows ();
00564 const octave_idx_type a_nc = a.cols ();
00565
00566 const octave_idx_type d_nc = d.cols ();
00567
00568 using std::min;
00569 const octave_idx_type nr = min (d_nc, a_nr);
00570
00571 if ( ! mx_leftdiv_conform (d, a))
00572 return RT ();
00573
00574 const octave_idx_type nz = a.nnz ();
00575 RT r (nr, a_nc, nz);
00576
00577 typedef typename DM::element_type DM_elt_type;
00578 const DM_elt_type zero = DM_elt_type ();
00579
00580 octave_idx_type k_result = 0;
00581 for (octave_idx_type j = 0; j < a_nc; ++j)
00582 {
00583 octave_quit ();
00584 const octave_idx_type colend = a.cidx (j+1);
00585 r.xcidx (j) = k_result;
00586 for (octave_idx_type k = a.cidx (j); k < colend; ++k)
00587 {
00588 const octave_idx_type i = a.ridx (k);
00589 if (i < nr)
00590 {
00591 const DM_elt_type s = d.dgelem (i);
00592 if (s != zero)
00593 {
00594 r.xdata (k_result) = a.data (k) / s;
00595 r.xridx (k_result) = i;
00596 ++k_result;
00597 }
00598 }
00599 }
00600 }
00601 r.xcidx (a_nc) = k_result;
00602
00603 r.maybe_compress (true);
00604 return r;
00605 }
00606
00607
00608 SparseMatrix
00609 xleftdiv (const DiagMatrix& d, const SparseMatrix& a, MatrixType&)
00610 {
00611 return do_leftdiv_dm_sm<SparseMatrix> (d, a);
00612 }
00613
00614
00615 SparseComplexMatrix
00616 xleftdiv (const DiagMatrix& d, const SparseComplexMatrix& a, MatrixType&)
00617 {
00618 return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
00619 }
00620
00621
00622 SparseComplexMatrix
00623 xleftdiv (const ComplexDiagMatrix& d, const SparseMatrix& a, MatrixType&)
00624 {
00625 return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
00626 }
00627
00628
00629 SparseComplexMatrix
00630 xleftdiv (const ComplexDiagMatrix& d, const SparseComplexMatrix& a, MatrixType&)
00631 {
00632 return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
00633 }