Beispiel #1
0
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);
    }
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
Duration *Duration::negated() {
    if (getMillis() == LONG_MIN) {
        throw ArithmeticException("Negation of this duration would overflow");
    }
    return new Duration(-getMillis());
}
Beispiel #5
0
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;
}