/* XXL: The eXtensible and fleXible Library for data processing
Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger
Head of the Database Research Group
Department of Mathematics and Computer Science
University of Marburg
Germany
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; If not, see <http://www.gnu.org/licenses/>.
http://code.google.com/p/xxl/
*/
package xxl.core.util;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Random;
import xxl.core.io.converters.FixedSizeConverter;
public class Signature {
/**
* Constructs a converter for a signature.
* @return The converter.
*/
public static FixedSizeConverter getConverter(final int sigLength, final int sigWeight) {
return new FixedSizeConverter((sigLength+7)>>3) {
Signature nullSignature = new Signature(sigLength);
/**
* Serializes this Signature to the DataOutput-Stream.
* @param dataOutput the DataOutput-Stream
*/
public void write(DataOutput dataOutput, Object o) throws IOException {
// if (o==null)
// dataOutput.write(nullSignature.s);
// else
dataOutput.write(((Signature)o).s);
}
/**
* Reconstructs the attributes from the DataInput-Stream.
* @param dataInput the DataInput-Stream that contains the serialized informations.
*/
public Object read(DataInput dataInput, Object o) throws IOException {
if (o==null) {
byte b[] = new byte[(sigLength+7)>>3];
dataInput.readFully(b);
return new Signature(sigLength, b);
}
else {
Signature sig = (Signature) o;
sig.length = sigLength;
dataInput.readFully(((Signature)o).s);
return sig;
}
}
};
}
protected byte[] s;
protected int length;
protected Signature(int length, byte s[]) {
this.length = length;
this.s = s;
}
protected Signature(int length) {
this(length, new byte[(length+7)>>3]);
}
private static final void setBit(byte[] s, int i) {
s[i>>3] |= (1<<(i&3));
}
private static final boolean getBit(byte[] s, int i) {
return (((s[i>>3] >> (i&7))) &1)==1;
}
public static Signature createSignature(int length, int weight, Random random) {
byte newSignature[] = new byte[(length+7)>>3];
for (int i=0; i<weight; i++) {
while (true) {
int bitNumber = random.nextInt(length);
if (!getBit(newSignature, bitNumber)) {
setBit(newSignature, bitNumber);
break;
}
}
}
return new Signature(length, newSignature);
}
public final boolean isInSignature(Signature inSig) {
for (int i=0; i<s.length; i++)
if ((s[i]&inSig.s[i])!=s[i])
return false;
return true;
}
public final Signature overlayWith(Signature s2) {
byte[] b = Arrays.copy(s, 0, s.length);
for (int i=0; i<s.length; i++)
b[i] |= s2.s[i];
return new Signature(length, b);
}
public Object clone() {
return new Signature(length, Arrays.copy(s, 0, s.length));
}
public String toString() {
StringBuffer sb = new StringBuffer();
for (int i=0; i<length; i++) {
if (getBit(s,i))
sb.append("1");
else
sb.append("0");
}
return sb.toString();
}
public boolean equals(Object o2) {
if (o2==null)
return false;
Signature s2 = (Signature) o2;
for (int i=0; i<s.length; i++)
if (s[i]!=s2.s[i])
return false;
return true;
}
public int hashCode() {
if (length<8)
return s[0];
else if (length<24)
return (s[0]<<8) | s[1];
else
// 25 Bits ==> 4 Bytes available
return (s[0]<<24) | (s[1]<<16) | (s[2]<<8) | s[3];
}
}