package org.compass.core.converter.basic.format;
/**
* @author kimchy
*/
// TAKEN FROM SOLR, thanks!
public class NumberUtils {
public static String int2sortableStr(int val) {
char[] arr = new char[3];
int2sortableStr(val, arr, 0);
return new String(arr, 0, 3);
}
public static String int2sortableStr(String val) {
return int2sortableStr(Integer.parseInt(val));
}
public static int SortableStr2int(String val) {
return SortableStr2int(val, 0, 3);
}
public static String long2sortableStr(long val) {
char[] arr = new char[5];
long2sortableStr(val, arr, 0);
return new String(arr, 0, 5);
}
public static String long2sortableStr(String val) {
return long2sortableStr(Long.parseLong(val));
}
public static long SortableStr2long(String val) {
return SortableStr2long(val, 0, 5);
}
//
// IEEE floating point format is defined so that it sorts correctly
// when interpreted as a signed integer (or signed long in the case
// of a double) for positive values. For negative values, all the bits except
// the sign bit must be inverted.
// This correctly handles all possible float values including -Infinity and +Infinity.
// Note that in float-space, NaN<x is false, NaN>x is false, NaN==x is false, NaN!=x is true
// for all x (including NaN itself). Internal to Solr, NaN==NaN is true and NaN
// sorts higher than Infinity, so a range query of [-Infinity TO +Infinity] will
// exclude NaN values, but a query of "NaN" will find all NaN values.
// Also, -0==0 in float-space but -0<0 after this transformation.
//
public static String float2sortableStr(float val) {
int f = Float.floatToRawIntBits(val);
if (f < 0) f ^= 0x7fffffff;
return int2sortableStr(f);
}
public static String float2sortableStr(String val) {
return float2sortableStr(Float.parseFloat(val));
}
public static float SortableStr2float(String val) {
int f = SortableStr2int(val, 0, 3);
if (f < 0) f ^= 0x7fffffff;
return Float.intBitsToFloat(f);
}
public static String SortableStr2floatStr(String val) {
return Float.toString(SortableStr2float(val));
}
public static String double2sortableStr(double val) {
long f = Double.doubleToRawLongBits(val);
if (f < 0) f ^= 0x7fffffffffffffffL;
return long2sortableStr(f);
}
public static String double2sortableStr(String val) {
return double2sortableStr(Double.parseDouble(val));
}
public static double SortableStr2double(String val) {
long f = SortableStr2long(val, 0, 6);
if (f < 0) f ^= 0x7fffffffffffffffL;
return Double.longBitsToDouble(f);
}
public static String SortableStr2doubleStr(String val) {
return Double.toString(SortableStr2double(val));
}
// uses binary representation of an int to build a string of
// chars that will sort correctly. Only char ranges
// less than 0xd800 will be used to avoid UCS-16 surrogates.
public static int int2sortableStr(int val, char[] out, int offset) {
val += Integer.MIN_VALUE;
out[offset++] = (char) (val >>> 24);
out[offset++] = (char) ((val >>> 12) & 0x0fff);
out[offset++] = (char) (val & 0x0fff);
return 3;
}
public static int SortableStr2int(String sval, int offset, int len) {
int val = sval.charAt(offset++) << 24;
val |= sval.charAt(offset++) << 12;
val |= sval.charAt(offset++);
val -= Integer.MIN_VALUE;
return val;
}
// uses binary representation of an int to build a string of
// chars that will sort correctly. Only char ranges
// less than 0xd800 will be used to avoid UCS-16 surrogates.
// we can use the lowest 15 bits of a char, (or a mask of 0x7fff)
public static int long2sortableStr(long val, char[] out, int offset) {
val += Long.MIN_VALUE;
out[offset++] = (char) (val >>> 60);
out[offset++] = (char) (val >>> 45 & 0x7fff);
out[offset++] = (char) (val >>> 30 & 0x7fff);
out[offset++] = (char) (val >>> 15 & 0x7fff);
out[offset] = (char) (val & 0x7fff);
return 5;
}
public static long SortableStr2long(String sval, int offset, int len) {
long val = (long) (sval.charAt(offset++)) << 60;
val |= ((long) sval.charAt(offset++)) << 45;
val |= ((long) sval.charAt(offset++)) << 30;
val |= sval.charAt(offset++) << 15;
val |= sval.charAt(offset);
val -= Long.MIN_VALUE;
return val;
}
}