mirror of
https://github.com/josdejong/mathjs.git
synced 2026-01-18 14:59:29 +00:00
Merge pull request #294 from FSMaxB/totex
Update toTex to better handle parenthesis
This commit is contained in:
commit
ed47c7fa35
@ -92,12 +92,24 @@ AssignmentNode.prototype.toString = function() {
|
||||
* @return {String}
|
||||
*/
|
||||
AssignmentNode.prototype.toTex = function() {
|
||||
var precedence = operators.getPrecedence(this);
|
||||
var exprPrecedence = operators.getPrecedence(this.expr);
|
||||
|
||||
var expr = this.expr.toTex();
|
||||
if ((exprPrecedence !== null) && (exprPrecedence <= precedence)) {
|
||||
//adds visible round brackets
|
||||
expr = latex.addBraces(expr, true);
|
||||
}
|
||||
else {
|
||||
//adds (invisible) curly braces
|
||||
expr = latex.addBraces(expr, false);
|
||||
}
|
||||
|
||||
var brace;
|
||||
if (this.expr instanceof ArrayNode) {
|
||||
brace = ['\\mathbf{', '}'];
|
||||
}
|
||||
return latex.addBraces(latex.toSymbol(this.name), brace) + '=' +
|
||||
latex.addBraces(this.expr.toTex());
|
||||
return latex.addBraces(latex.toSymbol(this.name), brace) + '=' + expr;
|
||||
};
|
||||
|
||||
module.exports = AssignmentNode;
|
||||
module.exports = AssignmentNode;
|
||||
|
||||
@ -113,9 +113,22 @@ FunctionAssignmentNode.prototype.toString = function() {
|
||||
* @return {String} str
|
||||
*/
|
||||
FunctionAssignmentNode.prototype.toTex = function() {
|
||||
return this.name +
|
||||
latex.addBraces(this.params.map(latex.toSymbol).join(', '), true) + '=' +
|
||||
latex.addBraces(this.expr.toTex());
|
||||
var precedence = operators.getPrecedence(this);
|
||||
var exprPrecedence = operators.getPrecedence(this.expr);
|
||||
|
||||
var expr = this.expr.toTex();
|
||||
if ((exprPrecedence !== null) && (exprPrecedence <= precedence)) {
|
||||
//adds visible round brackets
|
||||
expr = latex.addBraces(expr, true);
|
||||
}
|
||||
else {
|
||||
//add (invisible) curly braces
|
||||
expr = latex.addBraces(expr, false);
|
||||
}
|
||||
|
||||
return latex.toFunction(this.name)
|
||||
+ latex.addBraces(this.params.map(latex.toSymbol).join(', '), true) + '='
|
||||
+ expr;
|
||||
};
|
||||
|
||||
module.exports = FunctionAssignmentNode;
|
||||
|
||||
@ -239,98 +239,53 @@ OperatorNode.prototype.toString = function() {
|
||||
* @return {String} str
|
||||
*/
|
||||
OperatorNode.prototype.toTex = function() {
|
||||
var args = this.args,
|
||||
mop = latex.toOperator(this.op),
|
||||
lp = args[0],
|
||||
rp = args[1];
|
||||
var args = this.args;
|
||||
var parens = calculateNecessaryParentheses(this, args);
|
||||
var op = latex.toOperator(this.op); //operator
|
||||
|
||||
switch (args.length) {
|
||||
case 1:
|
||||
var operand = lp.toTex();
|
||||
switch (this.op) {
|
||||
case '-': //unary minus needs brackets around '-' and '+'
|
||||
if (lp instanceof OperatorNode && (lp.op === '-' || lp.op === '+')) {
|
||||
return this.op + latex.addBraces(operand, true);
|
||||
}
|
||||
case '+':
|
||||
return this.op + operand;
|
||||
break;
|
||||
default: // fox example '5!'
|
||||
if (lp instanceof OperatorNode) {
|
||||
return latex.addBraces(operand, true) + this.op;
|
||||
}
|
||||
return operand + this.op;
|
||||
}
|
||||
switch (args.length) {
|
||||
case 1: //unary operators
|
||||
var assoc = operators.getAssociativity(this);
|
||||
|
||||
case 2: // for example '2+3'
|
||||
var lhs = lp.toTex(),
|
||||
lhb = false,
|
||||
rhs = rp.toTex(),
|
||||
rhb = false,
|
||||
lop = '',
|
||||
rop = '';
|
||||
var operand = args[0].toTex();
|
||||
if (parens[0]) {
|
||||
operand = latex.addBraces(operand, true);
|
||||
}
|
||||
|
||||
switch (this.op) {
|
||||
case '/':
|
||||
lop = mop;
|
||||
mop = '';
|
||||
if (assoc === 'right') { //prefix operator
|
||||
return op + operand;
|
||||
}
|
||||
else if (assoc === 'left') { //postfix operator
|
||||
return operand + op;
|
||||
}
|
||||
|
||||
break;
|
||||
//fall back to postfix
|
||||
return operand + op;
|
||||
|
||||
case '*':
|
||||
if (lp instanceof OperatorNode) {
|
||||
if (lp.op === '+' || lp.op === '-') {
|
||||
lhb = true;
|
||||
}
|
||||
}
|
||||
case 2: //binary operators
|
||||
var lhs = args[0]; //left hand side
|
||||
//reminder: if parens[0] is false, this puts it in curly braces
|
||||
var lhsTex = latex.addBraces(lhs.toTex(), parens[0]);
|
||||
var rhs = args[1]; //right hand side
|
||||
var rhsTex = latex.addBraces(rhs.toTex(), parens[1]);
|
||||
|
||||
if (rp instanceof OperatorNode) {
|
||||
if (rp.op === '+' || rp.op === '-' || rp.op === '*') {
|
||||
rhb = true;
|
||||
}
|
||||
}
|
||||
switch (this.getIdentifier()) {
|
||||
case 'OperatorNode:divide':
|
||||
//op contains '\\frac' at this point
|
||||
return op + lhsTex + rhsTex;
|
||||
|
||||
if ((lp instanceof ConstantNode || lp instanceof OperatorNode) &&
|
||||
(rp instanceof ConstantNode || rp instanceof OperatorNode)) {
|
||||
mop = ' \\cdot ';
|
||||
}
|
||||
else {
|
||||
mop = ' \\, ';
|
||||
}
|
||||
case 'OperatorNode:to':
|
||||
rhsTex = latex.toUnit(rhs.toTex());
|
||||
rhsTex = latex.addBraces(rhsTex, parens[1]);
|
||||
break;
|
||||
}
|
||||
return lhsTex + ' ' + op + ' ' + rhsTex;
|
||||
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if (rp instanceof OperatorNode) {
|
||||
if (rp.op === '+' | rp.op === '-' ) {
|
||||
rhb = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '^':
|
||||
if (lp instanceof OperatorNode || lp instanceof FunctionNode) {
|
||||
lhb = true;
|
||||
}
|
||||
else if (lp instanceof SymbolNode) {
|
||||
lhb = null;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'to':
|
||||
rhs = latex.toUnit(rhs, true);
|
||||
break;
|
||||
}
|
||||
|
||||
lhs = latex.addBraces(lhs, lhb);
|
||||
rhs = latex.addBraces(rhs, rhb);
|
||||
|
||||
return lop + lhs + mop + rhs + rop;
|
||||
|
||||
default: // this should not occur. format as a function call
|
||||
return mop + '(' + this.args.map(latex.toSymbol).join(', ') + ')';
|
||||
}
|
||||
default:
|
||||
//fall back to formatting as a function call
|
||||
var argumentList = this.args.map(latex.toSymbol).join(', ');
|
||||
return latex.toFunction(this.fn) + latex.addBraces(argumentList, true);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -216,4 +216,13 @@ describe('AssignmentNode', function() {
|
||||
assert.equal(n.toTex(), '{b}={3}');
|
||||
});
|
||||
|
||||
it ('should LaTeX an AssignmentNode containing an AssignmentNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new AssignmentNode('a', a);
|
||||
|
||||
var n = new AssignmentNode('b', b);
|
||||
|
||||
assert.equal(n.toTex(), '{b}=\\left({{a}={2}}\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@ -195,7 +195,15 @@ describe('FunctionAssignmentNode', function() {
|
||||
var p = new OperatorNode('^', 'pow', [o, a]);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], p);
|
||||
|
||||
assert.equal(n.toTex(), 'f\\left({x}\\right)={\\left({\\frac{x}{2}}\\right)^{2}}');
|
||||
assert.equal(n.toTex(), 'f\\left({x}\\right)={\\left({\\frac{x}{2}}\\right) ^ {2}}');
|
||||
});
|
||||
|
||||
it ('should LaTeX a FunctionAssignmentNode containing an AssignmentNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
|
||||
var n1 = new AssignmentNode('a', a);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], n1);
|
||||
|
||||
assert.equal(n.toTex(), 'f\\left({x}\\right)=\\left({{a}={2}}\\right)');
|
||||
});
|
||||
});
|
||||
|
||||
@ -278,7 +278,7 @@ describe('FunctionNode', function() {
|
||||
|
||||
var o = new OperatorNode('+', 'add', [c1, c2]);
|
||||
var n3 = new FunctionNode('permutations', [o]);
|
||||
assert.equal(n3.toTex(), '{\\left({4}+{5}\\right)!}');
|
||||
assert.equal(n3.toTex(), '{\\left({4} + {5}\\right)!}');
|
||||
});
|
||||
|
||||
it ('should have an identifier', function () {
|
||||
|
||||
@ -276,7 +276,7 @@ describe('OperatorNode', function() {
|
||||
var c = new ConstantNode(4);
|
||||
|
||||
var n = new OperatorNode('+', 'add', [a, b]);
|
||||
assert.equal(n.toTex(), '{2}+{3}');
|
||||
assert.equal(n.toTex(), '{2} + {3}');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with factorial', function () {
|
||||
@ -298,8 +298,8 @@ describe('OperatorNode', function() {
|
||||
var n2= new OperatorNode('!', 'factorial', [add] );
|
||||
var n3= new OperatorNode('!', 'factorial', [mult] );
|
||||
var n4= new OperatorNode('!', 'factorial', [div] );
|
||||
assert.equal(n1.toTex(), '\\left({{2}-{3}}\\right)!');
|
||||
assert.equal(n2.toTex(), '\\left({{2}+{3}}\\right)!');
|
||||
assert.equal(n1.toTex(), '\\left({{2} - {3}}\\right)!');
|
||||
assert.equal(n2.toTex(), '\\left({{2} + {3}}\\right)!');
|
||||
assert.equal(n3.toTex(), '\\left({{2} \\cdot {3}}\\right)!');
|
||||
assert.equal(n4.toTex(), '\\left({\\frac{2}{3}}\\right)!');
|
||||
});
|
||||
@ -316,8 +316,8 @@ describe('OperatorNode', function() {
|
||||
var n3 = new OperatorNode('-', 'unaryMinus', [add]);
|
||||
|
||||
assert.equal(n1.toTex(), '-2');
|
||||
assert.equal(n2.toTex(), '-\\left({{2}-{3}}\\right)');
|
||||
assert.equal(n3.toTex(), '-\\left({{2}+{3}}\\right)');
|
||||
assert.equal(n2.toTex(), '-\\left({{2} - {3}}\\right)');
|
||||
assert.equal(n3.toTex(), '-\\left({{2} + {3}}\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode that subtracts an OperatorNode', function() {
|
||||
@ -331,13 +331,13 @@ describe('OperatorNode', function() {
|
||||
var n1 = new OperatorNode('-', 'subtract', [a, sub]);
|
||||
var n2 = new OperatorNode('-', 'subtract', [a, add]);
|
||||
|
||||
assert.equal(n1.toTex(), '{1}-\\left({{2}-{3}}\\right)');
|
||||
assert.equal(n2.toTex(), '{1}-\\left({{2}+{3}}\\right)');
|
||||
assert.equal(n1.toTex(), '{1} - \\left({{2} - {3}}\\right)');
|
||||
assert.equal(n2.toTex(), '{1} - \\left({{2} + {3}}\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with zero arguments', function () {
|
||||
var n = new OperatorNode('foo', 'foo', []);
|
||||
assert.equal(n.toTex(), 'foo()');
|
||||
assert.equal(n.toTex(), 'foo\\left({}\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with more than two operators', function () {
|
||||
@ -346,7 +346,7 @@ describe('OperatorNode', function() {
|
||||
var c = new ConstantNode(4);
|
||||
|
||||
var n = new OperatorNode('foo', 'foo', [a, b, c]);
|
||||
assert.equal(n.toTex(), 'foo(2, 3, 4)');
|
||||
assert.equal(n.toTex(), 'foo\\left({2, 3, 4}\\right)');
|
||||
|
||||
});
|
||||
|
||||
@ -363,10 +363,10 @@ describe('OperatorNode', function() {
|
||||
var m2 = new OperatorNode('*', 'multiply', [n1, c]);
|
||||
var m3 = new OperatorNode('-', 'subtract', [m2, d]);
|
||||
|
||||
assert.equal(n1.toTex(), '{2}+{3}');
|
||||
assert.equal(n2.toTex(), '{4}-{5}');
|
||||
assert.equal(n3.toTex(), '\\left({{2}+{3}}\\right) \\cdot \\left({{4}-{5}}\\right)');
|
||||
assert.equal(m3.toTex(), '{\\left({{2}+{3}}\\right) \\cdot {4}}-{5}');
|
||||
assert.equal(n1.toTex(), '{2} + {3}');
|
||||
assert.equal(n2.toTex(), '{4} - {5}');
|
||||
assert.equal(n3.toTex(), '\\left({{2} + {3}}\\right) \\cdot \\left({{4} - {5}}\\right)');
|
||||
assert.equal(m3.toTex(), '{\\left({{2} + {3}}\\right) \\cdot {4}} - {5}');
|
||||
});
|
||||
|
||||
it ('should have an identifier', function () {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user