1 /*
2
3 This file is part of the Maude 2 interpreter.
4
5 Copyright 1997-2003 SRI International, Menlo Park, CA 94025, USA.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20
21 */
22
23 //
24 // Specialized mergesort algorithm for ACU argument lists.
25 //
26
27 void
mergeSortAndUniquize()28 ACU_DagNode::mergeSortAndUniquize()
29 {
30 int nrArgs = argArray.length();
31 int nrRuns = runsBuffer.length();
32 ArgVec<Pair> mergeBuffer(nrArgs);
33
34 while (nrRuns > 1)
35 {
36 int d = 0;
37 int rd = 0;
38 int i = 0;
39 for (; i < nrRuns - 1; i += 2)
40 {
41 //
42 // Merge runs i and i+1
43 //
44 int p1 = runsBuffer[i];
45 int e1 = runsBuffer[i + 1];
46 int p2 = runsBuffer[i + 1];
47 int e2 = i + 2 < nrRuns ? runsBuffer[i + 2] : nrArgs;
48 runsBuffer[rd++] = d; // save start of merged run we are creating
49 for(;;)
50 {
51 int r = argArray[p1].dagNode->compare(argArray[p2].dagNode);
52 if (r < 0)
53 {
54 mergeBuffer[d++] = argArray[p1++];
55 if (p1 == e1)
56 {
57 p1 = p2;
58 e1 = e2;
59 break;
60 }
61 }
62 else if (r > 0)
63 {
64 mergeBuffer[d++] = argArray[p2++];
65 if (p2 == e2)
66 break;
67 }
68 else
69 {
70 mergeBuffer[d].dagNode = argArray[p1].dagNode;
71 mergeBuffer[d++].multiplicity =
72 argArray[p1++].multiplicity + argArray[p2++].multiplicity;
73 if (p1 == e1)
74 {
75 p1 = p2;
76 e1 = e2;
77 break;
78 }
79 if (p2 == e2)
80 break;
81 }
82 }
83 while (p1 < e1)
84 mergeBuffer[d++] = argArray[p1++];
85 }
86 if (i < nrRuns)
87 {
88 Assert(rd < i, "floor(nrRuns/2) >= nrRuns - 1");
89 runsBuffer[rd++] = d; // Assert guarantees we don't overwrite runsBuffer[i]
90 //
91 // Copy odd run into merge buffer
92 //
93 for (int p = runsBuffer[i]; p < nrArgs; p++)
94 mergeBuffer[d++] = argArray[p];
95 }
96 nrArgs = d;
97 nrRuns = rd;
98 argArray.swap(mergeBuffer);
99 }
100 argArray.contractTo(nrArgs); // merging may have shrunk number of arguments
101 }
102
103 void
sortAndUniquize()104 ACU_DagNode::sortAndUniquize()
105 {
106 //
107 // ACU argument lists tend to have long runs of in order
108 // arguments so we discover these runs first befor running
109 // the mergesort algorithm.
110 //
111 int nrArgs = argArray.length();
112 for (int i = 1; i < nrArgs; i++)
113 {
114 int r = argArray[i - 1].dagNode->compare(argArray[i].dagNode);
115 if (r >= 0)
116 {
117 runsBuffer.contractTo(1);
118 int lastRun = 0;
119 runsBuffer[0] = lastRun;
120 int d = i - 1;
121 for(;;)
122 {
123 if (r == 0)
124 argArray[d].multiplicity += argArray[i].multiplicity;
125 else if (r < 0)
126 argArray[++d] = argArray[i];
127 else
128 {
129 if (lastRun == d) // don't make a run of length 1
130 {
131 Pair t(argArray[d]);
132 argArray[d] = argArray[i];
133 argArray[++d] = t;
134 }
135 else
136 {
137 argArray[++d] = argArray[i];
138 lastRun = d;
139 runsBuffer.append(lastRun);
140 }
141 }
142 if (++i == nrArgs)
143 break;
144 r = argArray[d].dagNode->compare(argArray[i].dagNode);
145 }
146 argArray.contractTo(d + 1);
147 if (runsBuffer.length() > 1)
148 mergeSortAndUniquize();
149 break;
150 }
151 }
152 }
153
154 void
flattenSortAndUniquize(int expansion)155 ACU_DagNode::flattenSortAndUniquize(int expansion)
156 {
157 Symbol* s = symbol();
158 int nrArgs = argArray.length();
159 ArgVec<Pair> newArray(nrArgs + expansion);
160 runsBuffer.contractTo(1);
161 int lastRun = 0;
162 runsBuffer[0] = lastRun;
163 int d = -1; // HACK: should use iterators for everything
164
165 for (int i = 0; i < nrArgs; i++)
166 {
167 DagNode* n = argArray[i].dagNode;
168 if (n->symbol() == s)
169 {
170 //
171 // Need to flatten in subterm.
172 //
173 int m = argArray[i].multiplicity;
174 if (d >= 0)
175 {
176 lastRun = d + 1;
177 runsBuffer.append(lastRun);
178 }
179 ArgVec<Pair>::iterator dest = newArray.begin() + (d + 1);
180
181 if (safeCast(ACU_BaseDagNode*, n)->isTree())
182 {
183 const ACU_Tree& tree = safeCast(ACU_TreeDagNode*, n)->getTree();
184 ACU_FastIter i(tree);
185 do
186 {
187 dest->dagNode = i.getDagNode();
188 dest->multiplicity = m * i.getMultiplicity();
189 ++dest;
190 i.next();
191 }
192 while (i.valid());
193 d += tree.getSize();
194 }
195 else
196 {
197 const ArgVec<Pair>& argArray2 = safeCast(ACU_DagNode*, n)->argArray;
198 ArgVec<Pair>::const_iterator i = argArray2.begin();
199 const ArgVec<Pair>::const_iterator e = argArray2.end();
200 do
201 {
202 dest->dagNode = i->dagNode;
203 dest->multiplicity = m * i->multiplicity;
204 ++dest;
205 ++i;
206 }
207 while (i != e);
208 d += argArray2.length();
209 }
210 }
211 else
212 {
213 if (d >= 0)
214 {
215 int r = newArray[d].dagNode->compare(n);
216 if (r == 0)
217 {
218 newArray[d].multiplicity += argArray[i].multiplicity;
219 continue;
220 }
221 else if (r > 0)
222 {
223 if (lastRun == d) // don't make a run of length 1
224 {
225 newArray[d + 1] = newArray[d];
226 newArray[d] = argArray[i];
227 ++d;
228 continue;
229 }
230 else
231 {
232 lastRun = d + 1;
233 runsBuffer.append(lastRun);
234 }
235 }
236 }
237 newArray[++d] = argArray[i];
238 }
239 }
240 /*
241 cout << " flattenSortAndUniquize() runs buffer: ";
242 for (int i = 0; i < runsBuffer.length(); i++)
243 cout << runsBuffer[i] << ' ';
244 cout << " nrArgs = " << newArray.length() << '\n';
245 */
246 newArray.contractTo(d + 1);
247 argArray.swap(newArray);
248 if (runsBuffer.length() > 1)
249 mergeSortAndUniquize();
250 }
251