Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Matrices/standard_complex_linear_solvers.adb, Revision 1.1.1.1
1.1 maekawa 1: with Standard_Complex_Numbers; use Standard_Complex_Numbers;
2:
3: package body Standard_Complex_Linear_Solvers is
4:
5: -- AUXLILIARIES :
6:
7: function cabs ( c : Complex_Number ) return double_float is
8: begin
9: return (ABS(REAL_PART(c)) + ABS(IMAG_PART(c)));
10: end cabs;
11:
12: function dconjg ( x : Complex_Number ) return Complex_Number is
13: begin
14: return Create(REAL_PART(x),-IMAG_PART(x));
15: end dconjg;
16:
17: function csign ( x,y : Complex_Number ) return Complex_Number is
18: begin
19: return (Create(cabs(x)) * y / Create(cabs(y)));
20: end csign;
21:
22: -- TARGET ROUTINES :
23:
24: procedure Scale ( a : in out Matrix; b : in out Vector ) is
25:
26: fac : Complex_Number;
27:
28: function Maximum ( a : in Matrix; i : in integer ) return Complex_Number is
29:
30: res : integer := a'first(2);
31: max : double_float := cabs(a(i,res));
32: tmp : double_float;
33:
34: begin
35: for j in a'first(2)+1..a'last(2) loop
36: tmp := cabs(a(i,j));
37: if tmp > max
38: then max := tmp; res := j;
39: end if;
40: end loop;
41: return a(i,res);
42: end Maximum;
43:
44: procedure Divide ( a : in out Matrix; b : in out Vector;
45: i : in integer; fac : in Complex_Number ) is
46: begin
47: for j in a'range(2) loop
48: a(i,j) := a(i,j)/fac;
49: end loop;
50: b(i) := b(i)/fac;
51: end Divide;
52:
53: begin
54: for i in a'range(1) loop
55: fac := Maximum(a,i);
56: Divide(a,b,i,fac);
57: end loop;
58: end Scale;
59:
60: -- TARGET ROUTINES :
61:
62: procedure lufac ( a : in out Matrix; n : in integer;
63: ipvt : out Standard_Natural_Vectors.Vector;
64: info : out natural ) is
65:
66: kp1,l,nm1 : integer;
67: smax : double_float;
68: temp : Complex_Number;
69:
70: begin
71: info := 0;
72: nm1 := n - 1;
73: if nm1 >= 1
74: then for k in 1..nm1 loop
75: kp1 := k + 1;
76:
77: -- find the pivot index l
78:
79: l := k; smax := cabs(a(k,k)); --modulus(a(k,k));
80: for i in kp1..n loop
81: if cabs(a(i,k)) > smax --modulus(a(i,k)) > smax
82: then l := i;
83: smax := cabs(a(i,k)); --modulus(a(i,k));
84: end if;
85: end loop;
86: ipvt(k) := l;
87:
88: if smax = 0.0
89: then -- this column is already triangularized
90: info := k;
91: else
92:
93: -- interchange if necessary
94:
95: if l /= k
96: then temp := a(l,k);
97: a(l,k) := a(k,k);
98: a(k,k) := temp;
99: end if;
100:
101: -- compute multipliers
102:
103: temp := -Create(1.0)/a(k,k);
104: for i in kp1..n loop
105: a(i,k) := temp * a(i,k);
106: end loop;
107:
108: -- row elimination with column indexing
109:
110: for j in kp1..n loop
111: temp := a(l,j);
112: if l /= k
113: then a(l,j) := a(k,j);
114: a(k,j) := temp;
115: end if;
116: for i in kp1..n loop
117: a(i,j) := a(i,j) + temp * a(i,k);
118: end loop;
119: end loop;
120:
121: end if;
122: end loop;
123: end if;
124: ipvt(n) := n;
125: if AbsVal(a(n,n)) = 0.0
126: then info := n;
127: end if;
128: end lufac;
129:
130: procedure lufco ( a : in out Matrix; n : in integer;
131: ipvt : out Standard_Natural_Vectors.Vector;
132: rcond : out double_float ) is
133:
134: -- NOTE :
135: -- rcond = 1/(norm(a)*(estimate of norm(inverse(a))))
136: -- estimate = norm(z)/norm(y) where a*z = y and ctrans(a)*y = e.
137: -- ctrans(a) is the conjugate transpose of a.
138: -- The components of e are chosen to cause maximum local
139: -- growth in teh elements of w where ctrans(u)*w = e.
140: -- The vectors are frequently rescaled to avoid overflow.
141:
142: z : Standard_Complex_Vectors.Vector(1..n);
143: info,kb,kp1,l : integer;
144: s,sm,sum,anorm,ynorm : double_float;
145: ek,t,wk,wkm : Complex_Number;
146: ipvtt : Standard_Natural_Vectors.Vector(1..n);
147:
148: begin
149: anorm := 0.0; -- compute 1-norm of a
150: for j in 1..n loop
151: sum := 0.0;
152: for i in 1..n loop
153: sum := sum + cabs(a(i,j));
154: end loop;
155: if sum > anorm
156: then anorm := sum;
157: end if;
158: end loop;
159: lufac(a,n,ipvtt,info); -- factor
160: for i in 1..n loop
161: ipvt(i) := ipvtt(i);
162: end loop;
163: ek := Create(1.0); -- solve ctrans(u)*w = e
164: for j in 1..n loop
165: z(j) := Create(0.0);
166: end loop;
167: for k in 1..n loop
168: if cabs(z(k)) /= 0.0
169: then ek := csign(ek,-z(k));
170: end if;
171: if cabs(ek-z(k)) > cabs(a(k,k))
172: then s := cabs(a(k,k))/cabs(ek-z(k));
173: z := Create(s) * z;
174: ek := Create(s) * ek;
175: end if;
176: wk := ek - z(k);
177: wkm := -ek - z(k);
178: s := cabs(wk);
179: sm := cabs(wkm);
180: if cabs(a(k,k)) = 0.0
181: then wk := Create(1.0);
182: wkm := Create(1.0);
183: else wk := wk / dconjg(a(k,k));
184: wkm := wkm / dconjg(a(k,k));
185: end if;
186: kp1 := k + 1;
187: if kp1 <= n
188: then for j in kp1..n loop
189: sm := sm + cabs(z(j)+wkm*dconjg(a(k,j)));
190: z(j) := z(j) + wk*dconjg(a(k,j));
191: s := s + cabs(z(j));
192: end loop;
193: if s < sm
194: then t := wkm - wk;
195: wk := wkm;
196: for j in kp1..n loop
197: z(j) := z(j) + t*dconjg(a(k,j));
198: end loop;
199: end if;
200: end if;
201: z(k) := wk;
202: end loop;
203: sum := 0.0;
204: for i in 1..n loop
205: sum := sum + cabs(z(i));
206: end loop;
207: s := 1.0 / sum;
208: z := Create(s) * z;
209: for k in 1..n loop -- solve ctrans(l)*y = w
210: kb := n+1-k;
211: if kb < n
212: then t := Create(0.0);
213: for i in (kb+1)..n loop
214: t := t + dconjg(a(i,kb))*z(i);
215: end loop;
216: z(kb) := z(kb) + t;
217: end if;
218: if cabs(z(kb)) > 1.0
219: then s := 1.0 / cabs(z(kb));
220: z := Create(s) * z;
221: end if;
222: l := ipvtt(kb);
223: t := z(l);
224: z(l) := z(kb);
225: z(kb) := t;
226: end loop;
227: sum := 0.0;
228: for i in 1..n loop
229: sum := sum + cabs(z(i));
230: end loop;
231: s := 1.0 / sum;
232: z := Create(s) * z;
233: ynorm := 1.0;
234: for k in 1..n loop -- solve l*v = y
235: l := ipvtt(k);
236: t := z(l);
237: z(l) := z(k);
238: z(k) := t;
239: if k < n
240: then for i in (k+1)..n loop
241: z(i) := z(i) + t * a(i,k);
242: end loop;
243: end if;
244: if cabs(z(k)) > 1.0
245: then s := 1.0 / cabs(z(k));
246: z := Create(s) * z;
247: ynorm := s * ynorm;
248: end if;
249: end loop;
250: sum := 0.0;
251: for i in 1..n loop
252: sum := sum + cabs(z(i));
253: end loop;
254: s := 1.0 / sum;
255: z := Create(s) * z;
256: ynorm := s * ynorm;
257: for k in 1..n loop -- solve u*z = v
258: kb := n+1-k;
259: if cabs(z(kb)) > cabs(a(kb,kb))
260: then s := cabs(a(kb,kb)) / cabs(z(kb));
261: z := Create(s) * z;
262: ynorm := s * ynorm;
263: end if;
264: if cabs(a(kb,kb)) = 0.0
265: then z(kb) := Create(1.0);
266: else z(kb) := z(kb) / a(kb,kb);
267: end if;
268: t := -z(kb);
269: for i in 1..(kb-1) loop
270: z(i) := z(i) + t * a(i,kb);
271: end loop;
272: end loop;
273: sum := 0.0; -- make znorm = 1.0
274: for i in 1..n loop
275: sum := sum + cabs(z(i));
276: end loop;
277: s := 1.0 / sum;
278: z := Create(s) * z;
279: ynorm := s * ynorm;
280: if anorm = 0.0
281: then rcond := 0.0;
282: else rcond := ynorm/anorm;
283: end if;
284: end lufco;
285:
286: procedure lusolve ( a : in Matrix; n : in integer;
287: ipvt : in Standard_Natural_Vectors.Vector;
288: b : in out Vector ) is
289:
290: l,nm1,kb : integer;
291: temp : Complex_Number;
292:
293: begin
294: nm1 := n-1;
295: if nm1 >= 1 -- solve l*y = b
296: then for k in 1..nm1 loop
297: l := ipvt(k);
298: temp := b(l);
299: if l /= k
300: then b(l) := b(k);
301: b(k) := temp;
302: end if;
303: for i in (k+1)..n loop
304: b(i) := b(i) + temp * a(i,k);
305: end loop;
306: end loop;
307: end if;
308: for k in 1..n loop -- solve u*x = y
309: kb := n+1-k;
310: b(kb) := b(kb) / a(kb,kb);
311: temp := -b(kb);
312: for j in 1..(kb-1) loop
313: b(j) := b(j) + temp * a(j,kb);
314: end loop;
315: end loop;
316: end lusolve;
317:
318: procedure Triangulate ( a : in out Matrix; n,m : in integer ) is
319:
320: max,cbs : double_float;
321: temp : Complex_Number;
322: pivot,k,kcolumn : integer;
323: tol : constant double_float := 10.0**(-10);
324:
325: begin
326: k := 1;
327: kcolumn := 1;
328: while (k <= n) and (kcolumn <= m) loop
329: max := 0.0; -- find pivot
330: pivot := 0;
331: for l in k..n loop
332: cbs := cabs(a(l,kcolumn));
333: if (cbs > tol) and then (cbs > max)
334: then max := cbs;
335: pivot := l;
336: end if;
337: end loop;
338: if pivot = 0
339: then kcolumn := kcolumn + 1;
340: else if pivot /= k -- interchange if necessary
341: then for i in 1..m loop
342: temp := a(pivot,i);
343: a(pivot,i) := a(k,i);
344: a(k,i) := temp;
345: end loop;
346: end if;
347: for j in (kcolumn+1)..m loop -- triangulate a
348: a(k,j) := a(k,j) / a(k,kcolumn);
349: end loop;
350: a(k,kcolumn) := Create(1.0);
351: for i in (k+1)..n loop
352: for j in (kcolumn+1)..m loop
353: a(i,j) := a(i,j) - a(i,kcolumn) * a(k,j);
354: end loop;
355: a(i,kcolumn) := Create(0.0);
356: end loop;
357: k := k + 1;
358: kcolumn := kcolumn + 1;
359: end if;
360: end loop;
361: end Triangulate;
362:
363: procedure Diagonalize ( a : in out Matrix; n,m : in integer ) is
364:
365: max : double_float;
366: temp : Complex_Number;
367: pivot,k,kcolumn : integer;
368:
369: begin
370: k := 1;
371: kcolumn := 1;
372: while (k <= n) and (kcolumn <= m) loop
373: max := 0.0; -- find pivot
374: for l in k..n loop
375: if cabs(a(l,kcolumn)) > max
376: then max := cabs(a(l,kcolumn));
377: pivot := l;
378: end if;
379: end loop;
380: if max = 0.0
381: then kcolumn := kcolumn + 1;
382: else if pivot /= k -- interchange if necessary
383: then for i in 1..m loop
384: temp := a(pivot,i);
385: a(pivot,i) := a(k,i);
386: a(k,i) := temp;
387: end loop;
388: end if;
389: for j in (kcolumn+1)..m loop -- diagonalize a
390: a(k,j) := a(k,j) / a(k,kcolumn);
391: end loop;
392: a(k,kcolumn) := Create(1.0);
393: for i in 1..(k-1) loop
394: for j in (kcolumn+1)..m loop
395: a(i,j) := a(i,j) - a(i,kcolumn) * a(k,j);
396: end loop;
397: end loop;
398: for i in (k+1)..n loop
399: for j in (kcolumn+1)..m loop
400: a(i,j) := a(i,j) - a(i,kcolumn) * a(k,j);
401: end loop;
402: end loop;
403: for j in 1..(k-1) loop
404: a(j,kcolumn) := Create(0.0);
405: end loop;
406: for j in (k+1)..n loop
407: a(j,kcolumn) := Create(0.0);
408: end loop;
409: k := k + 1;
410: kcolumn := kcolumn + 1;
411: end if;
412: end loop;
413: end Diagonalize;
414:
415: end Standard_Complex_Linear_Solvers;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>