WaveletConstants.java

package com.morphiqlabs.wavelet.util;

import com.morphiqlabs.wavelet.exception.InvalidArgumentException;

/**
 * Constants used throughout the wavelet transform implementation.
 *
 * <p>This class centralizes important constants to avoid duplication
 * and improve maintainability across the codebase.</p>
 */
public final class WaveletConstants {

    /**
     * The largest power of 2 that can be represented as a positive int in Java.
     * This is due to the two's complement representation of integers, where the
     * most significant bit is used as the sign bit. For a 32-bit signed integer,
     * 2^30 (1,073,741,824) is the largest power of two that remains positive.
     * The next power, 2^31, would overflow and be interpreted as a negative value.
     */
    public static final int MAX_SAFE_POWER_OF_TWO = 1 << 30;

    /**
     * Minimum size for wavelet decomposition. A signal cannot be decomposed
     * further once it reaches this size.
     */
    public static final int MIN_DECOMPOSITION_SIZE = 1;

    private WaveletConstants() {
        // Utility class, prevent instantiation
    }

    /**
     * Calculates the next power of two greater than or equal to n.
     * This method is used internally for validation and error messages.
     *
     * @param n the input number (must be positive and {@literal <=} MAX_SAFE_POWER_OF_TWO)
     * @return the next power of two >= n
     */
    public static int calculateNextPowerOfTwo(int n) {
        if (n <= 1) return 1;
        if (n > MAX_SAFE_POWER_OF_TWO) {
            throw new InvalidArgumentException("Input exceeds maximum safe power of two.");
        }
        // Find the next power of two using bit manipulation.
        // The formula works as follows:
        // 1. Subtract 1 from the input `n` to handle cases where `n` is already a power of two.
        // 2. Use `Integer.numberOfLeadingZeros(n - 1)` to count the number of leading zero bits in the 32-bit binary representation of `n - 1`.
        // 3. Subtract this count from 32 to determine the position of the highest set bit in `n - 1`.
        // 4. Shift the bit `1` left by this position to compute the next power of two.
        //
        // Example:
        // If n = 19:
        // Step 1: n - 1 = 18 (binary: 00000000 00000000 00000000 00010010)
        // Step 2: Integer.numberOfLeadingZeros(18) = 27 (since there are 27 leading zeros in the 32-bit representation)
        // Step 3: 32 - 27 = 5 (position of the highest set bit)
        // Step 4: 1 << 5 = 32 (binary: 00000000 00000000 00000000 00100000)
        // Result: The next power of two greater than or equal to 19 is 32.
        return 1 << (32 - Integer.numberOfLeadingZeros(n - 1));
    }
}