Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Matrices/multprec_complex_linear_solvers.adb, Revision 1.1
1.1 ! maekawa 1: with Multprec_Complex_Numbers; use Multprec_Complex_Numbers;
! 2:
! 3: package body Multprec_Complex_Linear_Solvers is
! 4:
! 5: -- AUXLILIARIES :
! 6:
! 7: function dconjg ( x : Complex_Number ) return Complex_Number is
! 8:
! 9: -- DESCRIPTION :
! 10: -- Returns the complex conjugate of x.
! 11:
! 12: res : Complex_Number;
! 13: re : Floating_Number := REAL_PART(x);
! 14: im : Floating_Number := IMAG_PART(x);
! 15:
! 16: begin
! 17: Min(im);
! 18: res := Create(re,im);
! 19: Clear(re); Clear(im);
! 20: return res;
! 21: end dconjg;
! 22:
! 23: function csign ( x,y : Complex_Number ) return Complex_Number is
! 24:
! 25: -- DESCRIPTION :
! 26: -- Returns |x|*y/|y|.
! 27:
! 28: res : Complex_Number;
! 29: fltacc : Floating_Number;
! 30: cmpacc : Complex_Number;
! 31:
! 32: begin
! 33: fltacc := AbsVal(x);
! 34: res := Create(fltacc);
! 35: Clear(fltacc);
! 36: Mul(res,y);
! 37: fltacc := AbsVal(y);
! 38: cmpacc := Create(fltacc);
! 39: Div(res,cmpacc);
! 40: Clear(fltacc);
! 41: Clear(cmpacc);
! 42: return res;
! 43: end csign;
! 44:
! 45: function Inverse_Abs_Sum ( z : Vector ) return Floating_Number is
! 46:
! 47: -- DESCRIPTION :
! 48: -- Returns the reciprocal of the sum of the absolute values in z.
! 49:
! 50: res,sum,acc : Floating_Number;
! 51:
! 52: begin
! 53: sum := Create(0);
! 54: for i in z'range loop
! 55: acc := AbsVal(z(i));
! 56: Add(sum,acc);
! 57: Clear(acc);
! 58: end loop;
! 59: res := Create(1);
! 60: Div(res,sum);
! 61: Clear(sum);
! 62: return res;
! 63: end Inverse_Abs_Sum;
! 64:
! 65: -- TARGET ROUTINES :
! 66:
! 67: procedure Scale ( a : in out Matrix; b : in out Vector ) is
! 68:
! 69: fac : Complex_Number;
! 70:
! 71: function Maximum ( a : in Matrix; i : in integer ) return Complex_Number is
! 72:
! 73: res : integer := a'first(2);
! 74: max : Floating_Number := AbsVal(a(i,res));
! 75: tmp : Floating_Number;
! 76:
! 77: begin
! 78: for j in a'first(2)+1..a'last(2) loop
! 79: tmp := AbsVal(a(i,j));
! 80: if tmp > max
! 81: then max := tmp; res := j;
! 82: end if;
! 83: end loop;
! 84: return a(i,res);
! 85: end Maximum;
! 86:
! 87: procedure Divide ( a : in out Matrix; b : in out Vector;
! 88: i : in integer; fac : in Complex_Number ) is
! 89: begin
! 90: for j in a'range(2) loop
! 91: a(i,j) := a(i,j)/fac;
! 92: end loop;
! 93: b(i) := b(i)/fac;
! 94: end Divide;
! 95:
! 96: begin
! 97: for i in a'range(1) loop
! 98: fac := Maximum(a,i);
! 99: Divide(a,b,i,fac);
! 100: end loop;
! 101: end Scale;
! 102:
! 103: -- TARGET ROUTINES :
! 104:
! 105: procedure lufac ( a : in out Matrix; n : in integer;
! 106: ipvt : out Standard_Natural_Vectors.Vector;
! 107: info : out natural ) is
! 108:
! 109: kp1,l,nm1 : integer;
! 110: smax,fltacc : Floating_Number;
! 111: temp,cmpacc : Complex_Number;
! 112:
! 113: begin
! 114: info := 0;
! 115: nm1 := n - 1;
! 116: if nm1 >= 1
! 117: then for k in 1..nm1 loop
! 118: kp1 := k + 1;
! 119: l := k;
! 120: smax := AbsVal(a(k,k)); -- find the pivot index l
! 121: for i in kp1..n loop
! 122: fltacc := AbsVal(a(i,k));
! 123: if fltacc > smax
! 124: then l := i;
! 125: Copy(fltacc,smax);
! 126: end if;
! 127: Clear(fltacc);
! 128: end loop;
! 129: ipvt(k) := l;
! 130: if Equal(smax,0.0) -- this column is already triangularized
! 131: then info := k;
! 132: else if l /= k -- interchange if necessary
! 133: then Copy(a(l,k),temp);
! 134: Copy(a(k,k),a(l,k));
! 135: Copy(temp,a(k,k)); Clear(temp);
! 136: end if;
! 137: cmpacc := Create(1); -- compute multipliers
! 138: Div(cmpacc,a(k,k));
! 139: Min(cmpacc);
! 140: for i in kp1..n loop
! 141: Mul(a(i,k),cmpacc);
! 142: end loop;
! 143: Clear(cmpacc);
! 144: for j in kp1..n loop -- row elimination
! 145: Copy(a(l,j),temp);
! 146: if l /= k
! 147: then Copy(a(k,j),a(l,j));
! 148: Copy(temp,a(k,j));
! 149: end if;
! 150: for i in kp1..n loop
! 151: cmpacc := temp*a(i,k);
! 152: Add(a(i,j),cmpacc);
! 153: Clear(cmpacc);
! 154: end loop;
! 155: end loop;
! 156: Clear(temp);
! 157: end if;
! 158: Clear(smax);
! 159: end loop;
! 160: end if;
! 161: ipvt(n) := n;
! 162: fltacc := AbsVal(a(n,n));
! 163: if Equal(fltacc,0.0)
! 164: then info := n;
! 165: end if;
! 166: Clear(fltacc);
! 167: end lufac;
! 168:
! 169: procedure lufco ( a : in out Matrix; n : in integer;
! 170: ipvt : out Standard_Natural_Vectors.Vector;
! 171: rcond : out Floating_Number ) is
! 172:
! 173: -- NOTE :
! 174: -- rcond = 1/(norm(a)*(estimate of norm(inverse(a))))
! 175: -- estimate = norm(z)/norm(y) where a*z = y and ctrans(a)*y = e.
! 176: -- ctrans(a) is the conjugate transpose of a.
! 177: -- The components of e are chosen to cause maximum local
! 178: -- growth in teh elements of w where ctrans(u)*w = e.
! 179: -- The vectors are frequently rescaled to avoid overflow.
! 180:
! 181: z : Multprec_Complex_Vectors.Vector(1..n);
! 182: info,kb,kp1,l : integer;
! 183: s,sm,sum,anorm,ynorm,fltacc1,fltacc2 : Floating_Number;
! 184: ek,t,wk,wkm,cmpacc1,cmpacc2 : Complex_Number;
! 185: ipvtt : Standard_Natural_Vectors.Vector(1..n);
! 186:
! 187: begin
! 188: anorm := Create(0); -- compute 1-norm of a
! 189: for j in 1..n loop
! 190: sum := Create(0);
! 191: for i in 1..n loop
! 192: fltacc1 := AbsVal(a(i,j));
! 193: Add(sum,fltacc1);
! 194: Clear(fltacc1);
! 195: end loop;
! 196: if sum > anorm
! 197: then Copy(sum,anorm);
! 198: end if;
! 199: Clear(sum);
! 200: end loop;
! 201: lufac(a,n,ipvtt,info); -- factor
! 202: ipvt := ipvtt;
! 203: ek := Create(1); -- solve ctrans(u)*w = e
! 204: for j in 1..n loop
! 205: z(j) := Create(0);
! 206: end loop;
! 207: for k in 1..n loop
! 208: fltacc1 := AbsVal(z(k));
! 209: if not Equal(fltacc1,0.0)
! 210: then cmpacc1 := -z(k);
! 211: Clear(ek);
! 212: ek := csign(ek,cmpacc1);
! 213: Clear(cmpacc1);
! 214: end if;
! 215: Clear(fltacc1);
! 216: cmpacc1 := ek - z(k);
! 217: fltacc1 := AbsVal(cmpacc1);
! 218: Clear(cmpacc1);
! 219: fltacc2 := AbsVal(a(k,k));
! 220: if fltacc1 > fltacc2
! 221: then s := fltacc2/fltacc1;
! 222: cmpacc1 := Create(s);
! 223: Mul(z,cmpacc1);
! 224: Mul(ek,cmpacc1);
! 225: Clear(cmpacc1);
! 226: Clear(s);
! 227: end if;
! 228: Clear(fltacc1); Clear(fltacc2);
! 229: Clear(wk); wk := ek - z(k);
! 230: Clear(wkm); wkm := ek + z(k);
! 231: Min(wkm);
! 232: s := AbsVal(wk);
! 233: sm := AbsVal(wkm);
! 234: fltacc1 := AbsVal(a(k,k));
! 235: if Equal(fltacc1,0.0)
! 236: then Clear(wk); wk := Create(1);
! 237: Clear(wkm); wkm := Create(1);
! 238: else cmpacc1 := dconjg(a(k,k));
! 239: Div(wk,cmpacc1);
! 240: Div(wkm,cmpacc1);
! 241: Clear(cmpacc1);
! 242: end if;
! 243: Clear(fltacc1);
! 244: kp1 := k + 1;
! 245: if kp1 <= n
! 246: then for j in kp1..n loop
! 247: cmpacc2 := dconjg(a(k,j));
! 248: cmpacc1 := wkm*cmpacc2;
! 249: Add(cmpacc1,z(j));
! 250: fltacc1 := AbsVal(cmpacc1);
! 251: Add(sm,fltacc1);
! 252: Clear(fltacc1);
! 253: Clear(cmpacc1);
! 254: cmpacc1 := wk*cmpacc2;
! 255: Add(z(j),cmpacc1);
! 256: Clear(cmpacc1);
! 257: Clear(cmpacc2);
! 258: fltacc1 := AbsVal(z(j));
! 259: Add(s,fltacc1);
! 260: Clear(fltacc1);
! 261: end loop;
! 262: if s < sm
! 263: then t := wkm - wk;
! 264: Copy(wkm,wk);
! 265: for j in kp1..n loop
! 266: cmpacc1 := t*dconjg(a(k,j));
! 267: Add(z(j),cmpacc1);
! 268: Clear(cmpacc1);
! 269: end loop;
! 270: Clear(t);
! 271: end if;
! 272: end if;
! 273: Copy(wk,z(k));
! 274: end loop;
! 275: s := Inverse_Abs_Sum(z);
! 276: cmpacc1 := Create(s);
! 277: Mul(z,cmpacc1);
! 278: Clear(cmpacc1);
! 279: Clear(s);
! 280: for k in 1..n loop -- solve ctrans(l)*y = w
! 281: kb := n+1-k;
! 282: if kb < n
! 283: then t := Create(0);
! 284: for i in (kb+1)..n loop
! 285: cmpacc1 := dconjg(a(i,kb))*z(i);
! 286: Add(t,cmpacc1);
! 287: Clear(cmpacc1);
! 288: end loop;
! 289: Add(z(kb),t);
! 290: end if;
! 291: fltacc1 := AbsVal(z(kb));
! 292: if fltacc1 > 1.0
! 293: then s := Create(1);
! 294: Div(s,fltacc1);
! 295: cmpacc1 := Create(s);
! 296: Mul(z,cmpacc1);
! 297: Clear(cmpacc1);
! 298: Clear(s);
! 299: end if;
! 300: Clear(fltacc1);
! 301: l := ipvtt(kb);
! 302: if l /= kb
! 303: then Copy(z(l),t);
! 304: Copy(z(kb),z(l));
! 305: Copy(t,z(kb));
! 306: Clear(t);
! 307: end if;
! 308: end loop;
! 309: s := Inverse_Abs_Sum(z);
! 310: cmpacc1 := Create(s);
! 311: Clear(s);
! 312: Mul(z,cmpacc1);
! 313: Clear(cmpacc1);
! 314: ynorm := Create(1);
! 315: for k in 1..n loop -- solve l*v = y
! 316: l := ipvtt(k);
! 317: if l /= k
! 318: then Copy(z(l),t);
! 319: Copy(z(k),z(l));
! 320: Copy(t,z(k));
! 321: else Copy(z(l),t);
! 322: end if;
! 323: if k < n
! 324: then for i in (k+1)..n loop
! 325: cmpacc1 := t*a(i,k);
! 326: Add(z(i),cmpacc1);
! 327: Clear(cmpacc1);
! 328: end loop;
! 329: end if;
! 330: Clear(t);
! 331: fltacc1 := AbsVal(z(k));
! 332: if fltacc1 > 1.0
! 333: then s := Create(1);
! 334: Div(s,fltacc1);
! 335: cmpacc1 := Create(s);
! 336: Mul(z,cmpacc1);
! 337: Clear(cmpacc1);
! 338: Mul(ynorm,s);
! 339: Clear(s);
! 340: end if;
! 341: Clear(fltacc1);
! 342: end loop;
! 343: s := Inverse_Abs_Sum(z);
! 344: cmpacc1 := Create(s);
! 345: Mul(z,cmpacc1);
! 346: Clear(cmpacc1);
! 347: Mul(ynorm,s);
! 348: Clear(s);
! 349: for k in 1..n loop -- solve u*z = v
! 350: kb := n+1-k;
! 351: fltacc1 := AbsVal(z(kb));
! 352: fltacc2 := AbsVal(a(kb,kb));
! 353: if fltacc1 > fltacc2
! 354: then s := fltacc2/fltacc1;
! 355: cmpacc1 := Create(s);
! 356: Mul(z,cmpacc1);
! 357: Mul(ynorm,s);
! 358: Clear(s);
! 359: end if;
! 360: if Equal(fltacc2,0.0)
! 361: then Clear(z(kb));
! 362: z(kb) := Create(1);
! 363: else Div(z(kb),a(kb,kb));
! 364: end if;
! 365: Clear(fltacc1);
! 366: Clear(fltacc2);
! 367: t := -z(kb);
! 368: for i in 1..(kb-1) loop
! 369: cmpacc1 := t*a(i,kb);
! 370: Add(z(i),cmpacc1);
! 371: Clear(cmpacc1);
! 372: end loop;
! 373: Clear(t);
! 374: end loop;
! 375: s := Inverse_Abs_Sum(z); -- make znorm = 1.0
! 376: cmpacc1 := Create(s);
! 377: Mul(z,cmpacc1);
! 378: Clear(cmpacc1);
! 379: Mul(ynorm,s);
! 380: if Equal(anorm,0.0)
! 381: then rcond := Create(0);
! 382: else rcond := ynorm/anorm;
! 383: end if;
! 384: Clear(ynorm); Clear(s); Clear(sm);
! 385: Clear(ek); Clear(t); Clear(wk); Clear(wkm);
! 386: Clear(z);
! 387: end lufco;
! 388:
! 389: procedure lusolve ( a : in Matrix; n : in integer;
! 390: ipvt : in Standard_Natural_Vectors.Vector;
! 391: b : in out Vector ) is
! 392:
! 393: l,nm1,kb : integer;
! 394: temp,acc : Complex_Number;
! 395:
! 396: begin
! 397: nm1 := n-1;
! 398: if nm1 >= 1 -- solve l*y = b
! 399: then for k in 1..nm1 loop
! 400: l := ipvt(k);
! 401: Copy(b(l),temp);
! 402: if l /= k
! 403: then Copy(b(k),b(l));
! 404: Copy(temp,b(k));
! 405: end if;
! 406: for i in (k+1)..n loop
! 407: acc := temp*a(i,k);
! 408: Add(b(i),acc);
! 409: Clear(acc);
! 410: end loop;
! 411: Clear(temp);
! 412: end loop;
! 413: end if;
! 414: for k in 1..n loop -- solve u*x = y
! 415: kb := n+1-k;
! 416: Div(b(kb),a(kb,kb));
! 417: temp := -b(kb);
! 418: for j in 1..(kb-1) loop
! 419: acc := temp*a(j,kb);
! 420: Add(b(j),acc);
! 421: Clear(acc);
! 422: end loop;
! 423: Clear(temp);
! 424: end loop;
! 425: end lusolve;
! 426:
! 427: procedure Triangulate ( a : in out Matrix; n,m : in integer ) is
! 428:
! 429: max,cbs : Floating_Number;
! 430: temp : Complex_Number;
! 431: pivot,k,kcolumn : integer;
! 432:
! 433: begin
! 434: k := 1;
! 435: kcolumn := 1;
! 436: while (k <= n) and (kcolumn <= m) loop
! 437: max := Create(0); -- find pivot
! 438: pivot := 0;
! 439: for l in k..n loop
! 440: cbs := AbsVal(a(l,kcolumn));
! 441: if cbs > max
! 442: then max := cbs;
! 443: pivot := l;
! 444: end if;
! 445: end loop;
! 446: if pivot = 0
! 447: then kcolumn := kcolumn + 1;
! 448: else if pivot /= k -- interchange if necessary
! 449: then for i in 1..m loop
! 450: temp := a(pivot,i);
! 451: a(pivot,i) := a(k,i);
! 452: a(k,i) := temp;
! 453: end loop;
! 454: end if;
! 455: for j in (kcolumn+1)..m loop -- triangulate a
! 456: a(k,j) := a(k,j) / a(k,kcolumn);
! 457: end loop;
! 458: a(k,kcolumn) := Create(1);
! 459: for i in (k+1)..n loop
! 460: for j in (kcolumn+1)..m loop
! 461: a(i,j) := a(i,j) - a(i,kcolumn) * a(k,j);
! 462: end loop;
! 463: a(i,kcolumn) := Create(0);
! 464: end loop;
! 465: k := k + 1;
! 466: kcolumn := kcolumn + 1;
! 467: end if;
! 468: end loop;
! 469: end Triangulate;
! 470:
! 471: procedure Diagonalize ( a : in out Matrix; n,m : in integer ) is
! 472:
! 473: max : Floating_Number;
! 474: temp : Complex_Number;
! 475: pivot,k,kcolumn : integer;
! 476:
! 477: begin
! 478: k := 1;
! 479: kcolumn := 1;
! 480: while (k <= n) and (kcolumn <= m) loop
! 481: max := Create(0); -- find pivot
! 482: for l in k..n loop
! 483: if AbsVal(a(l,kcolumn)) > max
! 484: then max := AbsVal(a(l,kcolumn));
! 485: pivot := l;
! 486: end if;
! 487: end loop;
! 488: if Equal(max,0.0)
! 489: then kcolumn := kcolumn + 1;
! 490: else if pivot /= k -- interchange if necessary
! 491: then for i in 1..m loop
! 492: temp := a(pivot,i);
! 493: a(pivot,i) := a(k,i);
! 494: a(k,i) := temp;
! 495: end loop;
! 496: end if;
! 497: for j in (kcolumn+1)..m loop -- diagonalize a
! 498: a(k,j) := a(k,j) / a(k,kcolumn);
! 499: end loop;
! 500: a(k,kcolumn) := Create(1);
! 501: for i in 1..(k-1) loop
! 502: for j in (kcolumn+1)..m loop
! 503: a(i,j) := a(i,j) - a(i,kcolumn) * a(k,j);
! 504: end loop;
! 505: end loop;
! 506: for i in (k+1)..n loop
! 507: for j in (kcolumn+1)..m loop
! 508: a(i,j) := a(i,j) - a(i,kcolumn) * a(k,j);
! 509: end loop;
! 510: end loop;
! 511: for j in 1..(k-1) loop
! 512: a(j,kcolumn) := Create(0);
! 513: end loop;
! 514: for j in (k+1)..n loop
! 515: a(j,kcolumn) := Create(0);
! 516: end loop;
! 517: k := k + 1;
! 518: kcolumn := kcolumn + 1;
! 519: end if;
! 520: end loop;
! 521: end Diagonalize;
! 522:
! 523: end Multprec_Complex_Linear_Solvers;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>