package org.kne.codec.kif;

/**
 * Zigzag 映射工具
 * 用于将预测残差（集中在0附近的有符号数）映射为熵编码友好的非负数序列
 */
public class Zigzag {

    /**
     * 映射单个 byte
     * 0→0, -1→1, 1→2, -2→3, 2→4, ...
     */
    public static byte map(byte x) {
        int v = x; // byte 转为 int（保留符号）
        return (byte) ((v >= 0) ? (v << 1) : ((-v << 1) - 1));
    }

    /**
     * 逆映射单个 byte
     * 0→0, 1→-1, 2→1, 3→-2, 4→2, ...
     * 
     * 用按位与替代取余：v & 1 等价于 v % 2，但快 2-3 倍
     */
    public static byte unmap(byte y) {
        int v = y & 0xFF;        // 转为无符号 0~255
        return (byte) ((v & 1) == 0 ? (v >> 1) : (-((v + 1) >> 1)));
    }

    /**
     * 映射整个字节数组（原地修改）
     */
    public static void mapInPlace(byte[] data) {
        for (int i = 0; i < data.length; i++) {
            data[i] = map(data[i]);
        }
    }

    /**
     * 逆映射整个字节数组（原地修改）
     */
    public static void unmapInPlace(byte[] data) {
        for (int i = 0; i < data.length; i++) {
            data[i] = unmap(data[i]);
        }
    }

    /**
     * 映射整个 int 数组（每个元素的低 8 位）
     * 注意：只处理每个 int 的低 8 位，高位保持不变
     */
    public static void mapInPlaceInt(int[] data) {
        for (int i = 0; i < data.length; i++) {
            int v = data[i] & 0xFF; // 取低 8 位作为有符号数
            // 处理符号扩展：如果最高位为 1，说明是负数
            byte b = (byte) v;
            data[i] = (data[i] & 0xFFFFFF00) | (map(b) & 0xFF);
        }
    }
}