mirror of
https://github.com/josdejong/mathjs.git
synced 2026-01-18 14:59:29 +00:00
* fix(simplify): Leave string constants as strings.
Note that because the `size` built-in function called on a string returns
a Matrix, which is represented in math.js expressions as an Array, this
commit has to add ArrayNode as a dependency of `simplify` (and hence
also of `rationalize`).
In addition, it requires changing the handling of ArrayNodes
and AccessorNodes in `simplifyConstant` from "unimplemented" to just a
pass-through (since a full implementation of simplification in Arrays and
indexing seemed beyond the scope of this change, but `simplify` must not
throw an error on `size("foo")`). Hence, this commit also adds skipped unit
tests for some expressions with arrays and indexing that should ultimately
simplify.
It also removes the skip on the test group "should not change the value of
numbers when converting to fractions (3)" since all of those tests already
appear to pass.
Resolves #2152.
Changes the behavior in #1913 from throwing an error to allowing Arrays and
indexes but not simplifying inside them.
* chore: Fix lint and remove explanatory comment
453 lines
19 KiB
JavaScript
453 lines
19 KiB
JavaScript
// test simplify
|
|
import assert from 'assert'
|
|
|
|
import math from '../../../../src/defaultInstance.js'
|
|
|
|
describe('simplify', function () {
|
|
function simplifyAndCompare (left, right, rules, scope, opt) {
|
|
try {
|
|
if (Array.isArray(rules)) {
|
|
if (opt) {
|
|
assert.strictEqual(math.simplify(left, rules, scope, opt).toString(), math.parse(right).toString())
|
|
} else if (scope) {
|
|
assert.strictEqual(math.simplify(left, rules, scope).toString(), math.parse(right).toString())
|
|
} else {
|
|
assert.strictEqual(math.simplify(left, rules).toString(), math.parse(right).toString())
|
|
}
|
|
} else {
|
|
if (scope) opt = scope
|
|
if (rules) scope = rules
|
|
if (opt) {
|
|
assert.strictEqual(math.simplify(left, scope, opt).toString(), math.parse(right).toString())
|
|
} else if (scope) {
|
|
assert.strictEqual(math.simplify(left, scope).toString(), math.parse(right).toString())
|
|
} else {
|
|
assert.strictEqual(math.simplify(left).toString(), math.parse(right).toString())
|
|
}
|
|
}
|
|
} catch (err) {
|
|
if (err instanceof Error) {
|
|
console.log(err.stack)
|
|
} else {
|
|
console.log(new Error(err))
|
|
}
|
|
throw err
|
|
}
|
|
}
|
|
|
|
function simplifyAndCompareEval (left, right, scope) {
|
|
scope = scope || {}
|
|
assert.strictEqual(math.simplify(left).evaluate(scope), math.parse(right).evaluate(scope))
|
|
}
|
|
|
|
it('should not change the value of the function', function () {
|
|
simplifyAndCompareEval('3+2/4+2*8', '39/2')
|
|
simplifyAndCompareEval('x+1+x', '2x+1', { x: 7 })
|
|
simplifyAndCompareEval('x+1+2x', '3x+1', { x: 7 })
|
|
simplifyAndCompareEval('x^2+x-3+x^2', '2x^2+x-3', { x: 7 })
|
|
})
|
|
|
|
it('should simplify exponents', function () {
|
|
// power rule
|
|
simplifyAndCompare('(x^2)^3', 'x^6')
|
|
simplifyAndCompare('2*(x^2)^3', '2*x^6')
|
|
|
|
// simplify exponent
|
|
simplifyAndCompare('x^(2+3)', 'x^5')
|
|
|
|
// right associative
|
|
simplifyAndCompare('x^2^3', 'x^8')
|
|
})
|
|
|
|
it('should simplify rational expressions with no symbols to fraction', function () {
|
|
simplifyAndCompare('3*4', '12')
|
|
simplifyAndCompare('3+2/4', '7/2')
|
|
})
|
|
|
|
it('handles string constants', function () {
|
|
simplifyAndCompare('"a"', '"a"')
|
|
simplifyAndCompare('f("0xffff")', 'f("0xffff")')
|
|
simplifyAndCompare('"1234"', '"1234"')
|
|
simplifyAndCompare('concat("a","b")', '"ab"')
|
|
simplifyAndCompare('size(concat("A","4/2"))', '[4]')
|
|
simplifyAndCompare('string(4/2)', '"2"')
|
|
simplifyAndCompare('2+number("2")', '4')
|
|
})
|
|
|
|
it('should simplify equations with different variables', function () {
|
|
simplifyAndCompare('-(x+y)', '-(x + y)')
|
|
simplifyAndCompare('-(x*y)', '-(x * y)')
|
|
simplifyAndCompare('-(x+y+x+y)', '-(2 * (y + x))')
|
|
simplifyAndCompare('(x-y)', 'x - y')
|
|
simplifyAndCompare('0+(x-y)', 'x - y')
|
|
simplifyAndCompare('-(x-y)', 'y - x')
|
|
simplifyAndCompare('-1 * (x-y)', 'y - x')
|
|
simplifyAndCompare('x + y + x + 2y', '3 * y + 2 * x')
|
|
})
|
|
|
|
it('should simplify (-1)*n', function () {
|
|
simplifyAndCompare('(-1)*4', '-4')
|
|
simplifyAndCompare('(-1)*x', '-x')
|
|
})
|
|
|
|
it('should handle function assignments', function () {
|
|
const f = new math.FunctionAssignmentNode('sigma', ['x'], math.parse('1 / (1 + exp(-x))'))
|
|
assert.strictEqual(f.toString(), 'sigma(x) = 1 / (1 + exp(-x))')
|
|
assert.strictEqual(f.evaluate()(5), 0.9933071490757153)
|
|
const fsimplified = math.simplify.simplifyCore(f)
|
|
assert.strictEqual(fsimplified.toString(), 'sigma(x) = 1 / (1 + exp(-x))')
|
|
assert.strictEqual(fsimplified.evaluate()(5), 0.9933071490757153)
|
|
})
|
|
|
|
it('simplifyCore should handle different node types', function () {
|
|
const testSimplifyCore = function (expr, expected) {
|
|
const actual = math.simplify.simplifyCore(math.parse(expr)).toString()
|
|
assert.strictEqual(actual, expected)
|
|
}
|
|
testSimplifyCore('5*x*3', '15 * x')
|
|
testSimplifyCore('5*x*3*x', '15 * x * x')
|
|
|
|
testSimplifyCore('x-0', 'x')
|
|
testSimplifyCore('0-x', '-x')
|
|
testSimplifyCore('0-3', '-3')
|
|
testSimplifyCore('x+0', 'x')
|
|
testSimplifyCore('0+x', 'x')
|
|
testSimplifyCore('0*x', '0')
|
|
testSimplifyCore('x*0', '0')
|
|
testSimplifyCore('x*1', 'x')
|
|
testSimplifyCore('1*x', 'x')
|
|
testSimplifyCore('-(x)', '-x')
|
|
testSimplifyCore('0/x', '0')
|
|
testSimplifyCore('(1*x + y*0)*1+0', 'x')
|
|
testSimplifyCore('sin(x+0)*1', 'sin(x)')
|
|
testSimplifyCore('((x+0)*1)', 'x')
|
|
testSimplifyCore('sin((x-0)*1+y*0)', 'sin(x)')
|
|
testSimplifyCore('((x)*(y))', '(x * y)')
|
|
testSimplifyCore('((x)*(y))^1', '(x * y)')
|
|
|
|
// constant folding
|
|
testSimplifyCore('1+2', '3')
|
|
testSimplifyCore('2*3', '6')
|
|
testSimplifyCore('2-3', '-1')
|
|
testSimplifyCore('3/2', '1.5')
|
|
testSimplifyCore('3^2', '9')
|
|
})
|
|
|
|
it('should simplifyCore convert +unaryMinus to subtract', function () {
|
|
simplifyAndCompareEval('--2', '2')
|
|
const result = math.simplify('x + y + a', [math.simplify.simplifyCore], { a: -1 }).toString()
|
|
assert.strictEqual(result, 'x + y - 1')
|
|
})
|
|
|
|
it('should simplify convert minus and unary minus', function () {
|
|
// see https://github.com/josdejong/mathjs/issues/1013
|
|
assert.strictEqual(math.simplify('0 - -1', {}).toString(), '1')
|
|
assert.strictEqual(math.simplify('0 - -x', {}).toString(), 'x')
|
|
assert.strictEqual(math.simplify('0----x', {}).toString(), 'x')
|
|
assert.strictEqual(math.simplify('1 - -x', {}).toString(), 'x + 1')
|
|
assert.strictEqual(math.simplify('0 - (-x)', {}).toString(), 'x')
|
|
assert.strictEqual(math.simplify('-(-x)', {}).toString(), 'x')
|
|
assert.strictEqual(math.simplify('0 - (x - y)', {}).toString(), 'y - x')
|
|
})
|
|
|
|
it.skip('should simplify inside arrays and indexing', function () {
|
|
simplifyAndCompare('[3x+5x]', '[8x]')
|
|
simplifyAndCompare('[2*3,6+2]', '[6,8]')
|
|
simplifyAndCompare('[x,y,z][(3-2)*a]', '[x,y,z][a]')
|
|
})
|
|
|
|
it.skip('should index an array or object with a constant', function () {
|
|
simplifyAndCompare('[x,y,z][2]', 'y')
|
|
simplifyAndCompare('{a:3,b:2}.b', '2')
|
|
})
|
|
|
|
it('should handle custom functions', function () {
|
|
function doubleIt (x) { return x + x }
|
|
const f = new math.FunctionNode(new math.SymbolNode('doubleIt'), [new math.SymbolNode('value')])
|
|
assert.strictEqual(f.toString(), 'doubleIt(value)')
|
|
assert.strictEqual(f.evaluate({ doubleIt: doubleIt, value: 4 }), 8)
|
|
const fsimplified = math.simplify.simplifyCore(f)
|
|
assert.strictEqual(fsimplified.toString(), 'doubleIt(value)')
|
|
assert.strictEqual(fsimplified.evaluate({ doubleIt: doubleIt, value: 4 }), 8)
|
|
})
|
|
|
|
it('should handle immediately invoked function assignments', function () {
|
|
const s = new math.FunctionAssignmentNode('sigma', ['x'], math.parse('1 / (1 + exp(-x))'))
|
|
const f = new math.FunctionNode(s, [new math.SymbolNode('x')])
|
|
assert.strictEqual(f.toString(), '(sigma(x) = 1 / (1 + exp(-x)))(x)')
|
|
assert.strictEqual(f.evaluate({ x: 5 }), 0.9933071490757153)
|
|
const fsimplified = math.simplify.simplifyCore(f)
|
|
assert.strictEqual(fsimplified.toString(), '(sigma(x) = 1 / (1 + exp(-x)))(x)')
|
|
assert.strictEqual(fsimplified.evaluate({ x: 5 }), 0.9933071490757153)
|
|
})
|
|
|
|
it('should simplify (n- -n1)', function () {
|
|
simplifyAndCompare('2 + -3', '-1')
|
|
simplifyAndCompare('2 - 3', '-1')
|
|
simplifyAndCompare('2 - -3', '5')
|
|
let e = math.parse('2 - -3')
|
|
e = math.simplify.simplifyCore(e)
|
|
assert.strictEqual(e.toString(), '5') // simplifyCore
|
|
simplifyAndCompare('x - -x', '2*x')
|
|
e = math.parse('x - -x')
|
|
e = math.simplify.simplifyCore(e)
|
|
assert.strictEqual(e.toString(), 'x + x') // not a core simplification since + is cheaper than *
|
|
})
|
|
|
|
it('should preserve the value of BigNumbers', function () {
|
|
const bigmath = math.create({ number: 'BigNumber', precision: 64 })
|
|
assert.deepStrictEqual(bigmath.simplify('111111111111111111 + 111111111111111111').evaluate(), bigmath.evaluate('222222222222222222'))
|
|
assert.deepStrictEqual(bigmath.simplify('1 + 111111111111111111').evaluate(), bigmath.evaluate('111111111111111112'))
|
|
assert.deepStrictEqual(bigmath.simplify('1/2 + 11111111111111111111').evaluate(), bigmath.evaluate('11111111111111111111.5'))
|
|
assert.deepStrictEqual(bigmath.simplify('1/3 + 11111111111111111111').evaluate(), bigmath.evaluate('11111111111111111111.33333333333333333333333333333333333333333333'))
|
|
assert.deepStrictEqual(bigmath.simplify('3 + 1 / 11111111111111111111').evaluate(), bigmath.evaluate('3 + 1 / 11111111111111111111'))
|
|
})
|
|
|
|
it('should not change the value of numbers when converting to fractions (1)', function () {
|
|
simplifyAndCompareEval('1e-10', '1e-10')
|
|
})
|
|
|
|
it('should not change the value of numbers when converting to fractions (2)', function () {
|
|
simplifyAndCompareEval('0.2 * 1e-14', '2e-15')
|
|
})
|
|
|
|
it('should not change the value of numbers when converting to fractions (3)', function () {
|
|
// TODO this requires that all operators and functions have the correct logic in their 'Fraction' typed-functions.
|
|
// Ideally they should convert parameters to Fractions if they can all be expressed exactly,
|
|
// otherwise convert all parameters to the 'number' type.
|
|
simplifyAndCompareEval('1 - 1e-10', '1 - 1e-10')
|
|
simplifyAndCompareEval('1 + 1e-10', '1 + 1e-10')
|
|
simplifyAndCompareEval('1e-10 / 2', '1e-10 / 2')
|
|
simplifyAndCompareEval('(1e-5)^2', '(1e-5)^2')
|
|
simplifyAndCompareEval('min(1, -1e-10)', '-1e-10')
|
|
simplifyAndCompareEval('max(1e-10, -1)', '1e-10')
|
|
})
|
|
|
|
it('should simplify non-rational expressions with no symbols to number', function () {
|
|
simplifyAndCompare('3+sin(4)', '2.2431975046920716')
|
|
})
|
|
|
|
it('should collect like terms', function () {
|
|
simplifyAndCompare('x+x', '2*x')
|
|
simplifyAndCompare('2x+x', '3*x')
|
|
simplifyAndCompare('2(x+1)+(x+1)', '3*(x + 1)')
|
|
simplifyAndCompare('y*x^2+2*x^2', '(y+2)*x^2')
|
|
})
|
|
|
|
it('should collect separated like terms', function () {
|
|
simplifyAndCompare('x+1+x', '2*x+1')
|
|
simplifyAndCompare('x^2+x+3+x^2', '2*x^2+x+3')
|
|
simplifyAndCompare('x+1+2x', '3*x+1')
|
|
simplifyAndCompare('x-1+x', '2*x-1')
|
|
simplifyAndCompare('x-1-2x+2', '1-x')
|
|
})
|
|
|
|
it('should collect like terms that are embedded in other terms', function () {
|
|
simplifyAndCompare('10 - (x - 2)', '12 - x')
|
|
simplifyAndCompare('x - (y + x)', '-y')
|
|
simplifyAndCompare('x - (y - (y - x))', '0')
|
|
})
|
|
|
|
it('should collect separated like factors', function () {
|
|
simplifyAndCompare('x*y*-x/(x^2)', '-y')
|
|
simplifyAndCompare('x/2*x', 'x^2/2')
|
|
simplifyAndCompare('x*2*x', '2*x^2')
|
|
})
|
|
|
|
it('should handle nested exponentiation', function () {
|
|
simplifyAndCompare('(x^2)^3', 'x^6')
|
|
simplifyAndCompare('(x^y)^z', 'x^(y*z)')
|
|
simplifyAndCompare('8 * x ^ 9 + 2 * (x ^ 3) ^ 3', '10 * x ^ 9')
|
|
})
|
|
|
|
it('should not run into an infinite recursive loop', function () {
|
|
simplifyAndCompare('2n - 1', '2 n - 1')
|
|
simplifyAndCompare('16n - 1', '16 n - 1')
|
|
simplifyAndCompare('16n / 1', '16 * n')
|
|
simplifyAndCompare('8 / 5n', 'n * 8 / 5')
|
|
simplifyAndCompare('8n - 4n', '4 * n')
|
|
simplifyAndCompare('8 - 4n', '8 - 4 * n')
|
|
simplifyAndCompare('8 - n', '8 - n')
|
|
})
|
|
|
|
it('should handle non-existing functions like a pro', function () {
|
|
simplifyAndCompare('foo(x)', 'foo(x)')
|
|
simplifyAndCompare('foo(1)', 'foo(1)')
|
|
simplifyAndCompare('myMultiArg(x, y, z, w)', 'myMultiArg(x, y, z, w)')
|
|
})
|
|
|
|
it('should simplify a/(b/c)', function () {
|
|
simplifyAndCompare('x/(x/y)', 'y')
|
|
simplifyAndCompare('x/(y/z)', 'x * z/y')
|
|
simplifyAndCompare('(x + 1)/((x + 1)/(z + 3))', 'z + 3')
|
|
simplifyAndCompare('(x + 1)/((y + 2)/(z + 3))', '(x + 1) * (z + 3)/(y + 2)')
|
|
})
|
|
|
|
it('should support custom rules', function () {
|
|
const node = math.simplify('y+x', [{ l: 'n1-n2', r: '-n2+n1' }], { x: 5 })
|
|
assert.strictEqual(node.toString(), 'y + 5')
|
|
})
|
|
|
|
it('should handle valid built-in constant symbols in rules', function () {
|
|
assert.strictEqual(math.simplify('true', ['true -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('false', ['false -> 0']).toString(), '0')
|
|
assert.strictEqual(math.simplify('log(e)', ['log(e) -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('sin(pi * x)', ['sin(pi * n) -> 0']).toString(), '0')
|
|
assert.strictEqual(math.simplify('i', ['i -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('Infinity', ['Infinity -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('LN2', ['LN2 -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('LN10', ['LN10 -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('LOG2E', ['LOG2E -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('LOG10E', ['LOG10E -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('null', ['null -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('phi', ['phi -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('SQRT1_2', ['SQRT1_2 -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('SQRT2', ['SQRT2 -> 1']).toString(), '1')
|
|
assert.strictEqual(math.simplify('tau', ['tau -> 1']).toString(), '1')
|
|
|
|
// note that NaN is a special case, we can't compare two values both NaN.
|
|
})
|
|
|
|
it('should remove addition of 0', function () {
|
|
simplifyAndCompare('x+0', 'x')
|
|
simplifyAndCompare('x-0', 'x')
|
|
})
|
|
|
|
it('options parameters', function () {
|
|
simplifyAndCompare('0.1*x', 'x/10')
|
|
simplifyAndCompare('0.1*x', 'x/10', math.simplify.rules, {}, { exactFractions: true })
|
|
simplifyAndCompare('0.1*x', '0.1*x', math.simplify.rules, {}, { exactFractions: false })
|
|
simplifyAndCompare('y+0.1*x', 'x/10+1', { y: 1 })
|
|
simplifyAndCompare('y+0.1*x', 'x/10+1', { y: 1 }, { exactFractions: true })
|
|
simplifyAndCompare('y+0.1*x', '0.1*x+1', { y: 1 }, { exactFractions: false })
|
|
|
|
simplifyAndCompare('0.00125', '1 / 800', math.simplify.rules, {}, { exactFractions: true })
|
|
simplifyAndCompare('0.00125', '0.00125', math.simplify.rules, {}, { exactFractions: true, fractionsLimit: 100 })
|
|
simplifyAndCompare('0.4', '2 / 5', math.simplify.rules, {}, { exactFractions: true, fractionsLimit: 100 })
|
|
simplifyAndCompare('100.8', '504 / 5', math.simplify.rules, {}, { exactFractions: true })
|
|
simplifyAndCompare('100.8', '100.8', math.simplify.rules, {}, { exactFractions: true, fractionsLimit: 100 })
|
|
})
|
|
|
|
it('resolve() should substitute scoped constants', function () {
|
|
assert.strictEqual(
|
|
math.simplify.resolve(math.parse('x+y'), { x: 1 }).toString(),
|
|
'1 + y'
|
|
) // direct
|
|
simplifyAndCompare('x+y', 'x+y', {}) // operator
|
|
simplifyAndCompare('x+y', 'y+1', { x: 1 })
|
|
simplifyAndCompare('x+y', 'y+1', { x: math.parse('1') })
|
|
simplifyAndCompare('x+y', '3', { x: 1, y: 2 })
|
|
simplifyAndCompare('x+x+x', '3*x')
|
|
simplifyAndCompare('y', 'x+1', { y: math.parse('1+x') })
|
|
simplifyAndCompare('y', '3', { x: 2, y: math.parse('1+x') })
|
|
simplifyAndCompare('x+y', '3*x', { y: math.parse('x+x') })
|
|
simplifyAndCompare('x+y', '6', { x: 2, y: math.parse('x+x') })
|
|
simplifyAndCompare('x+(y+2-1-1)', '6', { x: 2, y: math.parse('x+x') }) // parentheses
|
|
simplifyAndCompare('log(x+y)', String(Math.log(6)), { x: 2, y: math.parse('x+x') }) // function
|
|
simplifyAndCompare('combinations( ceil(abs(sin(x)) * y), abs(x) )',
|
|
'combinations(ceil(0.9092974268256817 * y ), 2)', { x: -2 })
|
|
|
|
// TODO(deal with accessor nodes) simplifyAndCompare('size(text)[1]', '11', {text: "hello world"})
|
|
})
|
|
|
|
it('resolve() should substitute scoped constants from Map like scopes', function () {
|
|
assert.strictEqual(
|
|
math.simplify.resolve(math.parse('x+y'), new Map([['x', 1]])).toString(),
|
|
'1 + y'
|
|
) // direct
|
|
simplifyAndCompare('x+y', 'x+y', new Map()) // operator
|
|
simplifyAndCompare('x+y', 'y+1', new Map([['x', 1]]))
|
|
simplifyAndCompare('x+y', 'y+1', new Map([['x', math.parse('1')]]))
|
|
})
|
|
|
|
it('should keep implicit multiplication implicit', function () {
|
|
const f = math.parse('2x')
|
|
assert.strictEqual(f.toString({ implicit: 'hide' }), '2 x')
|
|
const simplified = math.simplify(f)
|
|
assert.strictEqual(simplified.toString({ implicit: 'hide' }), '2 x')
|
|
})
|
|
|
|
describe('expression parser', function () {
|
|
it('should evaluate simplify containing string value', function () {
|
|
const res = math.evaluate('simplify("2x + 3x")')
|
|
assert.ok(res && res.isNode)
|
|
assert.strictEqual(res.toString(), '5 * x')
|
|
})
|
|
|
|
it('should evaluate simplify containing nodes', function () {
|
|
const res = math.evaluate('simplify(parse("2x + 3x"))')
|
|
assert.ok(res && res.isNode)
|
|
assert.strictEqual(res.toString(), '5 * x')
|
|
})
|
|
|
|
it('should compute and simplify derivatives', function () {
|
|
const res = math.evaluate('derivative("5x*3x", "x")')
|
|
assert.ok(res && res.isNode)
|
|
assert.strictEqual(res.toString(), '30 * x')
|
|
})
|
|
|
|
it('should compute and simplify derivatives (2)', function () {
|
|
const scope = {}
|
|
math.evaluate('a = derivative("5x*3x", "x")', scope)
|
|
const res = math.evaluate('simplify(a)', scope)
|
|
assert.ok(res && res.isNode)
|
|
assert.strictEqual(res.toString(), '30 * x')
|
|
})
|
|
|
|
it.skip('should compute and simplify derivatives (3)', function () {
|
|
// TODO: this requires the + operator to support Nodes,
|
|
// i.e. math.add(5, math.parse('2')) => return an OperatorNode
|
|
const res = math.evaluate('simplify(5+derivative(5/(3x), x))')
|
|
assert.ok(res && res.isNode)
|
|
assert.strictEqual(res.toString(), '5 - 15 / (3 * x) ^ 2')
|
|
})
|
|
})
|
|
|
|
it('should respect log arguments', function () {
|
|
simplifyAndCompareEval('log(e)', '1')
|
|
simplifyAndCompareEval('log(e,e)', '1')
|
|
simplifyAndCompareEval('log(3,5)', 'log(3,5)')
|
|
simplifyAndCompareEval('log(e,9)', 'log(e,9)')
|
|
})
|
|
|
|
describe('should simplify fraction where denominator has a minus', function () {
|
|
it('unary numerator and unary denominator', function () {
|
|
simplifyAndCompare('1/(-y)', '-(1/y)')
|
|
simplifyAndCompare('x/(-y)', '-(x/y)')
|
|
simplifyAndCompare('(-1)/(-y)', '1/y')
|
|
simplifyAndCompare('(-x)/(-y)', 'x/y')
|
|
})
|
|
|
|
it('binary numerator and unary denominator', function () {
|
|
simplifyAndCompare('(1+x)/(-y)', '-((x+1)/y)')
|
|
simplifyAndCompare('(w+x)/(-y)', '-((w+x)/y)')
|
|
simplifyAndCompare('(1-x)/(-y)', '(x-1)/y')
|
|
simplifyAndCompare('(w-x)/(-y)', '(x-w)/y')
|
|
})
|
|
|
|
it('unary numerator and binary denominator', function () {
|
|
simplifyAndCompare('1/(-(y+z))', '-(1/(y+z))')
|
|
simplifyAndCompare('x/(-(y+z))', '-(x/(y+z))')
|
|
simplifyAndCompare('(-1)/(-(y+z))', '1/(y+z)')
|
|
simplifyAndCompare('(-x)/(-(y+z))', 'x/(y+z)')
|
|
|
|
simplifyAndCompare('1/(-(y-z))', '1/(z-y)')
|
|
simplifyAndCompare('x/(-(y-z))', 'x/(z-y)')
|
|
simplifyAndCompare('(-1)/(-(y-z))', '-(1/(z-y))')
|
|
simplifyAndCompare('(-x)/(-(y-z))', '-(x/(z-y))')
|
|
})
|
|
|
|
it('binary numerator and binary denominator', function () {
|
|
simplifyAndCompare('(1+x)/(-(y+z))', '-((x+1)/(y+z))')
|
|
simplifyAndCompare('(w+x)/(-(y+z))', '-((w+x)/(y+z))')
|
|
simplifyAndCompare('(1-x)/(-(y+z))', '(x-1)/(y+z)')
|
|
simplifyAndCompare('(w-x)/(-(y+z))', '(x-w)/(y+z)')
|
|
|
|
simplifyAndCompare('(1+x)/(-(y-z))', '(x+1)/(z-y)')
|
|
simplifyAndCompare('(w+x)/(-(y-z))', '(w+x)/(z-y)')
|
|
simplifyAndCompare('(1-x)/(-(y-z))', '(1-x)/(z-y)')
|
|
simplifyAndCompare('(w-x)/(-(y-z))', '(w-x)/(z-y)')
|
|
})
|
|
})
|
|
})
|