MLN算法

f(x,y) = freq;
f(x,y) = freq越大映射的值越小     encode矩阵
f(x, freq越大映射的值越小) = y    decode矩阵


第一个值不变,加密时按照encode矩阵一个一个的转换

第一个值不变,解压缩时按照encode矩阵一个一个的转换


此方法对值的加密范围受限于矩阵的大小。
主要考虑前后这个值的出现频次。做相应的压缩
public class MLN {
    public static final int MAX_V = 8;
    public static final int BLOCK_SIZE = MAX_V*MAX_V;
    private final long[] tmp = new long[BLOCK_SIZE / 2];
    public static long[][] generateCompTab(long[] in){
        int size = in.length;
        long[][] freqTable = new long[8][8];
        for(int i = 0; i< size -1; ++i){
            long current = in[i];
            long next = in[i+1];
            if (current <= MAX_V && next <= MAX_V){
                freqTable[(int)current - 1][(int)next - 1] += 1;
            }
        }
        System.out.println("print freq");
        printTable(freqTable);
        System.out.println();

        long[][] encodeTable  = new long[8][8];
        for(int i = 0; i< freqTable.length; i++){
            long[] freqRow = freqTable[i];
            int[] idx = arraySort(freqRow);
            for(int j = 0; j < 8; j++){
                encodeTable[i][idx[j]] = j + 1;
            }
        }
        System.out.println("print encodeTable");
        printTable(encodeTable);
        System.out.println();
        return encodeTable;
    }

    public static int[] arraySort(long[]arr) {
        long temp;
        int index;
        int size = arr.length;
        int[] Index = new int[size];
        for (int i = 0; i < size; i++) {
            Index[i] = i;
        }
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length - i - 1; j++) {
                if (arr[j] < arr[j + 1]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;

                    index = Index[j];
                    Index[j] = Index[j + 1];
                    Index[j + 1] = index;
                }
            }
        }
        return Index;
    }


    public static long[][] generateDecomTable(long[][] encodeTabel){
        long[][] decomTable = new long[encodeTabel.length][encodeTabel.length];
        for(int i = 0; i< encodeTabel.length; i++){
            for (int j = 0; j < encodeTabel.length; j++){
                //decomTable[i][(int)encodeTabel[i][j] - 1] = j+1;

                //为了节省存储 减一
                decomTable[i][(int)encodeTabel[i][j] - 1] = j;
            }
        }
        return decomTable;
    }


    public static long[][] encode(long[] in, long[] out){
        for (int i = 0; i< in.length; i++){
            in[i] += 1;
        }
        long[][] encodeTable = generateCompTab(in);
        int size = in.length;
        out[0] = in[0];
        for (int i = 1; i< size; i++){
            long prev = in[i-1];
            long current = in[i];
            if (prev <= MAX_V && current <= MAX_V){
                out[i] = encodeTable[(int)prev - 1][(int)current - 1];
            }else {
                out[i] = in[i];
            }
        }
        return generateDecomTable(encodeTable);
    }

    public static void decode(long[] in, long[] out, long[][]decodeTable){
        out[0] = in[0];
        long pre = out[0];
        for (int i = 1; i< in.length; i++){
            long current = in[i];
            if (pre <= MAX_V && current <= MAX_V){
                //out[i] = decodeTable[(int)pre - 1][(int)current - 1];
                // 为了节省存储 加回来
                out[i] = decodeTable[(int)pre - 1][(int)current - 1] + 1;
            }else {
                out[i] = in[i];
            }
            pre = out[i];
        }
        for (int i = 0 ;i<out.length;i++){
            out[i] -= 1;
        }

    }


    /** Encode 128 integers from {@code longs} into {@code out}. */
    void encode(long[][] decodTable, int bitsPerValue, DataOutput out) throws IOException {
        long[] longs = new long[64];
        int x = 0;
        for (int i = 0;i<8; i++){
            for (int j= 0 ;j<8;j++){
                longs[x++]= decodTable[i][j];
            }
        }

        final int nextPrimitive;
        final int numLongs;

        nextPrimitive = 8;
        numLongs = BLOCK_SIZE / 8;
        collapse8(longs);


        final int numLongsPerShift = bitsPerValue;
        int idx = 0;
        int shift = nextPrimitive - bitsPerValue;
        for (int i = 0; i < numLongsPerShift; ++i) {
            tmp[i] = longs[idx++] << shift;
        }
        for (shift = shift - bitsPerValue; shift >= 0; shift -= bitsPerValue) {
            for (int i = 0; i < numLongsPerShift; ++i) {
                tmp[i] |= longs[idx++] << shift;
            }
        }

        final int remainingBitsPerLong = shift + bitsPerValue;
        final long maskRemainingBitsPerLong;
        if (nextPrimitive == 8) {
            maskRemainingBitsPerLong = MASKS8[remainingBitsPerLong];
        } else if (nextPrimitive == 16) {
            maskRemainingBitsPerLong = MASKS16[remainingBitsPerLong];
        } else {
            maskRemainingBitsPerLong = MASKS32[remainingBitsPerLong];
        }

        int tmpIdx = 0;
        int remainingBitsPerValue = bitsPerValue;
        while (idx < numLongs) {
            if (remainingBitsPerValue >= remainingBitsPerLong) {
                remainingBitsPerValue -= remainingBitsPerLong;
                tmp[tmpIdx++] |= (longs[idx] >>> remainingBitsPerValue) & maskRemainingBitsPerLong;
                if (remainingBitsPerValue == 0) {
                    idx++;
                    remainingBitsPerValue = bitsPerValue;
                }
            } else {
                final long mask1, mask2;
                if (nextPrimitive == 8) {
                    mask1 = MASKS8[remainingBitsPerValue];
                    mask2 = MASKS8[remainingBitsPerLong - remainingBitsPerValue];
                } else if (nextPrimitive == 16) {
                    mask1 = MASKS16[remainingBitsPerValue];
                    mask2 = MASKS16[remainingBitsPerLong - remainingBitsPerValue];
                } else {
                    mask1 = MASKS32[remainingBitsPerValue];
                    mask2 = MASKS32[remainingBitsPerLong - remainingBitsPerValue];
                }
                tmp[tmpIdx] |= (longs[idx++] & mask1) << (remainingBitsPerLong - remainingBitsPerValue);
                remainingBitsPerValue = bitsPerValue - remainingBitsPerLong + remainingBitsPerValue;
                tmp[tmpIdx++] |= (longs[idx] >>> remainingBitsPerValue) & mask2;
            }
        }

        for (int i = 0; i < numLongsPerShift; ++i) {
            // Java longs are big endian and we want to read little endian longs, so we need to reverse
            // bytes
            long l = Long.reverseBytes(tmp[i]);
            out.writeLong(l);
        }
    }
    private static void collapse8(long[] arr) {
        for (int i = 0; i < 8; ++i) {
            arr[i] =
                    (arr[i] << 56)
                            | (arr[8 + i] << 48)
                            | (arr[16 + i] << 40)
                            | (arr[24 + i] << 32)
                            | (arr[32 + i] << 24)
                            | (arr[40 + i] << 16)
                            | (arr[48 + i] << 8)
                            | arr[56 + i];
        }
    }

    private static final long[] MASKS8 = new long[8];
    private static final long[] MASKS16 = new long[16];
    private static final long[] MASKS32 = new long[32];

    static {
        for (int i = 0; i < 8; ++i) {
            MASKS8[i] = mask8(i);
        }
        for (int i = 0; i < 16; ++i) {
            MASKS16[i] = mask16(i);
        }
        for (int i = 0; i < 32; ++i) {
            MASKS32[i] = mask32(i);
        }
    }

    private static long mask32(int bitsPerValue) {
        return expandMask32((1L << bitsPerValue) - 1);
    }

    private static long mask16(int bitsPerValue) {
        return expandMask16((1L << bitsPerValue) - 1);
    }

    private static long mask8(int bitsPerValue) {
        return expandMask8((1L << bitsPerValue) - 1);
    }

    private static long expandMask32(long mask32) {
        return mask32 | (mask32 << 32);
    }

    private static long expandMask16(long mask16) {
        return expandMask32(mask16 | (mask16 << 16));
    }

    private static long expandMask8(long mask8) {
        return expandMask16(mask8 | (mask8 << 8));
    }

//    /** Decode 128 integers into {@code longs}. */
//    void decode(int bitsPerValue, DataInput in, long[][] decodeTable) throws IOException {
//        long[] longs = new long[64];
//        decode3(in, tmp, longs);
//        expand8(longs);
//        for (int i = 0;i < 64;i++){
//            decodeTable[i/8][i%8] = longs[i];
//        }
//
//    }

//    static void decode3(DataInput in, long[] tmp, long[] longs) throws IOException {
//        readLELongs(in, tmp, 0, 3);
//        shiftLongs(tmp, 3, longs, 0, 5, MASK8_3);
//        shiftLongs(tmp, 3, longs, 3, 2, MASK8_3);
//        for (int iter = 0, tmpIdx = 0, longsIdx = 6; iter < 1; ++iter, tmpIdx += 3, longsIdx += 2) {
//            long l0 = (tmp[tmpIdx + 0] & MASK8_2) << 1;
//            l0 |= (tmp[tmpIdx + 1] >>> 1) & MASK8_1;
//            longs[longsIdx + 0] = l0;
//            long l1 = (tmp[tmpIdx + 1] & MASK8_1) << 2;
//            l1 |= (tmp[tmpIdx + 2] & MASK8_2) << 0;
//            longs[longsIdx + 1] = l1;
//        }
//    }

    static void expand8(long[] arr) {
        for (int i = 0; i < 8; ++i) {
            long l = arr[i];
            arr[i] = (l >>> 56) & 0xFFL;
            arr[8 + i] = (l >>> 48) & 0xFFL;
            arr[16 + i] = (l >>> 40) & 0xFFL;
            arr[24 + i] = (l >>> 32) & 0xFFL;
            arr[32 + i] = (l >>> 24) & 0xFFL;
            arr[40 + i] = (l >>> 16) & 0xFFL;
            arr[48 + i] = (l >>> 8) & 0xFFL;
            arr[56 + i] = (l) & 0xFFL;
        }
    }


    public static void main(String[] args) throws IOException {
        long[] in = new long[]{1, 2, 3, 2, 1, 2, 1, 2, 8, 2, 7, 2};
        //long[] in = new long[]{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
        for (long l: in){
            System.out.print(l + " ");
        }
        System.out.println();
        long[] out = new long[in.length];
        long[][]decodTable = encode(in, out);

        System.out.println("print decodTable");
        printTable(decodTable);
        System.out.println();

        long[] mycode = new long[64];
        int x = 0;
        for (int i = 0;i<decodTable.length; i++){
            for (int j= 0 ;j<decodTable.length;j++){
                mycode[x++]= decodTable[i][j];
            }
        }



       // new MLN().encode(mycode, 3, null);

        for (long l: out){
            System.out.print(l + " ");
        }



        long[] result = new long[in.length];
        decode(out, result, decodTable);
        System.out.println();
        for (long l: result){
            System.out.print(l + " ");
        }

        System.exit(0);

    }
    public static void printTable(long[][] t){
        for (int i = 0;i<t.length;i++){
            for (int j = 0;j<t.length;j++){
                System.out.print(t[i][j]+" ");
            }
            System.out.println();
        }


    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值