Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 65.0% 26 / 0 / 40
Functions: -% 0 / 1 / 1
Branches: 28.6% 8 / 0 / 28

OMCompiler/Compiler/Util/SBLinearMap.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 SBLinearMap
37
38 protected
39 import Array;
40 import List;
41 import SBAtomicSet;
42 import SBInterval;
43 import SBMultiInterval;
44 import SBSet;
45 import System;
46 import Util;
47 import MetaModelica.Dangerous.*;
48
49 public
50 record LINEAR_MAP
51 array<Real> gain;
52 array<Real> offset;
53 end LINEAR_MAP;
54
55 function new
56 input array<Real> gain;
57 input array<Real> offset;
58 output SBLinearMap map;
59 algorithm
60
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
98 if Array.any(gain, Util.realNegative) then
61 // Warning: All gains should be positive.
62 ✗ map := newEmpty();
63 elseif arrayLength(gain) == arrayLength(offset) then
64 98 map := LINEAR_MAP(arrayCopy(gain), arrayCopy(offset));
65 else
66 // Warning: Offset and gain should be the same size.
67 ✗ map := newEmpty();
68 end if;
69 end new;
70
71 function newEmpty
72 output SBLinearMap map = LINEAR_MAP(listArray({}), listArray({}));
73 end newEmpty;
74
75 function newIdentity
76 input Integer dim;
77 output SBLinearMap map;
78 algorithm
79 7 map := LINEAR_MAP(arrayCreate(dim, 1.0), arrayCreate(dim, 0.0));
80 end newIdentity;
81
82 function copy
83 input SBLinearMap map;
84 output SBLinearMap outMap;
85 algorithm
86 5223 outMap := LINEAR_MAP(arrayCopy(map.gain), arrayCopy(map.offset));
87 end copy;
88
89 function ndim
90 input SBLinearMap map;
91 output Integer ndim = arrayLength(map.gain);
92 end ndim;
93
94 function isDim
95 input SBLinearMap map;
96 input Integer dim;
97 output Boolean res = arrayLength(map.gain) == dim;
98 end isDim;
99
100 function gain
101 input SBLinearMap map;
102 output array<Real> gain = map.gain;
103 end gain;
104
105 function offset
106 input SBLinearMap map;
107 output array<Real> offset = map.offset;
108 end offset;
109
110 function isEmpty
111 input SBLinearMap map;
112 output Boolean empty = arrayEmpty(map.gain);
113 end isEmpty;
114
115 function isIdentity
116 input SBLinearMap map;
117 output Boolean isIdentity;
118 algorithm
119 ✗ isIdentity := Array.all(map.gain, function realEq(x1 = 1.0)) and
120 Array.all(map.offset, function realEq(x1 = 0.0));
121 end isIdentity;
122
123 function isEqual
124 input SBLinearMap map1;
125 input SBLinearMap map2;
126 output Boolean equal;
127 algorithm
128 ✗ equal := Array.isEqualOnTrue(map1.gain, map2.gain, realEq) and
129 Array.isEqualOnTrue(map1.offset, map2.offset, realEq);
130 end isEqual;
131
132 function compose
133 input SBLinearMap map1;
134 input SBLinearMap map2;
135 output SBLinearMap map;
136 protected
137 array<Real> gain, offset;
138 Integer len1 = ndim(map1), len2 = ndim(map2);
139 Real g1, g2, o1, o2;
140 algorithm
141
1/2
✓ Branch 0 taken 213 times.
✗ Branch 1 not taken.
213 if len1 == len2 then
142 213 gain := arrayCreateNoInit(len1, 0.0);
143 213 offset := arrayCreateNoInit(len1, 0.0);
144
145
1/2
✓ Branch 0 taken 213 times.
✗ Branch 1 not taken.
458 for i in 1:len1 loop
146 245 g1 := arrayGetNoBoundsChecking(map1.gain, i);
147 245 g2 := arrayGetNoBoundsChecking(map2.gain, i);
148 245 o1 := arrayGetNoBoundsChecking(map1.offset, i);
149 245 o2 := arrayGetNoBoundsChecking(map2.offset, i);
150
151 245 arrayUpdateNoBoundsChecking(gain, i, g1 * g2);
152 245 arrayUpdateNoBoundsChecking(offset, i, o2 * g1 + o1);
153 end for;
154
155 213 map := LINEAR_MAP(gain, offset);
156 else
157 // Warning: Linear maps should be of the same size.
158 ✗ map := newEmpty();
159 end if;
160
161 end compose;
162
163 function inverse
164 input SBLinearMap map;
165 output SBLinearMap inv;
166 protected
167 array<Real> gain, offset;
168 Integer len = ndim(map);
169 Real g, o;
170 algorithm
171 866 gain := arrayCreateNoInit(len, 0.0);
172 866 offset := arrayCreateNoInit(len, 0.0);
173
174
1/2
✓ Branch 0 taken 866 times.
✗ Branch 1 not taken.
1828 for i in 1:len loop
175
2/2
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 529 times.
962 g := arrayGetNoBoundsChecking(map.gain, i);
176 962 o := arrayGetNoBoundsChecking(map.offset, i);
177
178
2/2
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 529 times.
962 if g <> 0 then
179 433 arrayUpdateNoBoundsChecking(gain, i, 1.0 / g);
180 433 arrayUpdateNoBoundsChecking(offset, i, -o / g);
181 else
182 529 arrayUpdateNoBoundsChecking(gain, i, intReal(System.intMaxLit()));
183 529 arrayUpdateNoBoundsChecking(offset, i, intReal(System.intMaxLit()));
184 end if;
185 end for;
186
187 866 inv := LINEAR_MAP(gain, offset);
188 end inverse;
189
190 function apply
191 input SBSet domain;
192 input SBLinearMap map;
193 output SBSet target = SBSet.copy(domain);
194 algorithm
195 ✗ if not isIdentity(map) then
196 ✗ target.asets := UnorderedSet.selfMap(target.asets, function applyAtomicSet(map = map));
197 end if;
198 end apply;
199
200 function applyAtomicSet
201 input output SBAtomicSet atomic;
202 input SBLinearMap map;
203 algorithm
204 ✗ atomic.aset := applyMultiInterval(atomic.aset, map);
205 end applyAtomicSet;
206
207 function applyMultiInterval
208 input output SBMultiInterval multiInt;
209 input SBLinearMap map;
210 algorithm
211 ✗ for i in 1:multiInt.ndim loop
212 ✗ multiInt.intervals[i] := applyInterval(multiInt.intervals[i], map.gain[i], map.offset[i]);
213 end for;
214 end applyMultiInterval;
215
216 function applyInterval
217 input output SBInterval interval;
218 input Real gain;
219 input Real offset;
220 algorithm
221 // take care! theses should always be convertible without rounding errors
222 ✗ interval.lo := realInt(intReal(interval.lo) * gain + offset);
223 interval.step := realInt(intReal(interval.step) * gain);
224 interval.hi := realInt(intReal(interval.hi) * gain + offset);
225 end applyInterval;
226
227 function toString
228 input SBLinearMap map;
229 output String str;
230 protected
231 list<String> strl = {};
232 algorithm
233 ✗ for i in arrayLength(map.gain):-1:1 loop
234 ✗ strl := String(arrayGetNoBoundsChecking(map.gain, i)) + " * x + " +
235 String(arrayGetNoBoundsChecking(map.offset, i)) :: strl;
236 end for;
237
238 ✗ str := stringDelimitList(strl, "\n");
239 end toString;
240
241 annotation(__OpenModelica_Interface="util");
242 end SBLinearMap;
243