Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 64 / 0 / 64
Functions: -% 0 / 1 / 1
Branches: 93.1% 54 / 0 / 58

OMCompiler/Compiler/BackEnd/Sorting.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package Sorting
37 " file: Sorting.mo
38 package: Sorting
39
40 "
41
42 public
43 import BackendDAE;
44
45 protected
46 import BackendDump;
47 import GCExt;
48 import Matching;
49
50 public function Tarjan "author: lochel
51 This sorting algorithm only considers equations e that have a matched variable v with e = ass1[v]."
52 input BackendDAE.AdjacencyMatrix m;
53 input array<Integer> ass1 "eqn := ass1[var]";
54 input Integer N = arrayLength(ass1);
55 output list<list<Integer>> outComponents = {} "eqn indices";
56 protected
57 Integer index = 0;
58 list<Integer> stack = {};
59
60 array<Integer> number, lowlink;
61 array<Boolean> onStack;
62 Integer eqn;
63 algorithm
64 //BackendDump.dumpAdjacencyMatrix(m);
65 //BackendDump.dumpMatchingVars(ass1);
66
67 3482 number := arrayCreate(N, -1);
68 3482 lowlink := arrayCreate(N, -1);
69 3482 onStack := arrayCreate(N, false);
70
71
2/2
✓ Branch 0 taken 3259 times.
✓ Branch 1 taken 223 times.
430876 for var in 1:arrayLength(ass1) loop
72 427394 eqn := ass1[var];
73
4/4
✓ Branch 0 taken 425393 times.
✓ Branch 1 taken 2001 times.
✓ Branch 3 taken 368162 times.
✓ Branch 4 taken 57231 times.
427394 if eqn > 0 and number[eqn] == -1 then
74 368162 (stack, index, outComponents) := StrongConnect(m, ass1, eqn, stack, index, number, lowlink, onStack, outComponents);
75 end if;
76 end for;
77 3482 GCExt.free(number);
78 3482 GCExt.free(lowlink);
79 3482 GCExt.free(onStack);
80
81 3482 outComponents := listReverse(outComponents);
82 end Tarjan;
83
84 protected function StrongConnect "author: lochel"
85 input BackendDAE.AdjacencyMatrix m;
86 input array<Integer> ass1 "eqn := ass1[var]";
87 input Integer eqn;
88 input list<Integer> stack;
89 input Integer index;
90 input array<Integer> number;
91 input array<Integer> lowlink;
92 input array<Boolean> onStack;
93 input list<list<Integer>> inComponents;
94 output list<Integer> outStack = stack;
95 output Integer outIndex = index;
96 output list<list<Integer>> outComponents = inComponents;
97 protected
98 list<tuple<Integer, list<Integer>>> callStack = {} "(eqn, successors left to visit)";
99 list<Integer> SCC, successors = {};
100 Integer current = eqn, eqn2, parent;
101 Boolean entering = true, descended;
102 algorithm
103 while true loop
104
2/2
✓ Branch 0 taken 425393 times.
✓ Branch 1 taken 57231 times.
482624 if entering then
105 entering := false;
106 // Set the depth index for current to the smallest unused index
107 425393 arrayUpdate(number, current, outIndex);
108 425393 arrayUpdate(lowlink, current, outIndex);
109 425393 arrayUpdate(onStack, current, true);
110 425393 outIndex := outIndex + 1;
111 outStack := current::outStack;
112 425393 successors := Matching.incomingEquations(current, m, ass1);
113 end if;
114
115 // Consider successors of current
116 descended := false;
117
2/2
✓ Branch 0 taken 392469 times.
✓ Branch 1 taken 425393 times.
817862 while not listEmpty(successors) loop
118 392469 eqn2::successors := successors;
119
2/2
✓ Branch 1 taken 57231 times.
✓ Branch 2 taken 335238 times.
392469 if number[eqn2] == -1 then
120 // Successor eqn2 has not yet been visited; descend into it
121 57231 callStack := (current, successors)::callStack;
122 current := eqn2;
123 entering := true;
124 descended := true;
125 57231 break;
126 elseif onStack[eqn2] then
127 // Successor eqn2 is in the stack and hence in the current SCC
128 227979 arrayUpdate(lowlink, current, intMin(lowlink[current], number[eqn2]));
129 end if;
130 end while;
131
132
2/2
✓ Branch 0 taken 57231 times.
✓ Branch 1 taken 425393 times.
482624 if not descended then
133 // If current is a root node, pop the stack and generate an SCC
134
2/2
✓ Branch 2 taken 409893 times.
✓ Branch 3 taken 15500 times.
425393 if lowlink[current] == number[current] then
135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 409893 times.
409893 eqn2::outStack := outStack;
136 409893 arrayUpdate(onStack, eqn2, false);
137 SCC := {eqn2};
138
2/2
✓ Branch 0 taken 15500 times.
✓ Branch 1 taken 409893 times.
425393 while current <> eqn2 loop
139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15500 times.
15500 eqn2::outStack := outStack;
140 15500 arrayUpdate(onStack, eqn2, false);
141 SCC := eqn2::SCC;
142 end while;
143 409893 outComponents := MetaModelica.Dangerous.listReverseInPlace(SCC)::outComponents;
144 end if;
145
146
2/2
✓ Branch 0 taken 57231 times.
✓ Branch 1 taken 368162 times.
425393 if listEmpty(callStack) then
147 break;
148 end if;
149 57231 (parent, successors)::callStack := callStack;
150 57231 arrayUpdate(lowlink, parent, intMin(lowlink[parent], lowlink[current]));
151 current := parent;
152 end if;
153 end while;
154 end StrongConnect;
155
156 public function TarjanTransposed "author: lochel
157 This sorting algorithm only considers equations e with ass2[e] > 0."
158 input BackendDAE.AdjacencyMatrixT mT;
159 input array<Integer> ass2 "var := ass2[eqn]";
160 output list<list<Integer>> outComponents = {} "eqn indices";
161 protected
162 Integer index = 0;
163 list<Integer> stack = {};
164
165 array<Integer> number, lowlink;
166 array<Boolean> onStack;
167 Integer N = arrayLength(ass2);
168 algorithm
169 //BackendDump.dumpAdjacencyMatrixT(mT);
170 //BackendDump.dumpMatchingEqns(ass2);
171
172 64085 number := arrayCreate(N, -1);
173 64085 lowlink := arrayCreate(N, -1);
174 64085 onStack := arrayCreate(N, false);
175
176
2/2
✓ Branch 0 taken 3216 times.
✓ Branch 1 taken 60869 times.
729939 for eqn in 1:N loop
177
4/4
✓ Branch 1 taken 327376 times.
✓ Branch 2 taken 338478 times.
✓ Branch 4 taken 326927 times.
✓ Branch 5 taken 449 times.
665854 if number[eqn] == -1 and ass2[eqn] > 0 then
178 326927 (stack, index, outComponents) := StrongConnectTransposed(mT, ass2, eqn, stack, index, number, lowlink, onStack, outComponents);
179 end if;
180 end for;
181 end TarjanTransposed;
182
183 protected function StrongConnectTransposed "author: lochel"
184 input BackendDAE.AdjacencyMatrixT mT;
185 input array<Integer> ass2 "var := ass2[eqn]";
186 input Integer eqn;
187 input list<Integer> stack;
188 input Integer index;
189 input array<Integer> number;
190 input array<Integer> lowlink;
191 input array<Boolean> onStack;
192 input list<list<Integer>> inComponents;
193 output list<Integer> outStack = stack;
194 output Integer outIndex = index;
195 output list<list<Integer>> outComponents = inComponents;
196 protected
197 list<tuple<Integer, list<Integer>>> callStack = {} "(eqn, successors left to visit)";
198 list<Integer> SCC, successors = {};
199 Integer current = eqn, var, eqn2, parent;
200 Boolean entering = true, descended;
201 algorithm
202 while true loop
203
2/2
✓ Branch 0 taken 665405 times.
✓ Branch 1 taken 338478 times.
1003883 if entering then
204 entering := false;
205 // Set the depth index for current to the smallest unused index
206 665405 arrayUpdate(number, current, outIndex);
207 665405 arrayUpdate(lowlink, current, outIndex);
208 665405 arrayUpdate(onStack, current, true);
209 665405 outIndex := outIndex + 1;
210 outStack := current::outStack;
211
212 665405 var := ass2[current] "get the variable that is solved in given equation";
213
10/10
✓ Branch 0 taken 665277 times.
✓ Branch 1 taken 128 times.
✓ Branch 3 taken 2650883 times.
✓ Branch 4 taken 106951 times.
✓ Branch 5 taken 665239 times.
✓ Branch 6 taken 1985644 times.
✓ Branch 7 taken 2757834 times.
✓ Branch 8 taken 665277 times.
✓ Branch 9 taken 1985644 times.
✓ Branch 10 taken 665277 times.
3423239 successors := if var > 0 then list(e for e guard(e > 0 and e <> current) in mT[var]) else {};
214 end if;
215
216 // Consider successors of current
217 descended := false;
218
2/2
✓ Branch 0 taken 1985644 times.
✓ Branch 1 taken 665405 times.
2651049 while not listEmpty(successors) loop
219 1985644 eqn2::successors := successors;
220
2/2
✓ Branch 1 taken 338478 times.
✓ Branch 2 taken 1647166 times.
1985644 if number[eqn2] == -1 then
221 // Successor eqn2 has not yet been visited; descend into it
222 338478 callStack := (current, successors)::callStack;
223 current := eqn2;
224 entering := true;
225 descended := true;
226 338478 break;
227 elseif onStack[eqn2] then
228 // Successor eqn2 is in the stack and hence in the current SCC
229 1027481 arrayUpdate(lowlink, current, intMin(lowlink[current], number[eqn2]));
230 end if;
231 end while;
232
233
2/2
✓ Branch 0 taken 338478 times.
✓ Branch 1 taken 665405 times.
1003883 if not descended then
234 // If current is a root node, pop the stack and generate an SCC
235
2/2
✓ Branch 2 taken 532426 times.
✓ Branch 3 taken 132979 times.
665405 if lowlink[current] == number[current] then
236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 532426 times.
532426 eqn2::outStack := outStack;
237 532426 arrayUpdate(onStack, eqn2, false);
238 SCC := {eqn2};
239
2/2
✓ Branch 0 taken 132979 times.
✓ Branch 1 taken 532426 times.
665405 while current <> eqn2 loop
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132979 times.
132979 eqn2::outStack := outStack;
241 132979 arrayUpdate(onStack, eqn2, false);
242 SCC := eqn2::SCC;
243 end while;
244 532426 outComponents := MetaModelica.Dangerous.listReverseInPlace(SCC)::outComponents;
245 end if;
246
247
2/2
✓ Branch 0 taken 338478 times.
✓ Branch 1 taken 326927 times.
665405 if listEmpty(callStack) then
248 break;
249 end if;
250 338478 (parent, successors)::callStack := callStack;
251 338478 arrayUpdate(lowlink, parent, intMin(lowlink[parent], lowlink[current]));
252 current := parent;
253 end if;
254 end while;
255 end StrongConnectTransposed;
256
257 annotation(__OpenModelica_Interface="backend");
258 end Sorting;
259