Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 78.3% 54 / 0 / 69
Functions: -% 0 / 1 / 1
Branches: 60.2% 59 / 0 / 98

OMCompiler/Compiler/Util/ExpandableArray.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 uniontype ExpandableArray<T> "Implementation of an expandable array
37
38 This provides a generic implementation of an expandable array. It basically
39 behaves like an ordinary array, which means all elements can get accessed via
40 index. When the array runs out of space, it get automatically resized. It is
41 also possible to delete an element from any position."
42
43 record EXPANDABLE_ARRAY
44 Mutable<Integer> numberOfElements;
45 Mutable<Integer> lastUsedIndex;
46 Mutable<Integer> capacity;
47 Mutable<array<Option<T>>> data;
48 end EXPANDABLE_ARRAY;
49
50 protected
51 import Array;
52 import MetaModelica.Dangerous;
53 import Mutable;
54 import Util;
55
56 public
57 impure function new "O(n)
58 Creates a new empty ExpandableArray with a certain capacity."
59 input Integer capacity;
60 input T dummy "This is needed to determine the type information, the actual value is not used";
61 output ExpandableArray<T> exarray;
62 algorithm
63 494977 exarray := EXPANDABLE_ARRAY(Mutable.create(0), Mutable.create(0), Mutable.create(capacity), Mutable.create(arrayCreate(capacity, NONE())));
64 end new;
65
66 function clear "O(n)
67 Deletes all elements."
68 input output ExpandableArray<T> exarray;
69 protected
70 Integer n = Mutable.access(exarray.numberOfElements);
71 Integer lastUsedIndex = Mutable.access(exarray.lastUsedIndex);
72 array<Option<T>> data = Mutable.access(exarray.data);
73 algorithm
74 3307 Mutable.update(exarray.numberOfElements, 0);
75 3307 Mutable.update(exarray.lastUsedIndex, 0);
76
2/2
✓ Branch 0 taken 3164 times.
✓ Branch 1 taken 143 times.
3708 for i in 1:lastUsedIndex loop
77
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 544 times.
✓ Branch 2 taken 544 times.
✗ Branch 3 not taken.
544 if isSome(Dangerous.arrayGetNoBoundsChecking(data, i)) then
78
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 401 times.
544 n := n-1;
79 Dangerous.arrayUpdateNoBoundsChecking(data, i, NONE());
80
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 401 times.
544 if n == 0 then
81 143 return;
82 end if;
83 end if;
84 end for;
85 end clear;
86
87 function copy
88 input ExpandableArray<T> inExarray;
89 input T dummy "This is needed to determine the type information, the actual value is not used";
90 output ExpandableArray<T> outExarray;
91 algorithm
92 71903 outExarray := new(Mutable.access(inExarray.capacity), dummy);
93 71903 outExarray.numberOfElements := Mutable.create(Mutable.access(inExarray.numberOfElements));
94 outExarray.lastUsedIndex := Mutable.create(Mutable.access(inExarray.lastUsedIndex));
95 outExarray.capacity := Mutable.create(Mutable.access((inExarray.capacity)));
96 outExarray.data := Mutable.create(arrayCopy(Mutable.access(inExarray.data)));
97 end copy;
98
99 function occupied "O(1)
100 Returns if the element at the given index is occupied or not."
101 input Integer index;
102 input ExpandableArray<T> exarray;
103 output Boolean b;
104 protected
105 Integer lastUsedIndex = Mutable.access(exarray.lastUsedIndex);
106 array<Option<T>> data = Mutable.access(exarray.data);
107 algorithm
108
4/6
✓ Branch 0 taken 10262674 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10262674 times.
✓ Branch 4 taken 13784 times.
✓ Branch 5 taken 10248890 times.
10262674 b := index >= 1 and index <= lastUsedIndex and isSome(Dangerous.arrayGetNoBoundsChecking(data, index));
109 end occupied;
110
111 function get "O(1)
112 Returns the value of the element at the given index.
113 Fails if there is nothing assigned to the given index."
114 input Integer index;
115 input ExpandableArray<T> exarray;
116 output T value;
117 protected
118 array<Option<T>> data = Mutable.access(exarray.data);
119 algorithm
120
2/4
✓ Branch 0 taken 16352768 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 16352768 times.
✗ Branch 4 not taken.
16352768 true := index >= 1 and index <= Mutable.access(exarray.lastUsedIndex);
121
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 16352768 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16352768 times.
16352768 SOME(value) := Dangerous.arrayGetNoBoundsChecking(data, index);
122 end get;
123
124 function expandToSize "O(n)
125 Expands an array to the given size, or does nothing if the array is already
126 large enough."
127 input Integer minCapacity;
128 input output ExpandableArray<T> exarray;
129 protected
130 Integer capacity = Mutable.access(exarray.capacity);
131 array<Option<T>> data = Mutable.access(exarray.data);
132 algorithm
133
2/2
✓ Branch 0 taken 133152 times.
✓ Branch 1 taken 57945 times.
191097 if minCapacity > capacity then
134 57945 Mutable.update(exarray.capacity, minCapacity);
135 57945 data := Array.expandToSize(minCapacity, data, NONE());
136 57945 Mutable.update(exarray.data, data);
137 end if;
138 end expandToSize;
139
140 function set "if index <= capacity then O(1) otherwise O(n)
141 Sets the element at the given index to the given value.
142 Fails if the index is already used."
143 input Integer index;
144 input T value;
145 input output ExpandableArray<T> exarray;
146 protected
147 Integer numberOfElements = Mutable.access(exarray.numberOfElements);
148 Integer lastUsedIndex = Mutable.access(exarray.lastUsedIndex);
149 Integer capacity = Mutable.access(exarray.capacity);
150 array<Option<T>> data = Mutable.access(exarray.data);
151 algorithm
152
5/10
✓ Branch 0 taken 2994225 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2993220 times.
✓ Branch 3 taken 1005 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2993220 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2993220 times.
✗ Branch 9 not taken.
2994225 if index > 0 and (index > capacity or isNone(Dangerous.arrayGetNoBoundsChecking(data, index))) then
153
2/2
✓ Branch 0 taken 1005 times.
✓ Branch 1 taken 2993220 times.
2994225 if index > capacity then
154 capacity := max(capacity, 1);
155
156
2/2
✓ Branch 0 taken 962 times.
✓ Branch 1 taken 1005 times.
1967 while index > capacity loop
157 962 capacity := capacity * 2;
158 end while;
159
160 1005 expandToSize(capacity, exarray);
161 1005 data := Mutable.access(exarray.data);
162 end if;
163
164 2994225 arrayUpdate(data, index, SOME(value));
165 2994225 Mutable.update(exarray.numberOfElements, numberOfElements+1);
166
1/2
✓ Branch 0 taken 2994225 times.
✗ Branch 1 not taken.
2994225 if index > lastUsedIndex then
167 2994225 Mutable.update(exarray.lastUsedIndex, index);
168 end if;
169 else
170 ✗ fail();
171 end if;
172 end set;
173
174 function add "if index <= capacity then O(1) otherwise O(n)
175 Sets the first unused element to the given value."
176 input T value;
177 input output ExpandableArray<T> exarray;
178 output Integer index;
179 protected
180 Integer lastUsedIndex = Mutable.access(exarray.lastUsedIndex);
181 algorithm
182 2988438 index := lastUsedIndex+1;
183 2988438 exarray := set(index, value, exarray);
184 end add;
185
186 function delete "O(1)
187 Deletes the value of the element at the given index.
188 Fails if there is no value stored at the given index."
189 input Integer index;
190 input output ExpandableArray<T> exarray;
191 protected
192 Integer numberOfElements = Mutable.access(exarray.numberOfElements);
193 Integer lastUsedIndex = Mutable.access(exarray.lastUsedIndex);
194 array<Option<T>> data = Mutable.access(exarray.data);
195 algorithm
196
3/6
✓ Branch 0 taken 10891 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10891 times.
✓ Branch 4 taken 10891 times.
✗ Branch 5 not taken.
10891 if index >= 1 and index <= lastUsedIndex and isSome(Dangerous.arrayGetNoBoundsChecking(data, index)) then
197 10891 arrayUpdate(data, index, NONE());
198 10891 Mutable.update(exarray.numberOfElements, numberOfElements-1);
199
200
2/2
✓ Branch 0 taken 570 times.
✓ Branch 1 taken 10321 times.
10891 if index == lastUsedIndex then
201 570 lastUsedIndex := lastUsedIndex-1;
202
5/6
✓ Branch 0 taken 707 times.
✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 707 times.
✓ Branch 4 taken 231 times.
✓ Branch 5 taken 476 times.
801 while lastUsedIndex > 0 and isNone(Dangerous.arrayGetNoBoundsChecking(data, lastUsedIndex)) loop
203 lastUsedIndex := lastUsedIndex-1;
204 end while;
205 570 Mutable.update(exarray.lastUsedIndex, lastUsedIndex);
206 end if;
207 else
208 ✗ fail();
209 end if;
210 end delete;
211
212 function update "O(1)
213 Overrides the value of the element at the given index.
214 Fails if there is no value stored at the given index."
215 input Integer index;
216 input T value;
217 input output ExpandableArray<T> exarray;
218 protected
219 Integer lastUsedIndex = Mutable.access(exarray.lastUsedIndex);
220 array<Option<T>> data = Mutable.access(exarray.data);
221 algorithm
222
3/6
✓ Branch 0 taken 2241279 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2241279 times.
✓ Branch 4 taken 2241279 times.
✗ Branch 5 not taken.
2241279 if index >= 1 and index <= lastUsedIndex and isSome(Dangerous.arrayGetNoBoundsChecking(data, index)) then
223 2241279 arrayUpdate(data, index, SOME(value));
224 else
225 ✗ fail();
226 end if;
227 end update;
228
229 function toList
230 input ExpandableArray<T> exarray;
231 output list<T> listT = {};
232 protected
233 Integer numberOfElements = Mutable.access(exarray.numberOfElements);
234 Integer lastUsedIndex = Mutable.access(exarray.lastUsedIndex);
235 array<Option<T>> data = Mutable.access(exarray.data);
236 algorithm
237
2/2
✓ Branch 0 taken 141119 times.
✓ Branch 1 taken 109907 times.
251026 if numberOfElements == 0 then
238 listT := {};
239 elseif lastUsedIndex == 1 then
240 93450 listT := {Util.getOption(data[1])};
241 else
242
7/8
✗ Branch 1 not taken.
✓ Branch 2 taken 1976370 times.
✓ Branch 3 taken 345 times.
✓ Branch 4 taken 1976025 times.
✓ Branch 5 taken 1976370 times.
✓ Branch 6 taken 47669 times.
✓ Branch 7 taken 1976025 times.
✓ Branch 8 taken 47669 times.
2024039 listT := list(Util.getOption(data[i]) for i guard isSome(data[i]) in 1:lastUsedIndex);
243 end if;
244 end toList;
245
246 function compress "O(n)
247 Reorders the elements in order to remove all the gaps.
248 Be careful: This changes the indices of the elements."
249 input output ExpandableArray<T> exarray;
250 protected
251 Integer numberOfElements = Mutable.access(exarray.numberOfElements);
252 Integer lastUsedIndex = Mutable.access(exarray.lastUsedIndex);
253 array<Option<T>> data = Mutable.access(exarray.data);
254 Integer i = 0;
255 algorithm
256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 223221 times.
223221 while lastUsedIndex > numberOfElements loop
257 ✗ i := i+1;
258 ✗ if isNone(Dangerous.arrayGetNoBoundsChecking(data, i)) then
259 ✗ Dangerous.arrayUpdateNoBoundsChecking(data, i, Dangerous.arrayGetNoBoundsChecking(data, lastUsedIndex));
260 Dangerous.arrayUpdateNoBoundsChecking(data, lastUsedIndex, NONE());
261 lastUsedIndex := lastUsedIndex-1;
262 ✗ while isNone(Dangerous.arrayGetNoBoundsChecking(data, lastUsedIndex)) loop
263 lastUsedIndex := lastUsedIndex-1;
264 end while;
265 end if;
266 end while;
267
268 223221 Mutable.update(exarray.lastUsedIndex, lastUsedIndex);
269 end compress;
270
271 function shrink "O(n)
272 Reduces the capacity of the ExpandableArray to the number of elements.
273 Be careful: This may change the indices of the elements."
274 input output ExpandableArray<T> exarray;
275 protected
276 Integer numberOfElements = Mutable.access(exarray.numberOfElements);
277 array<Option<T>> data = Mutable.access(exarray.data);
278 array<Option<T>> newData;
279 algorithm
280 ✗ exarray := compress(exarray);
281 ✗ Mutable.update(exarray.capacity, numberOfElements);
282 ✗ newData := Dangerous.arrayCreateNoInit(numberOfElements, Dangerous.arrayGetNoBoundsChecking(data, 1));
283 ✗ for i in 1:numberOfElements loop
284 ✗ Dangerous.arrayUpdateNoBoundsChecking(newData, i, Dangerous.arrayGetNoBoundsChecking(data, i));
285 end for;
286 ✗ Mutable.update(exarray.data, newData);
287 end shrink;
288
289 function toString "O(n)
290 Dumps all elements with the given print function."
291 input ExpandableArray<T> exarray;
292 input String header;
293 input PrintFunction func;
294 input Boolean debug = true;
295 output String str;
296
297 partial function PrintFunction
298 input T t;
299 output String str;
300 end PrintFunction;
301 protected
302 Integer numberOfElements = Mutable.access(exarray.numberOfElements);
303 Integer capacity = Mutable.access(exarray.capacity);
304 T value;
305 array<Option<T>> data = Mutable.access(exarray.data);
306 algorithm
307
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if debug then
308 27 str := header + " (" + intString(numberOfElements) + "/" + intString(capacity) + ")\n";
309 else
310 ✗ str := header + " (" + intString(numberOfElements) + ")\n";
311 end if;
312
313 27 str := str + "========================================\n";
314
315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if numberOfElements == 0 then
316 ✗ str := str + "<empty>\n";
317 else
318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
58 for i in 1:capacity loop
319
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
58 if isSome(Dangerous.arrayGetNoBoundsChecking(data, i)) then
320 58 SOME(value) := Dangerous.arrayGetNoBoundsChecking(data, i);
321 58 numberOfElements := numberOfElements-1;
322
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 58 times.
58 str := str + intString(i) + ": " + func(value) + "\n";
323
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 31 times.
58 if numberOfElements == 0 then
324 27 return;
325 end if;
326 end if;
327 end for;
328 end if;
329 end toString;
330
331 function getNumberOfElements
332 input ExpandableArray<T> exarray;
333 output Integer numberOfElements = Mutable.access(exarray.numberOfElements);
334 end getNumberOfElements;
335
336 function getLastUsedIndex
337 input ExpandableArray<T> exarray;
338 output Integer lastUsedIndex = Mutable.access(exarray.lastUsedIndex);
339 end getLastUsedIndex;
340
341 function getCapacity
342 input ExpandableArray<T> exarray;
343 output Integer capacity = Mutable.access(exarray.capacity);
344 end getCapacity;
345
346 function getData
347 input ExpandableArray<T> exarray;
348 output array<Option<T>> data = Mutable.access(exarray.data);
349 end getData;
350
351 annotation(__OpenModelica_Interface="util");
352 end ExpandableArray;
353