Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
68 lines
2.9 KiB
Plaintext
68 lines
2.9 KiB
Plaintext
import { Decimal } from "decimal.js";
|
|
import "../types/number.js";
|
|
import { invariant } from "../utils.js";
|
|
import { getPowerOf10 } from "./decimal-cache.js";
|
|
Decimal.set({ toExpPos: 100 });
|
|
/**
|
|
* The abstract operation ComputeExponentForMagnitude computes an exponent by which to scale a
|
|
* number of the given magnitude (power of ten of the most significant digit) according to the
|
|
* locale and the desired notation (scientific, engineering, or compact).
|
|
*/
|
|
export function ComputeExponentForMagnitude(internalSlots, magnitude) {
|
|
const { notation, dataLocaleData, numberingSystem } = internalSlots;
|
|
switch (notation) {
|
|
case "standard": return 0;
|
|
case "scientific": return magnitude.toNumber();
|
|
case "engineering":
|
|
const thousands = magnitude.div(3).floor();
|
|
return thousands.times(3).toNumber();
|
|
default: {
|
|
invariant(notation === "compact", "Invalid notation");
|
|
// Let exponent be an implementation- and locale-dependent (ILD) integer by which to scale a
|
|
// number of the given magnitude in compact notation for the current locale.
|
|
const { compactDisplay, style, currencyDisplay } = internalSlots;
|
|
let thresholdMap;
|
|
if (style === "currency" && currencyDisplay !== "name") {
|
|
const currency = dataLocaleData.numbers.currency[numberingSystem] || dataLocaleData.numbers.currency[dataLocaleData.numbers.nu[0]];
|
|
thresholdMap = currency.short;
|
|
} else {
|
|
const decimal = dataLocaleData.numbers.decimal[numberingSystem] || dataLocaleData.numbers.decimal[dataLocaleData.numbers.nu[0]];
|
|
thresholdMap = compactDisplay === "long" ? decimal.long : decimal.short;
|
|
}
|
|
if (!thresholdMap) {
|
|
return 0;
|
|
}
|
|
const num = getPowerOf10(magnitude).toString();
|
|
const thresholds = Object.keys(thresholdMap);
|
|
if (num < thresholds[0]) {
|
|
return 0;
|
|
}
|
|
if (num > thresholds[thresholds.length - 1]) {
|
|
// GH #4236: When number exceeds max threshold, use the exponent
|
|
// corresponding to the largest available threshold in locale data.
|
|
// Calculate exponent the same way as for normal thresholds (lines 70-73).
|
|
const magnitudeKey = thresholds[thresholds.length - 1];
|
|
const compactPattern = thresholdMap[magnitudeKey].other;
|
|
if (compactPattern === "0") {
|
|
return 0;
|
|
}
|
|
return magnitudeKey.length - thresholdMap[magnitudeKey].other.match(/0+/)[0].length;
|
|
}
|
|
const i = thresholds.indexOf(num);
|
|
if (i === -1) {
|
|
return 0;
|
|
}
|
|
// See https://unicode.org/reports/tr35/tr35-numbers.html#Compact_Number_Formats
|
|
// Special handling if the pattern is precisely `0`.
|
|
const magnitudeKey = thresholds[i];
|
|
// TODO: do we need to handle plural here?
|
|
const compactPattern = thresholdMap[magnitudeKey].other;
|
|
if (compactPattern === "0") {
|
|
return 0;
|
|
}
|
|
// Example: in zh-TW, `10000000` maps to `0000萬`. So we need to return 8 - 4 = 4 here.
|
|
return magnitudeKey.length - thresholdMap[magnitudeKey].other.match(/0+/)[0].length;
|
|
}
|
|
}
|
|
}
|