/* * 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 . */ static const char rcsid[] = "@(#)catalogif,ops.cc: $Header: /home/rasdev/CVS-repository/rasdaman/catalogmgr/ops.cc,v 1.67 2003/12/20 23:41:27 rasdev Exp $"; #include #include #include // memcpy() #include // malloc() #include "ops.hh" #include "relcatalogif/alltypes.hh" #include "typefactory.hh" #include "raslib/point.hh" //----------------------------------------------- // getUnaryOp //----------------------------------------------- UnaryOp* Ops::getUnaryOp(Ops::OpType op, const BaseType* resType, const BaseType* opType, unsigned int resOff, unsigned int opOff) { #ifndef NO_OPT_OPS ///////////////////////////////////////////// if(resType->getType() == opType->getType() && resType->getSize() == 1 && resType->getType() != STRUCT) { switch(op) { case Ops::OP_IDENTITY: return new OpIDENTITYChar(resType, opType, resOff, opOff ); } } if(resType->getType() == opType->getType() && resType->getSize() == 2 && resType->getType() != STRUCT) { switch(op) { case Ops::OP_IDENTITY: return new OpIDENTITYShort(resType, opType, resOff, opOff ); } } if(resType->getType() == opType->getType() && resType->getSize() == 4 && resType->getType() != STRUCT ) { switch(op) { case Ops::OP_IDENTITY: return new OpIDENTITYLong(resType, opType, resOff, opOff ); } } ///////////////////////////////////////////// #endif // cast operations if(op > Ops::OP_CAST_BEGIN && op < Ops::OP_CAST_END) { if(opType->getType() < STRUCT) return new OpCAST(resType, opType, resOff, opOff ); else if(opType->getType() == STRUCT) return new OpUnaryStruct(resType, opType, op, resOff, opOff); else return 0; } // all Char if( resType->getType() == BOOLTYPE && opType->getType() == BOOLTYPE ) { switch(op) { case Ops::OP_NOT: return new OpNOTBool(resType, opType, resOff, opOff ); } } if((resType->getType() >= ULONG && resType->getType() <= BOOLTYPE) && (opType->getType() >= ULONG && opType->getType() <= OCTET)) { switch(op) { case Ops::OP_NOT: return new OpNOTCULong(resType, opType, resOff, opOff ); case Ops::OP_IDENTITY: return new OpIDENTITYCULong(resType, opType, resOff, opOff ); default: return 0; } } // result is LONG, SHORT or OCTET and the only operand between ULONG and OCTET if((resType->getType() == LONG || resType->getType() == SHORT || resType->getType() == OCTET) && (opType->getType() >= ULONG && opType->getType() <= OCTET) ) { switch(op) { case Ops::OP_NOT: return new OpNOTCLong(resType, opType, resOff, opOff ); case Ops::OP_IDENTITY: return new OpIDENTITYCLong(resType, opType, resOff, opOff ); default: return 0; } } // result is COMPELEXTYPE1 or COMPLEXTYPE2 if(resType->getType() == COMPLEXTYPE1 && opType->getType() == COMPLEXTYPE1 || // remember && has precedence over || resType->getType() == COMPLEXTYPE2 && opType->getType() == COMPLEXTYPE2 ) return new OpIDENTITYComplex(resType, opType, resOff, opOff ); // result is FLOAT or DOUBLE and the only operand between ULONG and FLOAT if(resType->getType() == FLOAT || resType->getType() == DOUBLE && opType->getType() >= ULONG && opType->getType() <= FLOAT) { switch(op) { case Ops::OP_IDENTITY: return new OpIDENTITYCDouble(resType, opType, resOff, opOff ); case Ops::OP_SQRT: return new OpSQRTCDouble(resType, opType, resOff, opOff); case Ops::OP_ABS: return new OpABSCDouble(resType, opType, resOff, opOff); case Ops::OP_EXP: return new OpEXPCDouble(resType, opType, resOff, opOff); case Ops::OP_LOG: return new OpLOGCDouble(resType, opType, resOff, opOff); case Ops::OP_LN: return new OpLNCDouble(resType, opType, resOff, opOff); case Ops::OP_SIN: return new OpSINCDouble(resType, opType, resOff, opOff); case Ops::OP_COS: return new OpCOSCDouble(resType, opType, resOff, opOff); case Ops::OP_TAN: return new OpTANCDouble(resType, opType, resOff, opOff); case Ops::OP_SINH: return new OpSINHCDouble(resType, opType, resOff, opOff); case Ops::OP_COSH: return new OpCOSHCDouble(resType, opType, resOff, opOff); case Ops::OP_TANH: return new OpTANHCDouble(resType, opType, resOff, opOff); case Ops::OP_ARCSIN: return new OpARCSINCDouble(resType, opType, resOff, opOff); case Ops::OP_ARCCOS: return new OpARCCOSCDouble(resType, opType, resOff, opOff); case Ops::OP_ARCTAN: return new OpARCTANCDouble(resType, opType, resOff, opOff); case Ops::OP_REALPART: return new OpRealPart(resType, opType, resOff, opOff); case Ops::OP_IMAGINARPART: return new OpImaginarPart(resType, opType, resOff, opOff); default: return 0; } } // retriving real or imaginar parts of a complex argument if(resType->getType() == DOUBLE && (opType->getType() == COMPLEXTYPE1 || opType->getType() == COMPLEXTYPE2)) { switch(op) { case Ops::OP_REALPART: return new OpRealPart(resType, opType, resOff, opOff); case Ops::OP_IMAGINARPART: return new OpImaginarPart(resType, opType, resOff, opOff); default: return 0; } } if(resType->getType() == COMPLEXTYPE1 && opType->getType() == COMPLEXTYPE1 || // remember && has precedence over || resType->getType() == COMPLEXTYPE2 && opType->getType() == COMPLEXTYPE2 ) return new OpIDENTITYComplex(resType, opType, resOff, opOff ); if( resType->getType() == STRUCT && resType->compatibleWith(opType) ) { #ifndef NO_OPT_IDENTITY_STRUCT ///////////////////////////// switch(op) { case Ops::OP_IDENTITY: return new OpIDENTITYStruct(resType, opType, resOff, opOff ); default: ///////////////////////////// #endif return new OpUnaryStruct( resType, opType, op, resOff, opOff ); #ifndef NO_OPT_IDENTITY_STRUCT ///////////////////////////// } ///////////////////////////// #endif } return 0; } BinaryOp* Ops::getBinaryOp( Ops::OpType op, const BaseType* resType, const BaseType* op1Type, const BaseType* op2Type, unsigned int resOff, unsigned int op1Off, unsigned int op2Off ) { // if this flag is set, optimized operation execution for Char // is turned off. #ifndef NO_OPT_OPS // all Char if( resType->getType() == CHAR && op1Type->getType() == CHAR && op2Type->getType() == CHAR ) { switch(op) { case Ops::OP_PLUS: return new OpPLUSChar(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_MINUS: return new OpMINUSChar(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_DIV: return new OpDIVChar(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_MULT: return new OpMULTChar(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } #endif if ((resType->getType() == op1Type->getType()) && (resType->getType() == op2Type->getType()) && (op == Ops::OP_OVERLAY)) { return new OpOVERLAY(resType, op1Type, op2Type, resType->getSize(), OpOVERLAY::nullPattern, resOff, op1Off, op2Off); } // all Bool if( resType->getType() == BOOLTYPE && op1Type->getType() == BOOLTYPE && op2Type->getType() == BOOLTYPE ) { switch(op) { case Ops::OP_AND: return new OpANDBool(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_OR: return new OpORBool(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_XOR: return new OpXORBool(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } // result is unsigned integer if( (resType->getType() >= ULONG && resType->getType() <= BOOLTYPE) && (op1Type->getType() >= ULONG && op1Type->getType() <= OCTET) && (op2Type->getType() >= ULONG && op2Type->getType() <= OCTET) ) { switch(op) { case Ops::OP_PLUS: return new OpPLUSCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_MINUS: return new OpMINUSCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_DIV: return new OpDIVCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_MULT: return new OpMULTCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_AND: return new OpANDCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_OR: return new OpORCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_XOR: return new OpXORCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } // result is signed integer if( (resType->getType() == LONG || resType->getType() == SHORT || resType->getType() == OCTET) && (op1Type->getType() >= ULONG && op1Type->getType() <= OCTET) && (op2Type->getType() >= ULONG && op2Type->getType() <= OCTET) ) { switch(op) { case Ops::OP_PLUS: return new OpPLUSCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_MINUS: return new OpMINUSCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_DIV: return new OpDIVCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_MULT: return new OpMULTCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_AND: return new OpANDCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_OR: return new OpANDCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_XOR: return new OpANDCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } // result is float or double if( (resType->getType() == FLOAT || resType->getType() == DOUBLE) && (op1Type->getType() >= ULONG && op1Type->getType() <= FLOAT) && (op2Type->getType() >= ULONG && op2Type->getType() <= FLOAT) ) { switch(op) { case Ops::OP_PLUS: return new OpPLUSCDouble(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_MINUS: return new OpMINUSCDouble(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_DIV: return new OpDIVCDouble(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_MULT: return new OpMULTCDouble(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } //************************************************************************************* // *** COMPLEXTYPE *** //************************************************************************************ // result is complex if(resType->getType() == COMPLEXTYPE1 || resType->getType() == COMPLEXTYPE2) { switch(op) { case Ops::OP_PLUS: if(op1Type->getType() < COMPLEXTYPE1) return new OpPLUSComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off, OpPLUSComplex::FIRST); else if(op2Type->getType() < COMPLEXTYPE1) return new OpPLUSComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off, OpPLUSComplex::SECOND); else return new OpPLUSComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_MINUS: if(op1Type->getType() < COMPLEXTYPE1) return new OpMINUSComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off, OpMINUSComplex::FIRST); else if(op2Type->getType() < COMPLEXTYPE1) return new OpMINUSComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off, OpMINUSComplex::SECOND); else return new OpMINUSComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_DIV: if(op1Type->getType() < COMPLEXTYPE1) return new OpDIVComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off, OpDIVComplex::FIRST); else if(op2Type->getType() < COMPLEXTYPE1) return new OpDIVComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off, OpDIVComplex::SECOND); else return new OpDIVComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_MULT: if(op1Type->getType() < COMPLEXTYPE1) return new OpMULTComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off, OpMULTComplex::FIRST); else if(op2Type->getType() < COMPLEXTYPE1) return new OpMULTComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off, OpMULTComplex::SECOND); else return new OpMULTComplex(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } //************************************************************************************* #ifndef NO_OPT_OPS // result is bool, operands are Chars if( (resType->getType() == BOOLTYPE) && (op1Type->getType() == CHAR) && (op2Type->getType() == CHAR) ) { switch(op) { case Ops::OP_EQUAL: return new OpEQUALChar(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_LESS: return new OpLESSChar(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_LESSEQUAL: return new OpLESSEQUALChar(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_NOTEQUAL: return new OpNOTEQUALChar(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_GREATER: return new OpGREATERChar(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_GREATEREQUAL: return new OpGREATEREQUALChar(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } #endif // result is bool if( (resType->getType() == BOOLTYPE) && (op1Type->getType() >= ULONG && op1Type->getType() <= BOOLTYPE) && (op2Type->getType() >= ULONG && op2Type->getType() <= BOOLTYPE) ) { switch(op) { case Ops::OP_EQUAL: return new OpEQUALCCharCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_LESS: return new OpLESSCCharCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_LESSEQUAL: return new OpLESSEQUALCCharCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_NOTEQUAL: return new OpNOTEQUALCCharCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_GREATER: return new OpGREATERCCharCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_GREATEREQUAL: return new OpGREATEREQUALCCharCULong(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } if( (resType->getType() == BOOLTYPE) && (op1Type->getType() >= ULONG && op1Type->getType() <= OCTET ) && (op2Type->getType() >= ULONG && op2Type->getType() <= OCTET ) ) { switch(op) { case Ops::OP_EQUAL: return new OpEQUALCCharCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_LESS: return new OpLESSCCharCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_LESSEQUAL: return new OpLESSEQUALCCharCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_NOTEQUAL: return new OpNOTEQUALCCharCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_GREATER: return new OpGREATERCCharCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_GREATEREQUAL: return new OpGREATEREQUALCCharCLong(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_BIT: return new OpBIT(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } if( (resType->getType() == BOOLTYPE) && (op1Type->getType() >= ULONG && op1Type->getType() <= FLOAT ) && (op2Type->getType() >= ULONG && op2Type->getType() <= FLOAT ) ) { switch(op) { case Ops::OP_EQUAL: return new OpEQUALCCharCDouble(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_LESS: return new OpLESSCCharCDouble(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_LESSEQUAL: return new OpLESSEQUALCCharCDouble(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_NOTEQUAL: return new OpNOTEQUALCCharCDouble(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_GREATER: return new OpGREATERCCharCDouble(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_GREATEREQUAL: return new OpGREATEREQUALCCharCDouble(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } // comparison of structs if( (resType->getType() == BOOLTYPE) && (op1Type->getType() >= STRUCT && op1Type->getType() <= CLASSTYPE ) && (op1Type->compatibleWith(op2Type)) ) { switch(op) { case Ops::OP_EQUAL: return new OpEQUALStruct(resType, op1Type, op2Type, resOff, op1Off, op2Off); case Ops::OP_NOTEQUAL: return new OpNOTEQUALStruct(resType, op1Type, op2Type, resOff, op1Off, op2Off); } } // result is Struct, two operands are structs if( resType->getType() == STRUCT && op1Type->getType() == STRUCT && op2Type->getType() == STRUCT ) { if(op >= OP_MINUS && op <= OP_XOR && isApplicableOnStruct(op, op1Type) && resType->compatibleWith(op1Type) && resType->compatibleWith(op2Type)) { return new OpBinaryStruct( resType, op, resOff, op1Off, op2Off); } else return 0; } // result is Struct, first operand is struct if( resType->getType() == STRUCT && op1Type->getType() == STRUCT ) { if(op >= OP_MINUS && op <= OP_XOR && isApplicableOnStructConst(op, op1Type, op2Type)) { return new OpBinaryStructConst( resType, op1Type, op2Type, op, resOff, op1Off, op2Off ); } else return 0; } // result is Struct, second operand is struct if( resType->getType() == STRUCT && op2Type->getType() == STRUCT ) { if(op >= OP_MINUS && op <= OP_XOR && isApplicableOnStructConst(op, op2Type, op1Type)) return new OpBinaryConstStruct( resType, op1Type, op2Type, op, resOff, op1Off, op2Off ); else return 0; } return 0; } //----------------------------------------------------------------- // getCondenseOp //----------------------------------------------------------------- CondenseOp* Ops::getCondenseOp(Ops::OpType op, const BaseType* resType, const BaseType* opType, unsigned int resOff, unsigned int opOff) { if(resType->getType() == BOOLTYPE) { switch(op) { case Ops::OP_SOME: return new OpSOMECChar(resType, opType, resOff, opOff); case Ops::OP_ALL: return new OpALLCChar(resType, opType, resOff, opOff); } } else if( resType->getType() == ULONG && opType->getType() == BOOLTYPE ) { switch(op) { case Ops::OP_COUNT: return new OpCOUNTCChar(resType, opType, resOff, opOff); case Ops::OP_SUM: return new OpSUMCULong(resType, opType, resOff, opOff); } } else if((resType->getType() >= ULONG && resType->getType() <= BOOLTYPE) && (opType->getType() >= ULONG && opType->getType() <= BOOLTYPE)) { switch(op) { case Ops::OP_MAX: return new OpMAXCULong(resType, opType, resOff, opOff); case Ops::OP_MIN: return new OpMINCULong(resType, opType, resOff, opOff); case Ops::OP_SUM: return new OpSUMCULong(resType, opType, resOff, opOff); } } else if((resType->getType() == LONG || resType->getType() == SHORT || resType->getType() == OCTET) && (opType->getType() >= ULONG && opType->getType() <= OCTET) ) { switch(op) { case Ops::OP_MAX: return new OpMAXCLong(resType, opType, resOff, opOff); case Ops::OP_MIN: return new OpMINCLong(resType, opType, resOff, opOff); case Ops::OP_SUM: return new OpSUMCLong(resType, opType, resOff, opOff); } } else if((resType->getType() == FLOAT || resType->getType() == DOUBLE ) && (opType->getType() >= ULONG && opType->getType() <= FLOAT) ) { switch(op) { case Ops::OP_MAX: return new OpMAXCDouble(resType, opType, resOff, opOff); case Ops::OP_MIN: return new OpMINCDouble(resType, opType, resOff, opOff); case Ops::OP_SUM: return new OpSUMCDouble(resType, opType, resOff, opOff); } } else if( resType->getType() == STRUCT) // res and op are structs with same structure. return new OpCondenseStruct( resType, opType, op, resOff, opOff ); return 0; } CondenseOp* Ops::getCondenseOp( Ops::OpType op, const BaseType* resType, char* newAccu, const BaseType* opType, unsigned int resOff, unsigned int opOff ) { if(resType->getType() == BOOLTYPE) { switch(op) { case Ops::OP_SOME: return new OpSOMECChar(resType, newAccu, opType, resOff, opOff); case Ops::OP_ALL: return new OpALLCChar(resType, newAccu, opType, resOff, opOff); } } else if( resType->getType() == ULONG && opType->getType() == BOOLTYPE ) { switch(op) { case Ops::OP_COUNT: return new OpCOUNTCChar(resType, newAccu, opType, resOff, opOff); } } else if( (resType->getType() >= ULONG && resType->getType() <= BOOLTYPE) && (opType->getType() >= ULONG && opType->getType() <= BOOLTYPE) ) { switch(op) { case Ops::OP_MAX: return new OpMAXCULong(resType, newAccu, opType, resOff, opOff); case Ops::OP_MIN: return new OpMINCULong(resType, newAccu, opType, resOff, opOff); case Ops::OP_SUM: return new OpSUMCULong(resType, newAccu, opType, resOff, opOff); } } else if( (resType->getType() == LONG || resType->getType() == SHORT || resType->getType() == OCTET) && (opType->getType() >= ULONG && opType->getType() <= OCTET) ) { switch(op) { case Ops::OP_MAX: return new OpMAXCLong(resType, newAccu, opType, resOff, opOff); case Ops::OP_MIN: return new OpMINCLong(resType, newAccu, opType, resOff, opOff); case Ops::OP_SUM: return new OpSUMCLong(resType, newAccu, opType, resOff, opOff); } } else if( (resType->getType() == FLOAT || resType->getType() == DOUBLE ) && (opType->getType() >= ULONG && opType->getType() <= FLOAT) ) { switch(op) { case Ops::OP_MAX: return new OpMAXCDouble(resType, newAccu, opType, resOff, opOff); case Ops::OP_MIN: return new OpMINCDouble(resType, newAccu, opType, resOff, opOff); case Ops::OP_SUM: return new OpSUMCDouble(resType, newAccu, opType, resOff, opOff); } } else if( resType->getType() == STRUCT ) { // res and op are structs with same structure. return new OpCondenseStruct( resType, newAccu, opType, op, resOff, opOff ); } return 0; } //----------------------------------------------- // isApplicable //----------------------------------------------- int Ops::isApplicable(Ops::OpType op, const BaseType* op1Type, const BaseType* op2Type) { UnaryOp* myUnaryOp; BinaryOp* myBinaryOp; CondenseOp* myCondenseOp; const BaseType* resType; // could be getResType( op, op1Type, op2Type ), but this // introduces circular dependency between the two functions. // So it is broken here. if( op == OP_SOME || op == OP_ALL || (op >= OP_EQUAL && op <= OP_GREATEREQUAL) ) { // result must be Bool resType = TypeFactory::mapType("Bool"); } else if(op == OP_COUNT) resType = TypeFactory::mapType("ULong"); else if(op > OP_UFUNC_BEGIN && op < OP_UFUNC_END ) resType = TypeFactory::mapType("Double"); else if(op > Ops::OP_CAST_BEGIN && op < Ops::OP_CAST_END && op1Type->getType() <= FLOAT) { const char *typeName[] = { "Bool", "Char", "Octet", "Short", "UShort", "Long", "ULong", "Float", "Double" }; resType = TypeFactory::mapType(typeName[op - OP_CAST_BEGIN - 1]); } else if(op == OP_BIT) resType = TypeFactory::mapType("Bool"); else if(op == OP_SUM && op1Type->getType() <= CHAR) resType = TypeFactory::mapType("ULong"); else if(op == OP_SUM && op1Type->getType() <= OCTET) resType = TypeFactory::mapType("Long"); else if(op == OP_SUM && op1Type->getType() <= FLOAT) resType = TypeFactory::mapType("Double"); else if(op == OP_SUM && op1Type->getType() == COMPLEXTYPE1) resType = TypeFactory::mapType("Complex1"); else if(op == OP_SUM && op1Type->getType() == COMPLEXTYPE2) resType = TypeFactory::mapType("Complex2"); // unary operations on complex: re, im else if(op == OP_REALPART || op == OP_IMAGINARPART) { if(op1Type->getType() == COMPLEXTYPE1) resType = TypeFactory::mapType("Float"); if(op1Type->getType() == COMPLEXTYPE2) resType = TypeFactory::mapType("Double"); } else if(op2Type == 0) resType = (BaseType*)op1Type; else if( op1Type->getType() >= STRUCT && op1Type->getType() <= CLASSTYPE ) // composite types must be compatible, so just take one of them as // result resType = (BaseType*)op1Type; else if( op2Type->getType() >= STRUCT && op2Type->getType() <= CLASSTYPE ) // composite types must be compatible, so just take one of them as // result resType = (BaseType*)op2Type; else if(op1Type->getType() == COMPLEXTYPE2 || op2Type->getType() == COMPLEXTYPE2) // if one of the opernds is complex type and the other any atomic type // the result should be complex resType = TypeFactory::mapType("Complex2"); else if(op1Type->getType() == COMPLEXTYPE1 || op2Type->getType() == COMPLEXTYPE1) // idem resType = TypeFactory::mapType("Complex1"); else if( op >= OP_IS && op <= OP_XOR ) // result must be long in this case resType = TypeFactory::mapType("Long"); else // Double is the strongest type anyway resType = TypeFactory::mapType("Double"); if(op == OP_OVERLAY) resType = (BaseType*)op1Type; // unary or condense operations if(op2Type == 0) { myUnaryOp = getUnaryOp(op, resType, (BaseType*)op1Type); if(myUnaryOp != 0) { delete myUnaryOp; return 1; // found an unary op } myCondenseOp = getCondenseOp(op, (BaseType*)resType, (BaseType*)op1Type); if(myCondenseOp != 0) { delete myCondenseOp; return 1; // found a condense op } else return 0; // found neither } else { myBinaryOp = getBinaryOp(op, resType, (BaseType*)op1Type, (BaseType*)op2Type); if(myBinaryOp != 0) { delete myBinaryOp; return 1; } else return 0; } } //----------------------------------------------- // getResultType //----------------------------------------------- const BaseType* Ops::getResultType(Ops::OpType op, const BaseType* op1, const BaseType* op2) { // operations between composite types defined only on compatible types if(op == OP_OVERLAY) { if ((op1->getType() == STRUCT) || (op2->getType() == STRUCT)) { if (op1->compatibleWith(op2)) { return op1; } else { return NULL; } } if (op1->getType() == op2->getType()) { return op1; } return NULL; } // operation BIT returns bool or struct {bool, ...} if(op == OP_BIT) { if(op1->getType() == STRUCT) { StructType* resStructType = new StructType; TypeFactory::addTempType(resStructType); StructType* opStructType = (StructType* )op1; for(int i = 0; i < opStructType->getNumElems(); ++i) { const BaseType* resType = getResultType(op, opStructType->getElemType(i), op2); if(!resType) return 0; resStructType->addElement(opStructType->getElemName(i), resType); } return (BaseType *) resStructType; } // integral types else if(op1->getType() <= OCTET) return TypeFactory::mapType("Bool"); else return 0; } // operation not even applicable, so no result type if(!isApplicable(op, op1, op2)) { return 0; } // the condense operation COUNT always returns an unsigned long if( op == Ops::OP_COUNT ) return TypeFactory::mapType("ULong"); // SQRT returns DOUBLE if( op > Ops::OP_UFUNC_BEGIN && op < Ops::OP_UFUNC_END ) return TypeFactory::mapType("Double"); if(op > Ops::OP_CAST_BEGIN && op < Ops::OP_CAST_END) { if(op1->getType() < STRUCT) { const char *typeName[] = { "Bool", "Char", "Octet", "Short", "UShort", "Long", "ULong", "Float", "Double" }; return TypeFactory::mapType(typeName[op - OP_CAST_BEGIN - 1]); } else if(op1->getType() == STRUCT) { StructType* resStructType = new StructType; TypeFactory::addTempType(resStructType); StructType* opStructType = (StructType* )op1; for(int i = 0; i < opStructType->getNumElems(); ++i) { const BaseType* resType = getResultType(op, opStructType->getElemType(i)); if(!resType) return 0; resStructType->addElement(opStructType->getElemName(i), resType); } return (BaseType *)resStructType; } else return 0; } // the condense operation ADD_CELLS returns maximal type // (i.e. long/ulong or double) if(!op2 && op == Ops::OP_SUM) { if(op1->getType() <= BOOLTYPE) return TypeFactory::mapType("ULong"); if(op1->getType() <= OCTET) return TypeFactory::mapType("Long"); else if(op1->getType() <= FLOAT) return TypeFactory::mapType("Double"); else if(op1->getType() == COMPLEXTYPE1) return TypeFactory::mapType("Complex1"); else if(op1->getType() == COMPLEXTYPE2) return TypeFactory::mapType("Complex2"); else if(op1->getType() == STRUCT) { StructType* resStructType = new StructType; TypeFactory::addTempType(resStructType); StructType* opStructType = (StructType* )op1; for(int i = 0; i < opStructType->getNumElems(); ++i) { const BaseType* resType = getResultType(op, opStructType->getElemType(i)); if(!resType) return 0; resStructType->addElement(opStructType->getElemName(i), resType); } return (BaseType *)resStructType; } else return 0; } // some :-) unary and condense operations return the same type if(op == OP_REALPART || op == OP_IMAGINARPART) { if(op1->getType() == COMPLEXTYPE1) return TypeFactory::mapType("Float"); else if(op1->getType() == COMPLEXTYPE2) return TypeFactory::mapType("Double"); } if( op2 == 0 ) return (BaseType*)op1; // operations between composite types defined only on compatible types if( op1->getType() >= STRUCT && op1->getType() <= CLASSTYPE ) { if( op == OP_EQUAL || op == OP_NOTEQUAL ) return TypeFactory::mapType("Bool"); else { if(op1->getType() == STRUCT && op2->getType() <= FLOAT) { StructType* resStructType = new StructType; TypeFactory::addTempType(resStructType); StructType* opStructType = (StructType* )op1; for(int i = 0; i < opStructType->getNumElems(); ++i) { const BaseType* resType = getResultType(op, opStructType->getElemType(i), op2); if(!resType) return 0; resStructType->addElement(opStructType->getElemName(i), resType); } return (BaseType *)resStructType; } else return (BaseType*)op1; } } if( op2->getType() >= STRUCT && op2->getType() <= CLASSTYPE ) { if(op1->getType() <= FLOAT && op2->getType() == STRUCT) { StructType* resStructType = new StructType; TypeFactory::addTempType(resStructType); StructType* opStructType = (StructType* )op2; for(int i = 0; i < opStructType->getNumElems(); ++i) { const BaseType* resType = getResultType(op, op1, opStructType->getElemType(i)); if(!resType) return 0; resStructType->addElement(opStructType->getElemName(i), resType); } return (BaseType *)resStructType; } else return (BaseType*)op2; } // comparison operators always return bool if(op >= OP_EQUAL && op <= OP_GREATEREQUAL) return TypeFactory::mapType("Bool"); // all the other binary functions return "strongest" type // if only one of operand is signed, result also has to be signed. if( isSignedType(op1) && !isSignedType(op2) ) { // swap it, action is in next if clause const BaseType* dummy; dummy = op2; op2 = op1; op1 = dummy; } if( !isSignedType(op1) && isSignedType(op2) ) { // got to get the thing with the highest precision and make sure // it is signed. if( op2->getType() == COMPLEXTYPE1 || op2->getType() == COMPLEXTYPE2 || op2->getType() == FLOAT || op2->getType() == DOUBLE || op2->getType() == LONG ) return (BaseType*)op2; if( op1->getType() == USHORT ) return TypeFactory::mapType("Short"); if( op2->getType() == SHORT ) return (BaseType*)op2; return TypeFactory::mapType("Octet"); } // return the stronger type if(op1->getType() == COMPLEXTYPE2 || op2->getType() == COMPLEXTYPE2) return TypeFactory::mapType("Complex2"); if(op1->getType() == COMPLEXTYPE1 || op2->getType() == COMPLEXTYPE1) return TypeFactory::mapType("Complex1"); if(op1->getType() == DOUBLE || op2->getType() == DOUBLE) return TypeFactory::mapType("Double"); if(op1->getType() == FLOAT || op2->getType() == FLOAT) return TypeFactory::mapType("Float"); if(op1->getType() <= op2->getType()) return (BaseType*)op1; else return (BaseType*)op2; } int Ops::isApplicableOnStruct( Ops::OpType op, const BaseType* opType ) { int i = 0; StructType* myStructType = (StructType*)opType; int numElems = myStructType->getNumElems(); for(i = 0; i < numElems; i++) { if( !isApplicable(op, myStructType->getElemType(i), myStructType->getElemType(i)) ) return 0; } return 1; } int Ops::isApplicableOnStructConst( Ops::OpType op, const BaseType* op1Type, const BaseType* op2Type ) { int i = 0; StructType* myStructType = (StructType*)op1Type; int numElems = myStructType->getNumElems(); for(i = 0; i < numElems; i++) { if( !isApplicable(op, myStructType->getElemType(i), op2Type) ) return 0; } return 1; } int Ops::isSignedType( const BaseType* type ) { return ( type->getType() >= LONG && type->getType() <= COMPLEXTYPE2 ); } int Ops::isCondenseOp( Ops::OpType op ) { return ( op >= OP_SOME && op <= OP_ALL ); } int Ops::isUnaryOp( Ops::OpType op ) { return ( op >= OP_NOT && op <= OP_IDENTITY ); } int Ops::isBinaryOp( Ops::OpType op ) { return ( op >= OP_MINUS && op <= OP_GREATEREQUAL ); } void Ops::execUnaryConstOp( Ops::OpType op, const BaseType* resType, const BaseType* opType, char* res, const char* op1, unsigned int resOff, unsigned int opOff ) { UnaryOp* myOp = Ops::getUnaryOp( op, resType, opType, resOff, opOff ); try { (*myOp)(res, op1); } catch(...) { delete myOp; // cleanup throw; } delete myOp; } void Ops::execBinaryConstOp( Ops::OpType op, const BaseType* resType, const BaseType* op1Type, const BaseType* op2Type, char* res, const char* op1, const char* op2, unsigned int resOff, unsigned int op1Off, unsigned int op2Off ) { BinaryOp* myOp = Ops::getBinaryOp( op, resType, op1Type, op2Type, resOff, op1Off, op2Off ); (*myOp)(res, op1, op2); delete myOp; } UnaryOp::UnaryOp( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : resType(newResType), opType(newOpType), resOff(newResOff), opOff(newOpOff) { } OpIDENTITYStruct::OpIDENTITYStruct( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { } void OpIDENTITYStruct::operator()( char* res, const char* op ) { memcpy( (void*)(res + resOff), (void*)(op + opOff), resType->getSize() ); } OpNOTCULong::OpNOTCULong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { } void OpNOTCULong::operator()( char* res, const char* op ) { r_ULong longOp; r_ULong longRes; longRes = *(opType->convertToCULong(op + opOff, &longOp)) ^ 0xFFFFFFFF; resType->makeFromCULong( res + resOff, &longRes); } OpIDENTITYCULong::OpIDENTITYCULong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { } void OpIDENTITYCULong::operator()( char* res, const char* op ) { r_ULong longOp; // !!!! HP specific, assumes 4 Byte long and MSB..LSB // byte order resType->makeFromCULong( res + resOff, opType->convertToCULong(op + opOff, &longOp) ); } OpNOTCLong::OpNOTCLong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { } void OpNOTCLong::operator()( char* res, const char* op ) { r_Long longOp; r_Long longRes; longRes = *(opType->convertToCLong(op + opOff, &longOp)) ^ 0xFFFFFFFF; resType->makeFromCLong( res + resOff, &longRes); } OpIDENTITYCLong::OpIDENTITYCLong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { } void OpIDENTITYCLong::operator()( char* res, const char* op ) { r_Long longOp; resType->makeFromCLong( res + resOff, opType->convertToCLong(op + opOff, &longOp) ); } OpIDENTITYCDouble::OpIDENTITYCDouble( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { } void OpIDENTITYCDouble::operator()( char* res, const char* op ) { double doubleOp; // !!!! HP specific, assumes 4 Byte double and MSB..LSB // byte order resType->makeFromCDouble( res + resOff, opType->convertToCDouble(op + opOff, &doubleOp) ); } OpNOTBool::OpNOTBool( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { } void OpNOTBool::operator()( char* res, const char* op ) { // special case for bools, because bitwise not is not // equivalent to logical not *(res + resOff) = !(*(op + opOff)); } BinaryOp::BinaryOp( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : resType(newResType), op1Type(newOp1Type), op2Type(newOp2Type), resOff(newResOff), op1Off(newOp1Off), op2Off(newOp2Off) { } void BinaryOp::getCondenseInit(char* init) { init = 0; // perhaps should also raise exception as operation cannot be used // as condenser. } OpPLUSCULong::OpPLUSCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpPLUSCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1 = 0; r_ULong longOp2 = 0; r_ULong longRes = 0; longRes = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) + *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); resType->makeFromCULong( res + resOff, &longRes); } void OpPLUSCULong::getCondenseInit(char* init) { r_ULong dummy = 0; resType->makeFromCULong(init, &dummy); } OpPLUSULong::OpPLUSULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpPLUSULong::operator()( char* res, const char* op1, const char* op2 ) { cout << "Hier krachts?" << endl; *(r_ULong*)(res + resOff) = *(r_ULong*)(op1 + op1Off) + *(r_ULong*)(op2 + op2Off); } void OpPLUSULong::getCondenseInit(char* init) { r_ULong dummy = 0; resType->makeFromCULong(init, &dummy); } OpMINUSCULong::OpMINUSCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpMINUSCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1 = 0; r_ULong longOp2 = 0; r_ULong longRes = 0; longRes = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) - *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); resType->makeFromCULong( res + resOff, &longRes); } OpDIVCULong::OpDIVCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpDIVCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1 = 0; r_ULong longOp2 = 0; r_ULong longRes = 0; op2Type->convertToCULong(op2 + op2Off, &longOp2); if(longOp2 == 0) // catch division by zero, perhaps should throw exception longRes = 0; else { longRes = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) / longOp2; } resType->makeFromCULong( res + resOff, &longRes); } OpMULTCULong::OpMULTCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpMULTCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1 = 0; r_ULong longOp2 = 0; r_ULong longRes = 0; longRes = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) * *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); resType->makeFromCULong( res + resOff, &longRes); } void OpMULTCULong::getCondenseInit(char* init) { r_ULong dummy = 1; resType->makeFromCULong(init, &dummy); } OpANDCULong::OpANDCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpANDCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1 = 0; r_ULong longOp2 = 0; r_ULong longRes = 0; longRes = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) & *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); resType->makeFromCULong( res + resOff, &longRes); } void OpANDCULong::getCondenseInit(char* init) { char dummy[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; memcpy( init, dummy, resType->getSize() ); } OpANDBool::OpANDBool( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpANDBool::operator()( char* res, const char* op1, const char* op2 ) { *(res + resOff) = (*(op1 + op1Off) && *(op2 + op2Off)); } void OpANDBool::getCondenseInit(char* init) { *init = 1; } OpORCULong::OpORCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpORCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1 = 0; r_ULong longOp2 = 0; r_ULong longRes = 0; longRes = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) | *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); resType->makeFromCULong( res + resOff, &longRes); } void OpORCULong::getCondenseInit(char* init) { char dummy[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; memcpy( init, dummy, resType->getSize() ); } OpORBool::OpORBool( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpORBool::operator()( char* res, const char* op1, const char* op2 ) { *(res + resOff) = (*(op1 + op1Off) || *(op2 + op2Off)); } void OpORBool::getCondenseInit(char* init) { *init = 0; } OpXORCULong::OpXORCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpXORCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1 = 0; r_ULong longOp2 = 0; r_ULong longRes = 0; longRes = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) ^ *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); resType->makeFromCULong( res + resOff, &longRes); } OpXORBool::OpXORBool( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpXORBool::operator()( char* res, const char* op1, const char* op2 ) { *(res + resOff) = !(*(op1 + op1Off) == *(op2 + op2Off)); } OpPLUSCLong::OpPLUSCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpPLUSCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1 = 0; r_Long longOp2 = 0; r_Long longRes = 0; longRes = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) + *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); resType->makeFromCLong( res + resOff, &longRes); } void OpPLUSCLong::getCondenseInit(char* init) { r_Long dummy = 0; resType->makeFromCLong(init, &dummy); } OpMINUSCLong::OpMINUSCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpMINUSCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1 = 0; r_Long longOp2 = 0; r_Long longRes = 0; longRes = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) - *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); resType->makeFromCLong( res + resOff, &longRes); } OpDIVCLong::OpDIVCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpDIVCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1 = 0; r_Long longOp2 = 0; r_Long longRes = 0; op2Type->convertToCLong(op2, &longOp2); if(longOp2 == 0) // catch division by zero, perhaps should throw exception longRes = 0; else { longRes = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) / longOp2; } resType->makeFromCLong( res + resOff, &longRes); } OpMULTCLong::OpMULTCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpMULTCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1 = 0; r_Long longOp2 = 0; r_Long longRes = 0; longRes = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) * *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); resType->makeFromCLong( res + resOff, &longRes); } void OpMULTCLong::getCondenseInit(char* init) { r_Long dummy = 1; resType->makeFromCLong(init, &dummy); } OpANDCLong::OpANDCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpANDCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1 = 0; r_Long longOp2 = 0; r_Long longRes = 0; longRes = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) & *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); resType->makeFromCLong( res + resOff, &longRes); } void OpANDCLong::getCondenseInit(char* init) { char dummy[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; memcpy( init, dummy, resType->getSize() ); } OpORCLong::OpORCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpORCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1 = 0; r_Long longOp2 = 0; r_Long longRes = 0; longRes = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) | *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); resType->makeFromCLong( res + resOff, &longRes); } void OpORCLong::getCondenseInit(char* init) { char dummy[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; memcpy( init, dummy, resType->getSize() ); } OpXORCLong::OpXORCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpXORCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1 = 0; r_Long longOp2 = 0; r_Long longRes = 0; longRes = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) ^ *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); resType->makeFromCLong( res + resOff, &longRes); } OpPLUSCDouble::OpPLUSCDouble( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpPLUSCDouble::operator()( char* res, const char* op1, const char* op2 ) { double doubleOp1 = 0; double doubleOp2 = 0; double doubleRes = 0; doubleRes = *(op1Type->convertToCDouble(op1 + op1Off, &doubleOp1)) + *(op2Type->convertToCDouble(op2 + op2Off, &doubleOp2)); resType->makeFromCDouble( res + resOff, &doubleRes); } void OpPLUSCDouble::getCondenseInit(char* init) { double dummy = 0.0; resType->makeFromCDouble(init, &dummy); } OpMINUSCDouble::OpMINUSCDouble( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpMINUSCDouble::operator()( char* res, const char* op1, const char* op2 ) { double doubleOp1 = 0; double doubleOp2 = 0; double doubleRes = 0; doubleRes = *(op1Type->convertToCDouble(op1 + op1Off, &doubleOp1)) - *(op2Type->convertToCDouble(op2 + op2Off, &doubleOp2)); resType->makeFromCDouble( res + resOff, &doubleRes); } OpDIVCDouble::OpDIVCDouble( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpDIVCDouble::operator()( char* res, const char* op1, const char* op2 ) { double doubleOp1 = 0; double doubleOp2 = 0; double doubleRes = 0; op2Type->convertToCDouble(op2, &doubleOp2); if(doubleOp2 == 0) // catch division by zero, perhaps should throw exception doubleRes = 0; else { doubleRes = *(op1Type->convertToCDouble(op1 + op1Off, &doubleOp1)) / doubleOp2; } resType->makeFromCDouble( res + resOff, &doubleRes); } OpMULTCDouble::OpMULTCDouble( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpMULTCDouble::operator()( char* res, const char* op1, const char* op2 ) { double doubleOp1 = 0; double doubleOp2 = 0; double doubleRes = 0; doubleRes = *(op1Type->convertToCDouble(op1 + op1Off, &doubleOp1)) * *(op2Type->convertToCDouble(op2 + op2Off, &doubleOp2)); resType->makeFromCDouble( res + resOff, &doubleRes); } void OpMULTCDouble::getCondenseInit(char* init) { double dummy = 1.0; resType->makeFromCDouble(init, &dummy); } OpEQUALCCharCULong::OpEQUALCCharCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpEQUALCCharCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1; r_ULong longOp2; *(res + resOff) = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) == *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); } OpLESSCCharCULong::OpLESSCCharCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpLESSCCharCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1; r_ULong longOp2; *(res + resOff) = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) < *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); } OpLESSEQUALCCharCULong::OpLESSEQUALCCharCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpLESSEQUALCCharCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1; r_ULong longOp2; *(res + resOff) = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) <= *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); } OpNOTEQUALCCharCULong::OpNOTEQUALCCharCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpNOTEQUALCCharCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1; r_ULong longOp2; *(res + resOff) = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) != *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); } OpGREATERCCharCULong::OpGREATERCCharCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpGREATERCCharCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1; r_ULong longOp2; *(res + resOff) = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) > *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); } OpGREATEREQUALCCharCULong::OpGREATEREQUALCCharCULong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpGREATEREQUALCCharCULong::operator()( char* res, const char* op1, const char* op2 ) { r_ULong longOp1; r_ULong longOp2; *(res + resOff) = *(op1Type->convertToCULong(op1 + op1Off, &longOp1)) >= *(op2Type->convertToCULong(op2 + op2Off, &longOp2)); } OpEQUALCCharCLong::OpEQUALCCharCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpEQUALCCharCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1; r_Long longOp2; *(res + resOff) = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) == *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); } OpLESSCCharCLong::OpLESSCCharCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpLESSCCharCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1; r_Long longOp2; *(res + resOff) = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) < *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); } OpLESSEQUALCCharCLong::OpLESSEQUALCCharCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpLESSEQUALCCharCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1; r_Long longOp2; *(res + resOff) = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) <= *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); } OpNOTEQUALCCharCLong::OpNOTEQUALCCharCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpNOTEQUALCCharCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1; r_Long longOp2; *(res + resOff) = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) != *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); } OpGREATERCCharCLong::OpGREATERCCharCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpGREATERCCharCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1; r_Long longOp2; *(res + resOff) = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) > *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); } OpGREATEREQUALCCharCLong::OpGREATEREQUALCCharCLong( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpGREATEREQUALCCharCLong::operator()( char* res, const char* op1, const char* op2 ) { r_Long longOp1; r_Long longOp2; *(res + resOff) = *(op1Type->convertToCLong(op1 + op1Off, &longOp1)) >= *(op2Type->convertToCLong(op2 + op2Off, &longOp2)); } OpEQUALCCharCDouble::OpEQUALCCharCDouble( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpEQUALCCharCDouble::operator()( char* res, const char* op1, const char* op2 ) { double doubleOp1; double doubleOp2; *(res + resOff) = *(op1Type->convertToCDouble(op1 + op1Off, &doubleOp1)) == *(op2Type->convertToCDouble(op2 + op2Off, &doubleOp2)); } OpLESSCCharCDouble::OpLESSCCharCDouble( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpLESSCCharCDouble::operator()( char* res, const char* op1, const char* op2 ) { double doubleOp1; double doubleOp2; *(res + resOff) = *(op1Type->convertToCDouble(op1 + op1Off, &doubleOp1)) < *(op2Type->convertToCDouble(op2 + op2Off, &doubleOp2)); } OpLESSEQUALCCharCDouble::OpLESSEQUALCCharCDouble( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpLESSEQUALCCharCDouble::operator()( char* res, const char* op1, const char* op2 ) { double doubleOp1; double doubleOp2; *(res + resOff) = *(op1Type->convertToCDouble(op1 + op1Off, &doubleOp1)) <= *(op2Type->convertToCDouble(op2 + op2Off, &doubleOp2)); } OpNOTEQUALCCharCDouble::OpNOTEQUALCCharCDouble( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpNOTEQUALCCharCDouble::operator()( char* res, const char* op1, const char* op2 ) { double doubleOp1; double doubleOp2; *(res + resOff) = *(op1Type->convertToCDouble(op1 + op1Off, &doubleOp1)) != *(op2Type->convertToCDouble(op2 + op2Off, &doubleOp2)); } OpGREATERCCharCDouble::OpGREATERCCharCDouble( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpGREATERCCharCDouble::operator()( char* res, const char* op1, const char* op2 ) { double doubleOp1; double doubleOp2; *(res + resOff) = *(op1Type->convertToCDouble(op1 + op1Off, &doubleOp1)) > *(op2Type->convertToCDouble(op2 + op2Off, &doubleOp2)); } OpGREATEREQUALCCharCDouble::OpGREATEREQUALCCharCDouble( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpGREATEREQUALCCharCDouble::operator()( char* res, const char* op1, const char* op2 ) { double doubleOp1; double doubleOp2; *(res + resOff) = *(op1Type->convertToCDouble(op1 + op1Off, &doubleOp1)) >= *(op2Type->convertToCDouble(op2 + op2Off, &doubleOp2)); } CondenseOp::CondenseOp( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : resType(newResType), opType(newOpType), resOff(newResOff), opOff(newOpOff), accu(0) { } CondenseOp::CondenseOp( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : resType(newResType), opType(newOpType), resOff(newResOff), opOff(newOpOff) { accu = new char[resType->getSize()]; memcpy(accu, newAccu, resType->getSize()); } char* CondenseOp::getAccuVal() { return accu; } CondenseOp::~CondenseOp() { delete [] accu; } OpSOMECChar::OpSOMECChar( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { // initialising with neutral value accu = new char[1]; // result is always char *accu = 0; } OpSOMECChar::OpSOMECChar( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpSOMECChar::operator()( const char* op, char* init ) { *(unsigned char*)(init + resOff) = *(unsigned char*)(init + resOff) || *(unsigned char*)(op + opOff); return init; } char* OpSOMECChar::operator()( const char* op ) { *(unsigned char*)(accu + resOff) = *(unsigned char*)(accu + resOff) || *(unsigned char*)(op + opOff); return accu; } OpALLCChar::OpALLCChar( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { // initialising with neutral value accu = new char[1]; // result is always char *accu = 1; } OpALLCChar::OpALLCChar( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpALLCChar::operator()( const char* op, char* init ) { *(unsigned char*)(init + resOff) = *(unsigned char*)(init + resOff) && *(unsigned char*)(op + opOff); return init; } char* OpALLCChar::operator()( const char* op ) { *(unsigned char*)(accu + resOff) = *(unsigned char*)(accu + resOff) && *(unsigned char*)(op + opOff); return accu; } OpCOUNTCChar::OpCOUNTCChar( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { // initialising with neutral value accu = new char[4]; // result is always r_ULong *(r_ULong*)accu = 0; } OpCOUNTCChar::OpCOUNTCChar( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpCOUNTCChar::operator()( const char* op, char* init ) { *(r_ULong*)(init + resOff) = *(r_ULong*)(init + resOff) + *(unsigned char*)(op + opOff); return init; } char* OpCOUNTCChar::operator()( const char* op ) { *(r_ULong*)(accu + resOff) = *(r_ULong*)(accu + resOff) + *(unsigned char*)(op + opOff); return accu; } OpMAXCULong::OpMAXCULong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { r_ULong myVal = 0; // initialising with neutral value accu = new char[resType->getSize()]; resType->makeFromCULong(accu, &myVal); } OpMAXCULong::OpMAXCULong( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpMAXCULong::operator()( const char* op, char* init ) { r_ULong longOp = 0; r_ULong longRes = 0; longOp = *(opType->convertToCULong(op + opOff, &longOp)); longRes = *(resType->convertToCULong(init + resOff, &longRes)); if(longOp > longRes) { resType->makeFromCULong(init + resOff, &longOp); } return init; } char* OpMAXCULong::operator()( const char* op ) { return OpMAXCULong::operator()(op, accu); } OpMAXCLong::OpMAXCLong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { r_Long myVal = INT_MIN; // initialising with neutral value accu = new char[resType->getSize()]; resType->makeFromCLong(accu, &myVal); } OpMAXCLong::OpMAXCLong( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpMAXCLong::operator()( const char* op, char* init ) { r_Long longOp = 0; r_Long longRes = 0; longOp = *(opType->convertToCLong(op + opOff, &longOp)); longRes = *(resType->convertToCLong(init + resOff, &longRes)); if(longOp > longRes) { resType->makeFromCLong(init + resOff, &longOp); } return init; } char* OpMAXCLong::operator()( const char* op ) { return OpMAXCLong::operator()(op, accu); } OpMAXCDouble::OpMAXCDouble( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { double myVal = (-1.0)*DBL_MAX; // initialising with neutral value accu = new char[resType->getSize()]; // make sure accu contains a legal float memset(accu, 0, resType->getSize()); resType->makeFromCDouble(accu, &myVal); } OpMAXCDouble::OpMAXCDouble( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpMAXCDouble::operator()( const char* op, char* init ) { double longOp = 0; double longRes = 0; longOp = *(opType->convertToCDouble(op + opOff, &longOp)); longRes = *(resType->convertToCDouble(init + resOff, &longRes)); if(longOp > longRes) { resType->makeFromCDouble(init + resOff, &longOp); } return init; } char* OpMAXCDouble::operator()( const char* op ) { return OpMAXCDouble::operator()(op, accu); } OpMINCULong::OpMINCULong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { r_ULong myVal = UINT_MAX; // initialising with neutral value accu = new char[resType->getSize()]; resType->makeFromCULong(accu, &myVal); } OpMINCULong::OpMINCULong( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpMINCULong::operator()( const char* op, char* init ) { r_ULong longOp = 0; r_ULong longRes = 0; longOp = *(opType->convertToCULong(op + opOff, &longOp)); longRes = *(resType->convertToCULong(init + resOff, &longRes)); if(longOp < longRes) { resType->makeFromCULong(init + resOff, &longOp); } return init; } char* OpMINCULong::operator()( const char* op ) { return OpMINCULong::operator()(op, accu); } OpMINCLong::OpMINCLong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { r_Long myVal = INT_MAX; // initialising with neutral value accu = new char[resType->getSize()]; resType->makeFromCLong(accu, &myVal); } OpMINCLong::OpMINCLong( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpMINCLong::operator()( const char* op, char* init ) { r_Long longOp = 0; r_Long longRes = 0; longOp = *(opType->convertToCLong(op + opOff, &longOp)); longRes = *(resType->convertToCLong(init + resOff, &longRes)); if(longOp < longRes) { resType->makeFromCLong(init + resOff, &longOp); } return init; } char* OpMINCLong::operator()( const char* op ) { return OpMINCLong::operator()(op, accu); } OpMINCDouble::OpMINCDouble( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { double myVal = DBL_MAX; // initialising with neutral value accu = new char[resType->getSize()]; // make sure accu contains a legal float memset(accu, 0, resType->getSize()); resType->makeFromCDouble(accu, &myVal); } OpMINCDouble::OpMINCDouble( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpMINCDouble::operator()( const char* op, char* init ) { double longOp = 0; double longRes = 0; longOp = *(opType->convertToCDouble(op + opOff, &longOp)); longRes = *(resType->convertToCDouble(init + resOff, &longRes)); if(longOp < longRes) { resType->makeFromCDouble(init + resOff, &longOp); } return init; } char* OpMINCDouble::operator()( const char* op ) { return OpMINCDouble::operator()(op, accu); } OpSUMCULong::OpSUMCULong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { r_ULong myVal = 0; // initialising with neutral value accu = new char[resType->getSize()]; resType->makeFromCULong(accu, &myVal); } OpSUMCULong::OpSUMCULong( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpSUMCULong::operator()( const char* op, char* init ) { r_ULong longOp = 0; r_ULong longRes = 0; opType->convertToCULong(op + opOff, &longOp); resType->convertToCULong(init + resOff, &longRes); longRes += longOp; resType->makeFromCULong( init + resOff, &longRes); return init; } char* OpSUMCULong::operator()( const char* op ) { return OpSUMCULong::operator()(op, accu); } OpSUMCLong::OpSUMCLong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { r_Long myVal = 0; // initialising with neutral value accu = new char[resType->getSize()]; resType->makeFromCLong(accu, &myVal); } OpSUMCLong::OpSUMCLong( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpSUMCLong::operator()( const char* op, char* init ) { r_Long longOp = 0; r_Long longRes = 0; longOp = *(opType->convertToCLong(op + opOff, &longOp)); longRes = *(resType->convertToCLong(init + resOff, &longRes)); longRes = longOp + longRes; resType->makeFromCLong( init + resOff, &longRes); return init; } char* OpSUMCLong::operator()( const char* op ) { return OpSUMCLong::operator()(op, accu); } OpSUMCDouble::OpSUMCDouble( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { double myVal = 0.0; // initialising with neutral value accu = new char[resType->getSize()]; resType->makeFromCDouble(accu, &myVal); } OpSUMCDouble::OpSUMCDouble( const BaseType* newResType, char* newAccu, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newAccu, newOpType, newResOff, newOpOff) { } char* OpSUMCDouble::operator()( const char* op, char* init ) { double longOp = 0; double longRes = 0; longOp = *(opType->convertToCDouble(op + opOff, &longOp)); longRes = *(resType->convertToCDouble(init + resOff, &longRes)); longRes = longOp + longRes; resType->makeFromCDouble( init + resOff, &longRes); return init; } char* OpSUMCDouble::operator()( const char* op ) { return OpSUMCDouble::operator()(op, accu); } OpCondenseStruct::OpCondenseStruct( const BaseType* newResType, const BaseType* newOpType, Ops::OpType op, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { int i = 0; myResType = (StructType*)newResType; myOpType = (StructType*)newOpType; numElems = myOpType->getNumElems(); elemOps = new CondenseOp*[numElems]; for(i = 0; i < numElems; i++) { elemOps[i] = Ops::getCondenseOp( op, myResType->getElemType(i), myOpType->getElemType(i), newResOff + myResType->getOffset(i), newOpOff + myOpType->getOffset(i) ); } accu = new char[resType->getSize()]; for(i = 0; i < numElems; i++) { memcpy(accu + myResType->getOffset(i), elemOps[i]->getAccuVal(), myResType->getElemType(i)->getSize()); } } //-------------------------------------------- // OpCondenseStruct //-------------------------------------------- OpCondenseStruct::OpCondenseStruct( const BaseType* newResType, char* newAccu, const BaseType* newOpType, Ops::OpType op, unsigned int newResOff, unsigned int newOpOff ) : CondenseOp(newResType, newOpType, newResOff, newOpOff) { int i = 0; myResType = (StructType*)newResType; myOpType = (StructType*)newOpType; numElems = myOpType->getNumElems(); elemOps = new CondenseOp*[numElems]; for(i = 0; i < numElems; i++) { elemOps[i] = Ops::getCondenseOp( op, myResType->getElemType(i), myOpType->getElemType(i), newResOff + myResType->getOffset(i), newOpOff + myOpType->getOffset(i) ); } accu = new char[resType->getSize()]; memcpy(accu, newAccu, resType->getSize()); } OpCondenseStruct::~OpCondenseStruct() { int i; for(i = 0; i < numElems; i++) { delete elemOps[i]; } delete[] elemOps; } char* OpCondenseStruct::operator()( const char* op, char* init ) { int i; for(i = 0; i < numElems; i++) { (*elemOps[i])(op, init); } return init; } char* OpCondenseStruct::operator()( const char* op ) { int i; for(i = 0; i < numElems; i++) { (*elemOps[i])(op, accu); } return accu; } //-------------------------------------------- // OpBinaryStruct //-------------------------------------------- static Ops::OpType _operation; OpBinaryStruct::OpBinaryStruct( const BaseType* newStructType, Ops::OpType op, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newStructType, newStructType, newStructType, newResOff, newOp1Off, newOp2Off) { int i = 0; _operation = op; myStructType = (StructType*)newStructType; numElems = myStructType->getNumElems(); elemOps = new BinaryOp*[numElems]; for(i = 0; i < numElems; i++) { elemOps[i] = Ops::getBinaryOp( op, myStructType->getElemType(i), myStructType->getElemType(i), myStructType->getElemType(i), newResOff + myStructType->getOffset(i), newOp1Off + myStructType->getOffset(i), newOp2Off + myStructType->getOffset(i) ); } } OpBinaryStruct::~OpBinaryStruct() { int i; for(i = 0; i < numElems; i++) { delete elemOps[i]; } delete[] elemOps; } void OpBinaryStruct::operator()( char* res, const char* op1, const char* op2 ) { int i; if( _operation == Ops::OP_OVERLAY ) { RMInit::logOut << "OpBinaryStruct operation" << endl; for(i = 0; i < numElems; ++i) if(*(op2 + op2Off)) { for(int j = 0; j < numElems; ++j) *(res + resOff) = *(op2 + op2Off); return; } } for(i = 0; i < numElems; i++) { (*elemOps[i])(res, op1, op2); } } //-------------------------------------------- // OpBinaryStructConst //-------------------------------------------- OpBinaryStructConst::OpBinaryStructConst( const BaseType* res, const BaseType* op1, const BaseType* op2, Ops::OpType op, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(res, op1, op2, newResOff, newOp1Off, newOp2Off) { int i = 0; resStructType = (StructType*)resType; opStructType = (StructType*)op1Type; numElems = opStructType->getNumElems(); elemOps = new BinaryOp*[numElems]; for(i = 0; i < numElems; i++) { elemOps[i] = Ops::getBinaryOp( op, resStructType->getElemType(i), opStructType->getElemType(i), op2Type, newResOff + resStructType->getOffset(i), newOp1Off + opStructType->getOffset(i), newOp2Off ); } } OpBinaryStructConst::~OpBinaryStructConst() { int i; for(i = 0; i < numElems; i++) { delete elemOps[i]; } delete[] elemOps; } void OpBinaryStructConst::operator()( char* res, const char* op1, const char* op2 ) { int i; for(i = 0; i < numElems; i++) { (*elemOps[i])(res, op1, op2); } } //-------------------------------------------- // OpBinaryConstStruct //-------------------------------------------- OpBinaryConstStruct::OpBinaryConstStruct( const BaseType* res, const BaseType* op1, const BaseType* op2, Ops::OpType op, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(res, op1, op2, newResOff, newOp1Off, newOp2Off) { int i = 0; resStructType = (StructType*)resType; opStructType = (StructType*)op2Type; numElems = opStructType->getNumElems(); elemOps = new BinaryOp*[numElems]; for(i = 0; i < numElems; i++) { elemOps[i] = Ops::getBinaryOp( op, resStructType->getElemType(i), op1Type, opStructType->getElemType(i), newResOff + resStructType->getOffset(i), newOp1Off, newOp2Off + opStructType->getOffset(i) ); } } OpBinaryConstStruct::~OpBinaryConstStruct() { int i; for(i = 0; i < numElems; i++) { delete elemOps[i]; } delete[] elemOps; } void OpBinaryConstStruct::operator()( char* res, const char* op1, const char* op2 ) { int i; for(i = 0; i < numElems; i++) { (*elemOps[i])(res, op1, op2); } } //-------------------------------------------- // OpEQUALStruct //-------------------------------------------- OpEQUALStruct::OpEQUALStruct( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { int i = 0; numElems = ((StructType*)op1Type)->getNumElems(); elemOps = new BinaryOp*[numElems]; for(i = 0; i < numElems; i++) { elemOps[i] = Ops::getBinaryOp( Ops::OP_EQUAL, resType, ((StructType*)op1Type)->getElemType(i), ((StructType*)op2Type)->getElemType(i), newResOff, newOp1Off + ((StructType*)op1Type)->getOffset(i), newOp2Off + ((StructType*)op2Type)->getOffset(i) ); } } OpEQUALStruct::~OpEQUALStruct() { int i; for(i = 0; i < numElems; i++) { delete elemOps[i]; } delete[] elemOps; } void OpEQUALStruct::operator()( char* res, const char* op1, const char* op2 ) { int i; char dummy = 1; for(i = 0; i < numElems; i++) { (*elemOps[i])(res, op1, op2); dummy = *res && dummy; } *res = dummy; } //-------------------------------------------- // OpNOTEQUALStruct //-------------------------------------------- OpNOTEQUALStruct::OpNOTEQUALStruct( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { int i = 0; numElems = ((StructType*)op1Type)->getNumElems(); elemOps = new BinaryOp*[numElems]; for(i = 0; i < numElems; i++) { elemOps[i] = Ops::getBinaryOp( Ops::OP_NOTEQUAL, resType, ((StructType*)op1Type)->getElemType(i), ((StructType*)op2Type)->getElemType(i), newResOff, newOp1Off + ((StructType*)op1Type)->getOffset(i), newOp2Off + ((StructType*)op2Type)->getOffset(i) ); } } OpNOTEQUALStruct::~OpNOTEQUALStruct() { int i; for(i = 0; i < numElems; i++) { delete elemOps[i]; } delete[] elemOps; } void OpNOTEQUALStruct::operator()( char* res, const char* op1, const char* op2 ) { int i; char dummy = 0; for(i = 0; i < numElems; i++) { (*elemOps[i])(res, op1, op2); dummy = *res || dummy; } *res = dummy; } //-------------------------------------------- // OpUnaryStruct //-------------------------------------------- OpUnaryStruct::OpUnaryStruct( const BaseType* newResType, const BaseType* newOpType, Ops::OpType op, unsigned int newResOff, unsigned int newOpOff) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { int i = 0; myResType = (StructType*)newResType; myOpType = (StructType*)newOpType; numElems = myOpType->getNumElems(); elemOps = new UnaryOp*[numElems]; for(i = 0; i < numElems; i++) { elemOps[i] = Ops::getUnaryOp( op, myResType->getElemType(i), myOpType->getElemType(i), newResOff + myResType->getOffset(i), newOpOff + myOpType->getOffset(i) ); } } OpUnaryStruct::~OpUnaryStruct() { int i; for(i = 0; i < numElems; i++) { delete elemOps[i]; } delete[] elemOps; } void OpUnaryStruct::operator()( char* result, const char* op ) { int i; for(i = 0; i < numElems; i++) { try { (*elemOps[i])(result, op); } catch(...) { // cleanup for(i = 0; i < numElems; i++) { delete elemOps[i]; } delete[] elemOps; throw; } } } //-------------------------------------------- // OpPLUSChar //-------------------------------------------- OpPLUSChar::OpPLUSChar( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpPLUSChar::operator()( char* res, const char* op1, const char* op2 ) { *(unsigned char*)(res + resOff) = *(unsigned char*)(op1 + op1Off) + *(unsigned char*)(op2 + op2Off); } void OpPLUSChar::getCondenseInit(char* init) { *init = 0; } //-------------------------------------------- // OpMINUSChar //-------------------------------------------- OpMINUSChar::OpMINUSChar( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpMINUSChar::operator()( char* res, const char* op1, const char* op2 ) { *(unsigned char*)(res + resOff) = *(unsigned char*)(op1 + op1Off) - *(unsigned char*)(op2 + op2Off); } //-------------------------------------------- // OpDIVChar //-------------------------------------------- OpDIVChar::OpDIVChar( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpDIVChar::operator()( char* res, const char* op1, const char* op2 ) { if(*(unsigned char*)(op2 + op2Off) == 0) // catch division by zero, perhaps should throw exception *(unsigned char*)(res + resOff) = 0; else { *(unsigned char*)(res + resOff) = *(unsigned char*)(op1 + op1Off) / *(unsigned char*)(op2 + op2Off); } } //-------------------------------------------- // OpMULTChar //-------------------------------------------- OpMULTChar::OpMULTChar( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpMULTChar::operator()( char* res, const char* op1, const char* op2 ) { *(unsigned char*)(res + resOff) = *(unsigned char*)(op1 + op1Off) * *(unsigned char*)(op2 + op2Off); } void OpMULTChar::getCondenseInit(char* init) { *init = 1; } //-------------------------------------------- // OpEQUALChar //-------------------------------------------- OpEQUALChar::OpEQUALChar( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpEQUALChar::operator()( char* res, const char* op1, const char* op2 ) { *(unsigned char*)(res + resOff) = *(unsigned char*)(op1 + op1Off) == *(unsigned char*)(op2 + op2Off); } //-------------------------------------------- // OpLESSChar //-------------------------------------------- OpLESSChar::OpLESSChar( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpLESSChar::operator()( char* res, const char* op1, const char* op2 ) { *(unsigned char*)(res + resOff) = *(unsigned char*)(op1 + op1Off) < *(unsigned char*)(op2 + op2Off); } //-------------------------------------------- // OpLESSEQUALChar //-------------------------------------------- OpLESSEQUALChar::OpLESSEQUALChar( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpLESSEQUALChar::operator()( char* res, const char* op1, const char* op2 ) { *(unsigned char*)(res + resOff) = *(unsigned char*)(op1 + op1Off) <= *(unsigned char*)(op2 + op2Off); } //-------------------------------------------- // OpNOTEQUALChar //-------------------------------------------- OpNOTEQUALChar::OpNOTEQUALChar( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpNOTEQUALChar::operator()( char* res, const char* op1, const char* op2 ) { *(unsigned char*)(res + resOff) = *(unsigned char*)(op1 + op1Off) != *(unsigned char*)(op2 + op2Off); } //-------------------------------------------- // OpGREATERChar //-------------------------------------------- OpGREATERChar::OpGREATERChar( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpGREATERChar::operator()( char* res, const char* op1, const char* op2 ) { *(unsigned char*)(res + resOff) = *(unsigned char*)(op1 + op1Off) > *(unsigned char*)(op2 + op2Off); } //-------------------------------------------- // OpGREATEREQUALChar //-------------------------------------------- OpGREATEREQUALChar::OpGREATEREQUALChar( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off ) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) { } void OpGREATEREQUALChar::operator()( char* res, const char* op1, const char* op2 ) { *(unsigned char*)(res + resOff) = *(unsigned char*)(op1 + op1Off) >= *(unsigned char*)(op2 + op2Off); } //-------------------------------------------- // OpIDENTITYChar //-------------------------------------------- OpIDENTITYChar::OpIDENTITYChar( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { } void OpIDENTITYChar::operator()( char* res, const char* op ) { *(unsigned char*)(res + resOff) = *(unsigned char*)(op + opOff); } //-------------------------------------------- // //-------------------------------------------- OpIDENTITYShort::OpIDENTITYShort( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { } void OpIDENTITYShort::operator()( char* res, const char* op ) { *(unsigned short*)(res + resOff) = *(unsigned short*)(op + opOff); } //-------------------------------------------- // OpIDENTITYLong //-------------------------------------------- OpIDENTITYLong::OpIDENTITYLong( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { } void OpIDENTITYLong::operator()( char* res, const char* op ) { *(r_ULong*)(res + resOff) = *(r_ULong*)(op + opOff); } //-------------------------------------------- // MarrayOp //-------------------------------------------- MarrayOp::MarrayOp( const BaseType* newResType, unsigned int newResOff ) : resType(newResType), resOff(newResOff) { } void MarrayOp::operator()( char* result, const r_Point& p ) { r_ULong sum = 0; for(int i = 0; i < p.dimension(); i++) sum += p[i]; resType->makeFromCULong(result, &sum); } //-------------------------------------------- // GenCondenseOp //-------------------------------------------- GenCondenseOp::GenCondenseOp( const BaseType* newResType, unsigned int newResOff, BinaryOp* newAccuOp, char* newInitVal ) : resType(newResType), resOff(newResOff), accuOp(newAccuOp), myInitVal(0) { if(newInitVal == 0) { initVal = new char[resType->getSize()]; myInitVal = 1; accuOp->getCondenseInit(initVal); } else initVal = newInitVal; } GenCondenseOp::~GenCondenseOp() { if(myInitVal) delete [] initVal; } void GenCondenseOp::operator()( const r_Point& p ) { r_ULong sum = 0; char buf[8]; for(int i = 0; i < p.dimension(); i++) sum += p[i]; resType->makeFromCULong(buf, &sum); (*accuOp)(initVal, initVal, buf); } BinaryOp* GenCondenseOp::getAccuOp() { return accuOp; } const BaseType* GenCondenseOp::getResultType() { return resType; } unsigned int GenCondenseOp::getResultOff() { return resOff; } char* GenCondenseOp::getAccuVal() { return initVal; } //-------------------------------------------- // Complex //-------------------------------------------- // *** PLUS *** OpPLUSComplex::OpPLUSComplex( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off, ScalarFlag flag) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off), scalarFlag(flag) { op1ReOff = scalarFlag == OpPLUSComplex::FIRST ? 0: ((GenericComplexType *)newOp1Type)->getReOffset(); op1ImOff = scalarFlag == OpPLUSComplex::FIRST ? 0: ((GenericComplexType *)newOp1Type)->getImOffset(); op2ReOff = scalarFlag == OpPLUSComplex::SECOND ? 0: ((GenericComplexType *)newOp2Type)->getReOffset(); op2ImOff = scalarFlag == OpPLUSComplex::SECOND ? 0: ((GenericComplexType *)newOp2Type)->getImOffset(); resReOff = ((GenericComplexType *)newResType)->getReOffset(); resImOff = ((GenericComplexType *)newResType)->getImOffset(); } void OpPLUSComplex::operator()(char* res, const char* op1, const char* op2) { double op1Re = 0; double op2Re = 0; double op1Im = 0; double op2Im = 0; double resRe, resIm; if(scalarFlag == FIRST) { resRe = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) + *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); resIm = *(op2Type->convertToCDouble(op2 + op2Off + op2ImOff, &op2Im)); } else if(scalarFlag == SECOND) { resRe = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) + *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); resIm = *(op1Type->convertToCDouble(op1 + op1Off + op1ImOff, &op1Im)); } else { resRe = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) + *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); resIm = *(op1Type->convertToCDouble(op1 + op1Off + op1ImOff, &op1Im)) + *(op2Type->convertToCDouble(op2 + op2Off + op2ImOff, &op2Im)); } resType->makeFromCDouble(res + resOff + resReOff, &resRe); resType->makeFromCDouble(res + resOff + resImOff, &resIm); } void OpPLUSComplex::getCondenseInit(char* init) { double dummyRe = 0.0; double dummyIm = 0.0; resType->makeFromCDouble(init + resReOff, &dummyRe); resType->makeFromCDouble(init + resImOff, &dummyIm); } // *** MINUS *** OpMINUSComplex::OpMINUSComplex( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off, ScalarFlag flag) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off), scalarFlag(flag) { op1ReOff = scalarFlag == OpPLUSComplex::FIRST ? 0: ((GenericComplexType *)newOp1Type)->getReOffset(); op1ImOff = scalarFlag == OpPLUSComplex::FIRST ? 0: ((GenericComplexType *)newOp1Type)->getImOffset(); op2ReOff = scalarFlag == OpPLUSComplex::SECOND ? 0: ((GenericComplexType *)newOp2Type)->getReOffset(); op2ImOff = scalarFlag == OpPLUSComplex::SECOND ? 0: ((GenericComplexType *)newOp2Type)->getImOffset(); resReOff = ((GenericComplexType *)newResType)->getReOffset(); resImOff = ((GenericComplexType *)newResType)->getImOffset(); } void OpMINUSComplex::operator()(char* res, const char* op1, const char* op2) { double op1Re = 0; double op2Re = 0; double op1Im = 0; double op2Im = 0; double resRe, resIm; if(scalarFlag == FIRST) { resRe = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) - *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); resIm = *(op2Type->convertToCDouble(op2 + op2Off + op2ImOff, &op2Im)); } else if(scalarFlag == SECOND) { resRe = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) - *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); resIm = *(op1Type->convertToCDouble(op1 + op1Off + op1ImOff, &op1Im)); } else { resRe = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) - *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); resIm = *(op1Type->convertToCDouble(op1 + op1Off + op1ImOff, &op1Im)) - *(op2Type->convertToCDouble(op2 + op2Off + op2ImOff, &op2Im)); } resType->makeFromCDouble(res + resOff + resReOff, &resRe); resType->makeFromCDouble(res + resOff + resImOff, &resIm); } // *** DIV *** OpDIVComplex::OpDIVComplex( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off, ScalarFlag flag) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off), scalarFlag(flag) { op1ReOff = scalarFlag == OpPLUSComplex::FIRST ? 0: ((GenericComplexType *)newOp1Type)->getReOffset(); op1ImOff = scalarFlag == OpPLUSComplex::FIRST ? 0: ((GenericComplexType *)newOp1Type)->getImOffset(); op2ReOff = scalarFlag == OpPLUSComplex::SECOND ? 0: ((GenericComplexType *)newOp2Type)->getReOffset(); op2ImOff = scalarFlag == OpPLUSComplex::SECOND ? 0: ((GenericComplexType *)newOp2Type)->getImOffset(); resReOff = ((GenericComplexType *)newResType)->getReOffset(); resImOff = ((GenericComplexType *)newResType)->getImOffset(); } void OpDIVComplex::operator()(char* res, const char* op1, const char* op2) { double op1Re = 0; double op2Re = 0; double op1Im = 0; double op2Im = 0; double resRe, resIm; if(scalarFlag == FIRST) { double a = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)); double x = *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); double y = *(op2Type->convertToCDouble(op2 + op2Off + op2ImOff, &op2Im)); resRe = a * x / (x * x + y * y); resIm = - a * y / (x * x + y * y); } else if(scalarFlag == SECOND) { resRe = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) / *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); resIm = *(op1Type->convertToCDouble(op1 + op1Off + op1ImOff, &op1Im)) / *(op2Type->convertToCDouble(op2 + op2Off + op2ImOff, &op2Im)); } else { // NONE double x1 = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)); double y1 = *(op1Type->convertToCDouble(op1 + op1Off + op1ImOff, &op1Im)); double x2 = *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); double y2 = *(op2Type->convertToCDouble(op2 + op2Off + op2ImOff, &op2Im)); resRe = (x1 * x2 + y1 * y2) / (x2 * x2 + y2 * y2); resIm = (y1 * x2 - x1 * y2) / (x2 * x2 + y2 * y2); } resType->makeFromCDouble(res + resOff + resReOff, &resRe); resType->makeFromCDouble(res + resOff + resImOff, &resIm); } // *** MULT *** OpMULTComplex::OpMULTComplex( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off, ScalarFlag flag) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off), scalarFlag(flag) { op1ReOff = scalarFlag == OpPLUSComplex::FIRST ? 0: ((GenericComplexType *)newOp1Type)->getReOffset(); op1ImOff = scalarFlag == OpPLUSComplex::FIRST ? 0: ((GenericComplexType *)newOp1Type)->getImOffset(); op2ReOff = scalarFlag == OpPLUSComplex::SECOND ? 0: ((GenericComplexType *)newOp2Type)->getReOffset(); op2ImOff = scalarFlag == OpPLUSComplex::SECOND ? 0: ((GenericComplexType *)newOp2Type)->getImOffset(); resReOff = ((GenericComplexType *)newResType)->getReOffset(); resImOff = ((GenericComplexType *)newResType)->getImOffset(); } void OpMULTComplex::operator()(char* res, const char* op1, const char* op2) { double op1Re = 0; double op2Re = 0; double op1Im = 0; double op2Im = 0; double resRe, resIm; if(scalarFlag == FIRST) { resRe = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) * *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); resIm = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) * *(op2Type->convertToCDouble(op2 + op2Off + op2ImOff, &op2Im)); } else if(scalarFlag == SECOND) { resRe = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) * *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); resIm = *(op1Type->convertToCDouble(op1 + op1Off + op1ImOff, &op1Im)) * *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)); } else { // Re = x1 * x2 - y1 * y2 resRe = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) * // x1 *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)) - // x2 *(op1Type->convertToCDouble(op1 + op1Off + op1ImOff, &op1Im)) * // y1 *(op2Type->convertToCDouble(op2 + op2Off + op2ImOff, &op2Im)); // y2 // Im = x1 * y2 + x2 * y1 resIm = *(op1Type->convertToCDouble(op1 + op1Off + op1ReOff, &op1Re)) * // x1 *(op2Type->convertToCDouble(op2 + op2Off + op2ImOff, &op2Im)) + // y2 *(op2Type->convertToCDouble(op2 + op2Off + op2ReOff, &op2Re)) * // x2 *(op1Type->convertToCDouble(op1 + op1Off + op1ImOff, &op1Im)); // y1 } resType->makeFromCDouble(res + resOff + resReOff, &resRe); resType->makeFromCDouble(res + resOff + resImOff, &resIm); } void OpMULTComplex::getCondenseInit(char* init) { double dummyRe = 0.0; double dummyIm = 0.0; resType->makeFromCDouble(init + resReOff, &dummyRe); resType->makeFromCDouble(init + resImOff, &dummyIm); } // *** IDENTITY *** OpIDENTITYComplex::OpIDENTITYComplex( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff ) : UnaryOp(newResType, newOpType, newResOff, newOpOff) {} void OpIDENTITYComplex::operator()(char* res, const char* op) { memcpy((void *)(res + resOff), (void *)(op + opOff), resType->getSize()); } // *** REAL PART *** OpRealPart::OpRealPart( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { opReOff = ((GenericComplexType *)newOpType)->getReOffset(); } void OpRealPart::operator()(char* res, const char* op) { double result; opType->convertToCDouble(op + opOff + opReOff, &result); resType->makeFromCDouble(res + resOff, &result); } // *** IMAGINAR PART *** OpImaginarPart::OpImaginarPart( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff) : UnaryOp(newResType, newOpType, newResOff, newOpOff) { opImOff = ((GenericComplexType *)newOpType)->getImOffset(); } void OpImaginarPart::operator()(char* res, const char* op) { double result; opType->convertToCDouble(op + opOff + opImOff, &result); resType->makeFromCDouble(res + resOff, &result); } //-------------------------------------------- // OpCAST //-------------------------------------------- OpCAST::OpCAST( const BaseType* newResType, const BaseType* newOpType, unsigned int newResOff, unsigned int newOpOff) : UnaryOp(newResType, newOpType, newResOff, newOpOff) {} void OpCAST::operator()(char* res, const char* op) { if(resType->getType() == FLOAT || resType->getType() == DOUBLE) { // floating point types double dblOp; double dblRes = *(opType->convertToCDouble(op + opOff, &dblOp)); resType->makeFromCDouble(res + resOff, &dblRes); } else { // all integral types r_Long lngOp; r_Long lngRes = *(opType->convertToCLong(op + opOff, &lngOp)); resType->makeFromCLong(res + resOff, &lngRes); } } //-------------------------------------------- // OpOVERLAY //-------------------------------------------- OpOVERLAY::OpOVERLAY( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, size_t typeSize, const char* transparentPattern, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off), length(typeSize), pattern(transparentPattern) { if ((pattern == nullPattern) && (length > 16)) { RMInit::logOut << "OpOVERLAY overlay with types larger than 16 bytes not supported yet" << endl; throw r_Error(OVERLAYPATTERNTOOSMALL); } } void OpOVERLAY::operator()( char *res, const char *op1, const char *op2 ) { if (memcmp(pattern, op1 + op1Off, length) == 0) {//match memcpy(res + resOff, op2 + op2Off, length); } else {//no match memcpy(res + resOff, op1 + op1Off, length); } } const char* OpOVERLAY::nullPattern = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; //-------------------------------------------- // OpBIT //-------------------------------------------- OpBIT::OpBIT( const BaseType* newResType, const BaseType* newOp1Type, const BaseType* newOp2Type, unsigned int newResOff, unsigned int newOp1Off, unsigned int newOp2Off) : BinaryOp(newResType, newOp1Type, newOp2Type, newResOff, newOp1Off, newOp2Off) {} void OpBIT::operator() (char *res, const char *op1, const char *op2) { r_ULong lngOp1, lngOp2, lngRes; op1Type->convertToCULong(op1 + op1Off, &lngOp1); op2Type->convertToCULong(op2 + op2Off, &lngOp2); lngRes = lngOp1 >> lngOp2 & 0x1L; resType->makeFromCULong(res + resOff, &lngRes); } #include "autogen_ops.cc"