/************************************************************************************* * Copyright (C) 2008 by Aleix Pol * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * * as published by the Free Software Foundation; either version 2 * * of the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * *************************************************************************************/ #include "mathmlpresentationexpressionwriter.h" #include "value.h" #include "operator.h" #include "container.h" #include #include "vector.h" #include "list.h" #include "variable.h" using namespace Analitza; namespace { QStringList convertElements(const Vector* c, MathMLPresentationExpressionWriter* w) { QStringList elems; Vector::const_iterator it=c->constBegin(), itEnd=c->constEnd(); for(; it!=itEnd; ++it) { elems += (*it)->visit(w); } return elems; } QStringList convertElements(const List* c, MathMLPresentationExpressionWriter* w) { QStringList elems; List::const_iterator it=c->constBegin(), itEnd=c->constEnd(); for(; it!=itEnd; ++it) { elems += (*it)->visit(w); } return elems; } QStringList convertElements(const Container* c, MathMLPresentationExpressionWriter* w) { QStringList elems; Container::const_iterator it=c->firstValue(), itEnd=c->m_params.constEnd(); for(; it!=itEnd; ++it) { elems += (*it)->visit(w); } return elems; } template static QString joinOp(const Container* c, MathMLPresentationExpressionWriter* w) { QString op=QString("%1").arg(*C); return convertElements(c, w).join(op); } template static QString infix(const Container* c, MathMLPresentationExpressionWriter* w) { QString exp=QString("%1%2%3").arg(*C) .arg(convertElements(c, w).join(QString())).arg(*D); return exp; } template static QString prefix(const Container* c, MathMLPresentationExpressionWriter* w) { return QString("%1").arg(*C)+convertElements(c, w).join(QString()); } template static QString postfix(const Container* c, MathMLPresentationExpressionWriter* w) { return convertElements(c, w).join(QString())+QString("%1").arg(*C); } QString minus(const Container* c, MathMLPresentationExpressionWriter* w) { QStringList e=convertElements(c, w); if(e.count()==1) return "-"+e[0]; else return e.join("-"); } QString power(const Container* c, MathMLPresentationExpressionWriter* w) { return ""+convertElements(c, w).join(QString())+""; } QString divide(const Container* c, MathMLPresentationExpressionWriter* w) { return ""+convertElements(c, w).join("")+""; } QString quotient(const Container* c, MathMLPresentationExpressionWriter* w) { return divide(c, w); } QString root(const Container* c, MathMLPresentationExpressionWriter* w) { return ""+convertElements(c, w).join(QString())+""; } QString diff(const Container* c, MathMLPresentationExpressionWriter* w) { QStringList bv=c->bvarStrings(); return ""+convertElements(c, w).join(QString())+"" ""+bv.join(",")+"'"; } QString exp(const Container* c, MathMLPresentationExpressionWriter* w) { return ""+convertElements(c, w).first()+""; } QString logE(const Container* c, MathMLPresentationExpressionWriter* w) { return "log"+convertElements(c, w).first(); } QString log10(const Container* c, MathMLPresentationExpressionWriter* w) { return "log10"+convertElements(c, w).first(); } QString iterative(Operator::OperatorType t, const Container* c, MathMLPresentationExpressionWriter* w) { QString op= t==Operator::sum ? "∑" : "&Prod;"; QString ul=""+c->ulimit()->toString()+""; QString dl=""+c->bvarStrings().join(", ")+"="+c->dlimit()->toString()+""; return ""+op+""+dl+ul+""+convertElements(c, w).join(QString())+""; } QString sum(const Container* c, MathMLPresentationExpressionWriter* w) { return iterative(Operator::sum, c, w); } QString product(const Container* c, MathMLPresentationExpressionWriter* w) { return iterative(Operator::product, c, w); } QString selector(const Container* c, MathMLPresentationExpressionWriter* w) { QStringList el=convertElements(c, w); return ""+el.last()+el.first()+""; } const char* plus="+", *times="*", *equal="="; const char* lt="<", *gt=">", *_not="¬"; const char* leq="≤", *geq="≥", *neq="≠", *approx="≈"; const char* implies="⇒", *_and="∧", *_or="∨", *_xor="⊕"; const char* mabs="|", *factorial="!"; const char *lfloor="⌊", *rfloor="⌋"; const char *lceil="⌈", *rceil="⌉"; const char *cardinal="#", *scalarproduct="X"; } MathMLPresentationExpressionWriter::operatorToString MathMLPresentationExpressionWriter::m_operatorToPresentation[] = { 0, joinOp<&plus>, joinOp<×>, minus, divide, quotient, power, root, postfix<&factorial>, joinOp<&_and>,joinOp<&_or>,joinOp<&_xor>, prefix<&_not>, 0,0,0,0,//gcd, lcm, rem, factorof, 0,0,//max, min, joinOp<<>, joinOp<>>, joinOp<&equal>, joinOp<&neq>, joinOp<&leq>, joinOp<&geq>, joinOp<&implies>, joinOp<&approx>, infix<&mabs, &mabs>, infix<&lfloor, &rfloor>, infix<&lceil, &rceil>, // approx, abs, floor, ceiling, 0,0,0,// sin, cos, tan, 0,0,0,// sec, csc, cot, 0,0,0,// sinh, cosh, tanh, 0,0,0,// sech, csch, coth, 0,0,0,// arcsin, arccos, arctan, 0,// arccot,// arccoth, 0,0,0,// arccosh, arccsc, arccsch, 0,0,0,0,// arcsec, arcsech, arcsinh, arctanh, exp, logE, log10,// exp, ln, log, // 0,0,0,0,// // conjugate, arg, real, imaginary, sum, product, diff,// sum, product, diff, prefix<&cardinal>, joinOp<&scalarproduct>, selector // function }; MathMLPresentationExpressionWriter::MathMLPresentationExpressionWriter(const Object* o) { m_result=o->visit(this); } QString MathMLPresentationExpressionWriter::accept(const Ci* var) { return ""+var->name()+""; } QString MathMLPresentationExpressionWriter::accept(const Operator* op) { return op->name(); } QString MathMLPresentationExpressionWriter::accept(const Cn* val) { if(val->isBoolean()) { if(val->isTrue()) return "true"; else return "false"; } else return QString("%1").arg(val->value(), 0, 'g', 12); } QString piecewise(const Container* c, MathMLPresentationExpressionWriter* w) { QString ret="" " { " ""; for(QList::const_iterator it=c->firstValue(); it!=c->m_params.constEnd(); ++it) { Q_ASSERT((*it)->isContainer()); Container *piece=static_cast(*it); if(piece->containerType()==Container::piece) { ret += "" "" +piece->m_params.first()->visit(w)+ "" "" "if " +piece->m_params.last()->visit(w)+ "" ""; } else { ret += "" "" +piece->m_params.first()->visit(w)+ "" "" "otherwise" "" ""; } } ret+=""; return ret; } QString lambda(const Container* c, MathMLPresentationExpressionWriter* w) { QString ret=""; foreach(const Ci* bvar, c->bvarCi()) ret+=bvar->visit(w); ret+="->"; ret+=c->m_params.last()->visit(w); ret+=""; return ret; } QString MathMLPresentationExpressionWriter::accept(const Container* c) { QString ret; // objectWalker(c); // qDebug() << "ttttttttttt" << m_operatorToPresentation << op.operatorType() // << m_operatorToPresentation[op.operatorType()] << op.name(); switch(c->containerType()) { case Container::math: ret=""+convertElements(c, this).join(QString())+""; break; case Container::apply: { Operator op=c->firstOperator(); if(m_operatorToPresentation[op.operatorType()]!=0) { operatorToString call=m_operatorToPresentation[op.operatorType()]; ret = call(c, this); } else if(op.operatorType()!=0) { QString bvars; if(!c->bvarStrings().isEmpty()) { bvars=c->bvarStrings().join(QString()); if(c->bvarStrings().size()>1) bvars=""+bvars+""; const Object *ul=c->ulimit(), *dl=c->dlimit(); if(ul || dl) { bvars += "="; if(dl) bvars += dl->visit(this); bvars += ".."; if(ul) bvars += ul->visit(this); } bvars=":"+bvars; } ret=""+op.name()+"" "" "" +convertElements(c, this).join(QString()) +bvars +""; } } break; case Container::piecewise: ret=piecewise(c, this); break; case Container::lambda: ret=lambda(c, this); break; case Container::otherwise: case Container::piece: case Container::bvar: case Container::uplimit: case Container::downlimit: case Container::declare: case Container::domainofapplication: case Container::none: qDebug() << "error" << c->tagName(); Q_ASSERT(false); break; } return ret; } QString MathMLPresentationExpressionWriter::accept(const Vector* var) { return "<"+convertElements(var, this).join(",")+">"; } QString MathMLPresentationExpressionWriter::accept(const List* var) { return "["+convertElements(var, this).join(",")+"]"; }