From 033735c5e2cd113f602a8941a9b8de0bf64af39e Mon Sep 17 00:00:00 2001 From: jos Date: Fri, 23 Jun 2017 13:40:38 +0200 Subject: [PATCH] Implemented support for all types in `compareNatural` --- docs/reference/functions.md | 16 ++ docs/reference/functions/compare.md | 3 +- docs/reference/functions/sort.md | 6 +- lib/function/relational/compareNatural.js | 232 +++++++++++++++-- package.json | 1 - test/function/matrix/sort.test.js | 6 +- .../relational/compareNatural.test.js | 240 ++++++++---------- test/function/set/setCartesian.test.js | 2 +- test/function/set/setDistinct.test.js | 2 +- test/function/set/setIntersect.test.js | 2 +- test/function/set/setPowerset.test.js | 2 +- 11 files changed, 345 insertions(+), 167 deletions(-) diff --git a/docs/reference/functions.md b/docs/reference/functions.md index 9673de422..a78dc7e84 100644 --- a/docs/reference/functions.md +++ b/docs/reference/functions.md @@ -177,6 +177,7 @@ Function | Description Function | Description ---- | ----------- [math.compare(x, y)](functions/compare.md) | Compare two values. +[math.compareNatural(x, y)](functions/compareNatural.md) | Compare two values in a natural way. [math.deepEqual(x, y)](functions/deepEqual.md) | Test element wise whether two matrices are equal. [math.equal(x, y)](functions/equal.md) | Test whether two values are equal. [math.larger(x, y)](functions/larger.md) | Test whether value x is larger than y. @@ -185,6 +186,21 @@ Function | Description [math.smallerEq(x, y)](functions/smallerEq.md) | Test whether value x is smaller or equal to y. [math.unequal(x, y)](functions/unequal.md) | Test whether two values are unequal. +## Set functions + +Function | Description +---- | ----------- +[math.setCartesian(set1, set2)](functions/setCartesian.md) | Create the cartesian product of two (multi)sets. +[math.setDifference(set1, set2)](functions/setDifference.md) | Create the difference of two (multi)sets. +[math.setDistinct(set)](functions/setDistinct.md) | Collect the distinct elements of a multiset. +[math.setIntersect(set1, set2)](functions/setIntersect.md) | Create the intersection of two (multi)sets. +[math.setIsSubset(set1, set2)](functions/setIsSubset.md) | Decide whether a (multi)set is a subset of another (multi)set. +[math.setMultiplicity(set)](functions/setMultiplicity.md) | Count the multiplicity of an element in a multiset. +[math.setPowerset(set)](functions/setPowerset.md) | Create the powerset of a (multi)set. +[math.setSize(set)](functions/setSize.md) | Count the number of elements of a (multi)set. +[math.setSymDifference(set1, set2)](functions/setSymDifference.md) | Create the symmetric difference of two (multi)sets. +[math.setUnion(set1, set2)](functions/setUnion.md) | Create the union of two (multi)sets. + ## Special functions Function | Description diff --git a/docs/reference/functions/compare.md b/docs/reference/functions/compare.md index 80b16fb7a..926499d77 100644 --- a/docs/reference/functions/compare.md +++ b/docs/reference/functions/compare.md @@ -53,4 +53,5 @@ math.compare(2, [1, 2, 3]); // returns [1, 0, -1] [smaller](smaller.md), [smallerEq](smallerEq.md), [larger](larger.md), -[largerEq](largerEq.md) +[largerEq](largerEq.md), +[compareNatural](compareNatural.md) diff --git a/docs/reference/functions/sort.md b/docs/reference/functions/sort.md index 6fb4366b6..27a89b748 100644 --- a/docs/reference/functions/sort.md +++ b/docs/reference/functions/sort.md @@ -17,7 +17,7 @@ math.sort(x, compare) Parameter | Type | Description --------- | ---- | ----------- `x` | Matrix | Array | A one dimensional matrix or array to sort -`compare` | Function | 'asc' | 'desc' | An optional _comparator function. The function is called as `compare(a, b)`, and must return 1 when a > b, -1 when a < b, and 0 when a == b. Default value: 'asc'. +`compare` | Function | 'asc' | 'desc' | 'natural' | An optional _comparator function or name. The function is called as `compare(a, b)`, and must return 1 when a > b, -1 when a < b, and 0 when a == b. Default value: 'asc'. ### Returns @@ -43,4 +43,6 @@ math.sort(['Langdon', 'Tom', 'Sara'], sortByLength); // returns ['Tom', 'Sara', [filter](filter.md), [forEach](forEach.md), -[map](map.md) +[map](map.md), +[compare](compare.md), +[compareNatural](compareNatural.md) diff --git a/lib/function/relational/compareNatural.js b/lib/function/relational/compareNatural.js index e9423eee0..cefc68804 100644 --- a/lib/function/relational/compareNatural.js +++ b/lib/function/relational/compareNatural.js @@ -1,11 +1,18 @@ 'use strict'; -var compareString = require('natural-compare'); +var isCollection = require('../../utils/collection/isCollection'); function factory (type, config, load, typed) { - + var getTypeOf = load(require('../utils/typeof')); + var matrix = load(require('../../type/matrix/function/matrix')); var compare = load(require('./compare')); + var compareBooleans = compare.signatures['boolean,boolean'] + var compareUnits = compare.signatures['Unit,Unit'] + var compareNumbers = compare.signatures['number,number'] + var compareBigNumbers = compare.signatures['BigNumber,BigNumber'] + var compareFractions = compare.signatures['Fraction,Fraction'] + /** * Compare two values in a natural way. * @@ -27,54 +34,233 @@ function factory (type, config, load, typed) { * * Examples: * - * math.compareNatural(6, 1); // returns 1 - * math.compareNatural(2, 3); // returns -1 - * math.compareNatural(7, 7); // returns 0 + * math.compareNatural(6, 1); // returns 1 + * math.compareNatural(2, 3); // returns -1 + * math.compareNatural(7, 7); // returns 0 * * var a = math.unit('5 cm'); * var b = math.unit('40 mm'); - * math.compareNatural(a, b); // returns 1 + * math.compareNatural(a, b); // returns 1 * * var c = math.complex('2 + 3i'); * var d = math.complex('2 + 4i'); - * math.compareNatural(c, d); // returns -1 + * math.compareNatural(c, d); // returns -1 * - * math.compareNatural(2, [1, 2, 3]); // returns [1, 0, -1] + * math.compareNatural([1, 2, 3], [1, 2]); // returns 1 + * math.compareNatural([1, 2], [1, 2]); // returns 0 * * See also: * * equal, unequal, smaller, smallerEq, larger, largerEq, compare * - * @param {number | BigNumber | Fraction | Unit | string} x First value to compare - * @param {number | BigNumber | Fraction | Unit | string} y Second value to compare - * @return {number | BigNumber} Returns the result of the comparison: 1, 0 or -1. + * @param {*} x First value to compare + * @param {*} y Second value to compare + * @return {number} Returns the result of the comparison: 1, 0 or -1. */ var compareNatural = typed('compareNatural', { + 'any, any': function (x, y) { + var typeX = getTypeOf(x); + var typeY = getTypeOf(y); - 'boolean, boolean': compare.signatures['boolean,boolean'], + // in case of different types, order by name of type + // i.e. 'BigNumber' < 'Complex' + if (typeX !== typeY) { + return compareString(typeX, typeY); + } - 'number, number': compare.signatures['number,number'], + if (typeX === 'number') { + return compareNumbers(x, y); + } - 'BigNumber, BigNumber': compare.signatures['BigNumber,BigNumber'], + if (typeX === 'BigNumber') { + return compareBigNumbers(x, y).toNumber(); + } - 'Fraction, Fraction': compare.signatures['Fraction,Fraction'], + if (typeX === 'Fraction') { + return compareFractions(x, y); + } - 'Complex, Complex': compareComplex, + if (typeX === 'Complex') { + return compareComplexNumbers(x, y); + } - 'Unit, Unit': compare.signatures['Unit,Unit'], + if (typeX === 'Unit') { + // FIXME: implement ordering for units with different base + return compareUnits(x, y); + } - 'string, string': compareString + if (typeX === 'boolean') { + return compareBooleans(x, y); + } - // TODO: implement for Matrix. element-wise or whole matrix? - // TODO: implement for Array. element-wise or whole matrix? - // TODO: implement for Object. element-wise or whole object? + if (typeX === 'string') { + return compareString(x, y); + } + + if (typeX === 'Matrix') { + // can be SparseMatrix or DenseMatrix + if (x.type !== y.type) { + return compareString(x.type, y.type) + } + if (x.type === 'DenseMatrix') { + return compareDenseMatrices(x, y); + } + if (x.type === 'SparseMatrix') { + return compareSparseMatrices(x, y); + } + } + + if (typeX === 'Array') { + return compareArrays(x, y); + } + + if (typeX === 'Object') { + return compareObjects(x, y); + } + + if (typeX === 'null') { + return 0; + } + + if (typeX === 'undefined') { + return 0; + } + + // this should not occur... + throw new TypeError('Unsupported type of value "' + typeX + '"'); + } }); - compare.toTex = undefined; // use default template + compareNatural.toTex = undefined; // use default template + + /** + * Compare two Arrays + * + * - First compares the length of the arrays + * - Next, compares value by value + * + * @param {Array} a + * @param {Array} b + * @returns {number} Returns the comparison result: -1, 0, or 1 + */ + function compareArrays (a, b) { + // compare the size of the arrays + if (a.length > b.length) { return 1; } + if (a.length < b.length) { return -1; } + + // compare each value + for (var i = 0; i < a.length; i++) { + var v = compareNatural(a[i], b[i]); + if (v !== 0) { + return v; + } + } + + // both Arrays have equal size and content + return 0; + } + + /** + * Compare two dense matrices + * + * - First compares the number of dimensions + * - Next, compares the size of the dimensions + * - Last, compares value by value + * + * @param {DenseMatrix} a + * @param {DenseMatrix} b + * @returns {number} Returns the comparison result: -1, 0, or 1 + */ + function compareDenseMatrices (a, b) { + // get internal size and values without cloning anything + var _a = a.toJSON(); + var _b = b.toJSON(); + + // compare number and size of the dimensions + var c = compareArrays(_a.size, _b.size); + if (c !== 0) { + return c; + } + + // compare the values of the matrices + return compareArrays(_a.data, _b.data); + } + + /** + * Compare two sparse matrices + * + * - First compares the number of dimensions + * - Next, compares the size of the dimensions + * - Last, compares value by value + * + * @param {SparseMatrix} a + * @param {SparseMatrix} b + * @returns {number} Returns the comparison result: -1, 0, or 1 + */ + function compareSparseMatrices (a, b) { + // get internal size and values without cloning anything + var _a = a.toJSON(); + var _b = b.toJSON(); + + // compare number and size of the dimensions + var c = compareArrays(_a.size, _b.size); + if (c !== 0) { + return c; + } + + // compare the values of the matrices + return compareArrays(_a.values, _b.values); + } + + /** + * Compare two objects + * - First, compares the number of properties + * - Then, compare the property names when sorted + * - Lastly, compare the property values + * @param {Object} a + * @param {Object} b + * @returns {number} Returns the comparison result: -1, 0, or 1 + */ + function compareObjects (a, b) { + var keysA = Object.keys(a); + var keysB = Object.keys(b); + + // compare number of keys + if (keysA.length > keysB.length) { return 1; } + if (keysA.length < keysB.length) { return -1; } + + // compare keys + keysA.sort(compareString) + keysB.sort(compareString) + var c = compareArrays(keysA, keysB); + if (c !== 0) { + return c; + } + + // compare values + for (var i = 0; i < keysA.length; i++) { + var v = compareNatural(a[keysA[i]], b[keysB[i]]); + if (v !== 0) { + return v; + } + } + + return 0; + } return compareNatural; } +/** + * Compare two strings by the char code of their characters + * @param {string} a + * @param {string} b + * @return {number} + */ +function compareString (a, b) { + return a > b ? 1 : a < b ? -1 : 0; +} + /** * Compare two complex numbers, `a` and `b`: * @@ -90,7 +276,7 @@ function factory (type, config, load, typed) { * @params {Complex} b * @returns {number} Returns the comparison result: -1, 0, or 1 */ -function compareComplex (a, b) { +function compareComplexNumbers (a, b) { if (a.re > b.re) { return 1; } if (a.re < b.re) { return -1; } diff --git a/package.json b/package.json index b6db48c0f..46807b880 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,6 @@ "complex.js": "2.0.4", "decimal.js": "7.2.1", "fraction.js": "4.0.1", - "natural-compare": "1.4.0", "seed-random": "2.2.0", "tiny-emitter": "2.0.0", "typed-function": "0.10.5" diff --git a/test/function/matrix/sort.test.js b/test/function/matrix/sort.test.js index efcf13851..858740bbe 100644 --- a/test/function/matrix/sort.test.js +++ b/test/function/matrix/sort.test.js @@ -10,6 +10,7 @@ describe('sort', function() { it('should sort an array with strings', function() { assert.deepEqual(math.sort(['C', 'B', 'A', 'D']), ['A', 'B', 'C', 'D']); + assert.deepEqual(math.sort(['1', '2', '10'], 'asc'), ['1', '10', '2']); }); it('should sort a Matrix', function() { @@ -24,11 +25,6 @@ describe('sort', function() { assert.deepEqual(math.sort([5,10,1], 'desc'), [10,5,1]); }); - it('should sort an array in natural order', function() { - assert.deepEqual(math.sort(['1', '2', '10'], 'asc'), ['1', '10', '2']); - assert.deepEqual(math.sort(['1', '2', '10'], 'natural'), ['1', '2', '10']); - }); - it('should sort an array with a custom compare function', function() { function sortByLength (a, b) { return a.length - b.length; diff --git a/test/function/relational/compareNatural.test.js b/test/function/relational/compareNatural.test.js index 3c33bf8c3..8c63ac17a 100644 --- a/test/function/relational/compareNatural.test.js +++ b/test/function/relational/compareNatural.test.js @@ -10,7 +10,7 @@ var assert = require('assert'), describe('compareNatural', function() { - it('should naturally compare two numbers correctly', function() { + it('should compare two numbers correctly', function() { assert.equal(compareNatural(2, 3), -1); assert.equal(compareNatural(2, 2), 0); assert.equal(compareNatural(2, 1), 1); @@ -20,7 +20,7 @@ describe('compareNatural', function() { assert.equal(compareNatural(-3, -2), -1); }); - it('should naturally compare two floating point numbers correctly', function() { + it('should compare two floating point numbers correctly', function() { // Infinity assert.equal(compareNatural(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY), 0); assert.equal(compareNatural(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY), 0); @@ -34,48 +34,22 @@ describe('compareNatural', function() { assert.equal(compareNatural(0.3 - 0.2, 0.1), 0); }); - it('should naturally compare two booleans', function() { + it('should compare two booleans', function() { assert.equal(compareNatural(true, true), 0); assert.equal(compareNatural(true, false), 1); assert.equal(compareNatural(false, true), -1); assert.equal(compareNatural(false, false), 0); }); - it('should naturally compare mixed numbers and booleans', function() { - assert.equal(compareNatural(2, true), 1); - assert.equal(compareNatural(0, true), -1); - assert.equal(compareNatural(true, 2), -1); - assert.equal(compareNatural(false, 2), -1); + it('should compare bignumbers', function() { + assert.strictEqual(compareNatural(bignumber(2), bignumber(3)), -1); + assert.strictEqual(compareNatural(bignumber(2), bignumber(2)), 0); + assert.strictEqual(compareNatural(bignumber(3), bignumber(2)), 1); + assert.strictEqual(compareNatural(bignumber(0), bignumber(0)), 0); + assert.strictEqual(compareNatural(bignumber(-2), bignumber(2)), -1); }); - it('should naturally compare mixed numbers and null', function() { - assert.equal(compareNatural(2, null), 1); - assert.equal(compareNatural(0, null), 0); - assert.equal(compareNatural(null, 2), -1); - }); - - it('should naturally compare bignumbers', function() { - assert.deepEqual(compareNatural(bignumber(2), bignumber(3)), bignumber(-1)); - assert.deepEqual(compareNatural(bignumber(2), bignumber(2)), bignumber(0)); - assert.deepEqual(compareNatural(bignumber(3), bignumber(2)), bignumber(1)); - assert.deepEqual(compareNatural(bignumber(0), bignumber(0)), bignumber(0)); - assert.deepEqual(compareNatural(bignumber(-2), bignumber(2)), bignumber(-1)); - }); - - it('should naturally compare mixed numbers and bignumbers', function() { - assert.deepEqual(compareNatural(bignumber(2), 3), bignumber(-1)); - assert.deepEqual(compareNatural(2, bignumber(2)), bignumber(0)); - }); - - it('should naturally compare mixed booleans and bignumbers', function() { - assert.deepEqual(compareNatural(bignumber(0.1), true), bignumber(-1)); - assert.deepEqual(compareNatural(bignumber(1), true), bignumber(0)); - assert.deepEqual(compareNatural(bignumber(1), false), bignumber(1)); - assert.deepEqual(compareNatural(false, bignumber(0)), bignumber(0)); - assert.deepEqual(compareNatural(true, bignumber(0)), bignumber(1)); - }); - - it('should naturally compare two fractions', function() { + it('should compare two fractions', function() { var a = math.fraction(1,3); var b = math.fraction(1,6); assert(compareNatural(a, b) instanceof math.type.Fraction); @@ -89,103 +63,132 @@ describe('compareNatural', function() { assert.strictEqual(compareNatural(math.add(math.fraction(0.1), math.fraction(0.2)), math.fraction(0.3)).valueOf(), 0); // this would fail with numbers }); - it('should naturally compare mixed fractions and numbers', function() { - assert.deepEqual(compareNatural(1, math.fraction(1,3)), math.fraction(1)); - assert.deepEqual(compareNatural(math.fraction(1,3), 1), math.fraction(-1)); - }); - - it('should naturally compare two measures of the same unit', function() { + it('should compare two measures of the same unit', function() { assert.equal(compareNatural(unit('100cm'), unit('10inch')), 1); assert.equal(compareNatural(unit('99cm'), unit('1m')), -1); assert.equal(compareNatural(unit('1m'), unit('1m')), bignumber(0)); assert.equal(compareNatural(unit('101cm'), unit('1m')), 1); }); - it('should throw an error if comparing a unit with a number', function() { - assert.throws(function () {compareNatural(unit('100cm'), 22);}); - }); - it('should throw an error for two measures of different units', function() { + + // TODO: compare units with different base + assert.throws(function () {compareNatural(math.unit(5, 'km'), math.unit(100, 'gram'));}); }); - it('should throw an error if comparing a unit with a bignumber', function() { - assert.throws(function () {compareNatural(unit('100cm'), bignumber(22));}); + it('should compare mixed types (by type name)', function() { + // booleans + assert.strictEqual (compareNatural(2, true), 1); + assert.strictEqual (compareNatural(0, false), 1); + assert.strictEqual (compareNatural(true, 2), -1); + assert.strictEqual (compareNatural(false, 2), -1); + + // null + assert.strictEqual (compareNatural(2, null), 1); + assert.strictEqual (compareNatural(null, 2), -1); + + // undefined + assert.strictEqual (compareNatural(2, undefined), -1); + assert.strictEqual (compareNatural(undefined, 2), 1); + + // fractions and units + assert.strictEqual (compareNatural(1, math.fraction(1,3)), 1); + assert.strictEqual (compareNatural(math.fraction(1,3), 1), -1); + + // units and numbers + assert.strictEqual (compareNatural(unit('100cm'), 22), -1); + assert.strictEqual (compareNatural(22, unit('100cm')), 1); + + // units and bignumbers + assert.strictEqual (compareNatural(unit('100cm'), bignumber(22)), 1); + assert.strictEqual (compareNatural(bignumber(22), unit('100cm')), -1); + + // numbers and complex + assert.strictEqual (compareNatural(1, complex(2,3)), 1); + assert.strictEqual (compareNatural(complex(2,3), 1), -1); + + // numbers and bignumbers + assert.strictEqual (compareNatural(bignumber(2), 3), -1); + assert.strictEqual (compareNatural(2, bignumber(2)), 1); + + // array, DenseMatrix, SparseMatrix + assert.strictEqual (compareNatural(matrix([2]), [2]), 1); + assert.strictEqual (compareNatural(sparse([2]), [2]), 1); + assert.strictEqual (compareNatural(sparse([2]), matrix([2])), 1); + + // string and number + assert.strictEqual (compareNatural('0', 0), 1); }); it('should perform natural comparison for two strings', function() { - assert.equal(compareNatural('0', 0), 0); - assert.equal(compareNatural('abd', 'abc'), 1); assert.equal(compareNatural('abc', 'abc'), 0); assert.equal(compareNatural('abc', 'abd'), -1); - assert.equal(compareNatural('10', '2'), 1); + // no natural sorting here + assert.equal(compareNatural('10', '2'), -1); }); - // TODO: test deterministic ordering of mixed types: number, bignumber, unit, complex, ... + it('should compare arrays', function () { + // different number of dimensions + // Note: for arrays we don't compare the number of dimensions! + assert.strictEqual(compareNatural([[2]], [1]), -1); - // TODO: compareNatural for Array - describe.skip('Array', function () { - - it('should compare array - scalar', function () { - assert.deepEqual(compareNatural('B', ['A', 'B', 'C']), [1, 0, -1]); - assert.deepEqual(compareNatural(['A', 'B', 'C'], 'B'), [-1, 0, 1]); - }); - - it('should compare array - array', function () { - assert.deepEqual(compareNatural([[1, 2, 0], [-1, 0, 2]], [[3, -1, 0], [-2, 1, 0]]), [[-1, 1, 0], [1, -1, 1]]); - }); - - it('should compare array - dense matrix', function () { - assert.deepEqual(compareNatural([[1, 2, 0], [-1, 0, 2]], matrix([[3, -1, 0], [-2, 1, 0]])), matrix([[-1, 1, 0], [1, -1, 1]])); - }); - - it('should compare array - sparse matrix', function () { - assert.deepEqual(compareNatural([[1, 2, 0], [-1, 0, 2]], sparse([[3, -1, 0], [-2, 1, 0]])), matrix([[-1, 1, 0], [1, -1, 1]])); - }); + // different size + assert.strictEqual(compareNatural([[2,3]], [[4]]), 1); + + // different content + assert.strictEqual(compareNatural([[2,3]], [[2,4]]), -1); + + // equal + assert.strictEqual(compareNatural([[2,3], [5,6]], [[2,3], [5,6]]), 0); }); - // TODO: compareNatural for DenseMatrix - describe.skip('DenseMatrix', function () { + it('should compare dense matrices', function () { + // different number of dimensions + assert.strictEqual(compareNatural(matrix([[2]]), matrix([1])), 1); - it('should compare dense matrix - scalar', function () { - assert.deepEqual(compareNatural('B', matrix(['A', 'B', 'C'])), matrix([1, 0, -1])); - assert.deepEqual(compareNatural(matrix(['A', 'B', 'C']), 'B'), matrix([-1, 0, 1])); - }); + // different size + assert.strictEqual(compareNatural(matrix([[2,3]]), matrix([[4]])), 1); - it('should compare dense matrix - array', function () { - assert.deepEqual(compareNatural(matrix([[1, 2, 0], [-1, 0, 2]]), [[3, -1, 0], [-2, 1, 0]]), matrix([[-1, 1, 0], [1, -1, 1]])); - }); + // different content + assert.strictEqual(compareNatural(matrix([[2,3]]), matrix([[2,4]])), -1); - it('should compare dense matrix - dense matrix', function () { - assert.deepEqual(compareNatural(matrix([[1, 2, 0], [-1, 0, 2]]), matrix([[3, -1, 0], [-2, 1, 0]])), matrix([[-1, 1, 0], [1, -1, 1]])); - }); - - it('should compare dense matrix - sparse matrix', function () { - assert.deepEqual(compareNatural(matrix([[1, 2, 0], [-1, 0, 2]]), sparse([[3, -1, 0], [-2, 1, 0]])), matrix([[-1, 1, 0], [1, -1, 1]])); - }); + // equal + assert.strictEqual(compareNatural(matrix([[2,3], [5,6]]), matrix([[2,3], [5,6]])), 0); }); - // TODO: compareNatural for SparseMatrix - describe.skip('SparseMatrix', function () { + it('should compare sparse matrices', function () { + // different number of dimensions + assert.strictEqual(compareNatural(sparse([[2]]), sparse([1])), 1); - it('should compare sparse matrix - scalar', function () { - assert.deepEqual(compareNatural('B', sparse([['A', 'B'], ['C', 'X']])), matrix([[1, 0], [-1, -1]])); - assert.deepEqual(compareNatural(sparse([['A', 'B'], ['C', 'X']]), 'B'), matrix([[-1, 0], [1, 1]])); - }); + // different size + assert.strictEqual(compareNatural(sparse([[2,3]]), sparse([[4]])), 1); - it('should compare sparse matrix - array', function () { - assert.deepEqual(compareNatural(sparse([[1, 2, 0], [-1, 0, 2]]), [[3, -1, 0], [-2, 1, 0]]), matrix([[-1, 1, 0], [1, -1, 1]])); - }); + // different content + assert.strictEqual(compareNatural(sparse([[2,3]]), sparse([[2,4]])), -1); - it('should compare sparse matrix - dense matrix', function () { - assert.deepEqual(compareNatural(sparse([[1, 2, 0], [-1, 0, 2]]), matrix([[3, -1, 0], [-2, 1, 0]])), matrix([[-1, 1, 0], [1, -1, 1]])); - }); + // equal + assert.strictEqual(compareNatural(sparse([[2,3], [5,6]]), sparse([[2,3], [5,6]])), 0); + }); - it('should compare sparse matrix - sparse matrix', function () { - assert.deepEqual(compareNatural(sparse([[1, 2, 0], [-1, 0, 2]]), sparse([[3, -1, 0], [-2, 1, 0]])), sparse([[-1, 1, 0], [1, -1, 1]])); - }); + it('should compare objects', function () { + // different number of keys + assert.strictEqual(compareNatural({a:2, b:3}, {a:2}), 1); + + // different keys + assert.strictEqual(compareNatural({b:3}, {a:2}), 1); + + // different values + assert.strictEqual(compareNatural({a:3}, {a:2}), 1); + + // equal + assert.strictEqual(compareNatural({a:2, b:3}, {a:2, b:3}), 0); + + // nesting + assert.strictEqual(compareNatural({a:2, b: {c: 4}}, {a:2, b: {c: 3}}), 1); + assert.strictEqual(compareNatural({a:2, b: {c: 3}}, {a:2, b: {c: 4}}), -1); }); it('should apply configuration option epsilon', function() { @@ -199,35 +202,10 @@ describe('compareNatural', function() { assert.equal(mymath.compareNatural(math.bignumber(1), math.bignumber(0.991)), 0); }); - describe('Complex Numbers', function () { - - it('should naturally compare complex numbers', function() { - assert.equal(compareNatural(complex(1,1), complex(1,1)), 0); - assert.equal(compareNatural(complex(2,1), complex(1,2)), 1); - assert.equal(compareNatural(complex(0,1), complex(1,2)), -1); - }); - - it('should naturally compare complex number and number', function() { - assert.equal(compareNatural(complex(1,0), 1), 0); - assert.equal(compareNatural(complex(2,1), 1), 1); - assert.equal(compareNatural(complex(0,1), 1), -1); - assert.equal(compareNatural(1, complex(1,0)), 0); - assert.equal(compareNatural(1, complex(2,1)), -1); - assert.equal(compareNatural(1, complex(0,1)), 1); - }); - - it('should naturally compare complex number and bignumber', function() { - assert.equal(compareNatural(complex(1,0), math.bignumber(1)), 0); - assert.equal(compareNatural(complex(2,1), math.bignumber(1)), 1); - assert.equal(compareNatural(complex(0,1), math.bignumber(1)), -1); - assert.equal(compareNatural(math.bignumber(1), complex(1,0)), 0); - assert.equal(compareNatural(math.bignumber(1), complex(2,1)), -1); - assert.equal(compareNatural(math.bignumber(1), complex(0,1)), 1); - }); - }); - - it('should throw an error if matrices are different sizes', function() { - assert.throws(function () {compareNatural([1,4,6], [3,4]);}); + it('should compare complex numbers', function() { + assert.equal(compareNatural(complex(1,1), complex(1,1)), 0); + assert.equal(compareNatural(complex(2,1), complex(1,2)), 1); + assert.equal(compareNatural(complex(0,1), complex(1,2)), -1); }); it('should throw an error in case of invalid number of arguments', function() { diff --git a/test/function/set/setCartesian.test.js b/test/function/set/setCartesian.test.js index bc8a8849d..e5d32a76b 100644 --- a/test/function/set/setCartesian.test.js +++ b/test/function/set/setCartesian.test.js @@ -12,7 +12,7 @@ describe('setCartesian', function () { }); it('should return the cartesian product of two sets with mixed content', function () { - assert.deepEqual(math.setCartesian([1, math.complex(2, 3)], [3]), [[1, 3], [math.complex(2, 3), 3]]); + assert.deepEqual(math.setCartesian([1, math.complex(2, 3)], [3]), [[math.complex(2, 3), 3], [1, 3]]); }); it('should return the cartesian product of two multisets', function () { diff --git a/test/function/set/setDistinct.test.js b/test/function/set/setDistinct.test.js index fa5ccd419..72f16bbf4 100644 --- a/test/function/set/setDistinct.test.js +++ b/test/function/set/setDistinct.test.js @@ -11,7 +11,7 @@ describe('setDistinct', function () { it('should return the distinct elements of a multiset', function () { assert.deepEqual(math.setDistinct([1, 1, 2, 2]), [1, 2]); assert.deepEqual(math.setDistinct([1, 2, 1, 2]), [1, 2]); - assert.deepEqual(math.setDistinct([1, 2, math.complex(3,3), 2, math.complex(3,3)]), [1, 2, math.complex(3,3)]); + assert.deepEqual(math.setDistinct([1, 2, math.complex(3,3), 2, math.complex(3,3)]), [math.complex(3,3), 1, 2]); }); it('should return the same type of output as the inputs', function() { diff --git a/test/function/set/setIntersect.test.js b/test/function/set/setIntersect.test.js index 5275d4e68..974158ff2 100644 --- a/test/function/set/setIntersect.test.js +++ b/test/function/set/setIntersect.test.js @@ -8,7 +8,7 @@ describe('setIntersect', function () { assert.deepEqual(math.setIntersect([1, 2], [3, 4]), []); assert.deepEqual(math.setIntersect(["a", "b", "c"], ["c", "d"]), ["c"]); assert.deepEqual(math.setIntersect([1, math.complex(2,2), math.complex(3,3)], - [math.complex(3,3), 1]), [1, math.complex(3,3)]); + [math.complex(3,3), 1]), [math.complex(3,3), 1]); assert.deepEqual(math.setIntersect([], [3, 4]), []); assert.deepEqual(math.setIntersect([], []), []); }); diff --git a/test/function/set/setPowerset.test.js b/test/function/set/setPowerset.test.js index 280b03c89..c7d9e5b13 100644 --- a/test/function/set/setPowerset.test.js +++ b/test/function/set/setPowerset.test.js @@ -6,7 +6,7 @@ describe('setPowerset', function () { it('should return the powerset of a set', function () { assert.deepEqual(math.setPowerset([1, 2]), [[], [1], [2], [1, 2]]); assert.deepEqual(math.setPowerset([1, math.complex(2,2)]), - [[], [1], [math.complex(2,2)], [1, math.complex(2,2)]]); + [[], [math.complex(2,2)], [1], [math.complex(2,2), 1]]); assert.deepEqual(math.setPowerset([]), []); });