{"version":3,"file":"number.mjs","names":[],"sources":["../src/number.ts"],"sourcesContent":["import { dual } from './utils.ts'\n\nconst PRECISION = 8\n\n/**\n * Default tolerance for approximate equality between floating-point numbers.\n *\n * @since 1.1.0\n */\nexport const EPSILON = 1e-10\n\n/**\n * Approximate equality between two numbers, within an absolute tolerance.\n *\n * @param a - The first value.\n * @param b - The second value.\n * @param eps - The maximum allowed absolute difference. Defaults to {@link EPSILON}.\n * @returns `true` when `|a - b| <= eps`.\n * @since 1.1.0\n */\nexport function epsEquals(a: number, b: number, eps: number = EPSILON): boolean {\n  return Math.abs(a - b) <= eps\n}\n\n/**\n * Snaps near-zero values to exactly zero for stable sign tests.\n *\n * @param value - The value to test.\n * @param eps - The threshold below which `value` is considered zero.\n * @returns `0` when `|value| < eps`, otherwise `value` unchanged.\n * @since 1.1.0\n */\nexport function clampToZero(value: number, eps: number): number {\n  return Math.abs(value) < eps ? 0 : value\n}\n\n/**\n * Rounding function that rounds a number to a specified precision.\n *\n * @param value - The number to round.\n * @param precision - The number of decimal places to round to (default is 8).\n * @returns The rounded number.\n * @example\n * ```ts\n * import { round } from 'curvy/utils'\n *\n * const roundedValue = round(1.23456789, 4) // 1.2346\n * const roundedValue2 = round(1.23456789) // 1.23456789\n * ```\n * @since 1.0.0\n */\nexport function round(value: number, precision = PRECISION): number {\n  const scale = 10 ** precision\n  const result = Math.round(value * scale) / scale\n  if (result === 0) {\n    return 0\n  }\n  return result\n}\n\n/**\n * Rounding function that rounds a number down to a specified precision.\n *\n * @param value - The number to round down.\n * @param precision - The number of decimal places to round down to (default is 8).\n * @returns The rounded down number.\n * @example\n * ```ts\n * import { roundDown } from 'curvy/utils'\n *\n * const roundedDownValue = roundDown(1.23456789, 4) // 1.2345\n * const roundedDownValue2 = roundDown(1.23456789) // 1.23456789\n * ```\n * @since 1.0.0\n */\nexport function roundDown(value: number, precision = PRECISION): number {\n  const scale = 10 ** precision\n  const result = Math.floor(value * scale) / scale\n  if (result === 0) {\n    return 0\n  }\n  return result\n}\n\n/**\n * Rounding function that rounds a number up to a specified precision.\n *\n * @param value - The number to round up.\n * @param precision - The number of decimal places to round up to (default is 8).\n * @returns The rounded up number.\n * @example\n * ```ts\n * import { roundUp } from 'curvy/utils'\n *\n * const roundedUpValue = roundUp(1.23456789, 4) // 1.2346\n * const roundedUpValue2 = roundUp(1.23456789) // 1.23456789\n * ```\n * @since 1.0.0\n */\nexport function roundUp(value: number, precision = PRECISION): number {\n  const scale = 10 ** precision\n  const result = Math.ceil(value * scale) / scale\n  if (result === 0) {\n    return 0\n  }\n  return result\n}\n\nexport const lerp: {\n  /**\n   * Linearly interpolates between two values.\n   *\n   * @param t - The interpolation factor (between 0 and 1).\n   * @param a - The start value.\n   * @param b - The end value.\n   * @returns The interpolated value.\n   * @example\n   * ```ts\n   * import { lerp } from 'curvy/utils'\n   *\n   * lerp(0.5, 10, 20) // 15\n   * ```\n   * @since 1.0.0\n   */\n  (t: number, a: number, b: number): number\n  /**\n   * Linearly interpolates between two values.\n   *\n   * @param a - The start value.\n   * @param b - The end value.\n   * @returns A function that takes the interpolation factor and returns the interpolated value.\n   * @example\n   * ```ts\n   * import { lerp } from 'curvy/utils'\n   *\n   * lerp(10, 20)(0.5) // 15\n   * ```\n   * @since 1.0.0\n   */\n  (a: number, b: number): (t: number) => number\n} = dual(3, (t: number, a: number, b: number) => b * t + a * (1 - t))\n\nexport const normalize: {\n  /**\n   * Normalizes a value between two bounds to the unit interval.\n   *\n   * @param x - The value to normalize.\n   * @param a - The lower bound.\n   * @param b - The upper bound.\n   * @returns The normalized value.\n   * @example\n   * ```ts\n   * import { normalize } from 'curvy/utils'\n   *\n   * normalize(15, 10, 20) // 0.5\n   * ```\n   * @since 1.0.0\n   */\n  (x: number, a: number, b: number): number\n  /**\n   * Normalizes a value between two bounds to the unit interval.\n   *\n   * @param a - The lower bound.\n   * @param b - The upper bound.\n   * @returns A function that takes a value and returns the normalized value.\n   * @example\n   * ```ts\n   * import { normalize } from 'curvy/utils'\n   *\n   * normalize(10, 20)(15) // 0.5\n   * ```\n   * @since 1.0.0\n   */\n  (a: number, b: number): (x: number) => number\n} = dual(3, (x: number, a: number, b: number) => (x - a) / (b - a))\n\nexport const remap: {\n  /**\n   * Remaps a value from one range to another.\n   *\n   * @param x - The value to remap.\n   * @param x1 - The lower bound of the original range.\n   * @param x2 - The upper bound of the original range.\n   * @param y1 - The lower bound of the new range.\n   * @param y2 - The upper bound of the new range.\n   * @returns The remapped value.\n   * @example\n   * ```ts\n   * import { remap } from 'curvy/utils'\n   *\n   * remap(15, 10, 20, 0, 100) // 50\n   * ```\n   * @since 1.0.0\n   */\n  (x: number, x1: number, x2: number, y1: number, y2: number): number\n  /**\n   * Remaps a value from one range to another.\n   *\n   * @param x1 - The lower bound of the original range.\n   * @param x2 - The upper bound of the original range.\n   * @param y1 - The lower bound of the new range.\n   * @param y2 - The upper bound of the new range.\n   * @returns A function that takes a value and returns the remapped value.\n   * @example\n   * ```ts\n   * import { remap } from 'curvy/utils'\n   *\n   * remap(10, 20, 0, 100)(15) // 50\n   * ```\n   * @since 1.0.0\n   */\n  (x1: number, x2: number, y1: number, y2: number): (x: number) => number\n} = dual(\n  5,\n  (x: number, x1: number, x2: number, y1: number, y2: number) =>\n    y1 + ((x - x1) / (x2 - x1)) * (y2 - y1),\n)\n\nexport const clamp: {\n  /**\n   * Clamps a value between two bounds.\n   *\n   * @param value - The value to clamp.\n   * @param min - The lower bound.\n   * @param max - The upper bound.\n   * @returns The clamped value.\n   * @example\n   * ```ts\n   * import { clamp } from 'curvy/utils'\n   *\n   * clamp(25, 10, 20) // 20\n   * ```\n   * @since 1.0.0\n   */\n  (value: number, min: number, max: number): number\n  /**\n   * Clamps a value between two bounds.\n   *\n   * @param min - The lower bound.\n   * @param max - The upper bound.\n   * @returns A function that takes a value and returns the clamped value.\n   * @example\n   * ```ts\n   * import { clamp } from 'curvy/utils'\n   *\n   * clamp(10, 20)(25) // 20\n   * ```\n   * @since 1.0.0\n   */\n  (min: number, max: number): (value: number) => number\n} = dual(3, (value: number, min: number, max: number) =>\n  value < min ? min : value > max ? max : value,\n)\n\nexport const clip: {\n  /**\n   * Clips a value to a specified range, returning a fallback value if the value is outside the range.\n   *\n   * @param value - The value to clip.\n   * @param min - The lower bound.\n   * @param max - The upper bound.\n   * @param onClip - The fallback value to return if the value is outside the range.\n   * @returns The original value if within range, otherwise the fallback.\n   * @example\n   * ```ts\n   * import { clip } from 'curvy/utils'\n   *\n   * clip(25, 10, 20, 15) // 15\n   * ```\n   * @since 1.0.0\n   */\n  <T>(value: number, min: number, max: number, onClip: T): T | number\n  /**\n   * Clips a value to a specified range, returning a fallback value if the value is outside the range.\n   *\n   * @param min - The lower bound.\n   * @param max - The upper bound.\n   * @param onClip - The fallback value to return if the value is outside the range.\n   * @returns A function that takes a value and returns it if within range, otherwise the fallback.\n   * @example\n   * ```ts\n   * import { clip } from 'curvy/utils'\n   *\n   * clip(10, 20, 15)(25) // 15\n   * ```\n   * @since 1.0.0\n   */\n  <T>(min: number, max: number, onClip: T): (value: number) => T | number\n} = dual(4, (value: number, min: number, max: number, onClip: unknown) =>\n  value < min ? onClip : value > max ? onClip : value,\n)\n\n/**\n * Returns the minimum and maximum of two numbers.\n *\n * @param a - The first number.\n * @param b - The second number.\n * @returns A tuple containing the minimum and maximum values.\n * @example\n * ```ts\n * import { minMax } from 'curvy/utils'\n *\n * const [minValue, maxValue] = minMax(10, 20) // [10, 20]\n * const [minValue2, maxValue2] = minMax(20, 10) // [10, 20]\n * ```\n * @since 1.0.0\n */\nexport function minMax(a: number, b: number): [number, number] {\n  return a < b ? [a, b] : [b, a]\n}\n\n/**\n * Calculates the modulus of a number.\n *\n * @param n - The number to calculate the modulus of.\n * @param m - The modulus.\n * @returns The modulus of the number.\n * @example\n * ```ts\n * import { mod } from 'curvy/utils'\n *\n * const modulus = mod(10, 3) // 1\n * const modulus2 = mod(-10, 3) // 2\n * ```\n * @since 1.0.0\n */\nexport function mod(n: number, m: number): number {\n  return ((n % m) + m) % m\n}\n"],"mappings":";;AAEA,MAAM,YAAY;;;;;;AAOlB,MAAa,UAAU;;;;;;;;;;AAWvB,SAAgB,UAAU,GAAW,GAAW,MAAc,SAAkB;CAC9E,OAAO,KAAK,IAAI,IAAI,EAAE,IAAI;;;;;;;;;;AAW5B,SAAgB,YAAY,OAAe,KAAqB;CAC9D,OAAO,KAAK,IAAI,MAAM,GAAG,MAAM,IAAI;;;;;;;;;;;;;;;;;AAkBrC,SAAgB,MAAM,OAAe,YAAY,WAAmB;CAClE,MAAM,QAAQ,MAAM;CACpB,MAAM,SAAS,KAAK,MAAM,QAAQ,MAAM,GAAG;CAC3C,IAAI,WAAW,GACb,OAAO;CAET,OAAO;;;;;;;;;;;;;;;;;AAkBT,SAAgB,UAAU,OAAe,YAAY,WAAmB;CACtE,MAAM,QAAQ,MAAM;CACpB,MAAM,SAAS,KAAK,MAAM,QAAQ,MAAM,GAAG;CAC3C,IAAI,WAAW,GACb,OAAO;CAET,OAAO;;;;;;;;;;;;;;;;;AAkBT,SAAgB,QAAQ,OAAe,YAAY,WAAmB;CACpE,MAAM,QAAQ,MAAM;CACpB,MAAM,SAAS,KAAK,KAAK,QAAQ,MAAM,GAAG;CAC1C,IAAI,WAAW,GACb,OAAO;CAET,OAAO;;AAGT,MAAa,OAgCT,KAAK,IAAI,GAAW,GAAW,MAAc,IAAI,IAAI,KAAK,IAAI,GAAG;AAErE,MAAa,YAgCT,KAAK,IAAI,GAAW,GAAW,OAAe,IAAI,MAAM,IAAI,GAAG;AAEnE,MAAa,QAoCT,KACF,IACC,GAAW,IAAY,IAAY,IAAY,OAC9C,MAAO,IAAI,OAAO,KAAK,OAAQ,KAAK,IACvC;AAED,MAAa,QAgCT,KAAK,IAAI,OAAe,KAAa,QACvC,QAAQ,MAAM,MAAM,QAAQ,MAAM,MAAM,MACzC;AAED,MAAa,OAkCT,KAAK,IAAI,OAAe,KAAa,KAAa,WACpD,QAAQ,MAAM,SAAS,QAAQ,MAAM,SAAS,MAC/C;;;;;;;;;;;;;;;;AAiBD,SAAgB,OAAO,GAAW,GAA6B;CAC7D,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE;;;;;;;;;;;;;;;;;AAkBhC,SAAgB,IAAI,GAAW,GAAmB;CAChD,QAAS,IAAI,IAAK,KAAK"}