com.scudata.expression.fn.gather.ICount Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of esproc Show documentation
Show all versions of esproc Show documentation
SPL(Structured Process Language) A programming language specially for structured data computing.
package com.scudata.expression.fn.gather;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import com.scudata.array.IArray;
import com.scudata.array.IntArray;
import com.scudata.array.LongArray;
import com.scudata.array.ObjectArray;
import com.scudata.common.MessageManager;
import com.scudata.common.ObjectCache;
import com.scudata.common.RQException;
import com.scudata.dm.Context;
import com.scudata.dm.Env;
import com.scudata.dm.FileObject;
import com.scudata.dm.ObjectWriter;
import com.scudata.dm.Sequence;
import com.scudata.expression.Expression;
import com.scudata.expression.Gather;
import com.scudata.expression.IParam;
import com.scudata.resources.EngineMessage;
import com.scudata.thread.MultithreadUtil;
import com.scudata.util.HashUtil;
import com.scudata.util.Variant;
/**
* ȡ???ظ???Ԫ?ظ?????ȥ??ȡֵΪfalse??Ԫ??
* icount(x1,??)
* @author RunQian
*
*/
public class ICount extends Gather {
private Expression exp; // ????ʽ
private boolean isSorted = false; // ?????Ƿ???ʽ????
private boolean optB = false; // ʹ??λģʽ
private int maxSize = 0;
// ʹ????????icount
public static class ICountFile {
private final int MAX_SIZE;
private IArray elementArray; // ??ϣ????ŵ???Ԫ?ص?λ?ã???Ҫ????λ?õ?Դ??ȡԪ??
private int []linkArray; // ??ϣֵ??ͬ?ļ?¼????
private HashUtil hashUtil; // ???ڼ????ϣֵ
private int []entries; // ??ϣ????????Ź?ϣֵ??Ӧ?????һ????¼??λ??
private ArrayList fileList = new ArrayList();
public ICountFile(int maxSize) {
this.MAX_SIZE = maxSize;
elementArray = new ObjectArray(maxSize);
linkArray = new int[maxSize + 1];
hashUtil = new HashUtil(maxSize);
entries = new int[hashUtil.getCapacity()];
}
public ICountFile(IArray valueArray, int maxSize) {
this.MAX_SIZE = maxSize;
elementArray = valueArray.newInstance(maxSize);
linkArray = new int[maxSize + 1];
hashUtil = new HashUtil(maxSize);
entries = new int[hashUtil.getCapacity()];
}
private void addValue(Object value) {
int []entries = this.entries;
int hash = hashUtil.hashCode(value);
int seq = entries[hash];
while (seq != 0) {
if (elementArray.isEquals(seq, value)) {
return;
} else {
seq = linkArray[seq];
}
}
int count = elementArray.size();
if (count == MAX_SIZE) {
Object []values = elementArray.toArray();
MultithreadUtil.sort(values);
FileObject fo = FileObject.createTempFileObject();
fileList.add(fo);
ObjectWriter writer = new ObjectWriter(fo.getOutputStream(false));
try {
writer.writeInt(count);
for (Object obj : values) {
writer.writeObject(obj);
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
writer.close();
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
}
elementArray.clear();
for (int i = 0, size = entries.length; i < size; ++i) {
entries[i] = 0;
}
elementArray.push(value);
entries[hash] = 1;
} else {
elementArray.push(value);
linkArray[count + 1] = entries[hash];
entries[hash] = count + 1;
}
}
public void add(Object value) {
if (value instanceof ICountFile) {
ICountFile cf = (ICountFile)value;
fileList.addAll(cf.fileList);
IArray array = cf.elementArray;
int size1 = elementArray.size();
int size2 = array.size();
if (size1 + size2 > MAX_SIZE) {
if (size2 >= size1) {
Object []values = array.toArray();
MultithreadUtil.sort(values);
FileObject fo = FileObject.createTempFileObject();
fileList.add(fo);
ObjectWriter writer = new ObjectWriter(fo.getOutputStream(false));
try {
writer.writeInt(size2);
for (Object obj : values) {
writer.writeObject(obj);
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
writer.close();
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
}
} else {
Object []values = elementArray.toArray();
MultithreadUtil.sort(values);
FileObject fo = FileObject.createTempFileObject();
fileList.add(fo);
ObjectWriter writer = new ObjectWriter(fo.getOutputStream(false));
try {
writer.writeInt(size1);
for (Object obj : values) {
writer.writeObject(obj);
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
writer.close();
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
}
elementArray = cf.elementArray;
linkArray = cf.linkArray;
hashUtil = cf.hashUtil;
entries = cf.entries;
}
} else {
for (int i = 1; i <= size2; ++i) {
addValue(array.get(i));
}
}
} else if (value != null) {
addValue(value);
}
}
public long result() {
int fileCount = fileList.size();
if (fileCount == 0) {
return elementArray.size();
}
Object []objs = elementArray.toArray();
MultithreadUtil.sort(objs);
IValues []valuesArray = new IValues[fileCount + 1];
valuesArray[0] = new Values(objs);
for (int i = 0; i < fileCount; ++i) {
valuesArray[i + 1] = new FileValues(fileList.get(i));
}
long result = count(valuesArray);
return result;
}
private static long count(IValues []valuesArray, int path, Object value) {
if (valuesArray[path] == null) {
return 0;
}
long result = 0;
Object curValue = valuesArray[path].getTop();
int pathCount = valuesArray.length;
int nextPath = path + 1;
while (curValue != null) {
int cmp = Variant.compare(value, curValue, true);
if (cmp < 0) {
if (nextPath < valuesArray.length) {
return result + count(valuesArray, nextPath, value);
} else {
return result;
}
} else if (cmp == 0) {
valuesArray[path].pop();
if (nextPath < valuesArray.length) {
return result + count(valuesArray, nextPath, value);
} else {
return result;
}
} else {
result++;
if (nextPath < valuesArray.length) {
result += count(valuesArray, nextPath, curValue);
}
valuesArray[path].pop();
curValue = valuesArray[path].getTop();
}
}
pathCount--;
if (path < pathCount) {
System.arraycopy(valuesArray, path + 1, valuesArray, path, pathCount - path);
valuesArray[pathCount] = null;
return result + count(valuesArray, path, value);
} else {
valuesArray[pathCount] = null;
return result;
}
}
private static long count(IValues []valuesArray) {
int pathCount = valuesArray.length;
long result = 0;
while (true) {
Object value = valuesArray[0].pop();
if (value != null) {
result += count(valuesArray, 1, value) + 1;
} else if (valuesArray[1] != null){
pathCount--;
System.arraycopy(valuesArray, 1, valuesArray, 0, pathCount);
valuesArray[pathCount] = null;
} else {
break;
}
}
return result;
}
}
// ????icount???м?????Ϣ
public static class ICountInfo implements Serializable {
private static final long serialVersionUID = 1L;
private int count;
private Object startValue;
private Object endValue;
public ICountInfo() {
}
public ICountInfo(Object startValue) {
if (startValue != null) {
count = 1;
this.startValue = startValue;
this.endValue = startValue;
}
}
public void put(Object value) {
if (value instanceof ICountInfo) {
ICountInfo next = (ICountInfo)value;
if (count == 0) {
count = next.count;
startValue = next.startValue;
endValue = next.endValue;
} else if (next.count != 0) {
if (Variant.isEquals(endValue, next.startValue)) {
count += next.count - 1;
} else {
count += next.count;
}
endValue = next.endValue;
}
} else if (value != null) {
if (endValue == null) {
// ǰ??Ķ??ǿ?
startValue = value;
endValue = value;
count = 1;
} else if (!Variant.isEquals(endValue, value)) {
count++;
endValue = value;
}
}
}
}
//û??ʹ?ã??ȷ???????
public static class ICountHashSet implements Serializable {
private static final long serialVersionUID = 1L;
private static final int INIT_SIZE = 64;
private IArray elementArray; // ??ϣ????ŵ???Ԫ?ص?λ?ã???Ҫ????λ?õ?Դ??ȡԪ??
private HashUtil hashUtil; // ???ڼ????ϣֵ
private int count = 0;// ??ǰԪ?ظ???
private int []entries; // ??ϣ????????Ź?ϣֵ??Ӧ?????һ????¼??λ??
private IntArray linkArray; // ??ϣֵ??ͬ?ļ?¼????
public ICountHashSet(IArray src) {
hashUtil = new HashUtil(INIT_SIZE);
entries = new int[hashUtil.getCapacity()];
linkArray = new IntArray(INIT_SIZE);
elementArray = src.newInstance(INIT_SIZE);
}
public void add(IArray array, int index) {
if (array.isNull(index)) {
return;
}
IArray elementArray = this.elementArray;
int[] linkArray = this.linkArray.getDatas();
int[] entries = this.entries;
int hash = hashUtil.hashCode(array.hashCode(index));
int seq = entries[hash];
while (seq != 0) {
if (elementArray.isEquals(seq, array, index)) {
return;
} else {
seq = linkArray[seq];
}
}
count++;
int count = this.count;
if (count == linkArray.length) {
this.linkArray.setSize(count - 1);
elementArray.ensureCapacity(count);
this.linkArray.ensureCapacity(count);
linkArray = this.linkArray.getDatas();
}
elementArray.push(array, index);
linkArray[count] = entries[hash];
entries[hash] = count;
}
public void addInt(int key) {
int[] elementArray = ((IntArray) this.elementArray).getDatas();
int[] linkArray = this.linkArray.getDatas();
int[] entries = this.entries;
int hash = hashUtil.hashCode(key);//key % INIT_SIZE;//
int seq = entries[hash];
while (seq != 0) {
if (elementArray[seq] == key) {
return;
} else {
seq = linkArray[seq];
}
}
count++;
int count = this.count;
if (count == linkArray.length) {
this.elementArray.setSize(count - 1);
this.linkArray.setSize(count - 1);
this.elementArray.ensureCapacity(count);
this.linkArray.ensureCapacity(count);
elementArray = ((IntArray) this.elementArray).getDatas();
linkArray = this.linkArray.getDatas();
}
elementArray[count] = key;
linkArray[count] = entries[hash];
entries[hash] = count;
}
public void addAll(IArray array) {
if (elementArray == null) {
elementArray = array.newInstance(INIT_SIZE);
}
IArray elementArray = this.elementArray;
int[] linkArray = this.linkArray.getDatas();
int[] entries = this.entries;
HashUtil hashUtil = this.hashUtil;
int count = this.count;
for (int i = 1, len = array.size(); i <= len; i++) {
if (array.isNull(i)) {
continue;
}
int hash = hashUtil.hashCode(array.hashCode(i));
int seq = entries[hash];
boolean find = false;
while (seq != 0) {
if (elementArray.isEquals(seq, array, i)) {
find = true;
break;
} else {
seq = linkArray[seq];
}
}
if (find) continue;
count++;
if (count == linkArray.length) {
elementArray.ensureCapacity(count);
this.linkArray.setSize(count - 1);
this.linkArray.ensureCapacity(count);
linkArray = this.linkArray.getDatas();
}
elementArray.push(array, i);
linkArray[count] = entries[hash];
entries[hash] = count;
}
this.count = count;
}
public int size() {
return count;
}
}
//??bitλ?ж??Ƿ??ظ?
public static class ICountBitSet implements Serializable {
private static final long serialVersionUID = 1L;
private static final int INIT_BIT_SIZE = 1024;
private int count = 0;
private long[] bitArray;
public ICountBitSet() {
bitArray = new long[INIT_BIT_SIZE];
}
public ICountBitSet(long[] bitArray) {
this.bitArray = bitArray;
count = countBit(bitArray);
}
public boolean add(int num) {
//IntArray elementArray = this.elementArray;
int idx = (num / 64);
long bit = (1L << (num % 64));
long[] bitArray = this.bitArray;
if (idx >= bitArray.length) {
int newSize = idx + idx / 3;
long[] newBitArray = new long[newSize];
System.arraycopy(bitArray, 0, newBitArray, 0, bitArray.length);
bitArray = this.bitArray = newBitArray;
}
long cur = bitArray[idx];
if ((cur & bit) != 0) {
return false;
} else {
bitArray[idx] = cur | bit;
count++;
}
return true;
}
public boolean add(IArray array, int index) {
if (array.isNull(index)) {
return false;
}
int num = array.getInt(index);
int idx = (num / 64);
long bit = (1L << (num % 64));
long[] bitArray = this.bitArray;
if (idx >= bitArray.length) {
int newSize = idx + idx / 3;
long[] newBitArray = new long[newSize];
System.arraycopy(bitArray, 0, newBitArray, 0, bitArray.length);
bitArray = this.bitArray = newBitArray;
}
long cur = bitArray[idx];
if ((cur & bit) != 0) {
return false;
} else {
bitArray[idx] = cur | bit;
count++;;
}
return true;
}
public static int countBit(long[] bitArray) {
int count = 0;
for (long i : bitArray) {
i = i - ((i >>> 1) & 0x5555555555555555L);
i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L);
i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
i = i + (i >>> 8);
i = i + (i >>> 16);
i = i + (i >>> 32);
count += (int)i & 0x7f;
}
return count;
}
public int size() {
return count;
}
public void addAll(long[] newBits) {
long[] curBits = bitArray;
int newLen = newBits.length;
int curLen = curBits.length;
if (curLen >= newLen) {
for (int i = 0; i <= newLen; i++) {
curBits[i] |= newBits[i];
}
} else {
long[] temp = new long[newLen];
System.arraycopy(newBits, curLen, temp, curLen, newLen - curLen);
for (int i = 0; i <= curLen; i++) {
temp[i] = curBits[i] | newBits[i];
}
bitArray = temp;
}
count = countBit(bitArray);
}
public void addAll(ICountBitSet set) {
long[] newBits = set.bitArray;
addAll(newBits);
}
}
//??λ???ж??Ƿ??ظ?
public static class ICountPositionSet implements Serializable {
private static final long serialVersionUID = 1L;
private static final int INIT_SIZE = 65536;
private int count = 0;
private boolean[] posArray;
public ICountPositionSet() {
posArray = new boolean[INIT_SIZE];
}
public boolean add(int num) {
boolean[] posArray = this.posArray;
if (num >= posArray.length) {
int newSize = num + num / 3;
boolean[] newPosArray = new boolean[newSize];
System.arraycopy(posArray, 0, newPosArray, 0, posArray.length);
posArray = this.posArray = newPosArray;
}
if (posArray[num]) {
return false;
} else {
posArray[num] = true;
count++;
}
return true;
}
public boolean add(IArray array, int index) {
int num = array.getInt(index);
boolean[] posArray = this.posArray;
if (num >= posArray.length) {
int newSize = num + num / 3;
boolean[] newPosArray = new boolean[newSize];
System.arraycopy(posArray, 0, newPosArray, 0, posArray.length);
posArray = this.posArray = newPosArray;
}
if (posArray[num]) {
return false;
} else {
posArray[num] = true;
count++;;
}
return true;
}
public int size() {
return count;
}
}
public Object calculate(Context ctx) {
IParam param = this.param;
if (param == null) {
MessageManager mm = EngineMessage.get();
throw new RQException("icount" + mm.getMessage("function.missingParam"));
} else if (param.isLeaf()) {
Object obj = param.getLeafExpression().calculate(ctx);
if (obj instanceof Sequence) {
return ((Sequence)obj).icount(option);
} else {
if (Variant.isTrue(obj)) {
return ObjectCache.getInteger(1);
} else {
return ObjectCache.getInteger(0);
}
}
}
int size = param.getSubSize();
HashSet
© 2015 - 2024 Weber Informatics LLC | Privacy Policy