std::shared_ptr<ExpressionNode> ModuloNode::evaluate(Environment* e) { std::shared_ptr<ExpressionNode> left = a->evaluate(e); std::shared_ptr<ExpressionNode> right = b->evaluate(e); ConstantNode* cLeft = dynamic_cast<ConstantNode*>(&*left); ConstantNode* cRight = dynamic_cast<ConstantNode*>(&*right); if (cLeft != 0 && cRight != 0) { IntegerNode* iLeft = dynamic_cast<IntegerNode*>(cLeft); IntegerNode* iRight = dynamic_cast<IntegerNode*>(cRight); RealNode* rLeft = dynamic_cast<RealNode*>(cLeft); RealNode* rRight = dynamic_cast<RealNode*>(cRight); if (iLeft != 0 && iRight != 0) { return std::make_shared<IntegerNode> (iLeft->getValue() % iRight->getValue()); } throw ArithmeticException("modulo operator only defined for integer operands!"); } else { return std::make_shared<ModuloNode>(left, right); } }
std::shared_ptr<ExpressionNode> AssignmentNode::evaluate(Environment* e) { std::shared_ptr<ExpressionNode> newValue = b->evaluate(e); std::shared_ptr<VariableNode> var = std::dynamic_pointer_cast<VariableNode> (a); if (var.get()->equals(newValue.get())) return shared_from_this(); if (var) { const std::string varName = var->getString(); VariableSymbol* vs = e->getVariable(varName); if (vs) vs->setValue(newValue); else e->addSymbol(new VariableSymbol(var->getString(), newValue)); } else { throw ArithmeticException("left side of assignment must be a variable"); } return std::make_shared<AssignmentNode> (a, newValue); }
LongNumber LongNumber::operator /(LongNumber const& other) const { if (other == LongNumber("0")) throw ArithmeticException("Division by zero"); bool const needSign = container.hasSign() ^ other.container.hasSign(); if (container.isStatic() && other.container.isStatic()) { // both numbers are inside long long type, division always inside type long long val = container.getValue() / other.container.getValue(); val *= needSign ? -1 : 1; return LongNumber(NumberContainer(val)); } int const comp = compareAbs(container, other.container); if (comp < 0) return LongNumber(NumberContainer(0)); else if (comp == 0) { NumberContainer num(1); num.setSign(needSign); return LongNumber(num); } // we have to divide here int const thisLen = container.length(); int const otherLen = other.container.length(); // use upper bound of length int const numLen = thisLen - otherLen + 1; int pos = numLen; NumberContainer num(false, pos--); num.setSign(needSign); NumberContainer tmp(container);// create copy // find where first to place other int from = thisLen - 1; for (int k1 = 0; k1 < otherLen; k1++) { int k2 = otherLen - 1 - k1; char dig = tmp.getDigit(from - k1); char odig = other.getDigit(k2); if (dig < odig) { from--; break; } if (dig > odig) break; } for (; from >= otherLen - 1; from--) { bool found = false; char curDigit = 10; // pick digit in answer while (!found && curDigit > 0) { curDigit--; found = true; int borrowed = 0; if (from < thisLen - 1) borrowed = tmp.getDigit(from + 1); for (int k2 = otherLen - 1; k2 >= 0 && found; k2--) { int k1 = otherLen - 1 - k2; char dig = tmp.getDigit(from - k1); char subt = curDigit * other.getDigit(k2); borrowed -= subt / 10; if (borrowed < 0 || dig + borrowed * 10 - (subt % 10) < 0) found = false; borrowed = dig + borrowed * 10 - (subt % 10); if (borrowed > 99) // subtracting from our dividend at current position // we got mass left in higer digits, than where we are currently // so we can subtract break; } } // set digit in answer num.setDigit(pos--, curDigit); if (curDigit > 0) { // subtract from dividend char borrowed = 0; char transfered = 0; for (int k2 = 0; k2 < otherLen && found; k2++) { int k1 = otherLen - 1 - k2; char dig = tmp.getDigit(from - k1) + borrowed; char subt = curDigit * other.getDigit(k2) + transfered; transfered = subt / 10; subt %= 10; if (dig < 0) tmp.setDigit(from - k1, 9 - subt); else if (dig >= subt) { borrowed = 0; tmp.setDigit(from - k1, dig - subt); } else { borrowed = -1; tmp.setDigit(from - k1, 10 + dig - subt); } } } } if (pos < 0) return LongNumber(num); // need to resize (remove first zero digit) NumberContainer resized(false, numLen - pos - 1); resized.setSign(needSign); for (int i = pos + 1; i < numLen; i++) resized.setDigit(i - pos - 1, num.getDigit(i)); return LongNumber(resized); }
Duration *Duration::negated() { if (getMillis() == LONG_MIN) { throw ArithmeticException("Negation of this duration would overflow"); } return new Duration(-getMillis()); }
const Vector& Vector::operator+=(const Vector& v) { if (dim != v.dim) throw ArithmeticException(); for (int i = 0; i < dim; i++) _rep[i] += v._rep[i]; return *this; }