comparison liboctave/CSparse.cc @ 10314:07ebe522dac2

untabify liboctave C++ sources
author John W. Eaton <jwe@octave.org>
date Thu, 11 Feb 2010 12:23:32 -0500
parents 4c0cdbe0acca
children 12884915a8e4
comparison
equal deleted inserted replaced
10313:f3b65e1ae355 10314:07ebe522dac2
65 // Fortran functions we call. 65 // Fortran functions we call.
66 extern "C" 66 extern "C"
67 { 67 {
68 F77_RET_T 68 F77_RET_T
69 F77_FUNC (zgbtrf, ZGBTRF) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 69 F77_FUNC (zgbtrf, ZGBTRF) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&,
70 const octave_idx_type&, Complex*, const octave_idx_type&, octave_idx_type*, octave_idx_type&); 70 const octave_idx_type&, Complex*, const octave_idx_type&, octave_idx_type*, octave_idx_type&);
71 71
72 F77_RET_T 72 F77_RET_T
73 F77_FUNC (zgbtrs, ZGBTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, 73 F77_FUNC (zgbtrs, ZGBTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
74 const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 74 const octave_idx_type&, const octave_idx_type&, const octave_idx_type&,
75 const Complex*, const octave_idx_type&, 75 const Complex*, const octave_idx_type&,
76 const octave_idx_type*, Complex*, const octave_idx_type&, octave_idx_type& 76 const octave_idx_type*, Complex*, const octave_idx_type&, octave_idx_type&
77 F77_CHAR_ARG_LEN_DECL); 77 F77_CHAR_ARG_LEN_DECL);
78 78
79 F77_RET_T 79 F77_RET_T
80 F77_FUNC (zgbcon, ZGBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, 80 F77_FUNC (zgbcon, ZGBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
81 const octave_idx_type&, const octave_idx_type&, Complex*, 81 const octave_idx_type&, const octave_idx_type&, Complex*,
82 const octave_idx_type&, const octave_idx_type*, const double&, 82 const octave_idx_type&, const octave_idx_type*, const double&,
83 double&, Complex*, double*, octave_idx_type& 83 double&, Complex*, double*, octave_idx_type&
84 F77_CHAR_ARG_LEN_DECL); 84 F77_CHAR_ARG_LEN_DECL);
85 85
86 F77_RET_T 86 F77_RET_T
87 F77_FUNC (zpbtrf, ZPBTRF) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, 87 F77_FUNC (zpbtrf, ZPBTRF) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
88 const octave_idx_type&, Complex*, const octave_idx_type&, octave_idx_type& 88 const octave_idx_type&, Complex*, const octave_idx_type&, octave_idx_type&
89 F77_CHAR_ARG_LEN_DECL); 89 F77_CHAR_ARG_LEN_DECL);
90 90
91 F77_RET_T 91 F77_RET_T
92 F77_FUNC (zpbtrs, ZPBTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, 92 F77_FUNC (zpbtrs, ZPBTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
93 const octave_idx_type&, const octave_idx_type&, Complex*, const octave_idx_type&, 93 const octave_idx_type&, const octave_idx_type&, Complex*, const octave_idx_type&,
94 Complex*, const octave_idx_type&, octave_idx_type& 94 Complex*, const octave_idx_type&, octave_idx_type&
95 F77_CHAR_ARG_LEN_DECL); 95 F77_CHAR_ARG_LEN_DECL);
96 96
97 F77_RET_T 97 F77_RET_T
98 F77_FUNC (zpbcon, ZPBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, 98 F77_FUNC (zpbcon, ZPBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
99 const octave_idx_type&, Complex*, const octave_idx_type&, 99 const octave_idx_type&, Complex*, const octave_idx_type&,
100 const double&, double&, Complex*, double*, octave_idx_type& 100 const double&, double&, Complex*, double*, octave_idx_type&
101 F77_CHAR_ARG_LEN_DECL); 101 F77_CHAR_ARG_LEN_DECL);
102 102
103 F77_RET_T 103 F77_RET_T
104 F77_FUNC (zgttrf, ZGTTRF) (const octave_idx_type&, Complex*, Complex*, Complex*, 104 F77_FUNC (zgttrf, ZGTTRF) (const octave_idx_type&, Complex*, Complex*, Complex*,
105 Complex*, octave_idx_type*, octave_idx_type&); 105 Complex*, octave_idx_type*, octave_idx_type&);
106 106
107 F77_RET_T 107 F77_RET_T
108 F77_FUNC (zgttrs, ZGTTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, 108 F77_FUNC (zgttrs, ZGTTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&,
109 const octave_idx_type&, const Complex*, const Complex*, 109 const octave_idx_type&, const Complex*, const Complex*,
110 const Complex*, const Complex*, const octave_idx_type*, 110 const Complex*, const Complex*, const octave_idx_type*,
111 Complex *, const octave_idx_type&, octave_idx_type& 111 Complex *, const octave_idx_type&, octave_idx_type&
112 F77_CHAR_ARG_LEN_DECL); 112 F77_CHAR_ARG_LEN_DECL);
113 113
114 F77_RET_T 114 F77_RET_T
115 F77_FUNC (zptsv, ZPTSV) (const octave_idx_type&, const octave_idx_type&, double*, Complex*, 115 F77_FUNC (zptsv, ZPTSV) (const octave_idx_type&, const octave_idx_type&, double*, Complex*,
116 Complex*, const octave_idx_type&, octave_idx_type&); 116 Complex*, const octave_idx_type&, octave_idx_type&);
117 117
118 F77_RET_T 118 F77_RET_T
119 F77_FUNC (zgtsv, ZGTSV) (const octave_idx_type&, const octave_idx_type&, Complex*, Complex*, 119 F77_FUNC (zgtsv, ZGTSV) (const octave_idx_type&, const octave_idx_type&, Complex*, Complex*,
120 Complex*, Complex*, const octave_idx_type&, octave_idx_type&); 120 Complex*, Complex*, const octave_idx_type&, octave_idx_type&);
121 } 121 }
122 122
123 SparseComplexMatrix::SparseComplexMatrix (const SparseMatrix& a) 123 SparseComplexMatrix::SparseComplexMatrix (const SparseMatrix& a)
124 : MSparse<Complex> (a.rows (), a.cols (), a.nnz ()) 124 : MSparse<Complex> (a.rows (), a.cols (), a.nnz ())
125 { 125 {
182 if (nr != nr_a || nc != nc_a || nz != nz_a) 182 if (nr != nr_a || nc != nc_a || nz != nz_a)
183 return false; 183 return false;
184 184
185 for (octave_idx_type i = 0; i < nc + 1; i++) 185 for (octave_idx_type i = 0; i < nc + 1; i++)
186 if (cidx(i) != a.cidx(i)) 186 if (cidx(i) != a.cidx(i))
187 return false; 187 return false;
188 188
189 for (octave_idx_type i = 0; i < nz; i++) 189 for (octave_idx_type i = 0; i < nz; i++)
190 if (data(i) != a.data(i) || ridx(i) != a.ridx(i)) 190 if (data(i) != a.data(i) || ridx(i) != a.ridx(i))
191 return false; 191 return false;
192 192
206 octave_idx_type nc = cols (); 206 octave_idx_type nc = cols ();
207 207
208 if (nr == nc && nr > 0) 208 if (nr == nc && nr > 0)
209 { 209 {
210 for (octave_idx_type j = 0; j < nc; j++) 210 for (octave_idx_type j = 0; j < nc; j++)
211 { 211 {
212 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 212 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
213 { 213 {
214 octave_idx_type ri = ridx(i); 214 octave_idx_type ri = ridx(i);
215 215
216 if (ri != j) 216 if (ri != j)
217 { 217 {
218 bool found = false; 218 bool found = false;
219 219
220 for (octave_idx_type k = cidx(ri); k < cidx(ri+1); k++) 220 for (octave_idx_type k = cidx(ri); k < cidx(ri+1); k++)
221 { 221 {
222 if (ridx(k) == j) 222 if (ridx(k) == j)
223 { 223 {
224 if (data(i) == conj(data(k))) 224 if (data(i) == conj(data(k)))
225 found = true; 225 found = true;
226 break; 226 break;
227 } 227 }
228 } 228 }
229 229
230 if (! found) 230 if (! found)
231 return false; 231 return false;
232 } 232 }
233 } 233 }
234 } 234 }
235 235
236 return true; 236 return true;
237 } 237 }
238 238
239 return false; 239 return false;
266 if (dim == 0) 266 if (dim == 0)
267 { 267 {
268 idx_arg.clear (1, nc); 268 idx_arg.clear (1, nc);
269 octave_idx_type nel = 0; 269 octave_idx_type nel = 0;
270 for (octave_idx_type j = 0; j < nc; j++) 270 for (octave_idx_type j = 0; j < nc; j++)
271 { 271 {
272 Complex tmp_max; 272 Complex tmp_max;
273 double abs_max = octave_NaN; 273 double abs_max = octave_NaN;
274 octave_idx_type idx_j = 0; 274 octave_idx_type idx_j = 0;
275 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 275 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
276 { 276 {
277 if (ridx(i) != idx_j) 277 if (ridx(i) != idx_j)
278 break; 278 break;
279 else 279 else
280 idx_j++; 280 idx_j++;
281 } 281 }
282 282
283 if (idx_j != nr) 283 if (idx_j != nr)
284 { 284 {
285 tmp_max = 0.; 285 tmp_max = 0.;
286 abs_max = 0.; 286 abs_max = 0.;
287 } 287 }
288 288
289 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 289 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
290 { 290 {
291 Complex tmp = data (i); 291 Complex tmp = data (i);
292 292
293 if (xisnan (tmp)) 293 if (xisnan (tmp))
294 continue; 294 continue;
295 295
296 double abs_tmp = std::abs (tmp); 296 double abs_tmp = std::abs (tmp);
297 297
298 if (xisnan (abs_max) || abs_tmp > abs_max) 298 if (xisnan (abs_max) || abs_tmp > abs_max)
299 { 299 {
300 idx_j = ridx (i); 300 idx_j = ridx (i);
301 tmp_max = tmp; 301 tmp_max = tmp;
302 abs_max = abs_tmp; 302 abs_max = abs_tmp;
303 } 303 }
304 } 304 }
305 305
306 idx_arg.elem (j) = xisnan (tmp_max) ? 0 : idx_j; 306 idx_arg.elem (j) = xisnan (tmp_max) ? 0 : idx_j;
307 if (abs_max != 0.) 307 if (abs_max != 0.)
308 nel++; 308 nel++;
309 } 309 }
310 310
311 result = SparseComplexMatrix (1, nc, nel); 311 result = SparseComplexMatrix (1, nc, nel);
312 312
313 octave_idx_type ii = 0; 313 octave_idx_type ii = 0;
314 result.xcidx (0) = 0; 314 result.xcidx (0) = 0;
315 for (octave_idx_type j = 0; j < nc; j++) 315 for (octave_idx_type j = 0; j < nc; j++)
316 { 316 {
317 Complex tmp = elem (idx_arg(j), j); 317 Complex tmp = elem (idx_arg(j), j);
318 if (tmp != 0.) 318 if (tmp != 0.)
319 { 319 {
320 result.xdata (ii) = tmp; 320 result.xdata (ii) = tmp;
321 result.xridx (ii++) = 0; 321 result.xridx (ii++) = 0;
322 } 322 }
323 result.xcidx (j+1) = ii; 323 result.xcidx (j+1) = ii;
324 } 324 }
325 } 325 }
326 else 326 else
327 { 327 {
328 idx_arg.resize_fill (nr, 1, 0); 328 idx_arg.resize_fill (nr, 1, 0);
329 329
330 for (octave_idx_type i = cidx(0); i < cidx(1); i++) 330 for (octave_idx_type i = cidx(0); i < cidx(1); i++)
331 idx_arg.elem(ridx(i)) = -1; 331 idx_arg.elem(ridx(i)) = -1;
332 332
333 for (octave_idx_type j = 0; j < nc; j++) 333 for (octave_idx_type j = 0; j < nc; j++)
334 for (octave_idx_type i = 0; i < nr; i++) 334 for (octave_idx_type i = 0; i < nr; i++)
335 { 335 {
336 if (idx_arg.elem(i) != -1) 336 if (idx_arg.elem(i) != -1)
337 continue; 337 continue;
338 bool found = false; 338 bool found = false;
339 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++) 339 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++)
340 if (ridx(k) == i) 340 if (ridx(k) == i)
341 { 341 {
342 found = true; 342 found = true;
343 break; 343 break;
344 } 344 }
345 345
346 if (!found) 346 if (!found)
347 idx_arg.elem(i) = j; 347 idx_arg.elem(i) = j;
348 348
349 } 349 }
350 350
351 for (octave_idx_type j = 0; j < nc; j++) 351 for (octave_idx_type j = 0; j < nc; j++)
352 { 352 {
353 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 353 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
354 { 354 {
355 octave_idx_type ir = ridx (i); 355 octave_idx_type ir = ridx (i);
356 octave_idx_type ix = idx_arg.elem (ir); 356 octave_idx_type ix = idx_arg.elem (ir);
357 Complex tmp = data (i); 357 Complex tmp = data (i);
358 358
359 if (xisnan (tmp)) 359 if (xisnan (tmp))
360 continue; 360 continue;
361 else if (ix == -1 || std::abs(tmp) > std::abs(elem (ir, ix))) 361 else if (ix == -1 || std::abs(tmp) > std::abs(elem (ir, ix)))
362 idx_arg.elem (ir) = j; 362 idx_arg.elem (ir) = j;
363 } 363 }
364 } 364 }
365 365
366 octave_idx_type nel = 0; 366 octave_idx_type nel = 0;
367 for (octave_idx_type j = 0; j < nr; j++) 367 for (octave_idx_type j = 0; j < nr; j++)
368 if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.) 368 if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.)
369 nel++; 369 nel++;
370 370
371 result = SparseComplexMatrix (nr, 1, nel); 371 result = SparseComplexMatrix (nr, 1, nel);
372 372
373 octave_idx_type ii = 0; 373 octave_idx_type ii = 0;
374 result.xcidx (0) = 0; 374 result.xcidx (0) = 0;
375 result.xcidx (1) = nel; 375 result.xcidx (1) = nel;
376 for (octave_idx_type j = 0; j < nr; j++) 376 for (octave_idx_type j = 0; j < nr; j++)
377 { 377 {
378 if (idx_arg(j) == -1) 378 if (idx_arg(j) == -1)
379 { 379 {
380 idx_arg(j) = 0; 380 idx_arg(j) = 0;
381 result.xdata (ii) = Complex_NaN_result; 381 result.xdata (ii) = Complex_NaN_result;
382 result.xridx (ii++) = j; 382 result.xridx (ii++) = j;
383 } 383 }
384 else 384 else
385 { 385 {
386 Complex tmp = elem (j, idx_arg(j)); 386 Complex tmp = elem (j, idx_arg(j));
387 if (tmp != 0.) 387 if (tmp != 0.)
388 { 388 {
389 result.xdata (ii) = tmp; 389 result.xdata (ii) = tmp;
390 result.xridx (ii++) = j; 390 result.xridx (ii++) = j;
391 } 391 }
392 } 392 }
393 } 393 }
394 } 394 }
395 395
396 return result; 396 return result;
397 } 397 }
398 398
421 if (dim == 0) 421 if (dim == 0)
422 { 422 {
423 idx_arg.clear (1, nc); 423 idx_arg.clear (1, nc);
424 octave_idx_type nel = 0; 424 octave_idx_type nel = 0;
425 for (octave_idx_type j = 0; j < nc; j++) 425 for (octave_idx_type j = 0; j < nc; j++)
426 { 426 {
427 Complex tmp_min; 427 Complex tmp_min;
428 double abs_min = octave_NaN; 428 double abs_min = octave_NaN;
429 octave_idx_type idx_j = 0; 429 octave_idx_type idx_j = 0;
430 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 430 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
431 { 431 {
432 if (ridx(i) != idx_j) 432 if (ridx(i) != idx_j)
433 break; 433 break;
434 else 434 else
435 idx_j++; 435 idx_j++;
436 } 436 }
437 437
438 if (idx_j != nr) 438 if (idx_j != nr)
439 { 439 {
440 tmp_min = 0.; 440 tmp_min = 0.;
441 abs_min = 0.; 441 abs_min = 0.;
442 } 442 }
443 443
444 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 444 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
445 { 445 {
446 Complex tmp = data (i); 446 Complex tmp = data (i);
447 447
448 if (xisnan (tmp)) 448 if (xisnan (tmp))
449 continue; 449 continue;
450 450
451 double abs_tmp = std::abs (tmp); 451 double abs_tmp = std::abs (tmp);
452 452
453 if (xisnan (abs_min) || abs_tmp < abs_min) 453 if (xisnan (abs_min) || abs_tmp < abs_min)
454 { 454 {
455 idx_j = ridx (i); 455 idx_j = ridx (i);
456 tmp_min = tmp; 456 tmp_min = tmp;
457 abs_min = abs_tmp; 457 abs_min = abs_tmp;
458 } 458 }
459 } 459 }
460 460
461 idx_arg.elem (j) = xisnan (tmp_min) ? 0 : idx_j; 461 idx_arg.elem (j) = xisnan (tmp_min) ? 0 : idx_j;
462 if (abs_min != 0.) 462 if (abs_min != 0.)
463 nel++; 463 nel++;
464 } 464 }
465 465
466 result = SparseComplexMatrix (1, nc, nel); 466 result = SparseComplexMatrix (1, nc, nel);
467 467
468 octave_idx_type ii = 0; 468 octave_idx_type ii = 0;
469 result.xcidx (0) = 0; 469 result.xcidx (0) = 0;
470 for (octave_idx_type j = 0; j < nc; j++) 470 for (octave_idx_type j = 0; j < nc; j++)
471 { 471 {
472 Complex tmp = elem (idx_arg(j), j); 472 Complex tmp = elem (idx_arg(j), j);
473 if (tmp != 0.) 473 if (tmp != 0.)
474 { 474 {
475 result.xdata (ii) = tmp; 475 result.xdata (ii) = tmp;
476 result.xridx (ii++) = 0; 476 result.xridx (ii++) = 0;
477 } 477 }
478 result.xcidx (j+1) = ii; 478 result.xcidx (j+1) = ii;
479 } 479 }
480 } 480 }
481 else 481 else
482 { 482 {
483 idx_arg.resize_fill (nr, 1, 0); 483 idx_arg.resize_fill (nr, 1, 0);
484 484
485 for (octave_idx_type i = cidx(0); i < cidx(1); i++) 485 for (octave_idx_type i = cidx(0); i < cidx(1); i++)
486 idx_arg.elem(ridx(i)) = -1; 486 idx_arg.elem(ridx(i)) = -1;
487 487
488 for (octave_idx_type j = 0; j < nc; j++) 488 for (octave_idx_type j = 0; j < nc; j++)
489 for (octave_idx_type i = 0; i < nr; i++) 489 for (octave_idx_type i = 0; i < nr; i++)
490 { 490 {
491 if (idx_arg.elem(i) != -1) 491 if (idx_arg.elem(i) != -1)
492 continue; 492 continue;
493 bool found = false; 493 bool found = false;
494 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++) 494 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++)
495 if (ridx(k) == i) 495 if (ridx(k) == i)
496 { 496 {
497 found = true; 497 found = true;
498 break; 498 break;
499 } 499 }
500 500
501 if (!found) 501 if (!found)
502 idx_arg.elem(i) = j; 502 idx_arg.elem(i) = j;
503 503
504 } 504 }
505 505
506 for (octave_idx_type j = 0; j < nc; j++) 506 for (octave_idx_type j = 0; j < nc; j++)
507 { 507 {
508 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 508 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
509 { 509 {
510 octave_idx_type ir = ridx (i); 510 octave_idx_type ir = ridx (i);
511 octave_idx_type ix = idx_arg.elem (ir); 511 octave_idx_type ix = idx_arg.elem (ir);
512 Complex tmp = data (i); 512 Complex tmp = data (i);
513 513
514 if (xisnan (tmp)) 514 if (xisnan (tmp))
515 continue; 515 continue;
516 else if (ix == -1 || std::abs(tmp) < std::abs(elem (ir, ix))) 516 else if (ix == -1 || std::abs(tmp) < std::abs(elem (ir, ix)))
517 idx_arg.elem (ir) = j; 517 idx_arg.elem (ir) = j;
518 } 518 }
519 } 519 }
520 520
521 octave_idx_type nel = 0; 521 octave_idx_type nel = 0;
522 for (octave_idx_type j = 0; j < nr; j++) 522 for (octave_idx_type j = 0; j < nr; j++)
523 if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.) 523 if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.)
524 nel++; 524 nel++;
525 525
526 result = SparseComplexMatrix (nr, 1, nel); 526 result = SparseComplexMatrix (nr, 1, nel);
527 527
528 octave_idx_type ii = 0; 528 octave_idx_type ii = 0;
529 result.xcidx (0) = 0; 529 result.xcidx (0) = 0;
530 result.xcidx (1) = nel; 530 result.xcidx (1) = nel;
531 for (octave_idx_type j = 0; j < nr; j++) 531 for (octave_idx_type j = 0; j < nr; j++)
532 { 532 {
533 if (idx_arg(j) == -1) 533 if (idx_arg(j) == -1)
534 { 534 {
535 idx_arg(j) = 0; 535 idx_arg(j) = 0;
536 result.xdata (ii) = Complex_NaN_result; 536 result.xdata (ii) = Complex_NaN_result;
537 result.xridx (ii++) = j; 537 result.xridx (ii++) = j;
538 } 538 }
539 else 539 else
540 { 540 {
541 Complex tmp = elem (j, idx_arg(j)); 541 Complex tmp = elem (j, idx_arg(j));
542 if (tmp != 0.) 542 if (tmp != 0.)
543 { 543 {
544 result.xdata (ii) = tmp; 544 result.xdata (ii) = tmp;
545 result.xridx (ii++) = j; 545 result.xridx (ii++) = j;
546 } 546 }
547 } 547 }
548 } 548 }
549 } 549 }
550 550
551 return result; 551 return result;
552 } 552 }
553 553
612 return *this; 612 return *this;
613 } 613 }
614 614
615 SparseComplexMatrix 615 SparseComplexMatrix
616 SparseComplexMatrix::concat (const SparseComplexMatrix& rb, 616 SparseComplexMatrix::concat (const SparseComplexMatrix& rb,
617 const Array<octave_idx_type>& ra_idx) 617 const Array<octave_idx_type>& ra_idx)
618 { 618 {
619 // Don't use numel to avoid all possiblity of an overflow 619 // Don't use numel to avoid all possiblity of an overflow
620 if (rb.rows () > 0 && rb.cols () > 0) 620 if (rb.rows () > 0 && rb.cols () > 0)
621 insert (rb, ra_idx(0), ra_idx(1)); 621 insert (rb, ra_idx(0), ra_idx(1));
622 return *this; 622 return *this;
666 // retval.xcidx[1:nr] holds row entry *start* offsets for rows 0:(nr-1) 666 // retval.xcidx[1:nr] holds row entry *start* offsets for rows 0:(nr-1)
667 667
668 for (octave_idx_type j = 0; j < nc; j++) 668 for (octave_idx_type j = 0; j < nc; j++)
669 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++) 669 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++)
670 { 670 {
671 octave_idx_type q = retval.xcidx (ridx (k) + 1)++; 671 octave_idx_type q = retval.xcidx (ridx (k) + 1)++;
672 retval.xridx (q) = j; 672 retval.xridx (q) = j;
673 retval.xdata (q) = conj (data (k)); 673 retval.xdata (q) = conj (data (k));
674 } 674 }
675 assert (nnz () == retval.xcidx (nr)); 675 assert (nnz () == retval.xcidx (nr));
676 // retval.xcidx[1:nr] holds row entry *end* offsets for rows 0:(nr-1) 676 // retval.xcidx[1:nr] holds row entry *end* offsets for rows 0:(nr-1)
677 // and retval.xcidx[0:(nr-1)] holds their row entry *start* offsets 677 // and retval.xcidx[0:(nr-1)] holds their row entry *start* offsets
678 678
723 return inverse (mattype, info, rcond, 0, 0); 723 return inverse (mattype, info, rcond, 0, 0);
724 } 724 }
725 725
726 SparseComplexMatrix 726 SparseComplexMatrix
727 SparseComplexMatrix::dinverse (MatrixType &mattyp, octave_idx_type& info, 727 SparseComplexMatrix::dinverse (MatrixType &mattyp, octave_idx_type& info,
728 double& rcond, const bool, 728 double& rcond, const bool,
729 const bool calccond) const 729 const bool calccond) const
730 { 730 {
731 SparseComplexMatrix retval; 731 SparseComplexMatrix retval;
732 732
733 octave_idx_type nr = rows (); 733 octave_idx_type nr = rows ();
734 octave_idx_type nc = cols (); 734 octave_idx_type nc = cols ();
741 // Print spparms("spumoni") info if requested 741 // Print spparms("spumoni") info if requested
742 int typ = mattyp.type (); 742 int typ = mattyp.type ();
743 mattyp.info (); 743 mattyp.info ();
744 744
745 if (typ == MatrixType::Diagonal || 745 if (typ == MatrixType::Diagonal ||
746 typ == MatrixType::Permuted_Diagonal) 746 typ == MatrixType::Permuted_Diagonal)
747 { 747 {
748 if (typ == MatrixType::Permuted_Diagonal) 748 if (typ == MatrixType::Permuted_Diagonal)
749 retval = transpose(); 749 retval = transpose();
750 else 750 else
751 retval = *this; 751 retval = *this;
752 752
753 // Force make_unique to be called 753 // Force make_unique to be called
754 Complex *v = retval.data(); 754 Complex *v = retval.data();
755 755
756 if (calccond) 756 if (calccond)
757 { 757 {
758 double dmax = 0., dmin = octave_Inf; 758 double dmax = 0., dmin = octave_Inf;
759 for (octave_idx_type i = 0; i < nr; i++) 759 for (octave_idx_type i = 0; i < nr; i++)
760 { 760 {
761 double tmp = std::abs(v[i]); 761 double tmp = std::abs(v[i]);
762 if (tmp > dmax) 762 if (tmp > dmax)
763 dmax = tmp; 763 dmax = tmp;
764 if (tmp < dmin) 764 if (tmp < dmin)
765 dmin = tmp; 765 dmin = tmp;
766 } 766 }
767 rcond = dmin / dmax; 767 rcond = dmin / dmax;
768 } 768 }
769 769
770 for (octave_idx_type i = 0; i < nr; i++) 770 for (octave_idx_type i = 0; i < nr; i++)
771 v[i] = 1.0 / v[i]; 771 v[i] = 1.0 / v[i];
772 } 772 }
773 else 773 else
774 (*current_liboctave_error_handler) ("incorrect matrix type"); 774 (*current_liboctave_error_handler) ("incorrect matrix type");
775 } 775 }
776 776
777 return retval; 777 return retval;
778 } 778 }
779 779
780 SparseComplexMatrix 780 SparseComplexMatrix
781 SparseComplexMatrix::tinverse (MatrixType &mattyp, octave_idx_type& info, 781 SparseComplexMatrix::tinverse (MatrixType &mattyp, octave_idx_type& info,
782 double& rcond, const bool, 782 double& rcond, const bool,
783 const bool calccond) const 783 const bool calccond) const
784 { 784 {
785 SparseComplexMatrix retval; 785 SparseComplexMatrix retval;
786 786
787 octave_idx_type nr = rows (); 787 octave_idx_type nr = rows ();
788 octave_idx_type nc = cols (); 788 octave_idx_type nc = cols ();
795 // Print spparms("spumoni") info if requested 795 // Print spparms("spumoni") info if requested
796 int typ = mattyp.type (); 796 int typ = mattyp.type ();
797 mattyp.info (); 797 mattyp.info ();
798 798
799 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper || 799 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper ||
800 typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) 800 typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
801 { 801 {
802 double anorm = 0.; 802 double anorm = 0.;
803 double ainvnorm = 0.; 803 double ainvnorm = 0.;
804 804
805 if (calccond) 805 if (calccond)
806 { 806 {
807 // Calculate the 1-norm of matrix for rcond calculation 807 // Calculate the 1-norm of matrix for rcond calculation
808 for (octave_idx_type j = 0; j < nr; j++) 808 for (octave_idx_type j = 0; j < nr; j++)
809 { 809 {
810 double atmp = 0.; 810 double atmp = 0.;
811 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 811 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
812 atmp += std::abs(data(i)); 812 atmp += std::abs(data(i));
813 if (atmp > anorm) 813 if (atmp > anorm)
814 anorm = atmp; 814 anorm = atmp;
815 } 815 }
816 } 816 }
817 817
818 if (typ == MatrixType::Upper || typ == MatrixType::Lower) 818 if (typ == MatrixType::Upper || typ == MatrixType::Lower)
819 { 819 {
820 octave_idx_type nz = nnz (); 820 octave_idx_type nz = nnz ();
821 octave_idx_type cx = 0; 821 octave_idx_type cx = 0;
822 octave_idx_type nz2 = nz; 822 octave_idx_type nz2 = nz;
823 retval = SparseComplexMatrix (nr, nc, nz2); 823 retval = SparseComplexMatrix (nr, nc, nz2);
824 824
825 for (octave_idx_type i = 0; i < nr; i++) 825 for (octave_idx_type i = 0; i < nr; i++)
826 { 826 {
827 octave_quit (); 827 octave_quit ();
828 // place the 1 in the identity position 828 // place the 1 in the identity position
829 octave_idx_type cx_colstart = cx; 829 octave_idx_type cx_colstart = cx;
830 830
831 if (cx == nz2) 831 if (cx == nz2)
832 { 832 {
833 nz2 *= 2; 833 nz2 *= 2;
834 retval.change_capacity (nz2); 834 retval.change_capacity (nz2);
835 } 835 }
836 836
837 retval.xcidx(i) = cx; 837 retval.xcidx(i) = cx;
838 retval.xridx(cx) = i; 838 retval.xridx(cx) = i;
839 retval.xdata(cx) = 1.0; 839 retval.xdata(cx) = 1.0;
840 cx++; 840 cx++;
841 841
842 // iterate accross columns of input matrix 842 // iterate accross columns of input matrix
843 for (octave_idx_type j = i+1; j < nr; j++) 843 for (octave_idx_type j = i+1; j < nr; j++)
844 { 844 {
845 Complex v = 0.; 845 Complex v = 0.;
846 // iterate to calculate sum 846 // iterate to calculate sum
847 octave_idx_type colXp = retval.xcidx(i); 847 octave_idx_type colXp = retval.xcidx(i);
848 octave_idx_type colUp = cidx(j); 848 octave_idx_type colUp = cidx(j);
849 octave_idx_type rpX, rpU; 849 octave_idx_type rpX, rpU;
850 850
851 if (cidx(j) == cidx(j+1)) 851 if (cidx(j) == cidx(j+1))
852 { 852 {
853 (*current_liboctave_error_handler) 853 (*current_liboctave_error_handler)
854 ("division by zero"); 854 ("division by zero");
855 goto inverse_singular; 855 goto inverse_singular;
856 } 856 }
857 857
858 do 858 do
859 { 859 {
860 octave_quit (); 860 octave_quit ();
861 rpX = retval.xridx(colXp); 861 rpX = retval.xridx(colXp);
862 rpU = ridx(colUp); 862 rpU = ridx(colUp);
863 863
864 if (rpX < rpU) 864 if (rpX < rpU)
865 colXp++; 865 colXp++;
866 else if (rpX > rpU) 866 else if (rpX > rpU)
867 colUp++; 867 colUp++;
868 else 868 else
869 { 869 {
870 v -= retval.xdata(colXp) * data(colUp); 870 v -= retval.xdata(colXp) * data(colUp);
871 colXp++; 871 colXp++;
872 colUp++; 872 colUp++;
873 } 873 }
874 } while ((rpX<j) && (rpU<j) && 874 } while ((rpX<j) && (rpU<j) &&
875 (colXp<cx) && (colUp<nz)); 875 (colXp<cx) && (colUp<nz));
876 876
877 877
878 // get A(m,m) 878 // get A(m,m)
879 if (typ == MatrixType::Upper) 879 if (typ == MatrixType::Upper)
880 colUp = cidx(j+1) - 1; 880 colUp = cidx(j+1) - 1;
881 else 881 else
882 colUp = cidx(j); 882 colUp = cidx(j);
883 Complex pivot = data(colUp); 883 Complex pivot = data(colUp);
884 if (pivot == 0. || ridx(colUp) != j) 884 if (pivot == 0. || ridx(colUp) != j)
885 { 885 {
886 (*current_liboctave_error_handler) 886 (*current_liboctave_error_handler)
887 ("division by zero"); 887 ("division by zero");
888 goto inverse_singular; 888 goto inverse_singular;
889 } 889 }
890 890
891 if (v != 0.) 891 if (v != 0.)
892 { 892 {
893 if (cx == nz2) 893 if (cx == nz2)
894 { 894 {
895 nz2 *= 2; 895 nz2 *= 2;
896 retval.change_capacity (nz2); 896 retval.change_capacity (nz2);
897 } 897 }
898 898
899 retval.xridx(cx) = j; 899 retval.xridx(cx) = j;
900 retval.xdata(cx) = v / pivot; 900 retval.xdata(cx) = v / pivot;
901 cx++; 901 cx++;
902 } 902 }
903 } 903 }
904 904
905 // get A(m,m) 905 // get A(m,m)
906 octave_idx_type colUp; 906 octave_idx_type colUp;
907 if (typ == MatrixType::Upper) 907 if (typ == MatrixType::Upper)
908 colUp = cidx(i+1) - 1; 908 colUp = cidx(i+1) - 1;
909 else 909 else
910 colUp = cidx(i); 910 colUp = cidx(i);
911 Complex pivot = data(colUp); 911 Complex pivot = data(colUp);
912 if (pivot == 0. || ridx(colUp) != i) 912 if (pivot == 0. || ridx(colUp) != i)
913 { 913 {
914 (*current_liboctave_error_handler) ("division by zero"); 914 (*current_liboctave_error_handler) ("division by zero");
915 goto inverse_singular; 915 goto inverse_singular;
916 } 916 }
917 917
918 if (pivot != 1.0) 918 if (pivot != 1.0)
919 for (octave_idx_type j = cx_colstart; j < cx; j++) 919 for (octave_idx_type j = cx_colstart; j < cx; j++)
920 retval.xdata(j) /= pivot; 920 retval.xdata(j) /= pivot;
921 } 921 }
922 retval.xcidx(nr) = cx; 922 retval.xcidx(nr) = cx;
923 retval.maybe_compress (); 923 retval.maybe_compress ();
924 } 924 }
925 else 925 else
926 { 926 {
927 octave_idx_type nz = nnz (); 927 octave_idx_type nz = nnz ();
928 octave_idx_type cx = 0; 928 octave_idx_type cx = 0;
929 octave_idx_type nz2 = nz; 929 octave_idx_type nz2 = nz;
930 retval = SparseComplexMatrix (nr, nc, nz2); 930 retval = SparseComplexMatrix (nr, nc, nz2);
931 931
932 OCTAVE_LOCAL_BUFFER (Complex, work, nr); 932 OCTAVE_LOCAL_BUFFER (Complex, work, nr);
933 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nr); 933 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nr);
934 934
935 octave_idx_type *perm = mattyp.triangular_perm(); 935 octave_idx_type *perm = mattyp.triangular_perm();
936 if (typ == MatrixType::Permuted_Upper) 936 if (typ == MatrixType::Permuted_Upper)
937 { 937 {
938 for (octave_idx_type i = 0; i < nr; i++) 938 for (octave_idx_type i = 0; i < nr; i++)
939 rperm[perm[i]] = i; 939 rperm[perm[i]] = i;
940 } 940 }
941 else 941 else
942 { 942 {
943 for (octave_idx_type i = 0; i < nr; i++) 943 for (octave_idx_type i = 0; i < nr; i++)
944 rperm[i] = perm[i]; 944 rperm[i] = perm[i];
945 for (octave_idx_type i = 0; i < nr; i++) 945 for (octave_idx_type i = 0; i < nr; i++)
946 perm[rperm[i]] = i; 946 perm[rperm[i]] = i;
947 } 947 }
948 948
949 for (octave_idx_type i = 0; i < nr; i++) 949 for (octave_idx_type i = 0; i < nr; i++)
950 { 950 {
951 octave_quit (); 951 octave_quit ();
952 octave_idx_type iidx = rperm[i]; 952 octave_idx_type iidx = rperm[i];
953 953
954 for (octave_idx_type j = 0; j < nr; j++) 954 for (octave_idx_type j = 0; j < nr; j++)
955 work[j] = 0.; 955 work[j] = 0.;
956 956
957 // place the 1 in the identity position 957 // place the 1 in the identity position
958 work[iidx] = 1.0; 958 work[iidx] = 1.0;
959 959
960 // iterate accross columns of input matrix 960 // iterate accross columns of input matrix
961 for (octave_idx_type j = iidx+1; j < nr; j++) 961 for (octave_idx_type j = iidx+1; j < nr; j++)
962 { 962 {
963 Complex v = 0.; 963 Complex v = 0.;
964 octave_idx_type jidx = perm[j]; 964 octave_idx_type jidx = perm[j];
965 // iterate to calculate sum 965 // iterate to calculate sum
966 for (octave_idx_type k = cidx(jidx); 966 for (octave_idx_type k = cidx(jidx);
967 k < cidx(jidx+1); k++) 967 k < cidx(jidx+1); k++)
968 { 968 {
969 octave_quit (); 969 octave_quit ();
970 v -= work[ridx(k)] * data(k); 970 v -= work[ridx(k)] * data(k);
971 } 971 }
972 972
973 // get A(m,m) 973 // get A(m,m)
974 Complex pivot; 974 Complex pivot;
975 if (typ == MatrixType::Permuted_Upper) 975 if (typ == MatrixType::Permuted_Upper)
976 pivot = data(cidx(jidx+1) - 1); 976 pivot = data(cidx(jidx+1) - 1);
977 else 977 else
978 pivot = data(cidx(jidx)); 978 pivot = data(cidx(jidx));
979 if (pivot == 0.) 979 if (pivot == 0.)
980 { 980 {
981 (*current_liboctave_error_handler) 981 (*current_liboctave_error_handler)
982 ("division by zero"); 982 ("division by zero");
983 goto inverse_singular; 983 goto inverse_singular;
984 } 984 }
985 985
986 work[j] = v / pivot; 986 work[j] = v / pivot;
987 } 987 }
988 988
989 // get A(m,m) 989 // get A(m,m)
990 octave_idx_type colUp; 990 octave_idx_type colUp;
991 if (typ == MatrixType::Permuted_Upper) 991 if (typ == MatrixType::Permuted_Upper)
992 colUp = cidx(perm[iidx]+1) - 1; 992 colUp = cidx(perm[iidx]+1) - 1;
993 else 993 else
994 colUp = cidx(perm[iidx]); 994 colUp = cidx(perm[iidx]);
995 995
996 Complex pivot = data(colUp); 996 Complex pivot = data(colUp);
997 if (pivot == 0.) 997 if (pivot == 0.)
998 { 998 {
999 (*current_liboctave_error_handler) 999 (*current_liboctave_error_handler)
1000 ("division by zero"); 1000 ("division by zero");
1001 goto inverse_singular; 1001 goto inverse_singular;
1002 } 1002 }
1003 1003
1004 octave_idx_type new_cx = cx; 1004 octave_idx_type new_cx = cx;
1005 for (octave_idx_type j = iidx; j < nr; j++) 1005 for (octave_idx_type j = iidx; j < nr; j++)
1006 if (work[j] != 0.0) 1006 if (work[j] != 0.0)
1007 { 1007 {
1008 new_cx++; 1008 new_cx++;
1009 if (pivot != 1.0) 1009 if (pivot != 1.0)
1010 work[j] /= pivot; 1010 work[j] /= pivot;
1011 } 1011 }
1012 1012
1013 if (cx < new_cx) 1013 if (cx < new_cx)
1014 { 1014 {
1015 nz2 = (2*nz2 < new_cx ? new_cx : 2*nz2); 1015 nz2 = (2*nz2 < new_cx ? new_cx : 2*nz2);
1016 retval.change_capacity (nz2); 1016 retval.change_capacity (nz2);
1017 } 1017 }
1018 1018
1019 retval.xcidx(i) = cx; 1019 retval.xcidx(i) = cx;
1020 for (octave_idx_type j = iidx; j < nr; j++) 1020 for (octave_idx_type j = iidx; j < nr; j++)
1021 if (work[j] != 0.) 1021 if (work[j] != 0.)
1022 { 1022 {
1023 retval.xridx(cx) = j; 1023 retval.xridx(cx) = j;
1024 retval.xdata(cx++) = work[j]; 1024 retval.xdata(cx++) = work[j];
1025 } 1025 }
1026 } 1026 }
1027 1027
1028 retval.xcidx(nr) = cx; 1028 retval.xcidx(nr) = cx;
1029 retval.maybe_compress (); 1029 retval.maybe_compress ();
1030 } 1030 }
1031 1031
1032 if (calccond) 1032 if (calccond)
1033 { 1033 {
1034 // Calculate the 1-norm of inverse matrix for rcond calculation 1034 // Calculate the 1-norm of inverse matrix for rcond calculation
1035 for (octave_idx_type j = 0; j < nr; j++) 1035 for (octave_idx_type j = 0; j < nr; j++)
1036 { 1036 {
1037 double atmp = 0.; 1037 double atmp = 0.;
1038 for (octave_idx_type i = retval.cidx(j); 1038 for (octave_idx_type i = retval.cidx(j);
1039 i < retval.cidx(j+1); i++) 1039 i < retval.cidx(j+1); i++)
1040 atmp += std::abs(retval.data(i)); 1040 atmp += std::abs(retval.data(i));
1041 if (atmp > ainvnorm) 1041 if (atmp > ainvnorm)
1042 ainvnorm = atmp; 1042 ainvnorm = atmp;
1043 } 1043 }
1044 1044
1045 rcond = 1. / ainvnorm / anorm; 1045 rcond = 1. / ainvnorm / anorm;
1046 } 1046 }
1047 } 1047 }
1048 else 1048 else
1049 (*current_liboctave_error_handler) ("incorrect matrix type"); 1049 (*current_liboctave_error_handler) ("incorrect matrix type");
1050 } 1050 }
1051 1051
1052 return retval; 1052 return retval;
1053 1053
1054 inverse_singular: 1054 inverse_singular:
1055 return SparseComplexMatrix(); 1055 return SparseComplexMatrix();
1056 } 1056 }
1057 1057
1058 SparseComplexMatrix 1058 SparseComplexMatrix
1059 SparseComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info, 1059 SparseComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info,
1060 double& rcond, int, int calc_cond) const 1060 double& rcond, int, int calc_cond) const
1061 { 1061 {
1062 int typ = mattype.type (false); 1062 int typ = mattype.type (false);
1063 SparseComplexMatrix ret; 1063 SparseComplexMatrix ret;
1064 1064
1065 if (typ == MatrixType::Unknown) 1065 if (typ == MatrixType::Unknown)
1075 ret = transpose().tinverse (newtype, info, rcond, true, calc_cond); 1075 ret = transpose().tinverse (newtype, info, rcond, true, calc_cond);
1076 } 1076 }
1077 else 1077 else
1078 { 1078 {
1079 if (mattype.is_hermitian()) 1079 if (mattype.is_hermitian())
1080 { 1080 {
1081 MatrixType tmp_typ (MatrixType::Upper); 1081 MatrixType tmp_typ (MatrixType::Upper);
1082 SparseComplexCHOL fact (*this, info, false); 1082 SparseComplexCHOL fact (*this, info, false);
1083 rcond = fact.rcond(); 1083 rcond = fact.rcond();
1084 if (info == 0) 1084 if (info == 0)
1085 { 1085 {
1086 double rcond2; 1086 double rcond2;
1087 SparseMatrix Q = fact.Q(); 1087 SparseMatrix Q = fact.Q();
1088 SparseComplexMatrix InvL = fact.L().transpose(). 1088 SparseComplexMatrix InvL = fact.L().transpose().
1089 tinverse(tmp_typ, info, rcond2, true, false); 1089 tinverse(tmp_typ, info, rcond2, true, false);
1090 ret = Q * InvL.hermitian() * InvL * Q.transpose(); 1090 ret = Q * InvL.hermitian() * InvL * Q.transpose();
1091 } 1091 }
1092 else 1092 else
1093 { 1093 {
1094 // Matrix is either singular or not positive definite 1094 // Matrix is either singular or not positive definite
1095 mattype.mark_as_unsymmetric (); 1095 mattype.mark_as_unsymmetric ();
1096 typ = MatrixType::Full; 1096 typ = MatrixType::Full;
1097 } 1097 }
1098 } 1098 }
1099 1099
1100 if (!mattype.is_hermitian()) 1100 if (!mattype.is_hermitian())
1101 { 1101 {
1102 octave_idx_type n = rows(); 1102 octave_idx_type n = rows();
1103 ColumnVector Qinit(n); 1103 ColumnVector Qinit(n);
1104 for (octave_idx_type i = 0; i < n; i++) 1104 for (octave_idx_type i = 0; i < n; i++)
1105 Qinit(i) = i; 1105 Qinit(i) = i;
1106 1106
1107 MatrixType tmp_typ (MatrixType::Upper); 1107 MatrixType tmp_typ (MatrixType::Upper);
1108 SparseComplexLU fact (*this, Qinit, Matrix (), false, false); 1108 SparseComplexLU fact (*this, Qinit, Matrix (), false, false);
1109 rcond = fact.rcond(); 1109 rcond = fact.rcond();
1110 double rcond2; 1110 double rcond2;
1111 SparseComplexMatrix InvL = fact.L().transpose(). 1111 SparseComplexMatrix InvL = fact.L().transpose().
1112 tinverse(tmp_typ, info, rcond2, true, false); 1112 tinverse(tmp_typ, info, rcond2, true, false);
1113 SparseComplexMatrix InvU = fact.U(). 1113 SparseComplexMatrix InvU = fact.U().
1114 tinverse(tmp_typ, info, rcond2, true, false).transpose(); 1114 tinverse(tmp_typ, info, rcond2, true, false).transpose();
1115 ret = fact.Pc().transpose() * InvU * InvL * fact.Pr(); 1115 ret = fact.Pc().transpose() * InvU * InvL * fact.Pr();
1116 } 1116 }
1117 } 1117 }
1118 1118
1119 return ret; 1119 return ret;
1120 } 1120 }
1121 1121
1156 double *control = Control.fortran_vec (); 1156 double *control = Control.fortran_vec ();
1157 UMFPACK_ZNAME (defaults) (control); 1157 UMFPACK_ZNAME (defaults) (control);
1158 1158
1159 double tmp = octave_sparse_params::get_key ("spumoni"); 1159 double tmp = octave_sparse_params::get_key ("spumoni");
1160 if (!xisnan (tmp)) 1160 if (!xisnan (tmp))
1161 Control (UMFPACK_PRL) = tmp; 1161 Control (UMFPACK_PRL) = tmp;
1162 1162
1163 tmp = octave_sparse_params::get_key ("piv_tol"); 1163 tmp = octave_sparse_params::get_key ("piv_tol");
1164 if (!xisnan (tmp)) 1164 if (!xisnan (tmp))
1165 { 1165 {
1166 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; 1166 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
1167 Control (UMFPACK_PIVOT_TOLERANCE) = tmp; 1167 Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
1168 } 1168 }
1169 1169
1170 // Set whether we are allowed to modify Q or not 1170 // Set whether we are allowed to modify Q or not
1171 tmp = octave_sparse_params::get_key ("autoamd"); 1171 tmp = octave_sparse_params::get_key ("autoamd");
1172 if (!xisnan (tmp)) 1172 if (!xisnan (tmp))
1173 Control (UMFPACK_FIXQ) = tmp; 1173 Control (UMFPACK_FIXQ) = tmp;
1174 1174
1175 // Turn-off UMFPACK scaling for LU 1175 // Turn-off UMFPACK scaling for LU
1176 Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; 1176 Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;
1177 1177
1178 UMFPACK_ZNAME (report_control) (control); 1178 UMFPACK_ZNAME (report_control) (control);
1180 const octave_idx_type *Ap = cidx (); 1180 const octave_idx_type *Ap = cidx ();
1181 const octave_idx_type *Ai = ridx (); 1181 const octave_idx_type *Ai = ridx ();
1182 const Complex *Ax = data (); 1182 const Complex *Ax = data ();
1183 1183
1184 UMFPACK_ZNAME (report_matrix) (nr, nc, Ap, Ai, 1184 UMFPACK_ZNAME (report_matrix) (nr, nc, Ap, Ai,
1185 reinterpret_cast<const double *> (Ax), 1185 reinterpret_cast<const double *> (Ax),
1186 0, 1, control); 1186 0, 1, control);
1187 1187
1188 void *Symbolic; 1188 void *Symbolic;
1189 Matrix Info (1, UMFPACK_INFO); 1189 Matrix Info (1, UMFPACK_INFO);
1190 double *info = Info.fortran_vec (); 1190 double *info = Info.fortran_vec ();
1191 int status = UMFPACK_ZNAME (qsymbolic) 1191 int status = UMFPACK_ZNAME (qsymbolic)
1192 (nr, nc, Ap, Ai, reinterpret_cast<const double *> (Ax), 0, 1192 (nr, nc, Ap, Ai, reinterpret_cast<const double *> (Ax), 0,
1193 0, &Symbolic, control, info); 1193 0, &Symbolic, control, info);
1194 1194
1195 if (status < 0) 1195 if (status < 0)
1196 { 1196 {
1197 (*current_liboctave_error_handler) 1197 (*current_liboctave_error_handler)
1198 ("SparseComplexMatrix::determinant symbolic factorization failed"); 1198 ("SparseComplexMatrix::determinant symbolic factorization failed");
1199 1199
1200 UMFPACK_ZNAME (report_status) (control, status); 1200 UMFPACK_ZNAME (report_status) (control, status);
1201 UMFPACK_ZNAME (report_info) (control, info); 1201 UMFPACK_ZNAME (report_info) (control, info);
1202 1202
1203 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; 1203 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ;
1204 } 1204 }
1205 else 1205 else
1206 { 1206 {
1207 UMFPACK_ZNAME (report_symbolic) (Symbolic, control); 1207 UMFPACK_ZNAME (report_symbolic) (Symbolic, control);
1208 1208
1209 void *Numeric; 1209 void *Numeric;
1210 status 1210 status
1211 = UMFPACK_ZNAME (numeric) (Ap, Ai, 1211 = UMFPACK_ZNAME (numeric) (Ap, Ai,
1212 reinterpret_cast<const double *> (Ax), 1212 reinterpret_cast<const double *> (Ax),
1213 0, Symbolic, &Numeric, control, info) ; 1213 0, Symbolic, &Numeric, control, info) ;
1214 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; 1214 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ;
1215 1215
1216 rcond = Info (UMFPACK_RCOND); 1216 rcond = Info (UMFPACK_RCOND);
1217 1217
1218 if (status < 0) 1218 if (status < 0)
1219 { 1219 {
1220 (*current_liboctave_error_handler) 1220 (*current_liboctave_error_handler)
1221 ("SparseComplexMatrix::determinant numeric factorization failed"); 1221 ("SparseComplexMatrix::determinant numeric factorization failed");
1222 1222
1223 UMFPACK_ZNAME (report_status) (control, status); 1223 UMFPACK_ZNAME (report_status) (control, status);
1224 UMFPACK_ZNAME (report_info) (control, info); 1224 UMFPACK_ZNAME (report_info) (control, info);
1225 1225
1226 UMFPACK_ZNAME (free_numeric) (&Numeric); 1226 UMFPACK_ZNAME (free_numeric) (&Numeric);
1227 } 1227 }
1228 else 1228 else
1229 { 1229 {
1230 UMFPACK_ZNAME (report_numeric) (Numeric, control); 1230 UMFPACK_ZNAME (report_numeric) (Numeric, control);
1231 1231
1232 double c10[2], e10; 1232 double c10[2], e10;
1233 1233
1234 status = UMFPACK_ZNAME (get_determinant) (c10, 0, &e10, 1234 status = UMFPACK_ZNAME (get_determinant) (c10, 0, &e10,
1235 Numeric, info); 1235 Numeric, info);
1236 1236
1237 if (status < 0) 1237 if (status < 0)
1238 { 1238 {
1239 (*current_liboctave_error_handler) 1239 (*current_liboctave_error_handler)
1240 ("SparseComplexMatrix::determinant error calculating determinant"); 1240 ("SparseComplexMatrix::determinant error calculating determinant");
1241 1241
1242 UMFPACK_ZNAME (report_status) (control, status); 1242 UMFPACK_ZNAME (report_status) (control, status);
1243 UMFPACK_ZNAME (report_info) (control, info); 1243 UMFPACK_ZNAME (report_info) (control, info);
1244 } 1244 }
1245 else 1245 else
1246 retval = ComplexDET (Complex (c10[0], c10[1]), e10, 10); 1246 retval = ComplexDET (Complex (c10[0], c10[1]), e10, 10);
1247 1247
1248 UMFPACK_ZNAME (free_numeric) (&Numeric); 1248 UMFPACK_ZNAME (free_numeric) (&Numeric);
1249 } 1249 }
1250 } 1250 }
1251 } 1251 }
1252 #else 1252 #else
1253 (*current_liboctave_error_handler) ("UMFPACK not installed"); 1253 (*current_liboctave_error_handler) ("UMFPACK not installed");
1254 #endif 1254 #endif
1255 1255
1256 return retval; 1256 return retval;
1257 } 1257 }
1258 1258
1259 ComplexMatrix 1259 ComplexMatrix
1260 SparseComplexMatrix::dsolve (MatrixType &mattype, const Matrix& b, 1260 SparseComplexMatrix::dsolve (MatrixType &mattype, const Matrix& b,
1261 octave_idx_type& err, double& rcond, 1261 octave_idx_type& err, double& rcond,
1262 solve_singularity_handler, bool calc_cond) const 1262 solve_singularity_handler, bool calc_cond) const
1263 { 1263 {
1264 ComplexMatrix retval; 1264 ComplexMatrix retval;
1265 1265
1266 octave_idx_type nr = rows (); 1266 octave_idx_type nr = rows ();
1267 octave_idx_type nc = cols (); 1267 octave_idx_type nc = cols ();
1278 // Print spparms("spumoni") info if requested 1278 // Print spparms("spumoni") info if requested
1279 int typ = mattype.type (); 1279 int typ = mattype.type ();
1280 mattype.info (); 1280 mattype.info ();
1281 1281
1282 if (typ == MatrixType::Diagonal || 1282 if (typ == MatrixType::Diagonal ||
1283 typ == MatrixType::Permuted_Diagonal) 1283 typ == MatrixType::Permuted_Diagonal)
1284 { 1284 {
1285 retval.resize (nc, b.cols(), Complex(0.,0.)); 1285 retval.resize (nc, b.cols(), Complex(0.,0.));
1286 if (typ == MatrixType::Diagonal) 1286 if (typ == MatrixType::Diagonal)
1287 for (octave_idx_type j = 0; j < b.cols(); j++) 1287 for (octave_idx_type j = 0; j < b.cols(); j++)
1288 for (octave_idx_type i = 0; i < nm; i++) 1288 for (octave_idx_type i = 0; i < nm; i++)
1289 retval(i,j) = b(i,j) / data (i); 1289 retval(i,j) = b(i,j) / data (i);
1290 else 1290 else
1291 for (octave_idx_type j = 0; j < b.cols(); j++) 1291 for (octave_idx_type j = 0; j < b.cols(); j++)
1292 for (octave_idx_type k = 0; k < nc; k++) 1292 for (octave_idx_type k = 0; k < nc; k++)
1293 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 1293 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
1294 retval(k,j) = b(ridx(i),j) / data (i); 1294 retval(k,j) = b(ridx(i),j) / data (i);
1295 1295
1296 if (calc_cond) 1296 if (calc_cond)
1297 { 1297 {
1298 double dmax = 0., dmin = octave_Inf; 1298 double dmax = 0., dmin = octave_Inf;
1299 for (octave_idx_type i = 0; i < nm; i++) 1299 for (octave_idx_type i = 0; i < nm; i++)
1300 { 1300 {
1301 double tmp = std::abs(data(i)); 1301 double tmp = std::abs(data(i));
1302 if (tmp > dmax) 1302 if (tmp > dmax)
1303 dmax = tmp; 1303 dmax = tmp;
1304 if (tmp < dmin) 1304 if (tmp < dmin)
1305 dmin = tmp; 1305 dmin = tmp;
1306 } 1306 }
1307 rcond = dmin / dmax; 1307 rcond = dmin / dmax;
1308 } 1308 }
1309 else 1309 else
1310 rcond = 1.0; 1310 rcond = 1.0;
1311 } 1311 }
1312 else 1312 else
1313 (*current_liboctave_error_handler) ("incorrect matrix type"); 1313 (*current_liboctave_error_handler) ("incorrect matrix type");
1314 } 1314 }
1315 1315
1316 return retval; 1316 return retval;
1317 } 1317 }
1318 1318
1319 SparseComplexMatrix 1319 SparseComplexMatrix
1320 SparseComplexMatrix::dsolve (MatrixType &mattype, const SparseMatrix& b, 1320 SparseComplexMatrix::dsolve (MatrixType &mattype, const SparseMatrix& b,
1321 octave_idx_type& err, double& rcond, 1321 octave_idx_type& err, double& rcond,
1322 solve_singularity_handler, 1322 solve_singularity_handler,
1323 bool calc_cond) const 1323 bool calc_cond) const
1324 { 1324 {
1325 SparseComplexMatrix retval; 1325 SparseComplexMatrix retval;
1326 1326
1327 octave_idx_type nr = rows (); 1327 octave_idx_type nr = rows ();
1328 octave_idx_type nc = cols (); 1328 octave_idx_type nc = cols ();
1339 // Print spparms("spumoni") info if requested 1339 // Print spparms("spumoni") info if requested
1340 int typ = mattype.type (); 1340 int typ = mattype.type ();
1341 mattype.info (); 1341 mattype.info ();
1342 1342
1343 if (typ == MatrixType::Diagonal || 1343 if (typ == MatrixType::Diagonal ||
1344 typ == MatrixType::Permuted_Diagonal) 1344 typ == MatrixType::Permuted_Diagonal)
1345 { 1345 {
1346 octave_idx_type b_nc = b.cols (); 1346 octave_idx_type b_nc = b.cols ();
1347 octave_idx_type b_nz = b.nnz (); 1347 octave_idx_type b_nz = b.nnz ();
1348 retval = SparseComplexMatrix (nc, b_nc, b_nz); 1348 retval = SparseComplexMatrix (nc, b_nc, b_nz);
1349 1349
1350 retval.xcidx(0) = 0; 1350 retval.xcidx(0) = 0;
1351 octave_idx_type ii = 0; 1351 octave_idx_type ii = 0;
1352 if (typ == MatrixType::Diagonal) 1352 if (typ == MatrixType::Diagonal)
1353 for (octave_idx_type j = 0; j < b.cols(); j++) 1353 for (octave_idx_type j = 0; j < b.cols(); j++)
1354 { 1354 {
1355 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 1355 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
1356 { 1356 {
1357 if (b.ridx(i) >= nm) 1357 if (b.ridx(i) >= nm)
1358 break; 1358 break;
1359 retval.xridx (ii) = b.ridx(i); 1359 retval.xridx (ii) = b.ridx(i);
1360 retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); 1360 retval.xdata (ii++) = b.data(i) / data (b.ridx (i));
1361 } 1361 }
1362 retval.xcidx(j+1) = ii; 1362 retval.xcidx(j+1) = ii;
1363 } 1363 }
1364 else 1364 else
1365 for (octave_idx_type j = 0; j < b.cols(); j++) 1365 for (octave_idx_type j = 0; j < b.cols(); j++)
1366 { 1366 {
1367 for (octave_idx_type l = 0; l < nc; l++) 1367 for (octave_idx_type l = 0; l < nc; l++)
1368 for (octave_idx_type i = cidx(l); i < cidx(l+1); i++) 1368 for (octave_idx_type i = cidx(l); i < cidx(l+1); i++)
1369 { 1369 {
1370 bool found = false; 1370 bool found = false;
1371 octave_idx_type k; 1371 octave_idx_type k;
1372 for (k = b.cidx(j); k < b.cidx(j+1); k++) 1372 for (k = b.cidx(j); k < b.cidx(j+1); k++)
1373 if (ridx(i) == b.ridx(k)) 1373 if (ridx(i) == b.ridx(k))
1374 { 1374 {
1375 found = true; 1375 found = true;
1376 break; 1376 break;
1377 } 1377 }
1378 if (found) 1378 if (found)
1379 { 1379 {
1380 retval.xridx (ii) = l; 1380 retval.xridx (ii) = l;
1381 retval.xdata (ii++) = b.data(k) / data (i); 1381 retval.xdata (ii++) = b.data(k) / data (i);
1382 } 1382 }
1383 } 1383 }
1384 retval.xcidx(j+1) = ii; 1384 retval.xcidx(j+1) = ii;
1385 } 1385 }
1386 1386
1387 if (calc_cond) 1387 if (calc_cond)
1388 { 1388 {
1389 double dmax = 0., dmin = octave_Inf; 1389 double dmax = 0., dmin = octave_Inf;
1390 for (octave_idx_type i = 0; i < nm; i++) 1390 for (octave_idx_type i = 0; i < nm; i++)
1391 { 1391 {
1392 double tmp = std::abs(data(i)); 1392 double tmp = std::abs(data(i));
1393 if (tmp > dmax) 1393 if (tmp > dmax)
1394 dmax = tmp; 1394 dmax = tmp;
1395 if (tmp < dmin) 1395 if (tmp < dmin)
1396 dmin = tmp; 1396 dmin = tmp;
1397 } 1397 }
1398 rcond = dmin / dmax; 1398 rcond = dmin / dmax;
1399 } 1399 }
1400 else 1400 else
1401 rcond = 1.0; 1401 rcond = 1.0;
1402 } 1402 }
1403 else 1403 else
1404 (*current_liboctave_error_handler) ("incorrect matrix type"); 1404 (*current_liboctave_error_handler) ("incorrect matrix type");
1405 } 1405 }
1406 1406
1407 return retval; 1407 return retval;
1408 } 1408 }
1409 1409
1410 ComplexMatrix 1410 ComplexMatrix
1411 SparseComplexMatrix::dsolve (MatrixType &mattype, const ComplexMatrix& b, 1411 SparseComplexMatrix::dsolve (MatrixType &mattype, const ComplexMatrix& b,
1412 octave_idx_type& err, double& rcond, 1412 octave_idx_type& err, double& rcond,
1413 solve_singularity_handler, 1413 solve_singularity_handler,
1414 bool calc_cond) const 1414 bool calc_cond) const
1415 { 1415 {
1416 ComplexMatrix retval; 1416 ComplexMatrix retval;
1417 1417
1418 octave_idx_type nr = rows (); 1418 octave_idx_type nr = rows ();
1419 octave_idx_type nc = cols (); 1419 octave_idx_type nc = cols ();
1430 // Print spparms("spumoni") info if requested 1430 // Print spparms("spumoni") info if requested
1431 int typ = mattype.type (); 1431 int typ = mattype.type ();
1432 mattype.info (); 1432 mattype.info ();
1433 1433
1434 if (typ == MatrixType::Diagonal || 1434 if (typ == MatrixType::Diagonal ||
1435 typ == MatrixType::Permuted_Diagonal) 1435 typ == MatrixType::Permuted_Diagonal)
1436 { 1436 {
1437 retval.resize (nc, b.cols(), Complex(0.,0.)); 1437 retval.resize (nc, b.cols(), Complex(0.,0.));
1438 if (typ == MatrixType::Diagonal) 1438 if (typ == MatrixType::Diagonal)
1439 for (octave_idx_type j = 0; j < b.cols(); j++) 1439 for (octave_idx_type j = 0; j < b.cols(); j++)
1440 for (octave_idx_type i = 0; i < nm; i++) 1440 for (octave_idx_type i = 0; i < nm; i++)
1441 retval(i,j) = b(i,j) / data (i); 1441 retval(i,j) = b(i,j) / data (i);
1442 else 1442 else
1443 for (octave_idx_type j = 0; j < b.cols(); j++) 1443 for (octave_idx_type j = 0; j < b.cols(); j++)
1444 for (octave_idx_type k = 0; k < nc; k++) 1444 for (octave_idx_type k = 0; k < nc; k++)
1445 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 1445 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
1446 retval(k,j) = b(ridx(i),j) / data (i); 1446 retval(k,j) = b(ridx(i),j) / data (i);
1447 1447
1448 if (calc_cond) 1448 if (calc_cond)
1449 { 1449 {
1450 double dmax = 0., dmin = octave_Inf; 1450 double dmax = 0., dmin = octave_Inf;
1451 for (octave_idx_type i = 0; i < nr; i++) 1451 for (octave_idx_type i = 0; i < nr; i++)
1452 { 1452 {
1453 double tmp = std::abs(data(i)); 1453 double tmp = std::abs(data(i));
1454 if (tmp > dmax) 1454 if (tmp > dmax)
1455 dmax = tmp; 1455 dmax = tmp;
1456 if (tmp < dmin) 1456 if (tmp < dmin)
1457 dmin = tmp; 1457 dmin = tmp;
1458 } 1458 }
1459 rcond = dmin / dmax; 1459 rcond = dmin / dmax;
1460 } 1460 }
1461 else 1461 else
1462 rcond = 1.0; 1462 rcond = 1.0;
1463 } 1463 }
1464 else 1464 else
1465 (*current_liboctave_error_handler) ("incorrect matrix type"); 1465 (*current_liboctave_error_handler) ("incorrect matrix type");
1466 } 1466 }
1467 1467
1468 return retval; 1468 return retval;
1469 } 1469 }
1470 1470
1471 SparseComplexMatrix 1471 SparseComplexMatrix
1472 SparseComplexMatrix::dsolve (MatrixType &mattype, const SparseComplexMatrix& b, 1472 SparseComplexMatrix::dsolve (MatrixType &mattype, const SparseComplexMatrix& b,
1473 octave_idx_type& err, double& rcond, 1473 octave_idx_type& err, double& rcond,
1474 solve_singularity_handler, 1474 solve_singularity_handler,
1475 bool calc_cond) const 1475 bool calc_cond) const
1476 { 1476 {
1477 SparseComplexMatrix retval; 1477 SparseComplexMatrix retval;
1478 1478
1479 octave_idx_type nr = rows (); 1479 octave_idx_type nr = rows ();
1480 octave_idx_type nc = cols (); 1480 octave_idx_type nc = cols ();
1491 // Print spparms("spumoni") info if requested 1491 // Print spparms("spumoni") info if requested
1492 int typ = mattype.type (); 1492 int typ = mattype.type ();
1493 mattype.info (); 1493 mattype.info ();
1494 1494
1495 if (typ == MatrixType::Diagonal || 1495 if (typ == MatrixType::Diagonal ||
1496 typ == MatrixType::Permuted_Diagonal) 1496 typ == MatrixType::Permuted_Diagonal)
1497 { 1497 {
1498 octave_idx_type b_nc = b.cols (); 1498 octave_idx_type b_nc = b.cols ();
1499 octave_idx_type b_nz = b.nnz (); 1499 octave_idx_type b_nz = b.nnz ();
1500 retval = SparseComplexMatrix (nc, b_nc, b_nz); 1500 retval = SparseComplexMatrix (nc, b_nc, b_nz);
1501 1501
1502 retval.xcidx(0) = 0; 1502 retval.xcidx(0) = 0;
1503 octave_idx_type ii = 0; 1503 octave_idx_type ii = 0;
1504 if (typ == MatrixType::Diagonal) 1504 if (typ == MatrixType::Diagonal)
1505 for (octave_idx_type j = 0; j < b.cols(); j++) 1505 for (octave_idx_type j = 0; j < b.cols(); j++)
1506 { 1506 {
1507 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 1507 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
1508 { 1508 {
1509 if (b.ridx(i) >= nm) 1509 if (b.ridx(i) >= nm)
1510 break; 1510 break;
1511 retval.xridx (ii) = b.ridx(i); 1511 retval.xridx (ii) = b.ridx(i);
1512 retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); 1512 retval.xdata (ii++) = b.data(i) / data (b.ridx (i));
1513 } 1513 }
1514 retval.xcidx(j+1) = ii; 1514 retval.xcidx(j+1) = ii;
1515 } 1515 }
1516 else 1516 else
1517 for (octave_idx_type j = 0; j < b.cols(); j++) 1517 for (octave_idx_type j = 0; j < b.cols(); j++)
1518 { 1518 {
1519 for (octave_idx_type l = 0; l < nc; l++) 1519 for (octave_idx_type l = 0; l < nc; l++)
1520 for (octave_idx_type i = cidx(l); i < cidx(l+1); i++) 1520 for (octave_idx_type i = cidx(l); i < cidx(l+1); i++)
1521 { 1521 {
1522 bool found = false; 1522 bool found = false;
1523 octave_idx_type k; 1523 octave_idx_type k;
1524 for (k = b.cidx(j); k < b.cidx(j+1); k++) 1524 for (k = b.cidx(j); k < b.cidx(j+1); k++)
1525 if (ridx(i) == b.ridx(k)) 1525 if (ridx(i) == b.ridx(k))
1526 { 1526 {
1527 found = true; 1527 found = true;
1528 break; 1528 break;
1529 } 1529 }
1530 if (found) 1530 if (found)
1531 { 1531 {
1532 retval.xridx (ii) = l; 1532 retval.xridx (ii) = l;
1533 retval.xdata (ii++) = b.data(k) / data (i); 1533 retval.xdata (ii++) = b.data(k) / data (i);
1534 } 1534 }
1535 } 1535 }
1536 retval.xcidx(j+1) = ii; 1536 retval.xcidx(j+1) = ii;
1537 } 1537 }
1538 1538
1539 if (calc_cond) 1539 if (calc_cond)
1540 { 1540 {
1541 double dmax = 0., dmin = octave_Inf; 1541 double dmax = 0., dmin = octave_Inf;
1542 for (octave_idx_type i = 0; i < nm; i++) 1542 for (octave_idx_type i = 0; i < nm; i++)
1543 { 1543 {
1544 double tmp = std::abs(data(i)); 1544 double tmp = std::abs(data(i));
1545 if (tmp > dmax) 1545 if (tmp > dmax)
1546 dmax = tmp; 1546 dmax = tmp;
1547 if (tmp < dmin) 1547 if (tmp < dmin)
1548 dmin = tmp; 1548 dmin = tmp;
1549 } 1549 }
1550 rcond = dmin / dmax; 1550 rcond = dmin / dmax;
1551 } 1551 }
1552 else 1552 else
1553 rcond = 1.0; 1553 rcond = 1.0;
1554 } 1554 }
1555 else 1555 else
1556 (*current_liboctave_error_handler) ("incorrect matrix type"); 1556 (*current_liboctave_error_handler) ("incorrect matrix type");
1557 } 1557 }
1558 1558
1559 return retval; 1559 return retval;
1560 } 1560 }
1561 1561
1562 ComplexMatrix 1562 ComplexMatrix
1563 SparseComplexMatrix::utsolve (MatrixType &mattype, const Matrix& b, 1563 SparseComplexMatrix::utsolve (MatrixType &mattype, const Matrix& b,
1564 octave_idx_type& err, double& rcond, 1564 octave_idx_type& err, double& rcond,
1565 solve_singularity_handler sing_handler, 1565 solve_singularity_handler sing_handler,
1566 bool calc_cond) const 1566 bool calc_cond) const
1567 { 1567 {
1568 ComplexMatrix retval; 1568 ComplexMatrix retval;
1569 1569
1570 octave_idx_type nr = rows (); 1570 octave_idx_type nr = rows ();
1571 octave_idx_type nc = cols (); 1571 octave_idx_type nc = cols ();
1582 // Print spparms("spumoni") info if requested 1582 // Print spparms("spumoni") info if requested
1583 int typ = mattype.type (); 1583 int typ = mattype.type ();
1584 mattype.info (); 1584 mattype.info ();
1585 1585
1586 if (typ == MatrixType::Permuted_Upper || 1586 if (typ == MatrixType::Permuted_Upper ||
1587 typ == MatrixType::Upper) 1587 typ == MatrixType::Upper)
1588 { 1588 {
1589 double anorm = 0.; 1589 double anorm = 0.;
1590 double ainvnorm = 0.; 1590 double ainvnorm = 0.;
1591 octave_idx_type b_nc = b.cols (); 1591 octave_idx_type b_nc = b.cols ();
1592 rcond = 1.; 1592 rcond = 1.;
1593 1593
1594 if (calc_cond) 1594 if (calc_cond)
1595 { 1595 {
1596 // Calculate the 1-norm of matrix for rcond calculation 1596 // Calculate the 1-norm of matrix for rcond calculation
1597 for (octave_idx_type j = 0; j < nc; j++) 1597 for (octave_idx_type j = 0; j < nc; j++)
1598 { 1598 {
1599 double atmp = 0.; 1599 double atmp = 0.;
1600 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 1600 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
1601 atmp += std::abs(data(i)); 1601 atmp += std::abs(data(i));
1602 if (atmp > anorm) 1602 if (atmp > anorm)
1603 anorm = atmp; 1603 anorm = atmp;
1604 } 1604 }
1605 } 1605 }
1606 1606
1607 if (typ == MatrixType::Permuted_Upper) 1607 if (typ == MatrixType::Permuted_Upper)
1608 { 1608 {
1609 retval.resize (nc, b_nc); 1609 retval.resize (nc, b_nc);
1610 octave_idx_type *perm = mattype.triangular_perm (); 1610 octave_idx_type *perm = mattype.triangular_perm ();
1611 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 1611 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
1612 1612
1613 for (octave_idx_type j = 0; j < b_nc; j++) 1613 for (octave_idx_type j = 0; j < b_nc; j++)
1614 { 1614 {
1615 for (octave_idx_type i = 0; i < nr; i++) 1615 for (octave_idx_type i = 0; i < nr; i++)
1616 work[i] = b(i,j); 1616 work[i] = b(i,j);
1617 for (octave_idx_type i = nr; i < nc; i++) 1617 for (octave_idx_type i = nr; i < nc; i++)
1618 work[i] = 0.; 1618 work[i] = 0.;
1619 1619
1620 for (octave_idx_type k = nc-1; k >= 0; k--) 1620 for (octave_idx_type k = nc-1; k >= 0; k--)
1621 { 1621 {
1622 octave_idx_type kidx = perm[k]; 1622 octave_idx_type kidx = perm[k];
1623 1623
1624 if (work[k] != 0.) 1624 if (work[k] != 0.)
1625 { 1625 {
1626 if (ridx(cidx(kidx+1)-1) != k || 1626 if (ridx(cidx(kidx+1)-1) != k ||
1627 data(cidx(kidx+1)-1) == 0.) 1627 data(cidx(kidx+1)-1) == 0.)
1628 { 1628 {
1629 err = -2; 1629 err = -2;
1630 goto triangular_error; 1630 goto triangular_error;
1631 } 1631 }
1632 1632
1633 Complex tmp = work[k] / data(cidx(kidx+1)-1); 1633 Complex tmp = work[k] / data(cidx(kidx+1)-1);
1634 work[k] = tmp; 1634 work[k] = tmp;
1635 for (octave_idx_type i = cidx(kidx); 1635 for (octave_idx_type i = cidx(kidx);
1636 i < cidx(kidx+1)-1; i++) 1636 i < cidx(kidx+1)-1; i++)
1637 { 1637 {
1638 octave_idx_type iidx = ridx(i); 1638 octave_idx_type iidx = ridx(i);
1639 work[iidx] = work[iidx] - tmp * data(i); 1639 work[iidx] = work[iidx] - tmp * data(i);
1640 } 1640 }
1641 } 1641 }
1642 } 1642 }
1643 1643
1644 for (octave_idx_type i = 0; i < nc; i++) 1644 for (octave_idx_type i = 0; i < nc; i++)
1645 retval (perm[i], j) = work[i]; 1645 retval (perm[i], j) = work[i];
1646 } 1646 }
1647 1647
1648 if (calc_cond) 1648 if (calc_cond)
1649 { 1649 {
1650 // Calculation of 1-norm of inv(*this) 1650 // Calculation of 1-norm of inv(*this)
1651 for (octave_idx_type i = 0; i < nm; i++) 1651 for (octave_idx_type i = 0; i < nm; i++)
1652 work[i] = 0.; 1652 work[i] = 0.;
1653 1653
1654 for (octave_idx_type j = 0; j < nr; j++) 1654 for (octave_idx_type j = 0; j < nr; j++)
1655 { 1655 {
1656 work[j] = 1.; 1656 work[j] = 1.;
1657 1657
1658 for (octave_idx_type k = j; k >= 0; k--) 1658 for (octave_idx_type k = j; k >= 0; k--)
1659 { 1659 {
1660 octave_idx_type iidx = perm[k]; 1660 octave_idx_type iidx = perm[k];
1661 1661
1662 if (work[k] != 0.) 1662 if (work[k] != 0.)
1663 { 1663 {
1664 Complex tmp = work[k] / data(cidx(iidx+1)-1); 1664 Complex tmp = work[k] / data(cidx(iidx+1)-1);
1665 work[k] = tmp; 1665 work[k] = tmp;
1666 for (octave_idx_type i = cidx(iidx); 1666 for (octave_idx_type i = cidx(iidx);
1667 i < cidx(iidx+1)-1; i++) 1667 i < cidx(iidx+1)-1; i++)
1668 { 1668 {
1669 octave_idx_type idx2 = ridx(i); 1669 octave_idx_type idx2 = ridx(i);
1670 work[idx2] = work[idx2] - tmp * data(i); 1670 work[idx2] = work[idx2] - tmp * data(i);
1671 } 1671 }
1672 } 1672 }
1673 } 1673 }
1674 double atmp = 0; 1674 double atmp = 0;
1675 for (octave_idx_type i = 0; i < j+1; i++) 1675 for (octave_idx_type i = 0; i < j+1; i++)
1676 { 1676 {
1677 atmp += std::abs(work[i]); 1677 atmp += std::abs(work[i]);
1678 work[i] = 0.; 1678 work[i] = 0.;
1679 } 1679 }
1680 if (atmp > ainvnorm) 1680 if (atmp > ainvnorm)
1681 ainvnorm = atmp; 1681 ainvnorm = atmp;
1682 } 1682 }
1683 rcond = 1. / ainvnorm / anorm; 1683 rcond = 1. / ainvnorm / anorm;
1684 } 1684 }
1685 } 1685 }
1686 else 1686 else
1687 { 1687 {
1688 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 1688 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
1689 retval.resize (nc, b_nc); 1689 retval.resize (nc, b_nc);
1690 1690
1691 for (octave_idx_type j = 0; j < b_nc; j++) 1691 for (octave_idx_type j = 0; j < b_nc; j++)
1692 { 1692 {
1693 for (octave_idx_type i = 0; i < nr; i++) 1693 for (octave_idx_type i = 0; i < nr; i++)
1694 work[i] = b(i,j); 1694 work[i] = b(i,j);
1695 for (octave_idx_type i = nr; i < nc; i++) 1695 for (octave_idx_type i = nr; i < nc; i++)
1696 work[i] = 0.; 1696 work[i] = 0.;
1697 1697
1698 for (octave_idx_type k = nc-1; k >= 0; k--) 1698 for (octave_idx_type k = nc-1; k >= 0; k--)
1699 { 1699 {
1700 if (work[k] != 0.) 1700 if (work[k] != 0.)
1701 { 1701 {
1702 if (ridx(cidx(k+1)-1) != k || 1702 if (ridx(cidx(k+1)-1) != k ||
1703 data(cidx(k+1)-1) == 0.) 1703 data(cidx(k+1)-1) == 0.)
1704 { 1704 {
1705 err = -2; 1705 err = -2;
1706 goto triangular_error; 1706 goto triangular_error;
1707 } 1707 }
1708 1708
1709 Complex tmp = work[k] / data(cidx(k+1)-1); 1709 Complex tmp = work[k] / data(cidx(k+1)-1);
1710 work[k] = tmp; 1710 work[k] = tmp;
1711 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) 1711 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++)
1712 { 1712 {
1713 octave_idx_type iidx = ridx(i); 1713 octave_idx_type iidx = ridx(i);
1714 work[iidx] = work[iidx] - tmp * data(i); 1714 work[iidx] = work[iidx] - tmp * data(i);
1715 } 1715 }
1716 } 1716 }
1717 } 1717 }
1718 1718
1719 for (octave_idx_type i = 0; i < nc; i++) 1719 for (octave_idx_type i = 0; i < nc; i++)
1720 retval.xelem (i, j) = work[i]; 1720 retval.xelem (i, j) = work[i];
1721 } 1721 }
1722 1722
1723 if (calc_cond) 1723 if (calc_cond)
1724 { 1724 {
1725 // Calculation of 1-norm of inv(*this) 1725 // Calculation of 1-norm of inv(*this)
1726 for (octave_idx_type i = 0; i < nm; i++) 1726 for (octave_idx_type i = 0; i < nm; i++)
1727 work[i] = 0.; 1727 work[i] = 0.;
1728 1728
1729 for (octave_idx_type j = 0; j < nr; j++) 1729 for (octave_idx_type j = 0; j < nr; j++)
1730 { 1730 {
1731 work[j] = 1.; 1731 work[j] = 1.;
1732 1732
1733 for (octave_idx_type k = j; k >= 0; k--) 1733 for (octave_idx_type k = j; k >= 0; k--)
1734 { 1734 {
1735 if (work[k] != 0.) 1735 if (work[k] != 0.)
1736 { 1736 {
1737 Complex tmp = work[k] / data(cidx(k+1)-1); 1737 Complex tmp = work[k] / data(cidx(k+1)-1);
1738 work[k] = tmp; 1738 work[k] = tmp;
1739 for (octave_idx_type i = cidx(k); 1739 for (octave_idx_type i = cidx(k);
1740 i < cidx(k+1)-1; i++) 1740 i < cidx(k+1)-1; i++)
1741 { 1741 {
1742 octave_idx_type iidx = ridx(i); 1742 octave_idx_type iidx = ridx(i);
1743 work[iidx] = work[iidx] - tmp * data(i); 1743 work[iidx] = work[iidx] - tmp * data(i);
1744 } 1744 }
1745 } 1745 }
1746 } 1746 }
1747 double atmp = 0; 1747 double atmp = 0;
1748 for (octave_idx_type i = 0; i < j+1; i++) 1748 for (octave_idx_type i = 0; i < j+1; i++)
1749 { 1749 {
1750 atmp += std::abs(work[i]); 1750 atmp += std::abs(work[i]);
1751 work[i] = 0.; 1751 work[i] = 0.;
1752 } 1752 }
1753 if (atmp > ainvnorm) 1753 if (atmp > ainvnorm)
1754 ainvnorm = atmp; 1754 ainvnorm = atmp;
1755 } 1755 }
1756 rcond = 1. / ainvnorm / anorm; 1756 rcond = 1. / ainvnorm / anorm;
1757 } 1757 }
1758 } 1758 }
1759 1759
1760 triangular_error: 1760 triangular_error:
1761 if (err != 0) 1761 if (err != 0)
1762 { 1762 {
1763 if (sing_handler) 1763 if (sing_handler)
1764 { 1764 {
1765 sing_handler (rcond); 1765 sing_handler (rcond);
1766 mattype.mark_as_rectangular (); 1766 mattype.mark_as_rectangular ();
1767 } 1767 }
1768 else 1768 else
1769 (*current_liboctave_error_handler) 1769 (*current_liboctave_error_handler)
1770 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 1770 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
1771 rcond); 1771 rcond);
1772 } 1772 }
1773 1773
1774 volatile double rcond_plus_one = rcond + 1.0; 1774 volatile double rcond_plus_one = rcond + 1.0;
1775 1775
1776 if (rcond_plus_one == 1.0 || xisnan (rcond)) 1776 if (rcond_plus_one == 1.0 || xisnan (rcond))
1777 { 1777 {
1778 err = -2; 1778 err = -2;
1779 1779
1780 if (sing_handler) 1780 if (sing_handler)
1781 { 1781 {
1782 sing_handler (rcond); 1782 sing_handler (rcond);
1783 mattype.mark_as_rectangular (); 1783 mattype.mark_as_rectangular ();
1784 } 1784 }
1785 else 1785 else
1786 (*current_liboctave_error_handler) 1786 (*current_liboctave_error_handler)
1787 ("matrix singular to machine precision, rcond = %g", 1787 ("matrix singular to machine precision, rcond = %g",
1788 rcond); 1788 rcond);
1789 } 1789 }
1790 } 1790 }
1791 else 1791 else
1792 (*current_liboctave_error_handler) ("incorrect matrix type"); 1792 (*current_liboctave_error_handler) ("incorrect matrix type");
1793 } 1793 }
1794 1794
1795 return retval; 1795 return retval;
1796 } 1796 }
1797 1797
1798 SparseComplexMatrix 1798 SparseComplexMatrix
1799 SparseComplexMatrix::utsolve (MatrixType &mattype, const SparseMatrix& b, 1799 SparseComplexMatrix::utsolve (MatrixType &mattype, const SparseMatrix& b,
1800 octave_idx_type& err, double& rcond, 1800 octave_idx_type& err, double& rcond,
1801 solve_singularity_handler sing_handler, 1801 solve_singularity_handler sing_handler,
1802 bool calc_cond) const 1802 bool calc_cond) const
1803 { 1803 {
1804 SparseComplexMatrix retval; 1804 SparseComplexMatrix retval;
1805 1805
1806 octave_idx_type nr = rows (); 1806 octave_idx_type nr = rows ();
1807 octave_idx_type nc = cols (); 1807 octave_idx_type nc = cols ();
1818 // Print spparms("spumoni") info if requested 1818 // Print spparms("spumoni") info if requested
1819 int typ = mattype.type (); 1819 int typ = mattype.type ();
1820 mattype.info (); 1820 mattype.info ();
1821 1821
1822 if (typ == MatrixType::Permuted_Upper || 1822 if (typ == MatrixType::Permuted_Upper ||
1823 typ == MatrixType::Upper) 1823 typ == MatrixType::Upper)
1824 { 1824 {
1825 double anorm = 0.; 1825 double anorm = 0.;
1826 double ainvnorm = 0.; 1826 double ainvnorm = 0.;
1827 rcond = 1.; 1827 rcond = 1.;
1828 1828
1829 if (calc_cond) 1829 if (calc_cond)
1830 { 1830 {
1831 // Calculate the 1-norm of matrix for rcond calculation 1831 // Calculate the 1-norm of matrix for rcond calculation
1832 for (octave_idx_type j = 0; j < nc; j++) 1832 for (octave_idx_type j = 0; j < nc; j++)
1833 { 1833 {
1834 double atmp = 0.; 1834 double atmp = 0.;
1835 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 1835 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
1836 atmp += std::abs(data(i)); 1836 atmp += std::abs(data(i));
1837 if (atmp > anorm) 1837 if (atmp > anorm)
1838 anorm = atmp; 1838 anorm = atmp;
1839 } 1839 }
1840 } 1840 }
1841 1841
1842 octave_idx_type b_nc = b.cols (); 1842 octave_idx_type b_nc = b.cols ();
1843 octave_idx_type b_nz = b.nnz (); 1843 octave_idx_type b_nz = b.nnz ();
1844 retval = SparseComplexMatrix (nc, b_nc, b_nz); 1844 retval = SparseComplexMatrix (nc, b_nc, b_nz);
1845 retval.xcidx(0) = 0; 1845 retval.xcidx(0) = 0;
1846 octave_idx_type ii = 0; 1846 octave_idx_type ii = 0;
1847 octave_idx_type x_nz = b_nz; 1847 octave_idx_type x_nz = b_nz;
1848 1848
1849 if (typ == MatrixType::Permuted_Upper) 1849 if (typ == MatrixType::Permuted_Upper)
1850 { 1850 {
1851 octave_idx_type *perm = mattype.triangular_perm (); 1851 octave_idx_type *perm = mattype.triangular_perm ();
1852 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 1852 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
1853 1853
1854 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc); 1854 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc);
1855 for (octave_idx_type i = 0; i < nc; i++) 1855 for (octave_idx_type i = 0; i < nc; i++)
1856 rperm[perm[i]] = i; 1856 rperm[perm[i]] = i;
1857 1857
1858 for (octave_idx_type j = 0; j < b_nc; j++) 1858 for (octave_idx_type j = 0; j < b_nc; j++)
1859 { 1859 {
1860 for (octave_idx_type i = 0; i < nm; i++) 1860 for (octave_idx_type i = 0; i < nm; i++)
1861 work[i] = 0.; 1861 work[i] = 0.;
1862 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 1862 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
1863 work[b.ridx(i)] = b.data(i); 1863 work[b.ridx(i)] = b.data(i);
1864 1864
1865 for (octave_idx_type k = nc-1; k >= 0; k--) 1865 for (octave_idx_type k = nc-1; k >= 0; k--)
1866 { 1866 {
1867 octave_idx_type kidx = perm[k]; 1867 octave_idx_type kidx = perm[k];
1868 1868
1869 if (work[k] != 0.) 1869 if (work[k] != 0.)
1870 { 1870 {
1871 if (ridx(cidx(kidx+1)-1) != k || 1871 if (ridx(cidx(kidx+1)-1) != k ||
1872 data(cidx(kidx+1)-1) == 0.) 1872 data(cidx(kidx+1)-1) == 0.)
1873 { 1873 {
1874 err = -2; 1874 err = -2;
1875 goto triangular_error; 1875 goto triangular_error;
1876 } 1876 }
1877 1877
1878 Complex tmp = work[k] / data(cidx(kidx+1)-1); 1878 Complex tmp = work[k] / data(cidx(kidx+1)-1);
1879 work[k] = tmp; 1879 work[k] = tmp;
1880 for (octave_idx_type i = cidx(kidx); 1880 for (octave_idx_type i = cidx(kidx);
1881 i < cidx(kidx+1)-1; i++) 1881 i < cidx(kidx+1)-1; i++)
1882 { 1882 {
1883 octave_idx_type iidx = ridx(i); 1883 octave_idx_type iidx = ridx(i);
1884 work[iidx] = work[iidx] - tmp * data(i); 1884 work[iidx] = work[iidx] - tmp * data(i);
1885 } 1885 }
1886 } 1886 }
1887 } 1887 }
1888 1888
1889 // Count non-zeros in work vector and adjust space in 1889 // Count non-zeros in work vector and adjust space in
1890 // retval if needed 1890 // retval if needed
1891 octave_idx_type new_nnz = 0; 1891 octave_idx_type new_nnz = 0;
1892 for (octave_idx_type i = 0; i < nc; i++) 1892 for (octave_idx_type i = 0; i < nc; i++)
1893 if (work[i] != 0.) 1893 if (work[i] != 0.)
1894 new_nnz++; 1894 new_nnz++;
1895 1895
1896 if (ii + new_nnz > x_nz) 1896 if (ii + new_nnz > x_nz)
1897 { 1897 {
1898 // Resize the sparse matrix 1898 // Resize the sparse matrix
1899 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 1899 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
1900 retval.change_capacity (sz); 1900 retval.change_capacity (sz);
1901 x_nz = sz; 1901 x_nz = sz;
1902 } 1902 }
1903 1903
1904 for (octave_idx_type i = 0; i < nc; i++) 1904 for (octave_idx_type i = 0; i < nc; i++)
1905 if (work[rperm[i]] != 0.) 1905 if (work[rperm[i]] != 0.)
1906 { 1906 {
1907 retval.xridx(ii) = i; 1907 retval.xridx(ii) = i;
1908 retval.xdata(ii++) = work[rperm[i]]; 1908 retval.xdata(ii++) = work[rperm[i]];
1909 } 1909 }
1910 retval.xcidx(j+1) = ii; 1910 retval.xcidx(j+1) = ii;
1911 } 1911 }
1912 1912
1913 retval.maybe_compress (); 1913 retval.maybe_compress ();
1914 1914
1915 if (calc_cond) 1915 if (calc_cond)
1916 { 1916 {
1917 // Calculation of 1-norm of inv(*this) 1917 // Calculation of 1-norm of inv(*this)
1918 for (octave_idx_type i = 0; i < nm; i++) 1918 for (octave_idx_type i = 0; i < nm; i++)
1919 work[i] = 0.; 1919 work[i] = 0.;
1920 1920
1921 for (octave_idx_type j = 0; j < nr; j++) 1921 for (octave_idx_type j = 0; j < nr; j++)
1922 { 1922 {
1923 work[j] = 1.; 1923 work[j] = 1.;
1924 1924
1925 for (octave_idx_type k = j; k >= 0; k--) 1925 for (octave_idx_type k = j; k >= 0; k--)
1926 { 1926 {
1927 octave_idx_type iidx = perm[k]; 1927 octave_idx_type iidx = perm[k];
1928 1928
1929 if (work[k] != 0.) 1929 if (work[k] != 0.)
1930 { 1930 {
1931 Complex tmp = work[k] / data(cidx(iidx+1)-1); 1931 Complex tmp = work[k] / data(cidx(iidx+1)-1);
1932 work[k] = tmp; 1932 work[k] = tmp;
1933 for (octave_idx_type i = cidx(iidx); 1933 for (octave_idx_type i = cidx(iidx);
1934 i < cidx(iidx+1)-1; i++) 1934 i < cidx(iidx+1)-1; i++)
1935 { 1935 {
1936 octave_idx_type idx2 = ridx(i); 1936 octave_idx_type idx2 = ridx(i);
1937 work[idx2] = work[idx2] - tmp * data(i); 1937 work[idx2] = work[idx2] - tmp * data(i);
1938 } 1938 }
1939 } 1939 }
1940 } 1940 }
1941 double atmp = 0; 1941 double atmp = 0;
1942 for (octave_idx_type i = 0; i < j+1; i++) 1942 for (octave_idx_type i = 0; i < j+1; i++)
1943 { 1943 {
1944 atmp += std::abs(work[i]); 1944 atmp += std::abs(work[i]);
1945 work[i] = 0.; 1945 work[i] = 0.;
1946 } 1946 }
1947 if (atmp > ainvnorm) 1947 if (atmp > ainvnorm)
1948 ainvnorm = atmp; 1948 ainvnorm = atmp;
1949 } 1949 }
1950 rcond = 1. / ainvnorm / anorm; 1950 rcond = 1. / ainvnorm / anorm;
1951 } 1951 }
1952 } 1952 }
1953 else 1953 else
1954 { 1954 {
1955 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 1955 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
1956 1956
1957 for (octave_idx_type j = 0; j < b_nc; j++) 1957 for (octave_idx_type j = 0; j < b_nc; j++)
1958 { 1958 {
1959 for (octave_idx_type i = 0; i < nm; i++) 1959 for (octave_idx_type i = 0; i < nm; i++)
1960 work[i] = 0.; 1960 work[i] = 0.;
1961 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 1961 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
1962 work[b.ridx(i)] = b.data(i); 1962 work[b.ridx(i)] = b.data(i);
1963 1963
1964 for (octave_idx_type k = nc-1; k >= 0; k--) 1964 for (octave_idx_type k = nc-1; k >= 0; k--)
1965 { 1965 {
1966 if (work[k] != 0.) 1966 if (work[k] != 0.)
1967 { 1967 {
1968 if (ridx(cidx(k+1)-1) != k || 1968 if (ridx(cidx(k+1)-1) != k ||
1969 data(cidx(k+1)-1) == 0.) 1969 data(cidx(k+1)-1) == 0.)
1970 { 1970 {
1971 err = -2; 1971 err = -2;
1972 goto triangular_error; 1972 goto triangular_error;
1973 } 1973 }
1974 1974
1975 Complex tmp = work[k] / data(cidx(k+1)-1); 1975 Complex tmp = work[k] / data(cidx(k+1)-1);
1976 work[k] = tmp; 1976 work[k] = tmp;
1977 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) 1977 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++)
1978 { 1978 {
1979 octave_idx_type iidx = ridx(i); 1979 octave_idx_type iidx = ridx(i);
1980 work[iidx] = work[iidx] - tmp * data(i); 1980 work[iidx] = work[iidx] - tmp * data(i);
1981 } 1981 }
1982 } 1982 }
1983 } 1983 }
1984 1984
1985 // Count non-zeros in work vector and adjust space in 1985 // Count non-zeros in work vector and adjust space in
1986 // retval if needed 1986 // retval if needed
1987 octave_idx_type new_nnz = 0; 1987 octave_idx_type new_nnz = 0;
1988 for (octave_idx_type i = 0; i < nc; i++) 1988 for (octave_idx_type i = 0; i < nc; i++)
1989 if (work[i] != 0.) 1989 if (work[i] != 0.)
1990 new_nnz++; 1990 new_nnz++;
1991 1991
1992 if (ii + new_nnz > x_nz) 1992 if (ii + new_nnz > x_nz)
1993 { 1993 {
1994 // Resize the sparse matrix 1994 // Resize the sparse matrix
1995 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 1995 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
1996 retval.change_capacity (sz); 1996 retval.change_capacity (sz);
1997 x_nz = sz; 1997 x_nz = sz;
1998 } 1998 }
1999 1999
2000 for (octave_idx_type i = 0; i < nc; i++) 2000 for (octave_idx_type i = 0; i < nc; i++)
2001 if (work[i] != 0.) 2001 if (work[i] != 0.)
2002 { 2002 {
2003 retval.xridx(ii) = i; 2003 retval.xridx(ii) = i;
2004 retval.xdata(ii++) = work[i]; 2004 retval.xdata(ii++) = work[i];
2005 } 2005 }
2006 retval.xcidx(j+1) = ii; 2006 retval.xcidx(j+1) = ii;
2007 } 2007 }
2008 2008
2009 retval.maybe_compress (); 2009 retval.maybe_compress ();
2010 2010
2011 if (calc_cond) 2011 if (calc_cond)
2012 { 2012 {
2013 // Calculation of 1-norm of inv(*this) 2013 // Calculation of 1-norm of inv(*this)
2014 for (octave_idx_type i = 0; i < nm; i++) 2014 for (octave_idx_type i = 0; i < nm; i++)
2015 work[i] = 0.; 2015 work[i] = 0.;
2016 2016
2017 for (octave_idx_type j = 0; j < nr; j++) 2017 for (octave_idx_type j = 0; j < nr; j++)
2018 { 2018 {
2019 work[j] = 1.; 2019 work[j] = 1.;
2020 2020
2021 for (octave_idx_type k = j; k >= 0; k--) 2021 for (octave_idx_type k = j; k >= 0; k--)
2022 { 2022 {
2023 if (work[k] != 0.) 2023 if (work[k] != 0.)
2024 { 2024 {
2025 Complex tmp = work[k] / data(cidx(k+1)-1); 2025 Complex tmp = work[k] / data(cidx(k+1)-1);
2026 work[k] = tmp; 2026 work[k] = tmp;
2027 for (octave_idx_type i = cidx(k); 2027 for (octave_idx_type i = cidx(k);
2028 i < cidx(k+1)-1; i++) 2028 i < cidx(k+1)-1; i++)
2029 { 2029 {
2030 octave_idx_type iidx = ridx(i); 2030 octave_idx_type iidx = ridx(i);
2031 work[iidx] = work[iidx] - tmp * data(i); 2031 work[iidx] = work[iidx] - tmp * data(i);
2032 } 2032 }
2033 } 2033 }
2034 } 2034 }
2035 double atmp = 0; 2035 double atmp = 0;
2036 for (octave_idx_type i = 0; i < j+1; i++) 2036 for (octave_idx_type i = 0; i < j+1; i++)
2037 { 2037 {
2038 atmp += std::abs(work[i]); 2038 atmp += std::abs(work[i]);
2039 work[i] = 0.; 2039 work[i] = 0.;
2040 } 2040 }
2041 if (atmp > ainvnorm) 2041 if (atmp > ainvnorm)
2042 ainvnorm = atmp; 2042 ainvnorm = atmp;
2043 } 2043 }
2044 rcond = 1. / ainvnorm / anorm; 2044 rcond = 1. / ainvnorm / anorm;
2045 } 2045 }
2046 } 2046 }
2047 2047
2048 triangular_error: 2048 triangular_error:
2049 if (err != 0) 2049 if (err != 0)
2050 { 2050 {
2051 if (sing_handler) 2051 if (sing_handler)
2052 { 2052 {
2053 sing_handler (rcond); 2053 sing_handler (rcond);
2054 mattype.mark_as_rectangular (); 2054 mattype.mark_as_rectangular ();
2055 } 2055 }
2056 else 2056 else
2057 (*current_liboctave_error_handler) 2057 (*current_liboctave_error_handler)
2058 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 2058 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
2059 rcond); 2059 rcond);
2060 } 2060 }
2061 2061
2062 volatile double rcond_plus_one = rcond + 1.0; 2062 volatile double rcond_plus_one = rcond + 1.0;
2063 2063
2064 if (rcond_plus_one == 1.0 || xisnan (rcond)) 2064 if (rcond_plus_one == 1.0 || xisnan (rcond))
2065 { 2065 {
2066 err = -2; 2066 err = -2;
2067 2067
2068 if (sing_handler) 2068 if (sing_handler)
2069 { 2069 {
2070 sing_handler (rcond); 2070 sing_handler (rcond);
2071 mattype.mark_as_rectangular (); 2071 mattype.mark_as_rectangular ();
2072 } 2072 }
2073 else 2073 else
2074 (*current_liboctave_error_handler) 2074 (*current_liboctave_error_handler)
2075 ("matrix singular to machine precision, rcond = %g", 2075 ("matrix singular to machine precision, rcond = %g",
2076 rcond); 2076 rcond);
2077 } 2077 }
2078 } 2078 }
2079 else 2079 else
2080 (*current_liboctave_error_handler) ("incorrect matrix type"); 2080 (*current_liboctave_error_handler) ("incorrect matrix type");
2081 } 2081 }
2082 return retval; 2082 return retval;
2083 } 2083 }
2084 2084
2085 ComplexMatrix 2085 ComplexMatrix
2086 SparseComplexMatrix::utsolve (MatrixType &mattype, const ComplexMatrix& b, 2086 SparseComplexMatrix::utsolve (MatrixType &mattype, const ComplexMatrix& b,
2087 octave_idx_type& err, double& rcond, 2087 octave_idx_type& err, double& rcond,
2088 solve_singularity_handler sing_handler, 2088 solve_singularity_handler sing_handler,
2089 bool calc_cond) const 2089 bool calc_cond) const
2090 { 2090 {
2091 ComplexMatrix retval; 2091 ComplexMatrix retval;
2092 2092
2093 octave_idx_type nr = rows (); 2093 octave_idx_type nr = rows ();
2094 octave_idx_type nc = cols (); 2094 octave_idx_type nc = cols ();
2105 // Print spparms("spumoni") info if requested 2105 // Print spparms("spumoni") info if requested
2106 int typ = mattype.type (); 2106 int typ = mattype.type ();
2107 mattype.info (); 2107 mattype.info ();
2108 2108
2109 if (typ == MatrixType::Permuted_Upper || 2109 if (typ == MatrixType::Permuted_Upper ||
2110 typ == MatrixType::Upper) 2110 typ == MatrixType::Upper)
2111 { 2111 {
2112 double anorm = 0.; 2112 double anorm = 0.;
2113 double ainvnorm = 0.; 2113 double ainvnorm = 0.;
2114 octave_idx_type b_nc = b.cols (); 2114 octave_idx_type b_nc = b.cols ();
2115 rcond = 1.; 2115 rcond = 1.;
2116 2116
2117 if (calc_cond) 2117 if (calc_cond)
2118 { 2118 {
2119 // Calculate the 1-norm of matrix for rcond calculation 2119 // Calculate the 1-norm of matrix for rcond calculation
2120 for (octave_idx_type j = 0; j < nc; j++) 2120 for (octave_idx_type j = 0; j < nc; j++)
2121 { 2121 {
2122 double atmp = 0.; 2122 double atmp = 0.;
2123 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 2123 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
2124 atmp += std::abs(data(i)); 2124 atmp += std::abs(data(i));
2125 if (atmp > anorm) 2125 if (atmp > anorm)
2126 anorm = atmp; 2126 anorm = atmp;
2127 } 2127 }
2128 } 2128 }
2129 2129
2130 if (typ == MatrixType::Permuted_Upper) 2130 if (typ == MatrixType::Permuted_Upper)
2131 { 2131 {
2132 retval.resize (nc, b_nc); 2132 retval.resize (nc, b_nc);
2133 octave_idx_type *perm = mattype.triangular_perm (); 2133 octave_idx_type *perm = mattype.triangular_perm ();
2134 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2134 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
2135 2135
2136 for (octave_idx_type j = 0; j < b_nc; j++) 2136 for (octave_idx_type j = 0; j < b_nc; j++)
2137 { 2137 {
2138 for (octave_idx_type i = 0; i < nr; i++) 2138 for (octave_idx_type i = 0; i < nr; i++)
2139 work[i] = b(i,j); 2139 work[i] = b(i,j);
2140 for (octave_idx_type i = nr; i < nc; i++) 2140 for (octave_idx_type i = nr; i < nc; i++)
2141 work[i] = 0.; 2141 work[i] = 0.;
2142 2142
2143 for (octave_idx_type k = nc-1; k >= 0; k--) 2143 for (octave_idx_type k = nc-1; k >= 0; k--)
2144 { 2144 {
2145 octave_idx_type kidx = perm[k]; 2145 octave_idx_type kidx = perm[k];
2146 2146
2147 if (work[k] != 0.) 2147 if (work[k] != 0.)
2148 { 2148 {
2149 if (ridx(cidx(kidx+1)-1) != k || 2149 if (ridx(cidx(kidx+1)-1) != k ||
2150 data(cidx(kidx+1)-1) == 0.) 2150 data(cidx(kidx+1)-1) == 0.)
2151 { 2151 {
2152 err = -2; 2152 err = -2;
2153 goto triangular_error; 2153 goto triangular_error;
2154 } 2154 }
2155 2155
2156 Complex tmp = work[k] / data(cidx(kidx+1)-1); 2156 Complex tmp = work[k] / data(cidx(kidx+1)-1);
2157 work[k] = tmp; 2157 work[k] = tmp;
2158 for (octave_idx_type i = cidx(kidx); 2158 for (octave_idx_type i = cidx(kidx);
2159 i < cidx(kidx+1)-1; i++) 2159 i < cidx(kidx+1)-1; i++)
2160 { 2160 {
2161 octave_idx_type iidx = ridx(i); 2161 octave_idx_type iidx = ridx(i);
2162 work[iidx] = work[iidx] - tmp * data(i); 2162 work[iidx] = work[iidx] - tmp * data(i);
2163 } 2163 }
2164 } 2164 }
2165 } 2165 }
2166 2166
2167 for (octave_idx_type i = 0; i < nc; i++) 2167 for (octave_idx_type i = 0; i < nc; i++)
2168 retval (perm[i], j) = work[i]; 2168 retval (perm[i], j) = work[i];
2169 } 2169 }
2170 2170
2171 if (calc_cond) 2171 if (calc_cond)
2172 { 2172 {
2173 // Calculation of 1-norm of inv(*this) 2173 // Calculation of 1-norm of inv(*this)
2174 for (octave_idx_type i = 0; i < nm; i++) 2174 for (octave_idx_type i = 0; i < nm; i++)
2175 work[i] = 0.; 2175 work[i] = 0.;
2176 2176
2177 for (octave_idx_type j = 0; j < nr; j++) 2177 for (octave_idx_type j = 0; j < nr; j++)
2178 { 2178 {
2179 work[j] = 1.; 2179 work[j] = 1.;
2180 2180
2181 for (octave_idx_type k = j; k >= 0; k--) 2181 for (octave_idx_type k = j; k >= 0; k--)
2182 { 2182 {
2183 octave_idx_type iidx = perm[k]; 2183 octave_idx_type iidx = perm[k];
2184 2184
2185 if (work[k] != 0.) 2185 if (work[k] != 0.)
2186 { 2186 {
2187 Complex tmp = work[k] / data(cidx(iidx+1)-1); 2187 Complex tmp = work[k] / data(cidx(iidx+1)-1);
2188 work[k] = tmp; 2188 work[k] = tmp;
2189 for (octave_idx_type i = cidx(iidx); 2189 for (octave_idx_type i = cidx(iidx);
2190 i < cidx(iidx+1)-1; i++) 2190 i < cidx(iidx+1)-1; i++)
2191 { 2191 {
2192 octave_idx_type idx2 = ridx(i); 2192 octave_idx_type idx2 = ridx(i);
2193 work[idx2] = work[idx2] - tmp * data(i); 2193 work[idx2] = work[idx2] - tmp * data(i);
2194 } 2194 }
2195 } 2195 }
2196 } 2196 }
2197 double atmp = 0; 2197 double atmp = 0;
2198 for (octave_idx_type i = 0; i < j+1; i++) 2198 for (octave_idx_type i = 0; i < j+1; i++)
2199 { 2199 {
2200 atmp += std::abs(work[i]); 2200 atmp += std::abs(work[i]);
2201 work[i] = 0.; 2201 work[i] = 0.;
2202 } 2202 }
2203 if (atmp > ainvnorm) 2203 if (atmp > ainvnorm)
2204 ainvnorm = atmp; 2204 ainvnorm = atmp;
2205 } 2205 }
2206 rcond = 1. / ainvnorm / anorm; 2206 rcond = 1. / ainvnorm / anorm;
2207 } 2207 }
2208 } 2208 }
2209 else 2209 else
2210 { 2210 {
2211 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2211 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
2212 retval.resize (nc, b_nc); 2212 retval.resize (nc, b_nc);
2213 2213
2214 for (octave_idx_type j = 0; j < b_nc; j++) 2214 for (octave_idx_type j = 0; j < b_nc; j++)
2215 { 2215 {
2216 for (octave_idx_type i = 0; i < nr; i++) 2216 for (octave_idx_type i = 0; i < nr; i++)
2217 work[i] = b(i,j); 2217 work[i] = b(i,j);
2218 for (octave_idx_type i = nr; i < nc; i++) 2218 for (octave_idx_type i = nr; i < nc; i++)
2219 work[i] = 0.; 2219 work[i] = 0.;
2220 2220
2221 for (octave_idx_type k = nc-1; k >= 0; k--) 2221 for (octave_idx_type k = nc-1; k >= 0; k--)
2222 { 2222 {
2223 if (work[k] != 0.) 2223 if (work[k] != 0.)
2224 { 2224 {
2225 if (ridx(cidx(k+1)-1) != k || 2225 if (ridx(cidx(k+1)-1) != k ||
2226 data(cidx(k+1)-1) == 0.) 2226 data(cidx(k+1)-1) == 0.)
2227 { 2227 {
2228 err = -2; 2228 err = -2;
2229 goto triangular_error; 2229 goto triangular_error;
2230 } 2230 }
2231 2231
2232 Complex tmp = work[k] / data(cidx(k+1)-1); 2232 Complex tmp = work[k] / data(cidx(k+1)-1);
2233 work[k] = tmp; 2233 work[k] = tmp;
2234 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) 2234 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++)
2235 { 2235 {
2236 octave_idx_type iidx = ridx(i); 2236 octave_idx_type iidx = ridx(i);
2237 work[iidx] = work[iidx] - tmp * data(i); 2237 work[iidx] = work[iidx] - tmp * data(i);
2238 } 2238 }
2239 } 2239 }
2240 } 2240 }
2241 2241
2242 for (octave_idx_type i = 0; i < nc; i++) 2242 for (octave_idx_type i = 0; i < nc; i++)
2243 retval.xelem (i, j) = work[i]; 2243 retval.xelem (i, j) = work[i];
2244 } 2244 }
2245 2245
2246 if (calc_cond) 2246 if (calc_cond)
2247 { 2247 {
2248 // Calculation of 1-norm of inv(*this) 2248 // Calculation of 1-norm of inv(*this)
2249 for (octave_idx_type i = 0; i < nm; i++) 2249 for (octave_idx_type i = 0; i < nm; i++)
2250 work[i] = 0.; 2250 work[i] = 0.;
2251 2251
2252 for (octave_idx_type j = 0; j < nr; j++) 2252 for (octave_idx_type j = 0; j < nr; j++)
2253 { 2253 {
2254 work[j] = 1.; 2254 work[j] = 1.;
2255 2255
2256 for (octave_idx_type k = j; k >= 0; k--) 2256 for (octave_idx_type k = j; k >= 0; k--)
2257 { 2257 {
2258 if (work[k] != 0.) 2258 if (work[k] != 0.)
2259 { 2259 {
2260 Complex tmp = work[k] / data(cidx(k+1)-1); 2260 Complex tmp = work[k] / data(cidx(k+1)-1);
2261 work[k] = tmp; 2261 work[k] = tmp;
2262 for (octave_idx_type i = cidx(k); 2262 for (octave_idx_type i = cidx(k);
2263 i < cidx(k+1)-1; i++) 2263 i < cidx(k+1)-1; i++)
2264 { 2264 {
2265 octave_idx_type iidx = ridx(i); 2265 octave_idx_type iidx = ridx(i);
2266 work[iidx] = work[iidx] - tmp * data(i); 2266 work[iidx] = work[iidx] - tmp * data(i);
2267 } 2267 }
2268 } 2268 }
2269 } 2269 }
2270 double atmp = 0; 2270 double atmp = 0;
2271 for (octave_idx_type i = 0; i < j+1; i++) 2271 for (octave_idx_type i = 0; i < j+1; i++)
2272 { 2272 {
2273 atmp += std::abs(work[i]); 2273 atmp += std::abs(work[i]);
2274 work[i] = 0.; 2274 work[i] = 0.;
2275 } 2275 }
2276 if (atmp > ainvnorm) 2276 if (atmp > ainvnorm)
2277 ainvnorm = atmp; 2277 ainvnorm = atmp;
2278 } 2278 }
2279 rcond = 1. / ainvnorm / anorm; 2279 rcond = 1. / ainvnorm / anorm;
2280 } 2280 }
2281 } 2281 }
2282 2282
2283 triangular_error: 2283 triangular_error:
2284 if (err != 0) 2284 if (err != 0)
2285 { 2285 {
2286 if (sing_handler) 2286 if (sing_handler)
2287 { 2287 {
2288 sing_handler (rcond); 2288 sing_handler (rcond);
2289 mattype.mark_as_rectangular (); 2289 mattype.mark_as_rectangular ();
2290 } 2290 }
2291 else 2291 else
2292 (*current_liboctave_error_handler) 2292 (*current_liboctave_error_handler)
2293 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 2293 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
2294 rcond); 2294 rcond);
2295 } 2295 }
2296 2296
2297 volatile double rcond_plus_one = rcond + 1.0; 2297 volatile double rcond_plus_one = rcond + 1.0;
2298 2298
2299 if (rcond_plus_one == 1.0 || xisnan (rcond)) 2299 if (rcond_plus_one == 1.0 || xisnan (rcond))
2300 { 2300 {
2301 err = -2; 2301 err = -2;
2302 2302
2303 if (sing_handler) 2303 if (sing_handler)
2304 { 2304 {
2305 sing_handler (rcond); 2305 sing_handler (rcond);
2306 mattype.mark_as_rectangular (); 2306 mattype.mark_as_rectangular ();
2307 } 2307 }
2308 else 2308 else
2309 (*current_liboctave_error_handler) 2309 (*current_liboctave_error_handler)
2310 ("matrix singular to machine precision, rcond = %g", 2310 ("matrix singular to machine precision, rcond = %g",
2311 rcond); 2311 rcond);
2312 } 2312 }
2313 } 2313 }
2314 else 2314 else
2315 (*current_liboctave_error_handler) ("incorrect matrix type"); 2315 (*current_liboctave_error_handler) ("incorrect matrix type");
2316 } 2316 }
2317 2317
2318 return retval; 2318 return retval;
2319 } 2319 }
2320 2320
2321 SparseComplexMatrix 2321 SparseComplexMatrix
2322 SparseComplexMatrix::utsolve (MatrixType &mattype, const SparseComplexMatrix& b, 2322 SparseComplexMatrix::utsolve (MatrixType &mattype, const SparseComplexMatrix& b,
2323 octave_idx_type& err, double& rcond, 2323 octave_idx_type& err, double& rcond,
2324 solve_singularity_handler sing_handler, 2324 solve_singularity_handler sing_handler,
2325 bool calc_cond) const 2325 bool calc_cond) const
2326 { 2326 {
2327 SparseComplexMatrix retval; 2327 SparseComplexMatrix retval;
2328 2328
2329 octave_idx_type nr = rows (); 2329 octave_idx_type nr = rows ();
2330 octave_idx_type nc = cols (); 2330 octave_idx_type nc = cols ();
2341 // Print spparms("spumoni") info if requested 2341 // Print spparms("spumoni") info if requested
2342 int typ = mattype.type (); 2342 int typ = mattype.type ();
2343 mattype.info (); 2343 mattype.info ();
2344 2344
2345 if (typ == MatrixType::Permuted_Upper || 2345 if (typ == MatrixType::Permuted_Upper ||
2346 typ == MatrixType::Upper) 2346 typ == MatrixType::Upper)
2347 { 2347 {
2348 double anorm = 0.; 2348 double anorm = 0.;
2349 double ainvnorm = 0.; 2349 double ainvnorm = 0.;
2350 rcond = 1.; 2350 rcond = 1.;
2351 2351
2352 if (calc_cond) 2352 if (calc_cond)
2353 { 2353 {
2354 // Calculate the 1-norm of matrix for rcond calculation 2354 // Calculate the 1-norm of matrix for rcond calculation
2355 for (octave_idx_type j = 0; j < nc; j++) 2355 for (octave_idx_type j = 0; j < nc; j++)
2356 { 2356 {
2357 double atmp = 0.; 2357 double atmp = 0.;
2358 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 2358 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
2359 atmp += std::abs(data(i)); 2359 atmp += std::abs(data(i));
2360 if (atmp > anorm) 2360 if (atmp > anorm)
2361 anorm = atmp; 2361 anorm = atmp;
2362 } 2362 }
2363 } 2363 }
2364 2364
2365 octave_idx_type b_nc = b.cols (); 2365 octave_idx_type b_nc = b.cols ();
2366 octave_idx_type b_nz = b.nnz (); 2366 octave_idx_type b_nz = b.nnz ();
2367 retval = SparseComplexMatrix (nc, b_nc, b_nz); 2367 retval = SparseComplexMatrix (nc, b_nc, b_nz);
2368 retval.xcidx(0) = 0; 2368 retval.xcidx(0) = 0;
2369 octave_idx_type ii = 0; 2369 octave_idx_type ii = 0;
2370 octave_idx_type x_nz = b_nz; 2370 octave_idx_type x_nz = b_nz;
2371 2371
2372 if (typ == MatrixType::Permuted_Upper) 2372 if (typ == MatrixType::Permuted_Upper)
2373 { 2373 {
2374 octave_idx_type *perm = mattype.triangular_perm (); 2374 octave_idx_type *perm = mattype.triangular_perm ();
2375 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2375 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
2376 2376
2377 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc); 2377 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc);
2378 for (octave_idx_type i = 0; i < nc; i++) 2378 for (octave_idx_type i = 0; i < nc; i++)
2379 rperm[perm[i]] = i; 2379 rperm[perm[i]] = i;
2380 2380
2381 for (octave_idx_type j = 0; j < b_nc; j++) 2381 for (octave_idx_type j = 0; j < b_nc; j++)
2382 { 2382 {
2383 for (octave_idx_type i = 0; i < nm; i++) 2383 for (octave_idx_type i = 0; i < nm; i++)
2384 work[i] = 0.; 2384 work[i] = 0.;
2385 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 2385 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
2386 work[b.ridx(i)] = b.data(i); 2386 work[b.ridx(i)] = b.data(i);
2387 2387
2388 for (octave_idx_type k = nc-1; k >= 0; k--) 2388 for (octave_idx_type k = nc-1; k >= 0; k--)
2389 { 2389 {
2390 octave_idx_type kidx = perm[k]; 2390 octave_idx_type kidx = perm[k];
2391 2391
2392 if (work[k] != 0.) 2392 if (work[k] != 0.)
2393 { 2393 {
2394 if (ridx(cidx(kidx+1)-1) != k || 2394 if (ridx(cidx(kidx+1)-1) != k ||
2395 data(cidx(kidx+1)-1) == 0.) 2395 data(cidx(kidx+1)-1) == 0.)
2396 { 2396 {
2397 err = -2; 2397 err = -2;
2398 goto triangular_error; 2398 goto triangular_error;
2399 } 2399 }
2400 2400
2401 Complex tmp = work[k] / data(cidx(kidx+1)-1); 2401 Complex tmp = work[k] / data(cidx(kidx+1)-1);
2402 work[k] = tmp; 2402 work[k] = tmp;
2403 for (octave_idx_type i = cidx(kidx); 2403 for (octave_idx_type i = cidx(kidx);
2404 i < cidx(kidx+1)-1; i++) 2404 i < cidx(kidx+1)-1; i++)
2405 { 2405 {
2406 octave_idx_type iidx = ridx(i); 2406 octave_idx_type iidx = ridx(i);
2407 work[iidx] = work[iidx] - tmp * data(i); 2407 work[iidx] = work[iidx] - tmp * data(i);
2408 } 2408 }
2409 } 2409 }
2410 } 2410 }
2411 2411
2412 // Count non-zeros in work vector and adjust space in 2412 // Count non-zeros in work vector and adjust space in
2413 // retval if needed 2413 // retval if needed
2414 octave_idx_type new_nnz = 0; 2414 octave_idx_type new_nnz = 0;
2415 for (octave_idx_type i = 0; i < nc; i++) 2415 for (octave_idx_type i = 0; i < nc; i++)
2416 if (work[i] != 0.) 2416 if (work[i] != 0.)
2417 new_nnz++; 2417 new_nnz++;
2418 2418
2419 if (ii + new_nnz > x_nz) 2419 if (ii + new_nnz > x_nz)
2420 { 2420 {
2421 // Resize the sparse matrix 2421 // Resize the sparse matrix
2422 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 2422 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
2423 retval.change_capacity (sz); 2423 retval.change_capacity (sz);
2424 x_nz = sz; 2424 x_nz = sz;
2425 } 2425 }
2426 2426
2427 for (octave_idx_type i = 0; i < nc; i++) 2427 for (octave_idx_type i = 0; i < nc; i++)
2428 if (work[rperm[i]] != 0.) 2428 if (work[rperm[i]] != 0.)
2429 { 2429 {
2430 retval.xridx(ii) = i; 2430 retval.xridx(ii) = i;
2431 retval.xdata(ii++) = work[rperm[i]]; 2431 retval.xdata(ii++) = work[rperm[i]];
2432 } 2432 }
2433 retval.xcidx(j+1) = ii; 2433 retval.xcidx(j+1) = ii;
2434 } 2434 }
2435 2435
2436 retval.maybe_compress (); 2436 retval.maybe_compress ();
2437 2437
2438 if (calc_cond) 2438 if (calc_cond)
2439 { 2439 {
2440 // Calculation of 1-norm of inv(*this) 2440 // Calculation of 1-norm of inv(*this)
2441 for (octave_idx_type i = 0; i < nm; i++) 2441 for (octave_idx_type i = 0; i < nm; i++)
2442 work[i] = 0.; 2442 work[i] = 0.;
2443 2443
2444 for (octave_idx_type j = 0; j < nr; j++) 2444 for (octave_idx_type j = 0; j < nr; j++)
2445 { 2445 {
2446 work[j] = 1.; 2446 work[j] = 1.;
2447 2447
2448 for (octave_idx_type k = j; k >= 0; k--) 2448 for (octave_idx_type k = j; k >= 0; k--)
2449 { 2449 {
2450 octave_idx_type iidx = perm[k]; 2450 octave_idx_type iidx = perm[k];
2451 2451
2452 if (work[k] != 0.) 2452 if (work[k] != 0.)
2453 { 2453 {
2454 Complex tmp = work[k] / data(cidx(iidx+1)-1); 2454 Complex tmp = work[k] / data(cidx(iidx+1)-1);
2455 work[k] = tmp; 2455 work[k] = tmp;
2456 for (octave_idx_type i = cidx(iidx); 2456 for (octave_idx_type i = cidx(iidx);
2457 i < cidx(iidx+1)-1; i++) 2457 i < cidx(iidx+1)-1; i++)
2458 { 2458 {
2459 octave_idx_type idx2 = ridx(i); 2459 octave_idx_type idx2 = ridx(i);
2460 work[idx2] = work[idx2] - tmp * data(i); 2460 work[idx2] = work[idx2] - tmp * data(i);
2461 } 2461 }
2462 } 2462 }
2463 } 2463 }
2464 double atmp = 0; 2464 double atmp = 0;
2465 for (octave_idx_type i = 0; i < j+1; i++) 2465 for (octave_idx_type i = 0; i < j+1; i++)
2466 { 2466 {
2467 atmp += std::abs(work[i]); 2467 atmp += std::abs(work[i]);
2468 work[i] = 0.; 2468 work[i] = 0.;
2469 } 2469 }
2470 if (atmp > ainvnorm) 2470 if (atmp > ainvnorm)
2471 ainvnorm = atmp; 2471 ainvnorm = atmp;
2472 } 2472 }
2473 rcond = 1. / ainvnorm / anorm; 2473 rcond = 1. / ainvnorm / anorm;
2474 } 2474 }
2475 } 2475 }
2476 else 2476 else
2477 { 2477 {
2478 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2478 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
2479 2479
2480 for (octave_idx_type j = 0; j < b_nc; j++) 2480 for (octave_idx_type j = 0; j < b_nc; j++)
2481 { 2481 {
2482 for (octave_idx_type i = 0; i < nm; i++) 2482 for (octave_idx_type i = 0; i < nm; i++)
2483 work[i] = 0.; 2483 work[i] = 0.;
2484 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 2484 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
2485 work[b.ridx(i)] = b.data(i); 2485 work[b.ridx(i)] = b.data(i);
2486 2486
2487 for (octave_idx_type k = nr-1; k >= 0; k--) 2487 for (octave_idx_type k = nr-1; k >= 0; k--)
2488 { 2488 {
2489 if (work[k] != 0.) 2489 if (work[k] != 0.)
2490 { 2490 {
2491 if (ridx(cidx(k+1)-1) != k || 2491 if (ridx(cidx(k+1)-1) != k ||
2492 data(cidx(k+1)-1) == 0.) 2492 data(cidx(k+1)-1) == 0.)
2493 { 2493 {
2494 err = -2; 2494 err = -2;
2495 goto triangular_error; 2495 goto triangular_error;
2496 } 2496 }
2497 2497
2498 Complex tmp = work[k] / data(cidx(k+1)-1); 2498 Complex tmp = work[k] / data(cidx(k+1)-1);
2499 work[k] = tmp; 2499 work[k] = tmp;
2500 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) 2500 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++)
2501 { 2501 {
2502 octave_idx_type iidx = ridx(i); 2502 octave_idx_type iidx = ridx(i);
2503 work[iidx] = work[iidx] - tmp * data(i); 2503 work[iidx] = work[iidx] - tmp * data(i);
2504 } 2504 }
2505 } 2505 }
2506 } 2506 }
2507 2507
2508 // Count non-zeros in work vector and adjust space in 2508 // Count non-zeros in work vector and adjust space in
2509 // retval if needed 2509 // retval if needed
2510 octave_idx_type new_nnz = 0; 2510 octave_idx_type new_nnz = 0;
2511 for (octave_idx_type i = 0; i < nc; i++) 2511 for (octave_idx_type i = 0; i < nc; i++)
2512 if (work[i] != 0.) 2512 if (work[i] != 0.)
2513 new_nnz++; 2513 new_nnz++;
2514 2514
2515 if (ii + new_nnz > x_nz) 2515 if (ii + new_nnz > x_nz)
2516 { 2516 {
2517 // Resize the sparse matrix 2517 // Resize the sparse matrix
2518 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 2518 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
2519 retval.change_capacity (sz); 2519 retval.change_capacity (sz);
2520 x_nz = sz; 2520 x_nz = sz;
2521 } 2521 }
2522 2522
2523 for (octave_idx_type i = 0; i < nc; i++) 2523 for (octave_idx_type i = 0; i < nc; i++)
2524 if (work[i] != 0.) 2524 if (work[i] != 0.)
2525 { 2525 {
2526 retval.xridx(ii) = i; 2526 retval.xridx(ii) = i;
2527 retval.xdata(ii++) = work[i]; 2527 retval.xdata(ii++) = work[i];
2528 } 2528 }
2529 retval.xcidx(j+1) = ii; 2529 retval.xcidx(j+1) = ii;
2530 } 2530 }
2531 2531
2532 retval.maybe_compress (); 2532 retval.maybe_compress ();
2533 2533
2534 if (calc_cond) 2534 if (calc_cond)
2535 { 2535 {
2536 // Calculation of 1-norm of inv(*this) 2536 // Calculation of 1-norm of inv(*this)
2537 for (octave_idx_type i = 0; i < nm; i++) 2537 for (octave_idx_type i = 0; i < nm; i++)
2538 work[i] = 0.; 2538 work[i] = 0.;
2539 2539
2540 for (octave_idx_type j = 0; j < nr; j++) 2540 for (octave_idx_type j = 0; j < nr; j++)
2541 { 2541 {
2542 work[j] = 1.; 2542 work[j] = 1.;
2543 2543
2544 for (octave_idx_type k = j; k >= 0; k--) 2544 for (octave_idx_type k = j; k >= 0; k--)
2545 { 2545 {
2546 if (work[k] != 0.) 2546 if (work[k] != 0.)
2547 { 2547 {
2548 Complex tmp = work[k] / data(cidx(k+1)-1); 2548 Complex tmp = work[k] / data(cidx(k+1)-1);
2549 work[k] = tmp; 2549 work[k] = tmp;
2550 for (octave_idx_type i = cidx(k); 2550 for (octave_idx_type i = cidx(k);
2551 i < cidx(k+1)-1; i++) 2551 i < cidx(k+1)-1; i++)
2552 { 2552 {
2553 octave_idx_type iidx = ridx(i); 2553 octave_idx_type iidx = ridx(i);
2554 work[iidx] = work[iidx] - tmp * data(i); 2554 work[iidx] = work[iidx] - tmp * data(i);
2555 } 2555 }
2556 } 2556 }
2557 } 2557 }
2558 double atmp = 0; 2558 double atmp = 0;
2559 for (octave_idx_type i = 0; i < j+1; i++) 2559 for (octave_idx_type i = 0; i < j+1; i++)
2560 { 2560 {
2561 atmp += std::abs(work[i]); 2561 atmp += std::abs(work[i]);
2562 work[i] = 0.; 2562 work[i] = 0.;
2563 } 2563 }
2564 if (atmp > ainvnorm) 2564 if (atmp > ainvnorm)
2565 ainvnorm = atmp; 2565 ainvnorm = atmp;
2566 } 2566 }
2567 rcond = 1. / ainvnorm / anorm; 2567 rcond = 1. / ainvnorm / anorm;
2568 } 2568 }
2569 } 2569 }
2570 2570
2571 triangular_error: 2571 triangular_error:
2572 if (err != 0) 2572 if (err != 0)
2573 { 2573 {
2574 if (sing_handler) 2574 if (sing_handler)
2575 { 2575 {
2576 sing_handler (rcond); 2576 sing_handler (rcond);
2577 mattype.mark_as_rectangular (); 2577 mattype.mark_as_rectangular ();
2578 } 2578 }
2579 else 2579 else
2580 (*current_liboctave_error_handler) 2580 (*current_liboctave_error_handler)
2581 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 2581 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
2582 rcond); 2582 rcond);
2583 } 2583 }
2584 2584
2585 volatile double rcond_plus_one = rcond + 1.0; 2585 volatile double rcond_plus_one = rcond + 1.0;
2586 2586
2587 if (rcond_plus_one == 1.0 || xisnan (rcond)) 2587 if (rcond_plus_one == 1.0 || xisnan (rcond))
2588 { 2588 {
2589 err = -2; 2589 err = -2;
2590 2590
2591 if (sing_handler) 2591 if (sing_handler)
2592 { 2592 {
2593 sing_handler (rcond); 2593 sing_handler (rcond);
2594 mattype.mark_as_rectangular (); 2594 mattype.mark_as_rectangular ();
2595 } 2595 }
2596 else 2596 else
2597 (*current_liboctave_error_handler) 2597 (*current_liboctave_error_handler)
2598 ("matrix singular to machine precision, rcond = %g", 2598 ("matrix singular to machine precision, rcond = %g",
2599 rcond); 2599 rcond);
2600 } 2600 }
2601 } 2601 }
2602 else 2602 else
2603 (*current_liboctave_error_handler) ("incorrect matrix type"); 2603 (*current_liboctave_error_handler) ("incorrect matrix type");
2604 } 2604 }
2605 2605
2606 return retval; 2606 return retval;
2607 } 2607 }
2608 2608
2609 ComplexMatrix 2609 ComplexMatrix
2610 SparseComplexMatrix::ltsolve (MatrixType &mattype, const Matrix& b, 2610 SparseComplexMatrix::ltsolve (MatrixType &mattype, const Matrix& b,
2611 octave_idx_type& err, double& rcond, 2611 octave_idx_type& err, double& rcond,
2612 solve_singularity_handler sing_handler, 2612 solve_singularity_handler sing_handler,
2613 bool calc_cond) const 2613 bool calc_cond) const
2614 { 2614 {
2615 ComplexMatrix retval; 2615 ComplexMatrix retval;
2616 2616
2617 octave_idx_type nr = rows (); 2617 octave_idx_type nr = rows ();
2618 octave_idx_type nc = cols (); 2618 octave_idx_type nc = cols ();
2629 // Print spparms("spumoni") info if requested 2629 // Print spparms("spumoni") info if requested
2630 int typ = mattype.type (); 2630 int typ = mattype.type ();
2631 mattype.info (); 2631 mattype.info ();
2632 2632
2633 if (typ == MatrixType::Permuted_Lower || 2633 if (typ == MatrixType::Permuted_Lower ||
2634 typ == MatrixType::Lower) 2634 typ == MatrixType::Lower)
2635 { 2635 {
2636 double anorm = 0.; 2636 double anorm = 0.;
2637 double ainvnorm = 0.; 2637 double ainvnorm = 0.;
2638 octave_idx_type b_nc = b.cols (); 2638 octave_idx_type b_nc = b.cols ();
2639 rcond = 1.; 2639 rcond = 1.;
2640 2640
2641 if (calc_cond) 2641 if (calc_cond)
2642 { 2642 {
2643 // Calculate the 1-norm of matrix for rcond calculation 2643 // Calculate the 1-norm of matrix for rcond calculation
2644 for (octave_idx_type j = 0; j < nc; j++) 2644 for (octave_idx_type j = 0; j < nc; j++)
2645 { 2645 {
2646 double atmp = 0.; 2646 double atmp = 0.;
2647 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 2647 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
2648 atmp += std::abs(data(i)); 2648 atmp += std::abs(data(i));
2649 if (atmp > anorm) 2649 if (atmp > anorm)
2650 anorm = atmp; 2650 anorm = atmp;
2651 } 2651 }
2652 } 2652 }
2653 2653
2654 if (typ == MatrixType::Permuted_Lower) 2654 if (typ == MatrixType::Permuted_Lower)
2655 { 2655 {
2656 retval.resize (nc, b_nc); 2656 retval.resize (nc, b_nc);
2657 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2657 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
2658 octave_idx_type *perm = mattype.triangular_perm (); 2658 octave_idx_type *perm = mattype.triangular_perm ();
2659 2659
2660 for (octave_idx_type j = 0; j < b_nc; j++) 2660 for (octave_idx_type j = 0; j < b_nc; j++)
2661 { 2661 {
2662 for (octave_idx_type i = 0; i < nm; i++) 2662 for (octave_idx_type i = 0; i < nm; i++)
2663 work[i] = 0.; 2663 work[i] = 0.;
2664 for (octave_idx_type i = 0; i < nr; i++) 2664 for (octave_idx_type i = 0; i < nr; i++)
2665 work[perm[i]] = b(i,j); 2665 work[perm[i]] = b(i,j);
2666 2666
2667 for (octave_idx_type k = 0; k < nc; k++) 2667 for (octave_idx_type k = 0; k < nc; k++)
2668 { 2668 {
2669 if (work[k] != 0.) 2669 if (work[k] != 0.)
2670 { 2670 {
2671 octave_idx_type minr = nr; 2671 octave_idx_type minr = nr;
2672 octave_idx_type mini = 0; 2672 octave_idx_type mini = 0;
2673 2673
2674 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 2674 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
2675 if (perm[ridx(i)] < minr) 2675 if (perm[ridx(i)] < minr)
2676 { 2676 {
2677 minr = perm[ridx(i)]; 2677 minr = perm[ridx(i)];
2678 mini = i; 2678 mini = i;
2679 } 2679 }
2680 2680
2681 if (minr != k || data (mini) == 0.) 2681 if (minr != k || data (mini) == 0.)
2682 { 2682 {
2683 err = -2; 2683 err = -2;
2684 goto triangular_error; 2684 goto triangular_error;
2685 } 2685 }
2686 2686
2687 Complex tmp = work[k] / data(mini); 2687 Complex tmp = work[k] / data(mini);
2688 work[k] = tmp; 2688 work[k] = tmp;
2689 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 2689 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
2690 { 2690 {
2691 if (i == mini) 2691 if (i == mini)
2692 continue; 2692 continue;
2693 2693
2694 octave_idx_type iidx = perm[ridx(i)]; 2694 octave_idx_type iidx = perm[ridx(i)];
2695 work[iidx] = work[iidx] - tmp * data(i); 2695 work[iidx] = work[iidx] - tmp * data(i);
2696 } 2696 }
2697 } 2697 }
2698 } 2698 }
2699 2699
2700 for (octave_idx_type i = 0; i < nc; i++) 2700 for (octave_idx_type i = 0; i < nc; i++)
2701 retval (i, j) = work[i]; 2701 retval (i, j) = work[i];
2702 } 2702 }
2703 2703
2704 if (calc_cond) 2704 if (calc_cond)
2705 { 2705 {
2706 // Calculation of 1-norm of inv(*this) 2706 // Calculation of 1-norm of inv(*this)
2707 for (octave_idx_type i = 0; i < nm; i++) 2707 for (octave_idx_type i = 0; i < nm; i++)
2708 work[i] = 0.; 2708 work[i] = 0.;
2709 2709
2710 for (octave_idx_type j = 0; j < nr; j++) 2710 for (octave_idx_type j = 0; j < nr; j++)
2711 { 2711 {
2712 work[j] = 1.; 2712 work[j] = 1.;
2713 2713
2714 for (octave_idx_type k = 0; k < nc; k++) 2714 for (octave_idx_type k = 0; k < nc; k++)
2715 { 2715 {
2716 if (work[k] != 0.) 2716 if (work[k] != 0.)
2717 { 2717 {
2718 octave_idx_type minr = nr; 2718 octave_idx_type minr = nr;
2719 octave_idx_type mini = 0; 2719 octave_idx_type mini = 0;
2720 2720
2721 for (octave_idx_type i = cidx(k); 2721 for (octave_idx_type i = cidx(k);
2722 i < cidx(k+1); i++) 2722 i < cidx(k+1); i++)
2723 if (perm[ridx(i)] < minr) 2723 if (perm[ridx(i)] < minr)
2724 { 2724 {
2725 minr = perm[ridx(i)]; 2725 minr = perm[ridx(i)];
2726 mini = i; 2726 mini = i;
2727 } 2727 }
2728 2728
2729 Complex tmp = work[k] / data(mini); 2729 Complex tmp = work[k] / data(mini);
2730 work[k] = tmp; 2730 work[k] = tmp;
2731 for (octave_idx_type i = cidx(k); 2731 for (octave_idx_type i = cidx(k);
2732 i < cidx(k+1); i++) 2732 i < cidx(k+1); i++)
2733 { 2733 {
2734 if (i == mini) 2734 if (i == mini)
2735 continue; 2735 continue;
2736 2736
2737 octave_idx_type iidx = perm[ridx(i)]; 2737 octave_idx_type iidx = perm[ridx(i)];
2738 work[iidx] = work[iidx] - tmp * data(i); 2738 work[iidx] = work[iidx] - tmp * data(i);
2739 } 2739 }
2740 } 2740 }
2741 } 2741 }
2742 2742
2743 double atmp = 0; 2743 double atmp = 0;
2744 for (octave_idx_type i = j; i < nc; i++) 2744 for (octave_idx_type i = j; i < nc; i++)
2745 { 2745 {
2746 atmp += std::abs(work[i]); 2746 atmp += std::abs(work[i]);
2747 work[i] = 0.; 2747 work[i] = 0.;
2748 } 2748 }
2749 if (atmp > ainvnorm) 2749 if (atmp > ainvnorm)
2750 ainvnorm = atmp; 2750 ainvnorm = atmp;
2751 } 2751 }
2752 rcond = 1. / ainvnorm / anorm; 2752 rcond = 1. / ainvnorm / anorm;
2753 } 2753 }
2754 } 2754 }
2755 else 2755 else
2756 { 2756 {
2757 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2757 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
2758 retval.resize (nc, b_nc, 0.); 2758 retval.resize (nc, b_nc, 0.);
2759 2759
2760 for (octave_idx_type j = 0; j < b_nc; j++) 2760 for (octave_idx_type j = 0; j < b_nc; j++)
2761 { 2761 {
2762 for (octave_idx_type i = 0; i < nr; i++) 2762 for (octave_idx_type i = 0; i < nr; i++)
2763 work[i] = b(i,j); 2763 work[i] = b(i,j);
2764 for (octave_idx_type i = nr; i < nc; i++) 2764 for (octave_idx_type i = nr; i < nc; i++)
2765 work[i] = 0.; 2765 work[i] = 0.;
2766 for (octave_idx_type k = 0; k < nc; k++) 2766 for (octave_idx_type k = 0; k < nc; k++)
2767 { 2767 {
2768 if (work[k] != 0.) 2768 if (work[k] != 0.)
2769 { 2769 {
2770 if (ridx(cidx(k)) != k || 2770 if (ridx(cidx(k)) != k ||
2771 data(cidx(k)) == 0.) 2771 data(cidx(k)) == 0.)
2772 { 2772 {
2773 err = -2; 2773 err = -2;
2774 goto triangular_error; 2774 goto triangular_error;
2775 } 2775 }
2776 2776
2777 Complex tmp = work[k] / data(cidx(k)); 2777 Complex tmp = work[k] / data(cidx(k));
2778 work[k] = tmp; 2778 work[k] = tmp;
2779 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) 2779 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++)
2780 { 2780 {
2781 octave_idx_type iidx = ridx(i); 2781 octave_idx_type iidx = ridx(i);
2782 work[iidx] = work[iidx] - tmp * data(i); 2782 work[iidx] = work[iidx] - tmp * data(i);
2783 } 2783 }
2784 } 2784 }
2785 } 2785 }
2786 for (octave_idx_type i = 0; i < nc; i++) 2786 for (octave_idx_type i = 0; i < nc; i++)
2787 retval.xelem (i, j) = work[i]; 2787 retval.xelem (i, j) = work[i];
2788 } 2788 }
2789 2789
2790 if (calc_cond) 2790 if (calc_cond)
2791 { 2791 {
2792 // Calculation of 1-norm of inv(*this) 2792 // Calculation of 1-norm of inv(*this)
2793 for (octave_idx_type i = 0; i < nm; i++) 2793 for (octave_idx_type i = 0; i < nm; i++)
2794 work[i] = 0.; 2794 work[i] = 0.;
2795 2795
2796 for (octave_idx_type j = 0; j < nr; j++) 2796 for (octave_idx_type j = 0; j < nr; j++)
2797 { 2797 {
2798 work[j] = 1.; 2798 work[j] = 1.;
2799 2799
2800 for (octave_idx_type k = j; k < nc; k++) 2800 for (octave_idx_type k = j; k < nc; k++)
2801 { 2801 {
2802 2802
2803 if (work[k] != 0.) 2803 if (work[k] != 0.)
2804 { 2804 {
2805 Complex tmp = work[k] / data(cidx(k)); 2805 Complex tmp = work[k] / data(cidx(k));
2806 work[k] = tmp; 2806 work[k] = tmp;
2807 for (octave_idx_type i = cidx(k)+1; 2807 for (octave_idx_type i = cidx(k)+1;
2808 i < cidx(k+1); i++) 2808 i < cidx(k+1); i++)
2809 { 2809 {
2810 octave_idx_type iidx = ridx(i); 2810 octave_idx_type iidx = ridx(i);
2811 work[iidx] = work[iidx] - tmp * data(i); 2811 work[iidx] = work[iidx] - tmp * data(i);
2812 } 2812 }
2813 } 2813 }
2814 } 2814 }
2815 double atmp = 0; 2815 double atmp = 0;
2816 for (octave_idx_type i = j; i < nc; i++) 2816 for (octave_idx_type i = j; i < nc; i++)
2817 { 2817 {
2818 atmp += std::abs(work[i]); 2818 atmp += std::abs(work[i]);
2819 work[i] = 0.; 2819 work[i] = 0.;
2820 } 2820 }
2821 if (atmp > ainvnorm) 2821 if (atmp > ainvnorm)
2822 ainvnorm = atmp; 2822 ainvnorm = atmp;
2823 } 2823 }
2824 rcond = 1. / ainvnorm / anorm; 2824 rcond = 1. / ainvnorm / anorm;
2825 } 2825 }
2826 } 2826 }
2827 triangular_error: 2827 triangular_error:
2828 if (err != 0) 2828 if (err != 0)
2829 { 2829 {
2830 if (sing_handler) 2830 if (sing_handler)
2831 { 2831 {
2832 sing_handler (rcond); 2832 sing_handler (rcond);
2833 mattype.mark_as_rectangular (); 2833 mattype.mark_as_rectangular ();
2834 } 2834 }
2835 else 2835 else
2836 (*current_liboctave_error_handler) 2836 (*current_liboctave_error_handler)
2837 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 2837 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
2838 rcond); 2838 rcond);
2839 } 2839 }
2840 2840
2841 volatile double rcond_plus_one = rcond + 1.0; 2841 volatile double rcond_plus_one = rcond + 1.0;
2842 2842
2843 if (rcond_plus_one == 1.0 || xisnan (rcond)) 2843 if (rcond_plus_one == 1.0 || xisnan (rcond))
2844 { 2844 {
2845 err = -2; 2845 err = -2;
2846 2846
2847 if (sing_handler) 2847 if (sing_handler)
2848 { 2848 {
2849 sing_handler (rcond); 2849 sing_handler (rcond);
2850 mattype.mark_as_rectangular (); 2850 mattype.mark_as_rectangular ();
2851 } 2851 }
2852 else 2852 else
2853 (*current_liboctave_error_handler) 2853 (*current_liboctave_error_handler)
2854 ("matrix singular to machine precision, rcond = %g", 2854 ("matrix singular to machine precision, rcond = %g",
2855 rcond); 2855 rcond);
2856 } 2856 }
2857 } 2857 }
2858 else 2858 else
2859 (*current_liboctave_error_handler) ("incorrect matrix type"); 2859 (*current_liboctave_error_handler) ("incorrect matrix type");
2860 } 2860 }
2861 2861
2862 return retval; 2862 return retval;
2863 } 2863 }
2864 2864
2865 SparseComplexMatrix 2865 SparseComplexMatrix
2866 SparseComplexMatrix::ltsolve (MatrixType &mattype, const SparseMatrix& b, 2866 SparseComplexMatrix::ltsolve (MatrixType &mattype, const SparseMatrix& b,
2867 octave_idx_type& err, double& rcond, 2867 octave_idx_type& err, double& rcond,
2868 solve_singularity_handler sing_handler, 2868 solve_singularity_handler sing_handler,
2869 bool calc_cond) const 2869 bool calc_cond) const
2870 { 2870 {
2871 SparseComplexMatrix retval; 2871 SparseComplexMatrix retval;
2872 2872
2873 octave_idx_type nr = rows (); 2873 octave_idx_type nr = rows ();
2874 octave_idx_type nc = cols (); 2874 octave_idx_type nc = cols ();
2886 // Print spparms("spumoni") info if requested 2886 // Print spparms("spumoni") info if requested
2887 int typ = mattype.type (); 2887 int typ = mattype.type ();
2888 mattype.info (); 2888 mattype.info ();
2889 2889
2890 if (typ == MatrixType::Permuted_Lower || 2890 if (typ == MatrixType::Permuted_Lower ||
2891 typ == MatrixType::Lower) 2891 typ == MatrixType::Lower)
2892 { 2892 {
2893 double anorm = 0.; 2893 double anorm = 0.;
2894 double ainvnorm = 0.; 2894 double ainvnorm = 0.;
2895 rcond = 1.; 2895 rcond = 1.;
2896 2896
2897 if (calc_cond) 2897 if (calc_cond)
2898 { 2898 {
2899 // Calculate the 1-norm of matrix for rcond calculation 2899 // Calculate the 1-norm of matrix for rcond calculation
2900 for (octave_idx_type j = 0; j < nc; j++) 2900 for (octave_idx_type j = 0; j < nc; j++)
2901 { 2901 {
2902 double atmp = 0.; 2902 double atmp = 0.;
2903 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 2903 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
2904 atmp += std::abs(data(i)); 2904 atmp += std::abs(data(i));
2905 if (atmp > anorm) 2905 if (atmp > anorm)
2906 anorm = atmp; 2906 anorm = atmp;
2907 } 2907 }
2908 } 2908 }
2909 2909
2910 octave_idx_type b_nc = b.cols (); 2910 octave_idx_type b_nc = b.cols ();
2911 octave_idx_type b_nz = b.nnz (); 2911 octave_idx_type b_nz = b.nnz ();
2912 retval = SparseComplexMatrix (nc, b_nc, b_nz); 2912 retval = SparseComplexMatrix (nc, b_nc, b_nz);
2913 retval.xcidx(0) = 0; 2913 retval.xcidx(0) = 0;
2914 octave_idx_type ii = 0; 2914 octave_idx_type ii = 0;
2915 octave_idx_type x_nz = b_nz; 2915 octave_idx_type x_nz = b_nz;
2916 2916
2917 if (typ == MatrixType::Permuted_Lower) 2917 if (typ == MatrixType::Permuted_Lower)
2918 { 2918 {
2919 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 2919 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
2920 octave_idx_type *perm = mattype.triangular_perm (); 2920 octave_idx_type *perm = mattype.triangular_perm ();
2921 2921
2922 for (octave_idx_type j = 0; j < b_nc; j++) 2922 for (octave_idx_type j = 0; j < b_nc; j++)
2923 { 2923 {
2924 for (octave_idx_type i = 0; i < nm; i++) 2924 for (octave_idx_type i = 0; i < nm; i++)
2925 work[i] = 0.; 2925 work[i] = 0.;
2926 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 2926 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
2927 work[perm[b.ridx(i)]] = b.data(i); 2927 work[perm[b.ridx(i)]] = b.data(i);
2928 2928
2929 for (octave_idx_type k = 0; k < nc; k++) 2929 for (octave_idx_type k = 0; k < nc; k++)
2930 { 2930 {
2931 if (work[k] != 0.) 2931 if (work[k] != 0.)
2932 { 2932 {
2933 octave_idx_type minr = nr; 2933 octave_idx_type minr = nr;
2934 octave_idx_type mini = 0; 2934 octave_idx_type mini = 0;
2935 2935
2936 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 2936 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
2937 if (perm[ridx(i)] < minr) 2937 if (perm[ridx(i)] < minr)
2938 { 2938 {
2939 minr = perm[ridx(i)]; 2939 minr = perm[ridx(i)];
2940 mini = i; 2940 mini = i;
2941 } 2941 }
2942 2942
2943 if (minr != k || data (mini) == 0.) 2943 if (minr != k || data (mini) == 0.)
2944 { 2944 {
2945 err = -2; 2945 err = -2;
2946 goto triangular_error; 2946 goto triangular_error;
2947 } 2947 }
2948 2948
2949 Complex tmp = work[k] / data(mini); 2949 Complex tmp = work[k] / data(mini);
2950 work[k] = tmp; 2950 work[k] = tmp;
2951 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 2951 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
2952 { 2952 {
2953 if (i == mini) 2953 if (i == mini)
2954 continue; 2954 continue;
2955 2955
2956 octave_idx_type iidx = perm[ridx(i)]; 2956 octave_idx_type iidx = perm[ridx(i)];
2957 work[iidx] = work[iidx] - tmp * data(i); 2957 work[iidx] = work[iidx] - tmp * data(i);
2958 } 2958 }
2959 } 2959 }
2960 } 2960 }
2961 2961
2962 // Count non-zeros in work vector and adjust space in 2962 // Count non-zeros in work vector and adjust space in
2963 // retval if needed 2963 // retval if needed
2964 octave_idx_type new_nnz = 0; 2964 octave_idx_type new_nnz = 0;
2965 for (octave_idx_type i = 0; i < nc; i++) 2965 for (octave_idx_type i = 0; i < nc; i++)
2966 if (work[i] != 0.) 2966 if (work[i] != 0.)
2967 new_nnz++; 2967 new_nnz++;
2968 2968
2969 if (ii + new_nnz > x_nz) 2969 if (ii + new_nnz > x_nz)
2970 { 2970 {
2971 // Resize the sparse matrix 2971 // Resize the sparse matrix
2972 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 2972 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
2973 retval.change_capacity (sz); 2973 retval.change_capacity (sz);
2974 x_nz = sz; 2974 x_nz = sz;
2975 } 2975 }
2976 2976
2977 for (octave_idx_type i = 0; i < nc; i++) 2977 for (octave_idx_type i = 0; i < nc; i++)
2978 if (work[i] != 0.) 2978 if (work[i] != 0.)
2979 { 2979 {
2980 retval.xridx(ii) = i; 2980 retval.xridx(ii) = i;
2981 retval.xdata(ii++) = work[i]; 2981 retval.xdata(ii++) = work[i];
2982 } 2982 }
2983 retval.xcidx(j+1) = ii; 2983 retval.xcidx(j+1) = ii;
2984 } 2984 }
2985 2985
2986 retval.maybe_compress (); 2986 retval.maybe_compress ();
2987 2987
2988 if (calc_cond) 2988 if (calc_cond)
2989 { 2989 {
2990 // Calculation of 1-norm of inv(*this) 2990 // Calculation of 1-norm of inv(*this)
2991 for (octave_idx_type i = 0; i < nm; i++) 2991 for (octave_idx_type i = 0; i < nm; i++)
2992 work[i] = 0.; 2992 work[i] = 0.;
2993 2993
2994 for (octave_idx_type j = 0; j < nr; j++) 2994 for (octave_idx_type j = 0; j < nr; j++)
2995 { 2995 {
2996 work[j] = 1.; 2996 work[j] = 1.;
2997 2997
2998 for (octave_idx_type k = 0; k < nc; k++) 2998 for (octave_idx_type k = 0; k < nc; k++)
2999 { 2999 {
3000 if (work[k] != 0.) 3000 if (work[k] != 0.)
3001 { 3001 {
3002 octave_idx_type minr = nr; 3002 octave_idx_type minr = nr;
3003 octave_idx_type mini = 0; 3003 octave_idx_type mini = 0;
3004 3004
3005 for (octave_idx_type i = cidx(k); 3005 for (octave_idx_type i = cidx(k);
3006 i < cidx(k+1); i++) 3006 i < cidx(k+1); i++)
3007 if (perm[ridx(i)] < minr) 3007 if (perm[ridx(i)] < minr)
3008 { 3008 {
3009 minr = perm[ridx(i)]; 3009 minr = perm[ridx(i)];
3010 mini = i; 3010 mini = i;
3011 } 3011 }
3012 3012
3013 Complex tmp = work[k] / data(mini); 3013 Complex tmp = work[k] / data(mini);
3014 work[k] = tmp; 3014 work[k] = tmp;
3015 for (octave_idx_type i = cidx(k); 3015 for (octave_idx_type i = cidx(k);
3016 i < cidx(k+1); i++) 3016 i < cidx(k+1); i++)
3017 { 3017 {
3018 if (i == mini) 3018 if (i == mini)
3019 continue; 3019 continue;
3020 3020
3021 octave_idx_type iidx = perm[ridx(i)]; 3021 octave_idx_type iidx = perm[ridx(i)];
3022 work[iidx] = work[iidx] - tmp * data(i); 3022 work[iidx] = work[iidx] - tmp * data(i);
3023 } 3023 }
3024 } 3024 }
3025 } 3025 }
3026 3026
3027 double atmp = 0; 3027 double atmp = 0;
3028 for (octave_idx_type i = j; i < nc; i++) 3028 for (octave_idx_type i = j; i < nc; i++)
3029 { 3029 {
3030 atmp += std::abs(work[i]); 3030 atmp += std::abs(work[i]);
3031 work[i] = 0.; 3031 work[i] = 0.;
3032 } 3032 }
3033 if (atmp > ainvnorm) 3033 if (atmp > ainvnorm)
3034 ainvnorm = atmp; 3034 ainvnorm = atmp;
3035 } 3035 }
3036 rcond = 1. / ainvnorm / anorm; 3036 rcond = 1. / ainvnorm / anorm;
3037 } 3037 }
3038 } 3038 }
3039 else 3039 else
3040 { 3040 {
3041 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 3041 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
3042 3042
3043 for (octave_idx_type j = 0; j < b_nc; j++) 3043 for (octave_idx_type j = 0; j < b_nc; j++)
3044 { 3044 {
3045 for (octave_idx_type i = 0; i < nm; i++) 3045 for (octave_idx_type i = 0; i < nm; i++)
3046 work[i] = 0.; 3046 work[i] = 0.;
3047 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 3047 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
3048 work[b.ridx(i)] = b.data(i); 3048 work[b.ridx(i)] = b.data(i);
3049 3049
3050 for (octave_idx_type k = 0; k < nc; k++) 3050 for (octave_idx_type k = 0; k < nc; k++)
3051 { 3051 {
3052 if (work[k] != 0.) 3052 if (work[k] != 0.)
3053 { 3053 {
3054 if (ridx(cidx(k)) != k || 3054 if (ridx(cidx(k)) != k ||
3055 data(cidx(k)) == 0.) 3055 data(cidx(k)) == 0.)
3056 { 3056 {
3057 err = -2; 3057 err = -2;
3058 goto triangular_error; 3058 goto triangular_error;
3059 } 3059 }
3060 3060
3061 Complex tmp = work[k] / data(cidx(k)); 3061 Complex tmp = work[k] / data(cidx(k));
3062 work[k] = tmp; 3062 work[k] = tmp;
3063 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) 3063 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++)
3064 { 3064 {
3065 octave_idx_type iidx = ridx(i); 3065 octave_idx_type iidx = ridx(i);
3066 work[iidx] = work[iidx] - tmp * data(i); 3066 work[iidx] = work[iidx] - tmp * data(i);
3067 } 3067 }
3068 } 3068 }
3069 } 3069 }
3070 3070
3071 // Count non-zeros in work vector and adjust space in 3071 // Count non-zeros in work vector and adjust space in
3072 // retval if needed 3072 // retval if needed
3073 octave_idx_type new_nnz = 0; 3073 octave_idx_type new_nnz = 0;
3074 for (octave_idx_type i = 0; i < nc; i++) 3074 for (octave_idx_type i = 0; i < nc; i++)
3075 if (work[i] != 0.) 3075 if (work[i] != 0.)
3076 new_nnz++; 3076 new_nnz++;
3077 3077
3078 if (ii + new_nnz > x_nz) 3078 if (ii + new_nnz > x_nz)
3079 { 3079 {
3080 // Resize the sparse matrix 3080 // Resize the sparse matrix
3081 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 3081 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
3082 retval.change_capacity (sz); 3082 retval.change_capacity (sz);
3083 x_nz = sz; 3083 x_nz = sz;
3084 } 3084 }
3085 3085
3086 for (octave_idx_type i = 0; i < nc; i++) 3086 for (octave_idx_type i = 0; i < nc; i++)
3087 if (work[i] != 0.) 3087 if (work[i] != 0.)
3088 { 3088 {
3089 retval.xridx(ii) = i; 3089 retval.xridx(ii) = i;
3090 retval.xdata(ii++) = work[i]; 3090 retval.xdata(ii++) = work[i];
3091 } 3091 }
3092 retval.xcidx(j+1) = ii; 3092 retval.xcidx(j+1) = ii;
3093 } 3093 }
3094 3094
3095 retval.maybe_compress (); 3095 retval.maybe_compress ();
3096 3096
3097 if (calc_cond) 3097 if (calc_cond)
3098 { 3098 {
3099 // Calculation of 1-norm of inv(*this) 3099 // Calculation of 1-norm of inv(*this)
3100 for (octave_idx_type i = 0; i < nm; i++) 3100 for (octave_idx_type i = 0; i < nm; i++)
3101 work[i] = 0.; 3101 work[i] = 0.;
3102 3102
3103 for (octave_idx_type j = 0; j < nr; j++) 3103 for (octave_idx_type j = 0; j < nr; j++)
3104 { 3104 {
3105 work[j] = 1.; 3105 work[j] = 1.;
3106 3106
3107 for (octave_idx_type k = j; k < nc; k++) 3107 for (octave_idx_type k = j; k < nc; k++)
3108 { 3108 {
3109 3109
3110 if (work[k] != 0.) 3110 if (work[k] != 0.)
3111 { 3111 {
3112 Complex tmp = work[k] / data(cidx(k)); 3112 Complex tmp = work[k] / data(cidx(k));
3113 work[k] = tmp; 3113 work[k] = tmp;
3114 for (octave_idx_type i = cidx(k)+1; 3114 for (octave_idx_type i = cidx(k)+1;
3115 i < cidx(k+1); i++) 3115 i < cidx(k+1); i++)
3116 { 3116 {
3117 octave_idx_type iidx = ridx(i); 3117 octave_idx_type iidx = ridx(i);
3118 work[iidx] = work[iidx] - tmp * data(i); 3118 work[iidx] = work[iidx] - tmp * data(i);
3119 } 3119 }
3120 } 3120 }
3121 } 3121 }
3122 double atmp = 0; 3122 double atmp = 0;
3123 for (octave_idx_type i = j; i < nc; i++) 3123 for (octave_idx_type i = j; i < nc; i++)
3124 { 3124 {
3125 atmp += std::abs(work[i]); 3125 atmp += std::abs(work[i]);
3126 work[i] = 0.; 3126 work[i] = 0.;
3127 } 3127 }
3128 if (atmp > ainvnorm) 3128 if (atmp > ainvnorm)
3129 ainvnorm = atmp; 3129 ainvnorm = atmp;
3130 } 3130 }
3131 rcond = 1. / ainvnorm / anorm; 3131 rcond = 1. / ainvnorm / anorm;
3132 } 3132 }
3133 } 3133 }
3134 3134
3135 triangular_error: 3135 triangular_error:
3136 if (err != 0) 3136 if (err != 0)
3137 { 3137 {
3138 if (sing_handler) 3138 if (sing_handler)
3139 { 3139 {
3140 sing_handler (rcond); 3140 sing_handler (rcond);
3141 mattype.mark_as_rectangular (); 3141 mattype.mark_as_rectangular ();
3142 } 3142 }
3143 else 3143 else
3144 (*current_liboctave_error_handler) 3144 (*current_liboctave_error_handler)
3145 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 3145 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
3146 rcond); 3146 rcond);
3147 } 3147 }
3148 3148
3149 volatile double rcond_plus_one = rcond + 1.0; 3149 volatile double rcond_plus_one = rcond + 1.0;
3150 3150
3151 if (rcond_plus_one == 1.0 || xisnan (rcond)) 3151 if (rcond_plus_one == 1.0 || xisnan (rcond))
3152 { 3152 {
3153 err = -2; 3153 err = -2;
3154 3154
3155 if (sing_handler) 3155 if (sing_handler)
3156 { 3156 {
3157 sing_handler (rcond); 3157 sing_handler (rcond);
3158 mattype.mark_as_rectangular (); 3158 mattype.mark_as_rectangular ();
3159 } 3159 }
3160 else 3160 else
3161 (*current_liboctave_error_handler) 3161 (*current_liboctave_error_handler)
3162 ("matrix singular to machine precision, rcond = %g", 3162 ("matrix singular to machine precision, rcond = %g",
3163 rcond); 3163 rcond);
3164 } 3164 }
3165 } 3165 }
3166 else 3166 else
3167 (*current_liboctave_error_handler) ("incorrect matrix type"); 3167 (*current_liboctave_error_handler) ("incorrect matrix type");
3168 } 3168 }
3169 3169
3170 return retval; 3170 return retval;
3171 } 3171 }
3172 3172
3173 ComplexMatrix 3173 ComplexMatrix
3174 SparseComplexMatrix::ltsolve (MatrixType &mattype, const ComplexMatrix& b, 3174 SparseComplexMatrix::ltsolve (MatrixType &mattype, const ComplexMatrix& b,
3175 octave_idx_type& err, double& rcond, 3175 octave_idx_type& err, double& rcond,
3176 solve_singularity_handler sing_handler, 3176 solve_singularity_handler sing_handler,
3177 bool calc_cond) const 3177 bool calc_cond) const
3178 { 3178 {
3179 ComplexMatrix retval; 3179 ComplexMatrix retval;
3180 3180
3181 octave_idx_type nr = rows (); 3181 octave_idx_type nr = rows ();
3182 octave_idx_type nc = cols (); 3182 octave_idx_type nc = cols ();
3193 // Print spparms("spumoni") info if requested 3193 // Print spparms("spumoni") info if requested
3194 int typ = mattype.type (); 3194 int typ = mattype.type ();
3195 mattype.info (); 3195 mattype.info ();
3196 3196
3197 if (typ == MatrixType::Permuted_Lower || 3197 if (typ == MatrixType::Permuted_Lower ||
3198 typ == MatrixType::Lower) 3198 typ == MatrixType::Lower)
3199 { 3199 {
3200 double anorm = 0.; 3200 double anorm = 0.;
3201 double ainvnorm = 0.; 3201 double ainvnorm = 0.;
3202 octave_idx_type b_nc = b.cols (); 3202 octave_idx_type b_nc = b.cols ();
3203 rcond = 1.; 3203 rcond = 1.;
3204 3204
3205 if (calc_cond) 3205 if (calc_cond)
3206 { 3206 {
3207 // Calculate the 1-norm of matrix for rcond calculation 3207 // Calculate the 1-norm of matrix for rcond calculation
3208 for (octave_idx_type j = 0; j < nc; j++) 3208 for (octave_idx_type j = 0; j < nc; j++)
3209 { 3209 {
3210 double atmp = 0.; 3210 double atmp = 0.;
3211 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 3211 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
3212 atmp += std::abs(data(i)); 3212 atmp += std::abs(data(i));
3213 if (atmp > anorm) 3213 if (atmp > anorm)
3214 anorm = atmp; 3214 anorm = atmp;
3215 } 3215 }
3216 } 3216 }
3217 3217
3218 if (typ == MatrixType::Permuted_Lower) 3218 if (typ == MatrixType::Permuted_Lower)
3219 { 3219 {
3220 retval.resize (nc, b_nc); 3220 retval.resize (nc, b_nc);
3221 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 3221 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
3222 octave_idx_type *perm = mattype.triangular_perm (); 3222 octave_idx_type *perm = mattype.triangular_perm ();
3223 3223
3224 for (octave_idx_type j = 0; j < b_nc; j++) 3224 for (octave_idx_type j = 0; j < b_nc; j++)
3225 { 3225 {
3226 for (octave_idx_type i = 0; i < nm; i++) 3226 for (octave_idx_type i = 0; i < nm; i++)
3227 work[i] = 0.; 3227 work[i] = 0.;
3228 for (octave_idx_type i = 0; i < nr; i++) 3228 for (octave_idx_type i = 0; i < nr; i++)
3229 work[perm[i]] = b(i,j); 3229 work[perm[i]] = b(i,j);
3230 3230
3231 for (octave_idx_type k = 0; k < nc; k++) 3231 for (octave_idx_type k = 0; k < nc; k++)
3232 { 3232 {
3233 if (work[k] != 0.) 3233 if (work[k] != 0.)
3234 { 3234 {
3235 octave_idx_type minr = nr; 3235 octave_idx_type minr = nr;
3236 octave_idx_type mini = 0; 3236 octave_idx_type mini = 0;
3237 3237
3238 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 3238 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
3239 if (perm[ridx(i)] < minr) 3239 if (perm[ridx(i)] < minr)
3240 { 3240 {
3241 minr = perm[ridx(i)]; 3241 minr = perm[ridx(i)];
3242 mini = i; 3242 mini = i;
3243 } 3243 }
3244 3244
3245 if (minr != k || data (mini) == 0.) 3245 if (minr != k || data (mini) == 0.)
3246 { 3246 {
3247 err = -2; 3247 err = -2;
3248 goto triangular_error; 3248 goto triangular_error;
3249 } 3249 }
3250 3250
3251 Complex tmp = work[k] / data(mini); 3251 Complex tmp = work[k] / data(mini);
3252 work[k] = tmp; 3252 work[k] = tmp;
3253 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 3253 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
3254 { 3254 {
3255 if (i == mini) 3255 if (i == mini)
3256 continue; 3256 continue;
3257 3257
3258 octave_idx_type iidx = perm[ridx(i)]; 3258 octave_idx_type iidx = perm[ridx(i)];
3259 work[iidx] = work[iidx] - tmp * data(i); 3259 work[iidx] = work[iidx] - tmp * data(i);
3260 } 3260 }
3261 } 3261 }
3262 } 3262 }
3263 3263
3264 for (octave_idx_type i = 0; i < nc; i++) 3264 for (octave_idx_type i = 0; i < nc; i++)
3265 retval (i, j) = work[i]; 3265 retval (i, j) = work[i];
3266 } 3266 }
3267 3267
3268 if (calc_cond) 3268 if (calc_cond)
3269 { 3269 {
3270 // Calculation of 1-norm of inv(*this) 3270 // Calculation of 1-norm of inv(*this)
3271 for (octave_idx_type i = 0; i < nm; i++) 3271 for (octave_idx_type i = 0; i < nm; i++)
3272 work[i] = 0.; 3272 work[i] = 0.;
3273 3273
3274 for (octave_idx_type j = 0; j < nr; j++) 3274 for (octave_idx_type j = 0; j < nr; j++)
3275 { 3275 {
3276 work[j] = 1.; 3276 work[j] = 1.;
3277 3277
3278 for (octave_idx_type k = 0; k < nc; k++) 3278 for (octave_idx_type k = 0; k < nc; k++)
3279 { 3279 {
3280 if (work[k] != 0.) 3280 if (work[k] != 0.)
3281 { 3281 {
3282 octave_idx_type minr = nr; 3282 octave_idx_type minr = nr;
3283 octave_idx_type mini = 0; 3283 octave_idx_type mini = 0;
3284 3284
3285 for (octave_idx_type i = cidx(k); 3285 for (octave_idx_type i = cidx(k);
3286 i < cidx(k+1); i++) 3286 i < cidx(k+1); i++)
3287 if (perm[ridx(i)] < minr) 3287 if (perm[ridx(i)] < minr)
3288 { 3288 {
3289 minr = perm[ridx(i)]; 3289 minr = perm[ridx(i)];
3290 mini = i; 3290 mini = i;
3291 } 3291 }
3292 3292
3293 Complex tmp = work[k] / data(mini); 3293 Complex tmp = work[k] / data(mini);
3294 work[k] = tmp; 3294 work[k] = tmp;
3295 for (octave_idx_type i = cidx(k); 3295 for (octave_idx_type i = cidx(k);
3296 i < cidx(k+1); i++) 3296 i < cidx(k+1); i++)
3297 { 3297 {
3298 if (i == mini) 3298 if (i == mini)
3299 continue; 3299 continue;
3300 3300
3301 octave_idx_type iidx = perm[ridx(i)]; 3301 octave_idx_type iidx = perm[ridx(i)];
3302 work[iidx] = work[iidx] - tmp * data(i); 3302 work[iidx] = work[iidx] - tmp * data(i);
3303 } 3303 }
3304 } 3304 }
3305 } 3305 }
3306 3306
3307 double atmp = 0; 3307 double atmp = 0;
3308 for (octave_idx_type i = j; i < nc; i++) 3308 for (octave_idx_type i = j; i < nc; i++)
3309 { 3309 {
3310 atmp += std::abs(work[i]); 3310 atmp += std::abs(work[i]);
3311 work[i] = 0.; 3311 work[i] = 0.;
3312 } 3312 }
3313 if (atmp > ainvnorm) 3313 if (atmp > ainvnorm)
3314 ainvnorm = atmp; 3314 ainvnorm = atmp;
3315 } 3315 }
3316 rcond = 1. / ainvnorm / anorm; 3316 rcond = 1. / ainvnorm / anorm;
3317 } 3317 }
3318 } 3318 }
3319 else 3319 else
3320 { 3320 {
3321 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 3321 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
3322 retval.resize (nc, b_nc, 0.); 3322 retval.resize (nc, b_nc, 0.);
3323 3323
3324 3324
3325 for (octave_idx_type j = 0; j < b_nc; j++) 3325 for (octave_idx_type j = 0; j < b_nc; j++)
3326 { 3326 {
3327 for (octave_idx_type i = 0; i < nr; i++) 3327 for (octave_idx_type i = 0; i < nr; i++)
3328 work[i] = b(i,j); 3328 work[i] = b(i,j);
3329 for (octave_idx_type i = nr; i < nc; i++) 3329 for (octave_idx_type i = nr; i < nc; i++)
3330 work[i] = 0.; 3330 work[i] = 0.;
3331 3331
3332 for (octave_idx_type k = 0; k < nc; k++) 3332 for (octave_idx_type k = 0; k < nc; k++)
3333 { 3333 {
3334 if (work[k] != 0.) 3334 if (work[k] != 0.)
3335 { 3335 {
3336 if (ridx(cidx(k)) != k || 3336 if (ridx(cidx(k)) != k ||
3337 data(cidx(k)) == 0.) 3337 data(cidx(k)) == 0.)
3338 { 3338 {
3339 err = -2; 3339 err = -2;
3340 goto triangular_error; 3340 goto triangular_error;
3341 } 3341 }
3342 3342
3343 Complex tmp = work[k] / data(cidx(k)); 3343 Complex tmp = work[k] / data(cidx(k));
3344 work[k] = tmp; 3344 work[k] = tmp;
3345 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) 3345 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++)
3346 { 3346 {
3347 octave_idx_type iidx = ridx(i); 3347 octave_idx_type iidx = ridx(i);
3348 work[iidx] = work[iidx] - tmp * data(i); 3348 work[iidx] = work[iidx] - tmp * data(i);
3349 } 3349 }
3350 } 3350 }
3351 } 3351 }
3352 3352
3353 for (octave_idx_type i = 0; i < nc; i++) 3353 for (octave_idx_type i = 0; i < nc; i++)
3354 retval.xelem (i, j) = work[i]; 3354 retval.xelem (i, j) = work[i];
3355 } 3355 }
3356 3356
3357 if (calc_cond) 3357 if (calc_cond)
3358 { 3358 {
3359 // Calculation of 1-norm of inv(*this) 3359 // Calculation of 1-norm of inv(*this)
3360 for (octave_idx_type i = 0; i < nm; i++) 3360 for (octave_idx_type i = 0; i < nm; i++)
3361 work[i] = 0.; 3361 work[i] = 0.;
3362 3362
3363 for (octave_idx_type j = 0; j < nr; j++) 3363 for (octave_idx_type j = 0; j < nr; j++)
3364 { 3364 {
3365 work[j] = 1.; 3365 work[j] = 1.;
3366 3366
3367 for (octave_idx_type k = j; k < nc; k++) 3367 for (octave_idx_type k = j; k < nc; k++)
3368 { 3368 {
3369 3369
3370 if (work[k] != 0.) 3370 if (work[k] != 0.)
3371 { 3371 {
3372 Complex tmp = work[k] / data(cidx(k)); 3372 Complex tmp = work[k] / data(cidx(k));
3373 work[k] = tmp; 3373 work[k] = tmp;
3374 for (octave_idx_type i = cidx(k)+1; 3374 for (octave_idx_type i = cidx(k)+1;
3375 i < cidx(k+1); i++) 3375 i < cidx(k+1); i++)
3376 { 3376 {
3377 octave_idx_type iidx = ridx(i); 3377 octave_idx_type iidx = ridx(i);
3378 work[iidx] = work[iidx] - tmp * data(i); 3378 work[iidx] = work[iidx] - tmp * data(i);
3379 } 3379 }
3380 } 3380 }
3381 } 3381 }
3382 double atmp = 0; 3382 double atmp = 0;
3383 for (octave_idx_type i = j; i < nc; i++) 3383 for (octave_idx_type i = j; i < nc; i++)
3384 { 3384 {
3385 atmp += std::abs(work[i]); 3385 atmp += std::abs(work[i]);
3386 work[i] = 0.; 3386 work[i] = 0.;
3387 } 3387 }
3388 if (atmp > ainvnorm) 3388 if (atmp > ainvnorm)
3389 ainvnorm = atmp; 3389 ainvnorm = atmp;
3390 } 3390 }
3391 rcond = 1. / ainvnorm / anorm; 3391 rcond = 1. / ainvnorm / anorm;
3392 } 3392 }
3393 } 3393 }
3394 3394
3395 triangular_error: 3395 triangular_error:
3396 if (err != 0) 3396 if (err != 0)
3397 { 3397 {
3398 if (sing_handler) 3398 if (sing_handler)
3399 { 3399 {
3400 sing_handler (rcond); 3400 sing_handler (rcond);
3401 mattype.mark_as_rectangular (); 3401 mattype.mark_as_rectangular ();
3402 } 3402 }
3403 else 3403 else
3404 (*current_liboctave_error_handler) 3404 (*current_liboctave_error_handler)
3405 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 3405 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
3406 rcond); 3406 rcond);
3407 } 3407 }
3408 3408
3409 volatile double rcond_plus_one = rcond + 1.0; 3409 volatile double rcond_plus_one = rcond + 1.0;
3410 3410
3411 if (rcond_plus_one == 1.0 || xisnan (rcond)) 3411 if (rcond_plus_one == 1.0 || xisnan (rcond))
3412 { 3412 {
3413 err = -2; 3413 err = -2;
3414 3414
3415 if (sing_handler) 3415 if (sing_handler)
3416 { 3416 {
3417 sing_handler (rcond); 3417 sing_handler (rcond);
3418 mattype.mark_as_rectangular (); 3418 mattype.mark_as_rectangular ();
3419 } 3419 }
3420 else 3420 else
3421 (*current_liboctave_error_handler) 3421 (*current_liboctave_error_handler)
3422 ("matrix singular to machine precision, rcond = %g", 3422 ("matrix singular to machine precision, rcond = %g",
3423 rcond); 3423 rcond);
3424 } 3424 }
3425 } 3425 }
3426 else 3426 else
3427 (*current_liboctave_error_handler) ("incorrect matrix type"); 3427 (*current_liboctave_error_handler) ("incorrect matrix type");
3428 } 3428 }
3429 3429
3430 return retval; 3430 return retval;
3431 } 3431 }
3432 3432
3433 SparseComplexMatrix 3433 SparseComplexMatrix
3434 SparseComplexMatrix::ltsolve (MatrixType &mattype, const SparseComplexMatrix& b, 3434 SparseComplexMatrix::ltsolve (MatrixType &mattype, const SparseComplexMatrix& b,
3435 octave_idx_type& err, double& rcond, 3435 octave_idx_type& err, double& rcond,
3436 solve_singularity_handler sing_handler, 3436 solve_singularity_handler sing_handler,
3437 bool calc_cond) const 3437 bool calc_cond) const
3438 { 3438 {
3439 SparseComplexMatrix retval; 3439 SparseComplexMatrix retval;
3440 3440
3441 octave_idx_type nr = rows (); 3441 octave_idx_type nr = rows ();
3442 octave_idx_type nc = cols (); 3442 octave_idx_type nc = cols ();
3453 // Print spparms("spumoni") info if requested 3453 // Print spparms("spumoni") info if requested
3454 int typ = mattype.type (); 3454 int typ = mattype.type ();
3455 mattype.info (); 3455 mattype.info ();
3456 3456
3457 if (typ == MatrixType::Permuted_Lower || 3457 if (typ == MatrixType::Permuted_Lower ||
3458 typ == MatrixType::Lower) 3458 typ == MatrixType::Lower)
3459 { 3459 {
3460 double anorm = 0.; 3460 double anorm = 0.;
3461 double ainvnorm = 0.; 3461 double ainvnorm = 0.;
3462 rcond = 1.; 3462 rcond = 1.;
3463 3463
3464 if (calc_cond) 3464 if (calc_cond)
3465 { 3465 {
3466 // Calculate the 1-norm of matrix for rcond calculation 3466 // Calculate the 1-norm of matrix for rcond calculation
3467 for (octave_idx_type j = 0; j < nc; j++) 3467 for (octave_idx_type j = 0; j < nc; j++)
3468 { 3468 {
3469 double atmp = 0.; 3469 double atmp = 0.;
3470 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 3470 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
3471 atmp += std::abs(data(i)); 3471 atmp += std::abs(data(i));
3472 if (atmp > anorm) 3472 if (atmp > anorm)
3473 anorm = atmp; 3473 anorm = atmp;
3474 } 3474 }
3475 } 3475 }
3476 3476
3477 octave_idx_type b_nc = b.cols (); 3477 octave_idx_type b_nc = b.cols ();
3478 octave_idx_type b_nz = b.nnz (); 3478 octave_idx_type b_nz = b.nnz ();
3479 retval = SparseComplexMatrix (nc, b_nc, b_nz); 3479 retval = SparseComplexMatrix (nc, b_nc, b_nz);
3480 retval.xcidx(0) = 0; 3480 retval.xcidx(0) = 0;
3481 octave_idx_type ii = 0; 3481 octave_idx_type ii = 0;
3482 octave_idx_type x_nz = b_nz; 3482 octave_idx_type x_nz = b_nz;
3483 3483
3484 if (typ == MatrixType::Permuted_Lower) 3484 if (typ == MatrixType::Permuted_Lower)
3485 { 3485 {
3486 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 3486 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
3487 octave_idx_type *perm = mattype.triangular_perm (); 3487 octave_idx_type *perm = mattype.triangular_perm ();
3488 3488
3489 for (octave_idx_type j = 0; j < b_nc; j++) 3489 for (octave_idx_type j = 0; j < b_nc; j++)
3490 { 3490 {
3491 for (octave_idx_type i = 0; i < nm; i++) 3491 for (octave_idx_type i = 0; i < nm; i++)
3492 work[i] = 0.; 3492 work[i] = 0.;
3493 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 3493 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
3494 work[perm[b.ridx(i)]] = b.data(i); 3494 work[perm[b.ridx(i)]] = b.data(i);
3495 3495
3496 for (octave_idx_type k = 0; k < nc; k++) 3496 for (octave_idx_type k = 0; k < nc; k++)
3497 { 3497 {
3498 if (work[k] != 0.) 3498 if (work[k] != 0.)
3499 { 3499 {
3500 octave_idx_type minr = nr; 3500 octave_idx_type minr = nr;
3501 octave_idx_type mini = 0; 3501 octave_idx_type mini = 0;
3502 3502
3503 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 3503 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
3504 if (perm[ridx(i)] < minr) 3504 if (perm[ridx(i)] < minr)
3505 { 3505 {
3506 minr = perm[ridx(i)]; 3506 minr = perm[ridx(i)];
3507 mini = i; 3507 mini = i;
3508 } 3508 }
3509 3509
3510 if (minr != k || data (mini) == 0.) 3510 if (minr != k || data (mini) == 0.)
3511 { 3511 {
3512 err = -2; 3512 err = -2;
3513 goto triangular_error; 3513 goto triangular_error;
3514 } 3514 }
3515 3515
3516 Complex tmp = work[k] / data(mini); 3516 Complex tmp = work[k] / data(mini);
3517 work[k] = tmp; 3517 work[k] = tmp;
3518 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) 3518 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++)
3519 { 3519 {
3520 if (i == mini) 3520 if (i == mini)
3521 continue; 3521 continue;
3522 3522
3523 octave_idx_type iidx = perm[ridx(i)]; 3523 octave_idx_type iidx = perm[ridx(i)];
3524 work[iidx] = work[iidx] - tmp * data(i); 3524 work[iidx] = work[iidx] - tmp * data(i);
3525 } 3525 }
3526 } 3526 }
3527 } 3527 }
3528 3528
3529 // Count non-zeros in work vector and adjust space in 3529 // Count non-zeros in work vector and adjust space in
3530 // retval if needed 3530 // retval if needed
3531 octave_idx_type new_nnz = 0; 3531 octave_idx_type new_nnz = 0;
3532 for (octave_idx_type i = 0; i < nc; i++) 3532 for (octave_idx_type i = 0; i < nc; i++)
3533 if (work[i] != 0.) 3533 if (work[i] != 0.)
3534 new_nnz++; 3534 new_nnz++;
3535 3535
3536 if (ii + new_nnz > x_nz) 3536 if (ii + new_nnz > x_nz)
3537 { 3537 {
3538 // Resize the sparse matrix 3538 // Resize the sparse matrix
3539 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 3539 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
3540 retval.change_capacity (sz); 3540 retval.change_capacity (sz);
3541 x_nz = sz; 3541 x_nz = sz;
3542 } 3542 }
3543 3543
3544 for (octave_idx_type i = 0; i < nc; i++) 3544 for (octave_idx_type i = 0; i < nc; i++)
3545 if (work[i] != 0.) 3545 if (work[i] != 0.)
3546 { 3546 {
3547 retval.xridx(ii) = i; 3547 retval.xridx(ii) = i;
3548 retval.xdata(ii++) = work[i]; 3548 retval.xdata(ii++) = work[i];
3549 } 3549 }
3550 retval.xcidx(j+1) = ii; 3550 retval.xcidx(j+1) = ii;
3551 } 3551 }
3552 3552
3553 retval.maybe_compress (); 3553 retval.maybe_compress ();
3554 3554
3555 if (calc_cond) 3555 if (calc_cond)
3556 { 3556 {
3557 // Calculation of 1-norm of inv(*this) 3557 // Calculation of 1-norm of inv(*this)
3558 for (octave_idx_type i = 0; i < nm; i++) 3558 for (octave_idx_type i = 0; i < nm; i++)
3559 work[i] = 0.; 3559 work[i] = 0.;
3560 3560
3561 for (octave_idx_type j = 0; j < nr; j++) 3561 for (octave_idx_type j = 0; j < nr; j++)
3562 { 3562 {
3563 work[j] = 1.; 3563 work[j] = 1.;
3564 3564
3565 for (octave_idx_type k = 0; k < nc; k++) 3565 for (octave_idx_type k = 0; k < nc; k++)
3566 { 3566 {
3567 if (work[k] != 0.) 3567 if (work[k] != 0.)
3568 { 3568 {
3569 octave_idx_type minr = nr; 3569 octave_idx_type minr = nr;
3570 octave_idx_type mini = 0; 3570 octave_idx_type mini = 0;
3571 3571
3572 for (octave_idx_type i = cidx(k); 3572 for (octave_idx_type i = cidx(k);
3573 i < cidx(k+1); i++) 3573 i < cidx(k+1); i++)
3574 if (perm[ridx(i)] < minr) 3574 if (perm[ridx(i)] < minr)
3575 { 3575 {
3576 minr = perm[ridx(i)]; 3576 minr = perm[ridx(i)];
3577 mini = i; 3577 mini = i;
3578 } 3578 }
3579 3579
3580 Complex tmp = work[k] / data(mini); 3580 Complex tmp = work[k] / data(mini);
3581 work[k] = tmp; 3581 work[k] = tmp;
3582 for (octave_idx_type i = cidx(k); 3582 for (octave_idx_type i = cidx(k);
3583 i < cidx(k+1); i++) 3583 i < cidx(k+1); i++)
3584 { 3584 {
3585 if (i == mini) 3585 if (i == mini)
3586 continue; 3586 continue;
3587 3587
3588 octave_idx_type iidx = perm[ridx(i)]; 3588 octave_idx_type iidx = perm[ridx(i)];
3589 work[iidx] = work[iidx] - tmp * data(i); 3589 work[iidx] = work[iidx] - tmp * data(i);
3590 } 3590 }
3591 } 3591 }
3592 } 3592 }
3593 3593
3594 double atmp = 0; 3594 double atmp = 0;
3595 for (octave_idx_type i = j; i < nc; i++) 3595 for (octave_idx_type i = j; i < nc; i++)
3596 { 3596 {
3597 atmp += std::abs(work[i]); 3597 atmp += std::abs(work[i]);
3598 work[i] = 0.; 3598 work[i] = 0.;
3599 } 3599 }
3600 if (atmp > ainvnorm) 3600 if (atmp > ainvnorm)
3601 ainvnorm = atmp; 3601 ainvnorm = atmp;
3602 } 3602 }
3603 rcond = 1. / ainvnorm / anorm; 3603 rcond = 1. / ainvnorm / anorm;
3604 } 3604 }
3605 } 3605 }
3606 else 3606 else
3607 { 3607 {
3608 OCTAVE_LOCAL_BUFFER (Complex, work, nm); 3608 OCTAVE_LOCAL_BUFFER (Complex, work, nm);
3609 3609
3610 for (octave_idx_type j = 0; j < b_nc; j++) 3610 for (octave_idx_type j = 0; j < b_nc; j++)
3611 { 3611 {
3612 for (octave_idx_type i = 0; i < nm; i++) 3612 for (octave_idx_type i = 0; i < nm; i++)
3613 work[i] = 0.; 3613 work[i] = 0.;
3614 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 3614 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
3615 work[b.ridx(i)] = b.data(i); 3615 work[b.ridx(i)] = b.data(i);
3616 3616
3617 for (octave_idx_type k = 0; k < nc; k++) 3617 for (octave_idx_type k = 0; k < nc; k++)
3618 { 3618 {
3619 if (work[k] != 0.) 3619 if (work[k] != 0.)
3620 { 3620 {
3621 if (ridx(cidx(k)) != k || 3621 if (ridx(cidx(k)) != k ||
3622 data(cidx(k)) == 0.) 3622 data(cidx(k)) == 0.)
3623 { 3623 {
3624 err = -2; 3624 err = -2;
3625 goto triangular_error; 3625 goto triangular_error;
3626 } 3626 }
3627 3627
3628 Complex tmp = work[k] / data(cidx(k)); 3628 Complex tmp = work[k] / data(cidx(k));
3629 work[k] = tmp; 3629 work[k] = tmp;
3630 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) 3630 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++)
3631 { 3631 {
3632 octave_idx_type iidx = ridx(i); 3632 octave_idx_type iidx = ridx(i);
3633 work[iidx] = work[iidx] - tmp * data(i); 3633 work[iidx] = work[iidx] - tmp * data(i);
3634 } 3634 }
3635 } 3635 }
3636 } 3636 }
3637 3637
3638 // Count non-zeros in work vector and adjust space in 3638 // Count non-zeros in work vector and adjust space in
3639 // retval if needed 3639 // retval if needed
3640 octave_idx_type new_nnz = 0; 3640 octave_idx_type new_nnz = 0;
3641 for (octave_idx_type i = 0; i < nc; i++) 3641 for (octave_idx_type i = 0; i < nc; i++)
3642 if (work[i] != 0.) 3642 if (work[i] != 0.)
3643 new_nnz++; 3643 new_nnz++;
3644 3644
3645 if (ii + new_nnz > x_nz) 3645 if (ii + new_nnz > x_nz)
3646 { 3646 {
3647 // Resize the sparse matrix 3647 // Resize the sparse matrix
3648 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 3648 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
3649 retval.change_capacity (sz); 3649 retval.change_capacity (sz);
3650 x_nz = sz; 3650 x_nz = sz;
3651 } 3651 }
3652 3652
3653 for (octave_idx_type i = 0; i < nc; i++) 3653 for (octave_idx_type i = 0; i < nc; i++)
3654 if (work[i] != 0.) 3654 if (work[i] != 0.)
3655 { 3655 {
3656 retval.xridx(ii) = i; 3656 retval.xridx(ii) = i;
3657 retval.xdata(ii++) = work[i]; 3657 retval.xdata(ii++) = work[i];
3658 } 3658 }
3659 retval.xcidx(j+1) = ii; 3659 retval.xcidx(j+1) = ii;
3660 } 3660 }
3661 3661
3662 retval.maybe_compress (); 3662 retval.maybe_compress ();
3663 3663
3664 if (calc_cond) 3664 if (calc_cond)
3665 { 3665 {
3666 // Calculation of 1-norm of inv(*this) 3666 // Calculation of 1-norm of inv(*this)
3667 for (octave_idx_type i = 0; i < nm; i++) 3667 for (octave_idx_type i = 0; i < nm; i++)
3668 work[i] = 0.; 3668 work[i] = 0.;
3669 3669
3670 for (octave_idx_type j = 0; j < nr; j++) 3670 for (octave_idx_type j = 0; j < nr; j++)
3671 { 3671 {
3672 work[j] = 1.; 3672 work[j] = 1.;
3673 3673
3674 for (octave_idx_type k = j; k < nc; k++) 3674 for (octave_idx_type k = j; k < nc; k++)
3675 { 3675 {
3676 3676
3677 if (work[k] != 0.) 3677 if (work[k] != 0.)
3678 { 3678 {
3679 Complex tmp = work[k] / data(cidx(k)); 3679 Complex tmp = work[k] / data(cidx(k));
3680 work[k] = tmp; 3680 work[k] = tmp;
3681 for (octave_idx_type i = cidx(k)+1; 3681 for (octave_idx_type i = cidx(k)+1;
3682 i < cidx(k+1); i++) 3682 i < cidx(k+1); i++)
3683 { 3683 {
3684 octave_idx_type iidx = ridx(i); 3684 octave_idx_type iidx = ridx(i);
3685 work[iidx] = work[iidx] - tmp * data(i); 3685 work[iidx] = work[iidx] - tmp * data(i);
3686 } 3686 }
3687 } 3687 }
3688 } 3688 }
3689 double atmp = 0; 3689 double atmp = 0;
3690 for (octave_idx_type i = j; i < nc; i++) 3690 for (octave_idx_type i = j; i < nc; i++)
3691 { 3691 {
3692 atmp += std::abs(work[i]); 3692 atmp += std::abs(work[i]);
3693 work[i] = 0.; 3693 work[i] = 0.;
3694 } 3694 }
3695 if (atmp > ainvnorm) 3695 if (atmp > ainvnorm)
3696 ainvnorm = atmp; 3696 ainvnorm = atmp;
3697 } 3697 }
3698 rcond = 1. / ainvnorm / anorm; 3698 rcond = 1. / ainvnorm / anorm;
3699 } 3699 }
3700 } 3700 }
3701 3701
3702 triangular_error: 3702 triangular_error:
3703 if (err != 0) 3703 if (err != 0)
3704 { 3704 {
3705 if (sing_handler) 3705 if (sing_handler)
3706 { 3706 {
3707 sing_handler (rcond); 3707 sing_handler (rcond);
3708 mattype.mark_as_rectangular (); 3708 mattype.mark_as_rectangular ();
3709 } 3709 }
3710 else 3710 else
3711 (*current_liboctave_error_handler) 3711 (*current_liboctave_error_handler)
3712 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 3712 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
3713 rcond); 3713 rcond);
3714 } 3714 }
3715 3715
3716 volatile double rcond_plus_one = rcond + 1.0; 3716 volatile double rcond_plus_one = rcond + 1.0;
3717 3717
3718 if (rcond_plus_one == 1.0 || xisnan (rcond)) 3718 if (rcond_plus_one == 1.0 || xisnan (rcond))
3719 { 3719 {
3720 err = -2; 3720 err = -2;
3721 3721
3722 if (sing_handler) 3722 if (sing_handler)
3723 { 3723 {
3724 sing_handler (rcond); 3724 sing_handler (rcond);
3725 mattype.mark_as_rectangular (); 3725 mattype.mark_as_rectangular ();
3726 } 3726 }
3727 else 3727 else
3728 (*current_liboctave_error_handler) 3728 (*current_liboctave_error_handler)
3729 ("matrix singular to machine precision, rcond = %g", 3729 ("matrix singular to machine precision, rcond = %g",
3730 rcond); 3730 rcond);
3731 } 3731 }
3732 } 3732 }
3733 else 3733 else
3734 (*current_liboctave_error_handler) ("incorrect matrix type"); 3734 (*current_liboctave_error_handler) ("incorrect matrix type");
3735 } 3735 }
3736 3736
3737 return retval; 3737 return retval;
3738 } 3738 }
3739 3739
3740 ComplexMatrix 3740 ComplexMatrix
3741 SparseComplexMatrix::trisolve (MatrixType &mattype, const Matrix& b, 3741 SparseComplexMatrix::trisolve (MatrixType &mattype, const Matrix& b,
3742 octave_idx_type& err, double& rcond, 3742 octave_idx_type& err, double& rcond,
3743 solve_singularity_handler sing_handler, 3743 solve_singularity_handler sing_handler,
3744 bool calc_cond) const 3744 bool calc_cond) const
3745 { 3745 {
3746 ComplexMatrix retval; 3746 ComplexMatrix retval;
3747 3747
3748 octave_idx_type nr = rows (); 3748 octave_idx_type nr = rows ();
3749 octave_idx_type nc = cols (); 3749 octave_idx_type nc = cols ();
3762 // Print spparms("spumoni") info if requested 3762 // Print spparms("spumoni") info if requested
3763 volatile int typ = mattype.type (); 3763 volatile int typ = mattype.type ();
3764 mattype.info (); 3764 mattype.info ();
3765 3765
3766 if (typ == MatrixType::Tridiagonal_Hermitian) 3766 if (typ == MatrixType::Tridiagonal_Hermitian)
3767 { 3767 {
3768 OCTAVE_LOCAL_BUFFER (double, D, nr); 3768 OCTAVE_LOCAL_BUFFER (double, D, nr);
3769 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); 3769 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);
3770 3770
3771 if (mattype.is_dense ()) 3771 if (mattype.is_dense ())
3772 { 3772 {
3773 octave_idx_type ii = 0; 3773 octave_idx_type ii = 0;
3774 3774
3775 for (octave_idx_type j = 0; j < nc-1; j++) 3775 for (octave_idx_type j = 0; j < nc-1; j++)
3776 { 3776 {
3777 D[j] = std::real(data(ii++)); 3777 D[j] = std::real(data(ii++));
3778 DL[j] = data(ii); 3778 DL[j] = data(ii);
3779 ii += 2; 3779 ii += 2;
3780 } 3780 }
3781 D[nc-1] = std::real(data(ii)); 3781 D[nc-1] = std::real(data(ii));
3782 } 3782 }
3783 else 3783 else
3784 { 3784 {
3785 D[0] = 0.; 3785 D[0] = 0.;
3786 for (octave_idx_type i = 0; i < nr - 1; i++) 3786 for (octave_idx_type i = 0; i < nr - 1; i++)
3787 { 3787 {
3788 D[i+1] = 0.; 3788 D[i+1] = 0.;
3789 DL[i] = 0.; 3789 DL[i] = 0.;
3790 } 3790 }
3791 3791
3792 for (octave_idx_type j = 0; j < nc; j++) 3792 for (octave_idx_type j = 0; j < nc; j++)
3793 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 3793 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
3794 { 3794 {
3795 if (ridx(i) == j) 3795 if (ridx(i) == j)
3796 D[j] = std::real(data(i)); 3796 D[j] = std::real(data(i));
3797 else if (ridx(i) == j + 1) 3797 else if (ridx(i) == j + 1)
3798 DL[j] = data(i); 3798 DL[j] = data(i);
3799 } 3799 }
3800 } 3800 }
3801 3801
3802 octave_idx_type b_nc = b.cols(); 3802 octave_idx_type b_nc = b.cols();
3803 retval = ComplexMatrix (b); 3803 retval = ComplexMatrix (b);
3804 Complex *result = retval.fortran_vec (); 3804 Complex *result = retval.fortran_vec ();
3805 3805
3806 F77_XFCN (zptsv, ZPTSV, (nr, b_nc, D, DL, result, 3806 F77_XFCN (zptsv, ZPTSV, (nr, b_nc, D, DL, result,
3807 b.rows(), err)); 3807 b.rows(), err));
3808 3808
3809 if (err != 0) 3809 if (err != 0)
3810 { 3810 {
3811 err = 0; 3811 err = 0;
3812 mattype.mark_as_unsymmetric (); 3812 mattype.mark_as_unsymmetric ();
3813 typ = MatrixType::Tridiagonal; 3813 typ = MatrixType::Tridiagonal;
3814 } 3814 }
3815 else 3815 else
3816 rcond = 1.; 3816 rcond = 1.;
3817 } 3817 }
3818 3818
3819 if (typ == MatrixType::Tridiagonal) 3819 if (typ == MatrixType::Tridiagonal)
3820 { 3820 {
3821 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); 3821 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1);
3822 OCTAVE_LOCAL_BUFFER (Complex, D, nr); 3822 OCTAVE_LOCAL_BUFFER (Complex, D, nr);
3823 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); 3823 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);
3824 3824
3825 if (mattype.is_dense ()) 3825 if (mattype.is_dense ())
3826 { 3826 {
3827 octave_idx_type ii = 0; 3827 octave_idx_type ii = 0;
3828 3828
3829 for (octave_idx_type j = 0; j < nc-1; j++) 3829 for (octave_idx_type j = 0; j < nc-1; j++)
3830 { 3830 {
3831 D[j] = data(ii++); 3831 D[j] = data(ii++);
3832 DL[j] = data(ii++); 3832 DL[j] = data(ii++);
3833 DU[j] = data(ii++); 3833 DU[j] = data(ii++);
3834 } 3834 }
3835 D[nc-1] = data(ii); 3835 D[nc-1] = data(ii);
3836 } 3836 }
3837 else 3837 else
3838 { 3838 {
3839 D[0] = 0.; 3839 D[0] = 0.;
3840 for (octave_idx_type i = 0; i < nr - 1; i++) 3840 for (octave_idx_type i = 0; i < nr - 1; i++)
3841 { 3841 {
3842 D[i+1] = 0.; 3842 D[i+1] = 0.;
3843 DL[i] = 0.; 3843 DL[i] = 0.;
3844 DU[i] = 0.; 3844 DU[i] = 0.;
3845 } 3845 }
3846 3846
3847 for (octave_idx_type j = 0; j < nc; j++) 3847 for (octave_idx_type j = 0; j < nc; j++)
3848 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 3848 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
3849 { 3849 {
3850 if (ridx(i) == j) 3850 if (ridx(i) == j)
3851 D[j] = data(i); 3851 D[j] = data(i);
3852 else if (ridx(i) == j + 1) 3852 else if (ridx(i) == j + 1)
3853 DL[j] = data(i); 3853 DL[j] = data(i);
3854 else if (ridx(i) == j - 1) 3854 else if (ridx(i) == j - 1)
3855 DU[j-1] = data(i); 3855 DU[j-1] = data(i);
3856 } 3856 }
3857 } 3857 }
3858 3858
3859 octave_idx_type b_nc = b.cols(); 3859 octave_idx_type b_nc = b.cols();
3860 retval = ComplexMatrix (b); 3860 retval = ComplexMatrix (b);
3861 Complex *result = retval.fortran_vec (); 3861 Complex *result = retval.fortran_vec ();
3862 3862
3863 F77_XFCN (zgtsv, ZGTSV, (nr, b_nc, DL, D, DU, result, 3863 F77_XFCN (zgtsv, ZGTSV, (nr, b_nc, DL, D, DU, result,
3864 b.rows(), err)); 3864 b.rows(), err));
3865 3865
3866 if (err != 0) 3866 if (err != 0)
3867 { 3867 {
3868 rcond = 0.; 3868 rcond = 0.;
3869 err = -2; 3869 err = -2;
3870 3870
3871 if (sing_handler) 3871 if (sing_handler)
3872 { 3872 {
3873 sing_handler (rcond); 3873 sing_handler (rcond);
3874 mattype.mark_as_rectangular (); 3874 mattype.mark_as_rectangular ();
3875 } 3875 }
3876 else 3876 else
3877 (*current_liboctave_error_handler) 3877 (*current_liboctave_error_handler)
3878 ("matrix singular to machine precision"); 3878 ("matrix singular to machine precision");
3879 3879
3880 } 3880 }
3881 else 3881 else
3882 rcond = 1.; 3882 rcond = 1.;
3883 } 3883 }
3884 else if (typ != MatrixType::Tridiagonal_Hermitian) 3884 else if (typ != MatrixType::Tridiagonal_Hermitian)
3885 (*current_liboctave_error_handler) ("incorrect matrix type"); 3885 (*current_liboctave_error_handler) ("incorrect matrix type");
3886 } 3886 }
3887 3887
3888 return retval; 3888 return retval;
3889 } 3889 }
3890 3890
3891 SparseComplexMatrix 3891 SparseComplexMatrix
3892 SparseComplexMatrix::trisolve (MatrixType &mattype, const SparseMatrix& b, 3892 SparseComplexMatrix::trisolve (MatrixType &mattype, const SparseMatrix& b,
3893 octave_idx_type& err, double& rcond, 3893 octave_idx_type& err, double& rcond,
3894 solve_singularity_handler sing_handler, 3894 solve_singularity_handler sing_handler,
3895 bool calc_cond) const 3895 bool calc_cond) const
3896 { 3896 {
3897 SparseComplexMatrix retval; 3897 SparseComplexMatrix retval;
3898 3898
3899 octave_idx_type nr = rows (); 3899 octave_idx_type nr = rows ();
3900 octave_idx_type nc = cols (); 3900 octave_idx_type nc = cols ();
3914 int typ = mattype.type (); 3914 int typ = mattype.type ();
3915 mattype.info (); 3915 mattype.info ();
3916 3916
3917 // Note can't treat symmetric case as there is no dpttrf function 3917 // Note can't treat symmetric case as there is no dpttrf function
3918 if (typ == MatrixType::Tridiagonal || 3918 if (typ == MatrixType::Tridiagonal ||
3919 typ == MatrixType::Tridiagonal_Hermitian) 3919 typ == MatrixType::Tridiagonal_Hermitian)
3920 { 3920 {
3921 OCTAVE_LOCAL_BUFFER (Complex, DU2, nr - 2); 3921 OCTAVE_LOCAL_BUFFER (Complex, DU2, nr - 2);
3922 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); 3922 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1);
3923 OCTAVE_LOCAL_BUFFER (Complex, D, nr); 3923 OCTAVE_LOCAL_BUFFER (Complex, D, nr);
3924 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); 3924 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);
3925 Array<octave_idx_type> ipvt (nr); 3925 Array<octave_idx_type> ipvt (nr);
3926 octave_idx_type *pipvt = ipvt.fortran_vec (); 3926 octave_idx_type *pipvt = ipvt.fortran_vec ();
3927 3927
3928 if (mattype.is_dense ()) 3928 if (mattype.is_dense ())
3929 { 3929 {
3930 octave_idx_type ii = 0; 3930 octave_idx_type ii = 0;
3931 3931
3932 for (octave_idx_type j = 0; j < nc-1; j++) 3932 for (octave_idx_type j = 0; j < nc-1; j++)
3933 { 3933 {
3934 D[j] = data(ii++); 3934 D[j] = data(ii++);
3935 DL[j] = data(ii++); 3935 DL[j] = data(ii++);
3936 DU[j] = data(ii++); 3936 DU[j] = data(ii++);
3937 } 3937 }
3938 D[nc-1] = data(ii); 3938 D[nc-1] = data(ii);
3939 } 3939 }
3940 else 3940 else
3941 { 3941 {
3942 D[0] = 0.; 3942 D[0] = 0.;
3943 for (octave_idx_type i = 0; i < nr - 1; i++) 3943 for (octave_idx_type i = 0; i < nr - 1; i++)
3944 { 3944 {
3945 D[i+1] = 0.; 3945 D[i+1] = 0.;
3946 DL[i] = 0.; 3946 DL[i] = 0.;
3947 DU[i] = 0.; 3947 DU[i] = 0.;
3948 } 3948 }
3949 3949
3950 for (octave_idx_type j = 0; j < nc; j++) 3950 for (octave_idx_type j = 0; j < nc; j++)
3951 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 3951 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
3952 { 3952 {
3953 if (ridx(i) == j) 3953 if (ridx(i) == j)
3954 D[j] = data(i); 3954 D[j] = data(i);
3955 else if (ridx(i) == j + 1) 3955 else if (ridx(i) == j + 1)
3956 DL[j] = data(i); 3956 DL[j] = data(i);
3957 else if (ridx(i) == j - 1) 3957 else if (ridx(i) == j - 1)
3958 DU[j-1] = data(i); 3958 DU[j-1] = data(i);
3959 } 3959 }
3960 } 3960 }
3961 3961
3962 F77_XFCN (zgttrf, ZGTTRF, (nr, DL, D, DU, DU2, pipvt, err)); 3962 F77_XFCN (zgttrf, ZGTTRF, (nr, DL, D, DU, DU2, pipvt, err));
3963 3963
3964 if (err != 0) 3964 if (err != 0)
3965 { 3965 {
3966 err = -2; 3966 err = -2;
3967 rcond = 0.0; 3967 rcond = 0.0;
3968 3968
3969 if (sing_handler) 3969 if (sing_handler)
3970 { 3970 {
3971 sing_handler (rcond); 3971 sing_handler (rcond);
3972 mattype.mark_as_rectangular (); 3972 mattype.mark_as_rectangular ();
3973 } 3973 }
3974 else 3974 else
3975 (*current_liboctave_error_handler) 3975 (*current_liboctave_error_handler)
3976 ("matrix singular to machine precision"); 3976 ("matrix singular to machine precision");
3977 3977
3978 } 3978 }
3979 else 3979 else
3980 { 3980 {
3981 char job = 'N'; 3981 char job = 'N';
3982 volatile octave_idx_type x_nz = b.nnz (); 3982 volatile octave_idx_type x_nz = b.nnz ();
3983 octave_idx_type b_nc = b.cols (); 3983 octave_idx_type b_nc = b.cols ();
3984 retval = SparseComplexMatrix (nr, b_nc, x_nz); 3984 retval = SparseComplexMatrix (nr, b_nc, x_nz);
3985 retval.xcidx(0) = 0; 3985 retval.xcidx(0) = 0;
3986 volatile octave_idx_type ii = 0; 3986 volatile octave_idx_type ii = 0;
3987 rcond = 1.0; 3987 rcond = 1.0;
3988 3988
3989 OCTAVE_LOCAL_BUFFER (Complex, work, nr); 3989 OCTAVE_LOCAL_BUFFER (Complex, work, nr);
3990 3990
3991 for (volatile octave_idx_type j = 0; j < b_nc; j++) 3991 for (volatile octave_idx_type j = 0; j < b_nc; j++)
3992 { 3992 {
3993 for (octave_idx_type i = 0; i < nr; i++) 3993 for (octave_idx_type i = 0; i < nr; i++)
3994 work[i] = 0.; 3994 work[i] = 0.;
3995 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) 3995 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++)
3996 work[b.ridx(i)] = b.data(i); 3996 work[b.ridx(i)] = b.data(i);
3997 3997
3998 F77_XFCN (zgttrs, ZGTTRS, 3998 F77_XFCN (zgttrs, ZGTTRS,
3999 (F77_CONST_CHAR_ARG2 (&job, 1), 3999 (F77_CONST_CHAR_ARG2 (&job, 1),
4000 nr, 1, DL, D, DU, DU2, pipvt, 4000 nr, 1, DL, D, DU, DU2, pipvt,
4001 work, b.rows (), err 4001 work, b.rows (), err
4002 F77_CHAR_ARG_LEN (1))); 4002 F77_CHAR_ARG_LEN (1)));
4003 4003
4004 // Count non-zeros in work vector and adjust 4004 // Count non-zeros in work vector and adjust
4005 // space in retval if needed 4005 // space in retval if needed
4006 octave_idx_type new_nnz = 0; 4006 octave_idx_type new_nnz = 0;
4007 for (octave_idx_type i = 0; i < nr; i++) 4007 for (octave_idx_type i = 0; i < nr; i++)
4008 if (work[i] != 0.) 4008 if (work[i] != 0.)
4009 new_nnz++; 4009 new_nnz++;
4010 4010
4011 if (ii + new_nnz > x_nz) 4011 if (ii + new_nnz > x_nz)
4012 { 4012 {
4013 // Resize the sparse matrix 4013 // Resize the sparse matrix
4014 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 4014 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
4015 retval.change_capacity (sz); 4015 retval.change_capacity (sz);
4016 x_nz = sz; 4016 x_nz = sz;
4017 } 4017 }
4018 4018
4019 for (octave_idx_type i = 0; i < nr; i++) 4019 for (octave_idx_type i = 0; i < nr; i++)
4020 if (work[i] != 0.) 4020 if (work[i] != 0.)
4021 { 4021 {
4022 retval.xridx(ii) = i; 4022 retval.xridx(ii) = i;
4023 retval.xdata(ii++) = work[i]; 4023 retval.xdata(ii++) = work[i];
4024 } 4024 }
4025 retval.xcidx(j+1) = ii; 4025 retval.xcidx(j+1) = ii;
4026 } 4026 }
4027 4027
4028 retval.maybe_compress (); 4028 retval.maybe_compress ();
4029 } 4029 }
4030 } 4030 }
4031 else if (typ != MatrixType::Tridiagonal_Hermitian) 4031 else if (typ != MatrixType::Tridiagonal_Hermitian)
4032 (*current_liboctave_error_handler) ("incorrect matrix type"); 4032 (*current_liboctave_error_handler) ("incorrect matrix type");
4033 } 4033 }
4034 4034
4035 return retval; 4035 return retval;
4036 } 4036 }
4037 4037
4038 ComplexMatrix 4038 ComplexMatrix
4039 SparseComplexMatrix::trisolve (MatrixType &mattype, const ComplexMatrix& b, 4039 SparseComplexMatrix::trisolve (MatrixType &mattype, const ComplexMatrix& b,
4040 octave_idx_type& err, double& rcond, 4040 octave_idx_type& err, double& rcond,
4041 solve_singularity_handler sing_handler, 4041 solve_singularity_handler sing_handler,
4042 bool calc_cond) const 4042 bool calc_cond) const
4043 { 4043 {
4044 ComplexMatrix retval; 4044 ComplexMatrix retval;
4045 4045
4046 octave_idx_type nr = rows (); 4046 octave_idx_type nr = rows ();
4047 octave_idx_type nc = cols (); 4047 octave_idx_type nc = cols ();
4060 // Print spparms("spumoni") info if requested 4060 // Print spparms("spumoni") info if requested
4061 volatile int typ = mattype.type (); 4061 volatile int typ = mattype.type ();
4062 mattype.info (); 4062 mattype.info ();
4063 4063
4064 if (typ == MatrixType::Tridiagonal_Hermitian) 4064 if (typ == MatrixType::Tridiagonal_Hermitian)
4065 { 4065 {
4066 OCTAVE_LOCAL_BUFFER (double, D, nr); 4066 OCTAVE_LOCAL_BUFFER (double, D, nr);
4067 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); 4067 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);
4068 4068
4069 if (mattype.is_dense ()) 4069 if (mattype.is_dense ())
4070 { 4070 {
4071 octave_idx_type ii = 0; 4071 octave_idx_type ii = 0;
4072 4072
4073 for (octave_idx_type j = 0; j < nc-1; j++) 4073 for (octave_idx_type j = 0; j < nc-1; j++)
4074 { 4074 {
4075 D[j] = std::real(data(ii++)); 4075 D[j] = std::real(data(ii++));
4076 DL[j] = data(ii); 4076 DL[j] = data(ii);
4077 ii += 2; 4077 ii += 2;
4078 } 4078 }
4079 D[nc-1] = std::real(data(ii)); 4079 D[nc-1] = std::real(data(ii));
4080 } 4080 }
4081 else 4081 else
4082 { 4082 {
4083 D[0] = 0.; 4083 D[0] = 0.;
4084 for (octave_idx_type i = 0; i < nr - 1; i++) 4084 for (octave_idx_type i = 0; i < nr - 1; i++)
4085 { 4085 {
4086 D[i+1] = 0.; 4086 D[i+1] = 0.;
4087 DL[i] = 0.; 4087 DL[i] = 0.;
4088 } 4088 }
4089 4089
4090 for (octave_idx_type j = 0; j < nc; j++) 4090 for (octave_idx_type j = 0; j < nc; j++)
4091 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4091 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4092 { 4092 {
4093 if (ridx(i) == j) 4093 if (ridx(i) == j)
4094 D[j] = std::real (data(i)); 4094 D[j] = std::real (data(i));
4095 else if (ridx(i) == j + 1) 4095 else if (ridx(i) == j + 1)
4096 DL[j] = data(i); 4096 DL[j] = data(i);
4097 } 4097 }
4098 } 4098 }
4099 4099
4100 octave_idx_type b_nr = b.rows (); 4100 octave_idx_type b_nr = b.rows ();
4101 octave_idx_type b_nc = b.cols(); 4101 octave_idx_type b_nc = b.cols();
4102 rcond = 1.; 4102 rcond = 1.;
4103 4103
4104 retval = ComplexMatrix (b); 4104 retval = ComplexMatrix (b);
4105 Complex *result = retval.fortran_vec (); 4105 Complex *result = retval.fortran_vec ();
4106 4106
4107 F77_XFCN (zptsv, ZPTSV, (nr, b_nc, D, DL, result, 4107 F77_XFCN (zptsv, ZPTSV, (nr, b_nc, D, DL, result,
4108 b_nr, err)); 4108 b_nr, err));
4109 4109
4110 if (err != 0) 4110 if (err != 0)
4111 { 4111 {
4112 err = 0; 4112 err = 0;
4113 mattype.mark_as_unsymmetric (); 4113 mattype.mark_as_unsymmetric ();
4114 typ = MatrixType::Tridiagonal; 4114 typ = MatrixType::Tridiagonal;
4115 } 4115 }
4116 } 4116 }
4117 4117
4118 if (typ == MatrixType::Tridiagonal) 4118 if (typ == MatrixType::Tridiagonal)
4119 { 4119 {
4120 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); 4120 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1);
4121 OCTAVE_LOCAL_BUFFER (Complex, D, nr); 4121 OCTAVE_LOCAL_BUFFER (Complex, D, nr);
4122 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); 4122 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);
4123 4123
4124 if (mattype.is_dense ()) 4124 if (mattype.is_dense ())
4125 { 4125 {
4126 octave_idx_type ii = 0; 4126 octave_idx_type ii = 0;
4127 4127
4128 for (octave_idx_type j = 0; j < nc-1; j++) 4128 for (octave_idx_type j = 0; j < nc-1; j++)
4129 { 4129 {
4130 D[j] = data(ii++); 4130 D[j] = data(ii++);
4131 DL[j] = data(ii++); 4131 DL[j] = data(ii++);
4132 DU[j] = data(ii++); 4132 DU[j] = data(ii++);
4133 } 4133 }
4134 D[nc-1] = data(ii); 4134 D[nc-1] = data(ii);
4135 } 4135 }
4136 else 4136 else
4137 { 4137 {
4138 D[0] = 0.; 4138 D[0] = 0.;
4139 for (octave_idx_type i = 0; i < nr - 1; i++) 4139 for (octave_idx_type i = 0; i < nr - 1; i++)
4140 { 4140 {
4141 D[i+1] = 0.; 4141 D[i+1] = 0.;
4142 DL[i] = 0.; 4142 DL[i] = 0.;
4143 DU[i] = 0.; 4143 DU[i] = 0.;
4144 } 4144 }
4145 4145
4146 for (octave_idx_type j = 0; j < nc; j++) 4146 for (octave_idx_type j = 0; j < nc; j++)
4147 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4147 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4148 { 4148 {
4149 if (ridx(i) == j) 4149 if (ridx(i) == j)
4150 D[j] = data(i); 4150 D[j] = data(i);
4151 else if (ridx(i) == j + 1) 4151 else if (ridx(i) == j + 1)
4152 DL[j] = data(i); 4152 DL[j] = data(i);
4153 else if (ridx(i) == j - 1) 4153 else if (ridx(i) == j - 1)
4154 DU[j-1] = data(i); 4154 DU[j-1] = data(i);
4155 } 4155 }
4156 } 4156 }
4157 4157
4158 octave_idx_type b_nr = b.rows(); 4158 octave_idx_type b_nr = b.rows();
4159 octave_idx_type b_nc = b.cols(); 4159 octave_idx_type b_nc = b.cols();
4160 rcond = 1.; 4160 rcond = 1.;
4161 4161
4162 retval = ComplexMatrix (b); 4162 retval = ComplexMatrix (b);
4163 Complex *result = retval.fortran_vec (); 4163 Complex *result = retval.fortran_vec ();
4164 4164
4165 F77_XFCN (zgtsv, ZGTSV, (nr, b_nc, DL, D, DU, result, 4165 F77_XFCN (zgtsv, ZGTSV, (nr, b_nc, DL, D, DU, result,
4166 b_nr, err)); 4166 b_nr, err));
4167 4167
4168 if (err != 0) 4168 if (err != 0)
4169 { 4169 {
4170 rcond = 0.; 4170 rcond = 0.;
4171 err = -2; 4171 err = -2;
4172 4172
4173 if (sing_handler) 4173 if (sing_handler)
4174 { 4174 {
4175 sing_handler (rcond); 4175 sing_handler (rcond);
4176 mattype.mark_as_rectangular (); 4176 mattype.mark_as_rectangular ();
4177 } 4177 }
4178 else 4178 else
4179 (*current_liboctave_error_handler) 4179 (*current_liboctave_error_handler)
4180 ("matrix singular to machine precision"); 4180 ("matrix singular to machine precision");
4181 } 4181 }
4182 } 4182 }
4183 else if (typ != MatrixType::Tridiagonal_Hermitian) 4183 else if (typ != MatrixType::Tridiagonal_Hermitian)
4184 (*current_liboctave_error_handler) ("incorrect matrix type"); 4184 (*current_liboctave_error_handler) ("incorrect matrix type");
4185 } 4185 }
4186 4186
4187 return retval; 4187 return retval;
4188 } 4188 }
4189 4189
4190 SparseComplexMatrix 4190 SparseComplexMatrix
4191 SparseComplexMatrix::trisolve (MatrixType &mattype, 4191 SparseComplexMatrix::trisolve (MatrixType &mattype,
4192 const SparseComplexMatrix& b, 4192 const SparseComplexMatrix& b,
4193 octave_idx_type& err, double& rcond, 4193 octave_idx_type& err, double& rcond,
4194 solve_singularity_handler sing_handler, 4194 solve_singularity_handler sing_handler,
4195 bool calc_cond) const 4195 bool calc_cond) const
4196 { 4196 {
4197 SparseComplexMatrix retval; 4197 SparseComplexMatrix retval;
4198 4198
4199 octave_idx_type nr = rows (); 4199 octave_idx_type nr = rows ();
4200 octave_idx_type nc = cols (); 4200 octave_idx_type nc = cols ();
4214 int typ = mattype.type (); 4214 int typ = mattype.type ();
4215 mattype.info (); 4215 mattype.info ();
4216 4216
4217 // Note can't treat symmetric case as there is no dpttrf function 4217 // Note can't treat symmetric case as there is no dpttrf function
4218 if (typ == MatrixType::Tridiagonal || 4218 if (typ == MatrixType::Tridiagonal ||
4219 typ == MatrixType::Tridiagonal_Hermitian) 4219 typ == MatrixType::Tridiagonal_Hermitian)
4220 { 4220 {
4221 OCTAVE_LOCAL_BUFFER (Complex, DU2, nr - 2); 4221 OCTAVE_LOCAL_BUFFER (Complex, DU2, nr - 2);
4222 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); 4222 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1);
4223 OCTAVE_LOCAL_BUFFER (Complex, D, nr); 4223 OCTAVE_LOCAL_BUFFER (Complex, D, nr);
4224 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); 4224 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);
4225 Array<octave_idx_type> ipvt (nr); 4225 Array<octave_idx_type> ipvt (nr);
4226 octave_idx_type *pipvt = ipvt.fortran_vec (); 4226 octave_idx_type *pipvt = ipvt.fortran_vec ();
4227 4227
4228 if (mattype.is_dense ()) 4228 if (mattype.is_dense ())
4229 { 4229 {
4230 octave_idx_type ii = 0; 4230 octave_idx_type ii = 0;
4231 4231
4232 for (octave_idx_type j = 0; j < nc-1; j++) 4232 for (octave_idx_type j = 0; j < nc-1; j++)
4233 { 4233 {
4234 D[j] = data(ii++); 4234 D[j] = data(ii++);
4235 DL[j] = data(ii++); 4235 DL[j] = data(ii++);
4236 DU[j] = data(ii++); 4236 DU[j] = data(ii++);
4237 } 4237 }
4238 D[nc-1] = data(ii); 4238 D[nc-1] = data(ii);
4239 } 4239 }
4240 else 4240 else
4241 { 4241 {
4242 D[0] = 0.; 4242 D[0] = 0.;
4243 for (octave_idx_type i = 0; i < nr - 1; i++) 4243 for (octave_idx_type i = 0; i < nr - 1; i++)
4244 { 4244 {
4245 D[i+1] = 0.; 4245 D[i+1] = 0.;
4246 DL[i] = 0.; 4246 DL[i] = 0.;
4247 DU[i] = 0.; 4247 DU[i] = 0.;
4248 } 4248 }
4249 4249
4250 for (octave_idx_type j = 0; j < nc; j++) 4250 for (octave_idx_type j = 0; j < nc; j++)
4251 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4251 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4252 { 4252 {
4253 if (ridx(i) == j) 4253 if (ridx(i) == j)
4254 D[j] = data(i); 4254 D[j] = data(i);
4255 else if (ridx(i) == j + 1) 4255 else if (ridx(i) == j + 1)
4256 DL[j] = data(i); 4256 DL[j] = data(i);
4257 else if (ridx(i) == j - 1) 4257 else if (ridx(i) == j - 1)
4258 DU[j-1] = data(i); 4258 DU[j-1] = data(i);
4259 } 4259 }
4260 } 4260 }
4261 4261
4262 F77_XFCN (zgttrf, ZGTTRF, (nr, DL, D, DU, DU2, pipvt, err)); 4262 F77_XFCN (zgttrf, ZGTTRF, (nr, DL, D, DU, DU2, pipvt, err));
4263 4263
4264 if (err != 0) 4264 if (err != 0)
4265 { 4265 {
4266 rcond = 0.0; 4266 rcond = 0.0;
4267 err = -2; 4267 err = -2;
4268 4268
4269 if (sing_handler) 4269 if (sing_handler)
4270 { 4270 {
4271 sing_handler (rcond); 4271 sing_handler (rcond);
4272 mattype.mark_as_rectangular (); 4272 mattype.mark_as_rectangular ();
4273 } 4273 }
4274 else 4274 else
4275 (*current_liboctave_error_handler) 4275 (*current_liboctave_error_handler)
4276 ("matrix singular to machine precision"); 4276 ("matrix singular to machine precision");
4277 } 4277 }
4278 else 4278 else
4279 { 4279 {
4280 rcond = 1.; 4280 rcond = 1.;
4281 char job = 'N'; 4281 char job = 'N';
4282 octave_idx_type b_nr = b.rows (); 4282 octave_idx_type b_nr = b.rows ();
4283 octave_idx_type b_nc = b.cols (); 4283 octave_idx_type b_nc = b.cols ();
4284 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); 4284 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
4285 4285
4286 // Take a first guess that the number of non-zero terms 4286 // Take a first guess that the number of non-zero terms
4287 // will be as many as in b 4287 // will be as many as in b
4288 volatile octave_idx_type x_nz = b.nnz (); 4288 volatile octave_idx_type x_nz = b.nnz ();
4289 volatile octave_idx_type ii = 0; 4289 volatile octave_idx_type ii = 0;
4290 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); 4290 retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
4291 4291
4292 retval.xcidx(0) = 0; 4292 retval.xcidx(0) = 0;
4293 for (volatile octave_idx_type j = 0; j < b_nc; j++) 4293 for (volatile octave_idx_type j = 0; j < b_nc; j++)
4294 { 4294 {
4295 4295
4296 for (octave_idx_type i = 0; i < b_nr; i++) 4296 for (octave_idx_type i = 0; i < b_nr; i++)
4297 Bx[i] = b (i,j); 4297 Bx[i] = b (i,j);
4298 4298
4299 F77_XFCN (zgttrs, ZGTTRS, 4299 F77_XFCN (zgttrs, ZGTTRS,
4300 (F77_CONST_CHAR_ARG2 (&job, 1), 4300 (F77_CONST_CHAR_ARG2 (&job, 1),
4301 nr, 1, DL, D, DU, DU2, pipvt, 4301 nr, 1, DL, D, DU, DU2, pipvt,
4302 Bx, b_nr, err 4302 Bx, b_nr, err
4303 F77_CHAR_ARG_LEN (1))); 4303 F77_CHAR_ARG_LEN (1)));
4304 4304
4305 if (err != 0) 4305 if (err != 0)
4306 { 4306 {
4307 (*current_liboctave_error_handler) 4307 (*current_liboctave_error_handler)
4308 ("SparseComplexMatrix::solve solve failed"); 4308 ("SparseComplexMatrix::solve solve failed");
4309 4309
4310 err = -1; 4310 err = -1;
4311 break; 4311 break;
4312 } 4312 }
4313 4313
4314 // Count non-zeros in work vector and adjust 4314 // Count non-zeros in work vector and adjust
4315 // space in retval if needed 4315 // space in retval if needed
4316 octave_idx_type new_nnz = 0; 4316 octave_idx_type new_nnz = 0;
4317 for (octave_idx_type i = 0; i < nr; i++) 4317 for (octave_idx_type i = 0; i < nr; i++)
4318 if (Bx[i] != 0.) 4318 if (Bx[i] != 0.)
4319 new_nnz++; 4319 new_nnz++;
4320 4320
4321 if (ii + new_nnz > x_nz) 4321 if (ii + new_nnz > x_nz)
4322 { 4322 {
4323 // Resize the sparse matrix 4323 // Resize the sparse matrix
4324 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 4324 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
4325 retval.change_capacity (sz); 4325 retval.change_capacity (sz);
4326 x_nz = sz; 4326 x_nz = sz;
4327 } 4327 }
4328 4328
4329 for (octave_idx_type i = 0; i < nr; i++) 4329 for (octave_idx_type i = 0; i < nr; i++)
4330 if (Bx[i] != 0.) 4330 if (Bx[i] != 0.)
4331 { 4331 {
4332 retval.xridx(ii) = i; 4332 retval.xridx(ii) = i;
4333 retval.xdata(ii++) = Bx[i]; 4333 retval.xdata(ii++) = Bx[i];
4334 } 4334 }
4335 4335
4336 retval.xcidx(j+1) = ii; 4336 retval.xcidx(j+1) = ii;
4337 } 4337 }
4338 4338
4339 retval.maybe_compress (); 4339 retval.maybe_compress ();
4340 } 4340 }
4341 } 4341 }
4342 else if (typ != MatrixType::Tridiagonal_Hermitian) 4342 else if (typ != MatrixType::Tridiagonal_Hermitian)
4343 (*current_liboctave_error_handler) ("incorrect matrix type"); 4343 (*current_liboctave_error_handler) ("incorrect matrix type");
4344 } 4344 }
4345 4345
4346 return retval; 4346 return retval;
4347 } 4347 }
4348 4348
4349 ComplexMatrix 4349 ComplexMatrix
4350 SparseComplexMatrix::bsolve (MatrixType &mattype, const Matrix& b, 4350 SparseComplexMatrix::bsolve (MatrixType &mattype, const Matrix& b,
4351 octave_idx_type& err, double& rcond, 4351 octave_idx_type& err, double& rcond,
4352 solve_singularity_handler sing_handler, 4352 solve_singularity_handler sing_handler,
4353 bool calc_cond) const 4353 bool calc_cond) const
4354 { 4354 {
4355 ComplexMatrix retval; 4355 ComplexMatrix retval;
4356 4356
4357 octave_idx_type nr = rows (); 4357 octave_idx_type nr = rows ();
4358 octave_idx_type nc = cols (); 4358 octave_idx_type nc = cols ();
4368 // Print spparms("spumoni") info if requested 4368 // Print spparms("spumoni") info if requested
4369 volatile int typ = mattype.type (); 4369 volatile int typ = mattype.type ();
4370 mattype.info (); 4370 mattype.info ();
4371 4371
4372 if (typ == MatrixType::Banded_Hermitian) 4372 if (typ == MatrixType::Banded_Hermitian)
4373 { 4373 {
4374 octave_idx_type n_lower = mattype.nlower (); 4374 octave_idx_type n_lower = mattype.nlower ();
4375 octave_idx_type ldm = n_lower + 1; 4375 octave_idx_type ldm = n_lower + 1;
4376 ComplexMatrix m_band (ldm, nc); 4376 ComplexMatrix m_band (ldm, nc);
4377 Complex *tmp_data = m_band.fortran_vec (); 4377 Complex *tmp_data = m_band.fortran_vec ();
4378 4378
4379 if (! mattype.is_dense ()) 4379 if (! mattype.is_dense ())
4380 { 4380 {
4381 octave_idx_type ii = 0; 4381 octave_idx_type ii = 0;
4382 4382
4383 for (octave_idx_type j = 0; j < ldm; j++) 4383 for (octave_idx_type j = 0; j < ldm; j++)
4384 for (octave_idx_type i = 0; i < nc; i++) 4384 for (octave_idx_type i = 0; i < nc; i++)
4385 tmp_data[ii++] = 0.; 4385 tmp_data[ii++] = 0.;
4386 } 4386 }
4387 4387
4388 for (octave_idx_type j = 0; j < nc; j++) 4388 for (octave_idx_type j = 0; j < nc; j++)
4389 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4389 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4390 { 4390 {
4391 octave_idx_type ri = ridx (i); 4391 octave_idx_type ri = ridx (i);
4392 if (ri >= j) 4392 if (ri >= j)
4393 m_band(ri - j, j) = data(i); 4393 m_band(ri - j, j) = data(i);
4394 } 4394 }
4395 4395
4396 // Calculate the norm of the matrix, for later use. 4396 // Calculate the norm of the matrix, for later use.
4397 double anorm; 4397 double anorm;
4398 if (calc_cond) 4398 if (calc_cond)
4399 anorm = m_band.abs().sum().row(0).max(); 4399 anorm = m_band.abs().sum().row(0).max();
4400 4400
4401 char job = 'L'; 4401 char job = 'L';
4402 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), 4402 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),
4403 nr, n_lower, tmp_data, ldm, err 4403 nr, n_lower, tmp_data, ldm, err
4404 F77_CHAR_ARG_LEN (1))); 4404 F77_CHAR_ARG_LEN (1)));
4405 4405
4406 if (err != 0) 4406 if (err != 0)
4407 { 4407 {
4408 rcond = 0.0; 4408 rcond = 0.0;
4409 // Matrix is not positive definite!! Fall through to 4409 // Matrix is not positive definite!! Fall through to
4410 // unsymmetric banded solver. 4410 // unsymmetric banded solver.
4411 mattype.mark_as_unsymmetric (); 4411 mattype.mark_as_unsymmetric ();
4412 typ = MatrixType::Banded; 4412 typ = MatrixType::Banded;
4413 err = 0; 4413 err = 0;
4414 } 4414 }
4415 else 4415 else
4416 { 4416 {
4417 if (calc_cond) 4417 if (calc_cond)
4418 { 4418 {
4419 Array<Complex> z (2 * nr); 4419 Array<Complex> z (2 * nr);
4420 Complex *pz = z.fortran_vec (); 4420 Complex *pz = z.fortran_vec ();
4421 Array<double> iz (nr); 4421 Array<double> iz (nr);
4422 double *piz = iz.fortran_vec (); 4422 double *piz = iz.fortran_vec ();
4423 4423
4424 F77_XFCN (zpbcon, ZPBCON, 4424 F77_XFCN (zpbcon, ZPBCON,
4425 (F77_CONST_CHAR_ARG2 (&job, 1), 4425 (F77_CONST_CHAR_ARG2 (&job, 1),
4426 nr, n_lower, tmp_data, ldm, 4426 nr, n_lower, tmp_data, ldm,
4427 anorm, rcond, pz, piz, err 4427 anorm, rcond, pz, piz, err
4428 F77_CHAR_ARG_LEN (1))); 4428 F77_CHAR_ARG_LEN (1)));
4429 4429
4430 if (err != 0) 4430 if (err != 0)
4431 err = -2; 4431 err = -2;
4432 4432
4433 volatile double rcond_plus_one = rcond + 1.0; 4433 volatile double rcond_plus_one = rcond + 1.0;
4434 4434
4435 if (rcond_plus_one == 1.0 || xisnan (rcond)) 4435 if (rcond_plus_one == 1.0 || xisnan (rcond))
4436 { 4436 {
4437 err = -2; 4437 err = -2;
4438 4438
4439 if (sing_handler) 4439 if (sing_handler)
4440 { 4440 {
4441 sing_handler (rcond); 4441 sing_handler (rcond);
4442 mattype.mark_as_rectangular (); 4442 mattype.mark_as_rectangular ();
4443 } 4443 }
4444 else 4444 else
4445 (*current_liboctave_error_handler) 4445 (*current_liboctave_error_handler)
4446 ("matrix singular to machine precision, rcond = %g", 4446 ("matrix singular to machine precision, rcond = %g",
4447 rcond); 4447 rcond);
4448 } 4448 }
4449 } 4449 }
4450 else 4450 else
4451 rcond = 1.0; 4451 rcond = 1.0;
4452 4452
4453 if (err == 0) 4453 if (err == 0)
4454 { 4454 {
4455 retval = ComplexMatrix (b); 4455 retval = ComplexMatrix (b);
4456 Complex *result = retval.fortran_vec (); 4456 Complex *result = retval.fortran_vec ();
4457 4457
4458 octave_idx_type b_nc = b.cols (); 4458 octave_idx_type b_nc = b.cols ();
4459 4459
4460 F77_XFCN (zpbtrs, ZPBTRS, 4460 F77_XFCN (zpbtrs, ZPBTRS,
4461 (F77_CONST_CHAR_ARG2 (&job, 1), 4461 (F77_CONST_CHAR_ARG2 (&job, 1),
4462 nr, n_lower, b_nc, tmp_data, 4462 nr, n_lower, b_nc, tmp_data,
4463 ldm, result, b.rows(), err 4463 ldm, result, b.rows(), err
4464 F77_CHAR_ARG_LEN (1))); 4464 F77_CHAR_ARG_LEN (1)));
4465 4465
4466 if (err != 0) 4466 if (err != 0)
4467 { 4467 {
4468 (*current_liboctave_error_handler) 4468 (*current_liboctave_error_handler)
4469 ("SparseMatrix::solve solve failed"); 4469 ("SparseMatrix::solve solve failed");
4470 err = -1; 4470 err = -1;
4471 } 4471 }
4472 } 4472 }
4473 } 4473 }
4474 } 4474 }
4475 4475
4476 if (typ == MatrixType::Banded) 4476 if (typ == MatrixType::Banded)
4477 { 4477 {
4478 // Create the storage for the banded form of the sparse matrix 4478 // Create the storage for the banded form of the sparse matrix
4479 octave_idx_type n_upper = mattype.nupper (); 4479 octave_idx_type n_upper = mattype.nupper ();
4480 octave_idx_type n_lower = mattype.nlower (); 4480 octave_idx_type n_lower = mattype.nlower ();
4481 octave_idx_type ldm = n_upper + 2 * n_lower + 1; 4481 octave_idx_type ldm = n_upper + 2 * n_lower + 1;
4482 4482
4483 ComplexMatrix m_band (ldm, nc); 4483 ComplexMatrix m_band (ldm, nc);
4484 Complex *tmp_data = m_band.fortran_vec (); 4484 Complex *tmp_data = m_band.fortran_vec ();
4485 4485
4486 if (! mattype.is_dense ()) 4486 if (! mattype.is_dense ())
4487 { 4487 {
4488 octave_idx_type ii = 0; 4488 octave_idx_type ii = 0;
4489 4489
4490 for (octave_idx_type j = 0; j < ldm; j++) 4490 for (octave_idx_type j = 0; j < ldm; j++)
4491 for (octave_idx_type i = 0; i < nc; i++) 4491 for (octave_idx_type i = 0; i < nc; i++)
4492 tmp_data[ii++] = 0.; 4492 tmp_data[ii++] = 0.;
4493 } 4493 }
4494 4494
4495 for (octave_idx_type j = 0; j < nc; j++) 4495 for (octave_idx_type j = 0; j < nc; j++)
4496 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4496 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4497 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); 4497 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i);
4498 4498
4499 // Calculate the norm of the matrix, for later use. 4499 // Calculate the norm of the matrix, for later use.
4500 double anorm; 4500 double anorm;
4501 if (calc_cond) 4501 if (calc_cond)
4502 { 4502 {
4503 for (octave_idx_type j = 0; j < nr; j++) 4503 for (octave_idx_type j = 0; j < nr; j++)
4504 { 4504 {
4505 double atmp = 0.; 4505 double atmp = 0.;
4506 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4506 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4507 atmp += std::abs(data(i)); 4507 atmp += std::abs(data(i));
4508 if (atmp > anorm) 4508 if (atmp > anorm)
4509 anorm = atmp; 4509 anorm = atmp;
4510 } 4510 }
4511 } 4511 }
4512 4512
4513 Array<octave_idx_type> ipvt (nr); 4513 Array<octave_idx_type> ipvt (nr);
4514 octave_idx_type *pipvt = ipvt.fortran_vec (); 4514 octave_idx_type *pipvt = ipvt.fortran_vec ();
4515 4515
4516 F77_XFCN (zgbtrf, ZGBTRF, (nr, nc, n_lower, n_upper, tmp_data, 4516 F77_XFCN (zgbtrf, ZGBTRF, (nr, nc, n_lower, n_upper, tmp_data,
4517 ldm, pipvt, err)); 4517 ldm, pipvt, err));
4518 4518
4519 // Throw-away extra info LAPACK gives so as to not 4519 // Throw-away extra info LAPACK gives so as to not
4520 // change output. 4520 // change output.
4521 if (err != 0) 4521 if (err != 0)
4522 { 4522 {
4523 rcond = 0.0; 4523 rcond = 0.0;
4524 err = -2; 4524 err = -2;
4525 4525
4526 if (sing_handler) 4526 if (sing_handler)
4527 { 4527 {
4528 sing_handler (rcond); 4528 sing_handler (rcond);
4529 mattype.mark_as_rectangular (); 4529 mattype.mark_as_rectangular ();
4530 } 4530 }
4531 else 4531 else
4532 (*current_liboctave_error_handler) 4532 (*current_liboctave_error_handler)
4533 ("matrix singular to machine precision"); 4533 ("matrix singular to machine precision");
4534 } 4534 }
4535 else 4535 else
4536 { 4536 {
4537 if (calc_cond) 4537 if (calc_cond)
4538 { 4538 {
4539 char job = '1'; 4539 char job = '1';
4540 Array<Complex> z (2 * nr); 4540 Array<Complex> z (2 * nr);
4541 Complex *pz = z.fortran_vec (); 4541 Complex *pz = z.fortran_vec ();
4542 Array<double> iz (nr); 4542 Array<double> iz (nr);
4543 double *piz = iz.fortran_vec (); 4543 double *piz = iz.fortran_vec ();
4544 4544
4545 F77_XFCN (zgbcon, ZGBCON, 4545 F77_XFCN (zgbcon, ZGBCON,
4546 (F77_CONST_CHAR_ARG2 (&job, 1), 4546 (F77_CONST_CHAR_ARG2 (&job, 1),
4547 nc, n_lower, n_upper, tmp_data, ldm, pipvt, 4547 nc, n_lower, n_upper, tmp_data, ldm, pipvt,
4548 anorm, rcond, pz, piz, err 4548 anorm, rcond, pz, piz, err
4549 F77_CHAR_ARG_LEN (1))); 4549 F77_CHAR_ARG_LEN (1)));
4550 4550
4551 if (err != 0) 4551 if (err != 0)
4552 err = -2; 4552 err = -2;
4553 4553
4554 volatile double rcond_plus_one = rcond + 1.0; 4554 volatile double rcond_plus_one = rcond + 1.0;
4555 4555
4556 if (rcond_plus_one == 1.0 || xisnan (rcond)) 4556 if (rcond_plus_one == 1.0 || xisnan (rcond))
4557 { 4557 {
4558 err = -2; 4558 err = -2;
4559 4559
4560 if (sing_handler) 4560 if (sing_handler)
4561 { 4561 {
4562 sing_handler (rcond); 4562 sing_handler (rcond);
4563 mattype.mark_as_rectangular (); 4563 mattype.mark_as_rectangular ();
4564 } 4564 }
4565 else 4565 else
4566 (*current_liboctave_error_handler) 4566 (*current_liboctave_error_handler)
4567 ("matrix singular to machine precision, rcond = %g", 4567 ("matrix singular to machine precision, rcond = %g",
4568 rcond); 4568 rcond);
4569 } 4569 }
4570 } 4570 }
4571 else 4571 else
4572 rcond = 1.; 4572 rcond = 1.;
4573 4573
4574 if (err == 0) 4574 if (err == 0)
4575 { 4575 {
4576 retval = ComplexMatrix (b); 4576 retval = ComplexMatrix (b);
4577 Complex *result = retval.fortran_vec (); 4577 Complex *result = retval.fortran_vec ();
4578 4578
4579 octave_idx_type b_nc = b.cols (); 4579 octave_idx_type b_nc = b.cols ();
4580 4580
4581 char job = 'N'; 4581 char job = 'N';
4582 F77_XFCN (zgbtrs, ZGBTRS, 4582 F77_XFCN (zgbtrs, ZGBTRS,
4583 (F77_CONST_CHAR_ARG2 (&job, 1), 4583 (F77_CONST_CHAR_ARG2 (&job, 1),
4584 nr, n_lower, n_upper, b_nc, tmp_data, 4584 nr, n_lower, n_upper, b_nc, tmp_data,
4585 ldm, pipvt, result, b.rows(), err 4585 ldm, pipvt, result, b.rows(), err
4586 F77_CHAR_ARG_LEN (1))); 4586 F77_CHAR_ARG_LEN (1)));
4587 } 4587 }
4588 } 4588 }
4589 } 4589 }
4590 else if (typ != MatrixType::Banded_Hermitian) 4590 else if (typ != MatrixType::Banded_Hermitian)
4591 (*current_liboctave_error_handler) ("incorrect matrix type"); 4591 (*current_liboctave_error_handler) ("incorrect matrix type");
4592 } 4592 }
4593 4593
4594 return retval; 4594 return retval;
4595 } 4595 }
4596 4596
4597 SparseComplexMatrix 4597 SparseComplexMatrix
4598 SparseComplexMatrix::bsolve (MatrixType &mattype, const SparseMatrix& b, 4598 SparseComplexMatrix::bsolve (MatrixType &mattype, const SparseMatrix& b,
4599 octave_idx_type& err, double& rcond, 4599 octave_idx_type& err, double& rcond,
4600 solve_singularity_handler sing_handler, 4600 solve_singularity_handler sing_handler,
4601 bool calc_cond) const 4601 bool calc_cond) const
4602 { 4602 {
4603 SparseComplexMatrix retval; 4603 SparseComplexMatrix retval;
4604 4604
4605 octave_idx_type nr = rows (); 4605 octave_idx_type nr = rows ();
4606 octave_idx_type nc = cols (); 4606 octave_idx_type nc = cols ();
4616 // Print spparms("spumoni") info if requested 4616 // Print spparms("spumoni") info if requested
4617 volatile int typ = mattype.type (); 4617 volatile int typ = mattype.type ();
4618 mattype.info (); 4618 mattype.info ();
4619 4619
4620 if (typ == MatrixType::Banded_Hermitian) 4620 if (typ == MatrixType::Banded_Hermitian)
4621 { 4621 {
4622 octave_idx_type n_lower = mattype.nlower (); 4622 octave_idx_type n_lower = mattype.nlower ();
4623 octave_idx_type ldm = n_lower + 1; 4623 octave_idx_type ldm = n_lower + 1;
4624 4624
4625 ComplexMatrix m_band (ldm, nc); 4625 ComplexMatrix m_band (ldm, nc);
4626 Complex *tmp_data = m_band.fortran_vec (); 4626 Complex *tmp_data = m_band.fortran_vec ();
4627 4627
4628 if (! mattype.is_dense ()) 4628 if (! mattype.is_dense ())
4629 { 4629 {
4630 octave_idx_type ii = 0; 4630 octave_idx_type ii = 0;
4631 4631
4632 for (octave_idx_type j = 0; j < ldm; j++) 4632 for (octave_idx_type j = 0; j < ldm; j++)
4633 for (octave_idx_type i = 0; i < nc; i++) 4633 for (octave_idx_type i = 0; i < nc; i++)
4634 tmp_data[ii++] = 0.; 4634 tmp_data[ii++] = 0.;
4635 } 4635 }
4636 4636
4637 for (octave_idx_type j = 0; j < nc; j++) 4637 for (octave_idx_type j = 0; j < nc; j++)
4638 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4638 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4639 { 4639 {
4640 octave_idx_type ri = ridx (i); 4640 octave_idx_type ri = ridx (i);
4641 if (ri >= j) 4641 if (ri >= j)
4642 m_band(ri - j, j) = data(i); 4642 m_band(ri - j, j) = data(i);
4643 } 4643 }
4644 4644
4645 // Calculate the norm of the matrix, for later use. 4645 // Calculate the norm of the matrix, for later use.
4646 double anorm; 4646 double anorm;
4647 if (calc_cond) 4647 if (calc_cond)
4648 anorm = m_band.abs().sum().row(0).max(); 4648 anorm = m_band.abs().sum().row(0).max();
4649 4649
4650 char job = 'L'; 4650 char job = 'L';
4651 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), 4651 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),
4652 nr, n_lower, tmp_data, ldm, err 4652 nr, n_lower, tmp_data, ldm, err
4653 F77_CHAR_ARG_LEN (1))); 4653 F77_CHAR_ARG_LEN (1)));
4654 4654
4655 if (err != 0) 4655 if (err != 0)
4656 { 4656 {
4657 rcond = 0.0; 4657 rcond = 0.0;
4658 mattype.mark_as_unsymmetric (); 4658 mattype.mark_as_unsymmetric ();
4659 typ = MatrixType::Banded; 4659 typ = MatrixType::Banded;
4660 err = 0; 4660 err = 0;
4661 } 4661 }
4662 else 4662 else
4663 { 4663 {
4664 if (calc_cond) 4664 if (calc_cond)
4665 { 4665 {
4666 Array<Complex> z (2 * nr); 4666 Array<Complex> z (2 * nr);
4667 Complex *pz = z.fortran_vec (); 4667 Complex *pz = z.fortran_vec ();
4668 Array<double> iz (nr); 4668 Array<double> iz (nr);
4669 double *piz = iz.fortran_vec (); 4669 double *piz = iz.fortran_vec ();
4670 4670
4671 F77_XFCN (zpbcon, ZPBCON, 4671 F77_XFCN (zpbcon, ZPBCON,
4672 (F77_CONST_CHAR_ARG2 (&job, 1), 4672 (F77_CONST_CHAR_ARG2 (&job, 1),
4673 nr, n_lower, tmp_data, ldm, 4673 nr, n_lower, tmp_data, ldm,
4674 anorm, rcond, pz, piz, err 4674 anorm, rcond, pz, piz, err
4675 F77_CHAR_ARG_LEN (1))); 4675 F77_CHAR_ARG_LEN (1)));
4676 4676
4677 if (err != 0) 4677 if (err != 0)
4678 err = -2; 4678 err = -2;
4679 4679
4680 volatile double rcond_plus_one = rcond + 1.0; 4680 volatile double rcond_plus_one = rcond + 1.0;
4681 4681
4682 if (rcond_plus_one == 1.0 || xisnan (rcond)) 4682 if (rcond_plus_one == 1.0 || xisnan (rcond))
4683 { 4683 {
4684 err = -2; 4684 err = -2;
4685 4685
4686 if (sing_handler) 4686 if (sing_handler)
4687 { 4687 {
4688 sing_handler (rcond); 4688 sing_handler (rcond);
4689 mattype.mark_as_rectangular (); 4689 mattype.mark_as_rectangular ();
4690 } 4690 }
4691 else 4691 else
4692 (*current_liboctave_error_handler) 4692 (*current_liboctave_error_handler)
4693 ("matrix singular to machine precision, rcond = %g", 4693 ("matrix singular to machine precision, rcond = %g",
4694 rcond); 4694 rcond);
4695 } 4695 }
4696 } 4696 }
4697 else 4697 else
4698 rcond = 1.0; 4698 rcond = 1.0;
4699 4699
4700 if (err == 0) 4700 if (err == 0)
4701 { 4701 {
4702 octave_idx_type b_nr = b.rows (); 4702 octave_idx_type b_nr = b.rows ();
4703 octave_idx_type b_nc = b.cols (); 4703 octave_idx_type b_nc = b.cols ();
4704 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); 4704 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
4705 4705
4706 // Take a first guess that the number of non-zero terms 4706 // Take a first guess that the number of non-zero terms
4707 // will be as many as in b 4707 // will be as many as in b
4708 volatile octave_idx_type x_nz = b.nnz (); 4708 volatile octave_idx_type x_nz = b.nnz ();
4709 volatile octave_idx_type ii = 0; 4709 volatile octave_idx_type ii = 0;
4710 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); 4710 retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
4711 4711
4712 retval.xcidx(0) = 0; 4712 retval.xcidx(0) = 0;
4713 for (volatile octave_idx_type j = 0; j < b_nc; j++) 4713 for (volatile octave_idx_type j = 0; j < b_nc; j++)
4714 { 4714 {
4715 for (octave_idx_type i = 0; i < b_nr; i++) 4715 for (octave_idx_type i = 0; i < b_nr; i++)
4716 Bx[i] = b.elem (i, j); 4716 Bx[i] = b.elem (i, j);
4717 4717
4718 F77_XFCN (zpbtrs, ZPBTRS, 4718 F77_XFCN (zpbtrs, ZPBTRS,
4719 (F77_CONST_CHAR_ARG2 (&job, 1), 4719 (F77_CONST_CHAR_ARG2 (&job, 1),
4720 nr, n_lower, 1, tmp_data, 4720 nr, n_lower, 1, tmp_data,
4721 ldm, Bx, b_nr, err 4721 ldm, Bx, b_nr, err
4722 F77_CHAR_ARG_LEN (1))); 4722 F77_CHAR_ARG_LEN (1)));
4723 4723
4724 if (err != 0) 4724 if (err != 0)
4725 { 4725 {
4726 (*current_liboctave_error_handler) 4726 (*current_liboctave_error_handler)
4727 ("SparseComplexMatrix::solve solve failed"); 4727 ("SparseComplexMatrix::solve solve failed");
4728 err = -1; 4728 err = -1;
4729 break; 4729 break;
4730 } 4730 }
4731 4731
4732 for (octave_idx_type i = 0; i < b_nr; i++) 4732 for (octave_idx_type i = 0; i < b_nr; i++)
4733 { 4733 {
4734 Complex tmp = Bx[i]; 4734 Complex tmp = Bx[i];
4735 if (tmp != 0.0) 4735 if (tmp != 0.0)
4736 { 4736 {
4737 if (ii == x_nz) 4737 if (ii == x_nz)
4738 { 4738 {
4739 // Resize the sparse matrix 4739 // Resize the sparse matrix
4740 octave_idx_type sz = x_nz * 4740 octave_idx_type sz = x_nz *
4741 (b_nc - j) / b_nc; 4741 (b_nc - j) / b_nc;
4742 sz = (sz > 10 ? sz : 10) + x_nz; 4742 sz = (sz > 10 ? sz : 10) + x_nz;
4743 retval.change_capacity (sz); 4743 retval.change_capacity (sz);
4744 x_nz = sz; 4744 x_nz = sz;
4745 } 4745 }
4746 retval.xdata(ii) = tmp; 4746 retval.xdata(ii) = tmp;
4747 retval.xridx(ii++) = i; 4747 retval.xridx(ii++) = i;
4748 } 4748 }
4749 } 4749 }
4750 retval.xcidx(j+1) = ii; 4750 retval.xcidx(j+1) = ii;
4751 } 4751 }
4752 4752
4753 retval.maybe_compress (); 4753 retval.maybe_compress ();
4754 } 4754 }
4755 } 4755 }
4756 } 4756 }
4757 4757
4758 if (typ == MatrixType::Banded) 4758 if (typ == MatrixType::Banded)
4759 { 4759 {
4760 // Create the storage for the banded form of the sparse matrix 4760 // Create the storage for the banded form of the sparse matrix
4761 octave_idx_type n_upper = mattype.nupper (); 4761 octave_idx_type n_upper = mattype.nupper ();
4762 octave_idx_type n_lower = mattype.nlower (); 4762 octave_idx_type n_lower = mattype.nlower ();
4763 octave_idx_type ldm = n_upper + 2 * n_lower + 1; 4763 octave_idx_type ldm = n_upper + 2 * n_lower + 1;
4764 4764
4765 ComplexMatrix m_band (ldm, nc); 4765 ComplexMatrix m_band (ldm, nc);
4766 Complex *tmp_data = m_band.fortran_vec (); 4766 Complex *tmp_data = m_band.fortran_vec ();
4767 4767
4768 if (! mattype.is_dense ()) 4768 if (! mattype.is_dense ())
4769 { 4769 {
4770 octave_idx_type ii = 0; 4770 octave_idx_type ii = 0;
4771 4771
4772 for (octave_idx_type j = 0; j < ldm; j++) 4772 for (octave_idx_type j = 0; j < ldm; j++)
4773 for (octave_idx_type i = 0; i < nc; i++) 4773 for (octave_idx_type i = 0; i < nc; i++)
4774 tmp_data[ii++] = 0.; 4774 tmp_data[ii++] = 0.;
4775 } 4775 }
4776 4776
4777 for (octave_idx_type j = 0; j < nc; j++) 4777 for (octave_idx_type j = 0; j < nc; j++)
4778 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4778 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4779 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); 4779 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i);
4780 4780
4781 // Calculate the norm of the matrix, for later use. 4781 // Calculate the norm of the matrix, for later use.
4782 double anorm; 4782 double anorm;
4783 if (calc_cond) 4783 if (calc_cond)
4784 { 4784 {
4785 for (octave_idx_type j = 0; j < nr; j++) 4785 for (octave_idx_type j = 0; j < nr; j++)
4786 { 4786 {
4787 double atmp = 0.; 4787 double atmp = 0.;
4788 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4788 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4789 atmp += std::abs(data(i)); 4789 atmp += std::abs(data(i));
4790 if (atmp > anorm) 4790 if (atmp > anorm)
4791 anorm = atmp; 4791 anorm = atmp;
4792 } 4792 }
4793 } 4793 }
4794 4794
4795 Array<octave_idx_type> ipvt (nr); 4795 Array<octave_idx_type> ipvt (nr);
4796 octave_idx_type *pipvt = ipvt.fortran_vec (); 4796 octave_idx_type *pipvt = ipvt.fortran_vec ();
4797 4797
4798 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, 4798 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data,
4799 ldm, pipvt, err)); 4799 ldm, pipvt, err));
4800 4800
4801 if (err != 0) 4801 if (err != 0)
4802 { 4802 {
4803 rcond = 0.0; 4803 rcond = 0.0;
4804 err = -2; 4804 err = -2;
4805 4805
4806 if (sing_handler) 4806 if (sing_handler)
4807 { 4807 {
4808 sing_handler (rcond); 4808 sing_handler (rcond);
4809 mattype.mark_as_rectangular (); 4809 mattype.mark_as_rectangular ();
4810 } 4810 }
4811 else 4811 else
4812 (*current_liboctave_error_handler) 4812 (*current_liboctave_error_handler)
4813 ("matrix singular to machine precision"); 4813 ("matrix singular to machine precision");
4814 4814
4815 } 4815 }
4816 else 4816 else
4817 { 4817 {
4818 if (calc_cond) 4818 if (calc_cond)
4819 { 4819 {
4820 char job = '1'; 4820 char job = '1';
4821 Array<Complex> z (2 * nr); 4821 Array<Complex> z (2 * nr);
4822 Complex *pz = z.fortran_vec (); 4822 Complex *pz = z.fortran_vec ();
4823 Array<double> iz (nr); 4823 Array<double> iz (nr);
4824 double *piz = iz.fortran_vec (); 4824 double *piz = iz.fortran_vec ();
4825 4825
4826 F77_XFCN (zgbcon, ZGBCON, 4826 F77_XFCN (zgbcon, ZGBCON,
4827 (F77_CONST_CHAR_ARG2 (&job, 1), 4827 (F77_CONST_CHAR_ARG2 (&job, 1),
4828 nc, n_lower, n_upper, tmp_data, ldm, pipvt, 4828 nc, n_lower, n_upper, tmp_data, ldm, pipvt,
4829 anorm, rcond, pz, piz, err 4829 anorm, rcond, pz, piz, err
4830 F77_CHAR_ARG_LEN (1))); 4830 F77_CHAR_ARG_LEN (1)));
4831 4831
4832 if (err != 0) 4832 if (err != 0)
4833 err = -2; 4833 err = -2;
4834 4834
4835 volatile double rcond_plus_one = rcond + 1.0; 4835 volatile double rcond_plus_one = rcond + 1.0;
4836 4836
4837 if (rcond_plus_one == 1.0 || xisnan (rcond)) 4837 if (rcond_plus_one == 1.0 || xisnan (rcond))
4838 { 4838 {
4839 err = -2; 4839 err = -2;
4840 4840
4841 if (sing_handler) 4841 if (sing_handler)
4842 { 4842 {
4843 sing_handler (rcond); 4843 sing_handler (rcond);
4844 mattype.mark_as_rectangular (); 4844 mattype.mark_as_rectangular ();
4845 } 4845 }
4846 else 4846 else
4847 (*current_liboctave_error_handler) 4847 (*current_liboctave_error_handler)
4848 ("matrix singular to machine precision, rcond = %g", 4848 ("matrix singular to machine precision, rcond = %g",
4849 rcond); 4849 rcond);
4850 } 4850 }
4851 } 4851 }
4852 else 4852 else
4853 rcond = 1.; 4853 rcond = 1.;
4854 4854
4855 if (err == 0) 4855 if (err == 0)
4856 { 4856 {
4857 char job = 'N'; 4857 char job = 'N';
4858 volatile octave_idx_type x_nz = b.nnz (); 4858 volatile octave_idx_type x_nz = b.nnz ();
4859 octave_idx_type b_nc = b.cols (); 4859 octave_idx_type b_nc = b.cols ();
4860 retval = SparseComplexMatrix (nr, b_nc, x_nz); 4860 retval = SparseComplexMatrix (nr, b_nc, x_nz);
4861 retval.xcidx(0) = 0; 4861 retval.xcidx(0) = 0;
4862 volatile octave_idx_type ii = 0; 4862 volatile octave_idx_type ii = 0;
4863 4863
4864 OCTAVE_LOCAL_BUFFER (Complex, work, nr); 4864 OCTAVE_LOCAL_BUFFER (Complex, work, nr);
4865 4865
4866 for (volatile octave_idx_type j = 0; j < b_nc; j++) 4866 for (volatile octave_idx_type j = 0; j < b_nc; j++)
4867 { 4867 {
4868 for (octave_idx_type i = 0; i < nr; i++) 4868 for (octave_idx_type i = 0; i < nr; i++)
4869 work[i] = 0.; 4869 work[i] = 0.;
4870 for (octave_idx_type i = b.cidx(j); 4870 for (octave_idx_type i = b.cidx(j);
4871 i < b.cidx(j+1); i++) 4871 i < b.cidx(j+1); i++)
4872 work[b.ridx(i)] = b.data(i); 4872 work[b.ridx(i)] = b.data(i);
4873 4873
4874 F77_XFCN (zgbtrs, ZGBTRS, 4874 F77_XFCN (zgbtrs, ZGBTRS,
4875 (F77_CONST_CHAR_ARG2 (&job, 1), 4875 (F77_CONST_CHAR_ARG2 (&job, 1),
4876 nr, n_lower, n_upper, 1, tmp_data, 4876 nr, n_lower, n_upper, 1, tmp_data,
4877 ldm, pipvt, work, b.rows (), err 4877 ldm, pipvt, work, b.rows (), err
4878 F77_CHAR_ARG_LEN (1))); 4878 F77_CHAR_ARG_LEN (1)));
4879 4879
4880 // Count non-zeros in work vector and adjust 4880 // Count non-zeros in work vector and adjust
4881 // space in retval if needed 4881 // space in retval if needed
4882 octave_idx_type new_nnz = 0; 4882 octave_idx_type new_nnz = 0;
4883 for (octave_idx_type i = 0; i < nr; i++) 4883 for (octave_idx_type i = 0; i < nr; i++)
4884 if (work[i] != 0.) 4884 if (work[i] != 0.)
4885 new_nnz++; 4885 new_nnz++;
4886 4886
4887 if (ii + new_nnz > x_nz) 4887 if (ii + new_nnz > x_nz)
4888 { 4888 {
4889 // Resize the sparse matrix 4889 // Resize the sparse matrix
4890 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 4890 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
4891 retval.change_capacity (sz); 4891 retval.change_capacity (sz);
4892 x_nz = sz; 4892 x_nz = sz;
4893 } 4893 }
4894 4894
4895 for (octave_idx_type i = 0; i < nr; i++) 4895 for (octave_idx_type i = 0; i < nr; i++)
4896 if (work[i] != 0.) 4896 if (work[i] != 0.)
4897 { 4897 {
4898 retval.xridx(ii) = i; 4898 retval.xridx(ii) = i;
4899 retval.xdata(ii++) = work[i]; 4899 retval.xdata(ii++) = work[i];
4900 } 4900 }
4901 retval.xcidx(j+1) = ii; 4901 retval.xcidx(j+1) = ii;
4902 } 4902 }
4903 4903
4904 retval.maybe_compress (); 4904 retval.maybe_compress ();
4905 } 4905 }
4906 } 4906 }
4907 } 4907 }
4908 else if (typ != MatrixType::Banded_Hermitian) 4908 else if (typ != MatrixType::Banded_Hermitian)
4909 (*current_liboctave_error_handler) ("incorrect matrix type"); 4909 (*current_liboctave_error_handler) ("incorrect matrix type");
4910 } 4910 }
4911 4911
4912 return retval; 4912 return retval;
4913 } 4913 }
4914 4914
4915 ComplexMatrix 4915 ComplexMatrix
4916 SparseComplexMatrix::bsolve (MatrixType &mattype, const ComplexMatrix& b, 4916 SparseComplexMatrix::bsolve (MatrixType &mattype, const ComplexMatrix& b,
4917 octave_idx_type& err, double& rcond, 4917 octave_idx_type& err, double& rcond,
4918 solve_singularity_handler sing_handler, 4918 solve_singularity_handler sing_handler,
4919 bool calc_cond) const 4919 bool calc_cond) const
4920 { 4920 {
4921 ComplexMatrix retval; 4921 ComplexMatrix retval;
4922 4922
4923 octave_idx_type nr = rows (); 4923 octave_idx_type nr = rows ();
4924 octave_idx_type nc = cols (); 4924 octave_idx_type nc = cols ();
4934 // Print spparms("spumoni") info if requested 4934 // Print spparms("spumoni") info if requested
4935 volatile int typ = mattype.type (); 4935 volatile int typ = mattype.type ();
4936 mattype.info (); 4936 mattype.info ();
4937 4937
4938 if (typ == MatrixType::Banded_Hermitian) 4938 if (typ == MatrixType::Banded_Hermitian)
4939 { 4939 {
4940 octave_idx_type n_lower = mattype.nlower (); 4940 octave_idx_type n_lower = mattype.nlower ();
4941 octave_idx_type ldm = n_lower + 1; 4941 octave_idx_type ldm = n_lower + 1;
4942 4942
4943 ComplexMatrix m_band (ldm, nc); 4943 ComplexMatrix m_band (ldm, nc);
4944 Complex *tmp_data = m_band.fortran_vec (); 4944 Complex *tmp_data = m_band.fortran_vec ();
4945 4945
4946 if (! mattype.is_dense ()) 4946 if (! mattype.is_dense ())
4947 { 4947 {
4948 octave_idx_type ii = 0; 4948 octave_idx_type ii = 0;
4949 4949
4950 for (octave_idx_type j = 0; j < ldm; j++) 4950 for (octave_idx_type j = 0; j < ldm; j++)
4951 for (octave_idx_type i = 0; i < nc; i++) 4951 for (octave_idx_type i = 0; i < nc; i++)
4952 tmp_data[ii++] = 0.; 4952 tmp_data[ii++] = 0.;
4953 } 4953 }
4954 4954
4955 for (octave_idx_type j = 0; j < nc; j++) 4955 for (octave_idx_type j = 0; j < nc; j++)
4956 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 4956 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
4957 { 4957 {
4958 octave_idx_type ri = ridx (i); 4958 octave_idx_type ri = ridx (i);
4959 if (ri >= j) 4959 if (ri >= j)
4960 m_band(ri - j, j) = data(i); 4960 m_band(ri - j, j) = data(i);
4961 } 4961 }
4962 4962
4963 // Calculate the norm of the matrix, for later use. 4963 // Calculate the norm of the matrix, for later use.
4964 double anorm; 4964 double anorm;
4965 if (calc_cond) 4965 if (calc_cond)
4966 anorm = m_band.abs().sum().row(0).max(); 4966 anorm = m_band.abs().sum().row(0).max();
4967 4967
4968 char job = 'L'; 4968 char job = 'L';
4969 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), 4969 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),
4970 nr, n_lower, tmp_data, ldm, err 4970 nr, n_lower, tmp_data, ldm, err
4971 F77_CHAR_ARG_LEN (1))); 4971 F77_CHAR_ARG_LEN (1)));
4972 4972
4973 if (err != 0) 4973 if (err != 0)
4974 { 4974 {
4975 // Matrix is not positive definite!! Fall through to 4975 // Matrix is not positive definite!! Fall through to
4976 // unsymmetric banded solver. 4976 // unsymmetric banded solver.
4977 rcond = 0.0; 4977 rcond = 0.0;
4978 mattype.mark_as_unsymmetric (); 4978 mattype.mark_as_unsymmetric ();
4979 typ = MatrixType::Banded; 4979 typ = MatrixType::Banded;
4980 err = 0; 4980 err = 0;
4981 } 4981 }
4982 else 4982 else
4983 { 4983 {
4984 if (calc_cond) 4984 if (calc_cond)
4985 { 4985 {
4986 Array<Complex> z (2 * nr); 4986 Array<Complex> z (2 * nr);
4987 Complex *pz = z.fortran_vec (); 4987 Complex *pz = z.fortran_vec ();
4988 Array<double> iz (nr); 4988 Array<double> iz (nr);
4989 double *piz = iz.fortran_vec (); 4989 double *piz = iz.fortran_vec ();
4990 4990
4991 F77_XFCN (zpbcon, ZPBCON, 4991 F77_XFCN (zpbcon, ZPBCON,
4992 (F77_CONST_CHAR_ARG2 (&job, 1), 4992 (F77_CONST_CHAR_ARG2 (&job, 1),
4993 nr, n_lower, tmp_data, ldm, 4993 nr, n_lower, tmp_data, ldm,
4994 anorm, rcond, pz, piz, err 4994 anorm, rcond, pz, piz, err
4995 F77_CHAR_ARG_LEN (1))); 4995 F77_CHAR_ARG_LEN (1)));
4996 4996
4997 if (err != 0) 4997 if (err != 0)
4998 err = -2; 4998 err = -2;
4999 4999
5000 volatile double rcond_plus_one = rcond + 1.0; 5000 volatile double rcond_plus_one = rcond + 1.0;
5001 5001
5002 if (rcond_plus_one == 1.0 || xisnan (rcond)) 5002 if (rcond_plus_one == 1.0 || xisnan (rcond))
5003 { 5003 {
5004 err = -2; 5004 err = -2;
5005 5005
5006 if (sing_handler) 5006 if (sing_handler)
5007 { 5007 {
5008 sing_handler (rcond); 5008 sing_handler (rcond);
5009 mattype.mark_as_rectangular (); 5009 mattype.mark_as_rectangular ();
5010 } 5010 }
5011 else 5011 else
5012 (*current_liboctave_error_handler) 5012 (*current_liboctave_error_handler)
5013 ("matrix singular to machine precision, rcond = %g", 5013 ("matrix singular to machine precision, rcond = %g",
5014 rcond); 5014 rcond);
5015 } 5015 }
5016 } 5016 }
5017 else 5017 else
5018 rcond = 1.0; 5018 rcond = 1.0;
5019 5019
5020 if (err == 0) 5020 if (err == 0)
5021 { 5021 {
5022 octave_idx_type b_nr = b.rows (); 5022 octave_idx_type b_nr = b.rows ();
5023 octave_idx_type b_nc = b.cols (); 5023 octave_idx_type b_nc = b.cols ();
5024 retval = ComplexMatrix (b); 5024 retval = ComplexMatrix (b);
5025 Complex *result = retval.fortran_vec (); 5025 Complex *result = retval.fortran_vec ();
5026 5026
5027 F77_XFCN (zpbtrs, ZPBTRS, 5027 F77_XFCN (zpbtrs, ZPBTRS,
5028 (F77_CONST_CHAR_ARG2 (&job, 1), 5028 (F77_CONST_CHAR_ARG2 (&job, 1),
5029 nr, n_lower, b_nc, tmp_data, 5029 nr, n_lower, b_nc, tmp_data,
5030 ldm, result, b_nr, err 5030 ldm, result, b_nr, err
5031 F77_CHAR_ARG_LEN (1))); 5031 F77_CHAR_ARG_LEN (1)));
5032 5032
5033 if (err != 0) 5033 if (err != 0)
5034 { 5034 {
5035 (*current_liboctave_error_handler) 5035 (*current_liboctave_error_handler)
5036 ("SparseComplexMatrix::solve solve failed"); 5036 ("SparseComplexMatrix::solve solve failed");
5037 err = -1; 5037 err = -1;
5038 } 5038 }
5039 } 5039 }
5040 } 5040 }
5041 } 5041 }
5042 5042
5043 if (typ == MatrixType::Banded) 5043 if (typ == MatrixType::Banded)
5044 { 5044 {
5045 // Create the storage for the banded form of the sparse matrix 5045 // Create the storage for the banded form of the sparse matrix
5046 octave_idx_type n_upper = mattype.nupper (); 5046 octave_idx_type n_upper = mattype.nupper ();
5047 octave_idx_type n_lower = mattype.nlower (); 5047 octave_idx_type n_lower = mattype.nlower ();
5048 octave_idx_type ldm = n_upper + 2 * n_lower + 1; 5048 octave_idx_type ldm = n_upper + 2 * n_lower + 1;
5049 5049
5050 ComplexMatrix m_band (ldm, nc); 5050 ComplexMatrix m_band (ldm, nc);
5051 Complex *tmp_data = m_band.fortran_vec (); 5051 Complex *tmp_data = m_band.fortran_vec ();
5052 5052
5053 if (! mattype.is_dense ()) 5053 if (! mattype.is_dense ())
5054 { 5054 {
5055 octave_idx_type ii = 0; 5055 octave_idx_type ii = 0;
5056 5056
5057 for (octave_idx_type j = 0; j < ldm; j++) 5057 for (octave_idx_type j = 0; j < ldm; j++)
5058 for (octave_idx_type i = 0; i < nc; i++) 5058 for (octave_idx_type i = 0; i < nc; i++)
5059 tmp_data[ii++] = 0.; 5059 tmp_data[ii++] = 0.;
5060 } 5060 }
5061 5061
5062 for (octave_idx_type j = 0; j < nc; j++) 5062 for (octave_idx_type j = 0; j < nc; j++)
5063 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 5063 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
5064 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); 5064 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i);
5065 5065
5066 // Calculate the norm of the matrix, for later use. 5066 // Calculate the norm of the matrix, for later use.
5067 double anorm; 5067 double anorm;
5068 if (calc_cond) 5068 if (calc_cond)
5069 { 5069 {
5070 for (octave_idx_type j = 0; j < nr; j++) 5070 for (octave_idx_type j = 0; j < nr; j++)
5071 { 5071 {
5072 double atmp = 0.; 5072 double atmp = 0.;
5073 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 5073 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
5074 atmp += std::abs(data(i)); 5074 atmp += std::abs(data(i));
5075 if (atmp > anorm) 5075 if (atmp > anorm)
5076 anorm = atmp; 5076 anorm = atmp;
5077 } 5077 }
5078 } 5078 }
5079 5079
5080 Array<octave_idx_type> ipvt (nr); 5080 Array<octave_idx_type> ipvt (nr);
5081 octave_idx_type *pipvt = ipvt.fortran_vec (); 5081 octave_idx_type *pipvt = ipvt.fortran_vec ();
5082 5082
5083 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, 5083 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data,
5084 ldm, pipvt, err)); 5084 ldm, pipvt, err));
5085 5085
5086 if (err != 0) 5086 if (err != 0)
5087 { 5087 {
5088 err = -2; 5088 err = -2;
5089 rcond = 0.0; 5089 rcond = 0.0;
5090 5090
5091 if (sing_handler) 5091 if (sing_handler)
5092 { 5092 {
5093 sing_handler (rcond); 5093 sing_handler (rcond);
5094 mattype.mark_as_rectangular (); 5094 mattype.mark_as_rectangular ();
5095 } 5095 }
5096 else 5096 else
5097 (*current_liboctave_error_handler) 5097 (*current_liboctave_error_handler)
5098 ("matrix singular to machine precision"); 5098 ("matrix singular to machine precision");
5099 } 5099 }
5100 else 5100 else
5101 { 5101 {
5102 if (calc_cond) 5102 if (calc_cond)
5103 { 5103 {
5104 char job = '1'; 5104 char job = '1';
5105 Array<Complex> z (2 * nr); 5105 Array<Complex> z (2 * nr);
5106 Complex *pz = z.fortran_vec (); 5106 Complex *pz = z.fortran_vec ();
5107 Array<double> iz (nr); 5107 Array<double> iz (nr);
5108 double *piz = iz.fortran_vec (); 5108 double *piz = iz.fortran_vec ();
5109 5109
5110 F77_XFCN (zgbcon, ZGBCON, 5110 F77_XFCN (zgbcon, ZGBCON,
5111 (F77_CONST_CHAR_ARG2 (&job, 1), 5111 (F77_CONST_CHAR_ARG2 (&job, 1),
5112 nc, n_lower, n_upper, tmp_data, ldm, pipvt, 5112 nc, n_lower, n_upper, tmp_data, ldm, pipvt,
5113 anorm, rcond, pz, piz, err 5113 anorm, rcond, pz, piz, err
5114 F77_CHAR_ARG_LEN (1))); 5114 F77_CHAR_ARG_LEN (1)));
5115 5115
5116 if (err != 0) 5116 if (err != 0)
5117 err = -2; 5117 err = -2;
5118 5118
5119 volatile double rcond_plus_one = rcond + 1.0; 5119 volatile double rcond_plus_one = rcond + 1.0;
5120 5120
5121 if (rcond_plus_one == 1.0 || xisnan (rcond)) 5121 if (rcond_plus_one == 1.0 || xisnan (rcond))
5122 { 5122 {
5123 err = -2; 5123 err = -2;
5124 5124
5125 if (sing_handler) 5125 if (sing_handler)
5126 { 5126 {
5127 sing_handler (rcond); 5127 sing_handler (rcond);
5128 mattype.mark_as_rectangular (); 5128 mattype.mark_as_rectangular ();
5129 } 5129 }
5130 else 5130 else
5131 (*current_liboctave_error_handler) 5131 (*current_liboctave_error_handler)
5132 ("matrix singular to machine precision, rcond = %g", 5132 ("matrix singular to machine precision, rcond = %g",
5133 rcond); 5133 rcond);
5134 } 5134 }
5135 } 5135 }
5136 else 5136 else
5137 rcond = 1.; 5137 rcond = 1.;
5138 5138
5139 if (err == 0) 5139 if (err == 0)
5140 { 5140 {
5141 char job = 'N'; 5141 char job = 'N';
5142 octave_idx_type b_nc = b.cols (); 5142 octave_idx_type b_nc = b.cols ();
5143 retval = ComplexMatrix (b); 5143 retval = ComplexMatrix (b);
5144 Complex *result = retval.fortran_vec (); 5144 Complex *result = retval.fortran_vec ();
5145 5145
5146 F77_XFCN (zgbtrs, ZGBTRS, 5146 F77_XFCN (zgbtrs, ZGBTRS,
5147 (F77_CONST_CHAR_ARG2 (&job, 1), 5147 (F77_CONST_CHAR_ARG2 (&job, 1),
5148 nr, n_lower, n_upper, b_nc, tmp_data, 5148 nr, n_lower, n_upper, b_nc, tmp_data,
5149 ldm, pipvt, result, b.rows (), err 5149 ldm, pipvt, result, b.rows (), err
5150 F77_CHAR_ARG_LEN (1))); 5150 F77_CHAR_ARG_LEN (1)));
5151 } 5151 }
5152 } 5152 }
5153 } 5153 }
5154 else if (typ != MatrixType::Banded_Hermitian) 5154 else if (typ != MatrixType::Banded_Hermitian)
5155 (*current_liboctave_error_handler) ("incorrect matrix type"); 5155 (*current_liboctave_error_handler) ("incorrect matrix type");
5156 } 5156 }
5157 5157
5158 return retval; 5158 return retval;
5159 } 5159 }
5160 5160
5161 SparseComplexMatrix 5161 SparseComplexMatrix
5162 SparseComplexMatrix::bsolve (MatrixType &mattype, const SparseComplexMatrix& b, 5162 SparseComplexMatrix::bsolve (MatrixType &mattype, const SparseComplexMatrix& b,
5163 octave_idx_type& err, double& rcond, 5163 octave_idx_type& err, double& rcond,
5164 solve_singularity_handler sing_handler, 5164 solve_singularity_handler sing_handler,
5165 bool calc_cond) const 5165 bool calc_cond) const
5166 { 5166 {
5167 SparseComplexMatrix retval; 5167 SparseComplexMatrix retval;
5168 5168
5169 octave_idx_type nr = rows (); 5169 octave_idx_type nr = rows ();
5170 octave_idx_type nc = cols (); 5170 octave_idx_type nc = cols ();
5180 // Print spparms("spumoni") info if requested 5180 // Print spparms("spumoni") info if requested
5181 volatile int typ = mattype.type (); 5181 volatile int typ = mattype.type ();
5182 mattype.info (); 5182 mattype.info ();
5183 5183
5184 if (typ == MatrixType::Banded_Hermitian) 5184 if (typ == MatrixType::Banded_Hermitian)
5185 { 5185 {
5186 octave_idx_type n_lower = mattype.nlower (); 5186 octave_idx_type n_lower = mattype.nlower ();
5187 octave_idx_type ldm = n_lower + 1; 5187 octave_idx_type ldm = n_lower + 1;
5188 5188
5189 ComplexMatrix m_band (ldm, nc); 5189 ComplexMatrix m_band (ldm, nc);
5190 Complex *tmp_data = m_band.fortran_vec (); 5190 Complex *tmp_data = m_band.fortran_vec ();
5191 5191
5192 if (! mattype.is_dense ()) 5192 if (! mattype.is_dense ())
5193 { 5193 {
5194 octave_idx_type ii = 0; 5194 octave_idx_type ii = 0;
5195 5195
5196 for (octave_idx_type j = 0; j < ldm; j++) 5196 for (octave_idx_type j = 0; j < ldm; j++)
5197 for (octave_idx_type i = 0; i < nc; i++) 5197 for (octave_idx_type i = 0; i < nc; i++)
5198 tmp_data[ii++] = 0.; 5198 tmp_data[ii++] = 0.;
5199 } 5199 }
5200 5200
5201 for (octave_idx_type j = 0; j < nc; j++) 5201 for (octave_idx_type j = 0; j < nc; j++)
5202 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 5202 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
5203 { 5203 {
5204 octave_idx_type ri = ridx (i); 5204 octave_idx_type ri = ridx (i);
5205 if (ri >= j) 5205 if (ri >= j)
5206 m_band(ri - j, j) = data(i); 5206 m_band(ri - j, j) = data(i);
5207 } 5207 }
5208 5208
5209 // Calculate the norm of the matrix, for later use. 5209 // Calculate the norm of the matrix, for later use.
5210 double anorm; 5210 double anorm;
5211 if (calc_cond) 5211 if (calc_cond)
5212 anorm = m_band.abs().sum().row(0).max(); 5212 anorm = m_band.abs().sum().row(0).max();
5213 5213
5214 char job = 'L'; 5214 char job = 'L';
5215 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), 5215 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1),
5216 nr, n_lower, tmp_data, ldm, err 5216 nr, n_lower, tmp_data, ldm, err
5217 F77_CHAR_ARG_LEN (1))); 5217 F77_CHAR_ARG_LEN (1)));
5218 5218
5219 if (err != 0) 5219 if (err != 0)
5220 { 5220 {
5221 // Matrix is not positive definite!! Fall through to 5221 // Matrix is not positive definite!! Fall through to
5222 // unsymmetric banded solver. 5222 // unsymmetric banded solver.
5223 mattype.mark_as_unsymmetric (); 5223 mattype.mark_as_unsymmetric ();
5224 typ = MatrixType::Banded; 5224 typ = MatrixType::Banded;
5225 5225
5226 rcond = 0.0; 5226 rcond = 0.0;
5227 err = 0; 5227 err = 0;
5228 } 5228 }
5229 else 5229 else
5230 { 5230 {
5231 if (calc_cond) 5231 if (calc_cond)
5232 { 5232 {
5233 Array<Complex> z (2 * nr); 5233 Array<Complex> z (2 * nr);
5234 Complex *pz = z.fortran_vec (); 5234 Complex *pz = z.fortran_vec ();
5235 Array<double> iz (nr); 5235 Array<double> iz (nr);
5236 double *piz = iz.fortran_vec (); 5236 double *piz = iz.fortran_vec ();
5237 5237
5238 F77_XFCN (zpbcon, ZPBCON, 5238 F77_XFCN (zpbcon, ZPBCON,
5239 (F77_CONST_CHAR_ARG2 (&job, 1), 5239 (F77_CONST_CHAR_ARG2 (&job, 1),
5240 nr, n_lower, tmp_data, ldm, 5240 nr, n_lower, tmp_data, ldm,
5241 anorm, rcond, pz, piz, err 5241 anorm, rcond, pz, piz, err
5242 F77_CHAR_ARG_LEN (1))); 5242 F77_CHAR_ARG_LEN (1)));
5243 5243
5244 if (err != 0) 5244 if (err != 0)
5245 err = -2; 5245 err = -2;
5246 5246
5247 volatile double rcond_plus_one = rcond + 1.0; 5247 volatile double rcond_plus_one = rcond + 1.0;
5248 5248
5249 if (rcond_plus_one == 1.0 || xisnan (rcond)) 5249 if (rcond_plus_one == 1.0 || xisnan (rcond))
5250 { 5250 {
5251 err = -2; 5251 err = -2;
5252 5252
5253 if (sing_handler) 5253 if (sing_handler)
5254 { 5254 {
5255 sing_handler (rcond); 5255 sing_handler (rcond);
5256 mattype.mark_as_rectangular (); 5256 mattype.mark_as_rectangular ();
5257 } 5257 }
5258 else 5258 else
5259 (*current_liboctave_error_handler) 5259 (*current_liboctave_error_handler)
5260 ("matrix singular to machine precision, rcond = %g", 5260 ("matrix singular to machine precision, rcond = %g",
5261 rcond); 5261 rcond);
5262 } 5262 }
5263 } 5263 }
5264 else 5264 else
5265 rcond = 1.0; 5265 rcond = 1.0;
5266 5266
5267 if (err == 0) 5267 if (err == 0)
5268 { 5268 {
5269 octave_idx_type b_nr = b.rows (); 5269 octave_idx_type b_nr = b.rows ();
5270 octave_idx_type b_nc = b.cols (); 5270 octave_idx_type b_nc = b.cols ();
5271 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); 5271 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
5272 5272
5273 // Take a first guess that the number of non-zero terms 5273 // Take a first guess that the number of non-zero terms
5274 // will be as many as in b 5274 // will be as many as in b
5275 volatile octave_idx_type x_nz = b.nnz (); 5275 volatile octave_idx_type x_nz = b.nnz ();
5276 volatile octave_idx_type ii = 0; 5276 volatile octave_idx_type ii = 0;
5277 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); 5277 retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
5278 5278
5279 retval.xcidx(0) = 0; 5279 retval.xcidx(0) = 0;
5280 for (volatile octave_idx_type j = 0; j < b_nc; j++) 5280 for (volatile octave_idx_type j = 0; j < b_nc; j++)
5281 { 5281 {
5282 5282
5283 for (octave_idx_type i = 0; i < b_nr; i++) 5283 for (octave_idx_type i = 0; i < b_nr; i++)
5284 Bx[i] = b (i,j); 5284 Bx[i] = b (i,j);
5285 5285
5286 F77_XFCN (zpbtrs, ZPBTRS, 5286 F77_XFCN (zpbtrs, ZPBTRS,
5287 (F77_CONST_CHAR_ARG2 (&job, 1), 5287 (F77_CONST_CHAR_ARG2 (&job, 1),
5288 nr, n_lower, 1, tmp_data, 5288 nr, n_lower, 1, tmp_data,
5289 ldm, Bx, b_nr, err 5289 ldm, Bx, b_nr, err
5290 F77_CHAR_ARG_LEN (1))); 5290 F77_CHAR_ARG_LEN (1)));
5291 5291
5292 if (err != 0) 5292 if (err != 0)
5293 { 5293 {
5294 (*current_liboctave_error_handler) 5294 (*current_liboctave_error_handler)
5295 ("SparseMatrix::solve solve failed"); 5295 ("SparseMatrix::solve solve failed");
5296 err = -1; 5296 err = -1;
5297 break; 5297 break;
5298 } 5298 }
5299 5299
5300 // Count non-zeros in work vector and adjust 5300 // Count non-zeros in work vector and adjust
5301 // space in retval if needed 5301 // space in retval if needed
5302 octave_idx_type new_nnz = 0; 5302 octave_idx_type new_nnz = 0;
5303 for (octave_idx_type i = 0; i < nr; i++) 5303 for (octave_idx_type i = 0; i < nr; i++)
5304 if (Bx[i] != 0.) 5304 if (Bx[i] != 0.)
5305 new_nnz++; 5305 new_nnz++;
5306 5306
5307 if (ii + new_nnz > x_nz) 5307 if (ii + new_nnz > x_nz)
5308 { 5308 {
5309 // Resize the sparse matrix 5309 // Resize the sparse matrix
5310 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 5310 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
5311 retval.change_capacity (sz); 5311 retval.change_capacity (sz);
5312 x_nz = sz; 5312 x_nz = sz;
5313 } 5313 }
5314 5314
5315 for (octave_idx_type i = 0; i < nr; i++) 5315 for (octave_idx_type i = 0; i < nr; i++)
5316 if (Bx[i] != 0.) 5316 if (Bx[i] != 0.)
5317 { 5317 {
5318 retval.xridx(ii) = i; 5318 retval.xridx(ii) = i;
5319 retval.xdata(ii++) = Bx[i]; 5319 retval.xdata(ii++) = Bx[i];
5320 } 5320 }
5321 5321
5322 retval.xcidx(j+1) = ii; 5322 retval.xcidx(j+1) = ii;
5323 } 5323 }
5324 5324
5325 retval.maybe_compress (); 5325 retval.maybe_compress ();
5326 } 5326 }
5327 } 5327 }
5328 } 5328 }
5329 5329
5330 if (typ == MatrixType::Banded) 5330 if (typ == MatrixType::Banded)
5331 { 5331 {
5332 // Create the storage for the banded form of the sparse matrix 5332 // Create the storage for the banded form of the sparse matrix
5333 octave_idx_type n_upper = mattype.nupper (); 5333 octave_idx_type n_upper = mattype.nupper ();
5334 octave_idx_type n_lower = mattype.nlower (); 5334 octave_idx_type n_lower = mattype.nlower ();
5335 octave_idx_type ldm = n_upper + 2 * n_lower + 1; 5335 octave_idx_type ldm = n_upper + 2 * n_lower + 1;
5336 5336
5337 ComplexMatrix m_band (ldm, nc); 5337 ComplexMatrix m_band (ldm, nc);
5338 Complex *tmp_data = m_band.fortran_vec (); 5338 Complex *tmp_data = m_band.fortran_vec ();
5339 5339
5340 if (! mattype.is_dense ()) 5340 if (! mattype.is_dense ())
5341 { 5341 {
5342 octave_idx_type ii = 0; 5342 octave_idx_type ii = 0;
5343 5343
5344 for (octave_idx_type j = 0; j < ldm; j++) 5344 for (octave_idx_type j = 0; j < ldm; j++)
5345 for (octave_idx_type i = 0; i < nc; i++) 5345 for (octave_idx_type i = 0; i < nc; i++)
5346 tmp_data[ii++] = 0.; 5346 tmp_data[ii++] = 0.;
5347 } 5347 }
5348 5348
5349 for (octave_idx_type j = 0; j < nc; j++) 5349 for (octave_idx_type j = 0; j < nc; j++)
5350 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 5350 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
5351 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); 5351 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i);
5352 5352
5353 // Calculate the norm of the matrix, for later use. 5353 // Calculate the norm of the matrix, for later use.
5354 double anorm; 5354 double anorm;
5355 if (calc_cond) 5355 if (calc_cond)
5356 { 5356 {
5357 for (octave_idx_type j = 0; j < nr; j++) 5357 for (octave_idx_type j = 0; j < nr; j++)
5358 { 5358 {
5359 double atmp = 0.; 5359 double atmp = 0.;
5360 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) 5360 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++)
5361 atmp += std::abs(data(i)); 5361 atmp += std::abs(data(i));
5362 if (atmp > anorm) 5362 if (atmp > anorm)
5363 anorm = atmp; 5363 anorm = atmp;
5364 } 5364 }
5365 } 5365 }
5366 5366
5367 Array<octave_idx_type> ipvt (nr); 5367 Array<octave_idx_type> ipvt (nr);
5368 octave_idx_type *pipvt = ipvt.fortran_vec (); 5368 octave_idx_type *pipvt = ipvt.fortran_vec ();
5369 5369
5370 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, 5370 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data,
5371 ldm, pipvt, err)); 5371 ldm, pipvt, err));
5372 5372
5373 if (err != 0) 5373 if (err != 0)
5374 { 5374 {
5375 err = -2; 5375 err = -2;
5376 rcond = 0.0; 5376 rcond = 0.0;
5377 5377
5378 if (sing_handler) 5378 if (sing_handler)
5379 { 5379 {
5380 sing_handler (rcond); 5380 sing_handler (rcond);
5381 mattype.mark_as_rectangular (); 5381 mattype.mark_as_rectangular ();
5382 } 5382 }
5383 else 5383 else
5384 (*current_liboctave_error_handler) 5384 (*current_liboctave_error_handler)
5385 ("matrix singular to machine precision"); 5385 ("matrix singular to machine precision");
5386 5386
5387 } 5387 }
5388 else 5388 else
5389 { 5389 {
5390 if (calc_cond) 5390 if (calc_cond)
5391 { 5391 {
5392 char job = '1'; 5392 char job = '1';
5393 Array<Complex> z (2 * nr); 5393 Array<Complex> z (2 * nr);
5394 Complex *pz = z.fortran_vec (); 5394 Complex *pz = z.fortran_vec ();
5395 Array<double> iz (nr); 5395 Array<double> iz (nr);
5396 double *piz = iz.fortran_vec (); 5396 double *piz = iz.fortran_vec ();
5397 5397
5398 F77_XFCN (zgbcon, ZGBCON, 5398 F77_XFCN (zgbcon, ZGBCON,
5399 (F77_CONST_CHAR_ARG2 (&job, 1), 5399 (F77_CONST_CHAR_ARG2 (&job, 1),
5400 nc, n_lower, n_upper, tmp_data, ldm, pipvt, 5400 nc, n_lower, n_upper, tmp_data, ldm, pipvt,
5401 anorm, rcond, pz, piz, err 5401 anorm, rcond, pz, piz, err
5402 F77_CHAR_ARG_LEN (1))); 5402 F77_CHAR_ARG_LEN (1)));
5403 5403
5404 if (err != 0) 5404 if (err != 0)
5405 err = -2; 5405 err = -2;
5406 5406
5407 volatile double rcond_plus_one = rcond + 1.0; 5407 volatile double rcond_plus_one = rcond + 1.0;
5408 5408
5409 if (rcond_plus_one == 1.0 || xisnan (rcond)) 5409 if (rcond_plus_one == 1.0 || xisnan (rcond))
5410 { 5410 {
5411 err = -2; 5411 err = -2;
5412 5412
5413 if (sing_handler) 5413 if (sing_handler)
5414 { 5414 {
5415 sing_handler (rcond); 5415 sing_handler (rcond);
5416 mattype.mark_as_rectangular (); 5416 mattype.mark_as_rectangular ();
5417 } 5417 }
5418 else 5418 else
5419 (*current_liboctave_error_handler) 5419 (*current_liboctave_error_handler)
5420 ("matrix singular to machine precision, rcond = %g", 5420 ("matrix singular to machine precision, rcond = %g",
5421 rcond); 5421 rcond);
5422 } 5422 }
5423 } 5423 }
5424 else 5424 else
5425 rcond = 1.; 5425 rcond = 1.;
5426 5426
5427 if (err == 0) 5427 if (err == 0)
5428 { 5428 {
5429 char job = 'N'; 5429 char job = 'N';
5430 volatile octave_idx_type x_nz = b.nnz (); 5430 volatile octave_idx_type x_nz = b.nnz ();
5431 octave_idx_type b_nc = b.cols (); 5431 octave_idx_type b_nc = b.cols ();
5432 retval = SparseComplexMatrix (nr, b_nc, x_nz); 5432 retval = SparseComplexMatrix (nr, b_nc, x_nz);
5433 retval.xcidx(0) = 0; 5433 retval.xcidx(0) = 0;
5434 volatile octave_idx_type ii = 0; 5434 volatile octave_idx_type ii = 0;
5435 5435
5436 OCTAVE_LOCAL_BUFFER (Complex, Bx, nr); 5436 OCTAVE_LOCAL_BUFFER (Complex, Bx, nr);
5437 5437
5438 for (volatile octave_idx_type j = 0; j < b_nc; j++) 5438 for (volatile octave_idx_type j = 0; j < b_nc; j++)
5439 { 5439 {
5440 for (octave_idx_type i = 0; i < nr; i++) 5440 for (octave_idx_type i = 0; i < nr; i++)
5441 Bx[i] = 0.; 5441 Bx[i] = 0.;
5442 5442
5443 for (octave_idx_type i = b.cidx(j); 5443 for (octave_idx_type i = b.cidx(j);
5444 i < b.cidx(j+1); i++) 5444 i < b.cidx(j+1); i++)
5445 Bx[b.ridx(i)] = b.data(i); 5445 Bx[b.ridx(i)] = b.data(i);
5446 5446
5447 F77_XFCN (zgbtrs, ZGBTRS, 5447 F77_XFCN (zgbtrs, ZGBTRS,
5448 (F77_CONST_CHAR_ARG2 (&job, 1), 5448 (F77_CONST_CHAR_ARG2 (&job, 1),
5449 nr, n_lower, n_upper, 1, tmp_data, 5449 nr, n_lower, n_upper, 1, tmp_data,
5450 ldm, pipvt, Bx, b.rows (), err 5450 ldm, pipvt, Bx, b.rows (), err
5451 F77_CHAR_ARG_LEN (1))); 5451 F77_CHAR_ARG_LEN (1)));
5452 5452
5453 // Count non-zeros in work vector and adjust 5453 // Count non-zeros in work vector and adjust
5454 // space in retval if needed 5454 // space in retval if needed
5455 octave_idx_type new_nnz = 0; 5455 octave_idx_type new_nnz = 0;
5456 for (octave_idx_type i = 0; i < nr; i++) 5456 for (octave_idx_type i = 0; i < nr; i++)
5457 if (Bx[i] != 0.) 5457 if (Bx[i] != 0.)
5458 new_nnz++; 5458 new_nnz++;
5459 5459
5460 if (ii + new_nnz > x_nz) 5460 if (ii + new_nnz > x_nz)
5461 { 5461 {
5462 // Resize the sparse matrix 5462 // Resize the sparse matrix
5463 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; 5463 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz;
5464 retval.change_capacity (sz); 5464 retval.change_capacity (sz);
5465 x_nz = sz; 5465 x_nz = sz;
5466 } 5466 }
5467 5467
5468 for (octave_idx_type i = 0; i < nr; i++) 5468 for (octave_idx_type i = 0; i < nr; i++)
5469 if (Bx[i] != 0.) 5469 if (Bx[i] != 0.)
5470 { 5470 {
5471 retval.xridx(ii) = i; 5471 retval.xridx(ii) = i;
5472 retval.xdata(ii++) = Bx[i]; 5472 retval.xdata(ii++) = Bx[i];
5473 } 5473 }
5474 retval.xcidx(j+1) = ii; 5474 retval.xcidx(j+1) = ii;
5475 } 5475 }
5476 5476
5477 retval.maybe_compress (); 5477 retval.maybe_compress ();
5478 } 5478 }
5479 } 5479 }
5480 } 5480 }
5481 else if (typ != MatrixType::Banded_Hermitian) 5481 else if (typ != MatrixType::Banded_Hermitian)
5482 (*current_liboctave_error_handler) ("incorrect matrix type"); 5482 (*current_liboctave_error_handler) ("incorrect matrix type");
5483 } 5483 }
5484 5484
5485 return retval; 5485 return retval;
5486 } 5486 }
5487 5487
5488 void * 5488 void *
5489 SparseComplexMatrix::factorize (octave_idx_type& err, double &rcond, 5489 SparseComplexMatrix::factorize (octave_idx_type& err, double &rcond,
5490 Matrix &Control, Matrix &Info, 5490 Matrix &Control, Matrix &Info,
5491 solve_singularity_handler sing_handler, 5491 solve_singularity_handler sing_handler,
5492 bool calc_cond) const 5492 bool calc_cond) const
5493 { 5493 {
5494 // The return values 5494 // The return values
5495 void *Numeric = 0; 5495 void *Numeric = 0;
5496 err = 0; 5496 err = 0;
5497 5497
5523 const Complex *Ax = data (); 5523 const Complex *Ax = data ();
5524 octave_idx_type nr = rows (); 5524 octave_idx_type nr = rows ();
5525 octave_idx_type nc = cols (); 5525 octave_idx_type nc = cols ();
5526 5526
5527 UMFPACK_ZNAME (report_matrix) (nr, nc, Ap, Ai, 5527 UMFPACK_ZNAME (report_matrix) (nr, nc, Ap, Ai,
5528 reinterpret_cast<const double *> (Ax), 5528 reinterpret_cast<const double *> (Ax),
5529 0, 1, control); 5529 0, 1, control);
5530 5530
5531 void *Symbolic; 5531 void *Symbolic;
5532 Info = Matrix (1, UMFPACK_INFO); 5532 Info = Matrix (1, UMFPACK_INFO);
5533 double *info = Info.fortran_vec (); 5533 double *info = Info.fortran_vec ();
5534 int status = UMFPACK_ZNAME (qsymbolic) (nr, nc, Ap, Ai, 5534 int status = UMFPACK_ZNAME (qsymbolic) (nr, nc, Ap, Ai,
5535 reinterpret_cast<const double *> (Ax), 5535 reinterpret_cast<const double *> (Ax),
5536 0, 0, &Symbolic, control, info); 5536 0, 0, &Symbolic, control, info);
5537 5537
5538 if (status < 0) 5538 if (status < 0)
5539 { 5539 {
5540 (*current_liboctave_error_handler) 5540 (*current_liboctave_error_handler)
5541 ("SparseComplexMatrix::solve symbolic factorization failed"); 5541 ("SparseComplexMatrix::solve symbolic factorization failed");
5542 err = -1; 5542 err = -1;
5543 5543
5544 UMFPACK_ZNAME (report_status) (control, status); 5544 UMFPACK_ZNAME (report_status) (control, status);
5545 UMFPACK_ZNAME (report_info) (control, info); 5545 UMFPACK_ZNAME (report_info) (control, info);
5546 5546
5549 else 5549 else
5550 { 5550 {
5551 UMFPACK_ZNAME (report_symbolic) (Symbolic, control); 5551 UMFPACK_ZNAME (report_symbolic) (Symbolic, control);
5552 5552
5553 status = UMFPACK_ZNAME (numeric) (Ap, Ai, 5553 status = UMFPACK_ZNAME (numeric) (Ap, Ai,
5554 reinterpret_cast<const double *> (Ax), 0, 5554 reinterpret_cast<const double *> (Ax), 0,
5555 Symbolic, &Numeric, control, info) ; 5555 Symbolic, &Numeric, control, info) ;
5556 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; 5556 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ;
5557 5557
5558 if (calc_cond) 5558 if (calc_cond)
5559 rcond = Info (UMFPACK_RCOND); 5559 rcond = Info (UMFPACK_RCOND);
5560 else 5560 else
5561 rcond = 1.; 5561 rcond = 1.;
5562 volatile double rcond_plus_one = rcond + 1.0; 5562 volatile double rcond_plus_one = rcond + 1.0;
5563 5563
5564 if (status == UMFPACK_WARNING_singular_matrix || 5564 if (status == UMFPACK_WARNING_singular_matrix ||
5565 rcond_plus_one == 1.0 || xisnan (rcond)) 5565 rcond_plus_one == 1.0 || xisnan (rcond))
5566 { 5566 {
5567 UMFPACK_ZNAME (report_numeric) (Numeric, control); 5567 UMFPACK_ZNAME (report_numeric) (Numeric, control);
5568 5568
5569 err = -2; 5569 err = -2;
5570 5570
5571 if (sing_handler) 5571 if (sing_handler)
5572 sing_handler (rcond); 5572 sing_handler (rcond);
5573 else 5573 else
5574 (*current_liboctave_error_handler) 5574 (*current_liboctave_error_handler)
5575 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 5575 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
5576 rcond); 5576 rcond);
5577 5577
5578 } 5578 }
5579 else if (status < 0) 5579 else if (status < 0)
5580 { 5580 {
5581 (*current_liboctave_error_handler) 5581 (*current_liboctave_error_handler)
5582 ("SparseComplexMatrix::solve numeric factorization failed"); 5582 ("SparseComplexMatrix::solve numeric factorization failed");
5583 5583
5584 UMFPACK_ZNAME (report_status) (control, status); 5584 UMFPACK_ZNAME (report_status) (control, status);
5585 UMFPACK_ZNAME (report_info) (control, info); 5585 UMFPACK_ZNAME (report_info) (control, info);
5586 5586
5587 err = -1; 5587 err = -1;
5588 } 5588 }
5589 else 5589 else
5590 { 5590 {
5591 UMFPACK_ZNAME (report_numeric) (Numeric, control); 5591 UMFPACK_ZNAME (report_numeric) (Numeric, control);
5592 } 5592 }
5593 } 5593 }
5594 5594
5595 if (err != 0) 5595 if (err != 0)
5596 UMFPACK_ZNAME (free_numeric) (&Numeric); 5596 UMFPACK_ZNAME (free_numeric) (&Numeric);
5597 #else 5597 #else
5601 return Numeric; 5601 return Numeric;
5602 } 5602 }
5603 5603
5604 ComplexMatrix 5604 ComplexMatrix
5605 SparseComplexMatrix::fsolve (MatrixType &mattype, const Matrix& b, 5605 SparseComplexMatrix::fsolve (MatrixType &mattype, const Matrix& b,
5606 octave_idx_type& err, double& rcond, 5606 octave_idx_type& err, double& rcond,
5607 solve_singularity_handler sing_handler, 5607 solve_singularity_handler sing_handler,
5608 bool calc_cond) const 5608 bool calc_cond) const
5609 { 5609 {
5610 ComplexMatrix retval; 5610 ComplexMatrix retval;
5611 5611
5612 octave_idx_type nr = rows (); 5612 octave_idx_type nr = rows ();
5613 octave_idx_type nc = cols (); 5613 octave_idx_type nc = cols ();
5623 // Print spparms("spumoni") info if requested 5623 // Print spparms("spumoni") info if requested
5624 volatile int typ = mattype.type (); 5624 volatile int typ = mattype.type ();
5625 mattype.info (); 5625 mattype.info ();
5626 5626
5627 if (typ == MatrixType::Hermitian) 5627 if (typ == MatrixType::Hermitian)
5628 { 5628 {
5629 #ifdef HAVE_CHOLMOD 5629 #ifdef HAVE_CHOLMOD
5630 cholmod_common Common; 5630 cholmod_common Common;
5631 cholmod_common *cm = &Common; 5631 cholmod_common *cm = &Common;
5632 5632
5633 // Setup initial parameters 5633 // Setup initial parameters
5634 CHOLMOD_NAME(start) (cm); 5634 CHOLMOD_NAME(start) (cm);
5635 cm->prefer_zomplex = false; 5635 cm->prefer_zomplex = false;
5636 5636
5637 double spu = octave_sparse_params::get_key ("spumoni"); 5637 double spu = octave_sparse_params::get_key ("spumoni");
5638 if (spu == 0.) 5638 if (spu == 0.)
5639 { 5639 {
5640 cm->print = -1; 5640 cm->print = -1;
5641 cm->print_function = 0; 5641 cm->print_function = 0;
5642 } 5642 }
5643 else 5643 else
5644 { 5644 {
5645 cm->print = static_cast<int> (spu) + 2; 5645 cm->print = static_cast<int> (spu) + 2;
5646 cm->print_function =&SparseCholPrint; 5646 cm->print_function =&SparseCholPrint;
5647 } 5647 }
5648 5648
5649 cm->error_handler = &SparseCholError; 5649 cm->error_handler = &SparseCholError;
5650 cm->complex_divide = CHOLMOD_NAME(divcomplex); 5650 cm->complex_divide = CHOLMOD_NAME(divcomplex);
5651 cm->hypotenuse = CHOLMOD_NAME(hypot); 5651 cm->hypotenuse = CHOLMOD_NAME(hypot);
5652 5652
5653 cm->final_ll = true; 5653 cm->final_ll = true;
5654 5654
5655 cholmod_sparse Astore; 5655 cholmod_sparse Astore;
5656 cholmod_sparse *A = &Astore; 5656 cholmod_sparse *A = &Astore;
5657 double dummy; 5657 double dummy;
5658 A->nrow = nr; 5658 A->nrow = nr;
5659 A->ncol = nc; 5659 A->ncol = nc;
5660 5660
5661 A->p = cidx(); 5661 A->p = cidx();
5662 A->i = ridx(); 5662 A->i = ridx();
5663 A->nzmax = nnz(); 5663 A->nzmax = nnz();
5664 A->packed = true; 5664 A->packed = true;
5665 A->sorted = true; 5665 A->sorted = true;
5666 A->nz = 0; 5666 A->nz = 0;
5667 #ifdef IDX_TYPE_LONG 5667 #ifdef IDX_TYPE_LONG
5668 A->itype = CHOLMOD_LONG; 5668 A->itype = CHOLMOD_LONG;
5669 #else 5669 #else
5670 A->itype = CHOLMOD_INT; 5670 A->itype = CHOLMOD_INT;
5671 #endif 5671 #endif
5672 A->dtype = CHOLMOD_DOUBLE; 5672 A->dtype = CHOLMOD_DOUBLE;
5673 A->stype = 1; 5673 A->stype = 1;
5674 A->xtype = CHOLMOD_COMPLEX; 5674 A->xtype = CHOLMOD_COMPLEX;
5675 5675
5676 if (nr < 1) 5676 if (nr < 1)
5677 A->x = &dummy; 5677 A->x = &dummy;
5678 else 5678 else
5679 A->x = data(); 5679 A->x = data();
5680 5680
5681 cholmod_dense Bstore; 5681 cholmod_dense Bstore;
5682 cholmod_dense *B = &Bstore; 5682 cholmod_dense *B = &Bstore;
5683 B->nrow = b.rows(); 5683 B->nrow = b.rows();
5684 B->ncol = b.cols(); 5684 B->ncol = b.cols();
5685 B->d = B->nrow; 5685 B->d = B->nrow;
5686 B->nzmax = B->nrow * B->ncol; 5686 B->nzmax = B->nrow * B->ncol;
5687 B->dtype = CHOLMOD_DOUBLE; 5687 B->dtype = CHOLMOD_DOUBLE;
5688 B->xtype = CHOLMOD_REAL; 5688 B->xtype = CHOLMOD_REAL;
5689 if (nc < 1 || b.cols() < 1) 5689 if (nc < 1 || b.cols() < 1)
5690 B->x = &dummy; 5690 B->x = &dummy;
5691 else 5691 else
5692 // We won't alter it, honest :-) 5692 // We won't alter it, honest :-)
5693 B->x = const_cast<double *>(b.fortran_vec()); 5693 B->x = const_cast<double *>(b.fortran_vec());
5694 5694
5695 cholmod_factor *L; 5695 cholmod_factor *L;
5696 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5696 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5697 L = CHOLMOD_NAME(analyze) (A, cm); 5697 L = CHOLMOD_NAME(analyze) (A, cm);
5698 CHOLMOD_NAME(factorize) (A, L, cm); 5698 CHOLMOD_NAME(factorize) (A, L, cm);
5699 if (calc_cond) 5699 if (calc_cond)
5700 rcond = CHOLMOD_NAME(rcond)(L, cm); 5700 rcond = CHOLMOD_NAME(rcond)(L, cm);
5701 else 5701 else
5702 rcond = 1.; 5702 rcond = 1.;
5703 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5703 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5704 5704
5705 if (rcond == 0.0) 5705 if (rcond == 0.0)
5706 { 5706 {
5707 // Either its indefinite or singular. Try UMFPACK 5707 // Either its indefinite or singular. Try UMFPACK
5708 mattype.mark_as_unsymmetric (); 5708 mattype.mark_as_unsymmetric ();
5709 typ = MatrixType::Full; 5709 typ = MatrixType::Full;
5710 } 5710 }
5711 else 5711 else
5712 { 5712 {
5713 volatile double rcond_plus_one = rcond + 1.0; 5713 volatile double rcond_plus_one = rcond + 1.0;
5714 5714
5715 if (rcond_plus_one == 1.0 || xisnan (rcond)) 5715 if (rcond_plus_one == 1.0 || xisnan (rcond))
5716 { 5716 {
5717 err = -2; 5717 err = -2;
5718 5718
5719 if (sing_handler) 5719 if (sing_handler)
5720 { 5720 {
5721 sing_handler (rcond); 5721 sing_handler (rcond);
5722 mattype.mark_as_rectangular (); 5722 mattype.mark_as_rectangular ();
5723 } 5723 }
5724 else 5724 else
5725 (*current_liboctave_error_handler) 5725 (*current_liboctave_error_handler)
5726 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", 5726 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
5727 rcond); 5727 rcond);
5728 5728
5729 return retval; 5729 return retval;
5730 } 5730 }
5731 5731
5732 cholmod_dense *X; 5732 cholmod_dense *X;
5733 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5733 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5734 X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm); 5734 X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm);
5735 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5735 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5736 5736
5737 retval.resize (b.rows (), b.cols()); 5737 retval.resize (b.rows (), b.cols());
5738 for (octave_idx_type j = 0; j < b.cols(); j++) 5738 for (octave_idx_type j = 0; j < b.cols(); j++)
5739 { 5739 {
5740 octave_idx_type jr = j * b.rows(); 5740 octave_idx_type jr = j * b.rows();
5741 for (octave_idx_type i = 0; i < b.rows(); i++) 5741 for (octave_idx_type i = 0; i < b.rows(); i++)
5742 retval.xelem(i,j) = static_cast<Complex *>(X->x)[jr + i]; 5742 retval.xelem(i,j) = static_cast<Complex *>(X->x)[jr + i];
5743 } 5743 }
5744 5744
5745 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5745 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5746 CHOLMOD_NAME(free_dense) (&X, cm); 5746 CHOLMOD_NAME(free_dense) (&X, cm);
5747 CHOLMOD_NAME(free_factor) (&L, cm); 5747 CHOLMOD_NAME(free_factor) (&L, cm);
5748 CHOLMOD_NAME(finish) (cm); 5748 CHOLMOD_NAME(finish) (cm);
5749 static char tmp[] = " "; 5749 static char tmp[] = " ";
5750 CHOLMOD_NAME(print_common) (tmp, cm); 5750 CHOLMOD_NAME(print_common) (tmp, cm);
5751 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5751 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5752 } 5752 }
5753 #else 5753 #else
5754 (*current_liboctave_warning_handler) 5754 (*current_liboctave_warning_handler)
5755 ("CHOLMOD not installed"); 5755 ("CHOLMOD not installed");
5756 5756
5757 mattype.mark_as_unsymmetric (); 5757 mattype.mark_as_unsymmetric ();
5758 typ = MatrixType::Full; 5758 typ = MatrixType::Full;
5759 #endif 5759 #endif
5760 } 5760 }
5761 5761
5762 if (typ == MatrixType::Full) 5762 if (typ == MatrixType::Full)
5763 { 5763 {
5764 #ifdef HAVE_UMFPACK 5764 #ifdef HAVE_UMFPACK
5765 Matrix Control, Info; 5765 Matrix Control, Info;
5766 void *Numeric = factorize (err, rcond, Control, Info, 5766 void *Numeric = factorize (err, rcond, Control, Info,
5767 sing_handler, calc_cond); 5767 sing_handler, calc_cond);
5768 5768
5769 if (err == 0) 5769 if (err == 0)
5770 { 5770 {
5771 octave_idx_type b_nr = b.rows (); 5771 octave_idx_type b_nr = b.rows ();
5772 octave_idx_type b_nc = b.cols (); 5772 octave_idx_type b_nc = b.cols ();
5773 int status = 0; 5773 int status = 0;
5774 double *control = Control.fortran_vec (); 5774 double *control = Control.fortran_vec ();
5775 double *info = Info.fortran_vec (); 5775 double *info = Info.fortran_vec ();
5776 const octave_idx_type *Ap = cidx (); 5776 const octave_idx_type *Ap = cidx ();
5777 const octave_idx_type *Ai = ridx (); 5777 const octave_idx_type *Ai = ridx ();
5778 const Complex *Ax = data (); 5778 const Complex *Ax = data ();
5779 #ifdef UMFPACK_SEPARATE_SPLIT 5779 #ifdef UMFPACK_SEPARATE_SPLIT
5780 const double *Bx = b.fortran_vec (); 5780 const double *Bx = b.fortran_vec ();
5781 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); 5781 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);
5782 for (octave_idx_type i = 0; i < b_nr; i++) 5782 for (octave_idx_type i = 0; i < b_nr; i++)
5783 Bz[i] = 0.; 5783 Bz[i] = 0.;
5784 #else 5784 #else
5785 OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr); 5785 OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr);
5786 #endif 5786 #endif
5787 retval.resize (b_nr, b_nc); 5787 retval.resize (b_nr, b_nc);
5788 Complex *Xx = retval.fortran_vec (); 5788 Complex *Xx = retval.fortran_vec ();
5789 5789
5790 for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr) 5790 for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr)
5791 { 5791 {
5792 #ifdef UMFPACK_SEPARATE_SPLIT 5792 #ifdef UMFPACK_SEPARATE_SPLIT
5793 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, 5793 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap,
5794 Ai, 5794 Ai,
5795 reinterpret_cast<const double *> (Ax), 5795 reinterpret_cast<const double *> (Ax),
5796 0, 5796 0,
5797 reinterpret_cast<double *> (&Xx[iidx]), 5797 reinterpret_cast<double *> (&Xx[iidx]),
5798 0, 5798 0,
5799 &Bx[iidx], Bz, Numeric, 5799 &Bx[iidx], Bz, Numeric,
5800 control, info); 5800 control, info);
5801 #else 5801 #else
5802 for (octave_idx_type i = 0; i < b_nr; i++) 5802 for (octave_idx_type i = 0; i < b_nr; i++)
5803 Bz[i] = b.elem (i, j); 5803 Bz[i] = b.elem (i, j);
5804 5804
5805 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, 5805 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap,
5806 Ai, 5806 Ai,
5807 reinterpret_cast<const double *> (Ax), 5807 reinterpret_cast<const double *> (Ax),
5808 0, 5808 0,
5809 reinterpret_cast<double *> (&Xx[iidx]), 5809 reinterpret_cast<double *> (&Xx[iidx]),
5810 0, 5810 0,
5811 reinterpret_cast<const double *> (Bz), 5811 reinterpret_cast<const double *> (Bz),
5812 0, Numeric, 5812 0, Numeric,
5813 control, info); 5813 control, info);
5814 #endif 5814 #endif
5815 5815
5816 if (status < 0) 5816 if (status < 0)
5817 { 5817 {
5818 (*current_liboctave_error_handler) 5818 (*current_liboctave_error_handler)
5819 ("SparseComplexMatrix::solve solve failed"); 5819 ("SparseComplexMatrix::solve solve failed");
5820 5820
5821 UMFPACK_ZNAME (report_status) (control, status); 5821 UMFPACK_ZNAME (report_status) (control, status);
5822 5822
5823 err = -1; 5823 err = -1;
5824 5824
5825 break; 5825 break;
5826 } 5826 }
5827 } 5827 }
5828 5828
5829 UMFPACK_ZNAME (report_info) (control, info); 5829 UMFPACK_ZNAME (report_info) (control, info);
5830 5830
5831 UMFPACK_ZNAME (free_numeric) (&Numeric); 5831 UMFPACK_ZNAME (free_numeric) (&Numeric);
5832 } 5832 }
5833 else 5833 else
5834 mattype.mark_as_rectangular (); 5834 mattype.mark_as_rectangular ();
5835 5835
5836 #else 5836 #else
5837 (*current_liboctave_error_handler) ("UMFPACK not installed"); 5837 (*current_liboctave_error_handler) ("UMFPACK not installed");
5838 #endif 5838 #endif
5839 } 5839 }
5840 else if (typ != MatrixType::Hermitian) 5840 else if (typ != MatrixType::Hermitian)
5841 (*current_liboctave_error_handler) ("incorrect matrix type"); 5841 (*current_liboctave_error_handler) ("incorrect matrix type");
5842 } 5842 }
5843 5843
5844 return retval; 5844 return retval;
5845 } 5845 }
5846 5846
5847 SparseComplexMatrix 5847 SparseComplexMatrix
5848 SparseComplexMatrix::fsolve (MatrixType &mattype, const SparseMatrix& b, 5848 SparseComplexMatrix::fsolve (MatrixType &mattype, const SparseMatrix& b,
5849 octave_idx_type& err, double& rcond, 5849 octave_idx_type& err, double& rcond,
5850 solve_singularity_handler sing_handler, 5850 solve_singularity_handler sing_handler,
5851 bool calc_cond) const 5851 bool calc_cond) const
5852 { 5852 {
5853 SparseComplexMatrix retval; 5853 SparseComplexMatrix retval;
5854 5854
5855 octave_idx_type nr = rows (); 5855 octave_idx_type nr = rows ();
5856 octave_idx_type nc = cols (); 5856 octave_idx_type nc = cols ();
5866 // Print spparms("spumoni") info if requested 5866 // Print spparms("spumoni") info if requested
5867 volatile int typ = mattype.type (); 5867 volatile int typ = mattype.type ();
5868 mattype.info (); 5868 mattype.info ();
5869 5869
5870 if (typ == MatrixType::Hermitian) 5870 if (typ == MatrixType::Hermitian)
5871 { 5871 {
5872 #ifdef HAVE_CHOLMOD 5872 #ifdef HAVE_CHOLMOD
5873 cholmod_common Common; 5873 cholmod_common Common;
5874 cholmod_common *cm = &Common; 5874 cholmod_common *cm = &Common;
5875 5875
5876 // Setup initial parameters 5876 // Setup initial parameters
5877 CHOLMOD_NAME(start) (cm); 5877 CHOLMOD_NAME(start) (cm);
5878 cm->prefer_zomplex = false; 5878 cm->prefer_zomplex = false;
5879 5879
5880 double spu = octave_sparse_params::get_key ("spumoni"); 5880 double spu = octave_sparse_params::get_key ("spumoni");
5881 if (spu == 0.) 5881 if (spu == 0.)
5882 { 5882 {
5883 cm->print = -1; 5883 cm->print = -1;
5884 cm->print_function = 0; 5884 cm->print_function = 0;
5885 } 5885 }
5886 else 5886 else
5887 { 5887 {
5888 cm->print = static_cast<int> (spu) + 2; 5888 cm->print = static_cast<int> (spu) + 2;
5889 cm->print_function =&SparseCholPrint; 5889 cm->print_function =&SparseCholPrint;
5890 } 5890 }
5891 5891
5892 cm->error_handler = &SparseCholError; 5892 cm->error_handler = &SparseCholError;
5893 cm->complex_divide = CHOLMOD_NAME(divcomplex); 5893 cm->complex_divide = CHOLMOD_NAME(divcomplex);
5894 cm->hypotenuse = CHOLMOD_NAME(hypot); 5894 cm->hypotenuse = CHOLMOD_NAME(hypot);
5895 5895
5896 cm->final_ll = true; 5896 cm->final_ll = true;
5897 5897
5898 cholmod_sparse Astore; 5898 cholmod_sparse Astore;
5899 cholmod_sparse *A = &Astore; 5899 cholmod_sparse *A = &Astore;
5900 double dummy; 5900 double dummy;
5901 A->nrow = nr; 5901 A->nrow = nr;
5902 A->ncol = nc; 5902 A->ncol = nc;
5903 5903
5904 A->p = cidx(); 5904 A->p = cidx();
5905 A->i = ridx(); 5905 A->i = ridx();
5906 A->nzmax = nnz(); 5906 A->nzmax = nnz();
5907 A->packed = true; 5907 A->packed = true;
5908 A->sorted = true; 5908 A->sorted = true;
5909 A->nz = 0; 5909 A->nz = 0;
5910 #ifdef IDX_TYPE_LONG 5910 #ifdef IDX_TYPE_LONG
5911 A->itype = CHOLMOD_LONG; 5911 A->itype = CHOLMOD_LONG;
5912 #else 5912 #else
5913 A->itype = CHOLMOD_INT; 5913 A->itype = CHOLMOD_INT;
5914 #endif 5914 #endif
5915 A->dtype = CHOLMOD_DOUBLE; 5915 A->dtype = CHOLMOD_DOUBLE;
5916 A->stype = 1; 5916 A->stype = 1;
5917 A->xtype = CHOLMOD_COMPLEX; 5917 A->xtype = CHOLMOD_COMPLEX;
5918 5918
5919 if (nr < 1) 5919 if (nr < 1)
5920 A->x = &dummy; 5920 A->x = &dummy;
5921 else 5921 else
5922 A->x = data(); 5922 A->x = data();
5923 5923
5924 cholmod_sparse Bstore; 5924 cholmod_sparse Bstore;
5925 cholmod_sparse *B = &Bstore; 5925 cholmod_sparse *B = &Bstore;
5926 B->nrow = b.rows(); 5926 B->nrow = b.rows();
5927 B->ncol = b.cols(); 5927 B->ncol = b.cols();
5928 B->p = b.cidx(); 5928 B->p = b.cidx();
5929 B->i = b.ridx(); 5929 B->i = b.ridx();
5930 B->nzmax = b.nnz(); 5930 B->nzmax = b.nnz();
5931 B->packed = true; 5931 B->packed = true;
5932 B->sorted = true; 5932 B->sorted = true;
5933 B->nz = 0; 5933 B->nz = 0;
5934 #ifdef IDX_TYPE_LONG 5934 #ifdef IDX_TYPE_LONG
5935 B->itype = CHOLMOD_LONG; 5935 B->itype = CHOLMOD_LONG;
5936 #else 5936 #else
5937 B->itype = CHOLMOD_INT; 5937 B->itype = CHOLMOD_INT;
5938 #endif 5938 #endif
5939 B->dtype = CHOLMOD_DOUBLE; 5939 B->dtype = CHOLMOD_DOUBLE;
5940 B->stype = 0; 5940 B->stype = 0;
5941 B->xtype = CHOLMOD_REAL; 5941 B->xtype = CHOLMOD_REAL;
5942 5942
5943 if (b.rows() < 1 || b.cols() < 1) 5943 if (b.rows() < 1 || b.cols() < 1)
5944 B->x = &dummy; 5944 B->x = &dummy;
5945 else 5945 else
5946 B->x = b.data(); 5946 B->x = b.data();
5947 5947
5948 cholmod_factor *L; 5948 cholmod_factor *L;
5949 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5949 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5950 L = CHOLMOD_NAME(analyze) (A, cm); 5950 L = CHOLMOD_NAME(analyze) (A, cm);
5951 CHOLMOD_NAME(factorize) (A, L, cm); 5951 CHOLMOD_NAME(factorize) (A, L, cm);
5952 if (calc_cond) 5952 if (calc_cond)
5953 rcond = CHOLMOD_NAME(rcond)(L, cm); 5953 rcond = CHOLMOD_NAME(rcond)(L, cm);
5954 else 5954 else
5955 rcond = 1.; 5955 rcond = 1.;
5956 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5956 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5957 5957
5958 if (rcond == 0.0) 5958 if (rcond == 0.0)
5959 { 5959 {
5960 // Either its indefinite or singular. Try UMFPACK 5960 // Either its indefinite or singular. Try UMFPACK
5961 mattype.mark_as_unsymmetric (); 5961 mattype.mark_as_unsymmetric ();
5962 typ = MatrixType::Full; 5962 typ = MatrixType::Full;
5963 } 5963 }
5964 else 5964 else
5965 { 5965 {
5966 volatile double rcond_plus_one = rcond + 1.0; 5966 volatile double rcond_plus_one = rcond + 1.0;
5967 5967
5968 if (rcond_plus_one == 1.0 || xisnan (rcond)) 5968 if (rcond_plus_one == 1.0 || xisnan (rcond))
5969 { 5969 {
5970 err = -2; 5970 err = -2;
5971 5971
5972 if (sing_handler) 5972 if (sing_handler)
5973 { 5973 {
5974 sing_handler (rcond); 5974 sing_handler (rcond);
5975 mattype.mark_as_rectangular (); 5975 mattype.mark_as_rectangular ();
5976 } 5976 }
5977 else 5977 else
5978 (*current_liboctave_error_handler) 5978 (*current_liboctave_error_handler)
5979 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", 5979 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
5980 rcond); 5980 rcond);
5981 5981
5982 return retval; 5982 return retval;
5983 } 5983 }
5984 5984
5985 cholmod_sparse *X; 5985 cholmod_sparse *X;
5986 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5986 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5987 X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm); 5987 X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm);
5988 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 5988 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
5989 5989
5990 retval = SparseComplexMatrix 5990 retval = SparseComplexMatrix
5991 (static_cast<octave_idx_type>(X->nrow), 5991 (static_cast<octave_idx_type>(X->nrow),
5992 static_cast<octave_idx_type>(X->ncol), 5992 static_cast<octave_idx_type>(X->ncol),
5993 static_cast<octave_idx_type>(X->nzmax)); 5993 static_cast<octave_idx_type>(X->nzmax));
5994 for (octave_idx_type j = 0; 5994 for (octave_idx_type j = 0;
5995 j <= static_cast<octave_idx_type>(X->ncol); j++) 5995 j <= static_cast<octave_idx_type>(X->ncol); j++)
5996 retval.xcidx(j) = static_cast<octave_idx_type *>(X->p)[j]; 5996 retval.xcidx(j) = static_cast<octave_idx_type *>(X->p)[j];
5997 for (octave_idx_type j = 0; 5997 for (octave_idx_type j = 0;
5998 j < static_cast<octave_idx_type>(X->nzmax); j++) 5998 j < static_cast<octave_idx_type>(X->nzmax); j++)
5999 { 5999 {
6000 retval.xridx(j) = static_cast<octave_idx_type *>(X->i)[j]; 6000 retval.xridx(j) = static_cast<octave_idx_type *>(X->i)[j];
6001 retval.xdata(j) = static_cast<Complex *>(X->x)[j]; 6001 retval.xdata(j) = static_cast<Complex *>(X->x)[j];
6002 } 6002 }
6003 6003
6004 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6004 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6005 CHOLMOD_NAME(free_sparse) (&X, cm); 6005 CHOLMOD_NAME(free_sparse) (&X, cm);
6006 CHOLMOD_NAME(free_factor) (&L, cm); 6006 CHOLMOD_NAME(free_factor) (&L, cm);
6007 CHOLMOD_NAME(finish) (cm); 6007 CHOLMOD_NAME(finish) (cm);
6008 static char tmp[] = " "; 6008 static char tmp[] = " ";
6009 CHOLMOD_NAME(print_common) (tmp, cm); 6009 CHOLMOD_NAME(print_common) (tmp, cm);
6010 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6010 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6011 } 6011 }
6012 #else 6012 #else
6013 (*current_liboctave_warning_handler) 6013 (*current_liboctave_warning_handler)
6014 ("CHOLMOD not installed"); 6014 ("CHOLMOD not installed");
6015 6015
6016 mattype.mark_as_unsymmetric (); 6016 mattype.mark_as_unsymmetric ();
6017 typ = MatrixType::Full; 6017 typ = MatrixType::Full;
6018 #endif 6018 #endif
6019 } 6019 }
6020 6020
6021 if (typ == MatrixType::Full) 6021 if (typ == MatrixType::Full)
6022 { 6022 {
6023 #ifdef HAVE_UMFPACK 6023 #ifdef HAVE_UMFPACK
6024 Matrix Control, Info; 6024 Matrix Control, Info;
6025 void *Numeric = factorize (err, rcond, Control, Info, 6025 void *Numeric = factorize (err, rcond, Control, Info,
6026 sing_handler, calc_cond); 6026 sing_handler, calc_cond);
6027 6027
6028 if (err == 0) 6028 if (err == 0)
6029 { 6029 {
6030 octave_idx_type b_nr = b.rows (); 6030 octave_idx_type b_nr = b.rows ();
6031 octave_idx_type b_nc = b.cols (); 6031 octave_idx_type b_nc = b.cols ();
6032 int status = 0; 6032 int status = 0;
6033 double *control = Control.fortran_vec (); 6033 double *control = Control.fortran_vec ();
6034 double *info = Info.fortran_vec (); 6034 double *info = Info.fortran_vec ();
6035 const octave_idx_type *Ap = cidx (); 6035 const octave_idx_type *Ap = cidx ();
6036 const octave_idx_type *Ai = ridx (); 6036 const octave_idx_type *Ai = ridx ();
6037 const Complex *Ax = data (); 6037 const Complex *Ax = data ();
6038 6038
6039 #ifdef UMFPACK_SEPARATE_SPLIT 6039 #ifdef UMFPACK_SEPARATE_SPLIT
6040 OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); 6040 OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);
6041 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); 6041 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);
6042 for (octave_idx_type i = 0; i < b_nr; i++) 6042 for (octave_idx_type i = 0; i < b_nr; i++)
6043 Bz[i] = 0.; 6043 Bz[i] = 0.;
6044 #else 6044 #else
6045 OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr); 6045 OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr);
6046 #endif 6046 #endif
6047 6047
6048 // Take a first guess that the number of non-zero terms 6048 // Take a first guess that the number of non-zero terms
6049 // will be as many as in b 6049 // will be as many as in b
6050 octave_idx_type x_nz = b.nnz (); 6050 octave_idx_type x_nz = b.nnz ();
6051 octave_idx_type ii = 0; 6051 octave_idx_type ii = 0;
6052 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); 6052 retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
6053 6053
6054 OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); 6054 OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr);
6055 6055
6056 retval.xcidx(0) = 0; 6056 retval.xcidx(0) = 0;
6057 for (octave_idx_type j = 0; j < b_nc; j++) 6057 for (octave_idx_type j = 0; j < b_nc; j++)
6058 { 6058 {
6059 6059
6060 #ifdef UMFPACK_SEPARATE_SPLIT 6060 #ifdef UMFPACK_SEPARATE_SPLIT
6061 for (octave_idx_type i = 0; i < b_nr; i++) 6061 for (octave_idx_type i = 0; i < b_nr; i++)
6062 Bx[i] = b.elem (i, j); 6062 Bx[i] = b.elem (i, j);
6063 6063
6064 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, 6064 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap,
6065 Ai, 6065 Ai,
6066 reinterpret_cast<const double *> (Ax), 6066 reinterpret_cast<const double *> (Ax),
6067 0, 6067 0,
6068 reinterpret_cast<double *> (Xx), 6068 reinterpret_cast<double *> (Xx),
6069 0, 6069 0,
6070 Bx, Bz, Numeric, control, 6070 Bx, Bz, Numeric, control,
6071 info); 6071 info);
6072 #else 6072 #else
6073 for (octave_idx_type i = 0; i < b_nr; i++) 6073 for (octave_idx_type i = 0; i < b_nr; i++)
6074 Bz[i] = b.elem (i, j); 6074 Bz[i] = b.elem (i, j);
6075 6075
6076 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, Ai, 6076 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, Ai,
6077 reinterpret_cast<const double *> (Ax), 6077 reinterpret_cast<const double *> (Ax),
6078 0, 6078 0,
6079 reinterpret_cast<double *> (Xx), 6079 reinterpret_cast<double *> (Xx),
6080 0, 6080 0,
6081 reinterpret_cast<double *> (Bz), 6081 reinterpret_cast<double *> (Bz),
6082 0, 6082 0,
6083 Numeric, control, 6083 Numeric, control,
6084 info); 6084 info);
6085 #endif 6085 #endif
6086 if (status < 0) 6086 if (status < 0)
6087 { 6087 {
6088 (*current_liboctave_error_handler) 6088 (*current_liboctave_error_handler)
6089 ("SparseComplexMatrix::solve solve failed"); 6089 ("SparseComplexMatrix::solve solve failed");
6090 6090
6091 UMFPACK_ZNAME (report_status) (control, status); 6091 UMFPACK_ZNAME (report_status) (control, status);
6092 6092
6093 err = -1; 6093 err = -1;
6094 6094
6095 break; 6095 break;
6096 } 6096 }
6097 6097
6098 for (octave_idx_type i = 0; i < b_nr; i++) 6098 for (octave_idx_type i = 0; i < b_nr; i++)
6099 { 6099 {
6100 Complex tmp = Xx[i]; 6100 Complex tmp = Xx[i];
6101 if (tmp != 0.0) 6101 if (tmp != 0.0)
6102 { 6102 {
6103 if (ii == x_nz) 6103 if (ii == x_nz)
6104 { 6104 {
6105 // Resize the sparse matrix 6105 // Resize the sparse matrix
6106 octave_idx_type sz = x_nz * (b_nc - j) / b_nc; 6106 octave_idx_type sz = x_nz * (b_nc - j) / b_nc;
6107 sz = (sz > 10 ? sz : 10) + x_nz; 6107 sz = (sz > 10 ? sz : 10) + x_nz;
6108 retval.change_capacity (sz); 6108 retval.change_capacity (sz);
6109 x_nz = sz; 6109 x_nz = sz;
6110 } 6110 }
6111 retval.xdata(ii) = tmp; 6111 retval.xdata(ii) = tmp;
6112 retval.xridx(ii++) = i; 6112 retval.xridx(ii++) = i;
6113 } 6113 }
6114 } 6114 }
6115 retval.xcidx(j+1) = ii; 6115 retval.xcidx(j+1) = ii;
6116 } 6116 }
6117 6117
6118 retval.maybe_compress (); 6118 retval.maybe_compress ();
6119 6119
6120 UMFPACK_ZNAME (report_info) (control, info); 6120 UMFPACK_ZNAME (report_info) (control, info);
6121 6121
6122 UMFPACK_ZNAME (free_numeric) (&Numeric); 6122 UMFPACK_ZNAME (free_numeric) (&Numeric);
6123 } 6123 }
6124 else 6124 else
6125 mattype.mark_as_rectangular (); 6125 mattype.mark_as_rectangular ();
6126 6126
6127 #else 6127 #else
6128 (*current_liboctave_error_handler) ("UMFPACK not installed"); 6128 (*current_liboctave_error_handler) ("UMFPACK not installed");
6129 #endif 6129 #endif
6130 } 6130 }
6131 else if (typ != MatrixType::Hermitian) 6131 else if (typ != MatrixType::Hermitian)
6132 (*current_liboctave_error_handler) ("incorrect matrix type"); 6132 (*current_liboctave_error_handler) ("incorrect matrix type");
6133 } 6133 }
6134 6134
6135 return retval; 6135 return retval;
6136 } 6136 }
6137 6137
6138 ComplexMatrix 6138 ComplexMatrix
6139 SparseComplexMatrix::fsolve (MatrixType &mattype, const ComplexMatrix& b, 6139 SparseComplexMatrix::fsolve (MatrixType &mattype, const ComplexMatrix& b,
6140 octave_idx_type& err, double& rcond, 6140 octave_idx_type& err, double& rcond,
6141 solve_singularity_handler sing_handler, 6141 solve_singularity_handler sing_handler,
6142 bool calc_cond) const 6142 bool calc_cond) const
6143 { 6143 {
6144 ComplexMatrix retval; 6144 ComplexMatrix retval;
6145 6145
6146 octave_idx_type nr = rows (); 6146 octave_idx_type nr = rows ();
6147 octave_idx_type nc = cols (); 6147 octave_idx_type nc = cols ();
6157 // Print spparms("spumoni") info if requested 6157 // Print spparms("spumoni") info if requested
6158 volatile int typ = mattype.type (); 6158 volatile int typ = mattype.type ();
6159 mattype.info (); 6159 mattype.info ();
6160 6160
6161 if (typ == MatrixType::Hermitian) 6161 if (typ == MatrixType::Hermitian)
6162 { 6162 {
6163 #ifdef HAVE_CHOLMOD 6163 #ifdef HAVE_CHOLMOD
6164 cholmod_common Common; 6164 cholmod_common Common;
6165 cholmod_common *cm = &Common; 6165 cholmod_common *cm = &Common;
6166 6166
6167 // Setup initial parameters 6167 // Setup initial parameters
6168 CHOLMOD_NAME(start) (cm); 6168 CHOLMOD_NAME(start) (cm);
6169 cm->prefer_zomplex = false; 6169 cm->prefer_zomplex = false;
6170 6170
6171 double spu = octave_sparse_params::get_key ("spumoni"); 6171 double spu = octave_sparse_params::get_key ("spumoni");
6172 if (spu == 0.) 6172 if (spu == 0.)
6173 { 6173 {
6174 cm->print = -1; 6174 cm->print = -1;
6175 cm->print_function = 0; 6175 cm->print_function = 0;
6176 } 6176 }
6177 else 6177 else
6178 { 6178 {
6179 cm->print = static_cast<int> (spu) + 2; 6179 cm->print = static_cast<int> (spu) + 2;
6180 cm->print_function =&SparseCholPrint; 6180 cm->print_function =&SparseCholPrint;
6181 } 6181 }
6182 6182
6183 cm->error_handler = &SparseCholError; 6183 cm->error_handler = &SparseCholError;
6184 cm->complex_divide = CHOLMOD_NAME(divcomplex); 6184 cm->complex_divide = CHOLMOD_NAME(divcomplex);
6185 cm->hypotenuse = CHOLMOD_NAME(hypot); 6185 cm->hypotenuse = CHOLMOD_NAME(hypot);
6186 6186
6187 cm->final_ll = true; 6187 cm->final_ll = true;
6188 6188
6189 cholmod_sparse Astore; 6189 cholmod_sparse Astore;
6190 cholmod_sparse *A = &Astore; 6190 cholmod_sparse *A = &Astore;
6191 double dummy; 6191 double dummy;
6192 A->nrow = nr; 6192 A->nrow = nr;
6193 A->ncol = nc; 6193 A->ncol = nc;
6194 6194
6195 A->p = cidx(); 6195 A->p = cidx();
6196 A->i = ridx(); 6196 A->i = ridx();
6197 A->nzmax = nnz(); 6197 A->nzmax = nnz();
6198 A->packed = true; 6198 A->packed = true;
6199 A->sorted = true; 6199 A->sorted = true;
6200 A->nz = 0; 6200 A->nz = 0;
6201 #ifdef IDX_TYPE_LONG 6201 #ifdef IDX_TYPE_LONG
6202 A->itype = CHOLMOD_LONG; 6202 A->itype = CHOLMOD_LONG;
6203 #else 6203 #else
6204 A->itype = CHOLMOD_INT; 6204 A->itype = CHOLMOD_INT;
6205 #endif 6205 #endif
6206 A->dtype = CHOLMOD_DOUBLE; 6206 A->dtype = CHOLMOD_DOUBLE;
6207 A->stype = 1; 6207 A->stype = 1;
6208 A->xtype = CHOLMOD_COMPLEX; 6208 A->xtype = CHOLMOD_COMPLEX;
6209 6209
6210 if (nr < 1) 6210 if (nr < 1)
6211 A->x = &dummy; 6211 A->x = &dummy;
6212 else 6212 else
6213 A->x = data(); 6213 A->x = data();
6214 6214
6215 cholmod_dense Bstore; 6215 cholmod_dense Bstore;
6216 cholmod_dense *B = &Bstore; 6216 cholmod_dense *B = &Bstore;
6217 B->nrow = b.rows(); 6217 B->nrow = b.rows();
6218 B->ncol = b.cols(); 6218 B->ncol = b.cols();
6219 B->d = B->nrow; 6219 B->d = B->nrow;
6220 B->nzmax = B->nrow * B->ncol; 6220 B->nzmax = B->nrow * B->ncol;
6221 B->dtype = CHOLMOD_DOUBLE; 6221 B->dtype = CHOLMOD_DOUBLE;
6222 B->xtype = CHOLMOD_COMPLEX; 6222 B->xtype = CHOLMOD_COMPLEX;
6223 if (nc < 1 || b.cols() < 1) 6223 if (nc < 1 || b.cols() < 1)
6224 B->x = &dummy; 6224 B->x = &dummy;
6225 else 6225 else
6226 // We won't alter it, honest :-) 6226 // We won't alter it, honest :-)
6227 B->x = const_cast<Complex *>(b.fortran_vec()); 6227 B->x = const_cast<Complex *>(b.fortran_vec());
6228 6228
6229 cholmod_factor *L; 6229 cholmod_factor *L;
6230 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6230 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6231 L = CHOLMOD_NAME(analyze) (A, cm); 6231 L = CHOLMOD_NAME(analyze) (A, cm);
6232 CHOLMOD_NAME(factorize) (A, L, cm); 6232 CHOLMOD_NAME(factorize) (A, L, cm);
6233 if (calc_cond) 6233 if (calc_cond)
6234 rcond = CHOLMOD_NAME(rcond)(L, cm); 6234 rcond = CHOLMOD_NAME(rcond)(L, cm);
6235 else 6235 else
6236 rcond = 1.; 6236 rcond = 1.;
6237 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6237 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6238 6238
6239 if (rcond == 0.0) 6239 if (rcond == 0.0)
6240 { 6240 {
6241 // Either its indefinite or singular. Try UMFPACK 6241 // Either its indefinite or singular. Try UMFPACK
6242 mattype.mark_as_unsymmetric (); 6242 mattype.mark_as_unsymmetric ();
6243 typ = MatrixType::Full; 6243 typ = MatrixType::Full;
6244 } 6244 }
6245 else 6245 else
6246 { 6246 {
6247 volatile double rcond_plus_one = rcond + 1.0; 6247 volatile double rcond_plus_one = rcond + 1.0;
6248 6248
6249 if (rcond_plus_one == 1.0 || xisnan (rcond)) 6249 if (rcond_plus_one == 1.0 || xisnan (rcond))
6250 { 6250 {
6251 err = -2; 6251 err = -2;
6252 6252
6253 if (sing_handler) 6253 if (sing_handler)
6254 { 6254 {
6255 sing_handler (rcond); 6255 sing_handler (rcond);
6256 mattype.mark_as_rectangular (); 6256 mattype.mark_as_rectangular ();
6257 } 6257 }
6258 else 6258 else
6259 (*current_liboctave_error_handler) 6259 (*current_liboctave_error_handler)
6260 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", 6260 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
6261 rcond); 6261 rcond);
6262 6262
6263 return retval; 6263 return retval;
6264 } 6264 }
6265 6265
6266 cholmod_dense *X; 6266 cholmod_dense *X;
6267 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6267 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6268 X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm); 6268 X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm);
6269 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6269 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6270 6270
6271 retval.resize (b.rows (), b.cols()); 6271 retval.resize (b.rows (), b.cols());
6272 for (octave_idx_type j = 0; j < b.cols(); j++) 6272 for (octave_idx_type j = 0; j < b.cols(); j++)
6273 { 6273 {
6274 octave_idx_type jr = j * b.rows(); 6274 octave_idx_type jr = j * b.rows();
6275 for (octave_idx_type i = 0; i < b.rows(); i++) 6275 for (octave_idx_type i = 0; i < b.rows(); i++)
6276 retval.xelem(i,j) = static_cast<Complex *>(X->x)[jr + i]; 6276 retval.xelem(i,j) = static_cast<Complex *>(X->x)[jr + i];
6277 } 6277 }
6278 6278
6279 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6279 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6280 CHOLMOD_NAME(free_dense) (&X, cm); 6280 CHOLMOD_NAME(free_dense) (&X, cm);
6281 CHOLMOD_NAME(free_factor) (&L, cm); 6281 CHOLMOD_NAME(free_factor) (&L, cm);
6282 CHOLMOD_NAME(finish) (cm); 6282 CHOLMOD_NAME(finish) (cm);
6283 static char tmp[] = " "; 6283 static char tmp[] = " ";
6284 CHOLMOD_NAME(print_common) (tmp, cm); 6284 CHOLMOD_NAME(print_common) (tmp, cm);
6285 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6285 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6286 } 6286 }
6287 #else 6287 #else
6288 (*current_liboctave_warning_handler) 6288 (*current_liboctave_warning_handler)
6289 ("CHOLMOD not installed"); 6289 ("CHOLMOD not installed");
6290 6290
6291 mattype.mark_as_unsymmetric (); 6291 mattype.mark_as_unsymmetric ();
6292 typ = MatrixType::Full; 6292 typ = MatrixType::Full;
6293 #endif 6293 #endif
6294 } 6294 }
6295 6295
6296 if (typ == MatrixType::Full) 6296 if (typ == MatrixType::Full)
6297 { 6297 {
6298 #ifdef HAVE_UMFPACK 6298 #ifdef HAVE_UMFPACK
6299 Matrix Control, Info; 6299 Matrix Control, Info;
6300 void *Numeric = factorize (err, rcond, Control, Info, 6300 void *Numeric = factorize (err, rcond, Control, Info,
6301 sing_handler, calc_cond); 6301 sing_handler, calc_cond);
6302 6302
6303 if (err == 0) 6303 if (err == 0)
6304 { 6304 {
6305 octave_idx_type b_nr = b.rows (); 6305 octave_idx_type b_nr = b.rows ();
6306 octave_idx_type b_nc = b.cols (); 6306 octave_idx_type b_nc = b.cols ();
6307 int status = 0; 6307 int status = 0;
6308 double *control = Control.fortran_vec (); 6308 double *control = Control.fortran_vec ();
6309 double *info = Info.fortran_vec (); 6309 double *info = Info.fortran_vec ();
6310 const octave_idx_type *Ap = cidx (); 6310 const octave_idx_type *Ap = cidx ();
6311 const octave_idx_type *Ai = ridx (); 6311 const octave_idx_type *Ai = ridx ();
6312 const Complex *Ax = data (); 6312 const Complex *Ax = data ();
6313 const Complex *Bx = b.fortran_vec (); 6313 const Complex *Bx = b.fortran_vec ();
6314 6314
6315 retval.resize (b_nr, b_nc); 6315 retval.resize (b_nr, b_nc);
6316 Complex *Xx = retval.fortran_vec (); 6316 Complex *Xx = retval.fortran_vec ();
6317 6317
6318 for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr) 6318 for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr)
6319 { 6319 {
6320 status = 6320 status =
6321 UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, Ai, 6321 UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, Ai,
6322 reinterpret_cast<const double *> (Ax), 6322 reinterpret_cast<const double *> (Ax),
6323 0, 6323 0,
6324 reinterpret_cast<double *> (&Xx[iidx]), 6324 reinterpret_cast<double *> (&Xx[iidx]),
6325 0, 6325 0,
6326 reinterpret_cast<const double *> (&Bx[iidx]), 6326 reinterpret_cast<const double *> (&Bx[iidx]),
6327 0, Numeric, control, info); 6327 0, Numeric, control, info);
6328 6328
6329 if (status < 0) 6329 if (status < 0)
6330 { 6330 {
6331 (*current_liboctave_error_handler) 6331 (*current_liboctave_error_handler)
6332 ("SparseComplexMatrix::solve solve failed"); 6332 ("SparseComplexMatrix::solve solve failed");
6333 6333
6334 UMFPACK_ZNAME (report_status) (control, status); 6334 UMFPACK_ZNAME (report_status) (control, status);
6335 6335
6336 err = -1; 6336 err = -1;
6337 6337
6338 break; 6338 break;
6339 } 6339 }
6340 } 6340 }
6341 6341
6342 UMFPACK_ZNAME (report_info) (control, info); 6342 UMFPACK_ZNAME (report_info) (control, info);
6343 6343
6344 UMFPACK_ZNAME (free_numeric) (&Numeric); 6344 UMFPACK_ZNAME (free_numeric) (&Numeric);
6345 } 6345 }
6346 else 6346 else
6347 mattype.mark_as_rectangular (); 6347 mattype.mark_as_rectangular ();
6348 6348
6349 #else 6349 #else
6350 (*current_liboctave_error_handler) ("UMFPACK not installed"); 6350 (*current_liboctave_error_handler) ("UMFPACK not installed");
6351 #endif 6351 #endif
6352 } 6352 }
6353 else if (typ != MatrixType::Hermitian) 6353 else if (typ != MatrixType::Hermitian)
6354 (*current_liboctave_error_handler) ("incorrect matrix type"); 6354 (*current_liboctave_error_handler) ("incorrect matrix type");
6355 } 6355 }
6356 6356
6357 return retval; 6357 return retval;
6358 } 6358 }
6359 6359
6360 SparseComplexMatrix 6360 SparseComplexMatrix
6361 SparseComplexMatrix::fsolve (MatrixType &mattype, const SparseComplexMatrix& b, 6361 SparseComplexMatrix::fsolve (MatrixType &mattype, const SparseComplexMatrix& b,
6362 octave_idx_type& err, double& rcond, 6362 octave_idx_type& err, double& rcond,
6363 solve_singularity_handler sing_handler, 6363 solve_singularity_handler sing_handler,
6364 bool calc_cond) const 6364 bool calc_cond) const
6365 { 6365 {
6366 SparseComplexMatrix retval; 6366 SparseComplexMatrix retval;
6367 6367
6368 octave_idx_type nr = rows (); 6368 octave_idx_type nr = rows ();
6369 octave_idx_type nc = cols (); 6369 octave_idx_type nc = cols ();
6379 // Print spparms("spumoni") info if requested 6379 // Print spparms("spumoni") info if requested
6380 volatile int typ = mattype.type (); 6380 volatile int typ = mattype.type ();
6381 mattype.info (); 6381 mattype.info ();
6382 6382
6383 if (typ == MatrixType::Hermitian) 6383 if (typ == MatrixType::Hermitian)
6384 { 6384 {
6385 #ifdef HAVE_CHOLMOD 6385 #ifdef HAVE_CHOLMOD
6386 cholmod_common Common; 6386 cholmod_common Common;
6387 cholmod_common *cm = &Common; 6387 cholmod_common *cm = &Common;
6388 6388
6389 // Setup initial parameters 6389 // Setup initial parameters
6390 CHOLMOD_NAME(start) (cm); 6390 CHOLMOD_NAME(start) (cm);
6391 cm->prefer_zomplex = false; 6391 cm->prefer_zomplex = false;
6392 6392
6393 double spu = octave_sparse_params::get_key ("spumoni"); 6393 double spu = octave_sparse_params::get_key ("spumoni");
6394 if (spu == 0.) 6394 if (spu == 0.)
6395 { 6395 {
6396 cm->print = -1; 6396 cm->print = -1;
6397 cm->print_function = 0; 6397 cm->print_function = 0;
6398 } 6398 }
6399 else 6399 else
6400 { 6400 {
6401 cm->print = static_cast<int> (spu) + 2; 6401 cm->print = static_cast<int> (spu) + 2;
6402 cm->print_function =&SparseCholPrint; 6402 cm->print_function =&SparseCholPrint;
6403 } 6403 }
6404 6404
6405 cm->error_handler = &SparseCholError; 6405 cm->error_handler = &SparseCholError;
6406 cm->complex_divide = CHOLMOD_NAME(divcomplex); 6406 cm->complex_divide = CHOLMOD_NAME(divcomplex);
6407 cm->hypotenuse = CHOLMOD_NAME(hypot); 6407 cm->hypotenuse = CHOLMOD_NAME(hypot);
6408 6408
6409 cm->final_ll = true; 6409 cm->final_ll = true;
6410 6410
6411 cholmod_sparse Astore; 6411 cholmod_sparse Astore;
6412 cholmod_sparse *A = &Astore; 6412 cholmod_sparse *A = &Astore;
6413 double dummy; 6413 double dummy;
6414 A->nrow = nr; 6414 A->nrow = nr;
6415 A->ncol = nc; 6415 A->ncol = nc;
6416 6416
6417 A->p = cidx(); 6417 A->p = cidx();
6418 A->i = ridx(); 6418 A->i = ridx();
6419 A->nzmax = nnz(); 6419 A->nzmax = nnz();
6420 A->packed = true; 6420 A->packed = true;
6421 A->sorted = true; 6421 A->sorted = true;
6422 A->nz = 0; 6422 A->nz = 0;
6423 #ifdef IDX_TYPE_LONG 6423 #ifdef IDX_TYPE_LONG
6424 A->itype = CHOLMOD_LONG; 6424 A->itype = CHOLMOD_LONG;
6425 #else 6425 #else
6426 A->itype = CHOLMOD_INT; 6426 A->itype = CHOLMOD_INT;
6427 #endif 6427 #endif
6428 A->dtype = CHOLMOD_DOUBLE; 6428 A->dtype = CHOLMOD_DOUBLE;
6429 A->stype = 1; 6429 A->stype = 1;
6430 A->xtype = CHOLMOD_COMPLEX; 6430 A->xtype = CHOLMOD_COMPLEX;
6431 6431
6432 if (nr < 1) 6432 if (nr < 1)
6433 A->x = &dummy; 6433 A->x = &dummy;
6434 else 6434 else
6435 A->x = data(); 6435 A->x = data();
6436 6436
6437 cholmod_sparse Bstore; 6437 cholmod_sparse Bstore;
6438 cholmod_sparse *B = &Bstore; 6438 cholmod_sparse *B = &Bstore;
6439 B->nrow = b.rows(); 6439 B->nrow = b.rows();
6440 B->ncol = b.cols(); 6440 B->ncol = b.cols();
6441 B->p = b.cidx(); 6441 B->p = b.cidx();
6442 B->i = b.ridx(); 6442 B->i = b.ridx();
6443 B->nzmax = b.nnz(); 6443 B->nzmax = b.nnz();
6444 B->packed = true; 6444 B->packed = true;
6445 B->sorted = true; 6445 B->sorted = true;
6446 B->nz = 0; 6446 B->nz = 0;
6447 #ifdef IDX_TYPE_LONG 6447 #ifdef IDX_TYPE_LONG
6448 B->itype = CHOLMOD_LONG; 6448 B->itype = CHOLMOD_LONG;
6449 #else 6449 #else
6450 B->itype = CHOLMOD_INT; 6450 B->itype = CHOLMOD_INT;
6451 #endif 6451 #endif
6452 B->dtype = CHOLMOD_DOUBLE; 6452 B->dtype = CHOLMOD_DOUBLE;
6453 B->stype = 0; 6453 B->stype = 0;
6454 B->xtype = CHOLMOD_COMPLEX; 6454 B->xtype = CHOLMOD_COMPLEX;
6455 6455
6456 if (b.rows() < 1 || b.cols() < 1) 6456 if (b.rows() < 1 || b.cols() < 1)
6457 B->x = &dummy; 6457 B->x = &dummy;
6458 else 6458 else
6459 B->x = b.data(); 6459 B->x = b.data();
6460 6460
6461 cholmod_factor *L; 6461 cholmod_factor *L;
6462 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6462 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6463 L = CHOLMOD_NAME(analyze) (A, cm); 6463 L = CHOLMOD_NAME(analyze) (A, cm);
6464 CHOLMOD_NAME(factorize) (A, L, cm); 6464 CHOLMOD_NAME(factorize) (A, L, cm);
6465 if (calc_cond) 6465 if (calc_cond)
6466 rcond = CHOLMOD_NAME(rcond)(L, cm); 6466 rcond = CHOLMOD_NAME(rcond)(L, cm);
6467 else 6467 else
6468 rcond = 1.; 6468 rcond = 1.;
6469 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6469 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6470 6470
6471 if (rcond == 0.0) 6471 if (rcond == 0.0)
6472 { 6472 {
6473 // Either its indefinite or singular. Try UMFPACK 6473 // Either its indefinite or singular. Try UMFPACK
6474 mattype.mark_as_unsymmetric (); 6474 mattype.mark_as_unsymmetric ();
6475 typ = MatrixType::Full; 6475 typ = MatrixType::Full;
6476 } 6476 }
6477 else 6477 else
6478 { 6478 {
6479 volatile double rcond_plus_one = rcond + 1.0; 6479 volatile double rcond_plus_one = rcond + 1.0;
6480 6480
6481 if (rcond_plus_one == 1.0 || xisnan (rcond)) 6481 if (rcond_plus_one == 1.0 || xisnan (rcond))
6482 { 6482 {
6483 err = -2; 6483 err = -2;
6484 6484
6485 if (sing_handler) 6485 if (sing_handler)
6486 { 6486 {
6487 sing_handler (rcond); 6487 sing_handler (rcond);
6488 mattype.mark_as_rectangular (); 6488 mattype.mark_as_rectangular ();
6489 } 6489 }
6490 else 6490 else
6491 (*current_liboctave_error_handler) 6491 (*current_liboctave_error_handler)
6492 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", 6492 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
6493 rcond); 6493 rcond);
6494 6494
6495 return retval; 6495 return retval;
6496 } 6496 }
6497 6497
6498 cholmod_sparse *X; 6498 cholmod_sparse *X;
6499 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6499 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6500 X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm); 6500 X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm);
6501 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6501 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6502 6502
6503 retval = SparseComplexMatrix 6503 retval = SparseComplexMatrix
6504 (static_cast<octave_idx_type>(X->nrow), 6504 (static_cast<octave_idx_type>(X->nrow),
6505 static_cast<octave_idx_type>(X->ncol), 6505 static_cast<octave_idx_type>(X->ncol),
6506 static_cast<octave_idx_type>(X->nzmax)); 6506 static_cast<octave_idx_type>(X->nzmax));
6507 for (octave_idx_type j = 0; 6507 for (octave_idx_type j = 0;
6508 j <= static_cast<octave_idx_type>(X->ncol); j++) 6508 j <= static_cast<octave_idx_type>(X->ncol); j++)
6509 retval.xcidx(j) = static_cast<octave_idx_type *>(X->p)[j]; 6509 retval.xcidx(j) = static_cast<octave_idx_type *>(X->p)[j];
6510 for (octave_idx_type j = 0; 6510 for (octave_idx_type j = 0;
6511 j < static_cast<octave_idx_type>(X->nzmax); j++) 6511 j < static_cast<octave_idx_type>(X->nzmax); j++)
6512 { 6512 {
6513 retval.xridx(j) = static_cast<octave_idx_type *>(X->i)[j]; 6513 retval.xridx(j) = static_cast<octave_idx_type *>(X->i)[j];
6514 retval.xdata(j) = static_cast<Complex *>(X->x)[j]; 6514 retval.xdata(j) = static_cast<Complex *>(X->x)[j];
6515 } 6515 }
6516 6516
6517 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6517 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6518 CHOLMOD_NAME(free_sparse) (&X, cm); 6518 CHOLMOD_NAME(free_sparse) (&X, cm);
6519 CHOLMOD_NAME(free_factor) (&L, cm); 6519 CHOLMOD_NAME(free_factor) (&L, cm);
6520 CHOLMOD_NAME(finish) (cm); 6520 CHOLMOD_NAME(finish) (cm);
6521 static char tmp[] = " "; 6521 static char tmp[] = " ";
6522 CHOLMOD_NAME(print_common) (tmp, cm); 6522 CHOLMOD_NAME(print_common) (tmp, cm);
6523 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; 6523 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
6524 } 6524 }
6525 #else 6525 #else
6526 (*current_liboctave_warning_handler) 6526 (*current_liboctave_warning_handler)
6527 ("CHOLMOD not installed"); 6527 ("CHOLMOD not installed");
6528 6528
6529 mattype.mark_as_unsymmetric (); 6529 mattype.mark_as_unsymmetric ();
6530 typ = MatrixType::Full; 6530 typ = MatrixType::Full;
6531 #endif 6531 #endif
6532 } 6532 }
6533 6533
6534 if (typ == MatrixType::Full) 6534 if (typ == MatrixType::Full)
6535 { 6535 {
6536 #ifdef HAVE_UMFPACK 6536 #ifdef HAVE_UMFPACK
6537 Matrix Control, Info; 6537 Matrix Control, Info;
6538 void *Numeric = factorize (err, rcond, Control, Info, 6538 void *Numeric = factorize (err, rcond, Control, Info,
6539 sing_handler, calc_cond); 6539 sing_handler, calc_cond);
6540 6540
6541 if (err == 0) 6541 if (err == 0)
6542 { 6542 {
6543 octave_idx_type b_nr = b.rows (); 6543 octave_idx_type b_nr = b.rows ();
6544 octave_idx_type b_nc = b.cols (); 6544 octave_idx_type b_nc = b.cols ();
6545 int status = 0; 6545 int status = 0;
6546 double *control = Control.fortran_vec (); 6546 double *control = Control.fortran_vec ();
6547 double *info = Info.fortran_vec (); 6547 double *info = Info.fortran_vec ();
6548 const octave_idx_type *Ap = cidx (); 6548 const octave_idx_type *Ap = cidx ();
6549 const octave_idx_type *Ai = ridx (); 6549 const octave_idx_type *Ai = ridx ();
6550 const Complex *Ax = data (); 6550 const Complex *Ax = data ();
6551 6551
6552 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); 6552 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
6553 6553
6554 // Take a first guess that the number of non-zero terms 6554 // Take a first guess that the number of non-zero terms
6555 // will be as many as in b 6555 // will be as many as in b
6556 octave_idx_type x_nz = b.nnz (); 6556 octave_idx_type x_nz = b.nnz ();
6557 octave_idx_type ii = 0; 6557 octave_idx_type ii = 0;
6558 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); 6558 retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
6559 6559
6560 OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); 6560 OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr);
6561 6561
6562 retval.xcidx(0) = 0; 6562 retval.xcidx(0) = 0;
6563 for (octave_idx_type j = 0; j < b_nc; j++) 6563 for (octave_idx_type j = 0; j < b_nc; j++)
6564 { 6564 {
6565 for (octave_idx_type i = 0; i < b_nr; i++) 6565 for (octave_idx_type i = 0; i < b_nr; i++)
6566 Bx[i] = b (i,j); 6566 Bx[i] = b (i,j);
6567 6567
6568 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, 6568 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap,
6569 Ai, 6569 Ai,
6570 reinterpret_cast<const double *> (Ax), 6570 reinterpret_cast<const double *> (Ax),
6571 0, 6571 0,
6572 reinterpret_cast<double *> (Xx), 6572 reinterpret_cast<double *> (Xx),
6573 0, 6573 0,
6574 reinterpret_cast<double *> (Bx), 6574 reinterpret_cast<double *> (Bx),
6575 0, Numeric, control, info); 6575 0, Numeric, control, info);
6576 6576
6577 if (status < 0) 6577 if (status < 0)
6578 { 6578 {
6579 (*current_liboctave_error_handler) 6579 (*current_liboctave_error_handler)
6580 ("SparseComplexMatrix::solve solve failed"); 6580 ("SparseComplexMatrix::solve solve failed");
6581 6581
6582 UMFPACK_ZNAME (report_status) (control, status); 6582 UMFPACK_ZNAME (report_status) (control, status);
6583 6583
6584 err = -1; 6584 err = -1;
6585 6585
6586 break; 6586 break;
6587 } 6587 }
6588 6588
6589 for (octave_idx_type i = 0; i < b_nr; i++) 6589 for (octave_idx_type i = 0; i < b_nr; i++)
6590 { 6590 {
6591 Complex tmp = Xx[i]; 6591 Complex tmp = Xx[i];
6592 if (tmp != 0.0) 6592 if (tmp != 0.0)
6593 { 6593 {
6594 if (ii == x_nz) 6594 if (ii == x_nz)
6595 { 6595 {
6596 // Resize the sparse matrix 6596 // Resize the sparse matrix
6597 octave_idx_type sz = x_nz * (b_nc - j) / b_nc; 6597 octave_idx_type sz = x_nz * (b_nc - j) / b_nc;
6598 sz = (sz > 10 ? sz : 10) + x_nz; 6598 sz = (sz > 10 ? sz : 10) + x_nz;
6599 retval.change_capacity (sz); 6599 retval.change_capacity (sz);
6600 x_nz = sz; 6600 x_nz = sz;
6601 } 6601 }
6602 retval.xdata(ii) = tmp; 6602 retval.xdata(ii) = tmp;
6603 retval.xridx(ii++) = i; 6603 retval.xridx(ii++) = i;
6604 } 6604 }
6605 } 6605 }
6606 retval.xcidx(j+1) = ii; 6606 retval.xcidx(j+1) = ii;
6607 } 6607 }
6608 6608
6609 retval.maybe_compress (); 6609 retval.maybe_compress ();
6610 6610
6611 rcond = Info (UMFPACK_RCOND); 6611 rcond = Info (UMFPACK_RCOND);
6612 volatile double rcond_plus_one = rcond + 1.0; 6612 volatile double rcond_plus_one = rcond + 1.0;
6613 6613
6614 if (status == UMFPACK_WARNING_singular_matrix || 6614 if (status == UMFPACK_WARNING_singular_matrix ||
6615 rcond_plus_one == 1.0 || xisnan (rcond)) 6615 rcond_plus_one == 1.0 || xisnan (rcond))
6616 { 6616 {
6617 err = -2; 6617 err = -2;
6618 6618
6619 if (sing_handler) 6619 if (sing_handler)
6620 sing_handler (rcond); 6620 sing_handler (rcond);
6621 else 6621 else
6622 (*current_liboctave_error_handler) 6622 (*current_liboctave_error_handler)
6623 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", 6623 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
6624 rcond); 6624 rcond);
6625 6625
6626 } 6626 }
6627 6627
6628 UMFPACK_ZNAME (report_info) (control, info); 6628 UMFPACK_ZNAME (report_info) (control, info);
6629 6629
6630 UMFPACK_ZNAME (free_numeric) (&Numeric); 6630 UMFPACK_ZNAME (free_numeric) (&Numeric);
6631 } 6631 }
6632 else 6632 else
6633 mattype.mark_as_rectangular (); 6633 mattype.mark_as_rectangular ();
6634 6634
6635 #else 6635 #else
6636 (*current_liboctave_error_handler) ("UMFPACK not installed"); 6636 (*current_liboctave_error_handler) ("UMFPACK not installed");
6637 #endif 6637 #endif
6638 } 6638 }
6639 else if (typ != MatrixType::Hermitian) 6639 else if (typ != MatrixType::Hermitian)
6640 (*current_liboctave_error_handler) ("incorrect matrix type"); 6640 (*current_liboctave_error_handler) ("incorrect matrix type");
6641 } 6641 }
6642 6642
6643 return retval; 6643 return retval;
6644 } 6644 }
6645 6645
6651 return solve (mattype, b, info, rcond, 0); 6651 return solve (mattype, b, info, rcond, 0);
6652 } 6652 }
6653 6653
6654 ComplexMatrix 6654 ComplexMatrix
6655 SparseComplexMatrix::solve (MatrixType &mattype, const Matrix& b, 6655 SparseComplexMatrix::solve (MatrixType &mattype, const Matrix& b,
6656 octave_idx_type& info) const 6656 octave_idx_type& info) const
6657 { 6657 {
6658 double rcond; 6658 double rcond;
6659 return solve (mattype, b, info, rcond, 0); 6659 return solve (mattype, b, info, rcond, 0);
6660 } 6660 }
6661 6661
6662 ComplexMatrix 6662 ComplexMatrix
6663 SparseComplexMatrix::solve (MatrixType &mattype, const Matrix& b, 6663 SparseComplexMatrix::solve (MatrixType &mattype, const Matrix& b,
6664 octave_idx_type& info, double& rcond) const 6664 octave_idx_type& info, double& rcond) const
6665 { 6665 {
6666 return solve (mattype, b, info, rcond, 0); 6666 return solve (mattype, b, info, rcond, 0);
6667 } 6667 }
6668 6668
6669 ComplexMatrix 6669 ComplexMatrix
6670 SparseComplexMatrix::solve (MatrixType &mattype, const Matrix& b, 6670 SparseComplexMatrix::solve (MatrixType &mattype, const Matrix& b,
6671 octave_idx_type& err, double& rcond, 6671 octave_idx_type& err, double& rcond,
6672 solve_singularity_handler sing_handler, 6672 solve_singularity_handler sing_handler,
6673 bool singular_fallback) const 6673 bool singular_fallback) const
6674 { 6674 {
6675 ComplexMatrix retval; 6675 ComplexMatrix retval;
6676 int typ = mattype.type (false); 6676 int typ = mattype.type (false);
6677 6677
6678 if (typ == MatrixType::Unknown) 6678 if (typ == MatrixType::Unknown)
6685 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) 6685 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
6686 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); 6686 retval = ltsolve (mattype, b, err, rcond, sing_handler, false);
6687 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) 6687 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)
6688 retval = bsolve (mattype, b, err, rcond, sing_handler, false); 6688 retval = bsolve (mattype, b, err, rcond, sing_handler, false);
6689 else if (typ == MatrixType::Tridiagonal || 6689 else if (typ == MatrixType::Tridiagonal ||
6690 typ == MatrixType::Tridiagonal_Hermitian) 6690 typ == MatrixType::Tridiagonal_Hermitian)
6691 retval = trisolve (mattype, b, err, rcond, sing_handler, false); 6691 retval = trisolve (mattype, b, err, rcond, sing_handler, false);
6692 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) 6692 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
6693 retval = fsolve (mattype, b, err, rcond, sing_handler, true); 6693 retval = fsolve (mattype, b, err, rcond, sing_handler, true);
6694 else if (typ != MatrixType::Rectangular) 6694 else if (typ != MatrixType::Rectangular)
6695 { 6695 {
6702 rcond = 1.; 6702 rcond = 1.;
6703 #ifdef USE_QRSOLVE 6703 #ifdef USE_QRSOLVE
6704 retval = qrsolve (*this, b, err); 6704 retval = qrsolve (*this, b, err);
6705 #else 6705 #else
6706 retval = dmsolve<ComplexMatrix, SparseComplexMatrix, 6706 retval = dmsolve<ComplexMatrix, SparseComplexMatrix,
6707 Matrix> (*this, b, err); 6707 Matrix> (*this, b, err);
6708 #endif 6708 #endif
6709 } 6709 }
6710 6710
6711 return retval; 6711 return retval;
6712 } 6712 }
6719 return solve (mattype, b, info, rcond, 0); 6719 return solve (mattype, b, info, rcond, 0);
6720 } 6720 }
6721 6721
6722 SparseComplexMatrix 6722 SparseComplexMatrix
6723 SparseComplexMatrix::solve (MatrixType &mattype, const SparseMatrix& b, 6723 SparseComplexMatrix::solve (MatrixType &mattype, const SparseMatrix& b,
6724 octave_idx_type& info) const 6724 octave_idx_type& info) const
6725 { 6725 {
6726 double rcond; 6726 double rcond;
6727 return solve (mattype, b, info, rcond, 0); 6727 return solve (mattype, b, info, rcond, 0);
6728 } 6728 }
6729 6729
6730 SparseComplexMatrix 6730 SparseComplexMatrix
6731 SparseComplexMatrix::solve (MatrixType &mattype, const SparseMatrix& b, 6731 SparseComplexMatrix::solve (MatrixType &mattype, const SparseMatrix& b,
6732 octave_idx_type& info, double& rcond) const 6732 octave_idx_type& info, double& rcond) const
6733 { 6733 {
6734 return solve (mattype, b, info, rcond, 0); 6734 return solve (mattype, b, info, rcond, 0);
6735 } 6735 }
6736 6736
6737 SparseComplexMatrix 6737 SparseComplexMatrix
6738 SparseComplexMatrix::solve (MatrixType &mattype, const SparseMatrix& b, 6738 SparseComplexMatrix::solve (MatrixType &mattype, const SparseMatrix& b,
6739 octave_idx_type& err, double& rcond, 6739 octave_idx_type& err, double& rcond,
6740 solve_singularity_handler sing_handler, 6740 solve_singularity_handler sing_handler,
6741 bool singular_fallback) const 6741 bool singular_fallback) const
6742 { 6742 {
6743 SparseComplexMatrix retval; 6743 SparseComplexMatrix retval;
6744 int typ = mattype.type (false); 6744 int typ = mattype.type (false);
6745 6745
6746 if (typ == MatrixType::Unknown) 6746 if (typ == MatrixType::Unknown)
6753 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) 6753 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
6754 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); 6754 retval = ltsolve (mattype, b, err, rcond, sing_handler, false);
6755 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) 6755 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)
6756 retval = bsolve (mattype, b, err, rcond, sing_handler, false); 6756 retval = bsolve (mattype, b, err, rcond, sing_handler, false);
6757 else if (typ == MatrixType::Tridiagonal || 6757 else if (typ == MatrixType::Tridiagonal ||
6758 typ == MatrixType::Tridiagonal_Hermitian) 6758 typ == MatrixType::Tridiagonal_Hermitian)
6759 retval = trisolve (mattype, b, err, rcond, sing_handler, false); 6759 retval = trisolve (mattype, b, err, rcond, sing_handler, false);
6760 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) 6760 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
6761 retval = fsolve (mattype, b, err, rcond, sing_handler, true); 6761 retval = fsolve (mattype, b, err, rcond, sing_handler, true);
6762 else if (typ != MatrixType::Rectangular) 6762 else if (typ != MatrixType::Rectangular)
6763 { 6763 {
6770 rcond = 1.; 6770 rcond = 1.;
6771 #ifdef USE_QRSOLVE 6771 #ifdef USE_QRSOLVE
6772 retval = qrsolve (*this, b, err); 6772 retval = qrsolve (*this, b, err);
6773 #else 6773 #else
6774 retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix, 6774 retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix,
6775 SparseMatrix> (*this, b, err); 6775 SparseMatrix> (*this, b, err);
6776 #endif 6776 #endif
6777 } 6777 }
6778 6778
6779 return retval; 6779 return retval;
6780 } 6780 }
6787 return solve (mattype, b, info, rcond, 0); 6787 return solve (mattype, b, info, rcond, 0);
6788 } 6788 }
6789 6789
6790 ComplexMatrix 6790 ComplexMatrix
6791 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, 6791 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b,
6792 octave_idx_type& info) const 6792 octave_idx_type& info) const
6793 { 6793 {
6794 double rcond; 6794 double rcond;
6795 return solve (mattype, b, info, rcond, 0); 6795 return solve (mattype, b, info, rcond, 0);
6796 } 6796 }
6797 6797
6798 ComplexMatrix 6798 ComplexMatrix
6799 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, 6799 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b,
6800 octave_idx_type& info, double& rcond) const 6800 octave_idx_type& info, double& rcond) const
6801 { 6801 {
6802 return solve (mattype, b, info, rcond, 0); 6802 return solve (mattype, b, info, rcond, 0);
6803 } 6803 }
6804 6804
6805 ComplexMatrix 6805 ComplexMatrix
6806 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, 6806 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b,
6807 octave_idx_type& err, double& rcond, 6807 octave_idx_type& err, double& rcond,
6808 solve_singularity_handler sing_handler, 6808 solve_singularity_handler sing_handler,
6809 bool singular_fallback) const 6809 bool singular_fallback) const
6810 { 6810 {
6811 ComplexMatrix retval; 6811 ComplexMatrix retval;
6812 int typ = mattype.type (false); 6812 int typ = mattype.type (false);
6813 6813
6814 if (typ == MatrixType::Unknown) 6814 if (typ == MatrixType::Unknown)
6821 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) 6821 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
6822 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); 6822 retval = ltsolve (mattype, b, err, rcond, sing_handler, false);
6823 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) 6823 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)
6824 retval = bsolve (mattype, b, err, rcond, sing_handler, false); 6824 retval = bsolve (mattype, b, err, rcond, sing_handler, false);
6825 else if (typ == MatrixType::Tridiagonal || 6825 else if (typ == MatrixType::Tridiagonal ||
6826 typ == MatrixType::Tridiagonal_Hermitian) 6826 typ == MatrixType::Tridiagonal_Hermitian)
6827 retval = trisolve (mattype, b, err, rcond, sing_handler, false); 6827 retval = trisolve (mattype, b, err, rcond, sing_handler, false);
6828 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) 6828 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
6829 retval = fsolve (mattype, b, err, rcond, sing_handler, true); 6829 retval = fsolve (mattype, b, err, rcond, sing_handler, true);
6830 else if (typ != MatrixType::Rectangular) 6830 else if (typ != MatrixType::Rectangular)
6831 { 6831 {
6838 rcond = 1.; 6838 rcond = 1.;
6839 #ifdef USE_QRSOLVE 6839 #ifdef USE_QRSOLVE
6840 retval = qrsolve (*this, b, err); 6840 retval = qrsolve (*this, b, err);
6841 #else 6841 #else
6842 retval = dmsolve<ComplexMatrix, SparseComplexMatrix, 6842 retval = dmsolve<ComplexMatrix, SparseComplexMatrix,
6843 ComplexMatrix> (*this, b, err); 6843 ComplexMatrix> (*this, b, err);
6844 #endif 6844 #endif
6845 } 6845 }
6846 6846
6847 return retval; 6847 return retval;
6848 } 6848 }
6849 6849
6850 SparseComplexMatrix 6850 SparseComplexMatrix
6851 SparseComplexMatrix::solve (MatrixType &mattype, 6851 SparseComplexMatrix::solve (MatrixType &mattype,
6852 const SparseComplexMatrix& b) const 6852 const SparseComplexMatrix& b) const
6853 { 6853 {
6854 octave_idx_type info; 6854 octave_idx_type info;
6855 double rcond; 6855 double rcond;
6856 return solve (mattype, b, info, rcond, 0); 6856 return solve (mattype, b, info, rcond, 0);
6857 } 6857 }
6858 6858
6859 SparseComplexMatrix 6859 SparseComplexMatrix
6860 SparseComplexMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b, 6860 SparseComplexMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b,
6861 octave_idx_type& info) const 6861 octave_idx_type& info) const
6862 { 6862 {
6863 double rcond; 6863 double rcond;
6864 return solve (mattype, b, info, rcond, 0); 6864 return solve (mattype, b, info, rcond, 0);
6865 } 6865 }
6866 6866
6867 SparseComplexMatrix 6867 SparseComplexMatrix
6868 SparseComplexMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b, 6868 SparseComplexMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b,
6869 octave_idx_type& info, double& rcond) const 6869 octave_idx_type& info, double& rcond) const
6870 { 6870 {
6871 return solve (mattype, b, info, rcond, 0); 6871 return solve (mattype, b, info, rcond, 0);
6872 } 6872 }
6873 6873
6874 SparseComplexMatrix 6874 SparseComplexMatrix
6875 SparseComplexMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b, 6875 SparseComplexMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b,
6876 octave_idx_type& err, double& rcond, 6876 octave_idx_type& err, double& rcond,
6877 solve_singularity_handler sing_handler, 6877 solve_singularity_handler sing_handler,
6878 bool singular_fallback) const 6878 bool singular_fallback) const
6879 { 6879 {
6880 SparseComplexMatrix retval; 6880 SparseComplexMatrix retval;
6881 int typ = mattype.type (false); 6881 int typ = mattype.type (false);
6882 6882
6883 if (typ == MatrixType::Unknown) 6883 if (typ == MatrixType::Unknown)
6890 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) 6890 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
6891 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); 6891 retval = ltsolve (mattype, b, err, rcond, sing_handler, false);
6892 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) 6892 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian)
6893 retval = bsolve (mattype, b, err, rcond, sing_handler, false); 6893 retval = bsolve (mattype, b, err, rcond, sing_handler, false);
6894 else if (typ == MatrixType::Tridiagonal || 6894 else if (typ == MatrixType::Tridiagonal ||
6895 typ == MatrixType::Tridiagonal_Hermitian) 6895 typ == MatrixType::Tridiagonal_Hermitian)
6896 retval = trisolve (mattype, b, err, rcond, sing_handler, false); 6896 retval = trisolve (mattype, b, err, rcond, sing_handler, false);
6897 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) 6897 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
6898 retval = fsolve (mattype, b, err, rcond, sing_handler, true); 6898 retval = fsolve (mattype, b, err, rcond, sing_handler, true);
6899 else if (typ != MatrixType::Rectangular) 6899 else if (typ != MatrixType::Rectangular)
6900 { 6900 {
6907 rcond = 1.; 6907 rcond = 1.;
6908 #ifdef USE_QRSOLVE 6908 #ifdef USE_QRSOLVE
6909 retval = qrsolve (*this, b, err); 6909 retval = qrsolve (*this, b, err);
6910 #else 6910 #else
6911 retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix, 6911 retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix,
6912 SparseComplexMatrix> (*this, b, err); 6912 SparseComplexMatrix> (*this, b, err);
6913 #endif 6913 #endif
6914 } 6914 }
6915 6915
6916 return retval; 6916 return retval;
6917 } 6917 }
6923 return solve (mattype, b, info, rcond); 6923 return solve (mattype, b, info, rcond);
6924 } 6924 }
6925 6925
6926 ComplexColumnVector 6926 ComplexColumnVector
6927 SparseComplexMatrix::solve (MatrixType &mattype, const ColumnVector& b, 6927 SparseComplexMatrix::solve (MatrixType &mattype, const ColumnVector& b,
6928 octave_idx_type& info) const 6928 octave_idx_type& info) const
6929 { 6929 {
6930 double rcond; 6930 double rcond;
6931 return solve (mattype, b, info, rcond); 6931 return solve (mattype, b, info, rcond);
6932 } 6932 }
6933 6933
6934 ComplexColumnVector 6934 ComplexColumnVector
6935 SparseComplexMatrix::solve (MatrixType &mattype, const ColumnVector& b, 6935 SparseComplexMatrix::solve (MatrixType &mattype, const ColumnVector& b,
6936 octave_idx_type& info, double& rcond) const 6936 octave_idx_type& info, double& rcond) const
6937 { 6937 {
6938 return solve (mattype, b, info, rcond, 0); 6938 return solve (mattype, b, info, rcond, 0);
6939 } 6939 }
6940 6940
6941 ComplexColumnVector 6941 ComplexColumnVector
6942 SparseComplexMatrix::solve (MatrixType &mattype, const ColumnVector& b, 6942 SparseComplexMatrix::solve (MatrixType &mattype, const ColumnVector& b,
6943 octave_idx_type& info, double& rcond, 6943 octave_idx_type& info, double& rcond,
6944 solve_singularity_handler sing_handler) const 6944 solve_singularity_handler sing_handler) const
6945 { 6945 {
6946 Matrix tmp (b); 6946 Matrix tmp (b);
6947 return solve (mattype, tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); 6947 return solve (mattype, tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0));
6948 } 6948 }
6949 6949
6950 ComplexColumnVector 6950 ComplexColumnVector
6951 SparseComplexMatrix::solve (MatrixType &mattype, 6951 SparseComplexMatrix::solve (MatrixType &mattype,
6952 const ComplexColumnVector& b) const 6952 const ComplexColumnVector& b) const
6953 { 6953 {
6954 octave_idx_type info; 6954 octave_idx_type info;
6955 double rcond; 6955 double rcond;
6956 return solve (mattype, b, info, rcond, 0); 6956 return solve (mattype, b, info, rcond, 0);
6957 } 6957 }
6958 6958
6959 ComplexColumnVector 6959 ComplexColumnVector
6960 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b, 6960 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b,
6961 octave_idx_type& info) const 6961 octave_idx_type& info) const
6962 { 6962 {
6963 double rcond; 6963 double rcond;
6964 return solve (mattype, b, info, rcond, 0); 6964 return solve (mattype, b, info, rcond, 0);
6965 } 6965 }
6966 6966
6967 ComplexColumnVector 6967 ComplexColumnVector
6968 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b, 6968 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b,
6969 octave_idx_type& info, double& rcond) const 6969 octave_idx_type& info, double& rcond) const
6970 { 6970 {
6971 return solve (mattype, b, info, rcond, 0); 6971 return solve (mattype, b, info, rcond, 0);
6972 } 6972 }
6973 6973
6974 ComplexColumnVector 6974 ComplexColumnVector
6975 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b, 6975 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b,
6976 octave_idx_type& info, double& rcond, 6976 octave_idx_type& info, double& rcond,
6977 solve_singularity_handler sing_handler) const 6977 solve_singularity_handler sing_handler) const
6978 { 6978 {
6979 ComplexMatrix tmp (b); 6979 ComplexMatrix tmp (b);
6980 return solve (mattype, tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); 6980 return solve (mattype, tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0));
6981 } 6981 }
6982 6982
6995 return solve (b, info, rcond, 0); 6995 return solve (b, info, rcond, 0);
6996 } 6996 }
6997 6997
6998 ComplexMatrix 6998 ComplexMatrix
6999 SparseComplexMatrix::solve (const Matrix& b, octave_idx_type& info, 6999 SparseComplexMatrix::solve (const Matrix& b, octave_idx_type& info,
7000 double& rcond) const 7000 double& rcond) const
7001 { 7001 {
7002 return solve (b, info, rcond, 0); 7002 return solve (b, info, rcond, 0);
7003 } 7003 }
7004 7004
7005 ComplexMatrix 7005 ComplexMatrix
7006 SparseComplexMatrix::solve (const Matrix& b, octave_idx_type& err, 7006 SparseComplexMatrix::solve (const Matrix& b, octave_idx_type& err,
7007 double& rcond, 7007 double& rcond,
7008 solve_singularity_handler sing_handler) const 7008 solve_singularity_handler sing_handler) const
7009 { 7009 {
7010 MatrixType mattype (*this); 7010 MatrixType mattype (*this);
7011 return solve (mattype, b, err, rcond, sing_handler); 7011 return solve (mattype, b, err, rcond, sing_handler);
7012 } 7012 }
7013 7013
7019 return solve (b, info, rcond, 0); 7019 return solve (b, info, rcond, 0);
7020 } 7020 }
7021 7021
7022 SparseComplexMatrix 7022 SparseComplexMatrix
7023 SparseComplexMatrix::solve (const SparseMatrix& b, 7023 SparseComplexMatrix::solve (const SparseMatrix& b,
7024 octave_idx_type& info) const 7024 octave_idx_type& info) const
7025 { 7025 {
7026 double rcond; 7026 double rcond;
7027 return solve (b, info, rcond, 0); 7027 return solve (b, info, rcond, 0);
7028 } 7028 }
7029 7029
7030 SparseComplexMatrix 7030 SparseComplexMatrix
7031 SparseComplexMatrix::solve (const SparseMatrix& b, 7031 SparseComplexMatrix::solve (const SparseMatrix& b,
7032 octave_idx_type& info, double& rcond) const 7032 octave_idx_type& info, double& rcond) const
7033 { 7033 {
7034 return solve (b, info, rcond, 0); 7034 return solve (b, info, rcond, 0);
7035 } 7035 }
7036 7036
7037 SparseComplexMatrix 7037 SparseComplexMatrix
7038 SparseComplexMatrix::solve (const SparseMatrix& b, 7038 SparseComplexMatrix::solve (const SparseMatrix& b,
7039 octave_idx_type& err, double& rcond, 7039 octave_idx_type& err, double& rcond,
7040 solve_singularity_handler sing_handler) const 7040 solve_singularity_handler sing_handler) const
7041 { 7041 {
7042 MatrixType mattype (*this); 7042 MatrixType mattype (*this);
7043 return solve (mattype, b, err, rcond, sing_handler); 7043 return solve (mattype, b, err, rcond, sing_handler);
7044 } 7044 }
7045 7045
7046 ComplexMatrix 7046 ComplexMatrix
7047 SparseComplexMatrix::solve (const ComplexMatrix& b, 7047 SparseComplexMatrix::solve (const ComplexMatrix& b,
7048 octave_idx_type& info) const 7048 octave_idx_type& info) const
7049 { 7049 {
7050 double rcond; 7050 double rcond;
7051 return solve (b, info, rcond, 0); 7051 return solve (b, info, rcond, 0);
7052 } 7052 }
7053 7053
7054 ComplexMatrix 7054 ComplexMatrix
7055 SparseComplexMatrix::solve (const ComplexMatrix& b, 7055 SparseComplexMatrix::solve (const ComplexMatrix& b,
7056 octave_idx_type& info, double& rcond) const 7056 octave_idx_type& info, double& rcond) const
7057 { 7057 {
7058 return solve (b, info, rcond, 0); 7058 return solve (b, info, rcond, 0);
7059 } 7059 }
7060 7060
7061 ComplexMatrix 7061 ComplexMatrix
7062 SparseComplexMatrix::solve (const ComplexMatrix& b, 7062 SparseComplexMatrix::solve (const ComplexMatrix& b,
7063 octave_idx_type& err, double& rcond, 7063 octave_idx_type& err, double& rcond,
7064 solve_singularity_handler sing_handler) const 7064 solve_singularity_handler sing_handler) const
7065 { 7065 {
7066 MatrixType mattype (*this); 7066 MatrixType mattype (*this);
7067 return solve (mattype, b, err, rcond, sing_handler); 7067 return solve (mattype, b, err, rcond, sing_handler);
7068 } 7068 }
7069 7069
7075 return solve (b, info, rcond, 0); 7075 return solve (b, info, rcond, 0);
7076 } 7076 }
7077 7077
7078 SparseComplexMatrix 7078 SparseComplexMatrix
7079 SparseComplexMatrix::solve (const SparseComplexMatrix& b, 7079 SparseComplexMatrix::solve (const SparseComplexMatrix& b,
7080 octave_idx_type& info) const 7080 octave_idx_type& info) const
7081 { 7081 {
7082 double rcond; 7082 double rcond;
7083 return solve (b, info, rcond, 0); 7083 return solve (b, info, rcond, 0);
7084 } 7084 }
7085 7085
7086 SparseComplexMatrix 7086 SparseComplexMatrix
7087 SparseComplexMatrix::solve (const SparseComplexMatrix& b, 7087 SparseComplexMatrix::solve (const SparseComplexMatrix& b,
7088 octave_idx_type& info, double& rcond) const 7088 octave_idx_type& info, double& rcond) const
7089 { 7089 {
7090 return solve (b, info, rcond, 0); 7090 return solve (b, info, rcond, 0);
7091 } 7091 }
7092 7092
7093 SparseComplexMatrix 7093 SparseComplexMatrix
7094 SparseComplexMatrix::solve (const SparseComplexMatrix& b, 7094 SparseComplexMatrix::solve (const SparseComplexMatrix& b,
7095 octave_idx_type& err, double& rcond, 7095 octave_idx_type& err, double& rcond,
7096 solve_singularity_handler sing_handler) const 7096 solve_singularity_handler sing_handler) const
7097 { 7097 {
7098 MatrixType mattype (*this); 7098 MatrixType mattype (*this);
7099 return solve (mattype, b, err, rcond, sing_handler); 7099 return solve (mattype, b, err, rcond, sing_handler);
7100 } 7100 }
7101 7101
7113 return solve (b, info, rcond); 7113 return solve (b, info, rcond);
7114 } 7114 }
7115 7115
7116 ComplexColumnVector 7116 ComplexColumnVector
7117 SparseComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, 7117 SparseComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info,
7118 double& rcond) const 7118 double& rcond) const
7119 { 7119 {
7120 return solve (b, info, rcond, 0); 7120 return solve (b, info, rcond, 0);
7121 } 7121 }
7122 7122
7123 ComplexColumnVector 7123 ComplexColumnVector
7124 SparseComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcond, 7124 SparseComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcond,
7125 solve_singularity_handler sing_handler) const 7125 solve_singularity_handler sing_handler) const
7126 { 7126 {
7127 Matrix tmp (b); 7127 Matrix tmp (b);
7128 return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); 7128 return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0));
7129 } 7129 }
7130 7130
7143 return solve (b, info, rcond, 0); 7143 return solve (b, info, rcond, 0);
7144 } 7144 }
7145 7145
7146 ComplexColumnVector 7146 ComplexColumnVector
7147 SparseComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, 7147 SparseComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info,
7148 double& rcond) const 7148 double& rcond) const
7149 { 7149 {
7150 return solve (b, info, rcond, 0); 7150 return solve (b, info, rcond, 0);
7151 } 7151 }
7152 7152
7153 ComplexColumnVector 7153 ComplexColumnVector
7154 SparseComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, 7154 SparseComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info,
7155 double& rcond, 7155 double& rcond,
7156 solve_singularity_handler sing_handler) const 7156 solve_singularity_handler sing_handler) const
7157 { 7157 {
7158 ComplexMatrix tmp (b); 7158 ComplexMatrix tmp (b);
7159 return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); 7159 return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0));
7160 } 7160 }
7161 7161
7174 octave_idx_type jj = 0; 7174 octave_idx_type jj = 0;
7175 r.cidx (0) = 0; 7175 r.cidx (0) = 0;
7176 for (octave_idx_type i = 0; i < nc; i++) 7176 for (octave_idx_type i = 0; i < nc; i++)
7177 { 7177 {
7178 for (octave_idx_type j = 0; j < nr; j++) 7178 for (octave_idx_type j = 0; j < nr; j++)
7179 { 7179 {
7180 if (jj < cidx(i+1) && ridx(jj) == j) 7180 if (jj < cidx(i+1) && ridx(jj) == j)
7181 jj++; 7181 jj++;
7182 else 7182 else
7183 { 7183 {
7184 r.data(ii) = true; 7184 r.data(ii) = true;
7185 r.ridx(ii++) = j; 7185 r.ridx(ii++) = j;
7186 } 7186 }
7187 } 7187 }
7188 r.cidx (i+1) = ii; 7188 r.cidx (i+1) = ii;
7189 } 7189 }
7190 7190
7191 return r; 7191 return r;
7192 } 7192 }
7241 7241
7242 for (octave_idx_type i = 0; i < nel; i++) 7242 for (octave_idx_type i = 0; i < nel; i++)
7243 { 7243 {
7244 Complex val = data (i); 7244 Complex val = data (i);
7245 if (xisnan (val)) 7245 if (xisnan (val))
7246 return true; 7246 return true;
7247 } 7247 }
7248 7248
7249 return false; 7249 return false;
7250 } 7250 }
7251 7251
7256 7256
7257 for (octave_idx_type i = 0; i < nel; i++) 7257 for (octave_idx_type i = 0; i < nel; i++)
7258 { 7258 {
7259 Complex val = data (i); 7259 Complex val = data (i);
7260 if (xisinf (val) || xisnan (val)) 7260 if (xisinf (val) || xisnan (val))
7261 return true; 7261 return true;
7262 } 7262 }
7263 7263
7264 return false; 7264 return false;
7265 } 7265 }
7266 7266
7287 max_val = std::real(data (0)); 7287 max_val = std::real(data (0));
7288 min_val = std::real(data (0)); 7288 min_val = std::real(data (0));
7289 7289
7290 for (octave_idx_type i = 0; i < nel; i++) 7290 for (octave_idx_type i = 0; i < nel; i++)
7291 { 7291 {
7292 Complex val = data (i); 7292 Complex val = data (i);
7293 7293
7294 double r_val = std::real (val); 7294 double r_val = std::real (val);
7295 double i_val = std::imag (val); 7295 double i_val = std::imag (val);
7296 7296
7297 if (r_val > max_val) 7297 if (r_val > max_val)
7298 max_val = r_val; 7298 max_val = r_val;
7299 7299
7300 if (i_val > max_val) 7300 if (i_val > max_val)
7301 max_val = i_val; 7301 max_val = i_val;
7302 7302
7303 if (r_val < min_val) 7303 if (r_val < min_val)
7304 min_val = r_val; 7304 min_val = r_val;
7305 7305
7306 if (i_val < min_val) 7306 if (i_val < min_val)
7307 min_val = i_val; 7307 min_val = i_val;
7308 7308
7309 if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val) 7309 if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val)
7310 return false; 7310 return false;
7311 } 7311 }
7312 7312
7313 return true; 7313 return true;
7314 } 7314 }
7315 7315
7318 { 7318 {
7319 octave_idx_type nel = nnz (); 7319 octave_idx_type nel = nnz ();
7320 7320
7321 for (octave_idx_type i = 0; i < nel; i++) 7321 for (octave_idx_type i = 0; i < nel; i++)
7322 { 7322 {
7323 Complex val = data (i); 7323 Complex val = data (i);
7324 7324
7325 double r_val = std::real (val); 7325 double r_val = std::real (val);
7326 double i_val = std::imag (val); 7326 double i_val = std::imag (val);
7327 7327
7328 if (r_val > FLT_MAX 7328 if (r_val > FLT_MAX
7329 || i_val > FLT_MAX 7329 || i_val > FLT_MAX
7330 || r_val < FLT_MIN 7330 || r_val < FLT_MIN
7331 || i_val < FLT_MIN) 7331 || i_val < FLT_MIN)
7332 return true; 7332 return true;
7333 } 7333 }
7334 7334
7335 return false; 7335 return false;
7336 } 7336 }
7337 7337
7368 if ((rows() == 1 && dim == -1) || dim == 1) 7368 if ((rows() == 1 && dim == -1) || dim == 1)
7369 return transpose (). prod (0). transpose(); 7369 return transpose (). prod (0). transpose();
7370 else 7370 else
7371 { 7371 {
7372 SPARSE_REDUCTION_OP (SparseComplexMatrix, Complex, *=, 7372 SPARSE_REDUCTION_OP (SparseComplexMatrix, Complex, *=,
7373 (cidx(j+1) - cidx(j) < nr ? 0.0 : 1.0), 1.0); 7373 (cidx(j+1) - cidx(j) < nr ? 0.0 : 1.0), 1.0);
7374 } 7374 }
7375 } 7375 }
7376 7376
7377 SparseComplexMatrix 7377 SparseComplexMatrix
7378 SparseComplexMatrix::sum (int dim) const 7378 SparseComplexMatrix::sum (int dim) const
7390 #define COL_EXPR \ 7390 #define COL_EXPR \
7391 Complex d = data (i); \ 7391 Complex d = data (i); \
7392 tmp [j] += d * conj (d) 7392 tmp [j] += d * conj (d)
7393 7393
7394 SPARSE_BASE_REDUCTION_OP (SparseComplexMatrix, Complex, ROW_EXPR, 7394 SPARSE_BASE_REDUCTION_OP (SparseComplexMatrix, Complex, ROW_EXPR,
7395 COL_EXPR, 0.0, 0.0); 7395 COL_EXPR, 0.0, 0.0);
7396 7396
7397 #undef ROW_EXPR 7397 #undef ROW_EXPR
7398 #undef COL_EXPR 7398 #undef COL_EXPR
7399 } 7399 }
7400 7400
7431 // add one to the printed indices to go from 7431 // add one to the printed indices to go from
7432 // zero-based to one-based arrays 7432 // zero-based to one-based arrays
7433 for (octave_idx_type j = 0; j < nc; j++) { 7433 for (octave_idx_type j = 0; j < nc; j++) {
7434 octave_quit (); 7434 octave_quit ();
7435 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++) { 7435 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++) {
7436 os << a.ridx(i) + 1 << " " << j + 1 << " "; 7436 os << a.ridx(i) + 1 << " " << j + 1 << " ";
7437 octave_write_complex (os, a.data(i)); 7437 octave_write_complex (os, a.data(i));
7438 os << "\n"; 7438 os << "\n";
7439 } 7439 }
7440 } 7440 }
7441 7441
7442 return os; 7442 return os;
7443 } 7443 }
7660 else 7660 else
7661 { 7661 {
7662 result = SparseComplexMatrix (m); 7662 result = SparseComplexMatrix (m);
7663 7663
7664 for (octave_idx_type j = 0; j < nc; j++) 7664 for (octave_idx_type j = 0; j < nc; j++)
7665 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) 7665 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++)
7666 result.data(i) = xmin(c, m.data(i)); 7666 result.data(i) = xmin(c, m.data(i));
7667 } 7667 }
7668 7668
7669 return result; 7669 return result;
7670 } 7670 }
7671 7671
7687 7687
7688 octave_idx_type b_nr = b.rows (); 7688 octave_idx_type b_nr = b.rows ();
7689 octave_idx_type b_nc = b.cols (); 7689 octave_idx_type b_nc = b.cols ();
7690 7690
7691 if (a_nr == 0 || b_nc == 0 || a.nnz () == 0 || b.nnz () == 0) 7691 if (a_nr == 0 || b_nc == 0 || a.nnz () == 0 || b.nnz () == 0)
7692 return SparseComplexMatrix (a_nr, a_nc); 7692 return SparseComplexMatrix (a_nr, a_nc);
7693 7693
7694 if (a_nr != b_nr || a_nc != b_nc) 7694 if (a_nr != b_nr || a_nc != b_nc)
7695 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); 7695 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
7696 else 7696 else
7697 { 7697 {
7698 r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); 7698 r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
7699 7699
7700 octave_idx_type jx = 0; 7700 octave_idx_type jx = 0;
7701 r.cidx (0) = 0; 7701 r.cidx (0) = 0;
7702 for (octave_idx_type i = 0 ; i < a_nc ; i++) 7702 for (octave_idx_type i = 0 ; i < a_nc ; i++)
7703 { 7703 {
7704 octave_idx_type ja = a.cidx(i); 7704 octave_idx_type ja = a.cidx(i);
7705 octave_idx_type ja_max = a.cidx(i+1); 7705 octave_idx_type ja_max = a.cidx(i+1);
7706 bool ja_lt_max= ja < ja_max; 7706 bool ja_lt_max= ja < ja_max;
7707 7707
7708 octave_idx_type jb = b.cidx(i); 7708 octave_idx_type jb = b.cidx(i);
7709 octave_idx_type jb_max = b.cidx(i+1); 7709 octave_idx_type jb_max = b.cidx(i+1);
7710 bool jb_lt_max = jb < jb_max; 7710 bool jb_lt_max = jb < jb_max;
7711 7711
7712 while (ja_lt_max || jb_lt_max ) 7712 while (ja_lt_max || jb_lt_max )
7713 { 7713 {
7714 octave_quit (); 7714 octave_quit ();
7715 if ((! jb_lt_max) || 7715 if ((! jb_lt_max) ||
7716 (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) 7716 (ja_lt_max && (a.ridx(ja) < b.ridx(jb))))
7717 { 7717 {
7718 Complex tmp = xmin (a.data(ja), 0.); 7718 Complex tmp = xmin (a.data(ja), 0.);
7719 if (tmp != 0.) 7719 if (tmp != 0.)
7720 { 7720 {
7721 r.ridx(jx) = a.ridx(ja); 7721 r.ridx(jx) = a.ridx(ja);
7722 r.data(jx) = tmp; 7722 r.data(jx) = tmp;
7723 jx++; 7723 jx++;
7724 } 7724 }
7725 ja++; 7725 ja++;
7726 ja_lt_max= ja < ja_max; 7726 ja_lt_max= ja < ja_max;
7727 } 7727 }
7728 else if (( !ja_lt_max ) || 7728 else if (( !ja_lt_max ) ||
7729 (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) 7729 (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) )
7730 { 7730 {
7731 Complex tmp = xmin (0., b.data(jb)); 7731 Complex tmp = xmin (0., b.data(jb));
7732 if (tmp != 0.) 7732 if (tmp != 0.)
7733 { 7733 {
7734 r.ridx(jx) = b.ridx(jb); 7734 r.ridx(jx) = b.ridx(jb);
7735 r.data(jx) = tmp; 7735 r.data(jx) = tmp;
7736 jx++; 7736 jx++;
7737 } 7737 }
7738 jb++; 7738 jb++;
7739 jb_lt_max= jb < jb_max; 7739 jb_lt_max= jb < jb_max;
7740 } 7740 }
7741 else 7741 else
7742 { 7742 {
7743 Complex tmp = xmin (a.data(ja), b.data(jb)); 7743 Complex tmp = xmin (a.data(ja), b.data(jb));
7744 if (tmp != 0.) 7744 if (tmp != 0.)
7745 { 7745 {
7746 r.data(jx) = tmp; 7746 r.data(jx) = tmp;
7747 r.ridx(jx) = a.ridx(ja); 7747 r.ridx(jx) = a.ridx(ja);
7748 jx++; 7748 jx++;
7749 } 7749 }
7750 ja++; 7750 ja++;
7751 ja_lt_max= ja < ja_max; 7751 ja_lt_max= ja < ja_max;
7752 jb++; 7752 jb++;
7753 jb_lt_max= jb < jb_max; 7753 jb_lt_max= jb < jb_max;
7754 } 7754 }
7755 } 7755 }
7756 r.cidx(i+1) = jx; 7756 r.cidx(i+1) = jx;
7757 } 7757 }
7758 7758
7759 r.maybe_compress (); 7759 r.maybe_compress ();
7760 } 7760 }
7761 } 7761 }
7762 else 7762 else
7763 (*current_liboctave_error_handler) ("matrix size mismatch"); 7763 (*current_liboctave_error_handler) ("matrix size mismatch");
7764 7764
7765 return r; 7765 return r;
7778 // Count the number of non-zero elements 7778 // Count the number of non-zero elements
7779 if (xmax(c, 0.) != 0.) 7779 if (xmax(c, 0.) != 0.)
7780 { 7780 {
7781 result = SparseComplexMatrix (nr, nc, c); 7781 result = SparseComplexMatrix (nr, nc, c);
7782 for (octave_idx_type j = 0; j < nc; j++) 7782 for (octave_idx_type j = 0; j < nc; j++)
7783 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) 7783 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++)
7784 result.xdata(m.ridx(i) + j * nr) = xmax (c, m.data(i)); 7784 result.xdata(m.ridx(i) + j * nr) = xmax (c, m.data(i));
7785 } 7785 }
7786 else 7786 else
7787 result = SparseComplexMatrix (m); 7787 result = SparseComplexMatrix (m);
7788 7788
7789 return result; 7789 return result;
7807 7807
7808 octave_idx_type b_nr = b.rows (); 7808 octave_idx_type b_nr = b.rows ();
7809 octave_idx_type b_nc = b.cols (); 7809 octave_idx_type b_nc = b.cols ();
7810 7810
7811 if (a_nr == 0 || b_nc == 0) 7811 if (a_nr == 0 || b_nc == 0)
7812 return SparseComplexMatrix (a_nr, a_nc); 7812 return SparseComplexMatrix (a_nr, a_nc);
7813 if (a.nnz () == 0) 7813 if (a.nnz () == 0)
7814 return SparseComplexMatrix (b); 7814 return SparseComplexMatrix (b);
7815 if (b.nnz () == 0) 7815 if (b.nnz () == 0)
7816 return SparseComplexMatrix (a); 7816 return SparseComplexMatrix (a);
7817 7817
7818 if (a_nr != b_nr || a_nc != b_nc) 7818 if (a_nr != b_nr || a_nc != b_nc)
7819 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); 7819 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
7820 else 7820 else
7821 { 7821 {
7822 r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); 7822 r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
7823 7823
7824 octave_idx_type jx = 0; 7824 octave_idx_type jx = 0;
7825 r.cidx (0) = 0; 7825 r.cidx (0) = 0;
7826 for (octave_idx_type i = 0 ; i < a_nc ; i++) 7826 for (octave_idx_type i = 0 ; i < a_nc ; i++)
7827 { 7827 {
7828 octave_idx_type ja = a.cidx(i); 7828 octave_idx_type ja = a.cidx(i);
7829 octave_idx_type ja_max = a.cidx(i+1); 7829 octave_idx_type ja_max = a.cidx(i+1);
7830 bool ja_lt_max= ja < ja_max; 7830 bool ja_lt_max= ja < ja_max;
7831 7831
7832 octave_idx_type jb = b.cidx(i); 7832 octave_idx_type jb = b.cidx(i);
7833 octave_idx_type jb_max = b.cidx(i+1); 7833 octave_idx_type jb_max = b.cidx(i+1);
7834 bool jb_lt_max = jb < jb_max; 7834 bool jb_lt_max = jb < jb_max;
7835 7835
7836 while (ja_lt_max || jb_lt_max ) 7836 while (ja_lt_max || jb_lt_max )
7837 { 7837 {
7838 octave_quit (); 7838 octave_quit ();
7839 if ((! jb_lt_max) || 7839 if ((! jb_lt_max) ||
7840 (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) 7840 (ja_lt_max && (a.ridx(ja) < b.ridx(jb))))
7841 { 7841 {
7842 Complex tmp = xmax (a.data(ja), 0.); 7842 Complex tmp = xmax (a.data(ja), 0.);
7843 if (tmp != 0.) 7843 if (tmp != 0.)
7844 { 7844 {
7845 r.ridx(jx) = a.ridx(ja); 7845 r.ridx(jx) = a.ridx(ja);
7846 r.data(jx) = tmp; 7846 r.data(jx) = tmp;
7847 jx++; 7847 jx++;
7848 } 7848 }
7849 ja++; 7849 ja++;
7850 ja_lt_max= ja < ja_max; 7850 ja_lt_max= ja < ja_max;
7851 } 7851 }
7852 else if (( !ja_lt_max ) || 7852 else if (( !ja_lt_max ) ||
7853 (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) 7853 (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) )
7854 { 7854 {
7855 Complex tmp = xmax (0., b.data(jb)); 7855 Complex tmp = xmax (0., b.data(jb));
7856 if (tmp != 0.) 7856 if (tmp != 0.)
7857 { 7857 {
7858 r.ridx(jx) = b.ridx(jb); 7858 r.ridx(jx) = b.ridx(jb);
7859 r.data(jx) = tmp; 7859 r.data(jx) = tmp;
7860 jx++; 7860 jx++;
7861 } 7861 }
7862 jb++; 7862 jb++;
7863 jb_lt_max= jb < jb_max; 7863 jb_lt_max= jb < jb_max;
7864 } 7864 }
7865 else 7865 else
7866 { 7866 {
7867 Complex tmp = xmax (a.data(ja), b.data(jb)); 7867 Complex tmp = xmax (a.data(ja), b.data(jb));
7868 if (tmp != 0.) 7868 if (tmp != 0.)
7869 { 7869 {
7870 r.data(jx) = tmp; 7870 r.data(jx) = tmp;
7871 r.ridx(jx) = a.ridx(ja); 7871 r.ridx(jx) = a.ridx(ja);
7872 jx++; 7872 jx++;
7873 } 7873 }
7874 ja++; 7874 ja++;
7875 ja_lt_max= ja < ja_max; 7875 ja_lt_max= ja < ja_max;
7876 jb++; 7876 jb++;
7877 jb_lt_max= jb < jb_max; 7877 jb_lt_max= jb < jb_max;
7878 } 7878 }
7879 } 7879 }
7880 r.cidx(i+1) = jx; 7880 r.cidx(i+1) = jx;
7881 } 7881 }
7882 7882
7883 r.maybe_compress (); 7883 r.maybe_compress ();
7884 } 7884 }
7885 } 7885 }
7886 else 7886 else
7887 (*current_liboctave_error_handler) ("matrix size mismatch"); 7887 (*current_liboctave_error_handler) ("matrix size mismatch");
7888 7888
7889 return r; 7889 return r;
7890 } 7890 }
7891 7891
7892 SPARSE_SMS_CMP_OPS (SparseComplexMatrix, 0.0, real, Complex, 7892 SPARSE_SMS_CMP_OPS (SparseComplexMatrix, 0.0, real, Complex,
7893 0.0, real) 7893 0.0, real)
7894 SPARSE_SMS_BOOL_OPS (SparseComplexMatrix, Complex, 0.0) 7894 SPARSE_SMS_BOOL_OPS (SparseComplexMatrix, Complex, 0.0)
7895 7895
7896 SPARSE_SSM_CMP_OPS (Complex, 0.0, real, SparseComplexMatrix, 7896 SPARSE_SSM_CMP_OPS (Complex, 0.0, real, SparseComplexMatrix,
7897 0.0, real) 7897 0.0, real)
7898 SPARSE_SSM_BOOL_OPS (Complex, SparseComplexMatrix, 0.0) 7898 SPARSE_SSM_BOOL_OPS (Complex, SparseComplexMatrix, 0.0)
7899 7899
7900 SPARSE_SMSM_CMP_OPS (SparseComplexMatrix, 0.0, real, SparseComplexMatrix, 7900 SPARSE_SMSM_CMP_OPS (SparseComplexMatrix, 0.0, real, SparseComplexMatrix,
7901 0.0, real) 7901 0.0, real)
7902 SPARSE_SMSM_BOOL_OPS (SparseComplexMatrix, SparseComplexMatrix, 0.0) 7902 SPARSE_SMSM_BOOL_OPS (SparseComplexMatrix, SparseComplexMatrix, 0.0)