OMCompiler/Compiler/Util/Array.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 package Array | ||
| 37 | " file: Array.mo | ||
| 38 | package: Array | ||
| 39 | description: Array functions | ||
| 40 | |||
| 41 | " | ||
| 42 | |||
| 43 | protected | ||
| 44 | import MetaModelica.Dangerous.{arrayGetNoBoundsChecking, arrayUpdateNoBoundsChecking, arrayCreateNoInit}; | ||
| 45 | import List; | ||
| 46 | |||
| 47 | public | ||
| 48 | function mapNoCopy<T> | ||
| 49 | "Takes an array and a function over the elements of the array, which is | ||
| 50 | applied for each element. Since it will update the array values the returned | ||
| 51 | array must have the same type, and thus the applied function must also return | ||
| 52 | the same type." | ||
| 53 | input array<T> inArray; | ||
| 54 | input FuncType inFunc; | ||
| 55 | output array<T> outArray = inArray; | ||
| 56 | |||
| 57 | partial function FuncType | ||
| 58 | input T inElement; | ||
| 59 | output T outElement; | ||
| 60 | end FuncType; | ||
| 61 | algorithm | ||
| 62 |
2/2✓ Branch 0 taken 29202 times.
✓ Branch 1 taken 948 times.
|
54569 | for i in 1:arrayLength(inArray) loop |
| 63 |
2/2✓ Branch 0 taken 1750 times.
✓ Branch 1 taken 22669 times.
|
24419 | arrayUpdateNoBoundsChecking(inArray, i, inFunc(arrayGetNoBoundsChecking(inArray, i))); |
| 64 | end for; | ||
| 65 | end mapNoCopy; | ||
| 66 | |||
| 67 | function mapNoCopy_1<T, ArgT> | ||
| 68 | "Same as arrayMapNoCopy, but with an additional arguments that's updated for | ||
| 69 | each call." | ||
| 70 | input array<T> inArray; | ||
| 71 | input FuncType inFunc; | ||
| 72 | input ArgT inArg; | ||
| 73 | output array<T> outArray = inArray; | ||
| 74 | output ArgT outArg = inArg; | ||
| 75 | |||
| 76 | partial function FuncType | ||
| 77 | input tuple<T, ArgT> inTuple; | ||
| 78 | output tuple<T, ArgT> outTuple; | ||
| 79 | end FuncType; | ||
| 80 | protected | ||
| 81 | T e; | ||
| 82 | algorithm | ||
| 83 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
97 | for i in 1:arrayLength(inArray) loop |
| 84 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 89 times.
|
89 | (e, outArg) := inFunc((arrayGetNoBoundsChecking(inArray, i), outArg)); |
| 85 | arrayUpdateNoBoundsChecking(inArray, i, e); | ||
| 86 | end for; | ||
| 87 | end mapNoCopy_1; | ||
| 88 | |||
| 89 | protected function downheap | ||
| 90 | input output array<Integer> inArray; | ||
| 91 | input Integer n; | ||
| 92 | input Integer vIn; | ||
| 93 | protected | ||
| 94 | Integer v = vIn; | ||
| 95 | Integer w = 2*v+1; | ||
| 96 | Integer tmp; | ||
| 97 | algorithm | ||
| 98 |
2/2✓ Branch 0 taken 669701 times.
✓ Branch 1 taken 470908 times.
|
1140609 | while w < n loop |
| 99 |
2/2✓ Branch 0 taken 494372 times.
✓ Branch 1 taken 175329 times.
|
669701 | if w+1 < n then |
| 100 |
2/2✓ Branch 2 taken 241380 times.
✓ Branch 3 taken 252992 times.
|
494372 | if inArray[w+2]>inArray[w+1] then |
| 101 | w := w + 1; | ||
| 102 | end if; | ||
| 103 | end if; | ||
| 104 |
2/2✓ Branch 2 taken 86997 times.
✓ Branch 3 taken 582704 times.
|
669701 | if inArray[v+1]>=inArray[w+1] then |
| 105 | 86997 | return; | |
| 106 | end if; | ||
| 107 | tmp := inArray[v+1]; | ||
| 108 | inArray[v+1] := inArray[w+1]; | ||
| 109 | 582704 | inArray[w+1] := tmp; | |
| 110 | v := w; | ||
| 111 | 582704 | w := 2*v + 1; | |
| 112 | end while; | ||
| 113 | end downheap; | ||
| 114 | |||
| 115 | public function heapSort | ||
| 116 | input output array<Integer> inArray; | ||
| 117 | protected | ||
| 118 | Integer n = arrayLength(inArray); | ||
| 119 | Integer tmp; | ||
| 120 | algorithm | ||
| 121 |
1/2✓ Branch 0 taken 136151 times.
✗ Branch 1 not taken.
|
340310 | for v in (intDiv(n,2)-1):-1:0 loop |
| 122 | 204159 | inArray := downheap(inArray, n, v); | |
| 123 | end for; | ||
| 124 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 136151 times.
|
136151 | for v in n:-1:2 loop |
| 125 | tmp := inArray[1]; | ||
| 126 | 353746 | inArray[1] := inArray[v]; | |
| 127 | 353746 | inArray[v] := tmp; | |
| 128 | 353746 | inArray := downheap(inArray, v-1, 0); | |
| 129 | end for; | ||
| 130 | end heapSort; | ||
| 131 | |||
| 132 | function findFirstOnTrue<T> | ||
| 133 | input array<T> inArray; | ||
| 134 | input FuncType inPredicate; | ||
| 135 | output Option<T> outElement; | ||
| 136 | |||
| 137 | partial function FuncType | ||
| 138 | input T inElement; | ||
| 139 | output Boolean outMatch; | ||
| 140 | end FuncType; | ||
| 141 | algorithm | ||
| 142 | outElement := NONE(); | ||
| 143 | ✗ | for e in inArray loop | |
| 144 | ✗ | if inPredicate(e) then | |
| 145 | outElement := SOME(e); | ||
| 146 | ✗ | break; | |
| 147 | end if; | ||
| 148 | end for; | ||
| 149 | end findFirstOnTrue; | ||
| 150 | |||
| 151 | function findFirstOnTrueWithIdx<T> | ||
| 152 | input array<T> inArray; | ||
| 153 | input FuncType inPredicate; | ||
| 154 | output Option<T> outElement; | ||
| 155 | output Integer idxOut = -1; | ||
| 156 | |||
| 157 | partial function FuncType | ||
| 158 | input T inElement; | ||
| 159 | output Boolean outMatch; | ||
| 160 | end FuncType; | ||
| 161 | protected | ||
| 162 | Integer idx=1; | ||
| 163 | algorithm | ||
| 164 | outElement := NONE(); | ||
| 165 | ✗ | for e in inArray loop | |
| 166 | ✗ | if inPredicate(e) then | |
| 167 | idxOut := idx; | ||
| 168 | outElement := SOME(e); | ||
| 169 | ✗ | break; | |
| 170 | end if; | ||
| 171 | ✗ | idx := idx+1; | |
| 172 | end for; | ||
| 173 | end findFirstOnTrueWithIdx; | ||
| 174 | |||
| 175 | function select<T> | ||
| 176 | "Takes an array and a list of indices, and returns a new array with the | ||
| 177 | indexed elements. Will fail if any index is out of bounds." | ||
| 178 | input array<T> inArray; | ||
| 179 | input list<Integer> inIndices; | ||
| 180 | output array<T> outArray; | ||
| 181 | protected | ||
| 182 | Integer i = 1; | ||
| 183 | algorithm | ||
| 184 | 4718 | outArray := arrayCreateNoInit(listLength(inIndices), inArray[1]); | |
| 185 | |||
| 186 |
2/2✓ Branch 0 taken 23654 times.
✓ Branch 1 taken 4718 times.
|
28372 | for e in inIndices loop |
| 187 | 23654 | arrayUpdate(outArray, i, arrayGet(inArray, e)); | |
| 188 | 23654 | i := i + 1; | |
| 189 | end for; | ||
| 190 | end select; | ||
| 191 | |||
| 192 | function map<TI, TO> | ||
| 193 | "Takes an array and a function over the elements of the array, which is | ||
| 194 | applied to each element. The updated elements will form a new array, leaving | ||
| 195 | the original array unchanged." | ||
| 196 | input array<TI> inArray; | ||
| 197 | input FuncType inFunc; | ||
| 198 | output array<TO> outArray; | ||
| 199 | |||
| 200 | partial function FuncType | ||
| 201 | input TI inElement; | ||
| 202 | output TO outElement; | ||
| 203 | end FuncType; | ||
| 204 | protected | ||
| 205 | Integer len = arrayLength(inArray); | ||
| 206 | TO res; | ||
| 207 | algorithm | ||
| 208 | // If the array is empty, use list transformations to fix the types! | ||
| 209 |
2/2✓ Branch 0 taken 3977 times.
✓ Branch 1 taken 2397411 times.
|
2401388 | if len == 0 then |
| 210 | 3977 | outArray := listArray({}); | |
| 211 | else | ||
| 212 | // If the array isn't empty, use the first element to create the new array. | ||
| 213 |
2/2✓ Branch 0 taken 2377474 times.
✓ Branch 1 taken 19937 times.
|
2397411 | res := inFunc(arrayGetNoBoundsChecking(inArray, 1)); |
| 214 | 2397398 | outArray := arrayCreateNoInit(len, res); | |
| 215 | arrayUpdateNoBoundsChecking(outArray, 1, res); | ||
| 216 | |||
| 217 |
2/2✓ Branch 0 taken 511748 times.
✓ Branch 1 taken 1885650 times.
|
23525183 | for i in 2:len loop |
| 218 |
2/2✓ Branch 0 taken 20974037 times.
✓ Branch 1 taken 153753 times.
|
21127790 | arrayUpdateNoBoundsChecking(outArray, i, inFunc(arrayGetNoBoundsChecking(inArray, i))); |
| 219 | end for; | ||
| 220 | end if; | ||
| 221 | end map; | ||
| 222 | |||
| 223 | function map1<TI, TO, ArgT> | ||
| 224 | "Takes an array, an extra arguments, and a function over the elements of the | ||
| 225 | array, which is applied to each element. The updated elements will form a new | ||
| 226 | array, leaving the original array unchanged." | ||
| 227 | input array<TI> inArray; | ||
| 228 | input FuncType inFunc; | ||
| 229 | input ArgT inArg; | ||
| 230 | output array<TO> outArray; | ||
| 231 | |||
| 232 | partial function FuncType | ||
| 233 | input TI inElement; | ||
| 234 | input ArgT inArg; | ||
| 235 | output TO outElement; | ||
| 236 | end FuncType; | ||
| 237 | protected | ||
| 238 | Integer len = arrayLength(inArray); | ||
| 239 | TO res; | ||
| 240 | algorithm | ||
| 241 | // If the array is empty, use list transformations to fix the types! | ||
| 242 |
2/2✓ Branch 0 taken 354 times.
✓ Branch 1 taken 16183 times.
|
16537 | if len == 0 then |
| 243 | 354 | outArray := listArray({}); | |
| 244 | else | ||
| 245 | // If the array isn't empty, use the first element to create the new array. | ||
| 246 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16183 times.
|
16183 | res := inFunc(arrayGetNoBoundsChecking(inArray, 1), inArg); |
| 247 | 16183 | outArray := arrayCreateNoInit(len, res); | |
| 248 | 16183 | arrayUpdate(outArray, 1, res); | |
| 249 | |||
| 250 |
2/2✓ Branch 0 taken 11211 times.
✓ Branch 1 taken 4972 times.
|
261810 | for i in 2:len loop |
| 251 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 245627 times.
|
245627 | arrayUpdate(outArray, i, inFunc(arrayGetNoBoundsChecking(inArray, i), inArg)); |
| 252 | end for; | ||
| 253 | end if; | ||
| 254 | end map1; | ||
| 255 | |||
| 256 | function map1Ind<TI, TO, ArgT> | ||
| 257 | "Takes an array, an extra arguments, and a function over the elements of the | ||
| 258 | array, which is applied to each element. The index is passed as an extra | ||
| 259 | argument. The updated elements will form a new | ||
| 260 | array, leaving the original array unchanged." | ||
| 261 | input array<TI> inArray; | ||
| 262 | input FuncType inFunc; | ||
| 263 | input ArgT inArg; | ||
| 264 | output array<TO> outArray; | ||
| 265 | |||
| 266 | partial function FuncType | ||
| 267 | input TI inElement; | ||
| 268 | input Integer index; | ||
| 269 | input ArgT inArg; | ||
| 270 | output TO outElement; | ||
| 271 | end FuncType; | ||
| 272 | protected | ||
| 273 | Integer len = arrayLength(inArray); | ||
| 274 | TO res; | ||
| 275 | algorithm | ||
| 276 | // If the array is empty, use list transformations to fix the types! | ||
| 277 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if len == 0 then |
| 278 | ✗ | outArray := listArray({}); | |
| 279 | else | ||
| 280 | // If the array isn't empty, use the first element to create the new array. | ||
| 281 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | res := inFunc(arrayGetNoBoundsChecking(inArray, 1), 1, inArg); |
| 282 | 1 | outArray := arrayCreateNoInit(len, res); | |
| 283 | 1 | arrayUpdate(outArray, 1, res); | |
| 284 | |||
| 285 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
52 | for i in 2:len loop |
| 286 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
|
51 | arrayUpdate(outArray, i, inFunc(arrayGetNoBoundsChecking(inArray, i), i, inArg)); |
| 287 | end for; | ||
| 288 | end if; | ||
| 289 | end map1Ind; | ||
| 290 | |||
| 291 | function mapList<TI, TO> | ||
| 292 | "As map, but takes a list in and creates an array from the result." | ||
| 293 | input list<TI> inList; | ||
| 294 | input FuncType inFunc; | ||
| 295 | output array<TO> outArray; | ||
| 296 | |||
| 297 | partial function FuncType | ||
| 298 | input TI inElement; | ||
| 299 | output TO outElement; | ||
| 300 | end FuncType; | ||
| 301 | protected | ||
| 302 | Integer i = 2, len = listLength(inList); | ||
| 303 | TO res; | ||
| 304 | algorithm | ||
| 305 |
2/2✓ Branch 0 taken 157 times.
✓ Branch 1 taken 163103 times.
|
163260 | if len == 0 then |
| 306 | 157 | outArray := listArray({}); | |
| 307 | else | ||
| 308 |
2/2✓ Branch 0 taken 156373 times.
✓ Branch 1 taken 6730 times.
|
163103 | res := inFunc(listHead(inList)); |
| 309 | 163103 | outArray := arrayCreateNoInit(len, res); | |
| 310 | 163103 | arrayUpdate(outArray, 1, res); | |
| 311 | |||
| 312 |
2/2✓ Branch 1 taken 552331 times.
✓ Branch 2 taken 163101 times.
|
715432 | for e in listRest(inList) loop |
| 313 |
2/2✓ Branch 0 taken 542938 times.
✓ Branch 1 taken 9393 times.
|
552331 | arrayUpdate(outArray, i, inFunc(e)); |
| 314 | 552329 | i := i + 1; | |
| 315 | end for; | ||
| 316 | end if; | ||
| 317 | end mapList; | ||
| 318 | |||
| 319 | function fold<T, FoldT> | ||
| 320 | "Takes an array, a function, and a start value. The function is applied to | ||
| 321 | each array element, and the start value is passed to the function and | ||
| 322 | updated." | ||
| 323 | input array<T> inArray; | ||
| 324 | input FoldFunc inFoldFunc; | ||
| 325 | input FoldT inStartValue; | ||
| 326 | output FoldT outResult = inStartValue; | ||
| 327 | |||
| 328 | partial function FoldFunc | ||
| 329 | input T inElement; | ||
| 330 | input FoldT inFoldArg; | ||
| 331 | output FoldT outFoldArg; | ||
| 332 | end FoldFunc; | ||
| 333 | algorithm | ||
| 334 |
2/2✓ Branch 1 taken 2793902 times.
✓ Branch 2 taken 7800 times.
|
2801702 | for e in inArray loop |
| 335 |
2/2✓ Branch 0 taken 9601 times.
✓ Branch 1 taken 2784301 times.
|
2793902 | outResult := inFoldFunc(e, outResult); |
| 336 | end for; | ||
| 337 | end fold; | ||
| 338 | |||
| 339 | function foldIndex<T, FoldT> | ||
| 340 | "Takes an array, a function, and a start value. The function is applied to | ||
| 341 | each array element, and the start value is passed to the function and | ||
| 342 | updated, additional the index of the passed element is also passed to the function." | ||
| 343 | input array<T> inArray; | ||
| 344 | input FoldFunc inFoldFunc; | ||
| 345 | input FoldT inStartValue; | ||
| 346 | output FoldT outResult = inStartValue; | ||
| 347 | |||
| 348 | partial function FoldFunc | ||
| 349 | input T inElement; | ||
| 350 | input Integer inIndex; | ||
| 351 | input FoldT inFoldArg; | ||
| 352 | output FoldT outFoldArg; | ||
| 353 | end FoldFunc; | ||
| 354 | protected | ||
| 355 | T e; | ||
| 356 | algorithm | ||
| 357 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1822 times.
|
20765 | for i in 1:arrayLength(inArray) loop |
| 358 | 18943 | e := arrayGet(inArray, i); | |
| 359 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18943 times.
|
18943 | outResult := inFoldFunc(e, i, outResult); |
| 360 | end for; | ||
| 361 | end foldIndex; | ||
| 362 | |||
| 363 | function reduce<T> | ||
| 364 | "Takes a list and a function operating on two elements of the array. | ||
| 365 | The function performs a reduction of the array to a single value using the | ||
| 366 | function. Example: | ||
| 367 | reduce([1, 2, 3], intAdd) => 6" | ||
| 368 | input array<T> inArray; | ||
| 369 | input ReduceFunc inReduceFunc; | ||
| 370 | output T outResult; | ||
| 371 | |||
| 372 | partial function ReduceFunc | ||
| 373 | input T inElement1; | ||
| 374 | input T inElement2; | ||
| 375 | output T outElement; | ||
| 376 | end ReduceFunc; | ||
| 377 | algorithm | ||
| 378 | outResult := arrayGet(inArray, 1); | ||
| 379 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 14690 times.
|
43898 | for i in 2:arrayLength(inArray) loop |
| 380 |
1/2✓ Branch 0 taken 29178 times.
✗ Branch 1 not taken.
|
29178 | outResult := inReduceFunc(outResult, arrayGet(inArray, i)); |
| 381 | end for; | ||
| 382 | end reduce; | ||
| 383 | |||
| 384 | function updateIndexFirst<T> | ||
| 385 | "Like arrayUpdate, but with the index first so it can be used with List.map." | ||
| 386 | input Integer inIndex; | ||
| 387 | input T inValue; | ||
| 388 | input array<T> inArray; | ||
| 389 | algorithm | ||
| 390 | 714778 | arrayUpdate(inArray, inIndex, inValue); | |
| 391 | end updateIndexFirst; | ||
| 392 | |||
| 393 | function getIndexFirst<T> | ||
| 394 | "Like arrayGet, but with the index first so it can used with List.map." | ||
| 395 | input Integer inIndex; | ||
| 396 | input array<T> inArray; | ||
| 397 | output T outElement = arrayGet(inArray, inIndex); | ||
| 398 | end getIndexFirst; | ||
| 399 | |||
| 400 | function replaceAtWithFill<T> | ||
| 401 | "Takes | ||
| 402 | - an element, | ||
| 403 | - a position (1..n) | ||
| 404 | - an array and | ||
| 405 | - a fill value | ||
| 406 | The function replaces the value at the given position in the array, if the | ||
| 407 | given position is out of range, the fill value is used to padd the array up | ||
| 408 | to that element position and then insert the value at the position. | ||
| 409 | |||
| 410 | Example: | ||
| 411 | replaceAtWithFill('A', 5, {'a', 'b', 'c'}, 'dummy') => {'a', 'b', 'c', 'dummy', 'A'}" | ||
| 412 | input Integer inPos; | ||
| 413 | input T inTypeReplace; | ||
| 414 | input T inTypeFill; | ||
| 415 | input array<T> inArray; | ||
| 416 | output array<T> outArray; | ||
| 417 | algorithm | ||
| 418 | 242580 | outArray := expandToSize(inPos, inArray, inTypeFill); | |
| 419 | 242580 | arrayUpdate(outArray, inPos, inTypeReplace); | |
| 420 | end replaceAtWithFill; | ||
| 421 | |||
| 422 | function expandToSize<T> | ||
| 423 | "Expands an array to the given size, or does nothing if the array is already | ||
| 424 | large enough." | ||
| 425 | input Integer inNewSize; | ||
| 426 | input array<T> inArray; | ||
| 427 | input T inFill; | ||
| 428 | output array<T> outArray; | ||
| 429 | algorithm | ||
| 430 |
2/2✓ Branch 0 taken 64892 times.
✓ Branch 1 taken 246145 times.
|
311037 | if inNewSize <= arrayLength(inArray) then |
| 431 | outArray := inArray; | ||
| 432 | else | ||
| 433 | 64892 | outArray := arrayCreate(inNewSize, inFill); | |
| 434 | 64892 | copy(inArray, outArray); | |
| 435 | end if; | ||
| 436 | end expandToSize; | ||
| 437 | |||
| 438 | function expand<T> | ||
| 439 | "Increases the number of elements of an array with inN. Each new element is | ||
| 440 | assigned the value inFill." | ||
| 441 | input Integer inN; | ||
| 442 | input array<T> inArray; | ||
| 443 | input T inFill; | ||
| 444 | output array<T> outArray; | ||
| 445 | protected | ||
| 446 | Integer len; | ||
| 447 | algorithm | ||
| 448 |
2/2✓ Branch 0 taken 26433 times.
✓ Branch 1 taken 2637220 times.
|
2663653 | if inN < 1 then |
| 449 | outArray := inArray; | ||
| 450 | else | ||
| 451 | len := arrayLength(inArray); | ||
| 452 | 26433 | outArray := arrayCreateNoInit(len + inN, inFill); | |
| 453 | 26433 | copy(inArray, outArray); | |
| 454 | 26433 | setRange(len + 1, len + inN, outArray, inFill); | |
| 455 | end if; | ||
| 456 | end expand; | ||
| 457 | |||
| 458 | function expandOnDemand<T> | ||
| 459 | "Resizes an array with the given factor if the array is smaller than the | ||
| 460 | requested size." | ||
| 461 | input Integer inNewSize "The number of elements that should fit in the array."; | ||
| 462 | input array<T> inArray "The array to resize."; | ||
| 463 | input Real inExpansionFactor "The factor to resize the array with."; | ||
| 464 | input T inFillValue "The value to fill the new part of the array."; | ||
| 465 | output array<T> outArray "The resulting array."; | ||
| 466 | protected | ||
| 467 | Integer new_size, len = arrayLength(inArray); | ||
| 468 | algorithm | ||
| 469 |
2/2✓ Branch 0 taken 412 times.
✓ Branch 1 taken 3792192 times.
|
3792604 | if inNewSize <= len then |
| 470 | outArray := inArray; | ||
| 471 | else | ||
| 472 | 412 | new_size := realInt(intReal(len) * inExpansionFactor); | |
| 473 | 412 | outArray := arrayCreateNoInit(new_size, inFillValue); | |
| 474 | 412 | copy(inArray, outArray); | |
| 475 | 412 | setRange(len + 1, new_size, outArray, inFillValue); | |
| 476 | end if; | ||
| 477 | end expandOnDemand; | ||
| 478 | |||
| 479 | function consToElement<T> | ||
| 480 | "Concatenates an element to a list element of an array." | ||
| 481 | input Integer inIndex; | ||
| 482 | input T inElement; | ||
| 483 | input array<list<T>> inArray; | ||
| 484 | output array<list<T>> outArray; | ||
| 485 | algorithm | ||
| 486 | 748194 | outArray := arrayUpdate(inArray, inIndex, inElement :: inArray[inIndex]); | |
| 487 | end consToElement; | ||
| 488 | |||
| 489 | function appendToElement<T> | ||
| 490 | "Appends a list to a list element of an array." | ||
| 491 | input Integer inIndex; | ||
| 492 | input list<T> inElements; | ||
| 493 | input array<list<T>> inArray; | ||
| 494 | output array<list<T>> outArray; | ||
| 495 | algorithm | ||
| 496 | 24615 | outArray := arrayUpdate(inArray, inIndex, listAppend(inArray[inIndex], inElements)); | |
| 497 | end appendToElement; | ||
| 498 | |||
| 499 | function appendList<T> | ||
| 500 | "Returns a new array with the list elements added to the end of the given array." | ||
| 501 | input array<T> arr; | ||
| 502 | input list<T> lst; | ||
| 503 | output array<T> outArray; | ||
| 504 | protected | ||
| 505 | Integer arr_len = arrayLength(arr), lst_len; | ||
| 506 | T e; | ||
| 507 | list<T> rest; | ||
| 508 | algorithm | ||
| 509 |
2/2✓ Branch 0 taken 133 times.
✓ Branch 1 taken 12 times.
|
145 | if listEmpty(lst) then |
| 510 | outArray := arr; | ||
| 511 | elseif arr_len == 0 then | ||
| 512 | 30 | outArray := listArray(lst); | |
| 513 | else | ||
| 514 | 103 | lst_len := listLength(lst); | |
| 515 | 103 | outArray := arrayCreateNoInit(arr_len + lst_len, arr[1]); | |
| 516 | 103 | copy(arr, outArray); | |
| 517 | |||
| 518 | rest := lst; | ||
| 519 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
|
381 | for i in arr_len+1:arr_len+lst_len loop |
| 520 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 278 times.
|
278 | e :: rest := rest; |
| 521 | arrayUpdateNoBoundsChecking(outArray, i, e); | ||
| 522 | end for; | ||
| 523 | end if; | ||
| 524 | end appendList; | ||
| 525 | |||
| 526 | function join<T> | ||
| 527 | "Returns a new array consisting of the elements from both the given arrays." | ||
| 528 | input array<T> arr1; | ||
| 529 | input array<T> arr2; | ||
| 530 | output array<T> outArray; | ||
| 531 | protected | ||
| 532 | Integer len1 = arrayLength(arr1), len2 = arrayLength(arr2); | ||
| 533 | algorithm | ||
| 534 | ✗ | if len1 == 0 then | |
| 535 | ✗ | outArray := arrayCopy(arr2); | |
| 536 | elseif len2 == 0 then | ||
| 537 | ✗ | outArray := arrayCopy(arr1); | |
| 538 | else | ||
| 539 | ✗ | outArray := arrayCreateNoInit(len1 + len2, arr1[1]); | |
| 540 | ✗ | copyRange(arr1, outArray, 1, len1, 1); | |
| 541 | ✗ | copyRange(arr2, outArray, 1, len2, len1 + 1); | |
| 542 | end if; | ||
| 543 | end join; | ||
| 544 | |||
| 545 | function copy<T> | ||
| 546 | "Copies all values from inArraySrc to inArrayDest. Fails if inArraySrc is | ||
| 547 | larger than inArrayDest. | ||
| 548 | |||
| 549 | NOTE: There's also a builtin arrayCopy operator that should be used if the | ||
| 550 | purpose is only to duplicate an array." | ||
| 551 | input array<T> inArraySrc; | ||
| 552 | input array<T> inArrayDest; | ||
| 553 | output array<T> outArray = inArrayDest; | ||
| 554 | algorithm | ||
| 555 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 91852 times.
|
91852 | if arrayLength(inArraySrc) > arrayLength(inArrayDest) then |
| 556 | ✗ | fail(); | |
| 557 | end if; | ||
| 558 | |||
| 559 |
2/2✓ Branch 0 taken 50925 times.
✓ Branch 1 taken 40927 times.
|
5993361 | for i in 1:arrayLength(inArraySrc) loop |
| 560 | 5901509 | arrayUpdateNoBoundsChecking(outArray, i, arrayGetNoBoundsChecking(inArraySrc, i)); | |
| 561 | end for; | ||
| 562 | end copy; | ||
| 563 | |||
| 564 | function copyN<T> | ||
| 565 | "Copies the first inN values from inArraySrc to inArrayDest. Fails if | ||
| 566 | inN is larger than either inArraySrc or inArrayDest." | ||
| 567 | input array<T> inArraySrc; | ||
| 568 | input array<T> inArrayDest; | ||
| 569 | input Integer inN; | ||
| 570 | input Integer srcOffset = 0; | ||
| 571 | input Integer dstOffset = 0; | ||
| 572 | output array<T> outArray = inArrayDest; | ||
| 573 | algorithm | ||
| 574 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 24 times.
|
72 | if inN + dstOffset > arrayLength(inArrayDest) or inN + srcOffset > arrayLength(inArraySrc) then |
| 575 | ✗ | fail(); | |
| 576 | end if; | ||
| 577 | |||
| 578 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 5 times.
|
29 | for i in 1:inN loop |
| 579 | 5 | arrayUpdateNoBoundsChecking(outArray, i + dstOffset, | |
| 580 | arrayGetNoBoundsChecking(inArraySrc, i + srcOffset)); | ||
| 581 | end for; | ||
| 582 | end copyN; | ||
| 583 | |||
| 584 | function copyRange<T> | ||
| 585 | "Copies a range of elements from one array to another." | ||
| 586 | input array<T> srcArray "The array to copy from."; | ||
| 587 | input array<T> dstArray "The array to insert into."; | ||
| 588 | input Integer srcFirst "The index of the first element to copy."; | ||
| 589 | input Integer srcLast "The index of the last element to copy."; | ||
| 590 | input Integer dstPos "The index to begin inserting at."; | ||
| 591 | protected | ||
| 592 | Integer offset = dstPos - srcFirst; | ||
| 593 | algorithm | ||
| 594 |
4/8✓ Branch 0 taken 34167 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34167 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 34167 times.
✓ Branch 6 taken 34167 times.
✗ Branch 7 not taken.
|
102501 | if srcFirst > srcLast or srcLast > arrayLength(srcArray) or |
| 595 | offset + srcLast > arrayLength(dstArray) then | ||
| 596 | ✗ | fail(); | |
| 597 | end if; | ||
| 598 | |||
| 599 | 274707 | for i in srcFirst:srcLast loop | |
| 600 | 274707 | arrayUpdateNoBoundsChecking(dstArray, offset + i, | |
| 601 | arrayGetNoBoundsChecking(srcArray, i)); | ||
| 602 | end for; | ||
| 603 | end copyRange; | ||
| 604 | |||
| 605 | function createIntRange | ||
| 606 | "Creates an array<Integer> of size inLen with the values set to the range of 1:inLen." | ||
| 607 | input Integer inLen; | ||
| 608 | output array<Integer> outArray; | ||
| 609 | algorithm | ||
| 610 | 1738 | outArray := arrayCreateNoInit(inLen, 0); | |
| 611 | |||
| 612 |
2/2✓ Branch 0 taken 295 times.
✓ Branch 1 taken 1443 times.
|
145662 | for i in 1:inLen loop |
| 613 | arrayUpdateNoBoundsChecking(outArray, i, i); | ||
| 614 | end for; | ||
| 615 | end createIntRange; | ||
| 616 | |||
| 617 | function setRange<T> | ||
| 618 | "Sets the elements in positions inStart to inEnd to inValue." | ||
| 619 | input Integer inStart; | ||
| 620 | input Integer inEnd; | ||
| 621 | input array<T> inArray; | ||
| 622 | input T inValue; | ||
| 623 | output array<T> outArray = inArray; | ||
| 624 | algorithm | ||
| 625 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31537 times.
|
31537 | if inStart > arrayLength(inArray) then |
| 626 | ✗ | fail(); | |
| 627 | end if; | ||
| 628 | |||
| 629 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31537 times.
|
1206816 | for i in inStart:inEnd loop |
| 630 | 1175279 | arrayUpdate(inArray, i, inValue); | |
| 631 | end for; | ||
| 632 | end setRange; | ||
| 633 | |||
| 634 | function getRange<T> | ||
| 635 | "Gets the elements between inStart and inEnd." | ||
| 636 | input Integer inStart; | ||
| 637 | input Integer inEnd; | ||
| 638 | input array<T> inArray; | ||
| 639 | output list<T> outList = {}; | ||
| 640 | protected | ||
| 641 | T value; | ||
| 642 | algorithm | ||
| 643 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if inStart > arrayLength(inArray) then |
| 644 | ✗ | fail(); | |
| 645 | end if; | ||
| 646 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
106 | for i in inStart:inEnd loop |
| 647 | 61 | value := arrayGet(inArray, i); | |
| 648 | outList := value::outList; | ||
| 649 | end for; | ||
| 650 | end getRange; | ||
| 651 | |||
| 652 | function position<T> | ||
| 653 | "Returns the index of the given element in the array, or 0 if it wasn't found." | ||
| 654 | input array<T> inArray; | ||
| 655 | input T inElement; | ||
| 656 | input Integer inFilledSize = arrayLength(inArray) "The filled size of the array."; | ||
| 657 | output Integer outIndex; | ||
| 658 | algorithm | ||
| 659 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
71 | for i in 1:inFilledSize loop |
| 660 |
2/2✓ Branch 2 taken 3 times.
✓ Branch 3 taken 68 times.
|
71 | if valueEq(inElement, inArray[i]) then |
| 661 | outIndex := i; | ||
| 662 | 3 | return; | |
| 663 | end if; | ||
| 664 | end for; | ||
| 665 | outIndex := 0; | ||
| 666 | end position; | ||
| 667 | |||
| 668 | function getMemberOnTrue<VT, ET> | ||
| 669 | "Takes a value and returns the first element for which the comparison | ||
| 670 | function returns true, along with that elements position in the array." | ||
| 671 | input VT inValue; | ||
| 672 | input array<ET> inArray; | ||
| 673 | input CompFunc inCompFunc; | ||
| 674 | output ET outElement; | ||
| 675 | output Integer outIndex; | ||
| 676 | |||
| 677 | partial function CompFunc | ||
| 678 | input VT inValue; | ||
| 679 | input ET inElement; | ||
| 680 | output Boolean outIsEqual; | ||
| 681 | end CompFunc; | ||
| 682 | algorithm | ||
| 683 |
1/2✓ Branch 0 taken 1815 times.
✗ Branch 1 not taken.
|
8910 | for i in 1:arrayLength(inArray) loop |
| 684 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 7150 times.
✓ Branch 4 taken 55 times.
✓ Branch 5 taken 7095 times.
|
7150 | if inCompFunc(inValue, arrayGetNoBoundsChecking(inArray, i)) then |
| 685 | 55 | outElement := arrayGetNoBoundsChecking(inArray, i); | |
| 686 | outIndex := i; | ||
| 687 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
|
55 | return; |
| 688 | end if; | ||
| 689 | end for; | ||
| 690 | 1760 | fail(); | |
| 691 | end getMemberOnTrue; | ||
| 692 | |||
| 693 | function reverse<T>"reverses the elements in an array" | ||
| 694 | input array<T> inArray; | ||
| 695 | output array<T> outArray; | ||
| 696 | protected | ||
| 697 | Integer size,i; | ||
| 698 | T elem1,elem2; | ||
| 699 | algorithm | ||
| 700 | outArray := inArray; | ||
| 701 | size := arrayLength(inArray); | ||
| 702 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
102 | for i in 1:(size/2) loop |
| 703 | 86 | elem1 := arrayGet(inArray,i); | |
| 704 | 86 | elem2 := arrayGet(inArray,size-i+1); | |
| 705 | 86 | outArray := arrayUpdate(outArray,i,elem2); | |
| 706 | 86 | outArray := arrayUpdate(outArray,size-i+1,elem1); | |
| 707 | end for; | ||
| 708 | end reverse; | ||
| 709 | |||
| 710 | public function toString<T> | ||
| 711 | "Creates a string from an array and a function that maps an array element to a | ||
| 712 | string. It also takes several parameters that determine the formatting of | ||
| 713 | the string. Ex: | ||
| 714 | toString([1, 2, 3], intString, 'nums', '[', ';', ']', true) => | ||
| 715 | 'nums[1;2;3]' | ||
| 716 | " | ||
| 717 | input array<T> inArray; | ||
| 718 | input FuncType inPrintFunc; | ||
| 719 | input String inNameStr = "" "The name of the array."; | ||
| 720 | input String inBeginStr = "[" "The start of the array"; | ||
| 721 | input String inDelimitStr = ", " "The delimiter between array elements."; | ||
| 722 | input String inEndStr = "]" "The end of the array."; | ||
| 723 | input Boolean inPrintEmpty = true "If false, don't output begin and end if the array is empty."; | ||
| 724 | input Integer maxLength = 0 "If > 0, only the first maxLength elements are printed"; | ||
| 725 | output String outString; | ||
| 726 | |||
| 727 | partial function FuncType | ||
| 728 | input T inElement; | ||
| 729 | output String outString; | ||
| 730 | end FuncType; | ||
| 731 | protected | ||
| 732 | list<T> lst; | ||
| 733 | String endStr = inEndStr; | ||
| 734 | algorithm | ||
| 735 | |||
| 736 | // TODO implement stringDelimitArray and don't use arrayList | ||
| 737 | |||
| 738 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 248 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
248 | if maxLength > 0 and arrayLength(inArray) > maxLength then |
| 739 | ✗ | lst := List.firstN(arrayList(inArray), maxLength); | |
| 740 | ✗ | endStr := stringAppendList({inDelimitStr, "...", inEndStr}); | |
| 741 | else | ||
| 742 | 248 | lst := arrayList(inArray); | |
| 743 | end if; | ||
| 744 | |||
| 745 | outString := match(lst, inPrintEmpty) | ||
| 746 | local | ||
| 747 | String str; | ||
| 748 | |||
| 749 | // Empty list and inPrintEmpty true => concatenate the list name, begin | ||
| 750 | // string and end string. | ||
| 751 | case ({}, true) | ||
| 752 | 245 | then stringAppendList({inNameStr, inBeginStr, inEndStr}); | |
| 753 | |||
| 754 | // Empty list and inPrintEmpty false => output only list name. | ||
| 755 | case ({}, false) | ||
| 756 | then inNameStr; | ||
| 757 | |||
| 758 | else | ||
| 759 | algorithm | ||
| 760 | 3 | str := stringDelimitList(List.map(lst, inPrintFunc), inDelimitStr); | |
| 761 | 3 | str := stringAppendList({inNameStr, inBeginStr, str, endStr}); | |
| 762 | then | ||
| 763 | str; | ||
| 764 | |||
| 765 | end match; | ||
| 766 | end toString; | ||
| 767 | |||
| 768 | function hashIntArray | ||
| 769 | "Computes a hash value for an array of Integer. | ||
| 770 | The same array contents always give the same hash value." | ||
| 771 | input array<Integer> arr; | ||
| 772 | output Integer hash = 5381; | ||
| 773 | algorithm | ||
| 774 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
|
780 | for i in 1:arrayLength(arr) loop |
| 775 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 624 times.
|
624 | hash := intMod(hash * 31 + arrayGetNoBoundsChecking(arr, i), 536870911); |
| 776 | end for; | ||
| 777 | end hashIntArray; | ||
| 778 | |||
| 779 | function isEqual<T> | ||
| 780 | "Checks if two arrays are equal." | ||
| 781 | input array<T> inArr1; | ||
| 782 | input array<T> inArr2; | ||
| 783 | output Boolean outIsEqual=true; | ||
| 784 | protected | ||
| 785 | Integer arrLength; | ||
| 786 | algorithm | ||
| 787 | arrLength := arrayLength(inArr1); | ||
| 788 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | if not intEq(arrLength,arrayLength(inArr2)) then |
| 789 | ✗ | fail(); | |
| 790 | end if; | ||
| 791 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
94 | for i in 1:arrLength loop |
| 792 |
2/2✓ Branch 3 taken 74 times.
✓ Branch 4 taken 2 times.
|
76 | if not valueEq(inArr1[i],inArr2[i]) then |
| 793 | outIsEqual := false; | ||
| 794 | break; | ||
| 795 | end if; | ||
| 796 | end for; | ||
| 797 | end isEqual; | ||
| 798 | |||
| 799 | function isEqualOnTrue<T1, T2> | ||
| 800 | "Returns whether the two arrays are equal or not, using the given predicate | ||
| 801 | function to check element equality." | ||
| 802 | input array<T1> arr1; | ||
| 803 | input array<T2> arr2; | ||
| 804 | input PredFunc pred; | ||
| 805 | output Boolean equal; | ||
| 806 | |||
| 807 | partial function PredFunc | ||
| 808 | input T1 e1; | ||
| 809 | input T2 e2; | ||
| 810 | output Boolean equal; | ||
| 811 | end PredFunc; | ||
| 812 | algorithm | ||
| 813 | 379 | equal := arrayLength(arr1) == arrayLength(arr2); | |
| 814 | |||
| 815 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
|
379 | if not equal then |
| 816 | ✗ | return; | |
| 817 | end if; | ||
| 818 | |||
| 819 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 370 times.
|
783 | for i in 1:arrayLength(arr1) loop |
| 820 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 463 times.
✓ Branch 4 taken 59 times.
✓ Branch 5 taken 404 times.
|
463 | if not pred(arrayGetNoBoundsChecking(arr1, i), |
| 821 | arrayGetNoBoundsChecking(arr2, i)) then | ||
| 822 | equal := false; | ||
| 823 | 59 | return; | |
| 824 | end if; | ||
| 825 | end for; | ||
| 826 | end isEqualOnTrue; | ||
| 827 | |||
| 828 | function allEqual<T> | ||
| 829 | input array<T> arr; | ||
| 830 | input PredFunc pred; | ||
| 831 | output Boolean equal = true; | ||
| 832 | |||
| 833 | partial function PredFunc | ||
| 834 | input T e1; | ||
| 835 | input T e2; | ||
| 836 | output Boolean equal; | ||
| 837 | end PredFunc; | ||
| 838 | algorithm | ||
| 839 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2029 times.
|
2029 | if arrayEmpty(arr) then |
| 840 | ✗ | return; | |
| 841 | end if; | ||
| 842 | |||
| 843 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2025 times.
|
3121 | for i in 2:arrayLength(arr) loop |
| 844 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 2632 times.
✓ Branch 4 taken 1540 times.
✓ Branch 5 taken 1092 times.
|
2632 | if not pred(arrayGetNoBoundsChecking(arr, 1), |
| 845 | arrayGetNoBoundsChecking(arr, i)) then | ||
| 846 | equal := false; | ||
| 847 | 1540 | return; | |
| 848 | end if; | ||
| 849 | end for; | ||
| 850 | end allEqual; | ||
| 851 | |||
| 852 | function isLess<T> | ||
| 853 | "Returns true if arr1 is less than arr2 using a lexicographical comparison." | ||
| 854 | input array<T> arr1; | ||
| 855 | input array<T> arr2; | ||
| 856 | input LessFn lessFn; | ||
| 857 | output Boolean res; | ||
| 858 | |||
| 859 | partial function LessFn | ||
| 860 | input T e1; | ||
| 861 | input T e2; | ||
| 862 | output Boolean res; | ||
| 863 | end LessFn; | ||
| 864 | protected | ||
| 865 | Integer len1, len2; | ||
| 866 | T e1; | ||
| 867 | T e2; | ||
| 868 | algorithm | ||
| 869 | len1 := arrayLength(arr1); | ||
| 870 | len2 := arrayLength(arr2); | ||
| 871 | |||
| 872 | // The first pair of elements that's not equal determines whether arr1 < arr2 or not. | ||
| 873 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | for i in 1:min(len1, len2) loop |
| 874 | 3 | e1 := arrayGetNoBoundsChecking(arr1, i); | |
| 875 | 3 | e2 := arrayGetNoBoundsChecking(arr2, i); | |
| 876 | |||
| 877 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 time.
|
3 | if lessFn(e1, e2) then |
| 878 | // arr1 < arr2 if e1 < e2. | ||
| 879 | res := true; | ||
| 880 | 2 | return; | |
| 881 | elseif lessFn(e2, e1) then | ||
| 882 | // arr1 > arr2 if e2 < e1. | ||
| 883 | res := false; | ||
| 884 | 1 | return; | |
| 885 | end if; | ||
| 886 | end for; | ||
| 887 | |||
| 888 | // arr1 < arr2 if arr1 is a prefix of arr2 and all elements in arr1 are equal | ||
| 889 | // to the corresponding elements in arr2. | ||
| 890 | ✗ | res := len1 < len2; | |
| 891 | end isLess; | ||
| 892 | |||
| 893 | function insertList<T> | ||
| 894 | input output array<T> arr; | ||
| 895 | input list<T> lst; | ||
| 896 | input Integer startPos; | ||
| 897 | protected | ||
| 898 | Integer i = startPos; | ||
| 899 | algorithm | ||
| 900 | ✗ | for e in lst loop | |
| 901 | ✗ | arr[i] := e; | |
| 902 | ✗ | i := i + 1; | |
| 903 | end for; | ||
| 904 | end insertList; | ||
| 905 | |||
| 906 | function remove<T> | ||
| 907 | "Returns a new array without the element at the given index." | ||
| 908 | input array<T> arr; | ||
| 909 | input Integer index; | ||
| 910 | output array<T> outArr; | ||
| 911 | protected | ||
| 912 | Integer len = arrayLength(arr); | ||
| 913 | algorithm | ||
| 914 | ✗ | true := index <= len and index >= 1; | |
| 915 | ✗ | if len <= 1 then | |
| 916 | ✗ | outArr := listArray({}); | |
| 917 | else | ||
| 918 | ✗ | outArr := arrayCreateNoInit(len - 1, arr[1]); | |
| 919 | |||
| 920 | ✗ | for i in 1:index-1 loop | |
| 921 | ✗ | arrayUpdateNoBoundsChecking(outArr, i, arrayGetNoBoundsChecking(arr, i)); | |
| 922 | end for; | ||
| 923 | |||
| 924 | ✗ | for i in index+1:len loop | |
| 925 | ✗ | arrayUpdateNoBoundsChecking(outArr, i - 1, arrayGetNoBoundsChecking(arr, i)); | |
| 926 | end for; | ||
| 927 | end if; | ||
| 928 | end remove; | ||
| 929 | |||
| 930 | function all<T> | ||
| 931 | "Returns true if the given predicate function returns true for all elements in | ||
| 932 | the given array." | ||
| 933 | input array<T> arr; | ||
| 934 | input PredFunc inFunc; | ||
| 935 | output Boolean outResult; | ||
| 936 | |||
| 937 | partial function PredFunc | ||
| 938 | input T e; | ||
| 939 | output Boolean res; | ||
| 940 | end PredFunc; | ||
| 941 | algorithm | ||
| 942 |
2/2✓ Branch 1 taken 3593512 times.
✓ Branch 2 taken 309375 times.
|
3902887 | for e in arr loop |
| 943 |
4/4✓ Branch 0 taken 9813 times.
✓ Branch 1 taken 3583699 times.
✓ Branch 4 taken 67729 times.
✓ Branch 5 taken 3525783 times.
|
3593512 | if not inFunc(e) then |
| 944 | outResult := false; | ||
| 945 | 67729 | return; | |
| 946 | end if; | ||
| 947 | end for; | ||
| 948 | |||
| 949 | outResult := true; | ||
| 950 | end all; | ||
| 951 | |||
| 952 | function any<T> | ||
| 953 | "Returns true if the given predicate function returns true for any element in | ||
| 954 | the given array." | ||
| 955 | input array<T> arr; | ||
| 956 | input PredFunc inFunc; | ||
| 957 | output Boolean outResult; | ||
| 958 | |||
| 959 | partial function PredFunc | ||
| 960 | input T element; | ||
| 961 | output Boolean matches; | ||
| 962 | end PredFunc; | ||
| 963 | algorithm | ||
| 964 |
2/2✓ Branch 1 taken 26395 times.
✓ Branch 2 taken 16187 times.
|
42582 | for e in arr loop |
| 965 |
4/4✓ Branch 0 taken 6672 times.
✓ Branch 1 taken 19723 times.
✓ Branch 4 taken 203 times.
✓ Branch 5 taken 26192 times.
|
26395 | if inFunc(e) then |
| 966 | outResult := true; | ||
| 967 | 203 | return; | |
| 968 | end if; | ||
| 969 | end for; | ||
| 970 | |||
| 971 | outResult := false; | ||
| 972 | end any; | ||
| 973 | |||
| 974 | function minElement<T> | ||
| 975 | "Returns the smallest element in the array, or fails if the array is empty." | ||
| 976 | input array<T> arr; | ||
| 977 | input LessFn lessFn; | ||
| 978 | output T res; | ||
| 979 | |||
| 980 | partial function LessFn | ||
| 981 | "Returns true if e1 < e2, otherwise false." | ||
| 982 | input T e1; | ||
| 983 | input T e2; | ||
| 984 | output Boolean res; | ||
| 985 | end LessFn; | ||
| 986 | protected | ||
| 987 | T e; | ||
| 988 | algorithm | ||
| 989 | res := arr[1]; | ||
| 990 | |||
| 991 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 14 times.
|
68 | for i in 2:arrayLength(arr) loop |
| 992 | 14 | e := arrayGetNoBoundsChecking(arr, i); | |
| 993 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
|
14 | if lessFn(e, res) then |
| 994 | res := e; | ||
| 995 | end if; | ||
| 996 | end for; | ||
| 997 | end minElement; | ||
| 998 | |||
| 999 | function maxElement<T> | ||
| 1000 | "Returns the largest element in the list, or fails if the list is empty." | ||
| 1001 | input array<T> arr; | ||
| 1002 | input LessFn lessFn; | ||
| 1003 | output T res; | ||
| 1004 | |||
| 1005 | partial function LessFn | ||
| 1006 | "Returns true if e1 < e2, otherwise false." | ||
| 1007 | input T e1; | ||
| 1008 | input T e2; | ||
| 1009 | output Boolean res; | ||
| 1010 | end LessFn; | ||
| 1011 | protected | ||
| 1012 | T e; | ||
| 1013 | algorithm | ||
| 1014 | res := arr[1]; | ||
| 1015 | |||
| 1016 |
2/2✓ Branch 0 taken 74 times.
✓ Branch 1 taken 14 times.
|
102 | for i in 2:arrayLength(arr) loop |
| 1017 | 14 | e := arrayGetNoBoundsChecking(arr, i); | |
| 1018 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 4 times.
|
14 | if lessFn(res, e) then |
| 1019 | res := e; | ||
| 1020 | end if; | ||
| 1021 | end for; | ||
| 1022 | end maxElement; | ||
| 1023 | |||
| 1024 | function compare<T1, T2> | ||
| 1025 | "Returns -1 if arr1 is shorter than arr2 or 1 if arr1 is longer than arr2. | ||
| 1026 | If both arrays are of equal length it applies the given compare function to | ||
| 1027 | each pair of array elements and returns the first nonzero value, or 0 if no | ||
| 1028 | nonzero value is received." | ||
| 1029 | input array<T1> arr1; | ||
| 1030 | input array<T2> arr2; | ||
| 1031 | input CompFunc compFn; | ||
| 1032 | output Integer res; | ||
| 1033 | |||
| 1034 | partial function CompFunc | ||
| 1035 | input T1 e1; | ||
| 1036 | input T2 e2; | ||
| 1037 | output Integer res; | ||
| 1038 | end CompFunc; | ||
| 1039 | protected | ||
| 1040 | Integer l1, l2; | ||
| 1041 | algorithm | ||
| 1042 | l1 := arrayLength(arr1); | ||
| 1043 | l2 := arrayLength(arr2); | ||
| 1044 |
1/4✓ Branch 0 taken 1161 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1161 | res := if l1 == l2 then 0 elseif l1 > l2 then 1 else -1; |
| 1045 | |||
| 1046 | if res <> 0 then | ||
| 1047 | ✗ | return; | |
| 1048 | end if; | ||
| 1049 | |||
| 1050 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
|
3755 | for i in 1:l1 loop |
| 1051 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2997 times.
|
2997 | res := compFn(arrayGetNoBoundsChecking(arr1, i), |
| 1052 | arrayGetNoBoundsChecking(arr2, i)); | ||
| 1053 | |||
| 1054 |
2/2✓ Branch 0 taken 403 times.
✓ Branch 1 taken 2594 times.
|
2997 | if res <> 0 then |
| 1055 | 403 | return; | |
| 1056 | end if; | ||
| 1057 | end for; | ||
| 1058 | end compare; | ||
| 1059 | |||
| 1060 | function mapFold<TI, TO, ArgT> | ||
| 1061 | input array<TI> arr; | ||
| 1062 | input FuncType func; | ||
| 1063 | input ArgT arg; | ||
| 1064 | output array<TO> outArray; | ||
| 1065 | output ArgT outArg = arg; | ||
| 1066 | |||
| 1067 | partial function FuncType | ||
| 1068 | input TI e; | ||
| 1069 | input ArgT arg; | ||
| 1070 | output TO result; | ||
| 1071 | output ArgT outArg; | ||
| 1072 | end FuncType; | ||
| 1073 | protected | ||
| 1074 | Integer len = arrayLength(arr); | ||
| 1075 | TO res; | ||
| 1076 | algorithm | ||
| 1077 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56572 times.
|
56572 | if len == 0 then |
| 1078 | ✗ | outArray := listArray({}); | |
| 1079 | else | ||
| 1080 |
2/2✓ Branch 0 taken 55572 times.
✓ Branch 1 taken 1000 times.
|
56572 | (res, outArg) := func(arrayGetNoBoundsChecking(arr, 1), outArg); |
| 1081 | 56572 | outArray := arrayCreateNoInit(len, res); | |
| 1082 | arrayUpdateNoBoundsChecking(outArray, 1, res); | ||
| 1083 | |||
| 1084 |
2/2✓ Branch 0 taken 42139 times.
✓ Branch 1 taken 14433 times.
|
955585 | for i in 2:len loop |
| 1085 |
2/2✓ Branch 0 taken 63175 times.
✓ Branch 1 taken 835838 times.
|
899013 | (res, outArg) := func(arrayGetNoBoundsChecking(arr, i), outArg); |
| 1086 | arrayUpdateNoBoundsChecking(outArray, i, res); | ||
| 1087 | end for; | ||
| 1088 | end if; | ||
| 1089 | end mapFold; | ||
| 1090 | |||
| 1091 | function transpose<T> | ||
| 1092 | "Transposes a two-dimensional array." | ||
| 1093 | input array<array<T>> arr; | ||
| 1094 | output array<array<T>> outArray; | ||
| 1095 | protected | ||
| 1096 | Integer c_len, r_len; | ||
| 1097 | T val; | ||
| 1098 | array<T> row; | ||
| 1099 | algorithm | ||
| 1100 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1246 times.
|
1246 | if arrayEmpty(arr) then |
| 1101 | outArray := arr; | ||
| 1102 | ✗ | return; | |
| 1103 | end if; | ||
| 1104 | |||
| 1105 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1246 times.
|
1246 | row := arrayGetNoBoundsChecking(arr, 1); |
| 1106 | |||
| 1107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1246 times.
|
1246 | if arrayEmpty(row) then |
| 1108 | outArray := arr; | ||
| 1109 | ✗ | return; | |
| 1110 | end if; | ||
| 1111 | |||
| 1112 | 1246 | val := arrayGetNoBoundsChecking(row, 1); | |
| 1113 | |||
| 1114 | c_len := arrayLength(arr); | ||
| 1115 | r_len := arrayLength(row); | ||
| 1116 | 1246 | outArray := arrayCreateNoInit(r_len, row); | |
| 1117 | |||
| 1118 | 4842 | for i in 1:r_len loop | |
| 1119 | 3596 | arrayUpdateNoBoundsChecking(outArray, i, arrayCreateNoInit(c_len, val)); | |
| 1120 | end for; | ||
| 1121 | |||
| 1122 | 3596 | for r in 1:r_len loop | |
| 1123 | 10396 | for c in 1:c_len loop | |
| 1124 | // outArray[r, c] := arr[c, r] | ||
| 1125 | 10396 | val := arrayGetNoBoundsChecking(arrayGetNoBoundsChecking(arr, c), r); | |
| 1126 | 10396 | arrayUpdateNoBoundsChecking(arrayGetNoBoundsChecking(outArray, r), c, val); | |
| 1127 | end for; | ||
| 1128 | end for; | ||
| 1129 | end transpose; | ||
| 1130 | |||
| 1131 | function threadMap<T1, T2, TO> | ||
| 1132 | "Creates an array with the result from calling the given function on each pair | ||
| 1133 | of elements in two arrays." | ||
| 1134 | input array<T1> arr1; | ||
| 1135 | input array<T2> arr2; | ||
| 1136 | input MapFunc func; | ||
| 1137 | output array<TO> outArray; | ||
| 1138 | |||
| 1139 | partial function MapFunc | ||
| 1140 | input T1 e1; | ||
| 1141 | input T2 e2; | ||
| 1142 | output TO res; | ||
| 1143 | end MapFunc; | ||
| 1144 | protected | ||
| 1145 | TO res; | ||
| 1146 | Integer len1, len2; | ||
| 1147 | algorithm | ||
| 1148 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 19926 times.
|
19932 | if arrayEmpty(arr1) then |
| 1149 | 6 | outArray := listArray({}); | |
| 1150 | 6 | return; | |
| 1151 | end if; | ||
| 1152 | |||
| 1153 | len1 := arrayLength(arr1); | ||
| 1154 | len2 := arrayLength(arr2); | ||
| 1155 | |||
| 1156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19926 times.
|
19926 | if len1 <> len2 then |
| 1157 | ✗ | fail(); | |
| 1158 | end if; | ||
| 1159 | |||
| 1160 |
2/2✓ Branch 0 taken 18444 times.
✓ Branch 1 taken 1482 times.
|
19926 | res := func(arrayGetNoBoundsChecking(arr1, 1), arrayGetNoBoundsChecking(arr2, 1)); |
| 1161 | 19926 | outArray := arrayCreateNoInit(len1, res); | |
| 1162 | arrayUpdateNoBoundsChecking(outArray, 1, res); | ||
| 1163 | |||
| 1164 |
2/2✓ Branch 0 taken 267 times.
✓ Branch 1 taken 19659 times.
|
58622 | for i in 2:len1 loop |
| 1165 |
2/2✓ Branch 0 taken 35841 times.
✓ Branch 1 taken 2855 times.
|
38696 | arrayUpdateNoBoundsChecking(outArray, i, |
| 1166 | func(arrayGetNoBoundsChecking(arr1, i), arrayGetNoBoundsChecking(arr2, i))); | ||
| 1167 | end for; | ||
| 1168 | end threadMap; | ||
| 1169 | |||
| 1170 | function generate<T> | ||
| 1171 | "Generates an array of length n and fills it by calling the given generator | ||
| 1172 | function for each array element." | ||
| 1173 | input Integer n; | ||
| 1174 | input Generator generator; | ||
| 1175 | output array<T> arr; | ||
| 1176 | |||
| 1177 | partial function Generator | ||
| 1178 | output T e; | ||
| 1179 | end Generator; | ||
| 1180 | protected | ||
| 1181 | T e; | ||
| 1182 | algorithm | ||
| 1183 |
2/2✓ Branch 0 taken 4255 times.
✓ Branch 1 taken 83723 times.
|
87978 | if n <= 0 then |
| 1184 | 4255 | arr := listArray({}); | |
| 1185 | else | ||
| 1186 |
1/2✓ Branch 0 taken 83723 times.
✗ Branch 1 not taken.
|
83723 | e := generator(); |
| 1187 | 83723 | arr := arrayCreateNoInit(n, e); | |
| 1188 | arrayUpdateNoBoundsChecking(arr, 1, e); | ||
| 1189 | |||
| 1190 |
2/2✓ Branch 0 taken 4124 times.
✓ Branch 1 taken 79599 times.
|
275890 | for i in 2:n loop |
| 1191 |
1/2✓ Branch 0 taken 192167 times.
✗ Branch 1 not taken.
|
192167 | arrayUpdateNoBoundsChecking(arr, i, generator()); |
| 1192 | end for; | ||
| 1193 | end if; | ||
| 1194 | end generate; | ||
| 1195 | |||
| 1196 | function filter<T> | ||
| 1197 | input array<T> arr; | ||
| 1198 | input filterFunc fun; | ||
| 1199 | output array<T> new_arr; | ||
| 1200 | partial function filterFunc | ||
| 1201 | input T t; | ||
| 1202 | output Boolean b "if b=true then 't' gets removed"; | ||
| 1203 | end filterFunc; | ||
| 1204 | protected | ||
| 1205 | Integer new_size; | ||
| 1206 | T dummy = dummy; // Fool the compiler into thinking dummy is initialized. | ||
| 1207 | Integer index = 1; | ||
| 1208 | algorithm | ||
| 1209 |
7/8✗ Branch 1 not taken.
✓ Branch 2 taken 2430 times.
✓ Branch 5 taken 2428 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 2430 times.
✓ Branch 8 taken 327 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 327 times.
|
3084 | new_size := arrayLength(arr) - sum(1 for e guard fun(e) in arr); |
| 1210 | 327 | new_arr := arrayCreateNoInit(new_size, dummy); | |
| 1211 |
2/2✓ Branch 1 taken 2430 times.
✓ Branch 2 taken 327 times.
|
2757 | for e in arr loop |
| 1212 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 2430 times.
✓ Branch 4 taken 2428 times.
✓ Branch 5 taken 2 times.
|
2430 | if not fun(e) then |
| 1213 | arrayUpdateNoBoundsChecking(new_arr, index, e); | ||
| 1214 | 2428 | index := index + 1; | |
| 1215 | end if; | ||
| 1216 | end for; | ||
| 1217 | end filter; | ||
| 1218 | |||
| 1219 | annotation(__OpenModelica_Interface="util_datatypes_basic"); | ||
| 1220 | end Array; | ||
| 1221 |