/**
   * 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;
  }
  /**
   * Return the SQL scale of this value, number of digits after the decimal point, or zero for a
   * whole number. This does not match the return from BigDecimal.scale() since in J2SE 5.0 onwards
   * that can return negative scales.
   */
  public int getDecimalValuePrecision() {
    if (isNull()) return 0;

    BigDecimal localValue = getBigDecimal();

    return SQLDecimal.getWholeDigits(localValue) + getDecimalValueScale();
  }
  /**
   * JDBC 2.0
   *
   * <p>Get the value of a NUMERIC parameter as a java.math.BigDecimal object.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @return the parameter value (full precision); if the value is SQL NULL, the result is null
   * @exception SQLException if a database-access error occurs.
   */
  public final BigDecimal getBigDecimal(int parameterIndex) throws SQLException {
    checkStatus();
    try {
      DataValueDescriptor dvd = getParms().getParameterForGet(parameterIndex - 1);
      if (wasNull = dvd.isNull()) return null;

      return org.apache.derby.iapi.types.SQLDecimal.getBigDecimal(dvd);

    } catch (StandardException e) {
      throw EmbedResultSet.noStateChangeException(e);
    }
  }
  /**
   * Set the precision/scale of the to the desired values. Used when CASTing. Ideally we'd recycle
   * normalize(), but the use is different.
   *
   * @param desiredPrecision the desired precision -- IGNORE_PREICISION if it is to be ignored.
   * @param desiredScale the desired scale
   * @param errorOnTrunc throw error on truncation (ignored -- always thrown if we truncate the
   *     non-decimal part of the value)
   * @exception StandardException Thrown on non-zero truncation if errorOnTrunc is true
   */
  public void setWidth(int desiredPrecision, int desiredScale, boolean errorOnTrunc)
      throws StandardException {
    if (isNull()) return;

    if (desiredPrecision != IGNORE_PRECISION
        && ((desiredPrecision - desiredScale) < SQLDecimal.getWholeDigits(getBigDecimal()))) {
      throw StandardException.newException(
          SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
          ("DECIMAL/NUMERIC(" + desiredPrecision + "," + desiredScale + ")"));
    }
    value = value.setScale(desiredScale, BigDecimal.ROUND_DOWN);
    rawData = null;
  }
  /**
   * 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;
  }
 /** @exception StandardException Thrown on error */
 protected int typeCompare(DataValueDescriptor arg) throws StandardException {
   BigDecimal otherValue = SQLDecimal.getBigDecimal(arg);
   return getBigDecimal().compareTo(otherValue);
 }
  protected void setFrom(DataValueDescriptor theValue) throws StandardException {

    setCoreValue(SQLDecimal.getBigDecimal(theValue));
  }