Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 63.8% 1042 / 0 / 1632
Functions: -% 0 / 1 / 1
Branches: 54.6% 591 / 0 / 1082

OMCompiler/Compiler/FrontEnd/ExpressionSimplify.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 ExpressionSimplify
37 " file: ExpressionSimplify.mo
38 package: ExpressionSimplify
39 description: ExpressionSimplify
40
41
42 This file contains the module ExpressionSimplify, which contains
43 functions to simplify a DAE.Expression."
44
45 // public imports
46 public import Absyn;
47 public import ClassInf;
48 public import DAE;
49 public import Error;
50 public import ExpressionSimplifyTypes;
51
52 protected type ComponentRef = DAE.ComponentRef;
53 protected type Ident = String;
54 protected type Operator = DAE.Operator;
55 protected type Type = DAE.Type;
56 protected type Subscript = DAE.Subscript;
57
58 // protected imports
59 protected import ComponentReference;
60 protected import ComponentReferenceBasics;
61 protected import Config;
62 protected import DAEUtil;
63 protected import Debug;
64 protected import FCore;
65 protected import ElementSource;
66 protected import ErrorExt;
67 protected import Expression;
68 protected import ExpressionBasics;
69 protected import Dump;
70 protected import ExpressionDump;
71 protected import Flags;
72 protected import List;
73 protected import MetaModelica.Dangerous;
74 protected import System;
75 protected import Types;
76 protected import UnorderedMap;
77 protected import Util;
78 protected import Values;
79 protected import ValuesUtil;
80
81 protected constant ExpressionSimplifyTypes.Options optionSimplifyOnly = ExpressionSimplifyTypes.optionSimplifyOnly;
82
83 public function simplify "Simplifies expressions"
84 input DAE.Exp inExp;
85 output DAE.Exp outExp;
86 output Boolean hasChanged;
87 algorithm
88 4140348 (outExp,hasChanged) := simplifyWithOptions(inExp,optionSimplifyOnly);
89 end simplify;
90
91 public function condsimplify "Simplifies expressions on condition"
92 input Boolean cond;
93 input output DAE.Exp ioExp;
94 output Boolean hasChanged = false;
95 algorithm
96
2/2
✓ Branch 0 taken 79802 times.
✓ Branch 1 taken 7863 times.
87665 if cond then
97 7863 (ioExp,hasChanged) := simplifyWithOptions(ioExp,optionSimplifyOnly);
98 end if;
99 end condsimplify;
100
101 public function simplifyBinaryExp
102 input DAE.Exp inExp;
103 output DAE.Exp outExp;
104 algorithm
105 outExp := match inExp
106 local
107 DAE.Exp e1, e2;
108 DAE.Operator op;
109 case DAE.BINARY(exp1 = e1,operator = op, exp2 = e2)
110 2616103 then simplifyBinary(inExp, op, e1, e2);
111
112 else inExp;
113 end match;
114 end simplifyBinaryExp;
115
116 public function simplifyUnaryExp
117 input DAE.Exp inExp;
118 output DAE.Exp outExp;
119 algorithm
120 outExp := match inExp
121 local
122 DAE.Exp e1;
123 DAE.Operator op;
124 case DAE.UNARY(exp = e1,operator = op)
125 181320 then simplifyUnary(inExp, op, e1);
126
127 else inExp;
128 end match;
129 end simplifyUnaryExp;
130
131 protected function simplifyWithOptions "Simplifies expressions"
132 input DAE.Exp inExp;
133 input ExpressionSimplifyTypes.Options options;
134 output DAE.Exp outExp;
135 output Boolean hasChanged;
136 algorithm
137 (outExp,hasChanged) := matchcontinue (inExp,options)
138 local
139 DAE.Exp e, eNew;
140 Boolean b;
141 case (e,ExpressionSimplifyTypes.DO_EVAL())
142 algorithm
143 ✗ (eNew,_) := simplify1WithOptions(e,options); // Basic local simplifications
144 ✗ Error.assertionOrAddSourceMessage(Expression.isConstValue(eNew), Error.INTERNAL_ERROR, {"eval exp failed"}, Absyn.dummyInfo);
145 ✗ b := not ExpressionBasics.expEqual(e,eNew);
146 ✗ then (eNew,b);
147 case (e,_)
148 algorithm
149
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4148211 times.
4148211 false := Config.getNoSimplify();
150 //print("SIMPLIFY BEFORE->" + ExpressionBasics.printExpStr(e) + "\n");
151 4148211 (eNew,_) := simplify1WithOptions(e,options); // Basic local simplifications
152 //print("SIMPLIFY INTERMEDIATE->" + ExpressionBasics.printExpStr(eNew) + "\n");
153 4148211 eNew := simplify2(eNew); // Advanced (global) simplifications
154 4142552 (eNew,_) := simplify1WithOptions(eNew,options); // Basic local simplifications
155 4142552 b := not ExpressionBasics.expEqual(e,eNew);
156 //print("SIMPLIFY FINAL->" + ExpressionBasics.printExpStr(eNew) + "\n");
157 4142552 then (eNew,b);
158 case (e,_)
159 algorithm
160 5659 (eNew,b) := simplify1WithOptions(e,options);
161 then (eNew,b);
162 end matchcontinue;
163 end simplifyWithOptions;
164
165 public function simplifyTraverseHelper
166 input DAE.Exp inExp;
167 input A inA;
168 output DAE.Exp exp;
169 output A a;
170 replaceable type A subtypeof Any;
171 algorithm
172 a := inA;
173 ✗ (exp,_) := simplify(inExp);
174 end simplifyTraverseHelper;
175
176 public function simplify1TraverseHelper
177 input DAE.Exp inExp;
178 input A inA;
179 output DAE.Exp outExp;
180 output A a;
181 replaceable type A subtypeof Any;
182 algorithm
183 a := inA;
184 1980464 outExp := simplify1(inExp);
185 end simplify1TraverseHelper;
186
187 public function simplify1time "simplify1 with timing"
188 input DAE.Exp e;
189 output DAE.Exp outE;
190 protected
191 Real t1,t2;
192 algorithm
193 ✗ t1 := clock();
194 ✗ (outE,_) := simplify1(e);
195 ✗ t2 := clock();
196 ✗ print(if t2 - t1 > 0.01 then ("simplify1 took "+realString(t2 - t1)+" seconds for exp: "+ExpressionBasics.printExpStr(e)+ " \nsimplified to :"+ExpressionBasics.printExpStr(outE)+"\n") else "");
197 end simplify1time;
198
199 public function simplifyWork
200 "This function does some very basic simplification
201 on expressions, like 0*a = 0, [1][1] => 1, etc.
202 This function can be optimised to a switch-statement due to all uniontypes being different.
203 "
204 input DAE.Exp inExp;
205 input ExpressionSimplifyTypes.Options options;
206 output DAE.Exp outExp;
207 output ExpressionSimplifyTypes.Options outOptions;
208 algorithm
209 (outExp,outOptions) := match /* switch: keep it as such */ inExp
210 local
211 DAE.Exp e,exp,e1,e2,e3,exp1;
212 Type t,tp;
213 Boolean b2;
214 list<DAE.Exp> expl;
215 list<DAE.Subscript> subs;
216 ComponentRef c_1;
217 Operator op;
218 Integer index_;
219 Option<tuple<DAE.Exp,Integer,Integer>> isExpisASUB;
220 DAE.ReductionInfo reductionInfo;
221 DAE.ReductionIterators riters;
222 Option<DAE.Exp> oe;
223
224 case DAE.SIZE(exp=e1,sz=oe)
225 5471 then (simplifySize(inExp,e1,oe),options);
226
227 /* simplify different casts. Optimized to only run simplify1 once on subexpression e*/
228 case DAE.CAST(ty = tp,exp=e)
229 algorithm
230 622417 e := simplifyCast(inExp,e,tp);
231 then (e,options);
232
233 case DAE.ASUB(exp = e, sub = subs)
234 algorithm
235
4/4
✓ Branch 0 taken 923045 times.
✓ Branch 1 taken 902274 times.
✓ Branch 2 taken 923045 times.
✓ Branch 3 taken 902274 times.
1825319 expl := list(Expression.getSubscriptExp(sub) for sub in subs);
236 902274 e := simplifyAsubExp(inExp,e,expl);
237 then (e,options);
238
239 930 case DAE.TSUB() then (simplifyTSub(inExp),options);
240
241 // unary operations
242 case DAE.UNARY(operator = op,exp = e1)
243 algorithm
244 2099506 e := simplifyUnary(inExp, op, e1);
245 then (e,options);
246
247 case DAE.BINARY(exp1 = e1, operator = op, exp2 = e2)
248 algorithm
249 34087503 e := simplifyBinary(inExp, op, e1, e2);
250 then (e,options);
251
252 // relations
253 case DAE.RELATION(exp1 = e1,operator = op,exp2 = e2, index=index_, optionExpisASUB=isExpisASUB)
254 algorithm
255 532754 e := simplifyRelation(inExp, op, e1, e2,index_,isExpisASUB);
256 then (e,options);
257
258 // logical unary expressions
259 case DAE.LUNARY(operator = op,exp = e1)
260 algorithm
261 34046 e := simplifyUnary(inExp, op, e1);
262 then (e,options);
263
264 // logical binary expressions
265 case DAE.LBINARY(exp1 = e1,operator = op,exp2 = e2)
266 algorithm
267 172759 e := simplifyLBinary(inExp, op, e1, e2);
268 then (e,options);
269
270 // if true and false branches are equal
271 case DAE.IFEXP(expCond = e1,expThen = e2,expElse = e3)
272 algorithm
273 292846 e := simplifyIfExp(inExp,e1,e2,e3);
274 then (e,options);
275
276 // component references
277 case DAE.CREF(componentRef = c_1,ty=t)
278 algorithm
279 35427158 e := simplifyCref(inExp,c_1,t);
280 then (e,options);
281
282 case DAE.REDUCTION(reductionInfo,e1,riters)
283 algorithm
284 1839 (riters,b2) := simplifyReductionIterators(riters, {}, false);
285
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1823 times.
1839 exp1 := if b2 then DAE.REDUCTION(reductionInfo,e1,riters) else inExp;
286 1839 then (simplifyReduction(exp1),options);
287
288 2692820 case DAE.CALL() then (simplifyCall(inExp),options);
289
290 165493 case DAE.RSUB() then (simplifyRSub(inExp),options);
291
292 3885 case DAE.MATCHEXPRESSION() then (simplifyMatch(inExp),options);
293 2235 case DAE.UNBOX() then (simplifyUnbox(inExp),options);
294 96237 case DAE.BOX() then (simplifyUnbox(inExp),options);
295 1187 case DAE.CONS() then (simplifyCons(inExp),options);
296
297 // Look for things we really *should* have simplified, but only if we did not modify anything!
298 /* case ((e,(false,_)))
299 algorithm
300 true = Flags.isSet(Flags.CHECK_SIMPLIFY);
301 true = Expression.isConst(e);
302 false = Expression.isConstValue(e);
303 str = ExpressionBasics.printExpStr(e);
304 Error.addSourceMessage(Error.SIMPLIFY_CONSTANT_ERROR, {str}, Absyn.dummyInfo);
305 then fail(); */
306
307 // anything else
308 else (inExp,options);
309 end match;
310 end simplifyWork;
311
312 protected function simplifyRSub
313 input output DAE.Exp e;
314 algorithm
315 e := match e
316 local
317 DAE.ComponentRef cr;
318 list<DAE.Exp> exps;
319 list<String> comp;
320 Absyn.Path p1,p2;
321 DAE.Type ty;
322 list<DAE.Var> vars;
323 case DAE.RSUB(exp=DAE.CREF(componentRef=cr), ix=-1)
324 15391 then DAE.CREF(ComponentReference.joinCrefs(cr, ComponentReferenceBasics.makeCrefIdent(e.fieldName, e.ty, {})), e.ty);
325 case DAE.RSUB(exp=DAE.CALL(path=p1, expLst=exps, attr=DAE.CALL_ATTR(ty=DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(path=p2), varLst=vars))), ix=-1)
326 guard AbsynUtil.pathEqual(p1,p2)
327
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 time.
4 then listGet(exps, List.position1OnTrue(list(v.name for v in vars), stringEq, e.fieldName));
328 case DAE.RSUB(exp=DAE.RECORD(exps=exps,comp=comp), ix=-1)
329 1452 then listGet(exps, List.position1OnTrue(comp, stringEq, e.fieldName));
330 else e;
331 end match;
332 end simplifyRSub;
333
334 protected function simplifyAsubExp
335 input DAE.Exp origExp;
336 input DAE.Exp inExp;
337 input list<DAE.Exp> inSubs;
338 output DAE.Exp outExp;
339 algorithm
340 outExp := matchcontinue (inExp, inSubs)
341 local
342 Integer sub, istart, istep, istop;
343 DAE.Type tp;
344 DAE.Exp e;
345 list<DAE.Exp> eLst, subs;
346 Boolean hasRange;
347 Option<DAE.Exp> step;
348 // No ASUB...
349 case (e, {}) then e;
350
351 // ASUB(CAST(e)) -> CAST(liftArray(t), ASUB(e))
352 case (DAE.CAST(tp,e), _)
353 algorithm
354 ✗ tp := Expression.unliftArray(tp);
355 ✗ e := DAE.CAST(tp, DAE.ASUB(e, list(Expression.makeIndexSubscript(s) for s in inSubs)));
356 then e;
357
358 // Simplify asubs which result from function calls
359 case (DAE.TUPLE(PR=eLst), {DAE.ICONST(sub)})
360 guard sub<=listLength(eLst)
361 ✗ then listGet(eLst,sub);
362
363 // Simplify asubs where some of the subscripts are slices.
364 case (_, _)
365 algorithm
366 902265 then simplifyAsubSlicing(inExp, inSubs);
367
368 // other subscripting/asub simplifications where e is not simplified first.
369 case (_, _)
370 algorithm
371 // Are all expressions integers?
372
2/2
✓ Branch 0 taken 921109 times.
✓ Branch 1 taken 896356 times.
1817465 for exp in inSubs loop
373 921109 Expression.expInt(exp);
374 end for;
375 896356 then List.foldr(inSubs,simplifyAsub,inExp);
376
377 // Any range in the subscripts that we can evaluate?
378 case (_, _)
379 algorithm
380 hasRange := false;
381
4/4
✓ Branch 0 taken 164182 times.
✓ Branch 1 taken 144584 times.
✓ Branch 2 taken 164182 times.
✓ Branch 3 taken 144584 times.
308766 subs := list(match exp
382 case DAE.RANGE(start = DAE.ICONST(istart),step = step, stop = DAE.ICONST(istop))
383 algorithm
384 e := Expression.makeArray(list(DAE.ICONST(i) for i in simplifyRange(istart,match step case NONE() then 1; case SOME(DAE.ICONST(istep)) then istep; end match,istop)), DAE.T_INTEGER_DEFAULT, true);
385 hasRange := true;
386 then e;
387 164182 else exp; end match
388 for exp in inSubs);
389
1/2
✓ Branch 0 taken 144584 times.
✗ Branch 1 not taken.
144584 true := hasRange;
390 ✗ then DAE.ASUB(inExp, list(Expression.makeIndexSubscript(s) for s in subs));
391
392 else origExp;
393 end matchcontinue;
394 end simplifyAsubExp;
395
396 protected function simplifyCall
397 input DAE.Exp inExp;
398 output DAE.Exp outExp;
399 algorithm
400 outExp := matchcontinue inExp
401 local
402 DAE.Exp e,e1,e2,exp,zero;
403 list<DAE.Exp> matrix,expl;
404 DAE.CallAttributes attr;
405 DAE.Type tp;
406 Boolean b2;
407 Real r1,r2;
408 String idn, idn2, name;
409 Integer n,i1,i2;
410 DAE.ReductionInfo ri;
411
412 // min|max|sum|product(array(x for x in ...)) -> min(x for x in ...). Only works for scalar arrays (might affect sum; other entries are not valid Modelica)
413 case DAE.CALL(path=Absyn.IDENT(name),expLst={e as DAE.REDUCTION(reductionInfo=ri as DAE.REDUCTIONINFO(path=Absyn.IDENT("array")), iterators={_})}, attr=DAE.CALL_ATTR(ty=tp))
414 guard listMember(name, {"sum", "product", "min", "max"})
415 algorithm
416 ✗ e.reductionInfo := DAE.REDUCTIONINFO(Absyn.IDENT(name), Absyn.COMBINE(), tp, SOME(reductionDefaultValue(name, tp)), ri.foldName, ri.resultName, SOME(reductionExpression(name, tp, ri.foldName, ri.resultName)));
417 then e;
418
419 // homotopy(e, e) => e
420 case DAE.CALL(path=Absyn.IDENT("homotopy"),expLst={e1,e2})
421 guard
422 ExpressionBasics.expEqual(e1,e2)
423 then e1;
424
425 // noEvent propagated to relations and event triggering functions
426 case DAE.CALL(path=Absyn.IDENT("noEvent"),expLst={e})
427 algorithm
428
3/4
✓ Branch 1 taken 8539 times.
✓ Branch 2 taken 207100 times.
✓ Branch 4 taken 8539 times.
✗ Branch 5 not taken.
215639 b2 := Expression.isRelation(e) or Expression.isEventTriggeringFunctionExp(e);
429 8539 then if not b2 then simplifyNoEvent(e) else inExp;
430
431 // der(-v) -> -der(v)
432 case DAE.CALL(path=Absyn.IDENT("der"), expLst={DAE.UNARY(DAE.UMINUS(tp),e1 as DAE.CREF())},attr=attr)
433 130 then
434 DAE.UNARY(DAE.UMINUS(tp),DAE.CALL(Absyn.IDENT("der"),{e1},attr));
435 case DAE.CALL(path=Absyn.IDENT("der"), expLst={DAE.UNARY(DAE.UMINUS_ARR(tp),e1 as DAE.CREF())},attr=attr)
436 ✗ then DAE.UNARY(DAE.UMINUS_ARR(tp),DAE.CALL(Absyn.IDENT("der"),{e1},attr));
437
438 case DAE.CALL(path=Absyn.IDENT("pre"), expLst={DAE.CREF()})
439 then inExp;
440
441 case DAE.CALL(path=Absyn.IDENT("previous"), expLst={DAE.CREF()})
442 then inExp;
443
444 case DAE.CALL(path=Absyn.IDENT("change"), expLst={DAE.CREF()})
445 then inExp;
446
447 case DAE.CALL(path=Absyn.IDENT("edge"), expLst={DAE.CREF()})
448 then inExp;
449
450 case DAE.CALL(path=Absyn.IDENT("pre"), expLst={e as DAE.ASUB(exp = exp)})
451 algorithm
452 ✗ b2 := Expression.isConst(exp);
453 ✗ then if b2 then e else inExp;
454 case DAE.CALL(path=Absyn.IDENT("previous"), expLst={e as DAE.ASUB(exp = exp)})
455 algorithm
456 ✗ b2 := Expression.isConst(exp);
457 ✗ then if b2 then e else inExp;
458 case DAE.CALL(path=Absyn.IDENT("change"), expLst={DAE.ASUB(exp = exp)})
459 algorithm
460 ✗ b2 := Expression.isConst(exp);
461 ✗ then if b2 then DAE.BCONST(false) else inExp;
462 case DAE.CALL(path=Absyn.IDENT("edge"), expLst={DAE.ASUB(exp = exp)})
463 algorithm
464 ✗ b2 := Expression.isConst(exp);
465 ✗ then if b2 then DAE.BCONST(false) else inExp;
466
467 // move pre inside
468 case DAE.CALL(path=Absyn.IDENT("pre"), expLst={e})
469 algorithm
470 28 (e,_) := Expression.traverseExpTopDown(e,preCref,false);
471 then e;
472 case DAE.CALL(path=Absyn.IDENT("previous"), expLst={e})
473 algorithm
474 ✗ (e,_) := Expression.traverseExpTopDown(e,previousCref,false);
475 then e;
476 case DAE.CALL(path=Absyn.IDENT("change"), expLst={e})
477 algorithm
478 ✗ (e,_) := Expression.traverseExpTopDown(e,changeCref,false);
479 then e;
480 case DAE.CALL(path=Absyn.IDENT("edge"), expLst={e})
481 algorithm
482 ✗ (e,_) := Expression.traverseExpTopDown(e,edgeCref,false);
483 then e;
484
485 // normal (pure) call
486 case DAE.CALL(path=Absyn.IDENT(idn),expLst=expl, attr=DAE.CALL_ATTR(isImpure=false))
487 guard
488 Expression.isConstWorkList(expl)
489 41119 then simplifyBuiltinConstantCalls(idn,inExp);
490
491 // simplify some builtin calls, like cross, etc
492 case DAE.CALL(attr=DAE.CALL_ATTR(builtin = true))
493 1549469 then simplifyBuiltinCalls(inExp);
494
495 // simplify identity
496 case DAE.CALL(path = Absyn.IDENT(name = "identity"), expLst = {DAE.ICONST(n)})
497 algorithm
498
6/6
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 80 times.
✓ Branch 4 taken 720 times.
✓ Branch 5 taken 240 times.
✓ Branch 6 taken 480 times.
✓ Branch 7 taken 240 times.
1280 matrix := list(DAE.ARRAY(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_INTEGER(n)}),true,list(if i==j then DAE.ICONST(1) else DAE.ICONST(0) for i in 1:n)) for j in 1:n);
499 160 then DAE.ARRAY(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_INTEGER(n),DAE.DIM_INTEGER(n)}),false,matrix);
500
501 case DAE.CALL(path = Absyn.IDENT(name = "diagonal"), expLst = {DAE.ARRAY(array=expl,ty=tp)})
502 algorithm
503 32 n := listLength(expl);
504 32 tp := Types.arrayElementType(tp);
505 32 zero := Expression.makeConstZero(tp);
506
6/6
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 32 times.
✓ Branch 4 taken 288 times.
✓ Branch 5 taken 96 times.
✓ Branch 6 taken 96 times.
✓ Branch 7 taken 192 times.
512 matrix := list(DAE.ARRAY(DAE.T_ARRAY(tp,{DAE.DIM_INTEGER(n)}),true,list(if i==j then listGet(expl,i) else zero for i in 1:n)) for j in 1:n);
507 64 then DAE.ARRAY(DAE.T_ARRAY(tp,{DAE.DIM_INTEGER(n),DAE.DIM_INTEGER(n)}),false,matrix);
508
509 // arcxxx(xxx(e)) => e; xxx(arcxxx(e)) => e
510 case DAE.CALL(path=Absyn.IDENT(idn),expLst={DAE.CALL(path=Absyn.IDENT(idn2),expLst={e})})
511 guard (idn=="tan" and idn2=="atan")
512 // or (idn=="sin" and idn2=="asin")
513 // or (idn=="cos" and idn2=="acos")
514 then e;
515
516 // modulo for real values
517 case DAE.CALL(path=Absyn.IDENT("mod"),expLst={DAE.RCONST(r1),DAE.RCONST(r2)})
518 guard r2 <> 0.0
519 14 then DAE.RCONST(mod(r1,r2));
520 // modulo for integer values
521 case DAE.CALL(path=Absyn.IDENT("mod"),expLst={DAE.ICONST(i1),DAE.ICONST(i2)})
522 guard i2 <> 0.0
523 ✗ then DAE.ICONST(mod(i1,i2));
524 // integer call
525 case DAE.CALL(path=Absyn.IDENT("integer"),expLst={DAE.RCONST(r1)})
526 ✗ then DAE.ICONST(realInt(r1));
527 // sin(acos(e)) = sqrt(1-e^2)
528 case DAE.CALL(path=Absyn.IDENT("sin"),expLst={DAE.CALL(path=Absyn.IDENT("acos"),expLst={e})})
529 ✗ then Expression.makePureBuiltinCall("sqrt",{DAE.BINARY(DAE.RCONST(1),DAE.SUB(DAE.T_REAL_DEFAULT),DAE.BINARY(e,DAE.MUL(DAE.T_REAL_DEFAULT),e))},DAE.T_REAL_DEFAULT);
530 // cos(asin(e)) = sqrt(1-e^2)
531 case DAE.CALL(path=Absyn.IDENT("cos"),expLst={DAE.CALL(path=Absyn.IDENT("asin"),expLst={e})})
532 ✗ then Expression.makePureBuiltinCall("sqrt",{DAE.BINARY(DAE.RCONST(1),DAE.SUB(DAE.T_REAL_DEFAULT),DAE.BINARY(e,DAE.MUL(DAE.T_REAL_DEFAULT),e))},DAE.T_REAL_DEFAULT);
533 // sin(atan(e)) = e/sqrt(1+e^2)
534 case DAE.CALL(path=Absyn.IDENT("sin"),expLst={DAE.CALL(path=Absyn.IDENT("atan"),expLst={e})})
535 ✗ then DAE.BINARY(e,DAE.DIV(DAE.T_REAL_DEFAULT),Expression.makePureBuiltinCall("sqrt",{DAE.BINARY(DAE.RCONST(1),DAE.ADD(DAE.T_REAL_DEFAULT),DAE.BINARY(e,DAE.MUL(DAE.T_REAL_DEFAULT),e))},DAE.T_REAL_DEFAULT));
536 // cos(atan(e)) = 1/sqrt(1+e^2)
537 case DAE.CALL(path=Absyn.IDENT("cos"),expLst={DAE.CALL(path=Absyn.IDENT("atan"),expLst={e})})
538 ✗ then DAE.BINARY(DAE.RCONST(1),DAE.DIV(DAE.T_REAL_DEFAULT),Expression.makePureBuiltinCall("sqrt",{DAE.BINARY(DAE.RCONST(1),DAE.ADD(DAE.T_REAL_DEFAULT),DAE.BINARY(e,DAE.MUL(DAE.T_REAL_DEFAULT),e))},DAE.T_REAL_DEFAULT));
539 // atan2(y,0) = sign(y)*pi/2
540 case DAE.CALL(path=Absyn.IDENT("atan2"),expLst={e1,e2})
541 guard
542 Expression.isZero(e2)
543 algorithm
544 8 e := Expression.makePureBuiltinCall("sign", {e1}, DAE.T_REAL_DEFAULT);
545 8 then DAE.BINARY(DAE.RCONST(1.570796326794896619231321691639751442),DAE.MUL(DAE.T_REAL_DEFAULT),e);
546 // atan2(0,x) = 0
547 case DAE.CALL(path=Absyn.IDENT("atan2"),expLst={e1 as DAE.RCONST(0.0),_})
548 then e1;
549 case DAE.CALL(path=Absyn.IDENT("atan2"), expLst={DAE.RCONST(r1),DAE.RCONST(r2)})
550 80 then DAE.RCONST(atan2(r1,r2));
551 // abs(-x) = abs(x)
552 case DAE.CALL(path=Absyn.IDENT("abs"),expLst={DAE.UNARY(operator = DAE.UMINUS(ty = tp),exp = e1)})
553 algorithm
554 1 e := Expression.makePureBuiltinCall("abs", {e1}, tp);
555 then e;
556
557 // MetaModelica builtin operators are calls
558 case _
559 guard
560 Config.acceptMetaModelicaGrammar()
561 66389 then simplifyMetaModelicaCalls(inExp);
562 else inExp;
563 end matchcontinue;
564 end simplifyCall;
565
566 protected function preCref
567 input DAE.Exp ie;
568 input Boolean ib;
569 output DAE.Exp oe;
570 output Boolean cont;
571 output Boolean ob;
572 algorithm
573 (oe,cont,ob) := match (ie,ib)
574 local
575 DAE.Exp e;
576 Boolean b;
577 DAE.Type ty;
578 ✗ case (e as DAE.CREF(ty=ty),_) then (Expression.makeBuiltinCall("pre",{e},ty,false),false,true);
579 case (e as DAE.CALL(path=Absyn.IDENT("pre")),b) then (e,false,b);
580 28 case (e,b) then (e,not b,b);
581 end match;
582 end preCref;
583
584 protected function previousCref
585 input DAE.Exp ie;
586 input Boolean ib;
587 output DAE.Exp oe;
588 output Boolean cont;
589 output Boolean ob;
590 algorithm
591 (oe,cont,ob) := match (ie,ib)
592 local
593 DAE.Exp e;
594 Boolean b;
595 DAE.Type ty;
596 ✗ case (e as DAE.CREF(ty=ty),_) then (Expression.makeBuiltinCall("previous",{e},ty,false),false,true);
597 case (e as DAE.CALL(path=Absyn.IDENT("previous")),b) then (e,false,b);
598 ✗ case (e,b) then (e,not b,b);
599 end match;
600 end previousCref;
601
602 protected function changeCref
603 input DAE.Exp ie;
604 input Boolean ib;
605 output DAE.Exp oe;
606 output Boolean cont;
607 output Boolean ob;
608 algorithm
609 (oe,cont,ob) := match (ie,ib)
610 local
611 DAE.Exp e;
612 Boolean b;
613 DAE.Type ty;
614 ✗ case (e as DAE.CREF(ty=ty),_) then (Expression.makeBuiltinCall("change",{e},ty,false),false,true);
615 case (e as DAE.CALL(path=Absyn.IDENT("change")),b) then (e,false,b);
616 ✗ case (e,b) then (e,not b,b);
617 end match;
618 end changeCref;
619
620 protected function edgeCref
621 input DAE.Exp ie;
622 input Boolean ib;
623 output DAE.Exp oe;
624 output Boolean cont;
625 output Boolean ob;
626 algorithm
627 (oe,cont,ob) := match (ie,ib)
628 local
629 DAE.Exp e;
630 Boolean b;
631 DAE.Type ty;
632 ✗ case (e as DAE.CREF(ty=ty),_) then (Expression.makeBuiltinCall("edge",{e},ty,false),false,true);
633 case (e as DAE.CALL(path=Absyn.IDENT("edge")),b) then (e,false,b);
634 ✗ case (e,b) then (e,not b,b);
635 end match;
636 end edgeCref;
637
638 public function simplify1
639 "This function does some very basic simplification
640 on expressions, like 0*a = 0, [1][1] => 1, etc."
641 input DAE.Exp inExp;
642 output DAE.Exp outExp;
643 output Boolean hasChanged;
644 algorithm
645 7398648 (outExp, hasChanged) := simplify1WithOptions(inExp, optionSimplifyOnly);
646 end simplify1;
647
648 public function simplify1o
649 "This function does some very basic simplification
650 on expressions, like 0*a = 0, [1][1] => 1, etc."
651 input Option<DAE.Exp> inExp;
652 output Option<DAE.Exp> outExp;
653 algorithm
654 outExp := match inExp
655 local DAE.Exp e;
656 case SOME(e) algorithm
657 12 (e, _) := simplify1WithOptions(e, optionSimplifyOnly);
658 then SOME(e);
659 else inExp;
660 end match;
661 end simplify1o;
662
663
664 public function simplify1WithOptions
665 "This function does some very basic simplification
666 on expressions, like 0*a = 0, [1][1] => 1, etc."
667 input DAE.Exp inExp;
668 input ExpressionSimplifyTypes.Options options;
669 output DAE.Exp outExp;
670 output Boolean hasChanged;
671 algorithm
672 15695082 (outExp, hasChanged) := simplify1FixP(inExp, options, 100, true, false);
673 15695082 checkSimplify(Flags.isSet(Flags.CHECK_SIMPLIFY), inExp, outExp);
674 end simplify1WithOptions;
675
676 protected function checkSimplify
677 "Verifies that the complexity of the expression is lower or equal than before the simplification was performed"
678 input Boolean check;
679 input DAE.Exp before;
680 input DAE.Exp after;
681 algorithm
682 () := match check
683 local
684 Integer c1,c2;
685 Boolean b;
686 String s1,s2,s3,s4;
687 DAE.Type ty1,ty2;
688 case false then ();
689 case true
690 algorithm
691 ✗ ty1 := Expression.typeof(before);
692 ✗ ty2 := Expression.typeof(after);
693 ✗ b := valueEq(ty1,ty2);
694 ✗ if not b then
695 ✗ s1 := ExpressionBasics.printExpStr(before);
696 ✗ s2 := ExpressionBasics.printExpStr(after);
697 ✗ s3 := TypesDump.unparseType(ty1);
698 ✗ s4 := TypesDump.unparseType(ty2);
699 ✗ Error.addMessage(Error.SIMPLIFICATION_TYPE, {s1,s2,s3,s4});
700 ✗ fail();
701 end if;
702 ✗ c1 := Expression.complexity(before);
703 ✗ c2 := Expression.complexity(after);
704 b := c1 < c2;
705 ✗ if b then
706 ✗ s1 := intString(c2);
707 ✗ s2 := intString(c1);
708 ✗ s3 := ExpressionBasics.printExpStr(before);
709 ✗ s4 := ExpressionBasics.printExpStr(after);
710 ✗ Error.addMessage(Error.SIMPLIFICATION_COMPLEXITY, {s1,s2,s3,s4});
711 ✗ fail();
712 end if;
713 then ();
714 end match;
715 end checkSimplify;
716
717 protected function simplify1FixP
718 "Does fixpoint simplify1 max n times"
719 input DAE.Exp inExp;
720 input ExpressionSimplifyTypes.Options inOptions;
721 input Integer n;
722 input Boolean cont;
723 input Boolean hasChanged;
724 output DAE.Exp outExp;
725 output Boolean outHasChanged;
726 algorithm
727 (outExp,outHasChanged) := match (inExp, inOptions, n, cont)
728 local
729 DAE.Exp exp,expAfterSimplify;
730 Boolean b;
731 String str1,str2;
732 ExpressionSimplifyTypes.Options options;
733 case (exp, _, _, false)
734 algorithm
735 // print("End fixp: " + ExpressionBasics.printExpStr(exp) + "\n");
736 then (exp,hasChanged);
737 case (exp, options, 0, _)
738 algorithm
739 ✗ str1 := ExpressionBasics.printExpStr(exp);
740 ✗ (exp,_) := Expression.traverseExpBottomUp(exp,simplifyWork,options);
741 ✗ str2 := ExpressionBasics.printExpStr(exp);
742 ✗ Error.addMessage(Error.SIMPLIFY_FIXPOINT_MAXIMUM, {str1,str2});
743 then (exp,hasChanged);
744 case (exp, options, _, true)
745 algorithm
746 // print("simplify1 start: " + ExpressionBasics.printExpStr(exp) + "\n");
747 18149716 ErrorExt.setCheckpoint("ExpressionSimplify");
748 18149716 (expAfterSimplify,options) := Expression.traverseExpBottomUp(exp,simplifyWork,options);
749 18149716 b := not referenceEq(expAfterSimplify, exp);
750
2/2
✓ Branch 0 taken 2454634 times.
✓ Branch 1 taken 15695082 times.
18149716 if b then
751 2454634 ErrorExt.rollBack("ExpressionSimplify");
752 else
753 15695082 ErrorExt.delCheckpoint("ExpressionSimplify");
754 end if;
755 // print("simplify1 iter: " + ExpressionBasics.printExpStr(expAfterSimplify) + "\n");
756 18149716 (expAfterSimplify,b) := simplify1FixP(expAfterSimplify,options,n-1,b,b or hasChanged);
757 then (expAfterSimplify,b);
758 end match;
759 end simplify1FixP;
760
761 protected function simplifyReductionIterators
762 input list<DAE.ReductionIterator> inIters;
763 input list<DAE.ReductionIterator> inAcc;
764 input Boolean inChange;
765 output list<DAE.ReductionIterator> outIters;
766 output Boolean outChange;
767 algorithm
768 (outIters,outChange) := match (inIters,inAcc,inChange)
769 local
770 String id;
771 DAE.Exp exp;
772 DAE.Type ty;
773 DAE.ReductionIterator iter;
774 list<DAE.ReductionIterator> iters,acc;
775 Boolean change;
776
777 1835 case ({},acc,change) then (listReverse(acc),change);
778
779 case (DAE.REDUCTIONITER(id,exp,SOME(DAE.BCONST(true)),ty)::iters,acc,_)
780 algorithm
781 24 (iters,change) := simplifyReductionIterators(iters,DAE.REDUCTIONITER(id,exp,NONE(),ty)::acc,true);
782 then (iters,change);
783
784 case (DAE.REDUCTIONITER(id,_,SOME(DAE.BCONST(false)),ty)::_,_,_)
785 4 then ({DAE.REDUCTIONITER(id,DAE.LIST({}),NONE(),ty)},true);
786
787 case (iter::iters,acc,change)
788 algorithm
789 1853 (iters,change) := simplifyReductionIterators(iters,iter::acc,change);
790 then (iters,change);
791 end match;
792 end simplifyReductionIterators;
793
794 protected function simplifyIfExp
795 "Handles simplification of if-expressions"
796 input DAE.Exp origExp;
797 input DAE.Exp cond;
798 input DAE.Exp tb;
799 input DAE.Exp fb;
800 output DAE.Exp exp;
801 algorithm
802 exp := match (cond, tb, fb)
803 local
804 DAE.Exp e,e1,e2;
805 // Condition is constant
806 case (DAE.BCONST(true), _, _) then tb;
807 case (DAE.BCONST(false), _, _) then fb;
808 // The expression is the condition
809 case (exp, DAE.BCONST(true), DAE.BCONST(false)) then exp;
810 case (exp, DAE.BCONST(false), DAE.BCONST(true))
811 algorithm
812 3 exp := DAE.LUNARY(DAE.NOT(DAE.T_BOOL_DEFAULT), exp);
813 then exp;
814 case (e, DAE.BOX(e1), DAE.BOX(e2))
815 algorithm
816 3 e := DAE.IFEXP(e,e1,e2);
817 3 then DAE.BOX(e);
818
2/2
✓ Branch 1 taken 268935 times.
✓ Branch 2 taken 18596 times.
287531 else // Are the branches equal? Then why bother with the condition
819 if ExpressionBasics.expEqual(tb,fb) then tb else origExp;
820 end match;
821 end simplifyIfExp;
822
823 protected function simplifyMetaModelicaCalls "simplifies MetaModelica operators"
824 input DAE.Exp exp;
825 output DAE.Exp outExp;
826 algorithm
827 outExp := match exp
828 local
829 DAE.Exp e,e1,e2,e1_1;
830 Boolean b;
831 Absyn.Path path;
832 list<DAE.Exp> el;
833 Integer i;
834 Real r;
835 String s;
836 Option<DAE.Exp> foldExp;
837 Option<Values.Value> v;
838 DAE.Type ty;
839 DAE.ReductionIterators riters;
840 String foldName,resultName;
841 Absyn.ReductionIterType rit;
842
843 case DAE.CALL(path=Absyn.IDENT("listAppend"),expLst={DAE.LIST(el),e2})
844 algorithm
845 ✗ e := List.fold(listReverse(el), Expression.makeCons, e2);
846 then e;
847
848 case DAE.CALL(path=Absyn.IDENT("listAppend"),expLst={e1,DAE.LIST(valList={})})
849 then e1;
850
851 case DAE.CALL(path=Absyn.IDENT("intString"),expLst={DAE.ICONST(i)})
852 algorithm
853 ✗ s := intString(i);
854 ✗ then DAE.SCONST(s);
855
856 case DAE.CALL(path=Absyn.IDENT("realString"),expLst={DAE.RCONST(r)})
857 algorithm
858 ✗ s := realString(r);
859 ✗ then DAE.SCONST(s);
860
861 case DAE.CALL(path=Absyn.IDENT("boolString"),expLst={DAE.BCONST(b)})
862 algorithm
863 ✗ s := boolString(b);
864 ✗ then DAE.SCONST(s);
865
866 case DAE.CALL(path=Absyn.IDENT("listReverse"),expLst={DAE.LIST(el)})
867 algorithm
868 ✗ el := listReverse(el);
869 ✗ e1_1 := DAE.LIST(el);
870 then e1_1;
871
872 case DAE.CALL(path=Absyn.IDENT("listReverse"),expLst={DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("list"),rit,ty,v,foldName,resultName,foldExp),e1,riters)})
873 algorithm
874 4 e1 := DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("listReverse"),rit,ty,v,foldName,resultName,foldExp),e1,riters);
875 then e1;
876
877 case DAE.CALL(path=Absyn.IDENT("listReverse"),expLst={DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("listReverse"),rit,ty,v,foldName,resultName,foldExp),e1,riters)})
878 algorithm
879 4 e1 := DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("list"),rit,ty,v,foldName,resultName,foldExp),e1,riters);
880 then e1;
881
882 case DAE.CALL(path=Absyn.IDENT("listLength"),expLst={DAE.LIST(el)})
883 algorithm
884 ✗ i := listLength(el);
885 ✗ then DAE.ICONST(i);
886
887 case DAE.CALL(path=Absyn.IDENT("mmc_mk_some"),expLst={e})
888 ✗ then DAE.META_OPTION(SOME(e));
889
890 case DAE.CALL(path=Absyn.IDENT("sourceInfo"))
891 algorithm
892 ✗ print("sourceInfo() - simplify?\n");
893 ✗ then fail();
894 end match;
895 end simplifyMetaModelicaCalls;
896
897 protected function simplifyCons
898 input DAE.Exp inExp;
899 output DAE.Exp outExp;
900 algorithm
901 outExp := match inExp
902 local
903 DAE.Exp e;
904 list<DAE.Exp> es;
905 49 case DAE.CONS(e,DAE.LIST(es)) then DAE.LIST(e::es);
906 else inExp;
907 end match;
908 end simplifyCons;
909
910 protected function simplifyUnbox "simplifies both box and unbox expressions"
911 input DAE.Exp exp;
912 output DAE.Exp outExp;
913 algorithm
914 outExp := match exp
915 case DAE.UNBOX(exp=DAE.BOX(outExp)) then outExp;
916 case DAE.BOX(DAE.UNBOX(exp=outExp)) then outExp;
917 else exp;
918 end match;
919 end simplifyUnbox;
920
921 protected function simplifyMatch "simplifies MetaModelica match expressions"
922 input DAE.Exp exp;
923 output DAE.Exp outExp;
924 algorithm
925 outExp := match exp
926 local
927 DAE.Exp e,e1,e2,e1_1,e2_1;
928 Boolean b1,b2;
929 DAE.Type ty;
930 // match () case () then exp; end match => exp
931 case DAE.MATCHEXPRESSION(inputs={}, et=ty, localDecls={}, cases={
932 DAE.CASE(patterns={},localDecls={},body={},result=SOME(e))
933 })
934 guard
935 not Types.isTuple(ty)
936 then e;
937
938 case DAE.MATCHEXPRESSION(inputs={e}, et=ty, localDecls={}, cases={
939 DAE.CASE(patterns={DAE.PAT_CONSTANT(exp=DAE.BCONST(b1))},localDecls={},body={},result=SOME(e1)),
940 DAE.CASE(patterns={DAE.PAT_CONSTANT(exp=DAE.BCONST(b2))},localDecls={},body={},result=SOME(e2))
941 })
942 guard
943 not boolEq(b1,b2) and
944 not Types.isTuple(ty)
945 algorithm
946 ✗ e1_1 := if b1 then e1 else e2;
947 ✗ e2_1 := if b1 then e2 else e1;
948 ✗ e := DAE.IFEXP(e, e1_1, e2_1);
949 then e;
950
951 case DAE.MATCHEXPRESSION(matchType=DAE.MATCH(), et=ty, inputs={e}, localDecls={}, cases={
952 DAE.CASE(patterns={DAE.PAT_CONSTANT(exp=DAE.BCONST(b1))},localDecls={},body={},result=SOME(e1)),
953 DAE.CASE(patterns={DAE.PAT_WILD()},localDecls={},body={},result=SOME(e2))
954 })
955 guard
956 not Types.isTuple(ty)
957 algorithm
958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 e1_1 := if b1 then e1 else e2;
959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 e2_1 := if b1 then e2 else e1;
960 1 e := DAE.IFEXP(e, e1_1, e2_1);
961 then e;
962
963 else exp;
964 end match;
965 end simplifyMatch;
966
967 protected function simplifyCast "help function to simplify1"
968 input DAE.Exp origExp;
969 input DAE.Exp exp;
970 input Type tp;
971 output DAE.Exp outExp;
972 algorithm
973 outExp := match(exp, tp)
974 local
975 Real r;
976 Integer i,n;
977 Boolean b;
978 list<DAE.Exp> exps,exps_1;
979 Type tp_1,tp1,tp2,t1,t2;
980 DAE.Exp e1,e2,cond,e1_1,e2_1,e;
981 list<list<DAE.Exp>> mexps,mexps_1;
982 Option<DAE.Exp> eo;
983 DAE.Dimensions dims;
984 Absyn.Path p1,p2,p3;
985 list<String> fieldNames;
986
987 // Real -> Real
988 8224 case(DAE.RCONST(r), DAE.T_REAL()) then DAE.RCONST(r);
989
990 // Int -> Real
991 case(DAE.ICONST(i), DAE.T_REAL())
992 algorithm
993 252777 r := intReal(i);
994 252777 then
995 DAE.RCONST(r);
996
997 // cast of unary
998 case(DAE.UNARY(DAE.UMINUS_ARR(_),e), _)
999 algorithm
1000 ✗ e := addCast(e,tp);
1001 ✗ then
1002 DAE.UNARY(DAE.UMINUS_ARR(tp),e);
1003 // cast of unary
1004 case(DAE.UNARY(DAE.UMINUS(_),e), _)
1005 algorithm
1006 ✗ e := addCast(e,tp);
1007 ✗ then
1008 DAE.UNARY(DAE.UMINUS(tp),e);
1009
1010 // cast of array
1011 case(DAE.ARRAY(_,b,exps), _)
1012 algorithm
1013 1419 tp_1 := Expression.unliftArray(tp);
1014 1419 exps_1 := List.map1(exps, addCast, tp_1);
1015
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1418 times.
1420 then
1016 DAE.ARRAY(tp,b,exps_1);
1017
1018 // cast of array
1019 case (DAE.RANGE(ty=DAE.T_ARRAY(ty = DAE.T_INTEGER()),start=e1,step=eo,stop=e2), DAE.T_ARRAY(ty=tp2 as DAE.T_REAL()))
1020 algorithm
1021 6 e1 := addCast(e1,tp2);
1022 6 e2 := addCast(e2,tp2);
1023 6 eo := Util.applyOption1(eo, addCast, tp2);
1024 6 then
1025 DAE.RANGE(tp,e1,eo,e2);
1026
1027 // simplify cast in an if expression
1028 case (DAE.IFEXP(cond,e1,e2), _)
1029 algorithm
1030 509 e1_1 := DAE.CAST(tp,e1);
1031 509 e2_1 := DAE.CAST(tp,e2);
1032 509 then DAE.IFEXP(cond,e1_1,e2_1);
1033
1034 // simplify cast of matrix expressions
1035 case (DAE.MATRIX(_,n,mexps), _)
1036 algorithm
1037 155 tp1 := Expression.unliftArray(tp);
1038 155 tp2 := Expression.unliftArray(tp1);
1039 155 mexps_1 := List.map1List(mexps, addCast, tp2);
1040 155 then DAE.MATRIX(tp,n,mexps_1);
1041
1042 // simplify record constructor from one to another
1043 case (DAE.CALL(p1,exps,DAE.CALL_ATTR(ty=DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(p2)))), DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(p3)))
1044 guard AbsynUtil.pathEqual(p1,p2) // It is a record constructor since it has the same path called as its output type
1045 4 then DAE.CALL(p3,exps,DAE.CALL_ATTR(tp,false,false,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS));
1046
1047 case (DAE.RECORD(_,exps,fieldNames,_), DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(p3)))
1048 3897 then DAE.RECORD(p3,exps,fieldNames,tp);
1049
1050 // fill(e, ...) can be simplified
1051 case(DAE.CALL(path=Absyn.IDENT("fill"),expLst=e::exps), _)
1052 algorithm
1053 10 tp_1 := List.fold(exps,Expression.unliftArrayIgnoreFirst,tp);
1054 10 e := DAE.CAST(tp_1,e);
1055 10 e := Expression.makePureBuiltinCall("fill",e::exps,tp);
1056 then e;
1057
1058 // cat(e, ...) can be simplified
1059 case(DAE.CALL(path=Absyn.IDENT("cat"),expLst=(e as DAE.ICONST(n))::exps), DAE.T_ARRAY(dims=dims))
1060 guard
1061 Expression.dimensionUnknown(listGet(dims,n))
1062 algorithm
1063 1 exps := List.map1(exps,addCast,tp);
1064 1 then Expression.makePureBuiltinCall("cat",e::exps,tp);
1065
1066 // expression already has a specified cast type.
1067 case(e, _)
1068 algorithm
1069 355415 t1 := Expression.arrayEltType(tp);
1070 355415 t2 := Expression.arrayEltType(Expression.typeof(e));
1071
2/2
✓ Branch 1 taken 355414 times.
✓ Branch 2 taken 1 time.
355415 then if valueEq(t1, t2) then e else origExp;
1072 else origExp;
1073 end match;
1074 end simplifyCast;
1075
1076 protected function addCast
1077 "Adds a cast of a Type to an expression."
1078 input DAE.Exp inExp;
1079 input Type inType;
1080 output DAE.Exp outExp;
1081 annotation(__OpenModelica_EarlyInline = true);
1082 algorithm
1083 4893 outExp:=DAE.CAST(inType,inExp);
1084 end addCast;
1085
1086 protected function reductionDefaultValue
1087 input String name;
1088 input DAE.Type ty;
1089 output Values.Value defaultValue;
1090 algorithm
1091 defaultValue := match (name, ty)
1092 case ("min", DAE.T_BOOL()) then Values.BOOL(true);
1093 ✗ case ("min", DAE.T_INTEGER()) then Values.INTEGER(System.intMaxLit());
1094 ✗ case ("min", DAE.T_REAL()) then Values.REAL(System.realMaxLit());
1095 case ("min", DAE.T_ENUMERATION())
1096 ✗ then Values.ENUM_LITERAL(AbsynUtil.suffixPath(ty.path, List.last(ty.names)), listLength(ty.names));
1097
1098 case ("max", DAE.T_BOOL()) then Values.BOOL(false);
1099 ✗ case ("max", DAE.T_INTEGER()) then Values.INTEGER(intNeg(System.intMaxLit()));
1100 ✗ case ("max", DAE.T_REAL()) then Values.REAL(realNeg(System.realMaxLit()));
1101 case ("max", DAE.T_ENUMERATION())
1102 ✗ then Values.ENUM_LITERAL(AbsynUtil.suffixPath(ty.path, List.last(ty.names)), 1);
1103
1104 case ("product", DAE.T_INTEGER()) then Values.INTEGER(1);
1105 case ("product", DAE.T_REAL()) then Values.REAL(1.0);
1106
1107 case ("sum", DAE.T_INTEGER()) then Values.INTEGER(0);
1108 case ("sum", DAE.T_REAL()) then Values.REAL(0.0);
1109 end match;
1110 end reductionDefaultValue;
1111
1112
1113 protected function reductionExpression
1114 input String name;
1115 input DAE.Type ty;
1116 input String foldName;
1117 input String resultName;
1118 output DAE.Exp foldExp;
1119 protected
1120 DAE.Exp foldNameExp, resultNameExp;
1121 algorithm
1122 ✗ foldNameExp := Expression.makeCrefExp(ComponentReferenceBasics.makeCrefIdent(foldName,ty,{}), ty);
1123 ✗ resultNameExp := Expression.makeCrefExp(ComponentReferenceBasics.makeCrefIdent(resultName,ty,{}), ty);
1124
1125 foldExp := match name
1126 ✗ case "min" then Expression.makeBuiltinCall("min",{foldNameExp, resultNameExp}, ty, false);
1127 ✗ case "max" then Expression.makeBuiltinCall("max",{foldNameExp, resultNameExp}, ty, false);
1128 ✗ case "product" then DAE.BINARY(foldNameExp, DAE.MUL(ty), resultNameExp);
1129 ✗ case "sum" then DAE.BINARY(foldNameExp, DAE.ADD(ty), resultNameExp);
1130 end match;
1131 end reductionExpression;
1132
1133
1134 public function elabBuiltinFill2
1135 "Helper that builds a filled array from a value list. Moved here from Static
1136 (and Static.elabBuiltinFill now calls this) so ExpressionSimplify does not
1137 depend on the instantiation cluster. The env/prefix that the old Static version
1138 carried were only used to decorate an internal-error message, so they are
1139 dropped here."
1140 input FCore.Cache inCache;
1141 input DAE.Exp inExp;
1142 input DAE.Type inType;
1143 input list<Values.Value> inValuesValueLst;
1144 input DAE.Const constVar;
1145 input list<Absyn.Exp> inDims;
1146 input SourceInfo inInfo;
1147 output FCore.Cache outCache;
1148 output DAE.Exp outExp;
1149 output DAE.Properties outProperties;
1150 algorithm
1151 (outCache,outExp,outProperties) := matchcontinue (inCache, inExp, inType, inValuesValueLst, constVar)
1152 local
1153 list<DAE.Exp> arraylist;
1154 DAE.Type at;
1155 Boolean is_scalar;
1156 DAE.Exp s,exp;
1157 DAE.Type sty,ty,sty2;
1158 Integer v;
1159 list<Values.Value> rest;
1160 FCore.Cache cache;
1161 DAE.Const c1;
1162 String str;
1163
1164 case (cache, s, sty, {Values.INTEGER(integer = v)}, c1)
1165 algorithm
1166
1/2
✓ Branch 0 taken 4600 times.
✗ Branch 1 not taken.
4600 true := intLt(v, 0); // fill with 0 then!
1167 v := 0;
1168 ✗ arraylist := List.fill(s, v);
1169 ✗ sty2 := DAE.T_ARRAY(sty, {DAE.DIM_INTEGER(v)});
1170 ✗ at := Types.simplifyType(sty2);
1171 ✗ is_scalar := not Types.isArray(sty);
1172 ✗ then
1173 (cache,DAE.ARRAY(at,is_scalar,arraylist),DAE.PROP(sty2,c1));
1174
1175 case (cache, s, sty, {Values.INTEGER(integer = v)}, c1)
1176 algorithm
1177 4600 arraylist := List.fill(s, v);
1178 9200 sty2 := DAE.T_ARRAY(sty, {DAE.DIM_INTEGER(v)});
1179 4600 at := Types.simplifyType(sty2);
1180 4600 is_scalar := not Types.isArray(sty);
1181
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4586 times.
4614 then
1182 (cache,DAE.ARRAY(at,is_scalar,arraylist),DAE.PROP(sty2,c1));
1183
1184 case (cache, s, sty, (Values.INTEGER(integer = v) :: rest), c1)
1185 algorithm
1186
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 116 times.
116 (cache,exp,DAE.PROP(ty,_)) := elabBuiltinFill2(cache, s, sty, rest, c1, inDims, inInfo);
1187 116 arraylist := List.fill(exp, v);
1188 232 sty2 := DAE.T_ARRAY(ty, {DAE.DIM_INTEGER(v)});
1189 116 at := Types.simplifyType(sty2);
1190 116 then
1191 (cache,DAE.ARRAY(at,false,arraylist),DAE.PROP(sty2,c1));
1192
1193 else
1194 algorithm
1195 ✗ str := "ExpressionSimplify.elabBuiltinFill2 failed for expression: fill(" + Dump.printExpLstStr(inDims) + ")";
1196 ✗ Error.addSourceMessage(Error.INTERNAL_ERROR, {str}, inInfo);
1197 ✗ then
1198 fail();
1199 end matchcontinue;
1200 end elabBuiltinFill2;
1201
1202 protected function simplifyBuiltinCalls "simplifies some builtin calls (with no constant expressions)"
1203 input DAE.Exp exp;
1204 output DAE.Exp outExp;
1205 algorithm
1206 outExp := matchcontinue exp
1207 local
1208 list<list<DAE.Exp>> mexpl;
1209 list<DAE.Exp> es,expl;
1210 DAE.Exp e,len_exp,just_exp,e1,e2,e3,e4;
1211 DAE.Type tp,tp1,tp2;
1212 DAE.Operator op;
1213 list<DAE.Exp> v1, v2;
1214 Boolean scalar,sc;
1215 list<Values.Value> valueLst;
1216 Integer i,i1,i2,dim;
1217 Real r1;
1218 array<array<DAE.Exp>> marr;
1219 String name, s1, s2;
1220 list<Integer> dims;
1221
1222 // If the argument to min/max is an array, try to flatten it.
1223 case DAE.CALL(path=Absyn.IDENT(name),expLst={e as DAE.ARRAY()},
1224 attr=DAE.CALL_ATTR(ty=tp))
1225 guard name=="max" or name=="min"
1226 algorithm
1227 599 expl := Expression.flattenArrayExpToList(e);
1228 599 e1 := Expression.makeScalarArray(expl, tp);
1229
2/2
✓ Branch 1 taken 540 times.
✓ Branch 2 taken 59 times.
599 false := ExpressionBasics.expEqual(e, e1);
1230 59 then
1231 Expression.makePureBuiltinCall(name, {e1}, tp);
1232
1233 // min/max function on arrays of only 1 element
1234 case DAE.CALL(path=Absyn.IDENT(name),expLst={DAE.ARRAY(array=expl as {e})})
1235 guard name=="max" or name=="min"
1236 algorithm
1237
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 96 times.
96 if Expression.isArrayType(Expression.typeof(e)) then
1238 ✗ exp.expLst := expl;
1239 e := exp;
1240 end if;
1241 then e;
1242 case DAE.CALL(path=Absyn.IDENT("max"),expLst={DAE.ARRAY(array={e})}) then e;
1243
1244 case DAE.CALL(path=Absyn.IDENT("max"),expLst={DAE.ARRAY(array=es)},attr=DAE.CALL_ATTR(ty=tp))
1245 algorithm
1246 307 i1 := listLength(es);
1247 307 es := List.union(es,{});
1248 307 i2 := listLength(es);
1249
2/2
✓ Branch 0 taken 265 times.
✓ Branch 1 taken 42 times.
307 if i1 == i2
1250 then
1251
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 265 times.
✓ Branch 3 taken 258 times.
✓ Branch 4 taken 7 times.
265 SOME(e) := List.fold(es, maxElement, NONE());
1252 7 es := List.select(es, removeMinMaxFoldableValues);
1253 es := e::es;
1254 7 i2 := listLength(es);
1255
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 time.
7 true := i2 < i1;
1256 1 e := Expression.makeScalarArray(es,tp);
1257 else
1258 42 e := Expression.makeScalarArray(es,tp);
1259 end if;
1260 43 then
1261 Expression.makePureBuiltinCall("max",{e},tp);
1262
1263 case DAE.CALL(path=Absyn.IDENT("min"),expLst={DAE.ARRAY(array=es)},attr=DAE.CALL_ATTR(ty=tp))
1264 algorithm
1265 137 i1 := listLength(es);
1266 137 es := List.union(es,{});
1267 137 i2 := listLength(es);
1268
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 1 time.
137 if i1 == i2
1269 then
1270
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 136 times.
✓ Branch 3 taken 133 times.
✓ Branch 4 taken 3 times.
136 SOME(e) := List.fold(es, minElement, NONE());
1271 3 es := List.select(es, removeMinMaxFoldableValues);
1272 es := e::es;
1273 3 i2 := listLength(es);
1274
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 true := i2 < i1;
1275 1 e := Expression.makeScalarArray(es,tp);
1276 else
1277 1 e := Expression.makeScalarArray(es,tp);
1278 end if;
1279 2 then
1280 Expression.makePureBuiltinCall("min",{e},tp);
1281
1282 case DAE.CALL(path=Absyn.IDENT("min"),attr=DAE.CALL_ATTR(ty=tp),expLst={DAE.ARRAY(array={e1,e2})})
1283 algorithm
1284 10 e := Expression.makePureBuiltinCall("min",{e1,e2},tp);
1285 then e;
1286 case DAE.CALL(path=Absyn.IDENT("max"),attr=DAE.CALL_ATTR(ty=tp),expLst={DAE.ARRAY(array={e1,e2})})
1287 algorithm
1288 30 e := Expression.makePureBuiltinCall("max",{e1,e2},tp);
1289 then e;
1290 case DAE.CALL(path=Absyn.IDENT("min"),attr=DAE.CALL_ATTR(ty=DAE.T_BOOL()),expLst={e1,e2})
1291 algorithm
1292 10 e := DAE.LBINARY(e1,DAE.AND(DAE.T_BOOL_DEFAULT),e2);
1293 then e;
1294 case DAE.CALL(path=Absyn.IDENT("max"),attr=DAE.CALL_ATTR(ty=DAE.T_BOOL()),expLst={e1,e2})
1295 algorithm
1296 11 e := DAE.LBINARY(e1,DAE.OR(DAE.T_BOOL_DEFAULT),e2);
1297 then e;
1298 case DAE.CALL(path=Absyn.IDENT("min"),attr=DAE.CALL_ATTR(ty=DAE.T_BOOL()),expLst={DAE.ARRAY(array=expl)})
1299 algorithm
1300 5 e := Expression.makeLBinary(expl,DAE.AND(DAE.T_BOOL_DEFAULT));
1301 then e;
1302 case DAE.CALL(path=Absyn.IDENT("max"),attr=DAE.CALL_ATTR(ty=DAE.T_BOOL()),expLst={DAE.ARRAY(array=expl)})
1303 algorithm
1304 5 e := Expression.makeLBinary(expl,DAE.OR(DAE.T_BOOL_DEFAULT));
1305 then e;
1306
1307 case DAE.CALL(path=Absyn.IDENT(name), expLst = {DAE.ARRAY(array = expl as _ :: _ :: _)},
1308 attr = DAE.CALL_ATTR(ty = tp))
1309 algorithm
1310
2/2
✓ Branch 1 taken 877 times.
✓ Branch 2 taken 2 times.
879 true := Config.scalarizeMinMax();
1311
5/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 9 not taken.
2 true := stringEq(name, "max") or stringEq(name, "min");
1312
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 e1 :: e2 :: expl := listReverse(expl);
1313 2 e1 := Expression.makePureBuiltinCall(name, {e2, e1}, tp);
1314 2 e1 := List.fold2(expl, makeNestedReduction, name, tp, e1);
1315 then
1316 e1;
1317
1318 // cross
1319 case e as DAE.CALL(path = Absyn.IDENT("cross"), expLst = expl)
1320 algorithm
1321
7/10
✗ Branch 0 not taken.
✓ Branch 1 taken 8127 times.
✓ Branch 2 taken 278 times.
✓ Branch 3 taken 7849 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7849 times.
✓ Branch 6 taken 5262 times.
✓ Branch 7 taken 2587 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2587 times.
8127 {DAE.ARRAY(array = v1),DAE.ARRAY(array = v2)} := expl;
1322 2587 expl := simplifyCross(v1, v2);
1323 2587 tp := Expression.typeof(e);
1324 // Since there is a bug somewhere in simplify that gives wrong types for arrays we take the type from cross.
1325 2587 scalar := not Expression.isArrayType(Expression.unliftArray(tp));
1326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2587 times.
2587 then
1327 DAE.ARRAY(tp, scalar,expl);
1328
1329 case e as DAE.CALL(path = Absyn.IDENT("skew"), expLst = {DAE.ARRAY(array = v1)})
1330 algorithm
1331 36 mexpl := simplifySkew(v1);
1332 36 tp := Expression.typeof(e);
1333 36 then DAE.MATRIX(tp, 3, mexpl);
1334
1335 // Simplify built-in function fill. MathCore depends on this being done here, do not remove!
1336 case DAE.CALL(path = Absyn.IDENT("fill"), expLst = e::expl)
1337 algorithm
1338 153 valueLst := List.map(expl, ValuesUtil.expValue);
1339 50 (_,outExp,_) := elabBuiltinFill2(FCore.noCache(), e, Expression.typeof(e), valueLst, DAE.C_CONST(), {}, Absyn.dummyInfo);
1340 50 then
1341 outExp;
1342
1343 case DAE.CALL(path = Absyn.IDENT("String"), expLst = {e,len_exp,just_exp})
1344 3788 then simplifyBuiltinStringFormat(e,len_exp,just_exp);
1345
1346 case DAE.CALL(path = Absyn.IDENT("stringAppendList"), expLst = {DAE.LIST(expl)})
1347 310 then simplifyStringAppendList(expl,{},false);
1348
1349 // sqrt(e ^ r) => e ^ (0.5 * r)
1350 case DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={DAE.BINARY(e1,DAE.POW(ty = DAE.T_REAL()),e2)})
1351 algorithm
1352 227 e := DAE.BINARY(e1,DAE.POW(DAE.T_REAL_DEFAULT),DAE.BINARY(DAE.RCONST(0.5),DAE.MUL(DAE.T_REAL_DEFAULT),e2));
1353 227 then Expression.makePureBuiltinCall("abs",{e},DAE.T_REAL_DEFAULT);
1354
1355 // sqrt(sqrt(e)) => e ^ (0.25)
1356 case DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={e1})})
1357 8 then DAE.BINARY(e1,DAE.POW(DAE.T_REAL_DEFAULT),DAE.RCONST(0.25));
1358
1359 // sqrt(c*e) => c1*sqrt(e)
1360 case DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={DAE.BINARY(e1 as DAE.RCONST(r1),DAE.MUL(tp),e2)})
1361 algorithm
1362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 true := r1 >= 0.0;
1363 139 e := Expression.makePureBuiltinCall("sqrt",{e1},DAE.T_REAL_DEFAULT);
1364 139 e3 := Expression.makePureBuiltinCall("sqrt",{e2},DAE.T_REAL_DEFAULT);
1365 139 then DAE.BINARY(e,DAE.MUL(tp),e3);
1366
1367 // exp(-(...*log(x)*...))
1368 case DAE.CALL(path=Absyn.IDENT("exp"),expLst={DAE.UNARY(DAE.UMINUS(),e1)})
1369 algorithm
1370 1978 expl := Expression.expandFactors(e1);
1371
1/4
✓ Branch 1 taken 1978 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1978 ({e2},es) := List.split1OnTrue(expl, Expression.isFunCall, "log");
1372 ✗ DAE.CALL(expLst={e}):= e2;
1373 ✗ e3 := Expression.makeProductLst(es);
1374 ✗ then Expression.expPow(e, Expression.negate(e3));
1375
1376 // exp(...*log(x)*...)
1377 case DAE.CALL(path=Absyn.IDENT("exp"),expLst={e1})
1378 algorithm
1379 27796 expl := Expression.expandFactors(e1);
1380
3/4
✓ Branch 1 taken 27791 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
27796 ({e2},es) := List.split1OnTrue(expl, Expression.isFunCall, "log");
1381
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
5 DAE.CALL(expLst={e}):= e2;
1382 5 e3 := Expression.makeProductLst(es);
1383 5 then Expression.expPow(e,e3);
1384
1385 // exp(e)^r = exp(e*r)
1386 case DAE.BINARY(DAE.CALL(path=Absyn.IDENT("exp"),expLst={e}),DAE.POW(ty = DAE.T_REAL()),e2)
1387 algorithm
1388 ✗ e3 := Expression.expMul(e,e2);
1389 ✗ then Expression.makePureBuiltinCall("exp",{e3},DAE.T_REAL_DEFAULT);
1390
1391 // log(x^n) = n*log(x)
1392 case DAE.CALL(path=Absyn.IDENT("log"),expLst={DAE.BINARY(e1,DAE.POW(ty = DAE.T_REAL()), DAE.RCONST(r1))})
1393 algorithm
1394
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 1.0 := realMod(r1,2.0);
1395 ✗ e3 := Expression.makePureBuiltinCall("log",{e1},DAE.T_REAL_DEFAULT);
1396 ✗ then Expression.expMul(DAE.RCONST(r1), e3);
1397 // log(1/x) = -log(x)
1398 case DAE.CALL(path=Absyn.IDENT("log"),expLst={DAE.BINARY(DAE.RCONST(1.0),DAE.DIV(ty = DAE.T_REAL()), e2)})
1399 algorithm
1400 1 e3 := Expression.makePureBuiltinCall("log",{e2},DAE.T_REAL_DEFAULT);
1401 1 then DAE.UNARY(DAE.UMINUS(DAE.T_REAL_DEFAULT),e3);
1402 // log(sqrt(x)) = 0.5*log(x)
1403 case DAE.CALL(path=Absyn.IDENT("log"),expLst={DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={e1})})
1404 algorithm
1405 2 e3 := Expression.makePureBuiltinCall("log",{e1},DAE.T_REAL_DEFAULT);
1406 2 then DAE.BINARY(DAE.RCONST(0.5),DAE.MUL(DAE.T_REAL_DEFAULT),e3);
1407
1408 // smooth of constant expression
1409 case DAE.CALL(path=Absyn.IDENT("smooth"),expLst={_,e1})
1410 guard Expression.isConst(e1)
1411 then e1;
1412
1413 // df_der(const) --> 0
1414 case DAE.CALL(path=Absyn.IDENT("$_DF$DER"),expLst={e1})
1415 guard Expression.isConst(e1)
1416 ✗ then Expression.makeConstZeroE(e1);
1417
1418 // We only match delay with 3 arguments in most places...
1419 case e as DAE.CALL(path=Absyn.IDENT("delay"),expLst={e1,e2})
1420 algorithm
1421 3 e.expLst := {e1,e2,e2};
1422 then e;
1423
1424 // delay of constant expression
1425 case DAE.CALL(path=Absyn.IDENT("delay"),expLst={e1,_,_})
1426 guard Expression.isConst(e1)
1427 then e1;
1428
1429 // delay of constant subexpression
1430 case DAE.CALL(path=Absyn.IDENT("delay"),expLst={DAE.BINARY(e1,op,e2),e3,e4},attr=DAE.CALL_ATTR(ty=tp))
1431 algorithm
1432
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 true := Expression.isConst(e1);
1433 2 e := Expression.makeImpureBuiltinCall("delay",{e2,e3,e4},tp);
1434 2 then DAE.BINARY(e1,op,e);
1435
1436 // delay of constant subexpression
1437 case DAE.CALL(path=Absyn.IDENT("delay"),expLst={DAE.BINARY(e1,op,e2),e3,e4},attr=DAE.CALL_ATTR(ty=tp))
1438 algorithm
1439 ✗ true := Expression.isConst(e2);
1440 ✗ e := Expression.makeImpureBuiltinCall("delay",{e1,e3,e4},tp);
1441 ✗ then DAE.BINARY(e,op,e2);
1442
1443 // delay(-x) = -delay(x)
1444 case DAE.CALL(path=Absyn.IDENT("delay"),expLst={DAE.UNARY(op,e),e3,e4},attr=DAE.CALL_ATTR(ty=tp))
1445 algorithm
1446 ✗ e := Expression.makeImpureBuiltinCall("delay",{e,e3,e4},tp);
1447 ✗ then DAE.UNARY(op,e);
1448
1449 // The sum of an empty array is simply the sum of its elements
1450 case DAE.CALL(path=Absyn.IDENT("sum"),expLst={DAE.ARRAY(array={})}, attr=DAE.CALL_ATTR(ty=tp1))
1451 16 then Expression.makeConstZero(tp1);
1452
1453 // To calculate sums, first try matrix concatenation
1454 case DAE.CALL(path=Absyn.IDENT("sum"),expLst={DAE.MATRIX(ty=tp1,matrix=mexpl)},attr=DAE.CALL_ATTR(ty=tp2))
1455 algorithm
1456 ✗ es := List.flatten(mexpl);
1457 ✗ tp1 := Expression.unliftArray(Expression.unliftArray(tp1));
1458 ✗ sc := not Expression.isArrayType(tp1);
1459 ✗ tp1 := if sc then Expression.unliftArray(tp1) else tp1;
1460 ✗ tp1 := if sc then Expression.liftArrayLeft(tp1,DAE.DIM_UNKNOWN()) else tp1;
1461 ✗ dim := listLength(es);
1462 ✗ tp1 := Expression.liftArrayLeft(tp1,DAE.DIM_INTEGER(dim));
1463 ✗ e := DAE.ARRAY(tp1,sc,es);
1464 ✗ e := Expression.makePureBuiltinCall("sum",{e},tp2);
1465 // print("Matrix sum: " + boolString(sc) + TypesDump.unparseType(tp1) + " " + ExpressionBasics.printExpStr(e) + "\n");
1466 then e;
1467 // Then try array concatenation
1468 case DAE.CALL(path=Absyn.IDENT("sum"),expLst={DAE.ARRAY(array=es,ty=tp1,scalar=false)},attr=DAE.CALL_ATTR(ty=tp2))
1469 algorithm
1470 ✗ es := simplifyCat(1,es);
1471 ✗ tp1 := Expression.unliftArray(tp1);
1472 ✗ sc := not Expression.isArrayType(tp1);
1473 ✗ tp1 := if sc then Expression.unliftArray(tp1) else tp1;
1474 ✗ tp1 := if sc then Expression.liftArrayLeft(tp1,DAE.DIM_UNKNOWN()) else tp1;
1475 ✗ dim := listLength(es);
1476 ✗ tp1 := Expression.liftArrayLeft(tp1,DAE.DIM_INTEGER(dim));
1477 ✗ e := DAE.ARRAY(tp1,sc,es);
1478 ✗ e := Expression.makePureBuiltinCall("sum",{e},tp2);
1479 // print("Array sum: " + boolString(sc) + TypesDump.unparseType(tp1) + " " + ExpressionBasics.printExpStr(e) + "\n");
1480 then e;
1481 // Try to reduce the number of dimensions
1482 case DAE.CALL(path=Absyn.IDENT("sum"),expLst={DAE.ARRAY(array={e},scalar=false)},attr=DAE.CALL_ATTR(ty=tp2))
1483 algorithm
1484 ✗ e := Expression.makePureBuiltinCall("sum",{e},tp2);
1485 then e;
1486 // The sum of a single array is simply the sum of its elements
1487 case DAE.CALL(path=Absyn.IDENT("sum"),expLst={DAE.ARRAY(array=es,scalar=true)})
1488 algorithm
1489 2165 e := Expression.makeSum(es);
1490 then e;
1491
1492 case DAE.CALL(path=Absyn.IDENT("cat"),expLst=_::{e1}) then e1;
1493
1494 case DAE.CALL(path=Absyn.IDENT("cat"),expLst=DAE.ICONST(i)::es,attr=DAE.CALL_ATTR(ty=tp))
1495 algorithm
1496 2007 es := simplifyCat(i,es);
1497 3366 e := Expression.makePureBuiltinCall("cat",DAE.ICONST(i)::es,tp);
1498 then e;
1499
1500 case DAE.CALL(path=Absyn.IDENT("cat"),expLst=DAE.ICONST(i)::es,attr=DAE.CALL_ATTR())
1501 algorithm
1502 324 (es,dims) := ExpressionBasics.evalCat(i, es, getArrayContents=Expression.getArrayOrMatrixContents, toString=ExpressionBasics.printExpStr);
1503
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
3 e := Expression.listToArray(es, list(DAE.DIM_INTEGER(d) for d in dims));
1504 then e;
1505
1506 // promote n-dim to n-dim
1507 case DAE.CALL(path=Absyn.IDENT("promote"),expLst=e1::DAE.ICONST(i)::{})
1508 guard Types.numberOfDimensions(Expression.typeof(e1))==i
1509 then e1;
1510
1511 // promote 1-dim to 2-dim
1512 case DAE.CALL(path=Absyn.IDENT("promote"),expLst=(DAE.ARRAY(tp1 as DAE.T_ARRAY(dims={_}),sc,es))::DAE.ICONST(2)::{})
1513 algorithm
1514 359 tp := Types.liftArray(Types.unliftArray(tp1), DAE.DIM_INTEGER(1));
1515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 359 times.
359 es := List.map2(List.map(es,List.create), Expression.makeArray, tp, sc);
1516 359 i := listLength(es);
1517 359 tp := Expression.liftArrayLeft(tp, DAE.DIM_INTEGER(i));
1518 359 then
1519 DAE.ARRAY(tp,false,es);
1520
1521 // scalar to n-dim
1522 case DAE.CALL(path=Absyn.IDENT("promote"),expLst=e1::DAE.ICONST(i)::{})
1523 guard not Types.isArray(Expression.typeof(e1))
1524 algorithm
1525 ✗ tp := Expression.typeof(e1);
1526 ✗ for j in 1:i loop
1527 ✗ tp1 := Types.liftArray(tp, DAE.DIM_INTEGER(1));
1528 ✗ e1 := Expression.makeArray({e1}, tp1, not Types.isArray(tp));
1529 tp := tp1;
1530 end for;
1531 then e1;
1532
1533 case DAE.CALL(path=Absyn.IDENT("transpose"),expLst=e::{},attr=DAE.CALL_ATTR())
1534 algorithm
1535
2/2
✓ Branch 1 taken 124 times.
✓ Branch 2 taken 260 times.
384 (e, true) := Expression.transposeArray(e);
1536 then
1537 e;
1538
1539 case DAE.CALL(path=Absyn.IDENT("symmetric"),expLst=e::{},attr=DAE.CALL_ATTR(ty=tp))
1540 algorithm
1541 1 mexpl := Expression.get2dArrayOrMatrixContent(e);
1542 e := match mexpl
1543 case {{}} then e;
1544 case {{_}} then e;
1545 case _ algorithm
1546 1 marr := listArray(List.map(mexpl,listArray));
1547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 true := arrayLength(marr) == arrayLength(arrayGet(marr,1));
1548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 true := arrayLength(marr) > 1;
1549 1 simplifySymmetric(marr, arrayLength(marr)-1, arrayLength(marr));
1550 1 mexpl := List.mapArray(marr, arrayList);
1551 1 tp1 := Expression.unliftArray(tp);
1552
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
2 es := List.map2(mexpl, Expression.makeArray, tp1, not Types.isArray(tp1));
1553 1 e := Expression.makeArray(es, tp, false);
1554 then e;
1555 end match;
1556 then e;
1557
1558 case DAE.CALL(path=Absyn.IDENT("scalar"),expLst=e::{},attr=DAE.CALL_ATTR(ty=tp))
1559 algorithm
1560 1 e := simplifyScalar(e,tp);
1561 then e;
1562
1563 case DAE.CALL(path=Absyn.IDENT("vector"),expLst=es as (e::_),attr=DAE.CALL_ATTR(ty=DAE.T_ARRAY(tp,_)))
1564 algorithm
1565
1/2
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 false := Types.isArray(Expression.typeof(e));
1566 ✗ i := listLength(es);
1567 ✗ tp := DAE.T_ARRAY(tp,{DAE.DIM_INTEGER(i)});
1568 ✗ then DAE.ARRAY(tp,true,es);
1569
1570 case DAE.CALL(path=Absyn.IDENT("vector"),expLst=(e as DAE.ARRAY(scalar=true))::{},attr=DAE.CALL_ATTR())
1571 then e;
1572
1573 case DAE.CALL(path=Absyn.IDENT("vector"),expLst=DAE.MATRIX(matrix=mexpl)::{},attr=DAE.CALL_ATTR(ty=tp))
1574 algorithm
1575 ✗ es := List.flatten(mexpl);
1576 ✗ es := List.map1(es, Expression.makeVectorCall, tp);
1577 ✗ e := Expression.makePureBuiltinCall("cat", DAE.ICONST(1)::es, tp);
1578 then e;
1579
1580 case DAE.CALL(path=Absyn.IDENT("vector"),expLst=DAE.ARRAY(array=es)::{},attr=DAE.CALL_ATTR(ty=tp))
1581 algorithm
1582 ✗ es := List.map1(es, Expression.makeVectorCall, tp);
1583 ✗ e := Expression.makePureBuiltinCall("cat", DAE.ICONST(1)::es, tp);
1584 then e;
1585
1586 /* Current design uses a special DAE.Expression */
1587
1588 case DAE.CALL(path=Absyn.IDENT("inferredClock"),expLst={})
1589 then DAE.CLKCONST(DAE.INFERRED_CLOCK());
1590
1591 case DAE.CALL(path=Absyn.IDENT("realClock"),expLst={e1})
1592 ✗ then DAE.CLKCONST(DAE.REAL_CLOCK(e1));
1593
1594 case DAE.CALL(path=Absyn.IDENT("booleanClock"),expLst={e1,e2})
1595 ✗ then DAE.CLKCONST(DAE.EVENT_CLOCK(e1,e2));
1596
1597 case DAE.CALL(path=Absyn.IDENT("rationalClock"),expLst={e1,e2})
1598 ✗ then DAE.CLKCONST(DAE.RATIONAL_CLOCK(e1, e2));
1599
1600 case DAE.CALL(path=Absyn.IDENT("solverClock"),expLst={e1,e2})
1601 ✗ then DAE.CLKCONST(DAE.SOLVER_CLOCK(e1, e2));
1602
1603 case DAE.CALL(path=Absyn.IDENT("OpenModelica_uriToFilename"),expLst={DAE.SCONST(s1)})
1604 algorithm
1605 ✗ s2 := OpenModelica.Scripting.uriToFilename(s1);
1606 ✗ if Flags.getConfigBool(Flags.BUILDING_FMU) then
1607 ✗ e := Expression.makeImpureBuiltinCall("OpenModelica_fmuLoadResource",{DAE.SCONST(s2)},DAE.T_STRING_DEFAULT);
1608 else
1609 ✗ e := DAE.SCONST(s2);
1610 end if;
1611 then e;
1612
1613 end matchcontinue;
1614 end simplifyBuiltinCalls;
1615
1616 protected function simplifyScalar "Handle the scalar() operator"
1617 input DAE.Exp inExp;
1618 input DAE.Type tp;
1619 output DAE.Exp exp;
1620 algorithm
1621 exp := match inExp
1622 case DAE.ARRAY(array={exp})
1623 ✗ then Expression.makePureBuiltinCall("scalar", {exp}, tp);
1624 case DAE.MATRIX(matrix={{exp}})
1625 ✗ then Expression.makePureBuiltinCall("scalar", {exp}, tp);
1626 case DAE.SIZE(exp=exp,sz=NONE())
1627 algorithm
1628
2/4
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
1 (_,{_}) := TypesDump.flattenArrayType(Expression.typeof(inExp));
1629 1 then DAE.SIZE(exp,SOME(DAE.ICONST(1)));
1630 else
1631 algorithm
1632 ✗ (_,{}) := TypesDump.flattenArrayType(Expression.typeof(inExp));
1633 then inExp;
1634 end match;
1635 end simplifyScalar;
1636
1637 protected function makeNestedReduction
1638 input DAE.Exp inExp;
1639 input String inName;
1640 input DAE.Type inType;
1641 input DAE.Exp inCall;
1642 output DAE.Exp outCall;
1643 algorithm
1644 6 outCall := Expression.makePureBuiltinCall(inName, {inExp, inCall}, inType);
1645 end makeNestedReduction;
1646
1647 protected function simplifySymmetric
1648 input array<array<DAE.Exp>> marr;
1649 input Integer i1;
1650 input Integer i2;
1651 algorithm
1652 () := match (i1, i2)
1653 local
1654 array<DAE.Exp> v1,v2;
1655 DAE.Exp exp;
1656 case (0, 1) then ();
1657 else
1658 algorithm
1659 3 v1 := arrayGet(marr, i1);
1660 3 v2 := arrayGet(marr, i2);
1661 3 exp := arrayGet(v1,i2);
1662 3 arrayUpdate(v2, i1, exp);
1663
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
3 simplifySymmetric(marr, if i1==1 then (i2-2) else (i1-1), if i1==1 then (i2-1) else i2);
1664 then ();
1665 end match;
1666 end simplifySymmetric;
1667
1668 protected function simplifyCat
1669 input Integer inDim;
1670 input list<DAE.Exp> inExpList;
1671 output list<DAE.Exp> outExpList;
1672 algorithm
1673 outExpList := match inDim
1674 local
1675 list<DAE.Exp> expl;
1676
1677 case 1
1678 algorithm
1679 1997 expl := List.map(inExpList, simplifyCatArg);
1680 1997 then
1681 simplifyCat2(inDim, expl, {}, false);
1682
1683 10 else simplifyCat2(inDim, inExpList, {}, false);
1684
1685 end match;
1686 end simplifyCat;
1687
1688 function simplifyCatArg
1689 input DAE.Exp arg;
1690 output DAE.Exp outArg;
1691 algorithm
1692 outArg := match arg
1693 local
1694 DAE.Dimension dim;
1695
1696 2 case DAE.MATRIX() then Expression.matrixToArray(arg);
1697 case DAE.CREF(ty = DAE.T_ARRAY(dims = {dim})) guard Expression.dimensionKnown(dim)
1698 1453 then DAE.ARRAY(arg.ty, true, Expression.expandExpression(arg, false));
1699 else arg;
1700 end match;
1701 end simplifyCatArg;
1702
1703 protected function simplifyCat2
1704 input Integer dim;
1705 input list<DAE.Exp> ies;
1706 input list<DAE.Exp> acc;
1707 input Boolean changed;
1708 output list<DAE.Exp> oes;
1709 algorithm
1710 oes := matchcontinue (dim, ies, changed)
1711 local
1712 list<DAE.Exp> es1,es2,esn,es;
1713 DAE.Exp e;
1714 DAE.Dimension ndim,dim1,dim2,dim11;
1715 DAE.Dimensions dims;
1716 DAE.Type etp;
1717 Integer i;
1718 list<list<DAE.Exp>> ms1,ms2,mss;
1719 Boolean sc;
1720
1721 1683 case (_, {}, true) then listReverse(acc);
1722
1723 case (1, DAE.ARRAY(array=es1,scalar=sc,ty=DAE.T_ARRAY(dims=dim1::dims,ty=etp)) ::
1724 DAE.ARRAY(array=es2,ty=DAE.T_ARRAY(dims=dim2::_))::es, _)
1725 algorithm
1726 1699 esn := listAppend(es1,es2);
1727 1699 ndim := Expression.addDimensions(dim1,dim2);
1728 1699 etp := DAE.T_ARRAY(etp,ndim::dims);
1729
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1698 times.
1700 e := DAE.ARRAY(etp,sc,esn);
1730 1699 then simplifyCat2(dim,e::es,acc,true);
1731
1732 case (2, DAE.MATRIX(matrix=ms1,integer=i,ty=DAE.T_ARRAY(dims=dim11::dim1::dims,ty=etp))::DAE.MATRIX(matrix=ms2,ty=DAE.T_ARRAY(dims=_::dim2::_))::es, _)
1733 algorithm
1734 1 mss := List.threadMap(ms1,ms2,listAppend);
1735 1 ndim := Expression.addDimensions(dim1,dim2);
1736 1 etp := DAE.T_ARRAY(etp,dim11::ndim::dims);
1737 1 e := DAE.MATRIX(etp,i,mss);
1738 1 then simplifyCat2(dim,e::es,acc,true);
1739
1740 2332 case (_, e::es, _) then simplifyCat2(dim,es,e::acc,changed);
1741 end matchcontinue;
1742 end simplifyCat2;
1743
1744 protected function simplifyBuiltinStringFormat
1745 input DAE.Exp exp;
1746 input DAE.Exp len_exp;
1747 input DAE.Exp just_exp;
1748 output DAE.Exp outExp;
1749 algorithm
1750 outExp := match (exp,len_exp,just_exp)
1751 local
1752 Integer i,len;
1753 Real r;
1754 Boolean b,just;
1755 String str;
1756 Absyn.Path name;
1757 case (DAE.ICONST(i),DAE.ICONST(len),DAE.BCONST(just))
1758 algorithm
1759 407 str := intString(i);
1760 407 str := cevalBuiltinStringFormat(str,stringLength(str),len,just);
1761 407 then DAE.SCONST(str);
1762 case (DAE.RCONST(r),DAE.ICONST(len),DAE.BCONST(just))
1763 algorithm
1764 ✗ str := realString(r);
1765 ✗ str := cevalBuiltinStringFormat(str,stringLength(str),len,just);
1766 ✗ then DAE.SCONST(str);
1767 case (DAE.BCONST(b),DAE.ICONST(len),DAE.BCONST(just))
1768 algorithm
1769
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
3 str := boolString(b);
1770 3 str := cevalBuiltinStringFormat(str,stringLength(str),len,just);
1771 3 then DAE.SCONST(str);
1772 case (DAE.ENUM_LITERAL(name=name),DAE.ICONST(len),DAE.BCONST(just))
1773 algorithm
1774 ✗ str := AbsynUtil.pathLastIdent(name);
1775 ✗ str := cevalBuiltinStringFormat(str,stringLength(str),len,just);
1776 ✗ then DAE.SCONST(str);
1777 end match;
1778 end simplifyBuiltinStringFormat;
1779
1780 public function cevalBuiltinStringFormat
1781 "Helper function to cevalBuiltinStringFormat, does the actual formatting."
1782 input String inString;
1783 input Integer stringLength;
1784 input Integer minLength;
1785 input Boolean leftJustified;
1786 output String outString;
1787 algorithm
1788
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 982 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
983 outString := if stringLength >= minLength then inString
1789 else
1790 if leftJustified then
1791 inString + stringAppendList(List.fill(" ", minLength - stringLength))
1792 else
1793 stringAppendList(List.fill(" ", minLength - stringLength)) + inString;
1794 end cevalBuiltinStringFormat;
1795
1796 protected function simplifyStringAppendList
1797 "
1798 stringAppendList({abc,def,String(time),ghi,jkl}) => stringAppendList({abcdef,String(time),ghijkl})
1799 stringAppendList({abc,def,ghi,jkl}) => abcdefghijkl
1800 stringAppendList({}) => abcdefghijkl
1801 "
1802 input list<DAE.Exp> iexpl;
1803 input list<DAE.Exp> iacc;
1804 input Boolean ichange;
1805 output DAE.Exp exp;
1806 algorithm
1807 exp := match (iexpl,iacc,ichange)
1808 local
1809 String s1,s2,s;
1810 DAE.Exp exp1,exp2;
1811 list<DAE.Exp> rest,acc;
1812 Boolean change;
1813
1814 case ({},{},_) then DAE.SCONST("");
1815 case ({},{exp},_) then exp;
1816 case ({},{exp1,exp2},_)
1817 ✗ then DAE.BINARY(exp2,DAE.ADD(DAE.T_STRING_DEFAULT),exp1);
1818 case ({},acc,true)
1819 algorithm
1820 ✗ acc := listReverse(acc);
1821 ✗ exp := DAE.LIST(acc);
1822 ✗ then Expression.makePureBuiltinCall("stringAppendList",{exp},DAE.T_STRING_DEFAULT);
1823 case (DAE.SCONST(s1)::rest,DAE.SCONST(s2)::acc,_)
1824 algorithm
1825 ✗ s := s2 + s1;
1826 ✗ then simplifyStringAppendList(rest,DAE.SCONST(s)::acc,true);
1827 1444 case (exp::rest,acc,change) then simplifyStringAppendList(rest,exp::acc,change);
1828 end match;
1829 end simplifyStringAppendList;
1830
1831 protected function simplifyBuiltinConstantCalls "simplifies some builtin calls if constant arguments"
1832 input String name;
1833 input DAE.Exp exp "assumes already simplified call arguments";
1834 output DAE.Exp outExp;
1835 algorithm
1836 outExp := matchcontinue (name,exp)
1837 local
1838 Real r,v1,v2;
1839 Integer i, j;
1840 DAE.Exp e,e1,e2;
1841
1842 // der(constant) ==> 0
1843 case ("der",DAE.CALL(expLst ={e}))
1844 algorithm
1845 10 e1 := simplifyBuiltinConstantDer(e);
1846 then e1;
1847
1848 // pre(constant) ==> constant
1849 case ("pre",DAE.CALL(expLst ={e}))
1850 then e;
1851
1852 // previous(constant) ==> constant
1853 case ("previous",DAE.CALL(expLst ={e}))
1854 then e;
1855
1856 // edge(constant) ==> false
1857 case ("edge",DAE.CALL(expLst ={_}))
1858 then DAE.BCONST(false);
1859
1860 // change(constant) ==> false
1861 case ("change",DAE.CALL(expLst ={_}))
1862 then DAE.BCONST(false);
1863
1864 // sqrt function; a negative argument is left for the generated code's
1865 // assertion to report rather than folded to NaN.
1866 case("sqrt",DAE.CALL(expLst={e}))
1867 algorithm
1868 2034 r := Expression.toReal(e);
1869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1574 times.
1574 true := r >= 0.0;
1870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1574 times.
1574 r := sqrt(r);
1871 1574 then
1872 DAE.RCONST(r);
1873
1874 // abs on real
1875 case("abs",DAE.CALL(expLst={DAE.RCONST(r)}))
1876 algorithm
1877 9154 r := abs(r);
1878 9154 then
1879 DAE.RCONST(r);
1880
1881 // abs on integer
1882 case("abs",DAE.CALL(expLst={DAE.ICONST(i)}))
1883 algorithm
1884 ✗ i := abs(i);
1885 ✗ then
1886 DAE.ICONST(i);
1887
1888 // sin function
1889 case("sin",DAE.CALL(expLst={e}))
1890 algorithm
1891 1659 r := sin(Expression.toReal(e));
1892 1659 then DAE.RCONST(r);
1893
1894 // cos function
1895 case("cos",DAE.CALL(expLst={e}))
1896 algorithm
1897 1138 r := cos(Expression.toReal(e));
1898 1138 then DAE.RCONST(r);
1899
1900 // sin function
1901 case("asin",DAE.CALL(expLst={e}))
1902 algorithm
1903 14 r := Expression.toReal(e);
1904
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 true := r >= -1.0 and r <= 1.0;
1905 ✗ r := asin(r);
1906 ✗ then DAE.RCONST(r);
1907
1908 // cos function
1909 case("acos",DAE.CALL(expLst={e}))
1910 algorithm
1911 144 r := Expression.toReal(e);
1912
2/4
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 144 times.
144 true := r >= -1.0 and r <= 1.0;
1913
2/4
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 144 times.
144 r := acos(Expression.toReal(e));
1914 144 then DAE.RCONST(r);
1915
1916 // tangent function
1917 case("tan",DAE.CALL(expLst={e}))
1918 algorithm
1919 ✗ r := tan(Expression.toReal(e));
1920 ✗ then DAE.RCONST(r);
1921
1922 // DAE.Exp function
1923 case("exp",DAE.CALL(expLst={e}))
1924 algorithm
1925 256 r := .exp(Expression.toReal(e));
1926 256 then DAE.RCONST(r);
1927
1928 // log function
1929 case("log",DAE.CALL(expLst={e}))
1930 algorithm
1931 912 r := Expression.toReal(e);
1932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 912 times.
912 true := r > 0;
1933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 912 times.
912 r := log(r);
1934 912 then
1935 DAE.RCONST(r);
1936
1937 // log10 function
1938 case("log10",DAE.CALL(expLst={e}))
1939 algorithm
1940 ✗ r := Expression.toReal(e);
1941 ✗ true := r > 0;
1942 ✗ r := log10(r);
1943 ✗ then
1944 DAE.RCONST(r);
1945
1946 // min function on integers
1947 case("min",DAE.CALL(expLst={DAE.ICONST(i), DAE.ICONST(j)}))
1948 algorithm
1949 i := min(i, j);
1950 88 then DAE.ICONST(i);
1951
1952 // min function on reals
1953 case("min",DAE.CALL(expLst={e, e1},attr=DAE.CALL_ATTR(ty=DAE.T_REAL())))
1954 algorithm
1955 5610 v1 := Expression.toReal(e);
1956 5610 v2 := Expression.toReal(e1);
1957 5610 r := min(v1, v2);
1958 5610 then DAE.RCONST(r);
1959
1960 // min function on enumerations
1961 case("min",DAE.CALL(expLst={e as DAE.ENUM_LITERAL(index=i), e1 as DAE.ENUM_LITERAL(index=j)}))
1962 algorithm
1963
1/2
✓ Branch 0 taken 674 times.
✗ Branch 1 not taken.
674 e2 := if i<j then e else e1;
1964 then e2;
1965
1966 // max function on integers
1967 case("max",DAE.CALL(expLst={DAE.ICONST(i), DAE.ICONST(j)}))
1968 algorithm
1969 i := max(i, j);
1970 89 then DAE.ICONST(i);
1971
1972 // max function on reals
1973 case("max",DAE.CALL(expLst={e, e1},attr=DAE.CALL_ATTR(ty=DAE.T_REAL())))
1974 algorithm
1975 6981 v1 := Expression.toReal(e);
1976 6981 v2 := Expression.toReal(e1);
1977 6981 r := max(v1, v2);
1978 6981 then DAE.RCONST(r);
1979
1980 // max function on enumerations
1981 case("max",DAE.CALL(expLst={e as DAE.ENUM_LITERAL(index=i), e1 as DAE.ENUM_LITERAL(index=j)}))
1982 algorithm
1983
1/2
✓ Branch 0 taken 674 times.
✗ Branch 1 not taken.
674 e2 := if i>j then e else e1;
1984 then e2;
1985
1986 case("sign",DAE.CALL(expLst={DAE.RCONST(r)}))
1987 algorithm
1988
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 18 times.
36 i := if realEq(r,0.0) then 0 else (if realGt(r,0.0) then 1 else -1);
1989 36 then DAE.ICONST(i);
1990
1991 end matchcontinue;
1992 end simplifyBuiltinConstantCalls;
1993
1994 protected function simplifyCref
1995 " Function for simplifying
1996 x[{y,z,q}] to {x[y], x[z], x[q]}"
1997 input DAE.Exp origExp;
1998 input ComponentRef inCREF;
1999 input Type inType;
2000 output DAE.Exp exp;
2001 algorithm
2002 exp := matchcontinue inCREF
2003 local
2004 Type t2;
2005 list<Subscript> ssl;
2006 ComponentRef cr;
2007 Ident idn;
2008 DAE.Exp expCref;
2009
2010 case DAE.CREF_IDENT(idn,t2,(ssl as ((DAE.SLICE(DAE.ARRAY(_,_,_))) :: _)))
2011 algorithm
2012 22 cr := ComponentReferenceBasics.makeCrefIdent(idn,t2,{});
2013 22 expCref := Expression.makeCrefExp(cr, inType);
2014 22 exp := simplifyCref2(expCref,ssl);
2015 then exp;
2016
2017 case DAE.CREF_IDENT(subscriptLst = DAE.SLICE(exp = DAE.RANGE()) :: _)
2018 algorithm
2019 87 cr := ComponentReference.crefStripSubs(inCREF);
2020 87 expCref := Expression.makeCrefExp(cr, inType);
2021 87 then
2022 simplifyCref2(expCref, inCREF.subscriptLst);
2023
2024 case DAE.CREF_QUAL(idn, DAE.T_METATYPE(ty=t2), ssl, cr)
2025 algorithm
2026 733 exp := simplifyCrefMM1(idn, t2, ssl);
2027 733 exp := simplifyCrefMM(exp, Expression.typeof(exp), cr);
2028 then exp;
2029
2030 else origExp;
2031 end matchcontinue;
2032 end simplifyCref;
2033
2034 protected function simplifyCref2
2035 "Helper function for simplifyCref
2036 Does the recursion."
2037 input DAE.Exp inExp;
2038 input list<Subscript> inSsl;
2039 output DAE.Exp outExp;
2040 algorithm
2041 outExp := matchcontinue(inExp,inSsl)
2042 local
2043 Type t,tp;
2044 DAE.Exp exp_1, exp;
2045 list<DAE.Exp> expl_1,expl;
2046 Subscript ss;
2047 list<Subscript> ssl,subs;
2048 list<ComponentRef> crefs;
2049 ComponentRef cr;
2050 Integer dim;
2051 Boolean sc;
2052
2053 case(exp_1,{}) then exp_1;
2054
2055 case(DAE.CREF(cr as DAE.CREF_IDENT(_, _,_),t), (((DAE.SLICE(DAE.ARRAY(_,_,(expl_1))))) :: ssl))
2056 algorithm
2057 22 subs := List.map(expl_1,Expression.makeIndexSubscript);
2058 22 crefs := List.map1r(List.map(subs,List.create),ComponentReference.subscriptCref,cr);
2059 22 t := Types.unliftArray(t);
2060 22 expl := List.map1(crefs,Expression.makeCrefExp,t);
2061 22 dim := listLength(expl);
2062 44 exp := simplifyCref2(DAE.ARRAY(DAE.T_ARRAY(t,{DAE.DIM_INTEGER(dim)}),true,expl),ssl);
2063 then
2064 exp;
2065
2066 case (DAE.CREF(cr as DAE.CREF_IDENT(), t),
2067 (ss as DAE.SLICE(exp = DAE.RANGE())) :: ssl)
2068 algorithm
2069 87 subs := Expression.expandSliceExp(ss.exp);
2070
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 6 times.
23 crefs := list(ComponentReference.subscriptCref(cr, List.create(s)) for s in subs);
2071 6 t := Types.unliftArray(t);
2072
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 6 times.
23 expl := list(Expression.makeCrefExp(cr, t) for cr in crefs);
2073 6 dim := listLength(expl);
2074 12 exp := DAE.ARRAY(DAE.T_ARRAY(t, {DAE.DIM_INTEGER(dim)}), true, expl);
2075 6 then
2076 simplifyCref2(exp, ssl);
2077
2078 case(DAE.ARRAY(tp,sc,expl), ssl )
2079 algorithm
2080 ✗ expl := List.map1(expl,simplifyCref2,ssl);
2081 ✗ then
2082 DAE.ARRAY(tp,sc,expl);
2083
2084 end matchcontinue;
2085 end simplifyCref2;
2086
2087 protected function simplifyCrefMM_index
2088 input DAE.Exp inExp;
2089 input String ident;
2090 input DAE.Type ty;
2091 output DAE.Exp exp;
2092 protected
2093 Integer index;
2094 DAE.Type nty;
2095 list<DAE.Var> fields;
2096 algorithm
2097 733 fields := Types.getMetaRecordFields(ty);
2098 733 index := Types.findVarIndex(ident, fields)+1;
2099 733 DAE.TYPES_VAR(ty=nty) := listGet(fields, index);
2100 733 exp := DAE.RSUB(inExp, index, ident, nty);
2101 end simplifyCrefMM_index;
2102
2103 protected function simplifyCrefMM
2104 input DAE.Exp inExp;
2105 input DAE.Type inType;
2106 input ComponentRef inCref;
2107 output DAE.Exp exp;
2108 algorithm
2109 exp := match inCref
2110 case DAE.CREF_IDENT()
2111 algorithm
2112 733 exp := simplifyCrefMM_index(inExp, inCref.ident, inType);
2113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 733 times.
733 exp := if listEmpty(inCref.subscriptLst) then exp else DAE.ASUB(exp, inCref.subscriptLst);
2114 then exp;
2115 case DAE.CREF_QUAL()
2116 algorithm
2117 ✗ exp := simplifyCrefMM_index(inExp, inCref.ident, inType);
2118 ✗ exp := if listEmpty(inCref.subscriptLst) then exp else DAE.ASUB(exp, inCref.subscriptLst);
2119 ✗ exp := simplifyCrefMM(exp, Expression.typeof(exp), inCref.componentRef);
2120 then exp;
2121 end match;
2122 end simplifyCrefMM;
2123
2124 protected function simplifyCrefMM1
2125 input String ident;
2126 input DAE.Type ty;
2127 input list<Subscript> ssl;
2128 output DAE.Exp outExp;
2129 algorithm
2130 outExp := match ssl
2131 733 case {} then DAE.CREF(DAE.CREF_IDENT(ident,ty,{}),ty);
2132 ✗ else DAE.ASUB(DAE.CREF(DAE.CREF_IDENT(ident,ty,{}),ty), ssl);
2133 end match;
2134 end simplifyCrefMM1;
2135
2136 public function simplify2
2137 "Advanced simplifications covering several
2138 terms or factors, like a +2a +3a = 5a "
2139 input DAE.Exp inExp;
2140 input Boolean simplifyAddOrSub = true;
2141 input Boolean simplifyMulOrDiv = true;
2142 output DAE.Exp outExp;
2143 protected
2144 DAE.Type ty;
2145 algorithm
2146 19144365 ty := Expression.typeof(inExp);
2147
2148
2/2
✓ Branch 1 taken 569296 times.
✓ Branch 2 taken 18575069 times.
19144365 if not Expression.isIntegerOrReal(ty) then
2149 outExp := inExp;
2150 569296 return;
2151 end if;
2152
2153 outExp := match inExp
2154 local
2155 DAE.Exp e1,e2,exp_2,exp_3, resConst;
2156 list<DAE.Exp> lstConstExp, lstExp;
2157 Operator op;
2158 Boolean hasConst;
2159
2160 // global simplify ADD and SUB
2161 case DAE.BINARY(operator = op) /* multiple terms simplifications */
2162 guard simplifyAddOrSub and Expression.isAddOrSub(op)
2163 algorithm
2164 /* Sorting constants, 1+a+2+b => 3+a+b */
2165 2374582 lstExp := Expression.terms(inExp);
2166 2374582 (lstConstExp, lstExp) := List.splitOnTrue(lstExp, Expression.isConstValue);
2167 2374582 hasConst := not listEmpty(lstConstExp);
2168
2/2
✓ Branch 0 taken 1321332 times.
✓ Branch 1 taken 1053250 times.
2374582 resConst := if hasConst then simplifyBinaryAddConstants(lstConstExp) else Expression.makeConstZero(ty);
2169
2/2
✓ Branch 0 taken 1321332 times.
✓ Branch 1 taken 1053250 times.
2374582 exp_2 := if hasConst then Expression.makeSum1(lstExp) else inExp;
2170 /* Merging coefficients 2a+4b+3a+b => 5a+5b */
2171 2374582 exp_3 := simplifyBinaryCoeff(exp_2);
2172
2/2
✓ Branch 0 taken 1321332 times.
✓ Branch 1 taken 1053250 times.
2374582 exp_3 := if hasConst then Expression.expAdd(resConst,simplify2(exp_3, false, true)) else simplify2(exp_3, false, true);
2173 then
2174 exp_3;
2175
2176 //locked global simplify ADD and SUB
2177 //unlocked global simplify MUL and DIV
2178 case DAE.BINARY(exp1 = e1,operator = op,exp2 = e2) /* multiple factors simplifications */
2179 guard Expression.isAddOrSub(op)
2180 algorithm
2181 1394550 e1 := simplify2(e1, false, true);
2182 1394251 e2 := simplify2(e2, false, true);
2183 1392729 then
2184 DAE.BINARY(e1,op,e2);
2185
2186 //global simplify MUL and DIV
2187 case DAE.BINARY(operator = op) /* multiple factors simplifications */
2188 guard simplifyMulOrDiv and Expression.isMulOrDiv(op)
2189 algorithm
2190 /* Sorting constants, 1+a+2+b => 3+a+b */
2191 3175664 lstExp := Expression.factors(inExp);
2192 3174689 (lstConstExp, lstExp) := List.splitOnTrue(lstExp, Expression.isConst);
2193
2/2
✓ Branch 0 taken 1156665 times.
✓ Branch 1 taken 2018024 times.
3174689 if not listEmpty(lstConstExp) then
2194 1156665 resConst := simplifyBinaryMulConstants(lstConstExp);
2195
2/2
✓ Branch 2 taken 1151850 times.
✓ Branch 3 taken 131 times.
1151981 exp_2 := Expression.makeProductLst(if Types.isScalarReal(Expression.typeofOp(op)) then simplifyMul(lstExp) else lstExp);
2196
2/2
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 1151894 times.
1151981 if Expression.isConstOne(resConst) then
2197 87 exp_3 := simplify2(exp_2, true, false);
2198 elseif Expression.isConstMinusOne(resConst) then
2199 3204 exp_3 := Expression.negate(simplify2(exp_2, true, false));
2200 else
2201 1148690 exp_3 := Expression.expMul(resConst,simplify2(exp_2, true, false));
2202 end if;
2203 else
2204 2018024 exp_2 := simplifyBinaryCoeff(inExp);
2205 2018024 exp_3 := simplify2(exp_2, true, false);
2206 end if;
2207 then
2208 exp_3;
2209
2210 //unlocked global simplify ADD and SUB
2211 //locked global simplify MUL and DIV
2212 case DAE.BINARY(exp1 = e1,operator = op,exp2 = e2) /* multiple terms simplifications */
2213 guard Expression.isMulOrDiv(op)
2214 algorithm
2215 2700115 e1 := simplify2(e1, true, false);
2216 2700115 e2 := simplify2(e2, true, false);
2217 2700115 then
2218 DAE.BINARY(e1,op,e2);
2219
2220 //others operators
2221 case DAE.BINARY(exp1 = e1,operator = op,exp2 = e2) /* multiple terms/factor simplifications */
2222 algorithm
2223 248222 e1 := simplify2(e1);
2224 248222 e2 := simplify2(e2);
2225 248222 then
2226 DAE.BINARY(e1,op,e2);
2227
2228 case DAE.UNARY(op,e1)
2229 algorithm
2230 765881 e1 := simplify2(e1);
2231 765881 then
2232 DAE.UNARY(op,e1);
2233
2234 else inExp;
2235
2236 end match;
2237 end simplify2;
2238
2239 protected function simplifyBinaryArrayOp
2240 input Operator inOperator;
2241 output Boolean found;
2242 algorithm
2243 found := match inOperator
2244 case DAE.MUL_MATRIX_PRODUCT() then true;
2245 case DAE.ADD_ARR() then true;
2246 case DAE.SUB_ARR() then true;
2247 case DAE.MUL_ARR() then true;
2248 case DAE.DIV_ARR() then true;
2249 case DAE.POW_ARR() then true;
2250 case DAE.POW_ARR2() then true;
2251 case DAE.MUL_ARRAY_SCALAR() then true;
2252 case DAE.ADD_ARRAY_SCALAR() then true;
2253 case DAE.DIV_ARRAY_SCALAR() then true;
2254 case DAE.POW_ARRAY_SCALAR() then true;
2255 case DAE.SUB_SCALAR_ARRAY() then true;
2256 case DAE.DIV_SCALAR_ARRAY() then true;
2257 case DAE.POW_SCALAR_ARRAY() then true;
2258 case DAE.MUL_SCALAR_PRODUCT() then true;
2259 else false;
2260 end match;
2261 end simplifyBinaryArrayOp;
2262
2263 protected function simplifyBinaryArray "Simplifies binary array expressions,
2264 e.g. matrix multiplication, etc."
2265 input DAE.Exp inExp1;
2266 input Operator inOperator2;
2267 input DAE.Exp inExp3;
2268 output DAE.Exp outExp;
2269 algorithm
2270 outExp := matchcontinue (inExp1,inOperator2,inExp3)
2271 local
2272 DAE.Exp e_1,e1,e2,res,s1,a1;
2273 Type tp;
2274 Operator op;
2275
2276 case (e1,DAE.MUL_MATRIX_PRODUCT(),e2)
2277 algorithm
2278 1929 e_1 := simplifyMatrixProduct(e1, e2);
2279 then
2280 e_1;
2281
2282 case(e1,op as DAE.ADD_ARR(),e2)
2283 algorithm
2284 32073 a1 := simplifyVectorBinary0(e1,op,e2);
2285 then
2286 a1;
2287
2288 case (e1,op as DAE.SUB_ARR(),e2)
2289 algorithm
2290 8090 a1 := simplifyVectorBinary0(e1, op, e2);
2291 then
2292 a1;
2293
2294 case (e1,op as DAE.MUL_ARR(),e2)
2295 algorithm
2296 80 a1 := simplifyVectorBinary(e1, op, e2);
2297 then a1;
2298
2299 case (e1,op as DAE.DIV_ARR(),e2)
2300 algorithm
2301 30 a1 := simplifyVectorBinary(e1, op, e2);
2302 then a1;
2303
2304 case (e1,DAE.POW_ARR(),e2)
2305 algorithm
2306 5 tp := Expression.typeof(e1);
2307 5 a1 := simplifyMatrixPow(e1, tp, e2);
2308 then a1;
2309
2310 case (e1,DAE.POW_ARR2(),e2)
2311 algorithm
2312 10 tp := Expression.typeof(e1);
2313 10 a1 := simplifyVectorBinary(e1, DAE.POW_ARR2(tp), e2);
2314 then a1;
2315
2316 // v1 - -v2 => v1 + v2
2317 case (e1,DAE.SUB_ARR(ty=tp),DAE.UNARY(_,e2))
2318 ✗ then
2319 DAE.BINARY(e1,DAE.ADD_ARR(tp),e2);
2320
2321 // v1 + -v2 => v1 - v2
2322 case (e1,DAE.ADD_ARR(ty=tp),DAE.UNARY(_,e2))
2323 ✗ then
2324 DAE.BINARY(e1,DAE.SUB_ARR(tp),e2);
2325
2326 case (a1, op, s1)
2327 algorithm
2328
2/2
✓ Branch 1 taken 39461 times.
✓ Branch 2 taken 9223 times.
48684 true := Expression.isArrayScalarOp(op);
2329 9223 op := unliftOperator(a1, op);
2330 9223 then
2331 simplifyVectorScalar(a1, op, s1);
2332
2333 case (s1, op, a1)
2334 algorithm
2335
2/2
✓ Branch 1 taken 45858 times.
✓ Branch 2 taken 8 times.
45866 true := Expression.isScalarArrayOp(op);
2336 8 op := unliftOperator(a1, op);
2337 8 then
2338 simplifyVectorScalar(s1, op, a1);
2339
2340 case (e1,DAE.MUL_SCALAR_PRODUCT(),e2)
2341 algorithm
2342 3645 res := simplifyScalarProduct(e1, e2);
2343 then
2344 res;
2345
2346 case (e1,op as DAE.ADD_ARR(),e2)
2347 algorithm
2348 28885 a1 := simplifyMatrixBinary(e1, op, e2);
2349 then a1;
2350
2351 case (e1,op as DAE.SUB_ARR(),e2)
2352 algorithm
2353 5747 a1 := simplifyMatrixBinary(e1, op, e2);
2354 // print("simplifyMatrixBinary: " + ExpressionBasics.printExpStr(e1) + "=>" + ExpressionBasics.printExpStr(a1) + "\n");
2355 then a1;
2356
2357 case (e1,op as DAE.MUL_ARR(),e2)
2358 algorithm
2359 52 a1 := simplifyMatrixBinary(e1, op, e2);
2360 then a1;
2361
2362 case (e1,op as DAE.DIV_ARR(),e2)
2363 algorithm
2364 1 a1 := simplifyMatrixBinary(e1, op, e2);
2365 then a1;
2366
2367 case (e1,op as DAE.POW_ARR2(),e2)
2368 algorithm
2369 2 a1 := simplifyMatrixBinary(e1, op, e2);
2370 then a1;
2371
2372 case (_,DAE.MUL_ARRAY_SCALAR(ty = tp),e2)
2373 algorithm
2374
2/2
✓ Branch 1 taken 5794 times.
✓ Branch 2 taken 21 times.
5815 true := Expression.isZero(e2);
2375 21 (a1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
2376 then a1;
2377
2378 case (e1,DAE.DIV_ARR(),_)
2379 algorithm
2380
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 true := Expression.isZero(e1);
2381 ✗ tp := Expression.typeof(e1);
2382 ✗ (a1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
2383 then a1;
2384
2385 case (e1,DAE.DIV_ARRAY_SCALAR(),_)
2386 algorithm
2387
1/2
✓ Branch 1 taken 491 times.
✗ Branch 2 not taken.
491 true := Expression.isZero(e1);
2388 ✗ tp := Expression.typeof(e1);
2389 ✗ (a1, _) := Expression.makeZeroExpression(Expression.arrayDimension(tp));
2390 then a1;
2391
2392 end matchcontinue;
2393 end simplifyBinaryArray;
2394
2395 public function simplifyScalarProduct
2396 "Simplifies the scalar product of two vectors."
2397 input DAE.Exp inVector1;
2398 input DAE.Exp inVector2;
2399 output DAE.Exp outProduct;
2400 algorithm
2401 outProduct := match(inVector1, inVector2)
2402 local
2403 list<DAE.Exp> expl, expl1, expl2;
2404 DAE.Exp exp;
2405 Type tp;
2406 ComponentRef cr1, cr2;
2407
2408 // Both arrays are empty. The result is defined in the spec by sum, so we
2409 // return the default value which is 0.
2410 case (DAE.ARRAY(ty = tp, array = {}), DAE.ARRAY(array = {}))
2411 ✗ then Expression.makeConstZero(tp);
2412
2413 // Normal scalar product of two vectors.
2414 case (DAE.ARRAY(array = expl1), DAE.ARRAY(array = expl2))
2415 algorithm
2416
2/4
✓ Branch 1 taken 6244 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6244 times.
✗ Branch 5 not taken.
6244 true := Expression.isVector(inVector1) and Expression.isVector(inVector2);
2417 6244 expl := List.threadMap(expl1, expl2, Expression.expMul);
2418 6244 exp := List.reduce(expl, Expression.expAdd);
2419 then
2420 exp;
2421
2422 // scalar product with two crefs: expand both! (issue #13853)
2423 case (DAE.CREF(componentRef = cr1), DAE.CREF(componentRef = cr2))
2424 guard Config.simCodeTarget() <> "Cpp"
2425 algorithm
2426
4/4
✓ Branch 1 taken 302 times.
✓ Branch 2 taken 213 times.
✓ Branch 3 taken 302 times.
✓ Branch 4 taken 213 times.
515 expl1 := list(Expression.crefToExp(c) for c in ComponentReference.expandCref(cr1, true));
2427
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 213 times.
213 true := listLength(expl1) <= 3;
2428
4/4
✓ Branch 1 taken 302 times.
✓ Branch 2 taken 213 times.
✓ Branch 3 taken 302 times.
✓ Branch 4 taken 213 times.
515 expl2 := list(Expression.crefToExp(c) for c in ComponentReference.expandCref(cr2, true));
2429
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 213 times.
213 true := listLength(expl1) == listLength(expl2);
2430 // expandCref leaves a non-constant slice alone; expMul would make it an array product.
2431
3/4
✓ Branch 1 taken 207 times.
✓ Branch 2 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 207 times.
213 true := List.none(expl1, isArrayTypedExp) and List.none(expl2, isArrayTypedExp);
2432 207 expl := List.threadMap(expl1, expl2, Expression.expMul);
2433 207 exp := List.reduce(expl, Expression.expAdd);
2434 then
2435 exp;
2436
2437 // Scalar product of any expression with zeros
2438 case (_, _)
2439 algorithm
2440
4/4
✓ Branch 1 taken 1265 times.
✓ Branch 2 taken 8 times.
✓ Branch 4 taken 1260 times.
✓ Branch 5 taken 5 times.
1273 true := Expression.isZero(inVector1) or Expression.isZero(inVector2);
2441 13 then
2442 Expression.makeConstZero(DAE.T_REAL_DEFAULT);
2443
2444 end match;
2445 end simplifyScalarProduct;
2446
2447 protected function isArrayTypedExp
2448 input DAE.Exp exp;
2449 output Boolean b = Expression.isArrayType(Expression.typeof(exp));
2450 end isArrayTypedExp;
2451
2452 protected function unliftOperator
2453 input DAE.Exp inArray;
2454 input Operator inOperator;
2455 output Operator outOperator;
2456 algorithm
2457 outOperator := match inArray
2458 154 case DAE.MATRIX() then Expression.unliftOperatorX(inOperator, 2);
2459 9077 else Expression.unliftOperator(inOperator);
2460 end match;
2461 end unliftOperator;
2462
2463 protected function simplifyVectorScalar
2464 "Simplifies vector scalar operations."
2465 input DAE.Exp inLhs;
2466 input Operator inOperator;
2467 input DAE.Exp inRhs;
2468 output DAE.Exp outExp;
2469 algorithm
2470 outExp := match(inLhs, inOperator, inRhs)
2471 local
2472 DAE.Exp s1;
2473 Operator op;
2474 Type tp;
2475 Boolean sc;
2476 list<DAE.Exp> es;
2477 list<list<DAE.Exp>> mexpl;
2478 Integer dims;
2479
2480 // scalar operator array
2481 case (_, _, DAE.ARRAY(ty = tp, scalar = sc, array = es))
2482 algorithm
2483
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
6 es := list(Expression.makeBinaryExp(inLhs, inOperator, e) for e in es);
2484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 then
2485 DAE.ARRAY(tp, sc, es);
2486
2487 case (s1,op,DAE.MATRIX(tp,dims,mexpl))
2488 algorithm
2489 2 mexpl := simplifyVectorScalarMatrix(mexpl,op,s1,false /*scalar-array*/);
2490 2 then
2491 DAE.MATRIX(tp,dims,mexpl);
2492
2493 // array operator scalar
2494 case (DAE.ARRAY(ty = tp, scalar = sc, array = es), _, _)
2495 algorithm
2496 2666 es := List.map2(es, Expression.makeBinaryExp, inOperator, inRhs);
2497
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 2520 times.
2812 then
2498 DAE.ARRAY(tp, sc, es);
2499
2500 case (DAE.MATRIX(tp,dims,mexpl),op,s1)
2501 algorithm
2502 152 mexpl := simplifyVectorScalarMatrix(mexpl,op,s1,true/*array-scalar*/);
2503 152 then
2504 DAE.MATRIX(tp,dims,mexpl);
2505
2506 end match;
2507 end simplifyVectorScalar;
2508
2509 protected function simplifyVectorBinary0 "help function to simplify1, prevents simplify1 to be called multiple times
2510 in subsequent cases"
2511 input DAE.Exp e1;
2512 input Operator op;
2513 input DAE.Exp e2;
2514 output DAE.Exp res;
2515 algorithm
2516 res := matchcontinue op
2517 local DAE.Exp a1;
2518
2519 case _
2520 algorithm
2521 40163 a1 := simplifyVectorBinary(e1,op,e2);
2522 then a1;
2523
2524 case DAE.ADD()
2525 algorithm
2526 ✗ true := Expression.isZero(e1);
2527 then
2528 e2;
2529
2530 case DAE.ADD_ARR()
2531 algorithm
2532
2/2
✓ Branch 1 taken 28971 times.
✓ Branch 2 taken 5 times.
28976 true := Expression.isZero(e1);
2533 then
2534 e2;
2535
2536 case DAE.SUB_ARR()
2537 algorithm
2538
2/2
✓ Branch 1 taken 5841 times.
✓ Branch 2 taken 1 time.
5842 true := Expression.isZero(e1);
2539 1 then
2540 Expression.negate(e2);
2541
2542 case DAE.SUB()
2543 algorithm
2544 ✗ true := Expression.isZero(e1);
2545 ✗ then
2546 Expression.negate(e2);
2547
2548 else
2549 algorithm
2550
2/2
✓ Branch 1 taken 34632 times.
✓ Branch 2 taken 180 times.
34812 true := Expression.isZero(e2);
2551 then
2552 e1;
2553
2554 end matchcontinue;
2555 end simplifyVectorBinary0;
2556
2557 protected function simplifyVectorBinary
2558 input DAE.Exp inLhs;
2559 input Operator inOperator;
2560 input DAE.Exp inRhs;
2561 output DAE.Exp outResult;
2562 protected
2563 DAE.Type ty;
2564 Boolean sc;
2565 list<DAE.Exp> lhs, rhs, res;
2566 Operator op;
2567 algorithm
2568
2/2
✓ Branch 0 taken 26792 times.
✓ Branch 1 taken 13491 times.
40283 DAE.ARRAY(ty = ty, scalar = sc, array = lhs) := inLhs;
2569
2/2
✓ Branch 0 taken 8081 times.
✓ Branch 1 taken 5410 times.
13491 DAE.ARRAY(array = rhs) := inRhs;
2570 5410 op := removeOperatorDimension(inOperator);
2571 5410 res := List.threadMap1(lhs, rhs, simplifyVectorBinary2, op);
2572
2/2
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 5175 times.
5645 outResult := DAE.ARRAY(ty, sc, res);
2573 end simplifyVectorBinary;
2574
2575 protected function simplifyVectorBinary2
2576 input DAE.Exp inLhs;
2577 input DAE.Exp inRhs;
2578 input Operator inOperator;
2579 output DAE.Exp outExp;
2580 algorithm
2581 15842 outExp := DAE.BINARY(inLhs, inOperator, inRhs);
2582 end simplifyVectorBinary2;
2583
2584 protected function simplifyMatrixBinary
2585 "Simplifies matrix addition and subtraction"
2586 input DAE.Exp inLhs;
2587 input Operator inOperator;
2588 input DAE.Exp inRhs;
2589 output DAE.Exp outResult;
2590 protected
2591 list<list<DAE.Exp>> lhs, rhs, res;
2592 Operator op;
2593 Integer sz;
2594 DAE.Type ty;
2595 algorithm
2596 34687 lhs := Expression.get2dArrayOrMatrixContent(inLhs);
2597 51 rhs := Expression.get2dArrayOrMatrixContent(inRhs);
2598 45 op := removeOperatorDimension(inOperator);
2599 45 res := List.threadMap1(lhs, rhs, simplifyMatrixBinary1, op);
2600 45 sz := listLength(res);
2601 45 ty := Expression.typeof(inLhs);
2602 45 outResult := DAE.MATRIX(ty, sz, res);
2603 end simplifyMatrixBinary;
2604
2605 protected function simplifyMatrixBinary1
2606 "Simplifies matrix addition and subtraction."
2607 input list<DAE.Exp> inLhs;
2608 input list<DAE.Exp> inRhs;
2609 input Operator inOperator;
2610 output list<DAE.Exp> outExpl;
2611 algorithm
2612 165 outExpl := List.threadMap1(inLhs, inRhs, simplifyMatrixBinary2, inOperator);
2613 end simplifyMatrixBinary1;
2614
2615 protected function simplifyMatrixBinary2
2616 input DAE.Exp inLhs;
2617 input DAE.Exp inRhs;
2618 input Operator inOperator;
2619 output DAE.Exp outExp;
2620 protected
2621 Operator op;
2622 algorithm
2623 389 op := removeOperatorDimension(inOperator);
2624 389 outExp := DAE.BINARY(inLhs, op, inRhs);
2625 end simplifyMatrixBinary2;
2626
2627 protected function simplifyMatrixPow
2628 "author: Frenkel TUD
2629 Simplifies matrix powers."
2630 input DAE.Exp inExp1;
2631 input Type inType;
2632 input DAE.Exp inExp2;
2633 output DAE.Exp outExp;
2634 algorithm
2635 outExp:=
2636 matchcontinue (inExp1, inExp2)
2637 local
2638 list<list<DAE.Exp>> expl_1,expl2;
2639 list<DAE.Exp> el;
2640 Type tp1;
2641 Integer size1,i,i_1;
2642 list<Integer> range;
2643 DAE.Exp e,m,res;
2644 /* A^0=I */
2645 case (DAE.MATRIX(ty = tp1,integer = size1), DAE.ICONST(integer = i))
2646 algorithm
2647
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 0:=i;
2648 2 el := List.fill(DAE.RCONST(0.0),size1);
2649 2 expl2 := List.fill(el,size1);
2650 2 range := List.intRange2(0,size1-1);
2651 2 expl_1 := simplifyMatrixPow1(range,expl2,DAE.RCONST(1.0));
2652 2 then
2653 DAE.MATRIX(tp1,size1,expl_1);
2654 /* A^1=A */
2655 case (m as DAE.MATRIX(), DAE.ICONST(integer = i))
2656 algorithm
2657
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 1:=i;
2658 then
2659 m;
2660
2661 // A^2 = A * A
2662 case (m as DAE.MATRIX(), DAE.ICONST(integer = i))
2663 algorithm
2664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 2 := i;
2665 2 res := simplifyMatrixProduct(m,m);
2666 then
2667 res;
2668
2669 // A^n = A^m*A^m where n = 2*m
2670 case(m as DAE.MATRIX(ty = tp1), DAE.ICONST(integer = i))
2671 algorithm
2672 ✗ true := i > 3;
2673 ✗ 0 := intMod(i,2);
2674 ✗ i_1 := intDiv(i,2);
2675 ✗ e := simplifyMatrixPow(m,tp1,DAE.ICONST(i_1));
2676 ✗ res := simplifyMatrixProduct(e,e);
2677 then
2678 res;
2679
2680 /* A^i */
2681 case (m as DAE.MATRIX(ty = tp1), DAE.ICONST(integer = i))
2682 algorithm
2683 ✗ true := 1 < i;
2684 ✗ i_1 := i - 1;
2685 ✗ e := simplifyMatrixPow(m,tp1,DAE.ICONST(i_1));
2686 ✗ res := simplifyMatrixProduct(m,e);
2687 then
2688 res;
2689 end matchcontinue;
2690 end simplifyMatrixPow;
2691
2692 protected function simplifyMatrixPow1
2693 "author: Frenkel TUD
2694 Simplifies matrix powers."
2695 input list<Integer> inRange;
2696 input list<list<DAE.Exp>> inMatrix;
2697 input DAE.Exp inValue;
2698 output list<list<DAE.Exp>> outMatrix;
2699 algorithm
2700 outMatrix:=
2701 matchcontinue (inRange,inMatrix,inValue)
2702 local
2703 list<list<DAE.Exp>> rm,rm1;
2704 list<DAE.Exp> row,row1;
2705 DAE.Exp e;
2706 Integer i;
2707 list<Integer> rr;
2708 case ({},{},_)
2709 then
2710 {};
2711 case (i::{},row::{},e)
2712 algorithm
2713 2 row1 := List.replaceAt(e,i+1,row);
2714 then
2715 {row1};
2716 case (i::rr,row::rm,e)
2717 algorithm
2718 3 row1 := List.replaceAt(e,i+1,row);
2719 3 rm1 := simplifyMatrixPow1(rr,rm,e);
2720 then
2721 row1::rm1;
2722 end matchcontinue;
2723 end simplifyMatrixPow1;
2724
2725 protected function simplifyMatrixProduct
2726 "Simplifies matrix multiplication."
2727 input DAE.Exp inMatrix1;
2728 input DAE.Exp inMatrix2;
2729 output DAE.Exp outProduct;
2730 protected
2731 DAE.Exp mat1, mat2;
2732 algorithm
2733 // Convert any DAE.MATRIX expressions to DAE.ARRAY.
2734 2525 mat1 := Expression.matrixToArray(inMatrix1);
2735 2525 mat2 := Expression.matrixToArray(inMatrix2);
2736 // Transpose the second matrix. This makes it easier to do the multiplication,
2737 // since we can do row-row multiplications instead of row-column.
2738 2525 (mat2, _) := Expression.transposeArray(mat2);
2739 2525 outProduct := simplifyMatrixProduct2(mat1, mat2);
2740 end simplifyMatrixProduct;
2741
2742 protected function simplifyMatrixProduct2
2743 "Helper function to simplifyMatrixProduct, does the actual work. Assumes that
2744 the second matrix has been transposed to make the multiplication easier."
2745 input DAE.Exp inMatrix1;
2746 input DAE.Exp inMatrix2;
2747 output DAE.Exp outProduct;
2748 algorithm
2749 outProduct := matchcontinue(inMatrix1, inMatrix2)
2750 local
2751 DAE.Dimension n, m, p;
2752 list<DAE.Exp> expl1, expl2;
2753 DAE.Type ty, row_ty;
2754 list<list<DAE.Exp>> matrix;
2755 DAE.Exp zero;
2756 list<DAE.Dimension> dims;
2757
2758 // The common dimension of the matrices is zero, the result will be an array
2759 // of zeroes (the default value of sum).
2760 case (DAE.ARRAY(ty = ty as DAE.T_ARRAY(dims = dims)), DAE.ARRAY())
2761 algorithm
2762 // It's sufficient to check the first array, because the only case where
2763 // the second array alone determines the result dimensions is the
2764 // vector-matrix case. The instantiation should just remove the
2765 // equations in that case, since the result will be an empty array.
2766
2/2
✓ Branch 1 taken 806 times.
✓ Branch 2 taken 5 times.
811 true := Expression.arrayContainZeroDimension(dims);
2767 5 zero := Expression.makeConstZero(ty);
2768 5 dims := simplifyMatrixProduct4(inMatrix1, inMatrix2);
2769 4 then
2770 Expression.arrayFill(dims, zero);
2771
2772 // Matrix-vector multiplication, c[n] = a[n, m] * b[m].
2773 case (DAE.ARRAY(ty = DAE.T_ARRAY(ty, {n, _}), array = expl1),
2774 DAE.ARRAY(ty = DAE.T_ARRAY(dims = {_})))
2775 algorithm
2776 // c[i] = a[i, :] * b for i in 1:n
2777 520 expl1 := List.map1(expl1, simplifyScalarProduct, inMatrix2);
2778 520 ty := DAE.T_ARRAY(ty, {n});
2779 520 then
2780 DAE.ARRAY(ty, true, expl1);
2781
2782 // Vector-matrix multiplication, c[m] = a[n] * b[n, m].
2783 case (DAE.ARRAY(ty = DAE.T_ARRAY(dims = {_})),
2784 DAE.ARRAY(ty = DAE.T_ARRAY(ty, {m, _}), array = expl2))
2785 algorithm
2786 // c[i] = a * b[:, i] for i in 1:m
2787 4 expl1 := List.map1r(expl2, simplifyScalarProduct, inMatrix1);
2788 4 ty := DAE.T_ARRAY(ty, {m});
2789 4 then
2790 DAE.ARRAY(ty, true, expl1);
2791
2792 // Matrix-matrix multiplication, c[n, p] = a[n, m] * b[m, p].
2793 case (DAE.ARRAY(ty = DAE.T_ARRAY(ty, {n, _}), array = expl1),
2794 DAE.ARRAY(ty = DAE.T_ARRAY(dims = {p, _}), array = expl2))
2795 algorithm
2796 // c[i, j] = a[i, :] * b[:, j] for i in 1:n, j in 1:p
2797 282 matrix := List.map1(expl1, simplifyMatrixProduct3, expl2);
2798 282 row_ty := DAE.T_ARRAY(ty, {p});
2799 282 expl1 := List.map2(matrix, Expression.makeArray, row_ty, true);
2800 282 then
2801 DAE.ARRAY(DAE.T_ARRAY(ty, {n, p}), false, expl1);
2802
2803 end matchcontinue;
2804 end simplifyMatrixProduct2;
2805
2806 protected function simplifyMatrixProduct3
2807 "Helper function to simplifyMatrixProduct2. Multiplies the given matrix row
2808 with each row in the given matrix and returns a list with the results."
2809 input DAE.Exp inRow;
2810 input list<DAE.Exp> inMatrix;
2811 output list<DAE.Exp> outRow;
2812 algorithm
2813 910 outRow := List.map1r(inMatrix, simplifyScalarProduct, inRow);
2814 end simplifyMatrixProduct3;
2815
2816 protected function simplifyMatrixProduct4
2817 "Helper function to simplifyMatrixProduct2. Returns the dimensions of the
2818 matrix multiplication product for two matrices."
2819 input DAE.Exp inMatrix1;
2820 input DAE.Exp inMatrix2;
2821 output list<DAE.Dimension> outDimensions;
2822 algorithm
2823 outDimensions := match(inMatrix1, inMatrix2)
2824 local
2825 DAE.Dimension n, m, p;
2826
2827 // c[n] = a[n, m] * b[m]
2828 case (DAE.ARRAY(ty = DAE.T_ARRAY(dims = {n, _})),
2829 DAE.ARRAY(ty = DAE.T_ARRAY(dims = {_})))
2830 then {n};
2831
2832 // c[m] = a[n] * b[n, m]
2833 case (DAE.ARRAY(ty = DAE.T_ARRAY(dims = {_})),
2834 DAE.ARRAY(ty = DAE.T_ARRAY(dims = {m, _})))
2835 then {m};
2836
2837 // c[n, p] = a[n, m] * b[m, p]
2838 case (DAE.ARRAY(ty = DAE.T_ARRAY(dims = {n, _})),
2839 DAE.ARRAY(ty = DAE.T_ARRAY(dims = {p, _})))
2840 then {n, p};
2841
2842 end match;
2843 end simplifyMatrixProduct4;
2844
2845 protected function simplifyBinarySortConstants
2846 "author: PA
2847 Sorts all constants of a sum or product to the
2848 beginning of the expression.
2849 Also combines expressions like 2a+4a and aaa+3a^3."
2850 input DAE.Exp inExp;
2851 output DAE.Exp outExp;
2852 algorithm
2853 outExp := matchcontinue inExp
2854 local
2855 list<DAE.Exp> e_lst,const_es1,notconst_es1;
2856 DAE.Exp res,e,e1,e2,res1,res2;
2857 Type tp;
2858
2859 // e1 * e2
2860 case e as DAE.BINARY(operator = DAE.MUL())
2861 algorithm
2862 ✗ res := simplifyBinarySortConstantsMul(e);
2863 then
2864 res;
2865
2866 // e1 / e2
2867 case DAE.BINARY(exp1 = e1,operator = DAE.DIV(ty = tp),exp2 = e2)
2868 algorithm
2869 ✗ e1 := simplifyBinarySortConstantsMul(e1);
2870 ✗ e2 := simplifyBinarySortConstantsMul(e2);
2871 ✗ then
2872 DAE.BINARY(e1,DAE.DIV(tp),e2);
2873
2874 // e1 + e2
2875 case e as DAE.BINARY(operator = DAE.ADD())
2876 algorithm
2877 ✗ e_lst := Expression.terms(e);
2878 //e_lst_1 = List.map(e_lst,simplify2);
2879 ✗ (const_es1, notconst_es1) :=
2880 List.splitOnTrue(e_lst, Expression.isConstValue);
2881 ✗ if not listEmpty(const_es1) then
2882 ✗ res1 := simplifyBinaryAddConstants(const_es1);
2883 ✗ res2 := Expression.makeSum1(notconst_es1); // Cannot simplify this, if const_es1_1 empty => infinite recursion.
2884 ✗ res := Expression.expAdd(res1, res2);
2885 else
2886 res := inExp;
2887 end if;
2888 then
2889 res;
2890
2891 // return e
2892 else inExp;
2893
2894 end matchcontinue;
2895 end simplifyBinarySortConstants;
2896
2897 protected function simplifyBinaryCoeff
2898 "author: PA
2899 Combines expressions like 2a+4a and aaa+3a^3, etc"
2900 input DAE.Exp inExp;
2901 output DAE.Exp outExp;
2902 algorithm
2903 outExp := matchcontinue inExp
2904 local
2905 list<DAE.Exp> e_lst,e_lst_1,e1_lst,e2_lst,e2_lst_1;
2906 DAE.Exp res,e,e1,e2;
2907 Type tp;
2908
2909 case e as DAE.BINARY(operator = DAE.MUL(tp))
2910 guard Types.isScalarReal(tp)
2911 algorithm
2912 2867073 e_lst := Expression.factors(e);
2913 2867073 e_lst_1 := simplifyMul(e_lst);
2914 2867073 res := Expression.makeProductLst(e_lst_1);
2915 then
2916 res;
2917
2918 case DAE.BINARY(exp1 = e1,operator = DAE.DIV(),exp2 = e2)
2919 algorithm
2920
2/2
✓ Branch 1 taken 643 times.
✓ Branch 2 taken 133156 times.
133799 false := Expression.isZero(e2);
2921 133156 e1_lst := Expression.factors(e1);
2922 133156 e2_lst := Expression.factors(e2);
2923 133156 e2_lst_1 := List.map(e2_lst, Expression.inverseFactors);
2924 133156 e_lst := listAppend(e1_lst, e2_lst_1);
2925 133156 e_lst_1 := simplifyMul(e_lst);
2926 133156 res := Expression.makeProductLst(e_lst_1);
2927 then
2928 res;
2929
2930 case e as DAE.BINARY(operator = DAE.ADD())
2931 algorithm
2932 763730 e_lst := Expression.terms(e);
2933 763730 e_lst_1 := simplifyAdd(e_lst);
2934 763730 res := Expression.makeSum(e_lst_1);
2935 then
2936 res;
2937
2938 case DAE.BINARY(exp1 = e1,operator = DAE.SUB(),exp2 = e2)
2939 algorithm
2940 461153 e1_lst := Expression.terms(e1);
2941 461153 e2_lst := Expression.terms(e2);
2942 461153 e2_lst := List.map(e2_lst, Expression.negate);
2943 461153 e_lst := listAppend(e1_lst, e2_lst);
2944 461153 e_lst_1 := simplifyAdd(e_lst);
2945 461153 res := Expression.makeSum(e_lst_1);
2946 then
2947 res;
2948
2949 else inExp;
2950
2951 end matchcontinue;
2952 end simplifyBinaryCoeff;
2953
2954 protected function simplifyBinaryAddConstants
2955 "author: PA
2956 Adds all expressions in the list, given that they are constant."
2957 input list<DAE.Exp> inExpLst;
2958 output DAE.Exp outExp;
2959 protected
2960 Type tp;
2961 list<DAE.Exp> es;
2962 algorithm
2963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1321332 times.
1321332 outExp :: es := inExpLst;
2964 1321332 tp := Expression.typeof(outExp);
2965
2/2
✓ Branch 0 taken 2912 times.
✓ Branch 1 taken 1321332 times.
1324244 for e in es loop
2966 2912 outExp := simplifyBinaryConst(DAE.ADD(tp), outExp, e);
2967 end for;
2968
2969 end simplifyBinaryAddConstants;
2970
2971 protected function simplifyBinaryMulConstants
2972 "author: PA
2973 Multiplies all expressions in the list, given that they are constant."
2974 input list<DAE.Exp> inExpLst;
2975 output DAE.Exp outExp;
2976 protected
2977 list<DAE.Exp> es;
2978 Type tp;
2979 algorithm
2980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1156665 times.
1156665 outExp :: es := inExpLst;
2981 1156665 tp := Expression.typeof(outExp);
2982
2/2
✓ Branch 0 taken 7114 times.
✓ Branch 1 taken 1151981 times.
1159095 for e in es loop
2983 7114 outExp := simplifyBinaryConst(DAE.MUL(tp), outExp, e);
2984 end for;
2985 end simplifyBinaryMulConstants;
2986
2987 protected function simplifyMul
2988 "author: PA
2989 Simplifies expressions like a*a*a*b*a*b*a"
2990 input list<DAE.Exp> expl;
2991 output list<DAE.Exp> expl_1;
2992 protected
2993 list<tuple<DAE.Exp, Real>> exp_const,exp_const_1;
2994 algorithm
2995 4152079 exp_const := List.map(expl, simplifyBinaryMulCoeff2);
2996 4152079 exp_const_1 := simplifyMulJoinFactors(exp_const);
2997 4152079 expl_1 := simplifyMulMakePow(exp_const_1);
2998 end simplifyMul;
2999
3000 protected function simplifyMulJoinFactors
3001 " author: PA
3002 Helper function to simplifyMul.
3003 Joins expressions that have the same base.
3004 E.g. {(a,2), (a,4), (b,2)} => {(a,6), (b,2)}"
3005 input list<tuple<DAE.Exp, Real>> inTplExpRealLst;
3006 output list<tuple<DAE.Exp, Real>> outTplExpRealLst = {};
3007 protected
3008 list<tuple<DAE.Exp, Real>> tplExpRealLst = inTplExpRealLst;
3009 DAE.Exp e;
3010 Real coeff, coeff2;
3011 algorithm
3012
3013
2/2
✓ Branch 0 taken 7761898 times.
✓ Branch 1 taken 4152079 times.
11913977 while not listEmpty(tplExpRealLst) loop
3014 7761898 (e, coeff) :: tplExpRealLst := tplExpRealLst;
3015 7761898 (coeff2, tplExpRealLst) := simplifyMulJoinFactorsFind(e, tplExpRealLst);
3016 7761898 coeff := coeff + coeff2;
3017 7761898 outTplExpRealLst := (e, coeff) :: outTplExpRealLst;
3018 end while;
3019
3020 // outTplExpRealLst := listReverse(outTplExpRealLst);
3021
3022 end simplifyMulJoinFactors;
3023
3024 protected function simplifyMulJoinFactorsFind
3025 "author: PA
3026 Helper function to simplifyMulJoinFactors.
3027 Searches rest of list to find all occurences of a base."
3028 input DAE.Exp inExp;
3029 input list<tuple<DAE.Exp, Real>> inTplExpRealLst;
3030 output Real outReal = 0.0;
3031 output list<tuple<DAE.Exp, Real>> outTplExpRealLst = {};
3032 protected
3033 tuple<DAE.Exp, Real> tplExpReal;
3034 algorithm
3035
2/2
✓ Branch 0 taken 4325243 times.
✓ Branch 1 taken 7761898 times.
12087141 for tplExpReal in inTplExpRealLst loop
3036
3037 (outReal,outTplExpRealLst) := match tplExpReal
3038 local
3039 Real coeff;
3040 DAE.Exp e2,e1;
3041 DAE.Operator op;
3042
3043 case (e2,coeff) /* e1 == e2 */
3044 guard ExpressionBasics.expEqual(inExp, e2)
3045 5689 then
3046 (coeff + outReal, outTplExpRealLst);
3047
3048 case (DAE.BINARY(exp1 = e1,operator = op as DAE.DIV(),exp2 = e2),coeff) // pow(a/b,n) * pow(b/a,m) = pow(a/b,n-m)
3049 guard if Expression.isOne(e1) then ExpressionBasics.expEqual(inExp, e2) else ExpressionBasics.expEqual(inExp, DAE.BINARY(e2, op, e1))
3050 39 then
3051 (outReal - coeff, outTplExpRealLst);
3052
3053 else /* not ExpressionBasics.expEqual */
3054 (outReal, tplExpReal :: outTplExpRealLst);
3055 end match;
3056
3057 end for;
3058
3059 7761898 outTplExpRealLst := listReverse(outTplExpRealLst);
3060 end simplifyMulJoinFactorsFind;
3061
3062 protected function simplifyMulMakePow
3063 "author: PA
3064 Helper function to simplifyMul.
3065 Makes each item in the list into a pow
3066 expression, except when exponent is 1.0."
3067 input list<tuple<DAE.Exp, Real>> inTplExpRealLst;
3068 output list<DAE.Exp> outExpLst = {};
3069 protected
3070 tuple<DAE.Exp, Real> tplExpReal;
3071 DAE.Exp e;
3072 Real r;
3073 algorithm
3074
2/2
✓ Branch 0 taken 7761898 times.
✓ Branch 1 taken 4152079 times.
11913977 for tplExpReal in inTplExpRealLst loop
3075
2/2
✓ Branch 0 taken 7663044 times.
✓ Branch 1 taken 98854 times.
7761898 (e,r) := tplExpReal;
3076
2/2
✓ Branch 0 taken 7663044 times.
✓ Branch 1 taken 98854 times.
7761898 outExpLst := if r == 1.0 then e :: outExpLst else DAE.BINARY(e,DAE.POW(DAE.T_REAL_DEFAULT),DAE.RCONST(r)) :: outExpLst;
3077 end for;
3078 end simplifyMulMakePow;
3079
3080 protected function simplifyAdd
3081 "author: PA
3082 Simplifies terms like 2a+4b+2a+a+b"
3083 input list<DAE.Exp> inExpLst;
3084 output list<DAE.Exp> outExpLst;
3085 protected
3086 list<tuple<DAE.Exp, Real>> coeffs;
3087 algorithm
3088 try
3089 1224883 coeffs := List.map(inExpLst, simplifyBinaryAddCoeff2);
3090 1224883 coeffs := simplifyAddJoinTerms(coeffs);
3091 1224883 outExpLst := simplifyAddMakeMul(coeffs);
3092 else
3093 ✗ if Flags.isSet(Flags.FAILTRACE) then
3094 ✗ Debug.trace("- ExpressionSimplify.simplifyAdd failed\n");
3095 end if;
3096 ✗ fail();
3097 end try;
3098 end simplifyAdd;
3099
3100 protected function simplifyAddJoinTerms
3101 "O(n)
3102 author: PA
3103 Helper function to simplifyAdd.
3104 Join all terms with the same expression.
3105 i.e. 2a+4a gives an element (a,6) in the list."
3106 input list<tuple<DAE.Exp, Real>> inTplExpRealLst;
3107 output list<tuple<DAE.Exp, Real>> outTplExpRealLst;
3108 protected
3109 function addCoeff
3110 input Option<Real> oldCoeff;
3111 input Real newCoeff;
3112 output Real coeff;
3113 algorithm
3114
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 162081 times.
✓ Branch 2 taken 471 times.
✓ Branch 3 taken 161610 times.
162081 coeff := if isSome(oldCoeff) then Util.getOption(oldCoeff) + newCoeff else newCoeff;
3115 end addCoeff;
3116 algorithm
3117 outTplExpRealLst := match inTplExpRealLst
3118 local
3119 DAE.Exp exp1, exp2, exp3;
3120 Real coeff1, coeff2, coeff3;
3121 UnorderedMap<DAE.Exp, Real> coeff_map;
3122
3123 // explicitly roll out the small cases since they happen a lot
3124 case {} then {};
3125 case {_} then inTplExpRealLst;
3126
3127 case {(exp1, coeff1), (exp2, coeff2)}
3128
2/2
✓ Branch 1 taken 184 times.
✓ Branch 2 taken 1120275 times.
1120459 then if ExpressionBasics.expEqual(exp1, exp2) then {(exp1, coeff1 + coeff2)} else inTplExpRealLst;
3129
3130 case {(exp1, coeff1), (exp2, coeff2), (exp3, coeff3)} algorithm
3131
2/2
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 72963 times.
73016 if ExpressionBasics.expEqual(exp1, exp2) then
3132
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
53 if ExpressionBasics.expEqual(exp1, exp3) then
3133 ✗ outTplExpRealLst := {(exp1, coeff1 + coeff2 + coeff3)};
3134 else
3135 53 outTplExpRealLst := {(exp1, coeff1 + coeff2), (exp3, coeff3)};
3136 end if;
3137 elseif ExpressionBasics.expEqual(exp1, exp3) then
3138 1439 outTplExpRealLst := {(exp1, coeff1 + coeff3), (exp2, coeff2)};
3139 elseif ExpressionBasics.expEqual(exp2, exp3) then
3140 76 outTplExpRealLst := {(exp1, coeff1), (exp2, coeff2 + coeff3)};
3141 else
3142 outTplExpRealLst := inTplExpRealLst;
3143 end if;
3144 then outTplExpRealLst;
3145
3146 // general case, this is O(n) but has a small overhead
3147 else algorithm
3148 31408 coeff_map := UnorderedMap.new<Real>(ExpressionBasics.hashExp, ExpressionBasics.expEqual, listLength(inTplExpRealLst));
3149
2/2
✓ Branch 0 taken 162081 times.
✓ Branch 1 taken 31408 times.
193489 for tpl in inTplExpRealLst loop
3150 162081 (exp1, coeff1) := tpl;
3151 // set the coefficient of exp1 to coeff1, add the previous coefficient if exp1 is already in the map
3152 162081 UnorderedMap.addUpdate(exp1, function addCoeff(newCoeff = coeff1), coeff_map);
3153 end for;
3154 31408 then UnorderedMap.toList(coeff_map);
3155 end match;
3156 end simplifyAddJoinTerms;
3157
3158 protected function simplifyAddMakeMul
3159 "author: PA
3160 Makes multiplications of each element
3161 in the list, except for coefficient 1.0"
3162 input list<tuple<DAE.Exp, Real>> inTplExpRealLst;
3163 output list<DAE.Exp> outExpLst = {};
3164 algorithm
3165
4/4
✓ Branch 0 taken 2619824 times.
✓ Branch 1 taken 1224883 times.
✓ Branch 2 taken 2619824 times.
✓ Branch 3 taken 1224883 times.
3844707 outExpLst := list(match tplExpReal
3166 local
3167 DAE.Exp e;
3168 Real r;
3169 case (e, 1.0) then e;
3170 385357 case (e, -1.0) then Expression.negate(e);
3171 case (e, r)
3172 then match Expression.typeof(e)
3173 44 case DAE.T_INTEGER() then DAE.BINARY(DAE.ICONST(realInt(r)), DAE.MUL(DAE.T_INTEGER_DEFAULT), e);
3174 461169 else DAE.BINARY(DAE.RCONST(r), DAE.MUL(DAE.T_REAL_DEFAULT), e);
3175 end match;
3176 end match for tplExpReal in inTplExpRealLst);
3177 end simplifyAddMakeMul;
3178
3179 protected function simplifyBinaryAddCoeff2
3180 "This function checks for x+x+x+x and returns (x,4.0)"
3181 input DAE.Exp inExp;
3182 output tuple<DAE.Exp, Real> outRes;
3183 algorithm
3184 outRes := match inExp
3185 local
3186 DAE.Exp exp,e1,e2;
3187 Real coeff,coeff_1;
3188 Integer icoeff;
3189
3190 871733 case DAE.CREF() then ((inExp,1.0));
3191
3192 case DAE.UNARY(operator = DAE.UMINUS(ty = DAE.T_REAL()), exp = exp)
3193 algorithm
3194 385708 (exp,coeff) := simplifyBinaryAddCoeff2(exp);
3195 385708 coeff := realMul(-1.0,coeff);
3196 385708 then ((exp,coeff));
3197
3198 case DAE.BINARY(exp1 = DAE.RCONST(real = coeff),operator = DAE.MUL(),exp2 = e1)
3199 451065 then ((e1,coeff));
3200
3201 case DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = DAE.RCONST(real = coeff))
3202 8397 then ((e1,coeff));
3203
3204 case DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = DAE.ICONST(integer = icoeff))
3205 algorithm
3206 6 coeff_1 := intReal(icoeff);
3207 6 then
3208 ((e1,coeff_1));
3209
3210 case DAE.BINARY(exp1 = DAE.ICONST(integer = icoeff),operator = DAE.MUL(),exp2 = e1)
3211 algorithm
3212 38 coeff_1 := intReal(icoeff);
3213 38 then
3214 ((e1,coeff_1));
3215
3216 case DAE.BINARY(exp1 = e1,operator = DAE.ADD(),exp2 = e2)
3217 guard
3218 ExpressionBasics.expEqual(e1, e2)
3219 ✗ then
3220 ((e1,2.0));
3221
3222 1290808 else ((inExp,1.0));
3223
3224 end match;
3225 end simplifyBinaryAddCoeff2;
3226
3227 protected function simplifyBinaryMulCoeff2
3228 "This function takes an expression XXXXX
3229 and return (X,5.0) to be used for X^5."
3230 input DAE.Exp inExp;
3231 output tuple<DAE.Exp, Real> outRes;
3232 algorithm
3233 outRes := match inExp
3234 local
3235 DAE.Exp e,e1,e2;
3236 Real coeff,coeff_1;
3237 Integer icoeff;
3238
3239 case e as DAE.CREF()
3240 4571935 then ((e,1.0));
3241
3242 case DAE.BINARY(exp1 = e1,operator = DAE.POW(),exp2 = DAE.RCONST(real = coeff))
3243 72274 then ((e1,coeff));
3244
3245 case DAE.BINARY(exp1 = e1,operator = DAE.POW(),exp2 = DAE.UNARY(operator = DAE.UMINUS(), exp = DAE.RCONST(real = coeff)))
3246 algorithm
3247 28033 coeff_1 := 0.0 - coeff;
3248 28033 then
3249 ((e1,coeff_1));
3250
3251 case DAE.BINARY(exp1 = e1, operator = DAE.POW(), exp2 = DAE.ICONST(integer = icoeff))
3252 algorithm
3253 ✗ coeff_1 := intReal(icoeff);
3254 ✗ then
3255 ((e1,coeff_1));
3256
3257 case DAE.BINARY(exp1 = e1, operator = DAE.POW(), exp2 = DAE.UNARY(operator = DAE.UMINUS(), exp = DAE.ICONST(integer = icoeff)))
3258 algorithm
3259 ✗ coeff_1 := 0.0 - intReal(icoeff);
3260 ✗ then
3261 ((e1,coeff_1));
3262
3263 case DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = e2)
3264 guard ExpressionBasics.expEqual(e1, e2)
3265 ✗ then
3266 ((e1,2.0));
3267
3268 3095384 else ((inExp,1.0));
3269
3270 end match;
3271 end simplifyBinaryMulCoeff2;
3272
3273 public function simplifySumOperatorExpression
3274 "
3275 In: (a/b + c + d + e/b)
3276 In: operator in {MUL, DIV}
3277 In: b
3278 -> (a/b + c + d) operator b
3279 Out: a' + e' + (c + b) operator b
3280
3281 where a' = simplified(a operator b) and e' = simplified(e operator b)
3282
3283 author: Vitalij Ruge
3284 "
3285 input DAE.Exp iSum;
3286 input DAE.Operator iop "MUL or DIV";
3287 input DAE.Exp iExp;
3288 output DAE.Exp oExp;
3289 protected
3290 list<DAE.Exp> T = Expression.termsExpandUnary(iSum);
3291 Boolean b "simplifed?";
3292 DAE.Exp e, newE, sE;
3293 DAE.Type tp = Expression.typeofOp(iop);
3294 algorithm
3295 59316 oExp := Expression.makeConstZero(tp);
3296 sE := oExp;
3297
3298
2/2
✓ Branch 0 taken 85193 times.
✓ Branch 1 taken 59316 times.
144509 for elem in T loop
3299 85193 e := DAE.BINARY(elem,iop,iExp);
3300 85193 newE := simplifyBinaryCoeff(e);
3301 85193 b := not ExpressionBasics.expEqual(e, newE);
3302
2/2
✓ Branch 0 taken 83855 times.
✓ Branch 1 taken 1338 times.
85193 if b then
3303 83855 sE := Expression.expAdd(sE, newE);
3304 else
3305 1338 oExp := Expression.expAdd(oExp, elem);
3306 end if;
3307 end for;
3308
3309 59316 e := DAE.BINARY(oExp, iop, iExp);
3310 59316 oExp := Expression.expAdd(sE, e);
3311
3312 end simplifySumOperatorExpression;
3313
3314
3315 protected function simplifyAsub0 "simplifies asub when expression already has been simplified with simplify1
3316 Earlier these cases were directly in simplify1, but now they are here so simplify1 only is called once for
3317 the subexpression"
3318 input DAE.Exp ie;
3319 input Integer sub;
3320 input DAE.Exp inSubExp;
3321 output DAE.Exp res;
3322 algorithm
3323 res := match ie
3324 local
3325 Type t,t1;
3326 Boolean b, bstart, bstop;
3327 list<DAE.Exp> exps;
3328 list<list<DAE.Exp>> mexps;
3329 list<DAE.Exp> mexpl;
3330 DAE.Exp e1,e2,cond,exp,e;
3331 Integer istart,istop,istep,ival;
3332 Real rstart,rstop,rstep,rval;
3333 DAE.ComponentRef c,c_1;
3334 Operator op;
3335
3336 // subscript of an array
3337 case DAE.ARRAY(_,_,exps)
3338 algorithm
3339 530157 exp := listGet(exps, sub);
3340 then
3341 exp;
3342
3343 case DAE.RANGE(start = DAE.BCONST(bstart), stop = DAE.BCONST(bstop))
3344 algorithm
3345 ✗ b := listGet(simplifyRangeBool(bstart, bstop), sub);
3346 ✗ then
3347 DAE.BCONST(b);
3348
3349 case DAE.RANGE(start = DAE.ICONST(istart), step = NONE(), stop = DAE.ICONST(istop))
3350 algorithm
3351 3 ival := listGet(simplifyRange(istart,1,istop),sub);
3352 3 exp := DAE.ICONST(ival);
3353 then exp;
3354
3355 case DAE.RANGE(start = DAE.ICONST(istart), step = SOME(DAE.ICONST(istep)), stop = DAE.ICONST(istop))
3356 algorithm
3357 5 ival := listGet(simplifyRange(istart,istep,istop),sub);
3358 5 exp := DAE.ICONST(ival);
3359 then exp;
3360
3361 case DAE.RANGE(start = DAE.RCONST(rstart), step = NONE(), stop = DAE.RCONST(rstop))
3362 algorithm
3363 7 rval := listGet(simplifyRangeReal(rstart,1.0,rstop),sub);
3364 7 exp := DAE.RCONST(rval);
3365 then exp;
3366
3367 case DAE.RANGE(start = DAE.RCONST(rstart), step = SOME(DAE.RCONST(rstep)), stop = DAE.RCONST(rstop))
3368 algorithm
3369 4 rval := listGet(simplifyRangeReal(rstart,rstep,rstop),sub);
3370 4 exp := DAE.RCONST(rval);
3371 then exp;
3372
3373 // subscript of a matrix
3374 case DAE.MATRIX(t,_,mexps)
3375 algorithm
3376 168688 t1 := Expression.unliftArray(t);
3377 168688 mexpl := listGet(mexps, sub);
3378 168688 then
3379 DAE.ARRAY(t1,true,mexpl);
3380
3381 // subscript of an if-expression
3382 case DAE.IFEXP(cond,e1,e2)
3383 algorithm
3384 769 e1 := Expression.makeASUB(e1,{inSubExp});
3385 769 e2 := Expression.makeASUB(e2,{inSubExp});
3386 769 e := DAE.IFEXP(cond,e1,e2);
3387 then
3388 e;
3389
3390 // name subscript
3391 case DAE.CREF(c,t)
3392 algorithm
3393
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 53161 times.
53161 true := Types.isArray(t);
3394 53161 t := Expression.unliftArray(t);
3395 53161 c_1 := simplifyAsubCref(c, inSubExp);
3396 53161 exp := Expression.makeCrefExp(c_1, t);
3397 then
3398 exp;
3399
3400 // BINARAY
3401 case DAE.BINARY(e1,op,e2)
3402 guard Expression.isMulOrDiv(op) or Expression.isAddOrSub(op)
3403 algorithm
3404 5978 e1 := Expression.makeASUB(e1,{inSubExp});
3405 5978 e2 := Expression.makeASUB(e2,{inSubExp});
3406 //wrap operator
3407
4/6
✗ Branch 1 not taken.
✓ Branch 2 taken 5978 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5978 times.
✓ Branch 9 taken 4884 times.
✓ Branch 10 taken 1094 times.
5978 e := if Expression.isMul(op) then
3408 Expression.expMul(e1,e2)
3409 elseif Expression.isDiv(op) then
3410 Expression.makeDiv(e1,e2)
3411 elseif Expression.isAdd(op) then
3412 Expression.expAdd(e1,e2)
3413 else
3414 Expression.expSub(e1,e2);
3415 then
3416 e;
3417
3418 end match;
3419 end simplifyAsub0;
3420
3421 protected function simplifyAsubCref
3422 input DAE.ComponentRef cr;
3423 input DAE.Exp sub;
3424 output DAE.ComponentRef res;
3425 algorithm
3426 res := matchcontinue cr
3427 local
3428 Type t2;
3429 DAE.ComponentRef c,c_1;
3430 list<Subscript> s,s_1;
3431 String idn;
3432 DAE.Dimensions dims;
3433
3434 // simple name subscript
3435 case DAE.CREF_IDENT(idn,t2,s)
3436 algorithm
3437 /* TODO: Make sure that the IDENT has enough dimensions? */
3438 53161 s_1 := Expression.subscriptsAppend(s, sub);
3439 53161 c_1 := ComponentReferenceBasics.makeCrefIdent(idn,t2,s_1);
3440 then
3441 c_1;
3442
3443 // qualified name subscript
3444 case DAE.CREF_QUAL(idn,t2 as DAE.T_ARRAY(dims=dims),s,c)
3445 algorithm
3446
1/2
✓ Branch 2 taken 8656 times.
✗ Branch 3 not taken.
8656 true := listLength(dims) > listLength(s);
3447 ✗ s_1 := Expression.subscriptsAppend(s, sub);
3448 ✗ c_1 := ComponentReferenceBasics.makeCrefQual(idn,t2,s_1,c);
3449 then
3450 c_1;
3451
3452 case DAE.CREF_QUAL(idn, t2, s, c)
3453 algorithm
3454 175864 s := Expression.subscriptsReplaceSlice(s, DAE.INDEX(sub));
3455 ✗ then
3456 ComponentReferenceBasics.makeCrefQual(idn, t2, s, c);
3457
3458 case DAE.CREF_QUAL(idn,t2,s,c)
3459 algorithm
3460 175864 c_1 := simplifyAsubCref(c,sub);
3461 175864 c_1 := ComponentReferenceBasics.makeCrefQual(idn,t2,s,c_1);
3462 then
3463 c_1;
3464
3465 end matchcontinue;
3466 end simplifyAsubCref;
3467
3468 protected function simplifyAsub
3469 "This function simplifies array subscripts on vector operations"
3470 input DAE.Exp inExp;
3471 input DAE.Exp inSub;
3472 output DAE.Exp outExp;
3473 algorithm
3474 outExp := matchcontinue (inExp,inSub)
3475 local
3476 DAE.Exp e_1,e,e1_1,e2_1,e1,e2,exp,cond,sub;
3477 Type t,t_1,t2;
3478 Integer indx;
3479 Operator op,op2;
3480 Boolean b;
3481 list<DAE.Exp> exps,expl;
3482 list<list<DAE.Exp>> lstexps;
3483 list<DAE.ReductionIterator> iters;
3484 DAE.ReductionIterator iter;
3485
3486 case (e,sub)
3487 algorithm
3488 905884 exp := simplifyAsub0(e,Expression.expInt(sub), inSub);
3489 then
3490 exp;
3491
3492 case (DAE.UNARY(operator = DAE.UMINUS_ARR(),exp = e),sub)
3493 algorithm
3494 7182 e_1 := simplifyAsub(e, sub);
3495 ✗ t2 := Expression.typeof(e_1);
3496 ✗ b := DAEUtil.expTypeArray(t2);
3497 ✗ op2 := if b then DAE.UMINUS_ARR(t2) else DAE.UMINUS(t2);
3498 ✗ exp := DAE.UNARY(op2,e_1);
3499 then
3500 exp;
3501
3502 case (DAE.LUNARY(operator = DAE.NOT(), exp = e), sub)
3503 algorithm
3504 ✗ e_1 := simplifyAsub(e, sub);
3505 ✗ t2 := Expression.typeof(e_1);
3506 ✗ exp := DAE.LUNARY(DAE.NOT(t2), e_1);
3507 then
3508 exp;
3509
3510 case (DAE.BINARY(exp1 = e1,operator = DAE.SUB_ARR(),exp2 = e2),sub)
3511 algorithm
3512 ✗ e1_1 := simplifyAsub(e1, sub);
3513 ✗ e2_1 := simplifyAsub(e2, sub);
3514 ✗ t2 := Expression.typeof(e1_1);
3515 ✗ b := DAEUtil.expTypeArray(t2);
3516 ✗ op2 := if b then DAE.SUB_ARR(t2) else DAE.SUB(t2);
3517 ✗ exp := DAE.BINARY(e1_1,op2,e2_1);
3518 then
3519 exp;
3520
3521 case (DAE.BINARY(exp1 = e1,operator = DAE.MUL_ARRAY_SCALAR(),exp2 = e2),sub)
3522 algorithm
3523 1143 e1_1 := simplifyAsub(e1, sub);
3524 732 t2 := Expression.typeof(e1_1);
3525 732 b := DAEUtil.expTypeArray(t2);
3526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 732 times.
732 op := if b then DAE.MUL_ARRAY_SCALAR(t2) else DAE.MUL(t2);
3527 732 exp := DAE.BINARY(e1_1,op,e2);
3528 then
3529 exp;
3530
3531 case (DAE.BINARY(exp1 = e1,operator = DAE.ADD_ARRAY_SCALAR(),exp2 = e2),sub)
3532 algorithm
3533 ✗ e1_1 := simplifyAsub(e1, sub);
3534 ✗ t2 := Expression.typeof(e1_1);
3535 ✗ b := DAEUtil.expTypeArray(t2);
3536 ✗ op := if b then DAE.ADD_ARRAY_SCALAR(t2) else DAE.ADD(t2);
3537 ✗ exp := DAE.BINARY(e1_1,op,e2);
3538 then
3539 exp;
3540
3541 case (DAE.BINARY(exp1 = e1,operator = DAE.SUB_SCALAR_ARRAY(),exp2 = e2),sub)
3542 algorithm
3543 ✗ e2_1 := simplifyAsub(e2, sub);
3544 ✗ t2 := Expression.typeof(e2_1);
3545 ✗ b := DAEUtil.expTypeArray(t2);
3546 ✗ op := if b then DAE.SUB_SCALAR_ARRAY(t2) else DAE.SUB(t2);
3547 ✗ exp := DAE.BINARY(e1,op,e2_1);
3548 then
3549 exp;
3550
3551 // For Matrix product M1 * M2
3552 case (DAE.BINARY(exp1 = e1,operator = DAE.MUL_MATRIX_PRODUCT(),exp2 = e2),sub)
3553 algorithm
3554 594 e := simplifyMatrixProduct(e1,e2);
3555 ✗ e := simplifyAsub(e, sub);
3556 then
3557 e;
3558
3559 case (DAE.BINARY(exp1 = e1,operator = DAE.DIV_SCALAR_ARRAY(),exp2 = e2),sub)
3560 algorithm
3561 ✗ e2_1 := simplifyAsub(e2, sub);
3562 ✗ t2 := Expression.typeof(e2_1);
3563 ✗ b := DAEUtil.expTypeArray(t2);
3564 ✗ op := if b then DAE.DIV_SCALAR_ARRAY(t2) else DAE.DIV(t2);
3565 ✗ exp := DAE.BINARY(e1,op,e2_1);
3566 then
3567 exp;
3568
3569 case (DAE.BINARY(exp1 = e1,operator = DAE.DIV_ARRAY_SCALAR(),exp2 = e2),sub)
3570 algorithm
3571 42 e1_1 := simplifyAsub(e1, sub);
3572 42 t2 := Expression.typeof(e1_1);
3573 42 b := DAEUtil.expTypeArray(t2);
3574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 op := if b then DAE.DIV_ARRAY_SCALAR(t2) else DAE.DIV(t2);
3575 42 exp := DAE.BINARY(e1_1,op,e2);
3576 then
3577 exp;
3578
3579 case (DAE.BINARY(exp1 = e1,operator = DAE.POW_SCALAR_ARRAY(),exp2 = e2),sub)
3580 algorithm
3581 ✗ e2_1 := simplifyAsub(e2, sub);
3582 ✗ t2 := Expression.typeof(e2_1);
3583 ✗ b := DAEUtil.expTypeArray(t2);
3584 ✗ op := if b then DAE.POW_SCALAR_ARRAY(t2) else DAE.POW(t2);
3585 ✗ exp := DAE.BINARY(e1,op,e2_1);
3586 then
3587 exp;
3588
3589 case (DAE.BINARY(exp1 = e1,operator = DAE.POW_ARRAY_SCALAR(),exp2 = e2),sub)
3590 algorithm
3591 ✗ e1_1 := simplifyAsub(e1, sub);
3592 ✗ t2 := Expression.typeof(e1_1);
3593 ✗ b := DAEUtil.expTypeArray(t2);
3594 ✗ op := if b then DAE.POW_ARRAY_SCALAR(t2) else DAE.POW(t2);
3595 ✗ exp := DAE.BINARY(e1_1,op,e2);
3596 then
3597 exp;
3598
3599 case (DAE.BINARY(exp1 = e1,operator = DAE.ADD_ARR(),exp2 = e2),sub)
3600 algorithm
3601 ✗ e1_1 := simplifyAsub(e1, sub);
3602 ✗ e2_1 := simplifyAsub(e2, sub);
3603 ✗ t2 := Expression.typeof(e1_1);
3604 ✗ b := DAEUtil.expTypeArray(t2);
3605 ✗ op2 := if b then DAE.ADD_ARR(t2) else DAE.ADD(t2);
3606 ✗ exp := DAE.BINARY(e1_1,op2,e2_1);
3607 then
3608 exp;
3609
3610 case (DAE.BINARY(exp1 = e1,operator = DAE.MUL_ARR(),exp2 = e2),sub)
3611 algorithm
3612 ✗ e1_1 := simplifyAsub(e1, sub);
3613 ✗ e2_1 := simplifyAsub(e2, sub);
3614 ✗ t2 := Expression.typeof(e1_1);
3615 ✗ b := DAEUtil.expTypeArray(t2);
3616 ✗ op2 := if b then DAE.MUL_ARR(t2) else DAE.MUL(t2);
3617 ✗ exp := DAE.BINARY(e1_1,op2,e2_1);
3618 then
3619 exp;
3620
3621 case (DAE.BINARY(exp1 = e1,operator = DAE.DIV_ARR(),exp2 = e2),sub)
3622 algorithm
3623 ✗ e1_1 := simplifyAsub(e1, sub);
3624 ✗ e2_1 := simplifyAsub(e2, sub);
3625 ✗ t2 := Expression.typeof(e1_1);
3626 ✗ b := DAEUtil.expTypeArray(t2);
3627 ✗ op2 := if b then DAE.DIV_ARR(t2) else DAE.DIV(t2);
3628 ✗ exp := DAE.BINARY(e1_1,op2,e2_1);
3629 then
3630 exp;
3631
3632 case (DAE.BINARY(exp1 = e1,operator = DAE.POW_ARR2(),exp2 = e2),sub)
3633 algorithm
3634 ✗ e1_1 := simplifyAsub(e1, sub);
3635 ✗ e2_1 := simplifyAsub(e2, sub);
3636 ✗ t2 := Expression.typeof(e1_1);
3637 ✗ b := DAEUtil.expTypeArray(t2);
3638 ✗ op2 := if b then DAE.POW_ARR2(t2) else DAE.POW(t2);
3639 ✗ exp := DAE.BINARY(e1_1,op2,e2_1);
3640 then
3641 exp;
3642
3643 case (DAE.LBINARY(exp1 = e1, operator = op, exp2 = e2), sub)
3644 algorithm
3645 ✗ e1_1 := simplifyAsub(e1, sub);
3646 ✗ e2_1 := simplifyAsub(e2, sub);
3647 ✗ t2 := Expression.typeof(e1_1);
3648 ✗ op := Expression.setOpType(op, t2);
3649 ✗ exp := DAE.LBINARY(e1_1, op, e2_1);
3650 then
3651 exp;
3652
3653 case (DAE.ARRAY(array = exps),sub)
3654 algorithm
3655 3 indx := Expression.expInt(sub);
3656 3 exp := listGet(exps, indx);
3657 then
3658 exp;
3659
3660 case (DAE.MATRIX(ty = t,matrix = lstexps),sub)
3661 algorithm
3662 ✗ indx := Expression.expInt(sub);
3663 ✗ expl := listGet(lstexps, indx);
3664 ✗ t_1 := Expression.unliftArray(t);
3665 ✗ then DAE.ARRAY(t_1,true,expl);
3666
3667 case(DAE.IFEXP(cond,e1,e2),sub)
3668 algorithm
3669 ✗ e1_1 := simplifyAsub(e1, sub);
3670 ✗ e2_1 := simplifyAsub(e2, sub);
3671 ✗ then DAE.IFEXP(cond,e1_1,e2_1);
3672
3673 case(DAE.REDUCTION(DAE.REDUCTIONINFO(path=Absyn.IDENT("array"),iterType=Absyn.THREAD()),exp,iters), sub)
3674 algorithm
3675 ✗ exp := List.fold1(iters,simplifyAsubArrayReduction,sub,exp);
3676 then exp;
3677
3678 case(DAE.REDUCTION(DAE.REDUCTIONINFO(path=Absyn.IDENT("array"),iterType=Absyn.COMBINE()),exp,{iter}), sub)
3679 algorithm
3680 ✗ exp := simplifyAsubArrayReduction(iter,sub,exp);
3681 then exp;
3682
3683 end matchcontinue;
3684 end simplifyAsub;
3685
3686 protected function simplifyAsubArrayReduction
3687 input DAE.ReductionIterator iter;
3688 input DAE.Exp sub;
3689 input DAE.Exp acc;
3690 output DAE.Exp res;
3691 algorithm
3692 res := match iter
3693 local
3694 DAE.Exp exp;
3695 String id;
3696 case DAE.REDUCTIONITER(id=id,exp=exp,guardExp=NONE())
3697 algorithm
3698 ✗ exp := Expression.makeASUB(exp, {sub});
3699 ✗ exp := replaceIteratorWithExp(exp, acc, id);
3700 then exp;
3701 end match;
3702 end simplifyAsubArrayReduction;
3703
3704 protected function simplifyAsubOperator
3705 input DAE.Exp inExp1;
3706 input Operator inOperator2;
3707 input Operator inOperator3;
3708 output Operator outOperator;
3709 algorithm
3710 outOperator:=
3711 match inExp1
3712 case DAE.ARRAY() then inOperator3;
3713 case DAE.MATRIX() then inOperator3;
3714 case DAE.RANGE() then inOperator3;
3715 else inOperator2;
3716 end match;
3717 end simplifyAsubOperator;
3718
3719 protected function simplifyAsubSlicing
3720 "Simplifies asubs where some of the subscripts are slices.
3721 Ex: x[i, 1:3] => {x[i, 1], x[i, 2], x[i, 3]}"
3722 input DAE.Exp inExp;
3723 input list<DAE.Exp> inSubscripts;
3724 output DAE.Exp outAsubArray;
3725 protected
3726 list<list<DAE.Exp>> indices;
3727 list<DAE.Exp> asubs, es;
3728 Boolean didSplit=false,b;
3729 algorithm
3730 // Expand the subscripts.
3731
7/8
✓ Branch 0 taken 923045 times.
✓ Branch 1 taken 902265 times.
✓ Branch 2 taken 923045 times.
✓ Branch 3 taken 902265 times.
✓ Branch 6 taken 923045 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 922972 times.
✓ Branch 9 taken 73 times.
2748355 indices := list(match () case () algorithm (es,b) := Expression.splitArray(simplify1(e)); didSplit := didSplit or b; then es; end match for e in inSubscripts);
3732 // We don't want to loop forever... So keep track of if we actually expanded something
3733
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 902192 times.
902265 true := didSplit;
3734
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 73 times.
167 for is in indices loop
3735
2/2
✓ Branch 1 taken 157 times.
✓ Branch 2 taken 94 times.
251 for i in is loop
3736 // Make sure all asubs are scalar (were split by splitArray; no function calls or weird stuff left)
3737 () := match Expression.typeof(i)
3738 case DAE.T_INTEGER() then ();
3739 case DAE.T_BOOL() then ();
3740 case DAE.T_ENUMERATION() then ();
3741 else fail();
3742 end match;
3743 end for;
3744 end for;
3745 // Make asubs from all combinations of the subscript indices.
3746 73 asubs := List.combinationMap(indices, function simplifyAsubSlicing2(inExp = inExp));
3747 73 outAsubArray := Expression.makeScalarArray(asubs, Types.unliftArray(Expression.typeof(inExp)));
3748 end simplifyAsubSlicing;
3749
3750 protected function simplifyAsubSlicing2
3751 input list<DAE.Exp> inSubscripts;
3752 input DAE.Exp inExp;
3753 output DAE.Exp outAsub;
3754 algorithm
3755 136 outAsub := Expression.makeASUB(inExp, inSubscripts);
3756 end simplifyAsubSlicing2;
3757
3758 protected function simplifyBinaryConst
3759 "This function evaluates constant binary expressions."
3760 input Operator inOperator1;
3761 input DAE.Exp inExp2;
3762 input DAE.Exp inExp3;
3763 output DAE.Exp outExp;
3764 algorithm
3765 outExp := match (inOperator1,inExp2,inExp3)
3766 local
3767 Integer ie1,ie2;
3768 Real e2_1,e1_1;
3769 DAE.Exp val;
3770 Real re1,re2,re3;
3771 String str,s1,s2;
3772
3773 case (DAE.ADD(),DAE.ICONST(integer = ie1),DAE.ICONST(integer = ie2))
3774 algorithm
3775 9862 val := safeIntOp(ie1,ie2,ExpressionSimplifyTypes.ADDOP());
3776 then val;
3777
3778 case (DAE.ADD(),DAE.RCONST(real = re1),DAE.RCONST(real = re2))
3779 algorithm
3780 26955 re3 := re1 + re2;
3781 26955 then DAE.RCONST(re3);
3782
3783 case (DAE.ADD(),DAE.RCONST(real = re1),DAE.ICONST(integer = ie2))
3784 algorithm
3785 ✗ e2_1 := intReal(ie2);
3786 ✗ re3 := re1 + e2_1;
3787 ✗ then DAE.RCONST(re3);
3788
3789 case (DAE.ADD(),DAE.ICONST(integer = ie1),DAE.RCONST(real = re2))
3790 algorithm
3791 ✗ e1_1 := intReal(ie1);
3792 ✗ re3 := e1_1 + re2;
3793 ✗ then DAE.RCONST(re3);
3794
3795 case (DAE.ADD(),DAE.SCONST(string = s1),DAE.SCONST(string = s2))
3796 algorithm
3797 2655 str := s1 + s2;
3798 2655 then DAE.SCONST(str);
3799
3800 case (DAE.SUB(),DAE.ICONST(integer = ie1),DAE.ICONST(integer = ie2))
3801 algorithm
3802 6627 val := safeIntOp(ie1,ie2,ExpressionSimplifyTypes.SUBOP());
3803 then val;
3804
3805 case (DAE.SUB(),DAE.RCONST(real = re1),DAE.RCONST(real = re2))
3806 algorithm
3807 469705 re3 := re1 - re2;
3808 469705 then DAE.RCONST(re3);
3809
3810 case (DAE.SUB(),DAE.RCONST(real = re1),DAE.ICONST(integer = ie2))
3811 algorithm
3812 33 e2_1 := intReal(ie2);
3813 33 re3 := re1 - e2_1;
3814 33 then DAE.RCONST(re3);
3815
3816 case (DAE.SUB(),DAE.ICONST(integer = ie1),DAE.RCONST(real = re2))
3817 algorithm
3818 2 e1_1 := intReal(ie1);
3819 2 re3 := e1_1 - re2;
3820 2 then DAE.RCONST(re3);
3821
3822 case (DAE.MUL(),DAE.ICONST(integer = ie1),DAE.ICONST(integer = ie2))
3823 algorithm
3824 305 val := safeIntOp(ie1,ie2,ExpressionSimplifyTypes.MULOP());
3825 then val;
3826
3827 case (DAE.MUL(),DAE.RCONST(real = re1),DAE.RCONST(real = re2))
3828 algorithm
3829 65981 re3 := re1 * re2;
3830 65981 then DAE.RCONST(re3);
3831
3832 case (DAE.MUL(),DAE.RCONST(real = re1),DAE.ICONST(integer = ie2))
3833 algorithm
3834 ✗ e2_1 := intReal(ie2);
3835 ✗ re3 := re1 * e2_1;
3836 ✗ then DAE.RCONST(re3);
3837
3838 case (DAE.MUL(),DAE.ICONST(integer = ie1),DAE.RCONST(real = re2))
3839 algorithm
3840 ✗ e1_1 := intReal(ie1);
3841 ✗ re3 := e1_1 * re2;
3842 ✗ then DAE.RCONST(re3);
3843
3844 case (DAE.DIV(),DAE.ICONST(integer = ie1),DAE.ICONST(integer = ie2))
3845 algorithm
3846 ✗ val := safeIntOp(ie1,ie2,ExpressionSimplifyTypes.DIVOP());
3847 then val;
3848
3849 case (DAE.DIV(),DAE.RCONST(real = re1),DAE.RCONST(real = re2))
3850 algorithm
3851
2/2
✓ Branch 0 taken 3826 times.
✓ Branch 1 taken 34038 times.
37864 re3 := re1 / re2;
3852 34038 then DAE.RCONST(re3);
3853
3854 case (DAE.DIV(),DAE.RCONST(real = re1),DAE.ICONST(integer = ie2))
3855 algorithm
3856 ✗ e2_1 := intReal(ie2);
3857 ✗ re3 := re1 / e2_1;
3858 ✗ then DAE.RCONST(re3);
3859
3860 case (DAE.DIV(),DAE.ICONST(integer = ie1),DAE.RCONST(real = re2))
3861 algorithm
3862 18 e1_1 := intReal(ie1);
3863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 re3 := e1_1 / re2;
3864 18 then DAE.RCONST(re3);
3865
3866 case (DAE.POW(),DAE.RCONST(real = re1),DAE.RCONST(real = re2))
3867 algorithm
3868
8/22
✓ Branch 0 taken 1110 times.
✓ Branch 1 taken 22109 times.
✓ Branch 2 taken 1110 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1110 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1110 times.
✓ Branch 8 taken 1110 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 23219 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 23219 times.
23219 re3 := re1 ^ re2;
3869 23219 then DAE.RCONST(re3);
3870
3871 end match;
3872 end simplifyBinaryConst;
3873
3874
3875 protected function simplifyRelationConst
3876 "This function evaluates constant binary expressions."
3877 input Operator op;
3878 input DAE.Exp e1;
3879 input DAE.Exp e2;
3880 output Boolean b;
3881 algorithm
3882 b := match (op,e1,e2)
3883 local
3884 Real v1,v2;
3885 Boolean b1,b2;
3886 String s1,s2;
3887 // Relation operations
3888 case(DAE.LESS(),DAE.BCONST(false),DAE.BCONST(true))
3889 then true;
3890
3891 case(DAE.LESS(),DAE.BCONST(_),DAE.BCONST(_))
3892 then false;
3893
3894 case(DAE.LESS(),_,_)
3895 algorithm
3896 1318 v1 := Expression.toReal(e1);
3897 1318 v2 := Expression.toReal(e2);
3898 1318 b := v1 < v2;
3899 then b;
3900
3901 case(DAE.LESSEQ(),DAE.BCONST(true),DAE.BCONST(false))
3902 then false;
3903
3904 case(DAE.LESSEQ(),DAE.BCONST(_),DAE.BCONST(_))
3905 then true;
3906
3907 case(DAE.LESSEQ(),_,_)
3908 algorithm
3909 2840 v1 := Expression.toReal(e1);
3910 2840 v2 := Expression.toReal(e2);
3911 2840 b := v1 <= v2;
3912 then b;
3913
3914 case(DAE.EQUAL(),DAE.BCONST(b1),DAE.BCONST(b2))
3915 5 then boolEq(b1,b2);
3916
3917 case(DAE.EQUAL(),DAE.SCONST(s1),DAE.SCONST(s2))
3918
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
16 then stringEqual(s1,s2);
3919
3920 case(DAE.EQUAL(),_,_)
3921 algorithm
3922 7564 v1 := Expression.toReal(e1);
3923 7564 v2 := Expression.toReal(e2);
3924 7564 then realEq(v1,v2);
3925
3926 // Express GT, GE, NE using LE, LT, EQ
3927 case (DAE.GREATER(),_,_)
3928 2293 then not simplifyRelationConst(DAE.LESSEQ(DAE.T_REAL_DEFAULT),e1,e2);
3929
3930 case (DAE.GREATEREQ(),_,_)
3931 391 then not simplifyRelationConst(DAE.LESS(DAE.T_REAL_DEFAULT),e1,e2);
3932
3933 case(DAE.GREATER(),DAE.BCONST(false),DAE.BCONST(true))
3934 ✗ then not simplifyRelationConst(DAE.LESSEQ(DAE.T_REAL_DEFAULT),e1,e2);
3935
3936 case(DAE.GREATEREQ(),DAE.BCONST(false),DAE.BCONST(true))
3937 ✗ then not simplifyRelationConst(DAE.LESS(DAE.T_REAL_DEFAULT),e1,e2);
3938
3939 case(DAE.NEQUAL(),_,_)
3940 988 then not simplifyRelationConst(DAE.EQUAL(DAE.T_REAL_DEFAULT),e1,e2);
3941 end match;
3942 end simplifyRelationConst;
3943
3944 public function safeIntOp
3945 "Safe mul, add, sub or pow operations for integers.
3946 The function returns an integer if possible, otherwise a real.
3947 "
3948 input Integer val1;
3949 input Integer val2;
3950 input ExpressionSimplifyTypes.IntOp op;
3951 output DAE.Exp outv;
3952 algorithm
3953 outv := match op
3954 local
3955 Real rv1,rv2,rv3;
3956 Integer ires;
3957
3958 case ExpressionSimplifyTypes.MULOP()
3959 algorithm
3960 15270 rv1 := intReal(val1);
3961 15270 rv2 := intReal(val2);
3962 15270 rv3 := rv1 * rv2;
3963 15270 outv := Expression.realToIntIfPossible(rv3);
3964 then
3965 outv;
3966
3967 case ExpressionSimplifyTypes.DIVOP()
3968 algorithm
3969 ✗ ires := intDiv(val1,val2);
3970 ✗ then
3971 DAE.ICONST(ires);
3972
3973 case ExpressionSimplifyTypes.SUBOP()
3974 algorithm
3975 6632 rv1 := intReal(val1);
3976 6632 rv2 := intReal(val2);
3977 6632 rv3 := rv1 - rv2;
3978 6632 outv := Expression.realToIntIfPossible(rv3);
3979 then
3980 outv;
3981
3982 case ExpressionSimplifyTypes.ADDOP()
3983 algorithm
3984 21347 rv1 := intReal(val1);
3985 21347 rv2 := intReal(val2);
3986 21347 rv3 := rv1 + rv2;
3987 21347 outv := Expression.realToIntIfPossible(rv3);
3988 then
3989 outv;
3990
3991 case ExpressionSimplifyTypes.POWOP()
3992 algorithm
3993 ✗ rv1 := intReal(val1);
3994 ✗ rv2 := intReal(val2);
3995 ✗ rv3 := realPow(rv1,rv2);
3996 ✗ outv := Expression.realToIntIfPossible(rv3);
3997 then
3998 outv;
3999 end match;
4000 end safeIntOp;
4001
4002 protected function simplifyBinaryCommutativeWork
4003 "This function simplifies commutative binary expressions."
4004 input Operator op;
4005 input DAE.Exp lhs;
4006 input DAE.Exp rhs;
4007 output DAE.Exp exp;
4008 algorithm
4009 exp := matchcontinue (op,lhs,rhs)
4010 local
4011 DAE.Exp e3,e4,e,e1,e2;
4012 Operator op1,op2;
4013 Type ty,tp,tp2;
4014 Real r1,r2;
4015 /* sin(2*x) = 2*sin(x)*cos(x) */
4016 case (DAE.MUL(_),DAE.CALL(path=Absyn.IDENT("sin"),expLst={e1}),DAE.CALL(path=Absyn.IDENT("cos"),expLst={e2}))
4017 guard ExpressionBasics.expEqual(e1,e2)
4018 algorithm
4019 op1 := DAE.MUL(DAE.T_REAL_DEFAULT);
4020 ✗ e := DAE.BINARY(DAE.RCONST(2.0),op1,e1);
4021 ✗ e := Expression.makePureBuiltinCall("sin",{e},DAE.T_REAL_DEFAULT);
4022 ✗ then DAE.BINARY(DAE.RCONST(0.5),op1,e);
4023
4024 /* sin^2(x)+cos^2(x) = 1 */
4025 case (DAE.ADD(_),DAE.BINARY(DAE.CALL(path=Absyn.IDENT("sin"),expLst={e1}),DAE.POW(DAE.T_REAL()),DAE.RCONST(real = 2.0)),
4026 DAE.BINARY(DAE.CALL(path=Absyn.IDENT("cos"),expLst={e2}),DAE.POW(DAE.T_REAL()),DAE.RCONST(real = 2.0)))
4027 guard ExpressionBasics.expEqual(e1,e2)
4028 then DAE.RCONST(1.0);
4029
4030 // tan(e)*cos(e) = sin(e)
4031 case(DAE.MUL(tp),DAE.CALL(path=Absyn.IDENT("tan"),expLst={e1}),DAE.CALL(path=Absyn.IDENT("cos"),expLst={e2}))
4032 guard ExpressionBasics.expEqual(e1,e2)
4033 ✗ then Expression.makePureBuiltinCall("sin",{e1},tp);
4034
4035 /* cosh^2(x)-sinh^2(x) = 1 */
4036 case (DAE.ADD(_),DAE.BINARY(DAE.CALL(path=Absyn.IDENT("cosh"),expLst={e1}),DAE.POW(DAE.T_REAL()),DAE.RCONST(real = 2.0)),
4037 DAE.UNARY(operator = DAE.UMINUS(),exp=DAE.BINARY(DAE.CALL(path=Absyn.IDENT("sinh"),expLst={e2}),DAE.POW(DAE.T_REAL()),DAE.RCONST(real = 2.0))))
4038 guard ExpressionBasics.expEqual(e1,e2)
4039 then DAE.RCONST(1.0);
4040
4041 // tanh(e)*cosh(e) = sinh(e)
4042 case(DAE.MUL(tp),DAE.CALL(path=Absyn.IDENT("tanh"),expLst={e1}),DAE.CALL(path=Absyn.IDENT("cosh"),expLst={e2}))
4043 guard ExpressionBasics.expEqual(e1,e2)
4044 ✗ then Expression.makePureBuiltinCall("sinh",{e1},tp);
4045
4046 // a+(-b)
4047 case (DAE.ADD(ty = tp),e1,DAE.UNARY(operator = DAE.UMINUS(),exp = e2))
4048 415226 then DAE.BINARY(e1,DAE.SUB(tp),e2);
4049
4050 // a + ((-b) op2 c) = a - (b op2 c)
4051 case (DAE.ADD(ty = tp),e1,DAE.BINARY(DAE.UNARY(operator = DAE.UMINUS(),exp = e2), op2, e3))
4052 guard Expression.isMulOrDiv(op2)
4053 235864 then DAE.BINARY(e1, DAE.SUB(tp), DAE.BINARY(e2,op2,e3));
4054
4055 // Commutative
4056 // (-a)+b = b + (-a)
4057 //case (DAE.ADD(ty = tp),DAE.UNARY(operator = DAE.UMINUS(ty = tp2),exp = e1),e2)
4058 // equation
4059 // e = DAE.BINARY(e2,DAE.SUB(tp),e1);
4060 // then e;
4061
4062 // 0+e => e
4063 case (DAE.ADD(),e1,e2)
4064 guard Expression.isZero(e1)
4065 then e2;
4066
4067 // e1*(e2/e3) => (e1e2)/e3
4068 case (DAE.MUL(ty = tp),e1,DAE.BINARY(exp1 = e2,operator = DAE.DIV(ty = tp2),exp2 = e3))
4069 algorithm
4070
2/2
✓ Branch 3 taken 383280 times.
✓ Branch 4 taken 95808 times.
479088 (e,true) := simplify1(DAE.BINARY(e1,DAE.MUL(tp),e2));
4071 95808 then DAE.BINARY(e,DAE.DIV(tp2),e3);
4072
4073 // 0 * a = 0
4074 case (DAE.MUL(),_,e2)
4075 guard Expression.isZero(e2)
4076 then e2;
4077
4078 // 1 * a = a
4079 case (DAE.MUL(),e1,e2)
4080 guard Expression.isConstOne(e2)
4081 then e1;
4082
4083 // -1 * a = -a
4084 case (DAE.MUL(ty = ty),e1,e2)
4085 guard Expression.isConstMinusOne(e2)
4086 28744 then DAE.UNARY(DAE.UMINUS(ty),e1);
4087
4088 // done in simplifyBinary
4089 // -a * -b = a * b
4090 //case (DAE.MUL(ty = ty),DAE.UNARY(operator = DAE.UMINUS(ty = ty1),exp = e1),DAE.UNARY(operator = DAE.UMINUS(ty = ty2),exp = e2))
4091 // equation
4092 // e = DAE.BINARY(e1,DAE.MUL(ty),e2);
4093 // then
4094 // e;
4095
4096 // (e * e1) * e => e1*e^2
4097 case (DAE.MUL(),DAE.BINARY(e2,op1 as DAE.MUL(ty),e3),e1)
4098 guard Types.isScalarReal(ty) and ExpressionBasics.expEqual(e2,e1)
4099 10791 then DAE.BINARY(e3,op1,DAE.BINARY(e1,DAE.POW(ty),DAE.RCONST(2.0)));
4100
4101 // e * (e1 * e) => e1*e^2
4102 case (DAE.MUL(),e1,DAE.BINARY(e2,op1 as DAE.MUL(ty),e3))
4103 guard Types.isScalarReal(ty) and ExpressionBasics.expEqual(e1,e3)
4104 10876 then DAE.BINARY(e2,op1,DAE.BINARY(e1,DAE.POW(ty),DAE.RCONST(2.0)));
4105
4106 // r1 * (r2 * e) => (r1*r2)*e
4107 case (DAE.MUL(),DAE.RCONST(real = r1),DAE.BINARY(DAE.RCONST(real = r2),DAE.MUL(DAE.T_REAL()),e2))
4108 31515 then DAE.BINARY(DAE.RCONST(r1 * r2),DAE.MUL(DAE.T_REAL_DEFAULT),e2);
4109
4110 // r1 * (e * r2) => (r1*r2)*e
4111 case (DAE.MUL(),DAE.RCONST(real = r1),DAE.BINARY(e2,DAE.MUL(DAE.T_REAL()),DAE.RCONST(real = r2)))
4112 4347 then DAE.BINARY(DAE.RCONST(r1 * r2),DAE.MUL(DAE.T_REAL_DEFAULT),e2);
4113
4114 // (r1 + (r2 - e)) => (r3 - e)
4115 case (DAE.ADD(),DAE.RCONST(r1),DAE.BINARY(DAE.RCONST(r2),DAE.SUB(ty=ty),e1 as DAE.CREF(_)))
4116 1029 then DAE.BINARY(DAE.RCONST(realAdd(r1,r2)),DAE.SUB(ty),e1);
4117
4118 // |e1| /e1 = e1/|e1| => sign(e1)
4119 case(DAE.DIV(ty),DAE.CALL(path=Absyn.IDENT("abs"),expLst={e1}),e2)
4120 guard ExpressionBasics.expEqual(e1,e2)
4121 ✗ then Expression.makePureBuiltinCall("sign",{e1},ty);
4122
4123 // SUB is not commutative
4124 // (e*e1) - (e*e2) => e*(e1-e2)
4125 //case (op1 as DAE.SUB(ty = _),DAE.BINARY(e1,op2 as DAE.MUL(ty=_),e2),DAE.BINARY(e3,DAE.MUL(ty=_),e4))
4126 // equation
4127 // true = ExpressionBasics.expEqual(e1,e3);
4128 // then
4129 // DAE.BINARY(e1,op2,DAE.BINARY(e2,op1,e4));
4130 // (e*e1) - (e2*e) => e*(e1-e2)
4131 //case (op1 as DAE.SUB(ty = _),DAE.BINARY(e1,op2 as DAE.MUL(ty=_),e2),DAE.BINARY(e3,DAE.MUL(ty=_),e4))
4132 // equation
4133 // true = ExpressionBasics.expEqual(e1,e4);
4134 // then
4135 // DAE.BINARY(e1,op2,DAE.BINARY(e2,op1,e3));
4136
4137 // e2 + (e*e2) = (1 + e)*e2
4138 // e2 + (e2*e) = (1 + e)*e2;
4139 case (op1 as DAE.ADD(ty), e1, DAE.BINARY(e2, op2 as DAE.MUL(),e3))
4140 guard not Expression.isConstValue(e1)
4141 algorithm
4142
2/2
✓ Branch 1 taken 117 times.
✓ Branch 2 taken 8030937 times.
8031054 if ExpressionBasics.expEqual(e1,e3)
4143 then
4144 117 exp := DAE.BINARY(e1,op2,DAE.BINARY(Expression.makeConstOne(ty),op1,e2));
4145
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 8030932 times.
8030937 else if ExpressionBasics.expEqual(e1,e2)
4146 then
4147 5 exp := DAE.BINARY(e1,op2,DAE.BINARY(Expression.makeConstOne(ty),op1,e3));
4148 else
4149 8030932 fail();
4150 end if;
4151 end if;
4152 then
4153 exp;
4154
4155 // sqrt(e) * e => e^1.5
4156 case (DAE.MUL(),DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={e1}),e2)
4157 guard ExpressionBasics.expEqual(e1,e2)
4158 79 then DAE.BINARY(e1,DAE.POW(DAE.T_REAL_DEFAULT),DAE.RCONST(1.5));
4159 // sqrt(e) * e^r => e^(r+0.5)
4160 case (DAE.MUL(),DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={e1}),DAE.BINARY(e2,DAE.POW(),e))
4161 guard ExpressionBasics.expEqual(e1,e2)
4162 48 then DAE.BINARY(e1,DAE.POW(DAE.T_REAL_DEFAULT),DAE.BINARY(e,DAE.ADD(DAE.T_REAL_DEFAULT),DAE.RCONST(0.5)));
4163 // x*x^y => x^(y+1)
4164 case (DAE.MUL(),e1,DAE.BINARY(e3, op1 as DAE.POW(tp),e4))
4165 guard ExpressionBasics.expEqual(e1,e3)
4166 algorithm
4167 1282 e := Expression.makeConstOne(tp);
4168 1282 then
4169 DAE.BINARY(e1,op1,DAE.BINARY(e,DAE.ADD(tp),e4));
4170
4171 end matchcontinue;
4172 end simplifyBinaryCommutativeWork;
4173
4174 protected function simplifyBinary
4175 "This function simplifies binary expressions."
4176 input DAE.Exp origExp;
4177 input Operator inOperator2;
4178 input DAE.Exp lhs "Note: already simplified";
4179 input DAE.Exp rhs "Note: aldready simplified";
4180 output DAE.Exp outExp;
4181 protected
4182 Boolean lhsIsConstValue = Expression.isConstValue(lhs);
4183 Boolean rhsIsConstValue = Expression.isConstValue(rhs);
4184 algorithm
4185 outExp := matchcontinue (inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue)
4186 local
4187 DAE.Exp e1_1,e3,e,e1,e2,e4,e5,e6,res,one;
4188 Operator oper, op1 ,op2, op3, op;
4189 Type ty,ty2,tp,tp2;
4190 list<DAE.Exp> exp_lst,exp_lst_1;
4191 Boolean b,b2;
4192 Real r, r1;
4193 Option<DAE.Exp> oexp;
4194
4195
4196 // binary operations on arrays
4197 case (op, e1, e2, _, _) guard simplifyBinaryArrayOp(op)
4198 55093 then simplifyBinaryArray(e1, op, e2);
4199
4200 // binary scalar simplifications
4201 case (op, e1, e2, _, _)
4202 36692038 then simplifyBinaryCommutativeWork(op, e1, e2);
4203 case (op, e1, e2, _, _)
4204 34519282 then simplifyBinaryCommutativeWork(op, e2, e1);
4205
4206 // constants
4207 case (oper, e1, e2, true, true)
4208 algorithm
4209 // print("simplifyBinaryConst " + ExpressionBasics.printExpStr(e1) + ExpressionDump.binopSymbol1(oper) + ExpressionBasics.printExpStr(e2) + "\n");
4210 633277 e3 := simplifyBinaryConst(oper, e1, e2);
4211 // print("simplifyBinaryConst " + ExpressionBasics.printExpStr(e1) + "," + ExpressionBasics.printExpStr(e2) + " => " + ExpressionBasics.printExpStr(e3) + "\n");
4212 then e3;
4213
4214 case (oper, DAE.BINARY(e1,op1,e2), DAE.BINARY(e3,op2,e4), _, _)
4215 6613674 then simplifyTwoBinaryExpressions(e1,op1,e2,oper,e3,op2,e4,
4216 /* These are checked in multiple cases and improve performance */
4217 ExpressionBasics.expEqual(e1,e3),
4218 ExpressionBasics.expEqual(e1,e4),
4219 ExpressionBasics.expEqual(e2,e3),
4220 ExpressionBasics.expEqual(e2,e4),
4221 Expression.isConstValue(e1),
4222 Expression.isConstValue(e2),
4223 Expression.isConstValue(e3),
4224 Expression.operatorEqual(op1,op2)
4225 );
4226
4227 // Look for empty arrays
4228 case (oper, e1, e2, _, _)
4229 algorithm
4230
3/4
✓ Branch 1 taken 31710095 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 31710095 times.
✗ Branch 5 not taken.
31710096 true := Expression.isConstZeroLength(e1) or Expression.isConstZeroLength(e2);
4231 1 checkZeroLengthArrayOp(oper);
4232 then e1;
4233 31710095 else simplifyBinaryByOperator(origExp, inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue);
4234 end matchcontinue;
4235 end simplifyBinary;
4236
4237 protected function simplifyBinaryByOperator
4238 "The operator-specific simplifyBinary cases. Cases for different operators
4239 never match the same input, so each operator only tries its own."
4240 input DAE.Exp origExp;
4241 input Operator inOperator2;
4242 input DAE.Exp lhs;
4243 input DAE.Exp rhs;
4244 input Boolean lhsIsConstValue;
4245 input Boolean rhsIsConstValue;
4246 output DAE.Exp outExp;
4247 algorithm
4248 outExp := match inOperator2
4249 15489114 case DAE.MUL() then simplifyBinaryMul(origExp, inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue);
4250 1582474 case DAE.DIV() then simplifyBinaryDiv(origExp, inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue);
4251 3843503 case DAE.SUB() then simplifyBinarySub(origExp, inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue);
4252 8973300 case DAE.ADD() then simplifyBinaryAdd(origExp, inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue);
4253 1778180 case DAE.POW() then simplifyBinaryPow(origExp, inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue);
4254 43524 else simplifyBinaryOther(origExp, inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue);
4255 end match;
4256 end simplifyBinaryByOperator;
4257
4258 protected function simplifyBinaryMul
4259 "simplifyBinary cases for DAE.MUL."
4260 input DAE.Exp origExp;
4261 input Operator inOperator2;
4262 input DAE.Exp lhs;
4263 input DAE.Exp rhs;
4264 input Boolean lhsIsConstValue;
4265 input Boolean rhsIsConstValue;
4266 output DAE.Exp outExp;
4267 algorithm
4268 outExp := matchcontinue (inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue)
4269 local
4270 DAE.Exp e1_1,e3,e,e1,e2,e4,e5,e6,res,one;
4271 Operator oper, op1 ,op2, op3, op;
4272 Type ty,ty2,tp,tp2;
4273 list<DAE.Exp> exp_lst,exp_lst_1;
4274 Boolean b,b2;
4275 Real r, r1;
4276 Option<DAE.Exp> oexp;
4277
4278 // a*(b^(-e)) => a/(b^e)
4279 case (DAE.MUL(), e1, DAE.BINARY(exp1 = e2,operator = op1 as DAE.POW(ty = ty2),exp2 = DAE.UNARY(exp=e3,operator=DAE.UMINUS())), _, _)
4280 algorithm
4281 241 res := DAE.BINARY(e1,DAE.DIV(ty2),DAE.BINARY(e2,op1,e3));
4282 then res;
4283
4284 // a*(b^(-r)) => a/(b^r)
4285 case (DAE.MUL(), e1, DAE.BINARY(exp1 = e2,operator = op1 as DAE.POW(ty = ty2),exp2 = DAE.RCONST(r)), _, _)
4286 algorithm
4287
2/2
✓ Branch 0 taken 432465 times.
✓ Branch 1 taken 23243 times.
455708 true := realLt(r,0.0);
4288 23243 r := realNeg(r);
4289 23243 res := DAE.BINARY(e1,DAE.DIV(ty2),DAE.BINARY(e2,op1,DAE.RCONST(r)));
4290 then res;
4291
4292 // |e1| op2 |e2| => |e1 op2 e2|
4293 case(op2, DAE.CALL(path=Absyn.IDENT("abs"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("abs"),expLst={e2}), _, _)
4294 algorithm
4295
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 true := Expression.isMulOrDiv(op2);
4296 11 ty := Expression.typeof(e1);
4297 11 res := DAE.BINARY(e1, op2, e2);
4298 11 then Expression.makePureBuiltinCall("abs",{res},ty);
4299 // exp(e1) * exp(e2) => exp(e1 + e2)
4300 case(DAE.MUL(ty), DAE.CALL(path=Absyn.IDENT("exp"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("exp"),expLst={e2}), _, _)
4301 algorithm
4302
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 false := Expression.isConstValue(e1) or Expression.isConstValue(e2);
4303 2 e := DAE.BINARY(e1, DAE.ADD(ty),e2);
4304 2 res := Expression.makePureBuiltinCall("exp",{e},ty);
4305 then res;
4306
4307 // a * a = a^2
4308 case (DAE.MUL(ty = ty), e1, e2, _, _)
4309 algorithm
4310
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15465617 times.
15465617 false := Expression.isZero(e2);
4311
2/2
✓ Branch 1 taken 1093 times.
✓ Branch 2 taken 15464524 times.
15465617 true := Types.isRealOrSubTypeReal(ty);
4312
2/2
✓ Branch 1 taken 15375885 times.
✓ Branch 2 taken 88639 times.
15464524 true := ExpressionBasics.expEqual(e1,e2);
4313 88639 res := DAE.BINARY(e1,DAE.POW(ty),DAE.RCONST(2.0));
4314 then res;
4315 // -a*(b-c) = a*(c -b)
4316 case (op2 as DAE.MUL(), DAE.UNARY(operator = DAE.UMINUS(),exp = e1), DAE.BINARY(e2, op1 as DAE.SUB(_),e3), _, _)
4317 3695 then DAE.BINARY(e1,op2,DAE.BINARY(e3,op1,e2));
4318 // a*(-b-c) = (-a)*(c + b)
4319 case (op2 as DAE.MUL(), e1, DAE.BINARY(DAE.UNARY(operator = op3 as DAE.UMINUS(),exp = e2), DAE.SUB(ty = ty), e3), _, _)
4320 148 then DAE.BINARY(DAE.UNARY(op3,e1),op2,DAE.BINARY(e2, DAE.ADD(ty),e3));
4321
4322 // (if b then x1 else y1) op (if b then x2 else y2)
4323 // => (if b then x1 op x2 else y1 op y2)
4324 case (op1, DAE.IFEXP(expCond = e1,expThen = e2,expElse = e3), DAE.IFEXP(expCond = e4,expThen = e5,expElse = e6), _, _)
4325 algorithm
4326
1/2
✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
124 true := ExpressionBasics.expEqual(e1,e4);
4327 ✗ e := DAE.BINARY(e2,op1,e5);
4328 ✗ res := DAE.BINARY(e3,op1,e6);
4329 ✗ then DAE.IFEXP(e1,e,res);
4330
4331
4332 // a*(x op2 b) op1 c*(x op3 d)
4333 // x *(a op2 b op1 c op3 d)
4334 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
4335 algorithm
4336
1/2
✓ Branch 1 taken 15374 times.
✗ Branch 2 not taken.
15374 true := Expression.isAddOrSub(op1);
4337 ✗ true := Expression.isMulOrDiv(op2);
4338 ✗ true := Expression.isMulOrDiv(op3);
4339 ✗ true := ExpressionBasics.expEqual(e2,e5);
4340 ✗ then DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,DAE.BINARY(e4,op3,e6)));
4341
4342 // a*x op1 c*x op3 d
4343 // x *(a op1 c op3 d)
4344 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),e2), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
4345 algorithm
4346
1/2
✓ Branch 1 taken 19100 times.
✗ Branch 2 not taken.
19100 true := Expression.isAddOrSub(op1);
4347 ✗ true := Expression.isMulOrDiv(op3);
4348 ✗ true := ExpressionBasics.expEqual(e2,e5);
4349 ✗ then DAE.BINARY(e5, oper, DAE.BINARY(e1,op1,DAE.BINARY(e4,op3,e6)));
4350
4351 // a*(x op2 b) op1 c*x
4352 // x*(a op2 b op1 c)
4353 // or
4354 // a*(x op2 b) op1 x*c
4355 // x*(a op2 b op1 c)
4356 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
4357 algorithm
4358
1/2
✓ Branch 1 taken 16892 times.
✗ Branch 2 not taken.
16892 true := Expression.isAddOrSub(op1);
4359 ✗ true := Expression.isMulOrDiv(op2);
4360 ✗ if ExpressionBasics.expEqual(e2,e5)
4361 then
4362 ✗ outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
4363 ✗ else if ExpressionBasics.expEqual(e2,e4)
4364 then
4365 ✗ outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
4366 else
4367 ✗ fail();
4368 end if;
4369 end if;
4370 then
4371 outExp;
4372
4373 // a*(x op2 b) op1 c*x
4374 // x*(a op2 b op1 c)
4375 // or
4376 // a*(x op2 b) op1 x*c
4377 // x*(a op2 b op1 c)
4378 case (op1, DAE.BINARY(DAE.BINARY(e1,oper as DAE.MUL(_),e2),op2,e3), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
4379 algorithm
4380
1/2
✓ Branch 1 taken 17811 times.
✗ Branch 2 not taken.
17811 true := Expression.isAddOrSub(op1);
4381 ✗ true := Expression.isMulOrDiv(op2);
4382 ✗ if ExpressionBasics.expEqual(e2,e5)
4383 then
4384 ✗ outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
4385 ✗ else if ExpressionBasics.expEqual(e2,e4)
4386 then
4387 ✗ outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
4388 else
4389 ✗ fail();
4390 end if;
4391 end if;
4392 then
4393 outExp;
4394
4395 // e1 -e2 => -e1 e2
4396 // Note: This rule is *not* commutative
4397 case (DAE.MUL(ty = ty), e1, DAE.UNARY(operator = DAE.UMINUS(),exp = e2), _, _)
4398 algorithm
4399 33684 e1_1 := DAE.UNARY(DAE.UMINUS(ty),e1);
4400 33684 then DAE.BINARY(e1_1,DAE.MUL(ty),e2);
4401 else origExp;
4402 end matchcontinue;
4403 end simplifyBinaryMul;
4404
4405 protected function simplifyBinaryDiv
4406 "simplifyBinary cases for DAE.DIV."
4407 input DAE.Exp origExp;
4408 input Operator inOperator2;
4409 input DAE.Exp lhs;
4410 input DAE.Exp rhs;
4411 input Boolean lhsIsConstValue;
4412 input Boolean rhsIsConstValue;
4413 output DAE.Exp outExp;
4414 algorithm
4415 outExp := matchcontinue (inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue)
4416 local
4417 DAE.Exp e1_1,e3,e,e1,e2,e4,e5,e6,res,one;
4418 Operator oper, op1 ,op2, op3, op;
4419 Type ty,ty2,tp,tp2;
4420 list<DAE.Exp> exp_lst,exp_lst_1;
4421 Boolean b,b2;
4422 Real r, r1;
4423 Option<DAE.Exp> oexp;
4424
4425 // a/(b^(-e)) => a*(b^e)
4426 case (DAE.DIV(), e1, DAE.BINARY(exp1 = e2,operator = op1 as DAE.POW(ty = ty2),exp2 = DAE.UNARY(exp=e3,operator=DAE.UMINUS())), _, _)
4427 algorithm
4428 ✗ res := DAE.BINARY(e1,DAE.MUL(ty2),DAE.BINARY(e2,op1,e3));
4429 then res;
4430
4431 // a/(b^(-r)) => a*(b^r)
4432 case (DAE.DIV(), e1, DAE.BINARY(exp1 = e2,operator = op1 as DAE.POW(ty = ty2),exp2 = DAE.RCONST(r)), _, _)
4433 algorithm
4434
1/2
✓ Branch 0 taken 177067 times.
✗ Branch 1 not taken.
177067 true := realLt(r,0.0);
4435 ✗ r := realNeg(r);
4436 ✗ res := DAE.BINARY(e1,DAE.MUL(ty2),DAE.BINARY(e2,op1,DAE.RCONST(r)));
4437 then res;
4438
4439 // (a*b op1 c)/b => a op1 c/b
4440 case (DAE.DIV(_), DAE.BINARY(DAE.BINARY(e1, DAE.MUL(_), e2), op1,e3), e4, _, _)
4441 algorithm
4442
2/2
✓ Branch 1 taken 42768 times.
✓ Branch 2 taken 147372 times.
190140 true := Expression.isAddOrSub(op1);
4443
2/2
✓ Branch 1 taken 147163 times.
✓ Branch 2 taken 209 times.
147372 true := ExpressionBasics.expEqual(e2,e4);
4444 209 e := Expression.makeDiv(e3,e4);
4445 209 res := DAE.BINARY(e1,op1,e);
4446 then res;
4447
4448 // (c op1 a*b)/b => c/b op1 a
4449 case (DAE.DIV(_), DAE.BINARY(e3, op1,DAE.BINARY(e1, DAE.MUL(_), e2)), e4, _, _)
4450 algorithm
4451
2/2
✓ Branch 1 taken 44101 times.
✓ Branch 2 taken 187924 times.
232025 true := Expression.isAddOrSub(op1);
4452
2/2
✓ Branch 1 taken 187830 times.
✓ Branch 2 taken 94 times.
187924 true := ExpressionBasics.expEqual(e2,e4);
4453 94 e := Expression.makeDiv(e3,e4);
4454 94 res := DAE.BINARY(e,op1,e1);
4455 then res;
4456
4457 // (e1 * e2*e3 op1 e4)/e3 => e1 * e2 op1 e4/e3
4458 case (DAE.DIV(_), DAE.BINARY(DAE.BINARY(e1, op2 as DAE.MUL(), DAE.BINARY(e2, DAE.MUL(_), e3)), op1,e4), e5, _, _)
4459 algorithm
4460
2/2
✓ Branch 1 taken 1312 times.
✓ Branch 2 taken 32616 times.
33928 true := Expression.isAddOrSub(op1);
4461
2/2
✓ Branch 1 taken 32580 times.
✓ Branch 2 taken 36 times.
32616 true := ExpressionBasics.expEqual(e3,e5);
4462 36 e := Expression.makeDiv(e4,e3);
4463 36 e1_1 := DAE.BINARY(e1,op2,e2);
4464 36 res := DAE.BINARY(e1_1,op1,e);
4465 then res;
4466
4467 // |e1| op2 |e2| => |e1 op2 e2|
4468 case(op2, DAE.CALL(path=Absyn.IDENT("abs"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("abs"),expLst={e2}), _, _)
4469 algorithm
4470 ✗ true := Expression.isMulOrDiv(op2);
4471 ✗ ty := Expression.typeof(e1);
4472 ✗ res := DAE.BINARY(e1, op2, e2);
4473 ✗ then Expression.makePureBuiltinCall("abs",{res},ty);
4474 // e1 / exp(e2) => e1*exp(-e2)
4475 case(DAE.DIV(ty), e1, DAE.CALL(path=Absyn.IDENT("exp"),expLst={e2}), _, _)
4476 algorithm
4477 15 e := DAE.UNARY(DAE.UMINUS(ty),e2);
4478 15 (e,_) := simplify1(e);
4479 15 e3 := Expression.makePureBuiltinCall("exp",{e},ty);
4480 15 res := DAE.BINARY(e1,DAE.MUL(ty),e3);
4481 then res;
4482
4483 // (a+b)/c1 => a/c1+b/c1, for constant c1
4484 case (op1 as DAE.DIV(), DAE.BINARY(exp1 = e1,operator = op2 as DAE.ADD(),exp2 = e2), e3, _, true)
4485 algorithm
4486 3380 (e,b) := simplify1(DAE.BINARY(e1,op1,e3));
4487 3380 (e4,b2) := simplify1(DAE.BINARY(e2,op1,e3));
4488
4/4
✓ Branch 0 taken 490 times.
✓ Branch 1 taken 2890 times.
✓ Branch 2 taken 481 times.
✓ Branch 3 taken 9 times.
3380 true := b or b2;
4489 2899 then DAE.BINARY(e ,op2,e4);
4490
4491 // (a-b)/c1 => a/c1-b/c1, for constant c1
4492 case (op1 as DAE.DIV(), DAE.BINARY(exp1 = e1,operator = op2 as DAE.SUB(),exp2 = e2), e3, _, true)
4493 algorithm
4494 16763 (e,b) := simplify1(DAE.BINARY(e1,op1,e3));
4495 16763 (e4,b2) := simplify1(DAE.BINARY(e2,op1,e3));
4496
4/4
✓ Branch 0 taken 14546 times.
✓ Branch 1 taken 2217 times.
✓ Branch 2 taken 14210 times.
✓ Branch 3 taken 336 times.
16763 true := b or b2;
4497 2553 then DAE.BINARY(e,op2,e4);
4498
4499 // a/(b/c) => (ac)/b
4500 case (DAE.DIV(ty = tp), e1, DAE.BINARY(exp1 = e2,operator = op2 as DAE.DIV(),exp2 = e3), _, _)
4501 4375 then DAE.BINARY(DAE.BINARY(e1,DAE.MUL(tp),e3),op2,e2);
4502
4503 // (a/b)/c => a/(bc))
4504 case (DAE.DIV(ty = tp), DAE.BINARY(exp1 = e1,operator = DAE.DIV(ty = tp2),exp2 = e2), e3, _, _)
4505 74387 then DAE.BINARY(e1,DAE.DIV(tp2),DAE.BINARY(e2,DAE.MUL(tp),e3));
4506
4507 // a / (b*a) = 1/b
4508 case (DAE.DIV(), e1, DAE.BINARY(exp1 = e2,operator = DAE.MUL(ty = tp2),exp2 = e3), _, _)
4509 algorithm
4510
2/2
✓ Branch 1 taken 213670 times.
✓ Branch 2 taken 37 times.
213707 true := ExpressionBasics.expEqual(e1,e3);
4511 37 then DAE.BINARY(DAE.RCONST(1.0),DAE.DIV(tp2),e2);
4512
4513 // a / (a*b) = 1/b
4514 case (DAE.DIV(), e1, DAE.BINARY(exp1 = e2,operator = DAE.MUL(ty = tp2),exp2 = e3), _, _)
4515 algorithm
4516
2/2
✓ Branch 1 taken 213542 times.
✓ Branch 2 taken 128 times.
213670 true := ExpressionBasics.expEqual(e1,e2);
4517 128 then DAE.BINARY(DAE.RCONST(1.0),DAE.DIV(tp2),e3);
4518
4519 // (a*b)/ a = b
4520 case (DAE.DIV(), DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = e2), e3, _, _)
4521 algorithm
4522
2/2
✓ Branch 1 taken 198295 times.
✓ Branch 2 taken 562 times.
198857 true := ExpressionBasics.expEqual(e1,e3);
4523 then e2;
4524
4525 // (a*b)/ b = a
4526 case (DAE.DIV(), DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = e2), e3, _, _)
4527 algorithm
4528
2/2
✓ Branch 1 taken 198260 times.
✓ Branch 2 taken 35 times.
198295 true := ExpressionBasics.expEqual(e2,e3);
4529 then e1;
4530
4531 // (-a*b)/ a = -b
4532 case (DAE.DIV(), DAE.BINARY(exp1 = DAE.UNARY(operator = DAE.UMINUS(),exp = e1),operator = DAE.MUL(),exp2 = e2), e3, _, _)
4533 algorithm
4534
2/2
✓ Branch 1 taken 27682 times.
✓ Branch 2 taken 3 times.
27685 true := ExpressionBasics.expEqual(e1,e3);
4535 3 tp2 := Expression.typeof(e2);
4536 3 e := DAE.UNARY(DAE.UMINUS(tp2),e2);
4537 then e;
4538
4539 // (-a*b)/ b = -a
4540 case (DAE.DIV(), DAE.BINARY(exp1 = DAE.UNARY(operator = DAE.UMINUS(),exp = e1),operator = DAE.MUL(),exp2 = e2), e3, _, _)
4541 algorithm
4542
1/2
✓ Branch 1 taken 27682 times.
✗ Branch 2 not taken.
27682 true := ExpressionBasics.expEqual(e2,e3);
4543 ✗ tp2 := Expression.typeof(e1);
4544 ✗ e := DAE.UNARY(DAE.UMINUS(tp2),e1);
4545 then e;
4546
4547 // (a*b)/ -b = -a
4548 case (DAE.DIV(), DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = e2), DAE.UNARY(operator = DAE.UMINUS(),exp = e3), _, _)
4549 algorithm
4550
2/2
✓ Branch 1 taken 321 times.
✓ Branch 2 taken 1 time.
322 true := ExpressionBasics.expEqual(e2,e3);
4551 1 tp2 := Expression.typeof(e1);
4552 1 then DAE.UNARY(DAE.UMINUS(tp2),e1);
4553
4554 // (a*b)/ -a = -b
4555 case (DAE.DIV(), DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = e2), DAE.UNARY(operator = DAE.UMINUS(),exp = e3), _, _)
4556 algorithm
4557
2/2
✓ Branch 1 taken 320 times.
✓ Branch 2 taken 1 time.
321 true := ExpressionBasics.expEqual(e1,e3);
4558 1 tp2 := Expression.typeof(e2);
4559 1 then DAE.UNARY(DAE.UMINUS(tp2),e2);
4560
4561 // 0 / x = 0
4562 case (DAE.DIV(), e1, e2, true, false)
4563 algorithm
4564
2/2
✓ Branch 1 taken 469312 times.
✓ Branch 2 taken 35357 times.
504669 true := Expression.isZero(e1);
4565
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 35357 times.
35357 false := Expression.isZero(e2);
4566 then DAE.RCONST(0.0);
4567
4568 // a / 1 = a
4569 case (DAE.DIV(), e1, e2, false, true)
4570 algorithm
4571
2/2
✓ Branch 1 taken 97246 times.
✓ Branch 2 taken 1834 times.
99080 true := Expression.isConstOne(e2);
4572 then e1;
4573
4574 // a / -1 = -a
4575 case (DAE.DIV(ty = ty), e1, e2, _, _)
4576 algorithm
4577
2/2
✓ Branch 1 taken 1459937 times.
✓ Branch 2 taken 11 times.
1459948 true := Expression.isConstMinusOne(e2);
4578 11 e := DAE.UNARY(DAE.UMINUS(ty),e1);
4579 then e;
4580
4581 // a / a = 1
4582 case (DAE.DIV(ty = ty), e1, e2, _, _)
4583 algorithm
4584
2/2
✓ Branch 1 taken 4795 times.
✓ Branch 2 taken 1455142 times.
1459937 false := Expression.isZero(e2);
4585
2/2
✓ Branch 1 taken 1455098 times.
✓ Branch 2 taken 44 times.
1455142 true := ExpressionBasics.expEqual(e1,e2);
4586 44 res := Expression.makeConstOne(ty);
4587 then res;
4588
4589 // exp / r = (1/r)*exp
4590 case(DAE.DIV(ty=tp), e1, DAE.RCONST(real=r1), _, _)
4591 algorithm
4592
2/2
✓ Branch 0 taken 4795 times.
✓ Branch 1 taken 96266 times.
101061 true := realAbs(r1) > 0.0;
4593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96266 times.
96266 r := 1.0 / r1;
4594
2/2
✓ Branch 0 taken 81732 times.
✓ Branch 1 taken 14534 times.
96266 r1 := 1e12 * r;
4595
2/2
✓ Branch 0 taken 81732 times.
✓ Branch 1 taken 14534 times.
96266 0.0 := realMod(r1, 1.0);
4596 14534 e3 := DAE.BINARY(DAE.RCONST(r),DAE.MUL(tp),e1);
4597 then e3;
4598 // x / (r*y) = (1/r)*x/y
4599 case(op2 as DAE.DIV(ty=tp), e1, DAE.BINARY(DAE.RCONST(real=r1),DAE.MUL(_),e3), _, _)
4600 algorithm
4601
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 10171 times.
10179 true := realAbs(r1) > 0.0;
4602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10171 times.
10171 r := 1.0 / r1;
4603
2/2
✓ Branch 0 taken 7046 times.
✓ Branch 1 taken 3125 times.
10171 r1 := 1e12 * r;
4604
2/2
✓ Branch 0 taken 7046 times.
✓ Branch 1 taken 3125 times.
10171 0.0 := realMod(r1, 1.0);
4605 3125 then DAE.BINARY(DAE.BINARY(DAE.RCONST(r),DAE.MUL(tp),e1),op2,e3);
4606 // -a / -b = a / b
4607 case (op1 as DAE.DIV(), DAE.UNARY(operator = DAE.UMINUS(),exp = e1), DAE.UNARY(operator = DAE.UMINUS(),exp = e2), _, _)
4608 2222 then DAE.BINARY(e1,op1,e2);
4609 // -a/(b-c) = a/(c -b)
4610 case (op2 as DAE.DIV(), DAE.UNARY(operator = DAE.UMINUS(),exp = e1), DAE.BINARY(e2, op1 as DAE.SUB(_),e3), _, _)
4611 4 then DAE.BINARY(e1,op2,DAE.BINARY(e3,op1,e2));
4612 // a/(-b-c) = (-a)/(c + b)
4613 case (op2 as DAE.DIV(), e1, DAE.BINARY(DAE.UNARY(operator = op3 as DAE.UMINUS(),exp = e2), DAE.SUB(ty = ty), e3), _, _)
4614 14 then DAE.BINARY(DAE.UNARY(op3,e1),op2,DAE.BINARY(e2, DAE.ADD(ty),e3));
4615 // e1 / -e2 => -e1 / e2
4616 case (op1 as DAE.DIV(ty = ty), e1, DAE.UNARY(operator = DAE.UMINUS(),exp = e2), _, _)
4617 algorithm
4618 1869 e1_1 := DAE.UNARY(DAE.UMINUS(ty),e1);
4619 1869 then DAE.BINARY(e1_1,op1,e2);
4620
4621 // (e2*e3)/e1 => (e3/e1)*e2
4622 case (op1 as DAE.DIV(), DAE.BINARY(exp1 = e2,operator = op2 as DAE.MUL(),exp2 = e3), e1, _, true)
4623 algorithm
4624
2/2
✓ Branch 1 taken 8748 times.
✓ Branch 2 taken 238 times.
8990 true := Expression.isConstValue(e3);
4625
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 234 times.
238 (e,true) := simplify1(DAE.BINARY(e3,op1,e1));
4626 234 then DAE.BINARY(e,op2,e2);
4627
4628 // e2*e3 / e1 => e2 / e1 * e3
4629 case (op1 as DAE.DIV(), DAE.BINARY(exp1 = e2,operator = op2 as DAE.MUL(),exp2 = e3), e1, _, true)
4630 algorithm
4631
2/2
✓ Branch 1 taken 5951 times.
✓ Branch 2 taken 2801 times.
8752 true := Expression.isConstValue(e2);
4632
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2801 times.
2801 (e,true) := simplify1(DAE.BINARY(e2,op1,e1));
4633 2801 then DAE.BINARY(e,op2,e3);
4634
4635 // e/sqrt(e) = sqrt(e)
4636 case (DAE.DIV(), e1, DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={e2}), _, _)
4637 algorithm
4638
1/2
✓ Branch 1 taken 10628 times.
✗ Branch 2 not taken.
10628 true := ExpressionBasics.expEqual(e1,e2);
4639 ✗ then Expression.makePureBuiltinCall("sqrt",{e1},DAE.T_REAL_DEFAULT);
4640 // x^y/x => x^(y-1)
4641 case (DAE.DIV(), DAE.BINARY(e1,op1 as DAE.POW(ty), e2), e3, _, _)
4642 algorithm
4643
2/2
✓ Branch 1 taken 46843 times.
✓ Branch 2 taken 17 times.
46860 true := ExpressionBasics.expEqual(e1,e3);
4644 17 e4 := Expression.makeConstOne(ty);
4645 17 e4 := DAE.BINARY(e2,DAE.SUB(ty), e4);
4646 17 then DAE.BINARY(e1,op1, e4);
4647 // x^y*z/x = x^(y-1)*z
4648 case (DAE.DIV(), DAE.BINARY(DAE.BINARY(e1,op1 as DAE.POW(ty), e2),op2 as DAE.MUL(_),e5), e3, _, _)
4649 algorithm
4650
1/2
✓ Branch 1 taken 2223 times.
✗ Branch 2 not taken.
2223 true := ExpressionBasics.expEqual(e1,e3);
4651 ✗ e4 := Expression.makeConstOne(ty);
4652 ✗ e4 := DAE.BINARY(e2,DAE.SUB(ty), e4);
4653 ✗ then DAE.BINARY(DAE.BINARY(e1,op1, e4),op2,e5);
4654 //x/x^y => x^(1-y)
4655 case (DAE.DIV(), e3, DAE.BINARY(e1,op1 as DAE.POW(ty), e2), _, _)
4656 algorithm
4657
2/2
✓ Branch 1 taken 152989 times.
✓ Branch 2 taken 5759 times.
158748 true := ExpressionBasics.expEqual(e1,e3);
4658 5759 e4 := Expression.makeConstOne(ty);
4659 5759 e4 := DAE.BINARY(e4,DAE.SUB(ty), e2);
4660 5759 then DAE.BINARY(e1,op1, e4);
4661 //(x/y)^(-r) => (y/x)^r
4662 case (op2 as DAE.POW(), DAE.BINARY(e1, op1 as DAE.DIV(_), e2), DAE.RCONST(r), _, _)
4663 algorithm
4664 ✗ true := realLt(r,0.0);
4665 ✗ r := realNeg(r);
4666 ✗ then DAE.BINARY(DAE.BINARY(e2,op1,e1),op2,DAE.RCONST(r));
4667
4668 // (if b then x1 else y1) op (if b then x2 else y2)
4669 // => (if b then x1 op x2 else y1 op y2)
4670 case (op1, DAE.IFEXP(expCond = e1,expThen = e2,expElse = e3), DAE.IFEXP(expCond = e4,expThen = e5,expElse = e6), _, _)
4671 algorithm
4672
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 14 times.
19 true := ExpressionBasics.expEqual(e1,e4);
4673 14 e := DAE.BINARY(e2,op1,e5);
4674 14 res := DAE.BINARY(e3,op1,e6);
4675 14 then DAE.IFEXP(e1,e,res);
4676
4677
4678 // a*(x op2 b) op1 c*(x op3 d)
4679 // x *(a op2 b op1 c op3 d)
4680 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
4681 algorithm
4682
1/2
✓ Branch 1 taken 2581 times.
✗ Branch 2 not taken.
2581 true := Expression.isAddOrSub(op1);
4683 ✗ true := Expression.isMulOrDiv(op2);
4684 ✗ true := Expression.isMulOrDiv(op3);
4685 ✗ true := ExpressionBasics.expEqual(e2,e5);
4686 ✗ then DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,DAE.BINARY(e4,op3,e6)));
4687
4688 // a*x op1 c*x op3 d
4689 // x *(a op1 c op3 d)
4690 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),e2), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
4691 algorithm
4692
1/2
✓ Branch 1 taken 7439 times.
✗ Branch 2 not taken.
7439 true := Expression.isAddOrSub(op1);
4693 ✗ true := Expression.isMulOrDiv(op3);
4694 ✗ true := ExpressionBasics.expEqual(e2,e5);
4695 ✗ then DAE.BINARY(e5, oper, DAE.BINARY(e1,op1,DAE.BINARY(e4,op3,e6)));
4696
4697 // a*(x op2 b) op1 c*x
4698 // x*(a op2 b op1 c)
4699 // or
4700 // a*(x op2 b) op1 x*c
4701 // x*(a op2 b op1 c)
4702 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
4703 algorithm
4704
1/2
✓ Branch 1 taken 12624 times.
✗ Branch 2 not taken.
12624 true := Expression.isAddOrSub(op1);
4705 ✗ true := Expression.isMulOrDiv(op2);
4706 ✗ if ExpressionBasics.expEqual(e2,e5)
4707 then
4708 ✗ outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
4709 ✗ else if ExpressionBasics.expEqual(e2,e4)
4710 then
4711 ✗ outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
4712 else
4713 ✗ fail();
4714 end if;
4715 end if;
4716 then
4717 outExp;
4718
4719 // a*(x op2 b) op1 c*x
4720 // x*(a op2 b op1 c)
4721 // or
4722 // a*(x op2 b) op1 x*c
4723 // x*(a op2 b op1 c)
4724 case (op1, DAE.BINARY(DAE.BINARY(e1,oper as DAE.MUL(_),e2),op2,e3), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
4725 algorithm
4726
1/2
✓ Branch 1 taken 60524 times.
✗ Branch 2 not taken.
60524 true := Expression.isAddOrSub(op1);
4727 ✗ true := Expression.isMulOrDiv(op2);
4728 ✗ if ExpressionBasics.expEqual(e2,e5)
4729 then
4730 ✗ outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
4731 ✗ else if ExpressionBasics.expEqual(e2,e4)
4732 then
4733 ✗ outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
4734 else
4735 ✗ fail();
4736 end if;
4737 end if;
4738 then
4739 outExp;
4740
4741 // sin(e)/cos(e) => tan(e)
4742 case(DAE.DIV(ty), DAE.CALL(path=Absyn.IDENT("sin"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("cos"),expLst={e2}), _, _)
4743 algorithm
4744
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 true := ExpressionBasics.expEqual(e1,e2);
4745 2 then Expression.makePureBuiltinCall("tan",{e1},ty);
4746 // tan(e2)/sin(e2) => 1.0/cos(e2)
4747 case(op2 as DAE.DIV(ty), DAE.CALL(path=Absyn.IDENT("tan"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("sin"),expLst={e2}), _, _)
4748 algorithm
4749 ✗ true := ExpressionBasics.expEqual(e1,e2);
4750 e3 := DAE.RCONST(1.0);
4751 ✗ e4 := Expression.makePureBuiltinCall("cos",{e2},ty);
4752 ✗ e := DAE.BINARY(e3,op2,e4);
4753 then e;
4754 // sin(e2)/tan(e2) => cos(e2)
4755 case(DAE.DIV(ty), DAE.CALL(path=Absyn.IDENT("sin"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("tan"),expLst={e2}), _, _)
4756 algorithm
4757 ✗ true := ExpressionBasics.expEqual(e1,e2);
4758 ✗ e := Expression.makePureBuiltinCall("cos",{e2},ty);
4759 then e;
4760 // e1/tan(e2) => e1*cos(e2)/sin(e2)
4761 case(op2 as DAE.DIV(ty), e1, DAE.CALL(path=Absyn.IDENT("tan"),expLst={e2}), _, _)
4762 algorithm
4763 ✗ e3 := Expression.makePureBuiltinCall("sin",{e2},ty);
4764 ✗ e4 := Expression.makePureBuiltinCall("cos",{e2},ty);
4765 ✗ e := DAE.BINARY(e4,op2,e3);
4766 ✗ then DAE.BINARY(e1,DAE.MUL(ty), e);
4767 // sinh(e)/cosh(e) => tanh(e)
4768 case(DAE.DIV(ty), DAE.CALL(path=Absyn.IDENT("sinh"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("cosh"),expLst={e2}), _, _)
4769 algorithm
4770
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 true := ExpressionBasics.expEqual(e1,e2);
4771 1 then Expression.makePureBuiltinCall("tanh",{e1},ty);
4772 // tanh(e2)/sinh(e2) => 1.0/cosh(e2)
4773 case(op2 as DAE.DIV(ty), DAE.CALL(path=Absyn.IDENT("tanh"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("sinh"),expLst={e2}), _, _)
4774 algorithm
4775 ✗ true := ExpressionBasics.expEqual(e1,e2);
4776 e3 := DAE.RCONST(1.0);
4777 ✗ e4 := Expression.makePureBuiltinCall("cosh",{e2},ty);
4778 ✗ e := DAE.BINARY(e3,op2,e4);
4779 then e;
4780 // sinh(e2)/tanh(e2) => cosh(e2)
4781 case(DAE.DIV(ty), DAE.CALL(path=Absyn.IDENT("sinh"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("tanh"),expLst={e2}), _, _)
4782 algorithm
4783 ✗ true := ExpressionBasics.expEqual(e1,e2);
4784 ✗ e := Expression.makePureBuiltinCall("cosh",{e2},ty);
4785 then e;
4786 else origExp;
4787 end matchcontinue;
4788 end simplifyBinaryDiv;
4789
4790 protected function simplifyBinarySub
4791 "simplifyBinary cases for DAE.SUB."
4792 input DAE.Exp origExp;
4793 input Operator inOperator2;
4794 input DAE.Exp lhs;
4795 input DAE.Exp rhs;
4796 input Boolean lhsIsConstValue;
4797 input Boolean rhsIsConstValue;
4798 output DAE.Exp outExp;
4799 algorithm
4800 outExp := matchcontinue (inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue)
4801 local
4802 DAE.Exp e1_1,e3,e,e1,e2,e4,e5,e6,res,one;
4803 Operator oper, op1 ,op2, op3, op;
4804 Type ty,ty2,tp,tp2;
4805 list<DAE.Exp> exp_lst,exp_lst_1;
4806 Boolean b,b2;
4807 Real r, r1;
4808 Option<DAE.Exp> oexp;
4809
4810 // |e1| op2 |e2| => |e1 op2 e2|
4811 case(op2, DAE.CALL(path=Absyn.IDENT("abs"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("abs"),expLst={e2}), _, _)
4812 algorithm
4813
1/2
✓ Branch 1 taken 636 times.
✗ Branch 2 not taken.
636 true := Expression.isMulOrDiv(op2);
4814 ✗ ty := Expression.typeof(e1);
4815 ✗ res := DAE.BINARY(e1, op2, e2);
4816 ✗ then Expression.makePureBuiltinCall("abs",{res},ty);
4817
4818 // subtract from zero
4819 case (DAE.SUB(ty = ty), e1, e2, true, _)
4820 algorithm
4821
2/2
✓ Branch 1 taken 792597 times.
✓ Branch 2 taken 182789 times.
975386 true := Expression.isZero(e1);
4822 182789 then DAE.UNARY(DAE.UMINUS(ty),e2);
4823
4824 // subtract zero
4825 case (DAE.SUB(), e1, e2, _, true)
4826 algorithm
4827
2/2
✓ Branch 1 taken 425071 times.
✓ Branch 2 taken 103387 times.
528458 true := Expression.isZero(e2);
4828 then e1;
4829
4830 // a - a = 0
4831 case (DAE.SUB(ty = ty), e1, e2, _, _)
4832 algorithm
4833
2/2
✓ Branch 1 taken 3556885 times.
✓ Branch 2 taken 442 times.
3557327 true := ExpressionBasics.expEqual(e1,e2);
4834 442 then Expression.makeConstZero(ty);
4835
4836 // a-(-b) = a+b
4837 case (DAE.SUB(ty = ty), e1, DAE.UNARY(operator = DAE.UMINUS(),exp = e2), _, _)
4838 5244 then DAE.BINARY(e1,DAE.ADD(ty),e2);
4839
4840 // a-(-b)*c = a+b*c
4841 case (DAE.SUB(ty = ty), e1, DAE.BINARY(DAE.UNARY(operator = DAE.UMINUS(),exp = e2),op1 as DAE.MUL(_),e3), _, _)
4842 1787 then DAE.BINARY(e1,DAE.ADD(ty),DAE.BINARY(e2,op1,e3));
4843
4844 // a-(-b)/c = a+b/c
4845 case (DAE.SUB(ty = ty), e1, DAE.BINARY(DAE.UNARY(operator = DAE.UMINUS(),exp = e2),op1 as DAE.DIV(_),e3), _, _)
4846 24 then DAE.BINARY(e1,DAE.ADD(ty),DAE.BINARY(e2,op1,e3));
4847
4848 // (if b then x1 else y1) op (if b then x2 else y2)
4849 // => (if b then x1 op x2 else y1 op y2)
4850 case (op1, DAE.IFEXP(expCond = e1,expThen = e2,expElse = e3), DAE.IFEXP(expCond = e4,expThen = e5,expElse = e6), _, _)
4851 algorithm
4852
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 true := ExpressionBasics.expEqual(e1,e4);
4853 ✗ e := DAE.BINARY(e2,op1,e5);
4854 ✗ res := DAE.BINARY(e3,op1,e6);
4855 ✗ then DAE.IFEXP(e1,e,res);
4856
4857 // (-x) * y - x * z = (-x)*(y+z)
4858 case (DAE.SUB(ty), DAE.BINARY(e as DAE.UNARY(operator = DAE.UMINUS(),exp = e1), op2 as DAE.MUL(), e2), DAE.BINARY(e3,DAE.MUL(),e4), false, false)
4859 algorithm
4860
2/2
✓ Branch 1 taken 64757 times.
✓ Branch 2 taken 426 times.
65183 true := ExpressionBasics.expEqual(e1,e3);
4861 426 res := DAE.BINARY(e, op2, DAE.BINARY(e2, DAE.ADD(ty),e4));
4862 then res;
4863
4864 // (-x) / y - x / z = -x(1/y+1/z)
4865 case (DAE.SUB(ty), DAE.BINARY(e as DAE.UNARY(operator = DAE.UMINUS(),exp = e1), DAE.DIV(), e2), DAE.BINARY(e3, DAE.DIV(),e4), false, false)
4866 algorithm
4867
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 28 times.
56 true := ExpressionBasics.expEqual(e1,e3);
4868 28 res := DAE.BINARY(e, DAE.MUL(ty), DAE.BINARY(Expression.inverseFactors(e2), DAE.ADD(ty), Expression.inverseFactors(e4)));
4869 then res;
4870
4871
4872 // a*(x op2 b) op1 c*(x op3 d)
4873 // x *(a op2 b op1 c op3 d)
4874 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
4875 algorithm
4876
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 117400 times.
117400 true := Expression.isAddOrSub(op1);
4877
2/2
✓ Branch 1 taken 85070 times.
✓ Branch 2 taken 32330 times.
117400 true := Expression.isMulOrDiv(op2);
4878
2/2
✓ Branch 1 taken 15522 times.
✓ Branch 2 taken 16808 times.
32330 true := Expression.isMulOrDiv(op3);
4879
2/2
✓ Branch 1 taken 16399 times.
✓ Branch 2 taken 409 times.
16808 true := ExpressionBasics.expEqual(e2,e5);
4880 409 then DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,DAE.BINARY(e4,op3,e6)));
4881
4882 // a*x op1 c*x op3 d
4883 // x *(a op1 c op3 d)
4884 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),e2), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
4885 algorithm
4886
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 159222 times.
159222 true := Expression.isAddOrSub(op1);
4887
2/2
✓ Branch 1 taken 77554 times.
✓ Branch 2 taken 81668 times.
159222 true := Expression.isMulOrDiv(op3);
4888
2/2
✓ Branch 1 taken 81574 times.
✓ Branch 2 taken 94 times.
81668 true := ExpressionBasics.expEqual(e2,e5);
4889 94 then DAE.BINARY(e5, oper, DAE.BINARY(e1,op1,DAE.BINARY(e4,op3,e6)));
4890
4891 // a*(x op2 b) op1 c*x
4892 // x*(a op2 b op1 c)
4893 // or
4894 // a*(x op2 b) op1 x*c
4895 // x*(a op2 b op1 c)
4896 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
4897 algorithm
4898
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 212366 times.
212366 true := Expression.isAddOrSub(op1);
4899
2/2
✓ Branch 1 taken 170254 times.
✓ Branch 2 taken 42112 times.
212366 true := Expression.isMulOrDiv(op2);
4900
2/2
✓ Branch 1 taken 229 times.
✓ Branch 2 taken 41883 times.
42112 if ExpressionBasics.expEqual(e2,e5)
4901 then
4902 229 outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
4903
2/2
✓ Branch 1 taken 252 times.
✓ Branch 2 taken 41631 times.
41883 else if ExpressionBasics.expEqual(e2,e4)
4904 then
4905 252 outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
4906 else
4907 41631 fail();
4908 end if;
4909 end if;
4910 then
4911 outExp;
4912
4913 // a*(x op2 b) op1 c*x
4914 // x*(a op2 b op1 c)
4915 // or
4916 // a*(x op2 b) op1 x*c
4917 // x*(a op2 b op1 c)
4918 case (op1, DAE.BINARY(DAE.BINARY(e1,oper as DAE.MUL(_),e2),op2,e3), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
4919 algorithm
4920
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 91302 times.
91302 true := Expression.isAddOrSub(op1);
4921
2/2
✓ Branch 1 taken 70866 times.
✓ Branch 2 taken 20436 times.
91302 true := Expression.isMulOrDiv(op2);
4922
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20436 times.
20436 if ExpressionBasics.expEqual(e2,e5)
4923 then
4924 ✗ outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
4925
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20436 times.
20436 else if ExpressionBasics.expEqual(e2,e4)
4926 then
4927 ✗ outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
4928 else
4929 20436 fail();
4930 end if;
4931 end if;
4932 then
4933 outExp;
4934
4935 case (DAE.SUB(), DAE.RANGE(ty=ty,start = e1,step=oexp,stop=e2), _, _, _)
4936 algorithm
4937 ✗ e1 := simplifyBinary(DAE.BINARY(e1,inOperator2,rhs), inOperator2, e1, rhs);
4938 ✗ e2 := simplifyBinary(DAE.BINARY(e2,inOperator2,rhs), inOperator2, e2, rhs);
4939 ✗ then DAE.RANGE(ty,e1,oexp,e2);
4940
4941 case (DAE.SUB(), _, DAE.RANGE(ty=ty,start = e1,step=oexp,stop=e2), _, _)
4942 algorithm
4943 ✗ e1 := simplifyBinary(DAE.BINARY(lhs,inOperator2,e1), inOperator2, lhs, e1);
4944 ✗ e2 := simplifyBinary(DAE.BINARY(lhs,inOperator2,e1), inOperator2, lhs, e2);
4945 ✗ then DAE.RANGE(ty,e1,oexp,e2);
4946 else origExp;
4947 end matchcontinue;
4948 end simplifyBinarySub;
4949
4950 protected function simplifyBinaryAdd
4951 "simplifyBinary cases for DAE.ADD."
4952 input DAE.Exp origExp;
4953 input Operator inOperator2;
4954 input DAE.Exp lhs;
4955 input DAE.Exp rhs;
4956 input Boolean lhsIsConstValue;
4957 input Boolean rhsIsConstValue;
4958 output DAE.Exp outExp;
4959 algorithm
4960 outExp := matchcontinue (inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue)
4961 local
4962 DAE.Exp e1_1,e3,e,e1,e2,e4,e5,e6,res,one;
4963 Operator oper, op1 ,op2, op3, op;
4964 Type ty,ty2,tp,tp2;
4965 list<DAE.Exp> exp_lst,exp_lst_1;
4966 Boolean b,b2;
4967 Real r, r1;
4968 Option<DAE.Exp> oexp;
4969
4970 // |e1| op2 |e2| => |e1 op2 e2|
4971 case(op2, DAE.CALL(path=Absyn.IDENT("abs"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("abs"),expLst={e2}), _, _)
4972 algorithm
4973
1/2
✓ Branch 1 taken 167 times.
✗ Branch 2 not taken.
167 true := Expression.isMulOrDiv(op2);
4974 ✗ ty := Expression.typeof(e1);
4975 ✗ res := DAE.BINARY(e1, op2, e2);
4976 ✗ then Expression.makePureBuiltinCall("abs",{res},ty);
4977
4978 // a + a = 2*a
4979 case (DAE.ADD(ty = ty), e1, e2, _, _)
4980 algorithm
4981
2/2
✓ Branch 1 taken 348834 times.
✓ Branch 2 taken 8624466 times.
8973300 true := Types.isRealOrSubTypeReal(ty);
4982
2/2
✓ Branch 1 taken 8623938 times.
✓ Branch 2 taken 528 times.
8624466 true := ExpressionBasics.expEqual(e1,e2);
4983 528 e := Expression.makeConstNumber(ty, 2);
4984 528 then DAE.BINARY(e,DAE.MUL(ty),e1);
4985
4986 // (if b then x1 else y1) op (if b then x2 else y2)
4987 // => (if b then x1 op x2 else y1 op y2)
4988 case (op1, DAE.IFEXP(expCond = e1,expThen = e2,expElse = e3), DAE.IFEXP(expCond = e4,expThen = e5,expElse = e6), _, _)
4989 algorithm
4990
1/2
✓ Branch 1 taken 179 times.
✗ Branch 2 not taken.
179 true := ExpressionBasics.expEqual(e1,e4);
4991 ✗ e := DAE.BINARY(e2,op1,e5);
4992 ✗ res := DAE.BINARY(e3,op1,e6);
4993 ✗ then DAE.IFEXP(e1,e,res);
4994
4995
4996 // a*(x op2 b) op1 c*(x op3 d)
4997 // x *(a op2 b op1 c op3 d)
4998 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
4999 algorithm
5000
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1003359 times.
1003359 true := Expression.isAddOrSub(op1);
5001
2/2
✓ Branch 1 taken 669933 times.
✓ Branch 2 taken 333426 times.
1003359 true := Expression.isMulOrDiv(op2);
5002
2/2
✓ Branch 1 taken 178185 times.
✓ Branch 2 taken 155241 times.
333426 true := Expression.isMulOrDiv(op3);
5003
2/2
✓ Branch 1 taken 154590 times.
✓ Branch 2 taken 651 times.
155241 true := ExpressionBasics.expEqual(e2,e5);
5004 651 then DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,DAE.BINARY(e4,op3,e6)));
5005
5006 // a*x op1 c*x op3 d
5007 // x *(a op1 c op3 d)
5008 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),e2), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
5009 algorithm
5010
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1579878 times.
1579878 true := Expression.isAddOrSub(op1);
5011
2/2
✓ Branch 1 taken 1191760 times.
✓ Branch 2 taken 388118 times.
1579878 true := Expression.isMulOrDiv(op3);
5012
2/2
✓ Branch 1 taken 386929 times.
✓ Branch 2 taken 1189 times.
388118 true := ExpressionBasics.expEqual(e2,e5);
5013 1189 then DAE.BINARY(e5, oper, DAE.BINARY(e1,op1,DAE.BINARY(e4,op3,e6)));
5014
5015 // a*(x op2 b) op1 c*x
5016 // x*(a op2 b op1 c)
5017 // or
5018 // a*(x op2 b) op1 x*c
5019 // x*(a op2 b op1 c)
5020 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
5021 algorithm
5022
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1415655 times.
1415655 true := Expression.isAddOrSub(op1);
5023
2/2
✓ Branch 1 taken 1010181 times.
✓ Branch 2 taken 405474 times.
1415655 true := Expression.isMulOrDiv(op2);
5024
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 405469 times.
405474 if ExpressionBasics.expEqual(e2,e5)
5025 then
5026 5 outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
5027
2/2
✓ Branch 1 taken 110084 times.
✓ Branch 2 taken 295385 times.
405469 else if ExpressionBasics.expEqual(e2,e4)
5028 then
5029 110084 outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
5030 else
5031 295385 fail();
5032 end if;
5033 end if;
5034 then
5035 outExp;
5036
5037 // a*(x op2 b) op1 c*x
5038 // x*(a op2 b op1 c)
5039 // or
5040 // a*(x op2 b) op1 x*c
5041 // x*(a op2 b op1 c)
5042 case (op1, DAE.BINARY(DAE.BINARY(e1,oper as DAE.MUL(_),e2),op2,e3), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
5043 algorithm
5044
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 263256 times.
263256 true := Expression.isAddOrSub(op1);
5045
2/2
✓ Branch 1 taken 229458 times.
✓ Branch 2 taken 33798 times.
263256 true := Expression.isMulOrDiv(op2);
5046
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33798 times.
33798 if ExpressionBasics.expEqual(e2,e5)
5047 then
5048 ✗ outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
5049
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 33787 times.
33798 else if ExpressionBasics.expEqual(e2,e4)
5050 then
5051 11 outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
5052 else
5053 33787 fail();
5054 end if;
5055 end if;
5056 then
5057 outExp;
5058
5059 case (DAE.ADD(), DAE.RANGE(ty=ty,start = e1,step=oexp,stop=e2), _, _, _)
5060 algorithm
5061 ✗ e1 := simplifyBinary(DAE.BINARY(e1,inOperator2,rhs), inOperator2, e1, rhs);
5062 ✗ e2 := simplifyBinary(DAE.BINARY(e2,inOperator2,rhs), inOperator2, e2, rhs);
5063 ✗ then DAE.RANGE(ty,e1,oexp,e2);
5064
5065 case (DAE.ADD(), _, DAE.RANGE(ty=ty,start = e1,step=oexp,stop=e2), _, _)
5066 algorithm
5067 ✗ e1 := simplifyBinary(DAE.BINARY(lhs,inOperator2,e1), inOperator2, lhs, e1);
5068 ✗ e2 := simplifyBinary(DAE.BINARY(lhs,inOperator2,e1), inOperator2, lhs, e2);
5069 ✗ then DAE.RANGE(ty,e1,oexp,e2);
5070 else origExp;
5071 end matchcontinue;
5072 end simplifyBinaryAdd;
5073
5074 protected function simplifyBinaryPow
5075 "simplifyBinary cases for DAE.POW."
5076 input DAE.Exp origExp;
5077 input Operator inOperator2;
5078 input DAE.Exp lhs;
5079 input DAE.Exp rhs;
5080 input Boolean lhsIsConstValue;
5081 input Boolean rhsIsConstValue;
5082 output DAE.Exp outExp;
5083 algorithm
5084 outExp := matchcontinue (inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue)
5085 local
5086 DAE.Exp e1_1,e3,e,e1,e2,e4,e5,e6,res,one;
5087 Operator oper, op1 ,op2, op3, op;
5088 Type ty,ty2,tp,tp2;
5089 list<DAE.Exp> exp_lst,exp_lst_1;
5090 Boolean b,b2;
5091 Real r, r1;
5092 Option<DAE.Exp> oexp;
5093
5094 // |e1| op2 |e2| => |e1 op2 e2|
5095 case(op2, DAE.CALL(path=Absyn.IDENT("abs"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("abs"),expLst={e2}), _, _)
5096 algorithm
5097 ✗ true := Expression.isMulOrDiv(op2);
5098 ✗ ty := Expression.typeof(e1);
5099 ✗ res := DAE.BINARY(e1, op2, e2);
5100 ✗ then Expression.makePureBuiltinCall("abs",{res},ty);
5101 // (-x)^2 = x^2
5102 case (op2 as DAE.POW(), DAE.UNARY(operator = DAE.UMINUS(),exp = e1), e2 as DAE.RCONST(2.0), _, _)
5103 367 then DAE.BINARY(e1, op2, e2);
5104
5105 // e ^ 1 => e
5106 case (DAE.POW(), e1, e, _, true)
5107 algorithm
5108
2/2
✓ Branch 1 taken 1727901 times.
✓ Branch 2 taken 21402 times.
1749303 true := Expression.isConstOne(e);
5109 then e1;
5110
5111 // e ^ - 1 => 1 / e
5112 case (DAE.POW(ty = tp), e2, e, _, _)
5113 algorithm
5114
2/2
✓ Branch 1 taken 1748229 times.
✓ Branch 2 taken 8182 times.
1756411 true := Expression.isConstMinusOne(e);
5115 8182 one := Expression.makeConstOne(tp);
5116 8182 then DAE.BINARY(one,DAE.DIV(DAE.T_REAL_DEFAULT),e2);
5117
5118 // e ^ 0 => 1
5119 case (DAE.POW(), e1, e, _, true)
5120 algorithm
5121
2/2
✓ Branch 1 taken 1719234 times.
✓ Branch 2 taken 485 times.
1719719 true := Expression.isZero(e);
5122 485 tp := Expression.typeof(e1);
5123 485 then Expression.makeConstOne(tp);
5124
5125 // sqrt(e) ^ 2.0 => e
5126 case (DAE.POW(), DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={e}), DAE.RCONST(2.0), _, _)
5127 then e;
5128 // phi: assert(e >= 0)?
5129
5130 // sqrt(e) ^ r => e ^ 0.5*r
5131 case (oper as DAE.POW(), DAE.CALL(path=Absyn.IDENT("sqrt"),expLst={e1}), e, _, _)
5132 ✗ then DAE.BINARY(e1,oper,DAE.BINARY(DAE.RCONST(0.5),DAE.MUL(DAE.T_REAL_DEFAULT),e));
5133
5134
5135 // 1 ^ e => 1
5136 case (DAE.POW(), e1, _, true, _)
5137 algorithm
5138
1/2
✓ Branch 1 taken 187 times.
✗ Branch 2 not taken.
187 true := Expression.isConstOne(e1);
5139 then e1;
5140
5141 // (if b then x1 else y1) op (if b then x2 else y2)
5142 // => (if b then x1 op x2 else y1 op y2)
5143 case (op1, DAE.IFEXP(expCond = e1,expThen = e2,expElse = e3), DAE.IFEXP(expCond = e4,expThen = e5,expElse = e6), _, _)
5144 algorithm
5145 ✗ true := ExpressionBasics.expEqual(e1,e4);
5146 ✗ e := DAE.BINARY(e2,op1,e5);
5147 ✗ res := DAE.BINARY(e3,op1,e6);
5148 ✗ then DAE.IFEXP(e1,e,res);
5149
5150
5151 // a*(x op2 b) op1 c*(x op3 d)
5152 // x *(a op2 b op1 c op3 d)
5153 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
5154 algorithm
5155 ✗ true := Expression.isAddOrSub(op1);
5156 ✗ true := Expression.isMulOrDiv(op2);
5157 ✗ true := Expression.isMulOrDiv(op3);
5158 ✗ true := ExpressionBasics.expEqual(e2,e5);
5159 ✗ then DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,DAE.BINARY(e4,op3,e6)));
5160
5161 // a*x op1 c*x op3 d
5162 // x *(a op1 c op3 d)
5163 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),e2), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
5164 algorithm
5165 ✗ true := Expression.isAddOrSub(op1);
5166 ✗ true := Expression.isMulOrDiv(op3);
5167 ✗ true := ExpressionBasics.expEqual(e2,e5);
5168 ✗ then DAE.BINARY(e5, oper, DAE.BINARY(e1,op1,DAE.BINARY(e4,op3,e6)));
5169
5170 // a*(x op2 b) op1 c*x
5171 // x*(a op2 b op1 c)
5172 // or
5173 // a*(x op2 b) op1 x*c
5174 // x*(a op2 b op1 c)
5175 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
5176 algorithm
5177 ✗ true := Expression.isAddOrSub(op1);
5178 ✗ true := Expression.isMulOrDiv(op2);
5179 ✗ if ExpressionBasics.expEqual(e2,e5)
5180 then
5181 ✗ outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
5182 ✗ else if ExpressionBasics.expEqual(e2,e4)
5183 then
5184 ✗ outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
5185 else
5186 ✗ fail();
5187 end if;
5188 end if;
5189 then
5190 outExp;
5191
5192 // a*(x op2 b) op1 c*x
5193 // x*(a op2 b op1 c)
5194 // or
5195 // a*(x op2 b) op1 x*c
5196 // x*(a op2 b op1 c)
5197 case (op1, DAE.BINARY(DAE.BINARY(e1,oper as DAE.MUL(_),e2),op2,e3), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
5198 algorithm
5199 ✗ true := Expression.isAddOrSub(op1);
5200 ✗ true := Expression.isMulOrDiv(op2);
5201 ✗ if ExpressionBasics.expEqual(e2,e5)
5202 then
5203 ✗ outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
5204 ✗ else if ExpressionBasics.expEqual(e2,e4)
5205 then
5206 ✗ outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
5207 else
5208 ✗ fail();
5209 end if;
5210 end if;
5211 then
5212 outExp;
5213
5214 // ticket #9575
5215 // For fractional exponents, i.e. roots, only distribute over non-negative factors
5216 case (DAE.POW(), e1, e2 as DAE.RCONST(r), _, true) guard r <> intReal(realInt(r))
5217 algorithm
5218 /*
5219 * Only do this for constant exponent and any constant expression.
5220 * Exponentation is very expensive compared to the inner expressions.
5221 */
5222
5/6
✗ Branch 1 not taken.
✓ Branch 2 taken 313701 times.
✓ Branch 3 taken 275905 times.
✓ Branch 4 taken 37796 times.
✓ Branch 5 taken 19021 times.
✓ Branch 6 taken 18775 times.
313701 exp_lst as (_ :: _ :: _ :: _) := Expression.factors(e1);
5223
2/2
✓ Branch 1 taken 18687 times.
✓ Branch 2 taken 88 times.
18775 true := List.any(exp_lst, Expression.isEvaluatedConst);
5224 88 (exp_lst, exp_lst_1) := List.splitOnTrue(exp_lst, Expression.isPositiveOrZero);
5225 88 exp_lst := simplifyBinaryDistributePow(exp_lst, e2);
5226 88 e := Expression.makeProductLst(exp_lst_1);
5227 88 e := DAE.BINARY(e, inOperator2, e2);
5228 88 outExp := Expression.makeProductLst(e :: exp_lst);
5229 then outExp;
5230
5231 // (a1a2...an)^e2 => a1^e2a2^e2..an^e2
5232 case (DAE.POW(), e1, e2, _, true) guard Expression.isEvaluatedConst(e2)
5233 algorithm
5234 /*
5235 * Only do this for constant exponent and any constant expression.
5236 * Exponentation is very expensive compared to the inner expressions.
5237 */
5238
5/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1719090 times.
✓ Branch 3 taken 1578391 times.
✓ Branch 4 taken 140699 times.
✓ Branch 5 taken 114488 times.
✓ Branch 6 taken 26211 times.
1719090 exp_lst as (_ :: _ :: _ :: _) := Expression.factors(e1);
5239
2/2
✓ Branch 1 taken 25641 times.
✓ Branch 2 taken 570 times.
26211 true := List.any(exp_lst,Expression.isEvaluatedConst);
5240 570 exp_lst_1 := simplifyBinaryDistributePow(exp_lst, e2);
5241 570 then Expression.makeProductLst(exp_lst_1);
5242
5243 // ticket #6068 (second issue)
5244 // (e1^e2)^e3 => abs(e1)^(e2*e3) if e2 is even but e2*e3 is not
5245 case (DAE.POW(), DAE.BINARY(e1,DAE.POW(),e2), e3, _, _) guard Expression.isEven(e2)
5246 algorithm
5247
1/2
✓ Branch 1 taken 4608 times.
✗ Branch 2 not taken.
4608 if Expression.isEvaluatedConst(e3) then
5248 4608 e := simplifyBinaryConst(DAE.MUL(DAE.T_REAL_DEFAULT), e2, e3);
5249
2/2
✓ Branch 1 taken 4527 times.
✓ Branch 2 taken 81 times.
4608 false := Expression.isEven(e);
5250 else
5251 ✗ e := DAE.BINARY(e2,DAE.MUL(DAE.T_REAL_DEFAULT),e3);
5252 end if;
5253 81 then DAE.BINARY(Expression.makePureBuiltinCall("abs", {e1}, Expression.typeof(e1)),DAE.POW(DAE.T_REAL_DEFAULT), e);
5254
5255 // (e1^e2)^e3 => e1^(e2*e3)
5256 case (DAE.POW(), DAE.BINARY(e1,DAE.POW(),e2), e3, _, _)
5257 4808 then DAE.BINARY(e1,DAE.POW(DAE.T_REAL_DEFAULT),DAE.BINARY(e2,DAE.MUL(DAE.T_REAL_DEFAULT),e3));
5258 else origExp;
5259 end matchcontinue;
5260 end simplifyBinaryPow;
5261
5262 protected function simplifyBinaryOther
5263 "simplifyBinary cases for any other operator."
5264 input DAE.Exp origExp;
5265 input Operator inOperator2;
5266 input DAE.Exp lhs;
5267 input DAE.Exp rhs;
5268 input Boolean lhsIsConstValue;
5269 input Boolean rhsIsConstValue;
5270 output DAE.Exp outExp;
5271 algorithm
5272 outExp := matchcontinue (inOperator2, lhs, rhs, lhsIsConstValue, rhsIsConstValue)
5273 local
5274 DAE.Exp e1_1,e3,e,e1,e2,e4,e5,e6,res,one;
5275 Operator oper, op1 ,op2, op3, op;
5276 Type ty,ty2,tp,tp2;
5277 list<DAE.Exp> exp_lst,exp_lst_1;
5278 Boolean b,b2;
5279 Real r, r1;
5280 Option<DAE.Exp> oexp;
5281
5282 // |e1| op2 |e2| => |e1 op2 e2|
5283 case(op2, DAE.CALL(path=Absyn.IDENT("abs"),expLst={e1}), DAE.CALL(path=Absyn.IDENT("abs"),expLst={e2}), _, _)
5284 algorithm
5285 ✗ true := Expression.isMulOrDiv(op2);
5286 ✗ ty := Expression.typeof(e1);
5287 ✗ res := DAE.BINARY(e1, op2, e2);
5288 ✗ then Expression.makePureBuiltinCall("abs",{res},ty);
5289
5290 // (if b then x1 else y1) op (if b then x2 else y2)
5291 // => (if b then x1 op x2 else y1 op y2)
5292 case (op1, DAE.IFEXP(expCond = e1,expThen = e2,expElse = e3), DAE.IFEXP(expCond = e4,expThen = e5,expElse = e6), _, _)
5293 algorithm
5294
1/2
✓ Branch 1 taken 93 times.
✗ Branch 2 not taken.
93 true := ExpressionBasics.expEqual(e1,e4);
5295 ✗ e := DAE.BINARY(e2,op1,e5);
5296 ✗ res := DAE.BINARY(e3,op1,e6);
5297 ✗ then DAE.IFEXP(e1,e,res);
5298
5299
5300 // a*(x op2 b) op1 c*(x op3 d)
5301 // x *(a op2 b op1 c op3 d)
5302 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
5303 algorithm
5304 ✗ true := Expression.isAddOrSub(op1);
5305 ✗ true := Expression.isMulOrDiv(op2);
5306 ✗ true := Expression.isMulOrDiv(op3);
5307 ✗ true := ExpressionBasics.expEqual(e2,e5);
5308 ✗ then DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,DAE.BINARY(e4,op3,e6)));
5309
5310 // a*x op1 c*x op3 d
5311 // x *(a op1 c op3 d)
5312 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),e2), DAE.BINARY(e4,DAE.MUL(_),DAE.BINARY(e5,op3,e6)), false, false)
5313 algorithm
5314 ✗ true := Expression.isAddOrSub(op1);
5315 ✗ true := Expression.isMulOrDiv(op3);
5316 ✗ true := ExpressionBasics.expEqual(e2,e5);
5317 ✗ then DAE.BINARY(e5, oper, DAE.BINARY(e1,op1,DAE.BINARY(e4,op3,e6)));
5318
5319 // a*(x op2 b) op1 c*x
5320 // x*(a op2 b op1 c)
5321 // or
5322 // a*(x op2 b) op1 x*c
5323 // x*(a op2 b op1 c)
5324 case (op1, DAE.BINARY(e1,oper as DAE.MUL(_),DAE.BINARY(e2,op2,e3)), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
5325 algorithm
5326 ✗ true := Expression.isAddOrSub(op1);
5327 ✗ true := Expression.isMulOrDiv(op2);
5328 ✗ if ExpressionBasics.expEqual(e2,e5)
5329 then
5330 ✗ outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
5331 ✗ else if ExpressionBasics.expEqual(e2,e4)
5332 then
5333 ✗ outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
5334 else
5335 ✗ fail();
5336 end if;
5337 end if;
5338 then
5339 outExp;
5340
5341 // a*(x op2 b) op1 c*x
5342 // x*(a op2 b op1 c)
5343 // or
5344 // a*(x op2 b) op1 x*c
5345 // x*(a op2 b op1 c)
5346 case (op1, DAE.BINARY(DAE.BINARY(e1,oper as DAE.MUL(_),e2),op2,e3), DAE.BINARY(e4,DAE.MUL(),e5), false, false)
5347 algorithm
5348 ✗ true := Expression.isAddOrSub(op1);
5349 ✗ true := Expression.isMulOrDiv(op2);
5350 ✗ if ExpressionBasics.expEqual(e2,e5)
5351 then
5352 ✗ outExp := DAE.BINARY(e5, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e4));
5353 ✗ else if ExpressionBasics.expEqual(e2,e4)
5354 then
5355 ✗ outExp := DAE.BINARY(e4, oper, DAE.BINARY(DAE.BINARY(e1,op2,e3),op1,e5));
5356 else
5357 ✗ fail();
5358 end if;
5359 end if;
5360 then
5361 outExp;
5362 else origExp;
5363 end matchcontinue;
5364 end simplifyBinaryOther;
5365
5366 protected function simplifyTwoBinaryExpressions
5367 "This function simplifies a binary expression of two binary expressions:
5368 (e1 lhsOp e2) mainOp (e3 rhsOp e4)
5369 "
5370 input DAE.Exp e1;
5371 input Operator lhsOperator;
5372 input DAE.Exp e2;
5373 input Operator mainOperator;
5374 input DAE.Exp e3;
5375 input Operator rhsOperator;
5376 input DAE.Exp e4;
5377 input Boolean expEqual_e1_e3;
5378 input Boolean expEqual_e1_e4;
5379 input Boolean expEqual_e2_e3;
5380 input Boolean expEqual_e2_e4;
5381 input Boolean isConst_e1;
5382 input Boolean isConst_e2;
5383 input Boolean isConst_e3;
5384 input Boolean operatorEqualLhsRhs;
5385 output DAE.Exp outExp;
5386 algorithm
5387 outExp := match (e1, lhsOperator, e2, mainOperator, e3, rhsOperator, e4, expEqual_e1_e3, expEqual_e1_e4, expEqual_e2_e3, expEqual_e2_e4, isConst_e1, isConst_e2, operatorEqualLhsRhs)
5388 local
5389 DAE.Exp e1_1,e,e_1,e_2,e_3,e_4,e_5,e_6,res,one;
5390 Operator op1 ,op2, op3, op;
5391 Type ty;
5392
5393 // (e*e1) + (e*e2) => e*(e1+e2)
5394 case (_, op2 as DAE.MUL(), _, op1 as DAE.ADD(), _, DAE.MUL(), _, true, _, _, _, _, _, _)
5395 174211 then DAE.BINARY(e1,op2,DAE.BINARY(e2,op1,e4));
5396
5397 // (e*e1) + (e2*e) = e*(e1+e2)
5398 case (_, op2 as DAE.MUL(), _, op1 as DAE.ADD(), _, DAE.MUL(), _, _, true, _, _, _, _, _)
5399 613 then DAE.BINARY(e1,op2,DAE.BINARY(e2,op1,e3));
5400
5401 // (e1*e) + (e*e4) = e*(e1+e2)
5402 case (_, op2 as DAE.MUL(), _, op1 as DAE.ADD(), _, DAE.MUL(), _, _, _, true, _, _, _, _)
5403 555690 then DAE.BINARY(e2,op2,DAE.BINARY(e1,op1,e4));
5404
5405 // (e1*e) + (e*e4) = e*(e1+e2)
5406 case (_, op2 as DAE.MUL(), _, op1 as DAE.ADD(), _, DAE.MUL(), _, _, _, _, true, _, _, _)
5407 279 then DAE.BINARY(e2,op2,DAE.BINARY(e1,op1,e3));
5408
5409 // a^e*b^e => (a*b)^e
5410 case (_, DAE.POW(), _, DAE.MUL(), _, DAE.POW(), _, _, _, _, true, _, _, _)
5411 algorithm
5412 7464 res := DAE.BINARY(DAE.BINARY(e1,mainOperator,e3),lhsOperator,e2);
5413 then res;
5414
5415 // a^e/b^e => (a/b)^e
5416 case (_, DAE.POW(), _, DAE.DIV(), _, DAE.POW(), _, _, _, _, true, _, _, _)
5417 algorithm
5418 996 res := DAE.BINARY(DAE.BINARY(e1,mainOperator,e3),lhsOperator,e2);
5419 then res;
5420
5421 // a^e1*a^e2 => a^(e1+e2)
5422 case (_, DAE.POW(), _, DAE.MUL(), _, DAE.POW(), _, true, _, _, _, _, _, _)
5423 algorithm
5424 18 res := Expression.expAdd(e2,e4);
5425 18 res := Expression.expPow(e1,res);
5426 then res;
5427
5428 // a^e1/a^e2 => a^(e1-e2)
5429 case (_, DAE.POW(), _, DAE.DIV(), _, DAE.POW(), _, true, _, _, _, _, _, _)
5430 algorithm
5431 325 res := Expression.expSub(e2,e4);
5432 325 res := Expression.expPow(e1,res);
5433 then res;
5434
5435 // (e1 op2 e2) op1 (e3 op3 e4) => (e1 op1 e3) op2 e2
5436 // e2 = e4; op2=op3 \in {*, /}; op1 \in {+, -}
5437 case (_, op2, _, op1, _, _, _, _, _, _, true, _, false, true)
5438 guard Expression.isAddOrSub(op1) and Expression.isMulOrDiv(op2)
5439 2009 then
5440 DAE.BINARY(DAE.BINARY(e1,op1,e3),op2,e4);
5441
5442 // (e1 * e2) op1 (e3 / e4) => (e1 * e2) op1 (e1 * (1/ e4) ) => e1*(e2 op1 (1/ e4))
5443 // e1 = e3; op1 \in {+, -}
5444 case (_, op as DAE.MUL(ty), _, op1, _, DAE.DIV(_), _, true, _, _, _, false, _, _)
5445 guard Expression.isAddOrSub(op1)
5446 algorithm
5447 2 one := Expression.makeConstOne(ty);
5448 2 e := Expression.makeDiv(one,e4);
5449 2 then
5450 DAE.BINARY(DAE.BINARY(e2,op1,e),op,e1);
5451
5452 // (e1 / e2) op1 (e3 * e4) => (e1 * (1/e2)) op1 (e1 * e4 ) => e1*(1/e2 op1 e4)
5453 // e1 = e3; op1 \in {+, -}
5454 case (_, DAE.DIV(ty), _, op1, _, DAE.MUL(_), _, true, _, _, _, false, _, _)
5455 guard Expression.isAddOrSub(op1)
5456 algorithm
5457 19 one := Expression.makeConstOne(ty);
5458 19 e := Expression.makeDiv(one,e2);
5459 19 then
5460 DAE.BINARY(DAE.BINARY(e,op1,e4),DAE.MUL(ty),e1);
5461
5462 // [x op2 e] op1 [y op2 e] => (x op1 y) op2 e
5463 // op2 \in {*, /}; op1 \in {+, -}
5464 case (e1_1, op2, e_3, op1, e, _, _, _, _, _, true, _, false, true)
5465 guard Expression.isAddOrSub(op1) and Expression.isMulOrDiv(op2)
5466 algorithm
5467 ✗ res := DAE.BINARY(e1_1,op1,e);
5468 ✗ then DAE.BINARY(res,op2,e_3);
5469
5470 // [(e1 op2 e) * e3] op1 [e4 op2 e] => (e1*e3 op1 e4) op2 e
5471 // op2 \in {*, /}; op1 \in {+, -}
5472 case (DAE.BINARY(e_1,op2,e_2), op as DAE.MUL(_), e_3, op1, e, op3, e_6, _, _, _, _, _, _, _)
5473 guard (not Expression.isConstValue(e_2)) and ExpressionBasics.expEqual(e_2,e_6) and Expression.operatorEqual(op2,op3) and Expression.isAddOrSub(op1)
5474 and Expression.isMulOrDiv(op2)
5475 algorithm
5476 1183 e1_1 := DAE.BINARY(e_1, op,e_3);
5477 1183 res := DAE.BINARY(e1_1,op1,e);
5478 1183 then DAE.BINARY(res,op2,e_2);
5479
5480 // [(e1 op2 e) * e3] op1 [(e4 op2 e) * e6] => (e1*e3 op1 e4*e6) op2 e
5481 // op2 \in {*, /}; op1 \in {+, -}
5482 case (DAE.BINARY(e_1,op2,e_2), op as DAE.MUL(_), e_3, op1, DAE.BINARY(e_4,op3,e_5), DAE.MUL(_), e_6, _, _, _, _, _, _, _)
5483 guard (not Expression.isConstValue(e_2)) and ExpressionBasics.expEqual(e_2,e_5) and Expression.operatorEqual(op2,op3) and Expression.isAddOrSub(op1)
5484 and Expression.isMulOrDiv(op2)
5485 algorithm
5486 484 e1_1 := DAE.BINARY(e_1, op,e_3);
5487 484 e := DAE.BINARY(e_4, op,e_6);
5488 484 res := DAE.BINARY(e1_1,op1,e);
5489 484 then DAE.BINARY(res,op2,e_2);
5490
5491 // [e1 op2 e] op1 [(e4 op2 e) * e6] => (e1 op1 e4*e6) op2 e
5492 // op2 \in {*, /}; op1 \in {+, -}
5493 case (e_1, op2, e_3, op1, DAE.BINARY(e_4,op3,e_5), op as DAE.MUL(_), e_6, _, _, _, _, _, false, _)
5494 guard ExpressionBasics.expEqual(e_3,e_5) and Expression.operatorEqual(op2,op3) and Expression.isAddOrSub(op1)
5495 and Expression.isMulOrDiv(op2)
5496 algorithm
5497 2512 e := DAE.BINARY(e_4,op,e_6);
5498 2512 res := DAE.BINARY(e_1,op1,e);
5499 2512 then DAE.BINARY(res,op2,e_3);
5500
5501 // (e*e1) - (e*e2) => e*(e1-e2)
5502 case (_, DAE.MUL(), _, DAE.SUB(), _, DAE.MUL(), _, true, _, _, _, _, _, _)
5503 31262 then DAE.BINARY(e1,lhsOperator,DAE.BINARY(e2,mainOperator,e4));
5504
5505 // (e*e1) - (e2*e) => e*(e1-e2)
5506 case (_, DAE.MUL(), _, DAE.SUB(), _, DAE.MUL(), _, _, true, _, _, _, _, _)
5507 151 then DAE.BINARY(e1,lhsOperator,DAE.BINARY(e2,mainOperator,e3));
5508
5509 end match;
5510 end simplifyTwoBinaryExpressions;
5511
5512 protected function simplifyLBinary
5513 "This function simplifies logical binary expressions."
5514 input DAE.Exp origExp;
5515 input Operator inOperator2;
5516 input DAE.Exp inExp3 "Note: already simplified"; // lhs
5517 input DAE.Exp inExp4 "Note: aldready simplified"; // rhs
5518 output DAE.Exp outExp;
5519 algorithm
5520 outExp := match (inOperator2, inExp3, inExp4)
5521 local
5522 DAE.Exp e1,e2;
5523 Boolean b;
5524
5525 // fix for PNLib where "{} and not {}" is evaluated
5526 case (_, DAE.ARRAY(array={}), _)
5527 then origExp;
5528 case (_, _, DAE.ARRAY(array={}))
5529 then origExp;
5530 // a AND not a -> false
5531 case (DAE.AND(DAE.T_BOOL()), e1, DAE.LUNARY(DAE.NOT(_),e2))
5532 guard ExpressionBasics.expEqual(e1, e2)
5533 then DAE.BCONST(false);
5534 case (DAE.AND(DAE.T_BOOL()), DAE.LUNARY(DAE.NOT(_),e1), e2)
5535 guard ExpressionBasics.expEqual(e1, e2)
5536 then DAE.BCONST(false);
5537
5538 // a OR not a -> true
5539 case (DAE.OR(DAE.T_BOOL()), e1, DAE.LUNARY(DAE.NOT(_),e2))
5540 guard ExpressionBasics.expEqual(e1, e2)
5541 then DAE.BCONST(true);
5542 case (DAE.OR(DAE.T_BOOL()), DAE.LUNARY(DAE.NOT(_),e1), e2)
5543 guard ExpressionBasics.expEqual(e1, e2)
5544 then DAE.BCONST(true);
5545
5546 // true AND e => e
5547
2/2
✓ Branch 0 taken 715 times.
✓ Branch 1 taken 1695 times.
2410 case (DAE.AND(_), e1 as DAE.BCONST(b), e2) then if b then e2 else e1;
5548
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 94 times.
172 case (DAE.AND(_), e1, e2 as DAE.BCONST(b)) then if b then e1 else e2;
5549 // false OR e => e
5550
2/2
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 348 times.
587 case (DAE.OR(_), e1 as DAE.BCONST(b), e2) then if b then e1 else e2;
5551
2/2
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 32 times.
215 case (DAE.OR(_), e1, e2 as DAE.BCONST(b)) then if b then e2 else e1;
5552
5553 // a AND a -> a
5554 case (DAE.AND(_), e1, e2)
5555 guard ExpressionBasics.expEqual(e1, e2)
5556 then e1;
5557 // a OR a -> a
5558 case (DAE.OR(_), e1, e2)
5559 guard ExpressionBasics.expEqual(e1, e2)
5560 then e1;
5561
5562 else origExp;
5563
5564 end match;
5565 end simplifyLBinary;
5566
5567 protected function simplifyRelation
5568 "This function simplifies logical binary expressions."
5569 input DAE.Exp origExp;
5570 input Operator inOperator2;
5571 input DAE.Exp inExp3 "Note: already simplified"; // lhs
5572 input DAE.Exp inExp4 "Note: aldready simplified"; // rhs
5573 input Integer index;
5574 input Option<tuple<DAE.Exp,Integer,Integer>> optionExpisASUB;
5575 output DAE.Exp outExp;
5576 algorithm
5577 outExp := matchcontinue (inOperator2, inExp3, inExp4)
5578 local
5579 DAE.Exp e1,e2;
5580 Operator oper;
5581 DAE.ComponentRef cr1,cr2;
5582 Boolean b ;
5583
5584 // constants
5585 case (oper, e1, e2)
5586 algorithm
5587
2/2
✓ Branch 1 taken 505595 times.
✓ Branch 2 taken 27159 times.
532754 true := Expression.isConstValue(e1);
5588
2/2
✓ Branch 1 taken 15416 times.
✓ Branch 2 taken 11743 times.
27159 true := Expression.isConstValue(e2);
5589 11743 b := simplifyRelationConst(oper, e1, e2);
5590
2/2
✓ Branch 0 taken 5376 times.
✓ Branch 1 taken 6367 times.
17119 then DAE.BCONST(b);
5591
5592 // relation: cr1 == cr2, where cr1 and cr2 are the same
5593 case (DAE.EQUAL(_), DAE.CREF(cr1,_), DAE.CREF(cr2,_))
5594 algorithm
5595
2/2
✓ Branch 1 taken 14799 times.
✓ Branch 2 taken 1 time.
14800 true := ComponentReferenceBasics.crefEqual(cr1,cr2);
5596 then DAE.BCONST(true);
5597
5598 // relation: cr1 <> cr2 . where cr1 and cr2 are the same
5599 case (DAE.NEQUAL(_), DAE.CREF(cr1,_), DAE.CREF(cr2,_))
5600 algorithm
5601
1/2
✓ Branch 1 taken 2158 times.
✗ Branch 2 not taken.
2158 true := ComponentReferenceBasics.crefEqual(cr1,cr2);
5602 then DAE.BCONST(false);
5603
5604 // a >= b
5605 case(DAE.GREATEREQ(), _, _)
5606 129754 then simplifyRelation2(origExp,inOperator2, inExp3,inExp4);
5607 // a > b
5608 case(DAE.GREATER(), _, _)
5609 121449 then simplifyRelation2(origExp,inOperator2, inExp3,inExp4);
5610 // a <= b
5611 case(DAE.LESSEQ(), _, _)
5612 82311 then simplifyRelation2(origExp,inOperator2, inExp4,inExp3);
5613 // a < b
5614 case(DAE.LESS(), _, _)
5615 92842 then simplifyRelation2(origExp,inOperator2, inExp4,inExp3);
5616
5617 else origExp;
5618
5619 end matchcontinue;
5620 end simplifyRelation;
5621
5622 protected function simplifyRelation2
5623 "This function simplifies logical binary expressions."
5624 input DAE.Exp origExp;
5625 input Operator inOp;
5626 input DAE.Exp lhs "Note: already simplified";
5627 input DAE.Exp rhs "Note: aldready simplified";
5628 output DAE.Exp oExp;
5629 algorithm
5630 426356 (oExp, _) := simplify(Expression.expSub(lhs, rhs));
5631
2/2
✓ Branch 1 taken 212065 times.
✓ Branch 2 taken 214265 times.
426330 if Expression.isGreatereqOrLesseq(inOp) then
5632 // lhs >= rhs holds when lhs - rhs is known to be >= 0.
5633
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 212065 times.
212065 oExp := if Expression.isPositiveOrZero(oExp) then DAE.BCONST(true) else origExp;
5634 else
5635 // lhs > rhs is false when lhs - rhs is known to be <= 0. isNegativeOrZero
5636 // is the structural dual of isPositiveOrZero, so it answers here what
5637 // negating the difference and simplifying it a second time used to.
5638
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 214265 times.
214265 oExp := if Expression.isNegativeOrZero(oExp) then DAE.BCONST(false) else origExp;
5639 end if;
5640 end simplifyRelation2;
5641
5642 protected function simplifyBinaryDistributePow
5643 "author: PA
5644 Distributes the pow operator over a list of expressions.
5645 Removes 1^pow_e
5646 ({e1,e2,..,en} , pow_e) => {e1^pow_e, e2^pow_e,..,en^pow_e}"
5647 input list<DAE.Exp> inExpLst;
5648 input DAE.Exp inExp;
5649 output list<DAE.Exp> outExpLst;
5650 algorithm
5651
5/6
✗ Branch 1 not taken.
✓ Branch 2 taken 2111 times.
✓ Branch 3 taken 2111 times.
✓ Branch 4 taken 658 times.
✓ Branch 5 taken 2111 times.
✓ Branch 6 taken 658 times.
2769 outExpLst := list (DAE.BINARY(e,DAE.POW(Expression.typeof(e)),inExp) for e guard not Expression.isConstOne(e) in inExpLst);
5652 end simplifyBinaryDistributePow;
5653
5654 protected function simplifyUnary
5655 "Simplifies unary expressions."
5656 input DAE.Exp origExp;
5657 input Operator inOperator2;
5658 input DAE.Exp inExp3;
5659 output DAE.Exp outExp;
5660 algorithm
5661 outExp := matchcontinue (inOperator2, inExp3)
5662 local
5663 Type ty1;
5664 DAE.Exp e1,e_1,e2,e3;
5665 Integer i_1,i;
5666 Real r_1,r;
5667 Boolean b1;
5668 DAE.CallAttributes attr;
5669 list<DAE.Exp> expl;
5670 list<list<DAE.Exp>> mat;
5671 Operator op, op2;
5672 Absyn.Path path;
5673
5674 // not true => false, not false => true
5675 case (DAE.NOT(), e1)
5676 algorithm
5677 34046 b1 := Expression.toBool(e1);
5678 b1 := not b1;
5679
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 146 times.
422 then DAE.BCONST(b1);
5680
5681 // not(not(exp)) -> exp
5682 case (DAE.NOT(_), DAE.LUNARY(DAE.NOT(_),e1))
5683 then e1;
5684
5685 // -x => 0 - x
5686 case (DAE.UMINUS(), DAE.ICONST(integer = i))
5687 algorithm
5688 1548 i_1 := intNeg(i);
5689 1548 then DAE.ICONST(i_1);
5690
5691 // -x => 0.0 - x
5692 case (DAE.UMINUS(), DAE.RCONST(real = r))
5693 algorithm
5694 345071 r_1 := realNeg(r);
5695 345071 then DAE.RCONST(r_1);
5696
5697 // -(a * b) => (-a) * b
5698 case (op2 as DAE.UMINUS(), DAE.BINARY(exp1 = e1,operator = op as DAE.MUL(),exp2 = e2))
5699 178908 then DAE.BINARY(DAE.UNARY(op2,e1),op,e2);
5700 // -(a*b) => (-a)*b
5701 case (op2 as DAE.UMINUS_ARR(), DAE.BINARY(exp1 = e1,operator = op as DAE.MUL_ARR(),exp2 = e2))
5702 ✗ then DAE.BINARY(DAE.UNARY(op2,e1),op,e2);
5703 // -0 => 0
5704 case (DAE.UMINUS(), e1)
5705 guard Expression.isZero(e1)
5706 then e1;
5707 case (DAE.UMINUS_ARR(), e1)
5708 guard Expression.isZero(e1)
5709 then e1;
5710 // -(a-b) => b - a
5711 case (DAE.UMINUS(), DAE.BINARY(exp1 = e1,operator = op as DAE.SUB(),exp2 = e2))
5712 21986 then DAE.BINARY(e2,op,e1);
5713 case (DAE.UMINUS_ARR(), DAE.BINARY(exp1 = e1,operator = op as DAE.SUB_ARR(),exp2 = e2))
5714 ✗ then DAE.BINARY(e2,op,e1);
5715 // -(a + b) => -b - a
5716 case (op2 as DAE.UMINUS(), DAE.BINARY(exp1 = e1,operator = op as DAE.ADD(),exp2 = e2))
5717 algorithm
5718
1/2
✗ Branch 4 not taken.
✓ Branch 5 taken 111536 times.
111536 (e_1,true) := simplify1(DAE.BINARY(DAE.UNARY(op2,e1),op,DAE.UNARY(op2,e2)));
5719 then e_1;
5720 case (op2 as DAE.UMINUS_ARR(), DAE.BINARY(exp1 = e1,operator = op as DAE.ADD_ARR(),exp2 = e2))
5721 ✗ then DAE.BINARY(DAE.UNARY(op2,e1),op,DAE.UNARY(op2,e2));
5722 // -( a / b) => (-a) / b
5723 case (op2 as DAE.UMINUS(), DAE.BINARY(exp1 = e1,operator = op as DAE.DIV(),exp2 = e2))
5724 25830 then DAE.BINARY(DAE.UNARY(op2,e1),op,e2);
5725 case (op2 as DAE.UMINUS_ARR(), DAE.BINARY(exp1 = e1,operator = op as DAE.DIV_ARR(),exp2 = e2))
5726 ✗ then DAE.BINARY(DAE.UNARY(op2,e1),op,e2);
5727 // --a => a
5728 case (DAE.UMINUS(), DAE.UNARY(operator = DAE.UMINUS(),exp = e1)) /* --a => a */
5729 then e1;
5730 case (DAE.UMINUS_ARR(), DAE.UNARY(operator = DAE.UMINUS_ARR(),exp = e1)) /* --a => a */
5731 then e1;
5732 // -semiLinear(-x,sb,sa) = semiLinear(x,sa,sb)
5733 case (DAE.UMINUS(), DAE.CALL(path=path as Absyn.IDENT("semiLinear"),expLst={DAE.UNARY(exp=e1),e2,e3},attr=attr))
5734 59 then DAE.CALL(path,{e1,e3,e2},attr);
5735
5736 case (DAE.UMINUS_ARR(), DAE.ARRAY(ty1, b1, expl))
5737 algorithm
5738 4583 expl := List.map(expl, Expression.negate);
5739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4583 times.
4583 then
5740 DAE.ARRAY(ty1, b1, expl);
5741
5742 case (DAE.UMINUS_ARR(), DAE.MATRIX(ty1, i, mat))
5743 algorithm
5744 2 mat := List.mapList(mat, Expression.negate);
5745 2 then
5746 DAE.MATRIX(ty1, i, mat);
5747
5748 else origExp;
5749 end matchcontinue;
5750 end simplifyUnary;
5751
5752 protected function simplifyVectorScalarMatrix "Help function to simplifyVectorScalar,
5753 handles MATRIX expressions"
5754 input list<list<DAE.Exp>> imexpl;
5755 input Operator op;
5756 input DAE.Exp s1;
5757 input Boolean arrayScalar "if true, array op scalar, otherwise scalar op array";
5758 output list<list<DAE.Exp>> outExp;
5759 algorithm
5760
18/18
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 339 times.
✓ Branch 3 taken 152 times.
✓ Branch 4 taken 339 times.
✓ Branch 5 taken 152 times.
✓ Branch 6 taken 783 times.
✓ Branch 7 taken 339 times.
✓ Branch 8 taken 783 times.
✓ Branch 9 taken 339 times.
✓ Branch 12 taken 4 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 4 times.
✓ Branch 15 taken 2 times.
✓ Branch 16 taken 8 times.
✓ Branch 17 taken 4 times.
✓ Branch 18 taken 8 times.
✓ Branch 19 taken 4 times.
1288 outExp := (if arrayScalar then
5761 list(list(DAE.BINARY(e,op,s1) for e in row) for row in imexpl)
5762 else
5763 list(list(DAE.BINARY(s1,op,e) for e in row) for row in imexpl));
5764 end simplifyVectorScalarMatrix;
5765
5766 protected function simplifyBinarySortConstantsMul
5767 "Helper relation to simplifyBinarySortConstants"
5768 input DAE.Exp inExp;
5769 output DAE.Exp outExp;
5770 protected list<DAE.Exp> e_lst, const_es1,notconst_es1;
5771 DAE.Exp res1,res2;
5772 algorithm
5773 ✗ e_lst := Expression.factors(inExp);
5774 //e_lst_1 := List.map(e_lst,simplify2); // simplify2 for recursive
5775 ✗ (const_es1, notconst_es1) :=
5776 List.splitOnTrue(e_lst, Expression.isConst);
5777
5778 ✗ if not listEmpty(const_es1) then
5779 ✗ res1 := simplifyBinaryMulConstants(const_es1);
5780 ✗ (res1,_) := simplify1(res1); // simplify1 for basic constant evaluation.
5781 ✗ res2 := Expression.makeProductLst(notconst_es1); // Cannot simplify this, if const_es1_1 empty => infinite recursion.
5782 ✗ outExp := Expression.expMul(res1,res2);
5783 else
5784 outExp := inExp;
5785 end if;
5786
5787 end simplifyBinarySortConstantsMul;
5788
5789 protected function simplifyBuiltinConstantDer
5790 "returns 0.0 or an array filled with 0.0 if the input is Real, Integer or an array of Real/Integer"
5791 input DAE.Exp inExp "assumes already simplified constant expression";
5792 output DAE.Exp outExp;
5793 algorithm
5794 outExp := match inExp
5795 local
5796 DAE.Exp e;
5797 DAE.Dimensions dims;
5798 case DAE.RCONST(_) then DAE.RCONST(0.0);
5799 case DAE.ICONST(_) then DAE.RCONST(0.0);
5800 case DAE.ARRAY(ty=DAE.T_ARRAY(ty=DAE.T_REAL(), dims=dims))
5801 algorithm
5802 ✗ (e,_) := Expression.makeZeroExpression(dims);
5803 then
5804 e;
5805 case DAE.ARRAY(ty=DAE.T_ARRAY(ty=DAE.T_INTEGER(), dims=dims))
5806 algorithm
5807 ✗ (e,_) := Expression.makeZeroExpression(dims);
5808 then
5809 e;
5810 end match;
5811 end simplifyBuiltinConstantDer;
5812
5813 protected function removeOperatorDimension "Function: removeOperatorDimension
5814 Helper function for simplifyVectorBinary, removes an dimension from the operator.
5815 "
5816 input Operator inop;
5817 output Operator outop;
5818 algorithm outop := match inop
5819 local
5820 Type ty1,ty2;
5821 Boolean b;
5822 Operator op;
5823 case DAE.ADD_ARR(ty=ty1)
5824 algorithm
5825 3106 ty2 := Expression.unliftArray(ty1);
5826 3106 b := DAEUtil.expTypeArray(ty2);
5827
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 3015 times.
3106 op := if b then DAE.ADD_ARR(ty2) else DAE.ADD(ty2);
5828 then op;
5829 case DAE.SUB_ARR(ty=ty1)
5830 algorithm
5831 2663 ty2 := Expression.unliftArray(ty1);
5832 2663 b := DAEUtil.expTypeArray(ty2);
5833
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 2479 times.
2663 op := if b then DAE.SUB_ARR(ty2) else DAE.SUB(ty2);
5834 then op;
5835 case DAE.DIV_ARR(ty=ty1)
5836 algorithm
5837 29 ty2 := Expression.unliftArray(ty1);
5838 29 b := DAEUtil.expTypeArray(ty2);
5839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 op := if b then DAE.DIV_ARR(ty2) else DAE.DIV(ty2);
5840 then op;
5841 case DAE.MUL_ARR(ty=ty1)
5842 algorithm
5843 28 ty2 := Expression.unliftArray(ty1);
5844 28 b := DAEUtil.expTypeArray(ty2);
5845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 op := if b then DAE.MUL_ARR(ty2) else DAE.MUL(ty2);
5846 then op;
5847 case DAE.POW_ARR2(ty=ty1)
5848 algorithm
5849 18 ty2 := Expression.unliftArray(ty1);
5850 18 b := DAEUtil.expTypeArray(ty2);
5851
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 13 times.
18 op := if b then DAE.POW_ARR2(ty2) else DAE.POW(ty2);
5852 then op;
5853 end match;
5854 end removeOperatorDimension;
5855
5856 public function simplifyRangeBool
5857 "This function evaluates a Boolean range expression."
5858 input Boolean inStart;
5859 input Boolean inStop;
5860 output list<Boolean> outRange;
5861 algorithm
5862
6/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 2 times.
5 outRange := (if inStart then
5863 (if inStop then {true} else {})
5864 else
5865 (if inStop then {false, true} else {false})
5866 );
5867 end simplifyRangeBool;
5868
5869 public function simplifyRange
5870 "This function evaluates an Integer range expression."
5871 input Integer inStart;
5872 input Integer inStep;
5873 input Integer inStop;
5874 output list<Integer> outValues;
5875 algorithm
5876 3246 outValues := List.intRange3(inStart, inStep, inStop);
5877 end simplifyRange;
5878
5879 public function simplifyRangeReal
5880 "This function evaluates a Real range expression."
5881 input Real inStart;
5882 input Real inStep;
5883 input Real inStop;
5884 output list<Real> outValues;
5885 algorithm
5886 outValues := matchcontinue inStop
5887 local
5888 String error_str;
5889 Integer steps;
5890
5891 case _
5892 algorithm
5893
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 true := realAbs(inStep) <= 1e-14;
5894 ✗ error_str := stringDelimitList(
5895 List.map({inStart, inStep, inStop}, realString), ":");
5896 ✗ Error.addMessage(Error.ZERO_STEP_IN_ARRAY_CONSTRUCTOR, {error_str});
5897 ✗ then
5898 fail();
5899
5900 case _ guard valueEq(inStart, inStop)
5901 ✗ then {inStart};
5902
5903 else
5904 algorithm
5905 16 steps := Util.realRangeSize(inStart, inStep, inStop) - 1;
5906 16 then
5907 simplifyRangeReal2(inStart, inStep, steps, {});
5908
5909 end matchcontinue;
5910 end simplifyRangeReal;
5911
5912 protected function simplifyRangeReal2
5913 "Helper function to simplifyRangeReal."
5914 input Real inStart;
5915 input Real inStep;
5916 input Integer inSteps;
5917 input list<Real> inValues;
5918 output list<Real> outValues;
5919 algorithm
5920 outValues := match inSteps
5921 local
5922 Real next;
5923 list<Real> vals;
5924
5925 case -1 then inValues;
5926
5927 else
5928 algorithm
5929 152 next := inStart + inStep * intReal(inSteps);
5930 152 vals := next :: inValues;
5931 152 then
5932 simplifyRangeReal2(inStart, inStep, inSteps - 1, vals);
5933
5934 end match;
5935 end simplifyRangeReal2;
5936
5937 protected function simplifyReduction
5938 input DAE.Exp inReduction;
5939 output DAE.Exp outValue;
5940 algorithm
5941 outValue := matchcontinue inReduction
5942 local
5943 DAE.Exp expr, range, foldExpr, foldExpr2;
5944 DAE.Ident iter_name;
5945 list<DAE.Exp> values;
5946 Option<Values.Value> defaultValue;
5947 Values.Value v;
5948 Option<DAE.Exp> foldExp;
5949 DAE.Type ty,ty1,ety;
5950 DAE.ReductionIterator iter;
5951 list<DAE.ReductionIterator> iterators;
5952 String foldName,resultName,foldName2,resultName2;
5953 Absyn.Path path;
5954
5955 case DAE.REDUCTION(iterators = iterators, reductionInfo=DAE.REDUCTIONINFO(defaultValue = SOME(v)))
5956 algorithm
5957
2/2
✓ Branch 1 taken 1358 times.
✓ Branch 2 taken 6 times.
1364 true := hasZeroLengthIterator(iterators);
5958 6 expr := ValuesUtil.valueExp(v);
5959 then expr;
5960
5961 case DAE.REDUCTION(iterators = iterators)
5962 algorithm
5963
1/2
✓ Branch 1 taken 1833 times.
✗ Branch 2 not taken.
1833 true := hasZeroLengthIterator(iterators);
5964 ✗ expr := ValuesUtil.valueExp(Values.META_FAIL());
5965 then expr;
5966
5967 case DAE.REDUCTION(reductionInfo = DAE.REDUCTIONINFO(path = path, foldName=foldName, resultName=resultName, foldExp=foldExp, exprType = ty, defaultValue = defaultValue), expr = expr, iterators = {DAE.REDUCTIONITER(id = iter_name, guardExp = NONE(), exp = range)})
5968 algorithm
5969 1657 values := Expression.getArrayOrRangeContents(range);
5970 // TODO: Use foldExp
5971 //ty = Types.unliftArray(ty);
5972 962 ety := Types.simplifyType(ty);
5973 962 values := replaceIteratorWithValues(values, expr, iter_name);
5974 962 expr := simplifyReductionFoldPhase(path,foldExp,foldName,resultName,ety,values,defaultValue);
5975 then expr;
5976
5977 // iterType=THREAD() can handle multiple iterators
5978 case DAE.REDUCTION(reductionInfo = DAE.REDUCTIONINFO(path = path, iterType = Absyn.THREAD(), foldName=foldName, resultName=resultName, exprType = ty, foldExp=foldExp, defaultValue = defaultValue), expr = expr, iterators = iterators)
5979 algorithm
5980 // Start like for the normal reductions
5981
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
32 DAE.REDUCTIONITER(id = iter_name, guardExp = NONE(), exp = range)::iterators := iterators;
5982 32 values := Expression.getArrayOrRangeContents(range);
5983 ✗ ety := Types.simplifyType(ty);
5984 ✗ values := List.map2(values, replaceIteratorWithExp, expr, iter_name);
5985 // Then also fix the rest of the iterators
5986 ✗ values := List.fold(iterators, getIteratorValues, values);
5987 // And fold
5988 ✗ expr := simplifyReductionFoldPhase(path,foldExp,foldName,resultName,ety,values,defaultValue);
5989 then expr;
5990
5991 // array can handle multiple iterators
5992 case DAE.REDUCTION(reductionInfo = DAE.REDUCTIONINFO(path = path as Absyn.IDENT("array"), iterType = Absyn.COMBINE(), foldName=foldName, resultName=resultName, exprType = ty), expr = expr, iterators = iter::(iterators as _::_))
5993 algorithm
5994 2 foldName2 := Util.getTempVariableIndex();
5995 2 resultName2 := Util.getTempVariableIndex();
5996 2 ty1 := Expression.unliftArray(ty);
5997 4 expr := DAE.REDUCTION(DAE.REDUCTIONINFO(path,Absyn.COMBINE(),ty1,NONE(),foldName2,resultName2,NONE()),expr,{iter});
5998 2 expr := DAE.REDUCTION(DAE.REDUCTIONINFO(path,Absyn.COMBINE(),ty,NONE(),foldName,resultName,NONE()),expr,iterators);
5999 then expr;
6000 // rest can also handle multiple iterators
6001 case DAE.REDUCTION(reductionInfo = DAE.REDUCTIONINFO(path = path, iterType = Absyn.COMBINE(), foldName=foldName, resultName=resultName, exprType = ty, foldExp=NONE(), defaultValue = defaultValue), expr = expr, iterators = iter::(iterators as _::_))
6002 algorithm
6003 ✗ foldName2 := Util.getTempVariableIndex();
6004 ✗ resultName2 := Util.getTempVariableIndex();
6005 ✗ expr := DAE.REDUCTION(DAE.REDUCTIONINFO(path,Absyn.COMBINE(),ty,defaultValue,foldName2,resultName2,NONE()),expr,{iter});
6006 ✗ expr := DAE.REDUCTION(DAE.REDUCTIONINFO(path,Absyn.COMBINE(),ty,defaultValue,foldName,resultName,NONE()),expr,iterators);
6007 then expr;
6008
6009 case DAE.REDUCTION(reductionInfo = DAE.REDUCTIONINFO(path = path, iterType = Absyn.COMBINE(), foldName=foldName, resultName=resultName, exprType = ty, foldExp=SOME(foldExpr), defaultValue = defaultValue), expr = expr, iterators = iter::(iterators as _::_))
6010 algorithm
6011 ✗ foldName2 := Util.getTempVariableIndex();
6012 ✗ resultName2 := Util.getTempVariableIndex();
6013 ✗ (foldExpr2,_) := Expression.traverseExpBottomUp(foldExpr,Expression.renameExpCrefIdent,(foldName,foldName2));
6014 ✗ (foldExpr2,_) := Expression.traverseExpBottomUp(foldExpr2,Expression.renameExpCrefIdent,(resultName,resultName2));
6015 ✗ expr := DAE.REDUCTION(DAE.REDUCTIONINFO(path,Absyn.COMBINE(),ty,defaultValue,foldName2,resultName2,SOME(foldExpr2)),expr,{iter});
6016 ✗ expr := DAE.REDUCTION(DAE.REDUCTIONINFO(path,Absyn.COMBINE(),ty,defaultValue,foldName,resultName,SOME(foldExpr)),expr,iterators);
6017 then expr;
6018
6019 else inReduction;
6020
6021 end matchcontinue;
6022 end simplifyReduction;
6023
6024 protected function getIteratorValues
6025 input DAE.ReductionIterator iter;
6026 input list<DAE.Exp> inValues;
6027 output list<DAE.Exp> values;
6028 protected
6029 String iter_name;
6030 DAE.Exp range;
6031 algorithm
6032 ✗ DAE.REDUCTIONITER(id = iter_name, guardExp = NONE(), exp = range) := iter;
6033 ✗ values := Expression.getArrayOrRangeContents(range);
6034 ✗ values := List.threadMap1(values, inValues, replaceIteratorWithExp, iter_name);
6035 end getIteratorValues;
6036
6037 protected function replaceIteratorWithExp
6038 input DAE.Exp iterExp;
6039 input DAE.Exp exp;
6040 input String name;
6041 output DAE.Exp outExp;
6042 algorithm
6043
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 13422 times.
13422 (outExp,(_,_,true)) := Expression.traverseExpBottomUp(exp, replaceIteratorWithExpTraverser, (name,iterExp,true));
6044 end replaceIteratorWithExp;
6045
6046 protected function replaceIteratorWithExpTraverser
6047 input DAE.Exp inExp;
6048 input tuple<String,DAE.Exp,Boolean> inTpl;
6049 output DAE.Exp outExp;
6050 output tuple<String,DAE.Exp,Boolean> outTpl;
6051 algorithm
6052 (outExp,outTpl) := matchcontinue (inExp,inTpl)
6053 local
6054 String id,id2,name,replName;
6055 DAE.Exp iterExp;
6056 DAE.Type ty,ty1;
6057 list<DAE.Subscript> ss;
6058 DAE.ComponentRef cr;
6059 DAE.Exp exp;
6060 tuple<String,DAE.Exp,Boolean> tpl;
6061 Absyn.Path callPath,recordPath;
6062 list<DAE.Var> varLst;
6063 list<DAE.Exp> exps;
6064 Integer i;
6065 case (_,(_,_,false)) then (inExp,inTpl);
6066 case (DAE.CREF(DAE.CREF_IDENT(id,_,{}),_),tpl as (name,iterExp,_))
6067 guard
6068 stringEq(name,id)
6069 then (iterExp,tpl);
6070 case (exp as DAE.CREF(componentRef=DAE.CREF_IDENT(ident=id)),(name,iterExp,_))
6071 guard stringEq(name,id)
6072 ✗ then (exp,(name,iterExp,false));
6073 case (DAE.CREF(DAE.CREF_QUAL(id,ty1,ss,cr),ty),tpl as (name,DAE.CREF(componentRef=DAE.CREF_IDENT(ident=replName,subscriptLst={})),_))
6074 guard stringEq(name,id)
6075 ✗ then (DAE.CREF(DAE.CREF_QUAL(replName,ty1,ss,cr),ty), tpl);
6076 case (DAE.CREF(DAE.CREF_QUAL(id,ty1,{},cr),ty),tpl as (name,DAE.CREF(componentRef=DAE.CREF_IDENT(ident=replName,subscriptLst=ss)),_))
6077 guard stringEq(name,id)
6078 ✗ then (DAE.CREF(DAE.CREF_QUAL(replName,ty1,ss,cr),ty), tpl);
6079 case (DAE.CREF(componentRef=DAE.CREF_QUAL(id,_,{},DAE.CREF_IDENT(id2,_,{}))),tpl as (name,DAE.CALL(expLst=exps,path=callPath,attr=DAE.CALL_ATTR(ty=DAE.T_COMPLEX(varLst=varLst,complexClassType=ClassInf.RECORD(recordPath)))),_))
6080 algorithm
6081 ✗ true := stringEq(name,id);
6082 ✗ true := AbsynUtil.pathEqual(callPath,recordPath);
6083 ✗ true := listLength(varLst) == listLength(exps);
6084 ✗ i := List.position1OnTrue(varLst,DAEUtil.typeVarIdentEqual,id2);
6085 ✗ exp := listGet(exps,i);
6086 then (exp,tpl);
6087 case (exp as DAE.CREF(componentRef=DAE.CREF_QUAL(ident=id)),(name,iterExp,_))
6088 guard stringEq(name,id)
6089 ✗ then (exp,(name,iterExp,false));
6090 else (inExp,inTpl);
6091 end matchcontinue;
6092 end replaceIteratorWithExpTraverser;
6093
6094 protected function replaceIteratorWithValues
6095 "The reduction body instantiated for each iterator value. Each x[iter] where x
6096 does not depend on the iterator becomes the selected element of x, so the
6097 copies do not each carry (and later simplify) all of x."
6098 input list<DAE.Exp> values;
6099 input DAE.Exp exp;
6100 input String name;
6101 output list<DAE.Exp> exps;
6102 protected
6103 DAE.Exp body = exp;
6104 list<DAE.Exp> sites = {};
6105 array<DAE.Exp> sitesArr;
6106 algorithm
6107
2/2
✓ Branch 1 taken 722 times.
✓ Branch 2 taken 240 times.
962 if List.all(values, isIntegerConstant) then
6108 722 (body, (_, sites)) := Expression.traverseExpBottomUp(exp, extractIteratorSubscript, (name, {}));
6109 end if;
6110
2/2
✓ Branch 0 taken 852 times.
✓ Branch 1 taken 110 times.
962 if listEmpty(sites) then
6111 852 exps := List.map2(values, replaceIteratorWithExp, exp, name);
6112 else
6113 110 sitesArr := listArray(listReverse(sites));
6114
4/4
✓ Branch 0 taken 1770 times.
✓ Branch 1 taken 110 times.
✓ Branch 2 taken 1770 times.
✓ Branch 3 taken 110 times.
1880 exps := list(Expression.traverseExpBottomUp(replaceIteratorWithExp(v, body, name), fillIteratorSubscript, (sitesArr, v)) for v in values);
6115 end if;
6116 end replaceIteratorWithValues;
6117
6118 protected function isIntegerConstant
6119 input DAE.Exp exp;
6120 output Boolean b;
6121 algorithm
6122 b := match exp case DAE.ICONST() then true; else false; end match;
6123 end isIntegerConstant;
6124
6125 protected function extractIteratorSubscript
6126 "Replaces x[iter] by the placeholder $iterSub[n], where n indexes x in the
6127 accumulated list."
6128 input DAE.Exp inExp;
6129 input tuple<String, list<DAE.Exp>> inTpl;
6130 output DAE.Exp outExp;
6131 output tuple<String, list<DAE.Exp>> outTpl;
6132 algorithm
6133 (outExp, outTpl) := match (inExp, inTpl)
6134 local
6135 String id, name;
6136 DAE.Exp arr;
6137 list<DAE.Exp> sites;
6138 DAE.Type ty;
6139 case (DAE.ASUB(exp = arr, sub = {DAE.INDEX(DAE.CREF(componentRef = DAE.CREF_IDENT(ident = id, subscriptLst = {})))}), (name, sites))
6140 guard stringEq(id, name) and not iteratorOrPlaceholderOccurs(arr, name)
6141 algorithm
6142 332 ty := Expression.typeof(inExp);
6143 996 then (DAE.CREF(DAE.CREF_IDENT("$iterSub", ty, {DAE.INDEX(DAE.ICONST(listLength(sites) + 1))}), ty), (name, arr :: sites));
6144 else (inExp, inTpl);
6145 end match;
6146 end extractIteratorSubscript;
6147
6148 protected function iteratorOrPlaceholderOccurs
6149 input DAE.Exp exp;
6150 input String name;
6151 output Boolean occurs;
6152 algorithm
6153 332 (_, (_, occurs)) := Expression.traverseExpBottomUp(exp, iteratorOrPlaceholderOccursTraverser, (name, false));
6154 end iteratorOrPlaceholderOccurs;
6155
6156 protected function iteratorOrPlaceholderOccursTraverser
6157 input DAE.Exp inExp;
6158 input tuple<String, Boolean> inTpl;
6159 output DAE.Exp outExp = inExp;
6160 output tuple<String, Boolean> outTpl;
6161 algorithm
6162 outTpl := match (inExp, inTpl)
6163 local
6164 String id, name;
6165 case (_, (_, true)) then inTpl;
6166 case (DAE.CREF(componentRef = DAE.CREF_IDENT(ident = id)), (name, _))
6167 ✗ then (name, stringEq(id, name) or stringEq(id, "$iterSub"));
6168 case (DAE.CREF(componentRef = DAE.CREF_QUAL(ident = id)), (name, _))
6169 ✗ then (name, stringEq(id, name));
6170 else inTpl;
6171 end match;
6172 end iteratorOrPlaceholderOccursTraverser;
6173
6174 protected function fillIteratorSubscript
6175 input DAE.Exp inExp;
6176 input tuple<array<DAE.Exp>, DAE.Exp> inTpl;
6177 output DAE.Exp outExp;
6178 output tuple<array<DAE.Exp>, DAE.Exp> outTpl = inTpl;
6179 algorithm
6180 outExp := match (inExp, inTpl)
6181 local
6182 Integer n;
6183 array<DAE.Exp> sites;
6184 DAE.Exp sub;
6185 case (DAE.CREF(componentRef = DAE.CREF_IDENT(ident = "$iterSub", subscriptLst = {DAE.INDEX(DAE.ICONST(n))})), (sites, sub))
6186 5620 then selectElement(arrayGet(sites, n), sub);
6187 else inExp;
6188 end match;
6189 end fillIteratorSubscript;
6190
6191 protected function selectElement
6192 "exp[sub] for a constant sub, selected the way simplifyAsub does but before
6193 the other elements are simplified."
6194 input DAE.Exp exp;
6195 input DAE.Exp sub;
6196 output DAE.Exp outExp;
6197 protected
6198 Integer i = Expression.expInt(sub);
6199 algorithm
6200 outExp := matchcontinue exp
6201 local
6202 DAE.Exp e1, e2;
6203 list<DAE.Exp> exps;
6204 list<list<DAE.Exp>> rows;
6205 DAE.Type ty;
6206 DAE.ComponentRef cr;
6207 Operator op;
6208
6209 case DAE.ARRAY(array = exps) guard i >= 1 and i <= listLength(exps)
6210 5620 then listGet(exps, i);
6211
6212 case DAE.MATRIX(ty = ty, matrix = rows) guard i >= 1 and i <= listLength(rows)
6213 ✗ then DAE.ARRAY(Expression.unliftArray(ty), true, listGet(rows, i));
6214
6215 case DAE.CREF(componentRef = cr, ty = ty)
6216 guard Types.isArray(ty) and referenceEq(simplifyCref(exp, cr, ty), exp)
6217 ✗ then Expression.makeCrefExp(simplifyAsubCref(cr, sub), Expression.unliftArray(ty));
6218
6219 case DAE.UNARY(operator = DAE.UMINUS_ARR(), exp = e1)
6220 algorithm
6221 ✗ e1 := selectElement(e1, sub);
6222 ✗ ty := Expression.typeof(e1);
6223 ✗ then DAE.UNARY(if DAEUtil.expTypeArray(ty) then DAE.UMINUS_ARR(ty) else DAE.UMINUS(ty), e1);
6224
6225 case DAE.BINARY(exp1 = e1, operator = op, exp2 = e2)
6226 guard isSelectableOperator(op)
6227 algorithm
6228 ✗ if not Expression.isScalarArrayOp(op) then
6229 ✗ e1 := selectElement(e1, sub);
6230 end if;
6231 ✗ if not Expression.isArrayScalarOp(op) then
6232 ✗ e2 := selectElement(e2, sub);
6233 end if;
6234 ✗ ty := Expression.typeof(if Expression.isScalarArrayOp(op) then e2 else e1);
6235 ✗ then DAE.BINARY(e1, selectedOperator(op, ty, DAEUtil.expTypeArray(ty)), e2);
6236
6237 ✗ else DAE.ASUB(exp, {DAE.INDEX(sub)});
6238 end matchcontinue;
6239 end selectElement;
6240
6241 protected function isSelectableOperator
6242 input Operator op;
6243 output Boolean b;
6244 algorithm
6245 b := match op
6246 case DAE.ADD_ARR() then true;
6247 case DAE.SUB_ARR() then true;
6248 case DAE.MUL_ARR() then true;
6249 case DAE.DIV_ARR() then true;
6250 case DAE.POW_ARR2() then true;
6251 ✗ else Expression.isArrayScalarOp(op) or Expression.isScalarArrayOp(op);
6252 end match;
6253 end isSelectableOperator;
6254
6255 protected function selectedOperator
6256 "The operator simplifyAsub gives an element of an array operation."
6257 input Operator op;
6258 input DAE.Type ty;
6259 input Boolean isArray;
6260 output Operator outOp;
6261 algorithm
6262 outOp := match op
6263 ✗ case DAE.ADD_ARR() then if isArray then DAE.ADD_ARR(ty) else DAE.ADD(ty);
6264 ✗ case DAE.SUB_ARR() then if isArray then DAE.SUB_ARR(ty) else DAE.SUB(ty);
6265 ✗ case DAE.MUL_ARR() then if isArray then DAE.MUL_ARR(ty) else DAE.MUL(ty);
6266 ✗ case DAE.DIV_ARR() then if isArray then DAE.DIV_ARR(ty) else DAE.DIV(ty);
6267 ✗ case DAE.POW_ARR2() then if isArray then DAE.POW_ARR2(ty) else DAE.POW(ty);
6268 ✗ case DAE.MUL_ARRAY_SCALAR() then if isArray then DAE.MUL_ARRAY_SCALAR(ty) else DAE.MUL(ty);
6269 ✗ case DAE.ADD_ARRAY_SCALAR() then if isArray then DAE.ADD_ARRAY_SCALAR(ty) else DAE.ADD(ty);
6270 ✗ case DAE.DIV_ARRAY_SCALAR() then if isArray then DAE.DIV_ARRAY_SCALAR(ty) else DAE.DIV(ty);
6271 ✗ case DAE.POW_ARRAY_SCALAR() then if isArray then DAE.POW_ARRAY_SCALAR(ty) else DAE.POW(ty);
6272 ✗ case DAE.SUB_SCALAR_ARRAY() then if isArray then DAE.SUB_SCALAR_ARRAY(ty) else DAE.SUB(ty);
6273 ✗ case DAE.DIV_SCALAR_ARRAY() then if isArray then DAE.DIV_SCALAR_ARRAY(ty) else DAE.DIV(ty);
6274 ✗ case DAE.POW_SCALAR_ARRAY() then if isArray then DAE.POW_SCALAR_ARRAY(ty) else DAE.POW(ty);
6275 end match;
6276 end selectedOperator;
6277
6278 protected function simplifyReductionFoldPhase
6279 input Absyn.Path path;
6280 input Option<DAE.Exp> optFoldExp;
6281 input String foldName,resultName;
6282 input DAE.Type ty;
6283 input list<DAE.Exp> inExps;
6284 input Option<Values.Value> defaultValue;
6285 output DAE.Exp exp;
6286 protected
6287 Boolean checkForSimplifications;
6288 algorithm
6289 (exp, checkForSimplifications) := match (path, optFoldExp, inExps, defaultValue)
6290 local
6291 Values.Value val;
6292 DAE.Exp arr_exp,foldExp;
6293 DAE.Type aty,ty2;
6294 list<DAE.Exp> exps;
6295 Integer length;
6296
6297 case (Absyn.IDENT("array"), _, _, _)
6298 algorithm
6299 664 aty := Types.unliftArray(Types.expTypetoTypesType(ty));
6300 664 length := listLength(inExps);
6301 664 ty2 := Types.liftArray(aty, DAE.DIM_INTEGER(length)); // The size can be unknown before the reduction...
6302 664 exp := Expression.makeArray(inExps, ty2, not Types.isArray(aty));
6303 then (exp, false);
6304
6305 ✗ case (_, _, {}, SOME(val)) then (ValuesUtil.valueExp(val), false);
6306 ✗ case (_, _, {}, NONE()) then fail();
6307
6308 case (Absyn.IDENT("min"), _, _, _)
6309 algorithm
6310 15 arr_exp := Expression.makeScalarArray(inExps, ty);
6311 15 then (Expression.makePureBuiltinCall("min", {arr_exp}, ty), true);
6312
6313 case (Absyn.IDENT("max"), _, _, _)
6314 algorithm
6315 17 arr_exp := Expression.makeScalarArray(inExps, ty);
6316 17 then (Expression.makePureBuiltinCall("max", {arr_exp}, ty), true);
6317
6318 case (_, SOME(_), {exp}, _)
6319 then (exp, false);
6320
6321
6322 // foldExp=(a+b) ; exps={1,2,3,4}
6323 // step 1: result=4
6324 // step 2: result= (replace b in (a+b) with 4, a with 3): 3+4
6325 // ...
6326 // Why reverse order? Smaller expressions to perform the replacements in
6327 case (_, SOME(foldExp), exp::exps, _)
6328 algorithm
6329 195 exp := simplifyReductionFoldPhase2(exps,foldExp,foldName,resultName,exp);
6330 then (exp, false);
6331
6332 end match;
6333 if checkForSimplifications then
6334
2/2
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 2 times.
32 (exp,true) := simplify1(exp);
6335 end if;
6336 end simplifyReductionFoldPhase;
6337
6338 protected function simplifyReductionFoldPhase2
6339 input list<DAE.Exp> inExps;
6340 input DAE.Exp foldExp;
6341 input String foldName,resultName;
6342 input DAE.Exp acc;
6343 output DAE.Exp exp;
6344 algorithm
6345 exp := match inExps
6346 local
6347 list<DAE.Exp> exps;
6348
6349 case {} then acc;
6350 case exp::exps
6351 algorithm
6352 2406 exp := replaceIteratorWithExp(exp, foldExp, foldName);
6353 2406 exp := replaceIteratorWithExp(acc, exp, resultName);
6354 2406 then simplifyReductionFoldPhase2(exps,foldExp,foldName,resultName,exp);
6355
6356 end match;
6357 end simplifyReductionFoldPhase2;
6358
6359 protected function hasZeroLengthIterator
6360 input list<DAE.ReductionIterator> inIters;
6361 output Boolean b;
6362 algorithm
6363 b := match inIters
6364 local list<DAE.ReductionIterator> iters;
6365 case {} then false;
6366 case DAE.REDUCTIONITER(guardExp=SOME(DAE.BCONST(false)))::_ then true;
6367 case DAE.REDUCTIONITER(exp=DAE.LIST({}))::_ then true;
6368 case DAE.REDUCTIONITER(exp=DAE.ARRAY(array={}))::_ then true;
6369 3251 case _::iters then hasZeroLengthIterator(iters);
6370 end match;
6371 end hasZeroLengthIterator;
6372
6373 public function simplifyList
6374 input list<DAE.Exp> expl;
6375 output list<DAE.Exp> outExpl;
6376 algorithm
6377
4/4
✓ Branch 0 taken 1064304 times.
✓ Branch 1 taken 1033936 times.
✓ Branch 2 taken 1064304 times.
✓ Branch 3 taken 1033936 times.
2098240 outExpl := list(simplify1(exp) for exp in expl);
6378 end simplifyList;
6379
6380 public function simplifyList1
6381 input list<DAE.Exp> expl;
6382 output list<DAE.Exp> outExpl;
6383 output list<Boolean> outBool = {};
6384 algorithm
6385 ✗ outExpl := list(match exp
6386 local
6387 DAE.Exp e;
6388 Boolean b2;
6389 case _
6390 algorithm
6391 ✗ (e,b2) := simplify(exp);
6392 ✗ outBool := b2::outBool;
6393 then e;
6394 end match for exp in expl);
6395 ✗ outBool := Dangerous.listReverseInPlace(outBool);
6396 end simplifyList1;
6397
6398 public function condsimplifyList1
6399 input list<Boolean> blst;
6400 input list<DAE.Exp> expl;
6401 output list<DAE.Exp> outExpl = {};
6402 output list<Boolean> outBool = {};
6403 protected
6404 list<DAE.Exp> rest_expl = expl;
6405 DAE.Exp exp;
6406 Boolean b2;
6407 algorithm
6408
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 155 times.
584 for b in blst loop
6409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429 times.
429 exp::rest_expl := rest_expl;
6410 429 (exp,b2) := condsimplify(b,exp);
6411 outExpl := exp::outExpl;
6412
1/2
✓ Branch 0 taken 429 times.
✗ Branch 1 not taken.
429 outBool := b2::outBool;
6413 end for;
6414 155 outExpl := Dangerous.listReverseInPlace(outExpl);
6415 155 outBool := Dangerous.listReverseInPlace(outBool);
6416 end condsimplifyList1;
6417
6418 protected function checkZeroLengthArrayOp
6419 "If this succeeds, and either argument to the operation is empty, the whole operation is empty"
6420 input DAE.Operator op;
6421 algorithm
6422 () := match op
6423 case DAE.ADD_ARR() then ();
6424 case DAE.SUB_ARR() then ();
6425 case DAE.MUL_ARR() then ();
6426 case DAE.DIV_ARR() then ();
6427 case DAE.POW_ARR() then ();
6428 case DAE.POW_ARR2() then ();
6429 case DAE.MUL_ARRAY_SCALAR() then ();
6430 case DAE.ADD_ARRAY_SCALAR() then ();
6431 case DAE.DIV_ARRAY_SCALAR() then ();
6432 case DAE.SUB_SCALAR_ARRAY() then ();
6433 case DAE.DIV_SCALAR_ARRAY() then ();
6434 case DAE.MUL_MATRIX_PRODUCT() then ();
6435 end match;
6436 end checkZeroLengthArrayOp;
6437
6438 public function simplifyAddSymbolicOperation
6439 input DAE.EquationExp exp;
6440 input DAE.ElementSource source;
6441 output DAE.EquationExp outExp;
6442 output DAE.ElementSource outSource;
6443 algorithm
6444 (outExp,outSource) := match exp
6445 local
6446 Boolean changed,changed1,changed2;
6447 DAE.Exp e,e1,e2;
6448 case DAE.PARTIAL_EQUATION(e)
6449 algorithm
6450 9736 (e,changed) := simplify(e);
6451
2/2
✓ Branch 0 taken 4343 times.
✓ Branch 1 taken 5393 times.
9736 outExp := if changed then DAE.PARTIAL_EQUATION(e) else exp;
6452 9736 outSource := ElementSource.condAddSymbolicTransformation(changed,source,DAE.SIMPLIFY(exp,outExp));
6453 then (outExp,outSource);
6454 case DAE.RESIDUAL_EXP(e)
6455 algorithm
6456 ✗ (e,changed) := simplify(e);
6457 ✗ outExp := if changed then DAE.RESIDUAL_EXP(e) else exp;
6458 ✗ outSource := ElementSource.condAddSymbolicTransformation(changed,source,DAE.SIMPLIFY(exp,outExp));
6459 then (outExp,outSource);
6460 case DAE.EQUALITY_EXPS(e1,e2)
6461 algorithm
6462 155271 (e1,changed1) := simplify(e1);
6463 155271 (e2,changed2) := simplify(e2);
6464
4/4
✓ Branch 0 taken 144344 times.
✓ Branch 1 taken 10927 times.
✓ Branch 2 taken 108414 times.
✓ Branch 3 taken 35930 times.
155271 changed := changed1 or changed2;
6465
2/2
✓ Branch 0 taken 46857 times.
✓ Branch 1 taken 108414 times.
155271 outExp := if changed then DAE.EQUALITY_EXPS(e1,e2) else exp;
6466 155271 outSource := ElementSource.condAddSymbolicTransformation(changed,source,DAE.SIMPLIFY(exp,outExp));
6467 then (outExp,outSource);
6468 else
6469 algorithm
6470 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"ExpressionSimplify.simplifyAddSymbolicOperation failed"});
6471 ✗ then fail();
6472 end match;
6473 end simplifyAddSymbolicOperation;
6474
6475 public function condSimplifyAddSymbolicOperation
6476 input Boolean cond;
6477 input output DAE.EquationExp exp;
6478 input output DAE.ElementSource source;
6479 algorithm
6480
2/2
✓ Branch 0 taken 1204 times.
✓ Branch 1 taken 1846 times.
3050 if cond then
6481 1846 (exp,source) := simplifyAddSymbolicOperation(exp,source);
6482 end if;
6483 end condSimplifyAddSymbolicOperation;
6484
6485 protected function simplifySize
6486 input DAE.Exp origExp;
6487 input DAE.Exp exp;
6488 input Option<DAE.Exp> optDim;
6489 output DAE.Exp outExp;
6490 algorithm
6491 outExp := matchcontinue optDim
6492 local
6493 Integer i,n;
6494 DAE.Type t;
6495 DAE.Dimensions dims;
6496 DAE.Dimension dim;
6497 DAE.Exp dimExp;
6498
6499 // simplify size operator
6500 case SOME(dimExp)
6501 algorithm
6502 5469 i := Expression.expInt(dimExp);
6503 5469 t := Expression.typeof(exp);
6504 5469 dims := Expression.arrayDimension(t);
6505 5469 dim := listGet(dims,i);
6506 5451 n := Expression.dimensionSize(dim);
6507 1757 then DAE.ICONST(n);
6508 // TODO: Handle optDim=NONE() when dims are known
6509 else origExp;
6510 end matchcontinue;
6511 end simplifySize;
6512
6513 protected function simplifyTSub
6514 input DAE.Exp origExp;
6515 output DAE.Exp outExp;
6516 algorithm
6517 outExp := match origExp
6518 local
6519 list<DAE.Exp> expl;
6520 Integer i;
6521 DAE.Exp e;
6522
6523 // NOTE: It should be impossible for TSUB to use an index that becomes out of range, so match is correct here...
6524 case DAE.TSUB(exp = DAE.CAST(exp = DAE.TUPLE(PR = expl)), ix = i)
6525 ✗ then listGet(expl, i);
6526 case DAE.TSUB(exp = DAE.TUPLE(PR = expl), ix = i)
6527 17 then listGet(expl, i);
6528 case DAE.TSUB(exp= e as (DAE.RCONST())) then e;
6529 else origExp;
6530 end match;
6531 end simplifyTSub;
6532
6533 protected function simplifyNoEvent "Adds noEvent() only to required subexpressions"
6534 input DAE.Exp inExp;
6535 output DAE.Exp e;
6536 algorithm
6537 8539 e := Expression.addNoEventToEventTriggeringFunctions(Expression.addNoEventToRelations(Expression.stripNoEvent(inExp)));
6538 end simplifyNoEvent;
6539
6540 protected function maxElement
6541 input DAE.Exp e1;
6542 input Option<DAE.Exp> e2;
6543 output Option<DAE.Exp> elt;
6544 algorithm
6545 elt := match (e1,e2)
6546 local
6547 Real r1,r2;
6548 Integer i1,i2;
6549 Boolean b1,b2;
6550 case (DAE.RCONST(_),NONE()) then SOME(e1);
6551 case (DAE.ICONST(_),NONE()) then SOME(e1);
6552 case (DAE.BCONST(_),NONE()) then SOME(e1);
6553 ✗ case (DAE.RCONST(r1),SOME(DAE.RCONST(r2))) then if r1 > r2 then SOME(e1) else e2;
6554 ✗ case (DAE.ICONST(i1),SOME(DAE.ICONST(i2))) then if intGt(i1,i2) then SOME(e1) else e2;
6555
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 case (DAE.BCONST(b1),SOME(DAE.BCONST(b2))) then (if b2 or b1==b2 then e2 else SOME(DAE.BCONST(b1)));
6556 else e2;
6557 end match;
6558 end maxElement;
6559
6560 protected function minElement
6561 input DAE.Exp e1;
6562 input Option<DAE.Exp> e2;
6563 output Option<DAE.Exp> elt;
6564 algorithm
6565 elt := match (e1,e2)
6566 local
6567 Real r1,r2;
6568 Integer i1,i2;
6569 Boolean b1,b2;
6570 case (DAE.RCONST(_),NONE()) then SOME(e1);
6571 case (DAE.ICONST(_),NONE()) then SOME(e1);
6572 case (DAE.BCONST(_),NONE()) then SOME(e1);
6573 ✗ case (DAE.RCONST(r1),SOME(DAE.RCONST(r2))) then if r1 < r2 then SOME(e1) else e2;
6574 ✗ case (DAE.ICONST(i1),SOME(DAE.ICONST(i2))) then if intLt(i1,i2) then SOME(e1) else e2;
6575
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 case (DAE.BCONST(b1),SOME(DAE.BCONST(b2))) then (if not b2 or b1==b2 then e2 else SOME(DAE.BCONST(b1)));
6576 else e2;
6577 end match;
6578 end minElement;
6579
6580 protected function removeMinMaxFoldableValues
6581 input DAE.Exp e;
6582 output Boolean filter;
6583 algorithm
6584 filter := match e
6585 case DAE.RCONST(_) then false;
6586 case DAE.ICONST(_) then false;
6587 case DAE.BCONST(_) then false;
6588 else true;
6589 end match;
6590 end removeMinMaxFoldableValues;
6591
6592 public function simplifySkew
6593 "Simplifies the skew operator."
6594 input list<DAE.Exp> v1;
6595 output list<list<DAE.Exp>> res;
6596 protected
6597 DAE.Exp x1, x2, x3, zero;
6598 algorithm
6599
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 36 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 36 times.
36 {x1, x2, x3} := v1;
6600 36 zero := Expression.makeConstZero(Expression.typeof(x1));
6601
6602 108 res := {{zero, Expression.negate(x3), x2},
6603 {x3, zero, Expression.negate(x1)},
6604 {Expression.negate(x2), x1, zero}};
6605 end simplifySkew;
6606
6607 public function simplifyCross
6608 "Simplifies the cross operator."
6609 input list<DAE.Exp> v1;
6610 input list<DAE.Exp> v2;
6611 output list<DAE.Exp> res;
6612 protected
6613 DAE.Exp x1, x2, x3, y1, y2, y3;
6614 algorithm
6615
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 2587 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2587 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2587 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2587 times.
2587 {x1, x2, x3} := v1;
6616
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 2587 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2587 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2587 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2587 times.
2587 {y1, y2, y3} := v2;
6617
6618 // res = {x[2]*y[3] - x[3]*y[2], x[3]*y[1] - x[1]*y[3], x[1]*y[2] - x[2]*y[1]}
6619 7761 res := {Expression.expSub(Expression.makeProduct(x2, y3), Expression.makeProduct(x3, y2)),
6620 Expression.expSub(Expression.makeProduct(x3, y1), Expression.makeProduct(x1, y3)),
6621 Expression.expSub(Expression.makeProduct(x1, y2), Expression.makeProduct(x2, y1))};
6622 end simplifyCross;
6623
6624 annotation(__OpenModelica_Interface="frontend_base");
6625 end ExpressionSimplify;
6626