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