Create structure for fraction module within commons-numbers. Add dependencyManagement to parent pom.xml for uniform dependency on numbers core; remove version from references to numbers-core in child modules. Add test jar to numbers core pom.xml to allow for re-use of TestUtils. Add ArithmeticUtils from commons-math since Fraction, BigFraction heavily depends on it.
Project: http://git-wip-us.apache.org/repos/asf/commons-numbers/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-numbers/commit/aaef6f7a Tree: http://git-wip-us.apache.org/repos/asf/commons-numbers/tree/aaef6f7a Diff: http://git-wip-us.apache.org/repos/asf/commons-numbers/diff/aaef6f7a Branch: refs/heads/multimodule Commit: aaef6f7aa74da893b018ec3debe4367de3243c48 Parents: b026db1 Author: Ray DeCampo <r...@decampo.org> Authored: Sun Jan 22 20:41:30 2017 -0500 Committer: Ray DeCampo <r...@decampo.org> Committed: Sun Jan 22 20:41:30 2017 -0500 ---------------------------------------------------------------------- commons-numbers-complex/pom.xml | 1 - commons-numbers-core/pom.xml | 15 + .../commons/numbers/core/ArithmeticUtils.java | 772 +++++++++++ .../core/NumbersArithmeticException.java | 54 + .../numbers/core/ArithmeticUtilsTest.java | 782 ++++++++++++ commons-numbers-fraction/LICENSE.txt | 201 +++ commons-numbers-fraction/NOTICE.txt | 6 + commons-numbers-fraction/README.md | 98 ++ commons-numbers-fraction/pom.xml | 58 + .../numbers/fraction/AbstractFormat.java | 206 +++ .../commons/numbers/fraction/BigFraction.java | 1199 ++++++++++++++++++ .../numbers/fraction/BigFractionField.java | 83 ++ .../numbers/fraction/BigFractionFormat.java | 283 +++++ .../commons/numbers/fraction/Fraction.java | 664 ++++++++++ .../fraction/FractionConversionException.java | 51 + .../numbers/fraction/FractionException.java | 44 + .../commons/numbers/fraction/FractionField.java | 82 ++ .../numbers/fraction/FractionFormat.java | 261 ++++ .../fraction/FractionOverflowException.java | 47 + .../fraction/FractionParseException.java | 38 + .../fraction/ProperBigFractionFormat.java | 235 ++++ .../numbers/fraction/ProperFractionFormat.java | 227 ++++ .../fraction/ZeroDenominatorException.java | 53 + .../commons/numbers/fraction/package-info.java | 22 + .../numbers/fraction/BigFractionFieldTest.java | 43 + .../numbers/fraction/BigFractionFormatTest.java | 330 +++++ .../numbers/fraction/BigFractionTest.java | 635 ++++++++++ .../numbers/fraction/FractionFieldTest.java | 43 + .../numbers/fraction/FractionFormatTest.java | 349 +++++ .../commons/numbers/fraction/FractionTest.java | 625 +++++++++ commons-numbers-quaternion/pom.xml | 1 - pom.xml | 20 +- 32 files changed, 7525 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/aaef6f7a/commons-numbers-complex/pom.xml ---------------------------------------------------------------------- diff --git a/commons-numbers-complex/pom.xml b/commons-numbers-complex/pom.xml index 735348f..3fec4ba 100644 --- a/commons-numbers-complex/pom.xml +++ b/commons-numbers-complex/pom.xml @@ -46,7 +46,6 @@ <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-numbers-core</artifactId> - <version>1.0-SNAPSHOT</version> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/aaef6f7a/commons-numbers-core/pom.xml ---------------------------------------------------------------------- diff --git a/commons-numbers-core/pom.xml b/commons-numbers-core/pom.xml index 39dbdcb..76c2512 100644 --- a/commons-numbers-core/pom.xml +++ b/commons-numbers-core/pom.xml @@ -42,5 +42,20 @@ <numbers.parent.dir>${basedir}/..</numbers.parent.dir> </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> </project> http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/aaef6f7a/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/ArithmeticUtils.java ---------------------------------------------------------------------- diff --git a/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/ArithmeticUtils.java b/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/ArithmeticUtils.java new file mode 100644 index 0000000..343d24b --- /dev/null +++ b/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/ArithmeticUtils.java @@ -0,0 +1,772 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.numbers.core; + +import java.math.BigInteger; + +/** + * Some useful, arithmetics related, additions to the built-in functions in + * {@link Math}. + * + */ +public final class ArithmeticUtils { + + /** Private constructor. */ + private ArithmeticUtils() { + super(); + } + + /** + * Add two integers, checking for overflow. + * + * @param x an addend + * @param y an addend + * @return the sum {@code x+y} + * @throws NumbersArithmeticException if the result can not be represented + * as an {@code int}. + * @since 1.1 + */ + public static int addAndCheck(int x, int y) + throws NumbersArithmeticException { + long s = (long)x + (long)y; + if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) { + throw new NumbersArithmeticException("overflow in addition: {0} + {1}", x, y); + } + return (int)s; + } + + /** + * Add two long integers, checking for overflow. + * + * @param a an addend + * @param b an addend + * @return the sum {@code a+b} + * @throws NumbersArithmeticException if the result can not be represented as an long + * @since 1.2 + */ + public static long addAndCheck(long a, long b) throws NumbersArithmeticException { + return addAndCheck(a, b, "overflow in addition: {0} + {1}"); + } + + /** + * Computes the greatest common divisor of the absolute value of two + * numbers, using a modified version of the "binary gcd" method. + * See Knuth 4.5.2 algorithm B. + * The algorithm is due to Josef Stein (1961). + * <br> + * Special cases: + * <ul> + * <li>The invocations + * {@code gcd(Integer.MIN_VALUE, Integer.MIN_VALUE)}, + * {@code gcd(Integer.MIN_VALUE, 0)} and + * {@code gcd(0, Integer.MIN_VALUE)} throw an + * {@code ArithmeticException}, because the result would be 2^31, which + * is too large for an int value.</li> + * <li>The result of {@code gcd(x, x)}, {@code gcd(0, x)} and + * {@code gcd(x, 0)} is the absolute value of {@code x}, except + * for the special cases above.</li> + * <li>The invocation {@code gcd(0, 0)} is the only one which returns + * {@code 0}.</li> + * </ul> + * + * @param p Number. + * @param q Number. + * @return the greatest common divisor (never negative). + * @throws NumbersArithmeticException if the result cannot be represented as + * a non-negative {@code int} value. + * @since 1.1 + */ + public static int gcd(int p, int q) throws NumbersArithmeticException { + int a = p; + int b = q; + if (a == 0 || + b == 0) { + if (a == Integer.MIN_VALUE || + b == Integer.MIN_VALUE) { + throw new NumbersArithmeticException("overflow: gcd({0}, {1}) is 2^31", + p, q); + } + return Math.abs(a + b); + } + + long al = a; + long bl = b; + boolean useLong = false; + if (a < 0) { + if(Integer.MIN_VALUE == a) { + useLong = true; + } else { + a = -a; + } + al = -al; + } + if (b < 0) { + if (Integer.MIN_VALUE == b) { + useLong = true; + } else { + b = -b; + } + bl = -bl; + } + if (useLong) { + if(al == bl) { + throw new NumbersArithmeticException("overflow: gcd({0}, {1}) is 2^31", + p, q); + } + long blbu = bl; + bl = al; + al = blbu % al; + if (al == 0) { + if (bl > Integer.MAX_VALUE) { + throw new NumbersArithmeticException("overflow: gcd({0}, {1}) is 2^31", + p, q); + } + return (int) bl; + } + blbu = bl; + + // Now "al" and "bl" fit in an "int". + b = (int) al; + a = (int) (blbu % al); + } + + return gcdPositive(a, b); + } + + /** + * Computes the greatest common divisor of two <em>positive</em> numbers + * (this precondition is <em>not</em> checked and the result is undefined + * if not fulfilled) using the "binary gcd" method which avoids division + * and modulo operations. + * See Knuth 4.5.2 algorithm B. + * The algorithm is due to Josef Stein (1961). + * <br/> + * Special cases: + * <ul> + * <li>The result of {@code gcd(x, x)}, {@code gcd(0, x)} and + * {@code gcd(x, 0)} is the value of {@code x}.</li> + * <li>The invocation {@code gcd(0, 0)} is the only one which returns + * {@code 0}.</li> + * </ul> + * + * @param a Positive number. + * @param b Positive number. + * @return the greatest common divisor. + */ + private static int gcdPositive(int a, int b) { + if (a == 0) { + return b; + } + else if (b == 0) { + return a; + } + + // Make "a" and "b" odd, keeping track of common power of 2. + final int aTwos = Integer.numberOfTrailingZeros(a); + a >>= aTwos; + final int bTwos = Integer.numberOfTrailingZeros(b); + b >>= bTwos; + final int shift = Math.min(aTwos, bTwos); + + // "a" and "b" are positive. + // If a > b then "gdc(a, b)" is equal to "gcd(a - b, b)". + // If a < b then "gcd(a, b)" is equal to "gcd(b - a, a)". + // Hence, in the successive iterations: + // "a" becomes the absolute difference of the current values, + // "b" becomes the minimum of the current values. + while (a != b) { + final int delta = a - b; + b = Math.min(a, b); + a = Math.abs(delta); + + // Remove any power of 2 in "a" ("b" is guaranteed to be odd). + a >>= Integer.numberOfTrailingZeros(a); + } + + // Recover the common power of 2. + return a << shift; + } + + /** + * <p> + * Gets the greatest common divisor of the absolute value of two numbers, + * using the "binary gcd" method which avoids division and modulo + * operations. See Knuth 4.5.2 algorithm B. This algorithm is due to Josef + * Stein (1961). + * </p> + * Special cases: + * <ul> + * <li>The invocations + * {@code gcd(Long.MIN_VALUE, Long.MIN_VALUE)}, + * {@code gcd(Long.MIN_VALUE, 0L)} and + * {@code gcd(0L, Long.MIN_VALUE)} throw an + * {@code ArithmeticException}, because the result would be 2^63, which + * is too large for a long value.</li> + * <li>The result of {@code gcd(x, x)}, {@code gcd(0L, x)} and + * {@code gcd(x, 0L)} is the absolute value of {@code x}, except + * for the special cases above. + * <li>The invocation {@code gcd(0L, 0L)} is the only one which returns + * {@code 0L}.</li> + * </ul> + * + * @param p Number. + * @param q Number. + * @return the greatest common divisor, never negative. + * @throws NumbersArithmeticException if the result cannot be represented as + * a non-negative {@code long} value. + * @since 2.1 + */ + public static long gcd(final long p, final long q) throws NumbersArithmeticException { + long u = p; + long v = q; + if ((u == 0) || (v == 0)) { + if ((u == Long.MIN_VALUE) || (v == Long.MIN_VALUE)){ + throw new NumbersArithmeticException("overflow: gcd({0}, {1}) is 2^63", + p, q); + } + return Math.abs(u) + Math.abs(v); + } + // keep u and v negative, as negative integers range down to + // -2^63, while positive numbers can only be as large as 2^63-1 + // (i.e. we can't necessarily negate a negative number without + // overflow) + /* assert u!=0 && v!=0; */ + if (u > 0) { + u = -u; + } // make u negative + if (v > 0) { + v = -v; + } // make v negative + // B1. [Find power of 2] + int k = 0; + while ((u & 1) == 0 && (v & 1) == 0 && k < 63) { // while u and v are + // both even... + u /= 2; + v /= 2; + k++; // cast out twos. + } + if (k == 63) { + throw new NumbersArithmeticException("overflow: gcd({0}, {1}) is 2^63", + p, q); + } + // B2. Initialize: u and v have been divided by 2^k and at least + // one is odd. + long t = ((u & 1) == 1) ? v : -(u / 2)/* B3 */; + // t negative: u was odd, v may be even (t replaces v) + // t positive: u was even, v is odd (t replaces u) + do { + /* assert u<0 && v<0; */ + // B4/B3: cast out twos from t. + while ((t & 1) == 0) { // while t is even.. + t /= 2; // cast out twos + } + // B5 [reset max(u,v)] + if (t > 0) { + u = -t; + } else { + v = t; + } + // B6/B3. at this point both u and v should be odd. + t = (v - u) / 2; + // |u| larger: t positive (replace u) + // |v| larger: t negative (replace v) + } while (t != 0); + return -u * (1L << k); // gcd is u*2^k + } + + /** + * <p> + * Returns the least common multiple of the absolute value of two numbers, + * using the formula {@code lcm(a,b) = (a / gcd(a,b)) * b}. + * </p> + * Special cases: + * <ul> + * <li>The invocations {@code lcm(Integer.MIN_VALUE, n)} and + * {@code lcm(n, Integer.MIN_VALUE)}, where {@code abs(n)} is a + * power of 2, throw an {@code ArithmeticException}, because the result + * would be 2^31, which is too large for an int value.</li> + * <li>The result of {@code lcm(0, x)} and {@code lcm(x, 0)} is + * {@code 0} for any {@code x}. + * </ul> + * + * @param a Number. + * @param b Number. + * @return the least common multiple, never negative. + * @throws NumbersArithmeticException if the result cannot be represented as + * a non-negative {@code int} value. + * @since 1.1 + */ + public static int lcm(int a, int b) throws NumbersArithmeticException { + if (a == 0 || b == 0){ + return 0; + } + int lcm = Math.abs(ArithmeticUtils.mulAndCheck(a / gcd(a, b), b)); + if (lcm == Integer.MIN_VALUE) { + throw new NumbersArithmeticException("overflow: lcm({0}, {1}) is 2^31", + a, b); + } + return lcm; + } + + /** + * <p> + * Returns the least common multiple of the absolute value of two numbers, + * using the formula {@code lcm(a,b) = (a / gcd(a,b)) * b}. + * </p> + * Special cases: + * <ul> + * <li>The invocations {@code lcm(Long.MIN_VALUE, n)} and + * {@code lcm(n, Long.MIN_VALUE)}, where {@code abs(n)} is a + * power of 2, throw an {@code ArithmeticException}, because the result + * would be 2^63, which is too large for an int value.</li> + * <li>The result of {@code lcm(0L, x)} and {@code lcm(x, 0L)} is + * {@code 0L} for any {@code x}. + * </ul> + * + * @param a Number. + * @param b Number. + * @return the least common multiple, never negative. + * @throws NumbersArithmeticException if the result cannot be represented + * as a non-negative {@code long} value. + * @since 2.1 + */ + public static long lcm(long a, long b) throws NumbersArithmeticException { + if (a == 0 || b == 0){ + return 0; + } + long lcm = Math.abs(ArithmeticUtils.mulAndCheck(a / gcd(a, b), b)); + if (lcm == Long.MIN_VALUE){ + throw new NumbersArithmeticException("overflow: lcm({0}, {1}) is 2^63", + a, b); + } + return lcm; + } + + /** + * Multiply two integers, checking for overflow. + * + * @param x Factor. + * @param y Factor. + * @return the product {@code x * y}. + * @throws NumbersArithmeticException if the result can not be + * represented as an {@code int}. + * @since 1.1 + */ + public static int mulAndCheck(int x, int y) throws NumbersArithmeticException { + long m = ((long)x) * ((long)y); + if (m < Integer.MIN_VALUE || m > Integer.MAX_VALUE) { + throw new NumbersArithmeticException(); + } + return (int)m; + } + + /** + * Multiply two long integers, checking for overflow. + * + * @param a Factor. + * @param b Factor. + * @return the product {@code a * b}. + * @throws NumbersArithmeticException if the result can not be represented + * as a {@code long}. + * @since 1.2 + */ + public static long mulAndCheck(long a, long b) throws NumbersArithmeticException { + long ret; + if (a > b) { + // use symmetry to reduce boundary cases + ret = mulAndCheck(b, a); + } else { + if (a < 0) { + if (b < 0) { + // check for positive overflow with negative a, negative b + if (a >= Long.MAX_VALUE / b) { + ret = a * b; + } else { + throw new NumbersArithmeticException(); + } + } else if (b > 0) { + // check for negative overflow with negative a, positive b + if (Long.MIN_VALUE / b <= a) { + ret = a * b; + } else { + throw new NumbersArithmeticException(); + + } + } else { + // assert b == 0 + ret = 0; + } + } else if (a > 0) { + // assert a > 0 + // assert b > 0 + + // check for positive overflow with positive a, positive b + if (a <= Long.MAX_VALUE / b) { + ret = a * b; + } else { + throw new NumbersArithmeticException(); + } + } else { + // assert a == 0 + ret = 0; + } + } + return ret; + } + + /** + * Subtract two integers, checking for overflow. + * + * @param x Minuend. + * @param y Subtrahend. + * @return the difference {@code x - y}. + * @throws NumbersArithmeticException if the result can not be represented + * as an {@code int}. + * @since 1.1 + */ + public static int subAndCheck(int x, int y) throws NumbersArithmeticException { + long s = (long)x - (long)y; + if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) { + throw new NumbersArithmeticException("overflow in subtraction: {0} - {1}", x, y); + } + return (int)s; + } + + /** + * Subtract two long integers, checking for overflow. + * + * @param a Value. + * @param b Value. + * @return the difference {@code a - b}. + * @throws NumbersArithmeticException if the result can not be represented as a + * {@code long}. + * @since 1.2 + */ + public static long subAndCheck(long a, long b) throws NumbersArithmeticException { + long ret; + if (b == Long.MIN_VALUE) { + if (a < 0) { + ret = a - b; + } else { + throw new NumbersArithmeticException("overflow in subtraction: {0} + {1}", a, -b); + } + } else { + // use additive inverse + ret = addAndCheck(a, -b, "overflow in subtraction: {0} + {1}"); + } + return ret; + } + + /** + * Raise an int to an int power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return \( k^e \) + * @throws IllegalArgumentException if {@code e < 0}. + * @throws NumbersArithmeticException if the result would overflow. + */ + public static int pow(final int k, + final int e) + throws NumbersArithmeticException { + if (e < 0) { + throw new IllegalArgumentException("negative exponent ({" + e + "})"); + } + + int exp = e; + int result = 1; + int k2p = k; + while (true) { + if ((exp & 0x1) != 0) { + result = mulAndCheck(result, k2p); + } + + exp >>= 1; + if (exp == 0) { + break; + } + + k2p = mulAndCheck(k2p, k2p); + } + + return result; + } + + /** + * Raise a long to an int power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return \( k^e \) + * @throws IllegalArgumentException if {@code e < 0}. + * @throws NumbersArithmeticException if the result would overflow. + */ + public static long pow(final long k, + final int e) + throws NumbersArithmeticException { + if (e < 0) { + throw new IllegalArgumentException("negative exponent ({" + e + "})"); + } + + int exp = e; + long result = 1; + long k2p = k; + while (true) { + if ((exp & 0x1) != 0) { + result = mulAndCheck(result, k2p); + } + + exp >>= 1; + if (exp == 0) { + break; + } + + k2p = mulAndCheck(k2p, k2p); + } + + return result; + } + + /** + * Raise a BigInteger to an int power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return k<sup>e</sup> + * @throws IllegalArgumentException if {@code e < 0}. + */ + public static BigInteger pow(final BigInteger k, int e) { + if (e < 0) { + throw new IllegalArgumentException("negative exponent ({" + e + "})"); + } + + return k.pow(e); + } + + /** + * Raise a BigInteger to a long power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return k<sup>e</sup> + * @throws IllegalArgumentException if {@code e < 0}. + */ + public static BigInteger pow(final BigInteger k, long e) { + if (e < 0) { + throw new IllegalArgumentException("negative exponent ({" + e + "})"); + } + + BigInteger result = BigInteger.ONE; + BigInteger k2p = k; + while (e != 0) { + if ((e & 0x1) != 0) { + result = result.multiply(k2p); + } + k2p = k2p.multiply(k2p); + e >>= 1; + } + + return result; + + } + + /** + * Raise a BigInteger to a BigInteger power. + * + * @param k Number to raise. + * @param e Exponent (must be positive or zero). + * @return k<sup>e</sup> + * @throws IllegalArgumentException if {@code e < 0}. + */ + public static BigInteger pow(final BigInteger k, BigInteger e) { + if (e.compareTo(BigInteger.ZERO) < 0) { + throw new IllegalArgumentException("negative exponent ({" + e + "})"); + } + + BigInteger result = BigInteger.ONE; + BigInteger k2p = k; + while (!BigInteger.ZERO.equals(e)) { + if (e.testBit(0)) { + result = result.multiply(k2p); + } + k2p = k2p.multiply(k2p); + e = e.shiftRight(1); + } + + return result; + } + + /** + * Add two long integers, checking for overflow. + * + * @param a Addend. + * @param b Addend. + * @param pattern Pattern to use for any thrown exception. + * @return the sum {@code a + b}. + * @throws NumbersArithmeticException if the result cannot be represented + * as a {@code long}. + * @since 1.2 + */ + private static long addAndCheck(long a, long b, String message) throws NumbersArithmeticException { + final long result = a + b; + if (!((a ^ b) < 0 || (a ^ result) >= 0)) { + throw new NumbersArithmeticException(message, a, b); + } + return result; + } + + /** + * Returns true if the argument is a power of two. + * + * @param n the number to test + * @return true if the argument is a power of two + */ + public static boolean isPowerOfTwo(long n) { + return (n > 0) && ((n & (n - 1)) == 0); + } + + /** + * Returns the unsigned remainder from dividing the first argument + * by the second where each argument and the result is interpreted + * as an unsigned value. + * <p>This method does not use the {@code long} datatype.</p> + * + * @param dividend the value to be divided + * @param divisor the value doing the dividing + * @return the unsigned remainder of the first argument divided by + * the second argument. + * + * @since 4.0 + */ + public static int remainderUnsigned(int dividend, int divisor) { + if (divisor >= 0) { + if (dividend >= 0) { + return dividend % divisor; + } + // The implementation is a Java port of algorithm described in the book + // "Hacker's Delight" (section "Unsigned short division from signed division"). + int q = ((dividend >>> 1) / divisor) << 1; + dividend -= q * divisor; + if (dividend < 0 || dividend >= divisor) { + dividend -= divisor; + } + return dividend; + } + return dividend >= 0 || dividend < divisor ? dividend : dividend - divisor; + } + + /** + * Returns the unsigned remainder from dividing the first argument + * by the second where each argument and the result is interpreted + * as an unsigned value. + * <p>This method does not use the {@code BigInteger} datatype.</p> + * + * @param dividend the value to be divided + * @param divisor the value doing the dividing + * @return the unsigned remainder of the first argument divided by + * the second argument. + * + * @since 4.0 + */ + public static long remainderUnsigned(long dividend, long divisor) { + if (divisor >= 0L) { + if (dividend >= 0L) { + return dividend % divisor; + } + // The implementation is a Java port of algorithm described in the book + // "Hacker's Delight" (section "Unsigned short division from signed division"). + long q = ((dividend >>> 1) / divisor) << 1; + dividend -= q * divisor; + if (dividend < 0L || dividend >= divisor) { + dividend -= divisor; + } + return dividend; + } + return dividend >= 0L || dividend < divisor ? dividend : dividend - divisor; + } + + /** + * Returns the unsigned quotient of dividing the first argument by + * the second where each argument and the result is interpreted as + * an unsigned value. + * <p>Note that in two's complement arithmetic, the three other + * basic arithmetic operations of add, subtract, and multiply are + * bit-wise identical if the two operands are regarded as both + * being signed or both being unsigned. Therefore separate {@code + * addUnsigned}, etc. methods are not provided.</p> + * <p>This method does not use the {@code long} datatype.</p> + * + * @param dividend the value to be divided + * @param divisor the value doing the dividing + * @return the unsigned quotient of the first argument divided by + * the second argument + * + * @since 4.0 + */ + public static int divideUnsigned(int dividend, int divisor) { + if (divisor >= 0) { + if (dividend >= 0) { + return dividend / divisor; + } + // The implementation is a Java port of algorithm described in the book + // "Hacker's Delight" (section "Unsigned short division from signed division"). + int q = ((dividend >>> 1) / divisor) << 1; + dividend -= q * divisor; + if (dividend < 0L || dividend >= divisor) { + q++; + } + return q; + } + return dividend >= 0 || dividend < divisor ? 0 : 1; + } + + /** + * Returns the unsigned quotient of dividing the first argument by + * the second where each argument and the result is interpreted as + * an unsigned value. + * <p>Note that in two's complement arithmetic, the three other + * basic arithmetic operations of add, subtract, and multiply are + * bit-wise identical if the two operands are regarded as both + * being signed or both being unsigned. Therefore separate {@code + * addUnsigned}, etc. methods are not provided.</p> + * <p>This method does not use the {@code BigInteger} datatype.</p> + * + * @param dividend the value to be divided + * @param divisor the value doing the dividing + * @return the unsigned quotient of the first argument divided by + * the second argument. + * + * @since 4.0 + */ + public static long divideUnsigned(long dividend, long divisor) { + if (divisor >= 0L) { + if (dividend >= 0L) { + return dividend / divisor; + } + // The implementation is a Java port of algorithm described in the book + // "Hacker's Delight" (section "Unsigned short division from signed division"). + long q = ((dividend >>> 1) / divisor) << 1; + dividend -= q * divisor; + if (dividend < 0L || dividend >= divisor) { + q++; + } + return q; + } + return dividend >= 0L || dividend < divisor ? 0L : 1L; + } + +} http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/aaef6f7a/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/NumbersArithmeticException.java ---------------------------------------------------------------------- diff --git a/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/NumbersArithmeticException.java b/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/NumbersArithmeticException.java new file mode 100644 index 0000000..a910e80 --- /dev/null +++ b/commons-numbers-core/src/main/java/org/apache/commons/numbers/core/NumbersArithmeticException.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.numbers.core; + +import java.text.MessageFormat; + +/** + * Base class for arithmetic exceptions. + */ +public class NumbersArithmeticException extends ArithmeticException { + /** Serializable version Id. */ + private static final long serialVersionUID = -6024911025449780474L; + + private final Object[] formatArguments; + + /** + * Default constructor. + */ + public NumbersArithmeticException() { + this("arithmetic exception"); + } + + /** + * Constructor with a specific message. + * + * @param message Message pattern providing the specific context of + * the error. + * @param args Arguments. + */ + public NumbersArithmeticException(String message, Object ... args) { + super(message); + this.formatArguments = args; + } + + @Override + public String getMessage() { + return MessageFormat.format(super.getMessage(), formatArguments); + } + +} http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/aaef6f7a/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/ArithmeticUtilsTest.java ---------------------------------------------------------------------- diff --git a/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/ArithmeticUtilsTest.java b/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/ArithmeticUtilsTest.java new file mode 100644 index 0000000..500aca3 --- /dev/null +++ b/commons-numbers-core/src/test/java/org/apache/commons/numbers/core/ArithmeticUtilsTest.java @@ -0,0 +1,782 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.numbers.core; + +import java.util.Arrays; +import java.math.BigInteger; +import java.util.Collections; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test cases for the {@link ArithmeticUtils} class. + * + */ +public class ArithmeticUtilsTest { + + @Test + public void testAddAndCheck() { + int big = Integer.MAX_VALUE; + int bigNeg = Integer.MIN_VALUE; + Assert.assertEquals(big, ArithmeticUtils.addAndCheck(big, 0)); + try { + ArithmeticUtils.addAndCheck(big, 1); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException ex) { + } + try { + ArithmeticUtils.addAndCheck(bigNeg, -1); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException ex) { + } + } + + @Test + public void testAddAndCheckLong() { + long max = Long.MAX_VALUE; + long min = Long.MIN_VALUE; + Assert.assertEquals(max, ArithmeticUtils.addAndCheck(max, 0L)); + Assert.assertEquals(min, ArithmeticUtils.addAndCheck(min, 0L)); + Assert.assertEquals(max, ArithmeticUtils.addAndCheck(0L, max)); + Assert.assertEquals(min, ArithmeticUtils.addAndCheck(0L, min)); + Assert.assertEquals(1, ArithmeticUtils.addAndCheck(-1L, 2L)); + Assert.assertEquals(1, ArithmeticUtils.addAndCheck(2L, -1L)); + Assert.assertEquals(-3, ArithmeticUtils.addAndCheck(-2L, -1L)); + Assert.assertEquals(min, ArithmeticUtils.addAndCheck(min + 1, -1L)); + Assert.assertEquals(-1, ArithmeticUtils.addAndCheck(min, max)); + testAddAndCheckLongFailure(max, 1L); + testAddAndCheckLongFailure(min, -1L); + testAddAndCheckLongFailure(1L, max); + testAddAndCheckLongFailure(-1L, min); + testAddAndCheckLongFailure(max, max); + testAddAndCheckLongFailure(min, min); + } + + @Test + public void testGcd() { + int a = 30; + int b = 50; + int c = 77; + + Assert.assertEquals(0, ArithmeticUtils.gcd(0, 0)); + + Assert.assertEquals(b, ArithmeticUtils.gcd(0, b)); + Assert.assertEquals(a, ArithmeticUtils.gcd(a, 0)); + Assert.assertEquals(b, ArithmeticUtils.gcd(0, -b)); + Assert.assertEquals(a, ArithmeticUtils.gcd(-a, 0)); + + Assert.assertEquals(10, ArithmeticUtils.gcd(a, b)); + Assert.assertEquals(10, ArithmeticUtils.gcd(-a, b)); + Assert.assertEquals(10, ArithmeticUtils.gcd(a, -b)); + Assert.assertEquals(10, ArithmeticUtils.gcd(-a, -b)); + + Assert.assertEquals(1, ArithmeticUtils.gcd(a, c)); + Assert.assertEquals(1, ArithmeticUtils.gcd(-a, c)); + Assert.assertEquals(1, ArithmeticUtils.gcd(a, -c)); + Assert.assertEquals(1, ArithmeticUtils.gcd(-a, -c)); + + Assert.assertEquals(3 * (1<<15), ArithmeticUtils.gcd(3 * (1<<20), 9 * (1<<15))); + + Assert.assertEquals(Integer.MAX_VALUE, ArithmeticUtils.gcd(Integer.MAX_VALUE, 0)); + Assert.assertEquals(Integer.MAX_VALUE, ArithmeticUtils.gcd(-Integer.MAX_VALUE, 0)); + Assert.assertEquals(1<<30, ArithmeticUtils.gcd(1<<30, -Integer.MIN_VALUE)); + try { + // gcd(Integer.MIN_VALUE, 0) > Integer.MAX_VALUE + ArithmeticUtils.gcd(Integer.MIN_VALUE, 0); + Assert.fail("expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + try { + // gcd(0, Integer.MIN_VALUE) > Integer.MAX_VALUE + ArithmeticUtils.gcd(0, Integer.MIN_VALUE); + Assert.fail("expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + try { + // gcd(Integer.MIN_VALUE, Integer.MIN_VALUE) > Integer.MAX_VALUE + ArithmeticUtils.gcd(Integer.MIN_VALUE, Integer.MIN_VALUE); + Assert.fail("expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + } + + @Test + public void testGcdConsistency() { + // Use Integer to prevent varargs vs array issue with Arrays.asList + Integer[] primeList = {19, 23, 53, 67, 73, 79, 101, 103, 111, 131}; + + for (int i = 0; i < 20; i++) { + Collections.shuffle(Arrays.asList(primeList)); + int p1 = primeList[0]; + int p2 = primeList[1]; + int p3 = primeList[2]; + int p4 = primeList[3]; + int i1 = p1 * p2 * p3; + int i2 = p1 * p2 * p4; + int gcd = p1 * p2; + Assert.assertEquals(gcd, ArithmeticUtils.gcd(i1, i2)); + long l1 = i1; + long l2 = i2; + Assert.assertEquals(gcd, ArithmeticUtils.gcd(l1, l2)); + } + } + + @Test + public void testGcdLong(){ + long a = 30; + long b = 50; + long c = 77; + + Assert.assertEquals(0, ArithmeticUtils.gcd(0L, 0)); + + Assert.assertEquals(b, ArithmeticUtils.gcd(0, b)); + Assert.assertEquals(a, ArithmeticUtils.gcd(a, 0)); + Assert.assertEquals(b, ArithmeticUtils.gcd(0, -b)); + Assert.assertEquals(a, ArithmeticUtils.gcd(-a, 0)); + + Assert.assertEquals(10, ArithmeticUtils.gcd(a, b)); + Assert.assertEquals(10, ArithmeticUtils.gcd(-a, b)); + Assert.assertEquals(10, ArithmeticUtils.gcd(a, -b)); + Assert.assertEquals(10, ArithmeticUtils.gcd(-a, -b)); + + Assert.assertEquals(1, ArithmeticUtils.gcd(a, c)); + Assert.assertEquals(1, ArithmeticUtils.gcd(-a, c)); + Assert.assertEquals(1, ArithmeticUtils.gcd(a, -c)); + Assert.assertEquals(1, ArithmeticUtils.gcd(-a, -c)); + + Assert.assertEquals(3L * (1L<<45), ArithmeticUtils.gcd(3L * (1L<<50), 9L * (1L<<45))); + + Assert.assertEquals(1L<<45, ArithmeticUtils.gcd(1L<<45, Long.MIN_VALUE)); + + Assert.assertEquals(Long.MAX_VALUE, ArithmeticUtils.gcd(Long.MAX_VALUE, 0L)); + Assert.assertEquals(Long.MAX_VALUE, ArithmeticUtils.gcd(-Long.MAX_VALUE, 0L)); + Assert.assertEquals(1, ArithmeticUtils.gcd(60247241209L, 153092023L)); + try { + // gcd(Long.MIN_VALUE, 0) > Long.MAX_VALUE + ArithmeticUtils.gcd(Long.MIN_VALUE, 0); + Assert.fail("expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + try { + // gcd(0, Long.MIN_VALUE) > Long.MAX_VALUE + ArithmeticUtils.gcd(0, Long.MIN_VALUE); + Assert.fail("expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + try { + // gcd(Long.MIN_VALUE, Long.MIN_VALUE) > Long.MAX_VALUE + ArithmeticUtils.gcd(Long.MIN_VALUE, Long.MIN_VALUE); + Assert.fail("expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + } + + + @Test + public void testLcm() { + int a = 30; + int b = 50; + int c = 77; + + Assert.assertEquals(0, ArithmeticUtils.lcm(0, b)); + Assert.assertEquals(0, ArithmeticUtils.lcm(a, 0)); + Assert.assertEquals(b, ArithmeticUtils.lcm(1, b)); + Assert.assertEquals(a, ArithmeticUtils.lcm(a, 1)); + Assert.assertEquals(150, ArithmeticUtils.lcm(a, b)); + Assert.assertEquals(150, ArithmeticUtils.lcm(-a, b)); + Assert.assertEquals(150, ArithmeticUtils.lcm(a, -b)); + Assert.assertEquals(150, ArithmeticUtils.lcm(-a, -b)); + Assert.assertEquals(2310, ArithmeticUtils.lcm(a, c)); + + // Assert that no intermediate value overflows: + // The naive implementation of lcm(a,b) would be (a*b)/gcd(a,b) + Assert.assertEquals((1<<20)*15, ArithmeticUtils.lcm((1<<20)*3, (1<<20)*5)); + + // Special case + Assert.assertEquals(0, ArithmeticUtils.lcm(0, 0)); + + try { + // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int + ArithmeticUtils.lcm(Integer.MIN_VALUE, 1); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + + try { + // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int + ArithmeticUtils.lcm(Integer.MIN_VALUE, 1<<20); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + + try { + ArithmeticUtils.lcm(Integer.MAX_VALUE, Integer.MAX_VALUE - 1); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + } + + @Test + public void testLcmLong() { + long a = 30; + long b = 50; + long c = 77; + + Assert.assertEquals(0, ArithmeticUtils.lcm(0, b)); + Assert.assertEquals(0, ArithmeticUtils.lcm(a, 0)); + Assert.assertEquals(b, ArithmeticUtils.lcm(1, b)); + Assert.assertEquals(a, ArithmeticUtils.lcm(a, 1)); + Assert.assertEquals(150, ArithmeticUtils.lcm(a, b)); + Assert.assertEquals(150, ArithmeticUtils.lcm(-a, b)); + Assert.assertEquals(150, ArithmeticUtils.lcm(a, -b)); + Assert.assertEquals(150, ArithmeticUtils.lcm(-a, -b)); + Assert.assertEquals(2310, ArithmeticUtils.lcm(a, c)); + + Assert.assertEquals(Long.MAX_VALUE, ArithmeticUtils.lcm(60247241209L, 153092023L)); + + // Assert that no intermediate value overflows: + // The naive implementation of lcm(a,b) would be (a*b)/gcd(a,b) + Assert.assertEquals((1L<<50)*15, ArithmeticUtils.lcm((1L<<45)*3, (1L<<50)*5)); + + // Special case + Assert.assertEquals(0L, ArithmeticUtils.lcm(0L, 0L)); + + try { + // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int + ArithmeticUtils.lcm(Long.MIN_VALUE, 1); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + + try { + // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int + ArithmeticUtils.lcm(Long.MIN_VALUE, 1<<20); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + + Assert.assertEquals((long) Integer.MAX_VALUE * (Integer.MAX_VALUE - 1), + ArithmeticUtils.lcm((long)Integer.MAX_VALUE, Integer.MAX_VALUE - 1)); + try { + ArithmeticUtils.lcm(Long.MAX_VALUE, Long.MAX_VALUE - 1); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException expected) { + // expected + } + } + + @Test + public void testMulAndCheck() { + int big = Integer.MAX_VALUE; + int bigNeg = Integer.MIN_VALUE; + Assert.assertEquals(big, ArithmeticUtils.mulAndCheck(big, 1)); + try { + ArithmeticUtils.mulAndCheck(big, 2); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException ex) { + } + try { + ArithmeticUtils.mulAndCheck(bigNeg, 2); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException ex) { + } + } + + @Test + public void testMulAndCheckLong() { + long max = Long.MAX_VALUE; + long min = Long.MIN_VALUE; + Assert.assertEquals(max, ArithmeticUtils.mulAndCheck(max, 1L)); + Assert.assertEquals(min, ArithmeticUtils.mulAndCheck(min, 1L)); + Assert.assertEquals(0L, ArithmeticUtils.mulAndCheck(max, 0L)); + Assert.assertEquals(0L, ArithmeticUtils.mulAndCheck(min, 0L)); + Assert.assertEquals(max, ArithmeticUtils.mulAndCheck(1L, max)); + Assert.assertEquals(min, ArithmeticUtils.mulAndCheck(1L, min)); + Assert.assertEquals(0L, ArithmeticUtils.mulAndCheck(0L, max)); + Assert.assertEquals(0L, ArithmeticUtils.mulAndCheck(0L, min)); + Assert.assertEquals(1L, ArithmeticUtils.mulAndCheck(-1L, -1L)); + Assert.assertEquals(min, ArithmeticUtils.mulAndCheck(min / 2, 2)); + testMulAndCheckLongFailure(max, 2L); + testMulAndCheckLongFailure(2L, max); + testMulAndCheckLongFailure(min, 2L); + testMulAndCheckLongFailure(2L, min); + testMulAndCheckLongFailure(min, -1L); + testMulAndCheckLongFailure(-1L, min); + } + + @Test + public void testSubAndCheck() { + int big = Integer.MAX_VALUE; + int bigNeg = Integer.MIN_VALUE; + Assert.assertEquals(big, ArithmeticUtils.subAndCheck(big, 0)); + Assert.assertEquals(bigNeg + 1, ArithmeticUtils.subAndCheck(bigNeg, -1)); + Assert.assertEquals(-1, ArithmeticUtils.subAndCheck(bigNeg, -big)); + try { + ArithmeticUtils.subAndCheck(big, -1); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException ex) { + } + try { + ArithmeticUtils.subAndCheck(bigNeg, 1); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException ex) { + } + } + + @Test + public void testSubAndCheckErrorMessage() { + int big = Integer.MAX_VALUE; + try { + ArithmeticUtils.subAndCheck(big, -1); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException ex) { + Assert.assertTrue(ex.getMessage().length() > 1); + } + } + + @Test + public void testSubAndCheckLong() { + long max = Long.MAX_VALUE; + long min = Long.MIN_VALUE; + Assert.assertEquals(max, ArithmeticUtils.subAndCheck(max, 0)); + Assert.assertEquals(min, ArithmeticUtils.subAndCheck(min, 0)); + Assert.assertEquals(-max, ArithmeticUtils.subAndCheck(0, max)); + Assert.assertEquals(min + 1, ArithmeticUtils.subAndCheck(min, -1)); + // min == -1-max + Assert.assertEquals(-1, ArithmeticUtils.subAndCheck(-max - 1, -max)); + Assert.assertEquals(max, ArithmeticUtils.subAndCheck(-1, -1 - max)); + testSubAndCheckLongFailure(0L, min); + testSubAndCheckLongFailure(max, -1L); + testSubAndCheckLongFailure(min, 1L); + } + + @Test + public void testPow() { + + Assert.assertEquals(1801088541, ArithmeticUtils.pow(21, 7)); + Assert.assertEquals(1, ArithmeticUtils.pow(21, 0)); + try { + ArithmeticUtils.pow(21, -7); + Assert.fail("Expecting IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected behavior + } + + Assert.assertEquals(1801088541, ArithmeticUtils.pow(21, 7)); + Assert.assertEquals(1, ArithmeticUtils.pow(21, 0)); + try { + ArithmeticUtils.pow(21, -7); + Assert.fail("Expecting IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected behavior + } + + Assert.assertEquals(1801088541l, ArithmeticUtils.pow(21l, 7)); + Assert.assertEquals(1l, ArithmeticUtils.pow(21l, 0)); + try { + ArithmeticUtils.pow(21l, -7); + Assert.fail("Expecting IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected behavior + } + + BigInteger twentyOne = BigInteger.valueOf(21l); + Assert.assertEquals(BigInteger.valueOf(1801088541l), ArithmeticUtils.pow(twentyOne, 7)); + Assert.assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, 0)); + try { + ArithmeticUtils.pow(twentyOne, -7); + Assert.fail("Expecting IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected behavior + } + + Assert.assertEquals(BigInteger.valueOf(1801088541l), ArithmeticUtils.pow(twentyOne, 7l)); + Assert.assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, 0l)); + try { + ArithmeticUtils.pow(twentyOne, -7l); + Assert.fail("Expecting IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected behavior + } + + Assert.assertEquals(BigInteger.valueOf(1801088541l), ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(7l))); + Assert.assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, BigInteger.ZERO)); + try { + ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(-7l)); + Assert.fail("Expecting IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected behavior + } + + BigInteger bigOne = + new BigInteger("1543786922199448028351389769265814882661837148" + + "4763915343722775611762713982220306372888519211" + + "560905579993523402015636025177602059044911261"); + Assert.assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, 103)); + Assert.assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, 103l)); + Assert.assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(103l))); + + } + + @Test(expected=NumbersArithmeticException.class) + public void testPowIntOverflow() { + ArithmeticUtils.pow(21, 8); + } + + @Test + public void testPowInt() { + final int base = 21; + + Assert.assertEquals(85766121L, + ArithmeticUtils.pow(base, 6)); + Assert.assertEquals(1801088541L, + ArithmeticUtils.pow(base, 7)); + } + + @Test(expected=NumbersArithmeticException.class) + public void testPowNegativeIntOverflow() { + ArithmeticUtils.pow(-21, 8); + } + + @Test + public void testPowNegativeInt() { + final int base = -21; + + Assert.assertEquals(85766121, + ArithmeticUtils.pow(base, 6)); + Assert.assertEquals(-1801088541, + ArithmeticUtils.pow(base, 7)); + } + + @Test + public void testPowMinusOneInt() { + final int base = -1; + for (int i = 0; i < 100; i++) { + final int pow = ArithmeticUtils.pow(base, i); + Assert.assertEquals("i: " + i, i % 2 == 0 ? 1 : -1, pow); + } + } + + @Test + public void testPowOneInt() { + final int base = 1; + for (int i = 0; i < 100; i++) { + final int pow = ArithmeticUtils.pow(base, i); + Assert.assertEquals("i: " + i, 1, pow); + } + } + + @Test(expected=NumbersArithmeticException.class) + public void testPowLongOverflow() { + ArithmeticUtils.pow(21, 15); + } + + @Test + public void testPowLong() { + final long base = 21; + + Assert.assertEquals(154472377739119461L, + ArithmeticUtils.pow(base, 13)); + Assert.assertEquals(3243919932521508681L, + ArithmeticUtils.pow(base, 14)); + } + + @Test(expected=NumbersArithmeticException.class) + public void testPowNegativeLongOverflow() { + ArithmeticUtils.pow(-21L, 15); + } + + @Test + public void testPowNegativeLong() { + final long base = -21; + + Assert.assertEquals(-154472377739119461L, + ArithmeticUtils.pow(base, 13)); + Assert.assertEquals(3243919932521508681L, + ArithmeticUtils.pow(base, 14)); + } + + @Test + public void testPowMinusOneLong() { + final long base = -1; + for (int i = 0; i < 100; i++) { + final long pow = ArithmeticUtils.pow(base, i); + Assert.assertEquals("i: " + i, i % 2 == 0 ? 1 : -1, pow); + } + } + + @Test + public void testPowOneLong() { + final long base = 1; + for (int i = 0; i < 100; i++) { + final long pow = ArithmeticUtils.pow(base, i); + Assert.assertEquals("i: " + i, 1, pow); + } + } + + @Test + public void testIsPowerOfTwo() { + final int n = 1025; + final boolean[] expected = new boolean[n]; + Arrays.fill(expected, false); + for (int i = 1; i < expected.length; i *= 2) { + expected[i] = true; + } + for (int i = 0; i < expected.length; i++) { + final boolean actual = ArithmeticUtils.isPowerOfTwo(i); + Assert.assertTrue(Integer.toString(i), actual == expected[i]); + } + } + + private void testAddAndCheckLongFailure(long a, long b) { + try { + ArithmeticUtils.addAndCheck(a, b); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException ex) { + // success + } + } + + private void testMulAndCheckLongFailure(long a, long b) { + try { + ArithmeticUtils.mulAndCheck(a, b); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException ex) { + // success + } + } + + private void testSubAndCheckLongFailure(long a, long b) { + try { + ArithmeticUtils.subAndCheck(a, b); + Assert.fail("Expecting ArithmeticException"); + } catch (NumbersArithmeticException ex) { + // success + } + } + + /** + * Testing helper method. + * @return an array of int numbers containing corner cases:<ul> + * <li>values near the beginning of int range,</li> + * <li>values near the end of int range,</li> + * <li>values near zero</li> + * <li>and some randomly distributed values.</li> + * </ul> + */ + private static int[] getIntSpecialCases() { + int ints[] = new int[100]; + int i = 0; + ints[i++] = Integer.MAX_VALUE; + ints[i++] = Integer.MAX_VALUE - 1; + ints[i++] = 100; + ints[i++] = 101; + ints[i++] = 102; + ints[i++] = 300; + ints[i++] = 567; + for (int j = 0; j < 20; j++) { + ints[i++] = j; + } + for (int j = i - 1; j >= 0; j--) { + ints[i++] = ints[j] > 0 ? -ints[j] : Integer.MIN_VALUE; + } + java.util.Random r = new java.util.Random(System.nanoTime()); + for (; i < ints.length;) { + ints[i++] = r.nextInt(); + } + return ints; + } + + /** + * Testing helper method. + * @return an array of long numbers containing corner cases:<ul> + * <li>values near the beginning of long range,</li> + * <li>values near the end of long range,</li> + * <li>values near the beginning of int range,</li> + * <li>values near the end of int range,</li> + * <li>values near zero</li> + * <li>and some randomly distributed values.</li> + * </ul> + */ + private static long[] getLongSpecialCases() { + long longs[] = new long[100]; + int i = 0; + longs[i++] = Long.MAX_VALUE; + longs[i++] = Long.MAX_VALUE - 1L; + longs[i++] = (long) Integer.MAX_VALUE + 1L; + longs[i++] = Integer.MAX_VALUE; + longs[i++] = Integer.MAX_VALUE - 1; + longs[i++] = 100L; + longs[i++] = 101L; + longs[i++] = 102L; + longs[i++] = 300L; + longs[i++] = 567L; + for (int j = 0; j < 20; j++) { + longs[i++] = j; + } + for (int j = i - 1; j >= 0; j--) { + longs[i++] = longs[j] > 0L ? -longs[j] : Long.MIN_VALUE; + } + java.util.Random r = new java.util.Random(System.nanoTime()); + for (; i < longs.length;) { + longs[i++] = r.nextLong(); + } + return longs; + } + + private static long toUnsignedLong(int number) { + return number < 0 ? 0x100000000L + (long)number : (long)number; + } + + private static int remainderUnsignedExpected(int dividend, int divisor) { + return (int)remainderUnsignedExpected(toUnsignedLong(dividend), toUnsignedLong(divisor)); + } + + private static int divideUnsignedExpected(int dividend, int divisor) { + return (int)divideUnsignedExpected(toUnsignedLong(dividend), toUnsignedLong(divisor)); + } + + private static BigInteger toUnsignedBigInteger(long number) { + return number < 0L ? BigInteger.ONE.shiftLeft(64).add(BigInteger.valueOf(number)) : BigInteger.valueOf(number); + } + + private static long remainderUnsignedExpected(long dividend, long divisor) { + return toUnsignedBigInteger(dividend).remainder(toUnsignedBigInteger(divisor)).longValue(); + } + + private static long divideUnsignedExpected(long dividend, long divisor) { + return toUnsignedBigInteger(dividend).divide(toUnsignedBigInteger(divisor)).longValue(); + } + + @Test(timeout=5000L) + public void testRemainderUnsignedInt() { + Assert.assertEquals(36, ArithmeticUtils.remainderUnsigned(-2147479015, 63)); + Assert.assertEquals(6, ArithmeticUtils.remainderUnsigned(-2147479015, 25)); + } + + @Test(timeout=5000L) + public void testRemainderUnsignedIntSpecialCases() { + int ints[] = getIntSpecialCases(); + for (int dividend : ints) { + for (int divisor : ints) { + if (divisor == 0) { + try { + ArithmeticUtils.remainderUnsigned(dividend, divisor); + Assert.fail("Should have failed with ArithmeticException: division by zero"); + } catch (ArithmeticException e) { + // Success. + } + } else { + Assert.assertEquals(remainderUnsignedExpected(dividend, divisor), ArithmeticUtils.remainderUnsigned(dividend, divisor)); + } + } + } + } + + @Test(timeout=5000L) + public void testRemainderUnsignedLong() { + Assert.assertEquals(48L, ArithmeticUtils.remainderUnsigned(-2147479015L, 63L)); + } + + @Test//(timeout=5000L) + public void testRemainderUnsignedLongSpecialCases() { + long longs[] = getLongSpecialCases(); + for (long dividend : longs) { + for (long divisor : longs) { + if (divisor == 0L) { + try { + ArithmeticUtils.remainderUnsigned(dividend, divisor); + Assert.fail("Should have failed with ArithmeticException: division by zero"); + } catch (ArithmeticException e) { + // Success. + } + } else { + Assert.assertEquals(remainderUnsignedExpected(dividend, divisor), ArithmeticUtils.remainderUnsigned(dividend, divisor)); + } + } + } + } + + @Test(timeout=5000L) + public void testDivideUnsignedInt() { + Assert.assertEquals(34087115, ArithmeticUtils.divideUnsigned(-2147479015, 63)); + Assert.assertEquals(85899531, ArithmeticUtils.divideUnsigned(-2147479015, 25)); + Assert.assertEquals(2147483646, ArithmeticUtils.divideUnsigned(-3, 2)); + Assert.assertEquals(330382098, ArithmeticUtils.divideUnsigned(-16, 13)); + Assert.assertEquals(306783377, ArithmeticUtils.divideUnsigned(-16, 14)); + Assert.assertEquals(2, ArithmeticUtils.divideUnsigned(-1, 2147483647)); + Assert.assertEquals(2, ArithmeticUtils.divideUnsigned(-2, 2147483647)); + Assert.assertEquals(1, ArithmeticUtils.divideUnsigned(-3, 2147483647)); + Assert.assertEquals(1, ArithmeticUtils.divideUnsigned(-16, 2147483647)); + Assert.assertEquals(1, ArithmeticUtils.divideUnsigned(-16, 2147483646)); + } + + @Test(timeout=5000L) + public void testDivideUnsignedIntSpecialCases() { + int ints[] = getIntSpecialCases(); + for (int dividend : ints) { + for (int divisor : ints) { + if (divisor == 0) { + try { + ArithmeticUtils.divideUnsigned(dividend, divisor); + Assert.fail("Should have failed with ArithmeticException: division by zero"); + } catch (ArithmeticException e) { + // Success. + } + } else { + Assert.assertEquals(divideUnsignedExpected(dividend, divisor), ArithmeticUtils.divideUnsigned(dividend, divisor)); + } + } + } + } + + @Test(timeout=5000L) + public void testDivideUnsignedLong() { + Assert.assertEquals(292805461453366231L, ArithmeticUtils.divideUnsigned(-2147479015L, 63L)); + } + + @Test(timeout=5000L) + public void testDivideUnsignedLongSpecialCases() { + long longs[] = getLongSpecialCases(); + for (long dividend : longs) { + for (long divisor : longs) { + if (divisor == 0L) { + try { + ArithmeticUtils.divideUnsigned(dividend, divisor); + Assert.fail("Should have failed with ArithmeticException: division by zero"); + } catch (ArithmeticException e) { + // Success. + } + } else { + Assert.assertEquals(divideUnsignedExpected(dividend, divisor), ArithmeticUtils.divideUnsigned(dividend, divisor)); + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/aaef6f7a/commons-numbers-fraction/LICENSE.txt ---------------------------------------------------------------------- diff --git a/commons-numbers-fraction/LICENSE.txt b/commons-numbers-fraction/LICENSE.txt new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/commons-numbers-fraction/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/aaef6f7a/commons-numbers-fraction/NOTICE.txt ---------------------------------------------------------------------- diff --git a/commons-numbers-fraction/NOTICE.txt b/commons-numbers-fraction/NOTICE.txt new file mode 100644 index 0000000..ea6ae07 --- /dev/null +++ b/commons-numbers-fraction/NOTICE.txt @@ -0,0 +1,6 @@ +Apache Commons Numbers +Copyright 2001-2016 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/aaef6f7a/commons-numbers-fraction/README.md ---------------------------------------------------------------------- diff --git a/commons-numbers-fraction/README.md b/commons-numbers-fraction/README.md new file mode 100644 index 0000000..0701bed --- /dev/null +++ b/commons-numbers-fraction/README.md @@ -0,0 +1,98 @@ +<!--- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!--- + +======================================================================+ + |**** ****| + |**** THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN ****| + |**** DO NOT EDIT DIRECTLY ****| + |**** ****| + +======================================================================+ + | TEMPLATE FILE: readme-md-template.md | + | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates | + +======================================================================+ + | | + | 1) Re-generate using: mvn commons:readme-md | + | | + | 2) Set the following properties in the component's pom: | + | - commons.componentid (required, alphabetic, lower case) | + | - commons.release.version (required) | + | | + | 3) Example Properties | + | | + | <properties> | + | <commons.componentid>math</commons.componentid> | + | <commons.release.version>1.2</commons.release.version> | + | </properties> | + | | + +======================================================================+ +---> +Apache Commons Numbers Core +=================== + +Basic utilities. + +Documentation +------------- + +More information can be found on the [homepage](https://commons.apache.org/proper/commons-numbers). +The [JavaDoc](https://commons.apache.org/proper/commons-numbers/javadocs/api-release) can be browsed. +Questions related to the usage of Apache Commons Numbers Core should be posted to the [user mailing list][ml]. + +Where can I get the latest release? +----------------------------------- +You can download source and binaries from our [download page](https://commons.apache.org/proper/commons-numbers/download_numbers.cgi). + +Alternatively you can pull it from the central Maven repositories: + +```xml +<dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-numbers-core</artifactId> + <version>1.0</version> +</dependency> +``` + +Contributing +------------ + +We accept PRs via github. The [developer mailing list][ml] is the main channel of communication for contributors. +There are some guidelines which will make applying PRs easier for us: ++ No tabs! Please use spaces for indentation. ++ Respect the code style. ++ Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change. ++ Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running ```mvn clean test```. + +If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas). +You can learn more about contributing via GitHub in our [contribution guidelines](CONTRIBUTING.md). + +License +------- +Code is under the [Apache Licence v2](https://www.apache.org/licenses/LICENSE-2.0.txt). + +Donations +--------- +You like Apache Commons Numbers Core? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support the development. + +Additional Resources +-------------------- + ++ [Apache Commons Homepage](https://commons.apache.org/) ++ [Apache Bugtracker (JIRA)](https://issues.apache.org/jira/) ++ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons) ++ #apachecommons IRC channel on freenode.org + +[ml]:https://commons.apache.org/mail-lists.html http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/aaef6f7a/commons-numbers-fraction/pom.xml ---------------------------------------------------------------------- diff --git a/commons-numbers-fraction/pom.xml b/commons-numbers-fraction/pom.xml new file mode 100644 index 0000000..42c3aa5 --- /dev/null +++ b/commons-numbers-fraction/pom.xml @@ -0,0 +1,58 @@ +<?xml version="1.0"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.commons</groupId> + <artifactId>commons-numbers-parent</artifactId> + <version>1.0-SNAPSHOT</version> + </parent> + + <groupId>org.apache.commons</groupId> + <artifactId>commons-numbers-fraction</artifactId> + <version>1.0-SNAPSHOT</version> + <name>Apache Commons Numbers Fraction</name> + + <description>Fraction utilities.</description> + + <properties> + <!-- This value must reflect the current name of the base package. --> + <commons.osgi.symbolicName>org.apache.commons.numbers.</commons.osgi.symbolicName> + <!-- OSGi --> + <commons.osgi.export>org.apache.commons.numbers.fraction</commons.osgi.export> + <!-- Workaround to avoid duplicating config files. --> + <numbers.parent.dir>${basedir}/..</numbers.parent.dir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-numbers-core</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-numbers-core</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + </dependencies> + +</project>