/* * This file is part of rasdaman community. * * Rasdaman community is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rasdaman community 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . */ /************************************************************* * * * PURPOSE: * * * COMMENTS: * ************************************************************/ static const char rcsid[] = "@(#)qlparser, QtBinaryOperation: $Id: qtbinaryoperation.cc,v 1.25 2002/04/12 09:51:53 coman Exp $"; #include "qlparser/qtbinaryoperation.hh" #include "qlparser/qtconst.hh" #include #ifndef CPPSTDLIB #include // STL #else #include using namespace std; #endif // constructors QtBinaryOperation::QtBinaryOperation() : QtOperation(), input1(NULL), input2(NULL) { } QtBinaryOperation::QtBinaryOperation( QtNode* node ) : QtOperation( node ), input1(NULL), input2(NULL) { } QtBinaryOperation::QtBinaryOperation( QtOperation* initInput1, QtOperation* initInput2 ) : QtOperation(), input1( initInput1 ), input2( initInput2 ) { if ( input1 ) input1->setParent( this ); if ( input2 ) input2->setParent( this ); } // destructor QtBinaryOperation::~QtBinaryOperation() { if ( input1 ) { delete input1; input1=NULL; } if ( input2 ) { delete input2; input2=NULL; } } // pre-evaluate the operation if the nodes contain constant data void QtBinaryOperation::simplify() { RMDBCLASS( "QtBinaryOperation", "simplify()", "qlparser", __FILE__, __LINE__ ) // In order to work bottom up, first inspect the descendants QtNode::simplify(); // Test, if both operands are available. if( input1 && input2 ) { // Test, if both operands are of const type. if( input1->getNodeType() == QT_CONST && input2->getNodeType() == QT_CONST ) { // evaluate the self node with no input list QtData* newConst = this->evaluate( NULL ); if( newConst ) { // create a new constant node and fill it with newConst QtConst* newNode = new QtConst( newConst ); // set its data stream type newNode->checkType( NULL ); // link it to the parent getParent()->setInput( this, newNode ); // delete the self node and its descendants delete this; } } } } // compare this to another node bool QtBinaryOperation::equalMeaning( QtNode* node ) { RMDBCLASS( "QtBinaryOperation", "equalMeaning( QtNode* )", "qlparser", __FILE__, __LINE__ ) bool result = false; // are the nodes of the same type? if ( getNodeType() == node->getNodeType() ) { QtBinaryOperation* binNode = (QtBinaryOperation *) node; // by force if ( input1 && input2 ) { if ( isCommutative() ) // operation is commutative result = ( input1->equalMeaning( binNode->getInput1() ) && input2->equalMeaning( binNode->getInput2() ) ) || ( input1->equalMeaning( binNode->getInput2() ) && input2->equalMeaning( binNode->getInput1() ) ); else // not commutative result = input1->equalMeaning( binNode->getInput1() ) && input2->equalMeaning( binNode->getInput2() ); }; }; return result; } // get childs QtNode::QtNodeList* QtBinaryOperation::getChilds( QtChildType flag ) { RMDBCLASS( "QtBinaryOperation", "getChilds( QtChildType )", "qlparser", __FILE__, __LINE__ ) QtNodeList* resultList = new QtNodeList(); if ( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) { QtNodeList* subList=NULL; if ( input1 ) { subList = input1->getChilds( flag ); resultList->splice(resultList->begin(), *subList); delete subList; subList=NULL; }; if ( input2 ) { subList = input2->getChilds( flag ); resultList->splice(resultList->begin(), *subList); delete subList; subList=NULL; }; }; if ( flag == QT_DIRECT_CHILDS || flag == QT_ALL_NODES ) { if ( input1 ) resultList->push_back( input1 ); if ( input2 ) resultList->push_back( input2 ); }; return resultList; } // get the two operands bool QtBinaryOperation::getOperands( QtDataList* inputList, QtData* &operand1, QtData* &operand2 ) { RMDBCLASS( "QtBinaryOperation", "getOperands( QtDataList*, QtData*, QtData* )", "qlparser", __FILE__, __LINE__ ) bool success = false; // get the operands try { if ( input1 ) operand1 = input1->evaluate( inputList ); if ( input2 ) operand2 = input2->evaluate( inputList ); } catch(...) { //clean up code if( operand1 ) { operand1->deleteRef(); operand1 = NULL; } if( operand2 ){ operand2->deleteRef(); operand2 = NULL; } throw; } // test if the operands are valid success = operand1 && operand2; if( !success ) { if( operand1 ) { operand1->deleteRef(); operand1 = NULL; } if( operand2 ) { operand2->deleteRef(); operand2 = NULL; } RMDBGONCE( 1, RMDebug::module_qlparser, "QtBinaryOperation", "Error: QtBinaryOperation::getOperands() - at least one operand is not provided." ) } return success; } // get the first or the second operand bool QtBinaryOperation::getOperand( QtDataList* inputList, QtData* &operand, int number ) { RMDBCLASS( "QtBinaryOperation", "getOperand( QtDataList*, QtData*, int )", "qlparser", __FILE__, __LINE__ ) bool success = false; // get the operand if ( number == 1 ) { if ( input1 ) { operand = input1->evaluate( inputList ); } else { if ( input2 ) operand = input2->evaluate( inputList ); } } else { if ( input2 ) operand = input2->evaluate( inputList ); } // test if the operands are valid if ( operand ) success = true; else { RMDBGONCE( 1, RMDebug::module_qlparser, "QtBinaryOperation", "Error: QtBinaryOperation::getOperand() - operand is not provided." ) } return success; } // get spelling string QtBinaryOperation::getSpelling() { char tempStr[20]; sprintf(tempStr, "%ud", (unsigned long)getNodeType()); string result = string(tempStr); result.append( "(" ); if ( input1 && input2 ) { string result1 = input1->getSpelling(); string result2 = input2->getSpelling(); if( result1.compare( result2 ) < 0 || !isCommutative() ) { result.append( result1 ); result.append( "," ); result.append( result2 ); } else { result.append( result2 ); result.append( "," ); result.append( result1 ); }; }; result.append( ")" ); RMDBGONCE(2, RMDebug::module_qlparser, "QtBinaryOperation", "Result:" << result.c_str()) return result; } // get area type QtNode::QtAreaType QtBinaryOperation::getAreaType() { QtNode::QtAreaType result = QT_AREA_MDD; if ( input1 && input2 ) if ( input1->getAreaType() == QtNode::QT_AREA_SCALAR && input2->getAreaType() == QtNode::QT_AREA_SCALAR ) result = QT_AREA_SCALAR; return result; } // idempotent /* void QtBinaryOperation::checkIdempotency() { } */ // optimize load void QtBinaryOperation::optimizeLoad( QtTrimList* trimList ) { RMDBCLASS( "QtBinaryOperation", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) QtNode::QtTrimList *list1=NULL; QtNode::QtTrimList *list2=NULL; if( input1 && input2 ) { list1 = trimList; // for list2 make a copy of list1 list2 = new QtNode::QtTrimList(); for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) { QtTrimElement* elem = new QtTrimElement; *elem = **iter; list2->push_back( elem ); } if ( input1 ) input1->optimizeLoad( list1 ); if ( input2 ) input2->optimizeLoad( list2 ); } else { // release( trimList->begin(), trimList->end() ); for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) { delete *iter; *iter=NULL; } delete trimList; trimList=NULL; } } void QtBinaryOperation::printTree( int tab, ostream& s, QtChildType mode ) { if( mode != QT_DIRECT_CHILDS ) { if( input1 ) { s << SPACE_STR(tab).c_str() << "input1: " << endl; input1->printTree( tab+2, s, mode ); } else s << SPACE_STR(tab).c_str() << "no input1" << endl; if( input2 ) { s << SPACE_STR(tab).c_str() << "input2: " << endl; input2->printTree( tab+2, s, mode ); } else s << SPACE_STR(tab).c_str() << "no input2" << endl; } } bool QtBinaryOperation::isCommutative() const { return true; // by default, a binary operation is commutative }