Skip to content

Commit

Permalink
[Cpp] Implement array fill assignments
Browse files Browse the repository at this point in the history
This prevents temporary arrays with all equal elements.
Also fix the assignment of bool(ean) arrays in CodegenCpp.tpl.

Belonging to [master]:
  - OpenModelica/OMCompiler#2792
  - OpenModelica/OpenModelica-testsuite#1078
  • Loading branch information
rfranke authored and OpenModelica-Hudson committed Nov 19, 2018
1 parent e2321ae commit cb53a44
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 3 deletions.
7 changes: 5 additions & 2 deletions Compiler/Template/CodegenCpp.tpl
Expand Up @@ -10989,19 +10989,22 @@ case eqn as SES_ARRAY_CALL_ASSIGN(lhs=lhs as CREF(__)) then
'localData->helpVars[<%hidx%>] && !localData->helpVars_saved[<%hidx%>] /* edge */'
;separator=" || ")C*/, &varDecls /*BUFD*/,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)
match expTypeFromExpShort(eqn.exp)
case "boolean"
case "bool"
case "int" then
let lhsStr = cref1(lhs.componentRef, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, context, varDeclsCref, stateDerVectorName, useFlatArrayNotation)
<<
<%if not assignToStartValues then '<%startFixedExp%>'%>
<%preExp%>
<%cref1(lhs.componentRef,simCode , &extraFuncs , &extraFuncsDecl, extraFuncsNamespace, context, varDeclsCref, stateDerVectorName, useFlatArrayNotation)%>=<%expPart%>;
<%lhsStr%>.assign(<%expPart%>);
>>
case "double" then
<<
<%if not assignToStartValues then '<%startFixedExp%>'%>
<%preExp%>
<%assignDerArray(context, expPart, lhs, simCode, &extraFuncs, &extraFuncsDecl, extraFuncsNamespace, stateDerVectorName, useFlatArrayNotation)%>
>>
else
error(sourceInfo(), 'Unsupported type of array call assign: <%expTypeFromExpShort(eqn.exp)%>')
end equationArrayCallAssign;

template assignDerArray(Context context, String arr, Exp lhs_ecr, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, Text stateDerVectorName /*=__zDot*/, Boolean useFlatArrayNotation)
Expand Down
33 changes: 32 additions & 1 deletion SimulationRuntime/cpp/Include/Core/Math/Array.h
Expand Up @@ -88,9 +88,9 @@ template<typename T> class BaseArray
virtual T& operator()(const vector<size_t>& idx) = 0;
virtual void assign(const T* data) = 0;
virtual void assign(const BaseArray<T>& b) = 0;
virtual void assign(const T& value) = 0; // fill value
virtual std::vector<size_t> getDims() const = 0;
virtual int getDim(size_t dim) const = 0; // { (int)getDims()[dim - 1]; }

virtual size_t getNumElems() const = 0;
virtual size_t getNumDims() const = 0;
virtual void setDims(const std::vector<size_t>& v) = 0;
Expand Down Expand Up @@ -271,6 +271,17 @@ class RefArray : public BaseArray<T>
_ref_array, CopyCArray2RefArray<T>());
}

/**
* Assigns value reference to each array element
* @param value new value for each element
* a.assign(value)
*/
virtual void assign(const T& value)
{
for (size_t i = 0; i < nelems; i++)
*_ref_array[i] = value;
}

/**
* Access to data (read-only)
*/
Expand Down Expand Up @@ -757,6 +768,20 @@ class StatArray : public BaseArray<T>
}
}

/**
* Assigns value to each array element
* @param value new array value
* a.assign(value)
*/
virtual void assign(const T& value)
{
if (nelems > 0) {
if (_data == NULL)
throw std::runtime_error("Cannot assign value to uninitialized StatArray!");
std::fill(_data, _data + nelems, value);
}
}

/**
* Access to data
*/
Expand Down Expand Up @@ -1397,6 +1422,12 @@ class DynArray : public BaseArray<T>
std::copy(data, data + _nelems, _array_data);
}

virtual void assign(const T& value)
{
if (_nelems > 0)
std::fill(_array_data, _array_data + _nelems, value);
}

virtual void resize(const std::vector<size_t>& dims)
{
if (dims.size() != ndims)
Expand Down
29 changes: 29 additions & 0 deletions SimulationRuntime/cpp/Include/Core/Math/ArraySlice.h
Expand Up @@ -176,6 +176,11 @@ class ArraySliceConst: public BaseArray<T> {
"Can't assign array to ArraySliceConst");
}

virtual void assign(const T& value) {
throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION,
"Can't assign value to ArraySliceConst");
}

virtual std::vector<size_t> getDims() const {
return _dims;
}
Expand Down Expand Up @@ -340,6 +345,10 @@ class ArraySlice: public ArraySliceConst<T> {
setDataDim(_idxs.size(), otherArray.getData());
}

virtual void assign(const T& value) {
setEachDim(_idxs.size(), value);
}

virtual T& operator()(size_t i) {
return _baseArray(ArraySliceConst<T>::baseIdx(1, &i));
}
Expand Down Expand Up @@ -390,5 +399,25 @@ class ArraySlice: public ArraySliceConst<T> {
}
return processed;
}

/**
* recursive method for muli-dimensional fill of each element
*/
void setEachDim(size_t dim, const T& value) {
const BaseArray<int> *iset = ArraySliceConst<T>::_isets[dim - 1];
size_t size = iset? iset->getNumElems(): _idxs[dim - 1].size();
if (size == 0)
size = _baseArray.getDim(dim);
for (size_t i = 1; i <= size; i++) {
if (iset)
_baseIdx[dim - 1] = iset->getNumElems() > 0? (*iset)(i): i;
else
_baseIdx[dim - 1] = _idxs[dim - 1].size() > 0? _idxs[dim - 1][i - 1]: i;
if (dim > 1)
setEachDim(dim - 1, value);
else
_baseArray(_baseIdx) = value;
}
}
};
/** @} */ // end of math

0 comments on commit cb53a44

Please sign in to comment.