Skip to content

Commit

Permalink
Fix for #3409.
Browse files Browse the repository at this point in the history
- Type cast matrix elements before assembling the matrix,
  not after when it's too late.
- Various type fixes for elaboration of matrices.
- Fix List.mapFoldList so that it updates the argument,
  not just reusing the input argument for each call.
  • Loading branch information
perost committed Sep 8, 2015
1 parent 0e43de5 commit ceb1975
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 30 deletions.
28 changes: 11 additions & 17 deletions Compiler/FrontEnd/InstSection.mo
Expand Up @@ -1768,24 +1768,18 @@ protected function instArrayElEq
input list<DAE.Exp> inRhsIndices;
input DAE.ElementSource inSource;
input SCode.Initial inInitial;
output DAE.DAElist outDAE;
output DAE.DAElist outDAE = DAE.emptyDae;
protected
DAE.Exp rhs_idx;
list<DAE.Exp> rhs_idxs = listReverse(inRhsIndices);
DAE.DAElist dae;
algorithm
outDAE := match(inLhsExp, inRhsExp, inType, inConst, inLhsIndices,
inRhsIndices, inSource, inInitial)
local
DAE.Exp lhs, rhs, lhs_idx, rhs_idx;
DAE.Type t;
list<DAE.Exp> lhs_idxs, rhs_idxs;
DAE.DAElist dae1, dae2;
case (_, _, _, _, {}, {}, _, _) then DAE.emptyDae;
case (lhs, rhs, t, _, lhs_idx :: lhs_idxs, rhs_idx :: rhs_idxs, _, _)
equation
dae1 = instEqEquation2(lhs_idx, rhs_idx, t, inConst, inSource, inInitial);
dae2 = instArrayElEq(lhs, rhs, t, inConst, lhs_idxs, rhs_idxs, inSource, inInitial);
dae1 = DAEUtil.joinDaes(dae1, dae2);
then
dae1;
end match;
for lhs_idx in listReverse(inLhsIndices) loop
rhs_idx :: rhs_idxs := rhs_idxs;

dae := instEqEquation2(lhs_idx, rhs_idx, inType, inConst, inSource, inInitial);
outDAE := DAEUtil.joinDaes(dae, outDAE);
end for;
end instArrayElEq;

protected function unrollForLoop
Expand Down
47 changes: 35 additions & 12 deletions Compiler/FrontEnd/Static.mo
Expand Up @@ -745,41 +745,64 @@ protected function elabExp_Matrix
extends PartialElabExpFunc;
protected
list<list<Absyn.Exp>> ess;
list<list<DAE.Exp>> dess;
list<list<DAE.Exp>> dess, dess2;
list<list<DAE.Properties>> props;
list<list<DAE.Type>> tps;
list<DAE.Type> tys;
list<DAE.Type> tys, tys2;
Integer nmax;
Boolean have_real;
DAE.Type ty;
DAE.Const c;
DAE.Dimension dim1, dim2;
list<DAE.Exp> expl;
algorithm
// Elaborate the individual expressions.
Absyn.MATRIX(matrix = ess) := inExp;
(outCache, dess, props) := elabExpListList(inCache, inEnv, ess, inImplicit,
inST, inDoVect, inPrefix, inInfo);

tps := List.mapList(props, Types.getPropType);
tys := List.flatten(tps);
// Check if any of the expressions is of Real type.
tys := listAppend(list(Types.getPropType(p) for p in pl) for pl in props);
nmax := matrixConstrMaxDim(tys);
have_real := Types.containReal(tys);

(outCache, outExp, DAE.PROP(ty, c), dim1, dim2) := elabMatrixSemi(outCache,
inEnv, dess, props, inImplicit, inST, have_real, nmax, inDoVect, inPrefix, inInfo);

// If we have any Real expressions, cast any Integer expressions to Real.
if have_real then
outExp := DAE.CAST(DAE.T_ARRAY(DAE.T_REAL_DEFAULT, {dim1, dim2}, DAE.emptyTypeSource), outExp);
(dess, props) := List.threadMapList_2(dess, props, elabExp_Matrix_realCast);
end if;

// TODO: Should this be moved into the if-statement above?
outExp := ExpressionSimplify.simplify1(outExp); // To propagate cast down to scalar elts.
(outCache, outExp, DAE.PROP(ty, c), dim1, dim2) := elabMatrixSemi(outCache,
inEnv, dess, props, inImplicit, inST, have_real, nmax, inDoVect, inPrefix, inInfo);

outExp := elabMatrixToMatrixExp(outExp);
ty := Types.unliftArray(Types.unliftArray(ty)); // All elts promoted to matrix, therefore unlifting.
ty := DAE.T_ARRAY(ty, {dim2}, DAE.emptyTypeSource);
ty := DAE.T_ARRAY(ty, {dim1}, DAE.emptyTypeSource);
outProperties := DAE.PROP(ty, c);
end elabExp_Matrix;

protected function elabExp_Matrix_realCast
"Casts an expression and property to Real if it's current type is Integer."
input DAE.Exp inExp;
input DAE.Properties inProperties;
output DAE.Exp outExp;
output DAE.Properties outProperties;
protected
DAE.Type ty;
algorithm
ty := Types.getPropType(inProperties);

if Types.isInteger(ty) then
ty := Types.setArrayElementType(ty, DAE.T_REAL_DEFAULT);
outProperties := Types.setPropType(inProperties, ty);
ty := Types.simplifyType(ty);
outExp := ExpressionSimplify.simplify1(DAE.CAST(ty, inExp));
else
outExp := inExp;
outProperties := inProperties;
end if;
end elabExp_Matrix_realCast;

protected function elabExp_Code
extends PartialElabExpFunc;
protected
Expand Down Expand Up @@ -2782,7 +2805,6 @@ algorithm
(exp, outProperties as DAE.PROP(type_ = ty)) := promoteExp(exp, prop, inDims);
accum_expl := exp :: accum_expl;
(_, outDim1 :: outDim2 :: _) := Types.flattenArrayTypeOpt(ty);
sty := Expression.liftArrayLeft(Types.simplifyType(ty), DAE.DIM_INTEGER(1));

while not listEmpty(rest_expl) loop
exp :: rest_expl := rest_expl;
Expand All @@ -2796,6 +2818,7 @@ algorithm
outProperties := Types.matchWithPromote(prop, outProperties, inHaveReal);
end while;

sty := Expression.liftArrayLeftList(Expression.unliftArrayX(ty, 2), {outDim1, outDim2});
outExp := DAE.ARRAY(sty, false, listReverse(accum_expl));
else
true := Flags.isSet(Flags.FAILTRACE);
Expand Down Expand Up @@ -2856,7 +2879,7 @@ algorithm
DAE.ARRAY(array = expl2) := inExp2;
expl1 := list(elabMatrixCatTwo3(e1, e2) threaded for e1 in expl1, e2 in expl2);
ty := Expression.typeof(listHead(expl1));
ty := Expression.liftArrayLeft(ty, DAE.DIM_INTEGER(1));
ty := Expression.liftArrayLeft(ty, DAE.DIM_INTEGER(listLength(expl1)));
outExp := DAE.ARRAY(ty, sc, expl1);
end elabMatrixCatTwo2;

Expand Down
64 changes: 63 additions & 1 deletion Compiler/Util/List.mo
Expand Up @@ -3644,7 +3644,7 @@ protected
list<TO> res;
algorithm
for lst in inListList loop
(res, outArg) := mapFold(lst, inFunc, inArg);
(res, outArg) := mapFold(lst, inFunc, outArg);
outListList := res :: outListList;
end for;
outListList := listReverseInPlace(outListList);
Expand Down Expand Up @@ -3967,6 +3967,37 @@ algorithm
outList := listReverse(inMapFunc(e1, e2) threaded for e1 in inList1, e2 in inList2);
end threadMapReverse;

public function threadMap_2<T1, T2, TO1, TO2>
"Like threadMap, but returns two lists instead of one."
input list<T1> inList1;
input list<T2> inList2;
input MapFunc inMapFunc;
output list<TO1> outList1 = {};
output list<TO2> outList2 = {};

partial function MapFunc
input T1 inElement1;
input T2 inElement2;
output TO1 outElement1;
output TO2 outElement2;
end MapFunc;
protected
T2 e2;
list<T2> rest_e2 = inList2;
TO1 ret1;
TO2 ret2;
algorithm
for e1 in inList1 loop
e2 :: rest_e2 := rest_e2;
(ret1, ret2) := inMapFunc(e1, e2);
outList1 := ret1 :: outList1;
outList2 := ret2 :: outList2;
end for;

outList1 := listReverse(outList1);
outList2 := listReverse(outList2);
end threadMap_2;

public function threadMapList<T1, T2, TO>
"Takes two lists of lists and a function and threads (interleaves) and maps
the elements of the two lists, creating a new list.
Expand All @@ -3986,6 +4017,37 @@ algorithm
lst2 in inList2);
end threadMapList;

public function threadMapList_2<T1, T2, TO1, TO2>
"Like threadMapList, but returns two lists instead of one."
input list<list<T1>> inList1;
input list<list<T2>> inList2;
input MapFunc inMapFunc;
output list<list<TO1>> outList1 = {};
output list<list<TO2>> outList2 = {};

partial function MapFunc
input T1 inElement1;
input T2 inElement2;
output TO1 outElement1;
output TO2 outElement2;
end MapFunc;
protected
list<T2> l2;
list<list<T2>> rest_l2 = inList2;
list<TO1> ret1;
list<TO2> ret2;
algorithm
for l1 in inList1 loop
l2 :: rest_l2 := rest_l2;
(ret1, ret2) := threadMap_2(l1, l2, inMapFunc);
outList1 := ret1 :: outList1;
outList2 := ret2 :: outList2;
end for;

outList1 := listReverse(outList1);
outList2 := listReverse(outList2);
end threadMapList_2;

public function threadTupleList<T1, T2>
"Takes two lists of lists as arguments and produces a list of lists of a two
tuple of the element types of each list.
Expand Down

0 comments on commit ceb1975

Please sign in to comment.