Author: luc Date: Mon Mar 30 15:48:56 2009 New Revision: 760016 URL: http://svn.apache.org/viewvc?rev=760016&view=rev Log: optimized some fraction operations (mainly pow) replaced pow(BigFraction) by pow(double) as it already converted the argument to double upon entry added tests for pow
Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/BigFraction.java commons/proper/math/trunk/src/test/org/apache/commons/math/fraction/BigFractionTest.java Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/BigFraction.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/BigFraction.java?rev=760016&r1=760015&r2=760016&view=diff ============================================================================== --- commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/BigFraction.java (original) +++ commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/BigFraction.java Mon Mar 30 15:48:56 2009 @@ -20,6 +20,7 @@ import java.math.BigInteger; import org.apache.commons.math.MathRuntimeException; +import org.apache.commons.math.util.MathUtils; /** * Representation of a rational number without any overflow. This class is @@ -457,7 +458,35 @@ * if the {...@link BigInteger} is <code>null</code>. */ public BigFraction add(final BigInteger bg) { - return add(new BigFraction(bg, BigInteger.ONE)); + return new BigFraction(numerator.add(denominator.multiply(bg)), denominator); + } + + /** + * <p> + * Adds the value of this fraction to the passed <tt>integer</tt>, returning + * the result in reduced form. + * </p> + * + * @param i + * the <tt>integer</tt> to add. + * @return a <code>BigFraction</code> instance with the resulting values. + */ + public BigFraction add(final int i) { + return add(BigInteger.valueOf(i)); + } + + /** + * <p> + * Adds the value of this fraction to the passed <tt>long</tt>, returning + * the result in reduced form. + * </p> + * + * @param l + * the <tt>long</tt> to add. + * @return a <code>BigFraction</code> instance with the resulting values. + */ + public BigFraction add(final long l) { + return add(BigInteger.valueOf(l)); } /** @@ -493,34 +522,6 @@ /** * <p> - * Adds the value of this fraction to the passed <tt>integer</tt>, returning - * the result in reduced form. - * </p> - * - * @param i - * the <tt>integer</tt> to add. - * @return a <code>BigFraction</code> instance with the resulting values. - */ - public BigFraction add(final int i) { - return add(new BigFraction(i, 1)); - } - - /** - * <p> - * Adds the value of this fraction to the passed <tt>long</tt>, returning - * the result in reduced form. - * </p> - * - * @param l - * the <tt>long</tt> to add. - * @return a <code>BigFraction</code> instance with the resulting values. - */ - public BigFraction add(final long l) { - return add(new BigFraction(l, 1L)); - } - - /** - * <p> * Gets the fraction as a <code>BigDecimal</code>. This calculates the * fraction as the numerator divided by denominator. * </p> @@ -602,31 +603,14 @@ * @return a {...@link BigFraction} instance with the resulting values. * @throws NullPointerException * if the <code>BigInteger</code> is <code>null</code>. - */ - public BigFraction divide(final BigInteger bg) { - return divide(new BigFraction(bg, BigInteger.ONE)); - } - - /** - * <p> - * Divide the value of this fraction by another, returning the result in - * reduced form. - * </p> - * - * @param fraction - * the fraction to divide by, must not be <code>null</code>. - * @return a {...@link BigFraction} instance with the resulting values. - * @throws NullPointerException - * if the fraction is <code>null</code>. * @throws ArithmeticException * if the fraction to divide by is zero. */ - public BigFraction divide(final BigFraction fraction) { - if (BigInteger.ZERO.equals(fraction.numerator)) { + public BigFraction divide(final BigInteger bg) { + if (BigInteger.ZERO.equals(bg)) { throw MathRuntimeException.createArithmeticException("denominator must be different from 0"); } - - return multiply(fraction.reciprocal()); + return new BigFraction(numerator, denominator.multiply(bg)); } /** @@ -638,9 +622,11 @@ * @param i * the <tt>int</tt> to divide by. * @return a {...@link BigFraction} instance with the resulting values. + * @throws ArithmeticException + * if the fraction to divide by is zero. */ public BigFraction divide(final int i) { - return divide(new BigFraction(i, 1)); + return divide(BigInteger.valueOf(i)); } /** @@ -652,9 +638,33 @@ * @param l * the <tt>long</tt> to divide by. * @return a {...@link BigFraction} instance with the resulting values. + * @throws ArithmeticException + * if the fraction to divide by is zero. */ public BigFraction divide(final long l) { - return divide(new BigFraction(l, 1L)); + return divide(BigInteger.valueOf(l)); + } + + /** + * <p> + * Divide the value of this fraction by another, returning the result in + * reduced form. + * </p> + * + * @param fraction + * the fraction to divide by, must not be <code>null</code>. + * @return a {...@link BigFraction} instance with the resulting values. + * @throws NullPointerException + * if the fraction is <code>null</code>. + * @throws ArithmeticException + * if the fraction to divide by is zero. + */ + public BigFraction divide(final BigFraction fraction) { + if (BigInteger.ZERO.equals(fraction.numerator)) { + throw MathRuntimeException.createArithmeticException("denominator must be different from 0"); + } + + return multiply(fraction.reciprocal()); } /** @@ -840,28 +850,6 @@ /** * <p> - * Multiplies the value of this fraction by another, returning the result in - * reduced form. - * </p> - * - * @param fraction - * the fraction to multiply by, must not be <code>null</code>. - * @return a {...@link BigFraction} instance with the resulting values. - * @throws NullPointerException - * if the fraction is <code>null</code>. - */ - public BigFraction multiply(final BigFraction fraction) { - BigFraction ret = ZERO; - - if (getNumeratorAsInt() != 0 && fraction.getNumeratorAsInt() != 0) { - ret = new BigFraction(numerator.multiply(fraction.numerator), denominator.multiply(fraction.denominator)); - } - - return ret; - } - - /** - * <p> * Multiply the value of this fraction by the passed <tt>int</tt>, returning * the result in reduced form. * </p> @@ -871,7 +859,7 @@ * @return a {...@link BigFraction} instance with the resulting values. */ public BigFraction multiply(final int i) { - return multiply(new BigFraction(i, 1)); + return multiply(BigInteger.valueOf(i)); } /** @@ -885,7 +873,29 @@ * @return a {...@link BigFraction} instance with the resulting values. */ public BigFraction multiply(final long l) { - return multiply(new BigFraction(l, 1L)); + return multiply(BigInteger.valueOf(l)); + } + + /** + * <p> + * Multiplies the value of this fraction by another, returning the result in + * reduced form. + * </p> + * + * @param fraction + * the fraction to multiply by, must not be <code>null</code>. + * @return a {...@link BigFraction} instance with the resulting values. + * @throws NullPointerException + * if the fraction is <code>null</code>. + */ + public BigFraction multiply(final BigFraction fraction) { + BigFraction ret = ZERO; + + if (getNumeratorAsInt() != 0 && fraction.getNumeratorAsInt() != 0) { + ret = new BigFraction(numerator.multiply(fraction.numerator), denominator.multiply(fraction.denominator)); + } + + return ret; } /** @@ -914,26 +924,20 @@ /** * <p> - * Returns a <code>BigFraction</code> whose value is + * Returns a <tt>integer</tt> whose value is * <tt>(this<sup>exponent</sup>)</tt>, returning the result in reduced form. * </p> * * @param exponent - * exponent to which this <code>BigFraction</code> is to be raised. - * @return <tt>this<sup>exponent</sup></tt> as a <code>BigFraction</code>. + * exponent to which this <code>BigInteger</code> is to be + * raised. + * @return <tt>this<sup>exponent</sup></tt>. */ - public BigFraction pow(final BigInteger exponent) { - BigFraction ret = this; - if (!BigInteger.ONE.equals(exponent)) { - ret = ONE; - if (!BigInteger.ZERO.equals(exponent)) { - for (BigInteger bg = BigInteger.ONE; bg.compareTo(exponent) < 0; bg = bg.add(BigInteger.ONE)) { - ret = ret.multiply(this); - } - } + public BigFraction pow(final int exponent) { + if (exponent < 0) { + return new BigFraction(denominator.pow(-exponent), numerator.pow(-exponent)); } - - return ret; + return new BigFraction(numerator.pow(exponent), denominator.pow(exponent)); } /** @@ -944,39 +948,50 @@ * * @param exponent * exponent to which this <code>BigFraction</code> is to be raised. - * @return <tt>this<sup>exponent</sup></tt>. + * @return <tt>this<sup>exponent</sup></tt> as a <code>BigFraction</code>. */ - public double pow(final BigFraction exponent) { - return Math.pow(numerator.doubleValue(), exponent.doubleValue()) / Math.pow(denominator.doubleValue(), exponent.doubleValue()); + public BigFraction pow(final long exponent) { + if (exponent < 0) { + return new BigFraction(MathUtils.pow(denominator, -exponent), + MathUtils.pow(numerator, -exponent)); + } + return new BigFraction(MathUtils.pow(numerator, exponent), + MathUtils.pow(denominator, exponent)); } - + /** * <p> - * Returns a <tt>integer</tt> whose value is + * Returns a <code>BigFraction</code> whose value is * <tt>(this<sup>exponent</sup>)</tt>, returning the result in reduced form. * </p> * * @param exponent - * exponent to which this <code>BigInteger</code> is to be - * raised. - * @return <tt>this<sup>exponent</sup></tt>. + * exponent to which this <code>BigFraction</code> is to be raised. + * @return <tt>this<sup>exponent</sup></tt> as a <code>BigFraction</code>. */ - public BigFraction pow(final int exponent) { - return pow(BigInteger.valueOf(exponent)); + public BigFraction pow(final BigInteger exponent) { + if (exponent.compareTo(BigInteger.ZERO) < 0) { + final BigInteger eNeg = exponent.negate(); + return new BigFraction(MathUtils.pow(denominator, eNeg), + MathUtils.pow(numerator, eNeg)); + } + return new BigFraction(MathUtils.pow(numerator, exponent), + MathUtils.pow(denominator, exponent)); } /** * <p> - * Returns a <code>BigFraction</code> whose value is + * Returns a <code>double</code> whose value is * <tt>(this<sup>exponent</sup>)</tt>, returning the result in reduced form. * </p> * * @param exponent * exponent to which this <code>BigFraction</code> is to be raised. - * @return <tt>this<sup>exponent</sup></tt> as a <code>BigFraction</code>. + * @return <tt>this<sup>exponent</sup></tt>. */ - public BigFraction pow(final long exponent) { - return pow(BigInteger.valueOf(exponent)); + public double pow(final double exponent) { + return Math.pow(numerator.doubleValue(), exponent) / + Math.pow(denominator.doubleValue(), exponent); } /** @@ -1017,7 +1032,36 @@ * if the {...@link BigInteger} is <code>null</code>. */ public BigFraction subtract(final BigInteger bg) { - return subtract(new BigFraction(bg, BigInteger.valueOf(1))); + return new BigFraction(numerator.subtract(denominator.multiply(bg)), denominator); + } + + /** + * <p> + * Subtracts the value of an <tt>integer</tt> from the value of this one, + * returning the result in reduced form. + * </p> + * + * @param i + * the <tt>integer</tt> to subtract. + * @return a <code>BigFraction</code> instance with the resulting values. + */ + public BigFraction subtract(final int i) { + return subtract(BigInteger.valueOf(i)); + } + + /** + * <p> + * Subtracts the value of an <tt>integer</tt> from the value of this one, + * returning the result in reduced form. + * </p> + * + * @param l + * the <tt>long</tt> to subtract. + * @return a <code>BigFraction</code> instance with the resulting values, or + * this object if the <tt>long</tt> is zero. + */ + public BigFraction subtract(final long l) { + return subtract(BigInteger.valueOf(l)); } /** @@ -1053,35 +1097,6 @@ /** * <p> - * Subtracts the value of an <tt>integer</tt> from the value of this one, - * returning the result in reduced form. - * </p> - * - * @param i - * the <tt>integer</tt> to subtract. - * @return a <code>BigFraction</code> instance with the resulting values. - */ - public BigFraction subtract(final int i) { - return subtract(new BigFraction(i, 1)); - } - - /** - * <p> - * Subtracts the value of an <tt>integer</tt> from the value of this one, - * returning the result in reduced form. - * </p> - * - * @param l - * the <tt>long</tt> to subtract. - * @return a <code>BigFraction</code> instance with the resulting values, or - * this object if the <tt>long</tt> is zero. - */ - public BigFraction subtract(final long l) { - return subtract(new BigFraction(l, 1L)); - } - - /** - * <p> * Returns the <code>String</code> representing this fraction, ie * "num / dem" or just "num" if the denominator is one. * </p> Modified: commons/proper/math/trunk/src/test/org/apache/commons/math/fraction/BigFractionTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/fraction/BigFractionTest.java?rev=760016&r1=760015&r2=760016&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/org/apache/commons/math/fraction/BigFractionTest.java (original) +++ commons/proper/math/trunk/src/test/org/apache/commons/math/fraction/BigFractionTest.java Mon Mar 30 15:48:56 2009 @@ -537,4 +537,17 @@ assertEquals(BigFraction.getReducedFraction(2, Integer.MIN_VALUE).getNumeratorAsInt(), -1); assertEquals(BigFraction.getReducedFraction(1, -1).getNumeratorAsInt(), -1); } + + public void testPow() { + assertEquals(new BigFraction(8192, 1594323), new BigFraction(2, 3).pow(13)); + assertEquals(new BigFraction(8192, 1594323), new BigFraction(2, 3).pow(13l)); + assertEquals(new BigFraction(8192, 1594323), new BigFraction(2, 3).pow(BigInteger.valueOf(13l))); + assertEquals(BigFraction.ONE, new BigFraction(2, 3).pow(0)); + assertEquals(BigFraction.ONE, new BigFraction(2, 3).pow(0l)); + assertEquals(BigFraction.ONE, new BigFraction(2, 3).pow(BigInteger.valueOf(0l))); + assertEquals(new BigFraction(1594323, 8192), new BigFraction(2, 3).pow(-13)); + assertEquals(new BigFraction(1594323, 8192), new BigFraction(2, 3).pow(-13l)); + assertEquals(new BigFraction(1594323, 8192), new BigFraction(2, 3).pow(BigInteger.valueOf(-13l))); + } + }