mirror of
https://github.com/josdejong/mathjs.git
synced 2026-01-18 14:59:29 +00:00
1299 lines
42 KiB
JavaScript
1299 lines
42 KiB
JavaScript
/**
|
|
* math.js
|
|
* An extended math library. Includes a parser, real and complex values, units,
|
|
* matrices, strings, and a large set of functions and constants.
|
|
* https://github.com/josdejong/mathjs
|
|
*
|
|
* @version 0.0.2
|
|
* @date 2013-02-17
|
|
*
|
|
* @license
|
|
* Copyright (C) 2013 Jos de Jong <wjosdejong@gmail.com>
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
* use this file except in compliance with the License. You may obtain a copy
|
|
* of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations under
|
|
* the License.
|
|
*/
|
|
|
|
(function() {
|
|
|
|
/**
|
|
* Define mathjs namespace
|
|
*/
|
|
var math = {
|
|
type: {},
|
|
parser: {}
|
|
};
|
|
|
|
/**
|
|
* CommonJS module exports
|
|
*/
|
|
if ((typeof module !== 'undefined') && (typeof module.exports !== 'undefined')) {
|
|
module.exports = math;
|
|
}
|
|
if (typeof exports !== 'undefined') {
|
|
exports = math;
|
|
}
|
|
|
|
/**
|
|
* AMD module exports
|
|
*/
|
|
if (typeof(require) != 'undefined' && typeof(define) != 'undefined') {
|
|
define(function () {
|
|
return math;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Browser exports
|
|
*/
|
|
if (typeof(window) != 'undefined') {
|
|
window['math'] = math;
|
|
}
|
|
|
|
|
|
var PRECISION = 1E10;
|
|
|
|
/**
|
|
* Convert a number to a formatted string representation
|
|
* @param {Number} value The value to be formatted
|
|
* @param {Number} [digits] number of digits
|
|
* @return {String} formattedValue The formatted value
|
|
* @private
|
|
*/
|
|
var format = function (value, digits) {
|
|
if (value === Infinity) {
|
|
return 'Infinity';
|
|
}
|
|
else if (value === -Infinity) {
|
|
return '-Infinity';
|
|
}
|
|
else if (value === NaN) {
|
|
return 'NaN';
|
|
}
|
|
|
|
// TODO: what is a nice limit for non-scientific values?
|
|
var abs = Math.abs(value);
|
|
if ( (abs > 0.0001 && abs < 1000000) || abs == 0.0 ) {
|
|
// round the func to a limited number of digits
|
|
return String(round(value, digits));
|
|
}
|
|
else {
|
|
// scientific notation
|
|
var exp = Math.round(Math.log(abs) / Math.LN10);
|
|
var v = value / (Math.pow(10.0, exp));
|
|
return round(v, digits) + 'E' + exp;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* round a number to the given number of digits, or to the default if
|
|
* digits is not provided
|
|
* @param {Number} value
|
|
* @param {Number} [digits]
|
|
* @return {Number} roundedValue
|
|
* @private
|
|
*/
|
|
var round = function (value, digits) {
|
|
digits = (digits != undefined) ? Math.pow(10, digits) : PRECISION;
|
|
|
|
return Math.round(value * digits) / digits;
|
|
};
|
|
|
|
/**
|
|
* Create a semi UUID
|
|
* source: http://stackoverflow.com/a/105074/1262753
|
|
* @return {String} uuid
|
|
* @private
|
|
*/
|
|
var createUUID = function () {
|
|
var S4 = function () {
|
|
return Math.floor(
|
|
Math.random() * 0x10000 /* 65536 */
|
|
).toString(16);
|
|
};
|
|
|
|
return (
|
|
S4() + S4() + "-" +
|
|
S4() + "-" +
|
|
S4() + "-" +
|
|
S4() + "-" +
|
|
S4() + S4() + S4()
|
|
);
|
|
};
|
|
|
|
// Internet Explorer 8 and older does not support Array.indexOf,
|
|
// so we define it here in that case
|
|
// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/
|
|
if(!Array.prototype.indexOf) {
|
|
Array.prototype.indexOf = function(obj){
|
|
for(var i = 0; i < this.length; i++){
|
|
if(this[i] == obj){
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
|
|
try {
|
|
console.log("Warning: Ancient browser detected. Please update your browser");
|
|
}
|
|
catch (err) {
|
|
}
|
|
}
|
|
|
|
// Internet Explorer 8 and older does not support Array.forEach,
|
|
// so we define it here in that case
|
|
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
|
|
if (!Array.prototype.forEach) {
|
|
Array.prototype.forEach = function(fn, scope) {
|
|
for(var i = 0, len = this.length; i < len; ++i) {
|
|
fn.call(scope || this, this[i], i, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @License Apache 2.0 License
|
|
*
|
|
* @Author Jos de Jong
|
|
* @Date 2011-12-03
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* @constructor math.type.Unit
|
|
*
|
|
* @param {Number} [value] A value for the unit, like 5.2
|
|
* @param {String} [prefixUnit] A unit like "cm" or "inch"
|
|
*/
|
|
function Unit(value, prefixUnit) {
|
|
if (this.constructor != Unit) {
|
|
throw new Error('Unit constructor must be called with the new operator');
|
|
}
|
|
|
|
this.value = 1;
|
|
this.unit = Unit.UNIT_NONE;
|
|
this.prefix = Unit.PREFIX_NONE; // link to a list with supported prefixes
|
|
|
|
this.hasUnit = false;
|
|
this.hasValue = false;
|
|
this.fixPrefix = false; // is set true by the method "x In unit"s
|
|
|
|
this._init(value, prefixUnit);
|
|
}
|
|
|
|
math.type.Unit = Unit;
|
|
|
|
/**
|
|
* create a copy of this unit
|
|
* @return {Unit} copy
|
|
*/
|
|
Unit.prototype.copy = function () {
|
|
var clone = new Unit();
|
|
|
|
for (var p in this) {
|
|
if (this.hasOwnProperty(p)) {
|
|
clone[p] = this[p];
|
|
}
|
|
}
|
|
|
|
return clone;
|
|
};
|
|
|
|
/**
|
|
* check if a text ends with a certain string
|
|
* @param {String} text
|
|
* @param {String} search
|
|
*/
|
|
// TODO: put the endsWith method in another
|
|
Unit.endsWith = function(text, search) {
|
|
var start = text.length - search.length;
|
|
var end = text.length;
|
|
return (text.substring(start, end) === search);
|
|
};
|
|
|
|
/**
|
|
* Initialize a unit and value
|
|
* @param {Number} [value]
|
|
* @param {String} [unit] A string containing unit (and prefix), like "cm"
|
|
* @private
|
|
*/
|
|
Unit.prototype._init = function (value, unit) {
|
|
// find the unit and prefix from the string
|
|
if (unit !== undefined) {
|
|
var UNITS = Unit.UNITS;
|
|
var found = false;
|
|
for (var i = 0, iMax = UNITS.length; i < iMax; i++) {
|
|
var UNIT = UNITS[i];
|
|
|
|
if (Unit.endsWith(unit, UNIT.name) ) {
|
|
var prefixLen = (unit.length - UNIT.name.length);
|
|
var prefixName = unit.substring(0, prefixLen);
|
|
var prefix = UNIT.prefixes[prefixName];
|
|
if (prefix !== undefined) {
|
|
// store unit, prefix, and value
|
|
this.unit = UNIT;
|
|
this.prefix = prefix;
|
|
this.hasUnit = true;
|
|
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
throw new Error('String "' + unit + '" is no unit');
|
|
}
|
|
}
|
|
|
|
if (value !== undefined) {
|
|
this.value = this._normalize(value);
|
|
this.hasValue = true;
|
|
}
|
|
else {
|
|
this.value = this._normalize(1);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Normalize a value, based on its currently set unit
|
|
* @param {Number} value
|
|
* @return {Number} normalized value
|
|
* @private
|
|
*/
|
|
Unit.prototype._normalize = function(value) {
|
|
return (value + this.unit.offset) *
|
|
this.unit.value * this.prefix.value;
|
|
};
|
|
|
|
/**
|
|
* Unnormalize a value, based on its currently set unit
|
|
* @param {Number} value
|
|
* @param {Number} prefixValue Optional prefixvalue to be used
|
|
* @return {Number} unnormalized value
|
|
* @private
|
|
*/
|
|
Unit.prototype._unnormalize = function (value, prefixValue) {
|
|
if (prefixValue === undefined) {
|
|
return value / this.unit.value / this.prefix.value -
|
|
this.unit.offset;
|
|
}
|
|
else {
|
|
return value / this.unit.value / prefixValue -
|
|
this.unit.offset;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Test if the given expression is a unit
|
|
* @param {String} unit A unit with prefix, like "cm"
|
|
* @return {Boolean} true if the given string is a unit
|
|
*/
|
|
Unit.isUnit = function (unit) {
|
|
var UNITS = Unit.UNITS;
|
|
var num = UNITS.length;
|
|
for (var i = 0; i < num; i++) {
|
|
var UNIT = UNITS[i];
|
|
|
|
if (Unit.endsWith(unit, UNIT.name) ) {
|
|
var prefixLen = (unit.length - UNIT.name.length);
|
|
if (prefixLen == 0) {
|
|
return true;
|
|
}
|
|
|
|
var prefixName = unit.substring(0, prefixLen);
|
|
var prefix = UNIT.prefixes[prefixName];
|
|
if (prefix !== undefined) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* check if this unit has given base unit
|
|
* @param {math.type.Unit.BASE_UNITS} base
|
|
*/
|
|
Unit.prototype.hasBase = function(base) {
|
|
if (this.unit.base === undefined) {
|
|
return (base === undefined);
|
|
}
|
|
return (this.unit.base === base);
|
|
};
|
|
|
|
/**
|
|
* Check if this unit has a base equal to another base
|
|
* @param {math.type.Unit} other
|
|
* @return {Boolean} true if equal base
|
|
*/
|
|
Unit.prototype.equalBase = function(other) {
|
|
return (this.unit.base === other.unit.base);
|
|
};
|
|
|
|
/**
|
|
* Check if this unit equals another unit
|
|
* @param {Unit} other
|
|
* @return {Boolean} true if both units are equal
|
|
*/
|
|
Unit.prototype.equals = function(other) {
|
|
return (this.equalBase(other) && this.value == other.value);
|
|
};
|
|
|
|
/**
|
|
* Get string representation
|
|
* @return {String}
|
|
*/
|
|
Unit.prototype.toString = function() {
|
|
if (!this.fixPrefix) {
|
|
// find the best prefix value (resulting in the value of which
|
|
// the absolute value of the log10 is closest to zero,
|
|
// though with a little offset of 1.5 for nicer values: 999m
|
|
// is still displayed as 999m, and 1000m as 1km)
|
|
var bestPrefix = Unit.PREFIX_NONE;
|
|
var bestDiff = Math.abs(
|
|
Math.log(this.value / bestPrefix.value) / Math.LN10 - 1.5);
|
|
|
|
// TODO: 1000m is still displayed as 1000m, 1001m correctly as 1.001km
|
|
// TODO: working wrong with prefixes below zero, should do + 1.5 offset?
|
|
var prefixes = this.unit.prefixes;
|
|
for (var p in prefixes) {
|
|
if (prefixes.hasOwnProperty(p)) {
|
|
var prefix = prefixes[p];
|
|
if (prefix.scientific) {
|
|
var diff = Math.abs(
|
|
Math.log(this.value / prefix.value) / Math.LN10 - 1.5);
|
|
|
|
if (diff < bestDiff) {
|
|
bestPrefix = prefix;
|
|
bestDiff = diff;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var value = this._unnormalize(this.value, bestPrefix.value);
|
|
return format(value) + ' ' + bestPrefix.name + this.unit.name;
|
|
}
|
|
else {
|
|
var value = this._unnormalize(this.value);
|
|
return format(value) + ' ' + this.prefix.name + this.unit.name;
|
|
}
|
|
};
|
|
|
|
Unit.PREFIXES = {
|
|
'NONE': {
|
|
'': {'name': '', 'value': 1, 'scientific': true}
|
|
},
|
|
'SHORT': {
|
|
'': {'name': '', 'value': 1, 'scientific': true},
|
|
|
|
'da': {'name': 'da', 'value': 1e1, 'scientific': false},
|
|
'h': {'name': 'h', 'value': 1e2, 'scientific': false},
|
|
'k': {'name': 'k', 'value': 1e3, 'scientific': true},
|
|
'M': {'name': 'M', 'value': 1e6, 'scientific': true},
|
|
'G': {'name': 'G', 'value': 1e9, 'scientific': true},
|
|
'T': {'name': 'T', 'value': 1e12, 'scientific': true},
|
|
'P': {'name': 'P', 'value': 1e15, 'scientific': true},
|
|
'E': {'name': 'E', 'value': 1e18, 'scientific': true},
|
|
'Z': {'name': 'Z', 'value': 1e21, 'scientific': true},
|
|
'Y': {'name': 'Y', 'value': 1e24, 'scientific': true},
|
|
|
|
'd': {'name': 'd', 'value': 1e-1, 'scientific': false},
|
|
'c': {'name': 'c', 'value': 1e-2, 'scientific': false},
|
|
'm': {'name': 'm', 'value': 1e-3, 'scientific': true},
|
|
// 'µ': {'name': 'µ', 'value': 1e-6, 'scientific': true},
|
|
'u': {'name': 'u', 'value': 1e-6, 'scientific': true},
|
|
'n': {'name': 'n', 'value': 1e-9, 'scientific': true},
|
|
'p': {'name': 'p', 'value': 1e-12, 'scientific': true},
|
|
'f': {'name': 'f', 'value': 1e-15, 'scientific': true},
|
|
'a': {'name': 'a', 'value': 1e-18, 'scientific': true},
|
|
'z': {'name': 'z', 'value': 1e-21, 'scientific': true},
|
|
'y': {'name': 'y', 'value': 1e-24, 'scientific': true}
|
|
},
|
|
'LONG': {
|
|
'': {'name': '', 'value': 1, 'scientific': true},
|
|
|
|
'deca': {'name': 'deca', 'value': 1e1, 'scientific': false},
|
|
'hecto': {'name': 'hecto', 'value': 1e2, 'scientific': false},
|
|
'kilo': {'name': 'kilo', 'value': 1e3, 'scientific': true},
|
|
'mega': {'name': 'mega', 'value': 1e6, 'scientific': true},
|
|
'giga': {'name': 'giga', 'value': 1e9, 'scientific': true},
|
|
'tera': {'name': 'tera', 'value': 1e12, 'scientific': true},
|
|
'peta': {'name': 'peta', 'value': 1e15, 'scientific': true},
|
|
'exa': {'name': 'exa', 'value': 1e18, 'scientific': true},
|
|
'zetta': {'name': 'zetta', 'value': 1e21, 'scientific': true},
|
|
'yotta': {'name': 'yotta', 'value': 1e24, 'scientific': true},
|
|
|
|
'deci': {'name': 'deci', 'value': 1e-1, 'scientific': false},
|
|
'centi': {'name': 'centi', 'value': 1e-2, 'scientific': false},
|
|
'milli': {'name': 'milli', 'value': 1e-3, 'scientific': true},
|
|
'micro': {'name': 'micro', 'value': 1e-6, 'scientific': true},
|
|
'nano': {'name': 'nano', 'value': 1e-9, 'scientific': true},
|
|
'pico': {'name': 'pico', 'value': 1e-12, 'scientific': true},
|
|
'femto': {'name': 'femto', 'value': 1e-15, 'scientific': true},
|
|
'atto': {'name': 'atto', 'value': 1e-18, 'scientific': true},
|
|
'zepto': {'name': 'zepto', 'value': 1e-21, 'scientific': true},
|
|
'yocto': {'name': 'yocto', 'value': 1e-24, 'scientific': true}
|
|
},
|
|
'BINARY_SHORT': {
|
|
'': {'name': '', 'value': 1, 'scientific': true},
|
|
'k': {'name': 'k', 'value': 1024, 'scientific': true},
|
|
'M': {'name': 'M', 'value': Math.pow(1024, 2), 'scientific': true},
|
|
'G': {'name': 'G', 'value': Math.pow(1024, 3), 'scientific': true},
|
|
'T': {'name': 'T', 'value': Math.pow(1024, 4), 'scientific': true},
|
|
'P': {'name': 'P', 'value': Math.pow(1024, 5), 'scientific': true},
|
|
'E': {'name': 'E', 'value': Math.pow(1024, 6), 'scientific': true},
|
|
'Z': {'name': 'Z', 'value': Math.pow(1024, 7), 'scientific': true},
|
|
'Y': {'name': 'Y', 'value': Math.pow(1024, 8), 'scientific': true},
|
|
|
|
'Ki': {'name': 'Ki', 'value': 1024, 'scientific': true},
|
|
'Mi': {'name': 'Mi', 'value': Math.pow(1024, 2), 'scientific': true},
|
|
'Gi': {'name': 'Gi', 'value': Math.pow(1024, 3), 'scientific': true},
|
|
'Ti': {'name': 'Ti', 'value': Math.pow(1024, 4), 'scientific': true},
|
|
'Pi': {'name': 'Pi', 'value': Math.pow(1024, 5), 'scientific': true},
|
|
'Ei': {'name': 'Ei', 'value': Math.pow(1024, 6), 'scientific': true},
|
|
'Zi': {'name': 'Zi', 'value': Math.pow(1024, 7), 'scientific': true},
|
|
'Yi': {'name': 'Yi', 'value': Math.pow(1024, 8), 'scientific': true}
|
|
},
|
|
'BINARY_LONG': {
|
|
'': {'name': '', 'value': 1, 'scientific': true},
|
|
'kilo': {'name': 'kilo', 'value': 1024, 'scientific': true},
|
|
'mega': {'name': 'mega', 'value': Math.pow(1024, 2), 'scientific': true},
|
|
'giga': {'name': 'giga', 'value': Math.pow(1024, 3), 'scientific': true},
|
|
'tera': {'name': 'tera', 'value': Math.pow(1024, 4), 'scientific': true},
|
|
'peta': {'name': 'peta', 'value': Math.pow(1024, 5), 'scientific': true},
|
|
'exa': {'name': 'exa', 'value': Math.pow(1024, 6), 'scientific': true},
|
|
'zetta': {'name': 'zetta', 'value': Math.pow(1024, 7), 'scientific': true},
|
|
'yotta': {'name': 'yotta', 'value': Math.pow(1024, 8), 'scientific': true},
|
|
|
|
'kibi': {'name': 'kibi', 'value': 1024, 'scientific': true},
|
|
'mebi': {'name': 'mebi', 'value': Math.pow(1024, 2), 'scientific': true},
|
|
'gibi': {'name': 'gibi', 'value': Math.pow(1024, 3), 'scientific': true},
|
|
'tebi': {'name': 'tebi', 'value': Math.pow(1024, 4), 'scientific': true},
|
|
'pebi': {'name': 'pebi', 'value': Math.pow(1024, 5), 'scientific': true},
|
|
'exi': {'name': 'exi', 'value': Math.pow(1024, 6), 'scientific': true},
|
|
'zebi': {'name': 'zebi', 'value': Math.pow(1024, 7), 'scientific': true},
|
|
'yobi': {'name': 'yobi', 'value': Math.pow(1024, 8), 'scientific': true}
|
|
}
|
|
};
|
|
|
|
Unit.PREFIX_NONE = {'name': '', 'value': 1, 'scientific': true};
|
|
|
|
Unit.BASE_UNITS = {
|
|
'NONE': {},
|
|
|
|
'LENGTH': {}, // meter
|
|
'MASS': {}, // kilogram
|
|
'TIME': {}, // second
|
|
'CURRENT': {}, // ampere
|
|
'TEMPERATURE': {}, // kelvin
|
|
'LUMINOUS_INTENSITY': {}, // candela
|
|
'AMOUNT_OF_SUBSTANCE': {}, // mole
|
|
|
|
'FORCE': {}, // Newton
|
|
'SURFACE': {}, // m2
|
|
'VOLUME': {}, // m3
|
|
'ANGLE': {}, // rad
|
|
'BIT': {} // bit (digital)
|
|
};
|
|
|
|
var BASE_UNITS = Unit.BASE_UNITS;
|
|
var PREFIXES = Unit.PREFIXES;
|
|
|
|
Unit.BASE_UNIT_NONE = {};
|
|
|
|
Unit.UNIT_NONE = {'name': '', 'base': Unit.BASE_UNIT_NONE, 'value': 1, 'offset': 0};
|
|
|
|
Unit.UNITS = [
|
|
// length
|
|
{'name': 'meter', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.LONG, 'value': 1, 'offset': 0},
|
|
{'name': 'inch', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 0.0254, 'offset': 0},
|
|
{'name': 'foot', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 0.3048, 'offset': 0},
|
|
{'name': 'yard', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 0.9144, 'offset': 0},
|
|
{'name': 'mile', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 1609.344, 'offset': 0},
|
|
{'name': 'link', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 0.201168, 'offset': 0},
|
|
{'name': 'rod', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 5.029210, 'offset': 0},
|
|
{'name': 'chain', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 20.1168, 'offset': 0},
|
|
{'name': 'angstrom', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 1e-10, 'offset': 0},
|
|
|
|
{'name': 'm', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.SHORT, 'value': 1, 'offset': 0},
|
|
//{'name': 'in', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 0.0254, 'offset': 0}, not supported, In is an operator
|
|
{'name': 'ft', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 0.3048, 'offset': 0},
|
|
{'name': 'yd', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 0.9144, 'offset': 0},
|
|
{'name': 'mi', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 1609.344, 'offset': 0},
|
|
{'name': 'li', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 0.201168, 'offset': 0},
|
|
{'name': 'rd', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 5.029210, 'offset': 0},
|
|
{'name': 'ch', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 20.1168, 'offset': 0},
|
|
{'name': 'mil', 'base': BASE_UNITS.LENGTH, 'prefixes': PREFIXES.NONE, 'value': 0.0000254, 'offset': 0}, // 1/1000 inch
|
|
|
|
// Surface
|
|
{'name': 'm2', 'base': BASE_UNITS.SURFACE, 'prefixes': PREFIXES.SHORT, 'value': 1, 'offset': 0},
|
|
{'name': 'sqin', 'base': BASE_UNITS.SURFACE, 'prefixes': PREFIXES.NONE, 'value': 0.00064516, 'offset': 0}, // 645.16 mm2
|
|
{'name': 'sqft', 'base': BASE_UNITS.SURFACE, 'prefixes': PREFIXES.NONE, 'value': 0.09290304, 'offset': 0}, // 0.09290304 m2
|
|
{'name': 'sqyd', 'base': BASE_UNITS.SURFACE, 'prefixes': PREFIXES.NONE, 'value': 0.83612736, 'offset': 0}, // 0.83612736 m2
|
|
{'name': 'sqmi', 'base': BASE_UNITS.SURFACE, 'prefixes': PREFIXES.NONE, 'value': 2589988.110336, 'offset': 0}, // 2.589988110336 km2
|
|
{'name': 'sqrd', 'base': BASE_UNITS.SURFACE, 'prefixes': PREFIXES.NONE, 'value': 25.29295, 'offset': 0}, // 25.29295 m2
|
|
{'name': 'sqch', 'base': BASE_UNITS.SURFACE, 'prefixes': PREFIXES.NONE, 'value': 404.6873, 'offset': 0}, // 404.6873 m2
|
|
{'name': 'sqmil', 'base': BASE_UNITS.SURFACE, 'prefixes': PREFIXES.NONE, 'value': 6.4516e-10, 'offset': 0}, // 6.4516 * 10^-10 m2
|
|
|
|
// Volume
|
|
{'name': 'm3', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.SHORT, 'value': 1, 'offset': 0},
|
|
{'name': 'L', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.SHORT, 'value': 0.001, 'offset': 0}, // litre
|
|
{'name': 'litre', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.LONG, 'value': 0.001, 'offset': 0},
|
|
{'name': 'cuin', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 1.6387064e-5, 'offset': 0}, // 1.6387064e-5 m3
|
|
{'name': 'cuft', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.028316846592, 'offset': 0}, // 28.316 846 592 L
|
|
{'name': 'cuyd', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.764554857984, 'offset': 0}, // 764.554 857 984 L
|
|
{'name': 'teaspoon', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.000005, 'offset': 0}, // 5 mL
|
|
{'name': 'tablespoon', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.000015, 'offset': 0}, // 15 mL
|
|
//{'name': 'cup', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.000240, 'offset': 0}, // 240 mL // not possible, we have already another cup
|
|
|
|
// Liquid volume
|
|
{'name': 'minim', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.00000006161152, 'offset': 0}, // 0.06161152 mL
|
|
{'name': 'fluiddram', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.0000036966911, 'offset': 0}, // 3.696691 mL
|
|
{'name': 'fluidounce', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.00002957353, 'offset': 0}, // 29.57353 mL
|
|
{'name': 'gill', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.0001182941, 'offset': 0}, // 118.2941 mL
|
|
{'name': 'cup', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.0002365882, 'offset': 0}, // 236.5882 mL
|
|
{'name': 'pint', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.0004731765, 'offset': 0}, // 473.1765 mL
|
|
{'name': 'quart', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.0009463529, 'offset': 0}, // 946.3529 mL
|
|
{'name': 'gallon', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.003785412, 'offset': 0}, // 3.785412 L
|
|
{'name': 'beerbarrel', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.1173478, 'offset': 0}, // 117.3478 L
|
|
{'name': 'oilbarrel', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.1589873, 'offset': 0}, // 158.9873 L
|
|
{'name': 'hogshead', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.2384810, 'offset': 0}, // 238.4810 L
|
|
|
|
//{'name': 'min', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.00000006161152, 'offset': 0}, // 0.06161152 mL // min is already in use as minute
|
|
{'name': 'fldr', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.0000036966911, 'offset': 0}, // 3.696691 mL
|
|
{'name': 'floz', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.00002957353, 'offset': 0}, // 29.57353 mL
|
|
{'name': 'gi', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.0001182941, 'offset': 0}, // 118.2941 mL
|
|
{'name': 'cp', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.0002365882, 'offset': 0}, // 236.5882 mL
|
|
{'name': 'pt', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.0004731765, 'offset': 0}, // 473.1765 mL
|
|
{'name': 'qt', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.0009463529, 'offset': 0}, // 946.3529 mL
|
|
{'name': 'gal', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.003785412, 'offset': 0}, // 3.785412 L
|
|
{'name': 'bbl', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.1173478, 'offset': 0}, // 117.3478 L
|
|
{'name': 'obl', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.1589873, 'offset': 0}, // 158.9873 L
|
|
//{'name': 'hogshead', 'base': BASE_UNITS.VOLUME, 'prefixes': PREFIXES.NONE, 'value': 0.2384810, 'offset': 0}, // 238.4810 L // TODO: hh?
|
|
|
|
// Mass
|
|
{'name': 'g', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.SHORT, 'value': 0.001, 'offset': 0},
|
|
{'name': 'gram', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.LONG, 'value': 0.001, 'offset': 0},
|
|
|
|
{'name': 'ton', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.SHORT, 'value': 907.18474, 'offset': 0},
|
|
{'name': 'tonne', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.SHORT, 'value': 1000, 'offset': 0},
|
|
|
|
{'name': 'grain', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 64.79891e-6, 'offset': 0},
|
|
{'name': 'dram', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 1.7718451953125e-3, 'offset': 0},
|
|
{'name': 'ounce', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 28.349523125e-3, 'offset': 0},
|
|
{'name': 'poundmass', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 453.59237e-3, 'offset': 0},
|
|
{'name': 'hundredweight', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 45.359237, 'offset': 0},
|
|
{'name': 'stick', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 115e-3, 'offset': 0},
|
|
|
|
{'name': 'gr', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 64.79891e-6, 'offset': 0},
|
|
{'name': 'dr', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 1.7718451953125e-3, 'offset': 0},
|
|
{'name': 'oz', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 28.349523125e-3, 'offset': 0},
|
|
{'name': 'lbm', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 453.59237e-3, 'offset': 0},
|
|
{'name': 'cwt', 'base': BASE_UNITS.MASS, 'prefixes': PREFIXES.NONE, 'value': 45.359237, 'offset': 0},
|
|
|
|
// Time
|
|
{'name': 's', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.SHORT, 'value': 1, 'offset': 0},
|
|
{'name': 'min', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.NONE, 'value': 60, 'offset': 0},
|
|
{'name': 'h', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.NONE, 'value': 3600, 'offset': 0},
|
|
{'name': 'seconds', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.LONG, 'value': 1, 'offset': 0},
|
|
{'name': 'second', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.LONG, 'value': 1, 'offset': 0},
|
|
{'name': 'sec', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.LONG, 'value': 1, 'offset': 0},
|
|
{'name': 'minutes', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.NONE, 'value': 60, 'offset': 0},
|
|
{'name': 'minute', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.NONE, 'value': 60, 'offset': 0},
|
|
{'name': 'hours', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.NONE, 'value': 3600, 'offset': 0},
|
|
{'name': 'hour', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.NONE, 'value': 3600, 'offset': 0},
|
|
{'name': 'day', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.NONE, 'value': 86400, 'offset': 0},
|
|
{'name': 'days', 'base': BASE_UNITS.TIME, 'prefixes': PREFIXES.NONE, 'value': 86400, 'offset': 0},
|
|
|
|
// Angles
|
|
{'name': 'rad', 'base': BASE_UNITS.ANGLE, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 0},
|
|
{'name': 'deg', 'base': BASE_UNITS.ANGLE, 'prefixes': PREFIXES.NONE, 'value': 0.017453292519943295769236907684888, 'offset': 0}, // deg = rad / (2*pi) * 360 = rad / 0.017453292519943295769236907684888
|
|
{'name': 'grad', 'base': BASE_UNITS.ANGLE, 'prefixes': PREFIXES.NONE, 'value': 0.015707963267948966192313216916399, 'offset': 0}, // grad = rad / (2*pi) * 400 = rad / 0.015707963267948966192313216916399
|
|
{'name': 'cycle', 'base': BASE_UNITS.ANGLE, 'prefixes': PREFIXES.NONE, 'value': 6.2831853071795864769252867665793, 'offset': 0}, // cycle = rad / (2*pi) = rad / 6.2831853071795864769252867665793
|
|
|
|
// Electric current
|
|
{'name': 'A', 'base': BASE_UNITS.CURRENT, 'prefixes': PREFIXES.SHORT, 'value': 1, 'offset': 0},
|
|
{'name': 'ampere', 'base': BASE_UNITS.CURRENT, 'prefixes': PREFIXES.LONG, 'value': 1, 'offset': 0},
|
|
|
|
// Temperature
|
|
// K(C) = °C + 273.15
|
|
// K(F) = (°F + 459.67) / 1.8
|
|
// K(R) = °R / 1.8
|
|
{'name': 'K', 'base': BASE_UNITS.TEMPERATURE, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 0},
|
|
{'name': 'degC', 'base': BASE_UNITS.TEMPERATURE, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 273.15},
|
|
{'name': 'degF', 'base': BASE_UNITS.TEMPERATURE, 'prefixes': PREFIXES.NONE, 'value': 1/1.8, 'offset': 459.67},
|
|
{'name': 'degR', 'base': BASE_UNITS.TEMPERATURE, 'prefixes': PREFIXES.NONE, 'value': 1/1.8, 'offset': 0},
|
|
{'name': 'kelvin', 'base': BASE_UNITS.TEMPERATURE, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 0},
|
|
{'name': 'celsius', 'base': BASE_UNITS.TEMPERATURE, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 273.15},
|
|
{'name': 'fahrenheit', 'base': BASE_UNITS.TEMPERATURE, 'prefixes': PREFIXES.NONE, 'value': 1/1.8, 'offset': 459.67},
|
|
{'name': 'rankine', 'base': BASE_UNITS.TEMPERATURE, 'prefixes': PREFIXES.NONE, 'value': 1/1.8, 'offset': 0},
|
|
|
|
// amount of substance
|
|
{'name': 'mol', 'base': BASE_UNITS.AMOUNT_OF_SUBSTANCE, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 0},
|
|
{'name': 'mole', 'base': BASE_UNITS.AMOUNT_OF_SUBSTANCE, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 0},
|
|
|
|
// luminous intensity
|
|
{'name': 'cd', 'base': BASE_UNITS.LUMINOUS_INTENSITY, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 0},
|
|
{'name': 'candela', 'base': BASE_UNITS.LUMINOUS_INTENSITY, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 0},
|
|
// TODO: units STERADIAN
|
|
//{'name': 'sr', 'base': BASE_UNITS.STERADIAN, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 0},
|
|
//{'name': 'steradian', 'base': BASE_UNITS.STERADIAN, 'prefixes': PREFIXES.NONE, 'value': 1, 'offset': 0},
|
|
|
|
// Force
|
|
{'name': 'N', 'base': BASE_UNITS.FORCE, 'prefixes': PREFIXES.SHORT, 'value': 1, 'offset': 0},
|
|
{'name': 'newton', 'base': BASE_UNITS.FORCE, 'prefixes': PREFIXES.LONG, 'value': 1, 'offset': 0},
|
|
{'name': 'lbf', 'base': BASE_UNITS.FORCE, 'prefixes': PREFIXES.NONE, 'value': 4.4482216152605, 'offset': 0},
|
|
{'name': 'poundforce', 'base': BASE_UNITS.FORCE, 'prefixes': PREFIXES.NONE, 'value': 4.4482216152605, 'offset': 0},
|
|
|
|
// Binary
|
|
{'name': 'b', 'base': BASE_UNITS.BIT, 'prefixes': PREFIXES.BINARY_SHORT, 'value': 1, 'offset': 0},
|
|
{'name': 'bits', 'base': BASE_UNITS.BIT, 'prefixes': PREFIXES.BINARY_LONG, 'value': 1, 'offset': 0},
|
|
{'name': 'B', 'base': BASE_UNITS.BIT, 'prefixes': PREFIXES.BINARY_SHORT, 'value': 8, 'offset': 0},
|
|
{'name': 'bytes', 'base': BASE_UNITS.BIT, 'prefixes': PREFIXES.BINARY_LONG, 'value': 8, 'offset': 0}
|
|
];
|
|
|
|
/**
|
|
* @constructor math.type.Complex
|
|
*
|
|
* @param {Number} [re]
|
|
* @param {Number} [im]
|
|
*/
|
|
function Complex(re, im) {
|
|
if (this.constructor != Complex) {
|
|
throw new Error('Complex constructor must be called with the new operator');
|
|
}
|
|
|
|
/**
|
|
* @type {Number}
|
|
*/
|
|
this.re = re || 0;
|
|
|
|
/**
|
|
* @type {Number}
|
|
*/
|
|
this.im = im || 0;
|
|
}
|
|
|
|
math.type.Complex = Complex;
|
|
|
|
/**
|
|
* Create a copy of the complex value
|
|
* @return {Complex} copy
|
|
*/
|
|
Complex.prototype.copy = function () {
|
|
return new Complex(this.re, this.im);
|
|
};
|
|
|
|
/**
|
|
* Get string representation of the Complex value
|
|
* @return {String} str
|
|
*/
|
|
Complex.prototype.toString = function () {
|
|
var str = '';
|
|
|
|
if (this.im === 0) {
|
|
// real value
|
|
str = format(this.re);
|
|
}
|
|
else if (this.re === 0) {
|
|
// purely complex value
|
|
if (this.im === 1) {
|
|
str = 'i';
|
|
}
|
|
else if (this.im === -1) {
|
|
str = '-i';
|
|
}
|
|
else {
|
|
str = format(this.im) + 'i';
|
|
}
|
|
}
|
|
else {
|
|
// complex value
|
|
if (this.im > 0) {
|
|
if (this.im == 1) {
|
|
str = format(this.re) + ' + i';
|
|
}
|
|
else {
|
|
str = format(this.re) + ' + ' + format(this.im) + 'i';
|
|
}
|
|
}
|
|
else {
|
|
if (this.im == -1) {
|
|
str = format(this.re) + ' - i';
|
|
}
|
|
else {
|
|
str = format(this.re) + ' - ' + format(Math.abs(this.im)) + 'i';
|
|
}
|
|
}
|
|
}
|
|
|
|
return str;
|
|
};
|
|
|
|
/**
|
|
* Type documentation
|
|
*/
|
|
Complex.doc = {
|
|
'name': 'Complex',
|
|
'category': 'type',
|
|
'syntax': [
|
|
'a + bi',
|
|
'a + b * i'
|
|
],
|
|
'description':
|
|
'A complex value a + bi, ' +
|
|
'where a is the real part and b is the complex part, ' +
|
|
'and i is the imaginary number defined as sqrt(-1).',
|
|
'examples': [
|
|
'2 + 3i',
|
|
'sqrt(-4)',
|
|
'(1.2 -5i) * 2'
|
|
],
|
|
'seealso': [
|
|
'abs',
|
|
'arg',
|
|
'conj',
|
|
'im',
|
|
're'
|
|
]
|
|
};
|
|
|
|
|
|
/**
|
|
* Generic type methods
|
|
*/
|
|
|
|
/**
|
|
* Test whether value is a Number
|
|
* @param {*} value
|
|
* @return {Boolean} isNumber
|
|
*/
|
|
function isNumber(value) {
|
|
return (value instanceof Number) || (typeof value == 'number');
|
|
}
|
|
|
|
/**
|
|
* Test whether value is a Complex value
|
|
* @param {*} value
|
|
* @return {Boolean} isComplex
|
|
*/
|
|
function isComplex(value) {
|
|
return (value instanceof Complex);
|
|
}
|
|
|
|
/**
|
|
* Test whether value is a Unit
|
|
* @param {*} value
|
|
* @return {Boolean} isUnit
|
|
*/
|
|
function isUnit(value) {
|
|
return (value instanceof Unit);
|
|
}
|
|
|
|
/**
|
|
* Get the type of an object.
|
|
* @param {*} obj
|
|
* @return {String} type
|
|
*/
|
|
function type (obj) {
|
|
var t = typeof obj;
|
|
|
|
if (t == 'object') {
|
|
if (obj == null) {
|
|
return 'null';
|
|
}
|
|
if (obj instanceof Array) {
|
|
return 'array';
|
|
}
|
|
if (obj && obj.constructor && obj.constructor.name) {
|
|
return obj.constructor.name;
|
|
}
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* mathjs constants
|
|
*/
|
|
math.E = Math.E;
|
|
math.LN2 = Math.LN2;
|
|
math.LN10 = Math.LN10;
|
|
math.LOG2E = Math.LOG2E;
|
|
math.LOG10E = Math.LOG10E;
|
|
math.PI = Math.PI;
|
|
math.SQRT1_2 = Math.SQRT1_2;
|
|
math.SQRT2 = Math.SQRT2;
|
|
|
|
math.I = new Complex(0, -1);
|
|
|
|
// lower case constants
|
|
math.pi = math.PI;
|
|
math.e = math.E;
|
|
math.i = math.I;
|
|
|
|
/**
|
|
* Helper methods for functions
|
|
*/
|
|
|
|
/**
|
|
* Create a TypeError with message:
|
|
* 'Function <fn> does not support a parameter of type <type>';
|
|
* @param {String} fn
|
|
* @param {*} value
|
|
* @return {TypeError | Error} error
|
|
*/
|
|
function newUnsupportedTypeError(fn, value) {
|
|
var t = type(value);
|
|
var msg = 'Function ' + fn + ' does not support a parameter of type ' + t;
|
|
|
|
if ((typeof TypeError) != 'undefined') {
|
|
return new TypeError(msg);
|
|
}
|
|
else {
|
|
return new Error(msg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Change the unit of a value. x in unit or in(x, unit)
|
|
* @param {Unit} x
|
|
* @param {Unit} unit
|
|
* @return {Unit} res
|
|
*/
|
|
function unit_in(x, unit) {
|
|
if (isUnit(x)) {
|
|
// Test if unit has no value
|
|
if (unit.hasValue) {
|
|
throw new Error('Cannot convert to a unit with a value');
|
|
}
|
|
// Test if unit has a unit
|
|
if (!unit.hasUnit) {
|
|
throw new Error('Unit expected on the right hand side of function in');
|
|
}
|
|
|
|
var res = unit.copy();
|
|
res.value = x.value;
|
|
res.fixPrefix = true;
|
|
|
|
return res;
|
|
}
|
|
|
|
// TODO: implement array support
|
|
// TODO: implement matrix support
|
|
|
|
throw newUnsupportedTypeError('in', x);
|
|
}
|
|
|
|
math['in'] = unit_in;
|
|
|
|
/**
|
|
* Function documentation
|
|
*/
|
|
unit_in.doc ={
|
|
'name': 'in',
|
|
'category': 'Units',
|
|
'syntax': [
|
|
'x in unit',
|
|
'in(x, unit)'
|
|
],
|
|
'description': 'Change the unit of a value.',
|
|
'examples': [
|
|
'5 inch in cm',
|
|
'3.2kg in g',
|
|
'16 bytes in bits'
|
|
],
|
|
'seealso': []
|
|
};
|
|
|
|
/**
|
|
* Calculate the sine of a value, sin(x)
|
|
* @param {Number | Complex | Unit} x
|
|
* @return {Number | Complex} res
|
|
*/
|
|
function sin(x) {
|
|
if (isNumber(x)) {
|
|
return Math.sin(x);
|
|
}
|
|
|
|
if (isComplex(x)) {
|
|
return new Complex(
|
|
0.5 * Math.sin(x.re) * (Math.exp(-x.im) + Math.exp( x.im)),
|
|
0.5 * Math.cos(x.re) * (Math.exp( x.im) - Math.exp(-x.im))
|
|
);
|
|
}
|
|
|
|
if (isUnit(x)) {
|
|
if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) {
|
|
throw new TypeError ('Unit in function cos is no angle');
|
|
}
|
|
return Math.sin(x.value);
|
|
}
|
|
|
|
// TODO: implement array support
|
|
// TODO: implement matrix support
|
|
|
|
throw newUnsupportedTypeError('sin', x);
|
|
}
|
|
|
|
math.sin = sin;
|
|
|
|
/**
|
|
* Function documentation
|
|
*/
|
|
sin.doc = {
|
|
'name': 'sin',
|
|
'category': 'Trigonometry',
|
|
'syntax': [
|
|
'sin(x)'
|
|
],
|
|
'description': 'Compute the sine of x in radians.',
|
|
'examples': [
|
|
'sin(2)',
|
|
'sin(pi / 4) ^ 2',
|
|
'sin(90 deg)',
|
|
'sin(30 deg)',
|
|
'sin(0.2)^2 + cos(0.2)^2'
|
|
],
|
|
'seealso': [
|
|
'asin',
|
|
'cos',
|
|
'tan'
|
|
]
|
|
};
|
|
|
|
/**
|
|
* Calculate the cosine of a value, cos(x)
|
|
* @param {Number | Complex | Unit} x
|
|
* @return {Number | Complex} res
|
|
*/
|
|
function cos(x) {
|
|
if (isNumber(x)) {
|
|
return Math.cos(x);
|
|
}
|
|
|
|
if (isComplex(x)) {
|
|
// cos(z) = (exp(iz) + exp(-iz)) / 2
|
|
return new Complex(
|
|
0.5 * Math.cos(x.re) * (Math.exp(-x.im) + Math.exp(x.im)),
|
|
0.5 * Math.sin(x.re) * (Math.exp(-x.im) - Math.exp(x.im))
|
|
);
|
|
}
|
|
|
|
if (isUnit(x)) {
|
|
if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) {
|
|
throw new TypeError ('Unit in function cos is no angle');
|
|
}
|
|
return Math.cos(x.value);
|
|
}
|
|
|
|
// TODO: implement array support
|
|
// TODO: implement matrix support
|
|
|
|
throw newUnsupportedTypeError('cos', x);
|
|
}
|
|
|
|
math.cos = cos;
|
|
|
|
/**
|
|
* Function documentation
|
|
*/
|
|
cos.doc = {
|
|
'name': 'cos',
|
|
'category': 'Trigonometry',
|
|
'syntax': [
|
|
'cos(x)'
|
|
],
|
|
'description': 'Compute the cosine of x in radians.',
|
|
'examples': [
|
|
'cos(2)',
|
|
'cos(pi / 4) ^ 2',
|
|
'cos(180 deg)',
|
|
'cos(60 deg)',
|
|
'sin(0.2)^2 + cos(0.2)^2'
|
|
],
|
|
'seealso': [
|
|
'acos',
|
|
'sin',
|
|
'tan'
|
|
]
|
|
};
|
|
|
|
/**
|
|
* Calculate the tangent of a value, tan(x)
|
|
* @param {Number | Complex | Unit} x
|
|
* @return {Number | Complex} res
|
|
*/
|
|
function tan(x) {
|
|
if (isNumber(x)) {
|
|
return Math.tan(x);
|
|
}
|
|
|
|
if (isComplex(x)) {
|
|
var den = Math.exp(-4.0 * x.im) +
|
|
2.0 * Math.exp(-2.0 * x.im) * Math.cos(2.0 * x.re) +
|
|
1.0;
|
|
|
|
return new Complex(
|
|
2.0 * Math.exp(-2.0 * x.im) * Math.sin(2.0 * x.re) / den,
|
|
(1.0 - Math.exp(-4.0 * x.im)) / den
|
|
);
|
|
}
|
|
|
|
if (isUnit(x)) {
|
|
if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) {
|
|
throw new TypeError ('Unit in function tan is no angle');
|
|
}
|
|
return Math.tan(x.value);
|
|
}
|
|
|
|
// TODO: implement array support
|
|
// TODO: implement matrix support
|
|
|
|
throw newUnsupportedTypeError('tan', x);
|
|
}
|
|
|
|
math.tan = tan;
|
|
|
|
/**
|
|
* Function documentation
|
|
*/
|
|
tan.doc = {
|
|
'name': 'tan',
|
|
'category': 'Trigonometry',
|
|
'syntax': [
|
|
'tan(x)'
|
|
],
|
|
'description': 'Compute the tangent of x in radians.',
|
|
'examples': [
|
|
'tan(0.5)',
|
|
'sin(0.5) / cos(0.5)',
|
|
'tan(pi / 4)',
|
|
'tan(45 deg)'
|
|
],
|
|
'seealso': [
|
|
'atan',
|
|
'sin',
|
|
'cos'
|
|
]
|
|
};
|
|
|
|
/**
|
|
* Calculate the exponent of a value, exp(x)
|
|
* @param {Number | Complex} x
|
|
* @return {Number | Complex} res
|
|
*/
|
|
function exp (x) {
|
|
if (isNumber(x)) {
|
|
return Math.exp(x);
|
|
}
|
|
if (isComplex(x)) {
|
|
var r = Math.exp(x.re);
|
|
return new Complex(
|
|
r * Math.cos(x.im),
|
|
r * Math.sin(x.im)
|
|
);
|
|
}
|
|
|
|
// TODO: implement array support
|
|
// TODO: implement matrix support
|
|
|
|
throw newUnsupportedTypeError('exp', x);
|
|
}
|
|
|
|
math.exp = exp;
|
|
|
|
/**
|
|
* Function documentation
|
|
*/
|
|
exp.doc = {
|
|
'name': 'exp',
|
|
'category': 'Arithmetic',
|
|
'syntax': [
|
|
'exp(x)'
|
|
],
|
|
'description': 'Calculate the exponent of a value.',
|
|
'examples': [
|
|
'exp(1.3)',
|
|
'e ^ 1.3',
|
|
'log(exp(1.3))',
|
|
'x = 2.4',
|
|
'(exp(i*x) == cos(x) + i*sin(x)) # Euler\'s formula'
|
|
],
|
|
'seealso': [
|
|
'square',
|
|
'multiply',
|
|
'log'
|
|
]
|
|
};
|
|
/**
|
|
* Calculate the square root of a value
|
|
* @param {Number | Complex} x
|
|
* @return {Number | Complex} res
|
|
*/
|
|
function sqrt (x) {
|
|
if (isNumber(x)) {
|
|
if (x >= 0) {
|
|
return Math.sqrt(x);
|
|
}
|
|
else {
|
|
return sqrt(new Complex(x, 0));
|
|
}
|
|
}
|
|
|
|
if (isComplex(x)) {
|
|
var r = Math.sqrt(x.re * x.re + x.im * x.im);
|
|
if (x.im >= 0.0) {
|
|
return new Complex(
|
|
0.5 * Math.sqrt(2.0 * (r + x.re)),
|
|
0.5 * Math.sqrt(2.0 * (r - x.re))
|
|
);
|
|
}
|
|
else {
|
|
return new Complex(
|
|
0.5 * Math.sqrt(2.0 * (r + x.re)),
|
|
-0.5 * Math.sqrt(2.0 * (r - x.re))
|
|
);
|
|
}
|
|
}
|
|
|
|
// TODO: implement array support
|
|
// TODO: implement matrix support
|
|
|
|
throw newUnsupportedTypeError('sqrt', x);
|
|
}
|
|
|
|
math.sqrt = sqrt;
|
|
|
|
/**
|
|
* Function documentation
|
|
*/
|
|
sqrt.doc = {
|
|
'name': 'sqrt',
|
|
'category': 'Arithmetic',
|
|
'syntax': [
|
|
'sqrt(x)'
|
|
],
|
|
'description':
|
|
'Compute the square root value. ' +
|
|
'If x = y * y, then y is the square root of x.',
|
|
'examples': [
|
|
'sqrt(25)',
|
|
'5 * 5',
|
|
'sqrt(-1)'
|
|
],
|
|
'seealso': [
|
|
'square',
|
|
'multiply'
|
|
]
|
|
};
|
|
|
|
/**
|
|
* Calculate the square root of a value
|
|
* @param {Number | Complex} x
|
|
* @return {Number | Complex} res
|
|
*/
|
|
function abs(x) {
|
|
if (isNumber(x)) {
|
|
return Math.abs(x);
|
|
}
|
|
|
|
if (isComplex(x)) {
|
|
return Math.sqrt(x.re * x.re + x.im * x.im);
|
|
}
|
|
|
|
// TODO: implement array support
|
|
// TODO: implement matrix support
|
|
|
|
throw newUnsupportedTypeError('abs', x);
|
|
}
|
|
|
|
math.abs = abs;
|
|
|
|
/**
|
|
* Function documentation
|
|
*/
|
|
abs.doc = {
|
|
'name': 'abs',
|
|
'category': 'Arithmetic',
|
|
'syntax': [
|
|
'abs(x)'
|
|
],
|
|
'description': 'Compute the absolute value.',
|
|
'examples': [
|
|
'abs(3.5)',
|
|
'abs(-4.2)'
|
|
],
|
|
'seealso': ['sign']
|
|
};
|
|
|
|
/**
|
|
* Calculate the natural logarithm of a value, log(x)
|
|
* @param {Number | Complex} x
|
|
* @return {Number | Complex} res
|
|
*/
|
|
function log(x) {
|
|
if (isNumber(x)) {
|
|
if (x >= 0) {
|
|
return Math.log(x);
|
|
}
|
|
else {
|
|
// negative value -> complex value computation
|
|
return log(new Complex(x, 0));
|
|
}
|
|
}
|
|
|
|
if (isComplex(x)) {
|
|
return new Complex (
|
|
Math.log(Math.sqrt(x.re * x.re + x.im * x.im)),
|
|
Math.atan2(x.im, x.re)
|
|
);
|
|
}
|
|
|
|
// TODO: implement array support
|
|
// TODO: implement matrix support
|
|
|
|
throw newUnsupportedTypeError('log', x);
|
|
}
|
|
|
|
math.log = log;
|
|
|
|
/**
|
|
* Function documentation
|
|
*/
|
|
log.doc = {
|
|
'name': 'log',
|
|
'category': 'Arithmetic',
|
|
'syntax': [
|
|
'log(x)'
|
|
],
|
|
'description': 'Compute the natural logarithm of a value.',
|
|
'examples': [
|
|
'log(3.5)',
|
|
'a = log(2.4)',
|
|
'exp(a)',
|
|
'log(1000) / log(10)'
|
|
],
|
|
'seealso': [
|
|
'exp',
|
|
'logb',
|
|
'log10'
|
|
]
|
|
};
|
|
|
|
|
|
})();
|