Back to compareNatural WIP (see #837)

This commit is contained in:
jos 2017-06-25 21:02:59 +02:00
parent 08695ef1c7
commit 0557e7ae1f
18 changed files with 291 additions and 301 deletions

View File

@ -5,7 +5,7 @@ module.exports = {
'compareNatural(x, y)'
],
'description':
'Compare two values in a natural way. For numeric values, returns 1 if x is larger than y, -1 if x is smaller than y, and 0 if x and y are equal. Strings and complex numbers are compared in a natural way.',
'Compare two values in a natural way.',
'examples': [
'compare(2, 3)',
'compare(3, 2)',

View File

@ -8,7 +8,7 @@ function factory (type, config, load, typed) {
var compareDesc = function (a, b) {
return -compareAsc(a, b);
};
var deepStrictCompare = load(require('../relational/deepStrictCompare'));
var compareNatural = load(require('../relational/compareNatural'));
/**
* Sort the items in a matrix.
@ -33,7 +33,7 @@ function factory (type, config, load, typed) {
* filter, forEach, map, compare, compareNatural
*
* @param {Matrix | Array} x A one dimensional matrix or array to sort
* @param {Function | 'asc' | 'desc' | 'deep'} [compare='asc']
* @param {Function | 'asc' | 'desc' | 'natural'} [compare='asc']
* 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.
@ -74,8 +74,8 @@ function factory (type, config, load, typed) {
sort.toTex = undefined; // use default template
/**
* Get the comparator for given order ('asc', 'desc', 'deep')
* @param {'asc' | 'desc' | 'deep'} order
* Get the comparator for given order ('asc', 'desc', 'natural')
* @param {'asc' | 'desc' | 'natural'} order
* @return {Function} Returns a _comparator function
*/
function _comparator (order) {
@ -85,11 +85,11 @@ function factory (type, config, load, typed) {
else if (order === 'desc') {
return compareDesc;
}
else if (order === 'deep') {
return deepStrictCompare;
else if (order === 'natural') {
return compareNatural;
}
else {
throw new Error('String "asc", "desc", or "deep" expected');
throw new Error('String "asc", "desc", or "natural" expected');
}
}

View File

@ -1,9 +1,11 @@
'use strict';
var naturalSort = require('javascript-natural-sort');
var isCollection = require('../../utils/collection/isCollection');
function factory (type, config, load, typed) {
var getTypeOf = load(require('../utils/typeof'));
var isNumeric = load(require('../utils/isNumeric'));
var matrix = load(require('../../type/matrix/function/matrix'));
var compare = load(require('./compare'));
@ -30,24 +32,24 @@ function factory (type, config, load, typed) {
*
* Syntax:
*
* math.deepStrictCompare(x, y)
* math.compareNatural(x, y)
*
* Examples:
*
* math.deepStrictCompare(6, 1); // returns 1
* math.deepStrictCompare(2, 3); // returns -1
* math.deepStrictCompare(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.deepStrictCompare(a, b); // returns 1
* math.compareNatural(a, b); // returns 1
*
* var c = math.complex('2 + 3i');
* var d = math.complex('2 + 4i');
* math.deepStrictCompare(c, d); // returns -1
* math.compareNatural(c, d); // returns -1
*
* math.deepStrictCompare([1, 2, 3], [1, 2]); // returns 1
* math.deepStrictCompare([1, 2], [1, 2]); // returns 0
* math.compareNatural([1, 2, 3], [1, 2]); // returns 1
* math.compareNatural([1, 2], [1, 2]); // returns 0
*
* See also:
*
@ -57,7 +59,7 @@ function factory (type, config, load, typed) {
* @param {*} y Second value to compare
* @return {number} Returns the result of the comparison: 1, 0 or -1.
*/
var deepStrictCompare = typed('deepStrictCompare', {
var compareNatural = typed('compareNatural', {
'any, any': function (x, y) {
var typeX = getTypeOf(x);
var typeY = getTypeOf(y);
@ -65,9 +67,11 @@ function factory (type, config, load, typed) {
// in case of different types, order by name of type
// i.e. 'BigNumber' < 'Complex'
if (typeX !== typeY) {
return compareString(typeX, typeY);
return naturalSort(typeX, typeY);
}
// FIXME: compare all numeric types first by value and then by type
if (typeX === 'number') {
return compareNumbers(x, y);
}
@ -77,7 +81,7 @@ function factory (type, config, load, typed) {
}
if (typeX === 'Fraction') {
return compareFractions(x, y);
return compareFractions(x, y).valueOf();
}
if (typeX === 'Complex') {
@ -85,8 +89,12 @@ function factory (type, config, load, typed) {
}
if (typeX === 'Unit') {
// FIXME: implement ordering for units with different base
return compareUnits(x, y);
if (x.equalBase(y)) {
return compareNatural(x.value, y.value);
}
// compare by units
return compareArrays(x.formatUnits(), y.formatUnits());
}
if (typeX === 'boolean') {
@ -94,13 +102,14 @@ function factory (type, config, load, typed) {
}
if (typeX === 'string') {
return compareString(x, y);
return naturalSort(x, y);
}
// FIXME: compare matrices and arrays first by their values and then by type
if (typeX === 'Matrix') {
// can be SparseMatrix or DenseMatrix
if (x.type !== y.type) {
return compareString(x.type, y.type)
return naturalSort(x.type, y.type)
}
if (x.type === 'DenseMatrix') {
return compareDenseMatrices(x, y);
@ -131,7 +140,7 @@ function factory (type, config, load, typed) {
}
});
deepStrictCompare.toTex = undefined; // use default template
compareNatural.toTex = undefined; // use default template
/**
* Compare two Arrays
@ -150,7 +159,7 @@ function factory (type, config, load, typed) {
// compare each value
for (var i = 0; i < a.length; i++) {
var v = deepStrictCompare(a[i], b[i]);
var v = compareNatural(a[i], b[i]);
if (v !== 0) {
return v;
}
@ -230,8 +239,8 @@ function factory (type, config, load, typed) {
if (keysA.length < keysB.length) { return -1; }
// compare keys
keysA.sort(compareString)
keysB.sort(compareString)
keysA.sort(naturalSort)
keysB.sort(naturalSort)
var c = compareArrays(keysA, keysB);
if (c !== 0) {
return c;
@ -239,7 +248,7 @@ function factory (type, config, load, typed) {
// compare values
for (var i = 0; i < keysA.length; i++) {
var v = deepStrictCompare(a[keysA[i]], b[keysB[i]]);
var v = compareNatural(a[keysA[i]], b[keysB[i]]);
if (v !== 0) {
return v;
}
@ -248,17 +257,7 @@ function factory (type, config, load, typed) {
return 0;
}
return deepStrictCompare;
}
/**
* 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;
return compareNatural;
}
/**
@ -286,5 +285,5 @@ function compareComplexNumbers (a, b) {
return 0;
}
exports.name = 'deepStrictCompare';
exports.name = 'compareNatural';
exports.factory = factory;

View File

@ -1,6 +1,6 @@
module.exports = [
require('./compare'),
require('./deepStrictCompare'),
require('./compareNatural'),
require('./deepEqual'),
require('./equal'),
require('./larger'),

View File

@ -7,7 +7,7 @@ function factory (type, config, load, typed) {
var matrix = load(require('../../type/matrix/DenseMatrix'));
var size = load(require('../matrix/size'));
var subset = load(require('../matrix/subset'));
var deepStrictCompare = load(require('../relational/deepStrictCompare'));
var compareNatural = load(require('../relational/compareNatural'));
/**
* Create the cartesian product of two (multi)sets.
@ -35,8 +35,8 @@ function factory (type, config, load, typed) {
var result = [];
}
else {
var b1 = flatten(Array.isArray(a1) ? a1 : a1.toArray()).sort(deepStrictCompare);
var b2 = flatten(Array.isArray(a2) ? a2 : a2.toArray()).sort(deepStrictCompare);
var b1 = flatten(Array.isArray(a1) ? a1 : a1.toArray()).sort(compareNatural);
var b2 = flatten(Array.isArray(a2) ? a2 : a2.toArray()).sort(compareNatural);
var result = [];
for (var i=0; i<b1.length; i++) {
for (var j=0; j<b2.length; j++) {

View File

@ -10,7 +10,7 @@ function factory (type, config, load, typed) {
var matrix = load(require('../../type/matrix/DenseMatrix'));
var size = load(require('../matrix/size'));
var subset = load(require('../matrix/subset'));
var deepStrictCompare = load(require('../relational/deepStrictCompare'));
var compareNatural = load(require('../relational/compareNatural'));
/**
* Create the difference of two (multi)sets. (Every element of set1, that is not the element of set2.)
@ -42,8 +42,8 @@ function factory (type, config, load, typed) {
return flatten(a1.toArray());
}
else {
var b1 = identify(flatten(Array.isArray(a1) ? a1: a1.toArray()).sort(deepStrictCompare));
var b2 = identify(flatten(Array.isArray(a2) ? a2: a2.toArray()).sort(deepStrictCompare));
var b1 = identify(flatten(Array.isArray(a1) ? a1: a1.toArray()).sort(compareNatural));
var b2 = identify(flatten(Array.isArray(a2) ? a2: a2.toArray()).sort(compareNatural));
var result = [];
var inb2;
for (var i=0; i<b1.length; i++) {

View File

@ -8,7 +8,7 @@ function factory (type, config, load, typed) {
var matrix = load(require('../../type/matrix/DenseMatrix'));
var size = load(require('../matrix/size'));
var subset = load(require('../matrix/subset'));
var deepStrictCompare = load(require('../relational/deepStrictCompare'));
var compareNatural = load(require('../relational/compareNatural'));
/**
* Collect the distinct elements of a multiset.
@ -35,7 +35,7 @@ function factory (type, config, load, typed) {
var result = [];
}
else {
var b = flatten(Array.isArray(a) ? a : a.toArray()).sort(deepStrictCompare);
var b = flatten(Array.isArray(a) ? a : a.toArray()).sort(compareNatural);
var result = [];
result.push(b[0]);
for (var i=1; i<b.length; i++) {

View File

@ -10,7 +10,7 @@ function factory (type, config, load, typed) {
var matrix = load(require('../../type/matrix/DenseMatrix'));
var size = load(require('../matrix/size'));
var subset = load(require('../matrix/subset'));
var deepStrictCompare = load(require('../relational/deepStrictCompare'));
var compareNatural = load(require('../relational/compareNatural'));
/**
* Create the intersection of two (multi)sets.
@ -39,8 +39,8 @@ function factory (type, config, load, typed) {
var result = [];
}
else {
var b1 = identify(flatten(Array.isArray(a1) ? a1 : a1.toArray()).sort(deepStrictCompare));
var b2 = identify(flatten(Array.isArray(a2) ? a2 : a2.toArray()).sort(deepStrictCompare));
var b1 = identify(flatten(Array.isArray(a1) ? a1 : a1.toArray()).sort(compareNatural));
var b2 = identify(flatten(Array.isArray(a2) ? a2 : a2.toArray()).sort(compareNatural));
var result = [];
for (var i=0; i<b1.length; i++) {
for (var j=0; j<b2.length; j++) {

View File

@ -8,7 +8,7 @@ function factory (type, config, load, typed) {
var index = load(require('../../type/matrix/MatrixIndex'));
var size = load(require('../matrix/size'));
var subset = load(require('../matrix/subset'));
var deepStrictCompare = load(require('../relational/deepStrictCompare'));
var compareNatural = load(require('../relational/compareNatural'));
/**
* Decide whether a (multi)set is a subset of another (multi)set. (Every element of set1 is the element of set2.)
@ -39,8 +39,8 @@ function factory (type, config, load, typed) {
else if (subset(size(a2), new index(0)) === 0) { // anything is not a subset of empty
return false;
}
var b1 = identify(flatten(Array.isArray(a1) ? a1 : a1.toArray()).sort(deepStrictCompare));
var b2 = identify(flatten(Array.isArray(a2) ? a2 : a2.toArray()).sort(deepStrictCompare));
var b1 = identify(flatten(Array.isArray(a1) ? a1 : a1.toArray()).sort(compareNatural));
var b2 = identify(flatten(Array.isArray(a2) ? a2 : a2.toArray()).sort(compareNatural));
var inb2;
for (var i=0; i<b1.length; i++) {
inb2 = false;

View File

@ -6,7 +6,7 @@ function factory (type, config, load, typed) {
var index = load(require('../../type/matrix/MatrixIndex'));
var size = load(require('../matrix/size'));
var subset = load(require('../matrix/subset'));
var deepStrictCompare = load(require('../relational/deepStrictCompare'));
var compareNatural = load(require('../relational/compareNatural'));
/**
* Create the powerset of a (multi)set. (The powerset contains very possible subsets of a (multi)set.)
@ -32,7 +32,7 @@ function factory (type, config, load, typed) {
if (subset(size(a), new index(0)) === 0) { // if empty, return empty
return [];
}
var b = flatten(Array.isArray(a) ? a : a.toArray()).sort(deepStrictCompare);
var b = flatten(Array.isArray(a) ? a : a.toArray()).sort(compareNatural);
var result = [];
var number = 0;
while (number.toString(2).length <= b.length) {

View File

@ -4,7 +4,7 @@ var flatten = require('../../utils/array').flatten;
function factory (type, config, load, typed) {
var equal = load(require('../relational/equal'));
var deepStrictCompare = load(require('../relational/deepStrictCompare'));
var compareNatural = load(require('../relational/compareNatural'));
/**
* Count the number of elements of a (multi)set. When a second parameter is 'true', count only the unique values.
@ -35,7 +35,7 @@ function factory (type, config, load, typed) {
return Array.isArray(a) ? flatten(a).length : flatten(a.toArray()).length;
}
else {
var b = flatten(Array.isArray(a) ? a : a.toArray()).sort(deepStrictCompare);
var b = flatten(Array.isArray(a) ? a : a.toArray()).sort(compareNatural);
var count = 1;
for (var i=1; i<b.length; i++) {
if (!equal(b[i], b[i-1])) {

View File

@ -6,7 +6,6 @@ function factory (type, config, load, typed) {
var index = load(require('../../type/matrix/MatrixIndex'));
var concat = load(require('../matrix/concat'));
var size = load(require('../matrix/size'));
var sort = load(require('../matrix/sort'));
var subset = load(require('../matrix/subset'));
var setIntersect = load(require('../set/setIntersect'));
var setSymDifference = load(require('../set/setSymDifference'));

View File

@ -28,12 +28,12 @@ exports.type = function(x) {
if (type === 'object') {
if (x === null) return 'null';
if (x instanceof Boolean) return 'boolean';
if (x instanceof Number) return 'number';
if (x instanceof String) return 'string';
if (Array.isArray(x)) return 'Array';
if (x instanceof Date) return 'Date';
if (x instanceof RegExp) return 'RegExp';
if (x instanceof Boolean) return 'boolean';
if (x instanceof Number) return 'number';
if (x instanceof String) return 'string';
return 'Object';
}
@ -42,13 +42,3 @@ exports.type = function(x) {
return type;
};
/**
* Test whether a value is a scalar
* @param x
* @return {boolean} Returns true when x is a scalar, returns false when
* x is a Matrix or Array.
*/
exports.isScalar = function (x) {
return !((x && x.isMatrix) || Array.isArray(x));
};

10
package-lock.json generated
View File

@ -1883,6 +1883,11 @@
}
}
},
"javascript-natural-sort": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
"integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k="
},
"js-yaml": {
"version": "3.8.4",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz",
@ -2294,11 +2299,6 @@
"integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=",
"dev": true
},
"natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
},
"ndarray": {
"version": "1.0.18",
"resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.18.tgz",

View File

@ -86,6 +86,7 @@
"complex.js": "2.0.4",
"decimal.js": "7.2.1",
"fraction.js": "4.0.1",
"javascript-natural-sort": "0.7.1",
"seed-random": "2.2.0",
"tiny-emitter": "2.0.0",
"typed-function": "0.10.5"

View File

@ -25,8 +25,8 @@ describe('sort', function() {
assert.deepEqual(math.sort([5,10,1], 'desc'), [10,5,1]);
});
it('should deep sort an array', function() {
assert.deepEqual(math.sort([{a:4}, {a:2}, {a:3}], 'deep'), [{a:2}, {a:3}, {a:4}]);
it('should sort an array naturally', function() {
assert.deepEqual(math.sort([{a:4}, {a:2}, {a:3}], 'natural'), [{a:2}, {a:3}, {a:4}]);
});
it('should sort an array with a custom compare function', function() {
@ -44,7 +44,7 @@ describe('sort', function() {
it('should throw an error if called with unsupported type', function() {
assert.throws(function() { math.sort(2) });
assert.throws(function() { math.sort('string') });
assert.throws(function() { math.sort([], 'string') }, /String "asc", "desc", or "deep" expected/);
assert.throws(function() { math.sort([], 'string') }, /String "asc", "desc", or "natural" expected/);
assert.throws(function() { math.sort([], {}) });
});

View File

@ -0,0 +1,221 @@
// test compareNatural
var assert = require('assert');
var math = require('../../../index');
var bignumber = math.bignumber;
var complex = math.complex;
var matrix = math.matrix;
var sparse = math.sparse;
var unit = math.unit;
var compareNatural = math.compareNatural;
describe('compareNatural', 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);
assert.equal(compareNatural(0, 0), 0);
assert.equal(compareNatural(-2, 2), -1);
assert.equal(compareNatural(-2, -3), 1);
assert.equal(compareNatural(-3, -2), -1);
});
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);
assert.equal(compareNatural(Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY), 1);
assert.equal(compareNatural(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY), -1);
assert.equal(compareNatural(Number.POSITIVE_INFINITY, 2.0), 1);
assert.equal(compareNatural(2.0, Number.POSITIVE_INFINITY), -1);
assert.equal(compareNatural(Number.NEGATIVE_INFINITY, 2.0), -1);
assert.equal(compareNatural(2.0, Number.NEGATIVE_INFINITY), 1);
// floating point numbers
assert.equal(compareNatural(0.3 - 0.2, 0.1), 0);
});
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 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);
assert.equal(typeof compareNatural(bignumber(-2), bignumber(2)), 'number');
});
it('should compare two fractions', function() {
var a = math.fraction(1,3);
var b = math.fraction(1,6);
assert.equal(typeof compareNatural(a, b), 'number');
assert.equal(a.toString(), '0.(3)');
assert.equal(b.toString(), '0.1(6)');
assert.equal(compareNatural(math.fraction(3), math.fraction(2)).valueOf(), 1);
assert.equal(compareNatural(math.fraction(2), math.fraction(3)).valueOf(), -1);
assert.equal(compareNatural(math.fraction(3), math.fraction(3)).valueOf(), 0);
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 compare two measures of the same unit', function() {
assert.strictEqual(compareNatural(unit('100cm'), unit('10inch')), 1);
assert.strictEqual(compareNatural(unit('99cm'), unit('1m')), -1);
assert.strictEqual(compareNatural(unit('1m'), unit('1m')), 0);
assert.strictEqual(compareNatural(unit('1m'), unit('100 cm')), 0);
assert.strictEqual(compareNatural(unit('101cm'), unit('1m')), 1);
});
it('should compare two measures of different unit', function() {
assert.strictEqual(compareNatural(math.unit(5, 'km'), math.unit(100, 'gram')), -1);
assert.strictEqual(compareNatural(math.unit(4, 'km/h'), math.unit(2, 'm/s^2')), -1);
assert.strictEqual(compareNatural(math.unit(2, 'm/s^2'), math.unit(4, 'km/h')), 1);
});
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.strictEqual(compareNatural('abd', 'abc'), 1);
assert.strictEqual(compareNatural('abc', 'abc'), 0);
assert.strictEqual(compareNatural('abc', 'abd'), -1);
// natural sorting of strings
assert.strictEqual(compareNatural('10', '2'), 1);
});
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);
// 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);
});
it('should compare dense matrices', function () {
// different number of dimensions
assert.strictEqual(compareNatural(matrix([[2]]), matrix([1])), 1);
// different size
assert.strictEqual(compareNatural(matrix([[2,3]]), matrix([[4]])), 1);
// different content
assert.strictEqual(compareNatural(matrix([[2,3]]), matrix([[2,4]])), -1);
// equal
assert.strictEqual(compareNatural(matrix([[2,3], [5,6]]), matrix([[2,3], [5,6]])), 0);
});
it('should compare sparse matrices', function () {
// different number of dimensions
assert.strictEqual(compareNatural(sparse([[2]]), sparse([1])), 1);
// different size
assert.strictEqual(compareNatural(sparse([[2,3]]), sparse([[4]])), 1);
// different content
assert.strictEqual(compareNatural(sparse([[2,3]]), sparse([[2,4]])), -1);
// equal
assert.strictEqual(compareNatural(sparse([[2,3], [5,6]]), sparse([[2,3], [5,6]])), 0);
});
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() {
var mymath = math.create();
assert.equal(mymath.compareNatural(1, 0.991), 1);
assert.equal(mymath.compareNatural(math.bignumber(1), math.bignumber(0.991)).valueOf(), 1);
mymath.config({epsilon: 1e-2});
assert.equal(mymath.compareNatural(1, 0.991), 0);
assert.equal(mymath.compareNatural(math.bignumber(1), math.bignumber(0.991)), 0);
});
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() {
assert.throws(function () {compareNatural(1);}, /TypeError: Too few arguments/);
assert.throws(function () {compareNatural(1, 2, 3);}, /TypeError: Too many arguments/);
});
it('should LaTeX compare', function () {
var expression = math.parse('compareNatural(1,2)');
assert.equal(expression.toTex(), '\\mathrm{compareNatural}\\left(1,2\\right)');
});
});

View File

@ -1,220 +0,0 @@
// test deepStrictCompare
var assert = require('assert'),
math = require('../../../index'),
bignumber = math.bignumber,
complex = math.complex,
matrix = math.matrix,
sparse = math.sparse,
unit = math.unit,
deepStrictCompare = math.deepStrictCompare;
describe('deepStrictCompare', function() {
it('should compare two numbers correctly', function() {
assert.equal(deepStrictCompare(2, 3), -1);
assert.equal(deepStrictCompare(2, 2), 0);
assert.equal(deepStrictCompare(2, 1), 1);
assert.equal(deepStrictCompare(0, 0), 0);
assert.equal(deepStrictCompare(-2, 2), -1);
assert.equal(deepStrictCompare(-2, -3), 1);
assert.equal(deepStrictCompare(-3, -2), -1);
});
it('should compare two floating point numbers correctly', function() {
// Infinity
assert.equal(deepStrictCompare(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY), 0);
assert.equal(deepStrictCompare(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY), 0);
assert.equal(deepStrictCompare(Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY), 1);
assert.equal(deepStrictCompare(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY), -1);
assert.equal(deepStrictCompare(Number.POSITIVE_INFINITY, 2.0), 1);
assert.equal(deepStrictCompare(2.0, Number.POSITIVE_INFINITY), -1);
assert.equal(deepStrictCompare(Number.NEGATIVE_INFINITY, 2.0), -1);
assert.equal(deepStrictCompare(2.0, Number.NEGATIVE_INFINITY), 1);
// floating point numbers
assert.equal(deepStrictCompare(0.3 - 0.2, 0.1), 0);
});
it('should compare two booleans', function() {
assert.equal(deepStrictCompare(true, true), 0);
assert.equal(deepStrictCompare(true, false), 1);
assert.equal(deepStrictCompare(false, true), -1);
assert.equal(deepStrictCompare(false, false), 0);
});
it('should compare bignumbers', function() {
assert.strictEqual(deepStrictCompare(bignumber(2), bignumber(3)), -1);
assert.strictEqual(deepStrictCompare(bignumber(2), bignumber(2)), 0);
assert.strictEqual(deepStrictCompare(bignumber(3), bignumber(2)), 1);
assert.strictEqual(deepStrictCompare(bignumber(0), bignumber(0)), 0);
assert.strictEqual(deepStrictCompare(bignumber(-2), bignumber(2)), -1);
});
it('should compare two fractions', function() {
var a = math.fraction(1,3);
var b = math.fraction(1,6);
assert(deepStrictCompare(a, b) instanceof math.type.Fraction);
assert.equal(a.toString(), '0.(3)');
assert.equal(b.toString(), '0.1(6)');
assert.equal(deepStrictCompare(math.fraction(3), math.fraction(2)).valueOf(), 1);
assert.equal(deepStrictCompare(math.fraction(2), math.fraction(3)).valueOf(), -1);
assert.equal(deepStrictCompare(math.fraction(3), math.fraction(3)).valueOf(), 0);
assert.strictEqual(deepStrictCompare(math.add(math.fraction(0.1), math.fraction(0.2)), math.fraction(0.3)).valueOf(), 0); // this would fail with numbers
});
it('should compare two measures of the same unit', function() {
assert.equal(deepStrictCompare(unit('100cm'), unit('10inch')), 1);
assert.equal(deepStrictCompare(unit('99cm'), unit('1m')), -1);
assert.equal(deepStrictCompare(unit('1m'), unit('1m')), bignumber(0));
assert.equal(deepStrictCompare(unit('101cm'), unit('1m')), 1);
});
it('should throw an error for two measures of different units', function() {
// TODO: compare units with different base
assert.throws(function () {deepStrictCompare(math.unit(5, 'km'), math.unit(100, 'gram'));});
});
it('should compare mixed types (by type name)', function() {
// booleans
assert.strictEqual (deepStrictCompare(2, true), 1);
assert.strictEqual (deepStrictCompare(0, false), 1);
assert.strictEqual (deepStrictCompare(true, 2), -1);
assert.strictEqual (deepStrictCompare(false, 2), -1);
// null
assert.strictEqual (deepStrictCompare(2, null), 1);
assert.strictEqual (deepStrictCompare(null, 2), -1);
// undefined
assert.strictEqual (deepStrictCompare(2, undefined), -1);
assert.strictEqual (deepStrictCompare(undefined, 2), 1);
// fractions and units
assert.strictEqual (deepStrictCompare(1, math.fraction(1,3)), 1);
assert.strictEqual (deepStrictCompare(math.fraction(1,3), 1), -1);
// units and numbers
assert.strictEqual (deepStrictCompare(unit('100cm'), 22), -1);
assert.strictEqual (deepStrictCompare(22, unit('100cm')), 1);
// units and bignumbers
assert.strictEqual (deepStrictCompare(unit('100cm'), bignumber(22)), 1);
assert.strictEqual (deepStrictCompare(bignumber(22), unit('100cm')), -1);
// numbers and complex
assert.strictEqual (deepStrictCompare(1, complex(2,3)), 1);
assert.strictEqual (deepStrictCompare(complex(2,3), 1), -1);
// numbers and bignumbers
assert.strictEqual (deepStrictCompare(bignumber(2), 3), -1);
assert.strictEqual (deepStrictCompare(2, bignumber(2)), 1);
// array, DenseMatrix, SparseMatrix
assert.strictEqual (deepStrictCompare(matrix([2]), [2]), 1);
assert.strictEqual (deepStrictCompare(sparse([2]), [2]), 1);
assert.strictEqual (deepStrictCompare(sparse([2]), matrix([2])), 1);
// string and number
assert.strictEqual (deepStrictCompare('0', 0), 1);
});
it('should perform natural comparison for two strings', function() {
assert.equal(deepStrictCompare('abd', 'abc'), 1);
assert.equal(deepStrictCompare('abc', 'abc'), 0);
assert.equal(deepStrictCompare('abc', 'abd'), -1);
// no natural sorting here
assert.equal(deepStrictCompare('10', '2'), -1);
});
it('should compare arrays', function () {
// different number of dimensions
// Note: for arrays we don't compare the number of dimensions!
assert.strictEqual(deepStrictCompare([[2]], [1]), -1);
// different size
assert.strictEqual(deepStrictCompare([[2,3]], [[4]]), 1);
// different content
assert.strictEqual(deepStrictCompare([[2,3]], [[2,4]]), -1);
// equal
assert.strictEqual(deepStrictCompare([[2,3], [5,6]], [[2,3], [5,6]]), 0);
});
it('should compare dense matrices', function () {
// different number of dimensions
assert.strictEqual(deepStrictCompare(matrix([[2]]), matrix([1])), 1);
// different size
assert.strictEqual(deepStrictCompare(matrix([[2,3]]), matrix([[4]])), 1);
// different content
assert.strictEqual(deepStrictCompare(matrix([[2,3]]), matrix([[2,4]])), -1);
// equal
assert.strictEqual(deepStrictCompare(matrix([[2,3], [5,6]]), matrix([[2,3], [5,6]])), 0);
});
it('should compare sparse matrices', function () {
// different number of dimensions
assert.strictEqual(deepStrictCompare(sparse([[2]]), sparse([1])), 1);
// different size
assert.strictEqual(deepStrictCompare(sparse([[2,3]]), sparse([[4]])), 1);
// different content
assert.strictEqual(deepStrictCompare(sparse([[2,3]]), sparse([[2,4]])), -1);
// equal
assert.strictEqual(deepStrictCompare(sparse([[2,3], [5,6]]), sparse([[2,3], [5,6]])), 0);
});
it('should compare objects', function () {
// different number of keys
assert.strictEqual(deepStrictCompare({a:2, b:3}, {a:2}), 1);
// different keys
assert.strictEqual(deepStrictCompare({b:3}, {a:2}), 1);
// different values
assert.strictEqual(deepStrictCompare({a:3}, {a:2}), 1);
// equal
assert.strictEqual(deepStrictCompare({a:2, b:3}, {a:2, b:3}), 0);
// nesting
assert.strictEqual(deepStrictCompare({a:2, b: {c: 4}}, {a:2, b: {c: 3}}), 1);
assert.strictEqual(deepStrictCompare({a:2, b: {c: 3}}, {a:2, b: {c: 4}}), -1);
});
it('should apply configuration option epsilon', function() {
var mymath = math.create();
assert.equal(mymath.deepStrictCompare(1, 0.991), 1);
assert.equal(mymath.deepStrictCompare(math.bignumber(1), math.bignumber(0.991)).valueOf(), 1);
mymath.config({epsilon: 1e-2});
assert.equal(mymath.deepStrictCompare(1, 0.991), 0);
assert.equal(mymath.deepStrictCompare(math.bignumber(1), math.bignumber(0.991)), 0);
});
it('should compare complex numbers', function() {
assert.equal(deepStrictCompare(complex(1,1), complex(1,1)), 0);
assert.equal(deepStrictCompare(complex(2,1), complex(1,2)), 1);
assert.equal(deepStrictCompare(complex(0,1), complex(1,2)), -1);
});
it('should throw an error in case of invalid number of arguments', function() {
assert.throws(function () {deepStrictCompare(1);}, /TypeError: Too few arguments/);
assert.throws(function () {deepStrictCompare(1, 2, 3);}, /TypeError: Too many arguments/);
});
it('should LaTeX compare', function () {
var expression = math.parse('deepStrictCompare(1,2)');
assert.equal(expression.toTex(), '\\mathrm{deepStrictCompare}\\left(1,2\\right)');
});
});