package com.alimama.mdrill.buffer; /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Implementation of the Simple16 algorithm for sorted integer arrays. The basic ideas are based on papers from * * 1. http://www2008.org/papers/pdf/p387-zhangA.pdf * * 2. http://www2009.org/proceedings/pdf/p401.pdf * */ public class Simple16 { private static final int S16_NUMSIZE = 16; private static final int S16_BITSSIZE = 28; // the possible number of bits used to represent one integer private static final int[] S16_NUM = {28, 21, 21, 21, 14, 9, 8, 7, 6, 6, 5, 5, 4, 3, 2, 1}; // the corresponding number of elements for each value of the number of bits private static final int[][] S16_BITS = { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0}, {1,1,1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1,1,1,0,0,0,0,0,0,0}, {1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,0,0,0,0,0,0,0}, {2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {4,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {3,4,4,4,4,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {5,5,5,5,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {4,4,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {6,6,6,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {5,5,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {10,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; /** * Compress an integer array using Simple16 * * @param out the compressed output * @param outOffset the offset of the output in the number of integers * @param in the integer input array * @param inOffset the offset of the input in the number of integers * @param n the number of elements to be compressed * @return the number of compressed integers */ public static final int s16Compress(int[] out, int outOffset, int[] in, int inOffset, int n, int blockSize, int oriBlockSize, int[] oriInputBlock) { int numIdx, j, num, bits; for (numIdx = 0; numIdx < S16_NUMSIZE; numIdx++) { out[outOffset] = numIdx<<S16_BITSSIZE; num = (S16_NUM[numIdx] < n) ? S16_NUM[numIdx] : n; for (j = 0, bits = 0; (j < num) && in[inOffset+j] < (1<<S16_BITS[numIdx][j]); ) { out[outOffset] |= (in[inOffset+j]<<bits); bits += S16_BITS[numIdx][j]; j++; } if (j == num) { return num; } } return -1; } /** * Decompress an integer array using Simple16 * * @param out the decompressed output * @param outOffset the offset of the output in the number of integers * @param in the compressed input array * @param inOffset the offset of the input in the number of integers * @param n the number of elements to be compressed * @return the number of processed integers */ public static final int s16Decompress(int[] out, int outOffset, int[] in, int inOffset, int n) { int numIdx, j=0, bits=0; numIdx = in[inOffset]>>>S16_BITSSIZE; int num = S16_NUM[numIdx] < n ? S16_NUM[numIdx] : n; for(j=0, bits=0; j<num; j++) { out[outOffset+j] = readBitsForS16(in, inOffset, bits, S16_BITS[numIdx][j]); bits += S16_BITS[numIdx][j]; } return num; } /** * Read a certain number of bits of a integer on the input array * @param in the input array * @param inIntOffset the start offset in ints in the input array * @param inWithIntOffset the start offset within a int in the input array * @param bits the number of bits to be read * @return the bits bits of the input */ static private int readBitsForS16(int[] in, final int inIntOffset, final int inWithIntOffset, final int bits) { final int val = (in[inIntOffset] >>> inWithIntOffset); return val & (0xffffffff >>> (32 - bits)); } }