Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Polynomials/generic_polynomial_functions.adb, Revision 1.1.1.1
1.1 maekawa 1: with unchecked_deallocation;
2: with Standard_Natural_Vectors;
3: with Standard_Natural_Matrices; use Standard_Natural_Matrices;
4:
5: package body Generic_Polynomial_Functions is
6:
7: -- DATA STRUCTURES :
8:
9: type kind is (coefficient,polynomial);
10: type Poly_Rec ( k : kind := coefficient ) is record
11: case k is
12: when coefficient => c : number;
13: when polynomial => p : Eval_Poly;
14: end case;
15: end record;
16: type Coeff_Poly_Rec ( k : kind := coefficient ) is record
17: case k is
18: when coefficient => c : integer;
19: when polynomial => p : Eval_Coeff_Poly;
20: end case;
21: end record;
22:
23: type Eval_Poly_Rep is array(integer range <>) of Poly_Rec;
24: type Eval_Coeff_Poly_Rep is array(integer range <>) of Coeff_Poly_Rec;
25:
26: procedure free is new unchecked_deallocation(Eval_Poly_Rep,Eval_Poly);
27: procedure free is
28: new unchecked_deallocation(Eval_Coeff_Poly_Rep,Eval_Coeff_Poly);
29:
30: -- AUXILIARY OPERATIONS :
31:
32: function Convert ( c : number; n : natural ) return natural is
33:
34: -- DESCRIPTION :
35: -- Returns the corresponding value for c, when it lies in 1..n,
36: -- otherwise 0 is returned.
37:
38: begin
39: for i in 1..n loop
40: if c = Create(i)
41: then return i;
42: end if;
43: end loop;
44: return 0;
45: end Convert;
46:
47: function Head_Term ( p : Poly ) return Term is
48:
49: -- DESCRIPTION :
50: -- Returns the leading term of the polynomial.
51:
52: res : Term;
53:
54: procedure Scan_Term ( t : in Term; continue : out boolean ) is
55: begin
56: res := t;
57: continue := false;
58: end Scan_Term;
59: procedure Scan_Terms is new Visiting_Iterator(Scan_Term);
60:
61: begin
62: Scan_Terms(p);
63: return res;
64: end Head_Term;
65:
66: procedure Initialize ( evpr : in out Eval_Poly_Rep ) is
67: begin
68: for i in evpr'range loop
69: declare
70: nullpr : Poly_Rec(polynomial);
71: begin
72: nullpr.p := null;
73: evpr(i) := nullpr;
74: end;
75: end loop;
76: end Initialize;
77:
78: procedure Initialize ( evpr : in out Eval_Coeff_Poly_Rep ) is
79: begin
80: for i in evpr'range loop
81: declare
82: nullpr : Coeff_Poly_Rec(polynomial);
83: begin
84: nullpr.p := null;
85: evpr(i) := nullpr;
86: end;
87: end loop;
88: end Initialize;
89:
90: procedure Initialize ( p : in Poly; cff : out Vector; deg : out Matrix ) is
91:
92: -- DESCRIPTION :
93: -- Returns a vector/matrix representation of the polynomial p.
94: -- Starts filling in backwards, since the highest degrees are in front
95: -- of the list. This could reduce the sorting time later.
96:
97: ind : natural := cff'last+1;
98:
99: procedure Scan_Term ( t : in Term; continue : out boolean ) is
100: begin
101: ind := ind-1;
102: Copy(t.cf,cff(ind));
103: for j in t.dg'range loop
104: deg(ind,j) := t.dg(j);
105: end loop;
106: continue := true;
107: end Scan_Term;
108: procedure Scan_Terms is new Visiting_Iterator(Scan_Term);
109:
110: begin
111: Scan_Terms(p);
112: end Initialize;
113:
114: procedure Swap ( cff : in out Vector; deg : in out Matrix;
115: i,j,k : in natural ) is
116:
117: -- DESCRIPTION :
118: -- Swaps the ith row with the jth row, starting from the kth column.
119:
120: tmpcff : number;
121: tmpdeg : natural;
122:
123: begin
124: Copy(cff(i),tmpcff);
125: Copy(cff(j),cff(i));
126: Copy(tmpcff,cff(j));
127: Clear(tmpcff);
128: for kk in k..deg'last(2) loop
129: tmpdeg := deg(i,kk);
130: deg(i,kk) := deg(j,kk);
131: deg(j,kk) := tmpdeg;
132: end loop;
133: end Swap;
134:
135: procedure Sort ( cff : in out Vector; deg : in out Matrix;
136: i1,i2,k : in natural ) is
137:
138: -- DESCRIPTION :
139: -- Sorts the elements in the kth column of the degree matrix, in
140: -- the range i1..i2. The coefficient vector gets sorted along.
141:
142: ind,min : natural;
143:
144: begin
145: for i in i1..i2 loop -- sort by swapping minimal element
146: min := deg(i,k);
147: ind := i;
148: for j in i+1..i2 loop -- search for minimal element
149: if deg(j,k) < min
150: then min := deg(j,k);
151: ind := j;
152: end if;
153: end loop;
154: if ind /= i -- swap cff and deg
155: then Swap(cff,deg,i,ind,k);
156: end if;
157: end loop;
158: end Sort;
159:
160: procedure Create ( cff : in out Vector; deg : in out Matrix;
161: i1,i2,k : in natural; ep : out Eval_Poly ) is
162:
163: -- DESCRIPTION :
164: -- Returns in ep a nested Horner scheme to evaluate a polynomial given
165: -- in vector/matrix representation with coefficients in cff and degrees
166: -- in deg. The range being considered is i1..i2, from the kth column.
167:
168: -- REQUIRED :
169: -- The entries in the kth column of deg in i1..i2 are sorted
170: -- in increasing order.
171:
172: evpr : Eval_Poly_Rep(0..deg(i2,k));
173: ind,j1,j2 : natural;
174:
175: begin
176: Initialize(evpr);
177: if k = deg'last(2) -- polynomial in one unknown
178: then for i in i1..i2 loop
179: declare
180: pr : Poly_Rec(Coefficient);
181: begin
182: Copy(cff(i),pr.c);
183: evpr(deg(i,k)) := pr;
184: end;
185: end loop;
186: else ind := i1; -- recursive call
187: while ind <= i2 loop
188: j1 := ind; j2 := ind;
189: while j2 < i2 and then deg(j1,k) = deg(j2+1,k) loop
190: j2 := j2 + 1;
191: end loop;
192: declare
193: pr : Poly_Rec(Polynomial);
194: begin
195: Sort(cff,deg,j1,j2,k+1);
196: Create(cff,deg,j1,j2,k+1,pr.p);
197: evpr(deg(ind,k)) := pr;
198: end;
199: ind := j2+1;
200: end loop;
201: end if;
202: ep := new Eval_Poly_Rep'(evpr);
203: end Create;
204:
205: -- CONSTRUCTORS :
206:
207: function Create ( p : Poly; n,nb : natural; d : integer )
208: return Eval_Coeff_Poly is
209:
210: -- DESCRIPTION :
211: -- An evaluable polynomial is returned for p, with d = Degree(p,x1),
212: -- n = Number_of_Unknowns(p) >= 1 and nb = Number_of_Terms(p).
213: -- The coefficients of p are converted natural numbers.
214:
215: res : Eval_Coeff_Poly;
216: evpr : Eval_Coeff_Poly_Rep(0..d);
217: terms : array(0..d) of Poly := (0..d => Null_Poly);
218:
219: procedure Add_Term1 ( t : in Term; cont : out boolean ) is
220:
221: pr : Coeff_Poly_Rec(coefficient);
222:
223: begin
224: pr.c := Convert(t.cf,nb);
225: evpr(t.dg(t.dg'first)) := pr;
226: cont := true;
227: end Add_Term1;
228: procedure Add_Terms1 is new Visiting_Iterator(Add_Term1);
229:
230: procedure Add_Term ( t : in Term; cont : out boolean ) is
231:
232: nt : Term;
233:
234: begin
235: Copy(t.cf,nt.cf);
236: nt.dg := new Standard_Natural_Vectors.Vector(t.dg'first..t.dg'last-1);
237: for i in nt.dg'range loop
238: nt.dg(i) := t.dg(i+1);
239: end loop;
240: Add(terms(t.dg(t.dg'first)),nt);
241: Clear(nt);
242: cont := true;
243: end Add_Term;
244: procedure Add_Terms is new Visiting_Iterator(Add_Term);
245:
246: begin
247: Initialize(evpr);
248: if n = 1
249: then Add_Terms1(p);
250: else Add_Terms(p);
251: for i in terms'range loop
252: declare
253: pr : Coeff_Poly_Rec(polynomial);
254: ind : integer;
255: begin
256: if terms(i) = Null_Poly
257: then pr.p := null;
258: else ind := Head_Term(terms(i)).dg'first;
259: pr.p := Create(terms(i),n-1,nb,Degree(terms(i),ind));
260: end if;
261: evpr(i) := pr;
262: Clear(terms(i));
263: end;
264: end loop;
265: end if;
266: res := new Eval_Coeff_Poly_Rep'(evpr);
267: return res;
268: end Create;
269:
270: function Create ( p : Poly ) return Eval_Poly is
271:
272: res : Eval_Poly;
273: nbvar : constant natural := Number_of_Unknowns(p);
274: nbtms : constant natural := Number_of_Terms(p);
275: cff : Vector(1..nbtms);
276: deg : Matrix(1..nbtms,1..nbvar);
277:
278: begin
279: if (p = Null_Poly) or else (nbvar = 0)
280: then return null;
281: else Initialize(p,cff,deg);
282: Sort(cff,deg,1,nbtms,1);
283: Create(cff,deg,1,nbtms,1,res);
284: Clear(cff);
285: return res;
286: end if;
287: end Create;
288:
289: function Create ( p : Poly ) return Eval_Coeff_Poly is
290:
291: res : Eval_Coeff_Poly;
292: lp : Poly := Null_Poly;
293: n : constant natural := Number_of_Unknowns(p);
294: nb : constant natural := Number_of_Terms(p);
295: cnt : natural := 0;
296: ind : integer;
297:
298: procedure Label_Term ( t : in Term; cont : out boolean ) is
299:
300: lt : Term;
301:
302: begin
303: cnt := cnt + 1;
304: lt.cf := Create(cnt);
305: lt.dg := new Standard_Natural_Vectors.Vector'(t.dg.all);
306: Add(lp,lt);
307: cont := true;
308: end Label_Term;
309: procedure Label_Terms is new Visiting_Iterator(Label_Term);
310:
311: begin
312: if (p = Null_Poly) or else (nb = 0)
313: then return null;
314: else Label_Terms(p);
315: ind := Head_Term(p).dg'first;
316: res := Create(lp,n,nb,Degree(p,ind));
317: Clear(lp);
318: end if;
319: return res;
320: end Create;
321:
322: procedure Diff ( p : in Poly; i : in integer;
323: cp : out Eval_Coeff_Poly; m : out Vector ) is
324:
325: nb : constant natural := Number_of_Terms(p);
326: n : constant natural := Number_of_Unknowns(p);
327: ind,cnt : integer;
328: dp : Poly := Null_Poly;
329:
330: procedure Diff_Term ( t : in Term; cont : out boolean ) is
331:
332: dt : Term;
333:
334: begin
335: cnt := cnt + 1;
336: if t.dg(i) > 0
337: then dt.cf := Create(cnt);
338: dt.dg := new Standard_Natural_Vectors.Vector'(t.dg.all);
339: m(cnt) := Create(t.dg(i));
340: dt.dg(i) := dt.dg(i) - 1;
341: Add(dp,dt);
342: Clear(dt);
343: else m(cnt) := Create(0);
344: end if;
345: cont := true;
346: end Diff_Term;
347: procedure Diff_Terms is new Visiting_Iterator(Diff_Term);
348:
349: begin
350: cnt := 0;
351: Diff_Terms(p);
352: if dp /= Null_Poly
353: then ind := Head_Term(dp).dg'first;
354: cp := Create(dp,n,nb,Degree(dp,ind));
355: end if;
356: end Diff;
357:
358: function Coeff ( p : Poly ) return Vector is
359:
360: res : Vector(1..Number_of_Terms(p));
361: cnt : natural := 0;
362:
363: procedure Collect_Term ( t : in Term; cont : out boolean ) is
364: begin
365: cnt := cnt + 1;
366: copy(t.cf,res(cnt));
367: cont := true;
368: end Collect_Term;
369: procedure Collect_Terms is new Visiting_Iterator(Collect_Term);
370:
371: begin
372: Collect_Terms(p);
373: return res;
374: end Coeff;
375:
376: -- EVALUATORS :
377:
378: function Eval ( p : Poly; x : number; i : integer ) return Poly is
379:
380: res : Poly := Null_Poly;
381:
382: procedure Eval_Term ( t : in Term; cont : out boolean ) is
383:
384: nt : Term;
385:
386: begin
387: Copy(t.cf,nt.cf);
388: nt.dg := new Standard_Natural_Vectors.Vector(t.dg'first..t.dg'last-1);
389: for j in t.dg'range loop
390: if j < i
391: then nt.dg(j) := t.dg(j);
392: elsif j > i
393: then nt.dg(j-1) := t.dg(j);
394: else for k in 1..t.dg(i) loop
395: Mul(nt.cf,x);
396: end loop;
397: end if;
398: end loop;
399: Add(res,nt);
400: Clear(nt);
401: cont := true;
402: end Eval_Term;
403: procedure Eval_Terms is new Visiting_Iterator(Eval_Term);
404:
405: begin
406: Eval_Terms(p);
407: return res;
408: end Eval;
409:
410: function Eval ( d : Degrees; c : number; x : Vector ) return number is
411:
412: res : number;
413:
414: begin
415: Copy(c,res);
416: for i in d'range loop
417: for j in 1..d(i) loop
418: Mul(res,x(i));
419: end loop;
420: end loop;
421: return res;
422: end Eval;
423:
424: function Eval ( t : Term; x : Vector ) return number is
425: begin
426: return Eval(t.dg,t.cf,x);
427: end Eval;
428:
429: function Eval ( t : Term; c : number; x : Vector ) return number is
430: begin
431: return Eval(t.dg,c,x);
432: end Eval;
433:
434: function Eval ( p : Poly; x : Vector ) return number is
435:
436: res : number;
437:
438: procedure Eval_Term ( t : in Term; cont : out boolean ) is
439:
440: tmp : number := Eval(t,x);
441:
442: begin
443: Add(res,tmp);
444: Clear(tmp);
445: cont := true;
446: end Eval_Term;
447: procedure Eval_Terms is new Visiting_Iterator(Eval_Term);
448:
449: begin
450: Copy(zero,res);
451: Eval_Terms(p);
452: return res;
453: end Eval;
454:
455: function Eval ( p : Poly; c,x : Vector ) return number is
456:
457: res : number;
458: cnt : natural := 0;
459:
460: procedure Eval_Term ( t : in Term; cont : out boolean ) is
461:
462: tmp : number := Eval(t,c(cnt),x);
463:
464: begin
465: cnt := cnt + 1;
466: Add(res,tmp);
467: Clear(tmp);
468: cont := true;
469: end Eval_Term;
470: procedure Eval_Terms is new Visiting_Iterator(Eval_Term);
471:
472: begin
473: Copy(zero,res);
474: Eval_Terms(p);
475: return res;
476: end Eval;
477:
478: function Eval ( vp : Eval_Poly_Rep; x : Vector; i : integer ) return number;
479:
480: function Eval ( vprec : Poly_Rec; x : Vector; i : integer ) return number is
481:
482: res : number;
483:
484: begin
485: if vprec.k = coefficient
486: then Copy(vprec.c,res);
487: elsif vprec.p = null
488: then Copy(zero,res);
489: else res := Eval(vprec.p.all,x,i);
490: end if;
491: return res;
492: end Eval;
493:
494: function Eval ( vp : Eval_Poly_Rep; x : Vector; i : integer )
495: return number is
496:
497: deg : natural := vp'length-1;
498: res : number;
499:
500: begin
501: if deg = 0
502: then res := Eval(vp(0),x,i+1);
503: else res := Eval(vp(deg),x,i+1);
504: for j in reverse 0..(deg-1) loop
505: Mul(res,x(i));
506: if (vp(j).k = coefficient) or else (vp(j).p /= null)
507: then declare
508: temp : number := Eval(vp(j),x,i+1);
509: begin
510: Add(res,temp);
511: Clear(temp);
512: end;
513: end if;
514: end loop;
515: end if;
516: return res;
517: end Eval;
518:
519: function Eval ( p : Eval_Poly; x : Vector ) return number is
520: begin
521: if p = null
522: then declare
523: res : number;
524: begin
525: Copy(zero,res);
526: return res;
527: end;
528: else return Eval(p.all,x,x'first);
529: end if;
530: end Eval;
531:
532: function Eval ( vp : Eval_Coeff_Poly_Rep; c,x : Vector; i : integer )
533: return number;
534:
535: function Eval ( vprec : Coeff_Poly_Rec; c,x : Vector; i : integer )
536: return number is
537:
538: res : number;
539:
540: begin
541: if vprec.k = coefficient
542: then Copy(c(vprec.c),res);
543: else res := Eval(vprec.p.all,c,x,i);
544: end if;
545: return res;
546: end Eval;
547:
548: function Eval ( vp : Eval_Coeff_Poly_Rep; c,x : Vector;
549: i : integer ) return number is
550:
551: deg : natural := vp'length-1;
552: res : number;
553:
554: begin
555: if deg = 0
556: then res := Eval(vp(0),c,x,i+1);
557: else res := Eval(vp(deg),c,x,i+1);
558: for j in reverse 0..(deg-1) loop
559: Mul(res,x(i));
560: if (vp(j).k = coefficient) or else (vp(j).p /= null)
561: then declare
562: temp : number := Eval(vp(j),c,x,i+1);
563: begin
564: Add(res,temp);
565: Clear(temp);
566: end;
567: end if;
568: end loop;
569: end if;
570: return res;
571: end Eval;
572:
573: function Eval ( p : Eval_Coeff_Poly; c,x : Vector ) return number is
574: begin
575: if p = null
576: then declare
577: res : number;
578: begin
579: Copy(zero,res);
580: return res;
581: end;
582: else return Eval(p.all,c,x,x'first);
583: end if;
584: end Eval;
585:
586: -- DESTRUCTORS :
587:
588: procedure Clear ( p : in out Eval_Poly ) is
589: begin
590: if p /= null
591: then declare
592: vp : Eval_Poly_Rep renames p.all;
593: begin
594: for i in vp'range loop
595: if vp(i).k = coefficient
596: then Clear(vp(i).c);
597: else Clear(vp(i).p);
598: end if;
599: end loop;
600: end;
601: free(p);
602: end if;
603: end Clear;
604:
605: procedure Clear ( p : in out Eval_Coeff_Poly ) is
606: begin
607: if p /= null
608: then declare
609: vp : Eval_Coeff_Poly_Rep renames p.all;
610: begin
611: for i in vp'range loop
612: if vp(i).k /= coefficient
613: then Clear(vp(i).p);
614: end if;
615: end loop;
616: end;
617: free(p);
618: end if;
619: end Clear;
620:
621: end Generic_Polynomial_Functions;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>