com.hazelcast.org.apache.calcite.util.NumberUtil Maven / Gradle / Ivy
/*
* 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 com.hazelcast.org.apache.calcite.util;
import com.hazelcast.org.checkerframework.checker.nullness.qual.Nullable;
import com.hazelcast.org.checkerframework.checker.nullness.qual.PolyNull;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;
import static com.hazelcast.org.apache.calcite.linq4j.Nullness.castNonNull;
/**
* Utility functions for working with numbers.
*/
public class NumberUtil {
private NumberUtil() {}
//~ Static fields/initializers ---------------------------------------------
private static final DecimalFormat FLOAT_FORMATTER;
private static final DecimalFormat DOUBLE_FORMATTER;
private static final BigInteger[] BIG_INT_TEN_POW;
private static final BigInteger[] BIG_INT_MIN_UNSCALED;
private static final BigInteger[] BIG_INT_MAX_UNSCALED;
static {
// TODO: DecimalFormat uses ROUND_HALF_EVEN, not ROUND_HALF_UP
// Float: precision of 7 (6 digits after .)
FLOAT_FORMATTER = decimalFormat("0.######E0");
// Double: precision of 16 (15 digits after .)
DOUBLE_FORMATTER = decimalFormat("0.###############E0");
BIG_INT_TEN_POW = new BigInteger[20];
BIG_INT_MIN_UNSCALED = new BigInteger[20];
BIG_INT_MAX_UNSCALED = new BigInteger[20];
for (int i = 0; i < BIG_INT_TEN_POW.length; i++) {
BIG_INT_TEN_POW[i] = BigInteger.TEN.pow(i);
if (i < 19) {
BIG_INT_MAX_UNSCALED[i] = BIG_INT_TEN_POW[i].subtract(BigInteger.ONE);
BIG_INT_MIN_UNSCALED[i] = BIG_INT_MAX_UNSCALED[i].negate();
} else {
BIG_INT_MAX_UNSCALED[i] = BigInteger.valueOf(Long.MAX_VALUE);
BIG_INT_MIN_UNSCALED[i] = BigInteger.valueOf(Long.MIN_VALUE);
}
}
}
//~ Methods ----------------------------------------------------------------
/** Creates a format. Locale-independent. */
public static DecimalFormat decimalFormat(String pattern) {
return new DecimalFormat(pattern,
DecimalFormatSymbols.getInstance(Locale.ROOT));
}
public static BigInteger powTen(int exponent) {
if ((exponent >= 0) && (exponent < BIG_INT_TEN_POW.length)) {
return BIG_INT_TEN_POW[exponent];
} else {
return BigInteger.TEN.pow(exponent);
}
}
public static BigInteger getMaxUnscaled(int precision) {
return BIG_INT_MAX_UNSCALED[precision];
}
public static BigInteger getMinUnscaled(int precision) {
return BIG_INT_MIN_UNSCALED[precision];
}
/** Sets the scale of a BigDecimal {@code bd} if it is not null;
* always returns {@code bd}. */
public static @PolyNull BigDecimal rescaleBigDecimal(@PolyNull BigDecimal bd,
int scale) {
if (bd != null) {
bd = bd.setScale(scale, RoundingMode.HALF_UP);
}
return bd;
}
public static BigDecimal toBigDecimal(Number number, int scale) {
BigDecimal bd = toBigDecimal(number);
return rescaleBigDecimal(bd, scale);
}
/** Converts a number to a BigDecimal with the same value;
* returns null if and only if the number is null. */
public static @PolyNull BigDecimal toBigDecimal(@PolyNull Number number) {
if (number == null) {
return castNonNull(null);
}
if (number instanceof BigDecimal) {
return (BigDecimal) number;
} else if ((number instanceof Double)
|| (number instanceof Float)) {
return BigDecimal.valueOf(number.doubleValue());
} else if (number instanceof BigInteger) {
return new BigDecimal((BigInteger) number);
} else {
return new BigDecimal(number.longValue());
}
}
/** Returns whether a {@link BigDecimal} is a valid Farrago decimal. If a
* BigDecimal's unscaled value overflows a long, then it is not a valid
* Farrago decimal. */
public static boolean isValidDecimal(BigDecimal bd) {
BigInteger usv = bd.unscaledValue();
long usvl = usv.longValue();
return usv.equals(BigInteger.valueOf(usvl));
}
public static NumberFormat getApproxFormatter(boolean isFloat) {
return isFloat ? FLOAT_FORMATTER : DOUBLE_FORMATTER;
}
public static long round(double d) {
if (d < 0) {
return (long) (d - 0.5);
} else {
return (long) (d + 0.5);
}
}
/** Returns the sum of two numbers, or null if either is null. */
public static @PolyNull Double add(@PolyNull Double a, @PolyNull Double b) {
if (a == null || b == null) {
return null;
}
return a + b;
}
/** Returns the difference of two numbers,
* or null if either is null. */
public static @PolyNull Double subtract(@PolyNull Double a, @PolyNull Double b) {
if (a == null || b == null) {
return castNonNull(null);
}
return a - b;
}
/** Returns the quotient of two numbers,
* or null if either is null or the divisor is zero. */
public static @Nullable Double divide(@Nullable Double a, @Nullable Double b) {
if ((a == null) || (b == null) || (b == 0D)) {
return castNonNull(null);
}
return a / b;
}
/** Returns the product of two numbers,
* or null if either is null. */
public static @PolyNull Double multiply(@PolyNull Double a, @PolyNull Double b) {
if (a == null || b == null) {
return castNonNull(null);
}
return a * b;
}
/** Like {@link Math#min} but null safe;
* returns the lesser of two numbers,
* ignoring numbers that are null,
* or null if both are null. */
public static @PolyNull Double min(@PolyNull Double a, @PolyNull Double b) {
if (a == null) {
return b;
} else if (b == null) {
return a;
} else {
return Math.min(a, b);
}
}
/** Like {@link Math#max} but null safe;
* returns the greater of two numbers,
* or null if either is null. */
public static @PolyNull Double max(@PolyNull Double a, @PolyNull Double b) {
if (a == null || b == null) {
return castNonNull(null);
}
return Math.max(a, b);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy