package com.meidusa.amoeba.sqljep.function;
import com.meidusa.amoeba.sqljep.ASTFunNode;
import com.meidusa.amoeba.sqljep.JepRuntime;
import com.meidusa.amoeba.sqljep.ParseException;
/**
* ���hash�ķ�������
*
* @author hexianmao
* @version 2008-11-14 ����03:45:03
*/
public class HashParttion extends PostfixCommand {
private static final int _unknown = -1;
/**
* ���ݶηֲ����壬����ȡģ����һ��Ҫ��2^n����Ϊ����ʹ��x % 2^n == x & (2^n - 1)��ʽ�����Ż����ܡ�
*/
private static final int[] parttion = new int[] { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024 };
/**
* ÿ������ӳ������ݶ�
*/
private static final int[] parttionMap;
private static final long andValue;
/**
* ӳ�����
*/
static {
int x = parttion[parttion.length - 1];
checkModValue(x);
parttionMap = new int[x];
andValue = x - 1;
for (int i = 1; i < parttion.length; i++) {
for (int j = parttion[i - 1]; j < parttion[i]; j++) {
parttionMap[j] = (i - 1);
}
}
}
/**
* ���x�Ƿ�Ϊ2^n
*/
private static void checkModValue(int x) {
if (x <= 0) {
throw new RuntimeException("error mod value:" + x);
}
int n = 0;
int c = 0;
int y = 1;
while (y <= x) {
if ((x & y) > 0) {
c++;
if (c > 1) {
throw new RuntimeException("error mod value:" + x);
}
}
y = 1 << (++n);
}
}
public Comparable<?>[] evaluate(ASTFunNode node, JepRuntime runtime) throws ParseException {
node.childrenAccept(runtime.ev, null);
Comparable<?> param = runtime.stack.pop();
return new Comparable<?>[] { param };
}
public int getNumberOfParameters() {
return 1;
}
public Comparable<?> getResult(Comparable<?>... comparables) throws ParseException {
if (comparables[0] != null && comparables[0] instanceof Long) {
Long l = (Long) comparables[0];
if (l == -1L) {
return _unknown;
}
return parttionMap[(int) (l & andValue)];
}
return _unknown;
}
}