diff --git a/lib/math.js b/lib/math.js index 9c281e355..6eb0c7484 100644 --- a/lib/math.js +++ b/lib/math.js @@ -62,14 +62,15 @@ if (typeof(window) != 'undefined') { var PRECISION = 1E10; +var util = {}; + /** * 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) { +util.format = function (value, digits) { if (value === Infinity) { return 'Infinity'; } @@ -84,13 +85,13 @@ var format = function (value, digits) { 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)); + return String(util.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; + return util.round(v, digits) + 'E' + exp; } }; @@ -100,9 +101,8 @@ var format = function (value, digits) { * @param {Number} value * @param {Number} [digits] * @return {Number} roundedValue - * @private */ -var round = function (value, digits) { +util.round = function (value, digits) { digits = (digits != undefined) ? Math.pow(10, digits) : PRECISION; return Math.round(value * digits) / digits; @@ -112,9 +112,8 @@ var round = function (value, digits) { * Create a semi UUID * source: http://stackoverflow.com/a/105074/1262753 * @return {String} uuid - * @private */ -var createUUID = function () { +util.createUUID = function () { var S4 = function () { return Math.floor( Math.random() * 0x10000 /* 65536 */ @@ -335,7 +334,7 @@ Unit.prototype.hasBase = function(base) { /** * Check if this unit has a base equal to another base - * @param {math.type.Unit} other + * @param {Unit} other * @return {Boolean} true if equal base */ Unit.prototype.equalBase = function(other) { @@ -356,6 +355,7 @@ Unit.prototype.equals = function(other) { * @return {String} */ Unit.prototype.toString = function() { + var value; if (!this.fixPrefix) { // find the best prefix value (resulting in the value of which // the absolute value of the log10 is closest to zero, @@ -383,12 +383,12 @@ Unit.prototype.toString = function() { } } - var value = this._unnormalize(this.value, bestPrefix.value); - return format(value) + ' ' + bestPrefix.name + this.unit.name; + value = this._unnormalize(this.value, bestPrefix.value); + return util.format(value) + ' ' + bestPrefix.name + this.unit.name; } else { - var value = this._unnormalize(this.value); - return format(value) + ' ' + this.prefix.name + this.unit.name; + value = this._unnormalize(this.value); + return util.format(value) + ' ' + this.prefix.name + this.unit.name; } }; @@ -706,7 +706,7 @@ Complex.prototype.toString = function () { if (this.im === 0) { // real value - str = format(this.re); + str = util.format(this.re); } else if (this.re === 0) { // purely complex value @@ -717,25 +717,25 @@ Complex.prototype.toString = function () { str = '-i'; } else { - str = format(this.im) + 'i'; + str = util.format(this.im) + 'i'; } } else { // complex value if (this.im > 0) { if (this.im == 1) { - str = format(this.re) + ' + i'; + str = util.format(this.re) + ' + i'; } else { - str = format(this.re) + ' + ' + format(this.im) + 'i'; + str = util.format(this.re) + ' + ' + util.format(this.im) + 'i'; } } else { if (this.im == -1) { - str = format(this.re) + ' - i'; + str = util.format(this.re) + ' - i'; } else { - str = format(this.re) + ' - ' + format(Math.abs(this.im)) + 'i'; + str = util.format(this.re) + ' - ' + util.format(Math.abs(this.im)) + 'i'; } } } @@ -853,19 +853,28 @@ math.i = math.I; * Create a TypeError with message: * 'Function does not support a parameter of type '; * @param {String} fn - * @param {*} value + * @param {*} value1 + * @param {*} [value2] * @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); +function newUnsupportedTypeError(fn, value1, value2) { + var msg = undefined; + if (arguments.length == 2) { + var t = type(value1); + msg = 'Function ' + fn + ' does not support a parameter of type ' + t; + } + else if (arguments.length > 2) { + var types = []; + for (var i = 1; i < arguments.length; i++) { + types += type(arguments[i]) + } + msg = 'Function ' + fn + ' does not support a parameters of type ' + types.join(', '); } else { - return new Error(msg); + msg = 'Unsupported parameter in function ' + fn; } + + return new TypeError(msg); } /** @@ -875,7 +884,7 @@ function newUnsupportedTypeError(fn, value) { * @return {Unit} res */ function unit_in(x, unit) { - if (isUnit(x)) { + if (x instanceof Unit) { // Test if unit has no value if (unit.hasValue) { throw new Error('Cannot convert to a unit with a value'); @@ -936,7 +945,7 @@ function sin(x) { ); } - if (isUnit(x)) { + if (x instanceof Unit) { if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { throw new TypeError ('Unit in function cos is no angle'); } @@ -975,9 +984,66 @@ sin.doc = { ] }; +/** + * Computes the principal value of the arc tangent of y/x in radians, atan2(y,x) + * @param {Number | Complex} y + * @param {Number | Complex} x + * @return {Number | Complex} res + */ +function atan2(y, x) { + if (isNumber(y)) { + if (isNumber(x)) { + return Math.atan2(y, x); + } + else if (x instanceof Complex) { + return Math.atan2(y, x.re); + } + } + else if (y instanceof Complex) { + if (isNumber(x)) { + return Math.atan2(y.re, x); + } + else if (x instanceof Complex) { + return Math.atan2(y.re, x.re); + } + } + + // TODO: implement array support + // TODO: implement matrix support + + throw newUnsupportedTypeError('atan2', y, x); +} + +math.atan2 = atan2; + +/** + * Function documentation + */ +atan2.doc = { + 'name': 'atan2', + 'category': 'Trigonometry', + 'syntax': [ + 'atan2(y, x)' + ], + 'description': + 'Computes the principal value of the arc tangent of y/x in radians.', + 'examples': [ + 'atan2(2, 2) / pi', + 'angle = 60 deg in rad', + 'x = cos(angle)', + 'y = sin(angle)', + 'atan2(y, x)' + ], + 'seealso': [ + 'sin', + 'cos', + 'tan' + ] +}; + /** * Calculate the inverse sine of a value, asin(x) - * @param {Number | Complex | Unit} x + * @param {Number | Complex} x * @return {Number | Complex} res */ function asin(x) { @@ -1041,7 +1107,7 @@ asin.doc = { /** * Calculate the inverse tangent of a value, atan(x) - * @param {Number | Complex | Unit} x + * @param {Number | Complex} x * @return {Number | Complex} res */ function atan(x) { @@ -1114,7 +1180,7 @@ function cos(x) { ); } - if (isUnit(x)) { + if (x instanceof Unit) { if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { throw new TypeError ('Unit in function cos is no angle'); } @@ -1174,7 +1240,7 @@ function tan(x) { ); } - if (isUnit(x)) { + if (x instanceof Unit) { if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { throw new TypeError ('Unit in function tan is no angle'); } @@ -1214,7 +1280,7 @@ tan.doc = { /** * Calculate the inverse cosine of a value, acos(x) - * @param {Number | Complex | Unit} x + * @param {Number | Complex} x * @return {Number | Complex} res */ function acos(x) { @@ -1276,6 +1342,135 @@ acos.doc = { ] }; +/** + * Round a value towards the nearest integer, round(x [, n]) + * @param {Number | Complex} x + * @param {Number} [n] number of digits + * @return {Number | Complex} res + */ +function round(x, n) { + if (n == undefined) { + // round (x) + if (isNumber(x)) { + return Math.round(x); + } + + if (x instanceof Complex) { + return new Complex ( + Math.round(x.re), + Math.round(x.im) + ); + } + + throw newUnsupportedTypeError('round', x); + } + else { + // round (x, n) + if (!isNumber(n)) { + throw new TypeError('Number of digits in function round must be an integer'); + } + if (n !== Math.round(n)) { + throw new TypeError('Number of digits in function round must be integer'); + } + if (n < 0 || n > 9) { + throw new Error ('Number of digits in function round must be in te range of 0-9'); + } + + if (isNumber(x)) { + return util.round(x, n); + } + + if (x instanceof Complex) { + return new Complex ( + util.round(x.re, n), + util.round(x.im, n) + ); + } + + throw newUnsupportedTypeError('round', x, n); + } + + // TODO: implement array support + // TODO: implement matrix support + +} + + +math.round = round; + +/** + * Function documentation + */ +round.doc = { + 'name': 'round', + 'category': 'Arithmetic', + 'syntax': [ + 'round(x)', + 'round(x, n)' + ], + 'description': + 'round a value towards the nearest integer.' + + 'If x is complex, both real and imaginary part are rounded ' + + 'towards the nearest integer. ' + + 'When n is specified, the value is rounded to n decimals.', + 'examples': [ + 'round(3.2)', + 'round(3.8)', + 'round(-4.2)', + 'round(-4.8)', + 'round(pi, 3)', + 'round(123.45678, 2)' + ], + 'seealso': ['ceil', 'floor', 'fix'] +}; + +/** + * Round a value towards zero, fix(x) + * @param {Number | Complex} x + * @return {Number | Complex} res + */ +function fix(x) { + if (isNumber(x)) { + return (value > 0) ? Math.floor(x) : Math.ceil(x); + } + + if (x instanceof Complex) { + new Complex( + (x.re > 0) ? Math.floor(x.re) : Math.ceil(x.re), + (x.im > 0) ? Math.floor(x.im) : Math.ceil(x.im) + ); + } + + // TODO: implement array support + // TODO: implement matrix support + + throw newUnsupportedTypeError('fix', x); +} + +math.fix = fix; + +/** + * Function documentation + */ +fix.doc = { + 'name': 'fix', + 'category': 'Arithmetic', + 'syntax': [ + 'fix(x)' + ], + 'description': + 'Round a value towards zero.' + + 'If x is complex, both real and imaginary part are rounded ' + + 'towards zero.', + 'examples': [ + 'fix(3.2)', + 'fix(3.8)', + 'fix(-4.2)', + 'fix(-4.8)' + ], + 'seealso': ['ceil', 'floor', 'round'] +}; + /** * Calculate the exponent of a value, exp(x) * @param {Number | Complex} x @@ -1479,5 +1674,126 @@ log.doc = { ] }; +/** + * Round a value towards minus infinity, floor(x) + * @param {Number | Complex} x + * @return {Number | Complex} res + */ +function floor(x) { + if (isNumber(x)) { + return Math.floor(x); + } + + if (x instanceof Complex) { + return new Complex ( + Math.floor(x.re), + Math.floor(x.im) + ); + } + + // TODO: implement array support + // TODO: implement matrix support + + throw newUnsupportedTypeError('floor', x); +} + +math.floor = floor; + +/** + * Function documentation + */ +floor.doc = { + 'name': 'floor', + 'category': 'Arithmetic', + 'syntax': [ + 'floor(x)' + ], + 'description': + 'Round a value towards minus infinity.' + + 'If x is complex, both real and imaginary part are rounded ' + + 'towards minus infinity.', + 'examples': [ + 'floor(3.2)', + 'floor(3.8)', + 'floor(-4.2)' + ], + 'seealso': ['ceil', 'fix', 'round'] +}; + +/** + * Round a value towards plus infinity, ceil(x) + * @param {Number | Complex} x + * @return {Number | Complex} res + */ +function ceil(x) { + if (isNumber(x)) { + return Math.ceil(x); + } + + if (x instanceof Complex) { + return new Complex ( + Math.ceil(x.re), + Math.ceil(x.im) + ); + } + + // TODO: implement array support + // TODO: implement matrix support + + throw newUnsupportedTypeError('ceil', x); +} + +math.ceil = ceil; + +/** + * Function documentation + */ +ceil.doc = { + 'name': 'ceil', + 'category': 'Arithmetic', + 'syntax': [ + 'ceil(x)' + ], + 'description': + 'Round a value towards plus infinity.' + + 'If x is complex, both real and imaginary part are rounded ' + + 'towards plus infinity.', + 'examples': [ + 'ceil(3.2)', + 'ceil(3.8)', + 'ceil(-4.2)' + ], + 'seealso': ['floor', 'fix', 'round'] +}; + +/** + * Return a random number between 0 and 1 + * @return {Number} res + */ +function random () { + // TODO: implement parameter min and max + return Math.random(); +} + +math.random = random; + +/** + * Function documentation + */ +random.doc = { + 'name': 'random', + 'category': 'Probability', + 'syntax': [ + 'random()' + ], + 'description': + 'Return a random number between 0 and 1.', + 'examples': [ + 'random()', + '100 * random()' + ], + 'seealso': [] +}; + })(); diff --git a/lib/math.min.js b/lib/math.min.js index 20cdffd64..68f70ce3f 100644 --- a/lib/math.min.js +++ b/lib/math.min.js @@ -22,4 +22,4 @@ * License for the specific language governing permissions and limitations under * the License. */ -(function(){function e(a,i){if(this.constructor!=e)throw Error("Unit constructor must be called with the new operator");this.value=1,this.unit=e.UNIT_NONE,this.prefix=e.PREFIX_NONE,this.hasUnit=!1,this.hasValue=!1,this.fixPrefix=!1,this._init(a,i)}function a(e,i){if(this.constructor!=a)throw Error("Complex constructor must be called with the new operator");this.re=e||0,this.im=i||0}function i(e){return e instanceof Number||"number"==typeof e}function t(a){return a instanceof e}function n(e){var a=typeof e;if("object"==a){if(null==e)return"null";if(e instanceof Array)return"array";if(e&&e.constructor&&e.constructor.name)return e.constructor.name}return a}function s(e,a){var i=n(a),t="Function "+e+" does not support a parameter of type "+i;return"undefined"!=typeof TypeError?new TypeError(t):Error(t)}function f(e,a){if(t(e)){if(a.hasValue)throw Error("Cannot convert to a unit with a value");if(!a.hasUnit)throw Error("Unit expected on the right hand side of function in");var i=a.copy();return i.value=e.value,i.fixPrefix=!0,i}throw s("in",e)}function r(n){if(i(n))return Math.sin(n);if(n instanceof a)return new a(.5*Math.sin(n.re)*(Math.exp(-n.im)+Math.exp(n.im)),.5*Math.cos(n.re)*(Math.exp(n.im)-Math.exp(-n.im)));if(t(n)){if(!n.hasBase(e.BASE_UNITS.ANGLE))throw new TypeError("Unit in function cos is no angle");return Math.sin(n.value)}throw s("sin",n)}function o(e){if(i(e))return e>=-1&&1>=e?Math.asin(e):o(new a(e,0));if(e instanceof a){var t=e.re,n=e.im,f=new a(n*n-t*t+1,-2*t*n),r=N(f),u=new a(r.re-n,r.im+t),c=h(u);return new a(c.im,-c.re)}throw s("asin",e)}function u(e){if(i(e))return Math.atan(e);if(e instanceof a){var t=e.re,n=e.im,f=t*t+(1-n)*(1-n),r=new a((1-n*n-t*t)/f,-2*t/f),o=h(r);return new a(-.5*o.im,.5*o.re)}throw s("atan",e)}function c(n){if(i(n))return Math.cos(n);if(n instanceof a)return new a(.5*Math.cos(n.re)*(Math.exp(-n.im)+Math.exp(n.im)),.5*Math.sin(n.re)*(Math.exp(-n.im)-Math.exp(n.im)));if(t(n)){if(!n.hasBase(e.BASE_UNITS.ANGLE))throw new TypeError("Unit in function cos is no angle");return Math.cos(n.value)}throw s("cos",n)}function l(n){if(i(n))return Math.tan(n);if(n instanceof a){var f=Math.exp(-4*n.im)+2*Math.exp(-2*n.im)*Math.cos(2*n.re)+1;return new a(2*Math.exp(-2*n.im)*Math.sin(2*n.re)/f,(1-Math.exp(-4*n.im))/f)}if(t(n)){if(!n.hasBase(e.BASE_UNITS.ANGLE))throw new TypeError("Unit in function tan is no angle");return Math.tan(n.value)}throw s("tan",n)}function m(e){if(i(e))return e>=-1&&1>=e?Math.acos(e):m(new a(e,0));if(e instanceof a){var t=new a(e.im*e.im-e.re*e.re+1,-2*e.re*e.im),n=N(t),f=new a(n.re-e.im,n.im+e.re),r=h(f);return new a(1.5707963267948966-r.im,r.re)}throw s("acos",e)}function p(e){if(i(e))return Math.exp(e);if(e instanceof a){var t=Math.exp(e.re);return new a(t*Math.cos(e.im),t*Math.sin(e.im))}throw s("exp",e)}function N(e){if(i(e))return e>=0?Math.sqrt(e):N(new a(e,0));if(e instanceof a){var t=Math.sqrt(e.re*e.re+e.im*e.im);return e.im>=0?new a(.5*Math.sqrt(2*(t+e.re)),.5*Math.sqrt(2*(t-e.re))):new a(.5*Math.sqrt(2*(t+e.re)),-.5*Math.sqrt(2*(t-e.re)))}throw s("sqrt",e)}function v(e){if(i(e))return Math.abs(e);if(e instanceof a)return Math.sqrt(e.re*e.re+e.im*e.im);throw s("abs",e)}function h(e){if(i(e))return e>=0?Math.log(e):h(new a(e,0));if(e instanceof a)return new a(Math.log(Math.sqrt(e.re*e.re+e.im*e.im)),Math.atan2(e.im,e.re));throw s("log",e)}var E={type:{},parser:{}};"undefined"!=typeof module&&module.exports!==void 0&&(module.exports=E),"undefined"!=typeof exports&&(exports=E),"undefined"!=typeof require&&"undefined"!=typeof define&&define(function(){return E}),"undefined"!=typeof window&&(window.math=E);var x=1e10,M=function(e,a){if(1/0===e)return"Infinity";if(e===-1/0)return"-Infinity";if(0/0===e)return"NaN";var i=Math.abs(e);if(i>1e-4&&1e6>i||0==i)return O(e,a)+"";var t=Math.round(Math.log(i)/Math.LN10),n=e/Math.pow(10,t);return O(n,a)+"E"+t},O=function(e,a){return a=void 0!=a?Math.pow(10,a):x,Math.round(e*a)/a};if(!Array.prototype.indexOf){Array.prototype.indexOf=function(e){for(var a=0;this.length>a;a++)if(this[a]==e)return a;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(b){}}Array.prototype.forEach||(Array.prototype.forEach=function(e,a){for(var i=0,t=this.length;t>i;++i)e.call(a||this,this[i],i,this)}),E.type.Unit=e,e.prototype.copy=function(){var a=new e;for(var i in this)this.hasOwnProperty(i)&&(a[i]=this[i]);return a},e.endsWith=function(e,a){var i=e.length-a.length,t=e.length;return e.substring(i,t)===a},e.prototype._init=function(a,i){if(void 0!==i){for(var t=e.UNITS,n=!1,s=0,f=t.length;f>s;s++){var r=t[s];if(e.endsWith(i,r.name)){var o=i.length-r.name.length,u=i.substring(0,o),c=r.prefixes[u];if(void 0!==c){this.unit=r,this.prefix=c,this.hasUnit=!0,n=!0;break}}}if(!n)throw Error('String "'+i+'" is no unit')}void 0!==a?(this.value=this._normalize(a),this.hasValue=!0):this.value=this._normalize(1)},e.prototype._normalize=function(e){return(e+this.unit.offset)*this.unit.value*this.prefix.value},e.prototype._unnormalize=function(e,a){return void 0===a?e/this.unit.value/this.prefix.value-this.unit.offset:e/this.unit.value/a-this.unit.offset},e.isUnit=function(a){for(var i=e.UNITS,t=i.length,n=0;t>n;n++){var s=i[n];if(e.endsWith(a,s.name)){var f=a.length-s.name.length;if(0==f)return!0;var r=a.substring(0,f),o=s.prefixes[r];if(void 0!==o)return!0}}return!1},e.prototype.hasBase=function(e){return void 0===this.unit.base?void 0===e:this.unit.base===e},e.prototype.equalBase=function(e){return this.unit.base===e.unit.base},e.prototype.equals=function(e){return this.equalBase(e)&&this.value==e.value},e.prototype.toString=function(){if(this.fixPrefix){var a=this._unnormalize(this.value);return M(a)+" "+this.prefix.name+this.unit.name}var i=e.PREFIX_NONE,t=Math.abs(Math.log(this.value/i.value)/Math.LN10-1.5),n=this.unit.prefixes;for(var s in n)if(n.hasOwnProperty(s)){var f=n[s];if(f.scientific){var r=Math.abs(Math.log(this.value/f.value)/Math.LN10-1.5);t>r&&(i=f,t=r)}}var a=this._unnormalize(this.value,i.value);return M(a)+" "+i.name+this.unit.name},e.PREFIXES={NONE:{"":{name:"",value:1,scientific:!0}},SHORT:{"":{name:"",value:1,scientific:!0},da:{name:"da",value:10,scientific:!1},h:{name:"h",value:100,scientific:!1},k:{name:"k",value:1e3,scientific:!0},M:{name:"M",value:1e6,scientific:!0},G:{name:"G",value:1e9,scientific:!0},T:{name:"T",value:1e12,scientific:!0},P:{name:"P",value:1e15,scientific:!0},E:{name:"E",value:1e18,scientific:!0},Z:{name:"Z",value:1e21,scientific:!0},Y:{name:"Y",value:1e24,scientific:!0},d:{name:"d",value:.1,scientific:!1},c:{name:"c",value:.01,scientific:!1},m:{name:"m",value:.001,scientific:!0},u:{name:"u",value:1e-6,scientific:!0},n:{name:"n",value:1e-9,scientific:!0},p:{name:"p",value:1e-12,scientific:!0},f:{name:"f",value:1e-15,scientific:!0},a:{name:"a",value:1e-18,scientific:!0},z:{name:"z",value:1e-21,scientific:!0},y:{name:"y",value:1e-24,scientific:!0}},LONG:{"":{name:"",value:1,scientific:!0},deca:{name:"deca",value:10,scientific:!1},hecto:{name:"hecto",value:100,scientific:!1},kilo:{name:"kilo",value:1e3,scientific:!0},mega:{name:"mega",value:1e6,scientific:!0},giga:{name:"giga",value:1e9,scientific:!0},tera:{name:"tera",value:1e12,scientific:!0},peta:{name:"peta",value:1e15,scientific:!0},exa:{name:"exa",value:1e18,scientific:!0},zetta:{name:"zetta",value:1e21,scientific:!0},yotta:{name:"yotta",value:1e24,scientific:!0},deci:{name:"deci",value:.1,scientific:!1},centi:{name:"centi",value:.01,scientific:!1},milli:{name:"milli",value:.001,scientific:!0},micro:{name:"micro",value:1e-6,scientific:!0},nano:{name:"nano",value:1e-9,scientific:!0},pico:{name:"pico",value:1e-12,scientific:!0},femto:{name:"femto",value:1e-15,scientific:!0},atto:{name:"atto",value:1e-18,scientific:!0},zepto:{name:"zepto",value:1e-21,scientific:!0},yocto:{name:"yocto",value:1e-24,scientific:!0}},BINARY_SHORT:{"":{name:"",value:1,scientific:!0},k:{name:"k",value:1024,scientific:!0},M:{name:"M",value:Math.pow(1024,2),scientific:!0},G:{name:"G",value:Math.pow(1024,3),scientific:!0},T:{name:"T",value:Math.pow(1024,4),scientific:!0},P:{name:"P",value:Math.pow(1024,5),scientific:!0},E:{name:"E",value:Math.pow(1024,6),scientific:!0},Z:{name:"Z",value:Math.pow(1024,7),scientific:!0},Y:{name:"Y",value:Math.pow(1024,8),scientific:!0},Ki:{name:"Ki",value:1024,scientific:!0},Mi:{name:"Mi",value:Math.pow(1024,2),scientific:!0},Gi:{name:"Gi",value:Math.pow(1024,3),scientific:!0},Ti:{name:"Ti",value:Math.pow(1024,4),scientific:!0},Pi:{name:"Pi",value:Math.pow(1024,5),scientific:!0},Ei:{name:"Ei",value:Math.pow(1024,6),scientific:!0},Zi:{name:"Zi",value:Math.pow(1024,7),scientific:!0},Yi:{name:"Yi",value:Math.pow(1024,8),scientific:!0}},BINARY_LONG:{"":{name:"",value:1,scientific:!0},kilo:{name:"kilo",value:1024,scientific:!0},mega:{name:"mega",value:Math.pow(1024,2),scientific:!0},giga:{name:"giga",value:Math.pow(1024,3),scientific:!0},tera:{name:"tera",value:Math.pow(1024,4),scientific:!0},peta:{name:"peta",value:Math.pow(1024,5),scientific:!0},exa:{name:"exa",value:Math.pow(1024,6),scientific:!0},zetta:{name:"zetta",value:Math.pow(1024,7),scientific:!0},yotta:{name:"yotta",value:Math.pow(1024,8),scientific:!0},kibi:{name:"kibi",value:1024,scientific:!0},mebi:{name:"mebi",value:Math.pow(1024,2),scientific:!0},gibi:{name:"gibi",value:Math.pow(1024,3),scientific:!0},tebi:{name:"tebi",value:Math.pow(1024,4),scientific:!0},pebi:{name:"pebi",value:Math.pow(1024,5),scientific:!0},exi:{name:"exi",value:Math.pow(1024,6),scientific:!0},zebi:{name:"zebi",value:Math.pow(1024,7),scientific:!0},yobi:{name:"yobi",value:Math.pow(1024,8),scientific:!0}}},e.PREFIX_NONE={name:"",value:1,scientific:!0},e.BASE_UNITS={NONE:{},LENGTH:{},MASS:{},TIME:{},CURRENT:{},TEMPERATURE:{},LUMINOUS_INTENSITY:{},AMOUNT_OF_SUBSTANCE:{},FORCE:{},SURFACE:{},VOLUME:{},ANGLE:{},BIT:{}};var d=e.BASE_UNITS,T=e.PREFIXES;e.BASE_UNIT_NONE={},e.UNIT_NONE={name:"",base:e.BASE_UNIT_NONE,value:1,offset:0},e.UNITS=[{name:"meter",base:d.LENGTH,prefixes:T.LONG,value:1,offset:0},{name:"inch",base:d.LENGTH,prefixes:T.NONE,value:.0254,offset:0},{name:"foot",base:d.LENGTH,prefixes:T.NONE,value:.3048,offset:0},{name:"yard",base:d.LENGTH,prefixes:T.NONE,value:.9144,offset:0},{name:"mile",base:d.LENGTH,prefixes:T.NONE,value:1609.344,offset:0},{name:"link",base:d.LENGTH,prefixes:T.NONE,value:.201168,offset:0},{name:"rod",base:d.LENGTH,prefixes:T.NONE,value:5.02921,offset:0},{name:"chain",base:d.LENGTH,prefixes:T.NONE,value:20.1168,offset:0},{name:"angstrom",base:d.LENGTH,prefixes:T.NONE,value:1e-10,offset:0},{name:"m",base:d.LENGTH,prefixes:T.SHORT,value:1,offset:0},{name:"ft",base:d.LENGTH,prefixes:T.NONE,value:.3048,offset:0},{name:"yd",base:d.LENGTH,prefixes:T.NONE,value:.9144,offset:0},{name:"mi",base:d.LENGTH,prefixes:T.NONE,value:1609.344,offset:0},{name:"li",base:d.LENGTH,prefixes:T.NONE,value:.201168,offset:0},{name:"rd",base:d.LENGTH,prefixes:T.NONE,value:5.02921,offset:0},{name:"ch",base:d.LENGTH,prefixes:T.NONE,value:20.1168,offset:0},{name:"mil",base:d.LENGTH,prefixes:T.NONE,value:254e-7,offset:0},{name:"m2",base:d.SURFACE,prefixes:T.SHORT,value:1,offset:0},{name:"sqin",base:d.SURFACE,prefixes:T.NONE,value:64516e-8,offset:0},{name:"sqft",base:d.SURFACE,prefixes:T.NONE,value:.09290304,offset:0},{name:"sqyd",base:d.SURFACE,prefixes:T.NONE,value:.83612736,offset:0},{name:"sqmi",base:d.SURFACE,prefixes:T.NONE,value:2589988.110336,offset:0},{name:"sqrd",base:d.SURFACE,prefixes:T.NONE,value:25.29295,offset:0},{name:"sqch",base:d.SURFACE,prefixes:T.NONE,value:404.6873,offset:0},{name:"sqmil",base:d.SURFACE,prefixes:T.NONE,value:6.4516e-10,offset:0},{name:"m3",base:d.VOLUME,prefixes:T.SHORT,value:1,offset:0},{name:"L",base:d.VOLUME,prefixes:T.SHORT,value:.001,offset:0},{name:"litre",base:d.VOLUME,prefixes:T.LONG,value:.001,offset:0},{name:"cuin",base:d.VOLUME,prefixes:T.NONE,value:16387064e-12,offset:0},{name:"cuft",base:d.VOLUME,prefixes:T.NONE,value:.028316846592,offset:0},{name:"cuyd",base:d.VOLUME,prefixes:T.NONE,value:.764554857984,offset:0},{name:"teaspoon",base:d.VOLUME,prefixes:T.NONE,value:5e-6,offset:0},{name:"tablespoon",base:d.VOLUME,prefixes:T.NONE,value:15e-6,offset:0},{name:"minim",base:d.VOLUME,prefixes:T.NONE,value:6.161152e-8,offset:0},{name:"fluiddram",base:d.VOLUME,prefixes:T.NONE,value:36966911e-13,offset:0},{name:"fluidounce",base:d.VOLUME,prefixes:T.NONE,value:2957353e-11,offset:0},{name:"gill",base:d.VOLUME,prefixes:T.NONE,value:.0001182941,offset:0},{name:"cup",base:d.VOLUME,prefixes:T.NONE,value:.0002365882,offset:0},{name:"pint",base:d.VOLUME,prefixes:T.NONE,value:.0004731765,offset:0},{name:"quart",base:d.VOLUME,prefixes:T.NONE,value:.0009463529,offset:0},{name:"gallon",base:d.VOLUME,prefixes:T.NONE,value:.003785412,offset:0},{name:"beerbarrel",base:d.VOLUME,prefixes:T.NONE,value:.1173478,offset:0},{name:"oilbarrel",base:d.VOLUME,prefixes:T.NONE,value:.1589873,offset:0},{name:"hogshead",base:d.VOLUME,prefixes:T.NONE,value:.238481,offset:0},{name:"fldr",base:d.VOLUME,prefixes:T.NONE,value:36966911e-13,offset:0},{name:"floz",base:d.VOLUME,prefixes:T.NONE,value:2957353e-11,offset:0},{name:"gi",base:d.VOLUME,prefixes:T.NONE,value:.0001182941,offset:0},{name:"cp",base:d.VOLUME,prefixes:T.NONE,value:.0002365882,offset:0},{name:"pt",base:d.VOLUME,prefixes:T.NONE,value:.0004731765,offset:0},{name:"qt",base:d.VOLUME,prefixes:T.NONE,value:.0009463529,offset:0},{name:"gal",base:d.VOLUME,prefixes:T.NONE,value:.003785412,offset:0},{name:"bbl",base:d.VOLUME,prefixes:T.NONE,value:.1173478,offset:0},{name:"obl",base:d.VOLUME,prefixes:T.NONE,value:.1589873,offset:0},{name:"g",base:d.MASS,prefixes:T.SHORT,value:.001,offset:0},{name:"gram",base:d.MASS,prefixes:T.LONG,value:.001,offset:0},{name:"ton",base:d.MASS,prefixes:T.SHORT,value:907.18474,offset:0},{name:"tonne",base:d.MASS,prefixes:T.SHORT,value:1e3,offset:0},{name:"grain",base:d.MASS,prefixes:T.NONE,value:6479891e-11,offset:0},{name:"dram",base:d.MASS,prefixes:T.NONE,value:.0017718451953125,offset:0},{name:"ounce",base:d.MASS,prefixes:T.NONE,value:.028349523125,offset:0},{name:"poundmass",base:d.MASS,prefixes:T.NONE,value:.45359237,offset:0},{name:"hundredweight",base:d.MASS,prefixes:T.NONE,value:45.359237,offset:0},{name:"stick",base:d.MASS,prefixes:T.NONE,value:.115,offset:0},{name:"gr",base:d.MASS,prefixes:T.NONE,value:6479891e-11,offset:0},{name:"dr",base:d.MASS,prefixes:T.NONE,value:.0017718451953125,offset:0},{name:"oz",base:d.MASS,prefixes:T.NONE,value:.028349523125,offset:0},{name:"lbm",base:d.MASS,prefixes:T.NONE,value:.45359237,offset:0},{name:"cwt",base:d.MASS,prefixes:T.NONE,value:45.359237,offset:0},{name:"s",base:d.TIME,prefixes:T.SHORT,value:1,offset:0},{name:"min",base:d.TIME,prefixes:T.NONE,value:60,offset:0},{name:"h",base:d.TIME,prefixes:T.NONE,value:3600,offset:0},{name:"seconds",base:d.TIME,prefixes:T.LONG,value:1,offset:0},{name:"second",base:d.TIME,prefixes:T.LONG,value:1,offset:0},{name:"sec",base:d.TIME,prefixes:T.LONG,value:1,offset:0},{name:"minutes",base:d.TIME,prefixes:T.NONE,value:60,offset:0},{name:"minute",base:d.TIME,prefixes:T.NONE,value:60,offset:0},{name:"hours",base:d.TIME,prefixes:T.NONE,value:3600,offset:0},{name:"hour",base:d.TIME,prefixes:T.NONE,value:3600,offset:0},{name:"day",base:d.TIME,prefixes:T.NONE,value:86400,offset:0},{name:"days",base:d.TIME,prefixes:T.NONE,value:86400,offset:0},{name:"rad",base:d.ANGLE,prefixes:T.NONE,value:1,offset:0},{name:"deg",base:d.ANGLE,prefixes:T.NONE,value:.017453292519943295,offset:0},{name:"grad",base:d.ANGLE,prefixes:T.NONE,value:.015707963267948967,offset:0},{name:"cycle",base:d.ANGLE,prefixes:T.NONE,value:6.283185307179586,offset:0},{name:"A",base:d.CURRENT,prefixes:T.SHORT,value:1,offset:0},{name:"ampere",base:d.CURRENT,prefixes:T.LONG,value:1,offset:0},{name:"K",base:d.TEMPERATURE,prefixes:T.NONE,value:1,offset:0},{name:"degC",base:d.TEMPERATURE,prefixes:T.NONE,value:1,offset:273.15},{name:"degF",base:d.TEMPERATURE,prefixes:T.NONE,value:1/1.8,offset:459.67},{name:"degR",base:d.TEMPERATURE,prefixes:T.NONE,value:1/1.8,offset:0},{name:"kelvin",base:d.TEMPERATURE,prefixes:T.NONE,value:1,offset:0},{name:"celsius",base:d.TEMPERATURE,prefixes:T.NONE,value:1,offset:273.15},{name:"fahrenheit",base:d.TEMPERATURE,prefixes:T.NONE,value:1/1.8,offset:459.67},{name:"rankine",base:d.TEMPERATURE,prefixes:T.NONE,value:1/1.8,offset:0},{name:"mol",base:d.AMOUNT_OF_SUBSTANCE,prefixes:T.NONE,value:1,offset:0},{name:"mole",base:d.AMOUNT_OF_SUBSTANCE,prefixes:T.NONE,value:1,offset:0},{name:"cd",base:d.LUMINOUS_INTENSITY,prefixes:T.NONE,value:1,offset:0},{name:"candela",base:d.LUMINOUS_INTENSITY,prefixes:T.NONE,value:1,offset:0},{name:"N",base:d.FORCE,prefixes:T.SHORT,value:1,offset:0},{name:"newton",base:d.FORCE,prefixes:T.LONG,value:1,offset:0},{name:"lbf",base:d.FORCE,prefixes:T.NONE,value:4.4482216152605,offset:0},{name:"poundforce",base:d.FORCE,prefixes:T.NONE,value:4.4482216152605,offset:0},{name:"b",base:d.BIT,prefixes:T.BINARY_SHORT,value:1,offset:0},{name:"bits",base:d.BIT,prefixes:T.BINARY_LONG,value:1,offset:0},{name:"B",base:d.BIT,prefixes:T.BINARY_SHORT,value:8,offset:0},{name:"bytes",base:d.BIT,prefixes:T.BINARY_LONG,value:8,offset:0}],E.type.Complex=a,a.prototype.copy=function(){return new a(this.re,this.im)},a.prototype.toString=function(){var e="";return e=0===this.im?M(this.re):0===this.re?1===this.im?"i":-1===this.im?"-i":M(this.im)+"i":this.im>0?1==this.im?M(this.re)+" + i":M(this.re)+" + "+M(this.im)+"i":-1==this.im?M(this.re)+" - i":M(this.re)+" - "+M(Math.abs(this.im))+"i"},a.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"]},E.E=Math.E,E.LN2=Math.LN2,E.LN10=Math.LN10,E.LOG2E=Math.LOG2E,E.LOG10E=Math.LOG10E,E.PI=Math.PI,E.SQRT1_2=Math.SQRT1_2,E.SQRT2=Math.SQRT2,E.I=new a(0,-1),E.pi=E.PI,E.e=E.E,E.i=E.I,E["in"]=f,f.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:[]},E.sin=r,r.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"]},E.asin=o,o.doc={name:"asin",category:"Trigonometry",syntax:["asin(x)"],description:"Compute the inverse sine of a value in radians.",examples:["asin(0.5)","asin(sin(2.3))"],seealso:["sin","acos","asin"]},E.atan=u,u.doc={name:"atan",category:"Trigonometry",syntax:["atan(x)"],description:"Compute the inverse tangent of a value in radians.",examples:["atan(0.5)","atan(tan(2.3))"],seealso:["tan","acos","asin"]},E.cos=c,c.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"]},E.tan=l,l.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"]},E.acos=m,m.doc={name:"acos",category:"Trigonometry",syntax:["acos(x)"],description:"Compute the inverse cosine of a value in radians.",examples:["acos(0.5)","acos(cos(2.3))"],seealso:["cos","acos","asin"]},E.exp=p,p.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"]},E.sqrt=N,N.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"]},E.abs=v,v.doc={name:"abs",category:"Arithmetic",syntax:["abs(x)"],description:"Compute the absolute value.",examples:["abs(3.5)","abs(-4.2)"],seealso:["sign"]},E.log=h,h.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"]}})(); \ No newline at end of file +(function(){function e(a,i){if(this.constructor!=e)throw Error("Unit constructor must be called with the new operator");this.value=1,this.unit=e.UNIT_NONE,this.prefix=e.PREFIX_NONE,this.hasUnit=!1,this.hasValue=!1,this.fixPrefix=!1,this._init(a,i)}function a(e,i){if(this.constructor!=a)throw Error("Complex constructor must be called with the new operator");this.re=e||0,this.im=i||0}function i(e){return e instanceof Number||"number"==typeof e}function t(e){var a=typeof e;if("object"==a){if(null==e)return"null";if(e instanceof Array)return"array";if(e&&e.constructor&&e.constructor.name)return e.constructor.name}return a}function n(e,a){var i=void 0;if(2==arguments.length){var n=t(a);i="Function "+e+" does not support a parameter of type "+n}else if(arguments.length>2){for(var s=[],r=1;arguments.length>r;r++)s+=t(arguments[r]);i="Function "+e+" does not support a parameters of type "+s.join(", ")}else i="Unsupported parameter in function "+e;return new TypeError(i)}function s(a,i){if(a instanceof e){if(i.hasValue)throw Error("Cannot convert to a unit with a value");if(!i.hasUnit)throw Error("Unit expected on the right hand side of function in");var t=i.copy();return t.value=a.value,t.fixPrefix=!0,t}throw n("in",a)}function r(t){if(i(t))return Math.sin(t);if(t instanceof a)return new a(.5*Math.sin(t.re)*(Math.exp(-t.im)+Math.exp(t.im)),.5*Math.cos(t.re)*(Math.exp(t.im)-Math.exp(-t.im)));if(t instanceof e){if(!t.hasBase(e.BASE_UNITS.ANGLE))throw new TypeError("Unit in function cos is no angle");return Math.sin(t.value)}throw n("sin",t)}function o(e,t){if(i(e)){if(i(t))return Math.atan2(e,t);if(t instanceof a)return Math.atan2(e,t.re)}else if(e instanceof a){if(i(t))return Math.atan2(e.re,t);if(t instanceof a)return Math.atan2(e.re,t.re)}throw n("atan2",e,t)}function f(e){if(i(e))return e>=-1&&1>=e?Math.asin(e):f(new a(e,0));if(e instanceof a){var t=e.re,s=e.im,r=new a(s*s-t*t+1,-2*t*s),o=N(r),u=new a(o.re-s,o.im+t),c=x(u);return new a(c.im,-c.re)}throw n("asin",e)}function u(e){if(i(e))return Math.atan(e);if(e instanceof a){var t=e.re,s=e.im,r=t*t+(1-s)*(1-s),o=new a((1-s*s-t*t)/r,-2*t/r),f=x(o);return new a(-.5*f.im,.5*f.re)}throw n("atan",e)}function c(t){if(i(t))return Math.cos(t);if(t instanceof a)return new a(.5*Math.cos(t.re)*(Math.exp(-t.im)+Math.exp(t.im)),.5*Math.sin(t.re)*(Math.exp(-t.im)-Math.exp(t.im)));if(t instanceof e){if(!t.hasBase(e.BASE_UNITS.ANGLE))throw new TypeError("Unit in function cos is no angle");return Math.cos(t.value)}throw n("cos",t)}function l(t){if(i(t))return Math.tan(t);if(t instanceof a){var s=Math.exp(-4*t.im)+2*Math.exp(-2*t.im)*Math.cos(2*t.re)+1;return new a(2*Math.exp(-2*t.im)*Math.sin(2*t.re)/s,(1-Math.exp(-4*t.im))/s)}if(t instanceof e){if(!t.hasBase(e.BASE_UNITS.ANGLE))throw new TypeError("Unit in function tan is no angle");return Math.tan(t.value)}throw n("tan",t)}function m(e){if(i(e))return e>=-1&&1>=e?Math.acos(e):m(new a(e,0));if(e instanceof a){var t=new a(e.im*e.im-e.re*e.re+1,-2*e.re*e.im),s=N(t),r=new a(s.re-e.im,s.im+e.re),o=x(r);return new a(1.5707963267948966-o.im,o.re)}throw n("acos",e)}function p(e,t){if(void 0==t){if(i(e))return Math.round(e);if(e instanceof a)return new a(Math.round(e.re),Math.round(e.im));throw n("round",e)}if(!i(t))throw new TypeError("Number of digits in function round must be an integer");if(t!==Math.round(t))throw new TypeError("Number of digits in function round must be integer");if(0>t||t>9)throw Error("Number of digits in function round must be in te range of 0-9");if(i(e))return y.round(e,t);if(e instanceof a)return new a(y.round(e.re,t),y.round(e.im,t));throw n("round",e,t)}function h(e){if(i(e))return value>0?Math.floor(e):Math.ceil(e);throw e instanceof a&&new a(e.re>0?Math.floor(e.re):Math.ceil(e.re),e.im>0?Math.floor(e.im):Math.ceil(e.im)),n("fix",e)}function v(e){if(i(e))return Math.exp(e);if(e instanceof a){var t=Math.exp(e.re);return new a(t*Math.cos(e.im),t*Math.sin(e.im))}throw n("exp",e)}function N(e){if(i(e))return e>=0?Math.sqrt(e):N(new a(e,0));if(e instanceof a){var t=Math.sqrt(e.re*e.re+e.im*e.im);return e.im>=0?new a(.5*Math.sqrt(2*(t+e.re)),.5*Math.sqrt(2*(t-e.re))):new a(.5*Math.sqrt(2*(t+e.re)),-.5*Math.sqrt(2*(t-e.re)))}throw n("sqrt",e)}function E(e){if(i(e))return Math.abs(e);if(e instanceof a)return Math.sqrt(e.re*e.re+e.im*e.im);throw n("abs",e)}function x(e){if(i(e))return e>=0?Math.log(e):x(new a(e,0));if(e instanceof a)return new a(Math.log(Math.sqrt(e.re*e.re+e.im*e.im)),Math.atan2(e.im,e.re));throw n("log",e)}function d(e){if(i(e))return Math.floor(e);if(e instanceof a)return new a(Math.floor(e.re),Math.floor(e.im));throw n("floor",e)}function M(e){if(i(e))return Math.ceil(e);if(e instanceof a)return new a(Math.ceil(e.re),Math.ceil(e.im));throw n("ceil",e)}function b(){return Math.random()}var O={type:{},parser:{}};"undefined"!=typeof module&&module.exports!==void 0&&(module.exports=O),"undefined"!=typeof exports&&(exports=O),"undefined"!=typeof require&&"undefined"!=typeof define&&define(function(){return O}),"undefined"!=typeof window&&(window.math=O);var g=1e10,y={};if(y.format=function(e,a){if(1/0===e)return"Infinity";if(e===-1/0)return"-Infinity";if(0/0===e)return"NaN";var i=Math.abs(e);if(i>1e-4&&1e6>i||0==i)return y.round(e,a)+"";var t=Math.round(Math.log(i)/Math.LN10),n=e/Math.pow(10,t);return y.round(n,a)+"E"+t},y.round=function(e,a){return a=void 0!=a?Math.pow(10,a):g,Math.round(e*a)/a},y.createUUID=function(){var e=function(){return Math.floor(65536*Math.random()).toString(16)};return e()+e()+"-"+e()+"-"+e()+"-"+e()+"-"+e()+e()+e()},!Array.prototype.indexOf){Array.prototype.indexOf=function(e){for(var a=0;this.length>a;a++)if(this[a]==e)return a;return-1};try{console.log("Warning: Ancient browser detected. Please update your browser")}catch(T){}}Array.prototype.forEach||(Array.prototype.forEach=function(e,a){for(var i=0,t=this.length;t>i;++i)e.call(a||this,this[i],i,this)}),O.type.Unit=e,e.prototype.copy=function(){var a=new e;for(var i in this)this.hasOwnProperty(i)&&(a[i]=this[i]);return a},e.endsWith=function(e,a){var i=e.length-a.length,t=e.length;return e.substring(i,t)===a},e.prototype._init=function(a,i){if(void 0!==i){for(var t=e.UNITS,n=!1,s=0,r=t.length;r>s;s++){var o=t[s];if(e.endsWith(i,o.name)){var f=i.length-o.name.length,u=i.substring(0,f),c=o.prefixes[u];if(void 0!==c){this.unit=o,this.prefix=c,this.hasUnit=!0,n=!0;break}}}if(!n)throw Error('String "'+i+'" is no unit')}void 0!==a?(this.value=this._normalize(a),this.hasValue=!0):this.value=this._normalize(1)},e.prototype._normalize=function(e){return(e+this.unit.offset)*this.unit.value*this.prefix.value},e.prototype._unnormalize=function(e,a){return void 0===a?e/this.unit.value/this.prefix.value-this.unit.offset:e/this.unit.value/a-this.unit.offset},e.isUnit=function(a){for(var i=e.UNITS,t=i.length,n=0;t>n;n++){var s=i[n];if(e.endsWith(a,s.name)){var r=a.length-s.name.length;if(0==r)return!0;var o=a.substring(0,r),f=s.prefixes[o];if(void 0!==f)return!0}}return!1},e.prototype.hasBase=function(e){return void 0===this.unit.base?void 0===e:this.unit.base===e},e.prototype.equalBase=function(e){return this.unit.base===e.unit.base},e.prototype.equals=function(e){return this.equalBase(e)&&this.value==e.value},e.prototype.toString=function(){var a;if(this.fixPrefix)return a=this._unnormalize(this.value),y.format(a)+" "+this.prefix.name+this.unit.name;var i=e.PREFIX_NONE,t=Math.abs(Math.log(this.value/i.value)/Math.LN10-1.5),n=this.unit.prefixes;for(var s in n)if(n.hasOwnProperty(s)){var r=n[s];if(r.scientific){var o=Math.abs(Math.log(this.value/r.value)/Math.LN10-1.5);t>o&&(i=r,t=o)}}return a=this._unnormalize(this.value,i.value),y.format(a)+" "+i.name+this.unit.name},e.PREFIXES={NONE:{"":{name:"",value:1,scientific:!0}},SHORT:{"":{name:"",value:1,scientific:!0},da:{name:"da",value:10,scientific:!1},h:{name:"h",value:100,scientific:!1},k:{name:"k",value:1e3,scientific:!0},M:{name:"M",value:1e6,scientific:!0},G:{name:"G",value:1e9,scientific:!0},T:{name:"T",value:1e12,scientific:!0},P:{name:"P",value:1e15,scientific:!0},E:{name:"E",value:1e18,scientific:!0},Z:{name:"Z",value:1e21,scientific:!0},Y:{name:"Y",value:1e24,scientific:!0},d:{name:"d",value:.1,scientific:!1},c:{name:"c",value:.01,scientific:!1},m:{name:"m",value:.001,scientific:!0},u:{name:"u",value:1e-6,scientific:!0},n:{name:"n",value:1e-9,scientific:!0},p:{name:"p",value:1e-12,scientific:!0},f:{name:"f",value:1e-15,scientific:!0},a:{name:"a",value:1e-18,scientific:!0},z:{name:"z",value:1e-21,scientific:!0},y:{name:"y",value:1e-24,scientific:!0}},LONG:{"":{name:"",value:1,scientific:!0},deca:{name:"deca",value:10,scientific:!1},hecto:{name:"hecto",value:100,scientific:!1},kilo:{name:"kilo",value:1e3,scientific:!0},mega:{name:"mega",value:1e6,scientific:!0},giga:{name:"giga",value:1e9,scientific:!0},tera:{name:"tera",value:1e12,scientific:!0},peta:{name:"peta",value:1e15,scientific:!0},exa:{name:"exa",value:1e18,scientific:!0},zetta:{name:"zetta",value:1e21,scientific:!0},yotta:{name:"yotta",value:1e24,scientific:!0},deci:{name:"deci",value:.1,scientific:!1},centi:{name:"centi",value:.01,scientific:!1},milli:{name:"milli",value:.001,scientific:!0},micro:{name:"micro",value:1e-6,scientific:!0},nano:{name:"nano",value:1e-9,scientific:!0},pico:{name:"pico",value:1e-12,scientific:!0},femto:{name:"femto",value:1e-15,scientific:!0},atto:{name:"atto",value:1e-18,scientific:!0},zepto:{name:"zepto",value:1e-21,scientific:!0},yocto:{name:"yocto",value:1e-24,scientific:!0}},BINARY_SHORT:{"":{name:"",value:1,scientific:!0},k:{name:"k",value:1024,scientific:!0},M:{name:"M",value:Math.pow(1024,2),scientific:!0},G:{name:"G",value:Math.pow(1024,3),scientific:!0},T:{name:"T",value:Math.pow(1024,4),scientific:!0},P:{name:"P",value:Math.pow(1024,5),scientific:!0},E:{name:"E",value:Math.pow(1024,6),scientific:!0},Z:{name:"Z",value:Math.pow(1024,7),scientific:!0},Y:{name:"Y",value:Math.pow(1024,8),scientific:!0},Ki:{name:"Ki",value:1024,scientific:!0},Mi:{name:"Mi",value:Math.pow(1024,2),scientific:!0},Gi:{name:"Gi",value:Math.pow(1024,3),scientific:!0},Ti:{name:"Ti",value:Math.pow(1024,4),scientific:!0},Pi:{name:"Pi",value:Math.pow(1024,5),scientific:!0},Ei:{name:"Ei",value:Math.pow(1024,6),scientific:!0},Zi:{name:"Zi",value:Math.pow(1024,7),scientific:!0},Yi:{name:"Yi",value:Math.pow(1024,8),scientific:!0}},BINARY_LONG:{"":{name:"",value:1,scientific:!0},kilo:{name:"kilo",value:1024,scientific:!0},mega:{name:"mega",value:Math.pow(1024,2),scientific:!0},giga:{name:"giga",value:Math.pow(1024,3),scientific:!0},tera:{name:"tera",value:Math.pow(1024,4),scientific:!0},peta:{name:"peta",value:Math.pow(1024,5),scientific:!0},exa:{name:"exa",value:Math.pow(1024,6),scientific:!0},zetta:{name:"zetta",value:Math.pow(1024,7),scientific:!0},yotta:{name:"yotta",value:Math.pow(1024,8),scientific:!0},kibi:{name:"kibi",value:1024,scientific:!0},mebi:{name:"mebi",value:Math.pow(1024,2),scientific:!0},gibi:{name:"gibi",value:Math.pow(1024,3),scientific:!0},tebi:{name:"tebi",value:Math.pow(1024,4),scientific:!0},pebi:{name:"pebi",value:Math.pow(1024,5),scientific:!0},exi:{name:"exi",value:Math.pow(1024,6),scientific:!0},zebi:{name:"zebi",value:Math.pow(1024,7),scientific:!0},yobi:{name:"yobi",value:Math.pow(1024,8),scientific:!0}}},e.PREFIX_NONE={name:"",value:1,scientific:!0},e.BASE_UNITS={NONE:{},LENGTH:{},MASS:{},TIME:{},CURRENT:{},TEMPERATURE:{},LUMINOUS_INTENSITY:{},AMOUNT_OF_SUBSTANCE:{},FORCE:{},SURFACE:{},VOLUME:{},ANGLE:{},BIT:{}};var w=e.BASE_UNITS,S=e.PREFIXES;e.BASE_UNIT_NONE={},e.UNIT_NONE={name:"",base:e.BASE_UNIT_NONE,value:1,offset:0},e.UNITS=[{name:"meter",base:w.LENGTH,prefixes:S.LONG,value:1,offset:0},{name:"inch",base:w.LENGTH,prefixes:S.NONE,value:.0254,offset:0},{name:"foot",base:w.LENGTH,prefixes:S.NONE,value:.3048,offset:0},{name:"yard",base:w.LENGTH,prefixes:S.NONE,value:.9144,offset:0},{name:"mile",base:w.LENGTH,prefixes:S.NONE,value:1609.344,offset:0},{name:"link",base:w.LENGTH,prefixes:S.NONE,value:.201168,offset:0},{name:"rod",base:w.LENGTH,prefixes:S.NONE,value:5.02921,offset:0},{name:"chain",base:w.LENGTH,prefixes:S.NONE,value:20.1168,offset:0},{name:"angstrom",base:w.LENGTH,prefixes:S.NONE,value:1e-10,offset:0},{name:"m",base:w.LENGTH,prefixes:S.SHORT,value:1,offset:0},{name:"ft",base:w.LENGTH,prefixes:S.NONE,value:.3048,offset:0},{name:"yd",base:w.LENGTH,prefixes:S.NONE,value:.9144,offset:0},{name:"mi",base:w.LENGTH,prefixes:S.NONE,value:1609.344,offset:0},{name:"li",base:w.LENGTH,prefixes:S.NONE,value:.201168,offset:0},{name:"rd",base:w.LENGTH,prefixes:S.NONE,value:5.02921,offset:0},{name:"ch",base:w.LENGTH,prefixes:S.NONE,value:20.1168,offset:0},{name:"mil",base:w.LENGTH,prefixes:S.NONE,value:254e-7,offset:0},{name:"m2",base:w.SURFACE,prefixes:S.SHORT,value:1,offset:0},{name:"sqin",base:w.SURFACE,prefixes:S.NONE,value:64516e-8,offset:0},{name:"sqft",base:w.SURFACE,prefixes:S.NONE,value:.09290304,offset:0},{name:"sqyd",base:w.SURFACE,prefixes:S.NONE,value:.83612736,offset:0},{name:"sqmi",base:w.SURFACE,prefixes:S.NONE,value:2589988.110336,offset:0},{name:"sqrd",base:w.SURFACE,prefixes:S.NONE,value:25.29295,offset:0},{name:"sqch",base:w.SURFACE,prefixes:S.NONE,value:404.6873,offset:0},{name:"sqmil",base:w.SURFACE,prefixes:S.NONE,value:6.4516e-10,offset:0},{name:"m3",base:w.VOLUME,prefixes:S.SHORT,value:1,offset:0},{name:"L",base:w.VOLUME,prefixes:S.SHORT,value:.001,offset:0},{name:"litre",base:w.VOLUME,prefixes:S.LONG,value:.001,offset:0},{name:"cuin",base:w.VOLUME,prefixes:S.NONE,value:16387064e-12,offset:0},{name:"cuft",base:w.VOLUME,prefixes:S.NONE,value:.028316846592,offset:0},{name:"cuyd",base:w.VOLUME,prefixes:S.NONE,value:.764554857984,offset:0},{name:"teaspoon",base:w.VOLUME,prefixes:S.NONE,value:5e-6,offset:0},{name:"tablespoon",base:w.VOLUME,prefixes:S.NONE,value:15e-6,offset:0},{name:"minim",base:w.VOLUME,prefixes:S.NONE,value:6.161152e-8,offset:0},{name:"fluiddram",base:w.VOLUME,prefixes:S.NONE,value:36966911e-13,offset:0},{name:"fluidounce",base:w.VOLUME,prefixes:S.NONE,value:2957353e-11,offset:0},{name:"gill",base:w.VOLUME,prefixes:S.NONE,value:.0001182941,offset:0},{name:"cup",base:w.VOLUME,prefixes:S.NONE,value:.0002365882,offset:0},{name:"pint",base:w.VOLUME,prefixes:S.NONE,value:.0004731765,offset:0},{name:"quart",base:w.VOLUME,prefixes:S.NONE,value:.0009463529,offset:0},{name:"gallon",base:w.VOLUME,prefixes:S.NONE,value:.003785412,offset:0},{name:"beerbarrel",base:w.VOLUME,prefixes:S.NONE,value:.1173478,offset:0},{name:"oilbarrel",base:w.VOLUME,prefixes:S.NONE,value:.1589873,offset:0},{name:"hogshead",base:w.VOLUME,prefixes:S.NONE,value:.238481,offset:0},{name:"fldr",base:w.VOLUME,prefixes:S.NONE,value:36966911e-13,offset:0},{name:"floz",base:w.VOLUME,prefixes:S.NONE,value:2957353e-11,offset:0},{name:"gi",base:w.VOLUME,prefixes:S.NONE,value:.0001182941,offset:0},{name:"cp",base:w.VOLUME,prefixes:S.NONE,value:.0002365882,offset:0},{name:"pt",base:w.VOLUME,prefixes:S.NONE,value:.0004731765,offset:0},{name:"qt",base:w.VOLUME,prefixes:S.NONE,value:.0009463529,offset:0},{name:"gal",base:w.VOLUME,prefixes:S.NONE,value:.003785412,offset:0},{name:"bbl",base:w.VOLUME,prefixes:S.NONE,value:.1173478,offset:0},{name:"obl",base:w.VOLUME,prefixes:S.NONE,value:.1589873,offset:0},{name:"g",base:w.MASS,prefixes:S.SHORT,value:.001,offset:0},{name:"gram",base:w.MASS,prefixes:S.LONG,value:.001,offset:0},{name:"ton",base:w.MASS,prefixes:S.SHORT,value:907.18474,offset:0},{name:"tonne",base:w.MASS,prefixes:S.SHORT,value:1e3,offset:0},{name:"grain",base:w.MASS,prefixes:S.NONE,value:6479891e-11,offset:0},{name:"dram",base:w.MASS,prefixes:S.NONE,value:.0017718451953125,offset:0},{name:"ounce",base:w.MASS,prefixes:S.NONE,value:.028349523125,offset:0},{name:"poundmass",base:w.MASS,prefixes:S.NONE,value:.45359237,offset:0},{name:"hundredweight",base:w.MASS,prefixes:S.NONE,value:45.359237,offset:0},{name:"stick",base:w.MASS,prefixes:S.NONE,value:.115,offset:0},{name:"gr",base:w.MASS,prefixes:S.NONE,value:6479891e-11,offset:0},{name:"dr",base:w.MASS,prefixes:S.NONE,value:.0017718451953125,offset:0},{name:"oz",base:w.MASS,prefixes:S.NONE,value:.028349523125,offset:0},{name:"lbm",base:w.MASS,prefixes:S.NONE,value:.45359237,offset:0},{name:"cwt",base:w.MASS,prefixes:S.NONE,value:45.359237,offset:0},{name:"s",base:w.TIME,prefixes:S.SHORT,value:1,offset:0},{name:"min",base:w.TIME,prefixes:S.NONE,value:60,offset:0},{name:"h",base:w.TIME,prefixes:S.NONE,value:3600,offset:0},{name:"seconds",base:w.TIME,prefixes:S.LONG,value:1,offset:0},{name:"second",base:w.TIME,prefixes:S.LONG,value:1,offset:0},{name:"sec",base:w.TIME,prefixes:S.LONG,value:1,offset:0},{name:"minutes",base:w.TIME,prefixes:S.NONE,value:60,offset:0},{name:"minute",base:w.TIME,prefixes:S.NONE,value:60,offset:0},{name:"hours",base:w.TIME,prefixes:S.NONE,value:3600,offset:0},{name:"hour",base:w.TIME,prefixes:S.NONE,value:3600,offset:0},{name:"day",base:w.TIME,prefixes:S.NONE,value:86400,offset:0},{name:"days",base:w.TIME,prefixes:S.NONE,value:86400,offset:0},{name:"rad",base:w.ANGLE,prefixes:S.NONE,value:1,offset:0},{name:"deg",base:w.ANGLE,prefixes:S.NONE,value:.017453292519943295,offset:0},{name:"grad",base:w.ANGLE,prefixes:S.NONE,value:.015707963267948967,offset:0},{name:"cycle",base:w.ANGLE,prefixes:S.NONE,value:6.283185307179586,offset:0},{name:"A",base:w.CURRENT,prefixes:S.SHORT,value:1,offset:0},{name:"ampere",base:w.CURRENT,prefixes:S.LONG,value:1,offset:0},{name:"K",base:w.TEMPERATURE,prefixes:S.NONE,value:1,offset:0},{name:"degC",base:w.TEMPERATURE,prefixes:S.NONE,value:1,offset:273.15},{name:"degF",base:w.TEMPERATURE,prefixes:S.NONE,value:1/1.8,offset:459.67},{name:"degR",base:w.TEMPERATURE,prefixes:S.NONE,value:1/1.8,offset:0},{name:"kelvin",base:w.TEMPERATURE,prefixes:S.NONE,value:1,offset:0},{name:"celsius",base:w.TEMPERATURE,prefixes:S.NONE,value:1,offset:273.15},{name:"fahrenheit",base:w.TEMPERATURE,prefixes:S.NONE,value:1/1.8,offset:459.67},{name:"rankine",base:w.TEMPERATURE,prefixes:S.NONE,value:1/1.8,offset:0},{name:"mol",base:w.AMOUNT_OF_SUBSTANCE,prefixes:S.NONE,value:1,offset:0},{name:"mole",base:w.AMOUNT_OF_SUBSTANCE,prefixes:S.NONE,value:1,offset:0},{name:"cd",base:w.LUMINOUS_INTENSITY,prefixes:S.NONE,value:1,offset:0},{name:"candela",base:w.LUMINOUS_INTENSITY,prefixes:S.NONE,value:1,offset:0},{name:"N",base:w.FORCE,prefixes:S.SHORT,value:1,offset:0},{name:"newton",base:w.FORCE,prefixes:S.LONG,value:1,offset:0},{name:"lbf",base:w.FORCE,prefixes:S.NONE,value:4.4482216152605,offset:0},{name:"poundforce",base:w.FORCE,prefixes:S.NONE,value:4.4482216152605,offset:0},{name:"b",base:w.BIT,prefixes:S.BINARY_SHORT,value:1,offset:0},{name:"bits",base:w.BIT,prefixes:S.BINARY_LONG,value:1,offset:0},{name:"B",base:w.BIT,prefixes:S.BINARY_SHORT,value:8,offset:0},{name:"bytes",base:w.BIT,prefixes:S.BINARY_LONG,value:8,offset:0}],O.type.Complex=a,a.prototype.copy=function(){return new a(this.re,this.im)},a.prototype.toString=function(){var e="";return e=0===this.im?y.format(this.re):0===this.re?1===this.im?"i":-1===this.im?"-i":y.format(this.im)+"i":this.im>0?1==this.im?y.format(this.re)+" + i":y.format(this.re)+" + "+y.format(this.im)+"i":-1==this.im?y.format(this.re)+" - i":y.format(this.re)+" - "+y.format(Math.abs(this.im))+"i"},a.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"]},O.E=Math.E,O.LN2=Math.LN2,O.LN10=Math.LN10,O.LOG2E=Math.LOG2E,O.LOG10E=Math.LOG10E,O.PI=Math.PI,O.SQRT1_2=Math.SQRT1_2,O.SQRT2=Math.SQRT2,O.I=new a(0,-1),O.pi=O.PI,O.e=O.E,O.i=O.I,O["in"]=s,s.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:[]},O.sin=r,r.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"]},O.atan2=o,o.doc={name:"atan2",category:"Trigonometry",syntax:["atan2(y, x)"],description:"Computes the principal value of the arc tangent of y/x in radians.",examples:["atan2(2, 2) / pi","angle = 60 deg in rad","x = cos(angle)","y = sin(angle)","atan2(y, x)"],seealso:["sin","cos","tan"]},O.asin=f,f.doc={name:"asin",category:"Trigonometry",syntax:["asin(x)"],description:"Compute the inverse sine of a value in radians.",examples:["asin(0.5)","asin(sin(2.3))"],seealso:["sin","acos","asin"]},O.atan=u,u.doc={name:"atan",category:"Trigonometry",syntax:["atan(x)"],description:"Compute the inverse tangent of a value in radians.",examples:["atan(0.5)","atan(tan(2.3))"],seealso:["tan","acos","asin"]},O.cos=c,c.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"]},O.tan=l,l.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"]},O.acos=m,m.doc={name:"acos",category:"Trigonometry",syntax:["acos(x)"],description:"Compute the inverse cosine of a value in radians.",examples:["acos(0.5)","acos(cos(2.3))"],seealso:["cos","acos","asin"]},O.round=p,p.doc={name:"round",category:"Arithmetic",syntax:["round(x)","round(x, n)"],description:"round a value towards the nearest integer.If x is complex, both real and imaginary part are rounded towards the nearest integer. When n is specified, the value is rounded to n decimals.",examples:["round(3.2)","round(3.8)","round(-4.2)","round(-4.8)","round(pi, 3)","round(123.45678, 2)"],seealso:["ceil","floor","fix"]},O.fix=h,h.doc={name:"fix",category:"Arithmetic",syntax:["fix(x)"],description:"Round a value towards zero.If x is complex, both real and imaginary part are rounded towards zero.",examples:["fix(3.2)","fix(3.8)","fix(-4.2)","fix(-4.8)"],seealso:["ceil","floor","round"]},O.exp=v,v.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"]},O.sqrt=N,N.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"]},O.abs=E,E.doc={name:"abs",category:"Arithmetic",syntax:["abs(x)"],description:"Compute the absolute value.",examples:["abs(3.5)","abs(-4.2)"],seealso:["sign"]},O.log=x,x.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"]},O.floor=d,d.doc={name:"floor",category:"Arithmetic",syntax:["floor(x)"],description:"Round a value towards minus infinity.If x is complex, both real and imaginary part are rounded towards minus infinity.",examples:["floor(3.2)","floor(3.8)","floor(-4.2)"],seealso:["ceil","fix","round"]},O.ceil=M,M.doc={name:"ceil",category:"Arithmetic",syntax:["ceil(x)"],description:"Round a value towards plus infinity.If x is complex, both real and imaginary part are rounded towards plus infinity.",examples:["ceil(3.2)","ceil(3.8)","ceil(-4.2)"],seealso:["floor","fix","round"]},O.random=b,b.doc={name:"random",category:"Probability",syntax:["random()"],description:"Return a random number between 0 and 1.",examples:["random()","100 * random()"],seealso:[]}})(); \ No newline at end of file diff --git a/src/function/arithmetic/ceil.js b/src/function/arithmetic/ceil.js new file mode 100644 index 000000000..7be6d8d90 --- /dev/null +++ b/src/function/arithmetic/ceil.js @@ -0,0 +1,45 @@ +/** + * Round a value towards plus infinity, ceil(x) + * @param {Number | Complex} x + * @return {Number | Complex} res + */ +function ceil(x) { + if (isNumber(x)) { + return Math.ceil(x); + } + + if (x instanceof Complex) { + return new Complex ( + Math.ceil(x.re), + Math.ceil(x.im) + ); + } + + // TODO: implement array support + // TODO: implement matrix support + + throw newUnsupportedTypeError('ceil', x); +} + +math.ceil = ceil; + +/** + * Function documentation + */ +ceil.doc = { + 'name': 'ceil', + 'category': 'Arithmetic', + 'syntax': [ + 'ceil(x)' + ], + 'description': + 'Round a value towards plus infinity.' + + 'If x is complex, both real and imaginary part are rounded ' + + 'towards plus infinity.', + 'examples': [ + 'ceil(3.2)', + 'ceil(3.8)', + 'ceil(-4.2)' + ], + 'seealso': ['floor', 'fix', 'round'] +}; diff --git a/src/function/arithmetic/fix.js b/src/function/arithmetic/fix.js new file mode 100644 index 000000000..eb0f4b50e --- /dev/null +++ b/src/function/arithmetic/fix.js @@ -0,0 +1,46 @@ +/** + * Round a value towards zero, fix(x) + * @param {Number | Complex} x + * @return {Number | Complex} res + */ +function fix(x) { + if (isNumber(x)) { + return (value > 0) ? Math.floor(x) : Math.ceil(x); + } + + if (x instanceof Complex) { + new Complex( + (x.re > 0) ? Math.floor(x.re) : Math.ceil(x.re), + (x.im > 0) ? Math.floor(x.im) : Math.ceil(x.im) + ); + } + + // TODO: implement array support + // TODO: implement matrix support + + throw newUnsupportedTypeError('fix', x); +} + +math.fix = fix; + +/** + * Function documentation + */ +fix.doc = { + 'name': 'fix', + 'category': 'Arithmetic', + 'syntax': [ + 'fix(x)' + ], + 'description': + 'Round a value towards zero.' + + 'If x is complex, both real and imaginary part are rounded ' + + 'towards zero.', + 'examples': [ + 'fix(3.2)', + 'fix(3.8)', + 'fix(-4.2)', + 'fix(-4.8)' + ], + 'seealso': ['ceil', 'floor', 'round'] +}; diff --git a/src/function/arithmetic/floor.js b/src/function/arithmetic/floor.js new file mode 100644 index 000000000..c81e2040a --- /dev/null +++ b/src/function/arithmetic/floor.js @@ -0,0 +1,45 @@ +/** + * Round a value towards minus infinity, floor(x) + * @param {Number | Complex} x + * @return {Number | Complex} res + */ +function floor(x) { + if (isNumber(x)) { + return Math.floor(x); + } + + if (x instanceof Complex) { + return new Complex ( + Math.floor(x.re), + Math.floor(x.im) + ); + } + + // TODO: implement array support + // TODO: implement matrix support + + throw newUnsupportedTypeError('floor', x); +} + +math.floor = floor; + +/** + * Function documentation + */ +floor.doc = { + 'name': 'floor', + 'category': 'Arithmetic', + 'syntax': [ + 'floor(x)' + ], + 'description': + 'Round a value towards minus infinity.' + + 'If x is complex, both real and imaginary part are rounded ' + + 'towards minus infinity.', + 'examples': [ + 'floor(3.2)', + 'floor(3.8)', + 'floor(-4.2)' + ], + 'seealso': ['ceil', 'fix', 'round'] +}; diff --git a/src/function/arithmetic/round.js b/src/function/arithmetic/round.js new file mode 100644 index 000000000..dacb22082 --- /dev/null +++ b/src/function/arithmetic/round.js @@ -0,0 +1,81 @@ +/** + * Round a value towards the nearest integer, round(x [, n]) + * @param {Number | Complex} x + * @param {Number} [n] number of digits + * @return {Number | Complex} res + */ +function round(x, n) { + if (n == undefined) { + // round (x) + if (isNumber(x)) { + return Math.round(x); + } + + if (x instanceof Complex) { + return new Complex ( + Math.round(x.re), + Math.round(x.im) + ); + } + + throw newUnsupportedTypeError('round', x); + } + else { + // round (x, n) + if (!isNumber(n)) { + throw new TypeError('Number of digits in function round must be an integer'); + } + if (n !== Math.round(n)) { + throw new TypeError('Number of digits in function round must be integer'); + } + if (n < 0 || n > 9) { + throw new Error ('Number of digits in function round must be in te range of 0-9'); + } + + if (isNumber(x)) { + return util.round(x, n); + } + + if (x instanceof Complex) { + return new Complex ( + util.round(x.re, n), + util.round(x.im, n) + ); + } + + throw newUnsupportedTypeError('round', x, n); + } + + // TODO: implement array support + // TODO: implement matrix support + +} + + +math.round = round; + +/** + * Function documentation + */ +round.doc = { + 'name': 'round', + 'category': 'Arithmetic', + 'syntax': [ + 'round(x)', + 'round(x, n)' + ], + 'description': + 'round a value towards the nearest integer.' + + 'If x is complex, both real and imaginary part are rounded ' + + 'towards the nearest integer. ' + + 'When n is specified, the value is rounded to n decimals.', + 'examples': [ + 'round(3.2)', + 'round(3.8)', + 'round(-4.2)', + 'round(-4.8)', + 'round(pi, 3)', + 'round(123.45678, 2)' + ], + 'seealso': ['ceil', 'floor', 'fix'] +}; diff --git a/src/function/probability/random.js b/src/function/probability/random.js new file mode 100644 index 000000000..9cd49af7a --- /dev/null +++ b/src/function/probability/random.js @@ -0,0 +1,28 @@ +/** + * Return a random number between 0 and 1 + * @return {Number} res + */ +function random () { + // TODO: implement parameter min and max + return Math.random(); +} + +math.random = random; + +/** + * Function documentation + */ +random.doc = { + 'name': 'random', + 'category': 'Probability', + 'syntax': [ + 'random()' + ], + 'description': + 'Return a random number between 0 and 1.', + 'examples': [ + 'random()', + '100 * random()' + ], + 'seealso': [] +}; diff --git a/src/function/trigonometry/acos.js b/src/function/trigonometry/acos.js index 38bb2bf32..a0b9981c8 100644 --- a/src/function/trigonometry/acos.js +++ b/src/function/trigonometry/acos.js @@ -1,6 +1,6 @@ /** * Calculate the inverse cosine of a value, acos(x) - * @param {Number | Complex | Unit} x + * @param {Number | Complex} x * @return {Number | Complex} res */ function acos(x) { diff --git a/src/function/trigonometry/asin.js b/src/function/trigonometry/asin.js index d63c11101..c81946e00 100644 --- a/src/function/trigonometry/asin.js +++ b/src/function/trigonometry/asin.js @@ -1,6 +1,6 @@ /** * Calculate the inverse sine of a value, asin(x) - * @param {Number | Complex | Unit} x + * @param {Number | Complex} x * @return {Number | Complex} res */ function asin(x) { diff --git a/src/function/trigonometry/atan.js b/src/function/trigonometry/atan.js index fc1457043..1d44a3eb1 100644 --- a/src/function/trigonometry/atan.js +++ b/src/function/trigonometry/atan.js @@ -1,6 +1,6 @@ /** * Calculate the inverse tangent of a value, atan(x) - * @param {Number | Complex | Unit} x + * @param {Number | Complex} x * @return {Number | Complex} res */ function atan(x) { diff --git a/src/function/trigonometry/atan2.js b/src/function/trigonometry/atan2.js new file mode 100644 index 000000000..3d1cc64e7 --- /dev/null +++ b/src/function/trigonometry/atan2.js @@ -0,0 +1,56 @@ +/** + * Computes the principal value of the arc tangent of y/x in radians, atan2(y,x) + * @param {Number | Complex} y + * @param {Number | Complex} x + * @return {Number | Complex} res + */ +function atan2(y, x) { + if (isNumber(y)) { + if (isNumber(x)) { + return Math.atan2(y, x); + } + else if (x instanceof Complex) { + return Math.atan2(y, x.re); + } + } + else if (y instanceof Complex) { + if (isNumber(x)) { + return Math.atan2(y.re, x); + } + else if (x instanceof Complex) { + return Math.atan2(y.re, x.re); + } + } + + // TODO: implement array support + // TODO: implement matrix support + + throw newUnsupportedTypeError('atan2', y, x); +} + +math.atan2 = atan2; + +/** + * Function documentation + */ +atan2.doc = { + 'name': 'atan2', + 'category': 'Trigonometry', + 'syntax': [ + 'atan2(y, x)' + ], + 'description': + 'Computes the principal value of the arc tangent of y/x in radians.', + 'examples': [ + 'atan2(2, 2) / pi', + 'angle = 60 deg in rad', + 'x = cos(angle)', + 'y = sin(angle)', + 'atan2(y, x)' + ], + 'seealso': [ + 'sin', + 'cos', + 'tan' + ] +}; diff --git a/src/function/trigonometry/cos.js b/src/function/trigonometry/cos.js index 68ad0a215..7eb9395f0 100644 --- a/src/function/trigonometry/cos.js +++ b/src/function/trigonometry/cos.js @@ -16,7 +16,7 @@ function cos(x) { ); } - if (isUnit(x)) { + if (x instanceof Unit) { if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { throw new TypeError ('Unit in function cos is no angle'); } diff --git a/src/function/trigonometry/sin.js b/src/function/trigonometry/sin.js index 86afd1716..5ab9cf1d3 100644 --- a/src/function/trigonometry/sin.js +++ b/src/function/trigonometry/sin.js @@ -15,7 +15,7 @@ function sin(x) { ); } - if (isUnit(x)) { + if (x instanceof Unit) { if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { throw new TypeError ('Unit in function cos is no angle'); } diff --git a/src/function/trigonometry/tan.js b/src/function/trigonometry/tan.js index e72725f8f..2963b2277 100644 --- a/src/function/trigonometry/tan.js +++ b/src/function/trigonometry/tan.js @@ -19,7 +19,7 @@ function tan(x) { ); } - if (isUnit(x)) { + if (x instanceof Unit) { if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { throw new TypeError ('Unit in function tan is no angle'); } diff --git a/src/function/units/in.js b/src/function/units/in.js index 3c22e759e..849bda95b 100644 --- a/src/function/units/in.js +++ b/src/function/units/in.js @@ -5,7 +5,7 @@ * @return {Unit} res */ function unit_in(x, unit) { - if (isUnit(x)) { + if (x instanceof Unit) { // Test if unit has no value if (unit.hasValue) { throw new Error('Cannot convert to a unit with a value'); diff --git a/src/functions.js b/src/functions.js index 3034bc98a..230ca5f63 100644 --- a/src/functions.js +++ b/src/functions.js @@ -6,17 +6,26 @@ * Create a TypeError with message: * 'Function does not support a parameter of type '; * @param {String} fn - * @param {*} value + * @param {*} value1 + * @param {*} [value2] * @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); +function newUnsupportedTypeError(fn, value1, value2) { + var msg = undefined; + if (arguments.length == 2) { + var t = type(value1); + msg = 'Function ' + fn + ' does not support a parameter of type ' + t; + } + else if (arguments.length > 2) { + var types = []; + for (var i = 1; i < arguments.length; i++) { + types += type(arguments[i]) + } + msg = 'Function ' + fn + ' does not support a parameters of type ' + types.join(', '); } else { - return new Error(msg); + msg = 'Unsupported parameter in function ' + fn; } + + return new TypeError(msg); } diff --git a/src/type/Complex.js b/src/type/Complex.js index d5ceb4399..48f9e2d03 100644 --- a/src/type/Complex.js +++ b/src/type/Complex.js @@ -39,7 +39,7 @@ Complex.prototype.toString = function () { if (this.im === 0) { // real value - str = format(this.re); + str = util.format(this.re); } else if (this.re === 0) { // purely complex value @@ -50,25 +50,25 @@ Complex.prototype.toString = function () { str = '-i'; } else { - str = format(this.im) + 'i'; + str = util.format(this.im) + 'i'; } } else { // complex value if (this.im > 0) { if (this.im == 1) { - str = format(this.re) + ' + i'; + str = util.format(this.re) + ' + i'; } else { - str = format(this.re) + ' + ' + format(this.im) + 'i'; + str = util.format(this.re) + ' + ' + util.format(this.im) + 'i'; } } else { if (this.im == -1) { - str = format(this.re) + ' - i'; + str = util.format(this.re) + ' - i'; } else { - str = format(this.re) + ' - ' + format(Math.abs(this.im)) + 'i'; + str = util.format(this.re) + ' - ' + util.format(Math.abs(this.im)) + 'i'; } } } diff --git a/src/type/Unit.js b/src/type/Unit.js index 41d6e83d7..89a461436 100644 --- a/src/type/Unit.js +++ b/src/type/Unit.js @@ -172,7 +172,7 @@ Unit.prototype.hasBase = function(base) { /** * Check if this unit has a base equal to another base - * @param {math.type.Unit} other + * @param {Unit} other * @return {Boolean} true if equal base */ Unit.prototype.equalBase = function(other) { @@ -193,6 +193,7 @@ Unit.prototype.equals = function(other) { * @return {String} */ Unit.prototype.toString = function() { + var value; if (!this.fixPrefix) { // find the best prefix value (resulting in the value of which // the absolute value of the log10 is closest to zero, @@ -220,12 +221,12 @@ Unit.prototype.toString = function() { } } - var value = this._unnormalize(this.value, bestPrefix.value); - return format(value) + ' ' + bestPrefix.name + this.unit.name; + value = this._unnormalize(this.value, bestPrefix.value); + return util.format(value) + ' ' + bestPrefix.name + this.unit.name; } else { - var value = this._unnormalize(this.value); - return format(value) + ' ' + this.prefix.name + this.unit.name; + value = this._unnormalize(this.value); + return util.format(value) + ' ' + this.prefix.name + this.unit.name; } }; diff --git a/src/util.js b/src/util.js index 32f45d07f..fb02597b9 100644 --- a/src/util.js +++ b/src/util.js @@ -1,14 +1,15 @@ var PRECISION = 1E10; +var util = {}; + /** * 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) { +util.format = function (value, digits) { if (value === Infinity) { return 'Infinity'; } @@ -23,13 +24,13 @@ var format = function (value, digits) { 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)); + return String(util.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; + return util.round(v, digits) + 'E' + exp; } }; @@ -39,9 +40,8 @@ var format = function (value, digits) { * @param {Number} value * @param {Number} [digits] * @return {Number} roundedValue - * @private */ -var round = function (value, digits) { +util.round = function (value, digits) { digits = (digits != undefined) ? Math.pow(10, digits) : PRECISION; return Math.round(value * digits) / digits; @@ -51,9 +51,8 @@ var round = function (value, digits) { * Create a semi UUID * source: http://stackoverflow.com/a/105074/1262753 * @return {String} uuid - * @private */ -var createUUID = function () { +util.createUUID = function () { var S4 = function () { return Math.floor( Math.random() * 0x10000 /* 65536 */