NumericLiteral NumericLiteral::operator/(const NumericLiteral &l) const { if (denominator == 0.0 || l.denominator == 0.0) throw UTComputerException("Error NumericLiteral::operator/(NumericLiteral &l) : one of the denominators is 0."); if (l.numerator == 0.0) throw UTComputerException("Error NumericLiteral::operator/(NumericLiteral &l) : l is 0 and division by zero is impossible."); /* if one of the arguments is real, we must return a * real literal with the result of the operation in the numerator attribute * and set the denominator to 1 */ if (isReal() || l.isReal()) { NumericLiteral tmp = NumericLiteral( numerator*l.denominator, denominator * l.numerator ); tmp.numerator = tmp.numerator/tmp.denominator; tmp.denominator = 1; return tmp; } /* In general, we return a new numeric literal with the normal division operation */ return NumericLiteral( numerator*l.denominator, denominator * l.numerator ); }
/*** OPERATEUR OR ***/ Entier& Rationnel::operatorOr(const Litteral& l) const{ try { return l.operatorOr(*this); } catch (UTComputerException e) { throw UTComputerException(e.what()); } }
/*** MODULO ***/ Litteral& Rationnel::operator%(const Litteral& l) const{ try { return l%*this; } catch (UTComputerException e) { throw UTComputerException(e.what()); } }
Litteral& Rationnel::operatorDivEntiere(const Rationnel& l) const{ /* double tmp = l.getValue() / getValue(); //on prend la partie entière. floor retourne un double. conversion auto entre double et int. int res = floor(tmp); return LitteralManager::getInstance().addEntier(res);*/ throw UTComputerException("Il est impossible d'appliquer DIV entre deux rationnels."); }
/* Tests done before in superclass : * - test that pointer to stack is not null * - test that stack contains enough Literal* (st.size() >= operator arity) * - test that every Literal* unstacked isn't null * * OperatorSuperior applies to * - two ComplexLiterals with no imaginary parts */ shared_ptr<Literal> OperatorSuperior::executeSpecificOperator() { try { Literal* a = arguments[0].get(); Literal* b = arguments[1].get(); ComplexLiteral* comp_a = dynamic_cast<ComplexLiteral*>(a); ComplexLiteral* comp_b = dynamic_cast<ComplexLiteral*>(b); // if the two literals are instance of ComplexLiteral if (comp_a != nullptr && comp_b != nullptr) { if (*comp_a > *comp_b) // then return a ComplexLiteral set to "integer" with a value of 1 return shared_ptr<ComplexLiteral>(new ComplexLiteral(NumericLiteral(1.0))); else // then return a ComplexLiteral set to "integer" with a value of 0 return shared_ptr<ComplexLiteral>(new ComplexLiteral(NumericLiteral(0.0))); } /* Note that the ComplexLiteral class throw exception if imaginary parts of both * arguments are different from 0*/ // Here we didn't return anything or throw any exception, so both arguments have invalid type. throw UTComputerException("Error in OperatorSuperior::executeSpecificOperator : invalid literal types") ; } catch (UTComputerException e) { UTComputerException e1(e.getMessage()); e1.insertBefore(" --> "); e1.insertBefore(arguments[1]->toString()); e1.insertBefore(" and "); e1.insertBefore(arguments[0]->toString()); e1.insertBefore("Error in applying OperatorSuperior on "); throw e1; } }
/* * Address of stack must not be changed, but "st" do not point to a const stack : we use a constant pointer * and not a pointer to constant */ void OperatorLASTOP::execute(StackUTComputer * const st) { /* * Call to StackOperator::execute(st) : * The super class function test that the current operator IS NOT "OperatorLASTOP" before setting * StackUTComputer.lastOperator attribute to the current operator. * Otherwise, we have an infinite loop : * - setting last operator to OperatorLASTOP * - calling this operator with st->getLastOperator()->execute(st) * - setting last operator to OperatorLASTOP * - ... * */ StackOperator::execute(st); // check usual possible errors try { if (st->getLastOperator() != nullptr) st->getLastOperator()->execute(st); else throw UTComputerException("Error OperatorLASTOP::execute : StackUTComputer.lastOperator is null."); } catch (UTComputerException e) { UTComputerException e1(e.getMessage()); e1.insertBefore(" --> "); e1.insertBefore("Error in applying OperatorLASTOP "); throw e1; } }
void NumericLiteral::simplification() { if (!isRational()) throw UTComputerException("Error NumericLiteral::simplification : simplifiaction on non retional literal is impossible."); // if numerator is 0, then set denominator to 1 if (numerator == 0) { denominator = 1; return; } // denominator can't be 0 if (denominator == 0) { throw UTComputerException("Error NumericLiteral::simplification : denominator can't be 0."); } /* Use of Euclide algorithm to find the greatest common divisor */ double a=numerator, b=denominator; // we only works with positive values if (a<0) a=-a; if (b<0) b=-b; while(a != b) { if (a>b) a = a - b; else b = b - a; } // division of numerator and denominator by a, the greatest common divisor numerator /= a; denominator /= a; // if denominator is negative, pass the negation to the numerator if (denominator < 0) { denominator = -denominator; numerator = -numerator; } }
// =============================================================================================================== // ====================== Override Methods ========================== // =============================================================================================================== string NumericLiteral::toString() const { ostringstream sting_stream; if (isInteger()) { sting_stream << (int) numerator; return sting_stream.str(); } if (isRational()) { sting_stream << numerator << "/" << denominator; return sting_stream.str(); } if (isReal()) { sting_stream << numerator; return sting_stream.str(); } throw UTComputerException("Error NumericLiteral::toString() : literal isn't integer nor rational nor real"); }
Entier& Rationnel::operator>=(const Complexe& l) const{ throw UTComputerException("Impossible de comparer un rationnel et un complexe."); }
Litteral& Rationnel::operator$(const Complexe& l) const{ throw UTComputerException("Impossible de creer un nombre complexe a partir d'un autre nombre complexe."); }
Litteral& Rationnel::operator%(const Complexe& l) const{ throw UTComputerException("Il est impossible d'appliquer MOD entre un complexe et un rationnel."); }
Litteral& Rationnel::operator%(const Rationnel& l) const{ throw UTComputerException("Il est impossible d'appliquer MOD entre deux rationnels."); }
/* Tests done before in superclass : * - test that pointer to stack is not null * - test that stack contains enough Literal* (st.size() >= operator arity) * - test that every Literal* unstacked isn't null * * OperatorMultiplication applies to * - two ComplexLiterals * - two ExpressionLiteral * - an ExpressionLiteral and a ComplexLiteral */ shared_ptr<Literal> OperatorMultiplication::executeSpecificOperator() { try { Literal* a = arguments[0].get(); Literal* b = arguments[1].get(); ComplexLiteral* comp_a = dynamic_cast<ComplexLiteral*>(a); ComplexLiteral* comp_b = dynamic_cast<ComplexLiteral*>(b); ExpressionLiteral* exp_a = dynamic_cast<ExpressionLiteral*>(a); ExpressionLiteral* exp_b = dynamic_cast<ExpressionLiteral*>(b); // if the two literals are instance of ComplexLiteral if (comp_a != nullptr && comp_b != nullptr) return *comp_a * *comp_b; // ComplexLiteral::operator*(ComplexLiteral &l) const // if the two literals are instance of ExpressionLiteral if (exp_a != nullptr && exp_b != nullptr) return *exp_a * *exp_b; // ExpressionLiteral::operator*(ExpressionLiteral &l) const /* If one of the two arguments isn't instance of ComplexLiteral then it must be instance of * ExpressionLiteral. Otherwise, it's an illegal argument.*/ // if the first element is instance of ComplexLiteral but not the second if (comp_a != nullptr) { /* then b is not instance of ComplexLiteral (because of the first if statement) and can only be instance of * ExpressionLiteral. If not, then b is an illegal argument */ if (exp_b != nullptr) { /* Multiplication between Complex and Expression is in fact multiplication between two Expression : * We have to create a temporary Expression with the Complex::toString() function * and then apply multiplication between the two Expression */ ExpressionLiteral tmp(comp_a->toString()); return tmp * *exp_b; // ExpressionLiteral::operator*(ExpressionLiteral &l) const } else { throw UTComputerException("Error in OperatorMultiplication::executeSpecificOperator : second argument has invalid type."); } } // if the second element is instance of ComplexLiteral but not the first if (comp_b != nullptr) { /* then a is not instance of ComplexLiteral (because of the first if statement) and can only be instance of * ExpressionLiteral. If not, then b is an illegal argument */ if (exp_a != nullptr) { /* Multiplication between Complex and Expression is in fact multiplication between two Expression : * We have to create a temporary Expression with the Complex::toString() function * and then apply multiplication between the two Expression */ ExpressionLiteral tmp(comp_b->toString()); return *exp_a * tmp; // ExpressionLiteral::operator*(ComplexLiteral &l) const } else { throw UTComputerException("Error in OperatorMultiplication::executeSpecificOperator : first argument is of invalid type."); } } // Here we didn't return anything or throw any exception, so both arguments have invalid type. throw UTComputerException("Error in OperatorMultiplication::executeSpecificOperator : invalid literal types for both arguments"); } catch (UTComputerException e) { UTComputerException e1(e.getMessage()); e1.insertBefore(" --> "); e1.insertBefore(arguments[1]->toString()); e1.insertBefore(" and "); e1.insertBefore(arguments[0]->toString()); e1.insertBefore("Error in applying OperatorMultiplication on "); throw e1; } }