Mercurial > hg > octave-nkf
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) |