# HG changeset patch # User Marco Caliari # Date 1523342364 -7200 # Node ID b3ee0179d7b005a29bea15bc9451e0e0ab85d39c # Parent 8cff7eceee87ffb96f46821e7c47051eb04ed069 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. diff -r 8cff7eceee87 -r b3ee0179d7b0 scripts/sparse/bicg.m --- a/scripts/sparse/bicg.m Mon Apr 09 18:35:45 2018 -0500 +++ b/scripts/sparse/bicg.m Tue Apr 10 08:39:24 2018 +0200 @@ -106,7 +106,8 @@ ## difference between the current iteration @var{x} and the previous is less ## than @code{eps * norm (@var{x},2)}. ## -## @item 4: The algorithm can't continue due to a division by zero. +## @item 4: The algorithm could not continue because intermediate values +## became too small or too large for reliable computation. ## @end itemize ## ## @item @@ -271,11 +272,12 @@ while ((flag != 2) && (iter < maxit) && (resvec(iter+1) >= norm_b * tol)) v = Afun (p, "notransp", varargin{:}); prod_qv = q' * v; - if (prod_qv == 0) + alpha = (s0' * prec_r0); + if (abs (prod_qv) <= eps * abs (alpha)) flag = 4; break endif - alpha = (s0' * prec_r0) / prod_qv; + alpha ./= prod_qv; x += alpha * p; prod_rs = (s0' * prec_r0); # Product between r0 and s0 r0 -= alpha * v; @@ -283,6 +285,12 @@ prec_r0 = M1fun (r0, "notransp", varargin{:}); prec_s0 = s0; prec_r0 = M2fun (prec_r0, "notransp", varargin{:}); + beta = s0' * prec_r0; + if (abs (prod_rs) <= abs (beta)) + flag = 4; + break; + endif + beta ./= prod_rs; prec_s0 = M2fun (prec_s0, "transp", varargin{:}); prec_s0 = M1fun (prec_s0, "transp", varargin{:}); iter += 1; @@ -295,11 +303,6 @@ flag = 3; break; endif - if (prod_rs == 0) - flag = 4; - break; - endif - beta = (s0' * prec_r0) / prod_rs; p = prec_r0 + beta*p; q = prec_s0 + conj (beta) * q; endwhile