Java Code Examples for java.math.BigDecimal#abs()

The following examples show how to use java.math.BigDecimal#abs() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: Formatter.java    From jdk1.8-source-analysis with Apache License 2.0 6 votes vote down vote up
private void print(BigDecimal value, Locale l) throws IOException {
    if (c == Conversion.HEXADECIMAL_FLOAT)
        failConversion(c, value);
    StringBuilder sb = new StringBuilder();
    boolean neg = value.signum() == -1;
    BigDecimal v = value.abs();
    // leading sign indicator
    leadingSign(sb, neg);

    // the value
    print(sb, v, l, f, c, precision, neg);

    // trailing sign indicator
    trailingSign(sb, neg);

    // justify based on width
    a.append(justify(sb.toString()));
}
 
Example 2
Source File: CrfUtilities.java    From CRF with MIT License 6 votes vote down vote up
/**
 * If |value1|>|value2| returns |value1|/|value2|. Otherwise returns |value2|/|value1|.
 */
public static BigDecimal relativeDifference(BigDecimal value1, BigDecimal value2)
{
	if (value1.equals(value2))  {return BigDecimal.ONE;}
	
	value1 = value1.abs();
	value2 = value2.abs();
	
	BigDecimal smaller;
	BigDecimal larger;
	if (value1.compareTo(value2)<0)
	{
		smaller = value1;
		larger = value2;
	}
	else
	{
		smaller = value2;
		larger = value1;
	}
	
	BigDecimal ret = safeDivide(larger, smaller);
	return ret;
}
 
Example 3
Source File: Formatter.java    From jdk8u-dev-jdk with GNU General Public License v2.0 6 votes vote down vote up
private void print(BigDecimal value, Locale l) throws IOException {
    if (c == Conversion.HEXADECIMAL_FLOAT)
        failConversion(c, value);
    StringBuilder sb = new StringBuilder();
    boolean neg = value.signum() == -1;
    BigDecimal v = value.abs();
    // leading sign indicator
    leadingSign(sb, neg);

    // the value
    print(sb, v, l, f, c, precision, neg);

    // trailing sign indicator
    trailingSign(sb, neg);

    // justify based on width
    a.append(justify(sb.toString()));
}
 
Example 4
Source File: Formatter.java    From jdk8u-jdk with GNU General Public License v2.0 6 votes vote down vote up
private void print(BigDecimal value, Locale l) throws IOException {
    if (c == Conversion.HEXADECIMAL_FLOAT)
        failConversion(c, value);
    StringBuilder sb = new StringBuilder();
    boolean neg = value.signum() == -1;
    BigDecimal v = value.abs();
    // leading sign indicator
    leadingSign(sb, neg);

    // the value
    print(sb, v, l, f, c, precision, neg);

    // trailing sign indicator
    trailingSign(sb, neg);

    // justify based on width
    a.append(justify(sb.toString()));
}
 
Example 5
Source File: Formatter.java    From TencentKona-8 with GNU General Public License v2.0 6 votes vote down vote up
private void print(BigDecimal value, Locale l) throws IOException {
    if (c == Conversion.HEXADECIMAL_FLOAT)
        failConversion(c, value);
    StringBuilder sb = new StringBuilder();
    boolean neg = value.signum() == -1;
    BigDecimal v = value.abs();
    // leading sign indicator
    leadingSign(sb, neg);

    // the value
    print(sb, v, l, f, c, precision, neg);

    // trailing sign indicator
    trailingSign(sb, neg);

    // justify based on width
    a.append(justify(sb.toString()));
}
 
Example 6
Source File: LinearCombinationsTest.java    From commons-numbers with Apache License 2.0 6 votes vote down vote up
/**
 * Clip the value to the minimum value that can be stored by a double.
 * Ideally this should round BigDecimal to values occupied by sub-normal numbers.
 * That is non-trivial so this just removes excess precision in the significand and
 * clips it to Double.MIN_VALUE or zero if the value is very small. The ultimate use for
 * the BigDecimal is rounded to the closest double so this method is adequate. It would
 * take many summations of extended precision sub-normal numbers to create more
 * than a few ULP difference to the final double value
 *
 * <p>In data output by the various tests the values have never been known to require
 * clipping so this is just a safety threshold.
 *
 * @param a the value
 * @return the clipped value
 */
private static BigDecimal clip(BigDecimal a) {
    // Min value is approx 4.9e-324. Anything with fewer decimal digits to the right of the
    // decimal point is OK.
    if (a.scale() < 324) {
        return a;
    }
    // Reduce the scale
    final BigDecimal b = a.setScale(MIN.scale(), RoundingMode.HALF_UP);
    // Clip to min value
    final BigDecimal bb = b.abs();
    if (bb.compareTo(MIN) < 0) {
        // Note the number may be closer to MIN than zero so do rounding
        if (MIN.subtract(bb).compareTo(bb) < 0) {
            // Closer to MIN
            return a.signum() == -1 ? MIN.negate() : MIN;
        }
        // Closer to zero
        return BigDecimal.ZERO;
    }
    // Anything above min is allowed.
    return b;
}
 
Example 7
Source File: Formatter.java    From openjdk-jdk8u with GNU General Public License v2.0 6 votes vote down vote up
private void print(BigDecimal value, Locale l) throws IOException {
    if (c == Conversion.HEXADECIMAL_FLOAT)
        failConversion(c, value);
    StringBuilder sb = new StringBuilder();
    boolean neg = value.signum() == -1;
    BigDecimal v = value.abs();
    // leading sign indicator
    leadingSign(sb, neg);

    // the value
    print(sb, v, l, f, c, precision, neg);

    // trailing sign indicator
    trailingSign(sb, neg);

    // justify based on width
    a.append(justify(sb.toString()));
}
 
Example 8
Source File: BigDecimalCompareTest.java    From j2objc with Apache License 2.0 5 votes vote down vote up
/**
 * Abs(MathContext) of a negative BigDecimal
 */
public void testAbsMathContextNeg() {
    String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
    BigDecimal aNumber = new BigDecimal(a);
    int precision = 15;
    RoundingMode rm = RoundingMode.HALF_DOWN;
    MathContext mc = new MathContext(precision, rm);
    String result = "1.23809648392385E+53";
    int resScale = -39;
    BigDecimal res = aNumber.abs(mc);
    assertEquals("incorrect value", result, res.toString());
    assertEquals("incorrect scale", resScale, res.scale());
}
 
Example 9
Source File: TickFactory.java    From nebula with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * @param x
 * @param round
 *            if true, then round else take ceiling
 * @return a nice number
 */
protected static BigDecimal nicenum(BigDecimal x, boolean round) {
	int expv; /* exponent of x */
	double f; /* fractional part of x */
	double nf; /* nice, rounded number */
	BigDecimal bf;

	boolean negative = x.signum() == -1;
	x = x.abs();
	expv = log10(x);
	bf = x.scaleByPowerOfTen(-expv);
	f = bf.doubleValue(); /* between 1 and 10 */
	if (round) {
		if (f < 1.5)
			nf = 1;
		else if (f < 2.25)
			nf = 2;
		else if (f < 3.25)
			nf = 2.5;
		else if (f < 7.5)
			nf = 5;
		else
			nf = 10;
	} else if (f <= 1.)
		nf = 1;
	else if (f <= 2.)
		nf = 2;
	else if (f <= 5.)
		nf = 5;
	else
		nf = 10;

	if (negative) {
		nf = -nf;
	}
	return BigDecimal.valueOf(nf).scaleByPowerOfTen(expv).stripTrailingZeros();
}
 
Example 10
Source File: DefaultNumericLib.java    From jdmn with Apache License 2.0 5 votes vote down vote up
public BigDecimal abs(BigDecimal number) {
    if (number == null) {
        return null;
    }

    return number.abs();
}
 
Example 11
Source File: TickFactory.java    From nebula with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Round numerator down to multiples of denominators
 *
 * @param numerator
 * @param denominator
 * @return rounded down value
 */
protected static double roundDown(BigDecimal numerator, BigDecimal denominator) {
	final int ns = numerator.signum();
	if (ns == 0)
		return 0;
	final int ds = denominator.signum();
	if (ds == 0) {
		throw new IllegalArgumentException("Zero denominator is not allowed");
	}

	numerator = numerator.abs();
	denominator = denominator.abs();
	final BigDecimal[] x = numerator.divideAndRemainder(denominator);
	double rx = x[1].doubleValue();
	if (rx > (1 - ROUND_FRACTION) * denominator.doubleValue()) {
		// trim up if close to denominator
		x[1] = BigDecimal.ZERO;
		x[0] = x[0].add(BigDecimal.ONE);
	} else if (rx < ROUND_FRACTION * denominator.doubleValue()) {
		x[1] = BigDecimal.ZERO;
	}
	final int xs = x[1].signum();
	if (xs == 0) {
		return ns != ds ? -x[0].multiply(denominator).doubleValue() : x[0].multiply(denominator).doubleValue();
	} else if (xs < 0) {
		throw new IllegalStateException("Cannot happen!");
	}

	if (ns != ds)
		return x[0].signum() == 0 ? -denominator.doubleValue() : -x[0].add(BigDecimal.ONE).multiply(denominator).doubleValue();

	return x[0].multiply(denominator).doubleValue();
}
 
Example 12
Source File: Transaction.java    From fingen with Apache License 2.0 4 votes vote down vote up
public void setExchangeRate(BigDecimal mExchangeRate) {
    this.mExchangeRate = mExchangeRate.abs();
}
 
Example 13
Source File: Template.java    From fingen with Apache License 2.0 4 votes vote down vote up
public void setAmount(BigDecimal mAmount) {
    this.mAmount = mAmount.abs();
}
 
Example 14
Source File: OrderedBytes.java    From hbase with Apache License 2.0 4 votes vote down vote up
/**
 * Encode the large magnitude floating point number {@code val} using
 * the key encoding. The caller guarantees that {@code val} will be
 * finite and abs(val) >= 1.0.
 * <p>
 * A floating point value is encoded as an integer exponent {@code E}
 * and a mantissa {@code M}. The original value is equal to
 * {@code (M * 100^E)}. {@code E} is set to the smallest value
 * possible without making {@code M} greater than or equal to 1.0.
 * </p>
 * <p>
 * Each centimal digit of the mantissa is stored in a byte. If the value of
 * the centimal digit is {@code X} (hence {@code X>=0} and
 * {@code X<=99}) then the byte value will be {@code 2*X+1} for
 * every byte of the mantissa, except for the last byte which will be
 * {@code 2*X+0}. The mantissa must be the minimum number of bytes
 * necessary to represent the value; trailing {@code X==0} digits are
 * omitted. This means that the mantissa will never contain a byte with the
 * value {@code 0x00}.
 * </p>
 * <p>
 * If {@code E > 10}, then this routine writes of {@code E} as a
 * varint followed by the mantissa as described above. Otherwise, if
 * {@code E <= 10}, this routine only writes the mantissa and leaves
 * the {@code E} value to be encoded as part of the opening byte of the
 * field by the calling function.
 *
 * <pre>
 *   Encoding:  M       (if E<=10)
 *              E M     (if E>10)
 * </pre>
 * </p>
 * @param dst The destination to which encoded digits are written.
 * @param val The value to encode.
 * @return the number of bytes written.
 */
private static int encodeNumericLarge(PositionedByteRange dst, BigDecimal val) {
  // TODO: this can be done faster
  BigDecimal abs = val.abs();
  byte[] a = dst.getBytes();
  boolean isNeg = val.signum() == -1;
  final int start = dst.getPosition(), offset = dst.getOffset();
  int e = 0, d, startM;

  if (isNeg) { /* Large negative number: 0x08, ~E, ~M */
    dst.put(NEG_LARGE);
  } else { /* Large positive number: 0x22, E, M */
    dst.put(POS_LARGE);
  }

  // normalize abs(val) to determine E
  while (abs.compareTo(E32) >= 0 && e <= 350) { abs = abs.movePointLeft(32); e +=16; }
  while (abs.compareTo(E8) >= 0 && e <= 350) { abs = abs.movePointLeft(8); e+= 4; }
  while (abs.compareTo(BigDecimal.ONE) >= 0 && e <= 350) { abs = abs.movePointLeft(2); e++; }

  // encode appropriate header byte and/or E value.
  if (e > 10) { /* large number, write out {~,}E */
    putVaruint64(dst, e, isNeg);
  } else {
    if (isNeg) { /* Medium negative number: 0x13-E, ~M */
      dst.put(start, (byte) (NEG_MED_MAX - e));
    } else { /* Medium positive number: 0x17+E, M */
      dst.put(start, (byte) (POS_MED_MIN + e));
    }
  }

  // encode M by peeling off centimal digits, encoding x as 2x+1
  startM = dst.getPosition();
  // TODO: 18 is an arbitrary encoding limit. Reevaluate once we have a better handling of
  // numeric scale.
  for (int i = 0; i < 18 && abs.compareTo(BigDecimal.ZERO) != 0; i++) {
    abs = abs.movePointRight(2);
    d = abs.intValue();
    dst.put((byte) (2 * d + 1));
    abs = abs.subtract(BigDecimal.valueOf(d));
  }
  // terminal digit should be 2x
  a[offset + dst.getPosition() - 1] = (byte) (a[offset + dst.getPosition() - 1] & 0xfe);
  if (isNeg) {
    // negative values encoded as ~M
    DESCENDING.apply(a, offset + startM, dst.getPosition() - startM);
  }
  return dst.getPosition() - start;
}
 
Example 15
Source File: ItemFuncAbs.java    From dble with GNU General Public License v2.0 4 votes vote down vote up
public BigDecimal realOp() {
    BigDecimal bd = args.get(0).valReal();
    nullValue = args.get(0).isNull();
    return bd.abs();
}
 
Example 16
Source File: DurationImpl.java    From Bytecoder with Apache License 2.0 2 votes vote down vote up
/**
 * Computes a new duration whose value is <code>factor</code> times
 * longer than the value of this duration.
 *
 * <p>
 * For example,
 * <pre>
 * "P1M" (1 month) * "12" = "P12M" (12 months)
 * "PT1M" (1 min) * "0.3" = "PT18S" (18 seconds)
 * "P1M" (1 month) * "1.5" = IllegalStateException
 * </pre>
 *
 * <p>
 * Since the {@link Duration} class is immutable, this method
 * doesn't change the value of this object. It simply computes
 * a new Duration object and returns it.
 *
 * <p>
 * The operation will be performed field by field with the precision
 * of {@link BigDecimal}. Since all the fields except seconds are
 * restricted to hold integers,
 * any fraction produced by the computation will be
 * carried down toward the next lower unit. For example,
 * if you multiply "P1D" (1 day) with "0.5", then it will be 0.5 day,
 * which will be carried down to "PT12H" (12 hours).
 * When fractions of month cannot be meaningfully carried down
 * to days, or year to months, this will cause an
 * {@link IllegalStateException} to be thrown.
 * For example if you multiple one month by 0.5.</p>
 *
 * <p>
 * To avoid {@link IllegalStateException}, use
 * the {@link #normalizeWith(Calendar)} method to remove the years
 * and months fields.
 *
 * @param factor to multiply by
 *
 * @return
 *      returns a non-null valid {@link Duration} object
 *
 * @throws IllegalStateException if operation produces fraction in
 * the months field.
 *
 * @throws NullPointerException if the <code>factor</code> parameter is
 * <code>null</code>.
 *
 */
public Duration multiply(BigDecimal factor) {
    BigDecimal carry = ZERO;
    int factorSign = factor.signum();
    factor = factor.abs();

    BigDecimal[] buf = new BigDecimal[6];

    for (int i = 0; i < 5; i++) {
        BigDecimal bd = getFieldAsBigDecimal(FIELDS[i]);
        bd = bd.multiply(factor).add(carry);

        buf[i] = bd.setScale(0, RoundingMode.DOWN);

        bd = bd.subtract(buf[i]);
        if (i == 1) {
            if (bd.signum() != 0) {
                throw new IllegalStateException(); // illegal carry-down
            } else {
                carry = ZERO;
            }
        }
        else {
            carry = bd.multiply(FACTORS[i]);
        }
    }

    if (seconds != null) {
        buf[5] = seconds.multiply(factor).add(carry);
    }
    else {
        buf[5] = carry;
    }

    return new DurationImpl(
        this.signum * factorSign >= 0,
        toBigInteger(buf[0], null == years),
        toBigInteger(buf[1], null == months),
        toBigInteger(buf[2], null == days),
        toBigInteger(buf[3], null == hours),
        toBigInteger(buf[4], null == minutes),
        (buf[5].signum() == 0 && seconds == null) ? null : buf[5]);
}
 
Example 17
Source File: DurationImpl.java    From openjdk-jdk9 with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Computes a new duration whose value is <code>factor</code> times
 * longer than the value of this duration.
 *
 * <p>
 * For example,
 * <pre>
 * "P1M" (1 month) * "12" = "P12M" (12 months)
 * "PT1M" (1 min) * "0.3" = "PT18S" (18 seconds)
 * "P1M" (1 month) * "1.5" = IllegalStateException
 * </pre>
 *
 * <p>
 * Since the {@link Duration} class is immutable, this method
 * doesn't change the value of this object. It simply computes
 * a new Duration object and returns it.
 *
 * <p>
 * The operation will be performed field by field with the precision
 * of {@link BigDecimal}. Since all the fields except seconds are
 * restricted to hold integers,
 * any fraction produced by the computation will be
 * carried down toward the next lower unit. For example,
 * if you multiply "P1D" (1 day) with "0.5", then it will be 0.5 day,
 * which will be carried down to "PT12H" (12 hours).
 * When fractions of month cannot be meaningfully carried down
 * to days, or year to months, this will cause an
 * {@link IllegalStateException} to be thrown.
 * For example if you multiple one month by 0.5.</p>
 *
 * <p>
 * To avoid {@link IllegalStateException}, use
 * the {@link #normalizeWith(Calendar)} method to remove the years
 * and months fields.
 *
 * @param factor to multiply by
 *
 * @return
 *      returns a non-null valid {@link Duration} object
 *
 * @throws IllegalStateException if operation produces fraction in
 * the months field.
 *
 * @throws NullPointerException if the <code>factor</code> parameter is
 * <code>null</code>.
 *
 */
public Duration multiply(BigDecimal factor) {
    BigDecimal carry = ZERO;
    int factorSign = factor.signum();
    factor = factor.abs();

    BigDecimal[] buf = new BigDecimal[6];

    for (int i = 0; i < 5; i++) {
        BigDecimal bd = getFieldAsBigDecimal(FIELDS[i]);
        bd = bd.multiply(factor).add(carry);

        buf[i] = bd.setScale(0, BigDecimal.ROUND_DOWN);

        bd = bd.subtract(buf[i]);
        if (i == 1) {
            if (bd.signum() != 0) {
                throw new IllegalStateException(); // illegal carry-down
            } else {
                carry = ZERO;
            }
        }
        else {
            carry = bd.multiply(FACTORS[i]);
        }
    }

    if (seconds != null) {
        buf[5] = seconds.multiply(factor).add(carry);
    }
    else {
        buf[5] = carry;
    }

    return new DurationImpl(
        this.signum * factorSign >= 0,
        toBigInteger(buf[0], null == years),
        toBigInteger(buf[1], null == months),
        toBigInteger(buf[2], null == days),
        toBigInteger(buf[3], null == hours),
        toBigInteger(buf[4], null == minutes),
        (buf[5].signum() == 0 && seconds == null) ? null : buf[5]);
}
 
Example 18
Source File: DurationImpl.java    From openjdk-8-source with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Computes a new duration whose value is <code>factor</code> times
 * longer than the value of this duration.
 *
 * <p>
 * For example,
 * <pre>
 * "P1M" (1 month) * "12" = "P12M" (12 months)
 * "PT1M" (1 min) * "0.3" = "PT18S" (18 seconds)
 * "P1M" (1 month) * "1.5" = IllegalStateException
 * </pre>
 *
 * <p>
 * Since the {@link Duration} class is immutable, this method
 * doesn't change the value of this object. It simply computes
 * a new Duration object and returns it.
 *
 * <p>
 * The operation will be performed field by field with the precision
 * of {@link BigDecimal}. Since all the fields except seconds are
 * restricted to hold integers,
 * any fraction produced by the computation will be
 * carried down toward the next lower unit. For example,
 * if you multiply "P1D" (1 day) with "0.5", then it will be 0.5 day,
 * which will be carried down to "PT12H" (12 hours).
 * When fractions of month cannot be meaningfully carried down
 * to days, or year to months, this will cause an
 * {@link IllegalStateException} to be thrown.
 * For example if you multiple one month by 0.5.</p>
 *
 * <p>
 * To avoid {@link IllegalStateException}, use
 * the {@link #normalizeWith(Calendar)} method to remove the years
 * and months fields.
 *
 * @param factor to multiply by
 *
 * @return
 *      returns a non-null valid {@link Duration} object
 *
 * @throws IllegalStateException if operation produces fraction in
 * the months field.
 *
 * @throws NullPointerException if the <code>factor</code> parameter is
 * <code>null</code>.
 *
 */
public Duration multiply(BigDecimal factor) {
    BigDecimal carry = ZERO;
    int factorSign = factor.signum();
    factor = factor.abs();

    BigDecimal[] buf = new BigDecimal[6];

    for (int i = 0; i < 5; i++) {
        BigDecimal bd = getFieldAsBigDecimal(FIELDS[i]);
        bd = bd.multiply(factor).add(carry);

        buf[i] = bd.setScale(0, BigDecimal.ROUND_DOWN);

        bd = bd.subtract(buf[i]);
        if (i == 1) {
            if (bd.signum() != 0) {
                throw new IllegalStateException(); // illegal carry-down
            } else {
                carry = ZERO;
            }
        } else {
            carry = bd.multiply(FACTORS[i]);
        }
    }

    if (seconds != null) {
        buf[5] = seconds.multiply(factor).add(carry);
    } else {
        buf[5] = carry;
    }

    return new DurationImpl(
        this.signum * factorSign >= 0,
        toBigInteger(buf[0], null == years),
        toBigInteger(buf[1], null == months),
        toBigInteger(buf[2], null == days),
        toBigInteger(buf[3], null == hours),
        toBigInteger(buf[4], null == minutes),
        (buf[5].signum() == 0 && seconds == null) ? null : buf[5]);
}
 
Example 19
Source File: ValueModel.java    From ET_Redux with Apache License 2.0 2 votes vote down vote up
/**
 * sets the value of the <code>one sigma</code> field
 *
 * @pre argument <code>oneSigma</code> is a valid <code>BigDecimal</code>
 * @post <code>one sigma</code> of this <code>ValueModel</code> is set to
 * argument <code>oneSigma</code>
 *
 * @param oneSigma value to which this <code>ValueModel</code>'s
 * <code>one sigma</code> is set
 */
@Override
public void setOneSigma(BigDecimal oneSigma) {
    this.oneSigma = oneSigma.abs();
}
 
Example 20
Source File: DurationImpl.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Computes a new duration whose value is <code>factor</code> times
 * longer than the value of this duration.
 *
 * <p>
 * For example,
 * <pre>
 * "P1M" (1 month) * "12" = "P12M" (12 months)
 * "PT1M" (1 min) * "0.3" = "PT18S" (18 seconds)
 * "P1M" (1 month) * "1.5" = IllegalStateException
 * </pre>
 *
 * <p>
 * Since the {@link Duration} class is immutable, this method
 * doesn't change the value of this object. It simply computes
 * a new Duration object and returns it.
 *
 * <p>
 * The operation will be performed field by field with the precision
 * of {@link BigDecimal}. Since all the fields except seconds are
 * restricted to hold integers,
 * any fraction produced by the computation will be
 * carried down toward the next lower unit. For example,
 * if you multiply "P1D" (1 day) with "0.5", then it will be 0.5 day,
 * which will be carried down to "PT12H" (12 hours).
 * When fractions of month cannot be meaningfully carried down
 * to days, or year to months, this will cause an
 * {@link IllegalStateException} to be thrown.
 * For example if you multiple one month by 0.5.</p>
 *
 * <p>
 * To avoid {@link IllegalStateException}, use
 * the {@link #normalizeWith(Calendar)} method to remove the years
 * and months fields.
 *
 * @param factor to multiply by
 *
 * @return
 *      returns a non-null valid {@link Duration} object
 *
 * @throws IllegalStateException if operation produces fraction in
 * the months field.
 *
 * @throws NullPointerException if the <code>factor</code> parameter is
 * <code>null</code>.
 *
 */
public Duration multiply(BigDecimal factor) {
    BigDecimal carry = ZERO;
    int factorSign = factor.signum();
    factor = factor.abs();

    BigDecimal[] buf = new BigDecimal[6];

    for (int i = 0; i < 5; i++) {
        BigDecimal bd = getFieldAsBigDecimal(FIELDS[i]);
        bd = bd.multiply(factor).add(carry);

        buf[i] = bd.setScale(0, BigDecimal.ROUND_DOWN);

        bd = bd.subtract(buf[i]);
        if (i == 1) {
            if (bd.signum() != 0) {
                throw new IllegalStateException(); // illegal carry-down
            } else {
                carry = ZERO;
            }
        } else {
            carry = bd.multiply(FACTORS[i]);
        }
    }

    if (seconds != null) {
        buf[5] = seconds.multiply(factor).add(carry);
    } else {
        buf[5] = carry;
    }

    return new DurationImpl(
        this.signum * factorSign >= 0,
        toBigInteger(buf[0], null == years),
        toBigInteger(buf[1], null == months),
        toBigInteger(buf[2], null == days),
        toBigInteger(buf[3], null == hours),
        toBigInteger(buf[4], null == minutes),
        (buf[5].signum() == 0 && seconds == null) ? null : buf[5]);
}