package org.matheclipse.core.form.mathml.reflection;
import org.matheclipse.core.convert.AST2Expr;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.expression.NumberUtil;
import org.matheclipse.core.form.mathml.AbstractOperator;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.IInteger;
import org.matheclipse.core.interfaces.IRational;
import org.matheclipse.core.interfaces.ISignedNumber;
import org.matheclipse.parser.client.operator.ASTNodeFactory;
public class Times extends AbstractOperator {
public final static int NO_SPECIAL_CALL = 0;
public final static int PLUS_CALL = 1;
public Times() {
super(ASTNodeFactory.MMA_STYLE_FACTORY.get("Times").getPrecedence(), "mrow", "");
}
/**
* Converts a given function into the corresponding MathML output
*
* @param buf
* StringBuffer for MathML output
* @param f
* The math function which should be converted to MathML
*/
@Override
public boolean convert(final StringBuffer buf, final IAST f, final int precedence) {
return convert(buf, f, precedence, NO_SPECIAL_CALL);
}
/**
* Converts a given function into the corresponding MathML output
*
* @param buf
* StringBuffer for MathML output
* @param f
* The math function which should be converted to MathML
*/
public boolean convert(final StringBuffer buf, final IAST f, final int precedence, final int caller) {
final IAST numerator = F.Times();
final IAST denominator = F.Times();
boolean flag = false;
IExpr expr;
for (int i = 1; i < f.size(); i++) {
expr = f.get(i);
if (expr instanceof IRational) {
IInteger num = ((IRational) expr).getNumerator();
IInteger den = ((IRational) expr).getDenominator();
if (!NumberUtil.isOne(num)) {
numerator.add(num);
}
if (!NumberUtil.isOne(den)) {
denominator.add(den);
}
flag = true;
continue;
}
if ((f.get(i) instanceof IAST) && ((IAST) f.get(i)).head().toString().equals(AST2Expr.POWER_STRING)) {
// filter negative Powers:
final IAST p = (IAST) f.get(i);
if ((p.size() == 3) && (p.get(2) instanceof ISignedNumber) && ((ISignedNumber) p.get(2)).isNegative()) {
if (NumberUtil.isMinusOne(p.get(2))) {
// x_^(-1) ?
denominator.add(p.get(1));
flag = true;
continue;
}
denominator.add(F.Power( p.get(1), F.Times( F.integer(-1), p.get(2))));
flag = true;
continue;
}
}
if (!NumberUtil.isOne(f.get(i))) {
numerator.add(f.get(i));
}
}
// do the output:
if (denominator.size() > 1 && flag) {
if (caller == PLUS_CALL) {
fFactory.tag(buf, "mo", "+");
}
fFactory.tagStart(buf, "mfrac");
// insert numerator in buffer:
if (numerator.size() > 1) {
if (numerator.size() == 2) {
fFactory.convert(buf, numerator.get(1), 0);
} else {
fFactory.convert(buf, numerator, fPrecedence);
}
} else {
fFactory.tag(buf, "mn", "1");
}
if (denominator.size() == 2) {
fFactory.convert(buf, denominator.get(1), 0);
} else {
fFactory.convert(buf, denominator, fPrecedence);
}
fFactory.tagEnd(buf, "mfrac");
} else {
if (numerator.size() <= 2) {
convertMultiply(buf, f, precedence, caller);
} else {
convertMultiply(buf, numerator, precedence, caller);
}
}
return true;
}
private boolean convertMultiply(final StringBuffer buf, final IAST f, final int precedence, final int caller) {
IExpr expr;
if (f.size() > 1) {
expr = f.get(1);
if (NumberUtil.isMinusOne(expr)) {
if (f.size() == 2) {
fFactory.tagStart(buf, fFirstTag);
precedenceOpen(buf, precedence);
fFactory.convert(buf, expr, fPrecedence);
} else {
if (caller == PLUS_CALL) {
fFactory.tag(buf, "mo", "-");
if (f.size() == 3) {
fFactory.convert(buf, f.get(2), fPrecedence);
return true;
}
fFactory.tagStart(buf, fFirstTag);
} else {
fFactory.tagStart(buf, fFirstTag);
precedenceOpen(buf, precedence);
fFactory.tag(buf, "mo", "-");
}
}
} else {
if (caller == PLUS_CALL) {
if ((expr instanceof ISignedNumber) && (((ISignedNumber) expr).isNegative())) {
fFactory.tag(buf, "mo", "-");
fFactory.tagStart(buf, fFirstTag);
expr = ((ISignedNumber) expr).negate();
} else {
fFactory.tag(buf, "mo", "+");
fFactory.tagStart(buf, fFirstTag);
}
} else {
fFactory.tagStart(buf, fFirstTag);
precedenceOpen(buf, precedence);
}
fFactory.convert(buf, expr, fPrecedence);
if (fOperator.compareTo("") != 0) {
fFactory.tag(buf, "mo", fOperator);
}
}
}
for (int i = 2; i < f.size(); i++) {
fFactory.convert(buf, f.get(i), fPrecedence);
if ((i < f.size() - 1) && (fOperator.compareTo("") != 0)) {
fFactory.tag(buf, "mo", fOperator);
}
}
precedenceClose(buf, precedence);
fFactory.tagEnd(buf, fFirstTag);
return true;
}
}
Ads help maintain this website.