[go: up one dir, main page]

Skip to content

Commit

Permalink
Implemented a first version of math.compareNatural
Browse files Browse the repository at this point in the history
  • Loading branch information
josdejong committed Jun 18, 2017
1 parent ac2a542 commit 151bc65
Show file tree
Hide file tree
Showing 13 changed files with 657 additions and 151 deletions.
5 changes: 3 additions & 2 deletions lib/expression/docs/function/matrix/sort.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ module.exports = {
'sort(x)',
'sort(x, compare)'
],
'description': 'Sort the items in a matrix. Compare can be a string "asc" or "desc", or a custom sort function.',
'description': 'Sort the items in a matrix. Compare can be a string "asc", "desc", "natural", or a custom sort function.',
'examples': [
'sort([5, 10, 1])',
'sort(["C", "B", "A", "D"])',
'sortByLength(a, b) = size(a)[1] - size(b)[1]',
'sort(["Langdon", "Tom", "Sara"], sortByLength)'
'sort(["Langdon", "Tom", "Sara"], sortByLength)',
'sort(["10", "1", "2"], "natural")'
],
'seealso': ['map', 'filter', 'forEach']
};
2 changes: 1 addition & 1 deletion lib/expression/docs/function/relational/compare.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ module.exports = {
'compare(2, [1, 2, 3])'
],
'seealso': [
'equal', 'unequal', 'smaller', 'smallerEq', 'largerEq'
'equal', 'unequal', 'smaller', 'smallerEq', 'largerEq', 'compareNatural'
]
};
20 changes: 20 additions & 0 deletions lib/expression/docs/function/relational/compareNatural.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
'name': 'compareNatural',
'category': 'Relational',
'syntax': [
'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.',
'examples': [
'compare(2, 3)',
'compare(3, 2)',
'compare(2, 2)',
'compare(5cm, 40mm)',
'compare("2", "10")',
'compare(2 + 3i, 2 + 4i)'
],
'seealso': [
'equal', 'unequal', 'smaller', 'smallerEq', 'largerEq', 'compare'
]
};
1 change: 1 addition & 0 deletions lib/expression/docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ function factory (construction, config, load, typed) {

// functions - relational
docs.compare = require('./function/relational/compare');
docs.compareNatural = require('./function/relational/compareNatural');
docs.deepEqual = require('./function/relational/deepEqual');
docs['equal'] = require('./function/relational/equal');
docs.larger = require('./function/relational/larger');
Expand Down
28 changes: 16 additions & 12 deletions lib/function/matrix/sort.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ var size = require('../../utils/array').size;

function factory (type, config, load, typed) {
var matrix = load(require('../../type/matrix/function/matrix'));
var asc = load(require('../relational/compare'));
var desc = function (a, b) {
return -asc(a, b);
var compareAsc = load(require('../relational/compare'));
var compareDesc = function (a, b) {
return -compareAsc(a, b);
};
var compareNatural = load(require('../relational/compareNatural'));

/**
* Sort the items in a matrix.
Expand All @@ -29,24 +30,24 @@ function factory (type, config, load, typed) {
*
* See also:
*
* filter, forEach, map
* filter, forEach, map, compare, compareNatural
*
* @param {Matrix | Array} x A one dimensional matrix or array to sort
* @param {Function | 'asc' | 'desc'} [compare='asc']
* An optional _comparator function. The function is called as
* @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.
* @return {Matrix | Array} Returns the sorted matrix.
*/
var sort = typed('sort', {
'Array': function (x) {
_arrayIsVector(x);
return x.sort(asc);
return x.sort(compareAsc);
},

'Matrix': function (x) {
_matrixIsVector(x);
return matrix(x.toArray().sort(asc), x.storage());
return matrix(x.toArray().sort(compareAsc), x.storage());
},

'Array, function': function (x, _comparator) {
Expand Down Expand Up @@ -74,18 +75,21 @@ function factory (type, config, load, typed) {

/**
* Get the comparator for given order ('asc' or 'desc')
* @param {'asc' | 'desc'} order
* @param {'asc' | 'desc' | 'natural'} order
* @return {Function} Returns a _comparator function
*/
function _comparator (order) {
if (order === 'asc') {
return asc;
return compareAsc;
}
else if (order === 'desc') {
return desc;
return compareDesc;
}
else if (order === 'natural') {
return compareNatural;
}
else {
throw new Error('String "asc" or "desc" expected');
throw new Error('String "asc", "desc", or "natural" expected');
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/function/relational/compare.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function factory (type, config, load, typed) {
*
* See also:
*
* equal, unequal, smaller, smallerEq, larger, largerEq
* equal, unequal, smaller, smallerEq, larger, largerEq, compareNatural
*
* @param {number | BigNumber | Fraction | Unit | string | Array | Matrix} x First value to compare
* @param {number | BigNumber | Fraction | Unit | string | Array | Matrix} y Second value to compare
Expand Down
104 changes: 104 additions & 0 deletions lib/function/relational/compareNatural.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use strict';

var compareString = require('natural-compare');

function factory (type, config, load, typed) {

var compare = load(require('./compare'));

/**
* Compare two values in a natural way.
*
* For numeric values, the function works the same as `math.compare`.
* For types of values that can't be compared mathematically,
* the function compares in a natural way.
*
* For numeric values, x and y are considered equal when the relative
* difference between x and y is smaller than the configured epsilon.
* The function cannot be used to compare values smaller than
* approximately 2.22e-16.
*
* For Complex numbers, first the real parts are compared. If equal,
* the imaginary parts are compared.
*
* Syntax:
*
* math.compareNatural(x, y)
*
* Examples:
*
* 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
*
* var c = math.complex('2 + 3i');
* var d = math.complex('2 + 4i');
* math.compareNatural(c, d); // returns -1
*
* math.compareNatural(2, [1, 2, 3]); // returns [1, 0, -1]
*
* 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.
*/
var compareNatural = typed('compareNatural', {

'boolean, boolean': compare.signatures['boolean,boolean'],

'number, number': compare.signatures['number,number'],

'BigNumber, BigNumber': compare.signatures['BigNumber,BigNumber'],

'Fraction, Fraction': compare.signatures['Fraction,Fraction'],

'Complex, Complex': compareComplex,

'Unit, Unit': compare.signatures['Unit,Unit'],

'string, string': compareString

// 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?
});

compare.toTex = undefined; // use default template

return compareNatural;
}

/**
* Compare two complex numbers, `a` and `b`:
*
* - Returns 1 when the real part of `a` is larger than the real part of `b`
* - Returns -1 when the real part of `a` is smaller than the real part of `b`
* - Returns 1 when the real parts are equal
* and the imaginary part of `a` is larger than the imaginary part of `b`
* - Returns -1 when the real parts are equal
* and the imaginary part of `a` is smaller than the imaginary part of `b`
* - Returns 0 when both real and imaginary parts are equal.
*
* @params {Complex} a
* @params {Complex} b
* @returns {number} Returns the comparison result: -1, 0, or 1
*/
function compareComplex (a, b) {
if (a.re > b.re) { return 1; }
if (a.re < b.re) { return -1; }

if (a.im > b.im) { return 1; }
if (a.im < b.im) { return -1; }

return 0;
}

exports.name = 'compareNatural';
exports.factory = factory;
1 change: 1 addition & 0 deletions lib/function/relational/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = [
require('./compare'),
require('./compareNatural'),
require('./deepEqual'),
require('./equal'),
require('./larger'),
Expand Down
Loading

0 comments on commit 151bc65

Please sign in to comment.