import { getHighestSetBit, getLowestSetBit } from "./get-max-set-bit.js";
import { exponent } from "./exponent.js";


/**
 * Returns true if the given number is bit-aligned in the sense that its a 
 * multiple of a given power of 2, say e, and such that the number, say a, 
 * conforms to: a/2^e < 2^(l-e), where l is the max allowed bit length. 
 * This essentially means the numbers act somewhat like fixed-point numbers 
 * which can drastically speed up some geometric algorithms and also reduce 
 * their complexity.
 * 
 * Visually:
 * These numbers (a,b and c) are grid aligned with e === 3 and max 
 * bitlength === 6:
 *   a -> 00|101100|000
 *   b -> 00|000100|000
 *   c -> 00|110111|000
 * These are not
 *   a -> 01|101100|000
 *   b -> 00|000100|000
 * These are not
 *   a -> 00|101100|000
 *   b -> 00|000100|100
 * These are not
 *   a -> 00|101100|100
 *   b -> 00|000100|100
 * @param as An array of numbers to check
 * @param maxBitLength The max allowed bitlength
 * @param gridSpacingExponent The grid spacing === 1^gridSpacingExponent
 */
function isBitAligned(
        a: number,
        maxBitLength: number,
        gridSpacingExponent: number) {

    if (a === 0) { return true; }

    const e = exponent(a);

    const maxSetBit = getHighestSetBit(a) - 52 + e;
    const minSetBit = getLowestSetBit (a) - 52 + e;

    const minBitBigEnough = minSetBit >= gridSpacingExponent;
    const maxBitSmallEnough = maxSetBit <= maxBitLength-1 + gridSpacingExponent;

    return minBitBigEnough && maxBitSmallEnough;
}


export { isBitAligned }
