/////////////////////////////////////////////////////////////////////// // Math Type Library // $Id: derive.tcc,v 1.7 2002/05/03 11:51:17 cparpart Exp $ // (This file contains the derivation specific template member methods) // // 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. /////////////////////////////////////////////////////////////////////// namespace math { template TNode *TDeriver::derive(TNode *AExpression) { TDeriver derive; AExpression->accept(derive); return derive.FResult; } template TDeriver::TDeriver() : FResult(0) { } template void TDeriver::visit(TNumberNode *ANode) { // [const]' = 0 FResult = new TNumberNode(T(0)); } template void TDeriver::visit(TSymbolNode *ANode) { // [const]' = 0 FResult = new TNumberNode(T(0)); } template void TDeriver::visit(TParamNode *ANode) { // [x]' = 1 <:= [x^1]' = 1x^0 // :=> [x]' = 1 FResult = new TNumberNode(T(1)); } template void TDeriver::visit(TPlusNode *ANode) { // [f + g]' = f' + g' FResult = new TPlusNode( derive(ANode->left()), derive(ANode->right()) ); } template void TDeriver::visit(TNegNode *ANode) { // [-f]' = -(f') FResult = new TNegNode( derive(ANode->node()) ); } template void TDeriver::visit(TMulNode *ANode) { // [f * g]' = f'g + g'f FResult = new TPlusNode( new TMulNode( derive(ANode->left()), ANode->right()->clone() ), new TMulNode( derive(ANode->right()), ANode->left()->clone() ) ); } template void TDeriver::visit(TDivNode *ANode) { // [f(x)/g(x)]' = (f'g - g'f)/(g^2), g <> 0 FResult = new TDivNode( new TPlusNode( new TMulNode( derive(ANode->left()), ANode->right()->clone() ), new TNegNode( new TMulNode( derive(ANode->right()), ANode->left()->clone() ) ) ), new TPowNode( ANode->right()->clone(), new TNumberNode(2) ) ); } template void TDeriver::visit(TPowNode *ANode) { // [f ^ g]' = f^g * (g'ln(f) + (f'g)/f) FResult = new TMulNode( ANode->clone(), new TPlusNode( new TMulNode( derive(ANode->right()), new TLnNode(ANode->left()->clone()) ), new TDivNode( new TMulNode( derive(ANode->left()), ANode->right()->clone() ), ANode->left()->clone() ) ) ); } template void TDeriver::visit(TSqrtNode *ANode) { // [sqrt(f)]' = sqrt'(f) * f' } template void TDeriver::visit(TSinNode *ANode) { // [sin(f(x))]' = sin'(f(x))*f'(x) // = cos(f(x))*f'(x) FResult = new TMulNode( new TCosNode( ANode->node()->clone() ), derive(ANode->node()) ); } template void TDeriver::visit(TCosNode *ANode) { // [cos(f)]' = -(sin(f) * f') FResult = new TNegNode( new TMulNode( new TSinNode( ANode->node()->clone() ), derive(ANode->node()) ) ); } template void TDeriver::visit(TTanNode *ANode) { // [tan(f)]' = (1 + tan(f)^2) * f' FResult = new TMulNode( new TPlusNode( new TNumberNode(T(1)), new TPowNode( ANode->clone(), new TNumberNode(T(2)) ) ), derive(ANode->node()) ); } template void TDeriver::visit(TLnNode *ANode) { // [ln(f)]' = f' / f FResult = new TDivNode( derive(ANode->node()), ANode->node()->clone() ); } template void TDeriver::visit(TFuncNode *ANode) { // TODO : Implement a good TFuncNode<> derivation here. FResult = ANode->clone(); } template void TDeriver::visit(TIfNode *ANode) { FResult = new TIfNode( ANode->condition()->clone(), derive(ANode->trueExpr()), derive(ANode->falseExpr()) ); } template void TDeriver::visit(TEquNode *ANode) { FResult = new TEquNode( ANode->left()->clone(), ANode->right()->clone() ); } template void TDeriver::visit(TUnEquNode *ANode) { FResult = new TUnEquNode( ANode->left()->clone(), ANode->right()->clone() ); } template void TDeriver::visit(TGreaterNode *ANode) { FResult = new TGreaterNode( ANode->left()->clone(), ANode->right()->clone() ); } template void TDeriver::visit(TLessNode *ANode) { FResult = new TLessNode( ANode->left()->clone(), ANode->right()->clone() ); } template void TDeriver::visit(TGreaterEquNode *ANode) { FResult = new TGreaterEquNode( ANode->left()->clone(), ANode->right()->clone() ); } template void TDeriver::visit(TLessEquNode *ANode) { FResult = new TLessEquNode( ANode->left()->clone(), ANode->right()->clone() ); } } // namespace math