/////////////////////////////////////////////////////////////////////// // Math Type Library // $Id: calculator.tcc,v 1.1 2002/04/20 06:39:18 cparpart Exp $ // (implements the function calculator) // // Copyright (c) 2002 by Christian Parpart // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with this library; see the file COPYING.LIB. If not, write to // the Free Software Foundation, Inc., 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. /////////////////////////////////////////////////////////////////////// #ifndef libmath_calculator_h #error You may not include math++/calculator.tcc directly; include math++/calculator.h instead. #endif #include namespace math { template T TCalculator::calculate(const TFunction& AFunction, const T& AParam, const TLibrary& ALibrary, unsigned ALimit) { TCalculator c(AFunction, AParam, ALibrary, ALimit); return c.FResult; } template TCalculator::TCalculator(const TFunction& AFunction, const T& AParam, const TLibrary& ALibrary, unsigned ALimit) : FParam(AParam), FLibrary(ALibrary), FLimit(ALimit) { AFunction.expression()->accept(*this); } template T TCalculator::calculate(const TNode *AExpression) { const_cast *>(AExpression)->accept(*this); return FResult; } template void TCalculator::visit(TNumberNode *ANode) { FResult = ANode->number(); } template void TCalculator::visit(TSymbolNode *ANode) { FResult = FLibrary.value(ANode->symbol()); } template void TCalculator::visit(TParamNode *ANode) { FResult = FParam; } template void TCalculator::visit(TPlusNode *ANode) { FResult = calculate(ANode->left()) + calculate(ANode->right()); } template void TCalculator::visit(TNegNode *ANode) { FResult = - calculate(ANode->node()); } template void TCalculator::visit(TMulNode *ANode) { FResult = calculate(ANode->left()) * calculate(ANode->right()); } template void TCalculator::visit(TDivNode *ANode) { FResult = calculate(ANode->left()) / calculate(ANode->right()); } template void TCalculator::visit(TPowNode *ANode) { FResult = pow(calculate(ANode->left()), calculate(ANode->right())); } template void TCalculator::visit(TSqrtNode *ANode) { FResult = sqrt(calculate(ANode->node())); } template void TCalculator::visit(TSinNode *ANode) { FResult = sin(calculate(ANode->node())); } template void TCalculator::visit(TCosNode *ANode) { FResult = cos(calculate(ANode->node())); } template void TCalculator::visit(TTanNode *ANode) { FResult = tan(calculate(ANode->node())); } template void TCalculator::visit(TLnNode *ANode) { FResult = log(calculate(ANode->node())); } template void TCalculator::visit(TFuncNode *ANode) { const std::string name(ANode->name()); if (FRecursions.find(name) == FRecursions.end()) FRecursions[name] = 0; if (++FRecursions[name] > FLimit) throw ECalcError("Function exceeds recursion counter: " + name + "."); T save(FParam); FParam = calculate(ANode->node()); FResult = calculate(FLibrary.function(name).expression()); FParam = save; } template void TCalculator::visit(TIfNode *ANode) { FResult = calculate(ANode->condition()) ? calculate(ANode->trueExpr()) : calculate(ANode->falseExpr()); } template void TCalculator::visit(TEquNode *ANode) { FResult = calculate(ANode->left()) == calculate(ANode->right()); } template void TCalculator::visit(TUnEquNode *ANode) { FResult = calculate(ANode->left()) != calculate(ANode->right()); } template void TCalculator::visit(TGreaterNode *ANode) { FResult = calculate(ANode->left()) > calculate(ANode->right()); } template void TCalculator::visit(TLessNode *ANode) { FResult = calculate(ANode->left()) < calculate(ANode->right()); } template void TCalculator::visit(TGreaterEquNode *ANode) { FResult = calculate(ANode->left()) >= calculate(ANode->right()); } template void TCalculator::visit(TLessEquNode *ANode) { FResult = calculate(ANode->left()) <= calculate(ANode->right()); } } // namespace math