org.zoodb.index.critbit.BitTools Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of phtree Show documentation
Show all versions of phtree Show documentation
The PH-Tree is a multi-dimensional index
/*
* Copyright 2009-2017 Tilmann Zaeschke. All rights reserved.
*
* This file is part of TinSpin.
*
* Licensed 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.
*/
package org.zoodb.index.critbit;
/**
*
* @author Tilmann Zaeschke
*/
public class BitTools {
/**
* @param value value to convert
* @return long representation.
*/
public static long toSortableLong(double value) {
//To create a sortable long, we convert the double to a long using the IEEE-754 standard,
//which stores floats in the form .
//This result is properly ordered longs for all positive doubles. Negative values have
//inverse ordering. For negative doubles, we therefore simply invert them to make them
//sortable, however the sign must be inverted again to stay negative.
long r = Double.doubleToRawLongBits(value);
return (r >= 0) ? r : r ^ 0x7FFFFFFFFFFFFFFFL;
}
public static long toSortableLong(float value) {
//see toSortableLong(double)
int r = Float.floatToRawIntBits(value);
return (r >= 0) ? r : r ^ 0x7FFFFFFF;
}
public static double toDouble(long value) {
return Double.longBitsToDouble(value >= 0.0 ? value : value ^ 0x7FFFFFFFFFFFFFFFL);
}
public static float toFloat(long value) {
int iVal = (int) value;
return Float.intBitsToFloat(iVal >= 0.0 ? iVal : iVal ^ 0x7FFFFFFF);
}
/**
* @param value Value to be transformed
* @param ret The array used to store the return value
* @return long representation.
*/
public static long[] toSortableLong(double[] value, long[] ret) {
//To create a sortable long, we convert the double to a long using the IEEE-754 standard,
//which stores floats in the form .
//This result is properly ordered longs for all positive doubles. Negative values have
//inverse ordering. For negative doubles, we therefore simply invert them to make them
//sortable, however the sign must be inverted again to stay negative.
for (int i = 0; i < value.length; i++) {
long r = Double.doubleToRawLongBits(value[i]);
ret[i] = (r >= 0) ? r : r ^ 0x7FFFFFFFFFFFFFFFL;
}
return ret;
}
public static long[] toSortableLong(float[] value, long[] ret) {
//see toSortableLong(double)
for (int i = 0; i < value.length; i++) {
int r = Float.floatToRawIntBits(value[i]);
ret[i] = (r >= 0) ? r : r ^ 0x7FFFFFFF;
}
return ret;
}
public static double[] toDouble(long value[], double[] ret) {
for (int i = 0; i < value.length; i++) {
ret[i] = Double.longBitsToDouble(
value[i] >= 0.0 ? value[i] : value[i] ^ 0x7FFFFFFFFFFFFFFFL);
}
return ret;
}
public static float[] toFloat(long[] value, float[] ret) {
for (int i = 0; i < value.length; i++) {
int iVal = (int) value[i];
ret[i] = Float.intBitsToFloat(iVal >= 0.0 ? iVal : iVal ^ 0x7FFFFFFF);
}
return ret;
}
public static long toSortableLong(String s) {
// store magic number: 6 chars + (hash >> 16)
long n = 0;
int i = 0;
for ( ; i < 6 && i < s.length(); i++ ) {
n |= (byte) s.charAt(i);
n = n << 8;
}
//Fill with empty spaces if string is too short
for ( ; i < 6; i++) {
n = n << 8;
}
n = n << 8;
//add hashcode
n |= (0xFFFF & s.hashCode());
return n;
}
/**
* Reverses the value, considering that not all 64bits of the long value are used.
* @param l value to be reversed
* @param usedBits Number of bits to be considered
* @return Reversed value
*/
public static long reverse(long l, int usedBits) {
long r = Long.reverse(l);
r >>>= (64-usedBits);
return r;
}
/**
* Splits a value and write it to trgV at position trg1 and trg2.
* This is the inverse operation to merge(...).
* @param toSplit value to split
* @param trgV return value
* @param trg1 return position part 1
* @param trg2 return position part 2
* @param nBits Number of bits of source value
*/
public static void split(final long toSplit, long[] trgV, final int trg1, final int trg2,
int nBits) {
long maskSrc = 1L << (nBits-1);
long t1 = 0;
long t2 = 0;
for (int i = 0; i < nBits; i++) {
if ((i&1) == 0) {
t1 <<= 1;
if ((toSplit & maskSrc) != 0L) {
t1 |= 1L;
}
} else {
t2 <<= 1;
if ((toSplit & maskSrc) != 0L) {
t2 |= 1L;
}
}
maskSrc >>>= 1;
}
trgV[trg1] = t1;
trgV[trg2] = t2;
}
/**
* Merges two long values into a single value by interleaving there respective bits.
* This is the inverse operation to split(...).
* @param srcV Source array
* @param src1 Position of 1st source value
* @param src2 Position of 2nd source value
* @param nBits Number of bits of RESULT
* @return Merged result
*/
public static long merge(long[] srcV, final int src1, final int src2, int nBits) {
long maskTrg = 1L;
long v = 0;
long s1 = srcV[src1];
long s2 = srcV[src2];
for (int i = nBits-1; i >=0; i--) {
if ( (i & 1) == 0) {
if ((s1 & 1L) == 1L) {
v |= maskTrg;
}
s1 >>>= 1;
} else {
if ((s2 & 1L) == 1L) {
v |= maskTrg;
}
s2 >>>= 1;
}
maskTrg <<= 1;
}
return v;
}
/**
* Merges long values into a single value by interleaving there respective bits.
* This is the inverse operation to split(...).
* @param src Source array
* @param nBitsPerValue Number of bits of each source value
* @return Merged result
*/
public static long[] mergeLong(final int nBitsPerValue, long[] src) {
final int DIM = src.length;
int intArrayLen = (src.length*nBitsPerValue+63) >>> 6;
long[] trg = new long[intArrayLen];
long maskSrc = 1L << (nBitsPerValue-1);
long maskTrg = 0x8000000000000000L;
int srcPos = 0;
int trgPos = 0;
for (int j = 0; j < nBitsPerValue*DIM; j++) {
if ((src[srcPos] & maskSrc) != 0) {
trg[trgPos] |= maskTrg;
} else {
trg[trgPos] &= ~maskTrg;
}
maskTrg >>>= 1;
if (maskTrg == 0) {
maskTrg = 0x8000000000000000L;
trgPos++;
}
if (++srcPos == DIM) {
srcPos = 0;
maskSrc >>>= 1;
}
}
return trg;
}
/**
* Splits a value and write it to trgV at position trg1 and trg2.
* This is the inverse operation to merge(...).
* @param dims number of splinters to split into
* @param toSplit value to split
* @param nBitsPerValue Number of bits of source value
* @return long[] with 'dims' entries
*/
public static long[] splitLong(final int dims, final int nBitsPerValue, final long[] toSplit) {
long[] trg = new long[dims];
long maskTrg = 1L << (nBitsPerValue-1);
for (int k = 0; k < nBitsPerValue; k++) {
for (int j = 0; j < trg.length; j++) {
int posBit = k*trg.length + j;
boolean bit = getBit(toSplit, posBit);
if (bit) {
trg[j] |= maskTrg;
}
}
maskTrg >>>= 1;
}
return trg;
}
/**
* @param ba byte array
* @param posBit Counts from left to right!!!
* @return current bit
*/
public static boolean getBit(long[] ba, int posBit) {
int pA = posBit >>> 6; // 1/64
//last 6 bit [0..63]
posBit &= 0x3F;
return (ba[pA] & (0x8000000000000000L >>> posBit)) != 0;
}
/**
* @param l bit set
* @param posBit Counts from left to right!!!
* @return current bit
*/
public static boolean getBit(long l, int posBit) {
//last 6 bit [0..63]
return (l & (0x8000000000000000L >>> posBit)) != 0;
}
/**
* @param src source array
* Reads a bit from {@code src}, writes it to {@code dst} and returns it.
* @param posBit Counts from left to right
* @param dst target array
* @return current bit
*/
public static boolean getAndCopyBit(long[] src, int posBit, long[] dst) {
int pA = posBit >>> 6; // 1/64
//last 6 bit [0..63]
posBit &= 0x3F;
long mask = (0x8000000000000000L >>> posBit);
if ( (src[pA] & mask) != 0 ) {
dst[pA] |= mask;
return true;
} else {
dst[pA] &= ~mask;
return false;
}
}
/**
* @param ba byte array
* @param posBit Counts from left to right (highest to lowest)!!!
* @param b bit to set
*/
public static void setBit(long[] ba, int posBit, boolean b) {
int pA = posBit >>> 6; // 1/64
//last 6 bit [0..63]
posBit &= 0x3F;
if (b) {
ba[pA] |= (0x8000000000000000L >>> posBit);
} else {
ba[pA] &= (~(0x8000000000000000L >>> posBit));
}
}
public static long setBit(long ba, int posBit, boolean b) {
if (b) {
return ba | (0x8000000000000000L >>> posBit);
} else {
return ba & (~(0x8000000000000000L >>> posBit));
}
}
public static long set1(long ba, int posBit) {
return ba | (0x8000000000000000L >>> posBit);
}
public static long set0(long ba, int posBit) {
return ba & (~(0x8000000000000000L >>> posBit));
}
public static String toBinary(long[] la, int DEPTH) {
StringBuilder sb = new StringBuilder();
for (long l: la) {
sb.append(toBinary(l, DEPTH));
sb.append(", ");
}
return sb.toString();
}
public static String toBinary(long l, int DEPTH) {
StringBuilder sb = new StringBuilder();
//long mask = DEPTH < 64 ? (1<<(DEPTH-1)) : 0x8000000000000000L;
for (int i = 0; i < DEPTH; i++) {
long mask = (1l << (long)(DEPTH-i-1));
if ((l & mask) != 0) { sb.append("1"); } else { sb.append("0"); }
if ((i+1)%8==0 && (i+1)>>= 1;
}
return sb.toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy