Skip to content

Commit

Permalink
introduce ArraySlice to treat assignments to subarrays on the lhs (#3263
Browse files Browse the repository at this point in the history
)

git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@25403 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
rfranke committed Apr 7, 2015
1 parent 4661b7e commit 22abefc
Show file tree
Hide file tree
Showing 3 changed files with 273 additions and 4 deletions.
51 changes: 47 additions & 4 deletions Compiler/Template/CodegenCpp.tpl
Expand Up @@ -12067,6 +12067,31 @@ template daeExpCrefRhsArrayBox2(Text var,DAE.Type type, Context context, Text &p
var
end daeExpCrefRhsArrayBox2;


template daeExpCrefIndexSpec(list<Subscript> subs, Context context,
Text &preExp, Text &varDecls, SimCode simCode,
Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace,
Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation)
"Generates index spec of an array as temporary vector<Slice>."
::=
let tmp_slice = tempDecl("vector<Slice>", &varDecls /*BUFD*/)
let &preExp += '<%tmp_slice%>.clear();<%\n%>'
let idx_str = (subs |> sub hasindex i1 =>
match sub
case INDEX(__) then
let expPart = daeExp(exp, context, &preExp /*BUFC*/, &varDecls /*BUFD*/,simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
let &preExp += '<%tmp_slice%>.push_back(Slice(<%expPart%>));<%\n%>'
''
case WHOLEDIM(__) then
let &preExp += '<%tmp_slice%>.push_back(Slice());<%\n%>'
''
case SLICE(__) then
error(sourceInfo(), "Unknown slice expression " + printExpStr(exp))
;separator="\n ")
<<<%tmp_slice%>>>
end daeExpCrefIndexSpec;


template cref1(ComponentRef cr, SimCode simCode ,Text& extraFuncs,Text& extraFuncsDecl,Text extraFuncsNamespace, Context context, Text &varDecls, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation) ::=
match cr
case CREF_IDENT(ident = "xloc") then '<%representationCref(cr, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, context, varDecls, stateDerVectorName, useFlatArrayNotation)%>'
Expand Down Expand Up @@ -14419,22 +14444,40 @@ case STMT_ASSIGN_ARR(exp=e as CALL(__), lhs=CREF(componentRef=cr), type_=t) then
<%preExp%>
<%cref%>.assign(<%expPart%>);
>>
case STMT_ASSIGN_ARR(exp=e, lhs=CREF(componentRef=cr), type_=t) then
case STMT_ASSIGN_ARR(exp=e, lhs=lhsexp as CREF(componentRef=cr), type_=t) then
let &preExp = buffer "" /*BUFD*/
let expPart = daeExp(e, context, &preExp /*BUFC*/, &varDecls /*BUFD*/, simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
let dest = algStmtAssignArrCref(lhsexp, context, &preExp /*BUFC*/, &varDecls /*BUFD*/, simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
/*previous multi_array
<<
<%preExp%>
assign_array(<%contextArrayCref(cr, context)%>,<%expPart%>);
>>
*/
<<
<%preExp%>
<%contextArrayCref(cr, context)%>.assign(<%expPart%>);
>>
<%preExp%>
<%dest%>.assign(<%expPart%>);
>>
end algStmtAssignArr;


template algStmtAssignArrCref(DAE.Exp exp, Context context,
Text &preExp /*BUFP*/, Text &varDecls /*BUFP*/, SimCode simCode,
Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace,
Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation)
"Generates a component reference to an array or a slice of it."
::=
match exp
case CREF(componentRef=cr, ty = T_ARRAY(ty=basety, dims=dims)) then
let typeStr = expTypeArray(ty)
let slice = if crefSubs(cr) then daeExpCrefIndexSpec(crefSubs(cr), context, &preExp /*BUFC*/, &varDecls /*BUFD*/,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
if slice then
'ArraySlice<<%typeStr%>>(<%contextArrayCref(cr, context)%>, <%slice%>)'
else
'<%contextArrayCref(cr, context)%>'
end algStmtAssignArrCref;


template indexSpecFromCref(ComponentRef cr, Context context, Text &preExp /*BUFP*/,
Text &varDecls /*BUFP*/,SimCode simCode, Text& extraFuncs,Text& extraFuncsDecl,Text extraFuncsNamespace, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation)
"Helper to algStmtAssignArr.
Expand Down
225 changes: 225 additions & 0 deletions SimulationRuntime/cpp/Include/Core/Math/ArraySlice.h
@@ -0,0 +1,225 @@
#pragma once
/*
* Implement Modelica array slices.
*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC),
* c/o Linköpings universitet, Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THE BSD NEW LICENSE OR THE
* GPL VERSION 3 LICENSE OR THE OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3,
* ACCORDING TO RECIPIENTS CHOICE.
*
* The OpenModelica software and the OSMC (Open Source Modelica Consortium)
* Public License (OSMC-PL) are obtained from OSMC, either from the above
* address, from the URLs: http://www.openmodelica.org or
* http://www.ida.liu.se/projects/OpenModelica, and in the OpenModelica
* distribution. GNU version 3 is obtained from:
* http://www.gnu.org/copyleft/gpl.html. The New BSD License is obtained from:
* http://www.opensource.org/licenses/BSD-3-Clause.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, EXCEPT AS
* EXPRESSLY SET FORTH IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE
* CONDITIONS OF OSMC-PL.
*
*/

#include "Array.h"

// Modelica slice
// Defined by start:stop or start:step:stop, start = 0 or stop = 0 meaning end,
// or by an index vector if step = 0.
class Slice {
public:
// all indices
Slice() {
this->start = 1;
this->step = 1;
this->stop = 0;
}

// one index
Slice(int index) {
this->start = index;
this->step = 1;
this->stop = index;
}

Slice(int start, int stop) {
this->start = start;
this->step = 1;
this->stop = stop;
}

Slice(int start, int step, int stop) {
this->start = start;
this->step = step;
this->stop = stop;
}

Slice(vector<int> &ivec) {
start = 0;
step = 0;
stop = 0;
vector<int>::const_iterator it;
for (it = ivec.begin(); it != ivec.end(); it++)
indices.push_back(*it);
}

size_t start;
size_t step;
size_t stop;
vector<size_t> indices;
};

// Multi-dimensional array slice holding a reference to a BaseArray.
template<class T>
class ArraySlice : public BaseArray<T> {
public:
ArraySlice(BaseArray<T> &baseArray, const vector<Slice> &slice)
: BaseArray<T>(baseArray.isStatic())
, _baseArray(baseArray)
, _idxs(slice.size())
, _baseIdx(slice.size()) {

if (baseArray.getNumDims() != slice.size())
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION,
"Wrong dimensions for ArraySlice");
// create an explicit index set per dimension,
// except for all indices that are indicated with an empty index set
vector<Slice>::const_iterator sit;
size_t dim;
for (dim = 1, sit = slice.begin(); sit != slice.end(); dim++, sit++) {
if (sit->step == 0)
_idxs[dim - 1] = sit->indices;
else {
size_t maxIndex = baseArray.getDims()[dim - 1];
size_t start = sit->start > 0? sit->start: maxIndex;
size_t stop = sit->stop > 0? sit->stop: maxIndex;
if (start > maxIndex || stop > maxIndex)
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION,
"Wrong slice exceeding array size");
if (start > 1 || sit->step > 1 || stop < maxIndex)
for (size_t i = start; i <= stop; i += sit->step)
_idxs[dim - 1].push_back(i);
}
}
}

virtual T& operator()(vector<size_t> idx) {
vector<size_t>::const_iterator it = idx.begin();
vector< vector<size_t> >::const_iterator dit;
size_t i, dim;
for (dim = 1, dit = _idxs.begin(); dit != _idxs.end(); dim++, dit++) {
switch (dit->size()) {
case 0:
// all indices
i = *it++;
break;
case 1:
// reduction
i = (*dit)[0];
break;
default:
// regular index mapping
i = (*dit)[*it++ - 1];
}
_baseIdx[dim - 1] = i;
}
return _baseArray(_baseIdx);
}

virtual void assign(const T* data) {
setDataDim(1, data);
}

virtual void assign(const BaseArray<T>& otherArray) {
setDataDim(1, otherArray.getData());
}

virtual std::vector<size_t> getDims() const {
vector<size_t> dims;
size_t dim;
vector< vector<size_t> >::const_iterator dit;
for (dim = 1, dit = _idxs.begin(); dit != _idxs.end(); dim++, dit++) {
switch (dit->size()) {
case 0:
// all indices
dims.push_back(_baseArray.getDims()[dim - 1]);
break;
case 1:
// reduction
break;
default:
// regular index mapping
dims.push_back(dit->size());
}
}
return dims;
}

virtual T* getData() {
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION,
"Can't get data pointer of ArraySlice");
}

virtual const T* getData() const {
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION,
"Can't get const data pointer of ArraySlice");
}

virtual unsigned int getNumElems() {
unsigned int nelems = 1;
size_t dim;
vector< vector<size_t> >::const_iterator dit;
for (dim = 1, dit = _idxs.begin(); dit != _idxs.end(); dim++, dit++)
nelems *= dit->size() != 0? dit->size(): _baseArray.getDims()[dim - 1];
return nelems;
}

virtual unsigned int getNumDims() {
int ndims = 0;
vector< vector<size_t> >::const_iterator dit;
for (dit = _idxs.begin(); dit != _idxs.end(); dit++)
ndims += dit->size() == 1? 0: 1;
return ndims;
}

virtual void setDims(std::vector<size_t> v) {
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION,
"Can't set dims of ArraySlice");
}

virtual void resize(std::vector<size_t> dims) {
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION,
"Can't resize ArraySlice");
}

protected:
BaseArray<T> &_baseArray;
vector< vector<size_t> > _idxs;
vector<size_t> _baseIdx;

// recursive method for muli-dimensional assignment of raw data
size_t setDataDim(size_t dim, const T* data) {
size_t processed = 0;
size_t size = _idxs[dim - 1].size();
if (size == 0)
size = _baseArray.getDims()[dim - 1];
for (size_t i = 1; i <= size; i++) {
_baseIdx[dim - 1] = _idxs[dim - 1].size() > 0? _idxs[dim - 1][i - 1]: i;
if (dim < _idxs.size())
processed += setDataDim(dim + 1, data + processed);
else
_baseArray(_baseIdx) = data[processed++];
}
return processed;
}
};
1 change: 1 addition & 0 deletions SimulationRuntime/cpp/Include/Core/Modelica.h
Expand Up @@ -195,6 +195,7 @@ typedef boost::function<void (unordered_map<string,unsigned int>&,unordered_map<
#include <Core/SimulationSettings/ISimControllerSettings.h>
#include <Core/Math/Functions.h>
#include <Core/Math/ArrayOperations.h>
#include <Core/Math/ArraySlice.h>
#include <Core/Math/Utility.h>
#include <Core/Math/SparseMatrix.h>
#include <Core/DataExchange/Policies/TextfileWriter.h>
Expand Down

0 comments on commit 22abefc

Please sign in to comment.