import { dequantize_float, quantize_float } from "./quantize_float.js";

/**
 * Position quantization helpers.
 *
 * A position component is a signed float in some bounded world range (e.g. ±256m
 * for a typical action game level). We pick a number of quanta per unit
 * (e.g. 4096 quanta/m for centimetre-precision-ish accuracy) which together with
 * the range determines the bit count.
 *
 * `bit_count = ceil(log2(2 * range * quanta_per_unit))`
 *
 * For the Glenn Fiedler State Synchronization defaults (range = 256m, 4096 quanta/m):
 * 2 * 256 * 4096 = 2097152 = 2^21 → 21 bits per component, 63 bits per vec3.
 *
 * (We measure "number of quanta intervals" rather than "number of distinct values",
 * which gives one fewer bit at exactly-power-of-two configurations and matches
 * the conventions used in the netcode literature.)
 *
 * @author Alex Goldring
 * @copyright Company Named Limited (c) 2026
 */

/**
 * @param {number} value
 * @param {number} range          half-extent (the value is expected to be in [-range, +range])
 * @param {number} bits
 * @returns {number}
 */
export function quantize_position(value, range, bits) {
    return quantize_float(value, -range, range, bits);
}

/**
 * @param {number} quantized
 * @param {number} range
 * @param {number} bits
 * @returns {number}
 */
export function dequantize_position(quantized, range, bits) {
    return dequantize_float(quantized, -range, range, bits);
}

/**
 * Compute the bit count required to represent positions in `[-range, +range]` at
 * `quanta_per_unit` precision.
 *
 * @param {number} range
 * @param {number} quanta_per_unit
 * @returns {number}
 */
export function position_bit_count(range, quanta_per_unit) {
    return Math.ceil(Math.log2(2 * range * quanta_per_unit));
}
