Skip to content

Commit e657602

Browse files
rfrankeOpenModelica-Hudson
authored andcommitted
Unifiy storage order of RefArray, ticket:4093, ticket:4072
Assigning between RefArray and value Array copies storage linearly. This is why RefArray must have column-major storage layout as well. The bug doesn't seem to show up because generated code currently instantiates an intermediate array element by element, e.g. if a RefArray is passed to a function. This could and should be optimized.
1 parent 7359ea2 commit e657602

File tree

2 files changed

+67
-16
lines changed

2 files changed

+67
-16
lines changed

Compiler/SimCode/SimCodeUtil.mo

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10965,7 +10965,12 @@ algorithm
1096510965
concreteVarIndex := getUnrolledArrayIndex(arraySubscripts,arrayDimensions);
1096610966
//print("SimCodeUtil.getVarIndexInfosByMapping: Found variable index for '" + ComponentReference.printComponentRefStr(iVarName) + "'. The value is " + intString(concreteVarIndex) + "\n");
1096710967
for arrayIdx in 0:(arraySize-1) loop
10968-
idx := arrayGet(varIndices, arraySize-arrayIdx);
10968+
idx := arraySize-arrayIdx;
10969+
if iColumnMajor then
10970+
// convert to row major so that column major access will give this idx
10971+
idx := convertIndexToRowMajor(idx, arrayDimensions0);
10972+
end if;
10973+
idx := arrayGet(varIndices, idx);
1096910974
if(intLt(idx, 0)) then
1097010975
tmpVarIndexListNew := intString((intMul(idx, -1) - 1))::tmpVarIndexListNew;
1097110976
//print("SimCodeUtil.tmpVarIndexListNew: Warning, negativ aliases (" + ComponentReference.printComponentRefStr(iVarName) + ") are not supported at the moment!\n");
@@ -10977,11 +10982,12 @@ algorithm
1097710982
end if;
1097810983
end if;
1097910984
end for;
10980-
if (not isVarIndexListConsecutive(iVarToArrayIndexMapping,iVarName) and iColumnMajor) then
10985+
if isVarIndexListConsecutive(iVarToArrayIndexMapping,iVarName) and iColumnMajor then
1098110986
//if the array is not completely stuffed (e.g. some array variables have been derived and became dummy-derivatives), the array will not be initialized as a consecutive array, therefore we cannot take the colMajor-indexes
10982-
concreteVarIndex := getUnrolledArrayIndex(arraySubscripts0,arrayDimensions0);
10987+
// otherwise convert to column major for consecutive array
10988+
concreteVarIndex := convertIndexToColumnMajor(concreteVarIndex + 1, arrayDimensions0) - 1;
1098310989
end if;
10984-
oConcreteVarIndex := listGet(tmpVarIndexListNew, concreteVarIndex + 1);
10990+
oConcreteVarIndex := listGet(tmpVarIndexListNew, concreteVarIndex + 1);
1098510991
end if;
1098610992
if(listEmpty(tmpVarIndexListNew)) then
1098710993
Error.addMessage(Error.INTERNAL_ERROR, {"GetVarIndexListByMapping: No Element for " + ComponentReference.printComponentRefStr(varName) + " found!"});
@@ -11010,6 +11016,51 @@ algorithm
1101011016
end if;
1101111017
end convertFlattenedIndexToRowMajor;
1101211018

11019+
protected function convertIndexToRowMajor
11020+
"Converts column-major unrolled idx to row-major, author: rfranke"
11021+
input Integer idx; // one based, row-major ordered
11022+
input list<Integer> arrayDimensions;
11023+
output Integer idxOut; // one based, column-major ordered
11024+
protected
11025+
Integer idx0, ndim, length, dimj, idxj, fac;
11026+
algorithm
11027+
ndim := listLength(arrayDimensions);
11028+
length := List.fold(arrayDimensions, intMul, 1);
11029+
idx0 := idx - 1; // zero based
11030+
idxOut := 1; // one based
11031+
fac := 1;
11032+
for i in 1:listLength(arrayDimensions) loop
11033+
dimj := listGet(arrayDimensions, ndim - i + 1);
11034+
length := intDiv(length, dimj);
11035+
idxj := intDiv(idx0, length);
11036+
idx0 := idx0 - idxj*length;
11037+
idxOut := idxOut + idxj*fac;
11038+
fac := fac * dimj;
11039+
end for;
11040+
end convertIndexToRowMajor;
11041+
11042+
protected function convertIndexToColumnMajor
11043+
"Converts row-major unrolled idx to column-major, author: rfranke"
11044+
input Integer idx; // one based, row-major ordered
11045+
input list<Integer> arrayDimensions;
11046+
output Integer idxOut; // one based, column-major ordered
11047+
protected
11048+
Integer idx0, ndim, length, idxi, fac;
11049+
algorithm
11050+
ndim := listLength(arrayDimensions);
11051+
length := List.fold(arrayDimensions, intMul, 1);
11052+
idx0 := idx - 1; // zero based
11053+
idxOut := 1; // one based
11054+
fac := 1;
11055+
for dimi in arrayDimensions loop
11056+
length := intDiv(length, dimi);
11057+
idxi := intDiv(idx0, length);
11058+
idx0 := idx0 - idxi*length;
11059+
idxOut := idxOut + idxi*fac;
11060+
fac := fac * dimi;
11061+
end for;
11062+
end convertIndexToColumnMajor;
11063+
1101311064
public function isVarIndexListConsecutive "author: marcusw
1101411065
Check if all variable indices of the given variables, stored in the hash table, are consecutive."
1101511066
input HashTableCrIListArray.HashTable iVarToArrayIndexMapping;

SimulationRuntime/cpp/Include/Core/Math/Array.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -452,9 +452,9 @@ class RefArrayDim2 : public RefArray<T, size1*size2>
452452
*/
453453
virtual const T& operator()(const vector<size_t>& idx) const
454454
{
455-
assert((size1*size2) > ((idx[0]-1)*size2 + (idx[1]-1)));
455+
assert((size1*size2) > ((idx[0]-1) + size1*(idx[1]-1)));
456456
return *(RefArray<T, size1*size2>::
457-
_ref_array[(idx[0]-1)*size2 + (idx[1]-1)]);
457+
_ref_array[(idx[0]-1) + size1*(idx[1]-1)]);
458458
}
459459

460460
/**
@@ -463,9 +463,9 @@ class RefArrayDim2 : public RefArray<T, size1*size2>
463463
*/
464464
virtual T& operator()(const vector<size_t>& idx)
465465
{
466-
assert((size1*size2) > ((idx[0]-1)*size2 + (idx[1]-1)));
466+
assert((size1*size2) > ((idx[0]-1) + size1*(idx[1]-1)));
467467
return *(RefArray<T, size1*size2>::
468-
_ref_array[(idx[0]-1)*size2 + (idx[1]-1)]);
468+
_ref_array[(idx[0]-1) + size1*(idx[1]-1)]);
469469
}
470470

471471
/**
@@ -475,9 +475,9 @@ class RefArrayDim2 : public RefArray<T, size1*size2>
475475
*/
476476
inline virtual T& operator()(size_t i, size_t j)
477477
{
478-
assert((size1*size2) > ((i-1)*size2 + (j-1)));
478+
assert((size1*size2) > ((i-1) + size1*(j-1)));
479479
return *(RefArray<T, size1*size2>::
480-
_ref_array[(i-1)*size2 + (j-1)]);
480+
_ref_array[(i-1) + size1*(j-1)]);
481481
}
482482

483483
/**
@@ -580,9 +580,9 @@ class RefArrayDim3 : public RefArray<T, size1*size2*size3>
580580
*/
581581
virtual const T& operator()(const vector<size_t>& idx) const
582582
{
583-
assert((size1*size2*size3) > (size3*(size2*(idx[0]-1) + (idx[1]-1)) + idx[2]-1));
583+
assert(size1*size2*size3 > idx[0]-1 + size1*(idx[1]-1 + size2*(idx[2]-1)));
584584
return *(RefArray<T, size1*size2*size3>::
585-
_ref_array[size3*(size2*(idx[0]-1) + (idx[1]-1)) + idx[2]-1]);
585+
_ref_array[idx[0]-1 + size1*(idx[1]-1 + size2*(idx[2]-1))]);
586586
}
587587

588588
/**
@@ -591,9 +591,9 @@ class RefArrayDim3 : public RefArray<T, size1*size2*size3>
591591
*/
592592
virtual T& operator()(const vector<size_t>& idx)
593593
{
594-
assert((size1*size2*size3) > (size3*(size2*(idx[0]-1) + (idx[1]-1)) + idx[2]-1));
594+
assert(size1*size2*size3 > idx[0]-1 + size1*(idx[1]-1 + size2*(idx[2]-1)));
595595
return *(RefArray<T, size1*size2*size3>::
596-
_ref_array[size3*(size2*(idx[0]-1) + (idx[1]-1)) + idx[2]-1]);
596+
_ref_array[idx[0]-1 + size1*(idx[1]-1 + size2*(idx[2]-1))]);
597597
}
598598

599599
/**
@@ -604,9 +604,9 @@ class RefArrayDim3 : public RefArray<T, size1*size2*size3>
604604
*/
605605
inline virtual T& operator()(size_t i, size_t j, size_t k)
606606
{
607-
assert((size1*size2*size3) > (size3*(size2*(i-1) + (j-1)) + (k-1)));
607+
assert(size1*size2*size3 > i-1 + size1*(j-1 + size2*(k-1)));
608608
return *(RefArray<T, size1*size2*size3>::
609-
_ref_array[size3*(size2*(i-1) + (j-1)) + (k-1)]);
609+
_ref_array[i-1 + size1*(j-1 + size2*(k-1))]);
610610
}
611611

612612
/**

0 commit comments

Comments
 (0)