{"version":3,"file":"_randomMultiple.mjs","names":[],"sources":["../../src/internal/_randomMultiple.ts"],"sourcesContent":["import {\n  _IDecimal,\n  _IDecimalRatio,\n  _decimalDecompose,\n  _decimalDivide,\n  _decimalGcd,\n  _decimalIntegerStep,\n  _decimalPower,\n  _decimalToNumber,\n} from \"./_decimal\";\nimport { _isMultipleOf } from \"./_isMultipleOf\";\n\nexport const _randomMultiple = (props: {\n  minimum: number;\n  maximum: number;\n  multipleOf: number;\n  exclusiveMinimum: boolean;\n  exclusiveMaximum: boolean;\n  integer: boolean;\n}): number => {\n  const step: _IDecimal | null = props.integer\n    ? _decimalIntegerStep(props.multipleOf)\n    : _decimalDecompose(props.multipleOf);\n  if (step === null || step.coefficient <= BigInt(0))\n    throw new Error(\"The multipleOf value must be a positive finite number.\");\n\n  const lower: _IDecimalRatio | null = _decimalDivide(props.minimum, step);\n  const upper: _IDecimalRatio | null = _decimalDivide(props.maximum, step);\n  if (lower === null || upper === null)\n    throw new Error(\"The random number range must be finite.\");\n  const minimum: bigint = lowerBound(lower, props.exclusiveMinimum);\n  const maximum: bigint = upperBound(upper, props.exclusiveMaximum);\n  if (minimum > maximum)\n    throw new Error(\"The range does not contain a multipleOf value.\");\n\n  const selected: bigint = randomBigint(minimum, maximum);\n  const candidates: bigint[] = unique([\n    selected,\n    minimum,\n    maximum,\n    clamp(BigInt(0), minimum, maximum),\n    clamp(BigInt(1), minimum, maximum),\n    clamp(BigInt(-1), minimum, maximum),\n    ...nearby(selected, minimum, maximum),\n  ]);\n  for (const coefficient of candidates) {\n    const value: number = _decimalToNumber({\n      coefficient: step.coefficient * coefficient,\n      exponent: step.exponent,\n    });\n    if (isValid(props, value)) return value;\n  }\n  const aligned: number | null = findRepresentableIntegerMultiple(props);\n  if (aligned !== null) return aligned;\n  const decimalAligned: number | null = findRepresentableDecimalMultiple(\n    props,\n    step,\n  );\n  if (decimalAligned !== null) return decimalAligned;\n  throw new Error(\n    \"The range does not contain a representable multipleOf value.\",\n  );\n};\n\nconst isValid = (\n  props: Parameters<typeof _randomMultiple>[0],\n  value: number,\n): boolean =>\n  Number.isFinite(value) &&\n  (props.integer === false || Number.isInteger(value)) &&\n  (props.exclusiveMinimum ? value > props.minimum : value >= props.minimum) &&\n  (props.exclusiveMaximum ? value < props.maximum : value <= props.maximum) &&\n  _isMultipleOf(value, props.multipleOf);\n\nconst findRepresentableDecimalMultiple = (\n  props: Parameters<typeof _randomMultiple>[0],\n  step: _IDecimal,\n): number | null => {\n  const limit: bigint = BigInt(\"999999999999999\");\n  for (let exponent = -324; exponent <= 308; ++exponent) {\n    const unit: _IDecimal = { coefficient: BigInt(1), exponent };\n    const lower: _IDecimalRatio | null = _decimalDivide(props.minimum, unit);\n    const upper: _IDecimalRatio | null = _decimalDivide(props.maximum, unit);\n    if (lower === null || upper === null) return null;\n\n    const coefficientMinimum: bigint = max(\n      -limit,\n      lowerBound(lower, props.exclusiveMinimum),\n    );\n    const coefficientMaximum: bigint = min(\n      limit,\n      upperBound(upper, props.exclusiveMaximum),\n    );\n    if (coefficientMinimum > coefficientMaximum) continue;\n\n    const coefficientStep: bigint = decimalCoefficientStep(step, exponent);\n    const minimum: bigint = lowerBound(\n      { numerator: coefficientMinimum, denominator: coefficientStep },\n      false,\n    );\n    const maximum: bigint = upperBound(\n      { numerator: coefficientMaximum, denominator: coefficientStep },\n      false,\n    );\n    if (minimum > maximum) continue;\n\n    const selected: bigint = randomBigint(minimum, maximum);\n    for (const quotient of unique([\n      selected,\n      minimum,\n      maximum,\n      clamp(BigInt(0), minimum, maximum),\n      ...nearby(selected, minimum, maximum),\n    ])) {\n      const value: number = _decimalToNumber({\n        coefficient: coefficientStep * quotient,\n        exponent,\n      });\n      if (isValid(props, value)) return value;\n    }\n  }\n  return null;\n};\n\nconst decimalCoefficientStep = (step: _IDecimal, exponent: number): bigint => {\n  const difference: number = exponent - step.exponent;\n  if (difference >= 0) {\n    const power: bigint = _decimalPower(difference);\n    return step.coefficient / _decimalGcd(step.coefficient, power);\n  }\n  return step.coefficient * _decimalPower(-difference);\n};\n\nconst findRepresentableIntegerMultiple = (\n  props: Parameters<typeof _randomMultiple>[0],\n): number | null => {\n  const step: _IDecimal | null = _decimalIntegerStep(props.multipleOf);\n  if (step === null) return null;\n  const unit: _IDecimal = { coefficient: BigInt(1), exponent: 0 };\n  const lower: _IDecimalRatio | null = _decimalDivide(props.minimum, unit);\n  const upper: _IDecimalRatio | null = _decimalDivide(props.maximum, unit);\n  if (lower === null || upper === null) return null;\n\n  const minimum: bigint = lowerBound(lower, props.exclusiveMinimum);\n  const maximum: bigint = upperBound(upper, props.exclusiveMaximum);\n  if (minimum > maximum) return null;\n  if (minimum <= BigInt(0) && maximum >= BigInt(0)) return 0;\n\n  const candidate: bigint | null =\n    minimum > BigInt(0)\n      ? findPositiveAligned(minimum, maximum, step.coefficient)\n      : (() => {\n          const magnitude: bigint | null = findPositiveAligned(\n            -maximum,\n            -minimum,\n            step.coefficient,\n          );\n          return magnitude === null ? null : -magnitude;\n        })();\n  if (candidate === null) return null;\n  const value: number = Number(candidate);\n  return isValid(props, value) ? value : null;\n};\n\nconst findPositiveAligned = (\n  minimum: bigint,\n  maximum: bigint,\n  integerStep: bigint,\n): bigint | null => {\n  const first: number = bitLength(minimum) - 1;\n  const last: number = bitLength(maximum) - 1;\n  for (let exponent = first; exponent <= last; ++exponent) {\n    const bandMinimum: bigint = max(minimum, BigInt(1) << BigInt(exponent));\n    const bandMaximum: bigint = min(\n      maximum,\n      (BigInt(1) << BigInt(exponent + 1)) - BigInt(1),\n    );\n    const quantum: bigint =\n      exponent <= 52 ? BigInt(1) : BigInt(1) << BigInt(exponent - 52);\n    const alignedStep: bigint =\n      (integerStep / _decimalGcd(integerStep, quantum)) * quantum;\n    const lower: bigint = lowerBound(\n      { numerator: bandMinimum, denominator: alignedStep },\n      false,\n    );\n    const upper: bigint = upperBound(\n      { numerator: bandMaximum, denominator: alignedStep },\n      false,\n    );\n    if (lower <= upper) return randomBigint(lower, upper) * alignedStep;\n  }\n  return null;\n};\n\nconst bitLength = (value: bigint): number => value.toString(2).length;\n\nconst min = (x: bigint, y: bigint): bigint => (x < y ? x : y);\nconst max = (x: bigint, y: bigint): bigint => (x > y ? x : y);\n\nconst lowerBound = (ratio: _IDecimalRatio, exclusive: boolean): bigint => {\n  const quotient: bigint = ratio.numerator / ratio.denominator;\n  const remainder: bigint = ratio.numerator % ratio.denominator;\n  const ceiling: bigint =\n    quotient + (remainder > BigInt(0) ? BigInt(1) : BigInt(0));\n  return (\n    ceiling + (exclusive && remainder === BigInt(0) ? BigInt(1) : BigInt(0))\n  );\n};\n\nconst upperBound = (ratio: _IDecimalRatio, exclusive: boolean): bigint => {\n  const quotient: bigint = ratio.numerator / ratio.denominator;\n  const remainder: bigint = ratio.numerator % ratio.denominator;\n  const floor: bigint =\n    quotient - (remainder < BigInt(0) ? BigInt(1) : BigInt(0));\n  return floor - (exclusive && remainder === BigInt(0) ? BigInt(1) : BigInt(0));\n};\n\nconst randomBigint = (minimum: bigint, maximum: bigint): bigint => {\n  const scale: bigint = BigInt(1) << BigInt(53);\n  const sample: bigint = BigInt(\n    Math.min(\n      Number(scale - BigInt(1)),\n      Math.floor(Math.max(0, Math.random()) * Number(scale)),\n    ),\n  );\n  return minimum + ((maximum - minimum + BigInt(1)) * sample) / scale;\n};\n\nconst clamp = (value: bigint, minimum: bigint, maximum: bigint): bigint =>\n  value < minimum ? minimum : value > maximum ? maximum : value;\n\nconst nearby = (\n  selected: bigint,\n  minimum: bigint,\n  maximum: bigint,\n): bigint[] => {\n  const output: bigint[] = [];\n  for (let distance = BigInt(1); distance <= BigInt(32); ++distance) {\n    if (selected - distance >= minimum) output.push(selected - distance);\n    if (selected + distance <= maximum) output.push(selected + distance);\n  }\n  return output;\n};\n\nconst unique = (values: bigint[]): bigint[] => [...new Set(values)];\n"],"mappings":"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"}