The functions erf, normpdf and normcdf work fine with bytecode option
parent
1c51ddf34b
commit
a812b0130e
|
@ -86,6 +86,7 @@ enum Tags
|
||||||
|
|
||||||
FUNARY, //!< A Unary operator - 14
|
FUNARY, //!< A Unary operator - 14
|
||||||
FBINARY, //!< A binary operator - 15
|
FBINARY, //!< A binary operator - 15
|
||||||
|
FTRINARY, //!< A trinary operator - 15'
|
||||||
|
|
||||||
FCUML, //!< Cumulates the result - 16
|
FCUML, //!< Cumulates the result - 16
|
||||||
|
|
||||||
|
@ -610,6 +611,22 @@ public:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FTRINARY_ : public TagWithOneArgument<uint8_t>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline FTRINARY_() : TagWithOneArgument<uint8_t>::TagWithOneArgument(FTRINARY)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
inline FTRINARY_(const int op_type_arg) : TagWithOneArgument<uint8_t>::TagWithOneArgument(FTRINARY, op_type_arg)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
inline uint8_t
|
||||||
|
get_op_type()
|
||||||
|
{
|
||||||
|
return arg1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
class FOK_ : public TagWithOneArgument<int>
|
class FOK_ : public TagWithOneArgument<int>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -1178,6 +1195,13 @@ public:
|
||||||
tags_liste.push_back(make_pair(FBINARY, code));
|
tags_liste.push_back(make_pair(FBINARY, code));
|
||||||
code += sizeof(FBINARY_);
|
code += sizeof(FBINARY_);
|
||||||
break;
|
break;
|
||||||
|
case FTRINARY:
|
||||||
|
# ifdef DEBUGL
|
||||||
|
mexPrintf("FTRINARY\n");
|
||||||
|
# endif
|
||||||
|
tags_liste.push_back(make_pair(FTRINARY, code));
|
||||||
|
code += sizeof(FTRINARY_);
|
||||||
|
break;
|
||||||
case FOK:
|
case FOK:
|
||||||
# ifdef DEBUGL
|
# ifdef DEBUGL
|
||||||
mexPrintf("FOK\n");
|
mexPrintf("FOK\n");
|
||||||
|
|
94
ExprNode.cc
94
ExprNode.cc
|
@ -237,6 +237,18 @@ ExprNode::createExoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<
|
||||||
return dynamic_cast<VariableNode *>(substexpr);
|
return dynamic_cast<VariableNode *>(substexpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ExprNode::isNumConstNodeEqualTo(double value) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ExprNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
NumConstNode::NumConstNode(DataTree &datatree_arg, int id_arg) :
|
NumConstNode::NumConstNode(DataTree &datatree_arg, int id_arg) :
|
||||||
ExprNode(datatree_arg),
|
ExprNode(datatree_arg),
|
||||||
id(id_arg)
|
id(id_arg)
|
||||||
|
@ -385,6 +397,21 @@ VariableNode::VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg)
|
||||||
&& (lag == 0 || (type != eModelLocalVariable && type != eModFileLocalVariable)));
|
&& (lag == 0 || (type != eModelLocalVariable && type != eModFileLocalVariable)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NumConstNode::isNumConstNodeEqualTo(double value) const
|
||||||
|
{
|
||||||
|
if (datatree.num_constants.getDouble(id) == value)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NumConstNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VariableNode::prepareForDerivation()
|
VariableNode::prepareForDerivation()
|
||||||
{
|
{
|
||||||
|
@ -999,6 +1026,21 @@ VariableNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpN
|
||||||
return const_cast<VariableNode *>(this);
|
return const_cast<VariableNode *>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
VariableNode::isNumConstNodeEqualTo(double value) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
VariableNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
|
||||||
|
{
|
||||||
|
if (type == type_arg && datatree.symbol_table.getTypeSpecificID(symb_id) == variable_id && lag == lag_arg)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const NodeID arg_arg, const int expectation_information_set_arg, const string &expectation_information_set_name_arg) :
|
UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const NodeID arg_arg, const int expectation_information_set_arg, const string &expectation_information_set_name_arg) :
|
||||||
ExprNode(datatree_arg),
|
ExprNode(datatree_arg),
|
||||||
arg(arg_arg),
|
arg(arg_arg),
|
||||||
|
@ -1820,6 +1862,18 @@ UnaryOpNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
UnaryOpNode::isNumConstNodeEqualTo(double value) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
UnaryOpNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const NodeID arg1_arg,
|
BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const NodeID arg1_arg,
|
||||||
BinaryOpcode op_code_arg, const NodeID arg2_arg) :
|
BinaryOpcode op_code_arg, const NodeID arg2_arg) :
|
||||||
ExprNode(datatree_arg),
|
ExprNode(datatree_arg),
|
||||||
|
@ -2810,6 +2864,18 @@ BinaryOpNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpN
|
||||||
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
|
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
BinaryOpNode::isNumConstNodeEqualTo(double value) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
BinaryOpNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
TrinaryOpNode::TrinaryOpNode(DataTree &datatree_arg, const NodeID arg1_arg,
|
TrinaryOpNode::TrinaryOpNode(DataTree &datatree_arg, const NodeID arg1_arg,
|
||||||
TrinaryOpcode op_code_arg, const NodeID arg2_arg, const NodeID arg3_arg) :
|
TrinaryOpcode op_code_arg, const NodeID arg2_arg, const NodeID arg3_arg) :
|
||||||
ExprNode(datatree_arg),
|
ExprNode(datatree_arg),
|
||||||
|
@ -3077,8 +3143,8 @@ TrinaryOpNode::compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms
|
||||||
arg1->compile(CompileCode, lhs_rhs, temporary_terms, map_idx, dynamic, steady_dynamic);
|
arg1->compile(CompileCode, lhs_rhs, temporary_terms, map_idx, dynamic, steady_dynamic);
|
||||||
arg2->compile(CompileCode, lhs_rhs, temporary_terms, map_idx, dynamic, steady_dynamic);
|
arg2->compile(CompileCode, lhs_rhs, temporary_terms, map_idx, dynamic, steady_dynamic);
|
||||||
arg3->compile(CompileCode, lhs_rhs, temporary_terms, map_idx, dynamic, steady_dynamic);
|
arg3->compile(CompileCode, lhs_rhs, temporary_terms, map_idx, dynamic, steady_dynamic);
|
||||||
FBINARY_ fbinary(op_code);
|
FTRINARY_ ftrinary(op_code);
|
||||||
fbinary.write(CompileCode);
|
ftrinary.write(CompileCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -3306,6 +3372,18 @@ TrinaryOpNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOp
|
||||||
return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
|
return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TrinaryOpNode::isNumConstNodeEqualTo(double value) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TrinaryOpNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ExternalFunctionNode::ExternalFunctionNode(DataTree &datatree_arg,
|
ExternalFunctionNode::ExternalFunctionNode(DataTree &datatree_arg,
|
||||||
int symb_id_arg,
|
int symb_id_arg,
|
||||||
const vector<NodeID> &arguments_arg) :
|
const vector<NodeID> &arguments_arg) :
|
||||||
|
@ -3632,6 +3710,18 @@ ExternalFunctionNode::getIndxInTefTerms(int the_symb_id, deriv_node_temp_terms_t
|
||||||
throw UnknownFunctionNameAndArgs();
|
throw UnknownFunctionNameAndArgs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ExternalFunctionNode::isNumConstNodeEqualTo(double value) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ExternalFunctionNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
FirstDerivExternalFunctionNode::FirstDerivExternalFunctionNode(DataTree &datatree_arg,
|
FirstDerivExternalFunctionNode::FirstDerivExternalFunctionNode(DataTree &datatree_arg,
|
||||||
int top_level_symb_id_arg,
|
int top_level_symb_id_arg,
|
||||||
const vector<NodeID> &arguments_arg,
|
const vector<NodeID> &arguments_arg,
|
||||||
|
|
26
ExprNode.hh
26
ExprNode.hh
|
@ -333,6 +333,20 @@ public:
|
||||||
|
|
||||||
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const = 0;
|
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const = 0;
|
||||||
|
|
||||||
|
//! Return true if the nodeID is a numerical constant equal to value and false otherwise
|
||||||
|
/*!
|
||||||
|
\param[in] value of the numerical constante
|
||||||
|
\param[out] the boolean equal to true if NodeId is a constant equal to value
|
||||||
|
*/
|
||||||
|
virtual bool isNumConstNodeEqualTo(double value) const = 0;
|
||||||
|
|
||||||
|
//! Return true if the nodeID is a variable withe a type equal to type_arg, a specific variable id aqual to varfiable_id and a lag equal to lag_arg and false otherwise
|
||||||
|
/*!
|
||||||
|
\param[in] the type (type_arg), specifique variable id (variable_id and the lag (lag_arg)
|
||||||
|
\param[out] the boolean equal to true if NodeId is the variable
|
||||||
|
*/
|
||||||
|
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Object used to compare two nodes (using their indexes)
|
//! Object used to compare two nodes (using their indexes)
|
||||||
|
@ -378,6 +392,8 @@ public:
|
||||||
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||||
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
||||||
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
||||||
|
virtual bool isNumConstNodeEqualTo(double value) const;
|
||||||
|
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Symbol or variable node
|
//! Symbol or variable node
|
||||||
|
@ -421,6 +437,8 @@ public:
|
||||||
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||||
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
||||||
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
||||||
|
virtual bool isNumConstNodeEqualTo(double value) const;
|
||||||
|
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Unary operator node
|
//! Unary operator node
|
||||||
|
@ -482,6 +500,8 @@ public:
|
||||||
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||||
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
||||||
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
||||||
|
virtual bool isNumConstNodeEqualTo(double value) const;
|
||||||
|
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Binary operator node
|
//! Binary operator node
|
||||||
|
@ -548,6 +568,8 @@ public:
|
||||||
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||||
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
||||||
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
||||||
|
virtual bool isNumConstNodeEqualTo(double value) const;
|
||||||
|
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Trinary operator node
|
//! Trinary operator node
|
||||||
|
@ -596,6 +618,8 @@ public:
|
||||||
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||||
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
||||||
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
||||||
|
virtual bool isNumConstNodeEqualTo(double value) const;
|
||||||
|
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! External function node
|
//! External function node
|
||||||
|
@ -649,6 +673,8 @@ public:
|
||||||
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
||||||
virtual NodeID buildSimilarExternalFunctionNode(vector<NodeID> &alt_args, DataTree &alt_datatree) const;
|
virtual NodeID buildSimilarExternalFunctionNode(vector<NodeID> &alt_args, DataTree &alt_datatree) const;
|
||||||
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
||||||
|
virtual bool isNumConstNodeEqualTo(double value) const;
|
||||||
|
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FirstDerivExternalFunctionNode : public ExternalFunctionNode
|
class FirstDerivExternalFunctionNode : public ExternalFunctionNode
|
||||||
|
|
11
ModelTree.cc
11
ModelTree.cc
|
@ -414,10 +414,7 @@ t_equation_type_and_normalized_equation
|
||||||
ModelTree::equationTypeDetermination(vector<BinaryOpNode *> &equations, map<pair<int, pair<int, int> >, NodeID> &first_order_endo_derivatives, vector<int> &Index_Var_IM, vector<int> &Index_Equ_IM, int mfs)
|
ModelTree::equationTypeDetermination(vector<BinaryOpNode *> &equations, map<pair<int, pair<int, int> >, NodeID> &first_order_endo_derivatives, vector<int> &Index_Var_IM, vector<int> &Index_Equ_IM, int mfs)
|
||||||
{
|
{
|
||||||
NodeID lhs, rhs;
|
NodeID lhs, rhs;
|
||||||
ostringstream tmp_output;
|
|
||||||
BinaryOpNode *eq_node;
|
BinaryOpNode *eq_node;
|
||||||
ostringstream tmp_s;
|
|
||||||
temporary_terms_type temporary_terms;
|
|
||||||
EquationType Equation_Simulation_Type;
|
EquationType Equation_Simulation_Type;
|
||||||
t_equation_type_and_normalized_equation V_Equation_Simulation_Type(equations.size());
|
t_equation_type_and_normalized_equation V_Equation_Simulation_Type(equations.size());
|
||||||
for (unsigned int i = 0; i < equations.size(); i++)
|
for (unsigned int i = 0; i < equations.size(); i++)
|
||||||
|
@ -429,10 +426,6 @@ ModelTree::equationTypeDetermination(vector<BinaryOpNode *> &equations, map<pair
|
||||||
lhs = eq_node->get_arg1();
|
lhs = eq_node->get_arg1();
|
||||||
rhs = eq_node->get_arg2();
|
rhs = eq_node->get_arg2();
|
||||||
Equation_Simulation_Type = E_SOLVE;
|
Equation_Simulation_Type = E_SOLVE;
|
||||||
tmp_s.str("");
|
|
||||||
tmp_output.str("");
|
|
||||||
lhs->writeOutput(tmp_output, oMatlabDynamicModelSparse, temporary_terms);
|
|
||||||
tmp_s << "y(it_, " << Index_Var_IM[i]+1 << ")";
|
|
||||||
map<pair<int, pair<int, int> >, NodeID>::iterator derivative = first_order_endo_derivatives.find(make_pair(eq, make_pair(var, 0)));
|
map<pair<int, pair<int, int> >, NodeID>::iterator derivative = first_order_endo_derivatives.find(make_pair(eq, make_pair(var, 0)));
|
||||||
pair<bool, NodeID> res;
|
pair<bool, NodeID> res;
|
||||||
if (derivative != first_order_endo_derivatives.end())
|
if (derivative != first_order_endo_derivatives.end())
|
||||||
|
@ -441,9 +434,7 @@ ModelTree::equationTypeDetermination(vector<BinaryOpNode *> &equations, map<pair
|
||||||
derivative->second->collectEndogenous(result);
|
derivative->second->collectEndogenous(result);
|
||||||
set<pair<int, int> >::const_iterator d_endo_variable = result.find(make_pair(var, 0));
|
set<pair<int, int> >::const_iterator d_endo_variable = result.find(make_pair(var, 0));
|
||||||
//Determine whether the equation could be evaluated rather than to be solved
|
//Determine whether the equation could be evaluated rather than to be solved
|
||||||
ostringstream tt("");
|
if (lhs->isVariableNodeEqualTo(eEndogenous, Index_Var_IM[i], 0) && derivative->second->isNumConstNodeEqualTo(1))
|
||||||
derivative->second->writeOutput(tt, oMatlabDynamicModelSparse, temporary_terms);
|
|
||||||
if (tmp_output.str() == tmp_s.str() and tt.str() == "1")
|
|
||||||
{
|
{
|
||||||
Equation_Simulation_Type = E_EVALUATE;
|
Equation_Simulation_Type = E_EVALUATE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue