OMCompiler/Compiler/NFFrontEnd/NFSimplifyExp.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 NFSimplifyExp | ||
| 37 | |||
| 38 | import Expression = NFExpression; | ||
| 39 | import Operator = NFOperator; | ||
| 40 | import Type = NFType; | ||
| 41 | import Call = NFCall; | ||
| 42 | import Subscript = NFSubscript; | ||
| 43 | import NFOperator.Op; | ||
| 44 | import NFPrefixes.{Variability, Purity}; | ||
| 45 | import NFInstNode.InstNode; | ||
| 46 | |||
| 47 | protected | ||
| 48 | |||
| 49 | import Dimension = NFDimension; | ||
| 50 | import Ceval = NFCeval; | ||
| 51 | import NFCeval.EvalTarget; | ||
| 52 | import NFFunction.Function; | ||
| 53 | import ComponentRef = NFComponentRef; | ||
| 54 | import ExpandExp = NFExpandExp; | ||
| 55 | import TypeCheck = NFTypeCheck; | ||
| 56 | import Absyn; | ||
| 57 | import AbsynUtil; | ||
| 58 | import ErrorExt; | ||
| 59 | import Flags; | ||
| 60 | import Debug; | ||
| 61 | import Array; | ||
| 62 | import MetaModelica.Dangerous.listReverseInPlace; | ||
| 63 | import UnorderedMap; | ||
| 64 | |||
| 65 | constant Integer MAX_CHAIN_TERMS = 32 | ||
| 66 | "Same limit as Expression.MAX_SUM_CHAIN, for the n-ary node."; | ||
| 67 | |||
| 68 | public | ||
| 69 | |||
| 70 | function simplifyDump | ||
| 71 | "wrapper function for simplification to allow dumping before and afterwards" | ||
| 72 | input Expression exp; | ||
| 73 | input Boolean includeScope; | ||
| 74 | output Expression res; | ||
| 75 | input String name = ""; | ||
| 76 | input String indent = ""; | ||
| 77 | algorithm | ||
| 78 | 71436 | res := simplify(exp, includeScope); | |
| 79 |
4/4✓ Branch 1 taken 71072 times.
✓ Branch 2 taken 364 times.
✓ Branch 4 taken 352 times.
✓ Branch 5 taken 12 times.
|
71436 | if Flags.isSet(Flags.DUMP_SIMPLIFY) and not Expression.isEqual(exp, res) then |
| 80 | 12 | print(indent + "### dumpSimplify | " + name + " ###\n"); | |
| 81 | 12 | print(indent + "[BEFORE] " + Expression.toString(exp) + "\n"); | |
| 82 | 12 | print(indent + "[AFTER ] " + Expression.toString(res) + "\n\n"); | |
| 83 | end if; | ||
| 84 | end simplifyDump; | ||
| 85 | |||
| 86 | function simplify | ||
| 87 | input output Expression exp; | ||
| 88 | input Boolean includeScope = false; | ||
| 89 | protected | ||
| 90 | Type old, new; | ||
| 91 | algorithm | ||
| 92 | exp := match exp | ||
| 93 | case Expression.CREF() | ||
| 94 | algorithm | ||
| 95 | 1290062 | exp.cref := ComponentRef.simplifySubscripts(exp.cref); | |
| 96 | 1290062 | exp.ty := ComponentRef.getSubscriptedType(exp.cref, includeScope); | |
| 97 | then | ||
| 98 | exp; | ||
| 99 | |||
| 100 | case Expression.ARRAY() | ||
| 101 | guard not exp.literal | ||
| 102 | algorithm | ||
| 103 | 103590 | exp.elements := Array.map(exp.elements, function simplify(includeScope = false)); | |
| 104 | then | ||
| 105 | exp; | ||
| 106 | |||
| 107 | case Expression.RANGE() | ||
| 108 | 14281 | then simplifyRange(exp); | |
| 109 | |||
| 110 | case Expression.RECORD() | ||
| 111 | algorithm | ||
| 112 |
4/4✓ Branch 0 taken 26665 times.
✓ Branch 1 taken 2106 times.
✓ Branch 2 taken 26665 times.
✓ Branch 3 taken 2106 times.
|
30877 | exp.elements := list(simplify(e) for e in exp.elements); |
| 113 | then | ||
| 114 | exp; | ||
| 115 | |||
| 116 | 189886 | case Expression.CALL() then simplifyCall(exp); | |
| 117 | 16869 | case Expression.SIZE() then simplifySize(exp); | |
| 118 | 78139 | case Expression.MULTARY() then simplifyMultary(exp); | |
| 119 | 800628 | case Expression.BINARY() then simplifyBinary(exp); | |
| 120 | 52427 | case Expression.UNARY() then simplifyUnary(exp); | |
| 121 | 6493 | case Expression.LBINARY() then simplifyLogicBinary(exp); | |
| 122 | 2044 | case Expression.LUNARY() then simplifyLogicUnary(exp); | |
| 123 | 29860 | case Expression.RELATION() then simplifyRelation(exp); | |
| 124 | 6760 | case Expression.IF() then simplifyIf(exp); | |
| 125 | 11326 | case Expression.CAST() then Expression.typeCast(simplify(exp.exp), exp.ty); | |
| 126 | 65 | case Expression.UNBOX() then Expression.unbox(simplify(exp.exp)); | |
| 127 | 7648 | case Expression.SUBSCRIPTED_EXP() then simplifySubscriptedExp(exp); | |
| 128 | 107 | case Expression.TUPLE_ELEMENT() then simplifyTupleElement(exp); | |
| 129 | 151 | case Expression.RECORD_ELEMENT() then simplifyRecordElement(exp); | |
| 130 | 65 | case Expression.BOX() then Expression.box(simplify(exp.exp)); | |
| 131 | 22343 | case Expression.MUTABLE() then simplify(Mutable.access(exp.exp)); | |
| 132 | 1 | case Expression.INSTANCE_NAME() then Ceval.evalGetInstanceName(exp.scope); | |
| 133 | else exp; | ||
| 134 | end match; | ||
| 135 | |||
| 136 | // simplify dimensions | ||
| 137 | 4609854 | old := Expression.typeOf(exp); | |
| 138 | 4609854 | new := Type.simplify(old); | |
| 139 |
2/2✓ Branch 0 taken 4318057 times.
✓ Branch 1 taken 291797 times.
|
4609854 | if not referenceEq(old, new) then |
| 140 | 291797 | exp := Expression.setType(new, exp); | |
| 141 | end if; | ||
| 142 | end simplify; | ||
| 143 | |||
| 144 | function simplifyRange | ||
| 145 | input Expression range; | ||
| 146 | output Expression exp; | ||
| 147 | protected | ||
| 148 | Expression start_exp1, stop_exp1, start_exp2, stop_exp2; | ||
| 149 | Option<Expression> step_exp1, step_exp2; | ||
| 150 | Type ty, ty2; | ||
| 151 | algorithm | ||
| 152 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14281 times.
|
14281 | Expression.RANGE(ty = ty, start = start_exp1, step = step_exp1, stop = stop_exp1) := range; |
| 153 | |||
| 154 | 14281 | start_exp2 := simplify(start_exp1); | |
| 155 | 14281 | step_exp2 := Util.applyOption(step_exp1, function simplify(includeScope = false)); | |
| 156 | 14281 | stop_exp2 := simplify(stop_exp1); | |
| 157 | 14281 | ty2 := Type.simplify(ty); | |
| 158 | |||
| 159 |
3/4✓ Branch 0 taken 11158 times.
✓ Branch 1 taken 3123 times.
✓ Branch 2 taken 11158 times.
✗ Branch 3 not taken.
|
14281 | if referenceEq(start_exp1, start_exp2) and |
| 160 | referenceEq(step_exp1, step_exp2) and | ||
| 161 | referenceEq(stop_exp1, stop_exp2) and | ||
| 162 | referenceEq(ty, ty2) then | ||
| 163 | exp := range; | ||
| 164 | else | ||
| 165 |
2/2✓ Branch 1 taken 13830 times.
✓ Branch 2 taken 451 times.
|
14281 | if not Type.isResizable(ty) then |
| 166 | 13830 | ty := TypeCheck.keepRangeSize( | |
| 167 | TypeCheck.getRangeType(start_exp2, step_exp2, stop_exp2, | ||
| 168 | Type.arrayElementType(ty), Absyn.dummyInfo), ty); | ||
| 169 | else | ||
| 170 | ty := ty2; | ||
| 171 | end if; | ||
| 172 | 14281 | exp := Expression.RANGE(ty, start_exp2, step_exp2, stop_exp2); | |
| 173 | end if; | ||
| 174 | end simplifyRange; | ||
| 175 | |||
| 176 | function simplifyCall | ||
| 177 | input output Expression callExp; | ||
| 178 | protected | ||
| 179 | Call call; | ||
| 180 | list<Expression> args; | ||
| 181 | Boolean builtin, is_pure, scalarize; | ||
| 182 | algorithm | ||
| 183 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 189886 times.
|
189886 | Expression.CALL(call = call) := callExp; |
| 184 | |||
| 185 | callExp := match call | ||
| 186 | case Call.TYPED_CALL(arguments = args) guard not Call.isExternal(call) | ||
| 187 | algorithm | ||
| 188 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 186974 times.
|
186974 | if Flags.isSet(Flags.NF_EXPAND_FUNC_ARGS) then |
| 189 | ✗ | args := list(if Expression.hasArrayCall(arg) then arg else ExpandExp.expand(arg) for arg in args); | |
| 190 | end if; | ||
| 191 | |||
| 192 |
4/4✓ Branch 0 taken 368446 times.
✓ Branch 1 taken 186974 times.
✓ Branch 2 taken 368446 times.
✓ Branch 3 taken 186974 times.
|
555420 | args := list(simplify(arg) for arg in args); |
| 193 | 186974 | call.arguments := args; | |
| 194 | 186974 | builtin := Function.isBuiltin(call.fn); | |
| 195 | 186974 | is_pure := not Function.isImpure(call.fn); | |
| 196 | |||
| 197 | // Use Ceval for builtin pure functions with literal arguments. | ||
| 198 |
2/2✓ Branch 0 taken 147256 times.
✓ Branch 1 taken 39718 times.
|
186974 | if builtin then |
| 199 | 147256 | scalarize := Flags.isSet(Flags.NF_SCALARIZE); | |
| 200 | |||
| 201 |
8/8✓ Branch 0 taken 146393 times.
✓ Branch 1 taken 863 times.
✓ Branch 3 taken 84700 times.
✓ Branch 4 taken 61693 times.
✓ Branch 5 taken 2255 times.
✓ Branch 6 taken 82445 times.
✓ Branch 8 taken 98 times.
✓ Branch 9 taken 2157 times.
|
147256 | if is_pure and List.all(args, Expression.isLiteral) and (scalarize or Type.isScalar(call.ty)) then |
| 202 | try | ||
| 203 | 82543 | callExp := Ceval.evalCall(call, NFCeval.noTarget); | |
| 204 | else | ||
| 205 | 2 | callExp := Expression.CALL(call); | |
| 206 | end try; | ||
| 207 | else | ||
| 208 | 64713 | callExp := simplifyBuiltinCall(Function.nameConsiderBuiltin(call.fn), args, call, expand = scalarize); | |
| 209 | end if; | ||
| 210 | elseif Flags.isSet(Flags.NF_EVAL_CONST_ARG_FUNCS) and is_pure and List.all(args, Expression.isLiteral) then | ||
| 211 | 4111 | callExp := simplifyCall2(call); | |
| 212 | else | ||
| 213 | 35607 | callExp := Expression.CALL(call); | |
| 214 | end if; | ||
| 215 | then | ||
| 216 | callExp; | ||
| 217 | |||
| 218 | case Call.TYPED_CALL(arguments = args) | ||
| 219 | algorithm | ||
| 220 |
4/4✓ Branch 0 taken 1594 times.
✓ Branch 1 taken 539 times.
✓ Branch 2 taken 1594 times.
✓ Branch 3 taken 539 times.
|
2133 | args := list(simplify(arg) for arg in args); |
| 221 | 539 | call.arguments := args; | |
| 222 | 539 | then | |
| 223 | Expression.CALL(call); | ||
| 224 | |||
| 225 | 2027 | case Call.TYPED_ARRAY_CONSTRUCTOR() then simplifyArrayConstructor(call); | |
| 226 | 346 | case Call.TYPED_REDUCTION() then simplifyReduction(call); | |
| 227 | else callExp; | ||
| 228 | end match; | ||
| 229 | end simplifyCall; | ||
| 230 | |||
| 231 | function simplifyCall2 | ||
| 232 | input Call call; | ||
| 233 | output Expression outExp; | ||
| 234 | algorithm | ||
| 235 | 4111 | ErrorExt.setCheckpoint(getInstanceName()); | |
| 236 | |||
| 237 | try | ||
| 238 | 4111 | outExp := Ceval.evalCall(call, NFCeval.noTarget); | |
| 239 | 4106 | ErrorExt.delCheckpoint(getInstanceName()); | |
| 240 | else | ||
| 241 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
|
5 | if Flags.isSet(Flags.FAILTRACE) then |
| 242 | ✗ | ErrorExt.delCheckpoint(getInstanceName()); | |
| 243 | ✗ | Debug.traceln("- " + getInstanceName() + " failed to evaluate " + Call.toString(call) + "\n"); | |
| 244 | else | ||
| 245 | 5 | ErrorExt.rollBack(getInstanceName()); | |
| 246 | end if; | ||
| 247 | |||
| 248 | 5 | outExp := Expression.CALL(call); | |
| 249 | end try; | ||
| 250 | end simplifyCall2; | ||
| 251 | |||
| 252 | function simplifyBuiltinCall | ||
| 253 | input Absyn.Path name; | ||
| 254 | input list<Expression> args; | ||
| 255 | input Call call; | ||
| 256 | input Boolean expand; | ||
| 257 | output Expression exp; | ||
| 258 | algorithm | ||
| 259 | exp := match AbsynUtil.pathFirstIdent(name) | ||
| 260 | case "cat" algorithm | ||
| 261 |
4/4✓ Branch 1 taken 220 times.
✓ Branch 2 taken 5619 times.
✓ Branch 4 taken 84 times.
✓ Branch 5 taken 136 times.
|
5839 | if(not Flags.getConfigBool(Flags.NEW_BACKEND) or List.all(args, Expression.isLiteral)) then |
| 262 | 5703 | exp := ExpandExp.expandBuiltinCat(args, call, false); | |
| 263 | else | ||
| 264 | 136 | exp := simplifyCat(args, call); | |
| 265 | end if; | ||
| 266 | then exp; | ||
| 267 | |||
| 268 | case "pre" then match args | ||
| 269 | case {exp as Expression.BOOLEAN()} then exp; | ||
| 270 | 1237 | else Expression.CALL(call); | |
| 271 | end match; | ||
| 272 | |||
| 273 | 29 | case "delay" then simplifyDelay(args, call); | |
| 274 | 9607 | case "der" then simplifyDer(listHead(args), call); | |
| 275 | 3871 | case "fill" then simplifyFill(listHead(args), listRest(args), call, expand); | |
| 276 | 253 | case "homotopy" then simplifyHomotopy(args, call); | |
| 277 | 16361 | case "max" then simplifyMinMax(args, call, isMin = false); | |
| 278 | 954 | case "min" then simplifyMinMax(args, call, isMin = true); | |
| 279 | ✗ | case "ones" then simplifyFill(Expression.INTEGER(1), args, call, expand); | |
| 280 | 3 | case "product" then simplifySumProduct(listHead(args), call, expand, isSum = false); | |
| 281 | 796 | case "sum" then simplifySumProduct(listHead(args), call, expand, isSum = true); | |
| 282 | 413 | case "transpose" then simplifyTranspose(listHead(args), call, expand); | |
| 283 | 934 | case "vector" then simplifyVector(listHead(args), call); | |
| 284 | ✗ | case "zeros" then simplifyFill(Expression.INTEGER(0), args, call, expand); | |
| 285 | 421 | case "semiLinear" then simplifySemiLinear(args, call); | |
| 286 | 1588 | case "$OMC$PositiveMax" then simplifyPositiveMax(args, call); | |
| 287 | 361 | case "$OMC$inStreamDiv" then simplifyInStreamDiv(args, call); | |
| 288 | 2 | case "OpenModelica_uriToFilename" then simplifyURIToFilename(listHead(args), call); | |
| 289 | |||
| 290 | 22044 | else Expression.CALL(call); | |
| 291 | end match; | ||
| 292 | end simplifyBuiltinCall; | ||
| 293 | |||
| 294 | function simplifyCat | ||
| 295 | input list<Expression> args; | ||
| 296 | input Call call; | ||
| 297 | output Expression exp; | ||
| 298 | protected | ||
| 299 | list<Expression> nonempty_args = list(arg for arg guard(not Expression.sizeZero(arg)) in args); | ||
| 300 | algorithm | ||
| 301 | // first argument is always the dimension to concatenate over | ||
| 302 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 134 times.
|
136 | if listLength(nonempty_args) == 2 then |
| 303 | // if there are two nonempty arguments, take the second as the other does not matter | ||
| 304 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
2 | {_, exp} := nonempty_args; |
| 305 | elseif listLength(nonempty_args) == 1 then | ||
| 306 | // if there is only one nonempty argument, its the dimension, so return any of the empty arguments (first one here) | ||
| 307 | ✗ | _ :: exp :: _ := args; | |
| 308 | else | ||
| 309 | // do nothing, just return original call without the empty arguments | ||
| 310 | 134 | exp := Expression.CALL(Call.setArguments(call, nonempty_args)); | |
| 311 | end if; | ||
| 312 | end simplifyCat; | ||
| 313 | |||
| 314 | function simplifySemiLinear | ||
| 315 | input list<Expression> args; | ||
| 316 | input Call call; | ||
| 317 | output Expression exp; | ||
| 318 | protected | ||
| 319 | Expression x, m1, m2; | ||
| 320 | Type ty; | ||
| 321 | algorithm | ||
| 322 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 421 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 421 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 421 times.
|
421 | {x, m1, m2} := args; |
| 323 | 421 | ty := Expression.typeOf(x); | |
| 324 |
5/6✓ Branch 1 taken 421 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 411 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 4 times.
|
421 | if Expression.isZero(x) or (Expression.isZero(m1) and Expression.isZero(m2)) then |
| 325 | // both slopes x*m1, x*m2 return 0 | ||
| 326 | 6 | exp := Expression.makeZero(ty); | |
| 327 | elseif Expression.isEqual(m1, m2) then | ||
| 328 | // both slopes x*m1, x*m2 are equal | ||
| 329 | ✗ | exp := Expression.BINARY(x, Operator.makeMul(ty), m1); | |
| 330 | else | ||
| 331 | // no simplification, just return | ||
| 332 | 415 | exp := Expression.CALL(call); | |
| 333 | end if; | ||
| 334 | end simplifySemiLinear; | ||
| 335 | |||
| 336 | function simplifyMinMax | ||
| 337 | input list<Expression> args; | ||
| 338 | input Call call; | ||
| 339 | input Boolean isMin; | ||
| 340 | output Expression exp; | ||
| 341 | protected | ||
| 342 | Expression arg; | ||
| 343 | Type ty; | ||
| 344 | algorithm | ||
| 345 |
2/2✓ Branch 1 taken 68 times.
✓ Branch 2 taken 17247 times.
|
17315 | if listLength(args) == 1 then |
| 346 | 68 | arg := listHead(args); | |
| 347 | 68 | ty := Expression.typeOf(arg); | |
| 348 | |||
| 349 |
2/2✓ Branch 1 taken 16 times.
✓ Branch 2 taken 52 times.
|
68 | if Type.isEmptyArray(ty) then |
| 350 | 16 | ty := Type.arrayElementType(ty); | |
| 351 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
|
16 | exp := if isMin then Expression.makeMaxValue(ty) else |
| 352 | Expression.makeMinValue(ty); | ||
| 353 | else | ||
| 354 | 52 | exp := simplifyReducedArrayConstructor(arg, call); | |
| 355 | end if; | ||
| 356 | else | ||
| 357 | 17247 | exp := Expression.CALL(call); | |
| 358 | end if; | ||
| 359 | end simplifyMinMax; | ||
| 360 | |||
| 361 | function simplifyPositiveMax | ||
| 362 | "Simplifies internal `$OMC$PositiveMax`-call if min/max attributes allow it. | ||
| 363 | This is needed because some min/max attributes are updated after alias removal." | ||
| 364 | input list<Expression> args; | ||
| 365 | input Call call; | ||
| 366 | output Expression exp; | ||
| 367 | protected | ||
| 368 | Expression flow_exp, eps; | ||
| 369 | algorithm | ||
| 370 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 1588 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1588 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1588 times.
|
1588 | {flow_exp, eps} := args; |
| 371 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1588 times.
|
1588 | if Expression.isNonPositive(flow_exp) then |
| 372 | // positiveMax(flow_exp, eps) = 0 if flow_exp <= 0 | ||
| 373 | ✗ | exp := Expression.makeZero(Expression.typeOf(flow_exp)); | |
| 374 | elseif Expression.isGreaterOrEqual(flow_exp, eps) then | ||
| 375 | // positiveMax(flow_exp, eps) = flow_exp if flow_exp >= eps | ||
| 376 | exp := flow_exp; | ||
| 377 | else | ||
| 378 | 1588 | exp := Expression.CALL(call); | |
| 379 | end if; | ||
| 380 | end simplifyPositiveMax; | ||
| 381 | |||
| 382 | function simplifyInStreamDiv | ||
| 383 | "Simplifies internal `$OMC$inStreamDiv`-call if first argument is `0/0`." | ||
| 384 | input list<Expression> args; | ||
| 385 | input Call call; | ||
| 386 | input Boolean removeStream = false; | ||
| 387 | output Expression exp; | ||
| 388 | protected | ||
| 389 | Expression stream_exp, fallback; | ||
| 390 | algorithm | ||
| 391 |
1/2✓ Branch 1 taken 434 times.
✗ Branch 2 not taken.
|
434 | if listLength(args) == 2 then |
| 392 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 434 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 434 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 434 times.
|
434 | {stream_exp, fallback} := args; |
| 393 | else | ||
| 394 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because inStreamDiv needs to have exactly two arguments:\n " | |
| 395 | + List.toString(args, Expression.toString)}); | ||
| 396 | ✗ | fail(); | |
| 397 | end if; | ||
| 398 | |||
| 399 |
1/2✓ Branch 1 taken 434 times.
✗ Branch 2 not taken.
|
434 | if Expression.isNaN(stream_exp) then |
| 400 | // inStreamDiv(0/0, fallback) = fallback | ||
| 401 | exp := fallback; | ||
| 402 | elseif removeStream then | ||
| 403 | // inStreamDiv(stream_exp, fallback) = stream_exp in the general case | ||
| 404 | exp := stream_exp; | ||
| 405 | else | ||
| 406 | 361 | exp := Expression.CALL(call); | |
| 407 | end if; | ||
| 408 | end simplifyInStreamDiv; | ||
| 409 | |||
| 410 | function removeStream | ||
| 411 | "Removes all internal calls related to stream connectors, | ||
| 412 | i.e. $OMC$inStreamDiv and $OMC$PositiveMax." | ||
| 413 | input output Expression exp; | ||
| 414 | algorithm | ||
| 415 | 8353 | exp := Expression.mapReverse(exp, removeInStreamDiv); | |
| 416 | end removeStream; | ||
| 417 | |||
| 418 | function removeInStreamDiv | ||
| 419 | input output Expression exp; | ||
| 420 | algorithm | ||
| 421 | exp := match exp | ||
| 422 | local | ||
| 423 | Call call; | ||
| 424 | Expression arg; | ||
| 425 | list<Expression> rest; | ||
| 426 | |||
| 427 | case Expression.CALL(call = call as Call.TYPED_CALL(arguments = arg::rest)) | ||
| 428 | guard("$OMC$inStreamDiv" == AbsynUtil.pathFirstIdent(Function.nameConsiderBuiltin(call.fn))) | ||
| 429 | algorithm | ||
| 430 | 73 | arg := simplify(Expression.map(arg, removePositiveMax), true); | |
| 431 | 73 | then simplifyInStreamDiv(arg :: rest, call, true); | |
| 432 | else exp; | ||
| 433 | end match; | ||
| 434 | end removeInStreamDiv; | ||
| 435 | |||
| 436 | function removePositiveMax | ||
| 437 | input output Expression exp; | ||
| 438 | algorithm | ||
| 439 | exp := match exp | ||
| 440 | local | ||
| 441 | Call call; | ||
| 442 | Expression res, arg; | ||
| 443 | |||
| 444 | case Expression.CALL(call = call as Call.TYPED_CALL(arguments = arg::_)) | ||
| 445 | guard "$OMC$PositiveMax" == AbsynUtil.pathFirstIdent(Function.nameConsiderBuiltin(call.fn)) | ||
| 446 | algorithm | ||
| 447 | // positiveMax(flow_exp, eps) = max(flow_exp, eps) in the general case | ||
| 448 | 318 | res := Expression.CALL(Call.makeTypedCall( | |
| 449 | fn = NFBuiltinFuncs.MAX_REAL, | ||
| 450 | args = call.arguments, | ||
| 451 | variability = Expression.variability(arg), | ||
| 452 | purity = NFPrefixes.Purity.PURE | ||
| 453 | )); | ||
| 454 | then res; | ||
| 455 | else exp; | ||
| 456 | end match; | ||
| 457 | end removePositiveMax; | ||
| 458 | |||
| 459 | function simplifySumProduct | ||
| 460 | input Expression arg; | ||
| 461 | input Call call; | ||
| 462 | input Boolean expand; | ||
| 463 | input Boolean isSum; | ||
| 464 | output Expression exp; | ||
| 465 | protected | ||
| 466 | Boolean expanded; | ||
| 467 | list<Expression> args; | ||
| 468 | Type ty, ety; | ||
| 469 | Operator op; | ||
| 470 | algorithm | ||
| 471 | 799 | ty := Expression.typeOf(arg); | |
| 472 | |||
| 473 |
2/2✓ Branch 1 taken 19 times.
✓ Branch 2 taken 780 times.
|
799 | if Type.isEmptyArray(ty) then |
| 474 | 19 | ety := Type.arrayElementType(ty); | |
| 475 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | exp := if isSum then Expression.makeZero(ety) else Expression.makeOne(ety); |
| 476 | elseif expand then | ||
| 477 | 590 | (exp, expanded) := ExpandExp.expand(arg); | |
| 478 | |||
| 479 |
2/2✓ Branch 0 taken 489 times.
✓ Branch 1 taken 101 times.
|
590 | if expanded then |
| 480 | 489 | args := Expression.arrayScalarElements(exp); | |
| 481 | 489 | ety := Type.arrayElementType(ty); | |
| 482 | |||
| 483 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 489 times.
|
489 | if listEmpty(args) then |
| 484 | ✗ | exp := if isSum then Expression.makeZero(ety) else Expression.makeOne(ety); | |
| 485 | else | ||
| 486 |
2/2✓ Branch 0 taken 487 times.
✓ Branch 1 taken 2 times.
|
489 | op := if isSum then Operator.makeAdd(ety) else |
| 487 | Operator.makeMul(ety); | ||
| 488 | 489 | exp := Expression.MULTARY(args, {}, op); | |
| 489 | 489 | exp := simplify(exp); | |
| 490 | end if; | ||
| 491 | else | ||
| 492 | 101 | exp := simplifyReducedArrayConstructor(arg, call); | |
| 493 | end if; | ||
| 494 | else | ||
| 495 | 190 | exp := simplifyReducedArrayConstructor(arg, call); | |
| 496 | end if; | ||
| 497 | end simplifySumProduct; | ||
| 498 | |||
| 499 | function simplifyReducedArrayConstructor | ||
| 500 | input Expression arg; | ||
| 501 | input Call call; | ||
| 502 | output Expression exp; | ||
| 503 | algorithm | ||
| 504 | exp := match arg | ||
| 505 | local | ||
| 506 | Call arr_call; | ||
| 507 | Function fn; | ||
| 508 | Type ty; | ||
| 509 | Variability var; | ||
| 510 | Purity purity; | ||
| 511 | |||
| 512 | case Expression.CALL(call = arr_call as Call.TYPED_ARRAY_CONSTRUCTOR()) | ||
| 513 | guard Type.dimensionCount(arr_call.ty) == 1 | ||
| 514 | algorithm | ||
| 515 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | Call.TYPED_CALL(fn = fn, ty = ty, var = var, purity = purity) := call; |
| 516 | 10 | then | |
| 517 | Expression.CALL(Call.makeTypedReduction(fn, ty, var, purity, arr_call.exp, arr_call.iters, Absyn.dummyInfo)); | ||
| 518 | |||
| 519 | 333 | else Expression.CALL(call); | |
| 520 | end match; | ||
| 521 | end simplifyReducedArrayConstructor; | ||
| 522 | |||
| 523 | function simplifyTranspose | ||
| 524 | input Expression arg; | ||
| 525 | input Call call; | ||
| 526 | input Boolean expand; | ||
| 527 | output Expression exp; | ||
| 528 | protected | ||
| 529 | Expression e; | ||
| 530 | algorithm | ||
| 531 |
4/4✓ Branch 0 taken 384 times.
✓ Branch 1 taken 29 times.
✓ Branch 3 taken 266 times.
✓ Branch 4 taken 118 times.
|
413 | e := if not expand or Expression.hasArrayCall(arg) then arg else ExpandExp.expand(arg); |
| 532 | |||
| 533 | exp := match e | ||
| 534 | case Expression.ARRAY() | ||
| 535 | guard Array.all(e.elements, Expression.isArray) | ||
| 536 | 268 | then Expression.transposeArray(e); | |
| 537 | |||
| 538 | 145 | else Expression.CALL(call); | |
| 539 | end match; | ||
| 540 | end simplifyTranspose; | ||
| 541 | |||
| 542 | function simplifyVector | ||
| 543 | input Expression arg; | ||
| 544 | input Call call; | ||
| 545 | output Expression exp; | ||
| 546 | protected | ||
| 547 | list<Expression> expl; | ||
| 548 | Boolean is_literal; | ||
| 549 | Type ty; | ||
| 550 | algorithm | ||
| 551 | 934 | expl := Expression.arrayScalarElements(arg); | |
| 552 | 934 | is_literal := Expression.isLiteral(arg); | |
| 553 | |||
| 554 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 934 times.
|
934 | if is_literal then |
| 555 | // Ranges count as literals, make sure they're expanded. | ||
| 556 | ✗ | expl := ExpandExp.expandList(expl); | |
| 557 | end if; | ||
| 558 | |||
| 559 |
3/4✓ Branch 0 taken 934 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 882 times.
✓ Branch 4 taken 52 times.
|
934 | if is_literal or List.all(expl, Expression.isScalar) then |
| 560 | 882 | ty := Type.arrayElementType(Expression.typeOf(arg)); | |
| 561 | 882 | exp := Expression.makeExpArray(listArray(expl), ty); | |
| 562 | else | ||
| 563 | 52 | exp := Expression.CALL(call); | |
| 564 | end if; | ||
| 565 | end simplifyVector; | ||
| 566 | |||
| 567 | function simplifyFill | ||
| 568 | input Expression fillArg; | ||
| 569 | input list<Expression> dimArgs; | ||
| 570 | input Call call; | ||
| 571 | input Boolean expand; | ||
| 572 | output Expression exp; | ||
| 573 | algorithm | ||
| 574 |
4/4✓ Branch 1 taken 2674 times.
✓ Branch 2 taken 1197 times.
✓ Branch 3 taken 507 times.
✓ Branch 4 taken 2167 times.
|
3871 | if List.all(dimArgs, Expression.isLiteral) and expand then |
| 575 | 507 | exp := Expression.fillArgs(fillArg, dimArgs); | |
| 576 | else | ||
| 577 | 3364 | exp := Expression.CALL(call); | |
| 578 | end if; | ||
| 579 | end simplifyFill; | ||
| 580 | |||
| 581 | function simplifyHomotopy | ||
| 582 | input list<Expression> args; | ||
| 583 | input Call call; | ||
| 584 | output Expression exp; | ||
| 585 | algorithm | ||
| 586 | exp := match Flags.getConfigString(Flags.REPLACE_HOMOTOPY) | ||
| 587 | 1 | case "actual" then listHead(args); | |
| 588 | 1 | case "simplified" then listHead(listRest(args)); | |
| 589 | 251 | else Expression.CALL(call); | |
| 590 | end match; | ||
| 591 | end simplifyHomotopy; | ||
| 592 | |||
| 593 | function simplifyDelay | ||
| 594 | input list<Expression> args; | ||
| 595 | input Call call; | ||
| 596 | output Expression callExp; | ||
| 597 | protected | ||
| 598 | Expression exp, delayTime; | ||
| 599 | algorithm | ||
| 600 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
|
29 | exp :: delayTime :: _ := args; |
| 601 | |||
| 602 |
1/2✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
|
29 | if Expression.variability(delayTime) <= Variability.PARAMETER then |
| 603 | 29 | delayTime := Ceval.tryEvalExp(delayTime); | |
| 604 | |||
| 605 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 28 times.
|
29 | if Expression.isZero(delayTime) then |
| 606 | callExp := exp; | ||
| 607 | 1 | return; | |
| 608 | end if; | ||
| 609 | end if; | ||
| 610 | |||
| 611 | 28 | callExp := Expression.CALL(call); | |
| 612 | end simplifyDelay; | ||
| 613 | |||
| 614 | function simplifyDer | ||
| 615 | input Expression arg; | ||
| 616 | input Call call; | ||
| 617 | output Expression exp; | ||
| 618 | algorithm | ||
| 619 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 9606 times.
|
9607 | if Call.variability(call) < Variability.DISCRETE then |
| 620 | 1 | exp := Expression.makeZero(Expression.typeOf(arg)); | |
| 621 | else | ||
| 622 | 9606 | exp := Expression.CALL(call); | |
| 623 | end if; | ||
| 624 | end simplifyDer; | ||
| 625 | |||
| 626 | function simplifyArrayConstructor | ||
| 627 | input Call call; | ||
| 628 | output Expression outExp; | ||
| 629 | protected | ||
| 630 | Type ty; | ||
| 631 | Variability var; | ||
| 632 | Purity pur; | ||
| 633 | Expression exp, e; | ||
| 634 | list<tuple<InstNode, Expression>> iters; | ||
| 635 | InstNode iter; | ||
| 636 | Dimension dim; | ||
| 637 | Integer dim_size; | ||
| 638 | Boolean expanded; | ||
| 639 | algorithm | ||
| 640 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2027 times.
|
2027 | Call.TYPED_ARRAY_CONSTRUCTOR(ty, var, pur, exp, iters) := call; |
| 641 |
4/4✓ Branch 0 taken 2037 times.
✓ Branch 1 taken 2027 times.
✓ Branch 2 taken 2037 times.
✓ Branch 3 taken 2027 times.
|
4064 | iters := list((Util.tuple21(i), simplify(Util.tuple22(i))) for i in iters); |
| 642 | |||
| 643 | outExp := matchcontinue iters | ||
| 644 | case {(iter, e)} | ||
| 645 | algorithm | ||
| 646 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 2019 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2019 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2019 times.
|
2019 | Type.ARRAY(dimensions = {dim}) := Expression.typeOf(e); |
| 647 | 2019 | dim_size := Dimension.size(dim); | |
| 648 | |||
| 649 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1988 times.
|
1990 | if dim_size == 0 then |
| 650 | // Result is Array[0], return empty array expression. | ||
| 651 | 2 | outExp := Expression.makeEmptyArray(ty); | |
| 652 | elseif dim_size == 1 then | ||
| 653 | // Result is Array[1], return array with the single element. | ||
| 654 | 239 | e := ExpandExp.expand(e); | |
| 655 | 239 | e := Expression.arrayScalarElement(e); | |
| 656 | 239 | exp := Expression.replaceIterator(exp, iter, e); | |
| 657 | 239 | exp := Expression.makeArray(ty, listArray({exp})); | |
| 658 | 239 | outExp := simplify(exp); | |
| 659 | elseif Expression.isLiteral(e) and isIteratorSubscriptedArray(exp, iter) then | ||
| 660 | // If the iterator is only used to subscript array expressions like | ||
| 661 | // {{1, 2, 3}[i] for i in 1:3}, then we might as well expand it. | ||
| 662 | 3 | (outExp, expanded) := ExpandExp.expandArrayConstructor(exp, ty, iters); | |
| 663 | |||
| 664 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if expanded then |
| 665 | 3 | outExp := simplify(outExp); | |
| 666 | end if; | ||
| 667 | else | ||
| 668 | 1746 | fail(); | |
| 669 | end if; | ||
| 670 | then | ||
| 671 | outExp; | ||
| 672 | |||
| 673 | else | ||
| 674 | algorithm | ||
| 675 | 1783 | exp := simplify(exp); | |
| 676 | 1783 | ty := Type.simplify(ty); | |
| 677 | 1783 | then | |
| 678 | Expression.CALL(Call.TYPED_ARRAY_CONSTRUCTOR(ty, var, pur, exp, iters)); | ||
| 679 | end matchcontinue; | ||
| 680 | end simplifyArrayConstructor; | ||
| 681 | |||
| 682 | function isIteratorSubscriptedArray | ||
| 683 | input Expression exp; | ||
| 684 | input InstNode iterator; | ||
| 685 | output Boolean res; | ||
| 686 | algorithm | ||
| 687 | res := match exp | ||
| 688 | case Expression.SUBSCRIPTED_EXP() | ||
| 689 |
2/4✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
|
3 | then Expression.isArray(exp.exp) and |
| 690 | List.all(exp.subscripts, function Subscript.equalsIterator(iterator = iterator)); | ||
| 691 | else false; | ||
| 692 | end match; | ||
| 693 | end isIteratorSubscriptedArray; | ||
| 694 | |||
| 695 | function simplifyReduction | ||
| 696 | input Call call; | ||
| 697 | output Expression outExp; | ||
| 698 | algorithm | ||
| 699 | outExp := match call | ||
| 700 | local | ||
| 701 | Expression exp, e; | ||
| 702 | list<tuple<InstNode, Expression>> iters; | ||
| 703 | InstNode iter; | ||
| 704 | Dimension dim; | ||
| 705 | Integer dim_size; | ||
| 706 | |||
| 707 | case Call.TYPED_REDUCTION() | ||
| 708 | algorithm | ||
| 709 |
4/4✓ Branch 0 taken 347 times.
✓ Branch 1 taken 346 times.
✓ Branch 2 taken 347 times.
✓ Branch 3 taken 346 times.
|
693 | iters := list((Util.tuple21(i), simplify(Util.tuple22(i))) for i in call.iters); |
| 710 | then matchcontinue iters | ||
| 711 | case {(iter, e)} | ||
| 712 | algorithm | ||
| 713 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 345 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 345 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 345 times.
|
345 | Type.ARRAY(dimensions = {dim}) := Expression.typeOf(e); |
| 714 | 345 | dim_size := Dimension.size(dim); | |
| 715 | |||
| 716 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 313 times.
|
325 | if dim_size == 0 then |
| 717 | // Iteration range is empty, return default value for reduction. | ||
| 718 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
|
12 | SOME(outExp) := call.defaultExp; |
| 719 | elseif dim_size == 1 then | ||
| 720 | // Iteration range is one, return reduction expression with iterator value applied. | ||
| 721 | 6 | e := ExpandExp.expand(e); | |
| 722 | 6 | e := Expression.arrayScalarElement(e); | |
| 723 | 6 | outExp := Expression.replaceIterator(call.exp, iter, e); | |
| 724 | 6 | outExp := simplify(outExp); | |
| 725 | else | ||
| 726 | 307 | fail(); | |
| 727 | end if; | ||
| 728 | then | ||
| 729 | outExp; | ||
| 730 | |||
| 731 | case _ | ||
| 732 | guard call.var <= Variability.STRUCTURAL_PARAMETER | ||
| 733 | 13 | then Ceval.tryEvalExp(Expression.CALL(call)); | |
| 734 | |||
| 735 | case _ | ||
| 736 | guard Flags.isSet(Flags.NF_SCALARIZE) | ||
| 737 | 234 | then simplifyReduction2(AbsynUtil.pathString(Function.name(call.fn)), call.exp, iters); | |
| 738 | |||
| 739 | else | ||
| 740 | algorithm | ||
| 741 | 96 | call.exp := simplify(call.exp); | |
| 742 | 96 | call.iters := iters; | |
| 743 | 96 | then | |
| 744 | Expression.CALL(call); | ||
| 745 | |||
| 746 | end matchcontinue; | ||
| 747 | end match; | ||
| 748 | end simplifyReduction; | ||
| 749 | |||
| 750 | function simplifyReduction2 | ||
| 751 | input String name; | ||
| 752 | input Expression exp; | ||
| 753 | input list<tuple<InstNode, Expression>> iterators; | ||
| 754 | output Expression outExp; | ||
| 755 | protected | ||
| 756 | InstNode iter; | ||
| 757 | Expression range, default_exp; | ||
| 758 | list<tuple<InstNode, Expression>> iters = {}; | ||
| 759 | Type ty; | ||
| 760 | Operator op; | ||
| 761 | algorithm | ||
| 762 | 234 | ty := Expression.typeOf(exp); | |
| 763 | // Operator records are problematic since the start value isn't simplified | ||
| 764 | // away currently. | ||
| 765 |
2/2✓ Branch 2 taken 1 time.
✓ Branch 3 taken 233 times.
|
234 | false := Type.isRecord(Type.arrayElementType(ty)); |
| 766 | |||
| 767 | (default_exp, op) := match name | ||
| 768 | 233 | case "sum" then (Expression.makeZero(ty), Operator.makeAdd(ty)); | |
| 769 | ✗ | case "product" then (Expression.makeOne(ty), Operator.makeMul(ty)); | |
| 770 | end match; | ||
| 771 | |||
| 772 |
2/2✓ Branch 0 taken 232 times.
✓ Branch 1 taken 219 times.
|
451 | for i in iterators loop |
| 773 | 232 | (iter, range) := i; | |
| 774 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 219 times.
|
232 | (range, true) := ExpandExp.expand(range); |
| 775 | 219 | iters := (iter, range) :: iters; | |
| 776 | end for; | ||
| 777 | |||
| 778 | 219 | outExp := Expression.foldReduction(simplify(exp), listReverseInPlace(iters), | |
| 779 | default_exp, function simplify(includeScope = false), function simplifyBinaryOp(op = op)); | ||
| 780 | end simplifyReduction2; | ||
| 781 | |||
| 782 | function simplifySize | ||
| 783 | input output Expression sizeExp; | ||
| 784 | algorithm | ||
| 785 | sizeExp := match sizeExp | ||
| 786 | local | ||
| 787 | Expression exp, index; | ||
| 788 | Dimension dim; | ||
| 789 | list<Dimension> dims; | ||
| 790 | |||
| 791 | case Expression.SIZE(exp, SOME(index)) | ||
| 792 | algorithm | ||
| 793 | 16866 | index := simplify(index); | |
| 794 | |||
| 795 |
2/2✓ Branch 1 taken 16865 times.
✓ Branch 2 taken 1 time.
|
16866 | if Expression.isLiteral(index) then |
| 796 | 16865 | dim := listGet(Type.arrayDims(Expression.typeOf(exp)), Expression.toInteger(index)); | |
| 797 | |||
| 798 |
2/2✓ Branch 1 taken 468 times.
✓ Branch 2 taken 16397 times.
|
16865 | if Dimension.isKnown(dim) then |
| 799 | 468 | exp := Expression.INTEGER(Dimension.size(dim)); | |
| 800 | else | ||
| 801 | 16397 | exp := Expression.SIZE(exp, SOME(index)); | |
| 802 | end if; | ||
| 803 | else | ||
| 804 | 1 | exp := Expression.SIZE(exp, SOME(index)); | |
| 805 | end if; | ||
| 806 | then | ||
| 807 | exp; | ||
| 808 | |||
| 809 | case Expression.SIZE() | ||
| 810 | algorithm | ||
| 811 | 3 | dims := Type.arrayDims(Expression.typeOf(sizeExp.exp)); | |
| 812 | |||
| 813 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
|
3 | if List.all(dims, function Dimension.isKnown(allowExp = true)) then |
| 814 | ✗ | exp := Expression.makeArray(Type.ARRAY(Type.INTEGER(), {Dimension.fromInteger(listLength(dims))}), | |
| 815 | listArray(list(Dimension.sizeExp(d) for d in dims))); | ||
| 816 | else | ||
| 817 | exp := sizeExp; | ||
| 818 | end if; | ||
| 819 | then | ||
| 820 | exp; | ||
| 821 | |||
| 822 | end match; | ||
| 823 | end simplifySize; | ||
| 824 | |||
| 825 | function simplifyMultary | ||
| 826 | input output Expression exp; | ||
| 827 | algorithm | ||
| 828 | exp := match exp | ||
| 829 | local | ||
| 830 | Operator operator; | ||
| 831 | list<Expression> arguments, inv_arguments, const_args, inv_const_args; | ||
| 832 | Expression new_const, tmp, result; | ||
| 833 | Operator.MathClassification mcl; | ||
| 834 | Boolean neutralConst, isNegative; | ||
| 835 | |||
| 836 | // empty multary with addition -> 0 | ||
| 837 | case Expression.MULTARY(arguments = {}, inv_arguments = {}, operator = operator) | ||
| 838 | guard(Operator.isDashClassification(Operator.getMathClassification(operator))) | ||
| 839 | 16 | then Expression.makeZero(operator.ty); | |
| 840 | |||
| 841 | // empty multary with multiplication -> 1 | ||
| 842 | case Expression.MULTARY(arguments = {}, inv_arguments = {}, operator = operator) | ||
| 843 | ✗ | then Expression.makeOne(operator.ty); | |
| 844 | |||
| 845 | // multary with only one argument | ||
| 846 | case Expression.MULTARY(arguments = {tmp}, inv_arguments = {}) algorithm | ||
| 847 | 1139 | then simplify(tmp); | |
| 848 | |||
| 849 | // non-empty multaries | ||
| 850 | case Expression.MULTARY(arguments = arguments, inv_arguments = inv_arguments, operator = operator) algorithm | ||
| 851 | // get math classification | ||
| 852 | 76984 | mcl := Operator.getMathClassification(operator); | |
| 853 | |||
| 854 | // simplify arguments first | ||
| 855 |
4/4✓ Branch 0 taken 140286 times.
✓ Branch 1 taken 76984 times.
✓ Branch 2 taken 140286 times.
✓ Branch 3 taken 76984 times.
|
217270 | arguments := list(simplify(arg) for arg in arguments); |
| 856 |
4/4✓ Branch 0 taken 24696 times.
✓ Branch 1 taken 76984 times.
✓ Branch 2 taken 24696 times.
✓ Branch 3 taken 76984 times.
|
101680 | inv_arguments := list(simplify(arg) for arg in inv_arguments); |
| 857 | 76984 | (arguments, inv_arguments, isNegative) := simplifyMultarySigns(arguments, inv_arguments, mcl); | |
| 858 | |||
| 859 | // split them into constant and non constant arguments | ||
| 860 | 76984 | (const_args, arguments) := List.splitOnTrue(arguments, isEvaluableLiteral); | |
| 861 | 76984 | (inv_const_args, inv_arguments) := List.splitOnTrue(inv_arguments, isEvaluableLiteral); | |
| 862 | |||
| 863 | // combine the constants | ||
| 864 |
2/2✓ Branch 0 taken 56439 times.
✓ Branch 1 taken 20545 times.
|
76984 | if mcl == NFOperator.MathClassification.ADDITION then |
| 865 | 56439 | (new_const, neutralConst) := Ceval.evalMultaryAddSub(const_args, inv_const_args, Operator.typeOf(operator)); | |
| 866 | elseif mcl == NFOperator.MathClassification.MULTIPLICATION then | ||
| 867 | 20545 | (new_const, neutralConst) := Ceval.evalMultaryMulDiv(const_args, inv_const_args, Operator.typeOf(operator)); | |
| 868 | else | ||
| 869 | ✗ | Error.terminate(getInstanceName() + " detected non-commutative operator in MULTARY(): [" + Operator.mathSymbol(mcl) + | |
| 870 | "]\n with following arguments: " + stringDelimitList(list(Expression.toString(e) for e in const_args), ", ") + | ||
| 871 | "\n and following inverse arguments: " + stringDelimitList(list(Expression.toString(e) for e in inv_const_args), ", "), | ||
| 872 | sourceInfo()); | ||
| 873 | ✗ | fail(); | |
| 874 | end if; | ||
| 875 | |||
| 876 | // remove expressions that are in both arguments and inv_arguments | ||
| 877 | 76984 | (arguments, inv_arguments) := cancelTermsInMultary(arguments, inv_arguments); | |
| 878 | |||
| 879 | // a neutral constant can not be removed if it is the only source of the dimensions, e.g. s * {1.0} | ||
| 880 |
6/6✓ Branch 0 taken 52541 times.
✓ Branch 1 taken 24443 times.
✓ Branch 2 taken 47883 times.
✓ Branch 3 taken 4658 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 47877 times.
|
76984 | if neutralConst and not listEmpty(arguments) and Type.dimensionCount(Expression.typeOf(new_const)) > |
| 881 | List.fold(listAppend(arguments, inv_arguments), maxDimensionCount, 0) then | ||
| 882 | 6 | neutralConst := false; | |
| 883 | end if; | ||
| 884 | |||
| 885 | result := match (mcl, arguments, inv_arguments) | ||
| 886 | // const + {} - {} = const | ||
| 887 | case (NFOperator.MathClassification.ADDITION, {}, {}) | ||
| 888 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12846 times.
|
12848 | then if Expression.isEmpty(new_const) then Expression.makeZero(Expression.typeOf(new_const)) else new_const; |
| 889 | |||
| 890 | // const * {} / {} = const | ||
| 891 | case (NFOperator.MathClassification.MULTIPLICATION, {}, {}) | ||
| 892 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1110 times.
|
1110 | then if Expression.isEmpty(new_const) then Expression.makeOne(Expression.typeOf(new_const)) else new_const; |
| 893 | |||
| 894 | // 0 + {cr} - {} = cr | ||
| 895 | // 1 * {cr} / {} = cr | ||
| 896 | case (_, {tmp}, {}) guard(neutralConst) then tmp; | ||
| 897 | |||
| 898 | // 0 + {} - {cr} = - cr | ||
| 899 | case (NFOperator.MathClassification.ADDITION, {}, {tmp}) guard(neutralConst) | ||
| 900 | 1723 | then Expression.negate(tmp); | |
| 901 | |||
| 902 | // 0 * {...} / {...} = 0 | ||
| 903 | case (NFOperator.MathClassification.MULTIPLICATION, _, _) guard(Expression.isZero(new_const) and not Type.isArray(Operator.typeOf(operator))) then new_const; | ||
| 904 | case (NFOperator.MathClassification.MULTIPLICATION, _, _) guard(Expression.isZero(new_const) and Type.hasKnownSize(Operator.typeOf(operator))) | ||
| 905 | 42 | then Expression.makeZero(Operator.typeOf(operator)); | |
| 906 | |||
| 907 |
2/2✓ Branch 0 taken 44182 times.
✓ Branch 1 taken 9485 times.
|
53667 | else Expression.MULTARY( |
| 908 | arguments = if neutralConst then arguments else new_const :: arguments, | ||
| 909 | inv_arguments = inv_arguments, | ||
| 910 | operator = operator | ||
| 911 | ); | ||
| 912 | end match; | ||
| 913 | |||
| 914 | // negate the expression if there was an odd number of negative arguments (only multiplication) | ||
| 915 |
2/2✓ Branch 0 taken 192 times.
✓ Branch 1 taken 76792 times.
|
76984 | then if isNegative then Expression.negate(result) else result; |
| 916 | |||
| 917 | else algorithm | ||
| 918 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for expression: " + Expression.toString(exp)}); | |
| 919 | ✗ | then fail(); | |
| 920 | end match; | ||
| 921 | end simplifyMultary; | ||
| 922 | |||
| 923 | function simplifyMultarySigns | ||
| 924 | input list<Expression> arguments; | ||
| 925 | input list<Expression> inv_arguments; | ||
| 926 | input Operator.MathClassification mcl; | ||
| 927 | output list<Expression> new_arguments = {}; | ||
| 928 | output list<Expression> new_inv_arguments = {}; | ||
| 929 | output Boolean isNegative = false; // only relevant for multiplication | ||
| 930 | algorithm | ||
| 931 | () := match mcl | ||
| 932 | case NFOperator.MathClassification.ADDITION algorithm | ||
| 933 | // check if arguments are negative | ||
| 934 | // negate them and swap them to the other list | ||
| 935 |
2/2✓ Branch 1 taken 100998 times.
✓ Branch 2 taken 56439 times.
|
157437 | for arg in listReverse(arguments) loop |
| 936 |
2/2✓ Branch 1 taken 12797 times.
✓ Branch 2 taken 88201 times.
|
100998 | if Expression.isNegated(arg) then |
| 937 | 12797 | new_inv_arguments := Expression.negate(arg) :: new_inv_arguments; | |
| 938 | else | ||
| 939 | new_arguments := arg :: new_arguments; | ||
| 940 | end if; | ||
| 941 | end for; | ||
| 942 |
2/2✓ Branch 1 taken 21482 times.
✓ Branch 2 taken 56439 times.
|
77921 | for arg in listReverse(inv_arguments) loop |
| 943 |
2/2✓ Branch 1 taken 270 times.
✓ Branch 2 taken 21212 times.
|
21482 | if Expression.isNegated(arg) then |
| 944 | 270 | new_arguments := Expression.negate(arg) :: new_arguments; | |
| 945 | else | ||
| 946 | new_inv_arguments := arg :: new_inv_arguments; | ||
| 947 | end if; | ||
| 948 | end for; | ||
| 949 | then (); | ||
| 950 | |||
| 951 | case NFOperator.MathClassification.MULTIPLICATION algorithm | ||
| 952 | // check if arguments are negative and negate them. | ||
| 953 | // track if there is an even or odd number of negative arguments | ||
| 954 |
2/2✓ Branch 1 taken 39288 times.
✓ Branch 2 taken 20545 times.
|
59833 | for arg in listReverse(arguments) loop |
| 955 |
2/2✓ Branch 1 taken 195 times.
✓ Branch 2 taken 39093 times.
|
39288 | if Expression.isNegated(arg) then |
| 956 | 195 | new_arguments := Expression.negate(arg) :: new_arguments; | |
| 957 | 195 | isNegative := not isNegative; | |
| 958 | else | ||
| 959 | new_arguments := arg :: new_arguments; | ||
| 960 | end if; | ||
| 961 | end for; | ||
| 962 |
2/2✓ Branch 1 taken 3214 times.
✓ Branch 2 taken 20545 times.
|
23759 | for arg in listReverse(inv_arguments) loop |
| 963 |
2/2✓ Branch 1 taken 11 times.
✓ Branch 2 taken 3203 times.
|
3214 | if Expression.isNegated(arg) then |
| 964 | 11 | new_inv_arguments := Expression.negate(arg) :: new_inv_arguments; | |
| 965 | 11 | isNegative := not isNegative; | |
| 966 | else | ||
| 967 | new_inv_arguments := arg :: new_inv_arguments; | ||
| 968 | end if; | ||
| 969 | end for; | ||
| 970 | then (); | ||
| 971 | |||
| 972 | else algorithm | ||
| 973 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."}); | |
| 974 | ✗ | then fail(); | |
| 975 | end match; | ||
| 976 | end simplifyMultarySigns; | ||
| 977 | |||
| 978 | function simplifyBinary | ||
| 979 | input output Expression binaryExp; | ||
| 980 | protected | ||
| 981 | Expression e1, e2, se1, se2; | ||
| 982 | Operator op; | ||
| 983 | algorithm | ||
| 984 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 800628 times.
|
800628 | Expression.BINARY(e1, op, e2) := binaryExp; |
| 985 | 800628 | se1 := simplify(e1); | |
| 986 | 800628 | se2 := simplify(e2); | |
| 987 | |||
| 988 | 800628 | binaryExp := simplifyBinaryOp(se1, op, se2); | |
| 989 | |||
| 990 |
4/4✓ Branch 1 taken 26073 times.
✓ Branch 2 taken 774555 times.
✓ Branch 4 taken 4675 times.
✓ Branch 5 taken 769880 times.
|
800628 | if Flags.isSet(Flags.NF_EXPAND_OPERATIONS) and not Expression.hasArrayCall(binaryExp) then |
| 991 | 769880 | binaryExp := ExpandExp.expand(binaryExp); | |
| 992 | end if; | ||
| 993 | end simplifyBinary; | ||
| 994 | |||
| 995 | function simplifyBinaryOp | ||
| 996 | input Expression exp1; | ||
| 997 | input Operator op; | ||
| 998 | input Expression exp2; | ||
| 999 | output Expression outExp; | ||
| 1000 | |||
| 1001 | import NFOperator.Op; | ||
| 1002 | algorithm | ||
| 1003 |
4/4✓ Branch 1 taken 184971 times.
✓ Branch 2 taken 714201 times.
✓ Branch 4 taken 32249 times.
✓ Branch 5 taken 152722 times.
|
899172 | if Expression.isLiteral(exp1) and Expression.isLiteral(exp2) then |
| 1004 | 32249 | outExp := Ceval.evalBinaryOp(ExpandExp.expand(exp1), op, ExpandExp.expand(exp2)); | |
| 1005 | elseif Expression.isArray(exp1) and Expression.isArray(exp2) then | ||
| 1006 | outExp := match op.op | ||
| 1007 | 962 | case Op.ADD then simplifyBinaryEW(exp1, op, exp2); | |
| 1008 | 30 | case Op.SUB then simplifyBinaryEW(exp1, op, exp2); | |
| 1009 | ✗ | case Op.ADD_EW then simplifyBinaryEW(exp1, op, exp2); | |
| 1010 | ✗ | case Op.SUB_EW then simplifyBinaryEW(exp1, op, exp2); | |
| 1011 | 1 | case Op.MUL_EW then simplifyBinaryEW(exp1, op, exp2); | |
| 1012 | ✗ | case Op.DIV_EW then simplifyBinaryEW(exp1, op, exp2); | |
| 1013 | ✗ | case Op.POW_EW then simplifyBinaryEW(exp1, op, exp2); | |
| 1014 | 1038 | else Expression.BINARY(exp1, op, exp2); | |
| 1015 | end match; | ||
| 1016 | else | ||
| 1017 | outExp := match op.op | ||
| 1018 | 210659 | case Op.ADD then simplifyBinaryAdd(exp1, op, exp2); | |
| 1019 | 118266 | case Op.SUB then simplifyBinarySub(exp1, op, exp2); | |
| 1020 | 448344 | case Op.MUL then simplifyBinaryMul(exp1, op, exp2); | |
| 1021 | 55063 | case Op.DIV then simplifyBinaryDiv(exp1, op, exp2); | |
| 1022 | 25273 | case Op.POW then simplifyBinaryPow(exp1, op, exp2); | |
| 1023 | 2 | case Op.POW_SCALAR_ARRAY then simplifyBinaryPow(exp1, op, exp2); | |
| 1024 | 28 | case Op.POW_ARRAY_SCALAR then simplifyBinaryPow(exp1, op, exp2); | |
| 1025 | 18 | case Op.SCALAR_PRODUCT guard(Expression.isZero(exp1) or Expression.isZero(exp2)) then Expression.makeZero(op.ty); | |
| 1026 | 7239 | else Expression.BINARY(exp1, op, exp2); | |
| 1027 | end match; | ||
| 1028 | end if; | ||
| 1029 | end simplifyBinaryOp; | ||
| 1030 | |||
| 1031 | function simplifyBinaryAdd | ||
| 1032 | input Expression exp1; | ||
| 1033 | input Operator op; | ||
| 1034 | input Expression exp2; | ||
| 1035 | output Expression outExp; | ||
| 1036 | algorithm | ||
| 1037 |
2/2✓ Branch 1 taken 217326 times.
✓ Branch 2 taken 3368 times.
|
220694 | if Expression.isZero(exp1) then |
| 1038 | // 0 + e = e | ||
| 1039 | outExp := exp2; | ||
| 1040 | elseif Expression.isZero(exp2) then | ||
| 1041 | // e + 0 = e | ||
| 1042 | outExp := exp1; | ||
| 1043 | elseif Expression.isNegated(exp1) then | ||
| 1044 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 35211 times.
|
35211 | if Expression.isNegated(exp2) then |
| 1045 | // (-e1) + (-e2) = -(e1 + e2) | ||
| 1046 | ✗ | outExp := Expression.negate(Expression.BINARY(Expression.negate(exp1), op, Expression.negate(exp2))); | |
| 1047 | else | ||
| 1048 | // (-e1) + e2 = e2 - e1 | ||
| 1049 | 35211 | outExp := simplifyBinarySub(exp2, Operator.invert(op), Expression.negate(exp1)); | |
| 1050 | end if; | ||
| 1051 | elseif Expression.isNegated(exp2) then | ||
| 1052 | // e1 + (-e2) = e1 - e2 | ||
| 1053 | 293 | outExp := simplifyBinarySub(exp1, Operator.invert(op), Expression.negate(exp2)); | |
| 1054 | else | ||
| 1055 | 175199 | outExp := Expression.BINARY(exp1, op, exp2); | |
| 1056 | end if; | ||
| 1057 | end simplifyBinaryAdd; | ||
| 1058 | |||
| 1059 | function simplifyBinarySub | ||
| 1060 | input Expression exp1; | ||
| 1061 | input Operator op; | ||
| 1062 | input Expression exp2; | ||
| 1063 | output Expression outExp; | ||
| 1064 | algorithm | ||
| 1065 |
2/2✓ Branch 1 taken 332 times.
✓ Branch 2 taken 153438 times.
|
153770 | if Expression.isZero(exp1) then |
| 1066 | // 0 - e = -e | ||
| 1067 | 332 | outExp := Expression.negate(exp2); | |
| 1068 | elseif Expression.isZero(exp2) then | ||
| 1069 | // e - 0 = e | ||
| 1070 | outExp := exp1; | ||
| 1071 | elseif Expression.isEqual(exp1, exp2) then | ||
| 1072 | // e - e = 0 | ||
| 1073 | 9 | outExp := Expression.makeZero(Operator.typeOf(op)); | |
| 1074 | elseif Expression.isNegated(exp1) then | ||
| 1075 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10017 times.
|
10017 | if Expression.isNegated(exp2) then |
| 1076 | // (-e1) - (-e2) = e2 - e1 | ||
| 1077 | ✗ | outExp := Expression.BINARY(Expression.negate(exp2), op, Expression.negate(exp1)); | |
| 1078 | else | ||
| 1079 | // (-e1) - e2 = -(e1 + e2) | ||
| 1080 | 10017 | outExp := Expression.negate(simplifyBinaryAdd(Expression.negate(exp1), Operator.invert(op), exp2)); | |
| 1081 | end if; | ||
| 1082 | elseif Expression.isNegated(exp2) then | ||
| 1083 | // e1 - (-e2) = e1 + e2 | ||
| 1084 | 18 | outExp := simplifyBinaryAdd(exp1, Operator.invert(op), Expression.negate(exp2)); | |
| 1085 | else | ||
| 1086 | 141874 | outExp := Expression.BINARY(exp1, op, exp2); | |
| 1087 | end if; | ||
| 1088 | end simplifyBinarySub; | ||
| 1089 | |||
| 1090 | function simplifyBinaryMul | ||
| 1091 | input Expression exp1; | ||
| 1092 | input Operator op; | ||
| 1093 | input Expression exp2; | ||
| 1094 | input Boolean switched = false; | ||
| 1095 | output Expression outExp; | ||
| 1096 | algorithm | ||
| 1097 | outExp := match exp1 | ||
| 1098 | // 0 * e = 0, the zero has to keep the dimensions if e is an array | ||
| 1099 | case Expression.INTEGER(value = 0) guard(not Type.isArray(Operator.typeOf(op))) then exp1; | ||
| 1100 | case Expression.REAL(value = 0.0) guard(not Type.isArray(Operator.typeOf(op))) then exp1; | ||
| 1101 | ✗ | case Expression.INTEGER(value = 0) guard(Type.hasKnownSize(Operator.typeOf(op))) then Expression.makeZero(Operator.typeOf(op)); | |
| 1102 | ✗ | case Expression.REAL(value = 0.0) guard(Type.hasKnownSize(Operator.typeOf(op))) then Expression.makeZero(Operator.typeOf(op)); | |
| 1103 | |||
| 1104 | // 1 * e = e | ||
| 1105 | case Expression.INTEGER(value = 1) then exp2; | ||
| 1106 | case Expression.REAL(value = 1.0) then exp2; | ||
| 1107 | |||
| 1108 |
2/2✓ Branch 0 taken 427111 times.
✓ Branch 1 taken 439109 times.
|
866220 | else |
| 1109 | if switched then | ||
| 1110 | Expression.BINARY(exp2, op, exp1) | ||
| 1111 | else | ||
| 1112 | simplifyBinaryMul(exp2, op, exp1, true); | ||
| 1113 | end match; | ||
| 1114 | end simplifyBinaryMul; | ||
| 1115 | |||
| 1116 | function simplifyBinaryDiv | ||
| 1117 | input Expression exp1; | ||
| 1118 | input Operator op; | ||
| 1119 | input Expression exp2; | ||
| 1120 | output Expression outExp; | ||
| 1121 | algorithm | ||
| 1122 | // fix constants | ||
| 1123 | // e / 1 = e | ||
| 1124 | // e / (-1) = -e | ||
| 1125 | // 0 / e = 0 (e <> 0) | ||
| 1126 |
6/8✓ Branch 1 taken 54741 times.
✓ Branch 2 taken 322 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54741 times.
✓ Branch 8 taken 93 times.
✓ Branch 9 taken 54648 times.
✓ Branch 11 taken 93 times.
✗ Branch 12 not taken.
|
55063 | outExp := |
| 1127 | if Expression.isOne(exp2) then exp1 | ||
| 1128 | elseif Expression.isMinusOne(exp2) then Expression.negate(exp1) | ||
| 1129 | elseif Expression.isZero(exp1) and Expression.isNonZero(exp2) then exp1 | ||
| 1130 | // fix minus signs | ||
| 1131 | // (-e1)/(-e2) = e1/e2 | ||
| 1132 | // e1/(-e2) = -(e1/e2) | ||
| 1133 | // (-e1)/e2 = -(e1/e2) | ||
| 1134 | // e1/e2 = e1/e2 | ||
| 1135 | else match (Expression.isNegated(exp1), Expression.isNegated(exp1)) | ||
| 1136 | 220 | case (true, true) then Expression.BINARY(Expression.negate(exp1), op, Expression.negate(exp2)); | |
| 1137 | ✗ | case (false, true) then Expression.negate(Expression.BINARY(exp1, op, Expression.negate(exp2))); | |
| 1138 | ✗ | case (true, false) then Expression.negate(Expression.BINARY(Expression.negate(exp1), op, exp2)); | |
| 1139 | 54521 | case (false, false) then Expression.BINARY(exp1, op, exp2); | |
| 1140 | end match; | ||
| 1141 | end simplifyBinaryDiv; | ||
| 1142 | |||
| 1143 | function simplifyBinaryPow | ||
| 1144 | input Expression exp1; | ||
| 1145 | input Operator op; | ||
| 1146 | input Expression exp2; | ||
| 1147 | output Expression outExp; | ||
| 1148 | algorithm | ||
| 1149 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 25295 times.
|
25303 | if Expression.isZero(exp2) then |
| 1150 | 8 | outExp := Expression.makeOne(Operator.typeOf(op)); | |
| 1151 | elseif Expression.isOne(exp2) then | ||
| 1152 | outExp := exp1; // FIXME cast to type of `op` | ||
| 1153 | elseif Expression.isZero(exp1) and Expression.isPositive(exp2) then | ||
| 1154 | ✗ | outExp := Expression.makeZero(Operator.typeOf(op)); | |
| 1155 | elseif Expression.isOne(exp1) then | ||
| 1156 | ✗ | outExp := Expression.makeOne(Operator.typeOf(op)); | |
| 1157 | else | ||
| 1158 | 25190 | outExp := Expression.BINARY(exp1, op, exp2); | |
| 1159 | end if; | ||
| 1160 | end simplifyBinaryPow; | ||
| 1161 | |||
| 1162 | function simplifyBinaryEW | ||
| 1163 | input Expression exp1; | ||
| 1164 | input Operator op; | ||
| 1165 | input Expression exp2; | ||
| 1166 | output Expression outExp; | ||
| 1167 | algorithm | ||
| 1168 | 993 | outExp := Expression.makeArray(Operator.typeOf(op), | |
| 1169 | Array.threadMap(Expression.arrayElements(exp1), Expression.arrayElements(exp2), | ||
| 1170 | function simplifyBinaryOp(op = Operator.stripEW(Operator.unlift(op))))); | ||
| 1171 | end simplifyBinaryEW; | ||
| 1172 | |||
| 1173 | function simplifyUnary | ||
| 1174 | input output Expression unaryExp; | ||
| 1175 | protected | ||
| 1176 | Expression e, se; | ||
| 1177 | Operator op; | ||
| 1178 | algorithm | ||
| 1179 | unaryExp := match unaryExp | ||
| 1180 | case Expression.UNARY(_, Expression.UNARY(_, e)) | ||
| 1181 | 337 | then simplify(e); | |
| 1182 | |||
| 1183 | case Expression.UNARY(op, e) algorithm | ||
| 1184 | 52090 | se := simplify(e); | |
| 1185 | 52090 | then simplifyUnaryOp(se, op); | |
| 1186 | |||
| 1187 | else algorithm | ||
| 1188 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, {getInstanceName() + " failed."}); | |
| 1189 | ✗ | then fail(); | |
| 1190 | end match; | ||
| 1191 | |||
| 1192 |
4/4✓ Branch 1 taken 4925 times.
✓ Branch 2 taken 47502 times.
✓ Branch 4 taken 256 times.
✓ Branch 5 taken 47246 times.
|
52427 | if Flags.isSet(Flags.NF_EXPAND_OPERATIONS) and not Expression.hasArrayCall(unaryExp) then |
| 1193 | 47246 | unaryExp := ExpandExp.expand(unaryExp); | |
| 1194 | end if; | ||
| 1195 | end simplifyUnary; | ||
| 1196 | |||
| 1197 | function simplifyUnaryOp | ||
| 1198 | input Expression exp; | ||
| 1199 | input Operator op; | ||
| 1200 | output Expression outExp; | ||
| 1201 | algorithm | ||
| 1202 |
2/2✓ Branch 1 taken 7624 times.
✓ Branch 2 taken 96663 times.
|
104287 | if Expression.isLiteral(exp) then |
| 1203 | 7624 | outExp := Ceval.evalUnaryOp(exp, op); | |
| 1204 | else | ||
| 1205 | 96663 | outExp := simplifyUnarySign(exp, true); | |
| 1206 | end if; | ||
| 1207 | end simplifyUnaryOp; | ||
| 1208 | |||
| 1209 | function simplifyUnarySign | ||
| 1210 | input output Expression unaryExp; | ||
| 1211 | input Boolean isNegative = false; | ||
| 1212 | algorithm | ||
| 1213 | unaryExp := match unaryExp | ||
| 1214 | 15 | case Expression.UNARY() then simplifyUnarySign(unaryExp.exp, not isNegative); | |
| 1215 |
2/2✓ Branch 0 taken 96648 times.
✓ Branch 1 taken 15 times.
|
96663 | else if isNegative then Expression.negate(unaryExp) else unaryExp; |
| 1216 | end match; | ||
| 1217 | end simplifyUnarySign; | ||
| 1218 | |||
| 1219 | function simplifyLogicBinary | ||
| 1220 | input output Expression binaryExp; | ||
| 1221 | protected | ||
| 1222 | Expression e1, e2, se1, se2; | ||
| 1223 | Operator op; | ||
| 1224 | algorithm | ||
| 1225 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6493 times.
|
6493 | Expression.LBINARY(e1, op, e2) := binaryExp; |
| 1226 | 6493 | se1 := simplify(e1); | |
| 1227 | 6493 | se2 := simplify(e2); | |
| 1228 | |||
| 1229 | binaryExp := match op.op | ||
| 1230 | 3918 | case Op.AND then simplifyLogicBinaryAnd(se1, op, se2); | |
| 1231 | 2575 | case Op.OR then simplifyLogicBinaryOr(se1, op, se2); | |
| 1232 | end match; | ||
| 1233 | end simplifyLogicBinary; | ||
| 1234 | |||
| 1235 | function simplifyLogicBinaryAnd | ||
| 1236 | input Expression exp1; | ||
| 1237 | input Operator op; | ||
| 1238 | input Expression exp2; | ||
| 1239 | output Expression exp; | ||
| 1240 | algorithm | ||
| 1241 | exp := match (exp1, exp2) | ||
| 1242 | local | ||
| 1243 | Operator o; | ||
| 1244 | array<Expression> arr; | ||
| 1245 | |||
| 1246 | // false and e => false | ||
| 1247 | case (Expression.BOOLEAN(false), _) then exp1; | ||
| 1248 | // e and false => false | ||
| 1249 | case (_, Expression.BOOLEAN(false)) then exp2; | ||
| 1250 | // true and e => e | ||
| 1251 | case (Expression.BOOLEAN(true), _) then exp2; | ||
| 1252 | // e and true => e | ||
| 1253 | case (_, Expression.BOOLEAN(true)) then exp1; | ||
| 1254 | |||
| 1255 | case (Expression.ARRAY(), Expression.ARRAY()) | ||
| 1256 | algorithm | ||
| 1257 | 1 | o := Operator.unlift(op); | |
| 1258 | 1 | arr := Array.threadMap(exp1.elements, exp2.elements, | |
| 1259 | function simplifyLogicBinaryAnd(op = o)); | ||
| 1260 | 1 | then | |
| 1261 | Expression.makeArray(Operator.typeOf(op), arr); | ||
| 1262 | |||
| 1263 | 3088 | else Expression.LBINARY(exp1, op, exp2); | |
| 1264 | end match; | ||
| 1265 | end simplifyLogicBinaryAnd; | ||
| 1266 | |||
| 1267 | function simplifyLogicBinaryOr | ||
| 1268 | input Expression exp1; | ||
| 1269 | input Operator op; | ||
| 1270 | input Expression exp2; | ||
| 1271 | output Expression exp; | ||
| 1272 | algorithm | ||
| 1273 | exp := match (exp1, exp2) | ||
| 1274 | local | ||
| 1275 | Operator o; | ||
| 1276 | array<Expression> arr; | ||
| 1277 | |||
| 1278 | // true or e => true | ||
| 1279 | case (Expression.BOOLEAN(true), _) then exp1; | ||
| 1280 | // e or true => true | ||
| 1281 | case (_, Expression.BOOLEAN(true)) then exp2; | ||
| 1282 | // false or e => e | ||
| 1283 | case (Expression.BOOLEAN(false), _) then exp2; | ||
| 1284 | // e or false => e | ||
| 1285 | case (_, Expression.BOOLEAN(false)) then exp1; | ||
| 1286 | |||
| 1287 | case (Expression.ARRAY(), Expression.ARRAY()) | ||
| 1288 | algorithm | ||
| 1289 | 1 | o := Operator.unlift(op); | |
| 1290 | 1 | arr := Array.threadMap(exp1.elements, exp2.elements, | |
| 1291 | function simplifyLogicBinaryOr(op = o)); | ||
| 1292 | 1 | then | |
| 1293 | Expression.makeArray(Operator.typeOf(op), arr); | ||
| 1294 | |||
| 1295 | 1459 | else Expression.LBINARY(exp1, op, exp2); | |
| 1296 | end match; | ||
| 1297 | end simplifyLogicBinaryOr; | ||
| 1298 | |||
| 1299 | function simplifyLogicUnary | ||
| 1300 | input output Expression unaryExp; | ||
| 1301 | protected | ||
| 1302 | Expression e, se, newExp; | ||
| 1303 | Operator op; | ||
| 1304 | algorithm | ||
| 1305 | unaryExp := match unaryExp | ||
| 1306 | case Expression.LUNARY(_, Expression.LUNARY(_, e)) | ||
| 1307 | 8 | then simplify(e); | |
| 1308 | |||
| 1309 | case Expression.LUNARY(op, e) algorithm | ||
| 1310 | 2036 | se := simplify(e); | |
| 1311 | |||
| 1312 |
2/2✓ Branch 1 taken 801 times.
✓ Branch 2 taken 1235 times.
|
2036 | if Expression.isLiteral(se) then |
| 1313 | 801 | newExp := Ceval.evalLogicUnaryOp(se, op); | |
| 1314 | elseif not referenceEq(e, se) then | ||
| 1315 | 1235 | newExp := Expression.LUNARY(op, se); | |
| 1316 | else | ||
| 1317 | newExp := unaryExp; | ||
| 1318 | end if; | ||
| 1319 | then newExp; | ||
| 1320 | end match; | ||
| 1321 | end simplifyLogicUnary; | ||
| 1322 | |||
| 1323 | function simplifyRelation | ||
| 1324 | input output Expression relationExp; | ||
| 1325 | protected | ||
| 1326 | Expression e1, e2, se1, se2; | ||
| 1327 | Operator op; | ||
| 1328 | Integer index; | ||
| 1329 | algorithm | ||
| 1330 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29860 times.
|
29860 | Expression.RELATION(e1, op, e2, index) := relationExp; |
| 1331 | 29860 | se1 := simplify(e1); | |
| 1332 | 29860 | se2 := simplify(e2); | |
| 1333 | |||
| 1334 |
4/4✓ Branch 1 taken 4494 times.
✓ Branch 2 taken 25366 times.
✓ Branch 4 taken 4472 times.
✓ Branch 5 taken 22 times.
|
29860 | if Expression.isLiteral(se1) and Expression.isLiteral(se2) then |
| 1335 | 4472 | relationExp := Ceval.evalRelationOp(se1, op, se2); | |
| 1336 | elseif not (referenceEq(e1, se1) and referenceEq(e2, se2)) then | ||
| 1337 | 25388 | relationExp := Expression.RELATION(se1, op, se2, index); | |
| 1338 | end if; | ||
| 1339 | end simplifyRelation; | ||
| 1340 | |||
| 1341 | function simplifyIf | ||
| 1342 | input output Expression ifExp; | ||
| 1343 | protected | ||
| 1344 | Type ty; | ||
| 1345 | Expression cond, tb, fb; | ||
| 1346 | Boolean tb_val; | ||
| 1347 | algorithm | ||
| 1348 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6760 times.
|
6760 | Expression.IF(ty, cond, tb, fb) := ifExp; |
| 1349 | 6760 | cond := simplify(cond); | |
| 1350 | |||
| 1351 | ifExp := match cond | ||
| 1352 | case Expression.BOOLEAN() | ||
| 1353 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 96 times.
|
240 | then simplify(if cond.value then tb else fb); |
| 1354 | |||
| 1355 | else | ||
| 1356 | algorithm | ||
| 1357 | 6592 | tb := simplify(tb); | |
| 1358 | 6592 | fb := simplify(fb); | |
| 1359 | |||
| 1360 |
2/2✓ Branch 1 taken 6557 times.
✓ Branch 2 taken 35 times.
|
6592 | if Expression.isEqual(tb, fb) then |
| 1361 | // if cond then x else x => x | ||
| 1362 | ifExp := tb; | ||
| 1363 | elseif Expression.isBoolean(tb) and Expression.isBoolean(fb) then | ||
| 1364 | // if cond then true else false => cond | ||
| 1365 | // if cond then false else true => not cond | ||
| 1366 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | Expression.BOOLEAN(value = tb_val) := tb; |
| 1367 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | ifExp := if tb_val then cond else Expression.logicNegate(cond); |
| 1368 | else | ||
| 1369 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6551 times.
|
6551 | ty := if Type.isConditionalArray(ty) then |
| 1370 | Type.setConditionalArrayTypes(ty, Expression.typeOf(tb), Expression.typeOf(fb)) else | ||
| 1371 | Expression.typeOf(tb); | ||
| 1372 | 6551 | ifExp := Expression.IF(ty, cond, tb, fb); | |
| 1373 | end if; | ||
| 1374 | then | ||
| 1375 | ifExp; | ||
| 1376 | |||
| 1377 | end match; | ||
| 1378 | end simplifyIf; | ||
| 1379 | |||
| 1380 | function isEvaluableLiteral | ||
| 1381 | "literals that can be combined by constant evaluation, records need their operator functions" | ||
| 1382 | input Expression exp; | ||
| 1383 | output Boolean b = Expression.isLiteral(exp) and not Type.isComplex(Type.arrayElementType(Expression.typeOf(exp))); | ||
| 1384 | end isEvaluableLiteral; | ||
| 1385 | |||
| 1386 | function maxDimensionCount | ||
| 1387 | input Expression exp; | ||
| 1388 | input output Integer count; | ||
| 1389 | algorithm | ||
| 1390 | 100022 | count := max(count, Type.dimensionCount(Expression.typeOf(exp))); | |
| 1391 | end maxDimensionCount; | ||
| 1392 | |||
| 1393 | function simplifySubscriptedExp | ||
| 1394 | input output Expression subscriptedExp; | ||
| 1395 | protected | ||
| 1396 | Expression e; | ||
| 1397 | list<Subscript> subs; | ||
| 1398 | Type ty; | ||
| 1399 | Boolean split; | ||
| 1400 | algorithm | ||
| 1401 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7648 times.
|
7648 | Expression.SUBSCRIPTED_EXP(e, subs, ty, split) := subscriptedExp; |
| 1402 | 7648 | subscriptedExp := simplify(e); | |
| 1403 | 7648 | subs := Subscript.simplifyList(subs, Type.arrayDims(Expression.typeOf(e))); | |
| 1404 | |||
| 1405 |
6/6✓ Branch 0 taken 7249 times.
✓ Branch 1 taken 399 times.
✓ Branch 3 taken 2036 times.
✓ Branch 4 taken 5213 times.
✓ Branch 6 taken 2034 times.
✓ Branch 7 taken 2 times.
|
7648 | if not split and not List.all(subs, Subscript.isLiteral) and Type.isScalar(ty) then |
| 1406 | // Select the first element as long as the subscripted expression is an | ||
| 1407 | // array where all elements are equal, unless all the subscripts are literal | ||
| 1408 | // in which case it's cheaper to just apply them. | ||
| 1409 |
7/8✓ Branch 0 taken 2035 times.
✓ Branch 1 taken 488 times.
✓ Branch 3 taken 2029 times.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 2029 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 489 times.
✓ Branch 11 taken 1540 times.
|
2523 | while not listEmpty(subs) and Expression.isArray(subscriptedExp) and not Expression.isEmptyArray(subscriptedExp) and |
| 1410 | Array.allEqual(Expression.arrayElements(subscriptedExp), Expression.isEqual) loop | ||
| 1411 | 489 | subs := listRest(subs); | |
| 1412 | 489 | subscriptedExp := arrayGet(Expression.arrayElements(subscriptedExp), 1); | |
| 1413 | end while; | ||
| 1414 | |||
| 1415 |
2/2✓ Branch 0 taken 488 times.
✓ Branch 1 taken 1546 times.
|
2034 | if listEmpty(subs) then |
| 1416 | 488 | return; | |
| 1417 | end if; | ||
| 1418 | end if; | ||
| 1419 | |||
| 1420 | |||
| 1421 |
2/2✓ Branch 0 taken 399 times.
✓ Branch 1 taken 6761 times.
|
7160 | if split then |
| 1422 | 399 | subscriptedExp := Expression.SUBSCRIPTED_EXP(subscriptedExp, subs, ty, split); | |
| 1423 | else | ||
| 1424 | 6761 | subscriptedExp := Expression.applySubscripts(subs, subscriptedExp); | |
| 1425 | end if; | ||
| 1426 | end simplifySubscriptedExp; | ||
| 1427 | |||
| 1428 | function simplifyTupleElement | ||
| 1429 | input output Expression tupleExp; | ||
| 1430 | protected | ||
| 1431 | Expression e; | ||
| 1432 | Integer index; | ||
| 1433 | algorithm | ||
| 1434 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
|
107 | Expression.TUPLE_ELEMENT(tupleExp = e, index = index) := tupleExp; |
| 1435 | 107 | e := simplify(e); | |
| 1436 | 107 | tupleExp := Expression.tupleElement(e, index); | |
| 1437 | end simplifyTupleElement; | ||
| 1438 | |||
| 1439 | function simplifyRecordElement | ||
| 1440 | input output Expression exp; | ||
| 1441 | protected | ||
| 1442 | Expression e, e2; | ||
| 1443 | Integer idx; | ||
| 1444 | Type ty; | ||
| 1445 | algorithm | ||
| 1446 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 151 times.
|
151 | Expression.RECORD_ELEMENT(e, idx, _, ty) := exp; |
| 1447 | 151 | e2 := simplify(e); | |
| 1448 | |||
| 1449 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 151 times.
|
151 | if not referenceEq(e, e2) then |
| 1450 | 151 | exp := Expression.nthRecordElement(idx, e2); | |
| 1451 | end if; | ||
| 1452 | end simplifyRecordElement; | ||
| 1453 | |||
| 1454 | public function combineConstantNumbers | ||
| 1455 | input list<Expression> const "has to be a list of REAL(), INTEGER() and/or CAST()"; | ||
| 1456 | input list<Expression> inv_const "has to be a list of REAL(), INTEGER() and/or CAST()"; | ||
| 1457 | input Operator.MathClassification mcl; | ||
| 1458 | input Type ty; | ||
| 1459 | output Expression res; | ||
| 1460 | protected | ||
| 1461 | Real tmp, result; | ||
| 1462 | algorithm | ||
| 1463 | res := match mcl | ||
| 1464 | |||
| 1465 | case NFOperator.MathClassification.ADDITION algorithm | ||
| 1466 | result := 0.0; | ||
| 1467 | // sum all constants | ||
| 1468 | ✗ | for exp in const loop | |
| 1469 | ✗ | tmp := getConstantValue(exp); | |
| 1470 | ✗ | result := result + tmp; | |
| 1471 | end for; | ||
| 1472 | // subtract all inverse constants | ||
| 1473 | ✗ | for exp in inv_const loop | |
| 1474 | ✗ | tmp := getConstantValue(exp); | |
| 1475 | ✗ | result := result - tmp; | |
| 1476 | end for; | ||
| 1477 | ✗ | res := if Type.isInteger(ty) then Expression.INTEGER(realInt(result)) | |
| 1478 | else Expression.REAL(result); | ||
| 1479 | then res; | ||
| 1480 | |||
| 1481 | case NFOperator.MathClassification.MULTIPLICATION algorithm | ||
| 1482 | result := 1.0; | ||
| 1483 | // multiply all constants | ||
| 1484 | ✗ | for exp in const loop | |
| 1485 | ✗ | tmp := getConstantValue(exp); | |
| 1486 | ✗ | result := result * tmp; | |
| 1487 | end for; | ||
| 1488 | ✗ | if result == 0.0 then | |
| 1489 | // numerator is zero | ||
| 1490 | ✗ | if List.any(inv_const, Expression.isZero) then | |
| 1491 | ✗ | res := Expression.makeNaN(ty); | |
| 1492 | else | ||
| 1493 | ✗ | res := Expression.makeZero(ty); | |
| 1494 | end if; | ||
| 1495 | else | ||
| 1496 | // divide all inverse constants | ||
| 1497 | ✗ | for exp in inv_const loop | |
| 1498 | ✗ | tmp := getConstantValue(exp); | |
| 1499 | ✗ | result := result / tmp; | |
| 1500 | end for; | ||
| 1501 | ✗ | res := if Type.isInteger(ty) then Expression.INTEGER(realInt(result)) | |
| 1502 | else Expression.REAL(result); | ||
| 1503 | end if; | ||
| 1504 | then res; | ||
| 1505 | |||
| 1506 | else algorithm | ||
| 1507 | ✗ | Error.terminate(getInstanceName() + " detected non-commutative operator in MULTARY(): [" + Operator.mathSymbol(mcl) + | |
| 1508 | "]\n with following arguments: " + stringDelimitList(list(Expression.toString(e) for e in const), ", ") + | ||
| 1509 | "\n and following inverse arguments: " + stringDelimitList(list(Expression.toString(e) for e in inv_const), ", "), | ||
| 1510 | sourceInfo()); | ||
| 1511 | ✗ | then fail(); | |
| 1512 | |||
| 1513 | end match; | ||
| 1514 | end combineConstantNumbers; | ||
| 1515 | |||
| 1516 | protected function getConstantValue | ||
| 1517 | input Expression exp; | ||
| 1518 | output Real value; | ||
| 1519 | algorithm | ||
| 1520 | try | ||
| 1521 | ✗ | value := Expression.realValue(Ceval.evalExp(exp)); | |
| 1522 | else | ||
| 1523 | ✗ | Error.addInternalError(getInstanceName() + " expression is not known to be a constant number: " + Expression.toString(exp), sourceInfo()); | |
| 1524 | ✗ | fail(); | |
| 1525 | end try; | ||
| 1526 | end getConstantValue; | ||
| 1527 | |||
| 1528 | function cancelTermsInMultary | ||
| 1529 | input list<Expression> inArguments; | ||
| 1530 | input list<Expression> inInv_arguments; | ||
| 1531 | output list<Expression> outArguments = {}; | ||
| 1532 | output list<Expression> outInv_arguments = {}; | ||
| 1533 | protected | ||
| 1534 | UnorderedMap<Expression, Integer> counter; | ||
| 1535 | Expression arg; | ||
| 1536 | Integer count; | ||
| 1537 | |||
| 1538 | function inc | ||
| 1539 | input Option<Integer> oldValue; | ||
| 1540 | input Integer step; | ||
| 1541 | output Integer value; | ||
| 1542 | algorithm | ||
| 1543 | value := match oldValue | ||
| 1544 | 20 | case SOME(value) then value + step; | |
| 1545 | else step; | ||
| 1546 | end match; | ||
| 1547 | end inc; | ||
| 1548 | algorithm | ||
| 1549 |
4/4✓ Branch 0 taken 60014 times.
✓ Branch 1 taken 16970 times.
✓ Branch 2 taken 40163 times.
✓ Branch 3 taken 19851 times.
|
76984 | if listEmpty(inArguments) or listEmpty(inInv_arguments) then |
| 1550 | // nothing can cancel | ||
| 1551 | outArguments := inArguments; | ||
| 1552 | outInv_arguments := inInv_arguments; | ||
| 1553 | 57133 | return; | |
| 1554 | end if; | ||
| 1555 | |||
| 1556 | // count occurences of expressions (numerator +1, denominator -1) | ||
| 1557 | 19851 | counter := UnorderedMap.new<Integer>(Expression.hash, Expression.isEqual); | |
| 1558 |
2/2✓ Branch 0 taken 24240 times.
✓ Branch 1 taken 19851 times.
|
44091 | for arg in inArguments loop |
| 1559 | 24240 | UnorderedMap.addUpdate(arg, function inc(step = 1), counter); | |
| 1560 | end for; | ||
| 1561 |
2/2✓ Branch 0 taken 20322 times.
✓ Branch 1 taken 19851 times.
|
40173 | for arg in inInv_arguments loop |
| 1562 | 20322 | UnorderedMap.addUpdate(arg, function inc(step = -1), counter); | |
| 1563 | end for; | ||
| 1564 | |||
| 1565 | // reconstruct numerator and denominator with remaining terms | ||
| 1566 |
2/2✓ Branch 1 taken 44542 times.
✓ Branch 2 taken 19851 times.
|
64393 | for tpl in UnorderedMap.toList(counter) loop |
| 1567 | 44542 | (arg, count) := tpl; | |
| 1568 |
2/2✓ Branch 0 taken 24224 times.
✓ Branch 1 taken 20318 times.
|
44542 | if count > 0 then |
| 1569 | 24224 | for i in 1:count loop | |
| 1570 | outArguments := arg :: outArguments; | ||
| 1571 | end for; | ||
| 1572 | elseif count < 0 then | ||
| 1573 | 40608 | for i in 1:-count loop | |
| 1574 | outInv_arguments := arg :: outInv_arguments; | ||
| 1575 | end for; | ||
| 1576 | end if; | ||
| 1577 | end for; | ||
| 1578 | 19851 | outArguments := listReverseInPlace(outArguments); | |
| 1579 | 19851 | outInv_arguments := listReverseInPlace(outInv_arguments); | |
| 1580 | end cancelTermsInMultary; | ||
| 1581 | |||
| 1582 | public function combineBinaries | ||
| 1583 | "just a wrapper to remove the interface for traversal" | ||
| 1584 | input output Expression exp; | ||
| 1585 | algorithm | ||
| 1586 | 34615 | exp := Expression.map(exp, removeTrivialScalarProduct); | |
| 1587 | 34615 | exp := combineBinariesExp(exp); | |
| 1588 | end combineBinaries; | ||
| 1589 | |||
| 1590 | public function splitMultary | ||
| 1591 | "inverse functionality to combineBinaries. | ||
| 1592 | returns a multary to its binary representation, as a balanced tree." | ||
| 1593 | input output Expression exp; | ||
| 1594 | algorithm | ||
| 1595 | exp := match exp | ||
| 1596 | local | ||
| 1597 | Expression new_exp, rhs; | ||
| 1598 | list<Expression> args, inv_args; | ||
| 1599 | Operator inv_op; | ||
| 1600 | Boolean is_add; | ||
| 1601 | |||
| 1602 | case Expression.MULTARY() algorithm | ||
| 1603 | 42336 | args := exp.arguments; | |
| 1604 | 42336 | inv_args := exp.inv_arguments; | |
| 1605 | 42336 | inv_op := Operator.invert(exp.operator); | |
| 1606 | 42336 | is_add := Operator.getMathClassification(exp.operator) == NFOperator.MathClassification.ADDITION; | |
| 1607 | |||
| 1608 |
2/2✓ Branch 0 taken 306 times.
✓ Branch 1 taken 42030 times.
|
42336 | if listEmpty(args) then |
| 1609 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 306 times.
|
306 | if listEmpty(inv_args) then |
| 1610 | ✗ | new_exp := if is_add then Expression.makeZero(Operator.typeOf(exp.operator)) | |
| 1611 | else Expression.makeOne(Operator.typeOf(exp.operator)); | ||
| 1612 | elseif is_add then | ||
| 1613 | // -a - b becomes -(a + b) | ||
| 1614 | 253 | new_exp := Expression.negate(chainBinaries(inv_args, exp.operator)); | |
| 1615 | inv_args := {}; | ||
| 1616 | else | ||
| 1617 | // create an artificial 1 to divide by the inverse arguments | ||
| 1618 | 53 | new_exp := Expression.makeOne(Operator.typeOf(exp.operator)); | |
| 1619 | end if; | ||
| 1620 | else | ||
| 1621 | 42030 | new_exp := chainBinaries(args, exp.operator); | |
| 1622 | end if; | ||
| 1623 | |||
| 1624 |
1/2✓ Branch 1 taken 42336 times.
✗ Branch 2 not taken.
|
42336 | if listLength(inv_args) > MAX_CHAIN_TERMS then |
| 1625 | // a - b - c becomes a - (b + c): one level, not one per term | ||
| 1626 | ✗ | rhs := chainBinaries(inv_args, exp.operator); | |
| 1627 | ✗ | new_exp := Expression.BINARY(new_exp, | |
| 1628 | Operator.repairBinary(inv_op, Expression.typeOf(new_exp), Expression.typeOf(rhs)), rhs); | ||
| 1629 | else | ||
| 1630 |
2/2✓ Branch 0 taken 16372 times.
✓ Branch 1 taken 42336 times.
|
58708 | for arg in inv_args loop |
| 1631 | 16372 | new_exp := Expression.BINARY(new_exp, | |
| 1632 | Operator.repairBinary(inv_op, Expression.typeOf(new_exp), Expression.typeOf(arg)), arg); | ||
| 1633 | end for; | ||
| 1634 | end if; | ||
| 1635 | then new_exp; | ||
| 1636 | |||
| 1637 | else exp; | ||
| 1638 | end match; | ||
| 1639 | end splitMultary; | ||
| 1640 | |||
| 1641 | public function chainBinaries | ||
| 1642 | "Chains the expressions with the given operator. A chain of more than | ||
| 1643 | MAX_CHAIN_TERMS is instead paired up level by level, keeping their order, so | ||
| 1644 | that the result is log2(N) deep instead of N." | ||
| 1645 | input list<Expression> args; | ||
| 1646 | input Operator op; | ||
| 1647 | output Expression exp; | ||
| 1648 | protected | ||
| 1649 | list<Expression> level = args, next; | ||
| 1650 | Expression e1, e2; | ||
| 1651 | Operator fixed_op; | ||
| 1652 | algorithm | ||
| 1653 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 42283 times.
|
42283 | if listLength(args) <= MAX_CHAIN_TERMS then |
| 1654 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42283 times.
|
42283 | exp :: level := args; |
| 1655 | |||
| 1656 |
2/2✓ Branch 0 taken 36983 times.
✓ Branch 1 taken 42283 times.
|
79266 | for e in level loop |
| 1657 | 36983 | exp := Expression.BINARY(exp, | |
| 1658 | Operator.repairBinary(op, Expression.typeOf(exp), Expression.typeOf(e)), e); | ||
| 1659 | end for; | ||
| 1660 | |||
| 1661 | 42283 | return; | |
| 1662 | end if; | ||
| 1663 | |||
| 1664 | ✗ | while not listEmpty(level) and not listEmpty(listRest(level)) loop | |
| 1665 | next := {}; | ||
| 1666 | ✗ | while not listEmpty(level) loop | |
| 1667 | ✗ | e1 :: level := level; | |
| 1668 | ✗ | if listEmpty(level) then | |
| 1669 | next := e1 :: next; | ||
| 1670 | else | ||
| 1671 | ✗ | e2 :: level := level; | |
| 1672 | ✗ | fixed_op := Operator.repairBinary(op, Expression.typeOf(e1), Expression.typeOf(e2)); | |
| 1673 | ✗ | next := Expression.BINARY(e1, fixed_op, e2) :: next; | |
| 1674 | end if; | ||
| 1675 | end while; | ||
| 1676 | ✗ | level := listReverseInPlace(next); | |
| 1677 | end while; | ||
| 1678 | ✗ | exp := listHead(level); | |
| 1679 | end chainBinaries; | ||
| 1680 | |||
| 1681 | protected function combineBinariesExp | ||
| 1682 | "author: kabdelhak 09-2020 | ||
| 1683 | Combines binaries for better handling in the backend. | ||
| 1684 | NOTE: 1. does not do any other simplification | ||
| 1685 | 2. also combines inverse operations | ||
| 1686 | e.g. BINARY(BINARY(2, /, y^2), *, BINARY(3, *, x)) | ||
| 1687 | --> MULTARY({2, 3, x}, {y^2},*)" | ||
| 1688 | input Expression exp; | ||
| 1689 | input Option<Operator> optOperator = NONE(); | ||
| 1690 | input output Expression result = Expression.EMPTY(Expression.typeOf(exp)); | ||
| 1691 | input Boolean inverse = false; | ||
| 1692 | algorithm | ||
| 1693 | result := match (optOperator, exp) | ||
| 1694 | local | ||
| 1695 | Operator op; | ||
| 1696 | Expression new_exp; | ||
| 1697 | ComponentRef cref; | ||
| 1698 | Call call; | ||
| 1699 | |||
| 1700 | // ####################################################### | ||
| 1701 | // Building MULTARY() recursively | ||
| 1702 | // ####################################################### | ||
| 1703 | |||
| 1704 | // case 1.0 binary SOME(op) same operator (+, *) | ||
| 1705 | case (SOME(op), Expression.BINARY()) guard(Operator.compare(op, exp.operator) == 0) algorithm | ||
| 1706 | 158 | result := combineBinariesExp(exp.exp1, SOME(op), result, inverse); | |
| 1707 | 158 | result := combineBinariesExp(exp.exp2, SOME(op), result, inverse); | |
| 1708 | then result; | ||
| 1709 | |||
| 1710 | // case 1.1 multary SOME(op) same operator (+, *) | ||
| 1711 | case (SOME(op), Expression.MULTARY()) guard(Operator.compare(op, exp.operator) == 0) algorithm | ||
| 1712 |
2/2✓ Branch 0 taken 313 times.
✓ Branch 1 taken 154 times.
|
467 | for arg in exp.arguments loop |
| 1713 | 313 | result := combineBinariesExp(arg, SOME(exp.operator), result, inverse); | |
| 1714 | end for; | ||
| 1715 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 154 times.
|
161 | for arg in exp.inv_arguments loop |
| 1716 | 7 | result := combineBinariesExp(arg, SOME(exp.operator), result, not inverse); | |
| 1717 | end for; | ||
| 1718 | then result; | ||
| 1719 | |||
| 1720 | // case 2.0 binary SOME(op) inverse operator (-, :) | ||
| 1721 | case (SOME(op), Expression.BINARY()) guard(Operator.isCombineable(op, exp.operator)) algorithm | ||
| 1722 | 24 | result := combineBinariesExp(exp.exp1, SOME(op), result, inverse); | |
| 1723 | 24 | result := combineBinariesExp(exp.exp2, SOME(op), result, not inverse); | |
| 1724 | then result; | ||
| 1725 | |||
| 1726 | // case 2.1 multary SOME(op) inverse operator (-, :) | ||
| 1727 | case (SOME(op), Expression.MULTARY()) guard(Operator.isCombineable(op, exp.operator)) algorithm | ||
| 1728 | ✗ | for arg in exp.arguments loop | |
| 1729 | ✗ | result := combineBinariesExp(arg, SOME(exp.operator), result, inverse); | |
| 1730 | end for; | ||
| 1731 | ✗ | for arg in exp.inv_arguments loop | |
| 1732 | ✗ | result := combineBinariesExp(arg, SOME(exp.operator), result, not inverse); | |
| 1733 | end for; | ||
| 1734 | then result; | ||
| 1735 | |||
| 1736 | // ########################################################## | ||
| 1737 | // Starts a new MULTARY() | ||
| 1738 | // previous not compatible or no MULTARY on the stack at all | ||
| 1739 | // ########################################################## | ||
| 1740 | |||
| 1741 | // case 3.0 _ binary | commutative operator (+, *) | ||
| 1742 | case (_, Expression.BINARY()) guard(Operator.isCommutative(exp.operator)) algorithm | ||
| 1743 | 3246 | new_exp := Expression.MULTARY({}, {}, exp.operator); | |
| 1744 | 3246 | new_exp := combineBinariesExp(exp.exp2, SOME(exp.operator), new_exp, false); | |
| 1745 | 3246 | new_exp := combineBinariesExp(exp.exp1, SOME(exp.operator), new_exp, false); | |
| 1746 | 3246 | then addArgument(result, new_exp, inverse); | |
| 1747 | |||
| 1748 | // case 3.1 _ multary | commutative operator (+, *) | ||
| 1749 | case (_, Expression.MULTARY()) guard(Operator.isCommutative(exp.operator)) algorithm | ||
| 1750 | 2231 | new_exp := Expression.MULTARY({}, {}, exp.operator); | |
| 1751 |
2/2✓ Branch 0 taken 4172 times.
✓ Branch 1 taken 2231 times.
|
6403 | for arg in exp.arguments loop |
| 1752 | 4172 | new_exp := combineBinariesExp(arg, SOME(exp.operator), new_exp, false); | |
| 1753 | end for; | ||
| 1754 |
2/2✓ Branch 0 taken 562 times.
✓ Branch 1 taken 2231 times.
|
2793 | for arg in exp.inv_arguments loop |
| 1755 | 562 | new_exp := combineBinariesExp(arg, SOME(exp.operator), new_exp, true); | |
| 1756 | end for; | ||
| 1757 | 2231 | then addArgument(result, new_exp, inverse); | |
| 1758 | |||
| 1759 | // case 4.0 _ binary | soft commutative operator (-, :) | ||
| 1760 | case (_, Expression.BINARY()) guard(Operator.isSoftCommutative(exp.operator)) algorithm | ||
| 1761 | 1522 | op := Operator.invert(exp.operator); | |
| 1762 | 1522 | new_exp := Expression.MULTARY({}, {}, op); | |
| 1763 | 1522 | new_exp := combineBinariesExp(exp.exp1, SOME(op), new_exp, false); | |
| 1764 | 1522 | new_exp := combineBinariesExp(exp.exp2, SOME(op), new_exp, true); | |
| 1765 | 1522 | then addArgument(result, new_exp, inverse); | |
| 1766 | |||
| 1767 | // case 4.1 _ multary soft | commutative operator (-, :) | ||
| 1768 | // THIS IS NOT ALLOWED TO EXIST! | ||
| 1769 | |||
| 1770 | // ####################################################### | ||
| 1771 | // Other expressions that do not get combined | ||
| 1772 | // ####################################################### | ||
| 1773 | |||
| 1774 | // going deeper on the different expression types | ||
| 1775 | |||
| 1776 | case (_, Expression.CREF(cref = cref as ComponentRef.CREF())) algorithm | ||
| 1777 |
4/4✓ Branch 0 taken 3719 times.
✓ Branch 1 taken 19900 times.
✓ Branch 2 taken 3719 times.
✓ Branch 3 taken 19900 times.
|
43519 | cref.subscripts := list(combineBinariesSubscript(sub) for sub in cref.subscripts); |
| 1778 | 19900 | exp.cref := cref; | |
| 1779 | 19900 | then addArgument(result, exp, inverse); | |
| 1780 | |||
| 1781 | case (_, Expression.ARRAY()) algorithm | ||
| 1782 |
2/2✓ Branch 0 taken 2091 times.
✓ Branch 1 taken 669 times.
|
2760 | if not exp.literal then |
| 1783 | 4182 | exp.elements := Array.map(exp.elements, | |
| 1784 | function combineBinariesExp(optOperator = NONE(), | ||
| 1785 | result = Expression.EMPTY(Expression.typeOf(exp)), inverse = false)); | ||
| 1786 | end if; | ||
| 1787 | 2760 | then addArgument(result, exp, inverse); | |
| 1788 | |||
| 1789 | case (_, Expression.RANGE()) algorithm | ||
| 1790 | 682 | exp.start := combineBinariesExp(exp.start); | |
| 1791 | 682 | exp.stop := combineBinariesExp(exp.stop); | |
| 1792 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 336 times.
|
341 | if isSome(exp.step) then |
| 1793 | 15 | exp.step := SOME(combineBinariesExp(Util.getOption(exp.step))); | |
| 1794 | end if; | ||
| 1795 | 341 | then addArgument(result, exp, inverse); | |
| 1796 | |||
| 1797 | case (_, Expression.TUPLE()) algorithm | ||
| 1798 |
4/4✓ Branch 0 taken 10 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 3 times.
|
16 | exp.elements := list(combineBinariesExp(element) for element in exp.elements); |
| 1799 | 3 | then addArgument(result, exp, inverse); | |
| 1800 | |||
| 1801 | case (_, Expression.RECORD()) algorithm | ||
| 1802 |
4/4✓ Branch 0 taken 364 times.
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 364 times.
✓ Branch 3 taken 130 times.
|
624 | exp.elements := list(combineBinariesExp(element) for element in exp.elements); |
| 1803 | 130 | then addArgument(result, exp, inverse); | |
| 1804 | |||
| 1805 | case (_, Expression.CALL(call = call as Call.TYPED_CALL())) algorithm | ||
| 1806 |
4/4✓ Branch 0 taken 10926 times.
✓ Branch 1 taken 5763 times.
✓ Branch 2 taken 10926 times.
✓ Branch 3 taken 5763 times.
|
22452 | call.arguments := list(combineBinariesExp(arg) for arg in call.arguments); |
| 1807 | 5763 | exp.call := call; | |
| 1808 | 5763 | then addArgument(result, exp, inverse); | |
| 1809 | |||
| 1810 | case (_, Expression.SIZE()) algorithm | ||
| 1811 | ✗ | exp.exp := combineBinariesExp(exp.exp); | |
| 1812 | ✗ | if isSome(exp.dimIndex) then | |
| 1813 | ✗ | exp.dimIndex := SOME(combineBinariesExp(Util.getOption(exp.dimIndex))); | |
| 1814 | end if; | ||
| 1815 | ✗ | then addArgument(result, exp, inverse); | |
| 1816 | |||
| 1817 | case (_, Expression.UNARY()) algorithm | ||
| 1818 | 3540 | exp.exp := combineBinariesExp(exp.exp); | |
| 1819 | 1770 | then addArgument(result, exp, inverse); | |
| 1820 | |||
| 1821 | // ToDo: rules for logical operators (LMULTARY ?) | ||
| 1822 | // For now leave them as is and traverse branches | ||
| 1823 | case (_, Expression.LBINARY()) algorithm | ||
| 1824 | 184 | exp.exp1 := combineBinariesExp(exp.exp1); | |
| 1825 | 184 | exp.exp2 := combineBinariesExp(exp.exp2); | |
| 1826 | 92 | then addArgument(result, exp, inverse); | |
| 1827 | |||
| 1828 | case (_, Expression.LUNARY()) algorithm | ||
| 1829 | 90 | exp.exp := combineBinariesExp(exp.exp); | |
| 1830 | 45 | then addArgument(result, exp, inverse); | |
| 1831 | |||
| 1832 | case (_, Expression.RELATION()) algorithm | ||
| 1833 | 1134 | exp.exp1 := combineBinariesExp(exp.exp1); | |
| 1834 | 1134 | exp.exp2 := combineBinariesExp(exp.exp2); | |
| 1835 | 567 | then addArgument(result, exp, inverse); | |
| 1836 | |||
| 1837 | case (_, Expression.IF()) algorithm | ||
| 1838 | 264 | exp.condition := combineBinariesExp(exp.condition); | |
| 1839 | 264 | exp.trueBranch := combineBinariesExp(exp.trueBranch); | |
| 1840 | 264 | exp.falseBranch := combineBinariesExp(exp.falseBranch); | |
| 1841 | 132 | then addArgument(result, exp, inverse); | |
| 1842 | |||
| 1843 | case (_, Expression.CAST()) algorithm | ||
| 1844 | 196 | exp.exp := combineBinariesExp(exp.exp); | |
| 1845 | 98 | then addArgument(result, exp, inverse); | |
| 1846 | |||
| 1847 | case (_, Expression.BOX()) algorithm | ||
| 1848 | 74 | exp.exp := combineBinariesExp(exp.exp); | |
| 1849 | 37 | then addArgument(result, exp, inverse); | |
| 1850 | |||
| 1851 | case (_, Expression.UNBOX()) algorithm | ||
| 1852 | ✗ | exp.exp := combineBinariesExp(exp.exp); | |
| 1853 | ✗ | then addArgument(result, exp, inverse); | |
| 1854 | |||
| 1855 | case (_, Expression.SUBSCRIPTED_EXP()) algorithm | ||
| 1856 | 200 | exp.exp := combineBinariesExp(exp.exp); | |
| 1857 |
4/4✓ Branch 0 taken 108 times.
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 100 times.
|
308 | exp.subscripts := list(combineBinariesSubscript(sub) for sub in exp.subscripts); |
| 1858 | 100 | then addArgument(result, exp, inverse); | |
| 1859 | |||
| 1860 | case (_, Expression.TUPLE_ELEMENT()) algorithm | ||
| 1861 | ✗ | exp.tupleExp := combineBinariesExp(exp.tupleExp); | |
| 1862 | ✗ | then addArgument(result, exp, inverse); | |
| 1863 | |||
| 1864 | case (_, Expression.RECORD_ELEMENT()) algorithm | ||
| 1865 | 74 | exp.recordExp := combineBinariesExp(exp.recordExp); | |
| 1866 | 37 | then addArgument(result, exp, inverse); | |
| 1867 | |||
| 1868 | case (_, Expression.MUTABLE()) algorithm | ||
| 1869 | ✗ | Mutable.update(exp.exp, combineBinariesExp(Mutable.access(exp.exp))); | |
| 1870 | ✗ | then addArgument(result, exp, inverse); | |
| 1871 | |||
| 1872 | case (_, Expression.PARTIAL_FUNCTION_APPLICATION()) algorithm | ||
| 1873 |
4/4✓ Branch 0 taken 37 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 9 times.
|
55 | exp.args := list(combineBinariesExp(arg) for arg in exp.args); |
| 1874 | 9 | then addArgument(result, exp, inverse); | |
| 1875 | |||
| 1876 | // done on this branch | ||
| 1877 | 33014 | else addArgument(result, exp, inverse); | |
| 1878 | end match; | ||
| 1879 | end combineBinariesExp; | ||
| 1880 | |||
| 1881 | protected function combineBinariesSubscript | ||
| 1882 | input output Subscript subscript; | ||
| 1883 | algorithm | ||
| 1884 | subscript := match subscript | ||
| 1885 | case Subscript.UNTYPED() algorithm | ||
| 1886 | ✗ | subscript.exp := combineBinariesExp(subscript.exp); | |
| 1887 | then subscript; | ||
| 1888 | |||
| 1889 | case Subscript.INDEX() algorithm | ||
| 1890 | 7538 | subscript.index := combineBinariesExp(subscript.index); | |
| 1891 | then subscript; | ||
| 1892 | |||
| 1893 | case Subscript.SLICE() algorithm | ||
| 1894 | 76 | subscript.slice := combineBinariesExp(subscript.slice); | |
| 1895 | then subscript; | ||
| 1896 | |||
| 1897 | case Subscript.EXPANDED_SLICE() algorithm | ||
| 1898 | ✗ | subscript.indices := list(combineBinariesSubscript(sub) for sub in subscript.indices); | |
| 1899 | then subscript; | ||
| 1900 | |||
| 1901 | else subscript; | ||
| 1902 | end match; | ||
| 1903 | end combineBinariesSubscript; | ||
| 1904 | |||
| 1905 | protected function addArgument | ||
| 1906 | input output Expression exp; | ||
| 1907 | input Expression arg; | ||
| 1908 | input Boolean inverse; | ||
| 1909 | algorithm | ||
| 1910 | exp := match exp | ||
| 1911 | // add to inverse arguments | ||
| 1912 | case Expression.MULTARY() guard(inverse) algorithm | ||
| 1913 | 4468 | exp.inv_arguments := arg :: exp.inv_arguments; | |
| 1914 | then exp; | ||
| 1915 | |||
| 1916 | // add to arguments | ||
| 1917 | case Expression.MULTARY() algorithm | ||
| 1918 | 24768 | exp.arguments := arg :: exp.arguments; | |
| 1919 | then exp; | ||
| 1920 | |||
| 1921 | // no multary on the stack, just return the expression | ||
| 1922 | case Expression.EMPTY() then arg; | ||
| 1923 | |||
| 1924 | // cannot be parsed | ||
| 1925 | else algorithm | ||
| 1926 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed to add : " + | |
| 1927 | Expression.toString(arg) + " to " + Expression.toString(exp) + ". Only works for MULTARY()!"}); | ||
| 1928 | ✗ | then fail(); | |
| 1929 | end match; | ||
| 1930 | end addArgument; | ||
| 1931 | |||
| 1932 | function removeTrivialScalarProduct | ||
| 1933 | "removes trivial scalar products of size 1 vectors" | ||
| 1934 | input output Expression exp; | ||
| 1935 | protected | ||
| 1936 | Type ty; | ||
| 1937 | Expression exp1, exp2; | ||
| 1938 | list<Subscript> subs; | ||
| 1939 | algorithm | ||
| 1940 | exp := match exp | ||
| 1941 | // only do something for scalar products of size 1 vectors | ||
| 1942 | case Expression.BINARY(operator = Operator.OPERATOR(ty = ty, op = NFOperator.Op.SCALAR_PRODUCT)) | ||
| 1943 | guard(Type.sizeOf(Expression.typeOf(exp.exp1)) == 1 and Type.sizeOf(Expression.typeOf(exp.exp2)) == 1) algorithm | ||
| 1944 | // generate "1" subscript for each dimension of the vector and apply them to left and right binary argument | ||
| 1945 |
2/2✓ Branch 2 taken 8 times.
✓ Branch 3 taken 8 times.
|
16 | subs := list(Subscript.INDEX(index = Expression.INTEGER(1)) for d in Type.arrayDims(Expression.typeOf(exp.exp1))); |
| 1946 | 8 | exp1 := Expression.applySubscripts(subs, exp.exp1); | |
| 1947 |
2/2✓ Branch 2 taken 8 times.
✓ Branch 3 taken 8 times.
|
16 | subs := list(Subscript.INDEX(index = Expression.INTEGER(1)) for d in Type.arrayDims(Expression.typeOf(exp.exp2))); |
| 1948 | 8 | exp2 := Expression.applySubscripts(subs, exp.exp2); | |
| 1949 | 8 | then Expression.BINARY(exp1, Operator.OPERATOR(ty, op = NFOperator.Op.MUL), exp2); | |
| 1950 | else exp; | ||
| 1951 | end match; | ||
| 1952 | end removeTrivialScalarProduct; | ||
| 1953 | |||
| 1954 | function simplifyURIToFilename | ||
| 1955 | input Expression arg; | ||
| 1956 | input Call call; | ||
| 1957 | output Expression outExp; | ||
| 1958 | algorithm | ||
| 1959 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if Flags.getConfigBool(Flags.BUILDING_FMU) then |
| 1960 | ✗ | outExp := Expression.CALL(Call.makeTypedCall(NFBuiltinFuncs.FMU_LOAD_RESOURCE, {arg}, Call.variability(call), NFPrefixes.Purity.IMPURE)); | |
| 1961 | else | ||
| 1962 | 2 | outExp := Expression.CALL(call); | |
| 1963 | end if; | ||
| 1964 | end simplifyURIToFilename; | ||
| 1965 | |||
| 1966 | annotation(__OpenModelica_Interface="nf_frontend"); | ||
| 1967 | end NFSimplifyExp; | ||
| 1968 |