All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.apache.calcite.util.NumberUtil Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * 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