Automatically detected by clang-tidy with performance-move-const-arg check.
Do not make the modification for Tokenizer::location type, since we have no
guarantee that the type will remain trivially-copyable in the future.
Instead of crashing the preprocessor (because DataTree::DivisionByZeroException
is not caught), just abort the normalization and mark it as failed.
Ref. #92
The C99 copysign() function was used in the generated C output, but that
function does not correctly handle zero. Replace it by a custom sign()
function.
Improve performance on very large models (⩾ 5000 equations).
Note that std::unordered_set cannot be used for the temporary_terms_t type,
because ordering is needed there (for writing the output files).
This is effectively a revert of commits 1b4f68f934,
32fb90d5f3 and f6f4ea70fb.
This transformation had been introduced in order to fix the computation of the
Ramsey steady state in the case where Lagrange multipliers appeared with a lead
or lag ⩾ 2 (and where thus part of the definition of an auxiliary variable).
But this transformation had introduced bugs in the handling of external
functions which were difficult to tackle.
Moreover, it seems preferable to keep the strict correspondence between the
dynamic and static model, in order to make reasoning about the preprocessor
internals easier (in particular, for this reason this transformation was not
implemented in ModFile::transformPass() but in ModFile::computingPass(), which
was a bit confusing).
A better solution for the Ramsey steady state issue will is implemented in the
descendent of the present commit.
Ref. dynare#633, dynare#1119, dynare#1133
If a given external function was called two times with different arguments,
then the second call would always be computed in the same temporary terms
chunk (derivation order or block) as the first call, even if this was not
necessary (technically, the second call would be promoted in the temporary
terms computation in the same category as the first call).
This could possibly lead to an inefficiency.
If an endogenous with a lead ⩾ 2 or an exogenous with a lead ⩾ 1 appeared in
the argument(s) of a call to an external function, the auxiliary variable
transformation was incorrect (the variable was replaced inside the function
call, while it is the whole function call that has to be replaced).
This could lead to incorrect results in stochastic contexts, when the external
function is nonlinear.
The argument had the same name as the data member “datatree”, so this could
lead to confusion (though there was no bug, since the argument was masking
the data member).
Commit 23b0c12d8e introduced caching in chain
rule derivation (used by block decomposition), which increased speed for mfs >
0, but actually decreased it for mfs=0.
This patch introduces the pre-computation of derivatives which are known to be
zero using symbolic a priori (similarly to what is done in the non-chain rule
context). The algorithms are now identical between the two contexts (both
symbolic a priori + caching), the difference being that in the chain rule
context, the symbolic a priori and the cache are not stored within the ExprNode
class, since they depend on the list of recursive variables.
This patch brings a significant performant improvement for all values of the
“mfs” option (the improvement is greater for small values of “mfs”).
Input and output ranges should not overlap when calling std::set_union(),
otherwise the behaviour is undefined.
It seems that in this precise case the computation would still be
correct (though inefficient), because of the properties of std::set or because
of the specific implementation in libstdc++. But it’s better to be on the safe
side.
In a dynamic context, the only potentially non-null derivatives of
STEADY_STATE(…) are the parameters. We know that the derivatives w.r.t. other
variables are zero, so store that information in non_null_derivatives.
More precisely, incorrect equation normalization could occur in the presence of
cos, sin, tan, cosh and x^n (where n is an even integer).
Also add some comments explaining why some other rules are (hopefully) correct.
The new representation is only supported for MATLAB/Octave, C and Julia output
for the time being. Bytecode and JSON are unsupported.
This commit adds new fields in M_.
This is a preliminary step for dynare#1859.
Should have no impact though, since diff nodes are already substituted out at
that point. But it’s better to implement it properly, in case we change the
substitution rules later.
By the way, make the computeSubExprContainingVariable method protected.
– factorize common code between the static and the dynamic version
– reorganise language-specific code into dedicated functions
– use a function template in the main helper to do some computations
at compile-time (using constexpr features)
When the same complex expression appears outside and inside a steady_state()
operator, the same temporary term would be used for both cases, which was
obviously wrong.
The fix consists in never substituting temporary terms for expressions inside
the steady_state operator().
Incidentally, this implies that external functions can no longer be used inside
steady_state operators (since their computed values are stored inside temporary
terms).