Beispiel #1
0
Abakus::Number BuiltinFunction::value() const
{
    if(function() && operand()) {
        Abakus::Number fnValue = operand()->value();
        return evaluateFunction(function(), fnValue);
    }

    return Abakus::Number(0);
}
Beispiel #2
0
void EXParser::priorityFunctionLoop(std::string &_expression)
{
	size_t pos;
	for(EXFunctionSet::iterator fiter = functions.begin(); fiter!=functions.end(); ++fiter){
		while((pos=_expression.find(fiter->first, 0))!=std::string::npos){
				evaluateFunction(_expression, pos+fiter->first.length(), fiter);
		}
	}
}
Beispiel #3
0
/**
  * Parse a subexpression and replace it with its result.
  */
void Calculator::parseSubexpression(QStringList & expressionParts)
{
  int operatorLine = 0;
  int prioLine = 0;
  int priority = 0;
  int parenthesisPos = 0;
  int functionLine = 0;
  for(parenthesisPos = 0; parenthesisPos < expressionParts.size(); parenthesisPos++)
      if((expressionParts[parenthesisPos]== "(") || (expressionParts[parenthesisPos]=="-("))
          parseParenthesis(expressionParts, parenthesisPos);
      else if(expressionParts[parenthesisPos]== ")"){
          throw ExExpressionError(tr("Parenthesis syntax error."));
      }
  if(expressionParts.size() < 2) //evaluation is complete, we had a (Expression)
      return;
  //now we have all function arguments directly behind the function name
  if(!(isNumber(expressionParts.last()) || isVariable(expressionParts.last())))
          throw ExExpressionError(tr("Last term of expression must be a number."));
  //evaluate function values from right to left
  for(functionLine = expressionParts.size() - 1; functionLine > -1; functionLine--)
      if(isFunction(expressionParts[functionLine]))
          evaluateFunction(expressionParts, functionLine);
  while(operatorLine < expressionParts.size() &&! isOperator(expressionParts[operatorLine]))
        operatorLine ++;
  if(operatorLine >= expressionParts.size() - 1) //no operator, invalid expression or nothing to be done
      throw ExExpressionError(tr("Missing operator."));

  //we found an operator, now search for the first operator with highest priority
  prioLine = operatorLine;
  priority = operatorPriority(expressionParts[operatorLine]);
  while( prioLine < expressionParts.size() - 1 )
  {
    prioLine ++;
    if(operatorPriority(expressionParts[prioLine]) > priority)
    {
        operatorLine = prioLine;
        priority = operatorPriority(expressionParts[prioLine]);
    }
  }
  //Now lets calculate
  if(operatorLine < 1) //we have a leading operator
  {
   if(expressionParts[operatorLine] == "-" | expressionParts[operatorLine] == "+") //we have a sign
   {
       if(expressionParts[operatorLine] == "-")
         expressionParts[0] = expressionParts[0] + expressionParts[1]; //make a negative number
       expressionParts.removeAt(1); //and delete the sign from list
       return;
   }
   else throw ExExpressionError(tr("No operator allowed in first position."));
  }
  calculateSubExpression(expressionParts, operatorLine);
}
void SDCFsiSolver::implicitSolve(
    bool corrector,
    const int k,
    const int kold,
    const scalar t,
    const scalar dt,
    const fsi::vector & qold,
    const fsi::vector & rhs,
    fsi::vector & f,
    fsi::vector & result
    )
{
    Eigen::Map<const fsi::vector> qoldFluid( qold.data(), dofFluid );
    Eigen::Map<const fsi::vector> qoldSolid( qold.data() + dofFluid, dofSolid );

    Eigen::Map<const fsi::vector> rhsFluid( rhs.data(), dofFluid );
    Eigen::Map<const fsi::vector> rhsSolid( rhs.data() + dofFluid, dofSolid );

    fluid->prepareImplicitSolve( corrector, k, kold, t, dt, qoldFluid, rhsFluid );
    solid->prepareImplicitSolve( corrector, k, kold, t, dt, qoldSolid, rhsSolid );

    // Perform FSI iterations to solve the coupled problem

    postProcessing->fsi->newMeasurementSeries();

    // Initial solution
    fsi::vector x0;

    if ( corrector )
        x0 = xStages.at( k + 1 );
    else
        x0 = xStages.at( k );

    postProcessing->initStage( k );
    postProcessing->performPostProcessing( x0, postProcessing->fsi->x );
    postProcessing->finalizeStage();

    getSolution( result, f );
    evaluateFunction( k, result, t, f );

    xStages.at( k + 1 ) = postProcessing->fsi->x;

    fluid->finalizeImplicitSolve( k );
    solid->finalizeImplicitSolve( k );
}
Beispiel #5
0
Abakus::Number RPNParser::rpnParseString(const QString &text)
{
    QStringList tokens = text.split(QRegExp("\\s"));
    Counter counter; // Will update stack count when we leave proc.
    (void) counter;  // Avoid warnings about it being unused.

    // Used in the case statements below
    Operand l, r;
    FunctionModel *manager = FunctionModel::instance();
    Function *fn = 0;

    m_error = false;
    m_errorStr = QString::null;

    for(QStringList::ConstIterator it = tokens.begin(); it != tokens.end(); ++it) {
        switch(tokenize(*it))
        {
        case Number:
            m_stack.push(Abakus::Number((*it).toLatin1()));
        break;

        case Pop:
            if(m_stack.isEmpty()) {
                m_error = true;
                m_errorStr = i18n("Cannot pop from an empty stack.");
                return Abakus::Number::nan();
            }

            m_stack.pop();
        break;

        case Clear:
            m_stack.clear();
        break;

        case Func:
            if(m_stack.count() < 1) {
                m_error = true;
                m_errorStr = i18n("Insufficient operands for function %1", *it);
                return Abakus::Number::nan();
            }

            fn = manager->function(*it);

            l = m_stack.pop();
            m_stack.push(evaluateFunction(fn, l));
        break;

        case Ident:
            m_stack.push(*it);
        break;

        case Set:
        case Remove:
            m_error = true;
            m_errorStr = i18n("The set and remove commands can only be used in normal mode.");
            return Abakus::Number::nan();
        break;

        case Power:
            if(m_stack.count() < 2) {
                m_error = true;
                m_errorStr = i18n("Insufficient operands for exponentiation operator.");
                return Abakus::Number::nan();
            }

            r = m_stack.pop();
            l = m_stack.pop();
            m_stack.push(l.value().pow(r));
        break;

        case Unknown:
            m_error = true;
            m_errorStr = i18n("Unknown token %1", *it);
            return Abakus::Number::nan();
        break;

        case '=':
            r = m_stack.pop();
            l = m_stack.pop();
            NumeralModel::instance()->setValue(l.text(), r);

            m_stack.push(l);
        break;

        case '+':
            if(m_stack.count() < 2) {
                m_error = true;
                m_errorStr = i18n("Insufficient operands for addition operator.");
                return Abakus::Number::nan();
            }

            r = m_stack.pop();
            l = m_stack.pop();
            m_stack.push(l.value() + r.value());
        break;

        case '-':
            if(m_stack.count() < 2) {
                m_error = true;
                m_errorStr = i18n("Insufficient operands for subtraction operator.");
                return Abakus::Number::nan();
            }

            r = m_stack.pop();
            l = m_stack.pop();
            m_stack.push(l.value() - r.value());
        break;

        case '*':
            if(m_stack.count() < 2) {
                m_error = true;
                m_errorStr = i18n("Insufficient operands for multiplication operator.");
                return Abakus::Number::nan();
            }

            r = m_stack.pop();
            l = m_stack.pop();
            m_stack.push(l.value() * r.value());
        break;

        case '/':
            if(m_stack.count() < 2) {
                m_error = true;
                m_errorStr = i18n("Insufficient operands for division operator.");
                return Abakus::Number::nan();
            }

            r = m_stack.pop();
            l = m_stack.pop();
            m_stack.push(l.value() / r.value());
        break;

        default:
            // Impossible case happened.
            kError() << "Impossible case happened in " << endl;
            m_error = true;
            m_errorStr = "Bug found in program, please report.";
            return Abakus::Number::nan();
        }
    }

    // TODO: Should this be an error?
    if(m_stack.isEmpty())
        return Abakus::Number::nan();

    return m_stack.top();
}
Beispiel #6
0
qreal KoEnhancedPathFormula::evaluate()
{
    // shortcut
    if( m_error != ErrorNone )
        return 0.0;

    // lazy evaluation
    if( ! m_compiled )
    {
        TokenList tokens = scan( m_text );
        if( m_error != ErrorNone )
            debugTokens( tokens );
        if( ! compile( tokens ) )
        {
            debugOpcodes();
            m_error = ErrorCompile;
            return false;
        }
        m_compiled = true;
    }

    QStack<QVariant> stack;
    int index = 0;

    if( ! m_valid )
    {
        m_error = ErrorParse;
        return 0.0;
    }

    for( int pc = 0; pc < m_codes.count(); pc++ )
    {
        QVariant ret;   // for the function caller
        Opcode& opcode = m_codes[pc];
        index = opcode.index;
        switch( opcode.type )
        {
            // no operation
            case Opcode::Nop:
            break;

            // load a constant, push to stack
            case Opcode::Load:
                stack.push( m_constants[index] );
            break;

            // unary operation
            case Opcode::Neg:
            {
                bool success = false;
                qreal value = stack.pop().toDouble( &success );
                if( success ) // do nothing if we got an error
                    value *= -1.0;
                stack.push( QVariant( value ) );
            }
            break;

            // binary operation: take two values from stack, do the operation,
            // push the result to stack
            case Opcode::Add:
            {
                qreal val2 = stack.pop().toDouble();
                qreal val1 = stack.pop().toDouble();
                stack.push( QVariant( val1 + val2 ) );
            }
            break;

            case Opcode::Sub:
            {
                qreal val2 = stack.pop().toDouble();
                qreal val1 = stack.pop().toDouble();
                stack.push( QVariant( val1 - val2 ) );
            }
            break;

            case Opcode::Mul:
            {
                qreal val2 = stack.pop().toDouble();
                qreal val1 = stack.pop().toDouble();
                stack.push( QVariant( val1 * val2 ) );
            }
            break;

            case Opcode::Div:
            {
                qreal val2 = stack.pop().toDouble();
                qreal val1 = stack.pop().toDouble();
                stack.push( QVariant( val1 / val2 ) );
            }
            break;

        case Opcode::Ref:
        {
            QString reference = m_constants[index].toString();
            // push function name if it is a function, else push evaluated reference
            Function function = matchFunction( reference );
            if( FunctionUnknown == function )
                stack.push( QVariant( m_parent->evaluateReference( reference ) ) );
            else
                stack.push( function );
        }
        break;

        // calling function
        case Opcode::Function:
        {
            // sanity check, this should not happen unless opcode is wrong
            // (i.e. there's a bug in the compile() function)
            if( stack.count() < index )
            {
                kWarning() << "not enough arguments for function " << m_text;
                m_error = ErrorValue; // not enough arguments
                return 0.0;
            }

            /// prepare function arguments
            QList<qreal> args;
            for( ; index; index-- )
            {
                qreal value = stack.pop().toDouble();
                args.push_front( value );
            }

            // function identifier as int value
            int function = stack.pop().toInt();
            stack.push( QVariant( evaluateFunction( (Function)function, args ) ) );
        }
        break;

        default:
        break;
        }
    }

    // more than one value in stack ? unsuccessful execution...
    if( stack.count() != 1 )
    {
        m_error = ErrorValue;
        return 0.0;
    }

    return stack.pop().toDouble();
}
Beispiel #7
0
Abakus::Number BuiltinFunction::derivative() const
{
    Abakus::Number du = operand()->derivative();
    Abakus::Number value = operand()->value();
    Abakus::Number one(1), zero(0);

    if(du == zero)
        return du;

    // In case these functions get added later, these derivatives may
    // be useful:
    // d/dx(asinh u) = (du/dx * 1 / sqrt(x^2 + 1))
    // d/dx(acosh u) = (du/dx * 1 / sqrt(x^2 - 1))
    // d/dx(atanh u) = (du/dx * 1 / (1 - x^2))

    // This is very unfortunate duplication.
    if(name() == "sin")
        return value.cos() * du;
    else if(name() == "cos")
        return -value.sin() * du;
    else if(name() == "tan") {
        Abakus::Number cosResult;

        cosResult = value.cos();
        cosResult = cosResult * cosResult;
        return one / cosResult;
    }
    else if(name() == "asinh") {
        value = value * value + one;
        return du / value.sqrt();
    }
    else if(name() == "acosh") {
        value = value * value - one;
        return du / value.sqrt();
    }
    else if(name() == "atanh") {
        value = one - value * value;
        return du / value;
    }
    else if(name() == "sinh") {
        return du * value.cosh();
    }
    else if(name() == "cosh") {
        return du * value.sinh(); // Yes the sign is correct.
    }
    else if(name() == "tanh") {
        Abakus::Number tanh = value.tanh();

        return du * (one - tanh * tanh);
    }
    else if(name() == "atan") {
        return one * du / (one + value * value);
    }
    else if(name() == "acos") {
        // Same as asin but with inverted sign.
        return -(one / (value * value - one).sqrt() * du);
    }
    else if(name() == "asin") {
        return one / (value * value - one).sqrt() * du;
    }
    else if(name() == "ln") {
        return du / value;
    }
    else if(name() == "exp") {
        return du * value.exp();
    }
    else if(name() == "log") {
        return du / value / Abakus::Number(10).ln();
    }
    else if(name() == "sqrt") {
        Abakus::Number half("0.5");
        return half * value.pow(-half) * du;
    }
    else if(name() == "abs") {
        return (value / value.abs()) * du;
    }

    // Approximate it.

    Abakus::Number epsilon("1e-15");
    Abakus::Number fxh = evaluateFunction(function(), value + epsilon);
    Abakus::Number fx = evaluateFunction(function(), value);
    return (fxh - fx) / epsilon;
}