#ifndef OPAL_SBinary_HH #define OPAL_SBinary_HH // ------------------------------------------------------------------------ // $RCSfile: SBinary.h,v $ // ------------------------------------------------------------------------ // $Revision: 1.1.1.1 $ // ------------------------------------------------------------------------ // Copyright: see Copyright.readme // ------------------------------------------------------------------------ // // Template class: SBinary // // ------------------------------------------------------------------------ // // $Date: 2000/03/27 09:33:42 $ // $Author: Andreas Adelmann $ // // ------------------------------------------------------------------------ #include "AbstractObjects/Expressions.h" #include "Expressions/SConstant.h" #include "Expressions/TFunction2.h" #include "Utilities/DomainError.h" #include "Utilities/OverflowError.h" #include #include namespace Expressions { // Template class SBinary // ---------------------------------------------------------------------- /// A scalar expression with two scalar operands. // The expression first evaluates the two scalar operands, and then // it applies the given function to the operands and returns the result. template class SBinary: public Scalar { public: /// Constructor. // Use scalar function with two operands and two scalars. SBinary(const TFunction2 &function, PtrToScalar left, PtrToScalar right); SBinary(const SBinary &); virtual ~SBinary(); /// Make clone. virtual Scalar *clone() const; /// Evaluate. virtual T evaluate() const; /// Make a new expression. // If both operands are constants and the function is not a random // generator, evaluate the expression and store the result as a // constant. static Scalar *make(const TFunction2 &, PtrToScalar left, PtrToScalar right); /// Print expression. virtual void print(std::ostream &str, int precedence = 99) const; private: // Not implemented. SBinary(); void operator=(const SBinary &); // The operation object. const TFunction2 &fun; // The two operands. PtrToScalar lft; PtrToScalar rgt; }; // Implementation // ------------------------------------------------------------------------ template inline SBinary::SBinary(const SBinary &rhs): Scalar(rhs), fun(rhs.fun), lft(rhs.lft->clone()), rgt(rhs.rgt->clone()) {} template inline SBinary::SBinary(const TFunction2 &function, PtrToScalar left, PtrToScalar right): fun(function), lft(left), rgt(right) {} template inline SBinary::~SBinary() {} template inline Scalar *SBinary::clone() const { return new SBinary(*this); } template inline T SBinary::evaluate() const { errno = 0; U op1 = lft->evaluate(); U op2 = rgt->evaluate(); T result = (*fun.function)(op1, op2); // Test for run-time evaluation errors. switch(errno) { case EDOM: throw DomainError("SBinary::evaluate()"); case ERANGE: // Ignore underflow. if(result == T(0)) return result; throw OverflowError("SBinary::evaluate()"); default: return result; } } template inline Scalar *SBinary::make (const TFunction2 &function, PtrToScalar left, PtrToScalar right) { // We must pick up the constant flag before the ownerships of "left" and // "right" are transferred to "result". bool isConst = left->isConstant() && right->isConstant(); PtrToScalar result = new SBinary(function, left, right); if(function.precedence != -2) { if(isConst) { // Replace constant expression by its value. result = new SConstant(result->evaluate()); } } // Other expression. return result.release(); } template inline void SBinary::print(std::ostream &os, int precedence) const { if(fun.precedence >= 0) { // Binary operation. if(fun.precedence <= precedence) os << "("; lft->print(os, fun.precedence - 1); os << fun.name; rgt->print(os, fun.precedence); if(fun.precedence <= precedence) os << ")"; } else { // Function. os << fun.name << '('; lft->print(os, 0); os << ','; rgt->print(os, 0); os << ')'; } return; } } #endif // OPAL_SBinary_HH