Package org.codehaus.groovy.runtime.typehandling

# Class NumberMath

java.lang.Object
org.codehaus.groovy.runtime.typehandling.NumberMath

Direct Known Subclasses:
  `BigDecimalMath`, `BigIntegerMath`, `FloatingPointMath`, `IntegerMath`, `LongMath`

public abstract class NumberMath extends Object
Stateless objects used to perform math on the various Number subclasses. Instances are required so that polymorphic calls work properly, but each subclass creates a singleton instance to minimize garbage. All methods must be thread-safe. The design goals of this class are as follows:

1. Support a 'least surprising' math model to scripting language users. This means that exact, or decimal math should be used for default calculations. This scheme assumes that by default, groovy literals with decimal points are instantiated as BigDecimal objects rather than binary floating points (Float, Double).
2. Do not force the appearance of exactness on a number that is by definition not guaranteed to be exact. In particular this means that if an operand in a NumberMath operation is a binary floating point number, ensure that the result remains a binary floating point number (i.e. never automatically promote a binary floating point number to a BigDecimal). This has the effect of preserving the expectations of binary floating point users and helps performance.
3. Provide an implementation that is as close as practical to the Java 1.5 BigDecimal math model which implements precision based floating point decimal math (ANSI X3.274-1996 and ANSI X3.274-1996/AM 1-2000 (section 7.4).

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `NumberMath()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static Number`
  `abs(Number number)`
  Computes the absolute value of a number using its specific type's math operations.
  `protected abstract Number`
  `absImpl(Number number)`
  Computes the absolute value of a number.
  `static Number`
  `add(Number left, Number right)`
  Adds two numbers using type promotion rules.
  `abstract Number`
  `addImpl(Number left, Number right)`
  Adds two numbers.
  `static Number`
  `and(Number left, Number right)`
  Bitwise AND operation on two integral numbers.
  `protected Number`
  `andImpl(Number left, Number right)`
  Bitwise AND of two numbers.
  `static Number`
  `bitwiseNegate(Number left)`
  Bitwise negation (complement) of an integral number.
  `protected Number`
  `bitwiseNegateImpl(Number left)`
  Bitwise negation of a number.
  `static int`
  `compareTo(Number left, Number right)`
  Compares two numbers using type promotion rules.
  `abstract int`
  `compareToImpl(Number left, Number right)`
  Compares two numbers.
  `protected UnsupportedOperationException`
  `createUnsupportedException(String operation, Number left)`
  Creates an UnsupportedOperationException for an unsupported operation.
  `static Number`
  `divide(Number left, Number right)`
  Divides two numbers using type promotion rules.
  `abstract Number`
  `divideImpl(Number left, Number right)`
  Divides two numbers.
  `static NumberMath`
  `getMath(Number left, Number right)`
  Determines which NumberMath instance to use for binary operations on two operands.
  `static Number`
  `intdiv(Number left, Number right)`
  Integer division (without remainder) of two numbers.
  `protected Number`
  `intdivImpl(Number left, Number right)`
  Integer division of two numbers.
  `static boolean`
  `isBigDecimal(Number number)`
  Tests whether a number is a BigDecimal.
  `static boolean`
  `isBigInteger(Number number)`
  Tests whether a number is a BigInteger.
  `static boolean`
  `isByte(Number number)`
  Tests whether a number is a Byte.
  `static boolean`
  `isFloatingPoint(Number number)`
  Tests whether a number is a floating-point type (Float or Double).
  `static boolean`
  `isInteger(Number number)`
  Tests whether a number is an Integer.
  `static boolean`
  `isLong(Number number)`
  Tests whether a number is a Long.
  `static boolean`
  `isShort(Number number)`
  Tests whether a number is a Short.
  `static Number`
  `leftShift(Number left, Number right)`
  Left shift operation on integral numbers.
  `protected Number`
  `leftShiftImpl(Number left, Number right)`
  Left shift of a number.
  `static Number`
  `mod(Number left, Number right)`
  Modulo operation on two numbers (for backwards compatibility).
  `protected Number`
  `modImpl(Number left, Number right)`
  Modulo of two numbers.
  `static Number`
  `multiply(Number left, Number right)`
  Multiplies two numbers using type promotion rules.
  `abstract Number`
  `multiplyImpl(Number left, Number right)`
  Multiplies two numbers.
  `static Number`
  `or(Number left, Number right)`
  Bitwise OR operation on two integral numbers.
  `protected Number`
  `orImpl(Number left, Number right)`
  Bitwise OR of two numbers.
  `static Number`
  `remainder(Number left, Number right)`
  Remainder operation on two numbers.
  `protected Number`
  `remainderImpl(Number left, Number right)`
  Remainder of two numbers.
  `static Number`
  `rightShift(Number left, Number right)`
  Right shift operation on integral numbers.
  `protected Number`
  `rightShiftImpl(Number left, Number right)`
  Right shift of a number.
  `static Number`
  `rightShiftUnsigned(Number left, Number right)`
  Unsigned right shift operation on integral numbers.
  `protected Number`
  `rightShiftUnsignedImpl(Number left, Number right)`
  Unsigned right shift of a number.
  `static Number`
  `subtract(Number left, Number right)`
  Subtracts two numbers using type promotion rules.
  `abstract Number`
  `subtractImpl(Number left, Number right)`
  Subtracts two numbers.
  `static BigDecimal`
  `toBigDecimal(Number n)`
  Converts a number to a BigDecimal.
  `static BigInteger`
  `toBigInteger(Number n)`
  Converts a number to a BigInteger.
  `static Number`
  `unaryMinus(Number left)`
  Unary negation of a number.
  `protected abstract Number`
  `unaryMinusImpl(Number left)`
  Negates a number.
  `static Number`
  `unaryPlus(Number left)`
  Unary plus (identity) operation on a number.
  `protected abstract Number`
  `unaryPlusImpl(Number left)`
  Returns the number as-is (unary plus/identity).
  `static Number`
  `xor(Number left, Number right)`
  Bitwise XOR operation on two integral numbers.
  `protected Number`
  `xorImpl(Number left, Number right)`
  Bitwise XOR of two numbers.

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### NumberMath

    public NumberMath()

- ## Method Details

  - ### abs

    public static Number abs(Number number)
    Computes the absolute value of a number using its specific type's math operations.
    Parameters:
      `number` - the number (must not be null)
    Returns:
      the absolute value using the appropriate NumberMath instance

  - ### add

    public static Number add(Number left, Number right)
    Adds two numbers using type promotion rules.
    Parameters:
      `left` - the left operand
      `right` - the right operand
    Returns:
      the sum using the appropriate NumberMath instance

  - ### subtract

    public static Number subtract(Number left, Number right)
    Subtracts two numbers using type promotion rules.
    Parameters:
      `left` - the minuend
      `right` - the subtrahend
    Returns:
      the difference using the appropriate NumberMath instance

  - ### multiply

    public static Number multiply(Number left, Number right)
    Multiplies two numbers using type promotion rules.
    Parameters:
      `left` - the first multiplicand
      `right` - the second multiplicand
    Returns:
      the product using the appropriate NumberMath instance

  - ### divide

    public static Number divide(Number left, Number right)
    Divides two numbers using type promotion rules.

    For floating-point operands, performs binary floating-point division. For integral types, delegates to BigDecimal division for exact results.

    Parameters:
      `left` - the dividend
      `right` - the divisor
    Returns:
      the quotient using the appropriate NumberMath instance
    Throws:
      `ArithmeticException` - if right is zero

  - ### compareTo

    public static int compareTo(Number left, Number right)
    Compares two numbers using type promotion rules.
    Parameters:
      `left` - the first number
      `right` - the second number
    Returns:
      a negative, zero, or positive int as left is less than, equal to, or greater than right

  - ### or

    @GroovyABI(since="2.5.0") public static Number or(Number left, Number right)
    Bitwise OR operation on two integral numbers.
    Parameters:
      `left` - the first operand
      `right` - the second operand
    Returns:
      the bitwise OR result
    Throws:
      `UnsupportedOperationException` - if operands are not integral types

  - ### and

    @GroovyABI(since="2.5.0") public static Number and(Number left, Number right)
    Bitwise AND operation on two integral numbers.
    Parameters:
      `left` - the first operand
      `right` - the second operand
    Returns:
      the bitwise AND result
    Throws:
      `UnsupportedOperationException` - if operands are not integral types

  - ### xor

    @GroovyABI(since="2.5.0") public static Number xor(Number left, Number right)
    Bitwise XOR operation on two integral numbers.
    Parameters:
      `left` - the first operand
      `right` - the second operand
    Returns:
      the bitwise XOR result
    Throws:
      `UnsupportedOperationException` - if operands are not integral types

  - ### intdiv

    public static Number intdiv(Number left, Number right)
    Integer division (without remainder) of two numbers.

    For BigInteger and integral types, performs exact integer division. For floating-point operands, delegates to FloatingPointMath.

    Parameters:
      `left` - the dividend
      `right` - the divisor
    Returns:
      the integer quotient
    Throws:
      `UnsupportedOperationException` - if operands don't support integer division

  - ### mod

    @GroovyABI(since="2.0.0") public static Number mod(Number left, Number right)
    Modulo operation on two numbers (for backwards compatibility).

    This method is retained for backwards compatibility

    Parameters:
      `left` - the dividend
      `right` - the divisor
    Returns:
      the modulo result

  - ### remainder

    @GroovyABI(since="2.5.0") public static Number remainder(Number left, Number right)
    Remainder operation on two numbers.

    Returns the remainder after integer division.

    Parameters:
      `left` - the dividend
      `right` - the divisor
    Returns:
      the remainder
    Throws:
      `UnsupportedOperationException` - if operands don't support remainder operation

  - ### leftShift

    @GroovyABI(since="2.5.0") public static Number leftShift(Number left, Number right)
    Left shift operation on integral numbers.

    The shift distance (right operand) must be an integral type. The value to shift (left operand) must also be integral.

    Parameters:
      `left` - the value to shift (must be integral)
      `right` - the shift distance (must be integral)
    Returns:
      the left-shifted value
    Throws:
      `UnsupportedOperationException` - if shift distance is floating-point or BigDecimal

  - ### rightShift

    @GroovyABI(since="2.5.0") public static Number rightShift(Number left, Number right)
    Right shift operation on integral numbers.

    The shift distance (right operand) must be an integral type. The value to shift (left operand) must also be integral.

    Parameters:
      `left` - the value to shift (must be integral)
      `right` - the shift distance (must be integral)
    Returns:
      the right-shifted value
    Throws:
      `UnsupportedOperationException` - if shift distance is floating-point or BigDecimal

  - ### rightShiftUnsigned

    @GroovyABI(since="2.5.0") public static Number rightShiftUnsigned(Number left, Number right)
    Unsigned right shift operation on integral numbers.

    The shift distance (right operand) must be an integral type. The value to shift (left operand) must also be integral.

    Parameters:
      `left` - the value to shift (must be integral)
      `right` - the shift distance (must be integral)
    Returns:
      the unsigned right-shifted value
    Throws:
      `UnsupportedOperationException` - if shift distance is floating-point or BigDecimal

  - ### bitwiseNegate

    public static Number bitwiseNegate(Number left)
    Bitwise negation (complement) of an integral number.
    Parameters:
      `left` - the operand (must be integral)
    Returns:
      the bitwise negation
    Throws:
      `UnsupportedOperationException` - if operand is not integral

  - ### unaryMinus

    public static Number unaryMinus(Number left)
    Unary negation of a number.
    Parameters:
      `left` - the operand
    Returns:
      the negation

  - ### unaryPlus

    public static Number unaryPlus(Number left)
    Unary plus (identity) operation on a number.
    Parameters:
      `left` - the operand
    Returns:
      the same value

  - ### isFloatingPoint

    public static boolean isFloatingPoint(Number number)
    Tests whether a number is a floating-point type (Float or Double).
    Parameters:
      `number` - the number to test
    Returns:
      true if the number is Float or Double

  - ### isInteger

    public static boolean isInteger(Number number)
    Tests whether a number is an Integer.
    Parameters:
      `number` - the number to test
    Returns:
      true if the number is an Integer

  - ### isShort

    public static boolean isShort(Number number)
    Tests whether a number is a Short.
    Parameters:
      `number` - the number to test
    Returns:
      true if the number is a Short

  - ### isByte

    public static boolean isByte(Number number)
    Tests whether a number is a Byte.
    Parameters:
      `number` - the number to test
    Returns:
      true if the number is a Byte

  - ### isLong

    public static boolean isLong(Number number)
    Tests whether a number is a Long.
    Parameters:
      `number` - the number to test
    Returns:
      true if the number is a Long

  - ### isBigDecimal

    public static boolean isBigDecimal(Number number)
    Tests whether a number is a BigDecimal.
    Parameters:
      `number` - the number to test
    Returns:
      true if the number is a BigDecimal

  - ### isBigInteger

    public static boolean isBigInteger(Number number)
    Tests whether a number is a BigInteger.
    Parameters:
      `number` - the number to test
    Returns:
      true if the number is a BigInteger

  - ### toBigDecimal

    public static BigDecimal toBigDecimal(Number n)
    Converts a number to a BigDecimal.

    Handles BigDecimal, BigInteger, integral types, and floating-point types. Floating-point numbers are converted via their string representation to preserve precision.

    Parameters:
      `n` - the number to convert (must not be null)
    Returns:
      a BigDecimal representation of the number

  - ### toBigInteger

    public static BigInteger toBigInteger(Number n)
    Converts a number to a BigInteger.

    Handles BigInteger, integral types, floating-point types, and BigDecimal. Floating-point numbers are first converted to BigDecimal before extraction.

    Parameters:
      `n` - the number to convert (must not be null)
    Returns:
      a BigInteger representation of the number

  - ### getMath

    public static NumberMath getMath(Number left, Number right)
    Determines which NumberMath instance to use for binary operations on two operands.

    Implements the type promotion matrix:

            bD bI  D  F  L  I
         bD bD bD  D  D bD bD
         bI bD bI  D  D bI bI
          D  D  D  D  D  D  D
          F  D  D  D  D  D  D
          L bD bI  D  D  L  L
          I bD bI  D  D  L  I

    Where: bD=BigDecimal, bI=BigInteger, D=Double, F=Float, L=Long, I=Integer

    Note: Byte, Character, and Short operands are pre-promoted to Integer. For division, if either operand is floating-point, the result is floating-point. Otherwise, the result is BigDecimal.

    Parameters:
      `left` - the left operand
      `right` - the right operand
    Returns:
      the appropriate NumberMath instance for these operands

  - ### absImpl

    protected abstract Number absImpl(Number number)
    Computes the absolute value of a number.

    Subclasses must implement this method according to type promotion hierarchy rules.

    Parameters:
      `number` - the operand
    Returns:
      the absolute value

  - ### addImpl

    public abstract Number addImpl(Number left, Number right)
    Adds two numbers.

    Subclasses must implement this method according to type promotion hierarchy rules.

    Parameters:
      `left` - the left operand
      `right` - the right operand
    Returns:
      the sum

  - ### subtractImpl

    public abstract Number subtractImpl(Number left, Number right)
    Subtracts two numbers.

    Subclasses must implement this method according to type promotion hierarchy rules.

    Parameters:
      `left` - the minuend
      `right` - the subtrahend
    Returns:
      the difference

  - ### multiplyImpl

    public abstract Number multiplyImpl(Number left, Number right)
    Multiplies two numbers.

    Subclasses must implement this method according to type promotion hierarchy rules.

    Parameters:
      `left` - the first multiplicand
      `right` - the second multiplicand
    Returns:
      the product

  - ### divideImpl

    public abstract Number divideImpl(Number left, Number right)
    Divides two numbers.

    Subclasses must implement this method according to type promotion hierarchy rules.

    Parameters:
      `left` - the dividend
      `right` - the divisor
    Returns:
      the quotient

  - ### compareToImpl

    public abstract int compareToImpl(Number left, Number right)
    Compares two numbers.

    Subclasses must implement this method according to type promotion hierarchy rules.

    Parameters:
      `left` - the first number
      `right` - the second number
    Returns:
      negative, zero, or positive as left is less than, equal to, or greater than right

  - ### unaryMinusImpl

    protected abstract Number unaryMinusImpl(Number left)
    Negates a number.

    Subclasses must implement this method according to type promotion hierarchy rules.

    Parameters:
      `left` - the operand
    Returns:
      the negation

  - ### unaryPlusImpl

    protected abstract Number unaryPlusImpl(Number left)
    Returns the number as-is (unary plus/identity).

    Subclasses must implement this method according to type promotion hierarchy rules.

    Parameters:
      `left` - the operand
    Returns:
      the same value

  - ### bitwiseNegateImpl

    protected Number bitwiseNegateImpl(Number left)
    Bitwise negation of a number.

    Default implementation throws UnsupportedOperationException. Subclasses supporting bitwise operations must override.

    Parameters:
      `left` - the operand
    Returns:
      the bitwise negation
    Throws:
      `UnsupportedOperationException` - if not supported for this type

  - ### orImpl

    protected Number orImpl(Number left, Number right)
    Bitwise OR of two numbers.

    Default implementation throws UnsupportedOperationException. Subclasses supporting bitwise operations must override.

    Parameters:
      `left` - the first operand
      `right` - the second operand
    Returns:
      the bitwise OR result
    Throws:
      `UnsupportedOperationException` - if not supported for this type

  - ### andImpl

    protected Number andImpl(Number left, Number right)
    Bitwise AND of two numbers.

    Default implementation throws UnsupportedOperationException. Subclasses supporting bitwise operations must override.

    Parameters:
      `left` - the first operand
      `right` - the second operand
    Returns:
      the bitwise AND result
    Throws:
      `UnsupportedOperationException` - if not supported for this type

  - ### xorImpl

    protected Number xorImpl(Number left, Number right)
    Bitwise XOR of two numbers.

    Default implementation throws UnsupportedOperationException. Subclasses supporting bitwise operations must override.

    Parameters:
      `left` - the first operand
      `right` - the second operand
    Returns:
      the bitwise XOR result
    Throws:
      `UnsupportedOperationException` - if not supported for this type

  - ### remainderImpl

    protected Number remainderImpl(Number left, Number right)
    Remainder of two numbers.

    Default implementation throws UnsupportedOperationException. Subclasses supporting remainder must override.

    Parameters:
      `left` - the dividend
      `right` - the divisor
    Returns:
      the remainder
    Throws:
      `UnsupportedOperationException` - if not supported for this type

  - ### modImpl

    protected Number modImpl(Number left, Number right)
    Modulo of two numbers.

    Default implementation throws UnsupportedOperationException. Subclasses supporting modulo must override.

    Parameters:
      `left` - the dividend
      `right` - the divisor
    Returns:
      the modulo result
    Throws:
      `UnsupportedOperationException` - if not supported for this type

  - ### intdivImpl

    protected Number intdivImpl(Number left, Number right)
    Integer division of two numbers.

    Default implementation throws UnsupportedOperationException. Subclasses supporting integer division must override.

    Parameters:
      `left` - the dividend
      `right` - the divisor
    Returns:
      the integer quotient
    Throws:
      `UnsupportedOperationException` - if not supported for this type

  - ### leftShiftImpl

    protected Number leftShiftImpl(Number left, Number right)
    Left shift of a number.

    Default implementation throws UnsupportedOperationException. Subclasses supporting bit shifting must override.

    Parameters:
      `left` - the value to shift
      `right` - the shift distance
    Returns:
      the left-shifted value
    Throws:
      `UnsupportedOperationException` - if not supported for this type

  - ### rightShiftImpl

    protected Number rightShiftImpl(Number left, Number right)
    Right shift of a number.

    Default implementation throws UnsupportedOperationException. Subclasses supporting bit shifting must override.

    Parameters:
      `left` - the value to shift
      `right` - the shift distance
    Returns:
      the right-shifted value
    Throws:
      `UnsupportedOperationException` - if not supported for this type

  - ### rightShiftUnsignedImpl

    protected Number rightShiftUnsignedImpl(Number left, Number right)
    Unsigned right shift of a number.

    Default implementation throws UnsupportedOperationException. Subclasses supporting bit shifting must override.

    Parameters:
      `left` - the value to shift
      `right` - the shift distance
    Returns:
      the unsigned right-shifted value
    Throws:
      `UnsupportedOperationException` - if not supported for this type

  - ### createUnsupportedException

    protected UnsupportedOperationException createUnsupportedException(String operation, Number left)
    Creates an UnsupportedOperationException for an unsupported operation.
    Parameters:
      `operation` - the name of the unsupported operation
      `left` - the operand
    Returns:
      a new UnsupportedOperationException