Skip to content

Commit

Permalink
use ArraySlice for rhs expressions as well, replacing create_array_fr…
Browse files Browse the repository at this point in the history
…om_shape

git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@25443 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
rfranke committed Apr 8, 2015
1 parent cbd5978 commit 267f1de
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 37 deletions.
22 changes: 14 additions & 8 deletions Compiler/Template/CodegenCpp.tpl
Expand Up @@ -11964,21 +11964,27 @@ template daeExpCrefRhs2(Exp ecr, Context context, Text &preExp, Text &varDecls,
else
// The array subscript denotes a slice
let arrName = contextArrayCref(cr, context)
let arrName = contextArrayCref(cr, context)
let arrayType = expTypeFlag(ty, 6)
let typeStr = expTypeArray(ty)
let slice = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp,
&varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace,
stateDerVectorName, useFlatArrayNotation)
let &preExp += 'ArraySlice<<%typeStr%>> <%slice%>_as(<%arrName%>, <%slice%>);<%\n%>'
'<%slice%>_as'
// old code making a copy of the slice using create_array_from_shape
//let arrayType = expTypeFlag(ty, 6)
/* let dimstr = listLength(crefSubs(cr))
let dimsValuesStr = (crefSubs(cr) |> INDEX(__) =>
daeExp(exp, context, &preExp , &varDecls ,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
;separator="][")*/
let tmp = tempDecl(arrayType, &varDecls /*BUFD*/)
let spec1 = daeExpCrefRhsIndexSpec(crefSubs(cr), context, &preExp, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
let &preExp += 'create_array_from_shape(<%spec1%>,<%arrName%>,<%tmp%>);<%\n%>'
tmp
//let tmp = tempDecl(arrayType, &varDecls /*BUFD*/)
//let spec1 = daeExpCrefRhsIndexSpec(crefSubs(cr), context, &preExp, &varDecls, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
//let &preExp += 'create_array_from_shape(<%spec1%>,<%arrName%>,<%tmp%>);<%\n%>'
//tmp
end daeExpCrefRhs2;

template daeExpCrefRhsIndexSpec(list<Subscript> subs, Context context, Text &preExp, Text &varDecls, SimCode simCode, Text& extraFuncs,
Text& extraFuncsDecl, Text extraFuncsNamespace, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation)
"Helper to daeExpCrefRhs."
"Helper to daeExpCrefRhs. Bogus and not used (#3263)."
::=

let nridx_str = listLength(subs)
Expand Down Expand Up @@ -14482,7 +14488,7 @@ 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.
"Helper to algStmtAssignArr. Not used.
Currently works only for CREF_IDENT." ::=
match cr
case CREF_IDENT(subscriptLst=subs as (_ :: _)) then
Expand Down
129 changes: 100 additions & 29 deletions SimulationRuntime/cpp/Include/Core/Math/ArraySlice.h
Expand Up @@ -32,6 +32,7 @@
*/

#include "Array.h"
#include <stdarg.h>

// Modelica slice
// Defined by start:stop or start:step:stop, start = 0 or stop = 0 meaning end,
Expand Down Expand Up @@ -93,7 +94,7 @@ class Slice {

// Multi-dimensional array slice holding a reference to a BaseArray.
template<class T>
class ArraySlice : public BaseArray<T> {
class ArraySlice: public BaseArray<T> {
public:
ArraySlice(BaseArray<T> &baseArray, const vector<Slice> &slice)
: BaseArray<T>(baseArray.isStatic())
Expand All @@ -106,44 +107,51 @@ class ArraySlice : public BaseArray<T> {
"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;
_ndims = 0;
_nelems = 1;
size_t dim;
vector<Slice>::const_iterator sit;
vector< vector<size_t> >::iterator dit = _idxs.begin();
for (dim = 1, sit = slice.begin(); sit != slice.end(); dim++, sit++) {
if (sit->step == 0)
_idxs[dim - 1].assign(sit->indices, sit->indices + sit->nindices);
dit->assign(sit->indices, sit->indices + sit->nindices);
else {
size_t maxIndex = baseArray.getDims()[dim - 1];
size_t maxIndex = baseArray.getDim(dim);
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);
dit->push_back(i);
}
if (dit->size() == 1)
// prefill constant _baseIdx in case of reduction
_baseIdx[dim - 1] = (*dit)[0];
_ndims += dit->size() == 1? 0: 1;
_nelems *= dit->size() != 0? dit->size(): _baseArray.getDim(dim);
dit++;
}
}

virtual T& operator()(const vector<size_t> &idx) {
vector<size_t>::const_iterator it = idx.begin();
size_t dim;
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++;
_baseIdx[dim - 1] = *it++;
break;
case 1:
// reduction
i = (*dit)[0];
break;
default:
// regular index mapping
i = (*dit)[*it++ - 1];
_baseIdx[dim - 1] = (*dit)[*it++ - 1];
}
_baseIdx[dim - 1] = i;
}
return _baseArray(_baseIdx);
}
Expand All @@ -164,7 +172,7 @@ class ArraySlice : public BaseArray<T> {
switch (dit->size()) {
case 0:
// all indices
dims.push_back(_baseArray.getDims()[dim - 1]);
dims.push_back(_baseArray.getDim(dim));
break;
case 1:
// reduction
Expand Down Expand Up @@ -201,29 +209,23 @@ class ArraySlice : public BaseArray<T> {

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

virtual const T* getData() const {
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION,
"Can't get const data pointer of ArraySlice");
if (_tmp_data.size() == 0)
// allocate on first use
_tmp_data.resize(_nelems);
getDataDim(1, &_tmp_data[0]);
return &_tmp_data[0];
}

virtual size_t getNumElems() const {
size_t 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;
return _nelems;
}

virtual size_t getNumDims() const {
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;
return _ndims;
}

virtual void setDims(const std::vector<size_t> &v) {
Expand All @@ -236,17 +238,44 @@ class ArraySlice : public BaseArray<T> {
"Can't resize ArraySlice");
}

virtual T& operator()(size_t i) {
accessElement(1, i);
}

virtual const T& operator()(size_t i) const {
accessElement(1, i);
}

virtual T& operator()(size_t i, size_t j) {
accessElement(2, i, j);
}

virtual T& operator()(size_t i, size_t j, size_t k) {
accessElement(3, i, j, k);
}

virtual T& operator()(size_t i, size_t j, size_t k, size_t l) {
accessElement(4, i, j, k, l);
}

virtual T& operator()(size_t i, size_t j, size_t k, size_t l, size_t m) {
accessElement(5, i, j, k, l, m);
}

protected:
BaseArray<T> &_baseArray;
vector< vector<size_t> > _idxs;
vector<size_t> _baseIdx;
BaseArray<T> &_baseArray; // underlying array
vector< vector<size_t> > _idxs; // index sets per dimension
size_t _ndims; // number of reduced dimensions
size_t _nelems; // number of elements
mutable vector<size_t> _baseIdx; // idx into underlying array
mutable vector<T> _tmp_data; // contiguous storage for const T* getData()

// 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];
size = _baseArray.getDim(dim);
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())
Expand All @@ -256,4 +285,46 @@ class ArraySlice : public BaseArray<T> {
}
return processed;
}

// recursive method for reading raw data
size_t getDataDim(size_t dim, T* data) const {
size_t processed = 0;
size_t size = _idxs[dim - 1].size();
if (size == 0)
size = _baseArray.getDim(dim);
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 += getDataDim(dim + 1, data + processed);
else
data[processed++] = _baseArray(_baseIdx);
}
return processed;
}

T& accessElement(size_t ndims, ...) const {
if (ndims != _ndims)
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION,
"Wrong dimensions accessing ArraySlice");
size_t dim;
va_list args;
va_start(args, ndims);
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
_baseIdx[dim - 1] = va_arg(args, size_t);
break;
case 1:
// reduction
break;
default:
// regular index mapping
_baseIdx[dim - 1] = (*dit)[va_arg(args, size_t) - 1];
}
}
va_end(args);
return _baseArray(_baseIdx);
}
};

0 comments on commit 267f1de

Please sign in to comment.