Annotation of OpenXM_contrib/PHC/Ada/Schubert/localization_posets.adb, Revision 1.1.1.1
1.1 maekawa 1: with unchecked_deallocation;
2:
3: package body Localization_Posets is
4:
5: -- NOTE :
6: -- The field nd.roco is set to -1 if all its children have been created.
7: -- This flag prevents traversing the poset needlessly.
8:
9: -- CREATOR AUXILIARIES :
10:
11: function Max ( i,j : integer ) return integer is
12: begin
13: if i > j
14: then return i;
15: else return j;
16: end if;
17: end Max;
18:
19: function Last_Sibling ( root : Link_to_Node; level : natural )
20: return Link_to_Node is
21:
22: -- DESCRIPTION :
23: -- Returns the last sibling at the level, or the empty pointer if
24: -- there is no node at that level.
25:
26: res : Link_to_Node := null;
27: sibnd : Link_to_Node := Find_Node(root,level);
28:
29: procedure Search_Next ( current : in Link_to_Node ) is
30: begin
31: if current.next_sibling = null
32: then res := current;
33: else Search_Next(current.next_sibling);
34: end if;
35: end Search_Next;
36:
37: begin
38: if sibnd /= null
39: then Search_Next(sibnd);
40: end if;
41: return res;
42: end Last_Sibling;
43:
44: procedure Search_Sibling ( root : in Link_to_Node; nd : in Node;
45: lnd : out Link_to_Node; found : out boolean ) is
46:
47: -- DESCRIPTION :
48: -- Searches the poset for the link to a node with contents nd.
49: -- If found is true, then lnd is a pointer to that node, otherwise
50: -- lnd points to the last sibling, or is empty when there is no
51: -- node at level nd.level.
52:
53: sibnd : Link_to_Node := Find_Node(root,nd.level);
54:
55: procedure Search_Next ( current : in Link_to_Node ) is
56: begin
57: if Equal(current.all,nd)
58: then found := true;
59: lnd := current;
60: elsif current.next_sibling = null
61: then found := false;
62: lnd := current;
63: else Search_Next(current.next_sibling);
64: end if;
65: end Search_Next;
66:
67: begin
68: if sibnd = null
69: then lnd := sibnd; found := false;
70: else Search_Next(sibnd);
71: end if;
72: end Search_Sibling;
73:
74: function Create_Child ( root : Link_to_Node; child : Node; share : boolean )
75: return Link_to_Node is
76:
77: -- DESCRIPTION :
78: -- If the flag share is on, then the poset is searched for a node
79: -- with the same contents as the child. If a sibling is found,
80: -- then the pointer to this sibling is returned, otherwise the link
81: -- on return is a newly created link to node with contents child.
82: -- If the flag share is off, then the link on return points to the
83: -- last sibling node on that level, which has now contents child.
84:
85: res,lnd : Link_to_Node;
86: found : boolean;
87:
88: begin
89: if share
90: then Search_Sibling(root,child,lnd,found);
91: if found
92: then res := lnd;
93: end if;
94: else lnd := Last_Sibling(root,child.level);
95: found := false;
96: end if;
97: if not found
98: then res := new Node'(child);
99: if lnd /= null
100: then lnd.next_sibling := res;
101: res.prev_sibling := lnd;
102: end if;
103: end if;
104: return res;
105: end Create_Child;
106:
107: function Find_Index ( indexed_poset : Array_of_Array_of_Nodes;
108: nd : Link_to_Node ) return natural is
109:
110: -- DESCRIPTION :
111: -- Returns 0 if the node does not occur at indexed_poset(nd.level),
112: -- otherwise returns the index of the node nd in that array.
113: -- Note that the pointers are compared to deal with sharing.
114:
115: begin
116: if indexed_poset(nd.level) /= null
117: then for i in indexed_poset(nd.level)'range loop
118: if indexed_poset(nd.level)(i) = nd
119: then return i;
120: end if;
121: end loop;
122: end if;
123: return 0;
124: end Find_Index;
125:
126: function Labels_of_Children ( indexed_poset : Array_of_Array_of_Nodes;
127: nd : Node ) return Link_to_Vector is
128:
129: -- DESCRIPTION :
130: -- Returns the labels of the children of the current node.
131:
132: -- REQUIRED : indexed_poset(i) created for i < nd.level.
133:
134: res : Link_to_Vector;
135: nbc : constant natural := Number_of_Children(nd);
136: cnt : natural;
137:
138: begin
139: if nbc /= 0
140: then res := new Standard_Natural_Vectors.Vector(1..nbc);
141: cnt := 0;
142: for i in nd.children'range(1) loop
143: for j in nd.children'range(2) loop
144: if nd.children(i,j) /= null
145: then cnt := cnt+1;
146: res(cnt) := Find_Index(indexed_poset,nd.children(i,j));
147: end if;
148: end loop;
149: end loop;
150: end if;
151: return res;
152: end Labels_of_Children;
153:
154: -- SPECIAL TEST FOR GENERAL QUANTUM PIERI RULE :
155:
156: function Special_Plane ( piv : Bracket; lag : natural ) return Bracket is
157:
158: -- DESCRIPTION :
159: -- Returns the indices of the basis vectors that span the special
160: -- m-dimensional plane, defined by the complementary indices in piv.
161:
162: res : Bracket(1..lag-piv'last);
163: ind : natural := 0;
164: found : boolean;
165:
166: begin
167: for i in 1..lag loop
168: found := false;
169: for j in piv'range loop
170: found := (piv(j) = i);
171: exit when found or (piv(j) > i);
172: end loop;
173: if not found
174: then ind := ind+1;
175: res(ind) := i;
176: end if;
177: end loop;
178: return res;
179: end Special_Plane;
180:
181: function Intersect_Spaces ( b1,b2 : Bracket ) return Bracket is
182:
183: -- DESCRIPTION :
184: -- Returns the pivots that are common to both brackets.
185:
186: res : Bracket(b1'range);
187: cnt : natural := 0;
188: found : boolean;
189:
190: begin
191: for i in b1'range loop
192: found := false;
193: for j in b2'range loop
194: found := (b2(j) = b1(i));
195: exit when found;
196: end loop;
197: if found
198: then cnt := cnt+1;
199: res(cnt) := b1(i);
200: end if;
201: end loop;
202: return res(1..cnt);
203: end Intersect_Spaces;
204:
205: function Merging_Top_Pivot_Test ( piv,spc : Bracket ) return boolean is
206:
207: -- DESCRIPTION :
208: -- Returns true if there exists a decreasing sequence of successive
209: -- pivots from piv and spc that has length strictly higher than the
210: -- value of the last pivot used, starting at the tails of the brackets.
211:
212: max : constant natural := piv'last + spc'last;
213: acc : Bracket(1..max) := (1..max => 0);
214: acc_ind : natural := max+1;
215: piv_ind : natural := piv'last;
216: spc_ind : natural := spc'last;
217: stop : boolean;
218:
219: procedure Merge ( fail : out boolean ) is
220:
221: -- DESCRIPTION :
222: -- A consecutive pivot is added to the accumulator;
223: -- failure is reported when such is not possible.
224:
225: procedure Add_from_Pivots is
226: begin
227: if (acc_ind = max+1) or else (piv(piv_ind) >= acc(acc_ind) - 1)
228: then acc_ind := acc_ind-1;
229: acc(acc_ind) := piv(piv_ind);
230: piv_ind := piv_ind-1;
231: fail := false;
232: end if;
233: end Add_from_Pivots;
234:
235: procedure Add_from_Space is
236: begin
237: if (acc_ind = max+1) or else (spc(spc_ind) >= acc(acc_ind) - 1)
238: then acc_ind := acc_ind-1;
239: acc(acc_ind) := spc(spc_ind);
240: spc_ind := spc_ind-1;
241: fail := false;
242: end if;
243: end Add_from_Space;
244:
245: begin
246: fail := true;
247: if piv_ind >= piv'first
248: then if spc_ind >= spc'first
249: then if piv(piv_ind) >= spc(spc_ind)
250: then Add_from_Pivots;
251: else Add_from_Space;
252: end if;
253: else Add_from_Pivots;
254: end if;
255: else if spc_ind >= spc'first
256: then Add_from_Space;
257: end if;
258: end if;
259: end Merge;
260:
261: begin
262: loop
263: Merge(stop);
264: if acc(acc_ind) > (acc_ind + (acc(max) - max))
265: then return true;
266: end if;
267: exit when stop;
268: end loop;
269: return false;
270: end Merging_Top_Pivot_Test;
271:
272: function Merging_Bottom_Pivot_Test ( piv,spc : Bracket ) return boolean is
273:
274: -- DESCRIPTION :
275: -- Returns true if there exists a increasing sequence of successive
276: -- pivots from piv and spc that has length strictly higher than the
277: -- value of the last pivot used, starting at the heads of the brackets.
278:
279: max : constant natural := piv'last + spc'last;
280: acc : Bracket(1..max) := (1..max => 0);
281: acc_ind : natural := 0;
282: piv_ind : natural := piv'first;
283: spc_ind : natural := spc'first;
284: stop : boolean;
285:
286: procedure Merge ( fail : out boolean ) is
287:
288: -- DESCRIPTION :
289: -- A consecutive pivot is added to the accumulator;
290: -- failure is reported when such is not possible.
291:
292: procedure Add_from_Pivots is
293: begin
294: if (acc_ind = 0) or else (piv(piv_ind) <= acc(acc_ind) + 1)
295: then acc_ind := acc_ind+1;
296: acc(acc_ind) := piv(piv_ind);
297: piv_ind := piv_ind+1;
298: fail := false;
299: end if;
300: end Add_from_Pivots;
301:
302: procedure Add_from_Space is
303: begin
304: if (acc_ind = 0) or else (spc(spc_ind) <= acc(acc_ind) + 1)
305: then acc_ind := acc_ind+1;
306: acc(acc_ind) := spc(spc_ind);
307: spc_ind := spc_ind+1;
308: fail := false;
309: end if;
310: end Add_from_Space;
311:
312: begin
313: fail := true;
314: if piv_ind <= piv'last
315: then if spc_ind <= spc'last
316: then if piv(piv_ind) <= spc(spc_ind)
317: then Add_from_Pivots;
318: else Add_from_Space;
319: end if;
320: else Add_from_Pivots;
321: end if;
322: else if spc_ind <= spc'last
323: then Add_from_Space;
324: end if;
325: end if;
326: end Merge;
327:
328: begin
329: loop
330: Merge(stop);
331: if acc(acc_ind) < (acc_ind + (acc(1) - 1))
332: then return true;
333: end if;
334: exit when stop;
335: end loop;
336: return false;
337: end Merging_Bottom_Pivot_Test;
338:
339: -- CREATOR PRIMITIVES I : CHECK IF CREATION IS POSSIBLE AND ALLOWED
340:
341: function Top_Creatable ( nd : Node; n,i : natural ) return boolean is
342:
343: -- DESCRIPTION :
344: -- Returns true if the i-th top pivot can be incremented.
345: -- The n is the dimension of the working space.
346:
347: begin
348: if nd.bottom(i) <= nd.top(i)
349: then return false;
350: elsif i = nd.p
351: then return (nd.top(i) < n);
352: else return (nd.top(i)+1 < nd.top(i+1));
353: end if;
354: end Top_Creatable;
355:
356: function Q_Top_Creatable ( nd : Node; n,lag,i : natural ) return boolean is
357:
358: -- DESCRIPTION :
359: -- Returns true if the i-th top pivot can be incremented.
360: -- The n is the dimension of the working space.
361:
362: begin
363: if not Top_Creatable(nd,n,i)
364: then return false;
365: elsif i < nd.p
366: then return true;
367: else return (nd.top(nd.p) - nd.top(1) + 1 < lag);
368: end if;
369: end Q_Top_Creatable;
370:
371: function Q_Top_Creatable
372: ( nd : Node; modtop,space : Bracket; n,lag,pi,i : natural )
373: return boolean is
374:
375: -- DESCRIPTION :
376: -- This is the quantum analogue to implement the modular bottom-left
377: -- rule as needed in the general intersection case.
378:
379: -- ON ENTRY :
380: -- nd current node;
381: -- modtop top pivots of nd, modulo the lag;
382: -- space generators of the intersection of special m-planes;
383: -- n dimension of the working space;
384: -- lag equals m+p;
385: -- pi index in nd.top, permuted index i used to sort modtop;
386: -- i modtop(i) will be increased to derive the child.
387:
388: child : Bracket(modtop'range) := modtop;
389:
390: begin
391: if not Q_Top_Creatable(nd,n,lag,pi) -- valid pattern ?
392: then return false;
393: else -- valid pattern => valid child, only last entry might be zero
394: child(i) := modtop(i)+1;
395: if i = child'last and child(i) = lag+1
396: then for j in reverse child'first+1..child'last loop
397: child(j) := child(j-1);
398: end loop;
399: child(child'first) := 1;
400: end if;
401: return Merging_Top_Pivot_Test(child,space);
402: end if;
403: end Q_Top_Creatable;
404:
405: function Bottom_Creatable ( nd : Node; i : natural ) return boolean is
406:
407: -- DESCRIPTION :
408: -- Returns true if the i-th bottom pivot can be decremented.
409:
410: begin
411: if nd.bottom(i) <= nd.top(i)
412: then return false;
413: elsif i = 1
414: then return (nd.bottom(i) > 1);
415: else return (nd.bottom(i)-1 > nd.bottom(i-1));
416: end if;
417: end Bottom_Creatable;
418:
419: function Q_Bottom_Creatable ( nd : Node; lag,i : natural ) return boolean is
420:
421: -- DESCRIPTION :
422: -- Returns true if the i-th bottom pivot can be decremented and if
423: -- the spacing between first and last bottom pivot will remain < lag.
424:
425: begin
426: if not Bottom_Creatable(nd,i)
427: then return false;
428: elsif i > 1
429: then return true;
430: else return (nd.bottom(nd.p) - nd.bottom(1) + 1 < lag);
431: end if;
432: end Q_Bottom_Creatable;
433:
434: function Q_Bottom_Creatable
435: ( nd : Node; modbot,space : Bracket; lag,pi,i : natural )
436: return boolean is
437:
438: -- DESCRIPTION :
439: -- This is the quantum analogue to implement the modular bottom-left
440: -- rule as needed in the general intersection case.
441:
442: -- ON ENTRY :
443: -- nd current node;
444: -- modbot bottom pivots of nd, modulo the lag;
445: -- space generators of the intersection of special m-planes;
446: -- lag equals m+p;
447: -- pi index in nd.bottom, permuted index i used to sort modbot;
448: -- i modbot(i) will be decreased to derive the child.
449:
450: child : Bracket(modbot'range) := modbot;
451:
452: begin
453: if not Q_Bottom_Creatable(nd,lag,pi) -- valid pattern ?
454: then return false;
455: else -- valid pattern => valid child, only 1st entry might be zero
456: child(i) := modbot(i)-1;
457: if i = 1 and child(i) = 0
458: then for j in child'first..child'last-1 loop
459: child(j) := child(j+1);
460: end loop;
461: child(child'last) := lag;
462: end if;
463: return Merging_Bottom_Pivot_Test(child,space);
464: end if;
465: end Q_Bottom_Creatable;
466:
467: function Top_Bottom_Creatable ( nd : Node; n,i,j : natural )
468: return boolean is
469:
470: -- DESCRIPTION :
471: -- Returns true if the i-th top pivot can be incremented and if
472: -- the j-th bottom pivot can be decremented.
473:
474: begin
475: if not Top_Creatable(nd,n,i)
476: then return false;
477: elsif not Bottom_Creatable(nd,j)
478: then return false;
479: elsif i /= j
480: then return true;
481: else return (nd.bottom(i) - nd.top(i) > 1);
482: end if;
483: end Top_Bottom_Creatable;
484:
485: function Q_Top_Bottom_Creatable ( nd : Node; n,lag,i,j : natural )
486: return boolean is
487:
488: -- DESCRIPTION :
489: -- Returns true if the i-th top pivot can be incremented and if
490: -- the j-th bottom pivot can be decremented.
491:
492: begin
493: if not Q_Top_Creatable(nd,n,lag,i)
494: then return false;
495: elsif not Q_Bottom_Creatable(nd,lag,j)
496: then return false;
497: elsif i /= j
498: then return true;
499: else return (nd.bottom(i) - nd.top(i) > 1);
500: end if;
501: end Q_Top_Bottom_Creatable;
502:
503: function Q_Top_Bottom_Creatable
504: ( nd : Node; modtop,topspc,modbot,botspc : Bracket;
505: n,lag,pi,i,pj,j : natural ) return boolean is
506:
507: -- DESCRIPTION :
508: -- Returns true if the i-th top pivot can be incremented and if
509: -- the j-th bottom pivot can be decremented in the general quantum
510: -- Pieri homotopy algorithm.
511:
512: begin
513: if not Q_Top_Creatable(nd,modtop,topspc,n,lag,pi,i)
514: then return false;
515: elsif not Q_Bottom_Creatable(nd,modbot,botspc,lag,pj,j)
516: then return false;
517: elsif pi /= pj
518: then return true;
519: else return (nd.bottom(pi) - nd.top(pi) > 1);
520: end if;
521: end Q_Top_Bottom_Creatable;
522:
523: -- CREATOR PRIMITIVES II : DERIVE CHILD FROM NODE
524:
525: procedure Create_Top_Child ( root,nd : in out Link_to_Node;
526: i : in natural; share : in boolean ) is
527:
528: -- DESCRIPTION :
529: -- Creates a child of the given node by incrementing the i-th top pivot.
530:
531: child : Node(nd.p);
532:
533: begin
534: child.level := nd.level-1;
535: child.roco := 0;
536: child.bottom := nd.bottom;
537: child.top := nd.top;
538: child.top(i) := nd.top(i)+1;
539: nd.children(i,0) := Create_Child(root,child,share);
540: end Create_Top_Child;
541:
542: procedure Create_Bottom_Child ( root,nd : in out Link_to_Node;
543: i : in natural; share : in boolean ) is
544:
545: -- DESCRIPTION :
546: -- Creates a child of the node nd by decrementing the i-th bottom pivot.
547:
548: child : Node(nd.p);
549:
550: begin
551: child.level := nd.level-1;
552: child.roco := 0;
553: child.bottom := nd.bottom;
554: child.top := nd.top;
555: child.bottom(i) := nd.bottom(i)-1;
556: nd.children(0,i) := Create_Child(root,child,share);
557: end Create_Bottom_Child;
558:
559: procedure Create_Top_Bottom_Child
560: ( root,nd : in out Link_to_Node;
561: i,j : in natural; share : in boolean ) is
562:
563: -- DESCRIPTION :
564: -- Creates a child of the node nd by incrementing the i-th top pivot
565: -- and decrementing the i-th bottom pivot.
566:
567: child : Node(nd.p);
568:
569: begin
570: child.level := nd.level-2;
571: child.roco := 0;
572: child.top := nd.top;
573: child.top(i) := nd.top(i)+1;
574: child.bottom := nd.bottom;
575: child.bottom(j) := nd.bottom(j)-1;
576: nd.children(i,j) := Create_Child(root,child,share);
577: end Create_Top_Bottom_Child;
578:
579: -- CREATOR PRIMITIVES III : TREAT ONE/TWO DEGREE(S) OF FREEDOM
580:
581: procedure Top_Create1 ( root,nd : in out Link_to_Node; n : in natural ) is
582:
583: -- DESCRIPTION :
584: -- Creates new nodes by incrementing the top pivots, bounded by n.
585: -- The levels of the children nodes decrease by one as this is the
586: -- hypersurface case.
587:
588: begin
589: nd.tp := top;
590: for i in nd.top'range loop
591: if Top_Creatable(nd.all,n,i)
592: then Create_Top_Child(root,nd,i,true);
593: end if;
594: end loop;
595: end Top_Create1;
596:
597: procedure Q_Top_Create1 ( root,nd : in out Link_to_Node;
598: n,lag : in natural ) is
599:
600: -- DESCRIPTION :
601: -- Creates new nodes by incrementing the top pivots, for general q,
602: -- where we need the parameters n = dimension of working space
603: -- and lag = m+p, to bound the space between first and last entry.
604:
605: begin
606: nd.tp := top;
607: for i in nd.top'range loop
608: if Q_Top_Creatable(nd.all,n,lag,i)
609: then Create_Top_Child(root,nd,i,true);
610: end if;
611: end loop;
612: end Q_Top_Create1;
613:
614: procedure Top_Create1 ( root,nd : in out Link_to_Node;
615: k,n,c : in natural ) is
616:
617: -- DESCRIPTION :
618: -- Does k steps of the other Top_Create1 taking pivots larger than c.
619: -- This is the general case, for k=1 we have the hypersurface case.
620:
621: share : boolean := (k = 1);
622:
623: begin
624: if k > 0
625: then nd.tp := top;
626: for i in c..nd.top'last loop
627: if Top_Creatable(nd.all,n,i)
628: then Create_Top_Child(root,nd,i,share);
629: if k > 1
630: then Top_Create1(root,nd.children(i,0),k-1,n,i);
631: end if;
632: end if;
633: end loop;
634: end if;
635: end Top_Create1;
636:
637: procedure Q_Top_Create1 ( root,nd : in out Link_to_Node;
638: first : in boolean; space : in Bracket;
639: k,n,lag : in natural ) is
640:
641: -- DESCRIPTION :
642: -- Does k steps in a top-right chain on modular brackets.
643: -- The top-right rule is enforced by the merging pivot test involving
644: -- top pivots and the indices of the vectors that span the space of
645: -- intersection of special m-planes.
646:
647: -- ON ENTRY :
648: -- root root of the poset where the construction started;
649: -- nd current node;
650: -- first if true, then this is the first step in the sequence,
651: -- and the space has yet to be determined;
652: -- space contains generators of the intersection of special m-planes;
653: -- k number of steps still left to do;
654: -- n dimension of the space;
655: -- lag m+p.
656:
657: share : boolean := (k=1);
658: modtop : Bracket(nd.top'range);
659: perm : Standard_Natural_Vectors.Vector(modtop'range);
660: special : Bracket(1..lag-nd.p);
661:
662: procedure Recursive_Top_Create1 ( new_space : in Bracket ) is
663:
664: -- DESCRIPTION :
665: -- Additional layer needed for the determination of the updated space.
666:
667: begin
668: for i in modtop'range loop
669: if Q_Top_Creatable(nd.all,modtop,new_space,n,lag,perm(i),i)
670: then Create_Top_Child(root,nd,perm(i),share);
671: if k > 1
672: then Q_Top_Create1(root,nd.children(perm(i),0),
673: false,new_space,k-1,n,lag);
674: end if;
675: end if;
676: end loop;
677: end Recursive_Top_Create1;
678:
679: begin
680: if k > 0
681: then nd.tp := top;
682: Modulo(nd.top,lag,perm,modtop);
683: special := Special_Plane(modtop,lag);
684: if first
685: then Recursive_Top_Create1(special);
686: else declare
687: int_spc : constant Bracket
688: := Intersect_Spaces(space,special);
689: begin
690: Recursive_Top_Create1(int_spc);
691: end;
692: end if;
693: end if;
694: end Q_Top_Create1;
695:
696: procedure Bottom_Create1 ( root,nd : in out Link_to_Node ) is
697:
698: -- DESCRIPTION :
699: -- Creates new nodes by decrementing the bottom pivots.
700: -- The levels of the children nodes decrease by one as this is
701: -- the hypersurface case.
702:
703: begin
704: nd.tp := bottom;
705: for i in nd.top'range loop
706: if Bottom_Creatable(nd.all,i)
707: then Create_Bottom_Child(root,nd,i,true);
708: end if;
709: end loop;
710: end Bottom_Create1;
711:
712: procedure Q_Bottom_Create1
713: ( root,nd : in out Link_to_Node; lag : in natural ) is
714:
715: -- DESCRIPTION :
716: -- Creates new nodes by decrementing the bottom pivots for general q,
717: -- where the parameter lag > max space between first and last entry.
718:
719: begin
720: nd.tp := bottom;
721: for i in nd.top'range loop
722: if Q_Bottom_Creatable(nd.all,lag,i)
723: then Create_Bottom_Child(root,nd,i,true);
724: end if;
725: end loop;
726: end Q_Bottom_Create1;
727:
728: procedure Bottom_Create1 ( root,nd : in out Link_to_Node;
729: k,c : in natural ) is
730:
731: -- DESCRIPTION :
732: -- Does k steps of the other Bottom_Create1 taking pivots smaller than c.
733: -- This is the general case, for k=1 we have the hypersurface case.
734:
735: share : boolean := (k=1);
736:
737: begin
738: if k > 0
739: then nd.tp := bottom;
740: for i in nd.bottom'first..c loop
741: if Bottom_Creatable(nd.all,i)
742: then Create_Bottom_Child(root,nd,i,share);
743: if k > 1
744: then Bottom_Create1(root,nd.children(0,i),k-1,i);
745: end if;
746: end if;
747: end loop;
748: end if;
749: end Bottom_Create1;
750:
751: procedure Q_Bottom_Create1 ( root,nd : in out Link_to_Node;
752: first : in boolean; space : in Bracket;
753: k,lag : in natural ) is
754:
755: -- DESCRIPTION :
756: -- Does k steps in a bottom-left chain on modular brackets.
757: -- The bottom-left rule is enforced by the merging pivot test involving
758: -- bottom pivots and the indices of the vectors that span the space of
759: -- intersection of special m-planes.
760:
761: -- ON ENTRY :
762: -- root root of the poset where the construction started;
763: -- nd current node;
764: -- first if true, then this is the first step in the sequence,
765: -- and the space has yet to be determined;
766: -- space contains generators of the intersection of special m-planes;
767: -- k number of steps still left to do;
768: -- lag m+p.
769:
770: share : boolean := (k=1);
771: modbot : Bracket(nd.bottom'range);
772: perm : Standard_Natural_Vectors.Vector(modbot'range);
773: special : Bracket(1..lag-nd.p);
774:
775: procedure Recursive_Bottom_Create1 ( new_space : in Bracket ) is
776:
777: -- DESCRIPTION :
778: -- Additional layer needed for the determination of the updated space.
779:
780: begin
781: for i in modbot'range loop
782: if Q_Bottom_Creatable(nd.all,modbot,new_space,lag,perm(i),i)
783: then Create_Bottom_Child(root,nd,perm(i),share);
784: if k > 1
785: then Q_Bottom_Create1(root,nd.children(0,perm(i)),
786: false,new_space,k-1,lag);
787: end if;
788: end if;
789: end loop;
790: end Recursive_Bottom_Create1;
791:
792: begin
793: if k > 0
794: then nd.tp := bottom;
795: Modulo(nd.bottom,lag,perm,modbot);
796: special := Special_Plane(modbot,lag);
797: if first
798: then Recursive_Bottom_Create1(special);
799: else declare
800: int_spc : constant Bracket
801: := Intersect_Spaces(space,special);
802: begin
803: Recursive_Bottom_Create1(int_spc);
804: end;
805: end if;
806: end if;
807: end Q_Bottom_Create1;
808:
809: procedure Top_Bottom_Create1 ( root,nd : in out Link_to_Node;
810: n : in natural ) is
811:
812: -- DESCRIPTION :
813: -- Creates new nodes by incrementing top pivots and decrementing bottom
814: -- pivots, with n the maximal entry in any pivot.
815: -- If no top create is possible, then a bottom create will be done,
816: -- and we have only a bottom create when no top create is possible.
817:
818: nocreate : boolean := true;
819:
820: begin
821: nd.tp := mixed;
822: for i in nd.top'range loop -- first do top+bottom
823: for j in nd.bottom'range loop
824: if Top_Bottom_Creatable(nd.all,n,i,j)
825: then Create_Top_Bottom_Child(root,nd,i,j,true);
826: nocreate := false;
827: end if;
828: end loop;
829: end loop;
830: if nocreate -- no top+bottom create possible
831: then Bottom_Create1(root,nd);
832: if Is_Leaf(nd.all) -- no bottom create possible
833: then Top_Create1(root,nd,n);
834: end if;
835: end if;
836: end Top_Bottom_Create1;
837:
838: procedure Q_Top_Bottom_Create1 ( root,nd : in out Link_to_Node;
839: n,lag : in natural ) is
840:
841: -- DESCRIPTION :
842: -- Creates new nodes by incrementing top pivots and decrementing bottom
843: -- pivots, with n the maximal entry in any pivot.
844: -- If no top create is possible, then a bottom create will be done,
845: -- and we have only a bottom create when no top create is possible.
846:
847: nocreate : boolean := true;
848:
849: begin
850: nd.tp := mixed;
851: for i in nd.top'range loop -- first do top+bottom
852: for j in nd.bottom'range loop
853: if Q_Top_Bottom_Creatable(nd.all,n,lag,i,j)
854: then Create_Top_Bottom_Child(root,nd,i,j,true);
855: nocreate := false;
856: end if;
857: end loop;
858: end loop;
859: if nocreate -- no top+bottom create possible
860: then Q_Bottom_Create1(root,nd,lag);
861: if Is_Leaf(nd.all) -- no bottom create possible
862: then Q_Top_Create1(root,nd,n,lag);
863: end if;
864: end if;
865: end Q_Top_Bottom_Create1;
866:
867: procedure Top_Bottom_Create1 ( root,nd : in out Link_to_Node;
868: k1,k2,n,c1,c2 : in natural ) is
869:
870: -- DESCRIPTION :
871: -- Applies the hypersurface Top_Bottom_Create max(k1,k2) times,
872: -- taking top pivots in c1..p and bottom pivots in 1..c2.
873: -- This is the top-bottom create that takes the codimensions in pairs,
874: -- which allows more possibilities for sharing.
875:
876: share : constant boolean := ((k1=1) and (k2=1));
877:
878: begin
879: if (k1 > 0) and (k2 > 0)
880: then
881: nd.tp := mixed;
882: for i in c1..nd.top'last loop -- first do top+bottom
883: for j in nd.bottom'first..c2 loop
884: if Top_Bottom_Creatable(nd.all,n,i,j)
885: then
886: Create_Top_Bottom_Child(root,nd,i,j,share);
887: if ((k1 > 1) or (k2 > 1))
888: then Top_Bottom_Create1(root,nd.children(i,j),k1-1,k2-1,n,i,j);
889: end if;
890: end if;
891: end loop;
892: end loop;
893: end if;
894: if ((k1 = 0) and (k2 > 0))
895: then Bottom_Create1(root,nd,k2,c2);
896: elsif ((k1 > 0) and (k2 = 0))
897: then Top_Create1(root,nd,k1,n,c1);
898: end if;
899: end Top_Bottom_Create1;
900:
901: procedure Recursive_Top_Bottom_Create
902: ( root,nd : in out Link_to_Node;
903: codim : in Bracket; ind,k1,k2,n,c1,c2 : in natural;
904: hyper : in boolean ) is
905:
906: -- DESCRIPTION :
907: -- Applies the hypersurface Top_Bottom_Create max(k1,k2) times,
908: -- taking top pivots in c1..p and bottom pivots in 1..c2.
909: -- In case k1 and/or k2 are zero, new conditions will be treated.
910:
911: -- ON ENTRY :
912: -- root root of the localization poset;
913: -- nd current node;
914: -- codim list of co-dimension conditions;
915: -- ind index of lowest condition being treated;
916: -- k1 co-dimension condition satisfied decrementing top pivots;
917: -- k2 co-dimension condition satisfied incrementing bottom pivots;
918: -- n dimension of the working space;
919: -- c1 needed to enforce the top-right rule;
920: -- c2 needed to enforce the bottom-left rule;
921: -- hyper indicates whether or not in the hypersurface case.
922:
923: newhyper : boolean;
924:
925: begin
926: if (k1 > 0) and (k2 > 0)
927: then
928: nd.tp := mixed;
929: for i in c1..nd.top'last loop -- first do top+bottom
930: for j in nd.bottom'first..c2 loop
931: if Top_Bottom_Creatable(nd.all,n,i,j)
932: then Create_Top_Bottom_Child(root,nd,i,j,hyper);
933: Recursive_Top_Bottom_Create
934: (root,nd.children(i,j),codim,ind,k1-1,k2-1,n,i,j,false);
935: end if;
936: end loop;
937: end loop;
938: nd.roco := -1;
939: else
940: if ((k1 = 0) and (k2 > 0))
941: then if ind > codim'first
942: then Recursive_Top_Bottom_Create
943: (root,nd,codim,ind-1,codim(ind-1),k2,n,1,c2,false);
944: else Bottom_Create1(root,nd,k2,c2);
945: end if;
946: elsif ((k1 > 0) and (k2 = 0))
947: then if ind > codim'first
948: then Recursive_Top_Bottom_Create
949: (root,nd,codim,ind-1,k1,codim(ind-1),n,c1,nd.p,false);
950: else Top_Create1(root,nd,k1,n,c1);
951: end if;
952: else -- k1 = 0 and k2 = 0
953: if ind > codim'first + 1
954: then newhyper
955: := ((codim(ind-2) = 1) and (codim(ind-1) = 1));
956: Recursive_Top_Bottom_Create
957: (root,nd,codim,ind-2,codim(ind-2),codim(ind-1),n,1,
958: nd.p,newhyper);
959: elsif ind > codim'first
960: then Bottom_Create1(root,nd,codim(ind-1),nd.p);
961: end if;
962: end if;
963: end if;
964: end Recursive_Top_Bottom_Create;
965:
966: procedure Q_Recursive_Top_Bottom_Create
967: ( root,nd : in out Link_to_Node; codim : in Bracket;
968: fsttop : in boolean; topspc : in Bracket;
969: fstbot : in boolean; botspc : in Bracket;
970: ind,k1,k2,n,lag : in natural; hyper : in boolean ) is
971:
972: -- DESCRIPTION :
973: -- Applies the hypersurface Q_Top_Bottom_Create max(k1,k2) times,
974: -- simulating the bottom-left and top-right rules with the modular
975: -- brackets and corresponding spaces.
976:
977: -- ON ENTRY :
978: -- root root of the localization poset;
979: -- nd current node;
980: -- codim list of co-dimension conditions;
981: -- fsttop if true, then first step taken using top pivots;
982: -- topspc intersection of special m-planes for top pivots;
983: -- fstbot if true, then first step taken using bottom pivots;
984: -- botspc intersection of special m-planes for bottom pivots;
985: -- ind index of lowest condition being treated;
986: -- k1 co-dimension condition satisfied decrementing top pivots;
987: -- k2 co-dimension condition satisfied incrementing bottom pivots;
988: -- n dimension of the working space;
989: -- lag space in the poset that is of interest;
990: -- hyper indicates whether or not in the hypersurface case.
991:
992: newhyper : boolean;
993: modtop,modbot : Bracket(1..nd.p);
994: topprm,botprm : Standard_Natural_Vectors.Vector(1..nd.p);
995: top_special,bot_special : Bracket(1..lag-nd.p);
996:
997: procedure Mixed_Create ( new_top_space,new_bot_space : in Bracket ) is
998: begin
999: for i in modtop'range loop
1000: for j in modbot'range loop
1001: if Q_Top_Bottom_Creatable
1002: (nd.all,modtop,new_top_space,modbot,new_bot_space,
1003: n,lag,topprm(i),i,botprm(j),j)
1004: then Create_Top_Bottom_Child(root,nd,topprm(i),botprm(j),hyper);
1005: Q_Recursive_Top_Bottom_Create
1006: (root,nd.children(topprm(i),botprm(j)),codim,
1007: false,new_top_space,false,new_bot_space,
1008: ind,k1-1,k2-1,n,lag,false);
1009: end if;
1010: end loop;
1011: end loop;
1012: nd.roco := -1;
1013: end Mixed_Create;
1014:
1015: begin
1016: if (k1 > 0) and (k2 > 0) -- first do top + bottom
1017: then
1018: nd.tp := mixed;
1019: Modulo(nd.top,lag,topprm,modtop);
1020: top_special := Special_Plane(modtop,lag);
1021: Modulo(nd.bottom,lag,botprm,modbot);
1022: bot_special := Special_Plane(modbot,lag);
1023: if fsttop
1024: then if fstbot
1025: then Mixed_Create(top_special,bot_special);
1026: else declare
1027: int_spc : constant Bracket
1028: := Intersect_Spaces(botspc,bot_special);
1029: begin
1030: Mixed_Create(top_special,int_spc);
1031: end;
1032: end if;
1033: else if fstbot
1034: then declare
1035: int_spc : constant Bracket
1036: := Intersect_Spaces(topspc,top_special);
1037: begin
1038: Mixed_Create(int_spc,bot_special);
1039: end;
1040: else declare
1041: int_top : constant Bracket
1042: := Intersect_Spaces(topspc,top_special);
1043: int_bot : constant Bracket
1044: := Intersect_Spaces(botspc,bot_special);
1045: begin
1046: Mixed_Create(int_top,int_bot);
1047: end;
1048: end if;
1049: end if;
1050: else
1051: if ((k1 = 0) and (k2 > 0))
1052: then if ind > codim'first
1053: then Q_Recursive_Top_Bottom_Create
1054: (root,nd,codim,true,topspc,fstbot,botspc,
1055: ind-1,codim(ind-1),k2,n,lag,false);
1056: else Q_Bottom_Create1(root,nd,fstbot,botspc,k2,lag);
1057: end if;
1058: elsif ((k1 > 0) and (k2 = 0))
1059: then if ind > codim'first
1060: then Q_Recursive_Top_Bottom_Create
1061: (root,nd,codim,fsttop,topspc,true,botspc,
1062: ind-1,k1,codim(ind-1),n,lag,false);
1063: else Q_Top_Create1(root,nd,fsttop,topspc,k1,n,lag);
1064: end if;
1065: else -- k1 = 0 and k2 = 0
1066: if ind > codim'first + 1
1067: then newhyper
1068: := ((codim(ind-2) = 1) and (codim(ind-1) = 1));
1069: Q_Recursive_Top_Bottom_Create
1070: (root,nd,codim,true,topspc,true,botspc,
1071: ind-2,codim(ind-2),codim(ind-1),n,lag,newhyper);
1072: elsif ind > codim'first
1073: then Q_Bottom_Create1
1074: (root,nd,true,botspc,codim(ind-1),lag);
1075: end if;
1076: end if;
1077: end if;
1078: end Q_Recursive_Top_Bottom_Create;
1079:
1080: -- TARGET CREATORS :
1081:
1082: function Trivial_Root ( m,p : natural ) return Node is
1083:
1084: nd : Node(p);
1085:
1086: begin
1087: nd.level := m*p;
1088: nd.roco := 0;
1089: for i in 1..p loop
1090: nd.top(i) := i;
1091: nd.bottom(i) := m+i;
1092: end loop;
1093: return nd;
1094: end Trivial_Root;
1095:
1096: function Trivial_Root ( m,p,q : natural ) return Node is
1097:
1098: nd : Node(p);
1099: last : natural;
1100:
1101: begin
1102: if q = 0
1103: then nd := Trivial_Root(m,p);
1104: else nd := Trivial_Root(m,p,q-1);
1105: nd.level := nd.level + m+p;
1106: last := nd.bottom(1)+m+p;
1107: for i in 1..(p-1) loop
1108: nd.bottom(i) := nd.bottom(i+1);
1109: end loop;
1110: nd.bottom(p) := last;
1111: end if;
1112: return nd;
1113: end Trivial_Root;
1114:
1115: procedure Top_Create ( root : in out Link_to_Node; n : in natural ) is
1116:
1117: procedure Create_Next ( root,nd : in out Link_to_Node ) is
1118: begin
1119: if ((nd.level > 0) and (nd.roco >= 0))
1120: then Top_Create1(root,nd,n);
1121: for i in nd.children'range(1) loop
1122: if nd.children(i,0) /= null
1123: then Create_Next(root,nd.children(i,0));
1124: end if;
1125: end loop;
1126: nd.roco := -1;
1127: end if;
1128: end Create_Next;
1129:
1130: begin
1131: Create_Next(root,root);
1132: end Top_Create;
1133:
1134: procedure Q_Top_Create ( root : in out Link_to_Node; n,lag : in natural ) is
1135:
1136: procedure Create_Next ( root,nd : in out Link_to_Node ) is
1137: begin
1138: if ((nd.level > 0) and (nd.roco >= 0))
1139: then Q_Top_Create1(root,nd,n,lag);
1140: for i in nd.children'range(1) loop
1141: if nd.children(i,0) /= null
1142: then Create_Next(root,nd.children(i,0));
1143: end if;
1144: end loop;
1145: nd.roco := -1;
1146: end if;
1147: end Create_Next;
1148:
1149: begin
1150: Create_Next(root,root);
1151: end Q_Top_Create;
1152:
1153: procedure Top_Create ( root : in out Link_to_Node;
1154: k : in Bracket; n : in natural ) is
1155:
1156: procedure Create ( current : in out Link_to_Node; ind : in natural );
1157:
1158: -- DESCRIPTION :
1159: -- Creates k(ind) levels above the current node.
1160:
1161: procedure Create_Children ( child : in out Link_to_Node;
1162: cnt,ind : in natural ) is
1163:
1164: -- DESCRIPTION :
1165: -- Goes to the topmost child to create, counting down with cnt.
1166:
1167: begin
1168: if cnt = 0
1169: then Create(child,ind);
1170: else for i in child.children'range(1) loop
1171: if child.children(i,0) /= null
1172: then Create_Children(child.children(i,0),cnt-1,ind);
1173: end if;
1174: end loop;
1175: end if;
1176: end Create_Children;
1177:
1178: procedure Create ( current : in out Link_to_Node; ind : in natural ) is
1179: begin
1180: if ((current.level > 0) and (ind <= k'last) and (current.roco >= 0))
1181: then
1182: Top_Create1(root,current,k(ind),n,1);
1183: if ind > k'first
1184: then
1185: for i in current.children'range(1) loop
1186: if current.children(i,0) /= null
1187: then Create_Children(current.children(i,0),k(ind)-1,ind-1);
1188: end if;
1189: end loop;
1190: end if;
1191: current.roco := -1;
1192: end if;
1193: end Create;
1194:
1195: begin
1196: Create(root,k'last);
1197: end Top_Create;
1198:
1199: procedure Q_Top_Create ( root : in out Link_to_Node;
1200: k : in Bracket; n,lag : in natural ) is
1201:
1202: procedure Create ( current : in out Link_to_Node; ind : in natural );
1203:
1204: -- DESCRIPTION :
1205: -- Creates k(ind) levels above the current node.
1206:
1207: procedure Create_Children ( child : in out Link_to_Node;
1208: cnt,ind : in natural ) is
1209:
1210: -- DESCRIPTION :
1211: -- Goes to the topmost child to create, counting down with cnt.
1212:
1213: begin
1214: if cnt = 0
1215: then Create(child,ind);
1216: else for i in child.children'range(1) loop
1217: if child.children(i,0) /= null
1218: then Create_Children(child.children(i,0),cnt-1,ind);
1219: end if;
1220: end loop;
1221: end if;
1222: end Create_Children;
1223:
1224: procedure Create ( current : in out Link_to_Node; ind : in natural ) is
1225:
1226: space : Bracket(1..lag-current.p) := (1..lag-current.p => 0);
1227:
1228: begin
1229: if ((current.level > 0) and (ind <= k'last) and (current.roco >= 0))
1230: then
1231: Q_Top_Create1(root,current,true,space,k(ind),n,lag);
1232: if ind > k'first
1233: then
1234: for i in current.children'range(1) loop
1235: if current.children(i,0) /= null
1236: then Create_Children(current.children(i,0),k(ind)-1,ind-1);
1237: end if;
1238: end loop;
1239: end if;
1240: current.roco := -1;
1241: end if;
1242: end Create;
1243:
1244: begin
1245: Create(root,k'last);
1246: end Q_Top_Create;
1247:
1248: procedure Bottom_Create ( root : in out Link_to_Node ) is
1249:
1250: procedure Create_Next ( root,nd : in out Link_to_Node ) is
1251: begin
1252: if ((nd.level > 0) and (nd.roco >= 0))
1253: then Bottom_Create1(root,nd);
1254: for i in nd.children'range(2) loop
1255: if nd.children(0,i) /= null
1256: then Create_Next(root,nd.children(0,i));
1257: end if;
1258: end loop;
1259: nd.roco := -1;
1260: end if;
1261: end Create_Next;
1262:
1263: begin
1264: Create_Next(root,root);
1265: end Bottom_Create;
1266:
1267: procedure Q_Bottom_Create ( root : in out Link_to_Node; lag : in natural ) is
1268:
1269: procedure Create_Next ( root,nd : in out Link_to_Node ) is
1270: begin
1271: if ((nd.level > 0) and (nd.roco >= 0))
1272: then Q_Bottom_Create1(root,nd,lag);
1273: for i in nd.children'range(2) loop
1274: if nd.children(0,i) /= null
1275: then Create_Next(root,nd.children(0,i));
1276: end if;
1277: end loop;
1278: nd.roco := -1;
1279: end if;
1280: end Create_Next;
1281:
1282: begin
1283: Create_Next(root,root);
1284: end Q_Bottom_Create;
1285:
1286: procedure Bottom_Create ( root : in out Link_to_Node; k : in Bracket ) is
1287:
1288: procedure Create ( current : in out Link_to_Node; ind : in natural );
1289:
1290: -- DESCRIPTION :
1291: -- Creates k(ind) levels above the current node.
1292:
1293: procedure Create_Children ( child : in out Link_to_Node;
1294: cnt,ind : in natural ) is
1295:
1296: -- DESCRIPTION :
1297: -- Goes to the topmost child to create, counting down with cnt.
1298:
1299: begin
1300: if cnt = 0
1301: then Create(child,ind);
1302: else for i in child.children'range(1) loop
1303: if child.children(0,i) /= null
1304: then Create_Children(child.children(0,i),cnt-1,ind);
1305: end if;
1306: end loop;
1307: end if;
1308: end Create_Children;
1309:
1310: procedure Create ( current : in out Link_to_Node; ind : in natural ) is
1311: begin
1312: if ((current.level > 0) and (ind <= k'last) and (current.roco >= 0))
1313: then
1314: Bottom_Create1(root,current,k(ind),current.p);
1315: if ind > k'first
1316: then
1317: for i in current.children'range(1) loop
1318: if current.children(0,i) /= null
1319: then Create_Children(current.children(0,i),k(ind)-1,ind-1);
1320: end if;
1321: end loop;
1322: end if;
1323: current.roco := -1;
1324: end if;
1325: end Create;
1326:
1327: begin
1328: Create(root,k'last);
1329: end Bottom_Create;
1330:
1331: procedure Q_Bottom_Create ( root : in out Link_to_Node; k : in Bracket;
1332: lag : in natural ) is
1333:
1334: procedure Create ( current : in out Link_to_Node; ind : in natural );
1335:
1336: -- DESCRIPTION :
1337: -- Creates k(ind) levels above the current node.
1338:
1339: procedure Create_Children ( child : in out Link_to_Node;
1340: cnt,ind : in natural ) is
1341:
1342: -- DESCRIPTION :
1343: -- Goes to the topmost child to create, counting down with cnt.
1344:
1345: begin
1346: if cnt = 0
1347: then Create(child,ind);
1348: else for i in child.children'range(1) loop
1349: if child.children(0,i) /= null
1350: then Create_Children(child.children(0,i),cnt-1,ind);
1351: end if;
1352: end loop;
1353: end if;
1354: end Create_Children;
1355:
1356: procedure Create ( current : in out Link_to_Node; ind : in natural ) is
1357:
1358: space : Bracket(1..lag-current.p) := (1..lag-current.p => 0);
1359:
1360: begin
1361: if ((current.level > 0) and (ind <= k'last) and (current.roco >= 0))
1362: then
1363: Q_Bottom_Create1(root,current,true,space,k(ind),lag);
1364: if ind > k'first
1365: then
1366: for i in current.children'range(1) loop
1367: if current.children(0,i) /= null
1368: then Create_Children(current.children(0,i),k(ind)-1,ind-1);
1369: end if;
1370: end loop;
1371: end if;
1372: current.roco := -1;
1373: end if;
1374: end Create;
1375:
1376: begin
1377: Create(root,k'last);
1378: end Q_Bottom_Create;
1379:
1380: procedure Top_Bottom_Create ( root : in out Link_to_Node; n : in natural ) is
1381:
1382: procedure Create_Next ( root,nd : in out Link_to_Node ) is
1383: begin
1384: if ((nd.level > 0) and (nd.roco >= 0))
1385: then Top_Bottom_Create1(root,nd,n);
1386: for i in nd.children'range(1) loop
1387: for j in nd.children'range(2) loop
1388: if nd.children(i,j) /= null
1389: then Create_Next(root,nd.children(i,j));
1390: end if;
1391: end loop;
1392: end loop;
1393: nd.roco := -1;
1394: end if;
1395: end Create_Next;
1396:
1397: begin
1398: Create_Next(root,root);
1399: end Top_Bottom_Create;
1400:
1401: procedure Q_Top_Bottom_Create ( root : in out Link_to_Node;
1402: n,lag : in natural ) is
1403:
1404: procedure Create_Next ( root,nd : in out Link_to_Node ) is
1405: begin
1406: if ((nd.level > 0) and (nd.roco >= 0))
1407: then Q_Top_Bottom_Create1(root,nd,n,lag);
1408: for i in nd.children'range(1) loop
1409: for j in nd.children'range(2) loop
1410: if nd.children(i,j) /= null
1411: then Create_Next(root,nd.children(i,j));
1412: end if;
1413: end loop;
1414: end loop;
1415: nd.roco := -1;
1416: end if;
1417: end Create_Next;
1418:
1419: begin
1420: Create_Next(root,root);
1421: end Q_Top_Bottom_Create;
1422:
1423: procedure Old_Top_Bottom_Create ( root : in out Link_to_Node;
1424: k : in Bracket; n : in natural ) is
1425:
1426: -- NOTE :
1427: -- This top-bottom create treats the co-dimension conditions in pairs,
1428: -- which allows more possibilities for sharing.
1429:
1430: procedure Create ( current : in out Link_to_Node; ind : in natural );
1431:
1432: -- DESCRIPTION :
1433: -- Creates k(ind) levels above the current node.
1434:
1435: procedure Create_Children ( child : in out Link_to_Node;
1436: cnt,ind : in natural ) is
1437:
1438: -- DESCRIPTION :
1439: -- Goes to the topmost child to create, counting down with cnt.
1440:
1441: begin
1442: if cnt = 0
1443: then Create(child,ind);
1444: else for i in child.children'range(1) loop
1445: for j in child.children'range(2) loop
1446: if child.children(i,j) /= null
1447: then Create_Children(child.children(i,j),cnt-1,ind);
1448: end if;
1449: end loop;
1450: end loop;
1451: end if;
1452: end Create_Children;
1453:
1454: procedure Create ( current : in out Link_to_Node; ind : in natural ) is
1455:
1456: cnt : natural;
1457:
1458: begin
1459: if ((current.level > 0) and (current.roco >= 0))
1460: then
1461: if ind = k'first
1462: then Bottom_Create1(root,current,k(ind),current.p);
1463: cnt := k(ind);
1464: elsif ind > k'first
1465: then
1466: Top_Bottom_Create1(root,current,k(ind),k(ind-1),n,1,current.p);
1467: cnt := max(k(ind),k(ind-1));
1468: end if;
1469: if ind > k'first-1
1470: then for i in current.children'range(1) loop
1471: for j in current.children'range(2) loop
1472: if current.children(i,j) /= null
1473: then Create_Children(current.children(i,j),cnt-1,ind-2);
1474: end if;
1475: end loop;
1476: end loop;
1477: end if;
1478: current.roco := -1;
1479: end if;
1480: end Create;
1481:
1482: begin
1483: Create(root,k'last);
1484: end Old_Top_Bottom_Create;
1485:
1486: procedure Top_Bottom_Create ( root : in out Link_to_Node;
1487: k : in Bracket; n : in natural ) is
1488:
1489: ind : constant natural := k'last;
1490: hyper : boolean;
1491:
1492: begin
1493: if ind = k'first
1494: then Bottom_Create1(root,root,k(k'last),root.p);
1495: elsif ind > k'first
1496: then hyper := ((k(ind-1) = 1) and (k(ind) = 1));
1497: Recursive_Top_Bottom_Create
1498: (root,root,k,ind-1,k(ind-1),k(ind),n,1,root.p,hyper);
1499: end if;
1500: end Top_Bottom_Create;
1501:
1502: procedure Q_Top_Bottom_Create ( root : in out Link_to_Node;
1503: k : in Bracket; n,lag : in natural ) is
1504:
1505: ind : constant natural := k'last;
1506: hyper : boolean;
1507: space : Bracket(1..lag-root.p) := (1..lag-root.p => 0);
1508:
1509: begin
1510: if ind = k'first
1511: then Q_Bottom_Create1(root,root,true,space,k(k'last),lag);
1512: elsif ind > k'first
1513: then hyper := ((k(ind-1) = 1) and (k(ind) = 1));
1514: Q_Recursive_Top_Bottom_Create
1515: (root,root,k,true,space,true,space,
1516: ind-1,k(ind-1),k(ind),n,lag,hyper);
1517: end if;
1518: end Q_Top_Bottom_Create;
1519:
1520: function Create_Leveled_Poset ( root : Link_to_Node )
1521: return Array_of_Nodes is
1522:
1523: res : Array_of_Nodes(0..root.level);
1524:
1525: begin
1526: for i in res'range loop
1527: res(i) := Find_Node(root,i);
1528: end loop;
1529: return res;
1530: end Create_Leveled_Poset;
1531:
1532: function Create_Indexed_Poset ( poset : Array_of_Nodes )
1533: return Array_of_Array_of_Nodes is
1534:
1535: res : Array_of_Array_of_Nodes(poset'range);
1536: ptr : Link_to_Node;
1537:
1538: begin
1539: for i in poset'range loop
1540: if poset(i) /= null
1541: then res(i) := new Array_of_Nodes(1..Number_of_Siblings(poset(i)));
1542: ptr := poset(i);
1543: for j in res(i)'range loop
1544: res(i)(j) := ptr;
1545: res(i)(j).label := j;
1546: res(i)(j).child_labels := Labels_of_Children(res,ptr.all);
1547: ptr := ptr.next_sibling;
1548: end loop;
1549: end if;
1550: end loop;
1551: return res;
1552: end Create_Indexed_Poset;
1553:
1554: -- SELECTORS :
1555:
1556: function Equal ( nd1,nd2 : Node ) return boolean is
1557: begin
1558: if nd1.level /= nd2.level
1559: then return false;
1560: elsif not Equal(nd1.top,nd2.top)
1561: then return false;
1562: else return Equal(nd1.bottom,nd2.bottom);
1563: end if;
1564: end Equal;
1565:
1566: function Is_Leaf ( nd : Node ) return boolean is
1567: begin
1568: for i in nd.children'range(1) loop
1569: for j in nd.children'range(2) loop
1570: if nd.children(i,j) /= null
1571: then return false;
1572: end if;
1573: end loop;
1574: end loop;
1575: return true;
1576: end Is_Leaf;
1577:
1578: function Find_Node ( root : Link_to_Node; lvl : natural )
1579: return Link_to_Node is
1580:
1581: res,fst : Link_to_Node := null;
1582:
1583: procedure Search_First ( current : in Link_to_Node ) is
1584:
1585: -- DESCRIPTION :
1586: -- Scans the list of previous siblings and sets fst to the node
1587: -- that does not have any previous siblings.
1588:
1589: -- REQUIRED : current /= null.
1590:
1591: begin
1592: if current.prev_sibling = null
1593: then fst := current;
1594: else Search_First(current.prev_sibling);
1595: end if;
1596: end Search_First;
1597:
1598: begin
1599: if root.level = lvl
1600: then res := root;
1601: elsif root.level > lvl
1602: then for i in root.children'range(1) loop
1603: for j in root.children'range(2) loop
1604: if root.children(i,j) /= null
1605: then res := Find_Node(root.children(i,j),lvl);
1606: end if;
1607: exit when (res /= null);
1608: end loop;
1609: exit when (res /= null);
1610: end loop;
1611: end if;
1612: if res = null
1613: then fst := res;
1614: else Search_First(res);
1615: end if;
1616: return fst;
1617: end Find_Node;
1618:
1619: function Number_of_Siblings ( nd : Link_to_Node ) return natural is
1620: begin
1621: if nd = null
1622: then return 0;
1623: else return 1 + Number_of_Siblings(nd.next_sibling);
1624: end if;
1625: end Number_of_Siblings;
1626:
1627: function Number_of_Children ( nd : Node ) return natural is
1628:
1629: cnt : natural := 0;
1630:
1631: begin
1632: for i in nd.children'range(1) loop
1633: for j in nd.children'range(2) loop
1634: if nd.children(i,j) /= null
1635: then cnt := cnt + 1;
1636: end if;
1637: end loop;
1638: end loop;
1639: return cnt;
1640: end Number_of_Children;
1641:
1642: -- ITERATORS :
1643:
1644: procedure Enumerate_Siblings ( nd : in Node ) is
1645:
1646: cont : boolean := true;
1647:
1648: begin
1649: Report(nd,cont);
1650: if cont and nd.next_sibling /= null
1651: then Enumerate_Siblings(nd.next_sibling.all);
1652: end if;
1653: end Enumerate_Siblings;
1654:
1655: procedure Enumerate_Grand_Children ( nd : in Node; k : in positive ) is
1656:
1657: cont : boolean := true;
1658:
1659: procedure Enumerate_Children ( current : in node; l : in positive ) is
1660: begin
1661: for i in current.children'range(1) loop
1662: for j in current.children'range(1) loop
1663: if current.children(i,j) /= null
1664: then if l = 1
1665: then Report(current.children(i,j),cont);
1666: else Enumerate_Children(current.children(i,j).all,l-1);
1667: end if;
1668: end if;
1669: exit when not cont;
1670: end loop;
1671: exit when not cont;
1672: end loop;
1673: end Enumerate_Children;
1674:
1675: begin
1676: Enumerate_Children(nd,k);
1677: end Enumerate_Grand_Children;
1678:
1679: procedure Modify_Siblings ( nd : in out Node ) is
1680:
1681: cont : boolean := true;
1682:
1683: begin
1684: Modify(nd,cont);
1685: if cont and nd.next_sibling /= null
1686: then Modify_Siblings(nd.next_sibling.all);
1687: end if;
1688: end Modify_Siblings;
1689:
1690: -- COMBINATORIAL ROOT COUNTING :
1691:
1692: procedure Count_Roots ( poset : in out Array_of_Nodes ) is
1693:
1694: procedure Initialize ( nd : in out Node; continue : out boolean ) is
1695: begin
1696: nd.roco := 1;
1697: continue := true;
1698: end Initialize;
1699: procedure Initialize_Leaves is new Modify_Siblings(Initialize);
1700:
1701: procedure Add_Children ( nd : in out Node; continue : out boolean ) is
1702: begin
1703: nd.roco := 0;
1704: for i in nd.children'range(1) loop
1705: for j in nd.children'range(2) loop
1706: if nd.children(i,j) /= null
1707: then nd.roco := nd.roco + nd.children(i,j).roco;
1708: end if;
1709: end loop;
1710: end loop;
1711: continue := true;
1712: end Add_Children;
1713: procedure Add_Children_Counts is new Modify_Siblings(Add_Children);
1714:
1715: begin
1716: if poset(0) /= null
1717: then Initialize_Leaves(poset(0).all);
1718: end if;
1719: for i in 1..poset'last loop
1720: if poset(i) /= null
1721: then Add_Children_Counts(poset(i).all);
1722: end if;
1723: end loop;
1724: end Count_Roots;
1725:
1726: function Row_Root_Count_Sum
1727: ( poset : Array_of_Nodes; i : natural ) return natural is
1728:
1729: res : natural := 0;
1730:
1731: procedure Count ( lnd : in Link_to_Node ) is
1732: begin
1733: if lnd /= null
1734: then res := res + lnd.roco;
1735: Count(lnd.next_sibling);
1736: end if;
1737: end Count;
1738:
1739: begin
1740: Count(poset(i));
1741: return res;
1742: end Row_Root_Count_Sum;
1743:
1744: function Root_Count_Sum ( poset : Array_of_Nodes ) return natural is
1745:
1746: res : natural := 0;
1747:
1748: begin
1749: for i in 1..poset'last loop
1750: res := res + Row_Root_Count_Sum(poset,i);
1751: end loop;
1752: return res;
1753: end Root_Count_Sum;
1754:
1755: -- DESTRUCTORS :
1756:
1757: procedure free is new unchecked_deallocation(Node,Link_to_Node);
1758: procedure free is
1759: new unchecked_deallocation(Array_of_Nodes,Link_to_Array_of_Nodes);
1760:
1761: procedure Clear ( nd : in out Node ) is
1762: begin
1763: if nd.next_sibling /= null
1764: then Clear(nd.next_sibling);
1765: end if;
1766: end Clear;
1767:
1768: procedure Clear ( lnd : in out Link_to_Node ) is
1769: begin
1770: if lnd /= null
1771: then Clear(lnd.all);
1772: free(lnd);
1773: end if;
1774: end Clear;
1775:
1776: procedure Clear ( arrnd : in out Array_of_Nodes ) is
1777: begin
1778: for i in arrnd'range loop
1779: Clear(arrnd(i));
1780: end loop;
1781: end Clear;
1782:
1783: procedure Clear ( arrnd : in out Link_to_Array_of_Nodes ) is
1784:
1785: procedure free is
1786: new unchecked_deallocation(Array_of_Nodes,Link_to_Array_of_Nodes);
1787:
1788: begin
1789: if arrnd /= null
1790: then Clear(arrnd.all);
1791: free(arrnd);
1792: end if;
1793: end Clear;
1794:
1795: procedure Clear ( arrnd : in out Array_of_Array_of_Nodes ) is
1796: begin
1797: for i in arrnd'range loop
1798: Clear(arrnd(i));
1799: end loop;
1800: end Clear;
1801:
1802: procedure Clear ( matnd : in out Matrix_of_Nodes ) is
1803: begin
1804: for i in matnd'range(1) loop
1805: for j in matnd'range(2) loop
1806: if matnd(i,j) /= null
1807: then free(matnd(i,j));
1808: end if;
1809: end loop;
1810: end loop;
1811: end Clear;
1812:
1813: end Localization_Posets;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>