/**
   * This method implements the unary minus operator for double.
   *
   * @param result The result of a previous call to this method, null if not called yet
   * @return A SQLDecimal containing the result of the division
   * @exception StandardException Thrown on error
   */
  public NumberDataValue minus(NumberDataValue result) throws StandardException {
    if (result == null) {
      result = new SQLDecimal();
    }

    if (this.isNull()) {
      result.setToNull();
      return result;
    }

    result.setBigDecimal(getBigDecimal().negate());
    return result;
  }
  /**
   * This method implements the * operator for "double * double".
   *
   * @param left The first value to be multiplied
   * @param right The second value to be multiplied
   * @param result The result of a previous call to this method, null if not called yet
   * @return A SQLDecimal containing the result of the multiplication
   * @exception StandardException Thrown on error
   */
  public NumberDataValue times(NumberDataValue left, NumberDataValue right, NumberDataValue result)
      throws StandardException {
    if (result == null) {
      result = new SQLDecimal();
    }

    if (left.isNull() || right.isNull()) {
      result.setToNull();
      return result;
    }

    result.setBigDecimal(SQLDecimal.getBigDecimal(left).multiply(SQLDecimal.getBigDecimal(right)));
    return result;
  }
  /**
   * This method implements the + operator for DECIMAL.
   *
   * @param addend1 One of the addends
   * @param addend2 The other addend
   * @param result The result of a previous call to this method, null if not called yet
   * @return A SQLDecimal containing the result of the addition
   * @exception StandardException Thrown on error
   */
  public NumberDataValue plus(
      NumberDataValue addend1, NumberDataValue addend2, NumberDataValue result)
      throws StandardException {
    if (result == null) {
      result = new SQLDecimal();
    }

    if (addend1.isNull() || addend2.isNull()) {
      result.setToNull();
      return result;
    }

    result.setBigDecimal(SQLDecimal.getBigDecimal(addend1).add(SQLDecimal.getBigDecimal(addend2)));
    return result;
  }
  /**
   * This method implements the / operator for BigDecimal/BigDecimal
   *
   * @param dividend The numerator
   * @param divisor The denominator
   * @param result The result of a previous call to this method, null if not called yet
   * @param scale The result scale, if < 0, calculate the scale according to the actual values'
   *     sizes
   * @return A SQLDecimal containing the result of the division
   * @exception StandardException Thrown on error
   */
  public NumberDataValue divide(
      NumberDataValue dividend, NumberDataValue divisor, NumberDataValue result, int scale)
      throws StandardException {
    if (result == null) {
      result = new SQLDecimal();
    }

    if (dividend.isNull() || divisor.isNull()) {
      result.setToNull();
      return result;
    }

    BigDecimal divisorBigDecimal = SQLDecimal.getBigDecimal(divisor);

    if (divisorBigDecimal.compareTo(ZERO) == 0) {
      throw StandardException.newException(SQLState.LANG_DIVIDE_BY_ZERO);
    }
    BigDecimal dividendBigDecimal = SQLDecimal.getBigDecimal(dividend);

    /*
     ** Set the result scale to be either the passed in scale, whcih was
     ** calculated at bind time to be max(ls+rp-rs+1, 4), where ls,rp,rs
     ** are static data types' sizes, which are predictable and stable
     ** (for the whole result set column, eg.); otherwise dynamically
     ** calculates the scale according to actual values.  Beetle 3901
     */
    result.setBigDecimal(
        dividendBigDecimal.divide(
            divisorBigDecimal,
            scale > -1
                ? scale
                : Math.max(
                    (dividendBigDecimal.scale() + SQLDecimal.getWholeDigits(divisorBigDecimal) + 1),
                    NumberDataValue.MIN_DECIMAL_DIVIDE_SCALE),
            BigDecimal.ROUND_DOWN));

    return result;
  }