Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Matrices/multprec_complex_linear_solvers.adb, Revision 1.1.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>