Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 52.9% 36 / 0 / 68
Functions: -% 0 / 1 / 1
Branches: 42.9% 42 / 0 / 98

OMCompiler/Compiler/Util/SBInterval.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 SBInterval
37 "Interval type for set based graphs."
38
39 import UnorderedSet;
40
41 protected
42 import System;
43 import MetaModelica.Dangerous.listReverseInPlace;
44
45 function euclid
46 "uses the extended euclidean algorithm to compute
47 - greatest common divisor d = gcd(a,b)
48 - least common multiple m = lcm(a,b) = a*(b/d)
49 - Bézout coefficients ua + vb = u*a + v*b = d
50 "
51 input Integer a;
52 input Integer b;
53 output Integer d "gcd";
54 output Integer m "lcm";
55 output Integer ua;
56 output Integer vb;
57 protected
58 Integer q;
59 Integer r1 = a, r2 = b;
60 Integer s1 = a, s2 = 0;
61 Integer tmp;
62 algorithm
63
2/2
✓ Branch 0 taken 6069 times.
✓ Branch 1 taken 6069 times.
12138 while r2 <> 0 loop
64 6069 q := div(r1, r2);
65
66 tmp := r2;
67 6069 r2 := r1 - q * r2;
68 r1 := tmp;
69
70 tmp := s2;
71 6069 s2 := s1 - q * s2;
72 s1 := tmp;
73 end while;
74 d := r1;
75 6069 m := abs(s2);
76 ua := s1;
77
1/2
✓ Branch 0 taken 6069 times.
✗ Branch 1 not taken.
6069 vb := r1 - s1;
78 end euclid;
79
80 public
81 record INTERVAL
82 Integer lo;
83 Integer step;
84 Integer hi;
85 end INTERVAL;
86
87 function new
88 input Integer lo;
89 input Integer step;
90 input Integer hi;
91 output SBInterval int;
92 algorithm
93
3/4
✓ Branch 0 taken 7734 times.
✓ Branch 1 taken 1108 times.
✓ Branch 2 taken 7734 times.
✗ Branch 3 not taken.
8842 if lo >= 0 and step > 0 and hi >= 0 then
94
3/4
✓ Branch 0 taken 7734 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 7386 times.
✓ Branch 4 taken 348 times.
7734 if lo <= hi and hi < System.intMaxLit() then
95
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7386 times.
7386 int := INTERVAL(lo, step, hi - mod(hi - lo, step));
96 elseif lo <= hi and hi == System.intMaxLit() then
97 348 int := INTERVAL(lo, step, System.intMaxLit());
98 else
99 // Warning: Wrong values for subscript (check low <= hi).
100 ✗ int := INTERVAL(lo, 0, hi);
101 end if;
102 elseif lo >= 0 and step == 0 and hi == lo then
103 1108 int := INTERVAL(lo, 1, hi);
104 else
105 // Warning: Subscript should be positive.
106 ✗ int := newEmpty();
107 end if;
108 end new;
109
110 function newEmpty
111 output SBInterval int = INTERVAL(-1, 0, -1);
112 end newEmpty;
113
114 function newUnit
115 output SBInterval int = INTERVAL(1, 1, 1);
116 end newUnit;
117
118 function newFull
119 output SBInterval int = INTERVAL(1, 1, System.intMaxLit());
120 end newFull;
121
122 function lowerBound
123 input SBInterval int;
124 output Integer lo = int.lo;
125 end lowerBound;
126
127 function stepValue
128 input SBInterval int;
129 output Integer step = int.step;
130 end stepValue;
131
132 function upperBound
133 input SBInterval int;
134 output Integer hi = int.hi;
135 end upperBound;
136
137 function crop
138 input output SBInterval int;
139 algorithm
140 ✗ if int.hi < System.intMaxLit() then
141 ✗ int.hi := int.hi - mod(int.hi - int.lo, int.step);
142 end if;
143 end crop;
144
145 function intersection
146 input SBInterval int1;
147 input SBInterval int2;
148 output SBInterval int;
149 protected
150 Integer new_lo, new_step, new_hi;
151 Integer gcd_, ua, vb, x;
152 algorithm
153
4/4
✓ Branch 0 taken 8795 times.
✓ Branch 1 taken 2687 times.
✓ Branch 2 taken 2726 times.
✓ Branch 3 taken 6069 times.
11482 if int1.hi < int2.lo or int2.hi < int1.lo then
154 // The intervals do not intersect.
155 5413 int := newEmpty();
156 else
157 // The new step will be the least common multiple of the two intervals' steps.
158 6069 (gcd_, new_step, ua, vb) := euclid(int1.step, int2.step);
159
160
2/4
✓ Branch 0 taken 6069 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6069 times.
12138 if 0 <> mod(int1.lo - int2.lo, gcd_) then
161 // The intervals step through each other without touching
162 ✗ int := newEmpty();
163 else
164 // x is an integer on both intervals (modulo new_step)
165
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 6069 times.
✓ Branch 3 taken 6069 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6069 times.
✗ Branch 6 not taken.
12138 x := div(int1.lo, gcd_) * vb + div(int2.lo, gcd_) * ua + mod(int1.lo, gcd_);
166
167 // Find new lower and upper bound, crop with x
168 new_lo := intMax(int1.lo, int2.lo);
169
1/2
✓ Branch 0 taken 6069 times.
✗ Branch 1 not taken.
6069 new_hi := intMin(int1.hi, int2.hi);
170
1/2
✓ Branch 0 taken 6069 times.
✗ Branch 1 not taken.
6069 new_lo := new_lo + mod(x - new_lo, new_step);
171
1/2
✓ Branch 1 taken 6069 times.
✗ Branch 2 not taken.
6069 if new_hi < System.intMaxLit() then
172
1/2
✓ Branch 0 taken 6069 times.
✗ Branch 1 not taken.
12138 new_hi := new_hi - mod(new_hi - x, new_step);
173 end if;
174
175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6069 times.
6069 if new_hi < new_lo then
176 // Empty interval
177 ✗ int := newEmpty();
178 else
179 6069 int := new(new_lo, new_step, new_hi);
180 end if;
181 end if;
182 end if;
183 end intersection;
184
185 function complement
186 "Returns a set of intervals corresponding to the removal of int2 from int1."
187 input SBInterval int1;
188 input SBInterval int2;
189 output UnorderedSet<SBInterval> ints;
190 protected
191 SBInterval i2;
192 Integer count_r, count_s;
193 algorithm
194 17 ints := UnorderedSet.new(hash, isEqual);
195 17 i2 := intersection(int1, int2);
196
197
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if isEmpty(i2) then
198 // No intersection, nothing to remove.
199 ✗ UnorderedSet.add(int1, ints);
200 elseif not isEqual(int1, i2) then
201 // Rightmost interval.
202
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 if i2.hi < int1.hi then
203 9 UnorderedSet.add(new(i2.hi + int1.step, int1.step, int1.hi), ints);
204 end if;
205
206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 count_r := div(i2.step, int1.step) - 1;
207
2/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 count_s := if i2.hi < System.intMaxLit() then div(i2.hi - i2.lo, i2.step) else System.intMaxLit();
208
209
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if count_r < count_s then
210 // create an interval for every residue class not equal to i2.lo
211
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if count_s < System.intMaxLit() then
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for i in count_r:-1:1 loop
213 ✗ UnorderedSet.add(new(i2.lo + i * int1.step, i2.step, i2.hi - i2.step + i * int1.step), ints);
214 end for;
215 else
216 ✗ for i in count_r:-1:1 loop
217 ✗ UnorderedSet.add(new(i2.lo + i * int1.step, i2.step, System.intMaxLit()), ints);
218 end for;
219 end if;
220 else
221 // create an interval for every space between removed points
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 for i in count_s:-1:1 loop
223 ✗ UnorderedSet.add(new(i2.lo + int1.step + (i - 1) * i2.step, int1.step, i2.lo - int1.step + i * i2.step), ints);
224 end for;
225 end if;
226
227 // Leftmost interval.
228
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 if i2.lo > int1.lo then
229 3 UnorderedSet.add(new(int1.lo, int1.step, i2.lo - int1.step), ints);
230 end if;
231 end if;
232 end complement;
233
234 function affine
235 "Affine function for scaling and offsetting an interval."
236 input SBInterval int;
237 input Real gain;
238 input Integer offset;
239 output SBInterval res;
240 protected
241 Real lo, step, hi;
242 Integer ilo, istep, ihi;
243 algorithm
244 ✗ INTERVAL(lo, step, hi) := int;
245
246 ✗ if gain > 0 then
247 ✗ lo := lo * gain + offset;
248 ✗ hi := hi * gain + offset;
249 ✗ step := step * gain;
250
251 ✗ if step < 1 then
252 step := 1.0;
253 ✗ lo := ceil(lo);
254 ✗ hi := floor(hi);
255 end if;
256
257 ✗ if lo < 0 then
258 ✗ lo := lo + step * (1 + floor(abs(lo) / step));
259 end if;
260
261 ✗ if hi < lo then
262 // Empty interval.
263 ✗ res := newEmpty();
264 else
265 ✗ ilo := integer(lo);
266 ✗ ihi := integer(hi);
267 ✗ istep := if ilo == ihi then 1 else integer(step);
268
269 ✗ res := new(ilo, istep, ihi);
270 end if;
271 else
272 ✗ if offset > 0 then
273 ✗ res := new(offset, 1, offset);
274 else
275 // Empty interval.
276 ✗ res := newEmpty();
277 end if;
278 end if;
279 end affine;
280
281 function cardinality
282 input SBInterval int;
283 output Integer card = realInt(intReal(int.hi - int.lo)/intReal(int.step));
284 end cardinality;
285
286 function contains
287 "Returns true if c belongs to the interval, otherwise false."
288 input Integer c;
289 input SBInterval int;
290 output Boolean res;
291 algorithm
292 ✗ res := not isEmpty(int) and
293 c >= int.lo and
294 c <= int.hi and
295 mod(c - int.lo, int.step) == 0;
296 end contains;
297
298 function isEmpty
299 input SBInterval int;
300 output Boolean res = int.step == 0;
301 end isEmpty;
302
303 function size
304 input SBInterval int;
305 output Integer res = intDiv(int.hi - int.lo, int.step) + 1;
306 end size;
307
308 function isEqual
309 input SBInterval int1;
310 input SBInterval int2;
311 output Boolean equal;
312 algorithm
313
5/6
✓ Branch 0 taken 354 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 354 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 336 times.
393 equal := int1.lo == int2.lo and int1.step == int2.step and int1.hi == int2.hi;
314 end isEqual;
315
316 function hash
317 input SBInterval int;
318 output Integer hash = int.lo;
319 end hash;
320
321 function toString
322 input SBInterval interval;
323 output String str;
324 algorithm
325 ✗ str := "[" + String(interval.lo) + ":" +
326 String(interval.step) + ":" +
327 String(interval.hi) + "]";
328 end toString;
329
330 annotation(__OpenModelica_Interface="util");
331 end SBInterval;
332