void KstEquation::save(QTextStream &ts, const QString& indent) { QString l2 = indent + " "; ts << indent << "<equationobject>" << endl; ts << l2 << "<tag>" << QStyleSheet::escape(tag().tagString()) << "</tag>" << endl; // Reparse the equation, then write it back out in text so that we can update // any vectors or scalars that had name changes, but we don't get affected by // the optimizer if (!_equation.isEmpty()) { QMutexLocker ml(&Equation::mutex()); yy_scan_string(_equation.latin1()); ParsedEquation = 0L; int rc = yyparse(); Equation::Node *en = static_cast<Equation::Node*>(ParsedEquation); if (rc == 0 && en) { if (!en->takeVectors(VectorsUsed)) { KstDebug::self()->log(i18n("Equation [%1] failed to find its vectors when saving. Resulting Kst file may have issues.").arg(_equation), KstDebug::Warning); } QString etext = en->text(); ts << l2 << "<equation>" << QStyleSheet::escape(etext) << "</equation>" << endl; } delete en; ParsedEquation = 0L; } ts << l2 << "<xvector>" << QStyleSheet::escape((*_xInVector)->tag().tagString()) << "</xvector>" << endl; if (_doInterp) { ts << l2 << "<interpolate/>" << endl; } ts << indent << "</equationobject>" << endl; }
void testText(const char *equation, const char *expect) { bool failure = false; QString txt; yy_scan_string(equation); int rc = yyparse(); if (rc == 0) { vectorsUsed.clear(); Equation::Node *eq = static_cast<Equation::Node*>(ParsedEquation); assert(eq); ParsedEquation = 0L; //eq->collectVectors(vectorsUsed); txt = eq->text(); failure = txt != expect; delete eq; } else { // Parse error delete (Equation::Node*)ParsedEquation; ParsedEquation = 0L; failure = true; } if (failure) { if (!Equation::errorStack.isEmpty()) { printf("Failures on [%s] -------------------------\n", equation); for (QStringList::ConstIterator i = Equation::errorStack.constBegin(); i != Equation::errorStack.constEnd(); ++i) { printf("%s\n", (*i).latin1()); } printf("------------------------------------------\n"); } else { printf("Got [%s], expected [%s]\n", txt.latin1(), expect); } --rc; } }
bool doTest(const char *equation, double x, double result, const double tol = 0.00000000001) { yy_scan_string(equation); int rc = yyparse(); if (rc == 0) { vectorsUsed.clear(); Equation::Node *eq = static_cast<Equation::Node*>(ParsedEquation); assert(eq); ParsedEquation = 0L; Equation::Context ctx; ctx.sampleCount = 2; ctx.noPoint = NOPOINT; ctx.x = x; ctx.xVector = xVector; if (xVector) { ctx.sampleCount = xVector->length(); } Equation::FoldVisitor vis(&ctx, &eq); if (eq->isConst() && !dynamic_cast<Equation::Number*>(eq)) { if (!optimizerFailed) { optimizerFailed = true; ::rc--; printf("Optimizer bug: found an unoptimized const equation. Optimizing for coverage purposes.\n"); } double v = eq->value(&ctx); delete eq; eq = new Equation::Number(v); } KstScalarMap scm; KstStringMap stm; eq->collectObjects(vectorsUsed, scm, stm); // // do not use -1 in the call to eq->update( ... ) // as this will simply return without updating the plugin, // unless an underlying data object was updated... // eq->update(0, &ctx); double v = eq->value(&ctx); delete eq; if (fabs(v - result) < tol || (result != result && v != v) || (result == INF && v == INF) || (result == -INF && v == -INF)) { return true; } else { printf("Result: %.16f\n", v); return false; } } else { // Parse error printf("Failures on [%s] -------------------------\n", equation); for (QStringList::ConstIterator i = Equation::errorStack.constBegin(); i != Equation::errorStack.constEnd(); ++i) { printf("%s\n", (*i).latin1()); } printf("------------------------------------------\n"); delete (Equation::Node*)ParsedEquation; ParsedEquation = 0L; return false; } }
double Equation::interpret(const char *txt, bool *ok) { if (!txt || !*txt) { if (ok) { *ok = false; } return 0.0; } mutex().lock(); yy_scan_string(txt); int rc = yyparse(); if (rc == 0) { Equation::Node *eq = static_cast<Equation::Node*>(ParsedEquation); ParsedEquation = 0L; mutex().unlock(); Equation::Context ctx; ctx.sampleCount = 2; ctx.noPoint = KST::NOPOINT; ctx.x = 0.0; ctx.xVector = 0L; Equation::FoldVisitor vis(&ctx, &eq); double v = eq->value(&ctx); delete eq; if (ok) { *ok = true; } return v; } else { ParsedEquation = 0L; mutex().unlock(); if (ok) { *ok = false; } return 0.0; } }