| 1 | within Modelica; |
|---|
| 2 | package Math "Library of mathematical functions (e.g., sin, cos) and of functions operating on vectors and matrices" |
|---|
| 3 | import SI = Modelica.SIunits; |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | extends Modelica.Icons.Library2; |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | annotation ( |
|---|
| 10 | Invisible=true, |
|---|
| 11 | Icon(coordinateSystem(preserveAspectRatio=true, extent={{-100,-100},{100,100}}), |
|---|
| 12 | graphics={Text( |
|---|
| 13 | extent={{-59,-9},{42,-56}}, |
|---|
| 14 | lineColor={0,0,0}, |
|---|
| 15 | textString="f(x)")}), |
|---|
| 16 | Documentation(info="<HTML> |
|---|
| 17 | <p> |
|---|
| 18 | This package contains <b>basic mathematical functions</b> (such as sin(..)), |
|---|
| 19 | as well as functions operating on <b>vectors</b> and <b>matrices</b>. |
|---|
| 20 | </p> |
|---|
| 21 | |
|---|
| 22 | <dl> |
|---|
| 23 | <dt><b>Main Author:</b> |
|---|
| 24 | <dd><a href=\"http://www.robotic.dlr.de/Martin.Otter/\">Martin Otter</a><br> |
|---|
| 25 | Deutsches Zentrum für Luft und Raumfahrt e.V. (DLR)<br> |
|---|
| 26 | Institut für Robotik und Mechatronik<br> |
|---|
| 27 | Postfach 1116<br> |
|---|
| 28 | D-82230 Wessling<br> |
|---|
| 29 | Germany<br> |
|---|
| 30 | email: <A HREF=\"mailto:Martin.Otter@dlr.de\">Martin.Otter@dlr.de</A><br> |
|---|
| 31 | </dl> |
|---|
| 32 | |
|---|
| 33 | <p> |
|---|
| 34 | Copyright © 1998-2008, Modelica Association and DLR. |
|---|
| 35 | </p> |
|---|
| 36 | <p> |
|---|
| 37 | <i>This Modelica package is <b>free</b> software; it can be redistributed and/or modified |
|---|
| 38 | under the terms of the <b>Modelica license</b>, see the license conditions |
|---|
| 39 | and the accompanying <b>disclaimer</b> |
|---|
| 40 | <a href=\"Modelica://Modelica.UsersGuide.ModelicaLicense\">here</a>.</i> |
|---|
| 41 | </p><br> |
|---|
| 42 | </HTML> |
|---|
| 43 | ", revisions="<html> |
|---|
| 44 | <ul> |
|---|
| 45 | <li><i>October 21, 2002</i> |
|---|
| 46 | by <a href=\"http://www.robotic.dlr.de/Martin.Otter/\">Martin Otter</a> |
|---|
| 47 | and <a href=\"http://www.robotic.dlr.de/Christian.Schweiger/\">Christian Schweiger</a>:<br> |
|---|
| 48 | Function tempInterpol2 added.</li> |
|---|
| 49 | <li><i>Oct. 24, 1999</i> |
|---|
| 50 | by <a href=\"http://www.robotic.dlr.de/Martin.Otter/\">Martin Otter</a>:<br> |
|---|
| 51 | Icons for icon and diagram level introduced.</li> |
|---|
| 52 | <li><i>June 30, 1999</i> |
|---|
| 53 | by <a href=\"http://www.robotic.dlr.de/Martin.Otter/\">Martin Otter</a>:<br> |
|---|
| 54 | Realized.</li> |
|---|
| 55 | </ul> |
|---|
| 56 | |
|---|
| 57 | </html>")); |
|---|
| 58 | |
|---|
| 59 | |
|---|
| 60 | package Vectors "Library of functions operating on vectors" |
|---|
| 61 | extends Modelica.Icons.Library; |
|---|
| 62 | |
|---|
| 63 | annotation ( |
|---|
| 64 | preferedView = "info", |
|---|
| 65 | Documentation(info="<HTML> |
|---|
| 66 | <h4>Library content</h4> |
|---|
| 67 | <p> |
|---|
| 68 | This library provides functions operating on vectors: |
|---|
| 69 | </p> |
|---|
| 70 | <table border=1 cellspacing=0 cellpadding=2> |
|---|
| 71 | <tr><th><i>Function</i></th> |
|---|
| 72 | <th><i>Description</i></th> |
|---|
| 73 | </tr> |
|---|
| 74 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Vectors.isEqual\">isEqual</a>(v1, v2)</td> |
|---|
| 75 | <td valign=\"top\">Determines whether two vectors have the same size and elements</td> |
|---|
| 76 | </tr> |
|---|
| 77 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Vectors.norm\">norm</a>(v,p)</td> |
|---|
| 78 | <td valign=\"top\">p-norm of vector v</td> |
|---|
| 79 | </tr> |
|---|
| 80 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Vectors.length\">length</a>(v)</td> |
|---|
| 81 | <td valign=\"top\">Length of vector v (= norm(v,2), but inlined and therefore usable in |
|---|
| 82 | symbolic manipulations) </td> |
|---|
| 83 | </tr> |
|---|
| 84 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Vectors.normalize\">normalize</a>(v)</td> |
|---|
| 85 | <td valign=\"top\">Return normalized vector such that length = 1 and prevent |
|---|
| 86 | zero-division for zero vector</td> |
|---|
| 87 | </tr> |
|---|
| 88 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Vectors.reverse\">reverse</a>(v)</td> |
|---|
| 89 | <td valign=\"top\">Reverse vector elements</td> |
|---|
| 90 | </tr> |
|---|
| 91 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Vectors.sort\">sort</a>(v)</td> |
|---|
| 92 | <td valign=\"top\">Sort elements of vector in ascending or descending order</td> |
|---|
| 93 | </tr> |
|---|
| 94 | </table> |
|---|
| 95 | <h4>See also</h4> |
|---|
| 96 | <a href=\"Modelica://Modelica.Math.Matrices\">Matrices</a> |
|---|
| 97 | </HTML>")); |
|---|
| 98 | |
|---|
| 99 | function isEqual "Determine if two Real vectors are numerically identical" |
|---|
| 100 | extends Modelica.Icons.Function; |
|---|
| 101 | input Real v1[:] "First vector"; |
|---|
| 102 | input Real v2[:] "Second vector (may have different length as v1"; |
|---|
| 103 | input Real eps(min=0) = 0 |
|---|
| 104 | "Two elements e1 and e2 of the two vectors are identical if abs(e1-e2) <= eps"; |
|---|
| 105 | output Boolean result |
|---|
| 106 | "= true, if vectors have the same length and the same elements"; |
|---|
| 107 | |
|---|
| 108 | annotation ( Documentation(info="<HTML> |
|---|
| 109 | <h4>Syntax</h4> |
|---|
| 110 | <blockquote><pre> |
|---|
| 111 | Vectors.<b>isEqual</b>(v1, v2); |
|---|
| 112 | Vectors.<b>isEqual</b>(v1, v2, eps=0); |
|---|
| 113 | </pre></blockquote> |
|---|
| 114 | <h4>Description</h4> |
|---|
| 115 | <p> |
|---|
| 116 | The function call \"<code>Vectors.isEqual(v1, v2)</code>\" returns <b>true</b>, |
|---|
| 117 | if the two Real vectors v1 and v2 have the same dimensions and |
|---|
| 118 | the same elements. Otherwise the function |
|---|
| 119 | returns <b>false</b>. Two elements e1 and e2 of the two vectors |
|---|
| 120 | are checked on equality by the test \"abs(e1-e2) ≤ eps\", where \"eps\" |
|---|
| 121 | can be provided as third argument of the function. Default is \"eps = 0\". |
|---|
| 122 | </p>Modelica.Utilities.Strings.isEqual |
|---|
| 123 | <h4>Example</h4> |
|---|
| 124 | <blockquote><pre> |
|---|
| 125 | Real v1[3] = {1, 2, 3}; |
|---|
| 126 | Real v2[3] = {1, 2, 3, 4}; |
|---|
| 127 | Real v3[3] = {1, 2, 3.0001}; |
|---|
| 128 | Boolean result; |
|---|
| 129 | <b>algorithm</b> |
|---|
| 130 | result := Vectors.isEqual(v1,v2); // = <b>false</b> |
|---|
| 131 | result := Vectors.isEqual(v1,v3); // = <b>false</b> |
|---|
| 132 | result := Vectors.isEqual(v1,v1); // = <b>true</b> |
|---|
| 133 | result := Vectors.isEqual(v1,v3,0.1); // = <b>true</b> |
|---|
| 134 | </pre></blockquote> |
|---|
| 135 | <h4>See also</h4> |
|---|
| 136 | <a href=\"Modelica://Modelica.Math.Matrices.isEqual\">Matrices.isEqual</a>, |
|---|
| 137 | <a href=\"Modelica://Modelica.Utilities.Strings.isEqual\">Strings.isEqual</a> |
|---|
| 138 | </HTML>")); |
|---|
| 139 | protected |
|---|
| 140 | Integer n=size(v1, 1) "Dimension of vector v1"; |
|---|
| 141 | Integer i=1; |
|---|
| 142 | algorithm |
|---|
| 143 | result := false; |
|---|
| 144 | if size(v2, 1) == n then |
|---|
| 145 | result := true; |
|---|
| 146 | while i <= n loop |
|---|
| 147 | if abs(v1[i] - v2[i]) > eps then |
|---|
| 148 | result := false; |
|---|
| 149 | i := n; |
|---|
| 150 | end if; |
|---|
| 151 | i := i + 1; |
|---|
| 152 | end while; |
|---|
| 153 | end if; |
|---|
| 154 | end isEqual; |
|---|
| 155 | |
|---|
| 156 | function norm "Return the p-norm of a vector" |
|---|
| 157 | extends Modelica.Icons.Function; |
|---|
| 158 | input Real v[:] "Vector"; |
|---|
| 159 | input Real p(min=1) = 2 |
|---|
| 160 | "Type of p-norm (often used: 1, 2, or Modelica.Constants.inf)"; |
|---|
| 161 | output Real result "p-norm of vector v"; |
|---|
| 162 | |
|---|
| 163 | annotation ( Documentation(info="<HTML> |
|---|
| 164 | <h4>Syntax</h4> |
|---|
| 165 | <blockquote><pre> |
|---|
| 166 | Vectors.<b>norm</b>(v); |
|---|
| 167 | Vectors.<b>norm</b>(v,p=2); // 1 ≤ p ≤ ∞ |
|---|
| 168 | </pre></blockquote> |
|---|
| 169 | <h4>Description</h4> |
|---|
| 170 | <p> |
|---|
| 171 | The function call \"<code>Vectors.<b>norm</b>(v)</code>\" returns the |
|---|
| 172 | <b>Euclidean norm</b> \"<code>sqrt(v*v)</code>\" of vector v. |
|---|
| 173 | With the optional |
|---|
| 174 | second argument \"p\", any other p-norm can be computed: |
|---|
| 175 | </p> |
|---|
| 176 | <center> |
|---|
| 177 | <IMG SRC=\"../Images/Math/vectorNorm.png\" ALT=\"function Vectors.norm\"> |
|---|
| 178 | </center> |
|---|
| 179 | <p> |
|---|
| 180 | Besides the Euclidean norm (p=2), also the 1-norm and the |
|---|
| 181 | infinity-norm are sometimes used: |
|---|
| 182 | </p> |
|---|
| 183 | <table border=1 cellspacing=0 cellpadding=2> |
|---|
| 184 | <tr><td valign=\"top\"><b>1-norm</b></td> |
|---|
| 185 | <td valign=\"top\">= sum(abs(v))</td> |
|---|
| 186 | <td valign=\"top\"><b>norm</b>(v,1)</td> |
|---|
| 187 | </tr> |
|---|
| 188 | <tr><td valign=\"top\"><b>2-norm</b></td> |
|---|
| 189 | <td valign=\"top\">= sqrt(v*v)</td> |
|---|
| 190 | <td valign=\"top\"><b>norm</b>(v) or <b>norm</b>(v,2)</td> |
|---|
| 191 | </tr> |
|---|
| 192 | <tr><td valign=\"top\"><b>infinity-norm</b></td> |
|---|
| 193 | <td valign=\"top\">= max(abs(v))</td> |
|---|
| 194 | <td valign=\"top\"><b>norm</b>(v,Modelica.Constants.<b>inf</b>)</td> |
|---|
| 195 | </tr> |
|---|
| 196 | </table> |
|---|
| 197 | <p> |
|---|
| 198 | Note, for any vector norm the following inequality holds: |
|---|
| 199 | </p> |
|---|
| 200 | <blockquote><pre> |
|---|
| 201 | <b>norm</b>(v1+v2,p) ≤ <b>norm</b>(v1,p) + <b>norm</b>(v2,p) |
|---|
| 202 | </pre></blockquote> |
|---|
| 203 | <h4>Example</h4> |
|---|
| 204 | <blockquote><pre> |
|---|
| 205 | v = {2, -4, -2, -1}; |
|---|
| 206 | <b>norm</b>(v,1); // = 9 |
|---|
| 207 | <b>norm</b>(v,2); // = 5 |
|---|
| 208 | <b>norm</b>(v); // = 5 |
|---|
| 209 | <b>norm</b>(v,10.5); // = 4.00052597412635 |
|---|
| 210 | <b>norm</b>(v,Modelica.Constants.inf); // = 4 |
|---|
| 211 | </pre></blockquote> |
|---|
| 212 | <h4>See also</h4> |
|---|
| 213 | <a href=\"Modelica://Modelica.Math.Matrices.norm\">Matrices.norm</a> |
|---|
| 214 | </HTML>")); |
|---|
| 215 | algorithm |
|---|
| 216 | if p == 2 then |
|---|
| 217 | result:=sqrt(v*v); |
|---|
| 218 | elseif p == Modelica.Constants.inf then |
|---|
| 219 | result:=max(abs(v)); |
|---|
| 220 | elseif p == 1 then |
|---|
| 221 | result:=sum(abs(v)); |
|---|
| 222 | else |
|---|
| 223 | result:=(sum(abs(v[i])^p for i in 1:size(v, 1)))^(1/p); |
|---|
| 224 | end if; |
|---|
| 225 | end norm; |
|---|
| 226 | |
|---|
| 227 | function length |
|---|
| 228 | "Return length of a vectorReturn length of a vector (better as norm(), if further symbolic processing is performed)" |
|---|
| 229 | extends Modelica.Icons.Function; |
|---|
| 230 | input Real v[:] "Vector"; |
|---|
| 231 | output Real result "Length of vector v"; |
|---|
| 232 | annotation (Inline=true, Documentation(info="<html> |
|---|
| 233 | <h4>Syntax</h4> |
|---|
| 234 | <blockquote><pre> |
|---|
| 235 | Vectors.<b>length</b>(v); |
|---|
| 236 | </pre></blockquote> |
|---|
| 237 | <h4>Description</h4> |
|---|
| 238 | <p> |
|---|
| 239 | The function call \"<code>Vectors.<b>length</b>(v)</code>\" returns the |
|---|
| 240 | <b>Euclidean length</b> \"<code>sqrt(v*v)</code>\" of vector v. |
|---|
| 241 | The function call is equivalent to Vectors.norm(v). The advantage of |
|---|
| 242 | length(v) over norm(v)\"is that function length(..) is implemented |
|---|
| 243 | in one statement and therefore the function is usually automatically |
|---|
| 244 | inlined. Further symbolic processing is therefore possible, which is |
|---|
| 245 | not the case with function norm(..). |
|---|
| 246 | </p> |
|---|
| 247 | <h4>Example</h4> |
|---|
| 248 | <blockquote><pre> |
|---|
| 249 | v = {2, -4, -2, -1}; |
|---|
| 250 | <b>length</b>(v); // = 5 |
|---|
| 251 | </pre></blockquote> |
|---|
| 252 | <h4>See also</h4> |
|---|
| 253 | <a href=\"Modelica://Modelica.Math.Vectors.norm\">Vectors.norm</a> |
|---|
| 254 | </html>")); |
|---|
| 255 | algorithm |
|---|
| 256 | result := sqrt(v*v); |
|---|
| 257 | end length; |
|---|
| 258 | |
|---|
| 259 | function normalize |
|---|
| 260 | "Return normalized vector such that length = 1Return normalized vector such that length = 1 and prevent zero-division for zero vector" |
|---|
| 261 | extends Modelica.Icons.Function; |
|---|
| 262 | input Real v[:] "Vector"; |
|---|
| 263 | input Real eps = 100*Modelica.Constants.eps |
|---|
| 264 | "if |v| < eps then result = v/eps"; |
|---|
| 265 | output Real result[size(v, 1)] "Input vector v normalized to length=1"; |
|---|
| 266 | |
|---|
| 267 | annotation (Inline=true, Documentation(info="<html> |
|---|
| 268 | <h4>Syntax</h4> |
|---|
| 269 | <blockquote><pre> |
|---|
| 270 | Vectors.<b>normalize</b>(v); |
|---|
| 271 | Vectors.<b>normalize</b>(v,eps=100*Modelica.Constants.eps); |
|---|
| 272 | </pre></blockquote> |
|---|
| 273 | <h4>Description</h4> |
|---|
| 274 | <p> |
|---|
| 275 | The function call \"<code>Vectors.<b>normalize</b>(v)</code>\" returns the |
|---|
| 276 | <b>unit vector</b> \"<code>v/length(v)</code>\" of vector v. |
|---|
| 277 | If length(v) is close to zero (more precisely, if length(v) < eps), |
|---|
| 278 | v/eps is returned in order to avoid |
|---|
| 279 | a division by zero. For many applications this is useful, because |
|---|
| 280 | often the unit vector <b>e</b> = <b>v</b>/length(<b>v</b>) is used to compute |
|---|
| 281 | a vector x*<b>e</b>, where the scalar x is in the order of length(<b>v</b>), |
|---|
| 282 | i.e., x*<b>e</b> is small, when length(<b>v</b>) is small and then |
|---|
| 283 | it is fine to replace <b>e</b> by <b>v</b> to avoid a division by zero. |
|---|
| 284 | </p> |
|---|
| 285 | <p> |
|---|
| 286 | Since the function is implemented in one statement, |
|---|
| 287 | it is usually inlined and therefore symbolic processing is |
|---|
| 288 | possible. |
|---|
| 289 | </p> |
|---|
| 290 | <h4>Example</h4> |
|---|
| 291 | <blockquote><pre> |
|---|
| 292 | <b>normalize</b>({1,2,3}); // = {0.267, 0.534, 0.802} |
|---|
| 293 | <b>normalize</b>({0,0,0}); // = {0,0,0} |
|---|
| 294 | </pre></blockquote> |
|---|
| 295 | <h4>See also</h4> |
|---|
| 296 | <a href=\"Modelica://Modelica.Math.Vectors.length\">Vectors.length</a> |
|---|
| 297 | </html>")); |
|---|
| 298 | algorithm |
|---|
| 299 | result := smooth(0,if length(v) >= eps then v/length(v) else v/eps); |
|---|
| 300 | end normalize; |
|---|
| 301 | |
|---|
| 302 | function reverse "Reverse vector elements (e.g. v[1] becomes last element)" |
|---|
| 303 | extends Modelica.Icons.Function; |
|---|
| 304 | input Real v[:] "Vector"; |
|---|
| 305 | output Real result[size(v, 1)] "Elements of vector v in reversed order"; |
|---|
| 306 | |
|---|
| 307 | annotation (Inline=true, Documentation(info="<html> |
|---|
| 308 | <h4>Syntax</h4> |
|---|
| 309 | <blockquote><pre> |
|---|
| 310 | Vectors.<b>reverse</b>(v); |
|---|
| 311 | </pre></blockquote> |
|---|
| 312 | <h4>Description</h4> |
|---|
| 313 | <p> |
|---|
| 314 | The function call \"<code>Vectors.<b>reverse</b>(v)</code>\" returns the |
|---|
| 315 | vector elements in reverse order. |
|---|
| 316 | </p> |
|---|
| 317 | <h4>Example</h4> |
|---|
| 318 | <blockquote><pre> |
|---|
| 319 | <b>reverse</b>({1,2,3,4}); // = {4,3,2,1} |
|---|
| 320 | </pre></blockquote> |
|---|
| 321 | </html>")); |
|---|
| 322 | algorithm |
|---|
| 323 | result := {v[end-i+1] for i in 1:size(v,1)}; |
|---|
| 324 | end reverse; |
|---|
| 325 | |
|---|
| 326 | function sort "Sort elements of vector in ascending or descending order" |
|---|
| 327 | extends Modelica.Icons.Function; |
|---|
| 328 | input Real v[:] "Vector to be sorted"; |
|---|
| 329 | input Boolean ascending = true |
|---|
| 330 | "= true if ascending order, otherwise descending order"; |
|---|
| 331 | output Real sorted_v[size(v,1)] = v "Sorted vector"; |
|---|
| 332 | output Integer indices[size(v,1)] = 1:size(v,1) "sorted_v = v[indices]"; |
|---|
| 333 | |
|---|
| 334 | annotation (Documentation(info="<HTML> |
|---|
| 335 | <h4>Syntax</h4> |
|---|
| 336 | <blockquote><pre> |
|---|
| 337 | sorted_v = Vectors.<b>sort</b>(v); |
|---|
| 338 | (sorted_v, indices) = Vectors.<b>sort</b>(v, ascending=true); |
|---|
| 339 | </pre></blockquote> |
|---|
| 340 | <h4>Description</h4> |
|---|
| 341 | <p> |
|---|
| 342 | Function <b>sort</b>(..) sorts a Real vector v |
|---|
| 343 | in ascending order and returns the result in sorted_v. |
|---|
| 344 | If the optional argument \"ascending\" is <b>false</b>, the vector |
|---|
| 345 | is sorted in descending order. In the optional second |
|---|
| 346 | output argument the indices of the sorted vector with respect |
|---|
| 347 | to the original vector are given, such that sorted_v = v[indices]. |
|---|
| 348 | </p> |
|---|
| 349 | <h4>Example</h4> |
|---|
| 350 | <blockquote><pre> |
|---|
| 351 | (v2, i2) := Vectors.sort({-1, 8, 3, 6, 2}); |
|---|
| 352 | -> v2 = {-1, 2, 3, 6, 8} |
|---|
| 353 | i2 = {1, 5, 3, 4, 2} |
|---|
| 354 | </pre></blockquote> |
|---|
| 355 | </HTML>")); |
|---|
| 356 | /* shellsort algorithm; should be improved later */ |
|---|
| 357 | protected |
|---|
| 358 | Integer gap; |
|---|
| 359 | Integer i; |
|---|
| 360 | Integer j; |
|---|
| 361 | Real wv; |
|---|
| 362 | Integer wi; |
|---|
| 363 | Integer nv = size(v,1); |
|---|
| 364 | Boolean swap; |
|---|
| 365 | algorithm |
|---|
| 366 | gap := div(nv,2); |
|---|
| 367 | |
|---|
| 368 | while gap > 0 loop |
|---|
| 369 | i := gap; |
|---|
| 370 | while i < nv loop |
|---|
| 371 | j := i-gap; |
|---|
| 372 | if j>=0 then |
|---|
| 373 | if ascending then |
|---|
| 374 | swap := sorted_v[j+1] > sorted_v[j + gap + 1]; |
|---|
| 375 | else |
|---|
| 376 | swap := sorted_v[j+1] < sorted_v[j + gap + 1]; |
|---|
| 377 | end if; |
|---|
| 378 | else |
|---|
| 379 | swap := false; |
|---|
| 380 | end if; |
|---|
| 381 | |
|---|
| 382 | while swap loop |
|---|
| 383 | wv := sorted_v[j+1]; |
|---|
| 384 | wi := indices[j+1]; |
|---|
| 385 | sorted_v[j+1] := sorted_v[j+gap+1]; |
|---|
| 386 | sorted_v[j+gap+1] := wv; |
|---|
| 387 | indices[j+1] := indices[j+gap+1]; |
|---|
| 388 | indices[j+gap+1] := wi; |
|---|
| 389 | j := j - gap; |
|---|
| 390 | if j >= 0 then |
|---|
| 391 | if ascending then |
|---|
| 392 | swap := sorted_v[j+1] > sorted_v[j + gap + 1]; |
|---|
| 393 | else |
|---|
| 394 | swap := sorted_v[j+1] < sorted_v[j + gap + 1]; |
|---|
| 395 | end if; |
|---|
| 396 | else |
|---|
| 397 | swap := false; |
|---|
| 398 | end if; |
|---|
| 399 | end while; |
|---|
| 400 | i := i + 1; |
|---|
| 401 | end while; |
|---|
| 402 | gap := div(gap,2); |
|---|
| 403 | end while; |
|---|
| 404 | end sort; |
|---|
| 405 | end Vectors; |
|---|
| 406 | |
|---|
| 407 | |
|---|
| 408 | package Matrices "Library of functions operating on matrices" |
|---|
| 409 | |
|---|
| 410 | extends Modelica.Icons.Library; |
|---|
| 411 | |
|---|
| 412 | annotation ( |
|---|
| 413 | version="0.8.1", |
|---|
| 414 | versionDate="2004-08-21", |
|---|
| 415 | Documentation(info="<HTML> |
|---|
| 416 | <h4>Library content</h4> |
|---|
| 417 | <p> |
|---|
| 418 | This library provides functions operating on matrices: |
|---|
| 419 | </p> |
|---|
| 420 | <table border=1 cellspacing=0 cellpadding=2> |
|---|
| 421 | <tr><th><i>Function</i></th> |
|---|
| 422 | <th><i>Description</i></th> |
|---|
| 423 | </tr> |
|---|
| 424 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.isEqual\">isEqual</a>(M1, M2)</td> |
|---|
| 425 | <td valign=\"top\">Determines whether two matrices have the same size and elements</td> |
|---|
| 426 | </tr> |
|---|
| 427 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.norm\">norm</a>(A)</td> |
|---|
| 428 | <td valign=\"top\">1-, 2- and infinity-norm of matrix A</td> |
|---|
| 429 | </tr> |
|---|
| 430 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.sort\">sort</a>(M)</td> |
|---|
| 431 | <td valign=\"top\">Sort rows or columns of matrix in ascending or descending order</td> |
|---|
| 432 | </tr> |
|---|
| 433 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.solve\">solve</a>(A,b)</td> |
|---|
| 434 | <td valign=\"top\">Solve real system of linear equations A*x=b with a b vector</td> |
|---|
| 435 | </tr> |
|---|
| 436 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.solve2\">solve2</a>(A,B)</td> |
|---|
| 437 | <td valign=\"top\">Solve real system of linear equations A*X=B with a B matrix</td> |
|---|
| 438 | </tr> |
|---|
| 439 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.leastSquares\">leastSquares</a>(A,b)</td> |
|---|
| 440 | <td valign=\"top\">Solve overdetermined or underdetermined real system of <br> |
|---|
| 441 | linear equations A*x=b in a least squares sense</td> |
|---|
| 442 | </tr> |
|---|
| 443 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.equalityLeastSquares\">equalityLeastSquares</a>(A,a,B,b)</td> |
|---|
| 444 | <td valign=\"top\">Solve a linear equality constrained least squares problem:<br> |
|---|
| 445 | min|A*x-a|^2 subject to B*x=b</td> |
|---|
| 446 | </tr> |
|---|
| 447 | <tr><td valign=\"top\">(LU,p,info) = <a href=\"Modelica://Modelica.Math.Matrices.LU\">LU</a>(A)</td> |
|---|
| 448 | <td valign=\"top\">LU decomposition of square or rectangular matrix</td> |
|---|
| 449 | </tr> |
|---|
| 450 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.LU_solve\">LU_solve</a>(LU,p,b)</td> |
|---|
| 451 | <td valign=\"top\">Solve real system of linear equations P*L*U*x=b with a<br> |
|---|
| 452 | b vector and an LU decomposition from \"LU(..)\"</td> |
|---|
| 453 | </tr> |
|---|
| 454 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.LU_solve2\">LU_solve2</a>(LU,p,B)</td> |
|---|
| 455 | <td valign=\"top\">Solve real system of linear equations P*L*U*X=B with a<br> |
|---|
| 456 | B matrix and an LU decomposition from \"LU(..)\"</td> |
|---|
| 457 | </tr> |
|---|
| 458 | <tr><td valign=\"top\">(Q,R,p) = <a href=\"Modelica://Modelica.Math.Matrices.QR\">QR</a>(A)</td> |
|---|
| 459 | <td valign=\"top\"> QR decomposition with column pivoting of rectangular matrix (Q*R = A[:,p]) </td> |
|---|
| 460 | </tr> |
|---|
| 461 | <tr><td valign=\"top\">eval = <a href=\"Modelica://Modelica.Math.Matrices.eigenValues\">eigenValues</a>(A)<br> |
|---|
| 462 | (eval,evec) = <a href=\"Modelica://Modelica.Math.Matrices.eigenValues\">eigenValues</a>(A)</td> |
|---|
| 463 | <td valign=\"top\"> Compute eigenvalues and optionally eigenvectors<br> |
|---|
| 464 | for a real, nonsymmetric matrix </td> |
|---|
| 465 | </tr> |
|---|
| 466 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.eigenValueMatrix\">eigenValueMatrix</a>(eigen)</td> |
|---|
| 467 | <td valign=\"top\"> Return real valued block diagonal matrix J of eigenvalues of |
|---|
| 468 | matrix A (A=V*J*Vinv) </td> |
|---|
| 469 | </tr> |
|---|
| 470 | <tr><td valign=\"top\">sigma = <a href=\"Modelica://Modelica.Math.Matrices.singularValues\">singularValues</a>(A)<br> |
|---|
| 471 | (sigma,U,VT) = <a href=\"Modelica://Modelica.Math.Matrices.singularValues\">singularValues</a>(A)</td> |
|---|
| 472 | <td valign=\"top\"> Compute singular values and optionally left and right singular vectors </td> |
|---|
| 473 | </tr> |
|---|
| 474 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.det\">det</a>(A)</td> |
|---|
| 475 | <td valign=\"top\"> Determinant of a matrix (do <b>not</b> use; use rank(..))</td> |
|---|
| 476 | </tr> |
|---|
| 477 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.inv\">inv</a>(A)</td> |
|---|
| 478 | <td valign=\"top\"> Inverse of a matrix </td> |
|---|
| 479 | </tr> |
|---|
| 480 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.rank\">rank</a>(A)</td> |
|---|
| 481 | <td valign=\"top\"> Rank of a matrix </td> |
|---|
| 482 | </tr> |
|---|
| 483 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.balance\">balance</a>(A)</td> |
|---|
| 484 | <td valign=\"top\">Balance a square matrix to improve the condition</td> |
|---|
| 485 | </tr> |
|---|
| 486 | <tr><td valign=\"top\"><a href=\"Modelica://Modelica.Math.Matrices.exp\">exp</a>(A)</td> |
|---|
| 487 | <td valign=\"top\"> Compute the exponential of a matrix by adaptive Taylor series<br> |
|---|
| 488 | expansion with scaling and balancing</td> |
|---|
| 489 | </tr> |
|---|
| 490 | <tr><td valign=\"top\">(P, G) = <a href=\"Modelica://Modelica.Math.Matrices.integralExp\">integralExp</a>(A,B)</td> |
|---|
| 491 | <td valign=\"top\"> Compute the exponential of a matrix and its integral</td> |
|---|
| 492 | </tr> |
|---|
| 493 | <tr><td valign=\"top\">(P, G, GT) = <a href=\"Modelica://Modelica.Math.Matrices.integralExpT\">integralExpT</a>(A,B)</td> |
|---|
| 494 | <td valign=\"top\"> Compute the exponential of a matrix and two integrals</td> |
|---|
| 495 | </tr> |
|---|
| 496 | </table> |
|---|
| 497 | |
|---|
| 498 | <p> |
|---|
| 499 | Most functions are solely an interface to the external LAPACK library |
|---|
| 500 | (<a href=\"http://www.netlib.org/lapack\">http://www.netlib.org/lapack</a>). |
|---|
| 501 | The details of this library are described in: |
|---|
| 502 | </p> |
|---|
| 503 | |
|---|
| 504 | <dl> |
|---|
| 505 | <dt>Anderson E., Bai Z., Bischof C., Blackford S., Demmel J., Dongarra J., |
|---|
| 506 | Du Croz J., Greenbaum A., Hammarling S., McKenney A., and Sorensen D.:</dt> |
|---|
| 507 | <dd> <b>Lapack Users' Guide</b>. |
|---|
| 508 | Third Edition, SIAM, 1999.</dd> |
|---|
| 509 | </dl> |
|---|
| 510 | |
|---|
| 511 | <h4>See also</h4> |
|---|
| 512 | <a href=\"Modelica://Modelica.Math.Vectors\">Vectors</a> |
|---|
| 513 | |
|---|
| 514 | </HTML> |
|---|
| 515 | ")); |
|---|
| 516 | |
|---|
| 517 | function isEqual "Compare whether two Real matrices are identical" |
|---|
| 518 | extends Modelica.Icons.Function; |
|---|
| 519 | input Real M1[:, :] "First matrix"; |
|---|
| 520 | input Real M2[:, :] "Second matrix (may have different size as M1"; |
|---|
| 521 | input Real eps(min=0) = 0 |
|---|
| 522 | "Two elements e1 and e2 of the two matrices are identical if abs(e1-e2) <= eps"; |
|---|
| 523 | output Boolean result |
|---|
| 524 | "= true, if matrices have the same size and the same elements"; |
|---|
| 525 | |
|---|
| 526 | annotation ( Documentation(info="<HTML> |
|---|
| 527 | <h4>Syntax</h4> |
|---|
| 528 | <blockquote><pre> |
|---|
| 529 | Matrices.<b>isEqual</b>(M1, M2); |
|---|
| 530 | Matrices.<b>isEqual</b>(M1, M2, eps=0); |
|---|
| 531 | </pre></blockquote> |
|---|
| 532 | <h4>Description</h4> |
|---|
| 533 | <p> |
|---|
| 534 | The function call \"<code>Matrices.isEqual(M1, M2)</code>\" returns <b>true</b>, |
|---|
| 535 | if the two Real matrices M1 and M2 have the same dimensions and |
|---|
| 536 | the same elements. Otherwise the function |
|---|
| 537 | returns <b>false</b>. Two elements e1 and e2 of the two matrices |
|---|
| 538 | are checked on equality by the test \"abs(e1-e2) ≤ eps\", where \"eps\" |
|---|
| 539 | can be provided as third argument of the function. Default is \"eps = 0\". |
|---|
| 540 | </p> |
|---|
| 541 | <h4>Example</h4> |
|---|
| 542 | <blockquote><pre> |
|---|
| 543 | Real A1[2,2] = [1,2; 3,4]; |
|---|
| 544 | Real A2[3,2] = [1,2; 3,4; 5,6]; |
|---|
| 545 | Real A3[2,2] = [1,2, 3,4.0001]; |
|---|
| 546 | Boolean result; |
|---|
| 547 | <b>algorithm</b> |
|---|
| 548 | result := Matrices.isEqual(M1,M2); // = <b>false</b> |
|---|
| 549 | result := Matrices.isEqual(M1,M3); // = <b>false</b> |
|---|
| 550 | result := Matrices.isEqual(M1,M1); // = <b>true</b> |
|---|
| 551 | result := Matrices.isEqual(M1,M3,0.1); // = <b>true</b> |
|---|
| 552 | </pre></blockquote> |
|---|
| 553 | <h4>See also</h4> |
|---|
| 554 | <a href=\"Modelica://Modelica.Math.Vectors.isEqual\">Vectors.isEqual</a>, |
|---|
| 555 | <a href=\"Modelica://Modelica.Utilities.Strings.isEqual\">Strings.isEqual</a> |
|---|
| 556 | </HTML>")); |
|---|
| 557 | protected |
|---|
| 558 | Integer nrow=size(M1, 1) "Number of rows of matrix M1"; |
|---|
| 559 | Integer ncol=size(M1, 2) "Number of columns of matrix M1"; |
|---|
| 560 | Integer i=1; |
|---|
| 561 | Integer j; |
|---|
| 562 | algorithm |
|---|
| 563 | result := false; |
|---|
| 564 | if size(M2, 1) == nrow and size(M2, 2) == ncol then |
|---|
| 565 | result := true; |
|---|
| 566 | while i <= nrow loop |
|---|
| 567 | j := 1; |
|---|
| 568 | while j <= ncol loop |
|---|
| 569 | if abs(M1[i, j] - M2[i, j]) > eps then |
|---|
| 570 | result := false; |
|---|
| 571 | i := nrow; |
|---|
| 572 | j := ncol; |
|---|
| 573 | end if; |
|---|
| 574 | j := j + 1; |
|---|
| 575 | end while; |
|---|
| 576 | i := i + 1; |
|---|
| 577 | end while; |
|---|
| 578 | end if; |
|---|
| 579 | |
|---|
| 580 | end isEqual; |
|---|
| 581 | |
|---|
| 582 | function norm "Returns the norm of a matrix" |
|---|
| 583 | extends Modelica.Icons.Function; |
|---|
| 584 | input Real A[:, :] "Input matrix"; |
|---|
| 585 | input Real p(min=1) = 2 |
|---|
| 586 | "Type of p-norm (only allowed: 1, 2 or Modelica.Constants.inf)"; |
|---|
| 587 | output Real result=0.0 "p-norm of matrix A"; |
|---|
| 588 | |
|---|
| 589 | annotation ( Documentation(info="<HTML> |
|---|
| 590 | <h4>Syntax</h4> |
|---|
| 591 | <blockquote><pre> |
|---|
| 592 | Matrices.<b>norm</b>(A); |
|---|
| 593 | Matrices.<b>norm</b>(A, p=2); |
|---|
| 594 | </pre></blockquote> |
|---|
| 595 | <h4>Description</h4> |
|---|
| 596 | <p> |
|---|
| 597 | The function call \"<code>Matrices.norm(A)</code>\" returns the |
|---|
| 598 | 2-norm of matrix A, i.e., the largest singular value of A.<br> |
|---|
| 599 | The function call \"<code>Matrices.norm(A, p)</code>\" returns the |
|---|
| 600 | p-norm of matrix A. The only allowed values for p are</p> |
|---|
| 601 | <ul> |
|---|
| 602 | <li> \"p=1\": the largest column sum of A</li> |
|---|
| 603 | <li> \"p=2\": the largest singular value of A</li> |
|---|
| 604 | <li> \"p=Modelica.Constants.inf\": the largest row sum of A</li> |
|---|
| 605 | </ul> |
|---|
| 606 | <p> |
|---|
| 607 | Note, for any matrices A1, A2 the following inequality holds: |
|---|
| 608 | </p> |
|---|
| 609 | <blockquote><pre> |
|---|
| 610 | Matrices.<b>norm</b>(A1+A2,p) ≤ Matrices.<b>norm</b>(A1,p) + Matrices.<b>norm</b>(A2,p) |
|---|
| 611 | </pre></blockquote> |
|---|
| 612 | <p> |
|---|
| 613 | Note, for any matrix A and vector v the following inequality holds: |
|---|
| 614 | </p> |
|---|
| 615 | <blockquote><pre> |
|---|
| 616 | Vectors.<b>norm</b>(A*v,p) ≤ Matrices.<b>norm</b>(A,p)*Vectors.<b>norm</b>(A,p) |
|---|
| 617 | </pre></blockquote> |
|---|
| 618 | </HTML>")); |
|---|
| 619 | algorithm |
|---|
| 620 | if p == 1 then |
|---|
| 621 | // column sum norm |
|---|
| 622 | for i in 1:size(A, 2) loop |
|---|
| 623 | result := max(result, sum(abs(A[:, i]))); |
|---|
| 624 | end for; |
|---|
| 625 | elseif p == 2 then |
|---|
| 626 | // largest singular value |
|---|
| 627 | result := max(singularValues(A)); |
|---|
| 628 | elseif p == Modelica.Constants.inf then |
|---|
| 629 | // row sum norm |
|---|
| 630 | for i in 1:size(A, 1) loop |
|---|
| 631 | result := max(result, sum(abs(A[i, :]))); |
|---|
| 632 | end for; |
|---|
| 633 | else |
|---|
| 634 | assert(false, "Optional argument \"p\" of function \"norm\" must be |
|---|
| 635 | 1, 2 or Modelica.Constants.inf"); |
|---|
| 636 | end if; |
|---|
| 637 | end norm; |
|---|
| 638 | |
|---|
| 639 | function sort |
|---|
| 640 | "Sort rows or columns of matrix in ascending or descending order" |
|---|
| 641 | extends Modelica.Icons.Function; |
|---|
| 642 | input Real M[:,:] "Matrix to be sorted"; |
|---|
| 643 | input Boolean sortRows = true |
|---|
| 644 | "= true if rows are sorted, otherwise columns"; |
|---|
| 645 | input Boolean ascending = true |
|---|
| 646 | "= true if ascending order, otherwise descending order"; |
|---|
| 647 | output Real sorted_M[size(M,1), size(M,2)] = M "Sorted matrix"; |
|---|
| 648 | output Integer indices[if sortRows then size(M,1) else size(M,2)] |
|---|
| 649 | "sorted_M = if sortRows then M[indices,:] else M[:,indices]"; |
|---|
| 650 | |
|---|
| 651 | annotation (Documentation(info="<HTML> |
|---|
| 652 | <h4>Syntax</h4> |
|---|
| 653 | <blockquote><pre> |
|---|
| 654 | sorted_M = Matrices.<b>sort</b>(M); |
|---|
| 655 | (sorted_M, indices) = Matrices.<b>sort</b>(M, sortRows=true, ascending=true); |
|---|
| 656 | </pre></blockquote> |
|---|
| 657 | <h4>Description</h4> |
|---|
| 658 | <p> |
|---|
| 659 | Function <b>sort</b>(..) sorts the rows of a Real matrix M |
|---|
| 660 | in ascending order and returns the result in sorted_M. |
|---|
| 661 | If the optional argument \"sortRows\" is <b>false</b>, the columns |
|---|
| 662 | of the matrix are sorted. |
|---|
| 663 | If the optional argument \"ascending\" is <b>false</b>, the rows or |
|---|
| 664 | columns are sorted in descending order. In the optional second |
|---|
| 665 | output argument, the indices of the sorted rows or columns with respect |
|---|
| 666 | to the original matrix are given, such that |
|---|
| 667 | </p> |
|---|
| 668 | <pre> |
|---|
| 669 | sorted_M = <b>if</b> sortedRow <b>then</b> M[indices,:] <b>else</b> M[:,indices]; |
|---|
| 670 | </pre> |
|---|
| 671 | <h4>Example</h4> |
|---|
| 672 | <blockquote><pre> |
|---|
| 673 | (M2, i2) := Matrices.sort([2, 1, 0; |
|---|
| 674 | 2, 0, -1]); |
|---|
| 675 | -> M2 = [2, 0, -1; |
|---|
| 676 | 2, 1, 0 ]; |
|---|
| 677 | i2 = {2,1}; |
|---|
| 678 | </pre></blockquote> |
|---|
| 679 | </HTML>")); |
|---|
| 680 | /* shellsort algorithm; should be improved later */ |
|---|
| 681 | protected |
|---|
| 682 | Integer gap; |
|---|
| 683 | Integer i; |
|---|
| 684 | Integer j; |
|---|
| 685 | Real wM2[size(M,2)]; |
|---|
| 686 | Integer wi; |
|---|
| 687 | Integer nM1 = size(M,1); |
|---|
| 688 | Boolean swap; |
|---|
| 689 | Real sorted_MT[size(M,2), size(M,1)]; |
|---|
| 690 | |
|---|
| 691 | encapsulated function greater "Compare whether vector v1 > v2" |
|---|
| 692 | import Modelica; |
|---|
| 693 | extends Modelica.Icons.Function; |
|---|
| 694 | import Modelica.Utilities.Types.Compare; |
|---|
| 695 | input Real v1[:]; |
|---|
| 696 | input Real v2[size(v1,1)]; |
|---|
| 697 | output Boolean result; |
|---|
| 698 | protected |
|---|
| 699 | Integer n = size(v1,1); |
|---|
| 700 | Integer |
|---|