Mercurial > octave
comparison scripts/sparse/bicg.m @ 25200:b3ee0179d7b0 stable
bicg.m: Check for denominators much smaller than numerators bicg.m (bug #53589).
* bicg.m: Set flag = 4 if the denominators are much smaller than the
numerators, not just if they are equal to zero.
author | Marco Caliari <marco.caliari@univr.it> |
---|---|
date | Tue, 10 Apr 2018 08:39:24 +0200 |
parents | 883564a561aa |
children | 07c2c42f457e |
comparison
equal
deleted
inserted
replaced
25199:8cff7eceee87 | 25200:b3ee0179d7b0 |
---|---|
104 ## | 104 ## |
105 ## @item 3: The algorithm stagnated, i.e., the absolute value of the | 105 ## @item 3: The algorithm stagnated, i.e., the absolute value of the |
106 ## difference between the current iteration @var{x} and the previous is less | 106 ## difference between the current iteration @var{x} and the previous is less |
107 ## than @code{eps * norm (@var{x},2)}. | 107 ## than @code{eps * norm (@var{x},2)}. |
108 ## | 108 ## |
109 ## @item 4: The algorithm can't continue due to a division by zero. | 109 ## @item 4: The algorithm could not continue because intermediate values |
110 ## became too small or too large for reliable computation. | |
110 ## @end itemize | 111 ## @end itemize |
111 ## | 112 ## |
112 ## @item | 113 ## @item |
113 ## @var{relres} is the ratio of the final residual to its initial value, | 114 ## @var{relres} is the ratio of the final residual to its initial value, |
114 ## measured in the Euclidean norm. | 115 ## measured in the Euclidean norm. |
269 end_try_catch | 270 end_try_catch |
270 | 271 |
271 while ((flag != 2) && (iter < maxit) && (resvec(iter+1) >= norm_b * tol)) | 272 while ((flag != 2) && (iter < maxit) && (resvec(iter+1) >= norm_b * tol)) |
272 v = Afun (p, "notransp", varargin{:}); | 273 v = Afun (p, "notransp", varargin{:}); |
273 prod_qv = q' * v; | 274 prod_qv = q' * v; |
274 if (prod_qv == 0) | 275 alpha = (s0' * prec_r0); |
276 if (abs (prod_qv) <= eps * abs (alpha)) | |
275 flag = 4; | 277 flag = 4; |
276 break | 278 break |
277 endif | 279 endif |
278 alpha = (s0' * prec_r0) / prod_qv; | 280 alpha ./= prod_qv; |
279 x += alpha * p; | 281 x += alpha * p; |
280 prod_rs = (s0' * prec_r0); # Product between r0 and s0 | 282 prod_rs = (s0' * prec_r0); # Product between r0 and s0 |
281 r0 -= alpha * v; | 283 r0 -= alpha * v; |
282 s0 -= conj (alpha) * Afun (q, "transp", varargin{:}); | 284 s0 -= conj (alpha) * Afun (q, "transp", varargin{:}); |
283 prec_r0 = M1fun (r0, "notransp", varargin{:}); | 285 prec_r0 = M1fun (r0, "notransp", varargin{:}); |
284 prec_s0 = s0; | 286 prec_s0 = s0; |
285 prec_r0 = M2fun (prec_r0, "notransp", varargin{:}); | 287 prec_r0 = M2fun (prec_r0, "notransp", varargin{:}); |
288 beta = s0' * prec_r0; | |
289 if (abs (prod_rs) <= abs (beta)) | |
290 flag = 4; | |
291 break; | |
292 endif | |
293 beta ./= prod_rs; | |
286 prec_s0 = M2fun (prec_s0, "transp", varargin{:}); | 294 prec_s0 = M2fun (prec_s0, "transp", varargin{:}); |
287 prec_s0 = M1fun (prec_s0, "transp", varargin{:}); | 295 prec_s0 = M1fun (prec_s0, "transp", varargin{:}); |
288 iter += 1; | 296 iter += 1; |
289 resvec(iter+1) = norm (r0); | 297 resvec(iter+1) = norm (r0); |
290 if (resvec(iter+1) <= resvec(iter_min+1)) | 298 if (resvec(iter+1) <= resvec(iter_min+1)) |
293 endif | 301 endif |
294 if (norm (x - x_pr) <= norm (x) * eps) | 302 if (norm (x - x_pr) <= norm (x) * eps) |
295 flag = 3; | 303 flag = 3; |
296 break; | 304 break; |
297 endif | 305 endif |
298 if (prod_rs == 0) | |
299 flag = 4; | |
300 break; | |
301 endif | |
302 beta = (s0' * prec_r0) / prod_rs; | |
303 p = prec_r0 + beta*p; | 306 p = prec_r0 + beta*p; |
304 q = prec_s0 + conj (beta) * q; | 307 q = prec_s0 + conj (beta) * q; |
305 endwhile | 308 endwhile |
306 resvec = resvec(1:iter+1,1); | 309 resvec = resvec(1:iter+1,1); |
307 | 310 |