UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

128 lines (115 loc) 3.32 kB
/** * SI decimal prefixes, ordered from smallest to largest. Indexed by {@link magnitude_prefix_index}. * * Covers the full SI prefix range: `q` (quecto, 1e-30) through `Q` (quetta, 1e30). * * @type {string[]} */ export const MAGNITUDE_PREFIXES = [ 'q', // 1e-30 quecto 'r', // 1e-27 ronto 'y', // 1e-24 yocto 'z', // 1e-21 zepto 'a', // 1e-18 atto 'f', // 1e-15 femto 'p', // 1e-12 pico 'n', // 1e-9 nano 'µ', // 1e-6 micro 'm', // 1e-3 milli '', // 1 'k', // 1e3 kilo 'M', // 1e6 mega 'G', // 1e9 giga 'T', // 1e12 tera 'P', // 1e15 peta 'E', // 1e18 exa 'Z', // 1e21 zetta 'Y', // 1e24 yotta 'R', // 1e27 ronna 'Q' // 1e30 quetta ]; /** * Decimal scale that matches each prefix in {@link MAGNITUDE_PREFIXES}, same indexing. * * A non-prefixed value at index `i` corresponds to scale `10^(3*(i - 10))`. * * @type {number[]} */ export const MAGNITUDE_SCALES = [ 1e-30, 1e-27, 1e-24, 1e-21, 1e-18, 1e-15, 1e-12, 1e-9, 1e-6, 1e-3, 1, 1e3, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24, 1e27, 1e30 ]; /** * Index of the unit-scale (`1`) entry in {@link MAGNITUDE_PREFIXES} / {@link MAGNITUDE_SCALES}. * @type {number} */ const NEUTRAL_INDEX = 10; /** * Smallest representable scale index. * @type {number} */ const MIN_INDEX = 0; /** * Largest representable scale index. * @type {number} */ const MAX_INDEX = 20; /** * Pick the index into {@link MAGNITUDE_PREFIXES} / {@link MAGNITUDE_SCALES} that best represents * `value`. * * "Best" here means: when `value` is divided by `MAGNITUDE_SCALES[i]`, the result lies in * `[1, 1000)` whenever possible. The sign of `value` is ignored — magnitude is what matters. * * Edge cases: * - `0`, `NaN` or any non-finite value returns the neutral index (no prefix, scale = 1) * - values smaller than `MAGNITUDE_SCALES[0]` clamp to the smallest prefix * - values larger than `MAGNITUDE_SCALES[MAX_INDEX]` clamp to the largest prefix * * @param {number} value * @returns {number} */ export function magnitude_prefix_index(value) { if (!Number.isFinite(value) || value === 0) { return NEUTRAL_INDEX; } const abs = value < 0 ? -value : value; // log1000(abs) -> shift relative to the neutral index (which represents 10^0) const exponent_step = Math.floor(Math.log10(abs) / 3); let index = NEUTRAL_INDEX + exponent_step; if (index < MIN_INDEX) { index = MIN_INDEX; } else if (index > MAX_INDEX) { index = MAX_INDEX; } return index; } /** * Get the SI prefix string that best represents `value`. * * @example * magnitude_prefix(1000) // 'k' * magnitude_prefix(0.001) // 'm' * magnitude_prefix(1) // '' * magnitude_prefix(1.5e9) // 'G' * * @param {number} value * @returns {string} */ export function magnitude_prefix(value) { return MAGNITUDE_PREFIXES[magnitude_prefix_index(value)]; } /** * Get the decimal scale that pairs with {@link magnitude_prefix} for the same input. * * @example * magnitude_scale(1000) // 1000 * magnitude_scale(0.001) // 0.001 * * @param {number} value * @returns {number} */ export function magnitude_scale(value) { return MAGNITUDE_SCALES[magnitude_prefix_index(value)]; }