Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 27.8% 5 / 0 / 18
Functions: -% 0 / 4 / 4
Branches: 15.6% 5 / 0 / 32

OMCompiler/SimulationRuntime/cpp/Core/Math/Matrix.h
Line Branch Exec Source
1 /*
2 * This file belongs to the OpenModelica Run-Time System
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), c/o Linköpings
5 * universitet, Department of Computer and Information Science, SE-58183 Linköping, Sweden. All rights
6 * reserved.
7 *
8 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THE BSD NEW LICENSE OR THE
9 * AGPL VERSION 3 LICENSE OR THE OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. ANY
10 * USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
11 * ACCEPTANCE OF THE BSD NEW LICENSE OR THE OSMC PUBLIC LICENSE OR THE AGPL
12 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
13 *
14 * The OpenModelica software and the OSMC (Open Source Modelica Consortium) Public License
15 * (OSMC-PL) are obtained from OSMC, either from the above address, from the URLs:
16 * http://www.openmodelica.org or https://github.com/OpenModelica/ or
17 * http://www.ida.liu.se/projects/OpenModelica, and in the OpenModelica distribution. GNU
18 * AGPL version 3 is obtained from: https://www.gnu.org/licenses/licenses.html#GPL. The BSD NEW
19 * License is obtained from: http://www.opensource.org/licenses/BSD-3-Clause.
20 *
21 * This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY
23 * SET FORTH IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF
24 * OSMC-PL.
25 *
26 */
27
28
29 #pragma once
30 /** @addtogroup coreMath
31 *
32 * @{
33 */
34
35 #include <algorithm>
36 #include <cstddef>
37 #include <vector>
38
39 /**
40 * Dense and compressed matrix types for the Jacobians and linear systems.
41 *
42 * Core/Modelica.h aliases this namespace to `ublas`, so generated code keeps
43 * the uBLAS spelling. Only the operations OpenModelica uses are provided.
44 */
45 namespace omcpp { namespace linalg {
46
47 struct row_major {
48 static constexpr std::size_t element(std::size_t i, std::size_t j, std::size_t, std::size_t n2)
49 ✗ { return i * n2 + j; }
50 };
51
52 struct column_major {
53 static constexpr std::size_t element(std::size_t i, std::size_t j, std::size_t n1, std::size_t)
54 { return i + j * n1; }
55 };
56
57 /** Storage with the subset of the uBLAS array interface that is used. */
58 template <class T>
59 ✗ class unbounded_array {
60 public:
61 typedef T value_type;
62 typedef T* iterator;
63 typedef const T* const_iterator;
64
65 unbounded_array() {}
66 ✗ explicit unbounded_array(std::size_t n) : _data(n, T()) {}
67 unbounded_array(std::size_t n, const T& init) : _data(n, init) {}
68
69 T* begin() { return _data.empty() ? 0 : &_data[0]; }
70
2/4
✓ Branch 0 taken 24015868 times.
✓ Branch 0 taken 2883 times.
✗ Branch 1 not taken.
✗ Branch 1 not taken.
24018751 const T* begin() const { return _data.empty() ? 0 : &_data[0]; }
71 T* end() { return begin() + _data.size(); }
72 const T* end() const { return begin() + _data.size(); }
73
74 T& operator[](std::size_t i) { return _data[i]; }
75 const T& operator[](std::size_t i) const { return _data[i]; }
76
77 std::size_t size() const { return _data.size(); }
78 ✗ void resize(std::size_t n) { _data.resize(n, T()); }
79 void clear() { std::fill(_data.begin(), _data.end(), T()); }
80 void insert(std::size_t pos, const T& v) { _data.insert(_data.begin() + pos, v); }
81
82 private:
83 std::vector<T> _data;
84 };
85
86 template <class T>
87 class zero_vector {
88 public:
89 explicit zero_vector(std::size_t n) : size(n) {}
90 std::size_t size;
91 };
92
93 template <class T>
94 class zero_matrix {
95 public:
96 zero_matrix(std::size_t n1, std::size_t n2) : size1(n1), size2(n2) {}
97 std::size_t size1, size2;
98 };
99
100 template <class T, class A = unbounded_array<T> >
101 ✗ class vector {
102 public:
103 typedef T value_type;
104 typedef std::size_t size_type;
105
106 vector() {}
107 explicit vector(std::size_t n) : _data(n) {}
108 vector(const zero_vector<T>& z) : _data(z.size) {}
109
110 T& operator()(std::size_t i) { return _data[i]; }
111 const T& operator()(std::size_t i) const { return _data[i]; }
112 T& operator[](std::size_t i) { return _data[i]; }
113 const T& operator[](std::size_t i) const { return _data[i]; }
114
115 std::size_t size() const { return _data.size(); }
116 /** uBLAS semantics: assign zero to every element, keeping the size. */
117 void clear() { _data.clear(); }
118 void resize(std::size_t n, bool preserve = true) { (void)preserve; _data.resize(n); }
119
120 A& data() { return _data; }
121 const A& data() const { return _data; }
122
123 private:
124 A _data;
125 };
126
127 template <class T, class L = row_major, class A = unbounded_array<T> >
128
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
1 class matrix {
129 public:
130 typedef T value_type;
131 typedef std::size_t size_type;
132
133
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 matrix() : _size1(0), _size2(0) {}
134 matrix(std::size_t n1, std::size_t n2) : _data(n1 * n2), _size1(n1), _size2(n2) {}
135 matrix(const zero_matrix<T>& z)
136 : _data(z.size1 * z.size2), _size1(z.size1), _size2(z.size2) {}
137
138 T& operator()(std::size_t i, std::size_t j)
139 { return _data[L::element(i, j, _size1, _size2)]; }
140 const T& operator()(std::size_t i, std::size_t j) const
141 { return _data[L::element(i, j, _size1, _size2)]; }
142
143
2/2
✓ Branch 0 taken 2302 times.
✓ Branch 1 taken 765724 times.
768026 std::size_t size1() const { return _size1; }
144
1/6
<unknown function 49>:
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
<unknown function 70>:
✓ Branch 0 taken 2302 times.
✗ Branch 1 not taken.
2302 std::size_t size2() const { return _size2; }
145 void clear() { _data.clear(); }
146
147 void resize(std::size_t n1, std::size_t n2, bool preserve = true) {
148 (void)preserve;
149 ✗ _data.resize(n1 * n2);
150 ✗ _size1 = n1;
151 ✗ _size2 = n2;
152 }
153
154 A& data() { return _data; }
155 const A& data() const { return _data; }
156
157 private:
158 A _data;
159 std::size_t _size1, _size2;
160 };
161
162 /**
163 * Compressed storage, major direction chosen by L. Entries are kept sorted
164 * because the code generator emits `A(row, col) = ...` once per entry and then
165 * addresses those same entries as `A.value_data()[n]`, in that order.
166 */
167 template <class T, class L = row_major, std::size_t IB = 0,
168 class IA = unbounded_array<int>, class TA = unbounded_array<T> >
169 class compressed_matrix {
170 public:
171 typedef T value_type;
172 typedef std::size_t size_type;
173
174 compressed_matrix() : _size1(0), _size2(0) { init(); }
175 compressed_matrix(std::size_t n1, std::size_t n2) : _size1(n1), _size2(n2) { init(); }
176 compressed_matrix(std::size_t n1, std::size_t n2, std::size_t nnz)
177 : _size1(n1), _size2(n2) { init(); (void)nnz; }
178
179 T& operator()(std::size_t i, std::size_t j) {
180 std::size_t major = is_column_major() ? j : i;
181 std::size_t minor = is_column_major() ? i : j;
182 std::size_t lo = (std::size_t)_index1[major];
183 std::size_t hi = (std::size_t)_index1[major + 1];
184 for (std::size_t n = lo; n < hi; ++n) {
185 if ((std::size_t)_index2[n] == minor + IB)
186 return _value[n];
187 if ((std::size_t)_index2[n] > minor + IB)
188 return insert(n, major, minor);
189 }
190 return insert(hi, major, minor);
191 }
192
193 const T& operator()(std::size_t i, std::size_t j) const {
194 std::size_t major = is_column_major() ? j : i;
195 std::size_t minor = is_column_major() ? i : j;
196 for (std::size_t n = (std::size_t)_index1[major]; n < (std::size_t)_index1[major + 1]; ++n)
197 if ((std::size_t)_index2[n] == minor + IB)
198 return _value[n];
199 return _zero;
200 }
201
202 std::size_t size1() const { return _size1; }
203 std::size_t size2() const { return _size2; }
204 std::size_t nnz() const { return _nnz; }
205
206 TA& value_data() { return _value; }
207 const TA& value_data() const { return _value; }
208 IA& index1_data() { return _index1; }
209 const IA& index1_data() const { return _index1; }
210 IA& index2_data() { return _index2; }
211 const IA& index2_data() const { return _index2; }
212
213 /** uBLAS semantics: drop every entry, keeping the dimensions. */
214 void clear() { init(); }
215
216 void resize(std::size_t n1, std::size_t n2, bool preserve = false) {
217 (void)preserve;
218 _size1 = n1;
219 _size2 = n2;
220 init();
221 }
222
223 private:
224 static constexpr bool is_column_major() { return L::element(0, 1, 2, 2) == 2; }
225 std::size_t majors() const { return is_column_major() ? _size2 : _size1; }
226
227 void init() {
228 _nnz = 0;
229 _value = TA();
230 _index2 = IA();
231 _index1 = IA(majors() + 1, (int)IB);
232 }
233
234 T& insert(std::size_t n, std::size_t major, std::size_t minor) {
235 _value.insert(n, T());
236 _index2.insert(n, (int)(minor + IB));
237 for (std::size_t m = major + 1; m <= majors(); ++m)
238 ++_index1[m];
239 ++_nnz;
240 return _value[n];
241 }
242
243 TA _value;
244 IA _index1, _index2;
245 std::size_t _size1, _size2, _nnz;
246 T _zero = T();
247 };
248
249 } } // namespace omcpp::linalg
250 /** @} */
251