CValidatedUnit CEvaluationNodeCall::getUnit(const CMathContainer & math, const std::vector< CValidatedUnit > & units) const { CEvaluationTree * pTree = NULL; switch (mSubType) { case S_FUNCTION: pTree = mpFunction; break; case S_EXPRESSION: pTree = mpExpression; break; default: return CValidatedUnit(); break; } CUnitValidator Validator(math, *pTree); Validator.validateUnits(CValidatedUnit(CBaseUnit::undefined, false), units); return Validator.getUnit(); }
void CUnitValidator::getUnits() { CValidatedUnit tmpUnit; CNodeContextIterator< CEvaluationNode, std::vector< CValidatedUnit > > it(const_cast< CEvaluationNode * >(mTree.getRoot())); while (it.next() != it.end()) { if (*it != NULL) { switch (it->mainType()) { case CEvaluationNode::T_VARIABLE: tmpUnit = it->getUnit(mMathContainer, mVariableUnits); break; case CEvaluationNode::T_OBJECT: { CObjectInterface * pObject = const_cast< CObjectInterface * >(static_cast< CEvaluationNodeObject * >(*it)->getObjectInterfacePtr()); std::vector< CValidatedUnit > ObjectUnit; if (pObject != NULL) { std::map < CObjectInterface *, CValidatedUnit >::iterator found = mObjectUnits.find(pObject); if (found == mObjectUnits.end()) { found = mObjectUnits.insert(std::make_pair(pObject, CValidatedUnit(CBaseUnit::undefined, false))).first; } ObjectUnit.push_back(found->second); } else { ObjectUnit.push_back(CValidatedUnit(CBaseUnit::undefined, false)); } tmpUnit = it->getUnit(mMathContainer, ObjectUnit); } break; default: tmpUnit = it->getUnit(mMathContainer, it.context()); break; } if (it.parentContextPtr() != NULL) { it.parentContextPtr()->push_back(tmpUnit); } // tmpUnit.buildExpression(pretty); // std::cout << "getUnit: " << it->getData() << ", " << tmpUnit.getExpression() << std::endl; mNodeUnits[*it] = tmpUnit; } } }
bool CUnitValidator::validateUnits(const CUnit & unit, const std::vector< CUnit > & variableUnits) { mTargetUnit = CValidatedUnit(unit, false); mProvidedVariableUnits.resize(variableUnits.size()); std::vector< CUnit >::const_iterator itSrc = variableUnits.begin(); std::vector< CUnit >::const_iterator endSrc = variableUnits.end(); std::vector< CValidatedUnit >::iterator itTarget = mProvidedVariableUnits.begin(); for (; itSrc != endSrc; ++itSrc, ++itTarget) { *itTarget = CValidatedUnit(*itSrc, false); } return validate(); }
// virtual CValidatedUnit CEvaluationNodeVariable::getUnit(const CMathContainer & /* container */, const std::vector< CValidatedUnit > & units) const { if (mIndex < units.size()) { return units[mIndex]; } return CValidatedUnit(); }
// virtual CValidatedUnit CEvaluationNodeCall::setUnit(const CMathContainer & container, const std::map < CEvaluationNode *, CValidatedUnit > & currentUnits, std::map < CEvaluationNode *, CValidatedUnit > & targetUnits) const { CEvaluationTree * pTree = NULL; switch (mSubType) { case S_FUNCTION: pTree = mpFunction; break; case S_EXPRESSION: pTree = mpExpression; break; default: return CValidatedUnit(); break; } // Retrieve the current units of the variables std::vector< CEvaluationNode * >::const_iterator it = mCallNodes.begin(); std::vector< CEvaluationNode * >::const_iterator end = mCallNodes.end(); std::vector< CValidatedUnit > CurrentVariableUnits(mCallNodes.size()); std::vector< CValidatedUnit >::iterator itUnit = CurrentVariableUnits.begin(); for (; it != end; ++it, ++itUnit) { *itUnit = currentUnits.find(const_cast< CEvaluationNode * >(*it))->second; } CUnitValidator Validator(container, *pTree); Validator.validateUnits(CValidatedUnit::merge(currentUnits.find(const_cast< CEvaluationNodeCall * >(this))->second, targetUnits[const_cast< CEvaluationNodeCall * >(this)]), CurrentVariableUnits); std::vector< CValidatedUnit >::const_iterator itValidatedVariableUnit = Validator.getVariableUnits().begin(); for (it = mCallNodes.begin(); it != end; ++it, ++itValidatedVariableUnit) { std::map < CEvaluationNode * , CValidatedUnit >::iterator found = targetUnits.find(const_cast< CEvaluationNode * >(*it)); if (found == targetUnits.end()) { found = targetUnits.insert(std::make_pair(const_cast< CEvaluationNode * >(*it), CValidatedUnit(CBaseUnit::undefined, false))).first; } found->second = CValidatedUnit::merge(found->second, *itValidatedVariableUnit); } return Validator.getUnit(); }
// virtual CValidatedUnit CEvaluationNodeDelay::setUnit(const CMathContainer & container, const std::map < CEvaluationNode * , CValidatedUnit > & currentUnits, std::map < CEvaluationNode * , CValidatedUnit > & targetUnits) const { CValidatedUnit Delay(CEvaluationNode::setUnit(container, currentUnits, targetUnits)); targetUnits[mpDelayValueNode] = Delay; targetUnits[mpDelayLagNode] = CValidatedUnit(container.getModel().getTimeUnit(), false); return Delay; }
// virtual CValidatedUnit CEvaluationNodeDelay::getUnit(const CMathContainer & container, const std::vector< CValidatedUnit > & units) const { // The units of the delay functions are the units of the delay value which is the first child CValidatedUnit Delay = units[0]; CValidatedUnit Lag = CValidatedUnit::merge(CValidatedUnit(container.getModel().getTimeUnit(), false), units[1]); Delay.setConflict(Delay.conflict() || Lag.conflict()); return Delay; }
//virtual CValidatedUnit CEvaluationNode::getUnit(const CMathContainer & /* math */, const std::vector< CValidatedUnit > & /*units*/) const { return CValidatedUnit(CBaseUnit::dimensionless, false); }
bool CUnitValidator::setUnits() { bool UnitDetermined = false; CValidatedUnit tmpUnit; std::map < CEvaluationNode * , CValidatedUnit > CurrentNodeUnits(mNodeUnits); std::map < CEvaluationNode * , CValidatedUnit > TargetNodeUnits; mNodeUnits.clear(); std::map < CEvaluationNode * , CValidatedUnit >::iterator found; CNodeIterator< CEvaluationNode > it(const_cast< CEvaluationNode * >(mTree.getRoot())); it.setProcessingModes(CNodeIteratorMode::Before); TargetNodeUnits.insert(std::make_pair(*it, mTargetUnit)); while (it.next() != it.end()) { if (*it != NULL) { tmpUnit = it->setUnit(mMathContainer, CurrentNodeUnits, TargetNodeUnits); mNodeUnits[*it] = tmpUnit; // tmpUnit.buildExpression(pretty); // std::cout << "setUnit: " << it->getData() << ", " << tmpUnit.getExpression() << std::endl; switch (it->mainType()) { case CEvaluationNode::T_VARIABLE: { size_t Index = static_cast< CEvaluationNodeVariable * >(*it)->getIndex(); if (Index >= mVariableUnits.size()) { CValidatedUnit Default; mVariableUnits.resize(Index, Default); } bool Undefined = mVariableUnits[Index] == CBaseUnit::undefined; mVariableUnits[Index] = CValidatedUnit::merge(mVariableUnits[Index], tmpUnit); UnitDetermined |= Undefined && !(mVariableUnits[Index] == CBaseUnit::undefined); } break; case CEvaluationNode::T_OBJECT: { CObjectInterface * pObject = const_cast< CObjectInterface * >(static_cast< CEvaluationNodeObject * >(*it)->getObjectInterfacePtr()); if (pObject != NULL) { std::map < CObjectInterface *, CValidatedUnit >::iterator found = mObjectUnits.find(pObject); if (found == mObjectUnits.end()) { found = mObjectUnits.insert(std::make_pair(pObject, CValidatedUnit(CBaseUnit::undefined, false))).first; } bool Undefined = found->second == CBaseUnit::undefined; found->second = CValidatedUnit::merge(found->second, tmpUnit); UnitDetermined |= Undefined && !(found->second == CBaseUnit::undefined); } } break; default: break; } } } std::cout << std::endl; return UnitDetermined; }
// virtual CValidatedUnit CEvaluationNodeFunction::setUnit(const CMathContainer & container, const std::map < CEvaluationNode * , CValidatedUnit > & currentUnits, std::map < CEvaluationNode * , CValidatedUnit > & targetUnits) const { CValidatedUnit Result = CValidatedUnit::merge(currentUnits.find(const_cast< CEvaluationNodeFunction * >(this))->second, targetUnits[const_cast< CEvaluationNodeFunction * >(this)]); switch ((SubType)this->subType()) { case S_LOG: case S_LOG10: case S_EXP: case S_SIN: case S_COS: case S_TAN: case S_SEC: case S_CSC: case S_COT: case S_SINH: case S_COSH: case S_TANH: case S_SECH: case S_CSCH: case S_COTH: case S_ARCSIN: case S_ARCCOS: case S_ARCTAN: case S_ARCSEC: case S_ARCCSC: case S_ARCCOT: case S_ARCSINH: case S_ARCCOSH: case S_ARCTANH: case S_ARCSECH: case S_ARCCSCH: case S_ARCCOTH: case S_FACTORIAL: case S_NOT: targetUnits[mpArgNode1] = CValidatedUnit(CBaseUnit::dimensionless, false); break; case S_MAX: case S_MIN: case S_RUNIFORM: case S_RNORMAL: targetUnits[mpArgNode1] = Result; targetUnits[mpArgNode2] = Result; break; case S_MINUS: case S_PLUS: case S_FLOOR: case S_CEIL: case S_ABS: case S_RPOISSON: targetUnits[mpArgNode1] = Result; break; case S_RGAMMA: targetUnits[mpArgNode1] = CValidatedUnit(CBaseUnit::dimensionless, false); targetUnits[mpArgNode2] = Result.exponentiate(-1); break; case S_SQRT: targetUnits[mpArgNode1] = Result.exponentiate(2.0); break; default: Result.setConflict(true); break; } return Result; }
CValidatedUnit CEvaluationNodeFunction::getUnit(const CMathContainer & /* container */, const std::vector< CValidatedUnit > & units) const { CValidatedUnit Unit(CBaseUnit::dimensionless, false); switch ((SubType)this->subType()) { case S_LOG: case S_LOG10: case S_EXP: case S_SIN: case S_COS: case S_TAN: case S_SEC: case S_CSC: case S_COT: case S_SINH: case S_COSH: case S_TANH: case S_SECH: case S_CSCH: case S_COTH: case S_ARCSIN: case S_ARCCOS: case S_ARCTAN: case S_ARCSEC: case S_ARCCSC: case S_ARCCOT: case S_ARCSINH: case S_ARCCOSH: case S_ARCTANH: case S_ARCSECH: case S_ARCCSCH: case S_ARCCOTH: case S_FACTORIAL: case S_NOT: Unit = CValidatedUnit::merge(Unit, units[0]); break; case S_MAX: case S_MIN: case S_RUNIFORM: case S_RNORMAL: Unit = CValidatedUnit::merge(units[0], units[1]); break; case S_MINUS: case S_PLUS: case S_FLOOR: case S_CEIL: case S_ABS: case S_RPOISSON: Unit = units[0]; break; case S_RGAMMA: // The unit of the gamma distribution is the inverse of the scale parameter (units[1]) Unit = units[1].exponentiate(-1); // The shape parameter must be dimensionless if (!Unit.conflict()) { Unit.setConflict(!(units[0] == CUnit(CBaseUnit::dimensionless))); } break; case S_SQRT: { // Exponentiate to 1/2. // Test if each component's exponent // is an integer. (don't want fractional exponents) by . . . // modf(exp, NULL) =< std::numeric_limits::epsilon Unit = units[0].exponentiate(1.0 / 2.0); std::set< CUnitComponent >::const_iterator it = Unit.getComponents().begin(); std::set< CUnitComponent >::const_iterator end = Unit.getComponents().end(); for (; it != end; it++) { if (!(remainder((*it).getExponent(), 1.0) <= 100.0 * std::numeric_limits< C_FLOAT64 >::epsilon())) { Unit = CValidatedUnit(CBaseUnit::undefined, true); break; } } break; } default: Unit.setConflict(true); break; } return Unit; }