Class Numerics

java.lang.Object
org.apache.sis.util.Static
org.apache.sis.internal.util.Numerics

public final class Numerics extends Static
Miscellaneous utilities methods working on floating point numbers.
Since:
0.3
Version:
1.3
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private static final Map<Object,Object>
    Some frequently used Double values.
    static final double
    Relative difference tolerated when comparing floating point numbers using ComparisonMode.APPROXIMATE.
    static final int
    Right shift to apply for a result equivalent to a division by 32 (ignoring negative numbers).
    static final int
    Right shift to apply for a result equivalent to a division by 64 (ignoring negative numbers).
    static final int
    Maximal integer value which is convertible to float type without lost of precision digits.
    static final int
    Maximum number of rows or columns in Apache SIS matrices.
    static final long
    Bit mask to isolate the sign bit of non-NaN values in a double.
    static final int
    Number of bits in the significand (mantissa) part of IEEE 754 double representation, not including the hidden bit.
    static final int
    Number of bits in the significand (mantissa) part of IEEE 754 float representation, not including the hidden bit.
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    private
    Do not allow instantiation of this class.
  • Method Summary

    Modifier and Type
    Method
    Description
    static long
    bitmask(int bit)
    Returns a mask with the given bit set.
    private static void
    cache(double value)
    Helper method for the construction of the CACHE map.
    static <T> T
    cached(T value)
    If the given value is presents in the cache, returns the cached value.
    static int
    ceilDiv(int x, int y)
    Returns the smallest (closest to negative infinity) integer value that is greater than or equals to x/y.
    static long
    ceilDiv(long x, long y)
    Returns the smallest (closest to negative infinity) long value that is greater than or equals to x/y.
    static int
    clamp(long value)
    Returns the given value clamped to the range on 32 bits integer.
    static boolean
    epsilonEqual(double v1, double v2, double threshold)
    Returns true if the given values are approximately equal, up to the given comparison threshold.
    static boolean
    epsilonEqual(double v1, double v2, ComparisonMode mode)
    Returns true if the given values are approximately equal given the comparison mode.
    static boolean
    equals(double v1, double v2)
    Returns true if the given doubles are equal.
    static boolean
    equals(float v1, float v2)
    Returns true if the given floats are equals.
    static boolean
    equalsIgnoreZeroSign(double v1, double v2)
    Returns true if the given doubles are equal, ignoring the sign of zero values.
    static int
    Suggests an amount of fraction digits for formatting in base 10 numbers of the given accuracy.
    static long
    getSignificand(double value)
    Returns the significand m of the given value such as value = m×2ⁿ where n is Math.getExponent(double) - 52.
    static int
    getSignificand(float value)
    Returns the significand m of the given value such as value = m×2ⁿ where n is Math.getExponent(float) - 23.
    static boolean
    isInteger(double x)
    Returns true if the given number is an integer value.
    static String
    messageForDifference(String name, double v1, double v2)
    Creates a messages to put in AssertionError when two values differ in an unexpected way.
    static long
    multiplyDivide(long value, long multiplier, long divisor)
    Returns value × multiplier / divisor with control against overflow.
    static long
    saturatingAdd(long x, int y)
    Returns x+y with saturation if the result overflows long capacity.
    static long
    saturatingSubtract(long x, int y)
    Returns x-y with saturation if the result overflows long capacity.
    static int
    suggestFractionDigits(double... values)
    Suggests an amount of fraction digits for the given values, ignoring NaN and infinities.
    static int
    Suggests an amount of fraction digits for data having the given statistics.
    static int
    toExp10(int exp2)
    Converts a power of 2 to a power of 10, rounded toward negative infinity.
    static double
    toUnsignedDouble(long value)
    Converts an unsigned long to a double value.
    static float
    toUnsignedFloat(long value)
    Converts an unsigned long to a float value.
    static String
    Formats the given value with the given format, using scientific notation if needed.
    static Double
    valueOf(double value)
    Wraps the given value in a Double wrapper, using one of the cached instance if possible.
    static int
    wholeDiv(int x, int y)
    Returns x/y with the requirement that the division must be integer.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • CACHE

      private static final Map<Object,Object> CACHE
      Some frequently used Double values. As of Java 8, those values do not seem to be cached by Double.valueOf(double) like JDK does for integers.
    • MAXIMUM_MATRIX_SIZE

      public static final int MAXIMUM_MATRIX_SIZE
      Maximum number of rows or columns in Apache SIS matrices. We define a maximum because SIS is expected to work mostly with small matrices, because their sizes are related to the number of dimensions in coordinate systems. The maximum should not be greater than 32767 in order to ensure that rows * columns stay below the Integer.MAX_VALUE / 2 limit.

      We also use this value as a limit for the number of dimensions minus 1 (we need to subtract one because of the room needed for the translation column and the extra row in affine transforms). Actually many Apache SIS classes have their number of dimensions limited mostly by the capacity of the int primitive type, but we nevertheless set the maximum number of dimensions to a lower value for catching probable errors. Note that this is not a "universal" limit through Apache SIS, as some algorithms impose a smaller number of dimensions. Some other limits found in specific Apache SIS code are 20 or 64.

      See Also:
    • COMPARISON_THRESHOLD

      public static final double COMPARISON_THRESHOLD
      Relative difference tolerated when comparing floating point numbers using ComparisonMode.APPROXIMATE.

      Historically, this was the relative tolerance threshold for considering two matrices as equal. This value has been determined empirically in order to allow org.apache.sis.referencing.operation.transform.ConcatenatedTransform to detect the cases where two LinearTransform are equal for practical purpose. This threshold can be used as below:

      By extension, the same threshold value is used for comparing other floating point values.

      The current value is set to the smallest power of 10 which allow the org.apache.sis.test.integration.ConsistencyTest to pass.

      See Also:
    • SIGN_BIT_MASK

      public static final long SIGN_BIT_MASK
      Bit mask to isolate the sign bit of non-NaN values in a double. For any real value, the following code evaluate to 0 if the given value is positive: Note that this idiom differentiates positive zero from negative zero. It should be used only when such difference matter.
      See Also:
    • SIGNIFICAND_SIZE

      public static final int SIGNIFICAND_SIZE
      Number of bits in the significand (mantissa) part of IEEE 754 double representation, not including the hidden bit.
      See Also:
    • SIGNIFICAND_SIZE_OF_FLOAT

      public static final int SIGNIFICAND_SIZE_OF_FLOAT
      Number of bits in the significand (mantissa) part of IEEE 754 float representation, not including the hidden bit.
      See Also:
    • MAX_INTEGER_CONVERTIBLE_TO_FLOAT

      public static final int MAX_INTEGER_CONVERTIBLE_TO_FLOAT
      Maximal integer value which is convertible to float type without lost of precision digits.
      See Also:
    • LONG_SHIFT

      public static final int LONG_SHIFT
      Right shift to apply for a result equivalent to a division by 64 (ignoring negative numbers). The value is 6 so that the following relationship hold: 2⁶ = 64.

      Usage

      The x / Long.SIZE operation can be replaced by x >>> LONG_SHIFT if x is positive. The compiler may not do this optimization itself because those two operations are not equivalent for negative x values (even with >> instead of >>>). By contrast it is not worth to apply such replacement on multiplications because the x * Long.SIZE and x << LONG_SHIFT operations are equivalent for all numbers (positive or negative), so the compiler is more likely to optimize itself.
      See Also:
    • INT_SHIFT

      public static final int INT_SHIFT
      Right shift to apply for a result equivalent to a division by 32 (ignoring negative numbers). This is for the same purpose as LONG_SHIFT but applied to 32 bits integer.
      See Also:
  • Constructor Details

    • Numerics

      private Numerics()
      Do not allow instantiation of this class.
  • Method Details

    • cache

      private static void cache(double value)
      Helper method for the construction of the CACHE map.
    • bitmask

      public static long bitmask(int bit)
      Returns a mask with the given bit set. The bit should be a number from 0 inclusive to 64 exclusive. If the given bit is outside that range, then this method returns 0. The latter condition is the main difference with the 1L << bit operation since 1L << 64 computes 1. By contrast, bitmask(64) returns 0.

      This method is invoked in contexts where we really need value 0 for a bit value of 64. For example if we want to compute the maximal value of an unsigned integer of the given number of bits, we can use bitmask(n) - 1. If n = 64, then bitmask(64) - 1 = -1 which is the desired value (the signed value -1 has the same bits pattern than the maximal possible value in unsigned integer representation).

      Parameters:
      bit - the bit to set.
      Returns:
      a mask with the given bit set, or 0 if the given argument is negative or ≥ 64.
    • isInteger

      public static boolean isInteger(double x)
      Returns true if the given number is an integer value. Special cases:
      • If the given value is NaN, than this method returns false.
      • If the given value is positive or negative infinity, then this method returns true (should be false, but this method does not check for infinities for performance reasons).
      Parameters:
      x - the value to test.
      Returns:
      whether the given value is an integer.
    • ceilDiv

      public static int ceilDiv(int x, int y)
      Returns the smallest (closest to negative infinity) integer value that is greater than or equals to x/y.
      Parameters:
      x - the dividend.
      y - the divisor.
      Returns:
      x/y rounded toward positive infinity.
      See Also:
    • ceilDiv

      public static long ceilDiv(long x, long y)
      Returns the smallest (closest to negative infinity) long value that is greater than or equals to x/y.
      Parameters:
      x - the dividend.
      y - the divisor.
      Returns:
      x/y rounded toward positive infinity.
      See Also:
    • wholeDiv

      public static int wholeDiv(int x, int y)
      Returns x/y with the requirement that the division must be integer.
      Parameters:
      x - the dividend.
      y - the divisor.
      Returns:
      x/y.
      Throws:
      ArithmeticException - if y is zero of if the result of x/y is not an integer.
    • multiplyDivide

      public static long multiplyDivide(long value, long multiplier, long divisor)
      Returns value × multiplier / divisor with control against overflow. The result is rounded toward zero.
      Parameters:
      value - the value to multiply and divide.
      multiplier - the multiplication factor.
      divisor - the division to apply after multiplication.
      Returns:
      value × multiplier / divisor rounded toward zero.
    • saturatingAdd

      public static long saturatingAdd(long x, int y)
      Returns x+y with saturation if the result overflows long capacity. This is saturation arithmetic.
      Parameters:
      x - the value for which to add something.
      y - the value to add to x.
      Returns:
      x+y computed with saturation arithmetic.
    • saturatingSubtract

      public static long saturatingSubtract(long x, int y)
      Returns x-y with saturation if the result overflows long capacity. This is saturation arithmetic.
      Parameters:
      x - the value for which to add something.
      y - the value to subtract from x.
      Returns:
      x-y computed with saturation arithmetic.
    • clamp

      public static int clamp(long value)
      Returns the given value clamped to the range on 32 bits integer.
      Parameters:
      value - the value to clamp.
      Returns:
      the value clamped to the range of 32 bits integer.
    • cached

      public static <T> T cached(T value)
      If the given value is presents in the cache, returns the cached value. Otherwise returns the given value as-is.
      Type Parameters:
      T - the type of the given value.
      Parameters:
      value - the given value for which to get a cached instance, if one exists.
      Returns:
      an object equals to the given value (may be the given instance itself).
    • valueOf

      public static Double valueOf(double value)
      Wraps the given value in a Double wrapper, using one of the cached instance if possible.
      Parameters:
      value - the value to get as a Double.
      Returns:
      the given value as a Double.
    • equals

      public static boolean equals(float v1, float v2)
      Returns true if the given floats are equals. Positive and negative zero are considered different, while a NaN value is considered equal to all other NaN values.
      Parameters:
      v1 - the first value to compare.
      v2 - the second value to compare.
      Returns:
      true if both values are equal.
      See Also:
    • equals

      public static boolean equals(double v1, double v2)
      Returns true if the given doubles are equal. Positive and negative zeros are considered different. NaN values are considered equal to all other NaN values.
      Parameters:
      v1 - the first value to compare.
      v2 - the second value to compare.
      Returns:
      true if both values are equal.
      See Also:
    • equalsIgnoreZeroSign

      public static boolean equalsIgnoreZeroSign(double v1, double v2)
      Returns true if the given doubles are equal, ignoring the sign of zero values. NaN values are considered equal to all other NaN values.
      Parameters:
      v1 - the first value to compare.
      v2 - the second value to compare.
      Returns:
      true if both values are equal.
    • epsilonEqual

      public static boolean epsilonEqual(double v1, double v2, double threshold)
      Returns true if the given values are approximately equal, up to the given comparison threshold.
      Parameters:
      v1 - the first value to compare.
      v2 - the second value to compare.
      threshold - the comparison threshold.
      Returns:
      true if both values are approximately equal.
    • epsilonEqual

      public static boolean epsilonEqual(double v1, double v2, ComparisonMode mode)
      Returns true if the given values are approximately equal given the comparison mode. In mode APPROXIMATE or DEBUG, this method will compute a relative comparison threshold from the COMPARISON_THRESHOLD constant.

      This method does not thrown AssertionError in ComparisonMode.DEBUG. It is caller responsibility to handle the DEBUG case.

      Parameters:
      v1 - the first value to compare.
      v2 - the second value to compare.
      mode - the comparison mode to use for comparing the numbers.
      Returns:
      true if both values are considered equal for the given comparison mode.
    • messageForDifference

      @Debug public static String messageForDifference(String name, double v1, double v2)
      Creates a messages to put in AssertionError when two values differ in an unexpected way. This is a helper method for debugging purpose only, typically used with assert statements.
      Parameters:
      name - the name of the property which differ, or null if unknown.
      v1 - the first value.
      v2 - the second value.
      Returns:
      the message to put in AssertionError.
      Since:
      0.6
    • toUnsignedFloat

      public static float toUnsignedFloat(long value)
      Converts an unsigned long to a float value.
      Parameters:
      value - the unsigned long value.
      Returns:
      the given unsigned long as a float value.
      Since:
      0.8
    • toUnsignedDouble

      public static double toUnsignedDouble(long value)
      Converts an unsigned long to a double value.
      Parameters:
      value - the unsigned long value.
      Returns:
      the given unsigned long as a double value.
      Since:
      0.8
    • toExp10

      public static int toExp10(int exp2)
      Converts a power of 2 to a power of 10, rounded toward negative infinity. This method is equivalent to the following code, but using only integer arithmetic: This method is valid only for arguments in the [-2620 … 2620] range, which is more than enough for the range of double exponents. We do not put this method in public API because it does not check the argument validity.

      Arithmetic notes

      toExp10(getExponent(10ⁿ)) returns n only for n == 0, and n-1 in all other cases. This is because 10ⁿ == m × 2exp2 where the m significand is always greater than 1, which must be compensated by a smaller exp2 value such as toExp10(exp2) < n. Note that if the getExponent(…) argument is not a power of 10, then the result can be either n or n-1.
      Parameters:
      exp2 - the power of 2 to convert Must be in the [-2620 … 2620] range.
      Returns:
      the power of 10, rounded toward negative infinity.
      See Also:
    • getSignificand

      public static long getSignificand(double value)
      Returns the significand m of the given value such as value = m×2ⁿ where n is Math.getExponent(double) - 52. For any non-NaN values (including infinity), the following relationship holds: For negative values, this method behaves as if the value was positive.
      Parameters:
      value - the value for which to get the significand.
      Returns:
      the significand of the given value.
    • getSignificand

      public static int getSignificand(float value)
      Returns the significand m of the given value such as value = m×2ⁿ where n is Math.getExponent(float) - 23. For any non-NaN positive values (including infinity), the following relationship holds: For negative values, this method behaves as if the value was positive.
      Parameters:
      value - the value for which to get the significand.
      Returns:
      the significand of the given value.
    • fractionDigitsForDelta

      public static int fractionDigitsForDelta(double ulp)
      Suggests an amount of fraction digits for formatting in base 10 numbers of the given accuracy. This method uses heuristic rules that may change in any future SIS version:
      • This method returns zero for Double.NaN of infinities.
      • This method arbitrarily returns zero for 0. This is different than DecimalFunctions.fractionDigitsForDelta(double, boolean), which returns 324 (maximal numbers of fraction digits an IEEE 754 may have).
      • An arbitrary limit is set to 16 digits, which is the number of digits for Math.ulp(1.0)}.
      This method can be used for string representations that are not controlled by the user. If instead the precision is specified by users, then DecimalFunctions.fractionDigitsForDelta(double, boolean) should be used instead in order to honor the user request exactly as specified.
      Parameters:
      ulp - the accuracy.
      Returns:
      suggested amount of fraction digits for the given precision. Always positive.
      Since:
      1.0
      See Also:
    • suggestFractionDigits

      public static int suggestFractionDigits(double... values)
      Suggests an amount of fraction digits for the given values, ignoring NaN and infinities. This method uses heuristic rules that may change in any future SIS version. Current implementation returns a value which avoid printing "garbage" digits with highest numbers, at the cost of loosing significant digits on smallest numbers. An arbitrary limit is set to 16 digits, which is the number of digits for Math.ulp(1.0)}.
      Parameters:
      values - the values for which to get suggested amount of fraction digits.
      Returns:
      suggested amount of fraction digits for the given values. Always positive.
      Since:
      1.0
    • suggestFractionDigits

      public static int suggestFractionDigits(Statistics stats)
      Suggests an amount of fraction digits for data having the given statistics. This method uses heuristic rules that may be modified in any future SIS version.
      Parameters:
      stats - statistics on the data to format.
      Returns:
      number of fraction digits suggested. May be negative.
      Since:
      1.0
    • useScientificNotationIfNeeded

      @Workaround(library="JDK", version="10") public static String useScientificNotationIfNeeded(Format format, Object value, BiFunction<Format,Object,String> action)
      Formats the given value with the given format, using scientific notation if needed. This is a workaround for DecimalFormat not switching automatically to scientific notation for large numbers.
      Parameters:
      format - the format to use for formatting the given value.
      value - the value to format.
      action - the method to invoke. Typically Format::format.
      Returns:
      the result of action.