/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.solr.util;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.solr.util.NumberUtils;
import org.apache.solr.util.BCDUtils;
import org.junit.Assert;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class TestNumberUtils extends LuceneTestCase {
private static String arrstr(char[] arr, int start, int end) {
String str="[";
for (int i=start; i<end; i++) str += arr[i]+"("+(int)arr[i]+"),";
return str+"]";
}
static Random rng = new Random();
static int[] special = {0,10,100,1000,10000,Integer.MAX_VALUE, Integer.MIN_VALUE};
static int getSpecial() {
int i = rng.nextInt();
int j = rng.nextInt();
if ((i & 0x10) != 0) return j;
return special[(j&0x7fffffff) % special.length]* ((i & 0x20)==0?1:-1) + ((i&0x03)-1);
}
static long[] lspecial = {0,10,100,1000,10000,2,4,8,256,16384,32768,65536,
Integer.MAX_VALUE, Integer.MIN_VALUE,
Long.MAX_VALUE, Long.MIN_VALUE};
static long getLongSpecial() {
int i = rng.nextInt();
long j = rng.nextLong();
if ((i & 0x10) != 0) return j;
return lspecial[((int)j&0x7fffffff) % special.length]* ((i & 0x20)==0?1:-1) + ((i&0x03)-1);
}
static float[] fspecial = {0,1,2,4,8,256,16384,32768,65536,.1f,.25f
,Float.NEGATIVE_INFINITY,Float.POSITIVE_INFINITY,Float.MIN_VALUE, Float.MAX_VALUE};
static float getFloatSpecial() {
int i = rng.nextInt();
int j = rng.nextInt();
float f = Float.intBitsToFloat(j);
if (f!=f) f=0; // get rid of NaN for comparison purposes
if ((i & 0x10) != 0) return f;
return fspecial[(j&0x7fffffff) % fspecial.length]* ((i & 0x20)==0?1:-1) + ((i&0x03)-1);
}
static double[] dspecial = {0,1,2,4,8,256,16384,32768,65536,.1,.25
,Float.NEGATIVE_INFINITY,Float.POSITIVE_INFINITY,Float.MIN_VALUE, Float.MAX_VALUE
,Double.NEGATIVE_INFINITY,Double.POSITIVE_INFINITY,Double.MIN_VALUE, Double.MAX_VALUE
};
static double getDoubleSpecial() {
int i = rng.nextInt();
long j = rng.nextLong();
double f = Double.longBitsToDouble(j);
if (f!=f) f=0; // get rid of NaN for comparison purposes
if ((i & 0x10) != 0) return f;
return dspecial[((int)j&0x7fffffff) % dspecial.length]* ((i & 0x20)==0?1:-1) + ((i&0x03)-1);
}
public static void test(Comparable n1, Comparable n2, Converter conv) {
String s1=n1.toString();
String s2=n2.toString();
String v1 = conv.toInternal(s1);
String v2 = conv.toInternal(s2);
String out1=conv.toExternal(v1);
String out2=conv.toExternal(v2);
Assert.assertEquals(conv + " :: n1 :: input!=output", s1, out1);
Assert.assertEquals(conv + " :: n2 :: input!=output", s2, out2);
int c1 = n1.compareTo(n2);
int c2 = v1.compareTo(v2);
Assert.assertFalse( (c1==0 && !(c2==0)) );
// Assert.assertFalse( c1 < 0 && !(c2<0) );
// Assert.assertFalse( c1 > 0 && !(c2>0) );
//
// if (c1==0 && !(c2==0)
// || c1 < 0 && !(c2<0)
// || c1 > 0 && !(c2>0)
// || !out1.equals(s1) || !out2.equals(s2))
// {
// Assert.fail("Comparison error:"+s1+","+s2 + " :: " + conv);
// System.out.print("v1=");
// for (int ii=0; ii<v1.length(); ii++) {
// System.out.print(" " + (int)v1.charAt(ii));
// }
// System.out.print("\nv2=");
// for (int ii=0; ii<v2.length(); ii++) {
// System.out.print(" " + (int)v2.charAt(ii));
// }
// System.out.println("\nout1='"+out1+"', out2='" + out2 + "'");
// }
}
public void testConverters()
{
int iter=1000;
int arrsz=100000;
int num=12345;
// INTEGERS
List<Converter> converters = new ArrayList<Converter>();
converters.add( new Int2Int() );
converters.add( new SortInt() );
converters.add( new Base10kS() );
converters.add( new Base100S() );
for( Converter c : converters ) {
for (int i=0; i<iter; i++) {
Comparable n1 = getSpecial();
Comparable n2 = getSpecial();
test( n1, n2, c );
}
}
// LONG
converters.clear();
converters.add( new SortLong() );
converters.add( new Base10kS() );
converters.add( new Base100S() );
for( Converter c : converters ) {
for (int i=0; i<iter; i++) {
Comparable n1 = getLongSpecial();
Comparable n2 = getLongSpecial();
test( n1, n2, c );
}
}
// FLOAT
converters.clear();
converters.add( new Float2Float() );
converters.add( new SortFloat() );
for( Converter c : converters ) {
for (int i=0; i<iter; i++) {
Comparable n1 = getFloatSpecial();
Comparable n2 = getFloatSpecial();
test( n1, n2, c );
}
}
// DOUBLE
converters.clear();
converters.add( new SortDouble() );
for( Converter c : converters ) {
for (int i=0; i<iter; i++) {
Comparable n1 = getDoubleSpecial();
Comparable n2 = getDoubleSpecial();
test( n1, n2, c );
}
}
}
}
abstract class Converter {
abstract String toInternal(String val);
abstract String toExternal(String val);
}
class Int2Int extends Converter {
public String toInternal(String val) {
return Integer.toString(Integer.parseInt(val));
}
public String toExternal(String val) {
return Integer.toString(Integer.parseInt(val));
}
}
class SortInt extends Converter {
public String toInternal(String val) {
return NumberUtils.int2sortableStr(val);
}
public String toExternal(String val) {
return NumberUtils.SortableStr2int(val);
}
}
class SortLong extends Converter {
public String toInternal(String val) {
return NumberUtils.long2sortableStr(val);
}
public String toExternal(String val) {
return NumberUtils.SortableStr2long(val);
}
}
class Float2Float extends Converter {
public String toInternal(String val) {
return Float.toString(Float.parseFloat(val));
}
public String toExternal(String val) {
return Float.toString(Float.parseFloat(val));
}
}
class SortFloat extends Converter {
public String toInternal(String val) {
return NumberUtils.float2sortableStr(val);
}
public String toExternal(String val) {
return NumberUtils.SortableStr2floatStr(val);
}
}
class SortDouble extends Converter {
public String toInternal(String val) {
return NumberUtils.double2sortableStr(val);
}
public String toExternal(String val) {
return NumberUtils.SortableStr2doubleStr(val);
}
}
class Base100S extends Converter {
public String toInternal(String val) {
return BCDUtils.base10toBase100SortableInt(val);
}
public String toExternal(String val) {
return BCDUtils.base100SortableIntToBase10(val);
}
}
class Base10kS extends Converter {
public String toInternal(String val) {
return BCDUtils.base10toBase10kSortableInt(val);
}
public String toExternal(String val) {
return BCDUtils.base10kSortableIntToBase10(val);
}
}