/**
* 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.hadoop.hive.common.type;
import java.util.Random;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.apache.hadoop.hive.common.type.RandomTypeUtil;
// A COPY of the one in storage-api since currently sharing test classes isn't supported in
// our build.
public class HiveDecimalTestBase {
public static int POUND_FACTOR = 1000;
public static enum BigDecimalFlavor {
NORMAL_RANGE,
FRACTIONS_ONLY,
NEGATIVE_SCALE,
LONG_TAIL
}
public static enum BigDecimalPairFlavor {
RANDOM,
NEAR,
INVERSE
}
public BigDecimal randHiveBigDecimal(Random r, String digitAlphabet, BigDecimalFlavor bigDecimalFlavor) {
switch (bigDecimalFlavor) {
case NORMAL_RANGE:
return randHiveBigDecimalNormalRange(r, digitAlphabet);
case FRACTIONS_ONLY:
return randHiveBigDecimalFractionsOnly(r, digitAlphabet);
case NEGATIVE_SCALE:
return randHiveBigDecimalNegativeScale(r, digitAlphabet);
case LONG_TAIL:
return randHiveBigDecimalLongTail(r, digitAlphabet);
default:
throw new RuntimeException("Unexpected big decimal flavor " + bigDecimalFlavor);
}
}
public BigDecimal[] randHiveBigDecimalPair(Random r, String digitAlphabet,
BigDecimalFlavor bigDecimalFlavor, BigDecimalPairFlavor bigDecimalPairFlavor) {
BigDecimal[] pair = new BigDecimal[2];
BigDecimal bigDecimal1 = randHiveBigDecimal(r, digitAlphabet, bigDecimalFlavor);
pair[0] = bigDecimal1;
BigDecimal bigDecimal2;
switch (bigDecimalPairFlavor) {
case RANDOM:
bigDecimal2 = randHiveBigDecimal(r, digitAlphabet, bigDecimalFlavor);
break;
case NEAR:
bigDecimal2 = randHiveBigDecimalNear(r, bigDecimal1);
break;
case INVERSE:
bigDecimal2 = randHiveBigDecimalNear(r, bigDecimal1);
break;
default:
throw new RuntimeException("Unexpected big decimal pair flavor " + bigDecimalPairFlavor);
}
pair[1] = bigDecimal2;
return pair;
}
public BigDecimal randHiveBigDecimalNormalRange(Random r, String digitAlphabet) {
String digits = RandomTypeUtil.getRandString(r, digitAlphabet, 1 + r.nextInt(38));
BigInteger bigInteger = new BigInteger(digits);
boolean negated = false;
if (r.nextBoolean()) {
bigInteger = bigInteger.negate();
negated = true;
}
int scale = 0 + r.nextInt(38 + 1);
return new BigDecimal(bigInteger, scale);
}
public BigDecimal randHiveBigDecimalNegativeScale(Random r, String digitAlphabet) {
String digits = RandomTypeUtil.getRandString(r, digitAlphabet, 1 + r.nextInt(38));
BigInteger bigInteger = new BigInteger(digits);
boolean negated = false;
if (r.nextBoolean()) {
bigInteger = bigInteger.negate();
negated = true;
}
int scale = 0 + (r.nextBoolean() ? 0 : r.nextInt(38 + 1));
if (r.nextBoolean()) {
scale = -scale;
}
return new BigDecimal(bigInteger, scale);
}
public BigDecimal randHiveBigDecimalLongTail(Random r, String digitAlphabet) {
int scale = 0 + r.nextInt(38 + 20);
final int maxDigits = 38 + (scale == 0 ? 0 : 20);
String digits = RandomTypeUtil.getRandString(r, digitAlphabet, 1 + r.nextInt(maxDigits));
BigInteger bigInteger = new BigInteger(digits);
boolean negated = false;
if (r.nextBoolean()) {
bigInteger = bigInteger.negate();
negated = true;
}
return new BigDecimal(bigInteger, scale);
}
public BigDecimal randHiveBigDecimalFractionsOnly(Random r, String digitAlphabet) {
int scale = 1 + r.nextInt(38 + 1);
String digits = RandomTypeUtil.getRandString(r, digitAlphabet, 1 + r.nextInt(scale));
BigInteger bigInteger = new BigInteger(digits);
boolean negated = false;
if (r.nextBoolean()) {
bigInteger = bigInteger.negate();
negated = true;
}
return new BigDecimal(bigInteger, scale);
}
public BigDecimal randHiveBigDecimalNear(Random r, BigDecimal bigDecimal) {
int scale = bigDecimal.scale();
int delta = r.nextInt(10);
if (r.nextBoolean()) {
return bigDecimal.add(new BigDecimal(BigInteger.valueOf(delta), scale));
} else {
return bigDecimal.subtract(new BigDecimal(BigInteger.valueOf(delta), scale));
}
}
public BigDecimal randHiveBigDecimalInverse(Random r, BigDecimal bigDecimal) {
if (bigDecimal.signum() == 0) {
return bigDecimal;
}
return BigDecimal.ONE.divide(bigDecimal);
}
public BigInteger randHiveBigInteger(Random r, String digitAlphabet) {
String digits = RandomTypeUtil.getRandString(r, digitAlphabet, 1 + r.nextInt(38));
BigInteger bigInteger = new BigInteger(digits);
boolean negated = false;
if (r.nextBoolean()) {
bigInteger = bigInteger.negate();
negated = true;
}
return bigInteger;
}
public boolean isTenPowerBug(String string) {
// // System.out.println("TEST_IS_TEN_TO_38_STRING isTenPowerBug " + string);
if (string.charAt(0) == '-') {
string = string.substring(1);
}
int index = string.indexOf('.');
if (index != -1) {
if (index == 0) {
string = string.substring(1);
} else {
string = string.substring(0, index) + string.substring(index + 1);
}
}
// // System.out.println("TEST_IS_TEN_TO_38_STRING isTenPowerBug " + string);
return string.equals("100000000000000000000000000000000000000");
}
//------------------------------------------------------------------------------------------------
public static String[] specialDecimalStrings = new String[] {
"0",
"1",
"-1",
"10",
"-10",
"100",
"-100",
"127", // Byte.MAX_VALUE
"127.1",
"127.0008",
"127.49",
"127.5",
"127.9999999999999999999",
"-127",
"-127.1",
"-127.0008",
"-127.49",
"-127.5",
"-127.999999",
"128",
"128.1",
"128.0008",
"128.49",
"128.5",
"128.9999999999999999999",
"-128", // Byte.MIN_VALUE
"-128.1",
"-128.0008",
"-128.49",
"-128.5",
"-128.999",
"129",
"129.1",
"-129",
"-129.1",
"1000",
"-1000",
"10000",
"-10000",
"32767", // Short.MAX_VALUE
"32767.1",
"32767.0008",
"32767.49",
"32767.5",
"32767.99999999999",
"-32767",
"-32767.1",
"-32767.0008",
"-32767.49",
"-32767.5",
"-32767.9",
"32768",
"32768.1",
"32768.0008",
"32768.49",
"32768.5",
"32768.9999999999",
"-32768", // Short.MIN_VALUE
"-32768.1",
"-32768.0008",
"-32768.49",
"-32768.5",
"-32768.9999999",
"32769",
"32769.1",
"-32769",
"-32769.1",
"100000",
"-100000",
"1000000",
"-1000000",
"10000000",
"-10000000",
"100000000",
"99999999", // 10^8 - 1
"-99999999",
"-100000000",
"1000000000",
"-1000000000",
"2147483647", // Integer.MAX_VALUE
"2147483647.1",
"2147483647.0008",
"2147483647.49",
"2147483647.5",
"2147483647.9999999999",
"-2147483647",
"-2147483647.1",
"-2147483647.0008",
"-2147483647.49",
"-2147483647.5",
"-2147483647.9999999999999999999",
"2147483648",
"2147483648.1",
"2147483648.0008",
"2147483648.49",
"2147483648.5",
"2147483648.9",
"-2147483648", // Integer.MIN_VALUE
"-2147483648.1",
"-2147483648.0008",
"-2147483648.49",
"-2147483648.5",
"-2147483648.999",
"2147483649",
"2147483649.1",
"-2147483649",
"-2147483649.1",
"10000000000",
"-10000000000",
"100000000000",
"-100000000000",
"1000000000000",
"-1000000000000",
"10000000000000",
"-10000000000000",
"100000000000000",
"-100000000000000",
"999999999999999",
"-999999999999999",
"1000000000000000", // 10^15
"-1000000000000000",
"9999999999999999", // 10^16 - 1
"-9999999999999999",
"10000000000000000", // 10^16
"-10000000000000000",
"100000000000000000",
"-100000000000000000",
"1000000000000000000",
"-1000000000000000000",
"9223372036854775807", // Long.MAX_VALUE
"9223372036854775807.1",
"9223372036854775807.0008",
"9223372036854775807.49",
"9223372036854775807.5",
"9223372036854775807.9",
"-9223372036854775807",
"-9223372036854775807.1",
"-9223372036854775807.0008",
"-9223372036854775807.49",
"-9223372036854775807.5",
"-9223372036854775807.9999999999999999999",
"-9223372036854775808",
"-9223372036854775808.1",
"9223372036854775808",
"9223372036854775808.1",
"9223372036854775808.0008",
"9223372036854775808.49",
"9223372036854775808.5",
"9223372036854775808.9",
"9223372036854775809",
"9223372036854775809.1",
"-9223372036854775808", // Long.MIN_VALUE
"-9223372036854775808.1",
"-9223372036854775808.0008",
"-9223372036854775808.49",
"-9223372036854775808.5",
"-9223372036854775808.9999999",
"9223372036854775809",
"9223372036854775809.1",
"-9223372036854775809",
"-9223372036854775809.1",
"10000000000000000000000000000000", // 10^31
"-10000000000000000000000000000000",
"99999999999999999999999999999999", // 10^32 - 1
"-99999999999999999999999999999999",
"100000000000000000000000000000000", // 10^32
"-100000000000000000000000000000000",
"10000000000000000000000000000000000000", // 10^37
"-10000000000000000000000000000000000000",
"99999999999999999999999999999999999999", // 10^38 - 1
"-99999999999999999999999999999999999999",
"100000000000000000000000000000000000000", // 10^38
"-100000000000000000000000000000000000000",
"1000000000000000000000000000000000000000", // 10^39
"-1000000000000000000000000000000000000000",
"18446744073709551616", // Unsigned 64 max.
"-18446744073709551616",
"340282366920938463463374607431768211455", // 2^128 - 1
"-340282366920938463463374607431768211455",
"0.999999999999999",
"-0.999999999999999",
"0.0000000000000001", // 10^-15
"-0.0000000000000001",
"0.9999999999999999",
"-0.9999999999999999",
"0.00000000000000001", // 10^-16
"-0.00000000000000001",
"0.00000000000000000000000000000001", // 10^-31
"-0.00000000000000000000000000000001",
"0.99999999999999999999999999999999", // 10^-32 + 1
"-0.99999999999999999999999999999999",
"0.000000000000000000000000000000001", // 10^-32
"-0.000000000000000000000000000000001",
"0.00000000000000000000000000000000000001", // 10^-37
"-0.00000000000000000000000000000000000001",
"0.99999999999999999999999999999999999999", // 10^-38 + 1
"-0.99999999999999999999999999999999999999",
"0.000000000000000000000000000000000000001", // 10^-38
"-0.000000000000000000000000000000000000001",
"0.0000000000000000000000000000000000000001", // 10^-39
"-0.0000000000000000000000000000000000000001",
"0.0000000000000000000000000000000000000005", // 10^-39 (rounds)
"-0.0000000000000000000000000000000000000005",
"0.340282366920938463463374607431768211455", // (2^128 - 1) * 10^-39
"-0.340282366920938463463374607431768211455",
"0.000000000000000000000000000000000000001", // 10^-38
"-0.000000000000000000000000000000000000001",
"0.000000000000000000000000000000000000005", // 10^-38
"-0.000000000000000000000000000000000000005",
"234.79",
"342348.343",
"12.25",
"-12.25",
"72057594037927935", // 2^56 - 1
"-72057594037927935",
"72057594037927936", // 2^56
"-72057594037927936",
"5192296858534827628530496329220095", // 2^56 * 2^56 - 1
"-5192296858534827628530496329220095",
"5192296858534827628530496329220096", // 2^56 * 2^56
"-5192296858534827628530496329220096",
"54216721532321902598.70",
"-906.62545207002374150309544832320",
"-0.0709351061072",
"1460849063411925.53",
"8.809130E-33",
"-4.0786300706013636202E-20",
"-3.8823936518E-1",
"-3.8823936518E-28",
"-3.8823936518E-29",
"598575157855521918987423259.94094",
"299999448432.001342152474197",
"1786135888657847525803324040144343378.09799306448796128931113691624", // More than 38 digits.
"-1786135888657847525803324040144343378.09799306448796128931113691624",
"57847525803324040144343378.09799306448796128931113691624",
"0.999999999999999999990000",
"005.34000",
"1E-90",
"0.4",
"-0.4",
"0.5",
"-0.5",
"0.6",
"-0.6",
"1.4",
"-1.4",
"1.5",
"-1.5",
"1.6",
"-1.6",
"2.4",
"-2.4",
"2.49",
"-2.49",
"2.5",
"-2.5",
"2.51",
"-2.51",
"-2.5",
"2.6",
"-2.6",
"3.00001415926",
"0.00",
"-12.25",
"234.79"
};
public static BigDecimal[] specialBigDecimals = stringArrayToBigDecimals(specialDecimalStrings);
// decimal_1_1.txt
public static String[] decimal_1_1_txt = {
"0.0",
"0.0000",
".0",
"0.1",
"0.15",
"0.9",
"0.94",
"0.99",
"0.345",
"1.0",
"1",
"0",
"00",
"22",
"1E-9",
"-0.0",
"-0.0000",
"-.0",
"-0.1",
"-0.15",
"-0.9",
"-0.94",
"-0.99",
"-0.345",
"-1.0",
"-1",
"-0",
"-00",
"-22",
"-1E-9"
};
// kv7.txt KEYS
public static String[] kv7_txt_keys = {
"-4400",
"1E+99",
"1E-99",
"0",
"100",
"10",
"1",
"0.1",
"0.01",
"200",
"20",
"2",
"0",
"0.2",
"0.02",
"0.3",
"0.33",
"0.333",
"-0.3",
"-0.33",
"-0.333",
"1.0",
"2",
"3.14",
"-1.12",
"-1.12",
"-1.122",
"1.12",
"1.122",
"124.00",
"125.2",
"-1255.49",
"3.14",
"3.14",
"3.140",
"0.9999999999999999999999999",
"-1234567890.1234567890",
"1234567890.1234567800"
};
public static String standardAlphabet = "0123456789";
public static String[] sparseAlphabets = new String[] {
"0000000000000000000000000000000000000003",
"0000000000000000000000000000000000000009",
"0000000000000000000000000000000000000001",
"0000000000000000000003",
"0000000000000000000009",
"0000000000000000000001",
"0000000000091",
"000000000005",
"9",
"5555555555999999999000000000000001111111",
"24680",
"1"
};
public static BigDecimal[] stringArrayToBigDecimals(String[] strings) {
BigDecimal[] result = new BigDecimal[strings.length];
for (int i = 0; i < strings.length; i++) {
result[i] = new BigDecimal(strings[i]);
}
return result;
}
}