@oliasoft-open-source/units 4.7.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3563 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let fraction_js = require("fraction.js");
25
+ fraction_js = __toESM(fraction_js, 1);
26
+ //#region src/internationalization/internationalization.ts
27
+ const options = { maximumFractionDigits: 20 };
28
+ /**
29
+ * Convert the given number to the browser's default or the given format.
30
+ * Returns the converted number
31
+ */
32
+ function convertNumberToLocale(number, countryCode) {
33
+ let numberFormat;
34
+ try {
35
+ if (countryCode) numberFormat = new Intl.NumberFormat(countryCode, options);
36
+ else numberFormat = new Intl.NumberFormat(void 0, options);
37
+ } catch {
38
+ numberFormat = new Intl.NumberFormat(void 0, options);
39
+ }
40
+ return numberFormat.format(number);
41
+ }
42
+ //#endregion
43
+ //#region src/numbers/numbers.ts
44
+ const parseValue = (value) => {
45
+ return typeof value === "string" && isValueWithUnit(value) ? getValue(value) : value;
46
+ };
47
+ /**
48
+ * Checks whether a value can be converted to number type by the toNum() function
49
+ *
50
+ * @param value - value to be checked
51
+ * @returns whether number can be converted by toNum() function
52
+ *
53
+ * @example
54
+ * isValidNum('1 1/2') -> true
55
+ * toNum('foobar|m') -> false
56
+ */
57
+ const isValidNum = (value) => {
58
+ const parsedValue = parseValue(value);
59
+ if (isEmptyString(parsedValue) || Number.isNaN(parsedValue) || parsedValue === Infinity || parsedValue === -Infinity) return true;
60
+ else if (!(isNull(parsedValue) || isUndefined(parsedValue) || isTrailingPeriodSeparator(parsedValue) || isTrailingCommaSeparator(parsedValue) || isArray(parsedValue) || isObject(parsedValue))) {
61
+ const cleanedValue = cleanNumStr(String(parsedValue));
62
+ if (cleanedValue.includes("|")) return false;
63
+ const number = isFraction(cleanedValue) ? numFraction(cleanedValue) : isNumeric(cleanedValue) ? parseFloat(cleanedValue) : cleanedValue;
64
+ if (number === Infinity || number === -Infinity) return true;
65
+ if (!isNumeric(number)) return false;
66
+ if (!Number.isNaN(number)) return true;
67
+ }
68
+ return false;
69
+ };
70
+ /**
71
+ * Checks whether a value is a valid number, in string representation with scientific notation (e.g. '1e3')
72
+ *
73
+ * Note - it's not possible to check whether *number* types are stored in scientific notation (all numbers are stored
74
+ * the same way internally in floating-point formats, so there is no difference between 1000 and 1e3 internally).
75
+ * Whether number types get displayed in scientific notation or not in the console is a browser-specific implementation
76
+ * detail (display formatting) and not something we can check/rely on, so this function is only intended for checking
77
+ * user-input values in string format. See https://stackoverflow.com/a/66005705/942635.
78
+ *
79
+ * @param value - value to be checked
80
+ * @returns whether the value is a valid number in scientific notation
81
+ *
82
+ * @example
83
+ * isValidNum('1e3') -> true
84
+ * toNum(1000) -> false
85
+ * toNum(1e3) -> false (we cannot check scientific notation of number types)
86
+ */
87
+ const isScientificStringNum = (value) => {
88
+ if (typeof value === "string") return isValidNum(value) && value.toLowerCase().includes("e");
89
+ return false;
90
+ };
91
+ /**
92
+ * Converts a numeric value to number type (when possible).
93
+ * - need to know if it's possible first? Call isValidNum()
94
+ * - accepts number types (1.234), stringified numbers ('1.234'), fractions ('1/2'), and unit numbers ('1.234|m')
95
+ * - returns the converted number if possible, otherwise returns the input value or default value when provided
96
+ *
97
+ * @param value - value to be converted to number type
98
+ * @param [fallback] - optional fallback value (returned when not possible to convert)
99
+ * @param [minimum] - optional minimum value
100
+ * @returns valid number after conversion, or fallback, or returns the original input
101
+ *
102
+ * @example
103
+ * toNum('1.2345) -> 1.2345
104
+ * toNum('1.2345|m') -> 1.2345
105
+ */
106
+ const toNum = (value, fallback, minimum) => {
107
+ const fallbackResult = fallback ?? value;
108
+ const parsedValue = parseValue(value);
109
+ if (!isValidNum(parsedValue)) return fallbackResult;
110
+ else {
111
+ const cleanedValue = cleanNumStr(String(parsedValue));
112
+ const number = isFraction(cleanedValue) ? numFraction(cleanedValue) : isNumeric(cleanedValue) ? parseFloat(cleanedValue) : cleanedValue;
113
+ if (number === Infinity || number === -Infinity) return number;
114
+ if (Number.isNaN(number) || !isNumeric(number)) return fallbackResult;
115
+ else if (minimum && number < minimum) return minimum;
116
+ return number;
117
+ }
118
+ };
119
+ /**
120
+ * Convert a number to a string safely, better than String(value)
121
+ * String(0.0000002) returns '2e-7' which is unwanted if we need to preserve formatting
122
+ *
123
+ * @param value
124
+ * @returns number or string output value
125
+ */
126
+ const toString = (value) => {
127
+ if (isValidNum(value)) {
128
+ if (typeof value === "string") return value;
129
+ if (typeof value === "number") {
130
+ if (Number.isNaN(value) || !Number.isFinite(value)) return String(value);
131
+ return formatDecimalDisplayNumber(value, { noThousandsSeparator: true });
132
+ }
133
+ }
134
+ return value;
135
+ };
136
+ //#endregion
137
+ //#region src/parse/parse-number.ts
138
+ const countTrailingZeros = (value, decimalPartOnly = false) => {
139
+ const condition = decimalPartOnly ? /0+((?=[|eE])|$)/ : /(0+|0+\.0+)((?=[|eE])|$)/;
140
+ if (typeof value === "string" && (decimalPartOnly ? value.includes(".") || value.includes(",") : true)) return value?.match(condition)?.[0]?.replaceAll(/[.,]/g, "")?.length ?? 0;
141
+ return 0;
142
+ };
143
+ const hasTrailingZeros = (value) => {
144
+ return countTrailingZeros(value) > 0;
145
+ };
146
+ /**
147
+ * Internal function to parse the value, unit, and type from a generic numeric input
148
+ *
149
+ * Accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
150
+ *
151
+ * @param value
152
+ * @returns object with number, unit, and type
153
+ */
154
+ const parseNumber = (value, preserveTrailingZeros = false) => {
155
+ const isString = typeof value === "string";
156
+ const hasUnit = isString && isValueWithUnit(value);
157
+ const unit = hasUnit ? getUnit(value) : null;
158
+ const cleaned = cleanNumStr(hasUnit ? getValue(value) : value);
159
+ return {
160
+ number: preserveTrailingZeros && hasTrailingZeros(value) ? cleaned : toNum(cleaned),
161
+ unit,
162
+ isString
163
+ };
164
+ };
165
+ /**
166
+ * Convert a number to a string safely, better than String(value)
167
+ * String(0.0000002) returns '2e-7' which is unwanted if we need to preserve formatting
168
+ *
169
+ * @param value
170
+ * @param [isScientific] whether to preserve scientific notation
171
+ * @returns number or string output value
172
+ */
173
+ const safeStringifyNumber = (value, isScientific) => {
174
+ return isScientific ? String(value) : String(toString(value));
175
+ };
176
+ /**
177
+ * Internal function to unParse a value, unit, and type back to an output value
178
+ *
179
+ * Accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
180
+ *
181
+ * @param args
182
+ * @param args.value
183
+ * @param args.unit
184
+ * @param args.isString
185
+ * @param args.isScientific
186
+ * @returns number or string output value
187
+ */
188
+ const unParseNumber = ({ value, unit, isString, isScientific }) => {
189
+ const convertedValue = typeof value === "number" && isString ? safeStringifyNumber(value, isScientific) : value;
190
+ if (unit) return withUnit(convertedValue, unit);
191
+ return convertedValue;
192
+ };
193
+ //#endregion
194
+ //#region src/comparison/comparison.ts
195
+ const DEFAULT_MAX_RELATIVE_DIFF = Number.EPSILON;
196
+ const convertNumbers = (firstValue, secondValue) => {
197
+ const { number: firstNumber, unit: firstUnit } = parseNumber(firstValue);
198
+ const { number: secondNumber, unit: secondUnit } = parseNumber(secondValue);
199
+ return {
200
+ firstNumber,
201
+ secondNumber: firstUnit && secondUnit && firstUnit !== secondUnit ? convertAndGetValue(secondNumber, firstUnit, secondUnit) : secondNumber
202
+ };
203
+ };
204
+ const getToleranceNumber = (relativeDiff) => {
205
+ if (relativeDiff !== null && relativeDiff !== void 0) {
206
+ if (isNumeric(relativeDiff) && typeof relativeDiff === "number") return relativeDiff;
207
+ if (isPercentage(relativeDiff)) {
208
+ const percentageValue = toNum(relativeDiff?.toString().replace("%", ""));
209
+ if (isNumeric(percentageValue)) return percentageValue / 100;
210
+ }
211
+ }
212
+ return null;
213
+ };
214
+ /**
215
+ * Determines whether two numbers are close in value with a tolerance
216
+ * (mitigates excess JavaScript floating point precision quirks)
217
+ */
218
+ const isCloseTo = (firstValue, secondValue, options = { relativeDiff: DEFAULT_MAX_RELATIVE_DIFF }) => {
219
+ const { relativeDiff, absoluteDiff } = options;
220
+ const toleranceNumber = getToleranceNumber(relativeDiff ?? absoluteDiff);
221
+ if (firstValue === null || secondValue === null) return false;
222
+ const hasUnitFirstValue = isValueWithUnit(firstValue);
223
+ const hasUnitSecondValue = isValueWithUnit(secondValue);
224
+ if (hasUnitFirstValue && !hasUnitSecondValue || !hasUnitFirstValue && hasUnitSecondValue) throw new Error(`Parameters must either both have units or both not have units. Received "${firstValue}" and "${secondValue}"`);
225
+ if (toleranceNumber === null) {
226
+ console.warn("Tolerance number is not defined!");
227
+ return firstValue === secondValue;
228
+ }
229
+ if (toleranceNumber <= 0 || toleranceNumber < Number.EPSILON) throw Error("Unpredictable results - toleranceNumber should be bigger than zero or less then EPSILON");
230
+ const { firstNumber, secondNumber } = convertNumbers(firstValue, secondValue);
231
+ if ((firstNumber === Infinity || firstNumber === "Infinity") && (secondNumber === Infinity || secondNumber === "Infinity") || (firstNumber === -Infinity || firstNumber === "-Infinity") && (secondNumber === -Infinity || secondNumber === "-Infinity")) return true;
232
+ if (typeof firstNumber === "number" && typeof secondNumber === "number") {
233
+ if (firstNumber === secondNumber) return true;
234
+ if (absoluteDiff || firstNumber === 0 || secondNumber === 0) {
235
+ const diff = Math.abs(firstNumber - secondNumber);
236
+ return isCloseTo(diff, toleranceNumber, { relativeDiff: "1%" }) || diff < toleranceNumber;
237
+ } else return 2 * Math.abs((firstNumber - secondNumber) / (firstNumber + secondNumber)) < toleranceNumber;
238
+ }
239
+ return false;
240
+ };
241
+ /**
242
+ * Determines whether two numbers are close enough to be equal
243
+ * or checks the firstValue is greater than the secondValue
244
+ */
245
+ const isCloseToOrGreaterThan = (firstValue, secondValue, options = { relativeDiff: DEFAULT_MAX_RELATIVE_DIFF }) => {
246
+ if (firstValue === null || secondValue === null) return false;
247
+ const { firstNumber, secondNumber } = convertNumbers(firstValue, secondValue);
248
+ if (typeof firstNumber === "number" && typeof secondNumber === "number") return isCloseTo(firstNumber, secondNumber, options) || firstNumber > secondNumber;
249
+ return false;
250
+ };
251
+ /**
252
+ * Determines whether two numbers are close enough to be equal
253
+ * or checks the firstValue is less than the secondValue
254
+ */
255
+ const isCloseToOrLessThan = (firstValue, secondValue, options = { relativeDiff: DEFAULT_MAX_RELATIVE_DIFF }) => {
256
+ if (firstValue === null || secondValue === null) return false;
257
+ const { firstNumber, secondNumber } = convertNumbers(firstValue, secondValue);
258
+ if (typeof firstNumber === "number" && typeof secondNumber === "number") return isCloseTo(firstNumber, secondNumber, options) || firstNumber < secondNumber;
259
+ return false;
260
+ };
261
+ /**
262
+ * Determines whether two objects or arrays are deeply close equal (all nested child numbers)
263
+ */
264
+ const isDeepCloseTo = (a, b, options = { relativeDiff: DEFAULT_MAX_RELATIVE_DIFF }) => {
265
+ if (Array.isArray(a) && Array.isArray(b)) {
266
+ if (a.length !== b.length) return false;
267
+ return a.every((a, i) => isDeepCloseTo(a, b[i], options));
268
+ }
269
+ if (typeof a === "object" && a !== null && typeof b === "object" && b !== null) {
270
+ const aKeys = Object.keys(a);
271
+ const bKeys = Object.keys(b);
272
+ if (aKeys.length !== bKeys.length) return false;
273
+ return aKeys.every((key) => isDeepCloseTo(a[key], b[key], options));
274
+ }
275
+ if (Number.isNaN(a) && Number.isNaN(b) || a === "" && b === "") return true;
276
+ if (typeof a === "number" && typeof b === "number" || isValueWithUnit(a) && isValueWithUnit(b) || isValidNum(a) && isValidNum(b)) return isCloseTo(a, b, options);
277
+ return true;
278
+ };
279
+ //#endregion
280
+ //#region src/rounding/rounding.ts
281
+ const DEFAULT_SIGNIFICANT_DIGITS = 4;
282
+ /**
283
+ * Rounds a number to N decimal places.
284
+ *
285
+ * @private (see round() for the public interface)
286
+ * @param value
287
+ * @param [n]
288
+ * @returns rounded number
289
+ */
290
+ const roundNumber = (value, n = DEFAULT_SIGNIFICANT_DIGITS) => {
291
+ const factor = 10 ** n;
292
+ return Math.round(value * factor) / factor;
293
+ };
294
+ /**
295
+ * Rounds a numeric value to N decimal places.
296
+ *
297
+ * - accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
298
+ * - returns same type as input
299
+ *
300
+ * @param value - the value to round
301
+ * @param [n] - the number of decimal places to round to
302
+ * @returns rounded value, or input value when unable to round
303
+ *
304
+ * @example
305
+ * round(3.14159265) -> 3.1416
306
+ */
307
+ const round = (value, n = DEFAULT_SIGNIFICANT_DIGITS) => {
308
+ if (typeof value === "number") return roundNumber(value, n);
309
+ if (value === null || Number.isNaN(value) || value === Infinity || value === -Infinity || value === void 0) return value;
310
+ const { number, unit, isString } = parseNumber(value);
311
+ return unParseNumber({
312
+ value: !isNumeric(number) || typeof number === "string" && number.endsWith(".") ? value : roundNumber(number, n),
313
+ unit,
314
+ isString,
315
+ isScientific: isScientificStringNum(value)
316
+ });
317
+ };
318
+ /**
319
+ * Rounds a number to N significant digits.
320
+ *
321
+ * @private (see roundToPrecision() for the public interface)
322
+ * @param value
323
+ * @param [n] number of significant digits
324
+ * @returns rounded number
325
+ */
326
+ const roundNumberToPrecision = (value, n = DEFAULT_SIGNIFICANT_DIGITS) => {
327
+ return Number(value.toPrecision(n));
328
+ };
329
+ /**
330
+ * Rounds a number to N significant digits, preserving trailing decimal zeros
331
+ *
332
+ * @private (see roundByMagnitudeToFixed() for the public interface)
333
+ * @param value
334
+ * @param [n] number of significant digits
335
+ * @returns rounded number as string
336
+ */
337
+ const roundNumberToFixedPrecision = (value, n = DEFAULT_SIGNIFICANT_DIGITS) => {
338
+ const [integerPart, decimalPart] = toNum(value).toPrecision(n).split(".");
339
+ if (decimalPart) {
340
+ const decimalDigits = n - integerPart.length;
341
+ return `${integerPart}.${decimalPart.padEnd(decimalDigits, "0")}`;
342
+ } else return integerPart;
343
+ };
344
+ /**
345
+ * Rounds a number to N significant digits, excluding the integer part (only rounds decimal part)
346
+ *
347
+ * @private (see roundToPrecision() for the public interface)
348
+ * @param value
349
+ * @param [n] number of significant digits
350
+ * @returns rounded number
351
+ */
352
+ const roundNumberToDecimalPrecision = (value, n = DEFAULT_SIGNIFICANT_DIGITS) => {
353
+ if (Math.abs(value) > 1) {
354
+ const [integerPart, decimalPart] = formatDecimal(value, "").split(".");
355
+ if (!decimalPart) return value;
356
+ else {
357
+ const roundedDecimalPart = Number(`0.${decimalPart}`).toPrecision(n).slice(1);
358
+ return Number(integerPart + roundedDecimalPart);
359
+ }
360
+ }
361
+ return roundNumberToPrecision(value, n);
362
+ };
363
+ /**
364
+ * Rounds a numeric value to N significant digits.
365
+ *
366
+ * - accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
367
+ * - returns same type as input
368
+ * - similar to Number.toPrecision() but safer
369
+ * - does *not* append trailing zeros (unlike `Number(4).toPrecision(4)` -> '4.000')
370
+ *
371
+ * @param value - the value to round
372
+ * @param [n] - the number of significant digits
373
+ * @returns rounded value, or input value when unable to round
374
+ *
375
+ * @example
376
+ * roundToPrecision(0.0000456789) -> 0.00004568
377
+ */
378
+ const roundToPrecision = (value, n = DEFAULT_SIGNIFICANT_DIGITS) => {
379
+ if (typeof value === "number") return roundNumberToPrecision(value, n);
380
+ if (value === null || Number.isNaN(value) || value === Infinity || value === -Infinity || value === void 0) return value;
381
+ const { number, unit, isString } = parseNumber(value);
382
+ return unParseNumber({
383
+ value: !isNumeric(number) || typeof number === "string" && number.endsWith(".") ? value : roundNumberToPrecision(number, n),
384
+ unit,
385
+ isString,
386
+ isScientific: isScientificStringNum(value)
387
+ });
388
+ };
389
+ /**
390
+ * Rounds a numeric value to N significant digits (only the decimal part)
391
+ *
392
+ * - accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
393
+ * - returns same type as input
394
+ * - unlike roundToPrecision(), acts only on the decimal part, not the integer part too
395
+ *
396
+ * @param value - the value to round
397
+ * @param [n]- the number of significant digits
398
+ * @returns rounded value, or input value when unable to round
399
+ *
400
+ * @example
401
+ * roundToPrecision(1234.0000456789) -> 1234.00004568
402
+ */
403
+ const roundToDecimalPrecision = (value, n = DEFAULT_SIGNIFICANT_DIGITS) => {
404
+ if (typeof value === "number") return roundNumberToDecimalPrecision(value, n);
405
+ if (value === null || Number.isNaN(value) || value === Infinity || value === -Infinity || value === void 0) return value;
406
+ const { number, unit, isString } = parseNumber(value);
407
+ return unParseNumber({
408
+ value: !isNumeric(number) || typeof number === "string" && number.endsWith(".") ? value : roundNumberToDecimalPrecision(number, n),
409
+ unit,
410
+ isString,
411
+ isScientific: isScientificStringNum(value)
412
+ });
413
+ };
414
+ /**
415
+ * Rounds a number to an appropriate number of digits, based on its size.
416
+ *
417
+ * @private (see roundByMagnitude() for the public interface)
418
+ * @param value
419
+ * @param [n] the number of significant digits
420
+ * @param [toFixed] to fixed digits (i.e. with trailing zeros)
421
+ * @returns rounded number
422
+ */
423
+ const roundNumberByMagnitude = (value, n = DEFAULT_SIGNIFICANT_DIGITS, toFixed = false) => {
424
+ const noDecimalsAbove = 10 ** n;
425
+ const result = noDecimalsAbove && value > noDecimalsAbove ? roundNumber(value, 0) : toFixed ? roundNumberToFixedPrecision(value, n) : roundNumberToPrecision(value, n);
426
+ return toFixed ? String(result) : result;
427
+ };
428
+ /**
429
+ * Rounds a numeric value to an appropriate number of digits, based on its size. It rounds to N significant digits,
430
+ * but never rounds the integer part.
431
+ *
432
+ * - accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
433
+ * - returns same type as input
434
+ *
435
+ * @param value - the value to round
436
+ * @param [n] - the number of significant digits
437
+ * @returns rounded value, or input value when unable to round
438
+ *
439
+ * @example
440
+ * roundByMagnitude(0.000123456789) -> 0.0001235
441
+ * roundByMagnitude(1.123456789) -> 1.123
442
+ * roundByMagnitude(19999.123456789) -> 19999
443
+ */
444
+ const roundByMagnitude = (value, n = DEFAULT_SIGNIFICANT_DIGITS) => {
445
+ if (typeof value === "number") return roundNumberByMagnitude(value, n);
446
+ if (value === null || Number.isNaN(value) || value === Infinity || value === -Infinity || value === void 0) return value;
447
+ const { number, unit, isString } = parseNumber(value);
448
+ return unParseNumber({
449
+ value: !isNumeric(number) || typeof number === "string" && number.endsWith(".") ? value : roundNumberByMagnitude(number, n),
450
+ unit,
451
+ isString,
452
+ isScientific: isScientificStringNum(value)
453
+ });
454
+ };
455
+ /**
456
+ * Rounds a numeric value to an appropriate number of digits, based on its size. It rounds to N significant digits,
457
+ * but never rounds the integer part. Similar to roundByMagnitude, but adds trailing zeros.
458
+ *
459
+ * - accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
460
+ * - returns string type (or original value and type when not possible to convert)
461
+ *
462
+ * @param value - the value to round
463
+ * @param [n] - the number of significant digits
464
+ * @returns rounded value as a string, or input value when unable to round
465
+ *
466
+ * @example
467
+ * roundByMagnitudeToFixed(0.000120016789) -> 0.0001200
468
+ */
469
+ const roundByMagnitudeToFixed = (value, n = DEFAULT_SIGNIFICANT_DIGITS) => {
470
+ const toFixed = true;
471
+ if (value === null || Number.isNaN(value) || value === Infinity || value === -Infinity || value === void 0) return value;
472
+ if (typeof value === "number") return roundNumberByMagnitude(value, n, toFixed);
473
+ const { number, unit } = parseNumber(value, true);
474
+ return unParseNumber({
475
+ value: !isNumeric(number) || typeof number === "string" && number.endsWith(".") ? value : roundNumberByMagnitude(number, n, toFixed),
476
+ unit,
477
+ isString: true,
478
+ isScientific: isScientificStringNum(value)
479
+ });
480
+ };
481
+ /**
482
+ * Rounds a number to an appropriate number of digits, based on its size in relation to a range.
483
+ *
484
+ * @private (see roundByMagnitude() for the public interface)
485
+ * @param value
486
+ * @param min
487
+ * @param max
488
+ * @param [n] the minimum number of significant digits
489
+ * @returns rounded number
490
+ */
491
+ const roundNumberByRange = (value, min, max, n = DEFAULT_SIGNIFICANT_DIGITS) => {
492
+ if (isCloseToOrLessThan(max, min)) return value;
493
+ const range = max - min;
494
+ return roundNumber(value, Math.max(n, 0 - Math.floor(Math.log10(range))));
495
+ };
496
+ /**
497
+ * Rounds a numeric value to an appropriate number of digits, based on its size within a range of values.
498
+ *
499
+ * - accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
500
+ * - returns same type as input
501
+ *
502
+ * @param value - the value to round
503
+ * @param min - the min value in the range
504
+ * @param max - the max value in the range
505
+ * @param [n] - the minimum number of significant digits
506
+ * @returns rounded value, or input value when unable to round
507
+ *
508
+ */
509
+ const roundByRange = (value, min, max, n = DEFAULT_SIGNIFICANT_DIGITS) => {
510
+ if (typeof value === "number") return roundNumberByRange(value, min, max, n);
511
+ if (value === null || Number.isNaN(value) || value === Infinity || value === -Infinity || value === void 0) return value;
512
+ const { number, unit, isString } = parseNumber(value);
513
+ return unParseNumber({
514
+ value: !isNumeric(number) || typeof number === "string" && number.endsWith(".") ? value : roundNumberByRange(number, min, max, n),
515
+ unit,
516
+ isString,
517
+ isScientific: isScientificStringNum(value)
518
+ });
519
+ };
520
+ /**
521
+ * Rounds a numeric value to N fixed decimal digits.
522
+ *
523
+ * - accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
524
+ * - returns same type as input
525
+ *
526
+ * @param value - the value to round
527
+ * @param [n] - the number of fixed decimal digits
528
+ * @returns rounded value, or input value when unable to round
529
+ *
530
+ */
531
+ const roundToFixed = (value, n = DEFAULT_SIGNIFICANT_DIGITS) => {
532
+ if (value === null || Number.isNaN(value) || value === Infinity || value === -Infinity || value === void 0) return value;
533
+ if (typeof value === "number") return value.toFixed(n);
534
+ const { number, unit, isString } = parseNumber(value);
535
+ return unParseNumber({
536
+ value: !isNumeric(number) || typeof number === "string" && number.endsWith(".") ? value : number.toFixed(n),
537
+ unit,
538
+ isString,
539
+ isScientific: isScientificStringNum(value)
540
+ });
541
+ };
542
+ //#endregion
543
+ //#region src/numbers/display-number.ts
544
+ const DEFAULT_AUTO_SCIENTIFIC_BELOW = 1e-4;
545
+ const DEFAULT_AUTO_SCIENTIFIC_ABOVE = 1e7;
546
+ const superscriptSymbols = {
547
+ "0": "⁰",
548
+ "1": "¹",
549
+ "2": "²",
550
+ "3": "³",
551
+ "4": "⁴",
552
+ "5": "⁵",
553
+ "6": "⁶",
554
+ "7": "⁷",
555
+ "8": "⁸",
556
+ "9": "⁹",
557
+ "+": "⁺",
558
+ "-": "⁻"
559
+ };
560
+ const appendTrailingZeros = (value, numberOfZeros) => {
561
+ const zeros = "0".repeat(numberOfZeros);
562
+ return numberOfZeros > 0 && value !== "0" ? !value.includes(".") ? `${value}.${zeros}` : `${value}${zeros}` : value;
563
+ };
564
+ const formatDecimal = (value, thousandSeparator, preserveTrailingZeros = false) => {
565
+ const convertedValue = convertNumberToLocale(toNum(value), "en-US").replaceAll(",", thousandSeparator);
566
+ return preserveTrailingZeros ? appendTrailingZeros(convertedValue, countTrailingZeros(value, true)) : convertedValue;
567
+ };
568
+ const formatDecimalDisplayNumber = (value, options) => {
569
+ const { nonBreakingSpace } = options ?? {};
570
+ if (value === "") return value;
571
+ if (value === null || value === void 0) return "";
572
+ if (!isValidNum(value)) return trim(value.toString());
573
+ return formatDecimal(value, options?.noThousandsSeparator ? "" : nonBreakingSpace ? " " : " ", options?.preserveTrailingZeros);
574
+ };
575
+ const formatScientificDisplayNumber = (value, options) => {
576
+ const { roundScientificCoefficient, eNotation } = options ?? {};
577
+ if (Number.isNaN(value)) return "Invalid";
578
+ if (value === null || value === void 0) return "";
579
+ if (!isValidNum(value) || value === "") return trim(value.toString());
580
+ const sanitizedValue = toNum(value);
581
+ if (!Number.isFinite(sanitizedValue)) return trim(value.toString());
582
+ const power = eNotation ? "e" : "·10";
583
+ const [coefficient, exponent] = sanitizedValue.toExponential().split("e");
584
+ const roundedCoefficient = typeof roundScientificCoefficient === "number" ? round(coefficient, roundScientificCoefficient) : coefficient;
585
+ const noExponent = exponent === "+0" || exponent === "-0";
586
+ const formattedExponent = [...exponent.replaceAll("+", "")].map((c) => eNotation ? c : superscriptSymbols[c]).join("");
587
+ return noExponent ? roundedCoefficient : `${roundedCoefficient}${power}${formattedExponent}`;
588
+ };
589
+ const formatDisplayNumber = (value, options) => {
590
+ const abs = Math.abs(toNum(value));
591
+ return (options?.scientific === "auto" && options?.autoScientificBelow && options?.autoScientificAbove ? abs < options?.autoScientificBelow || abs > options?.autoScientificAbove : options?.scientific) ? formatScientificDisplayNumber(value, options) : formatDecimalDisplayNumber(value, options);
592
+ };
593
+ /**
594
+ * Displays a number with human-friendly formatting (use for non-editable display labels, text)
595
+ *
596
+ * Accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
597
+ *
598
+ * @example
599
+ * //returns '1 234.56'
600
+ * displayNumber(1234.56)
601
+ *
602
+ * By default, adds thousands separators. Can be configured to display in scientific notation, and with formatted units.
603
+ *
604
+ * @param value
605
+ * @param options
606
+ * @returns formatted display number
607
+ */
608
+ const displayNumber = (value, options) => {
609
+ const optionsWithDefaults = {
610
+ scientific: options?.scientific ?? "auto",
611
+ eNotation: options?.eNotation ?? false,
612
+ autoScientificBelow: options?.autoScientificBelow ?? DEFAULT_AUTO_SCIENTIFIC_BELOW,
613
+ autoScientificAbove: options?.autoScientificAbove ?? DEFAULT_AUTO_SCIENTIFIC_ABOVE,
614
+ withUnit: options?.withUnit ?? false,
615
+ nonBreakingSpace: options?.nonBreakingSpace ?? false,
616
+ roundScientificCoefficient: options?.roundScientificCoefficient
617
+ };
618
+ const { withUnit } = optionsWithDefaults;
619
+ if (value === null || value === void 0) return "";
620
+ const { number, unit } = parseNumber(value);
621
+ const formattedNumber = formatDisplayNumber(number, optionsWithDefaults);
622
+ const formattedUnit = unit ? LABELS?.[unit] : "";
623
+ return withUnit && unit ? formattedNumber === "" ? formattedUnit : `${formattedNumber} ${formattedUnit}` : formattedNumber;
624
+ };
625
+ /**
626
+ * Displays a number with human-friendly formatting (use for non-editable display labels, text)
627
+ *
628
+ * Accepts number types (1.234), stringified numbers ('1.234'), and unit numbers ('1.234|m')
629
+ *
630
+ * @example
631
+ * //returns '1 234.5600'
632
+ * displayNumberToFixed('1234.5600')
633
+ *
634
+ * By default, adds thousands separators. Can be configured to display in scientific notation, and with formatted units.
635
+ *
636
+ * @param value
637
+ * @param options
638
+ * @returns formatted display number
639
+ */
640
+ const displayNumberToFixed = (value, options) => {
641
+ const optionsWithDefaults = {
642
+ scientific: options?.scientific ?? "auto",
643
+ eNotation: options?.eNotation ?? false,
644
+ autoScientificBelow: options?.autoScientificBelow ?? DEFAULT_AUTO_SCIENTIFIC_BELOW,
645
+ autoScientificAbove: options?.autoScientificAbove ?? DEFAULT_AUTO_SCIENTIFIC_ABOVE,
646
+ withUnit: options?.withUnit ?? false,
647
+ nonBreakingSpace: options?.nonBreakingSpace ?? false,
648
+ roundScientificCoefficient: options?.roundScientificCoefficient
649
+ };
650
+ const { withUnit } = optionsWithDefaults;
651
+ if (value === null || value === void 0) return "";
652
+ const { number, unit } = parseNumber(value, true);
653
+ const formattedNumber = formatDisplayNumber(number, {
654
+ ...optionsWithDefaults,
655
+ preserveTrailingZeros: true
656
+ });
657
+ const formattedUnit = unit ? LABELS?.[unit] : "";
658
+ return withUnit && unit ? formattedNumber === "" ? formattedUnit : `${formattedNumber} ${formattedUnit}` : formattedNumber;
659
+ };
660
+ //#endregion
661
+ //#region src/utils.ts
662
+ const isNull = (str) => str === null;
663
+ const isUndefined = (str) => str === void 0;
664
+ const isArray = (str) => str && str.constructor === Array;
665
+ const isObject = (str) => str && str.constructor === Object;
666
+ const isEmptyString = (str) => str === "";
667
+ const isTrailingPeriodSeparator = (str) => str && str[str.length - 1] === ".";
668
+ const isTrailingCommaSeparator = (str) => str && str[str.length - 1] === ",";
669
+ const isPercentage = (value) => typeof value === "string" && /^\d+(\.\d+)?%$/.test(value);
670
+ /**
671
+ * Checks if input is a string that starts with '|', e.g. '|m' or '|in'
672
+ *
673
+ * @param val - string or number for checking
674
+ * @returns true if input starts with '|', e.g. '|m' or '|in'
675
+ */
676
+ function isEmptyValueWithUnit(val) {
677
+ return typeof val === "string" && val.length > 0 && val.startsWith("|");
678
+ }
679
+ const trimWhiteSpace = (value) => value.trim().replace(/\s+/g, " ");
680
+ /**
681
+ * Check if provided argument is number
682
+ * @param v - value for checking
683
+ * @returns true if valid number
684
+ */
685
+ /**
686
+ * Checks if a value can be parsed as a valid fraction (uses fraction.js)
687
+ *
688
+ * @param value - The value to check.
689
+ * @returns True if the value is a valid fraction, false otherwise.
690
+ */
691
+ const isFraction = (value) => {
692
+ if (typeof value !== "string") return false;
693
+ if (!value.includes("/")) return false;
694
+ try {
695
+ new fraction_js.default(trimWhiteSpace(value));
696
+ return true;
697
+ } catch (error) {
698
+ return error.message === "Division by Zero";
699
+ }
700
+ };
701
+ function isNumeric(v) {
702
+ if (v === void 0 || v === null || Array.isArray(v) || typeof v === "object" || Number.isNaN(v) || v === "NaN" || v === Infinity || v === -Infinity || v === "Infinity" || v === "-Infinity") return false;
703
+ if (isFraction(v)) return true;
704
+ return typeof v === "string" ? !isNaN(parseFloat(v)) && (EXP_NOTATION_RE.test(v) || isFinite(v)) : isFinite(v);
705
+ }
706
+ /**
707
+ * Check array values if all are numbers
708
+ * @param arr - array of items
709
+ * @returns true if all array items are numbers
710
+ */
711
+ function allNumbers(arr) {
712
+ return !arr.some((val) => typeof val !== "number");
713
+ }
714
+ /**
715
+ * Outputs a human-friendly formatted number for UI display (with thousands separators)
716
+ *
717
+ * @deprecated use displayNumber instead
718
+ * @param number - anything for converting to pretty format
719
+ * @returns string with formatted display number
720
+ */
721
+ const formatNumber = (number) => displayNumber(number);
722
+ /**
723
+ * Counts all occurence of set character
724
+ * From http://stackoverflow.com/questions/4009756/how-to-count-string-occurrence-in-string
725
+ * @param chr - character that will be counted in string
726
+ * @param str - string in which the character will be counted
727
+ * @returns number of character occurencies
728
+ */
729
+ function charCount(chr, str) {
730
+ const single_char = (chr + "")[0];
731
+ let total = 0;
732
+ let last_location = str.indexOf(single_char, 0) + 1;
733
+ while (last_location > 0) {
734
+ last_location = str.indexOf(single_char, last_location) + 1;
735
+ total += 1;
736
+ }
737
+ return total;
738
+ }
739
+ /**
740
+ * Calculates the number of digits to be rounded off, typically for values less than 1
741
+ * E.g. when trying to format 1e-9 by roundNumber(), the output value will only show '0'
742
+ * if just rounded off with 4 digits from roundNumber(val)
743
+ * Then it is more useful to calculate the number of digits to be rounded off, and pass this in,
744
+ * i.e. roundNumber(val, getNumberOfDigitsToShow(val))
745
+ * which will return 0.0000000001.
746
+ * Probably a lot of room for improvement here...
747
+ *
748
+ * @deprecated Use roundByMagnitude or other units package rounding functions instead
749
+ * @param num - number for caculating digits
750
+ * @param maxNumDigits - optional limiter of digits number, by default 20
751
+ * @returns number of digits that will be shown for defined number
752
+ */
753
+ function getNumberOfDigitsToShow(num, maxNumDigits = 20) {
754
+ const defaultDigits = Math.min(4, maxNumDigits);
755
+ let digits = defaultDigits;
756
+ if (typeof num !== "number") return defaultDigits;
757
+ const numStr = String(num);
758
+ if (/-?[0-9.,]*[Ee]-?[0-9]+/.test(numStr)) {
759
+ while (Math.abs(num) * 10 ** digits < 1 && digits < maxNumDigits) digits++;
760
+ return Math.min(digits + (defaultDigits - 1), maxNumDigits);
761
+ }
762
+ if (num > 1 || num < -1) return defaultDigits;
763
+ for (let i = 2; i < numStr.length; i++) if (numStr[i] !== "0") return Math.min(maxNumDigits, digits + i - 2);
764
+ return digits;
765
+ }
766
+ /**
767
+ * Convert set fraction to decimal value
768
+ * @param str - fraction to be converted
769
+ * @returns either number in decimal format, Infinity if fraction is divided by 0 or NaN in other cases
770
+ */
771
+ function fraction(str) {
772
+ if (str instanceof Array || str === null || str === void 0) return NaN;
773
+ if (typeof str === "string") str = trimWhiteSpace(str);
774
+ if (str === "") return NaN;
775
+ let result = NaN;
776
+ let infinite = false;
777
+ try {
778
+ const fractionObject = new fraction_js.default(str);
779
+ if (fractionObject !== void 0) result = fractionObject.valueOf();
780
+ } catch (e) {
781
+ if (e instanceof Error && e.message === "Division by Zero") infinite = true;
782
+ }
783
+ return infinite ? Infinity : result;
784
+ }
785
+ /**
786
+ * Converts decimal number to fractional format
787
+ * @param str - value to be converted
788
+ * @returns string with fractional format of set value
789
+ */
790
+ function asFraction(str) {
791
+ if (typeof str === "string") str = trimWhiteSpace(str);
792
+ if (str === "") str = "0";
793
+ return new fraction_js.default(str).toFraction(true);
794
+ }
795
+ /**
796
+ * Convert fraction string to number (return input value if conversion fails)
797
+ * For historical reasons, numFraction returns the string value
798
+ * unmodified if it is not able to convert to a number. This is
799
+ * useful where user inputs are filtered through calls to
800
+ * numFraction. For "detecting" when numFraction fails, check
801
+ * if the return value is a string or a number. If it is a string
802
+ * it means number conversion failed.
803
+ *
804
+ * @param str - fraction to be converted
805
+ * @returns string or number with decimal format of fraction
806
+ */
807
+ function numFraction(str) {
808
+ if (str instanceof Array || str === null || str === void 0 || str === "" || str === Infinity || str === -Infinity || str === "Infinity" || str === "-Infinity" || Number.isNaN(str) || str === "NaN") return str;
809
+ if (typeof str === "string") str = trimWhiteSpace(str);
810
+ let result = str;
811
+ try {
812
+ const fractionObject = new fraction_js.default(str);
813
+ if (fractionObject !== void 0) result = fractionObject.valueOf();
814
+ } catch (error) {
815
+ if (error.message === "Division by Zero") return str.charAt(0) === "-" ? -Infinity : Infinity;
816
+ console.warn("Error in numFraction() method: ", str);
817
+ }
818
+ return result.valueOf();
819
+ }
820
+ /**
821
+ * Basic trimming of string values to remove leading and trailing spaces, tabs, newlines
822
+ * @param value
823
+ * @returns trimmed string
824
+ */
825
+ const trim = (value) => value.trim().replace(/[\t\r\n]/g, "");
826
+ /**
827
+ * Cleaning up and fixing provided number to correct numerical format
828
+ * removing redundant '.' dots, ',' commas, spaces
829
+ * @param str - string for cleaning up
830
+ * @returns cleaned/formatted string
831
+ */
832
+ function cleanNumStr(str) {
833
+ let cleanString = trim(str + "");
834
+ const slashCount = charCount("/", cleanString);
835
+ const spaceCount = charCount(" ", cleanString) + charCount("\xA0", cleanString);
836
+ let dotcount = charCount(".", cleanString);
837
+ let commacount = charCount(",", cleanString);
838
+ if (slashCount === 0 && spaceCount > 0) cleanString = cleanString.replace(/\s/g, "");
839
+ if (commacount > 1) cleanString = cleanString.replace(/,/g, "");
840
+ if (dotcount > 1) cleanString = cleanString.replace(/\./g, "");
841
+ commacount = charCount(",", cleanString);
842
+ dotcount = charCount(".", cleanString);
843
+ if (dotcount === 1 && commacount === 1) {
844
+ if (cleanString.indexOf(",") > cleanString.indexOf(".")) {
845
+ cleanString = cleanString.replace(".", "");
846
+ cleanString = cleanString.replace(",", ".");
847
+ } else cleanString = cleanString.replace(",", "");
848
+ if (cleanString.indexOf(".") === 0) cleanString = 0 + cleanString;
849
+ return cleanString;
850
+ }
851
+ if (!dotcount && commacount) cleanString = cleanString.replace(",", ".");
852
+ if (cleanString.indexOf(".") === 0) cleanString = 0 + cleanString;
853
+ return cleanString;
854
+ }
855
+ const stripLeadingZeros = (value) => {
856
+ const isMinus = value?.[0] === "-";
857
+ const cleanedValue = value.replace(/^-/gm, "").replace(/^(?:0+(?=[1-9])|0+(?=0))/gm, "");
858
+ return isMinus ? `-${cleanedValue}` : cleanedValue;
859
+ };
860
+ /**
861
+ * Cleaning and fixing numerical string but returns it as number
862
+ * @param str - string for cleaning up
863
+ * @returns number after cleanup and fixing
864
+ */
865
+ function cleanNum(str) {
866
+ if (typeof str === "number") return str;
867
+ return parseFloat(cleanNumStr(str));
868
+ }
869
+ /**
870
+ * Check if value is non-numerical
871
+ *
872
+ * @param value
873
+ * @return boolean
874
+ */
875
+ const isNonNumerical = (value) => !isNumeric(value);
876
+ const { abs, exp, sqrt } = Math;
877
+ /**
878
+ * The 1D iterative Newton's method
879
+ *
880
+ * @param f
881
+ * @param df
882
+ * @param x0
883
+ * @param tol
884
+ * @param max_iter
885
+ */
886
+ function newton(f, df, x0, tol = 1e-8, max_iter = 30) {
887
+ let X = x0;
888
+ let iter = 0;
889
+ let err = 1;
890
+ while (err > tol && iter < max_iter) {
891
+ const X_new = X - f(X) / df(X);
892
+ err = abs(f(X_new) - f(X));
893
+ if (err < tol) return [
894
+ X_new,
895
+ true,
896
+ iter
897
+ ];
898
+ else X = X_new;
899
+ iter++;
900
+ }
901
+ return [
902
+ x0,
903
+ false,
904
+ iter
905
+ ];
906
+ }
907
+ /**
908
+ * Approximating the error function erf
909
+ *
910
+ * @param z
911
+ */
912
+ function erf(z) {
913
+ const t = 1 / (1 + .5 * abs(z));
914
+ const ans = 1 - t * exp(-(z ** 2) - 1.26551223 + t * (1.00002368 + t * (.37409196 + t * (.09678418 + t * (-.18628806 + t * (.27886807 + t * (-1.13520398 + t * (1.48851587 + t * (-.82215223 + t * .17087277)))))))));
915
+ return z >= 0 ? ans : -ans;
916
+ }
917
+ /**
918
+ * Convert from confidence interval to number of standard deviations
919
+ *
920
+ * @param a
921
+ */
922
+ function get_k_from_conf_int(a) {
923
+ const f = (k) => a - erf(k / sqrt(2));
924
+ const df = (k) => -sqrt(2 / Math.PI) * exp(-.5 * k ** 2);
925
+ const [t0] = newton(f, df, 1);
926
+ return t0;
927
+ }
928
+ /**
929
+ * Convert from number of standard deviations to confidence interval
930
+ *
931
+ * @param k
932
+ */
933
+ function get_conf_int_from_k(k) {
934
+ return erf(k / sqrt(2));
935
+ }
936
+ const normalizeExponent = (input) => {
937
+ return input.replace(/^([+-]?(?:\d+\.?\d*|\.\d+))[ ]*[eE][ ]*([+-]?[ ]*\d+)/, (_m, mantissa, exp) => {
938
+ let m = mantissa.endsWith(".") ? mantissa.slice(0, -1) : mantissa;
939
+ if (m.startsWith(".")) m = "0" + m;
940
+ const e = exp.replace(/[ ]+/g, "");
941
+ return `${m}e${e}`;
942
+ });
943
+ };
944
+ function normalizeScientific(val) {
945
+ if (typeof val !== "string") return val;
946
+ let s = val.replace(/\u00A0|\u2007|\u202F/g, " ").trim();
947
+ if (isValueWithUnit(s)) {
948
+ const [val, unit] = split(s);
949
+ return `${normalizeExponent(val.trim())}|${unit.trim()}`;
950
+ }
951
+ const m = s.match(/^([+-]?(?:\d+(?:\.\d*)?|\.\d+)\s*[eE]\s*[+-]?\s*\d+)\s+(.+)$/);
952
+ if (m) return `${normalizeExponent(m[1])}|${m[2].trim()}`;
953
+ return normalizeExponent(s);
954
+ }
955
+ //#endregion
956
+ //#region src/constants.ts
957
+ /**
958
+ * Units labels
959
+ *
960
+ * @readonly
961
+ * @enum {Object}
962
+ */
963
+ const LABELS = Object.freeze({
964
+ in: "in",
965
+ mm: "mm",
966
+ cm: "cm",
967
+ m: "m",
968
+ microM: "μm",
969
+ km: "km",
970
+ ft: "ft",
971
+ usft: "usft",
972
+ in2: "in²",
973
+ cm2: "cm²",
974
+ m2: "m²",
975
+ kg: "kg",
976
+ tonnes: "t",
977
+ mt: "mt",
978
+ kip: "kip",
979
+ bbl: "bbl",
980
+ m3: "m³",
981
+ Mm3: "Mm³",
982
+ MMSCF: "MMSCF",
983
+ lbm: "lbm",
984
+ "kg/mol": "kg/mol",
985
+ "lbf/mol": "lbf/mol",
986
+ sg: "sg",
987
+ ppg: "ppg",
988
+ "kg/m3": "kg/m³",
989
+ "lbm/ft3": "lbm/ft³",
990
+ s: "s",
991
+ min: "min",
992
+ h: "h",
993
+ d: "d",
994
+ month: "month",
995
+ year: "year",
996
+ "bbl/ft": "bbl/ft",
997
+ lpm: "L/min",
998
+ lps: "L/s",
999
+ bpm: "bbl/min",
1000
+ "m3/min": "m³/min",
1001
+ "m3/s": "m³/s",
1002
+ MMSCFD: "MMSCFD",
1003
+ bar: "Bar",
1004
+ Pa: "Pa",
1005
+ kPa: "kPa",
1006
+ MPa: "MPa",
1007
+ GPa: "GPa",
1008
+ kPsi: "Psi",
1009
+ ksi: "ksi",
1010
+ "lbf/100ft2": "lbf/100ft²",
1011
+ "1/Pa": "Pa⁻¹",
1012
+ "1/kPa": "kPa⁻¹",
1013
+ "1/MPa": "MPa⁻¹",
1014
+ "1/GPa": "GPa⁻¹",
1015
+ "1/psi": "psi⁻¹",
1016
+ "kPa/m": "kPa/m",
1017
+ "1/bar": "bar⁻¹",
1018
+ klbf: "klbf",
1019
+ "psi/ft": "Psi/ft",
1020
+ "bar/100m": "bar/100m",
1021
+ "psi/100ft": "psi/100ft",
1022
+ "kPa/100m": "kPa/100m",
1023
+ C: "°C",
1024
+ F: "°F",
1025
+ K: "K",
1026
+ "C/100m": "°C/100m",
1027
+ "C/m": "°C/m",
1028
+ "Pa/C": "Pa/°C",
1029
+ "Bar/C": "Bar/°C",
1030
+ "psi/F": "psi/°F",
1031
+ "psi/C": "psi/°C",
1032
+ "F/100ft": "°F/100ft",
1033
+ "F/ft": "°F/ft",
1034
+ "K/100m": "K/100m",
1035
+ "K/m": "K/m",
1036
+ "lbf/ft": "lbf/ft",
1037
+ N: "N",
1038
+ kN: "kN",
1039
+ "N/m": "N/m",
1040
+ "daN/m": "daN/m",
1041
+ lbf: "lbf",
1042
+ kgf: "kgf",
1043
+ rad: "rad",
1044
+ "BTU/lbm": "BTU/lbm",
1045
+ ppf: "ppf",
1046
+ "kg/m": "kg/m",
1047
+ "E-06/degC": "10⁻⁶/°C",
1048
+ "E-06/degF": "10⁻⁶/°F",
1049
+ "1/K": "K⁻¹",
1050
+ km2: "km²",
1051
+ ft2: "ft²",
1052
+ mm2: "mm²",
1053
+ mile2: "mile²",
1054
+ ft3: "ft³",
1055
+ "g/cm3": "g/cm³",
1056
+ Sm3: "Sm³",
1057
+ "ft3/s": "ft³/s",
1058
+ "ft3/d": "ft³/d",
1059
+ "m3/d": "m³/d",
1060
+ "1/m3/d": "1/m³/d",
1061
+ "s/m3": "s/m³",
1062
+ "1/MMSCFD": "1/MMSCFD",
1063
+ "bbl/d": "bbl/d",
1064
+ tonneForce: "tonne-force",
1065
+ USGal: "US gal",
1066
+ "g/mol": "g/mol",
1067
+ Nm: "N⋅m",
1068
+ kNm: "kN⋅m",
1069
+ ftlbf: "ft⋅lbf",
1070
+ "J/(kg*degC)": "J/(kg⋅°C)",
1071
+ "J/(kg*degK)": "J/(kg⋅K)",
1072
+ "J/(s*m*degK)": "J/(s⋅m⋅K)",
1073
+ "BTU/(lbm*degF)": "BTU/(lbm⋅°F)",
1074
+ "BTU/(h*ft*degF)": "BTU/(h⋅ft⋅°F)",
1075
+ l: "L",
1076
+ "l/m": "L/m",
1077
+ "kJ/kg": "kJ/kg",
1078
+ "J/kg": "J/kg",
1079
+ deg: "°",
1080
+ "W/(mK)": "W/(m⋅K)",
1081
+ psi: "psi",
1082
+ "deg/100ft": "°/100ft",
1083
+ "deg/30m": "°/30m",
1084
+ "deg/10m": "°/10m",
1085
+ "%": "%",
1086
+ Hz: "Hz",
1087
+ "1/s": "1/s",
1088
+ rpm: "rpm",
1089
+ "Pa/m": "Pa/m",
1090
+ "bar/m": "bar/m",
1091
+ gpm: "gpm",
1092
+ "kg/s": "kg/s",
1093
+ "lbm/s": "lbm/s",
1094
+ "tonnes/h": "tonnes/h",
1095
+ "tons/h": "tons/h",
1096
+ "deg/m": "°/m",
1097
+ "deg/ft": "°/ft",
1098
+ "rad/m": "rad/m",
1099
+ "rad/ft": "rad/ft",
1100
+ "dyn/cm": "dyn/cm",
1101
+ "mN/m": "mN/m",
1102
+ "m/s": "m/s",
1103
+ "ft/s": "ft/s",
1104
+ "m/min": "m/min",
1105
+ "ft/min": "ft/min",
1106
+ "m/h": "m/h",
1107
+ "ft/h": "ft/h",
1108
+ mph: "mph",
1109
+ "km/h": "km/h",
1110
+ "m/s2": "m/s²",
1111
+ Gs: "Gs",
1112
+ nT: "nT",
1113
+ g: "g",
1114
+ "ft/s2": "ft/s²",
1115
+ "Pa*s": "Pa⋅s",
1116
+ P: "P",
1117
+ "mPa*s": "mPa⋅s",
1118
+ cP: "cP",
1119
+ W: "W",
1120
+ hhp: "hhp",
1121
+ hp: "hp",
1122
+ kW: "kW",
1123
+ MW: "MW",
1124
+ "BTU/h": "BTU/h",
1125
+ "W/m2": "W/m²",
1126
+ "hhp/in2": "hhp/in²",
1127
+ "hhp/ft2": "hhp/ft²",
1128
+ "Mm3/d": "Mm³/d",
1129
+ "STB/d": "STB/d",
1130
+ "Sm3/d": "Sm³/d",
1131
+ "Sm3/min": "Sm³/min",
1132
+ "MSm3/d": "MSm³/d",
1133
+ "SCF/STB": "SCF / STB",
1134
+ "Sm3/Sm3": "Sm³ / Sm³",
1135
+ "SCF/d": "SCF/d",
1136
+ STB: "STB",
1137
+ SCF: "SCF",
1138
+ MSm3: "MSm³",
1139
+ Gsg: "sg",
1140
+ Gppg: "ppg",
1141
+ "Gkg/m3": "kg/m³",
1142
+ "Glbm/ft3": "lbm/ft³",
1143
+ "lb/ft3": "lb/ft³",
1144
+ "°N": "°N",
1145
+ "°S": "°S",
1146
+ "°W": "°W",
1147
+ "°E": "°E",
1148
+ fr: " ",
1149
+ mD: "mD",
1150
+ CI: "CI",
1151
+ Sigma: "σ",
1152
+ "Sm3/d/bar": "Sm³/d/bar",
1153
+ "STB/d/psi": "STB/d/psi",
1154
+ "m3/s/bar": "m³/s/bar",
1155
+ "lb/ft": "lb/ft",
1156
+ "E-09/bar": "10⁻⁹/bar",
1157
+ "E-10/psi": "10⁻¹⁰/psi",
1158
+ "E-14/pa": "10⁻¹⁴/pa",
1159
+ "m3/m": " m³/m",
1160
+ "cm3/m": "cm³/m",
1161
+ "mm3/m": "mm³/m",
1162
+ "ft3/ft": "ft³/ft",
1163
+ "in3/ft": "in³/ft",
1164
+ lk: "lk",
1165
+ ftCla: "ftCla",
1166
+ lkCla: "lkCla",
1167
+ ftSe: "ftSe",
1168
+ ydSe: "ydSe",
1169
+ chSe: "chSe",
1170
+ "chSe(T)": "chSe(T)",
1171
+ ftGC: "ftGC",
1172
+ ydInd: "ydInd",
1173
+ "d/stand": "d/stand",
1174
+ "h/stand": "h/stand",
1175
+ "min/stand": "min/stand",
1176
+ "s/stand": "s/stand",
1177
+ "m3/t": "m3/t",
1178
+ "L/100kg": "L/100kg"
1179
+ });
1180
+ /**
1181
+ * Alternative units grouped by quantity
1182
+ *
1183
+ * @readonly
1184
+ * @enum {Object}
1185
+ */
1186
+ const ALT_UNITS = Object.freeze({
1187
+ acceleration: ["ft/s2", "m/s2"],
1188
+ angleGradient: [
1189
+ "deg/30m",
1190
+ "rad/m",
1191
+ "deg/m",
1192
+ "deg/ft",
1193
+ "rad/ft",
1194
+ "deg/100ft",
1195
+ "deg/10m"
1196
+ ],
1197
+ angles: ["deg", "rad"],
1198
+ areaOther: [
1199
+ "in2",
1200
+ "ft2",
1201
+ "mm2",
1202
+ "cm2",
1203
+ "m2",
1204
+ "mile2",
1205
+ "km2"
1206
+ ],
1207
+ areaTubular: [
1208
+ "in2",
1209
+ "cm2",
1210
+ "ft2",
1211
+ "m2"
1212
+ ],
1213
+ blowoutFlowRate: [
1214
+ "lpm",
1215
+ "bpm",
1216
+ "m3/min",
1217
+ "ft3/s",
1218
+ "m3/s",
1219
+ "MMSCFD",
1220
+ "ft3/d",
1221
+ "m3/d",
1222
+ "bbl/d",
1223
+ "Mm3/d",
1224
+ "STB/d",
1225
+ "Sm3/d",
1226
+ "Sm3/min",
1227
+ "MSm3/d",
1228
+ "SCF/d"
1229
+ ],
1230
+ blowoutGasFlowRate: [
1231
+ "MMSCFD",
1232
+ "Sm3/d",
1233
+ "MSm3/d",
1234
+ "SCF/d"
1235
+ ],
1236
+ blowoutOilFlowRate: [
1237
+ "Sm3/d",
1238
+ "Sm3/min",
1239
+ "STB/d"
1240
+ ],
1241
+ deg: ["deg", "rad"],
1242
+ density: [
1243
+ "sg",
1244
+ "ppg",
1245
+ "kg/m3",
1246
+ "lbm/ft3",
1247
+ "g/cm3",
1248
+ "lb/ft3",
1249
+ "kPa/m"
1250
+ ],
1251
+ densityGas: [
1252
+ "Gsg",
1253
+ "Gppg",
1254
+ "Gkg/m3",
1255
+ "Glbm/ft3"
1256
+ ],
1257
+ densityOil: [
1258
+ "sg",
1259
+ "ppg",
1260
+ "kg/m3",
1261
+ "lbm/ft3"
1262
+ ],
1263
+ densityOilGas: [
1264
+ "ppg",
1265
+ "kg/m3",
1266
+ "lbm/ft3"
1267
+ ],
1268
+ densitySolid: [
1269
+ "sg",
1270
+ "ppg",
1271
+ "kg/m3",
1272
+ "lbm/ft3"
1273
+ ],
1274
+ depth: ["m", "ft"],
1275
+ diameters: [
1276
+ "in",
1277
+ "m",
1278
+ "cm",
1279
+ "ft",
1280
+ "mm"
1281
+ ],
1282
+ distance: ["m", "ft"],
1283
+ dls: [
1284
+ "deg/10m",
1285
+ "deg/30m",
1286
+ "deg/100ft"
1287
+ ],
1288
+ doglegSeverity: [
1289
+ "deg/10m",
1290
+ "deg/30m",
1291
+ "deg/100ft"
1292
+ ],
1293
+ duration: [
1294
+ "s",
1295
+ "h",
1296
+ "d",
1297
+ "min"
1298
+ ],
1299
+ durationShort: [
1300
+ "s",
1301
+ "min",
1302
+ "h",
1303
+ "d"
1304
+ ],
1305
+ durationLong: [
1306
+ "min",
1307
+ "h",
1308
+ "d",
1309
+ "month",
1310
+ "year"
1311
+ ],
1312
+ flowrate: [
1313
+ "lpm",
1314
+ "gpm",
1315
+ "bpm",
1316
+ "ft3/d",
1317
+ "ft3/s",
1318
+ "m3/s",
1319
+ "m3/d",
1320
+ "m3/min",
1321
+ "Mm3/d",
1322
+ "bbl/d",
1323
+ "MMSCFD",
1324
+ "STB/d",
1325
+ "Sm3/d",
1326
+ "Sm3/min",
1327
+ "MSm3/d",
1328
+ "SCF/d"
1329
+ ],
1330
+ fluidCompressibility: [
1331
+ "1/bar",
1332
+ "1/psi",
1333
+ "1/Pa",
1334
+ "1/kPa",
1335
+ "1/MPa",
1336
+ "1/GPa"
1337
+ ],
1338
+ force: [
1339
+ "tonnes",
1340
+ "lbf",
1341
+ "kgf",
1342
+ "N",
1343
+ "kN",
1344
+ "tonneForce",
1345
+ "klbf"
1346
+ ],
1347
+ forceGradient: ["lbf/ft", "N/m"],
1348
+ frequency: ["Hz"],
1349
+ gasVolume: [
1350
+ "MMSCF",
1351
+ "Sm3",
1352
+ "MSm3",
1353
+ "SCF"
1354
+ ],
1355
+ gor: ["Sm3/Sm3", "SCF/STB"],
1356
+ height: ["m", "ft"],
1357
+ intensity: [
1358
+ "W/m2",
1359
+ "hhp/in2",
1360
+ "hhp/ft2"
1361
+ ],
1362
+ interfacialTension: [
1363
+ "dyn/cm",
1364
+ "N/m",
1365
+ "lbf/ft",
1366
+ "mN/m"
1367
+ ],
1368
+ latitude: ["°N", "°S"],
1369
+ length: [
1370
+ "m",
1371
+ "cm",
1372
+ "ft",
1373
+ "km",
1374
+ "in",
1375
+ "mm"
1376
+ ],
1377
+ linearCapacity: ["l/m", "bbl/ft"],
1378
+ longitude: ["°E", "°W"],
1379
+ massFlowRate: [
1380
+ "kg/s",
1381
+ "lbm/s",
1382
+ "tonnes/h",
1383
+ "tons/h"
1384
+ ],
1385
+ moleWeight: [
1386
+ "kg/mol",
1387
+ "lbf/mol",
1388
+ "g/mol"
1389
+ ],
1390
+ oilVolume: ["STB", "Sm3"],
1391
+ percentage: ["%", "fr"],
1392
+ permeability: ["mD", "m2"],
1393
+ power: [
1394
+ "hp",
1395
+ "W",
1396
+ "hhp",
1397
+ "MW",
1398
+ "kW",
1399
+ "BTU/h"
1400
+ ],
1401
+ pressure: [
1402
+ "bar",
1403
+ "psi",
1404
+ "Pa",
1405
+ "kPa",
1406
+ "MPa",
1407
+ "ksi",
1408
+ "GPa",
1409
+ "lbf/100ft2"
1410
+ ],
1411
+ pressureGradient: [
1412
+ "bar/100m",
1413
+ "Pa/m",
1414
+ "bar/m",
1415
+ "psi/100ft",
1416
+ "psi/ft",
1417
+ "kPa/m"
1418
+ ],
1419
+ pressurechange: [
1420
+ "bar",
1421
+ "psi",
1422
+ "Pa",
1423
+ "MPa",
1424
+ "kPa"
1425
+ ],
1426
+ gasliftFlowRate: [
1427
+ "STB/d",
1428
+ "Sm3/d",
1429
+ "SCF/d"
1430
+ ],
1431
+ productionFlowRate: [
1432
+ "MMSCFD",
1433
+ "STB/d",
1434
+ "Sm3/d",
1435
+ "Sm3/min",
1436
+ "MSm3/d",
1437
+ "SCF/d"
1438
+ ],
1439
+ productionFlowRateOil: [
1440
+ "MMSCFD",
1441
+ "STB/d",
1442
+ "Sm3/d",
1443
+ "Sm3/min",
1444
+ "MSm3/d",
1445
+ "SCF/d"
1446
+ ],
1447
+ productionFlowRateGas: [
1448
+ "MMSCFD",
1449
+ "STB/d",
1450
+ "Sm3/d",
1451
+ "MSm3/d",
1452
+ "SCF/d"
1453
+ ],
1454
+ injectionFlowRate: [
1455
+ "lpm",
1456
+ "lps",
1457
+ "bpm",
1458
+ "gpm",
1459
+ "MMSCFD",
1460
+ "STB/d",
1461
+ "Sm3/d",
1462
+ "Sm3/min",
1463
+ "MSm3/d",
1464
+ "SCF/d"
1465
+ ],
1466
+ pumpRate: [
1467
+ "lpm",
1468
+ "lps",
1469
+ "bpm",
1470
+ "m3/s",
1471
+ "Sm3/min",
1472
+ "ft3/s",
1473
+ "gpm"
1474
+ ],
1475
+ rotationalSpeed: ["rpm", "Hz"],
1476
+ roughness: [
1477
+ "m",
1478
+ "microM",
1479
+ "in"
1480
+ ],
1481
+ rpm: ["rpm", "Hz"],
1482
+ sdstats: ["CI", "Sigma"],
1483
+ specificHeatCapacity: [
1484
+ "J/(kg*degC)",
1485
+ "J/(kg*degK)",
1486
+ "BTU/(lbm*degF)"
1487
+ ],
1488
+ speed: [
1489
+ "km/h",
1490
+ "ft/min",
1491
+ "mph",
1492
+ "ft/h",
1493
+ "ft/s",
1494
+ "m/min",
1495
+ "m/s",
1496
+ "m/h"
1497
+ ],
1498
+ inverseStandSpeed: [
1499
+ "d/stand",
1500
+ "h/stand",
1501
+ "min/stand",
1502
+ "s/stand"
1503
+ ],
1504
+ rop: [
1505
+ "ft/h",
1506
+ "ft/min",
1507
+ "ft/s",
1508
+ "km/h",
1509
+ "m/h",
1510
+ "m/min",
1511
+ "m/s",
1512
+ "mph"
1513
+ ],
1514
+ stress: [
1515
+ "MPa",
1516
+ "kPa",
1517
+ "psi",
1518
+ "bar",
1519
+ "Pa",
1520
+ "ksi",
1521
+ "lbf/100ft2"
1522
+ ],
1523
+ temperature: [
1524
+ "C",
1525
+ "F",
1526
+ "K"
1527
+ ],
1528
+ pressurePerTemperature: [
1529
+ "Pa/C",
1530
+ "Bar/C",
1531
+ "psi/F",
1532
+ "psi/C"
1533
+ ],
1534
+ tempgrad: [
1535
+ "C/100m",
1536
+ "F/100ft",
1537
+ "K/100m",
1538
+ "C/m",
1539
+ "F/ft",
1540
+ "K/m"
1541
+ ],
1542
+ thermalConductivity: ["BTU/(h*ft*degF)", "W/(mK)"],
1543
+ thermalExpansionCoefficient: [
1544
+ "E-06/degC",
1545
+ "E-06/degF",
1546
+ "1/K"
1547
+ ],
1548
+ torque: [
1549
+ "Nm",
1550
+ "ftlbf",
1551
+ "kNm"
1552
+ ],
1553
+ torqueGradient: [
1554
+ "N",
1555
+ "lbf",
1556
+ "tonnes"
1557
+ ],
1558
+ turbulentSkin: [
1559
+ "s/m3",
1560
+ "1/m3/d",
1561
+ "1/MMSCFD"
1562
+ ],
1563
+ viscosity: [
1564
+ "Pa*s",
1565
+ "P",
1566
+ "mPa*s",
1567
+ "cP"
1568
+ ],
1569
+ inflowProductivityIndex: [
1570
+ "Sm3/d/bar",
1571
+ "STB/d/psi",
1572
+ "m3/s/bar"
1573
+ ],
1574
+ volume: [
1575
+ "m3",
1576
+ "bbl",
1577
+ "Mm3",
1578
+ "l",
1579
+ "USGal",
1580
+ "ft3",
1581
+ "STB",
1582
+ "Sm3",
1583
+ "MMSCF",
1584
+ "MSm3",
1585
+ "SCF"
1586
+ ],
1587
+ kickToleranceVolume: [
1588
+ "m3",
1589
+ "bbl",
1590
+ "USGal",
1591
+ "ft3",
1592
+ "STB",
1593
+ "Sm3",
1594
+ "SCF"
1595
+ ],
1596
+ weight: [
1597
+ "tonnes",
1598
+ "kg",
1599
+ "lbf",
1600
+ "mt",
1601
+ "kip",
1602
+ "N"
1603
+ ],
1604
+ weightGradient: ["ppf", "kg/m"],
1605
+ wgrad: ["sg", "ppg"],
1606
+ wltubulars: ["ppf", "kg/m"],
1607
+ youngsModulus: ["Pa", "psi"],
1608
+ massPerLength: ["kg/m", "lb/ft"],
1609
+ wearFactor: [
1610
+ "E-09/bar",
1611
+ "E-10/psi",
1612
+ "E-14/pa"
1613
+ ],
1614
+ volumeGradient: [
1615
+ "m3/m",
1616
+ "cm3/m",
1617
+ "mm3/m",
1618
+ "ft3/ft",
1619
+ "in3/ft"
1620
+ ],
1621
+ shearStress: ["Pa", "lbf/100ft2"],
1622
+ sensorAccelerometer: ["g", "m/s2"],
1623
+ sensorMagnetometer: ["nT", "Gs"],
1624
+ location: [
1625
+ "lk",
1626
+ "ftCla",
1627
+ "lkCla",
1628
+ "ftSe",
1629
+ "ydSe",
1630
+ "chSe",
1631
+ "chSe(T)",
1632
+ "ftGC",
1633
+ "ydInd",
1634
+ "ft",
1635
+ "m",
1636
+ "usft"
1637
+ ],
1638
+ mixingRequirements: ["m3/t", "L/100kg"],
1639
+ entalphy: [
1640
+ "J/kg",
1641
+ "kJ/kg",
1642
+ "BTU/lbm"
1643
+ ]
1644
+ });
1645
+ /**
1646
+ * Units list
1647
+ *
1648
+ * @readonly
1649
+ * @enum {Object}
1650
+ */
1651
+ const UNIT_FROM_KEY = Object.freeze({
1652
+ density: "sg",
1653
+ densityGas: "Gsg",
1654
+ densityOil: "sg",
1655
+ densityOilGas: "kg/m3",
1656
+ densitySolid: "kg/m3",
1657
+ length: "m",
1658
+ roughness: "m",
1659
+ speed: "m/s",
1660
+ diameters: "in",
1661
+ duration: "s",
1662
+ durationShort: "h",
1663
+ durationLong: "d",
1664
+ pressurechange: "bar",
1665
+ pressure: "bar",
1666
+ temperature: "C",
1667
+ tempgrad: "C/100m",
1668
+ volume: "m3",
1669
+ kickToleranceVolume: "m3",
1670
+ weight: "kg",
1671
+ force: "N",
1672
+ wgrad: "sg",
1673
+ wltubulars: "ppf",
1674
+ flowrate: "lpm",
1675
+ permeability: "mD",
1676
+ interfacialTension: "dyn/cm",
1677
+ deg: "deg",
1678
+ dls: "deg/30m",
1679
+ percentage: "%",
1680
+ latitude: "°N",
1681
+ longitude: "°E",
1682
+ torque: "Nm",
1683
+ rpm: "rpm",
1684
+ testSingleUnit: "m",
1685
+ turbulentSkin: "1/m3/d",
1686
+ pressurePerTemperature: "Pa/C",
1687
+ sdstats: "Sigma",
1688
+ acceleration: "m/s2",
1689
+ massFlowRate: "kg/s",
1690
+ angleGradient: "deg/m",
1691
+ viscosity: "Pa*s",
1692
+ weightGradient: "kg/m",
1693
+ intensity: "W/m2",
1694
+ gor: "Sm3/Sm3",
1695
+ inflowProductivityIndex: "Sm3/d/bar",
1696
+ wearFactor: "E-09/psi",
1697
+ location: "m",
1698
+ inverseStandSpeed: "s/stand",
1699
+ mixingRequirements: "m3/t",
1700
+ entalphy: "J/kg",
1701
+ shearStress: "Pa",
1702
+ volumeGradient: "m3/m",
1703
+ sensorAccelerometer: "g",
1704
+ sensorMagnetometer: "Gs"
1705
+ });
1706
+ /**
1707
+ * Constants to help conversion
1708
+ *
1709
+ * @readonly
1710
+ * @enum {Object}
1711
+ */
1712
+ const C = Object.freeze({
1713
+ g: .0980665175317196,
1714
+ ft_to_m: .3048,
1715
+ inch_to_m: .0254,
1716
+ lbf_to_kg: .45359237,
1717
+ kg_to_lbf: 2.20462262184877,
1718
+ ppf_to_kgm: .45359237 / .3048,
1719
+ kg_cm3: .0293984025938081,
1720
+ bar_to_psi: 14.503773773022,
1721
+ bar_to_pascal: 1e5,
1722
+ sg_to_ppg: 8.345404265,
1723
+ bbl_to_m3: .158987294928,
1724
+ USGal_to_m3: .003785411784,
1725
+ kelvin_to_degrees: 273.15,
1726
+ tonnes_to_pascal: 9806.65,
1727
+ therm_exp_coeff: 1242e-8,
1728
+ psi_to_pascal: 6894.757293168361,
1729
+ ft3_to_m3: .028316846592,
1730
+ ft3_to_in3: 1728,
1731
+ day_to_second: 3600 * 24,
1732
+ m3_per_m_to_ft3_per_ft: 10.763910416709722,
1733
+ in3_per_ft_to_m3_per_m: 537633333333e-16,
1734
+ MSm3d_to_m3s: 625 / 54
1735
+ });
1736
+ /**
1737
+ * Conversions list
1738
+ *
1739
+ * All unit conversion formulas should have a credible source/reference (please add a comment with URL to where you
1740
+ * got the formula when adding new units to this package). For example:
1741
+ * - Wikipedia
1742
+ * - https://www.nist.gov/pml/special-publication-811/nist-guide-si-appendix-b-conversion-factors/nist-guide-si-appendix-b8
1743
+ * - https://www.wolframalpha.com/input?i=cubic+meter+to+bbl
1744
+ *
1745
+ * Do not round conversion factors in formulas (we need full precision). Make sure the inverse conversion (A->B->A)
1746
+ * produces a valid result.
1747
+ *
1748
+ * @readonly
1749
+ * @enum {Object}
1750
+ */
1751
+ const KNOWN_CONVERSIONS = Object.freeze({
1752
+ "m|mm": (val) => val * 1e3,
1753
+ "m|cm": (val) => val * 100,
1754
+ "m|km": (val) => val / 1e3,
1755
+ "m|ft": (val) => val / C.ft_to_m,
1756
+ "m|in": (val) => val / C.inch_to_m,
1757
+ "m|microM": (val) => val * 1e6,
1758
+ "mm|m": (val) => val / 1e3,
1759
+ "cm|m": (val) => val / 100,
1760
+ "km|m": (val) => val * 1e3,
1761
+ "ft|m": (val) => val * C.ft_to_m,
1762
+ "in|m": (val) => val * C.inch_to_m,
1763
+ "microM|m": (val) => val / 1e6,
1764
+ "m2|mm2": (val) => val * 1e6,
1765
+ "m2|cm2": (val) => val * 1e4,
1766
+ "m2|km2": (val) => val / 1e6,
1767
+ "m2|in2": (val) => val * 1550.0031,
1768
+ "m2|ft2": (val) => val * 10.76391,
1769
+ "m2|mile2": (val) => val * 3.861022e-7,
1770
+ "mm2|m2": (val) => val / 1e6,
1771
+ "cm2|m2": (val) => val / 1e4,
1772
+ "km2|m2": (val) => val * 1e6,
1773
+ "in2|m2": (val) => val / 1550.0031,
1774
+ "ft2|m2": (val) => val / 10.76391,
1775
+ "mile2|m2": (val) => val / 3.861022e-7,
1776
+ "m3|bbl": (val) => val / C.bbl_to_m3,
1777
+ "m3|ft3": (val) => val / C.ft3_to_m3,
1778
+ "m3|l": (val) => val * 1e3,
1779
+ "m3|Mm3": (val) => val / 1e6,
1780
+ "m3|USGal": (val) => val / C.USGal_to_m3,
1781
+ "bbl|m3": (val) => val * C.bbl_to_m3,
1782
+ "ft3|m3": (val) => val * C.ft3_to_m3,
1783
+ "Mm3|m3": (val) => val * 1e6,
1784
+ "l|m3": (val) => val / 1e3,
1785
+ "USGal|m3": (val) => val * C.USGal_to_m3,
1786
+ "m3|Sm3": (val) => val * 1,
1787
+ "m3|STB": (val) => val * 6.289512957422142,
1788
+ "Sm3|m3": (val) => val * 1,
1789
+ "STB|m3": (val) => val * .1589948230919721,
1790
+ "m3|MMSCF": (val) => val * 1e6 / C.ft3_to_m3,
1791
+ "m3|MSm3": (val) => val * 1e-6,
1792
+ "m3|SCF": (val) => val / C.ft3_to_m3,
1793
+ "MMSCF|m3": (val) => val * 1e-6 * C.ft3_to_m3,
1794
+ "MSm3|m3": (val) => val * 1e6,
1795
+ "SCF|m3": (val) => val * C.ft3_to_m3,
1796
+ "kg/m3|sg": (val) => val * .001,
1797
+ "kg/m3|g/cm3": (val) => val * .001,
1798
+ "kg/m3|lbm/ft3": (val) => val / 16.01846337,
1799
+ "kg/m3|lb/ft3": (val) => val / 16.01846337,
1800
+ "kg/m3|ppg": (val) => val * .008345404265,
1801
+ "sg|kg/m3": (val) => val * 1e3,
1802
+ "g/cm3|kg/m3": (val) => val * 1e3,
1803
+ "lbm/ft3|kg/m3": (val) => val * 16.01846337,
1804
+ "lb/ft3|kg/m3": (val) => val * 16.01846337,
1805
+ "ppg|kg/m3": (val) => val / .008345404265,
1806
+ "sg|kPa/m": (val) => val * 9.81,
1807
+ "kPa/m|sg": (val) => val / 9.81,
1808
+ "Gkg/m3|Gsg": (val) => val / 1.225,
1809
+ "Gkg/m3|Glbm/ft3": (val) => val / 16.0176516725,
1810
+ "Gkg/m3|Gppg": (val) => val / 119.8659491193,
1811
+ "Gsg|Gkg/m3": (val) => val * 1.225,
1812
+ "Glbm/ft3|Gkg/m3": (val) => val * 16.0176516725,
1813
+ "Gppg|Gkg/m3": (val) => val * 119.8659491193,
1814
+ "ppf|kg/m": (val) => val * .45359237 / .3048,
1815
+ "kg/m|ppf": (val) => val * 1 / (.45359237 / .3048),
1816
+ "kg/m|lbf/ft": (val) => val / .67196897675131,
1817
+ "lbf/ft|kg/m": (val) => val * .67196897675131,
1818
+ "Pa|psi": (val) => val / C.psi_to_pascal,
1819
+ "psi|Pa": (val) => val * C.psi_to_pascal,
1820
+ "Pa|bar": (val) => val * 1e-5,
1821
+ "Pa|kPa": (val) => val * .001,
1822
+ "Pa|MPa": (val) => val * 1e-6,
1823
+ "Pa|GPa": (val) => val * 1e-9,
1824
+ "bar|Pa": (val) => val * 1e5,
1825
+ "kPa|Pa": (val) => val * 1e3,
1826
+ "MPa|Pa": (val) => val * 1e6,
1827
+ "GPa|Pa": (val) => val * 1e9,
1828
+ "psi|ksi": (val) => val / 1e3,
1829
+ "ksi|psi": (val) => val * 1e3,
1830
+ "psi|lbf/100ft2": (val) => val * 14400,
1831
+ "lbf/100ft2|psi": (val) => val / 14400,
1832
+ "1/psi|1/Pa": (val) => val / C.psi_to_pascal,
1833
+ "1/bar|1/Pa": (val) => val * 1e-5,
1834
+ "1/kPa|1/Pa": (val) => val * .001,
1835
+ "1/MPa|1/Pa": (val) => val * 1e-6,
1836
+ "1/GPa|1/Pa": (val) => val * 1e-9,
1837
+ "1/Pa|1/psi": (val) => val * C.psi_to_pascal,
1838
+ "1/Pa|1/bar": (val) => val * 1e5,
1839
+ "1/Pa|1/kPa": (val) => val * 1e3,
1840
+ "1/Pa|1/MPa": (val) => val * 1e6,
1841
+ "1/Pa|1/GPa": (val) => val * 1e9,
1842
+ "C|F": (val) => val * 1.8 + 32,
1843
+ "F|C": (val) => (val - 32) * 5 / 9,
1844
+ "K|C": (val) => val - C.kelvin_to_degrees,
1845
+ "C|K": (val) => val + C.kelvin_to_degrees,
1846
+ "C/100m|F/100ft": (val) => val * 1.8 * C.ft_to_m,
1847
+ "F/100ft|C/100m": (val) => val * 5 / 9 / C.ft_to_m,
1848
+ "C/100m|C/m": (val) => val / 100,
1849
+ "C/m|C/100m": (val) => val * 100,
1850
+ "C/100m|F/ft": (val) => val * 1.8 / 100 * C.ft_to_m,
1851
+ "F/ft|C/100m": (val) => val * 5 / 9 * 100 / C.ft_to_m,
1852
+ "C/100m|K/m": (val) => val / 100,
1853
+ "K/m|C/100m": (val) => val * 100,
1854
+ "K/100m|C/100m": (val) => val,
1855
+ "C/100m|K/100m": (val) => val,
1856
+ "Pa/C|Bar/C": (val) => val * 1e-5,
1857
+ "Pa/C|psi/F": (val) => val / 1.8 / C.psi_to_pascal,
1858
+ "Pa/C|psi/C": (val) => val / C.psi_to_pascal,
1859
+ "Bar/C|Pa/C": (val) => val * 1e5,
1860
+ "psi/F|Pa/C": (val) => val * 1.8 * C.psi_to_pascal,
1861
+ "psi/C|Pa/C": (val) => val * C.psi_to_pascal,
1862
+ "psi/F|psi/C": (val) => val * 1.8,
1863
+ "psi/C|psi/F": (val) => val / 1.8,
1864
+ "kg|kgf": (val) => val,
1865
+ "kg|lbf": (val) => val * C.kg_to_lbf,
1866
+ "kg|t": (val) => val / 1e3,
1867
+ "kg|tonnes": (val) => val / 1e3,
1868
+ "kg|mt": (val) => val / 1e3,
1869
+ "kg|kip": (val) => val * C.kg_to_lbf * .001,
1870
+ "kgf|kg": (val) => val,
1871
+ "lbf|kg": (val) => val * C.lbf_to_kg,
1872
+ "t|kg": (val) => val * 1e3,
1873
+ "tonnes|kg": (val) => val * 1e3,
1874
+ "mt|kg": (val) => val * 1e3,
1875
+ "kip|kg": (val) => val * 1e3 * C.lbf_to_kg,
1876
+ "tonnes|lbf": (val) => val * 1e3 * C.kg_to_lbf,
1877
+ "lbf|tonnes": (val) => val * C.lbf_to_kg / 1e3,
1878
+ "t|lbf": (val) => val * 1e3 * C.kg_to_lbf,
1879
+ "lbf|t": (val) => val * C.lbf_to_kg / 1e3,
1880
+ "mt|lbf": (val) => val * 1e3 * C.kg_to_lbf,
1881
+ "lbf|mt": (val) => val / (1e3 * C.kg_to_lbf),
1882
+ "kgf|lbf": (val) => val * C.kg_to_lbf,
1883
+ "lbf|kgf": (val) => val * C.lbf_to_kg,
1884
+ "kg|g": (val) => val * 1e3,
1885
+ "g|kg": (val) => val / 1e3,
1886
+ "kgf|t": (val) => val / 1e3,
1887
+ "t|kgf": (val) => val * 1e3,
1888
+ "kgf|tonnes": (val) => val / 1e3,
1889
+ "tonnes|kgf": (val) => val * 1e3,
1890
+ "kg/m|lb/ft": (val) => val * 1.4881639435695537,
1891
+ "lb/ft|kg/m": (val) => val * .6719689751395069,
1892
+ "kg|N": (val) => val * C.g * 100,
1893
+ "N|kg": (val) => val / (C.g * 100),
1894
+ "m/s|km/h": (val) => val * 3.6,
1895
+ "km/h|m/s": (val) => val / 3.6,
1896
+ "m/s|ft/s": (val) => val / C.ft_to_m,
1897
+ "m/s|ft/min": (val) => val * 60 / C.ft_to_m,
1898
+ "m/s|ft/h": (val) => val * 3600 / C.ft_to_m,
1899
+ "m/s|m/min": (val) => val * 60,
1900
+ "m/s|m/h": (val) => val * 3600,
1901
+ "ft/s|m/s": (val) => val * C.ft_to_m,
1902
+ "ft/min|m/s": (val) => val * C.ft_to_m / 60,
1903
+ "ft/h|m/s": (val) => val * C.ft_to_m / 3600,
1904
+ "m/min|m/s": (val) => val / 60,
1905
+ "m/h|m/s": (val) => val / 3600,
1906
+ "m/s|mph": (val) => val * 2.2369362920544,
1907
+ "mph|m/s": (val) => val / 2.2369362920544,
1908
+ "ft/h|ft/d": (val) => val * 24,
1909
+ "ft/d|ft/h": (val) => val / 24,
1910
+ "ft/h|m/h": (val) => val * C.ft_to_m,
1911
+ "m/h|ft/h": (val) => val / C.ft_to_m,
1912
+ "ft/d|m/h": (val) => val * C.ft_to_m / 24,
1913
+ "m/h|ft/d": (val) => val * 24 / C.ft_to_m,
1914
+ "ft/d|m/d": (val) => val * C.ft_to_m,
1915
+ "m/d|ft/d": (val) => val / C.ft_to_m,
1916
+ "m/h|m/d": (val) => val * 24,
1917
+ "m/d|m/h": (val) => val / 24,
1918
+ "l/m|bbl/ft": (val) => val * .0019171343228277056,
1919
+ "bbl/ft|l/m": (val) => val / .0019171343228277056,
1920
+ "m3/s|ft3/s": (val) => val / C.ft3_to_m3,
1921
+ "m3/s|lpm": (val) => val * 6e4,
1922
+ "m3/s|bpm": (val) => val * 377.388646,
1923
+ "m3/s|m3/min": (val) => val * 60,
1924
+ "m3/s|m3/d": (val) => val * C.day_to_second,
1925
+ "m3/s|bbl/d": (val) => val * 543439.6505653338,
1926
+ "m3/s|ft3/d": (val) => val * C.day_to_second / C.ft3_to_m3,
1927
+ "m3/s|gpm": (val) => val * 25e11 / 157725491,
1928
+ "m3/s|MMSCFD": (val) => val / .32774128,
1929
+ "m3/s|STB/d": (val) => val * 0x7a7f6097db00 / 247854343,
1930
+ "m3/s|Sm3/d": (val) => val * C.day_to_second,
1931
+ "m3/s|Sm3/min": (val) => val * 60,
1932
+ "Sm3/min|m3/s": (val) => val / 60,
1933
+ "m3/s|MSm3/d": (val) => val / C.MSm3d_to_m3s,
1934
+ "m3/s|SCF/d": (val) => val * 3051187.2047366146,
1935
+ "ft3/s|m3/s": (val) => val * C.ft3_to_m3,
1936
+ "lpm|m3/s": (val) => val / 6e4,
1937
+ "lps|lpm": (val) => val * 60,
1938
+ "lpm|lps": (val) => val / 60,
1939
+ "bpm|m3/s": (val) => val / 377.388646,
1940
+ "m3/d|m3/s": (val) => val / C.day_to_second,
1941
+ "m3/min|m3/s": (val) => val / 60,
1942
+ "bbl/d|m3/s": (val) => val / C.day_to_second * C.bbl_to_m3,
1943
+ "ft3/d|m3/s": (val) => val / C.day_to_second * C.ft3_to_m3,
1944
+ "ft3/d|m3/d": (val) => val * C.ft3_to_m3,
1945
+ "m3/d|ft3/d": (val) => val / C.ft3_to_m3,
1946
+ "m3/d|ft3/s": (val) => val / C.ft3_to_m3 / C.day_to_second,
1947
+ "gpm|m3/s": (val) => val * 157725491 / 25e11,
1948
+ "MMSCFD|m3/s": (val) => val * .32774128,
1949
+ "Mm3/d|m3/d": (val) => val * 1e6,
1950
+ "m3/d|Mm3/d": (val) => val * 1e-6,
1951
+ "STB/d|m3/s": (val) => val * 184021785986e-17,
1952
+ "Sm3/d|m3/d": (val) => val,
1953
+ "m3/d|Sm3/d": (val) => val,
1954
+ "Sm3/d|m3/s": (val) => val / C.day_to_second,
1955
+ "MSm3/d|Sm3/d": (val) => val * 1e6,
1956
+ "Sm3/d|MSm3/d": (val) => val * 1e-6,
1957
+ "MSm3/d|m3/s": (val) => val * C.MSm3d_to_m3s,
1958
+ "SCF/d|m3/s": (val) => val * 3.2774128e-7,
1959
+ "1/m3/d|1/MMSCFD": (val) => val * 28316.85,
1960
+ "1/MMSCFD|1/m3/d": (val) => val / 28316.85,
1961
+ "s/m3|1/m3/d": (val) => val / 86400,
1962
+ "1/m3/d|s/m3": (val) => val * 86400,
1963
+ "kg/s|lbm/s": (val) => val * 2.20462262,
1964
+ "lbm/s|kg/s": (val) => val / 2.20462262,
1965
+ "kg/s|tonnes/h": (val) => val * 3.6,
1966
+ "tonnes/h|kg/s": (val) => val / 3.6,
1967
+ "kg/s|tons/h": (val) => val * 3.9683207193277967,
1968
+ "tons/h|kg/s": (val) => val * .2519957611111111,
1969
+ "lbm/s|tonnes/h": (val) => val * 1.632932532,
1970
+ "tonnes/h|lbm/s": (val) => val * .612395172735771,
1971
+ "lbm/s|tons/h": (val) => val * 1.8,
1972
+ "tons/h|lbm/s": (val) => val / 1.8,
1973
+ "tonnes/h|tons/h": (val) => val * 1.1023113109243878,
1974
+ "tons/h|tonnes/h": (val) => val * .90718474,
1975
+ "mD|m2": (val) => val * 9869233e-19,
1976
+ "m2|mD": (val) => val / 9869233e-19,
1977
+ "N/m|lbf/ft": (val) => val * .22480894387096 * C.ft_to_m,
1978
+ "lbf/ft|N/m": (val) => val / .22480894387096 / C.ft_to_m,
1979
+ "dyn/cm|mN/m": (val) => val,
1980
+ "mN/m|dyn/cm": (val) => val,
1981
+ "dyn/cm|N/m": (val) => val * .001,
1982
+ "N/m|dyn/cm": (val) => val * 1e3,
1983
+ "mN/m|N/m": (val) => val * .001,
1984
+ "N/m|mN/m": (val) => val * 1e3,
1985
+ "Nm|ftlbf": (val) => val * .737562058700684,
1986
+ "Nm|kNm": (val) => val / 1e3,
1987
+ "kNm|Nm": (val) => val * 1e3,
1988
+ "ftlbf|Nm": (val) => val / .737562058700684,
1989
+ "N|kN": (val) => val * .001,
1990
+ "N|kgf": (val) => val * 2e4 / 196133,
1991
+ "N|lbf": (val) => val * 2e12 / 8896443230521,
1992
+ "kN|lbf": (val) => val * 1e3 * 2e12 / 8896443230521,
1993
+ "N|tonneForce": (val) => val * 20 / 196133,
1994
+ "kN|N": (val) => val / .001,
1995
+ "kgf|N": (val) => val * 196133 / 2e4,
1996
+ "lbf|N": (val) => val * 8896443230521 / 2e12,
1997
+ "lbf|kN": (val) => val * 8896443230521 / (2e12 * 1e3),
1998
+ "lbf|tonneForce": (val) => val * 45359237 / 1e11,
1999
+ "klbf|tonneForce": (val) => val * 45359237 / (1e11 * .001),
2000
+ "tonneForce|N": (val) => val * 196133 / 20,
2001
+ "tonneForce|lbf": (val) => val * 1e11 / 45359237,
2002
+ "tonneForce|klbf": (val) => val * 1e11 / (45359237 * 1e3),
2003
+ "klbf|lbf": (val) => val * 1e3,
2004
+ "lbf|klbf": (val) => val / 1e3,
2005
+ "s|min": (val) => val / 60,
2006
+ "s|h": (val) => val / 3600,
2007
+ "s|d": (val) => val / (24 * 3600),
2008
+ "min|s": (val) => val * 60,
2009
+ "h|s": (val) => val * 3600,
2010
+ "d|s": (val) => val * 24 * 3600,
2011
+ "year|d": (val) => val * 365.25,
2012
+ "d|year": (val) => val / 365.25,
2013
+ "year|month": (val) => val * 12,
2014
+ "month|year": (val) => val / 12,
2015
+ "month|d": (val) => val * 30.4375,
2016
+ "d|month": (val) => val / 30.4375,
2017
+ "s/stand|min/stand": (val) => val / 60,
2018
+ "s/stand|h/stand": (val) => val / 3600,
2019
+ "s/stand|d/stand": (val) => val / 86400,
2020
+ "min/stand|s/stand": (val) => val * 60,
2021
+ "h/stand|s/stand": (val) => val * 3600,
2022
+ "d/stand|s/stand": (val) => val * 86400,
2023
+ "min/stand|h/stand": (val) => val / 60,
2024
+ "min/stand|d/stand": (val) => val / 1440,
2025
+ "h/stand|min/stand": (val) => val * 60,
2026
+ "h/stand|d/stand": (val) => val / 24,
2027
+ "d/stand|min/stand": (val) => val * 1440,
2028
+ "d/stand|h/stand": (val) => val * 24,
2029
+ "%|fr": (val) => val * .01,
2030
+ "fr|%": (val) => val / .01,
2031
+ "deg|rad": (val) => val * Math.PI / 180,
2032
+ "rad|deg": (val) => val * 180 / Math.PI,
2033
+ "W|hp": (val) => val / 745.699872,
2034
+ "hp|W": (val) => val * 745.699872,
2035
+ "W|kW": (val) => val / 1e3,
2036
+ "W|MW": (val) => val / 1e6,
2037
+ "kW|W": (val) => val * 1e3,
2038
+ "MW|W": (val) => val * 1e6,
2039
+ "W|BTU/h": (val) => val * 3.4121416351331,
2040
+ "BTU/h|W": (val) => val / 3.4121416351331,
2041
+ "hhp|hp": (val) => val,
2042
+ "hp|hhp": (val) => val,
2043
+ "°N|°S": (val) => val,
2044
+ "°S|°N": (val) => val,
2045
+ "°W|°E": (val) => val,
2046
+ "°E|°W": (val) => val,
2047
+ "BTU/(Kg*K)|BTU/(lbm*degF)": (val) => val / 4186.798188,
2048
+ "BTU/(lbm*degF)|J/(kg*degC)": (val) => val * 4186.798188,
2049
+ "BTU/(lbm*degF)|BTU/(Kg*K)": (val) => val * 4186.798188,
2050
+ "J/(kg*degK)|J/(kg*degC)": (val) => val,
2051
+ "J/(kg*degC)|BTU/(lbm*degF)": (val) => val / 4186.798188,
2052
+ "J/(kg*degC)|J/(kg*degK)": (val) => val,
2053
+ "J/(kg*degC)|J/(s*m*degK)": (val) => val,
2054
+ "BTU/(h*ft*degF)|W/(mK)": (val) => val * 1.7295772056,
2055
+ "BTU/(h*ft*degF)|J/(s*m*degK)": (val) => val * 1.7295772056,
2056
+ "W/(mK)|BTU/(h*ft*degF)": (val) => val / 1.7295772056,
2057
+ "W/(mK)|J/(s*m*degK)": (val) => val,
2058
+ "W/(m*degK)|J/(s*m*degK)": (val) => val,
2059
+ "W/(m*degK)|BTU/(h*ft*degF)": (val) => val / 1.7295772056,
2060
+ "J/(s*m*degK)|BTU/(h*ft*degF)": (val) => val / 1.7295772056,
2061
+ "J/(s*m*degK)|W/(m*degK)": (val) => val,
2062
+ "J/(s*m*degK)|W/(mK)": (val) => val,
2063
+ "J/(s*m*degK)|J/(kg*degC)": (val) => val,
2064
+ "E-06/degF|E-06/degC": (val) => val * 1.8,
2065
+ "E-06/degC|E-06/degF": (val) => val / 1.8,
2066
+ "E-06/degC|1/K": (val) => val / 1e6,
2067
+ "1/K|E-06/degC": (val) => val * 1e6,
2068
+ "rpm|Hz": (val) => val / 60,
2069
+ "Hz|rpm": (val) => val * 60,
2070
+ "CI|Sigma": (val) => get_k_from_conf_int(val),
2071
+ "Sigma|CI": (val) => get_conf_int_from_k(val),
2072
+ "g/mol|kg/mol": (val) => val / 1e3,
2073
+ "kg/mol|g/mol": (val) => val * 1e3,
2074
+ "lbf/mol|kg/mol": (val) => val / C.kg_to_lbf,
2075
+ "kg/mol|lbf/mol": (val) => val * C.kg_to_lbf,
2076
+ "m/s2|ft/s2": (val) => val / C.ft_to_m,
2077
+ "ft/s2|m/s2": (val) => val * C.ft_to_m,
2078
+ "Pa*s|P": (val) => val * 10,
2079
+ "P|Pa*s": (val) => val / 10,
2080
+ "mPa*s|Pa*s": (val) => val / 1e3,
2081
+ "Pa*s|mPa*s": (val) => val * 1e3,
2082
+ "cP|Pa*s": (val) => val * .001,
2083
+ "Pa*s|cP": (val) => val / .001,
2084
+ "Pa/m|bar/m": (val) => val * 1e-5,
2085
+ "bar/m|Pa/m": (val) => val * 1e5,
2086
+ "Pa/m|kPa/m": (val) => val / 1e3,
2087
+ "kPa/m|Pa/m": (val) => val * 1e3,
2088
+ "Pa/m|bar/100m": (val) => val * .001,
2089
+ "bar/100m|Pa/m": (val) => val * 1e3,
2090
+ "bar/m|bar/100m": (val) => val * 100,
2091
+ "bar/100m|bar/m": (val) => val / 100,
2092
+ "psi/ft|Pa/m": (val) => val * C.psi_to_pascal / C.ft_to_m,
2093
+ "Pa/m|psi/ft": (val) => val / C.psi_to_pascal * C.ft_to_m,
2094
+ "psi/100ft|Pa/m": (val) => val * 68.9475729 / C.ft_to_m,
2095
+ "Pa/m|psi/100ft": (val) => val / 68.9475729 * C.ft_to_m,
2096
+ "deg/30m|deg/100ft": (val) => val * (100 * C.ft_to_m / 30),
2097
+ "deg/100ft|deg/30m": (val) => val / (100 * C.ft_to_m / 30),
2098
+ "deg/30m|deg/m": (val) => val / 30,
2099
+ "deg/m|deg/30m": (val) => val * 30,
2100
+ "deg/100ft|deg/ft": (val) => val / 100,
2101
+ "deg/ft|deg/100ft": (val) => val * 100,
2102
+ "deg/100ft|deg/m": (val) => val / (100 * C.ft_to_m),
2103
+ "deg/m|deg/100ft": (val) => val * (100 * C.ft_to_m),
2104
+ "deg/ft|deg/m": (val) => val / C.ft_to_m,
2105
+ "deg/m|deg/ft": (val) => val * C.ft_to_m,
2106
+ "deg/m|rad/m": (val) => val * Math.PI / 180,
2107
+ "rad/m|deg/m": (val) => val * 180 / Math.PI,
2108
+ "rad/ft|deg/m": (val) => val * 180 / Math.PI / C.ft_to_m,
2109
+ "deg/m|rad/ft": (val) => val * Math.PI / 180 * C.ft_to_m,
2110
+ "deg/10m|deg/100ft": (val) => val * (10 * C.ft_to_m),
2111
+ "deg/100ft|deg/10m": (val) => val / (10 * C.ft_to_m),
2112
+ "deg/10m|deg/m": (val) => val / 10,
2113
+ "deg/m|deg/10m": (val) => val * 10,
2114
+ "deg/30m|deg/10m": (val) => val / 3,
2115
+ "deg/10m|deg/30m": (val) => val * 3,
2116
+ "deg/10m|rad/m": (val) => val * Math.PI / 180 / 10,
2117
+ "rad/m|deg/10m": (val) => val * 180 / Math.PI * 10,
2118
+ "W/m2|hhp/in2": (val) => val * (1 / 745.699872 / 1550.0031),
2119
+ "W/m2|hhp/ft2": (val) => val * (1 / 745.699872 / 10.76391),
2120
+ "hhp/in2|W/m2": (val) => val / (1 / 745.699872 / 1550.0031),
2121
+ "hhp/ft2|W/m2": (val) => val / (1 / 745.699872 / 10.76391),
2122
+ "SCF/STB|Sm3/Sm3": (val) => val * .178099173553719,
2123
+ "Sm3/Sm3|SCF/STB": (val) => val * 5.614849187935035,
2124
+ "Sm3/d/bar|m3/s/bar": (val) => val / 86400,
2125
+ "STB/d/psi|m3/s/bar": (val) => val / 37468.77736,
2126
+ "m3/s/bar|Sm3/d/bar": (val) => val * 86400,
2127
+ "m3/s/bar|STB/d/psi": (val) => val * 37468.77736,
2128
+ "E-10/psi|E-09/bar": (val) => val * 1.450377378,
2129
+ "E-10/psi|E-14/pa": (val) => val * 1.450377378,
2130
+ "E-14/pa|E-10/psi": (val) => val / 1.450377378,
2131
+ "E-09/bar|E-10/psi": (val) => val / 1.450377378,
2132
+ "E-14/pa|1/Pa": (val) => val / Math.pow(10, 14),
2133
+ "E-09/bar|1/bar": (val) => val / Math.pow(10, 9),
2134
+ "E-10/psi|1/psi": (val) => val / Math.pow(10, 10),
2135
+ "1/Pa|E-14/pa": (val) => val * Math.pow(10, 14),
2136
+ "1/bar|E-09/bar": (val) => val * Math.pow(10, 9),
2137
+ "1/psi|E-10/psi": (val) => val * Math.pow(10, 10),
2138
+ "m3/m|cm3/m": (val) => val * 10 ** 6,
2139
+ "m3/m|mm3/m": (val) => val * 10 ** 9,
2140
+ "m3/m|ft3/ft": (val) => val * C.m3_per_m_to_ft3_per_ft,
2141
+ "m3/m|in3/ft": (val) => val * C.m3_per_m_to_ft3_per_ft * C.ft3_to_in3,
2142
+ "cm3/m|m3/m": (val) => val * 1e-6,
2143
+ "cm3/m|mm3/m": (val) => val * 1e3,
2144
+ "cm3/m|ft3/ft": (val) => val * C.m3_per_m_to_ft3_per_ft * 1e-6,
2145
+ "cm3/m|in3/ft": (val) => val * C.m3_per_m_to_ft3_per_ft * 1e-6 * C.ft3_to_in3,
2146
+ "mm3/m|m3/m": (val) => val * 1e-9,
2147
+ "mm3/m|cm3/m": (val) => val * .001,
2148
+ "mm3/m|ft3/ft": (val) => val * C.m3_per_m_to_ft3_per_ft * 1e-9,
2149
+ "mm3/m|in3/ft": (val) => val * C.m3_per_m_to_ft3_per_ft * 1e-9 * C.ft3_to_in3,
2150
+ "ft3/ft|m3/m": (val) => val * .09290304,
2151
+ "ft3/ft|cm3/m": (val) => val * 92903.04,
2152
+ "ft3/ft|mm3/m": (val) => val * 92903040,
2153
+ "ft3/ft|in3/ft": (val) => val * 1728,
2154
+ "in3/ft|m3/m": (val) => val * C.in3_per_ft_to_m3_per_m,
2155
+ "in3/ft|cm3/m": (val) => val * C.in3_per_ft_to_m3_per_m * 1e6,
2156
+ "in3/ft|mm3/m": (val) => val * C.in3_per_ft_to_m3_per_m * 1e9,
2157
+ "in3/ft|ft3/ft": (val) => val / C.ft3_to_in3,
2158
+ "Pa|lbf/100ft2": (val) => val * 2.088543423315013,
2159
+ "lbf/100ft2|Pa": (val) => val * .4788025898033584,
2160
+ "usft|m": (val) => val * .30480060960121924,
2161
+ "lk|m": (val) => val * .201168,
2162
+ "ftCla|m": (val) => val * .3047972651151,
2163
+ "lkCla|m": (val) => val * .2011057269733667,
2164
+ "ftGC|m": (val) => val * .30479971018150875,
2165
+ "ydInd|m": (val) => val * .9143985307444408,
2166
+ "ftSe|m": (val) => val * (12 / 39.370147),
2167
+ "ydSe|m": (val) => val * .9143991154275526,
2168
+ "chSe|m": (val) => val * 20.11676512155263,
2169
+ "chSe(T)|m": (val) => val * 20.116756,
2170
+ "m|usft": (val) => val / .30480060960121924,
2171
+ "m|lk": (val) => val / .201168,
2172
+ "m|ftCla": (val) => val / .3047972651151,
2173
+ "m|lkCla": (val) => val / .2011057269733667,
2174
+ "m|ftGC": (val) => val / .30479971018150875,
2175
+ "m|ydInd": (val) => val / .9143985307444408,
2176
+ "m|ftSe": (val) => val / (12 / 39.370147),
2177
+ "m|ydSe": (val) => val / .9143991154275526,
2178
+ "m|chSe": (val) => val / 20.11676512155263,
2179
+ "m|chSe(T)": (val) => val / 20.116756,
2180
+ "m3/t|L/100kg": (val) => val * 100,
2181
+ "L/100kg|m3/t": (val) => val * .01,
2182
+ "kJ/kg|J/kg": (val) => val * 1e3,
2183
+ "J/kg|kJ/kg": (val) => val / 1e3,
2184
+ "BTU/lbm|J/kg": (val) => val * 2326,
2185
+ "J/kg|BTU/lbm": (val) => val / 2326,
2186
+ "g|m/s2": (val) => val * 9.81,
2187
+ "m/s2|g": (val) => val / 9.81,
2188
+ "Gs|nT": (val) => val * 1e5,
2189
+ "nT|Gs": (val) => val / 1e5
2190
+ });
2191
+ /**
2192
+ * Deprecated units
2193
+ *
2194
+ * @readonly
2195
+ * @enum {Object}
2196
+ */
2197
+ const DEPRECATED_UNITS = Object.freeze({
2198
+ "N-m": "Nm",
2199
+ "ft-lbf": "ftlbf",
2200
+ "BTU/hr": "BTU/h",
2201
+ "BTU/(htf*degF)": "BTU/(h*ft*degF)",
2202
+ "BTU/(hft*degF)": "BTU/(h*ft*degF)"
2203
+ });
2204
+ /**
2205
+ * This list is mapping from legal alternative unit names to our selected unit name
2206
+ *
2207
+ * @readonly
2208
+ * @enum {Object}
2209
+ */
2210
+ const UNIT_ALIASES = Object.freeze({
2211
+ "lbs/ft": "lb/ft",
2212
+ "lbm/ft": "lb/ft",
2213
+ ftUS: "usft"
2214
+ });
2215
+ /**
2216
+ * Intermediate conversions
2217
+ *
2218
+ * @readonly
2219
+ * @enum {Object}
2220
+ */
2221
+ const INTERMEDIATE_CONVERSIONS = Object.freeze({
2222
+ mm: "m",
2223
+ cm: "m",
2224
+ km: "m",
2225
+ ft: "m",
2226
+ in: "m",
2227
+ microM: "m",
2228
+ lbf: "kg",
2229
+ t: "kg",
2230
+ tonnes: "kg",
2231
+ mt: "kg",
2232
+ kip: "kg",
2233
+ kW: "W",
2234
+ MW: "W",
2235
+ hp: "W",
2236
+ hhp: "hp",
2237
+ mm2: "m2",
2238
+ cm2: "m2",
2239
+ km2: "m2",
2240
+ in2: "m2",
2241
+ ft2: "m2",
2242
+ mile2: "m2",
2243
+ bbl: "m3",
2244
+ ft3: "m3",
2245
+ Mm3: "m3",
2246
+ l: "m3",
2247
+ USGal: "m3",
2248
+ Sm3: "m3",
2249
+ STB: "m3",
2250
+ MMSCF: "m3",
2251
+ MSm3: "m3",
2252
+ SCF: "m3",
2253
+ kN: "N",
2254
+ kgf: "N",
2255
+ tonneForce: "N",
2256
+ klbf: "lbf",
2257
+ psi: "Pa",
2258
+ bar: "Pa",
2259
+ kPa: "Pa",
2260
+ MPa: "Pa",
2261
+ ksi: "psi",
2262
+ "lbf/100ft2": "psi",
2263
+ "psi/100ft": "Pa/m",
2264
+ "psi/ft": "Pa/m",
2265
+ "bar/100m": "Pa/m",
2266
+ "bar/m": "Pa/m",
2267
+ "Pa/m": "kPa/m",
2268
+ sg: "kg/m3",
2269
+ "g/cm3": "kg/m3",
2270
+ "lbm/ft3": "kg/m3",
2271
+ "lb/ft3": "kg/m3",
2272
+ ppg: "kg/m3",
2273
+ "kPa/m": "sg",
2274
+ Gsg: "Gkg/m3",
2275
+ Gppg: "Gkg/m3",
2276
+ "Glbm/ft3": "Gkg/m3",
2277
+ "1/psi": "1/Pa",
2278
+ "1/bar": "1/Pa",
2279
+ "1/kPa": "1/Pa",
2280
+ "1/MPa": "1/Pa",
2281
+ "1/GPa": "1/Pa",
2282
+ "ft/s": "m/s",
2283
+ "ft/min": "m/s",
2284
+ "ft/h": "m/s",
2285
+ "m/min": "m/s",
2286
+ "m/h": "m/s",
2287
+ mph: "m/s",
2288
+ "ft3/s": "m3/s",
2289
+ lpm: "m3/s",
2290
+ lps: "lpm",
2291
+ bpm: "m3/s",
2292
+ "m3/d": "m3/s",
2293
+ "bbl/d": "m3/s",
2294
+ "ft3/d": "m3/s",
2295
+ "STB/d": "m3/s",
2296
+ "Sm3/d": "m3/s",
2297
+ "Sm3/min": "m3/s",
2298
+ gpm: "m3/s",
2299
+ MMSCFD: "m3/s",
2300
+ "Mm3/d": "m3/d",
2301
+ "m3/min": "m3/s",
2302
+ "MSm3/d": "m3/s",
2303
+ "lbf/ft": "N/m",
2304
+ min: "s",
2305
+ h: "s",
2306
+ d: "s",
2307
+ month: "d",
2308
+ year: "d",
2309
+ "J/(kg*degK)": "J/(kg*degC)",
2310
+ "BTU/(lbm*degF)": "J/(kg*degC)",
2311
+ "BTU/(Kg*K)": "J/(kg*degC)",
2312
+ "BTU/(h*ft*degF)": "J/(s*m*degK)",
2313
+ "W/(m*degK)": "J/(s*m*degK)",
2314
+ "W/(mK)": "J/(s*m*degK)",
2315
+ K: "C",
2316
+ "C/m": "C/100m",
2317
+ "F/ft": "C/100m",
2318
+ "K/m": "C/100m",
2319
+ "F/100ft": "C/100m",
2320
+ "K/100m": "C/100m",
2321
+ "Bar/C": "Pa/C",
2322
+ "s/m3": "1/m3/d",
2323
+ "1/MMSCFD": "1/m3/d",
2324
+ P: "Pa*s",
2325
+ "mPa*s": "Pa*s",
2326
+ cP: "Pa*s",
2327
+ "hhp/in2": "W/m2",
2328
+ "hhp/ft2": "W/m2",
2329
+ "Sm3/d/bar": "m3/s/bar",
2330
+ "STB/d/psi": "m3/s/bar",
2331
+ "deg/100ft": "deg/m",
2332
+ "deg/30m": "deg/m",
2333
+ "deg/10m": "deg/m",
2334
+ "deg/ft": "deg/m",
2335
+ "rad/ft": "deg/m",
2336
+ "lbf/mol": "kg/mol",
2337
+ "g/mol": "kg/mol",
2338
+ "1/K": "E-06/degC",
2339
+ "E-09/bar": "E-10/psi",
2340
+ "E-14/pa": "E-10/psi",
2341
+ "1/Pa": "E-14/pa",
2342
+ kNm: "Nm",
2343
+ ftlbf: "Nm",
2344
+ lk: "m",
2345
+ ftCla: "m",
2346
+ lkCla: "m",
2347
+ ftSe: "m",
2348
+ ydSe: "m",
2349
+ chSe: "m",
2350
+ "chSe(T)": "m",
2351
+ ftGC: "m",
2352
+ ydInd: "m",
2353
+ "BTU/lbm": "J/kg"
2354
+ });
2355
+ /**
2356
+ * List of all known units in application
2357
+ *
2358
+ * @readonly
2359
+ * @enum {string[]}
2360
+ */
2361
+ const KNOWN_UNITS = Object.freeze(Array.from(new Set(Object.values(ALT_UNITS).flat())));
2362
+ const SPECIAL_NUMBERS_STRING = [
2363
+ NaN,
2364
+ -Infinity,
2365
+ Infinity
2366
+ ].map((number) => number.toString());
2367
+ /**
2368
+ * Description for the different quantites
2369
+ * @readonly
2370
+ */
2371
+ const QUANTITIES_DESCRIPTION = {
2372
+ density: "Density",
2373
+ length: "Length",
2374
+ duration: "Duration",
2375
+ temperature: "Temperature",
2376
+ tempgrad: "Temperature Gradient",
2377
+ volume: "Volume",
2378
+ weight: "Weight",
2379
+ angles: "Angles",
2380
+ depth: "Depth",
2381
+ distance: "Distances",
2382
+ height: "Height",
2383
+ diameters: "Diameters",
2384
+ doglegSeverity: "Dogleg severity",
2385
+ fluidCompressibility: "Fluid Compressibility",
2386
+ force: "Force",
2387
+ gasVolume: "Gas volume",
2388
+ oilVolume: "Oil volume",
2389
+ moleWeight: "Mole weight",
2390
+ linearCapacity: "Linear Capacity",
2391
+ stress: "Stress",
2392
+ thermalConductivity: "Thermal conductivity",
2393
+ specificHeatCapacity: "Specific heat capacity",
2394
+ thermalExpansionCoefficient: "Thermal expansion coefficient",
2395
+ youngsModulus: "Youngs Modulus",
2396
+ torque: "Torque",
2397
+ areaOther: "Area - Other",
2398
+ areaTubular: "Area - Tubular",
2399
+ pumpRate: "Pump Rate",
2400
+ pressure: "Pressure",
2401
+ blowoutFlowRate: "Flowrate (blowout)",
2402
+ percentage: "Percentage",
2403
+ frequency: "Frequency",
2404
+ torqueGradient: "Torque gradient",
2405
+ pressureGradient: "Pressure gradient",
2406
+ flowrate: "Volumetric flow rate",
2407
+ massFlowRate: "Mass flow rate",
2408
+ angleGradient: "Angle gradient",
2409
+ weightGradient: "Weight gradient",
2410
+ forceGradient: "Force gradient",
2411
+ interfacialTension: "Interfacial tension",
2412
+ acceleration: "Acceleration",
2413
+ viscosity: "Viscosity",
2414
+ power: "Power",
2415
+ intensity: "Power intensity",
2416
+ gasliftFlowRate: "Flowrate (Gas lift)",
2417
+ productionFlowRate: "Flowrate (production)",
2418
+ productionFlowRateOil: "Flowrate for Oil (production)",
2419
+ productionFlowRateGas: "Flowrate for Gas (production)",
2420
+ injectionFlowRate: "Flowrate (injection)",
2421
+ blowoutOilFlowRate: "Flowrate for Oil (blowout)",
2422
+ blowoutGasFlowRate: "Flowrate for Gas (blowout)",
2423
+ gor: "Gas Oil Ratio",
2424
+ rotationalSpeed: "Rotational Speed",
2425
+ densityGas: "Density for gas",
2426
+ inflowProductivityIndex: "Inflow productivity index",
2427
+ latitude: "Latitude",
2428
+ longitude: "Longitude",
2429
+ permeability: "Permeability",
2430
+ sdstats: "Standard deviation",
2431
+ roughness: "Material Roughness",
2432
+ wltubulars: "Tubular weight",
2433
+ speed: "Velocity",
2434
+ inverseStandSpeed: "Inverse Stand velocity",
2435
+ rop: "Rate of Penetration (ROP)",
2436
+ densityOil: "Density for oil",
2437
+ densityOilGas: "Density for oil/gas",
2438
+ kickToleranceVolume: "Volume for kick tolerance",
2439
+ densitySolid: "Density for solid",
2440
+ massPerLength: "Mass Per Length",
2441
+ durationShort: "Duration (TempSim short)",
2442
+ durationLong: "Duration (TempSim long)",
2443
+ wearFactor: "Wear factor",
2444
+ turbulentSkin: "Turbulent skin",
2445
+ pressurePerTemperature: "Pressure per temperature",
2446
+ location: "Location coordinates length",
2447
+ mixingRequirements: "Ratio between water and cement",
2448
+ Entalphy: "Entalphy",
2449
+ shearStress: "Shear Stress, force parallel to surface",
2450
+ volumeGradient: "Rate of Volume change per unit",
2451
+ deg: "Degree, a unit of angular measurement",
2452
+ dls: "Dogleg Severity, measure of wellbore curvature changes per unit length",
2453
+ wgrad: "Weight Gradient, change in weight per unit length",
2454
+ entalphy: "Entalphy, total heat content of a system",
2455
+ pressurechange: "Change in pressure over time or between two points",
2456
+ rpm: "Rotations per minute, a measure of the frequency of rotation, specifying the number of full rotations completed in one minute around a fixed axis",
2457
+ sensorAccelerometer: "Strength of gravitational acceleration",
2458
+ sensorMagnetometer: "Strength of magnetic forces at a position"
2459
+ };
2460
+ /**
2461
+ * Description for the different units
2462
+ * @readonly
2463
+ */
2464
+ const UNITS_DESCRIPTION = {
2465
+ in: "Inches",
2466
+ mm: "Milimeters",
2467
+ cm: "Centimeters",
2468
+ m: "Meters",
2469
+ km: "Kilometers",
2470
+ ft: "Feets",
2471
+ usft: "US Feets",
2472
+ in2: "Square inches",
2473
+ cm2: "Square centimeters",
2474
+ m2: "Square meters",
2475
+ kg: "Kilograms",
2476
+ tonnes: "Tonnes",
2477
+ mt: "Metric tonnes",
2478
+ kip: "Kip",
2479
+ bbl: "Barrels",
2480
+ Mm3: "Mega cubic meters",
2481
+ MMSCF: "Million Standard Cubic Feet",
2482
+ lbm: "Pound mass",
2483
+ "kg/mol": "Kilograms per mole",
2484
+ "lbf/mol": "Pounds per mole",
2485
+ sg: "Specific gravity",
2486
+ ppg: "Pounds per gallon",
2487
+ "kg/m3": "Kilogram per cubic meters",
2488
+ "lbm/ft3": "Pounds per cubic foot",
2489
+ s: "Seconds",
2490
+ min: "Minutes",
2491
+ h: "Hours",
2492
+ d: "Days",
2493
+ month: "Months",
2494
+ year: "Years",
2495
+ "bbl/ft": "Barrels per foot",
2496
+ lpm: "Litres per minute",
2497
+ bpm: "Barrels per minute",
2498
+ "m3/min": "Cubic meters per minute",
2499
+ "m3/s": "Cubic meters per second",
2500
+ MMSCFD: "Million Standard Cubic Feet per day",
2501
+ "1/MMSCFD": "Inverse Million Standard Cubic Feet per day",
2502
+ bar: "Bar",
2503
+ Pa: "Pascals",
2504
+ kPa: "Kilopascals",
2505
+ MPa: "Megapascals",
2506
+ kPsi: "Kilo pounds per square inch",
2507
+ "kPa/m": "Kilopascals per meter",
2508
+ "psi/ft": "Psi per foot",
2509
+ "bar/100m": "Bars per 100m",
2510
+ "psi/100ft": "Psi per 100ft",
2511
+ "kPa/100m": "Kilopascals per 100m",
2512
+ C: "Degrees Celsius",
2513
+ F: "Degrees Fahrenheit",
2514
+ K: "Kelvins",
2515
+ "C/100m": "Degrees Celsius per 100m",
2516
+ "F/100ft": "Degrees Fahrenheit per 100m",
2517
+ "K/100m": "Kelvins per 100m",
2518
+ "lbf/ft": "Pound force / foot",
2519
+ "Pa/C": "Pascal per celsius",
2520
+ "Bar/C": "Bar per celsius",
2521
+ "psi/F": "Psi per fahrenheit",
2522
+ "psi/C": "Psi per celsius",
2523
+ N: "Newtons",
2524
+ kN: "Kilo Newtons",
2525
+ "N/m": "Newtons per meter",
2526
+ "daN/m": "Decanewtons per meter",
2527
+ lbf: "Pound force",
2528
+ kgf: "Kilogram force",
2529
+ rad: "Radians",
2530
+ "BTU/lbm": "British Thermal Units per pound",
2531
+ ppf: "Pound per foot",
2532
+ "kg/m": "Kilograms per meter",
2533
+ "E-06/degC": "Micro per degree Celsius",
2534
+ "E-06/degF": "Micro per degree Fahrenheit",
2535
+ km2: "Square kilometers",
2536
+ ft2: "Square feet",
2537
+ mm2: "Square millimeters",
2538
+ mile2: "Square miles",
2539
+ ft3: "Cubic feet",
2540
+ "g/cm3": "Grams per cubic centimeter",
2541
+ Sm3: "Standard cubic meter",
2542
+ "ft3/s": "Cubic feet per second",
2543
+ "ft3/d": "Cubic feet per day",
2544
+ "m3/d": "Cubic meter per day",
2545
+ "1/m3/d": "Inverse Cubic meter per day",
2546
+ "s/m3": "Seconds per cubic meters",
2547
+ "bbl/d": "Barrels per day",
2548
+ tonneForce: "Tonne force",
2549
+ USGal: "US gallon",
2550
+ "g/mol": "Grams per mol",
2551
+ Nm: "Newton meter",
2552
+ kNm: "Kilo Newton meter",
2553
+ ftlbf: "Foot pound",
2554
+ "J/(kg*degC)": "Joules per kilogram degree Celsius",
2555
+ "J/(kg*degK)": "Joules per kilogram degree Kelwin",
2556
+ "BTU/(lbm*degF)": "British Thermal Unit per pound Fahrenheit",
2557
+ "BTU/(h*ft*degF)": "British Thermal Units per hour feet degree Fahrenheit",
2558
+ l: "Litres",
2559
+ "l/m": "Litres per meter",
2560
+ "kJ/kg": "Kilo joules per kilogram",
2561
+ "J/kg": "Joules per kilogram",
2562
+ deg: "Degrees",
2563
+ "W/(mK)": "Watts per milli Kelvin",
2564
+ psi: "Pounds per square inch",
2565
+ "1/bar": "1/bar",
2566
+ "1/psi": "1/psi",
2567
+ "deg/100ft": "Degrees per 100ft",
2568
+ "deg/10m": "Degrees per 10m",
2569
+ "deg/30m": "Degrees per 30m",
2570
+ "%": "Percent",
2571
+ Hz: "Hertz",
2572
+ "1/s": "Inverse second",
2573
+ rpm: "Revolutions per minute",
2574
+ "Pa/m": "Pascal per meter",
2575
+ "bar/m": "Bar per meter",
2576
+ gpm: "Gallons per minute",
2577
+ "kg/s": "Kilograms per second",
2578
+ "lbm/s": "Pound mass per second",
2579
+ "tonnes/h": "Tonnes per hour",
2580
+ "tons/h": "Tons per hour",
2581
+ "deg/m": "Degrees per meter",
2582
+ "deg/ft": "Degrees per foot",
2583
+ "rad/m": "Radians per meter",
2584
+ "rad/ft": "Radians per foot",
2585
+ "dyn/cm": "Dyn per centimeter",
2586
+ "mN/m": "Millinewtons per meter",
2587
+ "1/kPa": "1/kPa",
2588
+ m3: "Cubic meters",
2589
+ "m/s": "Meters per second",
2590
+ "ft/s": "Feet per second",
2591
+ "m/min": "Meters per minute",
2592
+ "ft/min": "Feet per min",
2593
+ "m/h": "Meters per hour",
2594
+ "ft/h": "Feet per hour",
2595
+ mph: "Miles per hour",
2596
+ "km/h": "Kilometers per hour",
2597
+ "m/s2": "Meters per second squared",
2598
+ "ft/s2": "Feet per second squared",
2599
+ "Pa*s": "Pascal seconds",
2600
+ P: "Poise (dyne second per square centimeter)",
2601
+ "mPa*s": "Millipascal seconds",
2602
+ cP: "Centi Poise",
2603
+ W: "Watts",
2604
+ hhp: "Hydraulic horsepower",
2605
+ hp: "Horsepower",
2606
+ kW: "Kilowatts",
2607
+ MW: "Megawatts",
2608
+ "BTU/h": "British Thermal Units per hour",
2609
+ "hhp/in2": "Hydraulic horsepower per square inch",
2610
+ "hhp/ft2": "Hydraulic horsepower per square feet",
2611
+ "Mm3/d": "Mega cubic meters per day",
2612
+ "STB/d": "Stock Tank Barrel per day",
2613
+ "Sm3/d": "Standard cubic meters per day",
2614
+ "Sm3/min": "Standard cubic meters per minute",
2615
+ "MSm3/d": "Mega standard cubic meters per day",
2616
+ "SCF/STB": "Standard Cubic Feet per Stock Tank Barrel",
2617
+ "Sm3/Sm3": "Standard cubic meters per Standard cubic meter",
2618
+ "SCF/d": "Standard cubic feet per day",
2619
+ STB: "Stock Tank Barrel",
2620
+ SCF: "Standard Cubic Feet",
2621
+ Gsg: "Gas - specific gravity",
2622
+ Gppg: "Gas - pounds per gallon",
2623
+ "Gkg/m3": "Gas - kilogram per cubic meters",
2624
+ "Glbm/ft3": "Gas - pounds per cubic foot",
2625
+ MSm3: "Mega standard cubic meters",
2626
+ "m3/s/bar": "Cubic per second per bar",
2627
+ "Sm3/d/bar": "Standard cubic per day per bar",
2628
+ "STB/d/psi": "Standard barrels per day per psi",
2629
+ klbf: "kilopound force",
2630
+ "1/Pa": "1/Pascal",
2631
+ "1/MPa": "1/MPa",
2632
+ ksi: "Kilopound per square inch",
2633
+ "lbf/100ft2": "Pounds per 100 square foot",
2634
+ "lb/ft3": "lb/ft3",
2635
+ "°N": "°N (latitude)",
2636
+ "°S": "°S (latitude)",
2637
+ "°W": "°W (longitude)",
2638
+ "°E": "°E (longitude)",
2639
+ fr: "Fraction",
2640
+ mD: "Millidarcy",
2641
+ Sigma: "Sigma",
2642
+ CI: "Confidence Interval",
2643
+ "J/(s*m*degK)": "Joules per second meter Kelvin",
2644
+ "C/m": "Degrees Celsius per meter",
2645
+ "F/ft": "Degrees Fahrenheit per meter",
2646
+ "K/m": "Kelvin per meter",
2647
+ microM: "Micro meter",
2648
+ "W/m2": "Watt per square meter",
2649
+ "1/K": "Inverse Kelvin",
2650
+ "lb/ft": "Pound Per Feet",
2651
+ "E-09/bar": "Nano per bar",
2652
+ "E-10/psi": "10⁻¹⁰ per psi",
2653
+ "E-14/pa": "10⁻¹⁴ per pascal",
2654
+ lk: "Link",
2655
+ ftCla: "Clark`s foot",
2656
+ lkCla: "Clark`s link",
2657
+ ftSe: "British foot (Sears 1922)",
2658
+ ydSe: "British yard (Sears 1922)",
2659
+ chSe: "British chain (Sears 1922)",
2660
+ "chSe(T)": "British chain (Sears 1922 Truncated)",
2661
+ ftGC: "Gold Coast foot",
2662
+ ydInd: "Indian yard",
2663
+ "d/stand": "Day per stand",
2664
+ "h/stand": "Hour per stand",
2665
+ "min/stand": "Minute per stand",
2666
+ "s/stand": "Second per stand",
2667
+ "m3/t": "Cubic meter per ton",
2668
+ "L/100kg": "Liter per 100kg",
2669
+ GPa: "Gigapascals, unit of pressure",
2670
+ "cm3/m": "Cubic cm per meter",
2671
+ "in3/ft": "Cubic inches per foot",
2672
+ "ft3/ft": "Cubic feet per foot",
2673
+ "m3/m": "Cubic meters per meter",
2674
+ "mm3/m": "Cubic millimeters per meter",
2675
+ "1/GPa": "Inverse gigapascal",
2676
+ lps: "Liters per second",
2677
+ nT: "nanoTesla",
2678
+ Gs: "Gauss",
2679
+ g: "g force"
2680
+ };
2681
+ //#endregion
2682
+ //#region src/validate/ajv-validators.ts
2683
+ var import_ucs2length = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports) => {
2684
+ Object.defineProperty(exports, "__esModule", { value: true });
2685
+ function ucs2length(str) {
2686
+ const len = str.length;
2687
+ let length = 0;
2688
+ let pos = 0;
2689
+ let value;
2690
+ while (pos < len) {
2691
+ length++;
2692
+ value = str.charCodeAt(pos++);
2693
+ if (value >= 55296 && value <= 56319 && pos < len) {
2694
+ value = str.charCodeAt(pos);
2695
+ if ((value & 64512) === 56320) pos++;
2696
+ }
2697
+ }
2698
+ return length;
2699
+ }
2700
+ exports.default = ucs2length;
2701
+ ucs2length.code = "require(\"ajv/dist/runtime/ucs2length\").default";
2702
+ })))(), 1);
2703
+ import_ucs2length.default.default ?? import_ucs2length.default;
2704
+ const numberSchemaValidator = validate15;
2705
+ function validate15(data, { instancePath = "", parentData, parentDataProperty, rootData = data } = {}) {
2706
+ validate15.errors = null;
2707
+ let vErrors = null;
2708
+ let errors = 0;
2709
+ if (!(typeof data == "number" && isFinite(data))) {
2710
+ const err0 = {
2711
+ instancePath,
2712
+ schemaPath: "#/type",
2713
+ keyword: "type",
2714
+ params: { type: "number" },
2715
+ message: "must be number"
2716
+ };
2717
+ if (vErrors === null) vErrors = [err0];
2718
+ else vErrors.push(err0);
2719
+ errors++;
2720
+ }
2721
+ if (errors > 0) {
2722
+ const emErrs0 = [];
2723
+ for (const err1 of vErrors) if (err1.keyword !== "errorMessage" && !err1.emUsed && (err1.instancePath === instancePath || err1.instancePath.indexOf(instancePath) === 0 && err1.instancePath[instancePath.length] === "/") && err1.schemaPath.indexOf("#") === 0 && err1.schemaPath[1] === "/") {
2724
+ emErrs0.push(err1);
2725
+ err1.emUsed = true;
2726
+ }
2727
+ if (emErrs0.length) {
2728
+ const err2 = {
2729
+ instancePath,
2730
+ schemaPath: "#/errorMessage",
2731
+ keyword: "errorMessage",
2732
+ params: { errors: emErrs0 },
2733
+ message: "Must be a numerical value"
2734
+ };
2735
+ if (vErrors === null) vErrors = [err2];
2736
+ else vErrors.push(err2);
2737
+ errors++;
2738
+ }
2739
+ const emErrs1 = [];
2740
+ for (const err3 of vErrors) if (!err3.emUsed) emErrs1.push(err3);
2741
+ vErrors = emErrs1;
2742
+ errors = emErrs1.length;
2743
+ }
2744
+ validate15.errors = vErrors;
2745
+ return errors === 0;
2746
+ }
2747
+ //#endregion
2748
+ //#region src/validate/errors-transform.ts
2749
+ const transformErrors = (errors) => {
2750
+ return errors?.map(({ message }) => message);
2751
+ };
2752
+ //#endregion
2753
+ //#region src/units.ts
2754
+ const SEPARATOR = "|";
2755
+ const UNIT_RE = /^(-?[0-9., /]*?(?:e[-+]?[0-9]+)?)([^0-9-., /].*)?$/;
2756
+ const EXP_NOTATION_RE = /^[-+]?[0-9]*\.?[0-9]+(?:\/[0-9]*\.?[0-9]+)?(?:[eE][-+]?[0-9]+)?$/;
2757
+ /**
2758
+ * Get list of units for a given quantity
2759
+ *
2760
+ * @param quantityKey
2761
+ * @return []
2762
+ */
2763
+ function showAltUnitsList(quantityKey) {
2764
+ return ALT_UNITS[quantityKey];
2765
+ }
2766
+ /**
2767
+ * Get list of units for a given quantity
2768
+ *
2769
+ * @param quantity
2770
+ * @return [] | undefined
2771
+ */
2772
+ function getUnitsForQuantity(quantity) {
2773
+ return showAltUnitsList(quantity);
2774
+ }
2775
+ /**
2776
+ * Get list of all defined quantities
2777
+ * @returns []
2778
+ */
2779
+ function getQuantities() {
2780
+ return Object.keys(ALT_UNITS);
2781
+ }
2782
+ /**
2783
+ * Get unit label
2784
+ *
2785
+ * @param unitKey
2786
+ * @return string|undefined
2787
+ */
2788
+ function label(unitKey) {
2789
+ return LABELS[unitKey];
2790
+ }
2791
+ /**
2792
+ * Get unit by quantity
2793
+ *
2794
+ * @param quantity
2795
+ * @return string|undefined
2796
+ */
2797
+ function unitFromKey(quantity) {
2798
+ return UNIT_FROM_KEY[quantity];
2799
+ }
2800
+ /**
2801
+ * Get unit by quantity
2802
+ *
2803
+ * @param quantity
2804
+ * @return string|undefined
2805
+ */
2806
+ function unitFromQuantity(quantity) {
2807
+ return unitFromKey(quantity);
2808
+ }
2809
+ /**
2810
+ * Get list of alternative units, with labels, for a given quantity.
2811
+ *
2812
+ * @param quantity
2813
+ * @return AltUnitWithLabel[]|undefined
2814
+ */
2815
+ function getAltUnitsListByQuantity(quantity) {
2816
+ const quantityUnitList = showAltUnitsList(quantity);
2817
+ return quantityUnitList ? quantityUnitList.map((unit) => ({
2818
+ unit,
2819
+ label: label(unit)
2820
+ })) : void 0;
2821
+ }
2822
+ /**
2823
+ * Find double dot and comma in value and replace it with decimal dot.
2824
+ * For example: 123,4 => 123.4 or 123..4 => 123.4
2825
+ *
2826
+ * @param val
2827
+ * @return string|number
2828
+ */
2829
+ function checkAndCleanDecimalComma(val) {
2830
+ const RegExForMultiDots = /\.{2,}/;
2831
+ const RegexFindComma = /,/;
2832
+ if (typeof val === "string") while (RegExForMultiDots.test(val) || RegexFindComma.test(val)) {
2833
+ val = val.replace(RegExForMultiDots, ".");
2834
+ val = val.replace(RegexFindComma, ".");
2835
+ }
2836
+ return val;
2837
+ }
2838
+ /**
2839
+ * Convert value to another unit
2840
+ *
2841
+ * @param value clean value without unit
2842
+ * @param fromUnit unit from which we are trying to convert
2843
+ * @param toUnit unit to which we are trying to convert
2844
+ * @return number|Error
2845
+ */
2846
+ function to(value, fromUnit, toUnit) {
2847
+ value = checkAndCleanDecimalComma(value);
2848
+ value = normalizeScientific(value);
2849
+ if (toUnit === "undefined") console.warn("Inconsistent \"to unit\" - debug call to \"Units.to()\"");
2850
+ if (fromUnit === "undefined") {
2851
+ fromUnit = toUnit;
2852
+ console.warn("Inconsistent \"from unit\" - debug call to \"Units.to()\"");
2853
+ }
2854
+ if (fromUnit === toUnit) return toNum(value);
2855
+ if (value === Infinity || value === "Infinity") return Infinity;
2856
+ if (value === -Infinity || value === "-Infinity") return -Infinity;
2857
+ if (isNonNumerical(value) && value !== "") return NaN;
2858
+ const conv = KNOWN_CONVERSIONS[fromUnit + "|" + toUnit];
2859
+ if (conv) return conv(toNum(value));
2860
+ if (DEPRECATED_UNITS[fromUnit]) {
2861
+ console.warn(`Unit '${fromUnit}' is deprecated - use '${DEPRECATED_UNITS[fromUnit]}' instead.`);
2862
+ return to(value, DEPRECATED_UNITS[fromUnit], toUnit);
2863
+ }
2864
+ if (DEPRECATED_UNITS[toUnit]) {
2865
+ console.warn(`Unit '${toUnit}' is deprecated - use '${DEPRECATED_UNITS[toUnit]}' instead.`);
2866
+ return to(value, fromUnit, DEPRECATED_UNITS[toUnit]);
2867
+ }
2868
+ if (UNIT_ALIASES[toUnit]) return to(value, fromUnit, UNIT_ALIASES[toUnit]);
2869
+ if (UNIT_ALIASES[fromUnit]) return to(value, UNIT_ALIASES[fromUnit], toUnit);
2870
+ const int_from = INTERMEDIATE_CONVERSIONS[fromUnit];
2871
+ if (int_from) return to(to(value, fromUnit, int_from), int_from, toUnit);
2872
+ else {
2873
+ const int_to = INTERMEDIATE_CONVERSIONS[toUnit];
2874
+ if (toUnit && int_to && int_to !== toUnit) return to(to(value, fromUnit, int_to), int_to, toUnit);
2875
+ }
2876
+ console.error("no conversions found", value, fromUnit, "->", toUnit);
2877
+ throw new Error("No conversions found: " + value + " " + fromUnit + " -> " + toUnit);
2878
+ }
2879
+ /**
2880
+ * Split string into value and unit
2881
+ *
2882
+ * @param numWithUnit
2883
+ * @return string[] where first element it's actual value and second unit
2884
+ */
2885
+ function split(numWithUnit) {
2886
+ let m;
2887
+ let vu = numWithUnit !== void 0 && numWithUnit !== null ? String(numWithUnit) : "";
2888
+ if (charCount("|", vu) > 1) {
2889
+ m = vu.split("|");
2890
+ vu = m.slice(0, -1).join("") + "|" + m.slice(-1);
2891
+ }
2892
+ if (vu.indexOf("|") >= 0) m = vu.split("|");
2893
+ else if (SPECIAL_NUMBERS_STRING.includes(vu)) m = [vu, ""];
2894
+ else {
2895
+ m = cleanNumStr(vu).match(UNIT_RE);
2896
+ if (m) m = m.slice(1);
2897
+ }
2898
+ if (!m) m = ["0", ""];
2899
+ if (m[1] == null) m[1] = "";
2900
+ return [m[0], m[1]];
2901
+ }
2902
+ /**
2903
+ * Get value of the number with unit string ("1|m") will return "1"
2904
+ * @param {sting} numWithUnit
2905
+ * @returns {string}
2906
+ */
2907
+ function getValue(numWithUnit) {
2908
+ return split(numWithUnit)[0];
2909
+ }
2910
+ /**
2911
+ * Get unit of the number with unit string ("1|m") will return "m"
2912
+ * @param {sting} numWithUnit
2913
+ * @returns {string}
2914
+ */
2915
+ function getUnit(numWithUnit) {
2916
+ return split(numWithUnit)[1];
2917
+ }
2918
+ /**
2919
+ * Convert value with unit to another unit
2920
+ *
2921
+ * @param numWithUnit value with unit
2922
+ * @param toUnit unit to which we are trying to convert
2923
+ * @param fromUnit unit from which we are trying to convert
2924
+ */
2925
+ function unum(numWithUnit, toUnit, fromUnit) {
2926
+ if (numWithUnit == null || numWithUnit === "") return 0;
2927
+ if (typeof numWithUnit === "string" && numWithUnit.startsWith("NaN") || typeof numWithUnit === "number" && isNaN(numWithUnit)) return NaN;
2928
+ const m = split(cleanNumStr(normalizeScientific(numWithUnit)).replaceAll("+", ""));
2929
+ if (!m) if (toUnit && fromUnit) return unum(numWithUnit + fromUnit, toUnit);
2930
+ else throw new Error("unum: invalid number: " + numWithUnit);
2931
+ if (m[0] == null) m[0] = "0";
2932
+ if (m[1]) fromUnit = m[1];
2933
+ if (!fromUnit && toUnit !== fromUnit) throw new Error(`unum: unable to figure out unit: ${numWithUnit} fromUnit ${fromUnit}`);
2934
+ if (toUnit === fromUnit) {
2935
+ const v = m[0] ? toNum(m[0]) : 0;
2936
+ if (v === Infinity || v === "Infinity") return Infinity;
2937
+ if (v === -Infinity || v === "-Infinity") return -Infinity;
2938
+ if (typeof v === "string" && EXP_NOTATION_RE.test(v)) return parseFloat(v);
2939
+ if (!isNumeric(v) && v !== Infinity && v !== -Infinity) throw new Error("unum: invalid number: " + v + ", " + typeof v);
2940
+ return cleanNum(v);
2941
+ }
2942
+ return to(m[0], fromUnit, toUnit);
2943
+ }
2944
+ /**
2945
+ * Takes user input and returns true if it was input with unit and false in every other case
2946
+ *
2947
+ * @param {String|Number} value
2948
+ * @returns {Boolean}
2949
+ */
2950
+ function isValueWithUnit(value) {
2951
+ if (!value) return false;
2952
+ const splittedValue = String(value).split("|");
2953
+ return splittedValue.length === 2 && KNOWN_UNITS.includes(splittedValue[1]);
2954
+ }
2955
+ /**
2956
+ * Convert value to another unit
2957
+ *
2958
+ * @param numWithUnit value (with optional unit string)
2959
+ * @param toUnit unit to which we are trying to convert
2960
+ * @param fromUnit unit from which we are trying to convert
2961
+ */
2962
+ function convertAndGetValue(numWithUnit, toUnit, fromUnit) {
2963
+ return unum(numWithUnit, toUnit, fromUnit);
2964
+ }
2965
+ /**
2966
+ * Convert value to another unit (preserves types and empty values)
2967
+ *
2968
+ * @param value value (with optional unit string)
2969
+ * @param toUnit unit to which we are trying to convert
2970
+ * @param fromUnit unit from which we are trying to convert
2971
+ */
2972
+ function convertAndGetValueStrict(value, toUnit, fromUnit) {
2973
+ if (value === "" || value === null) return value;
2974
+ if (typeof value === "string" && isValueWithUnit(value) && getValue(value) === "") return "";
2975
+ const isString = typeof value === "string";
2976
+ const result = convertAndGetValue(value, toUnit, fromUnit);
2977
+ return isString ? String(toString(result)) : result;
2978
+ }
2979
+ /**
2980
+ * Convert value to the base unit given by the quantity
2981
+ *
2982
+ * @param value
2983
+ * @param quantity
2984
+ * @return number
2985
+ */
2986
+ function toBase(value, quantity) {
2987
+ const to_unit = unitFromKey(quantity);
2988
+ return unum(value, to_unit, split((value || "").toString())[1] || to_unit);
2989
+ }
2990
+ /**
2991
+ * Convert table of values to another unit
2992
+ *
2993
+ * @param toUnitRow array of units to which we are trying to convert for example: ['ft', 'ppg']
2994
+ * @param table array which represent table for example:
2995
+ * [['m', 'sg'],
2996
+ [100, 1],
2997
+ [1000, 1.25],
2998
+ [2000, 1.5],
2999
+ [3000, 1.1]]
3000
+ * @param defaultUnitRow
3001
+ * @param removeFinalUnitsRow if true first table row where we define units will be removed
3002
+ */
3003
+ function convertTable(toUnitRow, table, defaultUnitRow, removeFinalUnitsRow = false) {
3004
+ if (!table || !table.length || !table[0].length) return table;
3005
+ if (!toUnitRow) toUnitRow = table[0];
3006
+ if (!defaultUnitRow) defaultUnitRow = toUnitRow;
3007
+ const firstCell = table[0][0];
3008
+ const splittedFirstCell = firstCell && split(`${firstCell}`);
3009
+ const tableHasUnits = !(splittedFirstCell && splittedFirstCell[0] && isNaN(splittedFirstCell[1])) && isNaN(table[0][0]);
3010
+ let ix = tableHasUnits ? 1 : 0;
3011
+ const fromunitrow = tableHasUnits ? table[0] : defaultUnitRow;
3012
+ const newTable = [toUnitRow];
3013
+ for (; ix < table.length; ix++) {
3014
+ const cols = Array(toUnitRow.length);
3015
+ const coli = table[ix];
3016
+ for (let uix = 0; uix < cols.length; uix++) cols[uix] = toUnitRow[uix] && coli[uix] ? unum(coli[uix], toUnitRow[uix], fromunitrow[uix]) : coli[uix];
3017
+ newTable.push(cols);
3018
+ }
3019
+ if (removeFinalUnitsRow) newTable.shift();
3020
+ return newTable;
3021
+ }
3022
+ /**
3023
+ * Rounds a unit string to N decimal places and appends formatted unit label
3024
+ *
3025
+ * @param value
3026
+ * @param n number of decimal digits
3027
+ * @return rounded value with formatted units
3028
+ */
3029
+ function roundNumberWithLabel(value, n = 2) {
3030
+ return displayNumber(round(value, n), { withUnit: true });
3031
+ }
3032
+ /**
3033
+ * Get value with unit splitted by | separator
3034
+ *
3035
+ * @param value
3036
+ * @param unit
3037
+ * @param defaultVal
3038
+ * @return string
3039
+ */
3040
+ function withUnit(value, unit, defaultVal = "") {
3041
+ if (value === null || value === "" || value === void 0) value = defaultVal;
3042
+ if (unit === null) return String(value);
3043
+ let [v, u] = String(value).includes("|") ? split(String(value)) : [value, unit];
3044
+ if (!u) u = unit;
3045
+ return [v, u].join("|");
3046
+ }
3047
+ /**
3048
+ * Converts to given toUnit and return the converted value with unit.
3049
+ * @see roundNumberWithLabel
3050
+ *
3051
+ * @param numWithUnit value with unit
3052
+ * @param toUnit unit to which we are trying to convert
3053
+ * @param fromUnit unit from which we are trying to convert
3054
+ * @return {string} - "number converted | unit"
3055
+ */
3056
+ function unumWithUnit(numWithUnit, toUnit, fromUnit) {
3057
+ return withUnit(unum(numWithUnit, toUnit, fromUnit), toUnit);
3058
+ }
3059
+ /**
3060
+ * Convert value with unit to another unit and display it in pretty format.
3061
+ * It will preserv the number of digits in the input or alternativly converting to the given number of digits
3062
+ *
3063
+ * @param {string|number} numWithUnit - value with unit
3064
+ * @param {string} toUnit - unit to which we are trying to convert
3065
+ * @param {number} digits - optional number of digits to round the number
3066
+ * @returns {string} - converted number including the unit (number|unit)
3067
+ */
3068
+ function convertSamePrecision(numWithUnit, toUnit, digits) {
3069
+ const validNumWithUnit = String(numWithUnit);
3070
+ const m = split(validNumWithUnit);
3071
+ const convertedNumber = !m[1] || m[1] == toUnit ? Number(m[0]) : to(m[0], String(m[1]), toUnit);
3072
+ let prettyNumber = "0";
3073
+ let targetDigits = digits;
3074
+ if (convertedNumber !== 0) {
3075
+ if (!targetDigits) {
3076
+ if (m[1] === toUnit) return validNumWithUnit;
3077
+ const regx = String(m[0]).match(/^[-+.,0]*(\d*)[.,]?(\d*)/);
3078
+ if (regx) targetDigits = Math.max(3, regx[1].length + regx[2].length);
3079
+ else targetDigits = 3;
3080
+ }
3081
+ const lim = Math.pow(10, --targetDigits);
3082
+ const absNum = Math.abs(convertedNumber);
3083
+ if (absNum >= 1e5 * lim || absNum * 1e4 * (1 + lim) < lim) prettyNumber = convertedNumber.toExponential(targetDigits);
3084
+ else if (absNum >= lim) prettyNumber = convertedNumber.toFixed();
3085
+ else {
3086
+ const digs = Math.floor(Math.log10(absNum));
3087
+ prettyNumber = convertedNumber.toFixed(targetDigits - digs);
3088
+ let j = prettyNumber.length;
3089
+ if (prettyNumber[--j] == "0") {
3090
+ while (prettyNumber[--j] == "0");
3091
+ prettyNumber = prettyNumber.slice(0, j + (prettyNumber[j] == "." ? 0 : 1));
3092
+ }
3093
+ }
3094
+ }
3095
+ return withUnit(prettyNumber, toUnit);
3096
+ }
3097
+ /**
3098
+ * Get list of values, with same precision as the given value, in all the units of the given quantity
3099
+ *
3100
+ * @param {string} value
3101
+ * @param {string} quantity
3102
+ * @return {[][string, string, string]}
3103
+ */
3104
+ function altUnitsList(value, quantity) {
3105
+ let v = value;
3106
+ if (!getUnit(value)) v = withUnit(value, unitFromQuantity(quantity) ?? "");
3107
+ return (ALT_UNITS[quantity] ?? []).map((unit) => [...split(convertSamePrecision(v, unit)), label(unit)]);
3108
+ }
3109
+ /**
3110
+ * Validates and cleans raw text numeric user input, typically from UnitInput
3111
+ * The previous value is for optionally determining the pre-existing unit
3112
+ * The next text is a raw input string
3113
+ * The return value is reformatted from the next text (removing invalid patterns)
3114
+ *
3115
+ * @param {String} previousValue with optional unit e.g. `25|m`
3116
+ * @param {String} nextText raw text for next value e.g. `26` (no unit)
3117
+ * @returns {String} e.g. `26|m`
3118
+ */
3119
+ function validateAndClean(previousValue, nextText) {
3120
+ const unit = split(previousValue)[1];
3121
+ const cleanedValue = nextText.replace(/[^0-9.,-Ee]/g, "").replace(/^([^(e|E)]*[eE])|[eE]/g, "$1").replace(/^[E|e]*|[E|e]*$/g, "").replace(/,/g, ".").replace(/^([^.]*\.)|\./g, "$1").replace(/\.(?=e)/g, "").replace(/-|[eE]-/g, (match, offset) => offset === 0 || match.toLowerCase() === "e-" ? match : "");
3122
+ return !Number.isFinite(+cleanedValue) ? previousValue : `${cleanedValue}${unit ? "|" : ""}${unit}`;
3123
+ }
3124
+ /**
3125
+ * Takes string included value with units and return display it in pretty format.
3126
+ *
3127
+ * @param {String} valueWithUnits
3128
+ * @returns {String}
3129
+ */
3130
+ function withPrettyUnitLabel(valueWithUnits) {
3131
+ const [val, unit] = split(valueWithUnits);
3132
+ return `${val} ${LABELS[unit] ?? ""}`;
3133
+ }
3134
+ function validateNumber(value) {
3135
+ let val = value;
3136
+ if (typeof value === "string" && isValueWithUnit(value)) val = getValue(value);
3137
+ val = checkAndCleanDecimalComma(val);
3138
+ if (isNumeric(val)) return {
3139
+ valid: numberSchemaValidator(toNum(val)),
3140
+ errors: transformErrors(numberSchemaValidator.errors)
3141
+ };
3142
+ return {
3143
+ valid: numberSchemaValidator(val),
3144
+ errors: transformErrors(numberSchemaValidator.errors)
3145
+ };
3146
+ }
3147
+ //#endregion
3148
+ Object.defineProperty(exports, "ALT_UNITS", {
3149
+ enumerable: true,
3150
+ get: function() {
3151
+ return ALT_UNITS;
3152
+ }
3153
+ });
3154
+ Object.defineProperty(exports, "DEPRECATED_UNITS", {
3155
+ enumerable: true,
3156
+ get: function() {
3157
+ return DEPRECATED_UNITS;
3158
+ }
3159
+ });
3160
+ Object.defineProperty(exports, "EXP_NOTATION_RE", {
3161
+ enumerable: true,
3162
+ get: function() {
3163
+ return EXP_NOTATION_RE;
3164
+ }
3165
+ });
3166
+ Object.defineProperty(exports, "INTERMEDIATE_CONVERSIONS", {
3167
+ enumerable: true,
3168
+ get: function() {
3169
+ return INTERMEDIATE_CONVERSIONS;
3170
+ }
3171
+ });
3172
+ Object.defineProperty(exports, "KNOWN_CONVERSIONS", {
3173
+ enumerable: true,
3174
+ get: function() {
3175
+ return KNOWN_CONVERSIONS;
3176
+ }
3177
+ });
3178
+ Object.defineProperty(exports, "KNOWN_UNITS", {
3179
+ enumerable: true,
3180
+ get: function() {
3181
+ return KNOWN_UNITS;
3182
+ }
3183
+ });
3184
+ Object.defineProperty(exports, "LABELS", {
3185
+ enumerable: true,
3186
+ get: function() {
3187
+ return LABELS;
3188
+ }
3189
+ });
3190
+ Object.defineProperty(exports, "QUANTITIES_DESCRIPTION", {
3191
+ enumerable: true,
3192
+ get: function() {
3193
+ return QUANTITIES_DESCRIPTION;
3194
+ }
3195
+ });
3196
+ Object.defineProperty(exports, "SEPARATOR", {
3197
+ enumerable: true,
3198
+ get: function() {
3199
+ return SEPARATOR;
3200
+ }
3201
+ });
3202
+ Object.defineProperty(exports, "UNITS_DESCRIPTION", {
3203
+ enumerable: true,
3204
+ get: function() {
3205
+ return UNITS_DESCRIPTION;
3206
+ }
3207
+ });
3208
+ Object.defineProperty(exports, "UNIT_ALIASES", {
3209
+ enumerable: true,
3210
+ get: function() {
3211
+ return UNIT_ALIASES;
3212
+ }
3213
+ });
3214
+ Object.defineProperty(exports, "UNIT_FROM_KEY", {
3215
+ enumerable: true,
3216
+ get: function() {
3217
+ return UNIT_FROM_KEY;
3218
+ }
3219
+ });
3220
+ Object.defineProperty(exports, "allNumbers", {
3221
+ enumerable: true,
3222
+ get: function() {
3223
+ return allNumbers;
3224
+ }
3225
+ });
3226
+ Object.defineProperty(exports, "altUnitsList", {
3227
+ enumerable: true,
3228
+ get: function() {
3229
+ return altUnitsList;
3230
+ }
3231
+ });
3232
+ Object.defineProperty(exports, "asFraction", {
3233
+ enumerable: true,
3234
+ get: function() {
3235
+ return asFraction;
3236
+ }
3237
+ });
3238
+ Object.defineProperty(exports, "charCount", {
3239
+ enumerable: true,
3240
+ get: function() {
3241
+ return charCount;
3242
+ }
3243
+ });
3244
+ Object.defineProperty(exports, "checkAndCleanDecimalComma", {
3245
+ enumerable: true,
3246
+ get: function() {
3247
+ return checkAndCleanDecimalComma;
3248
+ }
3249
+ });
3250
+ Object.defineProperty(exports, "cleanNum", {
3251
+ enumerable: true,
3252
+ get: function() {
3253
+ return cleanNum;
3254
+ }
3255
+ });
3256
+ Object.defineProperty(exports, "cleanNumStr", {
3257
+ enumerable: true,
3258
+ get: function() {
3259
+ return cleanNumStr;
3260
+ }
3261
+ });
3262
+ Object.defineProperty(exports, "convertAndGetValue", {
3263
+ enumerable: true,
3264
+ get: function() {
3265
+ return convertAndGetValue;
3266
+ }
3267
+ });
3268
+ Object.defineProperty(exports, "convertAndGetValueStrict", {
3269
+ enumerable: true,
3270
+ get: function() {
3271
+ return convertAndGetValueStrict;
3272
+ }
3273
+ });
3274
+ Object.defineProperty(exports, "convertSamePrecision", {
3275
+ enumerable: true,
3276
+ get: function() {
3277
+ return convertSamePrecision;
3278
+ }
3279
+ });
3280
+ Object.defineProperty(exports, "convertTable", {
3281
+ enumerable: true,
3282
+ get: function() {
3283
+ return convertTable;
3284
+ }
3285
+ });
3286
+ Object.defineProperty(exports, "displayNumber", {
3287
+ enumerable: true,
3288
+ get: function() {
3289
+ return displayNumber;
3290
+ }
3291
+ });
3292
+ Object.defineProperty(exports, "displayNumberToFixed", {
3293
+ enumerable: true,
3294
+ get: function() {
3295
+ return displayNumberToFixed;
3296
+ }
3297
+ });
3298
+ Object.defineProperty(exports, "formatNumber", {
3299
+ enumerable: true,
3300
+ get: function() {
3301
+ return formatNumber;
3302
+ }
3303
+ });
3304
+ Object.defineProperty(exports, "fraction", {
3305
+ enumerable: true,
3306
+ get: function() {
3307
+ return fraction;
3308
+ }
3309
+ });
3310
+ Object.defineProperty(exports, "getAltUnitsListByQuantity", {
3311
+ enumerable: true,
3312
+ get: function() {
3313
+ return getAltUnitsListByQuantity;
3314
+ }
3315
+ });
3316
+ Object.defineProperty(exports, "getNumberOfDigitsToShow", {
3317
+ enumerable: true,
3318
+ get: function() {
3319
+ return getNumberOfDigitsToShow;
3320
+ }
3321
+ });
3322
+ Object.defineProperty(exports, "getQuantities", {
3323
+ enumerable: true,
3324
+ get: function() {
3325
+ return getQuantities;
3326
+ }
3327
+ });
3328
+ Object.defineProperty(exports, "getUnit", {
3329
+ enumerable: true,
3330
+ get: function() {
3331
+ return getUnit;
3332
+ }
3333
+ });
3334
+ Object.defineProperty(exports, "getUnitsForQuantity", {
3335
+ enumerable: true,
3336
+ get: function() {
3337
+ return getUnitsForQuantity;
3338
+ }
3339
+ });
3340
+ Object.defineProperty(exports, "getValue", {
3341
+ enumerable: true,
3342
+ get: function() {
3343
+ return getValue;
3344
+ }
3345
+ });
3346
+ Object.defineProperty(exports, "isCloseTo", {
3347
+ enumerable: true,
3348
+ get: function() {
3349
+ return isCloseTo;
3350
+ }
3351
+ });
3352
+ Object.defineProperty(exports, "isCloseToOrGreaterThan", {
3353
+ enumerable: true,
3354
+ get: function() {
3355
+ return isCloseToOrGreaterThan;
3356
+ }
3357
+ });
3358
+ Object.defineProperty(exports, "isCloseToOrLessThan", {
3359
+ enumerable: true,
3360
+ get: function() {
3361
+ return isCloseToOrLessThan;
3362
+ }
3363
+ });
3364
+ Object.defineProperty(exports, "isDeepCloseTo", {
3365
+ enumerable: true,
3366
+ get: function() {
3367
+ return isDeepCloseTo;
3368
+ }
3369
+ });
3370
+ Object.defineProperty(exports, "isEmptyValueWithUnit", {
3371
+ enumerable: true,
3372
+ get: function() {
3373
+ return isEmptyValueWithUnit;
3374
+ }
3375
+ });
3376
+ Object.defineProperty(exports, "isFraction", {
3377
+ enumerable: true,
3378
+ get: function() {
3379
+ return isFraction;
3380
+ }
3381
+ });
3382
+ Object.defineProperty(exports, "isNonNumerical", {
3383
+ enumerable: true,
3384
+ get: function() {
3385
+ return isNonNumerical;
3386
+ }
3387
+ });
3388
+ Object.defineProperty(exports, "isNumeric", {
3389
+ enumerable: true,
3390
+ get: function() {
3391
+ return isNumeric;
3392
+ }
3393
+ });
3394
+ Object.defineProperty(exports, "isScientificStringNum", {
3395
+ enumerable: true,
3396
+ get: function() {
3397
+ return isScientificStringNum;
3398
+ }
3399
+ });
3400
+ Object.defineProperty(exports, "isValidNum", {
3401
+ enumerable: true,
3402
+ get: function() {
3403
+ return isValidNum;
3404
+ }
3405
+ });
3406
+ Object.defineProperty(exports, "isValueWithUnit", {
3407
+ enumerable: true,
3408
+ get: function() {
3409
+ return isValueWithUnit;
3410
+ }
3411
+ });
3412
+ Object.defineProperty(exports, "label", {
3413
+ enumerable: true,
3414
+ get: function() {
3415
+ return label;
3416
+ }
3417
+ });
3418
+ Object.defineProperty(exports, "numFraction", {
3419
+ enumerable: true,
3420
+ get: function() {
3421
+ return numFraction;
3422
+ }
3423
+ });
3424
+ Object.defineProperty(exports, "round", {
3425
+ enumerable: true,
3426
+ get: function() {
3427
+ return round;
3428
+ }
3429
+ });
3430
+ Object.defineProperty(exports, "roundByMagnitude", {
3431
+ enumerable: true,
3432
+ get: function() {
3433
+ return roundByMagnitude;
3434
+ }
3435
+ });
3436
+ Object.defineProperty(exports, "roundByMagnitudeToFixed", {
3437
+ enumerable: true,
3438
+ get: function() {
3439
+ return roundByMagnitudeToFixed;
3440
+ }
3441
+ });
3442
+ Object.defineProperty(exports, "roundByRange", {
3443
+ enumerable: true,
3444
+ get: function() {
3445
+ return roundByRange;
3446
+ }
3447
+ });
3448
+ Object.defineProperty(exports, "roundNumberWithLabel", {
3449
+ enumerable: true,
3450
+ get: function() {
3451
+ return roundNumberWithLabel;
3452
+ }
3453
+ });
3454
+ Object.defineProperty(exports, "roundToDecimalPrecision", {
3455
+ enumerable: true,
3456
+ get: function() {
3457
+ return roundToDecimalPrecision;
3458
+ }
3459
+ });
3460
+ Object.defineProperty(exports, "roundToFixed", {
3461
+ enumerable: true,
3462
+ get: function() {
3463
+ return roundToFixed;
3464
+ }
3465
+ });
3466
+ Object.defineProperty(exports, "roundToPrecision", {
3467
+ enumerable: true,
3468
+ get: function() {
3469
+ return roundToPrecision;
3470
+ }
3471
+ });
3472
+ Object.defineProperty(exports, "showAltUnitsList", {
3473
+ enumerable: true,
3474
+ get: function() {
3475
+ return showAltUnitsList;
3476
+ }
3477
+ });
3478
+ Object.defineProperty(exports, "split", {
3479
+ enumerable: true,
3480
+ get: function() {
3481
+ return split;
3482
+ }
3483
+ });
3484
+ Object.defineProperty(exports, "stripLeadingZeros", {
3485
+ enumerable: true,
3486
+ get: function() {
3487
+ return stripLeadingZeros;
3488
+ }
3489
+ });
3490
+ Object.defineProperty(exports, "to", {
3491
+ enumerable: true,
3492
+ get: function() {
3493
+ return to;
3494
+ }
3495
+ });
3496
+ Object.defineProperty(exports, "toBase", {
3497
+ enumerable: true,
3498
+ get: function() {
3499
+ return toBase;
3500
+ }
3501
+ });
3502
+ Object.defineProperty(exports, "toNum", {
3503
+ enumerable: true,
3504
+ get: function() {
3505
+ return toNum;
3506
+ }
3507
+ });
3508
+ Object.defineProperty(exports, "toString", {
3509
+ enumerable: true,
3510
+ get: function() {
3511
+ return toString;
3512
+ }
3513
+ });
3514
+ Object.defineProperty(exports, "unitFromKey", {
3515
+ enumerable: true,
3516
+ get: function() {
3517
+ return unitFromKey;
3518
+ }
3519
+ });
3520
+ Object.defineProperty(exports, "unitFromQuantity", {
3521
+ enumerable: true,
3522
+ get: function() {
3523
+ return unitFromQuantity;
3524
+ }
3525
+ });
3526
+ Object.defineProperty(exports, "unum", {
3527
+ enumerable: true,
3528
+ get: function() {
3529
+ return unum;
3530
+ }
3531
+ });
3532
+ Object.defineProperty(exports, "unumWithUnit", {
3533
+ enumerable: true,
3534
+ get: function() {
3535
+ return unumWithUnit;
3536
+ }
3537
+ });
3538
+ Object.defineProperty(exports, "validateAndClean", {
3539
+ enumerable: true,
3540
+ get: function() {
3541
+ return validateAndClean;
3542
+ }
3543
+ });
3544
+ Object.defineProperty(exports, "validateNumber", {
3545
+ enumerable: true,
3546
+ get: function() {
3547
+ return validateNumber;
3548
+ }
3549
+ });
3550
+ Object.defineProperty(exports, "withPrettyUnitLabel", {
3551
+ enumerable: true,
3552
+ get: function() {
3553
+ return withPrettyUnitLabel;
3554
+ }
3555
+ });
3556
+ Object.defineProperty(exports, "withUnit", {
3557
+ enumerable: true,
3558
+ get: function() {
3559
+ return withUnit;
3560
+ }
3561
+ });
3562
+
3563
+ //# sourceMappingURL=units2.cjs.map