UNPKG

94.7 kBJavaScriptView Raw
1'use strict';
2
3var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
4
5var endsWith = require('../../utils/string').endsWith;
6var clone = require('../../utils/object').clone;
7var constants = require('../../utils/bignumber/constants');
8
9function factory(type, config, load, typed, math) {
10 var add = load(require('../../function/arithmetic/addScalar'));
11 var subtract = load(require('../../function/arithmetic/subtract'));
12 var multiply = load(require('../../function/arithmetic/multiplyScalar'));
13 var divide = load(require('../../function/arithmetic/divideScalar'));
14 var pow = load(require('../../function/arithmetic/pow'));
15 var abs = load(require('../../function/arithmetic/abs'));
16 var fix = load(require('../../function/arithmetic/fix'));
17 var round = load(require('../../function/arithmetic/round'));
18 var equal = load(require('../../function/relational/equal'));
19 var isNumeric = load(require('../../function/utils/isNumeric'));
20 var format = load(require('../../function/string/format'));
21 var getTypeOf = load(require('../../function/utils/typeof'));
22 var toNumber = load(require('../../type/number'));
23 var Complex = load(require('../../type/complex/Complex'));
24
25 /**
26 * A unit can be constructed in the following ways:
27 *
28 * const a = new Unit(value, name)
29 * const b = new Unit(null, name)
30 * const c = Unit.parse(str)
31 *
32 * Example usage:
33 *
34 * const a = new Unit(5, 'cm') // 50 mm
35 * const b = Unit.parse('23 kg') // 23 kg
36 * const c = math.in(a, new Unit(null, 'm') // 0.05 m
37 * const d = new Unit(9.81, "m/s^2") // 9.81 m/s^2
38 *
39 * @class Unit
40 * @constructor Unit
41 * @param {number | BigNumber | Fraction | Complex | boolean} [value] A value like 5.2
42 * @param {string} [name] A unit name like "cm" or "inch", or a derived unit of the form: "u1[^ex1] [u2[^ex2] ...] [/ u3[^ex3] [u4[^ex4]]]", such as "kg m^2/s^2", where each unit appearing after the forward slash is taken to be in the denominator. "kg m^2 s^-2" is a synonym and is also acceptable. Any of the units can include a prefix.
43 */
44 function Unit(value, name) {
45 if (!(this instanceof Unit)) {
46 throw new Error('Constructor must be called with the new operator');
47 }
48
49 if (!(value === null || value === undefined || isNumeric(value) || type.isComplex(value))) {
50 throw new TypeError('First parameter in Unit constructor must be number, BigNumber, Fraction, Complex, or undefined');
51 }
52 if (name !== undefined && (typeof name !== 'string' || name === '')) {
53 throw new TypeError('Second parameter in Unit constructor must be a string');
54 }
55
56 if (name !== undefined) {
57 var u = Unit.parse(name);
58 this.units = u.units;
59 this.dimensions = u.dimensions;
60 } else {
61 this.units = [{
62 unit: UNIT_NONE,
63 prefix: PREFIXES.NONE, // link to a list with supported prefixes
64 power: 0
65 }];
66 this.dimensions = [];
67 for (var i = 0; i < BASE_DIMENSIONS.length; i++) {
68 this.dimensions[i] = 0;
69 }
70 }
71
72 this.value = value !== undefined && value !== null ? this._normalize(value) : null;
73
74 this.fixPrefix = false; // if true, function format will not search for the
75 // best prefix but leave it as initially provided.
76 // fixPrefix is set true by the method Unit.to
77
78 // The justification behind this is that if the constructor is explicitly called,
79 // the caller wishes the units to be returned exactly as he supplied.
80 this.isUnitListSimplified = true;
81 }
82
83 /**
84 * Attach type information
85 */
86 Unit.prototype.type = 'Unit';
87 Unit.prototype.isUnit = true;
88
89 // private variables and functions for the Unit parser
90 var text = void 0,
91 index = void 0,
92 c = void 0;
93
94 function skipWhitespace() {
95 while (c === ' ' || c === '\t') {
96 next();
97 }
98 }
99
100 function isDigitDot(c) {
101 return c >= '0' && c <= '9' || c === '.';
102 }
103
104 function isDigit(c) {
105 return c >= '0' && c <= '9';
106 }
107
108 function next() {
109 index++;
110 c = text.charAt(index);
111 }
112
113 function revert(oldIndex) {
114 index = oldIndex;
115 c = text.charAt(index);
116 }
117
118 function parseNumber() {
119 var number = '';
120 var oldIndex = void 0;
121 oldIndex = index;
122
123 if (c === '+') {
124 next();
125 } else if (c === '-') {
126 number += c;
127 next();
128 }
129
130 if (!isDigitDot(c)) {
131 // a + or - must be followed by a digit
132 revert(oldIndex);
133 return null;
134 }
135
136 // get number, can have a single dot
137 if (c === '.') {
138 number += c;
139 next();
140 if (!isDigit(c)) {
141 // this is no legal number, it is just a dot
142 revert(oldIndex);
143 return null;
144 }
145 } else {
146 while (isDigit(c)) {
147 number += c;
148 next();
149 }
150 if (c === '.') {
151 number += c;
152 next();
153 }
154 }
155 while (isDigit(c)) {
156 number += c;
157 next();
158 }
159
160 // check for exponential notation like "2.3e-4" or "1.23e50"
161 if (c === 'E' || c === 'e') {
162 // The grammar branches here. This could either be part of an exponent or the start of a unit that begins with the letter e, such as "4exabytes"
163
164 var tentativeNumber = '';
165 var tentativeIndex = index;
166
167 tentativeNumber += c;
168 next();
169
170 if (c === '+' || c === '-') {
171 tentativeNumber += c;
172 next();
173 }
174
175 // Scientific notation MUST be followed by an exponent (otherwise we assume it is not scientific notation)
176 if (!isDigit(c)) {
177 // The e or E must belong to something else, so return the number without the e or E.
178 revert(tentativeIndex);
179 return number;
180 }
181
182 // We can now safely say that this is scientific notation.
183 number = number + tentativeNumber;
184 while (isDigit(c)) {
185 number += c;
186 next();
187 }
188 }
189
190 return number;
191 }
192
193 function parseUnit() {
194 var unitName = '';
195
196 // Alphanumeric characters only; matches [a-zA-Z0-9]
197 var code = text.charCodeAt(index);
198 while (code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122) {
199 unitName += c;
200 next();
201 code = text.charCodeAt(index);
202 }
203
204 // Must begin with [a-zA-Z]
205 code = unitName.charCodeAt(0);
206 if (code >= 65 && code <= 90 || code >= 97 && code <= 122) {
207 return unitName || null;
208 } else {
209 return null;
210 }
211 }
212
213 function parseCharacter(toFind) {
214 if (c === toFind) {
215 next();
216 return toFind;
217 } else {
218 return null;
219 }
220 }
221
222 /**
223 * Parse a string into a unit. The value of the unit is parsed as number,
224 * BigNumber, or Fraction depending on the math.js config setting `number`.
225 *
226 * Throws an exception if the provided string does not contain a valid unit or
227 * cannot be parsed.
228 * @memberof Unit
229 * @param {string} str A string like "5.2 inch", "4e2 cm/s^2"
230 * @return {Unit} unit
231 */
232 Unit.parse = function (str, options) {
233 options = options || {};
234 text = str;
235 index = -1;
236 c = '';
237
238 if (typeof text !== 'string') {
239 throw new TypeError('Invalid argument in Unit.parse, string expected');
240 }
241
242 var unit = new Unit();
243 unit.units = [];
244
245 var powerMultiplierCurrent = 1;
246 var expectingUnit = false;
247
248 // A unit should follow this pattern:
249 // [number] ...[ [*/] unit[^number] ]
250 // unit[^number] ... [ [*/] unit[^number] ]
251
252 // Rules:
253 // number is any floating point number.
254 // unit is any alphanumeric string beginning with an alpha. Units with names like e3 should be avoided because they look like the exponent of a floating point number!
255 // The string may optionally begin with a number.
256 // Each unit may optionally be followed by ^number.
257 // Whitespace or a forward slash is recommended between consecutive units, although the following technically is parseable:
258 // 2m^2kg/s^2
259 // it is not good form. If a unit starts with e, then it could be confused as a floating point number:
260 // 4erg
261
262 next();
263 skipWhitespace();
264
265 // Optional number at the start of the string
266 var valueStr = parseNumber();
267 var value = null;
268 if (valueStr) {
269 if (config.number === 'BigNumber') {
270 value = new type.BigNumber(valueStr);
271 } else if (config.number === 'Fraction') {
272 value = new type.Fraction(valueStr);
273 } else {
274 // number
275 value = parseFloat(valueStr);
276 }
277
278 skipWhitespace(); // Whitespace is not required here
279
280 // handle multiplication or division right after the value, like '1/s'
281 if (parseCharacter('*')) {
282 powerMultiplierCurrent = 1;
283 expectingUnit = true;
284 } else if (parseCharacter('/')) {
285 powerMultiplierCurrent = -1;
286 expectingUnit = true;
287 }
288 }
289
290 // Stack to keep track of powerMultipliers applied to each parentheses group
291 var powerMultiplierStack = [];
292
293 // Running product of all elements in powerMultiplierStack
294 var powerMultiplierStackProduct = 1;
295
296 while (true) {
297 skipWhitespace();
298
299 // Check for and consume opening parentheses, pushing powerMultiplierCurrent to the stack
300 // A '(' will always appear directly before a unit.
301 while (c === '(') {
302 powerMultiplierStack.push(powerMultiplierCurrent);
303 powerMultiplierStackProduct *= powerMultiplierCurrent;
304 powerMultiplierCurrent = 1;
305 next();
306 skipWhitespace();
307 }
308
309 // Is there something here?
310 var uStr = void 0;
311 if (c) {
312 var oldC = c;
313 uStr = parseUnit();
314 if (uStr === null) {
315 throw new SyntaxError('Unexpected "' + oldC + '" in "' + text + '" at index ' + index.toString());
316 }
317 } else {
318 // End of input.
319 break;
320 }
321
322 // Verify the unit exists and get the prefix (if any)
323 var res = _findUnit(uStr);
324 if (res === null) {
325 // Unit not found.
326 throw new SyntaxError('Unit "' + uStr + '" not found.');
327 }
328
329 var power = powerMultiplierCurrent * powerMultiplierStackProduct;
330 // Is there a "^ number"?
331 skipWhitespace();
332 if (parseCharacter('^')) {
333 skipWhitespace();
334 var p = parseNumber();
335 if (p === null) {
336 // No valid number found for the power!
337 throw new SyntaxError('In "' + str + '", "^" must be followed by a floating-point number');
338 }
339 power *= p;
340 }
341
342 // Add the unit to the list
343 unit.units.push({
344 unit: res.unit,
345 prefix: res.prefix,
346 power: power
347 });
348 for (var i = 0; i < BASE_DIMENSIONS.length; i++) {
349 unit.dimensions[i] += (res.unit.dimensions[i] || 0) * power;
350 }
351
352 // Check for and consume closing parentheses, popping from the stack.
353 // A ')' will always follow a unit.
354 skipWhitespace();
355 while (c === ')') {
356 if (powerMultiplierStack.length === 0) {
357 throw new SyntaxError('Unmatched ")" in "' + text + '" at index ' + index.toString());
358 }
359 powerMultiplierStackProduct /= powerMultiplierStack.pop();
360 next();
361 skipWhitespace();
362 }
363
364 // "*" and "/" should mean we are expecting something to come next.
365 // Is there a forward slash? If so, negate powerMultiplierCurrent. The next unit or paren group is in the denominator.
366 expectingUnit = false;
367
368 if (parseCharacter('*')) {
369 // explicit multiplication
370 powerMultiplierCurrent = 1;
371 expectingUnit = true;
372 } else if (parseCharacter('/')) {
373 // division
374 powerMultiplierCurrent = -1;
375 expectingUnit = true;
376 } else {
377 // implicit multiplication
378 powerMultiplierCurrent = 1;
379 }
380
381 // Replace the unit into the auto unit system
382 if (res.unit.base) {
383 var baseDim = res.unit.base.key;
384 UNIT_SYSTEMS.auto[baseDim] = {
385 unit: res.unit,
386 prefix: res.prefix
387 };
388 }
389 }
390
391 // Has the string been entirely consumed?
392 skipWhitespace();
393 if (c) {
394 throw new SyntaxError('Could not parse: "' + str + '"');
395 }
396
397 // Is there a trailing slash?
398 if (expectingUnit) {
399 throw new SyntaxError('Trailing characters: "' + str + '"');
400 }
401
402 // Is the parentheses stack empty?
403 if (powerMultiplierStack.length !== 0) {
404 throw new SyntaxError('Unmatched "(" in "' + text + '"');
405 }
406
407 // Are there any units at all?
408 if (unit.units.length === 0 && !options.allowNoUnits) {
409 throw new SyntaxError('"' + str + '" contains no units');
410 }
411
412 unit.value = value !== undefined ? unit._normalize(value) : null;
413 return unit;
414 };
415
416 /**
417 * create a copy of this unit
418 * @memberof Unit
419 * @return {Unit} Returns a cloned version of the unit
420 */
421 Unit.prototype.clone = function () {
422 var unit = new Unit();
423
424 unit.fixPrefix = this.fixPrefix;
425 unit.isUnitListSimplified = this.isUnitListSimplified;
426
427 unit.value = clone(this.value);
428 unit.dimensions = this.dimensions.slice(0);
429 unit.units = [];
430 for (var i = 0; i < this.units.length; i++) {
431 unit.units[i] = {};
432 for (var p in this.units[i]) {
433 if (this.units[i].hasOwnProperty(p)) {
434 unit.units[i][p] = this.units[i][p];
435 }
436 }
437 }
438
439 return unit;
440 };
441
442 /**
443 * Return whether the unit is derived (such as m/s, or cm^2, but not N)
444 * @memberof Unit
445 * @return {boolean} True if the unit is derived
446 */
447 Unit.prototype._isDerived = function () {
448 if (this.units.length === 0) {
449 return false;
450 }
451 return this.units.length > 1 || Math.abs(this.units[0].power - 1.0) > 1e-15;
452 };
453
454 /**
455 * Normalize a value, based on its currently set unit(s)
456 * @memberof Unit
457 * @param {number | BigNumber | Fraction | boolean} value
458 * @return {number | BigNumber | Fraction | boolean} normalized value
459 * @private
460 */
461 Unit.prototype._normalize = function (value) {
462 var unitValue = void 0,
463 unitOffset = void 0,
464 unitPower = void 0,
465 unitPrefixValue = void 0;
466 var convert = void 0;
467
468 if (value === null || value === undefined || this.units.length === 0) {
469 return value;
470 } else if (this._isDerived()) {
471 // This is a derived unit, so do not apply offsets.
472 // For example, with J kg^-1 degC^-1 you would NOT want to apply the offset.
473 var res = value;
474 convert = Unit._getNumberConverter(getTypeOf(value)); // convert to Fraction or BigNumber if needed
475
476 for (var i = 0; i < this.units.length; i++) {
477 unitValue = convert(this.units[i].unit.value);
478 unitPrefixValue = convert(this.units[i].prefix.value);
479 unitPower = convert(this.units[i].power);
480 res = multiply(res, pow(multiply(unitValue, unitPrefixValue), unitPower));
481 }
482
483 return res;
484 } else {
485 // This is a single unit of power 1, like kg or degC
486 convert = Unit._getNumberConverter(getTypeOf(value)); // convert to Fraction or BigNumber if needed
487
488 unitValue = convert(this.units[0].unit.value);
489 unitOffset = convert(this.units[0].unit.offset);
490 unitPrefixValue = convert(this.units[0].prefix.value);
491
492 return multiply(add(value, unitOffset), multiply(unitValue, unitPrefixValue));
493 }
494 };
495
496 /**
497 * Denormalize a value, based on its currently set unit(s)
498 * @memberof Unit
499 * @param {number} value
500 * @param {number} [prefixValue] Optional prefix value to be used (ignored if this is a derived unit)
501 * @return {number} denormalized value
502 * @private
503 */
504 Unit.prototype._denormalize = function (value, prefixValue) {
505 var unitValue = void 0,
506 unitOffset = void 0,
507 unitPower = void 0,
508 unitPrefixValue = void 0;
509 var convert = void 0;
510
511 if (value === null || value === undefined || this.units.length === 0) {
512 return value;
513 } else if (this._isDerived()) {
514 // This is a derived unit, so do not apply offsets.
515 // For example, with J kg^-1 degC^-1 you would NOT want to apply the offset.
516 // Also, prefixValue is ignored--but we will still use the prefix value stored in each unit, since kg is usually preferable to g unless the user decides otherwise.
517 var res = value;
518 convert = Unit._getNumberConverter(getTypeOf(value)); // convert to Fraction or BigNumber if needed
519
520 for (var i = 0; i < this.units.length; i++) {
521 unitValue = convert(this.units[i].unit.value);
522 unitPrefixValue = convert(this.units[i].prefix.value);
523 unitPower = convert(this.units[i].power);
524 res = divide(res, pow(multiply(unitValue, unitPrefixValue), unitPower));
525 }
526
527 return res;
528 } else {
529 // This is a single unit of power 1, like kg or degC
530 convert = Unit._getNumberConverter(getTypeOf(value)); // convert to Fraction or BigNumber if needed
531
532 unitValue = convert(this.units[0].unit.value);
533 unitPrefixValue = convert(this.units[0].prefix.value);
534 unitOffset = convert(this.units[0].unit.offset);
535
536 if (prefixValue === undefined || prefixValue === null) {
537 return subtract(divide(divide(value, unitValue), unitPrefixValue), unitOffset);
538 } else {
539 return subtract(divide(divide(value, unitValue), prefixValue), unitOffset);
540 }
541 }
542 };
543
544 /**
545 * Find a unit from a string
546 * @memberof Unit
547 * @param {string} str A string like 'cm' or 'inch'
548 * @returns {Object | null} result When found, an object with fields unit and
549 * prefix is returned. Else, null is returned.
550 * @private
551 */
552 function _findUnit(str) {
553 // First, match units names exactly. For example, a user could define 'mm' as 10^-4 m, which is silly, but then we would want 'mm' to match the user-defined unit.
554 if (UNITS.hasOwnProperty(str)) {
555 var unit = UNITS[str];
556 var prefix = unit.prefixes[''];
557 return {
558 unit: unit,
559 prefix: prefix
560 };
561 }
562
563 for (var name in UNITS) {
564 if (UNITS.hasOwnProperty(name)) {
565 if (endsWith(str, name)) {
566 var _unit = UNITS[name];
567 var prefixLen = str.length - name.length;
568 var prefixName = str.substring(0, prefixLen);
569 var _prefix = _unit.prefixes.hasOwnProperty(prefixName) ? _unit.prefixes[prefixName] : undefined;
570 if (_prefix !== undefined) {
571 // store unit, prefix, and value
572 return {
573 unit: _unit,
574 prefix: _prefix
575 };
576 }
577 }
578 }
579 }
580
581 return null;
582 }
583
584 /**
585 * Test if the given expression is a unit.
586 * The unit can have a prefix but cannot have a value.
587 * @memberof Unit
588 * @param {string} name A string to be tested whether it is a value less unit.
589 * The unit can have prefix, like "cm"
590 * @return {boolean} true if the given string is a unit
591 */
592 Unit.isValuelessUnit = function (name) {
593 return _findUnit(name) !== null;
594 };
595
596 /**
597 * check if this unit has given base unit
598 * If this unit is a derived unit, this will ALWAYS return false, since by definition base units are not derived.
599 * @memberof Unit
600 * @param {BASE_UNITS | string | undefined} base
601 */
602 Unit.prototype.hasBase = function (base) {
603 if (typeof base === 'string') {
604 base = BASE_UNITS[base];
605 }
606
607 if (!base) {
608 return false;
609 }
610
611 // All dimensions must be the same
612 for (var i = 0; i < BASE_DIMENSIONS.length; i++) {
613 if (Math.abs((this.dimensions[i] || 0) - (base.dimensions[i] || 0)) > 1e-12) {
614 return false;
615 }
616 }
617 return true;
618 };
619
620 /**
621 * Check if this unit has a base or bases equal to another base or bases
622 * For derived units, the exponent on each base also must match
623 * @memberof Unit
624 * @param {Unit} other
625 * @return {boolean} true if equal base
626 */
627 Unit.prototype.equalBase = function (other) {
628 // All dimensions must be the same
629 for (var i = 0; i < BASE_DIMENSIONS.length; i++) {
630 if (Math.abs((this.dimensions[i] || 0) - (other.dimensions[i] || 0)) > 1e-12) {
631 return false;
632 }
633 }
634 return true;
635 };
636
637 /**
638 * Check if this unit equals another unit
639 * @memberof Unit
640 * @param {Unit} other
641 * @return {boolean} true if both units are equal
642 */
643 Unit.prototype.equals = function (other) {
644 return this.equalBase(other) && equal(this.value, other.value);
645 };
646
647 /**
648 * Multiply this unit with another one
649 * @memberof Unit
650 * @param {Unit} other
651 * @return {Unit} product of this unit and the other unit
652 */
653 Unit.prototype.multiply = function (other) {
654 var res = this.clone();
655
656 for (var i = 0; i < BASE_DIMENSIONS.length; i++) {
657 // Dimensions arrays may be of different lengths. Default to 0.
658 res.dimensions[i] = (this.dimensions[i] || 0) + (other.dimensions[i] || 0);
659 }
660
661 // Append other's units list onto res (simplify later in Unit.prototype.format)
662 for (var _i = 0; _i < other.units.length; _i++) {
663 // Make a deep copy
664 var inverted = {};
665 for (var key in other.units[_i]) {
666 inverted[key] = other.units[_i][key];
667 }
668 res.units.push(inverted);
669 }
670
671 // If at least one operand has a value, then the result should also have a value
672 if (this.value !== null || other.value !== null) {
673 var valThis = this.value === null ? this._normalize(1) : this.value;
674 var valOther = other.value === null ? other._normalize(1) : other.value;
675 res.value = multiply(valThis, valOther);
676 } else {
677 res.value = null;
678 }
679
680 // Trigger simplification of the unit list at some future time
681 res.isUnitListSimplified = false;
682
683 return getNumericIfUnitless(res);
684 };
685
686 /**
687 * Divide this unit by another one
688 * @memberof Unit
689 * @param {Unit} other
690 * @return {Unit} result of dividing this unit by the other unit
691 */
692 Unit.prototype.divide = function (other) {
693 var res = this.clone();
694
695 for (var i = 0; i < BASE_DIMENSIONS.length; i++) {
696 // Dimensions arrays may be of different lengths. Default to 0.
697 res.dimensions[i] = (this.dimensions[i] || 0) - (other.dimensions[i] || 0);
698 }
699
700 // Invert and append other's units list onto res (simplify later in Unit.prototype.format)
701 for (var _i2 = 0; _i2 < other.units.length; _i2++) {
702 // Make a deep copy
703 var inverted = {};
704 for (var key in other.units[_i2]) {
705 inverted[key] = other.units[_i2][key];
706 }
707 inverted.power = -inverted.power;
708 res.units.push(inverted);
709 }
710
711 // If at least one operand has a value, the result should have a value
712 if (this.value !== null || other.value !== null) {
713 var valThis = this.value === null ? this._normalize(1) : this.value;
714 var valOther = other.value === null ? other._normalize(1) : other.value;
715 res.value = divide(valThis, valOther);
716 } else {
717 res.value = null;
718 }
719
720 // Trigger simplification of the unit list at some future time
721 res.isUnitListSimplified = false;
722
723 return getNumericIfUnitless(res);
724 };
725
726 /**
727 * Calculate the power of a unit
728 * @memberof Unit
729 * @param {number | Fraction | BigNumber} p
730 * @returns {Unit} The result: this^p
731 */
732 Unit.prototype.pow = function (p) {
733 var res = this.clone();
734
735 for (var i = 0; i < BASE_DIMENSIONS.length; i++) {
736 // Dimensions arrays may be of different lengths. Default to 0.
737 res.dimensions[i] = (this.dimensions[i] || 0) * p;
738 }
739
740 // Adjust the power of each unit in the list
741 for (var _i3 = 0; _i3 < res.units.length; _i3++) {
742 res.units[_i3].power *= p;
743 }
744
745 if (res.value !== null) {
746 res.value = pow(res.value, p);
747
748 // only allow numeric output, we don't want to return a Complex number
749 // if (!isNumeric(res.value)) {
750 // res.value = NaN
751 // }
752 // Update: Complex supported now
753 } else {
754 res.value = null;
755 }
756
757 // Trigger lazy evaluation of the unit list
758 res.isUnitListSimplified = false;
759
760 return getNumericIfUnitless(res);
761 };
762
763 /**
764 * Return the numeric value of this unit if it is dimensionless, has a value, and config.predictable == false; or the original unit otherwise
765 * @param {Unit} unit
766 * @returns {number | Fraction | BigNumber | Unit} The numeric value of the unit if conditions are met, or the original unit otherwise
767 */
768 function getNumericIfUnitless(unit) {
769 if (unit.equalBase(BASE_UNITS.NONE) && unit.value !== null && !config.predictable) {
770 return unit.value;
771 } else {
772 return unit;
773 }
774 }
775
776 /**
777 * Calculate the absolute value of a unit
778 * @memberof Unit
779 * @param {number | Fraction | BigNumber} x
780 * @returns {Unit} The result: |x|, absolute value of x
781 */
782 Unit.prototype.abs = function () {
783 // This gives correct, but unexpected, results for units with an offset.
784 // For example, abs(-283.15 degC) = -263.15 degC !!!
785 var ret = this.clone();
786 ret.value = ret.value !== null ? abs(ret.value) : null;
787
788 for (var i in ret.units) {
789 if (ret.units[i].unit.name === 'VA' || ret.units[i].unit.name === 'VAR') {
790 ret.units[i].unit = UNITS['W'];
791 }
792 }
793
794 return ret;
795 };
796
797 /**
798 * Convert the unit to a specific unit name.
799 * @memberof Unit
800 * @param {string | Unit} valuelessUnit A unit without value. Can have prefix, like "cm"
801 * @returns {Unit} Returns a clone of the unit with a fixed prefix and unit.
802 */
803 Unit.prototype.to = function (valuelessUnit) {
804 var other = void 0;
805 var value = this.value === null ? this._normalize(1) : this.value;
806 if (typeof valuelessUnit === 'string') {
807 // other = new Unit(null, valuelessUnit)
808 other = Unit.parse(valuelessUnit);
809 if (!this.equalBase(other)) {
810 throw new Error('Units do not match (\'' + other.toString() + '\' != \'' + this.toString() + '\')');
811 }
812 if (other.value !== null) {
813 throw new Error('Cannot convert to a unit with a value');
814 }
815
816 other.value = clone(value);
817 other.fixPrefix = true;
818 other.isUnitListSimplified = true;
819 return other;
820 } else if (type.isUnit(valuelessUnit)) {
821 if (!this.equalBase(valuelessUnit)) {
822 throw new Error('Units do not match (\'' + valuelessUnit.toString() + '\' != \'' + this.toString() + '\')');
823 }
824 if (valuelessUnit.value !== null) {
825 throw new Error('Cannot convert to a unit with a value');
826 }
827 other = valuelessUnit.clone();
828 other.value = clone(value);
829 other.fixPrefix = true;
830 other.isUnitListSimplified = true;
831 return other;
832 } else {
833 throw new Error('String or Unit expected as parameter');
834 }
835 };
836
837 /**
838 * Return the value of the unit when represented with given valueless unit
839 * @memberof Unit
840 * @param {string | Unit} valuelessUnit For example 'cm' or 'inch'
841 * @return {number} Returns the unit value as number.
842 */
843 // TODO: deprecate Unit.toNumber? It's always better to use toNumeric
844 Unit.prototype.toNumber = function (valuelessUnit) {
845 return toNumber(this.toNumeric(valuelessUnit));
846 };
847
848 /**
849 * Return the value of the unit in the original numeric type
850 * @memberof Unit
851 * @param {string | Unit} valuelessUnit For example 'cm' or 'inch'
852 * @return {number | BigNumber | Fraction} Returns the unit value
853 */
854 Unit.prototype.toNumeric = function (valuelessUnit) {
855 var other = this;
856 if (valuelessUnit) {
857 // Allow getting the numeric value without converting to a different unit
858 other = this.to(valuelessUnit);
859 }
860
861 other.simplifyUnitListLazy();
862
863 if (other._isDerived()) {
864 return other._denormalize(other.value);
865 } else {
866 return other._denormalize(other.value, other.units[0].prefix.value);
867 }
868 };
869
870 /**
871 * Get a string representation of the unit.
872 * @memberof Unit
873 * @return {string}
874 */
875 Unit.prototype.toString = function () {
876 return this.format();
877 };
878
879 /**
880 * Get a JSON representation of the unit
881 * @memberof Unit
882 * @returns {Object} Returns a JSON object structured as:
883 * `{"mathjs": "Unit", "value": 2, "unit": "cm", "fixPrefix": false}`
884 */
885 Unit.prototype.toJSON = function () {
886 return {
887 mathjs: 'Unit',
888 value: this._denormalize(this.value),
889 unit: this.formatUnits(),
890 fixPrefix: this.fixPrefix
891 };
892 };
893
894 /**
895 * Instantiate a Unit from a JSON object
896 * @memberof Unit
897 * @param {Object} json A JSON object structured as:
898 * `{"mathjs": "Unit", "value": 2, "unit": "cm", "fixPrefix": false}`
899 * @return {Unit}
900 */
901 Unit.fromJSON = function (json) {
902 var unit = new Unit(json.value, json.unit);
903 unit.fixPrefix = json.fixPrefix || false;
904 return unit;
905 };
906
907 /**
908 * Returns the string representation of the unit.
909 * @memberof Unit
910 * @return {string}
911 */
912 Unit.prototype.valueOf = Unit.prototype.toString;
913
914 /**
915 * Attempt to simplify the list of units for this unit according to the dimensions array and the current unit system. After the call, this Unit will contain a list of the "best" units for formatting.
916 * Intended to be evaluated lazily. You must set isUnitListSimplified = false before the call! After the call, isUnitListSimplified will be set to true.
917 */
918 Unit.prototype.simplifyUnitListLazy = function () {
919 if (this.isUnitListSimplified || this.value === null) {
920 return;
921 }
922
923 var proposedUnitList = [];
924
925 // Search for a matching base
926 var matchingBase = void 0;
927 for (var key in currentUnitSystem) {
928 if (this.hasBase(BASE_UNITS[key])) {
929 matchingBase = key;
930 break;
931 }
932 }
933
934 if (matchingBase === 'NONE') {
935 this.units = [];
936 } else {
937 var matchingUnit = void 0;
938 if (matchingBase) {
939 // Does the unit system have a matching unit?
940 if (currentUnitSystem.hasOwnProperty(matchingBase)) {
941 matchingUnit = currentUnitSystem[matchingBase];
942 }
943 }
944 if (matchingUnit) {
945 this.units = [{
946 unit: matchingUnit.unit,
947 prefix: matchingUnit.prefix,
948 power: 1.0
949 }];
950 } else {
951 // Multiple units or units with powers are formatted like this:
952 // 5 (kg m^2) / (s^3 mol)
953 // Build an representation from the base units of the current unit system
954 var missingBaseDim = false;
955 for (var i = 0; i < BASE_DIMENSIONS.length; i++) {
956 var baseDim = BASE_DIMENSIONS[i];
957 if (Math.abs(this.dimensions[i] || 0) > 1e-12) {
958 if (currentUnitSystem.hasOwnProperty(baseDim)) {
959 proposedUnitList.push({
960 unit: currentUnitSystem[baseDim].unit,
961 prefix: currentUnitSystem[baseDim].prefix,
962 power: this.dimensions[i] || 0
963 });
964 } else {
965 missingBaseDim = true;
966 }
967 }
968 }
969
970 // Is the proposed unit list "simpler" than the existing one?
971 if (proposedUnitList.length < this.units.length && !missingBaseDim) {
972 // Replace this unit list with the proposed list
973 this.units = proposedUnitList;
974 }
975 }
976 }
977
978 this.isUnitListSimplified = true;
979 };
980
981 Unit.prototype.toSI = function () {
982 var ret = this.clone();
983
984 var proposedUnitList = [];
985
986 // Multiple units or units with powers are formatted like this:
987 // 5 (kg m^2) / (s^3 mol)
988 // Build an representation from the base units of the SI unit system
989 for (var i = 0; i < BASE_DIMENSIONS.length; i++) {
990 var baseDim = BASE_DIMENSIONS[i];
991 if (Math.abs(ret.dimensions[i] || 0) > 1e-12) {
992 if (UNIT_SYSTEMS['si'].hasOwnProperty(baseDim)) {
993 proposedUnitList.push({
994 unit: UNIT_SYSTEMS['si'][baseDim].unit,
995 prefix: UNIT_SYSTEMS['si'][baseDim].prefix,
996 power: ret.dimensions[i] || 0
997 });
998 } else {
999 throw new Error('Cannot express custom unit ' + baseDim + ' in SI units');
1000 }
1001 }
1002 }
1003
1004 // Replace this unit list with the proposed list
1005 ret.units = proposedUnitList;
1006
1007 ret.isUnitListSimplified = true;
1008
1009 return ret;
1010 };
1011
1012 /**
1013 * Get a string representation of the units of this Unit, without the value.
1014 * @memberof Unit
1015 * @return {string}
1016 */
1017 Unit.prototype.formatUnits = function () {
1018 // Lazy evaluation of the unit list
1019 this.simplifyUnitListLazy();
1020
1021 var strNum = '';
1022 var strDen = '';
1023 var nNum = 0;
1024 var nDen = 0;
1025
1026 for (var i = 0; i < this.units.length; i++) {
1027 if (this.units[i].power > 0) {
1028 nNum++;
1029 strNum += ' ' + this.units[i].prefix.name + this.units[i].unit.name;
1030 if (Math.abs(this.units[i].power - 1.0) > 1e-15) {
1031 strNum += '^' + this.units[i].power;
1032 }
1033 } else if (this.units[i].power < 0) {
1034 nDen++;
1035 }
1036 }
1037
1038 if (nDen > 0) {
1039 for (var _i4 = 0; _i4 < this.units.length; _i4++) {
1040 if (this.units[_i4].power < 0) {
1041 if (nNum > 0) {
1042 strDen += ' ' + this.units[_i4].prefix.name + this.units[_i4].unit.name;
1043 if (Math.abs(this.units[_i4].power + 1.0) > 1e-15) {
1044 strDen += '^' + -this.units[_i4].power;
1045 }
1046 } else {
1047 strDen += ' ' + this.units[_i4].prefix.name + this.units[_i4].unit.name;
1048 strDen += '^' + this.units[_i4].power;
1049 }
1050 }
1051 }
1052 }
1053 // Remove leading " "
1054 strNum = strNum.substr(1);
1055 strDen = strDen.substr(1);
1056
1057 // Add parans for better copy/paste back into the eval, for example, or for better pretty print formatting
1058 if (nNum > 1 && nDen > 0) {
1059 strNum = '(' + strNum + ')';
1060 }
1061 if (nDen > 1 && nNum > 0) {
1062 strDen = '(' + strDen + ')';
1063 }
1064
1065 var str = strNum;
1066 if (nNum > 0 && nDen > 0) {
1067 str += ' / ';
1068 }
1069 str += strDen;
1070
1071 return str;
1072 };
1073
1074 /**
1075 * Get a string representation of the Unit, with optional formatting options.
1076 * @memberof Unit
1077 * @param {Object | number | Function} [options] Formatting options. See
1078 * lib/utils/number:format for a
1079 * description of the available
1080 * options.
1081 * @return {string}
1082 */
1083 Unit.prototype.format = function (options) {
1084 // Simplfy the unit list, if necessary
1085 this.simplifyUnitListLazy();
1086
1087 // Apply some custom logic for handling VA and VAR. The goal is to express the value of the unit as a real value, if possible. Otherwise, use a real-valued unit instead of a complex-valued one.
1088 var isImaginary = false;
1089 if (typeof this.value !== 'undefined' && this.value !== null && type.isComplex(this.value)) {
1090 // TODO: Make this better, for example, use relative magnitude of re and im rather than absolute
1091 isImaginary = Math.abs(this.value.re) < 1e-14;
1092 }
1093
1094 for (var i in this.units) {
1095 if (this.units[i].unit) {
1096 if (this.units[i].unit.name === 'VA' && isImaginary) {
1097 this.units[i].unit = UNITS['VAR'];
1098 } else if (this.units[i].unit.name === 'VAR' && !isImaginary) {
1099 this.units[i].unit = UNITS['VA'];
1100 }
1101 }
1102 }
1103
1104 // Now apply the best prefix
1105 // Units must have only one unit and not have the fixPrefix flag set
1106 if (this.units.length === 1 && !this.fixPrefix) {
1107 // Units must have integer powers, otherwise the prefix will change the
1108 // outputted value by not-an-integer-power-of-ten
1109 if (Math.abs(this.units[0].power - Math.round(this.units[0].power)) < 1e-14) {
1110 // Apply the best prefix
1111 this.units[0].prefix = this._bestPrefix();
1112 }
1113 }
1114
1115 var value = this._denormalize(this.value);
1116 var str = this.value !== null ? format(value, options || {}) : '';
1117 var unitStr = this.formatUnits();
1118 if (this.value && type.isComplex(this.value)) {
1119 str = '(' + str + ')'; // Surround complex values with ( ) to enable better parsing
1120 }
1121 if (unitStr.length > 0 && str.length > 0) {
1122 str += ' ';
1123 }
1124 str += unitStr;
1125
1126 return str;
1127 };
1128
1129 /**
1130 * Calculate the best prefix using current value.
1131 * @memberof Unit
1132 * @returns {Object} prefix
1133 * @private
1134 */
1135 Unit.prototype._bestPrefix = function () {
1136 if (this.units.length !== 1) {
1137 throw new Error('Can only compute the best prefix for single units with integer powers, like kg, s^2, N^-1, and so forth!');
1138 }
1139 if (Math.abs(this.units[0].power - Math.round(this.units[0].power)) >= 1e-14) {
1140 throw new Error('Can only compute the best prefix for single units with integer powers, like kg, s^2, N^-1, and so forth!');
1141 }
1142
1143 // find the best prefix value (resulting in the value of which
1144 // the absolute value of the log10 is closest to zero,
1145 // though with a little offset of 1.2 for nicer values: you get a
1146 // sequence 1mm 100mm 500mm 0.6m 1m 10m 100m 500m 0.6km 1km ...
1147
1148 // Note: the units value can be any numeric type, but to find the best
1149 // prefix it's enough to work with limited precision of a regular number
1150 // Update: using mathjs abs since we also allow complex numbers
1151 var absValue = this.value !== null ? abs(this.value) : 0;
1152 var absUnitValue = abs(this.units[0].unit.value);
1153 var bestPrefix = this.units[0].prefix;
1154 if (absValue === 0) {
1155 return bestPrefix;
1156 }
1157 var power = this.units[0].power;
1158 var bestDiff = Math.log(absValue / Math.pow(bestPrefix.value * absUnitValue, power)) / Math.LN10 - 1.2;
1159 if (bestDiff > -2.200001 && bestDiff < 1.800001) return bestPrefix; // Allow the original prefix
1160 bestDiff = Math.abs(bestDiff);
1161 var prefixes = this.units[0].unit.prefixes;
1162 for (var p in prefixes) {
1163 if (prefixes.hasOwnProperty(p)) {
1164 var prefix = prefixes[p];
1165 if (prefix.scientific) {
1166 var diff = Math.abs(Math.log(absValue / Math.pow(prefix.value * absUnitValue, power)) / Math.LN10 - 1.2);
1167
1168 if (diff < bestDiff || diff === bestDiff && prefix.name.length < bestPrefix.name.length) {
1169 // choose the prefix with the smallest diff, or if equal, choose the one
1170 // with the shortest name (can happen with SHORTLONG for example)
1171 bestPrefix = prefix;
1172 bestDiff = diff;
1173 }
1174 }
1175 }
1176 }
1177
1178 return bestPrefix;
1179 };
1180
1181 /**
1182 * Returns an array of units whose sum is equal to this unit
1183 * @memberof Unit
1184 * @param {Array} [parts] An array of strings or valueless units.
1185 *
1186 * Example:
1187 *
1188 * const u = new Unit(1, 'm')
1189 * u.splitUnit(['feet', 'inch'])
1190 * [ 3 feet, 3.3700787401575 inch ]
1191 *
1192 * @return {Array} An array of units.
1193 */
1194 Unit.prototype.splitUnit = function (parts) {
1195 var x = this.clone();
1196 var ret = [];
1197 for (var i = 0; i < parts.length; i++) {
1198 // Convert x to the requested unit
1199 x = x.to(parts[i]);
1200 if (i === parts.length - 1) break;
1201
1202 // Get the numeric value of this unit
1203 var xNumeric = x.toNumeric();
1204
1205 // Check to see if xNumeric is nearly equal to an integer,
1206 // since fix can incorrectly round down if there is round-off error
1207 var xRounded = round(xNumeric);
1208 var xFixed = void 0;
1209 var isNearlyEqual = equal(xRounded, xNumeric);
1210 if (isNearlyEqual) {
1211 xFixed = xRounded;
1212 } else {
1213 xFixed = fix(x.toNumeric());
1214 }
1215
1216 var y = new Unit(xFixed, parts[i].toString());
1217 ret.push(y);
1218 x = subtract(x, y);
1219 }
1220
1221 // This little bit fixes a bug where the remainder should be 0 but is a little bit off.
1222 // But instead of comparing x, the remainder, with zero--we will compare the sum of
1223 // all the parts so far with the original value. If they are nearly equal,
1224 // we set the remainder to 0.
1225 var testSum = 0;
1226 for (var _i5 = 0; _i5 < ret.length; _i5++) {
1227 testSum = add(testSum, ret[_i5].value);
1228 }
1229 if (equal(testSum, this.value)) {
1230 x.value = 0;
1231 }
1232
1233 ret.push(x);
1234
1235 return ret;
1236 };
1237
1238 var PREFIXES = {
1239 NONE: {
1240 '': { name: '', value: 1, scientific: true }
1241 },
1242 SHORT: {
1243 '': { name: '', value: 1, scientific: true },
1244
1245 'da': { name: 'da', value: 1e1, scientific: false },
1246 'h': { name: 'h', value: 1e2, scientific: false },
1247 'k': { name: 'k', value: 1e3, scientific: true },
1248 'M': { name: 'M', value: 1e6, scientific: true },
1249 'G': { name: 'G', value: 1e9, scientific: true },
1250 'T': { name: 'T', value: 1e12, scientific: true },
1251 'P': { name: 'P', value: 1e15, scientific: true },
1252 'E': { name: 'E', value: 1e18, scientific: true },
1253 'Z': { name: 'Z', value: 1e21, scientific: true },
1254 'Y': { name: 'Y', value: 1e24, scientific: true },
1255
1256 'd': { name: 'd', value: 1e-1, scientific: false },
1257 'c': { name: 'c', value: 1e-2, scientific: false },
1258 'm': { name: 'm', value: 1e-3, scientific: true },
1259 'u': { name: 'u', value: 1e-6, scientific: true },
1260 'n': { name: 'n', value: 1e-9, scientific: true },
1261 'p': { name: 'p', value: 1e-12, scientific: true },
1262 'f': { name: 'f', value: 1e-15, scientific: true },
1263 'a': { name: 'a', value: 1e-18, scientific: true },
1264 'z': { name: 'z', value: 1e-21, scientific: true },
1265 'y': { name: 'y', value: 1e-24, scientific: true }
1266 },
1267 LONG: {
1268 '': { name: '', value: 1, scientific: true },
1269
1270 'deca': { name: 'deca', value: 1e1, scientific: false },
1271 'hecto': { name: 'hecto', value: 1e2, scientific: false },
1272 'kilo': { name: 'kilo', value: 1e3, scientific: true },
1273 'mega': { name: 'mega', value: 1e6, scientific: true },
1274 'giga': { name: 'giga', value: 1e9, scientific: true },
1275 'tera': { name: 'tera', value: 1e12, scientific: true },
1276 'peta': { name: 'peta', value: 1e15, scientific: true },
1277 'exa': { name: 'exa', value: 1e18, scientific: true },
1278 'zetta': { name: 'zetta', value: 1e21, scientific: true },
1279 'yotta': { name: 'yotta', value: 1e24, scientific: true },
1280
1281 'deci': { name: 'deci', value: 1e-1, scientific: false },
1282 'centi': { name: 'centi', value: 1e-2, scientific: false },
1283 'milli': { name: 'milli', value: 1e-3, scientific: true },
1284 'micro': { name: 'micro', value: 1e-6, scientific: true },
1285 'nano': { name: 'nano', value: 1e-9, scientific: true },
1286 'pico': { name: 'pico', value: 1e-12, scientific: true },
1287 'femto': { name: 'femto', value: 1e-15, scientific: true },
1288 'atto': { name: 'atto', value: 1e-18, scientific: true },
1289 'zepto': { name: 'zepto', value: 1e-21, scientific: true },
1290 'yocto': { name: 'yocto', value: 1e-24, scientific: true }
1291 },
1292 SQUARED: {
1293 '': { name: '', value: 1, scientific: true },
1294
1295 'da': { name: 'da', value: 1e2, scientific: false },
1296 'h': { name: 'h', value: 1e4, scientific: false },
1297 'k': { name: 'k', value: 1e6, scientific: true },
1298 'M': { name: 'M', value: 1e12, scientific: true },
1299 'G': { name: 'G', value: 1e18, scientific: true },
1300 'T': { name: 'T', value: 1e24, scientific: true },
1301 'P': { name: 'P', value: 1e30, scientific: true },
1302 'E': { name: 'E', value: 1e36, scientific: true },
1303 'Z': { name: 'Z', value: 1e42, scientific: true },
1304 'Y': { name: 'Y', value: 1e48, scientific: true },
1305
1306 'd': { name: 'd', value: 1e-2, scientific: false },
1307 'c': { name: 'c', value: 1e-4, scientific: false },
1308 'm': { name: 'm', value: 1e-6, scientific: true },
1309 'u': { name: 'u', value: 1e-12, scientific: true },
1310 'n': { name: 'n', value: 1e-18, scientific: true },
1311 'p': { name: 'p', value: 1e-24, scientific: true },
1312 'f': { name: 'f', value: 1e-30, scientific: true },
1313 'a': { name: 'a', value: 1e-36, scientific: true },
1314 'z': { name: 'z', value: 1e-42, scientific: true },
1315 'y': { name: 'y', value: 1e-48, scientific: true }
1316 },
1317 CUBIC: {
1318 '': { name: '', value: 1, scientific: true },
1319
1320 'da': { name: 'da', value: 1e3, scientific: false },
1321 'h': { name: 'h', value: 1e6, scientific: false },
1322 'k': { name: 'k', value: 1e9, scientific: true },
1323 'M': { name: 'M', value: 1e18, scientific: true },
1324 'G': { name: 'G', value: 1e27, scientific: true },
1325 'T': { name: 'T', value: 1e36, scientific: true },
1326 'P': { name: 'P', value: 1e45, scientific: true },
1327 'E': { name: 'E', value: 1e54, scientific: true },
1328 'Z': { name: 'Z', value: 1e63, scientific: true },
1329 'Y': { name: 'Y', value: 1e72, scientific: true },
1330
1331 'd': { name: 'd', value: 1e-3, scientific: false },
1332 'c': { name: 'c', value: 1e-6, scientific: false },
1333 'm': { name: 'm', value: 1e-9, scientific: true },
1334 'u': { name: 'u', value: 1e-18, scientific: true },
1335 'n': { name: 'n', value: 1e-27, scientific: true },
1336 'p': { name: 'p', value: 1e-36, scientific: true },
1337 'f': { name: 'f', value: 1e-45, scientific: true },
1338 'a': { name: 'a', value: 1e-54, scientific: true },
1339 'z': { name: 'z', value: 1e-63, scientific: true },
1340 'y': { name: 'y', value: 1e-72, scientific: true }
1341 },
1342 BINARY_SHORT: {
1343 '': { name: '', value: 1, scientific: true },
1344 'k': { name: 'k', value: 1e3, scientific: true },
1345 'M': { name: 'M', value: 1e6, scientific: true },
1346 'G': { name: 'G', value: 1e9, scientific: true },
1347 'T': { name: 'T', value: 1e12, scientific: true },
1348 'P': { name: 'P', value: 1e15, scientific: true },
1349 'E': { name: 'E', value: 1e18, scientific: true },
1350 'Z': { name: 'Z', value: 1e21, scientific: true },
1351 'Y': { name: 'Y', value: 1e24, scientific: true },
1352
1353 'Ki': { name: 'Ki', value: 1024, scientific: true },
1354 'Mi': { name: 'Mi', value: Math.pow(1024, 2), scientific: true },
1355 'Gi': { name: 'Gi', value: Math.pow(1024, 3), scientific: true },
1356 'Ti': { name: 'Ti', value: Math.pow(1024, 4), scientific: true },
1357 'Pi': { name: 'Pi', value: Math.pow(1024, 5), scientific: true },
1358 'Ei': { name: 'Ei', value: Math.pow(1024, 6), scientific: true },
1359 'Zi': { name: 'Zi', value: Math.pow(1024, 7), scientific: true },
1360 'Yi': { name: 'Yi', value: Math.pow(1024, 8), scientific: true }
1361 },
1362 BINARY_LONG: {
1363 '': { name: '', value: 1, scientific: true },
1364 'kilo': { name: 'kilo', value: 1e3, scientific: true },
1365 'mega': { name: 'mega', value: 1e6, scientific: true },
1366 'giga': { name: 'giga', value: 1e9, scientific: true },
1367 'tera': { name: 'tera', value: 1e12, scientific: true },
1368 'peta': { name: 'peta', value: 1e15, scientific: true },
1369 'exa': { name: 'exa', value: 1e18, scientific: true },
1370 'zetta': { name: 'zetta', value: 1e21, scientific: true },
1371 'yotta': { name: 'yotta', value: 1e24, scientific: true },
1372
1373 'kibi': { name: 'kibi', value: 1024, scientific: true },
1374 'mebi': { name: 'mebi', value: Math.pow(1024, 2), scientific: true },
1375 'gibi': { name: 'gibi', value: Math.pow(1024, 3), scientific: true },
1376 'tebi': { name: 'tebi', value: Math.pow(1024, 4), scientific: true },
1377 'pebi': { name: 'pebi', value: Math.pow(1024, 5), scientific: true },
1378 'exi': { name: 'exi', value: Math.pow(1024, 6), scientific: true },
1379 'zebi': { name: 'zebi', value: Math.pow(1024, 7), scientific: true },
1380 'yobi': { name: 'yobi', value: Math.pow(1024, 8), scientific: true }
1381 },
1382 BTU: {
1383 '': { name: '', value: 1, scientific: true },
1384 'MM': { name: 'MM', value: 1e6, scientific: true }
1385 }
1386
1387 // Add a prefix list for both short and long prefixes (for example for ohm and bar which support both Mohm and megaohm, mbar and millibar):
1388 };PREFIXES.SHORTLONG = {};
1389 for (var key in PREFIXES.SHORT) {
1390 if (PREFIXES.SHORT.hasOwnProperty(key)) {
1391 PREFIXES.SHORTLONG[key] = PREFIXES.SHORT[key];
1392 }
1393 }
1394 for (var _key in PREFIXES.LONG) {
1395 if (PREFIXES.LONG.hasOwnProperty(_key)) {
1396 PREFIXES.SHORTLONG[_key] = PREFIXES.LONG[_key];
1397 }
1398 }
1399
1400 /* Internally, each unit is represented by a value and a dimension array. The elements of the dimensions array have the following meaning:
1401 * Index Dimension
1402 * ----- ---------
1403 * 0 Length
1404 * 1 Mass
1405 * 2 Time
1406 * 3 Current
1407 * 4 Temperature
1408 * 5 Luminous intensity
1409 * 6 Amount of substance
1410 * 7 Angle
1411 * 8 Bit (digital)
1412 * For example, the unit "298.15 K" is a pure temperature and would have a value of 298.15 and a dimension array of [0, 0, 0, 0, 1, 0, 0, 0, 0]. The unit "1 cal / (gm °C)" can be written in terms of the 9 fundamental dimensions as [length^2] / ([time^2] * [temperature]), and would a value of (after conversion to SI) 4184.0 and a dimensions array of [2, 0, -2, 0, -1, 0, 0, 0, 0].
1413 *
1414 */
1415
1416 var BASE_DIMENSIONS = ['MASS', 'LENGTH', 'TIME', 'CURRENT', 'TEMPERATURE', 'LUMINOUS_INTENSITY', 'AMOUNT_OF_SUBSTANCE', 'ANGLE', 'BIT'];
1417
1418 var BASE_UNITS = {
1419 NONE: {
1420 dimensions: [0, 0, 0, 0, 0, 0, 0, 0, 0]
1421 },
1422 MASS: {
1423 dimensions: [1, 0, 0, 0, 0, 0, 0, 0, 0]
1424 },
1425 LENGTH: {
1426 dimensions: [0, 1, 0, 0, 0, 0, 0, 0, 0]
1427 },
1428 TIME: {
1429 dimensions: [0, 0, 1, 0, 0, 0, 0, 0, 0]
1430 },
1431 CURRENT: {
1432 dimensions: [0, 0, 0, 1, 0, 0, 0, 0, 0]
1433 },
1434 TEMPERATURE: {
1435 dimensions: [0, 0, 0, 0, 1, 0, 0, 0, 0]
1436 },
1437 LUMINOUS_INTENSITY: {
1438 dimensions: [0, 0, 0, 0, 0, 1, 0, 0, 0]
1439 },
1440 AMOUNT_OF_SUBSTANCE: {
1441 dimensions: [0, 0, 0, 0, 0, 0, 1, 0, 0]
1442 },
1443
1444 FORCE: {
1445 dimensions: [1, 1, -2, 0, 0, 0, 0, 0, 0]
1446 },
1447 SURFACE: {
1448 dimensions: [0, 2, 0, 0, 0, 0, 0, 0, 0]
1449 },
1450 VOLUME: {
1451 dimensions: [0, 3, 0, 0, 0, 0, 0, 0, 0]
1452 },
1453 ENERGY: {
1454 dimensions: [1, 2, -2, 0, 0, 0, 0, 0, 0]
1455 },
1456 POWER: {
1457 dimensions: [1, 2, -3, 0, 0, 0, 0, 0, 0]
1458 },
1459 PRESSURE: {
1460 dimensions: [1, -1, -2, 0, 0, 0, 0, 0, 0]
1461 },
1462
1463 ELECTRIC_CHARGE: {
1464 dimensions: [0, 0, 1, 1, 0, 0, 0, 0, 0]
1465 },
1466 ELECTRIC_CAPACITANCE: {
1467 dimensions: [-1, -2, 4, 2, 0, 0, 0, 0, 0]
1468 },
1469 ELECTRIC_POTENTIAL: {
1470 dimensions: [1, 2, -3, -1, 0, 0, 0, 0, 0]
1471 },
1472 ELECTRIC_RESISTANCE: {
1473 dimensions: [1, 2, -3, -2, 0, 0, 0, 0, 0]
1474 },
1475 ELECTRIC_INDUCTANCE: {
1476 dimensions: [1, 2, -2, -2, 0, 0, 0, 0, 0]
1477 },
1478 ELECTRIC_CONDUCTANCE: {
1479 dimensions: [-1, -2, 3, 2, 0, 0, 0, 0, 0]
1480 },
1481 MAGNETIC_FLUX: {
1482 dimensions: [1, 2, -2, -1, 0, 0, 0, 0, 0]
1483 },
1484 MAGNETIC_FLUX_DENSITY: {
1485 dimensions: [1, 0, -2, -1, 0, 0, 0, 0, 0]
1486 },
1487
1488 FREQUENCY: {
1489 dimensions: [0, 0, -1, 0, 0, 0, 0, 0, 0]
1490 },
1491 ANGLE: {
1492 dimensions: [0, 0, 0, 0, 0, 0, 0, 1, 0]
1493 },
1494 BIT: {
1495 dimensions: [0, 0, 0, 0, 0, 0, 0, 0, 1]
1496 }
1497 };
1498
1499 for (var _key2 in BASE_UNITS) {
1500 BASE_UNITS[_key2].key = _key2;
1501 }
1502
1503 var BASE_UNIT_NONE = {};
1504
1505 var UNIT_NONE = { name: '', base: BASE_UNIT_NONE, value: 1, offset: 0, dimensions: [0, 0, 0, 0, 0, 0, 0, 0, 0] };
1506
1507 var UNITS = {
1508 // length
1509 meter: {
1510 name: 'meter',
1511 base: BASE_UNITS.LENGTH,
1512 prefixes: PREFIXES.LONG,
1513 value: 1,
1514 offset: 0
1515 },
1516 inch: {
1517 name: 'inch',
1518 base: BASE_UNITS.LENGTH,
1519 prefixes: PREFIXES.NONE,
1520 value: 0.0254,
1521 offset: 0
1522 },
1523 foot: {
1524 name: 'foot',
1525 base: BASE_UNITS.LENGTH,
1526 prefixes: PREFIXES.NONE,
1527 value: 0.3048,
1528 offset: 0
1529 },
1530 yard: {
1531 name: 'yard',
1532 base: BASE_UNITS.LENGTH,
1533 prefixes: PREFIXES.NONE,
1534 value: 0.9144,
1535 offset: 0
1536 },
1537 mile: {
1538 name: 'mile',
1539 base: BASE_UNITS.LENGTH,
1540 prefixes: PREFIXES.NONE,
1541 value: 1609.344,
1542 offset: 0
1543 },
1544 link: {
1545 name: 'link',
1546 base: BASE_UNITS.LENGTH,
1547 prefixes: PREFIXES.NONE,
1548 value: 0.201168,
1549 offset: 0
1550 },
1551 rod: {
1552 name: 'rod',
1553 base: BASE_UNITS.LENGTH,
1554 prefixes: PREFIXES.NONE,
1555 value: 5.029210,
1556 offset: 0
1557 },
1558 chain: {
1559 name: 'chain',
1560 base: BASE_UNITS.LENGTH,
1561 prefixes: PREFIXES.NONE,
1562 value: 20.1168,
1563 offset: 0
1564 },
1565 angstrom: {
1566 name: 'angstrom',
1567 base: BASE_UNITS.LENGTH,
1568 prefixes: PREFIXES.NONE,
1569 value: 1e-10,
1570 offset: 0
1571 },
1572
1573 m: {
1574 name: 'm',
1575 base: BASE_UNITS.LENGTH,
1576 prefixes: PREFIXES.SHORT,
1577 value: 1,
1578 offset: 0
1579 },
1580 'in': {
1581 name: 'in',
1582 base: BASE_UNITS.LENGTH,
1583 prefixes: PREFIXES.NONE,
1584 value: 0.0254,
1585 offset: 0
1586 },
1587 ft: {
1588 name: 'ft',
1589 base: BASE_UNITS.LENGTH,
1590 prefixes: PREFIXES.NONE,
1591 value: 0.3048,
1592 offset: 0
1593 },
1594 yd: {
1595 name: 'yd',
1596 base: BASE_UNITS.LENGTH,
1597 prefixes: PREFIXES.NONE,
1598 value: 0.9144,
1599 offset: 0
1600 },
1601 mi: {
1602 name: 'mi',
1603 base: BASE_UNITS.LENGTH,
1604 prefixes: PREFIXES.NONE,
1605 value: 1609.344,
1606 offset: 0
1607 },
1608 li: {
1609 name: 'li',
1610 base: BASE_UNITS.LENGTH,
1611 prefixes: PREFIXES.NONE,
1612 value: 0.201168,
1613 offset: 0
1614 },
1615 rd: {
1616 name: 'rd',
1617 base: BASE_UNITS.LENGTH,
1618 prefixes: PREFIXES.NONE,
1619 value: 5.029210,
1620 offset: 0
1621 },
1622 ch: {
1623 name: 'ch',
1624 base: BASE_UNITS.LENGTH,
1625 prefixes: PREFIXES.NONE,
1626 value: 20.1168,
1627 offset: 0
1628 },
1629 mil: {
1630 name: 'mil',
1631 base: BASE_UNITS.LENGTH,
1632 prefixes: PREFIXES.NONE,
1633 value: 0.0000254,
1634 offset: 0
1635 }, // 1/1000 inch
1636
1637 // Surface
1638 m2: {
1639 name: 'm2',
1640 base: BASE_UNITS.SURFACE,
1641 prefixes: PREFIXES.SQUARED,
1642 value: 1,
1643 offset: 0
1644 },
1645 sqin: {
1646 name: 'sqin',
1647 base: BASE_UNITS.SURFACE,
1648 prefixes: PREFIXES.NONE,
1649 value: 0.00064516,
1650 offset: 0
1651 }, // 645.16 mm2
1652 sqft: {
1653 name: 'sqft',
1654 base: BASE_UNITS.SURFACE,
1655 prefixes: PREFIXES.NONE,
1656 value: 0.09290304,
1657 offset: 0
1658 }, // 0.09290304 m2
1659 sqyd: {
1660 name: 'sqyd',
1661 base: BASE_UNITS.SURFACE,
1662 prefixes: PREFIXES.NONE,
1663 value: 0.83612736,
1664 offset: 0
1665 }, // 0.83612736 m2
1666 sqmi: {
1667 name: 'sqmi',
1668 base: BASE_UNITS.SURFACE,
1669 prefixes: PREFIXES.NONE,
1670 value: 2589988.110336,
1671 offset: 0
1672 }, // 2.589988110336 km2
1673 sqrd: {
1674 name: 'sqrd',
1675 base: BASE_UNITS.SURFACE,
1676 prefixes: PREFIXES.NONE,
1677 value: 25.29295,
1678 offset: 0
1679 }, // 25.29295 m2
1680 sqch: {
1681 name: 'sqch',
1682 base: BASE_UNITS.SURFACE,
1683 prefixes: PREFIXES.NONE,
1684 value: 404.6873,
1685 offset: 0
1686 }, // 404.6873 m2
1687 sqmil: {
1688 name: 'sqmil',
1689 base: BASE_UNITS.SURFACE,
1690 prefixes: PREFIXES.NONE,
1691 value: 6.4516e-10,
1692 offset: 0
1693 }, // 6.4516 * 10^-10 m2
1694 acre: {
1695 name: 'acre',
1696 base: BASE_UNITS.SURFACE,
1697 prefixes: PREFIXES.NONE,
1698 value: 4046.86,
1699 offset: 0
1700 }, // 4046.86 m2
1701 hectare: {
1702 name: 'hectare',
1703 base: BASE_UNITS.SURFACE,
1704 prefixes: PREFIXES.NONE,
1705 value: 10000,
1706 offset: 0
1707 }, // 10000 m2
1708
1709 // Volume
1710 m3: {
1711 name: 'm3',
1712 base: BASE_UNITS.VOLUME,
1713 prefixes: PREFIXES.CUBIC,
1714 value: 1,
1715 offset: 0
1716 },
1717 L: {
1718 name: 'L',
1719 base: BASE_UNITS.VOLUME,
1720 prefixes: PREFIXES.SHORT,
1721 value: 0.001,
1722 offset: 0
1723 }, // litre
1724 l: {
1725 name: 'l',
1726 base: BASE_UNITS.VOLUME,
1727 prefixes: PREFIXES.SHORT,
1728 value: 0.001,
1729 offset: 0
1730 }, // litre
1731 litre: {
1732 name: 'litre',
1733 base: BASE_UNITS.VOLUME,
1734 prefixes: PREFIXES.LONG,
1735 value: 0.001,
1736 offset: 0
1737 },
1738 cuin: {
1739 name: 'cuin',
1740 base: BASE_UNITS.VOLUME,
1741 prefixes: PREFIXES.NONE,
1742 value: 1.6387064e-5,
1743 offset: 0
1744 }, // 1.6387064e-5 m3
1745 cuft: {
1746 name: 'cuft',
1747 base: BASE_UNITS.VOLUME,
1748 prefixes: PREFIXES.NONE,
1749 value: 0.028316846592,
1750 offset: 0
1751 }, // 28.316 846 592 L
1752 cuyd: {
1753 name: 'cuyd',
1754 base: BASE_UNITS.VOLUME,
1755 prefixes: PREFIXES.NONE,
1756 value: 0.764554857984,
1757 offset: 0
1758 }, // 764.554 857 984 L
1759 teaspoon: {
1760 name: 'teaspoon',
1761 base: BASE_UNITS.VOLUME,
1762 prefixes: PREFIXES.NONE,
1763 value: 0.000005,
1764 offset: 0
1765 }, // 5 mL
1766 tablespoon: {
1767 name: 'tablespoon',
1768 base: BASE_UNITS.VOLUME,
1769 prefixes: PREFIXES.NONE,
1770 value: 0.000015,
1771 offset: 0
1772 }, // 15 mL
1773 // {name: 'cup', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.000240, offset: 0}, // 240 mL // not possible, we have already another cup
1774 drop: {
1775 name: 'drop',
1776 base: BASE_UNITS.VOLUME,
1777 prefixes: PREFIXES.NONE,
1778 value: 5e-8,
1779 offset: 0
1780 }, // 0.05 mL = 5e-8 m3
1781 gtt: {
1782 name: 'gtt',
1783 base: BASE_UNITS.VOLUME,
1784 prefixes: PREFIXES.NONE,
1785 value: 5e-8,
1786 offset: 0
1787 }, // 0.05 mL = 5e-8 m3
1788
1789 // Liquid volume
1790 minim: {
1791 name: 'minim',
1792 base: BASE_UNITS.VOLUME,
1793 prefixes: PREFIXES.NONE,
1794 value: 0.00000006161152,
1795 offset: 0
1796 }, // 0.06161152 mL
1797 fluiddram: {
1798 name: 'fluiddram',
1799 base: BASE_UNITS.VOLUME,
1800 prefixes: PREFIXES.NONE,
1801 value: 0.0000036966911,
1802 offset: 0
1803 }, // 3.696691 mL
1804 fluidounce: {
1805 name: 'fluidounce',
1806 base: BASE_UNITS.VOLUME,
1807 prefixes: PREFIXES.NONE,
1808 value: 0.00002957353,
1809 offset: 0
1810 }, // 29.57353 mL
1811 gill: {
1812 name: 'gill',
1813 base: BASE_UNITS.VOLUME,
1814 prefixes: PREFIXES.NONE,
1815 value: 0.0001182941,
1816 offset: 0
1817 }, // 118.2941 mL
1818 cc: {
1819 name: 'cc',
1820 base: BASE_UNITS.VOLUME,
1821 prefixes: PREFIXES.NONE,
1822 value: 1e-6,
1823 offset: 0
1824 }, // 1e-6 L
1825 cup: {
1826 name: 'cup',
1827 base: BASE_UNITS.VOLUME,
1828 prefixes: PREFIXES.NONE,
1829 value: 0.0002365882,
1830 offset: 0
1831 }, // 236.5882 mL
1832 pint: {
1833 name: 'pint',
1834 base: BASE_UNITS.VOLUME,
1835 prefixes: PREFIXES.NONE,
1836 value: 0.0004731765,
1837 offset: 0
1838 }, // 473.1765 mL
1839 quart: {
1840 name: 'quart',
1841 base: BASE_UNITS.VOLUME,
1842 prefixes: PREFIXES.NONE,
1843 value: 0.0009463529,
1844 offset: 0
1845 }, // 946.3529 mL
1846 gallon: {
1847 name: 'gallon',
1848 base: BASE_UNITS.VOLUME,
1849 prefixes: PREFIXES.NONE,
1850 value: 0.003785412,
1851 offset: 0
1852 }, // 3.785412 L
1853 beerbarrel: {
1854 name: 'beerbarrel',
1855 base: BASE_UNITS.VOLUME,
1856 prefixes: PREFIXES.NONE,
1857 value: 0.1173478,
1858 offset: 0
1859 }, // 117.3478 L
1860 oilbarrel: {
1861 name: 'oilbarrel',
1862 base: BASE_UNITS.VOLUME,
1863 prefixes: PREFIXES.NONE,
1864 value: 0.1589873,
1865 offset: 0
1866 }, // 158.9873 L
1867 hogshead: {
1868 name: 'hogshead',
1869 base: BASE_UNITS.VOLUME,
1870 prefixes: PREFIXES.NONE,
1871 value: 0.2384810,
1872 offset: 0
1873 }, // 238.4810 L
1874
1875 // {name: 'min', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.00000006161152, offset: 0}, // 0.06161152 mL // min is already in use as minute
1876 fldr: {
1877 name: 'fldr',
1878 base: BASE_UNITS.VOLUME,
1879 prefixes: PREFIXES.NONE,
1880 value: 0.0000036966911,
1881 offset: 0
1882 }, // 3.696691 mL
1883 floz: {
1884 name: 'floz',
1885 base: BASE_UNITS.VOLUME,
1886 prefixes: PREFIXES.NONE,
1887 value: 0.00002957353,
1888 offset: 0
1889 }, // 29.57353 mL
1890 gi: {
1891 name: 'gi',
1892 base: BASE_UNITS.VOLUME,
1893 prefixes: PREFIXES.NONE,
1894 value: 0.0001182941,
1895 offset: 0
1896 }, // 118.2941 mL
1897 cp: {
1898 name: 'cp',
1899 base: BASE_UNITS.VOLUME,
1900 prefixes: PREFIXES.NONE,
1901 value: 0.0002365882,
1902 offset: 0
1903 }, // 236.5882 mL
1904 pt: {
1905 name: 'pt',
1906 base: BASE_UNITS.VOLUME,
1907 prefixes: PREFIXES.NONE,
1908 value: 0.0004731765,
1909 offset: 0
1910 }, // 473.1765 mL
1911 qt: {
1912 name: 'qt',
1913 base: BASE_UNITS.VOLUME,
1914 prefixes: PREFIXES.NONE,
1915 value: 0.0009463529,
1916 offset: 0
1917 }, // 946.3529 mL
1918 gal: {
1919 name: 'gal',
1920 base: BASE_UNITS.VOLUME,
1921 prefixes: PREFIXES.NONE,
1922 value: 0.003785412,
1923 offset: 0
1924 }, // 3.785412 L
1925 bbl: {
1926 name: 'bbl',
1927 base: BASE_UNITS.VOLUME,
1928 prefixes: PREFIXES.NONE,
1929 value: 0.1173478,
1930 offset: 0
1931 }, // 117.3478 L
1932 obl: {
1933 name: 'obl',
1934 base: BASE_UNITS.VOLUME,
1935 prefixes: PREFIXES.NONE,
1936 value: 0.1589873,
1937 offset: 0
1938 }, // 158.9873 L
1939 // {name: 'hogshead', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.2384810, offset: 0}, // 238.4810 L // TODO: hh?
1940
1941 // Mass
1942 g: {
1943 name: 'g',
1944 base: BASE_UNITS.MASS,
1945 prefixes: PREFIXES.SHORT,
1946 value: 0.001,
1947 offset: 0
1948 },
1949 gram: {
1950 name: 'gram',
1951 base: BASE_UNITS.MASS,
1952 prefixes: PREFIXES.LONG,
1953 value: 0.001,
1954 offset: 0
1955 },
1956
1957 ton: {
1958 name: 'ton',
1959 base: BASE_UNITS.MASS,
1960 prefixes: PREFIXES.SHORT,
1961 value: 907.18474,
1962 offset: 0
1963 },
1964 tonne: {
1965 name: 'tonne',
1966 base: BASE_UNITS.MASS,
1967 prefixes: PREFIXES.SHORT,
1968 value: 1000,
1969 offset: 0
1970 },
1971
1972 grain: {
1973 name: 'grain',
1974 base: BASE_UNITS.MASS,
1975 prefixes: PREFIXES.NONE,
1976 value: 64.79891e-6,
1977 offset: 0
1978 },
1979 dram: {
1980 name: 'dram',
1981 base: BASE_UNITS.MASS,
1982 prefixes: PREFIXES.NONE,
1983 value: 1.7718451953125e-3,
1984 offset: 0
1985 },
1986 ounce: {
1987 name: 'ounce',
1988 base: BASE_UNITS.MASS,
1989 prefixes: PREFIXES.NONE,
1990 value: 28.349523125e-3,
1991 offset: 0
1992 },
1993 poundmass: {
1994 name: 'poundmass',
1995 base: BASE_UNITS.MASS,
1996 prefixes: PREFIXES.NONE,
1997 value: 453.59237e-3,
1998 offset: 0
1999 },
2000 hundredweight: {
2001 name: 'hundredweight',
2002 base: BASE_UNITS.MASS,
2003 prefixes: PREFIXES.NONE,
2004 value: 45.359237,
2005 offset: 0
2006 },
2007 stick: {
2008 name: 'stick',
2009 base: BASE_UNITS.MASS,
2010 prefixes: PREFIXES.NONE,
2011 value: 115e-3,
2012 offset: 0
2013 },
2014 stone: {
2015 name: 'stone',
2016 base: BASE_UNITS.MASS,
2017 prefixes: PREFIXES.NONE,
2018 value: 6.35029318,
2019 offset: 0
2020 },
2021
2022 gr: {
2023 name: 'gr',
2024 base: BASE_UNITS.MASS,
2025 prefixes: PREFIXES.NONE,
2026 value: 64.79891e-6,
2027 offset: 0
2028 },
2029 dr: {
2030 name: 'dr',
2031 base: BASE_UNITS.MASS,
2032 prefixes: PREFIXES.NONE,
2033 value: 1.7718451953125e-3,
2034 offset: 0
2035 },
2036 oz: {
2037 name: 'oz',
2038 base: BASE_UNITS.MASS,
2039 prefixes: PREFIXES.NONE,
2040 value: 28.349523125e-3,
2041 offset: 0
2042 },
2043 lbm: {
2044 name: 'lbm',
2045 base: BASE_UNITS.MASS,
2046 prefixes: PREFIXES.NONE,
2047 value: 453.59237e-3,
2048 offset: 0
2049 },
2050 cwt: {
2051 name: 'cwt',
2052 base: BASE_UNITS.MASS,
2053 prefixes: PREFIXES.NONE,
2054 value: 45.359237,
2055 offset: 0
2056 },
2057
2058 // Time
2059 s: {
2060 name: 's',
2061 base: BASE_UNITS.TIME,
2062 prefixes: PREFIXES.SHORT,
2063 value: 1,
2064 offset: 0
2065 },
2066 min: {
2067 name: 'min',
2068 base: BASE_UNITS.TIME,
2069 prefixes: PREFIXES.NONE,
2070 value: 60,
2071 offset: 0
2072 },
2073 h: {
2074 name: 'h',
2075 base: BASE_UNITS.TIME,
2076 prefixes: PREFIXES.NONE,
2077 value: 3600,
2078 offset: 0
2079 },
2080 second: {
2081 name: 'second',
2082 base: BASE_UNITS.TIME,
2083 prefixes: PREFIXES.LONG,
2084 value: 1,
2085 offset: 0
2086 },
2087 sec: {
2088 name: 'sec',
2089 base: BASE_UNITS.TIME,
2090 prefixes: PREFIXES.LONG,
2091 value: 1,
2092 offset: 0
2093 },
2094 minute: {
2095 name: 'minute',
2096 base: BASE_UNITS.TIME,
2097 prefixes: PREFIXES.NONE,
2098 value: 60,
2099 offset: 0
2100 },
2101 hour: {
2102 name: 'hour',
2103 base: BASE_UNITS.TIME,
2104 prefixes: PREFIXES.NONE,
2105 value: 3600,
2106 offset: 0
2107 },
2108 day: {
2109 name: 'day',
2110 base: BASE_UNITS.TIME,
2111 prefixes: PREFIXES.NONE,
2112 value: 86400,
2113 offset: 0
2114 },
2115 week: {
2116 name: 'week',
2117 base: BASE_UNITS.TIME,
2118 prefixes: PREFIXES.NONE,
2119 value: 7 * 86400,
2120 offset: 0
2121 },
2122 month: {
2123 name: 'month',
2124 base: BASE_UNITS.TIME,
2125 prefixes: PREFIXES.NONE,
2126 value: 2629800, // 1/12th of Julian year
2127 offset: 0
2128 },
2129 year: {
2130 name: 'year',
2131 base: BASE_UNITS.TIME,
2132 prefixes: PREFIXES.NONE,
2133 value: 31557600, // Julian year
2134 offset: 0
2135 },
2136 decade: {
2137 name: 'decade',
2138 base: BASE_UNITS.TIME,
2139 prefixes: PREFIXES.NONE,
2140 value: 315576000, // Julian decade
2141 offset: 0
2142 },
2143 century: {
2144 name: 'century',
2145 base: BASE_UNITS.TIME,
2146 prefixes: PREFIXES.NONE,
2147 value: 3155760000, // Julian century
2148 offset: 0
2149 },
2150 millennium: {
2151 name: 'millennium',
2152 base: BASE_UNITS.TIME,
2153 prefixes: PREFIXES.NONE,
2154 value: 31557600000, // Julian millennium
2155 offset: 0
2156 },
2157
2158 // Frequency
2159 hertz: {
2160 name: 'Hertz',
2161 base: BASE_UNITS.FREQUENCY,
2162 prefixes: PREFIXES.LONG,
2163 value: 1,
2164 offset: 0,
2165 reciprocal: true
2166 },
2167 Hz: {
2168 name: 'Hz',
2169 base: BASE_UNITS.FREQUENCY,
2170 prefixes: PREFIXES.SHORT,
2171 value: 1,
2172 offset: 0,
2173 reciprocal: true
2174 },
2175
2176 // Angle
2177 rad: {
2178 name: 'rad',
2179 base: BASE_UNITS.ANGLE,
2180 prefixes: PREFIXES.SHORT,
2181 value: 1,
2182 offset: 0
2183 },
2184 radian: {
2185 name: 'radian',
2186 base: BASE_UNITS.ANGLE,
2187 prefixes: PREFIXES.LONG,
2188 value: 1,
2189 offset: 0
2190 },
2191 // deg = rad / (2*pi) * 360 = rad / 0.017453292519943295769236907684888
2192 deg: {
2193 name: 'deg',
2194 base: BASE_UNITS.ANGLE,
2195 prefixes: PREFIXES.SHORT,
2196 value: null, // will be filled in by calculateAngleValues()
2197 offset: 0
2198 },
2199 degree: {
2200 name: 'degree',
2201 base: BASE_UNITS.ANGLE,
2202 prefixes: PREFIXES.LONG,
2203 value: null, // will be filled in by calculateAngleValues()
2204 offset: 0
2205 },
2206 // grad = rad / (2*pi) * 400 = rad / 0.015707963267948966192313216916399
2207 grad: {
2208 name: 'grad',
2209 base: BASE_UNITS.ANGLE,
2210 prefixes: PREFIXES.SHORT,
2211 value: null, // will be filled in by calculateAngleValues()
2212 offset: 0
2213 },
2214 gradian: {
2215 name: 'gradian',
2216 base: BASE_UNITS.ANGLE,
2217 prefixes: PREFIXES.LONG,
2218 value: null, // will be filled in by calculateAngleValues()
2219 offset: 0
2220 },
2221 // cycle = rad / (2*pi) = rad / 6.2831853071795864769252867665793
2222 cycle: {
2223 name: 'cycle',
2224 base: BASE_UNITS.ANGLE,
2225 prefixes: PREFIXES.NONE,
2226 value: null, // will be filled in by calculateAngleValues()
2227 offset: 0
2228 },
2229 // arcsec = rad / (3600 * (360 / 2 * pi)) = rad / 0.0000048481368110953599358991410235795
2230 arcsec: {
2231 name: 'arcsec',
2232 base: BASE_UNITS.ANGLE,
2233 prefixes: PREFIXES.NONE,
2234 value: null, // will be filled in by calculateAngleValues()
2235 offset: 0
2236 },
2237 // arcmin = rad / (60 * (360 / 2 * pi)) = rad / 0.00029088820866572159615394846141477
2238 arcmin: {
2239 name: 'arcmin',
2240 base: BASE_UNITS.ANGLE,
2241 prefixes: PREFIXES.NONE,
2242 value: null, // will be filled in by calculateAngleValues()
2243 offset: 0
2244 },
2245
2246 // Electric current
2247 A: {
2248 name: 'A',
2249 base: BASE_UNITS.CURRENT,
2250 prefixes: PREFIXES.SHORT,
2251 value: 1,
2252 offset: 0
2253 },
2254 ampere: {
2255 name: 'ampere',
2256 base: BASE_UNITS.CURRENT,
2257 prefixes: PREFIXES.LONG,
2258 value: 1,
2259 offset: 0
2260 },
2261
2262 // Temperature
2263 // K(C) = °C + 273.15
2264 // K(F) = (°F + 459.67) / 1.8
2265 // K(R) = °R / 1.8
2266 K: {
2267 name: 'K',
2268 base: BASE_UNITS.TEMPERATURE,
2269 prefixes: PREFIXES.NONE,
2270 value: 1,
2271 offset: 0
2272 },
2273 degC: {
2274 name: 'degC',
2275 base: BASE_UNITS.TEMPERATURE,
2276 prefixes: PREFIXES.NONE,
2277 value: 1,
2278 offset: 273.15
2279 },
2280 degF: {
2281 name: 'degF',
2282 base: BASE_UNITS.TEMPERATURE,
2283 prefixes: PREFIXES.NONE,
2284 value: 1 / 1.8,
2285 offset: 459.67
2286 },
2287 degR: {
2288 name: 'degR',
2289 base: BASE_UNITS.TEMPERATURE,
2290 prefixes: PREFIXES.NONE,
2291 value: 1 / 1.8,
2292 offset: 0
2293 },
2294 kelvin: {
2295 name: 'kelvin',
2296 base: BASE_UNITS.TEMPERATURE,
2297 prefixes: PREFIXES.NONE,
2298 value: 1,
2299 offset: 0
2300 },
2301 celsius: {
2302 name: 'celsius',
2303 base: BASE_UNITS.TEMPERATURE,
2304 prefixes: PREFIXES.NONE,
2305 value: 1,
2306 offset: 273.15
2307 },
2308 fahrenheit: {
2309 name: 'fahrenheit',
2310 base: BASE_UNITS.TEMPERATURE,
2311 prefixes: PREFIXES.NONE,
2312 value: 1 / 1.8,
2313 offset: 459.67
2314 },
2315 rankine: {
2316 name: 'rankine',
2317 base: BASE_UNITS.TEMPERATURE,
2318 prefixes: PREFIXES.NONE,
2319 value: 1 / 1.8,
2320 offset: 0
2321 },
2322
2323 // amount of substance
2324 mol: {
2325 name: 'mol',
2326 base: BASE_UNITS.AMOUNT_OF_SUBSTANCE,
2327 prefixes: PREFIXES.SHORT,
2328 value: 1,
2329 offset: 0
2330 },
2331 mole: {
2332 name: 'mole',
2333 base: BASE_UNITS.AMOUNT_OF_SUBSTANCE,
2334 prefixes: PREFIXES.LONG,
2335 value: 1,
2336 offset: 0
2337 },
2338
2339 // luminous intensity
2340 cd: {
2341 name: 'cd',
2342 base: BASE_UNITS.LUMINOUS_INTENSITY,
2343 prefixes: PREFIXES.NONE,
2344 value: 1,
2345 offset: 0
2346 },
2347 candela: {
2348 name: 'candela',
2349 base: BASE_UNITS.LUMINOUS_INTENSITY,
2350 prefixes: PREFIXES.NONE,
2351 value: 1,
2352 offset: 0
2353 },
2354 // TODO: units STERADIAN
2355 // {name: 'sr', base: BASE_UNITS.STERADIAN, prefixes: PREFIXES.NONE, value: 1, offset: 0},
2356 // {name: 'steradian', base: BASE_UNITS.STERADIAN, prefixes: PREFIXES.NONE, value: 1, offset: 0},
2357
2358 // Force
2359 N: {
2360 name: 'N',
2361 base: BASE_UNITS.FORCE,
2362 prefixes: PREFIXES.SHORT,
2363 value: 1,
2364 offset: 0
2365 },
2366 newton: {
2367 name: 'newton',
2368 base: BASE_UNITS.FORCE,
2369 prefixes: PREFIXES.LONG,
2370 value: 1,
2371 offset: 0
2372 },
2373 dyn: {
2374 name: 'dyn',
2375 base: BASE_UNITS.FORCE,
2376 prefixes: PREFIXES.SHORT,
2377 value: 0.00001,
2378 offset: 0
2379 },
2380 dyne: {
2381 name: 'dyne',
2382 base: BASE_UNITS.FORCE,
2383 prefixes: PREFIXES.LONG,
2384 value: 0.00001,
2385 offset: 0
2386 },
2387 lbf: {
2388 name: 'lbf',
2389 base: BASE_UNITS.FORCE,
2390 prefixes: PREFIXES.NONE,
2391 value: 4.4482216152605,
2392 offset: 0
2393 },
2394 poundforce: {
2395 name: 'poundforce',
2396 base: BASE_UNITS.FORCE,
2397 prefixes: PREFIXES.NONE,
2398 value: 4.4482216152605,
2399 offset: 0
2400 },
2401 kip: {
2402 name: 'kip',
2403 base: BASE_UNITS.FORCE,
2404 prefixes: PREFIXES.LONG,
2405 value: 4448.2216,
2406 offset: 0
2407 },
2408
2409 // Energy
2410 J: {
2411 name: 'J',
2412 base: BASE_UNITS.ENERGY,
2413 prefixes: PREFIXES.SHORT,
2414 value: 1,
2415 offset: 0
2416 },
2417 joule: {
2418 name: 'joule',
2419 base: BASE_UNITS.ENERGY,
2420 prefixes: PREFIXES.SHORT,
2421 value: 1,
2422 offset: 0
2423 },
2424 erg: {
2425 name: 'erg',
2426 base: BASE_UNITS.ENERGY,
2427 prefixes: PREFIXES.NONE,
2428 value: 1e-7,
2429 offset: 0
2430 },
2431 Wh: {
2432 name: 'Wh',
2433 base: BASE_UNITS.ENERGY,
2434 prefixes: PREFIXES.SHORT,
2435 value: 3600,
2436 offset: 0
2437 },
2438 BTU: {
2439 name: 'BTU',
2440 base: BASE_UNITS.ENERGY,
2441 prefixes: PREFIXES.BTU,
2442 value: 1055.05585262,
2443 offset: 0
2444 },
2445 eV: {
2446 name: 'eV',
2447 base: BASE_UNITS.ENERGY,
2448 prefixes: PREFIXES.SHORT,
2449 value: 1.602176565e-19,
2450 offset: 0
2451 },
2452 electronvolt: {
2453 name: 'electronvolt',
2454 base: BASE_UNITS.ENERGY,
2455 prefixes: PREFIXES.LONG,
2456 value: 1.602176565e-19,
2457 offset: 0
2458 },
2459
2460 // Power
2461 W: {
2462 name: 'W',
2463 base: BASE_UNITS.POWER,
2464 prefixes: PREFIXES.SHORT,
2465 value: 1,
2466 offset: 0
2467 },
2468 watt: {
2469 name: 'watt',
2470 base: BASE_UNITS.POWER,
2471 prefixes: PREFIXES.LONG,
2472 value: 1,
2473 offset: 0
2474 },
2475 hp: {
2476 name: 'hp',
2477 base: BASE_UNITS.POWER,
2478 prefixes: PREFIXES.NONE,
2479 value: 745.6998715386,
2480 offset: 0
2481 },
2482
2483 // Electrical power units
2484 VAR: {
2485 name: 'VAR',
2486 base: BASE_UNITS.POWER,
2487 prefixes: PREFIXES.SHORT,
2488 value: Complex.I,
2489 offset: 0
2490 },
2491
2492 VA: {
2493 name: 'VA',
2494 base: BASE_UNITS.POWER,
2495 prefixes: PREFIXES.SHORT,
2496 value: 1,
2497 offset: 0
2498 },
2499
2500 // Pressure
2501 Pa: {
2502 name: 'Pa',
2503 base: BASE_UNITS.PRESSURE,
2504 prefixes: PREFIXES.SHORT,
2505 value: 1,
2506 offset: 0
2507 },
2508 psi: {
2509 name: 'psi',
2510 base: BASE_UNITS.PRESSURE,
2511 prefixes: PREFIXES.NONE,
2512 value: 6894.75729276459,
2513 offset: 0
2514 },
2515 atm: {
2516 name: 'atm',
2517 base: BASE_UNITS.PRESSURE,
2518 prefixes: PREFIXES.NONE,
2519 value: 101325,
2520 offset: 0
2521 },
2522 bar: {
2523 name: 'bar',
2524 base: BASE_UNITS.PRESSURE,
2525 prefixes: PREFIXES.SHORTLONG,
2526 value: 100000,
2527 offset: 0
2528 },
2529 torr: {
2530 name: 'torr',
2531 base: BASE_UNITS.PRESSURE,
2532 prefixes: PREFIXES.NONE,
2533 value: 133.322,
2534 offset: 0
2535 },
2536 mmHg: {
2537 name: 'mmHg',
2538 base: BASE_UNITS.PRESSURE,
2539 prefixes: PREFIXES.NONE,
2540 value: 133.322,
2541 offset: 0
2542 },
2543 mmH2O: {
2544 name: 'mmH2O',
2545 base: BASE_UNITS.PRESSURE,
2546 prefixes: PREFIXES.NONE,
2547 value: 9.80665,
2548 offset: 0
2549 },
2550 cmH2O: {
2551 name: 'cmH2O',
2552 base: BASE_UNITS.PRESSURE,
2553 prefixes: PREFIXES.NONE,
2554 value: 98.0665,
2555 offset: 0
2556 },
2557
2558 // Electric charge
2559 coulomb: {
2560 name: 'coulomb',
2561 base: BASE_UNITS.ELECTRIC_CHARGE,
2562 prefixes: PREFIXES.LONG,
2563 value: 1,
2564 offset: 0
2565 },
2566 C: {
2567 name: 'C',
2568 base: BASE_UNITS.ELECTRIC_CHARGE,
2569 prefixes: PREFIXES.SHORT,
2570 value: 1,
2571 offset: 0
2572 },
2573 // Electric capacitance
2574 farad: {
2575 name: 'farad',
2576 base: BASE_UNITS.ELECTRIC_CAPACITANCE,
2577 prefixes: PREFIXES.LONG,
2578 value: 1,
2579 offset: 0
2580 },
2581 F: {
2582 name: 'F',
2583 base: BASE_UNITS.ELECTRIC_CAPACITANCE,
2584 prefixes: PREFIXES.SHORT,
2585 value: 1,
2586 offset: 0
2587 },
2588 // Electric potential
2589 volt: {
2590 name: 'volt',
2591 base: BASE_UNITS.ELECTRIC_POTENTIAL,
2592 prefixes: PREFIXES.LONG,
2593 value: 1,
2594 offset: 0
2595 },
2596 V: {
2597 name: 'V',
2598 base: BASE_UNITS.ELECTRIC_POTENTIAL,
2599 prefixes: PREFIXES.SHORT,
2600 value: 1,
2601 offset: 0
2602 },
2603 // Electric resistance
2604 ohm: {
2605 name: 'ohm',
2606 base: BASE_UNITS.ELECTRIC_RESISTANCE,
2607 prefixes: PREFIXES.SHORTLONG, // Both Mohm and megaohm are acceptable
2608 value: 1,
2609 offset: 0
2610 },
2611 /*
2612 * Unicode breaks in browsers if charset is not specified
2613 Ω: {
2614 name: 'Ω',
2615 base: BASE_UNITS.ELECTRIC_RESISTANCE,
2616 prefixes: PREFIXES.SHORT,
2617 value: 1,
2618 offset: 0
2619 },
2620 */
2621 // Electric inductance
2622 henry: {
2623 name: 'henry',
2624 base: BASE_UNITS.ELECTRIC_INDUCTANCE,
2625 prefixes: PREFIXES.LONG,
2626 value: 1,
2627 offset: 0
2628 },
2629 H: {
2630 name: 'H',
2631 base: BASE_UNITS.ELECTRIC_INDUCTANCE,
2632 prefixes: PREFIXES.SHORT,
2633 value: 1,
2634 offset: 0
2635 },
2636 // Electric conductance
2637 siemens: {
2638 name: 'siemens',
2639 base: BASE_UNITS.ELECTRIC_CONDUCTANCE,
2640 prefixes: PREFIXES.LONG,
2641 value: 1,
2642 offset: 0
2643 },
2644 S: {
2645 name: 'S',
2646 base: BASE_UNITS.ELECTRIC_CONDUCTANCE,
2647 prefixes: PREFIXES.SHORT,
2648 value: 1,
2649 offset: 0
2650 },
2651 // Magnetic flux
2652 weber: {
2653 name: 'weber',
2654 base: BASE_UNITS.MAGNETIC_FLUX,
2655 prefixes: PREFIXES.LONG,
2656 value: 1,
2657 offset: 0
2658 },
2659 Wb: {
2660 name: 'Wb',
2661 base: BASE_UNITS.MAGNETIC_FLUX,
2662 prefixes: PREFIXES.SHORT,
2663 value: 1,
2664 offset: 0
2665 },
2666 // Magnetic flux density
2667 tesla: {
2668 name: 'tesla',
2669 base: BASE_UNITS.MAGNETIC_FLUX_DENSITY,
2670 prefixes: PREFIXES.LONG,
2671 value: 1,
2672 offset: 0
2673 },
2674 T: {
2675 name: 'T',
2676 base: BASE_UNITS.MAGNETIC_FLUX_DENSITY,
2677 prefixes: PREFIXES.SHORT,
2678 value: 1,
2679 offset: 0
2680 },
2681
2682 // Binary
2683 b: {
2684 name: 'b',
2685 base: BASE_UNITS.BIT,
2686 prefixes: PREFIXES.BINARY_SHORT,
2687 value: 1,
2688 offset: 0
2689 },
2690 bits: {
2691 name: 'bits',
2692 base: BASE_UNITS.BIT,
2693 prefixes: PREFIXES.BINARY_LONG,
2694 value: 1,
2695 offset: 0
2696 },
2697 B: {
2698 name: 'B',
2699 base: BASE_UNITS.BIT,
2700 prefixes: PREFIXES.BINARY_SHORT,
2701 value: 8,
2702 offset: 0
2703 },
2704 bytes: {
2705 name: 'bytes',
2706 base: BASE_UNITS.BIT,
2707 prefixes: PREFIXES.BINARY_LONG,
2708 value: 8,
2709 offset: 0
2710 }
2711
2712 // aliases (formerly plurals)
2713 };var ALIASES = {
2714 meters: 'meter',
2715 inches: 'inch',
2716 feet: 'foot',
2717 yards: 'yard',
2718 miles: 'mile',
2719 links: 'link',
2720 rods: 'rod',
2721 chains: 'chain',
2722 angstroms: 'angstrom',
2723
2724 lt: 'l',
2725 litres: 'litre',
2726 liter: 'litre',
2727 liters: 'litre',
2728 teaspoons: 'teaspoon',
2729 tablespoons: 'tablespoon',
2730 minims: 'minim',
2731 fluiddrams: 'fluiddram',
2732 fluidounces: 'fluidounce',
2733 gills: 'gill',
2734 cups: 'cup',
2735 pints: 'pint',
2736 quarts: 'quart',
2737 gallons: 'gallon',
2738 beerbarrels: 'beerbarrel',
2739 oilbarrels: 'oilbarrel',
2740 hogsheads: 'hogshead',
2741 gtts: 'gtt',
2742
2743 grams: 'gram',
2744 tons: 'ton',
2745 tonnes: 'tonne',
2746 grains: 'grain',
2747 drams: 'dram',
2748 ounces: 'ounce',
2749 poundmasses: 'poundmass',
2750 hundredweights: 'hundredweight',
2751 sticks: 'stick',
2752 lb: 'lbm',
2753 lbs: 'lbm',
2754
2755 kips: 'kip',
2756
2757 acres: 'acre',
2758 hectares: 'hectare',
2759 sqfeet: 'sqft',
2760 sqyard: 'sqyd',
2761 sqmile: 'sqmi',
2762 sqmiles: 'sqmi',
2763
2764 mmhg: 'mmHg',
2765 mmh2o: 'mmH2O',
2766 cmh2o: 'cmH2O',
2767
2768 seconds: 'second',
2769 secs: 'second',
2770 minutes: 'minute',
2771 mins: 'minute',
2772 hours: 'hour',
2773 hr: 'hour',
2774 hrs: 'hour',
2775 days: 'day',
2776 weeks: 'week',
2777 months: 'month',
2778 years: 'year',
2779 decades: 'decade',
2780 centuries: 'century',
2781 millennia: 'millennium',
2782
2783 hertz: 'hertz',
2784
2785 radians: 'radian',
2786 degrees: 'degree',
2787 gradians: 'gradian',
2788 cycles: 'cycle',
2789 arcsecond: 'arcsec',
2790 arcseconds: 'arcsec',
2791 arcminute: 'arcmin',
2792 arcminutes: 'arcmin',
2793
2794 BTUs: 'BTU',
2795 watts: 'watt',
2796 joules: 'joule',
2797
2798 amperes: 'ampere',
2799 coulombs: 'coulomb',
2800 volts: 'volt',
2801 ohms: 'ohm',
2802 farads: 'farad',
2803 webers: 'weber',
2804 teslas: 'tesla',
2805 electronvolts: 'electronvolt',
2806 moles: 'mole'
2807
2808 /**
2809 * Calculate the values for the angle units.
2810 * Value is calculated as number or BigNumber depending on the configuration
2811 * @param {{number: 'number' | 'BigNumber'}} config
2812 */
2813 };function calculateAngleValues(config) {
2814 if (config.number === 'BigNumber') {
2815 var pi = constants.pi(type.BigNumber);
2816 UNITS.rad.value = new type.BigNumber(1);
2817 UNITS.deg.value = pi.div(180); // 2 * pi / 360
2818 UNITS.grad.value = pi.div(200); // 2 * pi / 400
2819 UNITS.cycle.value = pi.times(2); // 2 * pi
2820 UNITS.arcsec.value = pi.div(648000); // 2 * pi / 360 / 3600
2821 UNITS.arcmin.value = pi.div(10800); // 2 * pi / 360 / 60
2822 } else {
2823 // number
2824 UNITS.rad.value = 1;
2825 UNITS.deg.value = Math.PI / 180; // 2 * pi / 360
2826 UNITS.grad.value = Math.PI / 200; // 2 * pi / 400
2827 UNITS.cycle.value = Math.PI * 2; // 2 * pi
2828 UNITS.arcsec.value = Math.PI / 648000; // 2 * pi / 360 / 3600
2829 UNITS.arcmin.value = Math.PI / 10800; // 2 * pi / 360 / 60
2830 }
2831
2832 // copy to the full names of the angles
2833 UNITS.radian.value = UNITS.rad.value;
2834 UNITS.degree.value = UNITS.deg.value;
2835 UNITS.gradian.value = UNITS.grad.value;
2836 }
2837
2838 // apply the angle values now
2839 calculateAngleValues(config);
2840
2841 // recalculate the values on change of configuration
2842 math.on('config', function (curr, prev) {
2843 if (curr.number !== prev.number) {
2844 calculateAngleValues(curr);
2845 }
2846 });
2847
2848 /**
2849 * A unit system is a set of dimensionally independent base units plus a set of derived units, formed by multiplication and division of the base units, that are by convention used with the unit system.
2850 * A user perhaps could issue a command to select a preferred unit system, or use the default (see below).
2851 * Auto unit system: The default unit system is updated on the fly anytime a unit is parsed. The corresponding unit in the default unit system is updated, so that answers are given in the same units the user supplies.
2852 */
2853 var UNIT_SYSTEMS = {
2854 si: {
2855 // Base units
2856 NONE: { unit: UNIT_NONE, prefix: PREFIXES.NONE[''] },
2857 LENGTH: { unit: UNITS.m, prefix: PREFIXES.SHORT[''] },
2858 MASS: { unit: UNITS.g, prefix: PREFIXES.SHORT['k'] },
2859 TIME: { unit: UNITS.s, prefix: PREFIXES.SHORT[''] },
2860 CURRENT: { unit: UNITS.A, prefix: PREFIXES.SHORT[''] },
2861 TEMPERATURE: { unit: UNITS.K, prefix: PREFIXES.SHORT[''] },
2862 LUMINOUS_INTENSITY: { unit: UNITS.cd, prefix: PREFIXES.SHORT[''] },
2863 AMOUNT_OF_SUBSTANCE: { unit: UNITS.mol, prefix: PREFIXES.SHORT[''] },
2864 ANGLE: { unit: UNITS.rad, prefix: PREFIXES.SHORT[''] },
2865 BIT: { unit: UNITS.bit, prefix: PREFIXES.SHORT[''] },
2866
2867 // Derived units
2868 FORCE: { unit: UNITS.N, prefix: PREFIXES.SHORT[''] },
2869 ENERGY: { unit: UNITS.J, prefix: PREFIXES.SHORT[''] },
2870 POWER: { unit: UNITS.W, prefix: PREFIXES.SHORT[''] },
2871 PRESSURE: { unit: UNITS.Pa, prefix: PREFIXES.SHORT[''] },
2872 ELECTRIC_CHARGE: { unit: UNITS.C, prefix: PREFIXES.SHORT[''] },
2873 ELECTRIC_CAPACITANCE: { unit: UNITS.F, prefix: PREFIXES.SHORT[''] },
2874 ELECTRIC_POTENTIAL: { unit: UNITS.V, prefix: PREFIXES.SHORT[''] },
2875 ELECTRIC_RESISTANCE: { unit: UNITS.ohm, prefix: PREFIXES.SHORT[''] },
2876 ELECTRIC_INDUCTANCE: { unit: UNITS.H, prefix: PREFIXES.SHORT[''] },
2877 ELECTRIC_CONDUCTANCE: { unit: UNITS.S, prefix: PREFIXES.SHORT[''] },
2878 MAGNETIC_FLUX: { unit: UNITS.Wb, prefix: PREFIXES.SHORT[''] },
2879 MAGNETIC_FLUX_DENSITY: { unit: UNITS.T, prefix: PREFIXES.SHORT[''] },
2880 FREQUENCY: { unit: UNITS.Hz, prefix: PREFIXES.SHORT[''] }
2881 }
2882
2883 // Clone to create the other unit systems
2884 };UNIT_SYSTEMS.cgs = JSON.parse(JSON.stringify(UNIT_SYSTEMS.si));
2885 UNIT_SYSTEMS.cgs.LENGTH = { unit: UNITS.m, prefix: PREFIXES.SHORT['c'] };
2886 UNIT_SYSTEMS.cgs.MASS = { unit: UNITS.g, prefix: PREFIXES.SHORT[''] };
2887 UNIT_SYSTEMS.cgs.FORCE = { unit: UNITS.dyn, prefix: PREFIXES.SHORT[''] };
2888 UNIT_SYSTEMS.cgs.ENERGY = { unit: UNITS.erg, prefix: PREFIXES.NONE['']
2889 // there are wholly 4 unique cgs systems for electricity and magnetism,
2890 // so let's not worry about it unless somebody complains
2891
2892 };UNIT_SYSTEMS.us = JSON.parse(JSON.stringify(UNIT_SYSTEMS.si));
2893 UNIT_SYSTEMS.us.LENGTH = { unit: UNITS.ft, prefix: PREFIXES.NONE[''] };
2894 UNIT_SYSTEMS.us.MASS = { unit: UNITS.lbm, prefix: PREFIXES.NONE[''] };
2895 UNIT_SYSTEMS.us.TEMPERATURE = { unit: UNITS.degF, prefix: PREFIXES.NONE[''] };
2896 UNIT_SYSTEMS.us.FORCE = { unit: UNITS.lbf, prefix: PREFIXES.NONE[''] };
2897 UNIT_SYSTEMS.us.ENERGY = { unit: UNITS.BTU, prefix: PREFIXES.BTU[''] };
2898 UNIT_SYSTEMS.us.POWER = { unit: UNITS.hp, prefix: PREFIXES.NONE[''] };
2899 UNIT_SYSTEMS.us.PRESSURE = { unit: UNITS.psi, prefix: PREFIXES.NONE['']
2900
2901 // Add additional unit systems here.
2902
2903 // Choose a unit system to seed the auto unit system.
2904 };UNIT_SYSTEMS.auto = JSON.parse(JSON.stringify(UNIT_SYSTEMS.si));
2905
2906 // Set the current unit system
2907 var currentUnitSystem = UNIT_SYSTEMS.auto;
2908
2909 /**
2910 * Set a unit system for formatting derived units.
2911 * @param {string} [name] The name of the unit system.
2912 */
2913 Unit.setUnitSystem = function (name) {
2914 if (UNIT_SYSTEMS.hasOwnProperty(name)) {
2915 currentUnitSystem = UNIT_SYSTEMS[name];
2916 } else {
2917 throw new Error('Unit system ' + name + ' does not exist. Choices are: ' + Object.keys(UNIT_SYSTEMS).join(', '));
2918 }
2919 };
2920
2921 /**
2922 * Return the current unit system.
2923 * @return {string} The current unit system.
2924 */
2925 Unit.getUnitSystem = function () {
2926 for (var _key3 in UNIT_SYSTEMS) {
2927 if (UNIT_SYSTEMS[_key3] === currentUnitSystem) {
2928 return _key3;
2929 }
2930 }
2931 };
2932
2933 /**
2934 * Converters to convert from number to an other numeric type like BigNumber
2935 * or Fraction
2936 */
2937 Unit.typeConverters = {
2938 BigNumber: function BigNumber(x) {
2939 return new type.BigNumber(x + ''); // stringify to prevent constructor error
2940 },
2941
2942 Fraction: function Fraction(x) {
2943 return new type.Fraction(x);
2944 },
2945
2946 Complex: function Complex(x) {
2947 return x;
2948 },
2949
2950 number: function number(x) {
2951 return x;
2952 }
2953
2954 /**
2955 * Retrieve the right convertor function corresponding with the type
2956 * of provided exampleValue.
2957 *
2958 * @param {string} type A string 'number', 'BigNumber', or 'Fraction'
2959 * In case of an unknown type,
2960 * @return {Function}
2961 */
2962 };Unit._getNumberConverter = function (type) {
2963 if (!Unit.typeConverters[type]) {
2964 throw new TypeError('Unsupported type "' + type + '"');
2965 }
2966
2967 return Unit.typeConverters[type];
2968 };
2969
2970 // Add dimensions to each built-in unit
2971 for (var _key4 in UNITS) {
2972 var unit = UNITS[_key4];
2973 unit.dimensions = unit.base.dimensions;
2974 }
2975
2976 // Create aliases
2977 for (var name in ALIASES) {
2978 if (ALIASES.hasOwnProperty(name)) {
2979 var _unit2 = UNITS[ALIASES[name]];
2980 var alias = {};
2981 for (var _key5 in _unit2) {
2982 if (_unit2.hasOwnProperty(_key5)) {
2983 alias[_key5] = _unit2[_key5];
2984 }
2985 }
2986 alias.name = name;
2987 UNITS[name] = alias;
2988 }
2989 }
2990
2991 function assertUnitNameIsValid(name) {
2992 for (var i = 0; i < name.length; i++) {
2993 var _c = name.charAt(i);
2994
2995 var isValidAlpha = function isValidAlpha(p) {
2996 return (/^[a-zA-Z]$/.test(p)
2997 );
2998 };
2999
3000 var _isDigit = function _isDigit(c) {
3001 return c >= '0' && c <= '9';
3002 };
3003
3004 if (i === 0 && !isValidAlpha(_c)) {
3005 throw new Error('Invalid unit name (must begin with alpha character): "' + name + '"');
3006 }
3007
3008 if (i > 0 && !(isValidAlpha(_c) || _isDigit(_c))) {
3009 throw new Error('Invalid unit name (only alphanumeric characters are allowed): "' + name + '"');
3010 }
3011 }
3012 }
3013
3014 /**
3015 * Wrapper around createUnitSingle.
3016 * Example:
3017 * createUnit({
3018 * foo: { },
3019 * bar: {
3020 * definition: 'kg/foo',
3021 * aliases: ['ba', 'barr', 'bars'],
3022 * offset: 200
3023 * },
3024 * baz: '4 bar'
3025 * },
3026 * {
3027 * override: true
3028 * })
3029 * @param {object} obj Object map. Each key becomes a unit which is defined by its value.
3030 * @param {object} options
3031 */
3032 Unit.createUnit = function (obj, options) {
3033 if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object') {
3034 throw new TypeError("createUnit expects first parameter to be of type 'Object'");
3035 }
3036
3037 // Remove all units and aliases we are overriding
3038 if (options && options.override) {
3039 for (var _key6 in obj) {
3040 if (obj.hasOwnProperty(_key6)) {
3041 Unit.deleteUnit(_key6);
3042 }
3043 if (obj[_key6].aliases) {
3044 for (var i = 0; i < obj[_key6].aliases.length; i++) {
3045 Unit.deleteUnit(obj[_key6].aliases[i]);
3046 }
3047 }
3048 }
3049 }
3050
3051 // TODO: traverse multiple times until all units have been added
3052 var lastUnit = void 0;
3053 for (var _key7 in obj) {
3054 if (obj.hasOwnProperty(_key7)) {
3055 lastUnit = Unit.createUnitSingle(_key7, obj[_key7]);
3056 }
3057 }
3058 return lastUnit;
3059 };
3060
3061 /**
3062 * Create a user-defined unit and register it with the Unit type.
3063 * Example:
3064 * createUnitSingle('knot', '0.514444444 m/s')
3065 * createUnitSingle('acre', new Unit(43560, 'ft^2'))
3066 *
3067 * @param {string} name The name of the new unit. Must be unique. Example: 'knot'
3068 * @param {string, Unit} definition Definition of the unit in terms of existing units. For example, '0.514444444 m / s'.
3069 * @param {Object} options (optional) An object containing any of the following properties:
3070 * prefixes {string} "none", "short", "long", "binary_short", or "binary_long". The default is "none".
3071 * aliases {Array} Array of strings. Example: ['knots', 'kt', 'kts']
3072 * offset {Numeric} An offset to apply when converting from the unit. For example, the offset for celsius is 273.15 and the offset for farhenheit is 459.67. Default is 0.
3073 *
3074 * @return {Unit}
3075 */
3076 Unit.createUnitSingle = function (name, obj, options) {
3077 if (typeof obj === 'undefined' || obj === null) {
3078 obj = {};
3079 }
3080
3081 if (typeof name !== 'string') {
3082 throw new TypeError("createUnitSingle expects first parameter to be of type 'string'");
3083 }
3084
3085 // Check collisions with existing units
3086 if (UNITS.hasOwnProperty(name)) {
3087 throw new Error('Cannot create unit "' + name + '": a unit with that name already exists');
3088 }
3089
3090 // TODO: Validate name for collisions with other built-in functions (like abs or cos, for example), and for acceptable variable names. For example, '42' is probably not a valid unit. Nor is '%', since it is also an operator.
3091
3092 assertUnitNameIsValid(name);
3093
3094 var defUnit = null; // The Unit from which the new unit will be created.
3095 var aliases = [];
3096 var offset = 0;
3097 var definition = void 0;
3098 var prefixes = void 0;
3099 if (obj && obj.type === 'Unit') {
3100 defUnit = obj.clone();
3101 } else if (typeof obj === 'string') {
3102 if (obj !== '') {
3103 definition = obj;
3104 }
3105 } else if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object') {
3106 definition = obj.definition;
3107 prefixes = obj.prefixes;
3108 offset = obj.offset;
3109 if (obj.aliases) {
3110 aliases = obj.aliases.valueOf(); // aliases could be a Matrix, so convert to Array
3111 }
3112 } else {
3113 throw new TypeError('Cannot create unit "' + name + '" from "' + obj.toString() + '": expecting "string" or "Unit" or "Object"');
3114 }
3115
3116 if (aliases) {
3117 for (var i = 0; i < aliases.length; i++) {
3118 if (UNITS.hasOwnProperty(aliases[i])) {
3119 throw new Error('Cannot create alias "' + aliases[i] + '": a unit with that name already exists');
3120 }
3121 }
3122 }
3123
3124 if (definition && typeof definition === 'string' && !defUnit) {
3125 try {
3126 defUnit = Unit.parse(definition, { allowNoUnits: true });
3127 } catch (ex) {
3128 ex.message = 'Could not create unit "' + name + '" from "' + definition + '": ' + ex.message;
3129 throw ex;
3130 }
3131 } else if (definition && definition.type === 'Unit') {
3132 defUnit = definition.clone();
3133 }
3134
3135 aliases = aliases || [];
3136 offset = offset || 0;
3137 if (prefixes && prefixes.toUpperCase) {
3138 prefixes = PREFIXES[prefixes.toUpperCase()] || PREFIXES.NONE;
3139 } else {
3140 prefixes = PREFIXES.NONE;
3141 }
3142
3143 // If defUnit is null, it is because the user did not
3144 // specify a defintion. So create a new base dimension.
3145 var newUnit = {};
3146 if (!defUnit) {
3147 // Add a new base dimension
3148 var baseName = name + '_STUFF'; // foo --> foo_STUFF, or the essence of foo
3149 if (BASE_DIMENSIONS.indexOf(baseName) >= 0) {
3150 throw new Error('Cannot create new base unit "' + name + '": a base unit with that name already exists (and cannot be overridden)');
3151 }
3152 BASE_DIMENSIONS.push(baseName);
3153
3154 // Push 0 onto existing base units
3155 for (var b in BASE_UNITS) {
3156 if (BASE_UNITS.hasOwnProperty(b)) {
3157 BASE_UNITS[b].dimensions[BASE_DIMENSIONS.length - 1] = 0;
3158 }
3159 }
3160
3161 // Add the new base unit
3162 var newBaseUnit = { dimensions: [] };
3163 for (var _i6 = 0; _i6 < BASE_DIMENSIONS.length; _i6++) {
3164 newBaseUnit.dimensions[_i6] = 0;
3165 }
3166 newBaseUnit.dimensions[BASE_DIMENSIONS.length - 1] = 1;
3167 newBaseUnit.key = baseName;
3168 BASE_UNITS[baseName] = newBaseUnit;
3169
3170 newUnit = {
3171 name: name,
3172 value: 1,
3173 dimensions: BASE_UNITS[baseName].dimensions.slice(0),
3174 prefixes: prefixes,
3175 offset: offset,
3176 base: baseName
3177 };
3178
3179 currentUnitSystem[baseName] = {
3180 unit: newUnit,
3181 prefix: PREFIXES.NONE['']
3182 };
3183 } else {
3184 newUnit = {
3185 name: name,
3186 value: defUnit.value,
3187 dimensions: defUnit.dimensions.slice(0),
3188 prefixes: prefixes,
3189 offset: offset
3190
3191 // Create a new base if no matching base exists
3192 };var anyMatch = false;
3193 for (var _i7 in BASE_UNITS) {
3194 if (BASE_UNITS.hasOwnProperty(_i7)) {
3195 var match = true;
3196 for (var j = 0; j < BASE_DIMENSIONS.length; j++) {
3197 if (Math.abs((newUnit.dimensions[j] || 0) - (BASE_UNITS[_i7].dimensions[j] || 0)) > 1e-12) {
3198 match = false;
3199 break;
3200 }
3201 }
3202 if (match) {
3203 anyMatch = true;
3204 break;
3205 }
3206 }
3207 }
3208 if (!anyMatch) {
3209 var _baseName = name + '_STUFF'; // foo --> foo_STUFF, or the essence of foo
3210 // Add the new base unit
3211 var _newBaseUnit = { dimensions: defUnit.dimensions.slice(0) };
3212 _newBaseUnit.key = _baseName;
3213 BASE_UNITS[_baseName] = _newBaseUnit;
3214
3215 currentUnitSystem[_baseName] = {
3216 unit: newUnit,
3217 prefix: PREFIXES.NONE['']
3218 };
3219
3220 newUnit.base = _baseName;
3221 }
3222 }
3223
3224 Unit.UNITS[name] = newUnit;
3225
3226 for (var _i8 = 0; _i8 < aliases.length; _i8++) {
3227 var aliasName = aliases[_i8];
3228 var _alias = {};
3229 for (var _key8 in newUnit) {
3230 if (newUnit.hasOwnProperty(_key8)) {
3231 _alias[_key8] = newUnit[_key8];
3232 }
3233 }
3234 _alias.name = aliasName;
3235 Unit.UNITS[aliasName] = _alias;
3236 }
3237
3238 return new Unit(null, name);
3239 };
3240
3241 Unit.deleteUnit = function (name) {
3242 delete Unit.UNITS[name];
3243 };
3244
3245 // expose arrays with prefixes, dimensions, units, systems
3246 Unit.PREFIXES = PREFIXES;
3247 Unit.BASE_DIMENSIONS = BASE_DIMENSIONS;
3248 Unit.BASE_UNITS = BASE_UNITS;
3249 Unit.UNIT_SYSTEMS = UNIT_SYSTEMS;
3250 Unit.UNITS = UNITS;
3251
3252 return Unit;
3253}
3254
3255exports.name = 'Unit';
3256exports.path = 'type';
3257exports.factory = factory;
3258exports.math = true; // request access to the math namespace
\No newline at end of file