aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/ch/obermuhlner/math/big
diff options
context:
space:
mode:
authorTec <daniel112092@gmail.com>2020-07-19 11:30:33 +0200
committerTec <daniel112092@gmail.com>2020-07-19 11:30:33 +0200
commitfdb7847bcd0de41a3ff9dc96e5a51038a5e0f609 (patch)
treef9c5f040d34f86fe630170743c183c9bb46a087e /src/main/java/ch/obermuhlner/math/big
parent11e50eb56f6750d6bdfe15b986eef55e27452211 (diff)
downloadGT5-Unofficial-fdb7847bcd0de41a3ff9dc96e5a51038a5e0f609.tar.gz
GT5-Unofficial-fdb7847bcd0de41a3ff9dc96e5a51038a5e0f609.tar.bz2
GT5-Unofficial-fdb7847bcd0de41a3ff9dc96e5a51038a5e0f609.zip
Update decay logic
Diffstat (limited to 'src/main/java/ch/obermuhlner/math/big')
-rw-r--r--src/main/java/ch/obermuhlner/math/big/BigComplex.java556
-rw-r--r--src/main/java/ch/obermuhlner/math/big/BigComplexMath.java413
-rw-r--r--src/main/java/ch/obermuhlner/math/big/BigDecimalMath.java1671
-rw-r--r--src/main/java/ch/obermuhlner/math/big/BigFloat.java1947
-rw-r--r--src/main/java/ch/obermuhlner/math/big/BigRational.java1103
-rw-r--r--src/main/java/ch/obermuhlner/math/big/DefaultBigDecimalMath.java736
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/AsinCalculator.java46
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/AtanhCalculator.java40
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/CosCalculator.java48
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/CoshCalculator.java43
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/ExpCalculator.java42
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/PowerIterator.java28
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/PowerNIterator.java33
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNIterator.java33
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNMinusOneIterator.java35
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNPlusOneIterator.java33
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/SeriesCalculator.java127
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/SinCalculator.java49
-rw-r--r--src/main/java/ch/obermuhlner/math/big/internal/SinhCalculator.java44
-rw-r--r--src/main/java/ch/obermuhlner/math/big/stream/BigDecimalStream.java219
-rw-r--r--src/main/java/ch/obermuhlner/math/big/stream/BigFloatStream.java214
21 files changed, 0 insertions, 7460 deletions
diff --git a/src/main/java/ch/obermuhlner/math/big/BigComplex.java b/src/main/java/ch/obermuhlner/math/big/BigComplex.java
deleted file mode 100644
index a4620ff53b..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/BigComplex.java
+++ /dev/null
@@ -1,556 +0,0 @@
-package ch.obermuhlner.math.big;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.util.Objects;
-
-/**
- * Represents a complex number consisting of a real and an imaginary {@link BigDecimal} part in the form {@code a + bi}.
- *
- * <p>It generally follows the design of {@link BigDecimal} with some convenience improvements like overloaded operator methods.</p>
- *
- * <p>The biggest difference to {@link BigDecimal} is that {@link BigComplex#equals(Object) BigComplex.equals(Object)} implements the <strong>mathematical</strong> equality
- * and <strong>not</strong> the strict technical equality.
- * This was a difficult decision because it means that {@code BigComplex} behaves slightly different than {@link BigDecimal}
- * but considering that the strange equality of {@link BigDecimal} is a major source of bugs we
- * decided it was worth the slight inconsistency.
- * If you need the strict equality use {@link BigComplex#strictEquals(Object)}`.</p>
- *
- * <p>This class is immutable and therefore inherently thread safe.</p>
- */
-public final class BigComplex {
-
- /**
- * Zero represented as complex number.
- */
- public static final BigComplex ZERO = new BigComplex(BigDecimal.ZERO, BigDecimal.ZERO);
-
- /**
- * Real 1 represented as complex number.
- */
- public static final BigComplex ONE = new BigComplex(BigDecimal.ONE, BigDecimal.ZERO);
-
- /**
- * Imaginary 1 represented as complex number.
- */
- public static final BigComplex I = new BigComplex(BigDecimal.ZERO, BigDecimal.ONE);
-
- /**
- * The real {@link BigDecimal} part of this complex number.
- */
- public final BigDecimal re;
-
- /**
- * The imaginary {@link BigDecimal} part of this complex number.
- */
- public final BigDecimal im;
-
- private BigComplex(BigDecimal re, BigDecimal im) {
- this.re = re;
- this.im = im;
- }
-
- /**
- * Calculates the addition of the given complex value to this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the {@link BigComplex} value to add
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex add(BigComplex value) {
- return valueOf(
- re.add(value.re),
- im.add(value.im));
- }
-
- /**
- * Calculates the addition of the given complex value to this complex number using the specified {@link MathContext}.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the {@link BigComplex} value to add
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex add(BigComplex value, MathContext mathContext) {
- return valueOf(
- re.add(value.re, mathContext),
- im.add(value.im, mathContext));
- }
-
- /**
- * Calculates the addition of the given real {@link BigDecimal} value to this complex number using the specified {@link MathContext}.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the real {@link BigDecimal} value to add
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex add(BigDecimal value, MathContext mathContext) {
- return valueOf(
- re.add(value, mathContext),
- im);
- }
-
- /**
- * Calculates the addition of the given real {@link BigDecimal} value to this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the real {@link BigDecimal} value to add
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex add(BigDecimal value) {
- return valueOf(
- re.add(value),
- im);
- }
-
- /**
- * Calculates the addition of the given real {@code double} value to this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the real {@code double} value to add
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex add(double value) {
- return add(BigDecimal.valueOf(value));
- }
-
- /**
- * Calculates the subtraction of the given complex value from this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the {@link BigComplex} value to subtract
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex subtract(BigComplex value) {
- return valueOf(
- re.subtract(value.re),
- im.subtract(value.im));
- }
-
- /**
- * Calculates the subtraction of the given complex value from this complex number using the specified {@link MathContext}.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the {@link BigComplex} value to subtract
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex subtract(BigComplex value, MathContext mathContext) {
- return valueOf(
- re.subtract(value.re, mathContext),
- im.subtract(value.im, mathContext));
- }
-
- /**
- * Calculates the subtraction of the given real {@link BigDecimal} value from this complex number using the specified {@link MathContext}.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the real {@link BigDecimal} value to add
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex subtract(BigDecimal value, MathContext mathContext) {
- return valueOf(
- re.subtract(value, mathContext),
- im);
- }
-
- /**
- * Calculates the subtraction of the given real {@link BigDecimal} value from this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the real {@link BigDecimal} value to subtract
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex subtract(BigDecimal value) {
- return valueOf(
- re.subtract(value),
- im);
- }
-
- /**
- * Calculates the subtraction of the given real {@code double} value from this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the real {@code double} value to subtract
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex subtract(double value) {
- return subtract(BigDecimal.valueOf(value));
- }
-
- /**
- * Calculates the multiplication of the given complex value to this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the {@link BigComplex} value to multiply
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex multiply(BigComplex value) {
- return valueOf(
- re.multiply(value.re).subtract(im.multiply(value.im)),
- re.multiply(value.im).add(im.multiply(value.re)));
- }
-
- /**
- * Calculates the multiplication of the given complex value with this complex number using the specified {@link MathContext}.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the {@link BigComplex} value to multiply
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex multiply(BigComplex value, MathContext mathContext) {
- return valueOf(
- re.multiply(value.re, mathContext).subtract(im.multiply(value.im, mathContext), mathContext),
- re.multiply(value.im, mathContext).add(im.multiply(value.re, mathContext), mathContext));
- }
-
- /**
- * Calculates the multiplication of the given real {@link BigDecimal} value with this complex number using the specified {@link MathContext}.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the real {@link BigDecimal} value to multiply
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex multiply(BigDecimal value, MathContext mathContext) {
- return valueOf(
- re.multiply(value, mathContext),
- im.multiply(value, mathContext));
- }
-
- /**
- * Calculates the multiplication of the given real {@link BigDecimal} value with this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the real {@link BigDecimal} value to multiply
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex multiply(BigDecimal value) {
- return valueOf(
- re.multiply(value),
- im.multiply(value));
- }
-
- /**
- * Calculates the multiplication of the given real {@code double} value with this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the real {@code double} value to multiply
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex multiply(double value) {
- return multiply(BigDecimal.valueOf(value));
- }
-
- /**
- * Calculates this complex number divided by the given complex value using the specified {@link MathContext}.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the {@link BigComplex} value to divide by
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex divide(BigComplex value, MathContext mathContext) {
- return multiply(value.reciprocal(mathContext), mathContext);
- }
-
- /**
- * Calculates this complex number divided by the given real {@link BigDecimal} value using the specified {@link MathContext}.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the {@link BigDecimal} value to divide by
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex divide(BigDecimal value, MathContext mathContext) {
- return valueOf(
- re.divide(value, mathContext),
- im.divide(value, mathContext));
- }
-
- /**
- * Calculates this complex number divided by the given real {@code double} value using the specified {@link MathContext}.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param value the {@code double} value to divide by
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex divide(double value, MathContext mathContext) {
- return divide(BigDecimal.valueOf(value), mathContext);
- }
-
- /**
- * Calculates the reciprocal of this complex number using the specified {@link MathContext}.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex reciprocal(MathContext mathContext) {
- BigDecimal scale = absSquare(mathContext);
- return valueOf(
- re.divide(scale, mathContext),
- im.negate().divide(scale, mathContext));
- }
-
- /**
- * Calculates the conjugate {@code a - bi} of this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex conjugate() {
- return valueOf(re, im.negate());
- }
-
- /**
- * Calculates the negation {@code -a - bi} of this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @return the calculated {@link BigComplex} result
- */
- public BigComplex negate() {
- return valueOf(re.negate(), im.negate());
- }
-
- /**
- * Calculates the absolute value (also known as magnitude, length or radius) of this complex number.
- *
- * <p>This method is slower than {@link #absSquare(MathContext)} since it needs to calculate the {@link BigDecimalMath#sqrt(BigDecimal, MathContext)}.</p>
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- * @see #absSquare(MathContext)
- */
- public BigDecimal abs(MathContext mathContext) {
- return BigDecimalMath.sqrt(absSquare(mathContext), mathContext);
- }
-
- /**
- * Calculates the angle in radians (also known as argument) of this complex number.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- */
- public BigDecimal angle(MathContext mathContext) {
- return BigDecimalMath.atan2(im, re, mathContext);
- }
-
- /**
- * Calculates the square of the absolute value of this complex number.
- *
- * <p>This method is faster than {@link #abs(MathContext)} since it does not need to calculate the {@link BigDecimalMath#sqrt(BigDecimal, MathContext)}.</p>
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- * @see #abs(MathContext)
- */
- public BigDecimal absSquare(MathContext mathContext) {
- return re.multiply(re, mathContext).add(im.multiply(im, mathContext), mathContext);
- }
-
- /**
- * Returns whether this complex number only has a real part (the imaginary part is 0).
- *
- * @return {@code true} if this complex number only has a real part, {@code false} if the imaginary part is not 0
- */
- public boolean isReal() {
- return im.signum() == 0;
- }
-
- /**
- * Returns the real part of this complex number as {@link BigComplex} number.
- *
- * @return the real part as as {@link BigComplex} number
- */
- public BigComplex re() {
- return valueOf(re, BigDecimal.ZERO);
- }
-
- /**
- * Returns the imaginary part of this complex number as {@link BigComplex} number.
- *
- * @return the imaginary part as as {@link BigComplex} number
- */
- public BigComplex im() {
- return valueOf(BigDecimal.ZERO, im);
- }
-
- /**
- * Returns this complex nuber rounded to the specified precision.
- *
- * <p>This methods <strong>does not</strong> modify this instance.</p>
- *
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the rounded {@link BigComplex} result
- */
- public BigComplex round(MathContext mathContext) {
- return valueOf(re.round(mathContext), im.round(mathContext));
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(re, im);
- }
-
- /**
- * {@inheritDoc}
- *
- * <p>Contrary to {@link BigDecimal#equals(Object)} this method implements <strong>mathematical</strong> equality
- * (by calling {@link BigDecimal#compareTo(BigDecimal)} on the real and imaginary parts)
- * instead of strict equality.</p>
- *
- * @see #strictEquals(Object)
- */
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- BigComplex other = (BigComplex) obj;
-
- return re.compareTo(other.re) == 0 && im.compareTo(other.im) == 0;
- }
-
- /**
- * Returns whether the real and imaginary parts of this complex number are strictly equal.
- *
- * <p>This method uses the strict equality as defined by {@link BigDecimal#equals(Object)} on the real and imaginary parts.</p>
- * <p>Please note that {@link #equals(Object) BigComplex.equals(Object)} implements <strong>mathematical</strong> equality instead
- * (by calling {@link BigDecimal#compareTo(BigDecimal) on the real and imaginary parts}).</p>
- *
- * @param obj the object to compare for strict equality
- * @return {@code true} if the specified object is strictly equal to this complex number
- * @see #equals(Object)
- */
- public boolean strictEquals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- BigComplex other = (BigComplex) obj;
-
- return re.equals(other.re) && im.equals(other.im);
- }
-
- @Override
- public String toString() {
- if (im.signum() >= 0) {
- return "(" + re + " + " + im + " i)";
- } else {
- return "(" + re + " - " + im.negate() + " i)";
- }
- }
-
- /**
- * Returns a complex number with the specified real {@link BigDecimal} part.
- *
- * @param real the real {@link BigDecimal} part
- * @return the complex number
- */
- public static BigComplex valueOf(BigDecimal real) {
- return valueOf(real, BigDecimal.ZERO);
- }
-
- /**
- * Returns a complex number with the specified real {@code double} part.
- *
- * @param real the real {@code double} part
- * @return the complex number
- */
- public static BigComplex valueOf(double real) {
- return valueOf(BigDecimal.valueOf(real), BigDecimal.ZERO);
- }
-
- /**
- * Returns a complex number with the specified real and imaginary {@code double} parts.
- *
- * @param real the real {@code double} part
- * @param imaginary the imaginary {@code double} part
- * @return the complex number
- */
- public static BigComplex valueOf(double real, double imaginary) {
- return valueOf(BigDecimal.valueOf(real), BigDecimal.valueOf(imaginary));
- }
-
- /**
- * Returns a complex number with the specified real and imaginary {@link BigDecimal} parts.
- *
- * @param real the real {@link BigDecimal} part
- * @param imaginary the imaginary {@link BigDecimal} part
- * @return the complex number
- */
- public static BigComplex valueOf(BigDecimal real, BigDecimal imaginary) {
- if (real.signum() == 0) {
- if (imaginary.signum() == 0) {
- return ZERO;
- }
- if (imaginary.compareTo(BigDecimal.ONE) == 0) {
- return I;
- }
- }
- if (imaginary.signum() == 0 && real.compareTo(BigDecimal.ONE) == 0) {
- return ONE;
- }
-
- return new BigComplex(real, imaginary);
- }
-
- /**
- * Returns a complex number with the specified polar {@link BigDecimal} radius and angle using the specified {@link MathContext}.
- *
- * @param radius the {@link BigDecimal} radius of the polar representation
- * @param angle the {@link BigDecimal} angle in radians of the polar representation
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the complex number
- */
- public static BigComplex valueOfPolar(BigDecimal radius, BigDecimal angle, MathContext mathContext) {
- if (radius.signum() == 0) {
- return ZERO;
- }
-
- return valueOf(
- radius.multiply(BigDecimalMath.cos(angle, mathContext), mathContext),
- radius.multiply(BigDecimalMath.sin(angle, mathContext), mathContext));
- }
-
- public static BigComplex valueOfPolar(double radius, double angle, MathContext mathContext) {
- return valueOfPolar(BigDecimal.valueOf(radius), BigDecimal.valueOf(angle), mathContext);
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/BigComplexMath.java b/src/main/java/ch/obermuhlner/math/big/BigComplexMath.java
deleted file mode 100644
index a73d9bccdd..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/BigComplexMath.java
+++ /dev/null
@@ -1,413 +0,0 @@
-package ch.obermuhlner.math.big;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.util.List;
-
-import static ch.obermuhlner.math.big.BigComplex.I;
-
-/**
- * Provides advanced functions operating on {@link BigComplex}s.
- */
-public class BigComplexMath {
-
- private static final BigDecimal TWO = BigDecimal.valueOf(2);
-
- /**
- * Calculates the reciprocal of the given complex number using the specified {@link MathContext}.
- *
- * @param x the complex number to calculate the reciprocal
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- * @see BigComplex#reciprocal(MathContext)
- */
- public static BigComplex reciprocal(BigComplex x, MathContext mathContext) {
- return x.reciprocal(mathContext);
- }
-
- /**
- * Calculates the conjugate of the given complex number using the specified {@link MathContext}.
- *
- * @param x the complex number to calculate the conjugate
- * @return the calculated {@link BigComplex} result
- * @see BigComplex#conjugate()
- */
- public static BigComplex conjugate(BigComplex x) {
- return x.conjugate();
- }
-
- /**
- * Calculates the absolute value (also known as magnitude, length or radius) of the given complex number using the specified {@link MathContext}.
- *
- * @param x the complex number to calculate the absolute value
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- * @see BigComplex#abs(MathContext)
- */
- public static BigDecimal abs(BigComplex x, MathContext mathContext) {
- return x.abs(mathContext);
- }
-
- /**
- * Calculates the square of the absolute value (also known as magnitude, length or radius) of the given complex number using the specified {@link MathContext}.
- *
- * @param x the complex number to calculate the square of the absolute value
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} result
- * @see BigComplex#absSquare(MathContext)
- */
- public static BigDecimal absSquare(BigComplex x, MathContext mathContext) {
- return x.absSquare(mathContext);
- }
-
- /**
- * Calculates the angle in radians of the given complex number using the specified {@link MathContext}.
- *
- * @param x the complex number to calculate the angle
- * @param mathContext the {@link MathContext} used to calculate the result
- * @return the calculated {@link BigComplex} angle in radians
- * @see BigComplex#angle(MathContext)
- */
- public static BigDecimal angle(BigComplex x, MathContext mathContext) {
- return x.angle(mathContext);
- }
-
- /**
- * Calculates the factorial of the specified {@link BigComplex}.
- *
- * <p>This implementation uses
- * <a href="https://en.wikipedia.org/wiki/Spouge%27s_approximation">Spouge's approximation</a>
- * to calculate the factorial for non-integer values.</p>
- *
- * <p>This involves calculating a series of constants that depend on the desired precision.
- * Since this constant calculation is quite expensive (especially for higher precisions),
- * the constants for a specific precision will be cached
- * and subsequent calls to this method with the same precision will be much faster.</p>
- *
- * <p>It is therefore recommended to do one call to this method with the standard precision of your application during the startup phase
- * and to avoid calling it with many different precisions.</p>
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Factorial#Extension_of_factorial_to_non-integer_values_of_argument">Wikipedia: Factorial - Extension of factorial to non-integer values of argument</a></p>
- *
- * @param x the {@link BigComplex}
- * @param mathContext the {@link MathContext} used for the result
- * @return the factorial {@link BigComplex}
- * @throws ArithmeticException if x is a negative integer value (-1, -2, -3, ...)
- * @see BigDecimalMath#factorial(BigDecimal, MathContext)
- * @see #gamma(BigComplex, MathContext)
- */
- public static BigComplex factorial(BigComplex x, MathContext mathContext) {
- if (x.isReal() && BigDecimalMath.isIntValue(x.re)) {
- return BigComplex.valueOf(BigDecimalMath.factorial(x.re.intValueExact()).round(mathContext));
- }
-
- // https://en.wikipedia.org/wiki/Spouge%27s_approximation
- MathContext mc = new MathContext(mathContext.getPrecision() * 2, mathContext.getRoundingMode());
-
- int a = mathContext.getPrecision() * 13 / 10;
- List<BigDecimal> constants = BigDecimalMath.getSpougeFactorialConstants(a);
-
- BigDecimal bigA = BigDecimal.valueOf(a);
-
- boolean negative = false;
- BigComplex factor = BigComplex.valueOf(constants.get(0));
- for (int k = 1; k < a; k++) {
- BigDecimal bigK = BigDecimal.valueOf(k);
- factor = factor.add(BigComplex.valueOf(constants.get(k)).divide(x.add(bigK), mc), mc);
- negative = !negative;
- }
-
- BigComplex result = pow(x.add(bigA, mc), x.add(BigDecimal.valueOf(0.5), mc), mc);
- result = result.multiply(exp(x.negate().subtract(bigA, mc), mc), mc);
- result = result.multiply(factor, mc);
-
- return result.round(mathContext);
- }
-
- /**
- * Calculates the gamma function of the specified {@link BigComplex}.
- *
- * <p>This implementation uses {@link #factorial(BigComplex, MathContext)} internally,
- * therefore the performance implications described there apply also for this method.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Gamma_function">Wikipedia: Gamma function</a></p>
- *
- * @param x the {@link BigComplex}
- * @param mathContext the {@link MathContext} used for the result
- * @return the gamma {@link BigComplex}
- * @throws ArithmeticException if x-1 is a negative integer value (-1, -2, -3, ...)
- * @see BigDecimalMath#gamma(BigDecimal, MathContext)
- * @see #factorial(BigComplex, MathContext)
- */
- public static BigComplex gamma(BigComplex x, MathContext mathContext) {
- return factorial(x.subtract(BigComplex.ONE), mathContext);
- }
-
-
- /**
- * Calculates the natural exponent of {@link BigComplex} x (e<sup>x</sup>) in the complex domain.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Exponential_function#Complex_plane">Wikipedia: Exponent (Complex plane)</a></p>
- *
- * @param x the {@link BigComplex} to calculate the exponent for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated exponent {@link BigComplex} with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex exp(BigComplex x, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- BigDecimal expRe = BigDecimalMath.exp(x.re, mc);
- return BigComplex.valueOf(
- expRe.multiply(BigDecimalMath.cos(x.im, mc), mc).round(mathContext),
- expRe.multiply(BigDecimalMath.sin(x.im, mc), mc)).round(mathContext);
- }
-
- /**
- * Calculates the sine (sinus) of {@link BigComplex} x in the complex domain.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Sine#Sine_with_a_complex_argument">Wikipedia: Sine (Sine with a complex argument)</a></p>
- *
- * @param x the {@link BigComplex} to calculate the sine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated sine {@link BigComplex} with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex sin(BigComplex x, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- return BigComplex.valueOf(
- BigDecimalMath.sin(x.re, mc).multiply(BigDecimalMath.cosh(x.im, mc), mc).round(mathContext),
- BigDecimalMath.cos(x.re, mc).multiply(BigDecimalMath.sinh(x.im, mc), mc).round(mathContext));
- }
-
- /**
- * Calculates the cosine (cosinus) of {@link BigComplex} x in the complex domain.
- *
- * @param x the {@link BigComplex} to calculate the cosine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated cosine {@link BigComplex} with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex cos(BigComplex x, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- return BigComplex.valueOf(
- BigDecimalMath.cos(x.re, mc).multiply(BigDecimalMath.cosh(x.im, mc), mc).round(mathContext),
- BigDecimalMath.sin(x.re, mc).multiply(BigDecimalMath.sinh(x.im, mc), mc).negate().round(mathContext));
- }
-
- //
- // http://scipp.ucsc.edu/~haber/archives/physics116A10/arc_10.pdf
-
- /**
- * Calculates the tangens of {@link BigComplex} x in the complex domain.
- *
- * @param x the {@link BigComplex} to calculate the tangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated tangens {@link BigComplex} with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex tan(BigComplex x, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- return sin(x, mc).divide(cos(x, mc), mc).round(mathContext);
- }
-
- /**
- * Calculates the arc tangens (inverted tangens) of {@link BigComplex} x in the complex domain.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_complex_plane">Wikipedia: Inverse trigonometric functions (Extension to complex plane)</a></p>
- *
- * @param x the {@link BigComplex} to calculate the arc tangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc tangens {@link BigComplex} with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex atan(BigComplex x, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- return log(I.subtract(x, mc).divide(I.add(x, mc), mc), mc).divide(I, mc).divide(TWO, mc).round(mathContext);
- }
-
- /**
- * Calculates the arc cotangens (inverted cotangens) of {@link BigComplex} x in the complex domain.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_complex_plane">Wikipedia: Inverse trigonometric functions (Extension to complex plane)</a></p>
- *
- * @param x the {@link BigComplex} to calculate the arc cotangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc cotangens {@link BigComplex} with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex acot(BigComplex x, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- return log(x.add(I, mc).divide(x.subtract(I, mc), mc), mc).divide(I, mc).divide(TWO, mc).round(mathContext);
- }
-
- /**
- * Calculates the arc sine (inverted sine) of {@link BigComplex} x in the complex domain.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_complex_plane">Wikipedia: Inverse trigonometric functions (Extension to complex plane)</a></p>
- *
- * @param x the {@link BigComplex} to calculate the arc sine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc sine {@link BigComplex} with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex asin(BigComplex x, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- return I.negate().multiply(log(I.multiply(x, mc).add(sqrt(BigComplex.ONE.subtract(x.multiply(x, mc), mc), mc), mc), mc), mc).round(mathContext);
- }
-
- /**
- * Calculates the arc cosine (inverted cosine) of {@link BigComplex} x in the complex domain.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_complex_plane">Wikipedia: Inverse trigonometric functions (Extension to complex plane)</a></p>
- *
- * @param x the {@link BigComplex} to calculate the arc cosine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc cosine {@link BigComplex} with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex acos(BigComplex x, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- return I.negate().multiply(log(x.add(sqrt(x.multiply(x, mc).subtract(BigComplex.ONE, mc), mc), mc), mc), mc).round(mathContext);
- }
-
- /**
- * Calculates the square root of {@link BigComplex} x in the complex domain (sqrt x).
- *
- * <p>See <a href="https://en.wikipedia.org/wiki/Square_root#Square_root_of_an_imaginary_number">Wikipedia: Square root (Square root of an imaginary number)</a></p>
- *
- * @param x the {@link BigComplex} to calculate the square root for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated square root {@link BigComplex} with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex sqrt(BigComplex x, MathContext mathContext) {
- // https://math.stackexchange.com/questions/44406/how-do-i-get-the-square-root-of-a-complex-number
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- BigDecimal magnitude = x.abs(mc);
-
- BigComplex a = x.add(magnitude, mc);
- return a.divide(a.abs(mc), mc).multiply(BigDecimalMath.sqrt(magnitude, mc), mc).round(mathContext);
- }
-
- /**
- * Calculates the natural logarithm of {@link BigComplex} x in the complex domain.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Complex_logarithm">Wikipedia: Complex logarithm</a></p>
- *
- * @param x the {@link BigComplex} to calculate the natural logarithm for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated natural logarithm {@link BigComplex} with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex log(BigComplex x, MathContext mathContext) {
- // https://en.wikipedia.org/wiki/Complex_logarithm
- MathContext mc1 = new MathContext(mathContext.getPrecision() + 20, mathContext.getRoundingMode());
- MathContext mc2 = new MathContext(mathContext.getPrecision() + 5, mathContext.getRoundingMode());
-
- return BigComplex.valueOf(
- BigDecimalMath.log(x.abs(mc1), mc1).round(mathContext),
- x.angle(mc2)).round(mathContext);
- }
-
- /**
- * Calculates {@link BigComplex} x to the power of <code>long</code> y (x<sup>y</sup>).
- *
- * <p>The implementation tries to minimize the number of multiplications of {@link BigComplex x} (using squares whenever possible).</p>
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Exponentiation#Efficient_computation_with_integer_exponents">Wikipedia: Exponentiation - efficient computation</a></p>
- *
- * @param x the {@link BigComplex} value to take to the power
- * @param y the <code>long</code> value to serve as exponent
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated x to the power of y with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex pow(BigComplex x, long y, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 10, mathContext.getRoundingMode());
-
- if (y < 0) {
- return BigComplex.ONE.divide(pow(x, -y, mc), mc).round(mathContext);
- }
-
- BigComplex result = BigComplex.ONE;
- while (y > 0) {
- if ((y & 1) == 1) {
- // odd exponent -> multiply result with x
- result = result.multiply(x, mc);
- y -= 1;
- }
-
- if (y > 0) {
- // even exponent -> square x
- x = x.multiply(x, mc);
- }
-
- y >>= 1;
- }
-
- return result.round(mathContext);
- }
-
- /**
- * Calculates {@link BigComplex} x to the power of {@link BigDecimal} y (x<sup>y</sup>).
- *
- * @param x the {@link BigComplex} value to take to the power
- * @param y the {@link BigDecimal} value to serve as exponent
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated x to the power of y with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex pow(BigComplex x, BigDecimal y, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- BigDecimal angleTimesN = x.angle(mc).multiply(y, mc);
- return BigComplex.valueOf(
- BigDecimalMath.cos(angleTimesN, mc),
- BigDecimalMath.sin(angleTimesN, mc)).multiply(BigDecimalMath.pow(x.abs(mc), y, mc), mc).round(mathContext);
- }
-
- /**
- * Calculates {@link BigComplex} x to the power of {@link BigComplex} y (x<sup>y</sup>).
- *
- * @param x the {@link BigComplex} value to take to the power
- * @param y the {@link BigComplex} value to serve as exponent
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated x to the power of y with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex pow(BigComplex x, BigComplex y, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- return exp(y.multiply(log(x, mc), mc), mc).round(mathContext);
- }
-
- /**
- * Calculates the {@link BigDecimal} n'th root of {@link BigComplex} x (<sup>n</sup>sqrt x).
- *
- * <p>See <a href="http://en.wikipedia.org/wiki/Square_root">Wikipedia: Square root</a></p>
- * @param x the {@link BigComplex} value to calculate the n'th root
- * @param n the {@link BigDecimal} defining the root
- * @param mathContext the {@link MathContext} used for the result
- *
- * @return the calculated n'th root of x with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex root(BigComplex x, BigDecimal n, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- return pow(x, BigDecimal.ONE.divide(n, mc), mc).round(mathContext);
- }
-
- /**
- * Calculates the {@link BigComplex} n'th root of {@link BigComplex} x (<sup>n</sup>sqrt x).
- *
- * <p>See <a href="http://en.wikipedia.org/wiki/Square_root">Wikipedia: Square root</a></p>
- * @param x the {@link BigComplex} value to calculate the n'th root
- * @param n the {@link BigComplex} defining the root
- * @param mathContext the {@link MathContext} used for the result
- *
- * @return the calculated n'th root of x with the precision specified in the <code>mathContext</code>
- */
- public static BigComplex root(BigComplex x, BigComplex n, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- return pow(x, BigComplex.ONE.divide(n, mc), mc).round(mathContext);
- }
-
- // TODO add root() for the k'th root - https://math.stackexchange.com/questions/322481/principal-nth-root-of-a-complex-number
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/BigDecimalMath.java b/src/main/java/ch/obermuhlner/math/big/BigDecimalMath.java
deleted file mode 100644
index 552331f3b4..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/BigDecimalMath.java
+++ /dev/null
@@ -1,1671 +0,0 @@
-package ch.obermuhlner.math.big;
-
-import static java.math.BigDecimal.ONE;
-import static java.math.BigDecimal.TEN;
-import static java.math.BigDecimal.ZERO;
-import static java.math.BigDecimal.valueOf;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.util.*;
-
-import ch.obermuhlner.math.big.internal.AsinCalculator;
-import ch.obermuhlner.math.big.internal.CosCalculator;
-import ch.obermuhlner.math.big.internal.CoshCalculator;
-import ch.obermuhlner.math.big.internal.ExpCalculator;
-import ch.obermuhlner.math.big.internal.SinCalculator;
-import ch.obermuhlner.math.big.internal.SinhCalculator;
-
-/**
- * Provides advanced functions operating on {@link BigDecimal}s.
- */
-public class BigDecimalMath {
-
- private static final BigDecimal TWO = valueOf(2);
- private static final BigDecimal THREE = valueOf(3);
- private static final BigDecimal MINUS_ONE = valueOf(-1);
- private static final BigDecimal ONE_HALF = valueOf(0.5);
-
- private static final BigDecimal DOUBLE_MAX_VALUE = BigDecimal.valueOf(Double.MAX_VALUE);
-
- private static volatile BigDecimal log2Cache;
- private static final Object log2CacheLock = new Object();
-
- private static volatile BigDecimal log3Cache;
- private static final Object log3CacheLock = new Object();
-
- private static volatile BigDecimal log10Cache;
- private static final Object log10CacheLock = new Object();
-
- private static volatile BigDecimal piCache;
- private static final Object piCacheLock = new Object();
-
- private static volatile BigDecimal eCache;
- private static final Object eCacheLock = new Object();
-
- private static final BigDecimal ROUGHLY_TWO_PI = new BigDecimal("3.141592653589793").multiply(TWO);
-
- private static final int EXPECTED_INITIAL_PRECISION = 15;
-
- private static BigDecimal[] factorialCache = new BigDecimal[100];
-
- static {
- BigDecimal result = ONE;
- factorialCache[0] = result;
- for (int i = 1; i < factorialCache.length; i++) {
- result = result.multiply(valueOf(i));
- factorialCache[i] = result;
- }
- }
-
- private static final Map<Integer, List<BigDecimal>> spougeFactorialConstantsCache = new HashMap<>();
- private static final Object spougeFactorialConstantsCacheLock = new Object();
-
- private BigDecimalMath() {
- // prevent instances
- }
-
- /**
- * Creates a {@link BigDecimal} from the specified <code>String</code> representation.
- *
- * <p>This method is equivalent to the String constructor {@link BigDecimal#BigDecimal(String)}
- * but has been optimized for large strings (several thousand digits).</p>
- *
- * @param string the String representation
- * @return the created {@link BigDecimal}
- * @throws NumberFormatException if <code>string</code> is not a valid representation of a {@link BigDecimal}
- * @see BigDecimal#BigDecimal(String)
- * @see #toBigDecimal(String, MathContext)
- */
- public static BigDecimal toBigDecimal(String string) {
- return toBigDecimal(string, MathContext.UNLIMITED);
- }
-
- /**
- * Creates a {@link BigDecimal} from the specified <code>String</code> representation.
- *
- * <p>This method is equivalent to the String constructor {@link BigDecimal#BigDecimal(String, MathContext)}
- * but has been optimized for large strings (several thousand digits).</p>
- *
- * @param string the string representation
- * @param mathContext the {@link MathContext} used for the result
- * @return the created {@link BigDecimal}
- * @throws NumberFormatException if <code>string</code> is not a valid representation of a {@link BigDecimal}
- * @throws ArithmeticException if the result is inexact but the rounding mode is {@code UNNECESSARY}
- * @see BigDecimal#BigDecimal(String, MathContext)
- * @see #toBigDecimal(String)
- */
- public static BigDecimal toBigDecimal(String string, MathContext mathContext) {
- int len = string.length();
- if (len < 600) {
- return new BigDecimal(string, mathContext);
- }
-
- int splitLength = len / (len >= 10000 ? 8 : 5);
- return toBigDecimal(string, mathContext, splitLength);
- }
-
- static BigDecimal toBigDecimal(String string, MathContext mathContext, int splitLength) {
- int len = string.length();
-
- if (len < splitLength) {
- return new BigDecimal(string, mathContext);
- }
-
- char[] chars = string.toCharArray();
-
- boolean numberHasSign = false;
- boolean negative = false;
- int numberIndex = 0;
- int dotIndex = -1;
- int expIndex = -1;
- boolean expHasSign = false;
- int scale = 0;
-
- for (int i = 0; i < len; i++) {
- char c = chars[i];
- switch (c) {
- case '+':
- if (expIndex >= 0) {
- if (expHasSign) {
- throw new NumberFormatException("Multiple signs in exponent");
- }
- expHasSign = true;
- } else {
- if (numberHasSign) {
- throw new NumberFormatException("Multiple signs in number");
- }
- numberHasSign = true;
- numberIndex = i + 1;
- }
- break;
- case '-':
- if (expIndex >= 0) {
- if (expHasSign) {
- throw new NumberFormatException("Multiple signs in exponent");
- }
- expHasSign = true;
- } else {
- if (numberHasSign) {
- throw new NumberFormatException("Multiple signs in number");
- }
- numberHasSign = true;
- negative = true;
- numberIndex = i + 1;
- }
- break;
- case 'e':
- case 'E':
- if (expIndex >= 0) {
- throw new NumberFormatException("Multiple exponent markers");
- }
- expIndex = i;
- break;
- case '.':
- if (dotIndex >= 0) {
- throw new NumberFormatException("Multiple decimal points");
- }
- dotIndex = i;
- break;
- default:
- if (dotIndex >= 0 && expIndex == -1) {
- scale++;
- }
- }
- }
-
- int numberEndIndex;
- int exp = 0;
- if (expIndex >= 0) {
- numberEndIndex = expIndex;
- String expString = new String(chars, expIndex + 1, len - expIndex - 1);
- exp = Integer.parseInt(expString);
- scale = adjustScale(scale, exp);
- } else {
- numberEndIndex = len;
- }
-
- BigDecimal result;
-
- if (dotIndex >= 0) {
- int leftLength = dotIndex - numberIndex;
- BigDecimal bigDecimalLeft = toBigDecimalRecursive(chars, numberIndex, leftLength, exp, splitLength);
- int rightLength = numberEndIndex - dotIndex - 1;
- BigDecimal bigDecimalRight = toBigDecimalRecursive(chars, dotIndex + 1, rightLength, exp-rightLength, splitLength);
- result = bigDecimalLeft.add(bigDecimalRight);
- } else {
- result = toBigDecimalRecursive(chars, numberIndex, numberEndIndex - numberIndex, exp, splitLength);
- }
-
- if (scale != 0) {
- result = result.setScale(scale);
- }
-
- if (negative) {
- result = result.negate();
- }
-
- if (mathContext.getPrecision() != 0) {
- result = result.round(mathContext);
- }
-
- return result;
- }
-
- private static int adjustScale(int scale, long exp) {
- long adjustedScale = scale - exp;
- if (adjustedScale > Integer.MAX_VALUE || adjustedScale < Integer.MIN_VALUE)
- throw new NumberFormatException("Scale out of range: " + adjustedScale + " while adjusting scale " + scale + " to exponent " + exp);
- return (int) adjustedScale;
- }
-
- private static BigDecimal toBigDecimalRecursive(char[] chars, int offset, int length, int scale, int splitLength) {
- if (length > splitLength) {
- int mid = length / 2;
- BigDecimal bigDecimalLeft = toBigDecimalRecursive(chars, offset, mid, scale + length - mid, splitLength);
- BigDecimal bigDecimalRight = toBigDecimalRecursive(chars, offset + mid, length - mid, scale, splitLength);
- return bigDecimalLeft.add(bigDecimalRight);
- }
- if (length == 0) {
- return BigDecimal.ZERO;
- }
- return new BigDecimal(chars, offset, length).movePointRight(scale);
- }
-
- /**
- * Returns whether the specified {@link BigDecimal} value can be represented as <code>int</code>.
- *
- * <p>If this returns <code>true</code> you can call {@link BigDecimal#intValueExact()} without fear of an {@link ArithmeticException}.</p>
- *
- * @param value the {@link BigDecimal} to check
- * @return <code>true</code> if the value can be represented as <code>int</code> value
- */
- public static boolean isIntValue(BigDecimal value) {
- // TODO impl isIntValue() without exceptions
- try {
- value.intValueExact();
- return true;
- } catch (ArithmeticException ex) {
- // ignored
- }
- return false;
- }
-
- /**
- * Returns whether the specified {@link BigDecimal} value can be represented as <code>long</code>.
- *
- * <p>If this returns <code>true</code> you can call {@link BigDecimal#longValueExact()} without fear of an {@link ArithmeticException}.</p>
- *
- * @param value the {@link BigDecimal} to check
- * @return <code>true</code> if the value can be represented as <code>long</code> value
- */
- public static boolean isLongValue(BigDecimal value) {
- // TODO impl isLongValue() without exceptions
- try {
- value.longValueExact();
- return true;
- } catch (ArithmeticException ex) {
- // ignored
- }
- return false;
- }
-
- /**
- * Returns whether the specified {@link BigDecimal} value can be represented as <code>double</code>.
- *
- * <p>If this returns <code>true</code> you can call {@link BigDecimal#doubleValue()}
- * without fear of getting {@link Double#POSITIVE_INFINITY} or {@link Double#NEGATIVE_INFINITY} as result.</p>
- *
- * <p>Example: <code>BigDecimalMath.isDoubleValue(new BigDecimal("1E309"))</code> returns <code>false</code>,
- * because <code>new BigDecimal("1E309").doubleValue()</code> returns <code>Infinity</code>.</p>
- *
- * <p>Note: This method does <strong>not</strong> check for possible loss of precision.</p>
- *
- * <p>For example <code>BigDecimalMath.isDoubleValue(new BigDecimal("1.23400000000000000000000000000000001"))</code> will return <code>true</code>,
- * because <code>new BigDecimal("1.23400000000000000000000000000000001").doubleValue()</code> returns a valid double value,
- * although it loses precision and returns <code>1.234</code>.</p>
- *
- * <p><code>BigDecimalMath.isDoubleValue(new BigDecimal("1E-325"))</code> will return <code>true</code>
- * although this value is smaller than {@link Double#MIN_VALUE} (and therefore outside the range of values that can be represented as <code>double</code>)
- * because <code>new BigDecimal("1E-325").doubleValue()</code> returns <code>0</code> which is a legal value with loss of precision.</p>
- *
- * @param value the {@link BigDecimal} to check
- * @return <code>true</code> if the value can be represented as <code>double</code> value
- */
- public static boolean isDoubleValue(BigDecimal value) {
- if (value.compareTo(DOUBLE_MAX_VALUE) > 0) {
- return false;
- }
- if (value.compareTo(DOUBLE_MAX_VALUE.negate()) < 0) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Returns the mantissa of the specified {@link BigDecimal} written as <em>mantissa * 10<sup>exponent</sup></em>.
- *
- * <p>The mantissa is defined as having exactly 1 digit before the decimal point.</p>
- *
- * @param value the {@link BigDecimal}
- * @return the mantissa
- * @see #exponent(BigDecimal)
- */
- public static BigDecimal mantissa(BigDecimal value) {
- int exponent = exponent(value);
- if (exponent == 0) {
- return value;
- }
-
- return value.movePointLeft(exponent);
- }
-
- /**
- * Returns the exponent of the specified {@link BigDecimal} written as <em>mantissa * 10<sup>exponent</sup></em>.
- *
- * <p>The mantissa is defined as having exactly 1 digit before the decimal point.</p>
- *
- * @param value the {@link BigDecimal}
- * @return the exponent
- * @see #mantissa(BigDecimal)
- */
- public static int exponent(BigDecimal value) {
- return value.precision() - value.scale() - 1;
- }
-
- /**
- * Returns the number of significant digits of the specified {@link BigDecimal}.
- *
- * <p>The result contains the number of all digits before the decimal point and
- * all digits after the decimal point excluding trailing zeroes.</p>
- *
- * <p>Examples:</p>
- * <ul>
- * <li><code>significantDigits(new BigDecimal("12300.00"))</code> returns 5</li>
- * <li><code>significantDigits(new BigDecimal("1.23000"))</code> returns 3</li>
- * <li><code>significantDigits(new BigDecimal("0.00012300"))</code> returns 3</li>
- * <li><code>significantDigits(new BigDecimal("12300.4500"))</code> returns 7</li>
- * </ul>
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Significant_figures">Wikipedia: Significant figures</a></p>
- *
- * @param value the {@link BigDecimal}
- * @return the number of significant digits
- * @see BigDecimal#stripTrailingZeros()
- * @see BigDecimal#precision()
- */
- public static int significantDigits(BigDecimal value) {
- BigDecimal stripped = value.stripTrailingZeros();
- if (stripped.scale() >= 0) {
- return stripped.precision();
- } else {
- return stripped.precision() - stripped.scale();
- }
- }
-
- /**
- * Returns the integral part of the specified {@link BigDecimal} (left of the decimal point).
- *
- * @param value the {@link BigDecimal}
- * @return the integral part
- * @see #fractionalPart(BigDecimal)
- */
- public static BigDecimal integralPart(BigDecimal value) {
- return value.setScale(0, BigDecimal.ROUND_DOWN);
- }
-
- /**
- * Returns the fractional part of the specified {@link BigDecimal} (right of the decimal point).
- *
- * @param value the {@link BigDecimal}
- * @return the fractional part
- * @see #integralPart(BigDecimal)
- */
- public static BigDecimal fractionalPart(BigDecimal value) {
- return value.subtract(integralPart(value));
- }
-
- /**
- * Rounds the specified {@link BigDecimal} to the precision of the specified {@link MathContext}.
- *
- * <p>This method calls {@link BigDecimal#round(MathContext)}.</p>
- *
- * @param value the {@link BigDecimal} to round
- * @param mathContext the {@link MathContext} used for the result
- * @return the rounded {@link BigDecimal} value
- * @see BigDecimal#round(MathContext)
- * @see BigDecimalMath#roundWithTrailingZeroes(BigDecimal, MathContext)
- */
- public static BigDecimal round(BigDecimal value, MathContext mathContext) {
- return value.round(mathContext);
- }
-
- /**
- * Rounds the specified {@link BigDecimal} to the precision of the specified {@link MathContext} including trailing zeroes.
- *
- * <p>This method is similar to {@link BigDecimal#round(MathContext)} but does <strong>not</strong> remove the trailing zeroes.</p>
- *
- * <p>Example:</p>
-<pre>
-MathContext mc = new MathContext(5);
-System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("1.234567"), mc)); // 1.2346
-System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("123.4567"), mc)); // 123.46
-System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("0.001234567"), mc)); // 0.0012346
-System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("1.23"), mc)); // 1.2300
-System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("1.230000"), mc)); // 1.2300
-System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("0.00123"), mc)); // 0.0012300
-System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("0"), mc)); // 0.0000
-System.out.println(BigDecimalMath.roundWithTrailingZeroes(new BigDecimal("0.00000000"), mc)); // 0.0000
-</pre>
- *
- * @param value the {@link BigDecimal} to round
- * @param mathContext the {@link MathContext} used for the result
- * @return the rounded {@link BigDecimal} value including trailing zeroes
- * @see BigDecimal#round(MathContext)
- * @see BigDecimalMath#round(BigDecimal, MathContext)
- */
- public static BigDecimal roundWithTrailingZeroes(BigDecimal value, MathContext mathContext) {
- if (value.precision() == mathContext.getPrecision()) {
- return value;
- }
- if (value.signum() == 0) {
- return BigDecimal.ZERO.setScale(mathContext.getPrecision() - 1);
- }
-
- try {
- BigDecimal stripped = value.stripTrailingZeros();
- int exponentStripped = exponent(stripped); // value.precision() - value.scale() - 1;
-
- BigDecimal zero;
- if (exponentStripped < -1) {
- zero = BigDecimal.ZERO.setScale(mathContext.getPrecision() - exponentStripped);
- } else {
- zero = BigDecimal.ZERO.setScale(mathContext.getPrecision() + exponentStripped + 1);
- }
- return stripped.add(zero, mathContext);
- } catch (ArithmeticException ex) {
- return value.round(mathContext);
- }
- }
-
- /**
- * Calculates the reciprocal of the specified {@link BigDecimal}.
- *
- * @param x the {@link BigDecimal}
- * @param mathContext the {@link MathContext} used for the result
- * @return the reciprocal {@link BigDecimal}
- * @throws ArithmeticException if x = 0
- * @throws ArithmeticException if the result is inexact but the
- * rounding mode is {@code UNNECESSARY} or
- * {@code mc.precision == 0} and the quotient has a
- * non-terminating decimal expansion.
- */
- public static BigDecimal reciprocal(BigDecimal x, MathContext mathContext) {
- return BigDecimal.ONE.divide(x, mathContext);
- }
-
- /**
- * Calculates the factorial of the specified integer argument.
- *
- * <p>factorial = 1 * 2 * 3 * ... n</p>
- *
- * @param n the {@link BigDecimal}
- * @return the factorial {@link BigDecimal}
- * @throws ArithmeticException if x &lt; 0
- */
- public static BigDecimal factorial(int n) {
- if (n < 0) {
- throw new ArithmeticException("Illegal factorial(n) for n < 0: n = " + n);
- }
- if (n < factorialCache.length) {
- return factorialCache[n];
- }
-
- BigDecimal result = factorialCache[factorialCache.length - 1];
- return result.multiply(factorialRecursion(factorialCache.length, n));
- }
-
- private static BigDecimal factorialLoop(int n1, final int n2) {
- final long limit = Long.MAX_VALUE / n2;
- long accu = 1;
- BigDecimal result = BigDecimal.ONE;
- while (n1 <= n2) {
- if (accu <= limit) {
- accu *= n1;
- } else {
- result = result.multiply(BigDecimal.valueOf(accu));
- accu = n1;
- }
- n1++;
- }
- return result.multiply(BigDecimal.valueOf(accu));
- }
-
- private static BigDecimal factorialRecursion(final int n1, final int n2) {
- int threshold = n1 > 200 ? 80 : 150;
- if (n2 - n1 < threshold) {
- return factorialLoop(n1, n2);
- }
- final int mid = (n1 + n2) >> 1;
- return factorialRecursion(mid + 1, n2).multiply(factorialRecursion(n1, mid));
- }
-
- /**
- * Calculates the factorial of the specified {@link BigDecimal}.
- *
- * <p>This implementation uses
- * <a href="https://en.wikipedia.org/wiki/Spouge%27s_approximation">Spouge's approximation</a>
- * to calculate the factorial for non-integer values.</p>
- *
- * <p>This involves calculating a series of constants that depend on the desired precision.
- * Since this constant calculation is quite expensive (especially for higher precisions),
- * the constants for a specific precision will be cached
- * and subsequent calls to this method with the same precision will be much faster.</p>
- *
- * <p>It is therefore recommended to do one call to this method with the standard precision of your application during the startup phase
- * and to avoid calling it with many different precisions.</p>
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Factorial#Extension_of_factorial_to_non-integer_values_of_argument">Wikipedia: Factorial - Extension of factorial to non-integer values of argument</a></p>
- *
- * @param x the {@link BigDecimal}
- * @param mathContext the {@link MathContext} used for the result
- * @return the factorial {@link BigDecimal}
- * @throws ArithmeticException if x is a negative integer value (-1, -2, -3, ...)
- * @throws UnsupportedOperationException if x is a non-integer value and the {@link MathContext} has unlimited precision
- * @see #factorial(int)
- * @see #gamma(BigDecimal, MathContext)
- */
- public static BigDecimal factorial(BigDecimal x, MathContext mathContext) {
- if (isIntValue(x)) {
- return round(factorial(x.intValueExact()), mathContext);
- }
-
- // https://en.wikipedia.org/wiki/Spouge%27s_approximation
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() << 1, mathContext.getRoundingMode());
-
- int a = mathContext.getPrecision() * 13 / 10;
- List<BigDecimal> constants = getSpougeFactorialConstants(a);
-
- BigDecimal bigA = BigDecimal.valueOf(a);
-
- boolean negative = false;
- BigDecimal factor = constants.get(0);
- for (int k = 1; k < a; k++) {
- BigDecimal bigK = BigDecimal.valueOf(k);
- factor = factor.add(constants.get(k).divide(x.add(bigK), mc));
- negative = !negative;
- }
-
- BigDecimal result = pow(x.add(bigA), x.add(BigDecimal.valueOf(0.5)), mc);
- result = result.multiply(exp(x.negate().subtract(bigA), mc));
- result = result.multiply(factor);
-
- return round(result, mathContext);
- }
-
- static List<BigDecimal> getSpougeFactorialConstants(int a) {
- synchronized (spougeFactorialConstantsCacheLock) {
- return spougeFactorialConstantsCache.computeIfAbsent(a, key -> {
- List<BigDecimal> constants = new ArrayList<>(a);
- MathContext mc = new MathContext(a * 15 / 10);
-
- BigDecimal c0 = sqrt(pi(mc).multiply(TWO, mc), mc);
- constants.add(c0);
-
- boolean negative = false;
- for (int k = 1; k < a; k++) {
- BigDecimal bigK = BigDecimal.valueOf(k);
- long deltaAK = (long)a - k;
- BigDecimal ck = pow(BigDecimal.valueOf(deltaAK), bigK.subtract(ONE_HALF), mc);
- ck = ck.multiply(exp(BigDecimal.valueOf(deltaAK), mc), mc);
- ck = ck.divide(factorial(k - 1), mc);
- if (negative) {
- ck = ck.negate();
- }
- constants.add(ck);
-
- negative = !negative;
- }
-
- return Collections.unmodifiableList(constants);
- });
- }
- }
-
- /**
- * Calculates the gamma function of the specified {@link BigDecimal}.
- *
- * <p>This implementation uses {@link #factorial(BigDecimal, MathContext)} internally,
- * therefore the performance implications described there apply also for this method.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Gamma_function">Wikipedia: Gamma function</a></p>
- *
- * @param x the {@link BigDecimal}
- * @param mathContext the {@link MathContext} used for the result
- * @return the gamma {@link BigDecimal}
- * @throws ArithmeticException if x-1 is a negative integer value (-1, -2, -3, ...)
- * @throws UnsupportedOperationException if x is a non-integer value and the {@link MathContext} has unlimited precision
- * @see #factorial(BigDecimal, MathContext)
- */
- public static BigDecimal gamma(BigDecimal x, MathContext mathContext) {
- return factorial(x.subtract(ONE), mathContext);
- }
-
- /**
- * Calculates the Bernoulli number for the specified index.
- *
- * <p>This function calculates the <strong>first Bernoulli numbers</strong> and therefore <code>bernoulli(1)</code> returns -0.5</p>
- * <p>Note that <code>bernoulli(x)</code> for all odd x &gt; 1 returns 0</p>
- * <p>See: <a href="https://en.wikipedia.org/wiki/Bernoulli_number">Wikipedia: Bernoulli number</a></p>
- *
- * @param n the index of the Bernoulli number to be calculated (starting at 0)
- * @param mathContext the {@link MathContext} used for the result
- * @return the Bernoulli number for the specified index
- * @throws ArithmeticException if x &lt; 0
- * @throws ArithmeticException if the result is inexact but the
- * rounding mode is {@code UNNECESSARY} or
- * {@code mc.precision == 0} and the quotient has a
- * non-terminating decimal expansion.
- */
- public static BigDecimal bernoulli(int n, MathContext mathContext) {
- if (n < 0) {
- throw new ArithmeticException("Illegal bernoulli(n) for n < 0: n = " + n);
- }
-
- BigRational b = BigRational.bernoulli(n);
- return b.toBigDecimal(mathContext);
- }
-
- /**
- * Calculates {@link BigDecimal} x to the power of {@link BigDecimal} y (x<sup>y</sup>).
- *
- * @param x the {@link BigDecimal} value to take to the power
- * @param y the {@link BigDecimal} value to serve as exponent
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated x to the power of y with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- * @see #pow(BigDecimal, long, MathContext)
- */
- public static BigDecimal pow(BigDecimal x, BigDecimal y, MathContext mathContext) {
- checkMathContext(mathContext);
- if (x.signum() == 0) {
- switch (y.signum()) {
- case 0 : return round(ONE, mathContext);
- case 1 : return round(ZERO, mathContext);
- }
- }
-
- // TODO optimize y=0, y=1, y=10^k, y=-1, y=-10^k
-
- try {
- long longValue = y.longValueExact();
- return pow(x, longValue, mathContext);
- } catch (ArithmeticException ex) {
- // ignored
- }
-
- if (fractionalPart(y).signum() == 0) {
- return powInteger(x, y, mathContext);
- }
-
- // x^y = exp(y*log(x))
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
- BigDecimal result = exp(y.multiply(log(x, mc), mc), mc);
-
- return round(result, mathContext);
- }
-
- /**
- * Calculates {@link BigDecimal} x to the power of <code>long</code> y (x<sup>y</sup>).
- *
- * <p>The implementation tries to minimize the number of multiplications of {@link BigDecimal x} (using squares whenever possible).</p>
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Exponentiation#Efficient_computation_with_integer_exponents">Wikipedia: Exponentiation - efficient computation</a></p>
- *
- * @param x the {@link BigDecimal} value to take to the power
- * @param y the <code>long</code> value to serve as exponent
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated x to the power of y with the precision specified in the <code>mathContext</code>
- * @throws ArithmeticException if y is negative and the result is inexact but the
- * rounding mode is {@code UNNECESSARY} or
- * {@code mc.precision == 0} and the quotient has a
- * non-terminating decimal expansion.
- * @throws ArithmeticException if the rounding mode is
- * {@code UNNECESSARY} and the
- * {@code BigDecimal} operation would require rounding.
- */
- public static BigDecimal pow(BigDecimal x, long y, MathContext mathContext) {
- MathContext mc = mathContext.getPrecision() == 0 ? mathContext : new MathContext(mathContext.getPrecision() + 10, mathContext.getRoundingMode());
-
- // TODO optimize y=0, y=1, y=10^k, y=-1, y=-10^k
-
- if (y < 0) {
- BigDecimal value = reciprocal(pow(x, -y, mc), mc);
- return round(value, mathContext);
- }
-
- BigDecimal result = ONE;
- while (y > 0) {
- if ((y & 1) == 1) {
- // odd exponent -> multiply result with x
- result = result.multiply(x, mc);
- y -= 1;
- }
-
- if (y > 0) {
- // even exponent -> square x
- x = x.multiply(x, mc);
- }
-
- y >>= 1;
- }
-
- return round(result, mathContext);
- }
-
- /**
- * Calculates {@link BigDecimal} x to the power of the integer value y (x<sup>y</sup>).
- *
- * <p>The value y MUST be an integer value.</p>
- *
- * @param x the {@link BigDecimal} value to take to the power
- * @param integerY the {@link BigDecimal} <strong>integer</strong> value to serve as exponent
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated x to the power of y with the precision specified in the <code>mathContext</code>
- * @see #pow(BigDecimal, long, MathContext)
- */
- private static BigDecimal powInteger(BigDecimal x, BigDecimal integerY, MathContext mathContext) {
- if (fractionalPart(integerY).signum() != 0) {
- throw new IllegalArgumentException("Not integer value: " + integerY);
- }
-
- if (integerY.signum() < 0) {
- return ONE.divide(powInteger(x, integerY.negate(), mathContext), mathContext);
- }
-
- MathContext mc = new MathContext(Math.max(mathContext.getPrecision(), -integerY.scale()) + 30, mathContext.getRoundingMode());
-
- BigDecimal result = ONE;
- while (integerY.signum() > 0) {
- BigDecimal halfY = integerY.divide(TWO, mc);
-
- if (fractionalPart(halfY).signum() != 0) {
- // odd exponent -> multiply result with x
- result = result.multiply(x, mc);
- integerY = integerY.subtract(ONE);
- halfY = integerY.divide(TWO, mc);
- }
-
- if (halfY.signum() > 0) {
- // even exponent -> square x
- x = x.multiply(x, mc);
- }
-
- integerY = halfY;
- }
-
- return round(result, mathContext);
- }
-
- /**
- * Calculates the square root of {@link BigDecimal} x.
- *
- * <p>See <a href="http://en.wikipedia.org/wiki/Square_root">Wikipedia: Square root</a></p>
- *
- * @param x the {@link BigDecimal} value to calculate the square root
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated square root of x with the precision specified in the <code>mathContext</code>
- * @throws ArithmeticException if x &lt; 0
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal sqrt(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- switch (x.signum()) {
- case 0:
- return ZERO;
- case -1:
- throw new ArithmeticException("Illegal sqrt(x) for x < 0: x = " + x);
- }
-
- int maxPrecision = mathContext.getPrecision() + 6;
- BigDecimal acceptableError = ONE.movePointLeft(mathContext.getPrecision() + 1);
-
- BigDecimal result;
- int adaptivePrecision;
- if (isDoubleValue(x)) {
- result = BigDecimal.valueOf(Math.sqrt(x.doubleValue()));
- adaptivePrecision = EXPECTED_INITIAL_PRECISION;
- } else {
- result = x.multiply(ONE_HALF, mathContext);
- adaptivePrecision = 1;
- }
-
- BigDecimal last;
-
- if (adaptivePrecision < maxPrecision) {
- if (result.multiply(result).compareTo(x) == 0) {
- return round(result, mathContext); // early exit if x is a square number
- }
-
- do {
- last = result;
- adaptivePrecision <<= 1;
- if (adaptivePrecision > maxPrecision) {
- adaptivePrecision = maxPrecision;
- }
- MathContext mc = new MathContext(adaptivePrecision, mathContext.getRoundingMode());
- result = x.divide(result, mc).add(last).multiply(ONE_HALF, mc);
- }
- while (adaptivePrecision < maxPrecision || result.subtract(last).abs().compareTo(acceptableError) > 0);
- }
-
- return round(result, mathContext);
- }
-
- /**
- * Calculates the n'th root of {@link BigDecimal} x.
- *
- * <p>See <a href="http://en.wikipedia.org/wiki/Square_root">Wikipedia: Square root</a></p>
- * @param x the {@link BigDecimal} value to calculate the n'th root
- * @param n the {@link BigDecimal} defining the root
- * @param mathContext the {@link MathContext} used for the result
- *
- * @return the calculated n'th root of x with the precision specified in the <code>mathContext</code>
- * @throws ArithmeticException if x &lt; 0
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal root(BigDecimal x, BigDecimal n, MathContext mathContext) {
- checkMathContext(mathContext);
- switch (x.signum()) {
- case 0:
- return ZERO;
- case -1:
- throw new ArithmeticException("Illegal root(x) for x < 0: x = " + x);
- }
-
- if (n.compareTo(BigDecimal.ONE) <= 0) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
- return pow(x, BigDecimal.ONE.divide(n, mc), mathContext);
- }
-
- int maxPrecision = mathContext.getPrecision() + 4;
- BigDecimal acceptableError = ONE.movePointLeft(mathContext.getPrecision() + 1);
-
- BigDecimal nMinus1 = n.subtract(ONE);
- BigDecimal result = x.divide(TWO, MathContext.DECIMAL32);
- int adaptivePrecision = 2; // first approximation has really bad precision
- BigDecimal step;
-
- do {
- adaptivePrecision *= 3;
- if (adaptivePrecision > maxPrecision) {
- adaptivePrecision = maxPrecision;
- }
- MathContext mc = new MathContext(adaptivePrecision, mathContext.getRoundingMode());
-
- step = x.divide(pow(result, nMinus1, mc), mc).subtract(result).divide(n, mc);
- result = result.add(step);
- } while (adaptivePrecision < maxPrecision || step.abs().compareTo(acceptableError) > 0);
-
- return round(result, mathContext);
- }
-
- /**
- * Calculates the natural logarithm of {@link BigDecimal} x.
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Natural_logarithm">Wikipedia: Natural logarithm</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the natural logarithm for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated natural logarithm {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws ArithmeticException if x &lt;= 0
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal log(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- if (x.signum() <= 0) {
- throw new ArithmeticException("Illegal log(x) for x <= 0: x = " + x);
- }
- if (x.compareTo(ONE) == 0) {
- return ZERO;
- }
-
- BigDecimal result;
- switch (x.compareTo(TEN)) {
- case 0:
- result = logTen(mathContext);
- break;
- case 1:
- result = logUsingExponent(x, mathContext);
- break;
- default :
- result = logUsingTwoThree(x, mathContext);
- }
-
- return round(result, mathContext);
- }
-
- /**
- * Calculates the logarithm of {@link BigDecimal} x to the base 2.
- *
- * @param x the {@link BigDecimal} to calculate the logarithm base 2 for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated natural logarithm {@link BigDecimal} to the base 2 with the precision specified in the <code>mathContext</code>
- * @throws ArithmeticException if x &lt;= 0
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal log2(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
-
- BigDecimal result = log(x, mc).divide(logTwo(mc), mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the logarithm of {@link BigDecimal} x to the base 10.
- *
- * @param x the {@link BigDecimal} to calculate the logarithm base 10 for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated natural logarithm {@link BigDecimal} to the base 10 with the precision specified in the <code>mathContext</code>
- * @throws ArithmeticException if x &lt;= 0
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal log10(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 2, mathContext.getRoundingMode());
-
- BigDecimal result = log(x, mc).divide(logTen(mc), mc);
- return round(result, mathContext);
- }
-
- private static BigDecimal logUsingNewton(BigDecimal x, MathContext mathContext) {
- // https://en.wikipedia.org/wiki/Natural_logarithm in chapter 'High Precision'
- // y = y + 2 * (x-exp(y)) / (x+exp(y))
-
- int maxPrecision = mathContext.getPrecision() + 20;
- BigDecimal acceptableError = ONE.movePointLeft(mathContext.getPrecision() + 1);
- //System.out.println("logUsingNewton(" + x + " " + mathContext + ") precision " + maxPrecision);
-
- BigDecimal result;
- int adaptivePrecision;
- double doubleX = x.doubleValue();
- if (doubleX > 0.0 && isDoubleValue(x)) {
- result = BigDecimal.valueOf(Math.log(doubleX));
- adaptivePrecision = EXPECTED_INITIAL_PRECISION;
- } else {
- result = x.divide(TWO, mathContext);
- adaptivePrecision = 1;
- }
-
- BigDecimal step;
-
- do {
- adaptivePrecision *= 3;
- if (adaptivePrecision > maxPrecision) {
- adaptivePrecision = maxPrecision;
- }
- MathContext mc = new MathContext(adaptivePrecision, mathContext.getRoundingMode());
-
- BigDecimal expY = BigDecimalMath.exp(result, mc);
- step = TWO.multiply(x.subtract(expY)).divide(x.add(expY), mc);
- //System.out.println(" step " + step + " adaptivePrecision=" + adaptivePrecision);
- result = result.add(step);
- } while (adaptivePrecision < maxPrecision || step.abs().compareTo(acceptableError) > 0);
-
- return result;
- }
-
- private static BigDecimal logUsingExponent(BigDecimal x, MathContext mathContext) {
- MathContext mcDouble = new MathContext(mathContext.getPrecision() << 1, mathContext.getRoundingMode());
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
- //System.out.println("logUsingExponent(" + x + " " + mathContext + ") precision " + mc);
-
- int exponent = exponent(x);
- BigDecimal mantissa = mantissa(x);
-
- BigDecimal result = logUsingTwoThree(mantissa, mc);
- if (exponent != 0) {
- result = result.add(valueOf(exponent).multiply(logTen(mcDouble), mc));
- }
- return result;
- }
-
- private static BigDecimal logUsingTwoThree(BigDecimal x, MathContext mathContext) {
- MathContext mcDouble = new MathContext(mathContext.getPrecision() << 1, mathContext.getRoundingMode());
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
- //System.out.println("logUsingTwoThree(" + x + " " + mathContext + ") precision " + mc);
-
- int factorOfTwo = 0;
- int powerOfTwo = 1;
- int factorOfThree = 0;
- int powerOfThree = 1;
-
- double value = x.doubleValue();
- if (value < 0.01) {
- // do nothing
- } else if (value < 0.1) { // never happens when called by logUsingExponent()
- while (value < 0.6) {
- value *= 2;
- factorOfTwo--;
- powerOfTwo <<= 1;
- }
- }
- else if (value < 0.115) { // (0.1 - 0.11111 - 0.115) -> (0.9 - 1.0 - 1.035)
- factorOfThree = -2;
- powerOfThree = 9;
- }
- else if (value < 0.14) { // (0.115 - 0.125 - 0.14) -> (0.92 - 1.0 - 1.12)
- factorOfTwo = -3;
- powerOfTwo = 8;
- }
- else if (value < 0.2) { // (0.14 - 0.16667 - 0.2) - (0.84 - 1.0 - 1.2)
- factorOfTwo = -1;
- powerOfTwo = 2;
- factorOfThree = -1;
- powerOfThree = 3;
- }
- else if (value < 0.3) { // (0.2 - 0.25 - 0.3) -> (0.8 - 1.0 - 1.2)
- factorOfTwo = -2;
- powerOfTwo = 4;
- }
- else if (value < 0.42) { // (0.3 - 0.33333 - 0.42) -> (0.9 - 1.0 - 1.26)
- factorOfThree = -1;
- powerOfThree = 3;
- }
- else if (value < 0.7) { // (0.42 - 0.5 - 0.7) -> (0.84 - 1.0 - 1.4)
- factorOfTwo = -1;
- powerOfTwo = 2;
- }
- else if (value < 1.4) { // (0.7 - 1.0 - 1.4) -> (0.7 - 1.0 - 1.4)
- // do nothing
- }
- else if (value < 2.5) { // (1.4 - 2.0 - 2.5) -> (0.7 - 1.0 - 1.25)
- factorOfTwo = 1;
- powerOfTwo = 2;
- }
- else if (value < 3.5) { // (2.5 - 3.0 - 3.5) -> (0.833333 - 1.0 - 1.166667)
- factorOfThree = 1;
- powerOfThree = 3;
- }
- else if (value < 5.0) { // (3.5 - 4.0 - 5.0) -> (0.875 - 1.0 - 1.25)
- factorOfTwo = 2;
- powerOfTwo = 4;
- }
- else if (value < 7.0) { // (5.0 - 6.0 - 7.0) -> (0.833333 - 1.0 - 1.166667)
- factorOfThree = 1;
- powerOfThree = 3;
- factorOfTwo = 1;
- powerOfTwo = 2;
- }
- else if (value < 8.5) { // (7.0 - 8.0 - 8.5) -> (0.875 - 1.0 - 1.0625)
- factorOfTwo = 3;
- powerOfTwo = 8;
- }
- else if (value < 10.0) { // (8.5 - 9.0 - 10.0) -> (0.94444 - 1.0 - 1.11111)
- factorOfThree = 2;
- powerOfThree = 9;
- }
- else {
- while (value > 1.4) { // never happens when called by logUsingExponent()
- value /= 2;
- factorOfTwo++;
- powerOfTwo <<= 1;
- }
- }
-
- BigDecimal correctedX = x;
- BigDecimal result = ZERO;
-
- if (factorOfTwo > 0) {
- correctedX = correctedX.divide(valueOf(powerOfTwo), mc);
- result = result.add(logTwo(mcDouble).multiply(valueOf(factorOfTwo), mc));
- }
- else if (factorOfTwo < 0) {
- correctedX = correctedX.multiply(valueOf(powerOfTwo), mc);
- result = result.subtract(logTwo(mcDouble).multiply(valueOf(-factorOfTwo), mc));
- }
-
- if (factorOfThree > 0) {
- correctedX = correctedX.divide(valueOf(powerOfThree), mc);
- result = result.add(logThree(mcDouble).multiply(valueOf(factorOfThree), mc));
- }
- else if (factorOfThree < 0) {
- correctedX = correctedX.multiply(valueOf(powerOfThree), mc);
- result = result.subtract(logThree(mcDouble).multiply(valueOf(-factorOfThree), mc));
- }
-
- if (x == correctedX && result == ZERO) {
- return logUsingNewton(x, mathContext);
- }
-
- result = result.add(logUsingNewton(correctedX, mc), mc);
-
- return result;
- }
-
- /**
- * Returns the number pi.
- *
- * <p>See <a href="https://en.wikipedia.org/wiki/Pi">Wikipedia: Pi</a></p>
- *
- * @param mathContext the {@link MathContext} used for the result
- * @return the number pi with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal pi(MathContext mathContext) {
- checkMathContext(mathContext);
- BigDecimal result = null;
-
- synchronized (piCacheLock) {
- if (piCache != null && mathContext.getPrecision() <= piCache.precision()) {
- result = piCache;
- } else {
- piCache = piChudnovski(mathContext);
- return piCache;
- }
- }
-
- return round(result, mathContext);
- }
-
- private static BigDecimal piChudnovski(MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 10, mathContext.getRoundingMode());
-
- final BigDecimal value24 = BigDecimal.valueOf(24);
- final BigDecimal value640320 = BigDecimal.valueOf(640320);
- final BigDecimal value13591409 = BigDecimal.valueOf(13591409);
- final BigDecimal value545140134 = BigDecimal.valueOf(545140134);
- final BigDecimal valueDivisor = value640320.pow(3).divide(value24, mc);
-
- BigDecimal sumA = BigDecimal.ONE;
- BigDecimal sumB = BigDecimal.ZERO;
-
- BigDecimal a = BigDecimal.ONE;
- long dividendTerm1 = 5; // -(6*k - 5)
- long dividendTerm2 = -1; // 2*k - 1
- long dividendTerm3 = -1; // 6*k - 1
- BigDecimal kPower3 = BigDecimal.ZERO;
-
- long iterationCount = (mc.getPrecision()+13) / 14;
- for (long k = 1; k <= iterationCount; k++) {
- BigDecimal valueK = BigDecimal.valueOf(k);
- dividendTerm1 += -6;
- dividendTerm2 += 2;
- dividendTerm3 += 6;
- BigDecimal dividend = BigDecimal.valueOf(dividendTerm1).multiply(BigDecimal.valueOf(dividendTerm2)).multiply(BigDecimal.valueOf(dividendTerm3));
- kPower3 = valueK.pow(3);
- BigDecimal divisor = kPower3.multiply(valueDivisor, mc);
- a = a.multiply(dividend).divide(divisor, mc);
- BigDecimal b = valueK.multiply(a, mc);
-
- sumA = sumA.add(a);
- sumB = sumB.add(b);
- }
-
- final BigDecimal value426880 = BigDecimal.valueOf(426880);
- final BigDecimal value10005 = BigDecimal.valueOf(10005);
- final BigDecimal factor = value426880.multiply(sqrt(value10005, mc));
- BigDecimal pi = factor.divide(value13591409.multiply(sumA, mc).add(value545140134.multiply(sumB, mc)), mc);
-
- return round(pi, mathContext);
- }
-
- /**
- * Returns the number e.
- *
- * <p>See <a href="https://en.wikipedia.org/wiki/E_(mathematical_constant)">Wikipedia: E (mathematical_constant)</a></p>
- *
- * @param mathContext the {@link MathContext} used for the result
- * @return the number e with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal e(MathContext mathContext) {
- checkMathContext(mathContext);
- BigDecimal result = null;
-
- synchronized (eCacheLock) {
- if (eCache != null && mathContext.getPrecision() <= eCache.precision()) {
- result = eCache;
- } else {
- eCache = exp(ONE, mathContext);
- return eCache;
- }
- }
-
- return round(result, mathContext);
- }
-
- private static BigDecimal logTen(MathContext mathContext) {
- BigDecimal result = null;
-
- synchronized (log10CacheLock) {
- if (log10Cache != null && mathContext.getPrecision() <= log10Cache.precision()) {
- result = log10Cache;
- } else {
- log10Cache = logUsingNewton(BigDecimal.TEN, mathContext);
- return log10Cache;
- }
- }
-
- return round(result, mathContext);
- }
-
- private static BigDecimal logTwo(MathContext mathContext) {
- BigDecimal result = null;
-
- synchronized (log2CacheLock) {
- if (log2Cache != null && mathContext.getPrecision() <= log2Cache.precision()) {
- result = log2Cache;
- } else {
- log2Cache = logUsingNewton(TWO, mathContext);
- return log2Cache;
- }
- }
-
- return round(result, mathContext);
- }
-
- private static BigDecimal logThree(MathContext mathContext) {
- BigDecimal result = null;
-
- synchronized (log3CacheLock) {
- if (log3Cache != null && mathContext.getPrecision() <= log3Cache.precision()) {
- result = log3Cache;
- } else {
- log3Cache = logUsingNewton(THREE, mathContext);
- return log3Cache;
- }
- }
-
- return round(result, mathContext);
- }
-
- /**
- * Calculates the natural exponent of {@link BigDecimal} x (e<sup>x</sup>).
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Exponent">Wikipedia: Exponent</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the exponent for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated exponent {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal exp(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- if (x.signum() == 0) {
- return ONE;
- }
-
- return expIntegralFractional(x, mathContext);
- }
-
- private static BigDecimal expIntegralFractional(BigDecimal x, MathContext mathContext) {
- BigDecimal integralPart = integralPart(x);
-
- if (integralPart.signum() == 0) {
- return expTaylor(x, mathContext);
- }
-
- BigDecimal fractionalPart = x.subtract(integralPart);
-
- MathContext mc = new MathContext(mathContext.getPrecision() + 10, mathContext.getRoundingMode());
-
- BigDecimal z = ONE.add(fractionalPart.divide(integralPart, mc));
- BigDecimal t = expTaylor(z, mc);
-
- BigDecimal result = pow(t, integralPart.intValueExact(), mc);
-
- return round(result, mathContext);
- }
-
- private static BigDecimal expTaylor(BigDecimal x, MathContext mathContext) {
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
-
- x = x.divide(valueOf(256), mc);
-
- BigDecimal result = ExpCalculator.INSTANCE.calculate(x, mc);
- result = BigDecimalMath.pow(result, 256, mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the sine (sinus) of {@link BigDecimal} x.
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Sine">Wikipedia: Sine</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the sine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated sine {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal sin(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
-
- if (x.abs().compareTo(ROUGHLY_TWO_PI) > 0) {
- MathContext mc2 = new MathContext(mc.getPrecision() + 4, mathContext.getRoundingMode());
- BigDecimal twoPi = TWO.multiply(pi(mc2));
- x = x.remainder(twoPi, mc2);
- }
-
- BigDecimal result = SinCalculator.INSTANCE.calculate(x, mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the arc sine (inverted sine) of {@link BigDecimal} x.
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Arcsine">Wikipedia: Arcsine</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the arc sine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc sine {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws ArithmeticException if x &gt; 1 or x &lt; -1
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal asin(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- if (x.compareTo(ONE) > 0) {
- throw new ArithmeticException("Illegal asin(x) for x > 1: x = " + x);
- }
- if (x.compareTo(MINUS_ONE) < 0) {
- throw new ArithmeticException("Illegal asin(x) for x < -1: x = " + x);
- }
-
- if (x.signum() == -1) {
- return asin(x.negate(), mathContext).negate();
- }
-
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
-
- if (x.compareTo(BigDecimal.valueOf(0.707107)) >= 0) {
- BigDecimal xTransformed = sqrt(ONE.subtract(x.multiply(x)), mc);
- return acos(xTransformed, mathContext);
- }
-
- BigDecimal result = AsinCalculator.INSTANCE.calculate(x, mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the cosine (cosinus) of {@link BigDecimal} x.
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Cosine">Wikipedia: Cosine</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the cosine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated cosine {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal cos(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
-
- if (x.abs().compareTo(ROUGHLY_TWO_PI) > 0) {
- MathContext mc2 = new MathContext(mc.getPrecision() + 4, mathContext.getRoundingMode());
- BigDecimal twoPi = TWO.multiply(pi(mc2), mc2);
- x = x.remainder(twoPi, mc2);
- }
-
- BigDecimal result = CosCalculator.INSTANCE.calculate(x, mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the arc cosine (inverted cosine) of {@link BigDecimal} x.
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Arccosine">Wikipedia: Arccosine</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the arc cosine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc sine {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws ArithmeticException if x &gt; 1 or x &lt; -1
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal acos(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- if (x.compareTo(ONE) > 0) {
- throw new ArithmeticException("Illegal acos(x) for x > 1: x = " + x);
- }
- if (x.compareTo(MINUS_ONE) < 0) {
- throw new ArithmeticException("Illegal acos(x) for x < -1: x = " + x);
- }
-
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
-
- BigDecimal result = pi(mc).divide(TWO, mc).subtract(asin(x, mc));
- return round(result, mathContext);
- }
-
- /**
- * Calculates the tangens of {@link BigDecimal} x.
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Tangens">Wikipedia: Tangens</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the tangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated tangens {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal tan(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- if (x.signum() == 0) {
- return ZERO;
- }
-
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
- BigDecimal result = sin(x, mc).divide(cos(x, mc), mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the arc tangens (inverted tangens) of {@link BigDecimal} x.
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Arctangens">Wikipedia: Arctangens</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the arc tangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc tangens {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal atan(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
-
- x = x.divide(sqrt(ONE.add(x.multiply(x, mc)), mc), mc);
-
- BigDecimal result = asin(x, mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the arc tangens (inverted tangens) of {@link BigDecimal} y / x in the range -<i>pi</i> to <i>pi</i>.
- *
- * <p>This is useful to calculate the angle <i>theta</i> from the conversion of rectangular
- * coordinates (<code>x</code>,&nbsp;<code>y</code>) to polar coordinates (r,&nbsp;<i>theta</i>).</p>
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Atan2">Wikipedia: Atan2</a></p>
- *
- * @param y the {@link BigDecimal}
- * @param x the {@link BigDecimal}
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc tangens {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws ArithmeticException if x = 0 and y = 0
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal atan2(BigDecimal y, BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 3, mathContext.getRoundingMode());
-
- if (x.signum() > 0) { // x > 0
- return atan(y.divide(x, mc), mathContext);
- } else if (x.signum() < 0) {
- if (y.signum() > 0) { // x < 0 && y > 0
- return atan(y.divide(x, mc), mc).add(pi(mc), mathContext);
- } else if (y.signum() < 0) { // x < 0 && y < 0
- return atan(y.divide(x, mc), mc).subtract(pi(mc), mathContext);
- } else { // x < 0 && y = 0
- return pi(mathContext);
- }
- } else {
- if (y.signum() > 0) { // x == 0 && y > 0
- return pi(mc).divide(TWO, mathContext);
- } else if (y.signum() < 0) { // x == 0 && y < 0
- return pi(mc).divide(TWO, mathContext).negate();
- } else {
- throw new ArithmeticException("Illegal atan2(y, x) for x = 0; y = 0");
- }
- }
- }
-
- /**
- * Calculates the cotangens of {@link BigDecimal} x.
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Cotangens">Wikipedia: Cotangens</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the cotangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated cotanges {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws ArithmeticException if x = 0
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal cot(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- if (x.signum() == 0) {
- throw new ArithmeticException("Illegal cot(x) for x = 0");
- }
-
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
- BigDecimal result = cos(x, mc).divide(sin(x, mc), mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the inverse cotangens (arc cotangens) of {@link BigDecimal} x.
- *
- * <p>See: <a href="http://en.wikipedia.org/wiki/Arccotangens">Wikipedia: Arccotangens</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the arc cotangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc cotangens {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal acot(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
- BigDecimal result = pi(mc).divide(TWO, mc).subtract(atan(x, mc));
- return round(result, mathContext);
- }
-
- /**
- * Calculates the hyperbolic sine of {@link BigDecimal} x.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Hyperbolic_function">Wikipedia: Hyperbolic function</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the hyperbolic sine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated hyperbolic sine {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal sinh(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
- BigDecimal result = SinhCalculator.INSTANCE.calculate(x, mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the hyperbolic cosine of {@link BigDecimal} x.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Hyperbolic_function">Wikipedia: Hyperbolic function</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the hyperbolic cosine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated hyperbolic cosine {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal cosh(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 4, mathContext.getRoundingMode());
- BigDecimal result = CoshCalculator.INSTANCE.calculate(x, mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the hyperbolic tangens of {@link BigDecimal} x.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Hyperbolic_function">Wikipedia: Hyperbolic function</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the hyperbolic tangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated hyperbolic tangens {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal tanh(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
- BigDecimal result = sinh(x, mc).divide(cosh(x, mc), mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the hyperbolic cotangens of {@link BigDecimal} x.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Hyperbolic_function">Wikipedia: Hyperbolic function</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the hyperbolic cotangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated hyperbolic cotangens {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal coth(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
- BigDecimal result = cosh(x, mc).divide(sinh(x, mc), mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the arc hyperbolic sine (inverse hyperbolic sine) of {@link BigDecimal} x.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Hyperbolic_function">Wikipedia: Hyperbolic function</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the arc hyperbolic sine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc hyperbolic sine {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal asinh(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 10, mathContext.getRoundingMode());
- BigDecimal result = log(x.add(sqrt(x.multiply(x, mc).add(ONE, mc), mc)), mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the arc hyperbolic cosine (inverse hyperbolic cosine) of {@link BigDecimal} x.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Hyperbolic_function">Wikipedia: Hyperbolic function</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the arc hyperbolic cosine for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc hyperbolic cosine {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal acosh(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
- BigDecimal result = log(x.add(sqrt(x.multiply(x).subtract(ONE), mc)), mc);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the arc hyperbolic tangens (inverse hyperbolic tangens) of {@link BigDecimal} x.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Hyperbolic_function">Wikipedia: Hyperbolic function</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the arc hyperbolic tangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc hyperbolic tangens {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal atanh(BigDecimal x, MathContext mathContext) {
- if (x.compareTo(BigDecimal.ONE) >= 0) {
- throw new ArithmeticException("Illegal atanh(x) for x >= 1: x = " + x);
- }
- if (x.compareTo(MINUS_ONE) <= 0) {
- throw new ArithmeticException("Illegal atanh(x) for x <= -1: x = " + x);
- }
-
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
- BigDecimal result = log(ONE.add(x).divide(ONE.subtract(x), mc), mc).multiply(ONE_HALF);
- return round(result, mathContext);
- }
-
- /**
- * Calculates the arc hyperbolic cotangens (inverse hyperbolic cotangens) of {@link BigDecimal} x.
- *
- * <p>See: <a href="https://en.wikipedia.org/wiki/Hyperbolic_function">Wikipedia: Hyperbolic function</a></p>
- *
- * @param x the {@link BigDecimal} to calculate the arc hyperbolic cotangens for
- * @param mathContext the {@link MathContext} used for the result
- * @return the calculated arc hyperbolic cotangens {@link BigDecimal} with the precision specified in the <code>mathContext</code>
- * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision
- */
- public static BigDecimal acoth(BigDecimal x, MathContext mathContext) {
- checkMathContext(mathContext);
- MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
- BigDecimal result = log(x.add(ONE).divide(x.subtract(ONE), mc), mc).multiply(ONE_HALF);
- return round(result, mathContext);
- }
-
- private static void checkMathContext (MathContext mathContext) {
- if (mathContext.getPrecision() == 0) {
- throw new UnsupportedOperationException("Unlimited MathContext not supported");
- }
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/BigFloat.java b/src/main/java/ch/obermuhlner/math/big/BigFloat.java
deleted file mode 100644
index eb8944f2c4..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/BigFloat.java
+++ /dev/null
@@ -1,1947 +0,0 @@
-package ch.obermuhlner.math.big;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.math.RoundingMode;
-import java.util.Objects;
-
-/**
- * A wrapper around {@link BigDecimal} which simplifies the consistent usage of the {@link MathContext}
- * and provides a simpler API for calculations.
- *
- * <h1>Overview</h1>
- *
- * <p>Every {@link BigFloat} instance has a reference to a {@link Context} that specifies the {@link MathContext} to be used for all calculations and values.</p>
- *
- * <p>The API for calculations is simplified and more consistent with the typical mathematical usage.</p>
- * <ul>
- * <li>Factory methods for values:
- * <ul>
- * <li><code>valueOf(BigFloat)</code></li>
- * <li><code>valueOf(BigDecimal)</code></li>
- * <li><code>valueOf(int)</code></li>
- * <li><code>valueOf(long)</code></li>
- * <li><code>valueOf(double)</code></li>
- * <li><code>valueOf(String)</code></li>
- * <li><code>pi()</code></li>
- * <li><code>e()</code></li>
- * </ul>
- * </li>
- * <li>All standard operators:
- * <ul>
- * <li><code>add(x)</code></li>
- * <li><code>subtract(x)</code></li>
- * <li><code>multiply(x)</code></li>
- * <li><code>remainder(x)</code></li>
- * <li><code>pow(y)</code></li>
- * <li><code>root(y)</code></li>
- * </ul>
- * </li>
- * <li>Calculation methods are overloaded for different value types:
- * <ul>
- * <li><code>add(BigFloat)</code></li>
- * <li><code>add(BigDecimal)</code></li>
- * <li><code>add(int)</code></li>
- * <li><code>add(long)</code></li>
- * <li><code>add(double)</code></li>
- * <li>...</li>
- * </ul>
- * </li>
- * <li>Mathematical functions are written as they are traditionally are written:
- * <ul>
- * <li><code>abs(x)</code></li>
- * <li><code>log(x)</code></li>
- * <li><code>sin(x)</code></li>
- * <li><code>min(x1, x2, ...)</code></li>
- * <li><code>max(x1, x2, ...)</code></li>
- * <li>...</li>
- * </ul>
- * </li>
- * <li>Support for advanced mathematical functions:
- * <ul>
- * <li><code>sqrt(x)</code></li>
- * <li><code>log(x)</code></li>
- * <li><code>exp(x)</code></li>
- * <li><code>sin(x)</code></li>
- * <li><code>cos(x)</code></li>
- * <li><code>tan(x)</code></li>
- * <li>...</li>
- * </ul>
- * </li>
- * <li>Methods to access parts of a value:
- * <ul>
- * <li><code>getMantissa()</code></li>
- * <li><code>getExponent()</code></li>
- * <li><code>getIntegralPart()</code></li>
- * <li><code>getFractionalPart()</code></li>
- * </ul>
- * </li>
- * <li>Equals and Hashcode methods:
- * <ul>
- * <li><code>equals(Object)</code> that returns whether two <code>BigFloat</code> values are mathematically the same</li>
- * <li><code>hashCode()</code> consistent with <code>equals(Object)</code></li>
- * </ul>
- * </li>
- * <li>Comparison methods:
- * <ul>
- * <li><code>isEqual(BigFloat)</code></li>
- * <li><code>isLessThan(BigFloat)</code></li>
- * <li><code>isLessThanOrEqual(BigFloat)</code></li>
- * <li><code>isGreaterThan(BigFloat)</code></li>
- * <li><code>isGreaterThanOrEqual(BigFloat)</code></li>
- * </ul>
- * </li>
- * </ul>
- *
- * <h1>Usage</h1>
- *
- * <p>Before doing any calculations you need to create a <code>Context</code> specifying the precision used for all calculations.</p>
- * <pre>
- * Context context = BigFloat.context(100); // precision of 100 digits
- * Context anotherContext = BigFloat.context(new MathContext(10, RoundingMode.HALF_UP); // precision of 10 digits, rounding half up
- * </pre>
- *
- * <p>The <code>Context</code> can then be used to create the first value of the calculation:</p>
- * <pre>
- * BigFloat value1 = context.valueOf(640320);
- * </pre>
- *
- * <p>The <code>BigFloat</code> instance holds a reference to the <code>Context</code>. This context is then passed from calculation to calculation.</p>
- * <pre>
- * BigFloat value2 = context.valueOf(640320).pow(3).divide(24);
- * BigFloat value3 = BigFloat.sin(value2);
- * </pre>
- *
- * <p>The <code>BigFloat</code> result can be converted to other numerical types:</p>
- * <pre>
- * BigDecimal bigDecimalValue = value3.toBigDecimal();
- * double doubleValue = value3.toDouble();
- * long longValue = value3.toLong();
- * int intValue = value3.toInt();
- * </pre>
- */
-@SuppressWarnings("WeakerAccess")
-public class BigFloat implements Comparable<BigFloat>, Serializable {
- private static final long serialVersionUID = -7323679117445486894L;
-
- /**
- * Represents a value that is not a number.
- * @see Double#NaN
- */
- public static final BigFloat NaN = new SpecialBigFloat(SpecialBigFloat.Type.NaN);
-
- /**
- * Represents the positive infinity.
- * @see Double#POSITIVE_INFINITY
- */
- public static final BigFloat POSITIVE_INFINITY = new SpecialBigFloat(SpecialBigFloat.Type.POSITIVE_INFINITY);
-
- /**
- * Represents the positive infinity.
- * @see Double#NEGATIVE_INFINITY
- */
- public static final BigFloat NEGATIVE_INFINITY = new SpecialBigFloat(SpecialBigFloat.Type.NEGATIVE_INFINITY);
-
- private final BigDecimal value;
- private final Context context;
-
- private BigFloat(BigDecimal value, Context context) {
- this.value = value;
- this.context = context;
- }
-
- /**
- * Creates a {@link Context} with the specified precision and {@link RoundingMode#HALF_UP} rounding.
- *
- * @param precision the precision
- *
- * @return the {@link Context}
- */
- public static Context context(int precision) {
- return new Context(new MathContext(precision));
- }
-
- /**
- * Creates a {@link Context} with the specified {@link MathContext}.
- *
- * @param mathContext the {@link MathContext}
- *
- * @return the {@link Context}
- */
- public static Context context(MathContext mathContext) {
- return new Context(mathContext);
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this + x</code>.
- *
- * <p>If the two values do not have the same {@link Context}, the result will contain the {@link Context} with the larger precision.</p>
- *
- * @param x the value to add
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#add(BigDecimal, MathContext)
- */
- public BigFloat add(BigFloat x) {
- if (x.isSpecial())
- return x.add(this);
- Context c = max(context, x.context);
- return c.valueOf(value.add(x.value, c.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this + x</code>.
- *
- * @param x the value to add
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#add(BigDecimal, MathContext)
- */
- public BigFloat add(BigDecimal x) {
- return add(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this + x</code>.
- *
- * @param x the value to add
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#add(BigDecimal, MathContext)
- */
- public BigFloat add(int x) {
- return add(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this + x</code>.
- *
- * @param x the value to add
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#add(BigDecimal, MathContext)
- */
- public BigFloat add(long x) {
- return add(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this + x</code>.
- *
- * @param x the value to add
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#add(BigDecimal, MathContext)
- */
- public BigFloat add(double x) {
- return add(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this - x</code>.
- *
- * <p>If the two values do not have the same {@link Context}, the result will contain the {@link Context} with the larger precision.</p>
- *
- * @param x the value to subtract
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#subtract(BigDecimal, MathContext)
- */
- public BigFloat subtract(BigFloat x) {
- if (x.isSpecial())
- return negate(x).add(this);
- Context c = max(context, x.context);
- return c.valueOf(value.subtract(x.value, c.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this - x</code>.
- *
- * @param x the value to subtract
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#subtract(BigDecimal, MathContext)
- */
- public BigFloat subtract(BigDecimal x) {
- return subtract(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this - x</code>.
- *
- * @param x the value to subtract
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#subtract(BigDecimal, MathContext)
- */
- public BigFloat subtract(int x) {
- return subtract(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this - x</code>.
- *
- * @param x the value to subtract
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#subtract(BigDecimal, MathContext)
- */
- public BigFloat subtract(long x) {
- return subtract(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this - x</code>.
- *
- * @param x the value to subtract
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#subtract(BigDecimal, MathContext)
- */
- public BigFloat subtract(double x) {
- return subtract(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this * x</code>.
- *
- * <p>If the two values do not have the same {@link Context}, the result will contain the {@link Context} with the larger precision.</p>
- *
- * @param x the value to multiply
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#multiply(BigDecimal, MathContext)
- */
- public BigFloat multiply(BigFloat x) {
- if (x.isSpecial())
- return x.multiply(this);
- Context c = max(context, x.context);
- return c.valueOf(value.multiply(x.value, c.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this * x</code>.
- *
- * @param x the value to multiply
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#multiply(BigDecimal, MathContext)
- */
- public BigFloat multiply(BigDecimal x) {
- return multiply(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this * x</code>.
- *
- * @param x the value to multiply
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#multiply(BigDecimal, MathContext)
- */
- public BigFloat multiply(int x) {
- return multiply(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this * x</code>.
- *
- * @param x the value to multiply
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#multiply(BigDecimal, MathContext)
- */
- public BigFloat multiply(long x) {
- return multiply(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this * x</code>.
- *
- * @param x the value to multiply
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#multiply(BigDecimal, MathContext)
- */
- public BigFloat multiply(double x) {
- return multiply(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this / x</code>.
- *
- * <p>If the two values do not have the same {@link Context},
- * the result will contain the {@link Context} with the larger precision.</p>
- *
- * @param x the value to divide with
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#divide(BigDecimal, MathContext)
- */
- public BigFloat divide(BigFloat x) {
- if (x.isSpecial()) {
- if (x == NaN) {
- return NaN;
- } else {
- return context.valueOf(0);
- }
- }
- if (this.isZero() && !x.isZero()) {
- return context.valueOf(0);
- }
- if (x.isZero()) {
- if (this.isZero()) {
- return NaN; // 0 or -0 / 0 = NaN
- } else if (this.isNegative()) {
- return NEGATIVE_INFINITY;// -N / 0 = -INF
- } else {
- return POSITIVE_INFINITY;// N / 0 = +INF
- }
- }
-
- Context c = max(context, x.context);
- return c.valueOf(value.divide(x.value, c.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this / x</code>.
- *
- * @param x the value to divide with
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#divide(BigDecimal, MathContext)
- */
- public BigFloat divide(BigDecimal x) {
- return divide(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this / x</code>.
- *
- * @param x the value to divide with
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#divide(BigDecimal, MathContext)
- */
- public BigFloat divide(int x) {
- return divide(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this / x</code>.
- *
- * @param x the value to divide with
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#divide(BigDecimal, MathContext)
- */
- public BigFloat divide(long x) {
- return divide(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this / x</code>.
- *
- * @param x the value to divide with
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#divide(BigDecimal, MathContext)
- */
- public BigFloat divide(double x) {
- return divide(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is the remainder when dividing <code>this</code> by <code>x</code>.
- *
- * <p>If the two values do not have the same {@link Context}, the result will contain the {@link Context} with the larger precision.</p>
- *
- * @param x the value to divide with
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#remainder(BigDecimal, MathContext)
- */
- public BigFloat remainder(BigFloat x) {
- if (x.isSpecial()) {
- if (x == NaN) {
- return NaN;
- } else {
- return this;
- }
- }
- if (this.isZero() && !x.isZero()) {
- return context.valueOf(0);
- }
- if (x.isZero()) {
- return NaN;
- }
-
- Context c = max(context, x.context);
- return c.valueOf(value.remainder(x.value, c.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is the remainder when dividing <code>this</code> by <code>x</code>.
- *
- * @param x the value to divide with
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#remainder(BigDecimal, MathContext)
- */
- public BigFloat remainder(BigDecimal x) {
- return remainder(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is the remainder when dividing <code>this</code> by <code>x</code>.
- *
- * @param x the value to divide with
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#remainder(BigDecimal, MathContext)
- */
- public BigFloat remainder(int x) {
- return remainder(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is the remainder when dividing <code>this</code> by <code>x</code>.
- *
- * @param x the value to divide with
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#remainder(BigDecimal, MathContext)
- */
- public BigFloat remainder(long x) {
- return remainder(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is the remainder when dividing <code>this</code> by <code>x</code>.
- *
- * @param x the value to divide with
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#remainder(BigDecimal, MathContext)
- */
- public BigFloat remainder(double x) {
- return remainder(context.valueOf(x));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this</code> to the power of <code>y</code>.
- *
- * <p>If the two values do not have the same {@link Context}, the result will contain the {@link Context} with the larger precision.</p>
- *
- * @param y the value of the power
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#pow(BigDecimal, BigDecimal, MathContext)
- */
- public BigFloat pow(BigFloat y) {
- if (y.isSpecial()) {
- if (this.isZero()) {
- if (y == POSITIVE_INFINITY) {
- return this;
- }
- if (y == NEGATIVE_INFINITY) {
- return POSITIVE_INFINITY;
- }
- }
- if (y == NEGATIVE_INFINITY) {
- return context.ZERO;
- }
- return y;
- }
- if (this.isZero()) {
- if (y.isNegative()) {
- return POSITIVE_INFINITY;
- }
- }
-
- Context c = max(context, y.context);
- return c.valueOf(BigDecimalMath.pow(this.value, y.value, c.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this</code> to the power of <code>y</code>.
- *
- * @param y the value of the power
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#pow(BigDecimal, BigDecimal, MathContext)
- */
- public BigFloat pow(BigDecimal y) {
- return pow(context.valueOf(y));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this</code> to the power of <code>y</code>.
- *
- * @param y the value of the power
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#pow(BigDecimal, BigDecimal, MathContext)
- */
- public BigFloat pow(int y) {
- return pow(context.valueOf(y));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this</code> to the power of <code>y</code>.
- *
- * @param y the value of the power
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#pow(BigDecimal, BigDecimal, MathContext)
- */
- public BigFloat pow(long y) {
- return pow(context.valueOf(y));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>this</code> to the power of <code>y</code>.
- *
- * @param y the value of the power
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#pow(BigDecimal, BigDecimal, MathContext)
- */
- public BigFloat pow(double y) {
- return pow(context.valueOf(y));
- }
-
- /**
- * Returns the {@link BigFloat} that is the <code>y</code>th root of <code>this</code>.
- *
- * <p>If the two values do not have the same {@link Context}, the result will contain the {@link Context} with the larger precision.</p>
- *
- * @param y the value of the root
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#root(BigDecimal, BigDecimal, MathContext)
- */
- public BigFloat root(BigFloat y) {
- if (y.isSpecial())
- return y;
- Context c = max(context, y.context);
- return c.valueOf(BigDecimalMath.root(this.value, y.value, c.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is the <code>y</code>th root of <code>this</code>.
- *
- * @param y the value of the root
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#root(BigDecimal, BigDecimal, MathContext)
- */
- public BigFloat root(BigDecimal y) {
- return root(context.valueOf(y));
- }
-
- /**
- * Returns the {@link BigFloat} that is the <code>y</code>th root of <code>this</code>.
- *
- * @param y the value of the root
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#root(BigDecimal, BigDecimal, MathContext)
- */
- public BigFloat root(int y) {
- return root(context.valueOf(y));
- }
-
- /**
- * Returns the {@link BigFloat} that is the <code>y</code>th root of <code>this</code>.
- *
- * @param y the value of the root
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#root(BigDecimal, BigDecimal, MathContext)
- */
- public BigFloat root(long y) {
- return root(context.valueOf(y));
- }
-
- /**
- * Returns the {@link BigFloat} that is the <code>y</code>th root of <code>this</code>.
- *
- * @param y the value of the root
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#root(BigDecimal, BigDecimal, MathContext)
- */
- public BigFloat root(double y) {
- return root(context.valueOf(y));
- }
-
- @Override
- public int hashCode() {
- return value.stripTrailingZeros().hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- BigFloat other = (BigFloat) obj;
-
- return value.compareTo(other.value) == 0;
- //return Objects.equals(value, other.value) && Objects.equals(context, other.context);
- }
-
- /**
- * Returns the signum function of this {@link BigFloat}.
- *
- * @return -1, 0, or 1 as the value of this {@link BigDecimal} is negative, zero, or positive.
- */
- public int signum() {
- return value.signum();
- }
-
- /**
- * Returns whether this {@link BigFloat} is negative.
- *
- * @return <code>true</code> if negative, <code>false</code> if 0 or positive
- */
- public boolean isNegative() {
- return value.signum() < 0;
- }
-
- /**
- * Returns whether this {@link BigFloat} is 0.
- *
- * @return <code>true</code> if 0, <code>false</code> if negative or positive
- */
- public boolean isZero() {
- return value.signum() == 0;
- }
-
- /**
- * Returns whether this {@link BigFloat} is positive.
- *
- * @return <code>true</code> if positive, <code>false</code> if 0 or negative
- */
- public boolean isPositive() {
- return value.signum() > 0;
- }
-
- @Override
- public int compareTo(BigFloat other) {
- if (other.isSpecial()) {
- return -other.compareTo(this);
- }
- return value.compareTo(other.value);
- }
-
- /**
- * Returns whether <code>this</code> value is mathematically equal to the <code>other</code> value.
- *
- * @param other the other {@link BigFloat} to compare with
- *
- * @return <code>true</code> if both values are mathematically equal (equivalent to <code>this.compareTo(other) == 0</code>
- *
- * @see #compareTo(BigFloat)
- */
- public boolean isEqual(BigFloat other) {
- if (this == NaN || other == NaN) {
- return false;
- }
-
- return compareTo(other) == 0;
- }
-
- /**
- * Returns whether <code>this</code> value is mathematically less than to the <code>other</code> value.
- *
- * @param other the other {@link BigFloat} to compare with
- *
- * @return <code>true</code> <code>this</code> value is mathematically less than to the <code>other</code> value (equivalent to <code>this.compareTo(other) &lt; 0</code>
- *
- * @see #compareTo(BigFloat)
- */
- public boolean isLessThan(BigFloat other) {
- if (this == NaN || other == NaN) {
- return false;
- }
-
- return compareTo(other) < 0;
- }
-
- /**
- * Returns whether <code>this</code> value is mathematically greater than to the <code>other</code> value.
- *
- * @param other the other {@link BigFloat} to compare with
- *
- * @return <code>true</code> <code>this</code> value is mathematically greater than to the <code>other</code> value (equivalent to <code>this.compareTo(other) &gt; 0</code>
- *
- * @see #compareTo(BigFloat)
- */
- public boolean isGreaterThan(BigFloat other) {
- if (this == NaN || other == NaN) {
- return false;
- }
-
- return compareTo(other) > 0;
- }
-
- /**
- * Returns whether <code>this</code> value is mathematically less than or equal to the <code>other</code> value.
- *
- * @param other the other {@link BigFloat} to compare with
- *
- * @return <code>true</code> <code>this</code> value is mathematically less than or equal to the <code>other</code> value (equivalent to <code>this.compareTo(other) &lt;= 0</code>
- *
- * @see #compareTo(BigFloat)
- * @see #isLessThan(BigFloat)
- * @see #isEqual(BigFloat)
- */
- public boolean isLessThanOrEqual(BigFloat other) {
- if (this == NaN || other == NaN) {
- return false;
- }
-
- return compareTo(other) <= 0;
- }
-
- /**
- * Returns whether <code>this</code> value is mathematically greater than or equal to the <code>other</code> value.
- *
- * @param other the other {@link BigFloat} to compare with
- *
- * @return <code>true</code> <code>this</code> value is mathematically greater than or equal to the <code>other</code> value (equivalent to <code>this.compareTo(other) &gt;= 0</code>
- *
- * @see #compareTo(BigFloat)
- * @see #isGreaterThan(BigFloat)
- * @see #isEqual(BigFloat)
- */
- public boolean isGreaterThanOrEqual(BigFloat other) {
- if (this == NaN || other == NaN) {
- return false;
- }
-
- return compareTo(other) >= 0;
- }
-
- /**
- * Returns whether <code>this</code> value can be represented as <code>int</code>.
- *
- * @return <code>true</code> if the value can be represented as <code>int</code> value
- *
- * @see BigDecimalMath#isIntValue(BigDecimal)
- */
- public boolean isIntValue() {
- return BigDecimalMath.isIntValue(value);
- }
-
- /**
- * Returns whether <code>this</code> specified {@link BigDecimal} value can be represented as <code>double</code>.
- *
- * @return <code>true</code> if the value can be represented as <code>double</code> value
- *
- * @see BigDecimalMath#isDoubleValue(BigDecimal)
- */
- public boolean isDoubleValue() {
- return BigDecimalMath.isDoubleValue(value);
- }
-
- /**
- * Returns the mantissa of <code>this</code> value written as <em>mantissa * 10<sup>exponent</sup></em>.
- *
- * <p>The mantissa is defined as having exactly 1 digit before the decimal point.</p>
- *
- * @return the mantissa
- *
- * @see #getExponent()
- * @see BigDecimalMath#mantissa(BigDecimal)
- */
- public BigFloat getMantissa() {
- return context.valueOf(BigDecimalMath.mantissa(value));
- }
-
- /**
- * Returns the exponent of <code>this</code> value written as <em>mantissa * 10<sup>exponent</sup></em>.
- *
- * <p>The mantissa is defined as having exactly 1 digit before the decimal point.</p>
- *
- * @return the exponent
- *
- * @see #getMantissa()
- * @see BigDecimalMath#exponent(BigDecimal)
- */
- public BigFloat getExponent() {
- return context.valueOf(BigDecimalMath.exponent(value));
- }
-
- /**
- * Returns the integral part of <code>this</code> value (left of the decimal point).
- *
- * @return the integral part
- *
- * @see #getFractionalPart()
- * @see BigDecimalMath#fractionalPart(BigDecimal)
- */
- public BigFloat getIntegralPart() {
- return context.valueOf(BigDecimalMath.integralPart(value));
- }
-
- /**
- * Returns the fractional part of <code>this</code> value (right of the decimal point).
- *
- * @return the fractional part
- *
- * @see #getIntegralPart()
- * @see BigDecimalMath#fractionalPart(BigDecimal)
- */
- public BigFloat getFractionalPart() {
- return context.valueOf(BigDecimalMath.fractionalPart(value));
- }
-
- /**
- * Returns the {@link Context} of <code>this</code> value.
- *
- * @return the {@link Context}
- */
- public Context getContext() {
- return context;
- }
-
- /**
- * Returns <code>this</code> value as a {@link BigDecimal} value.
- *
- * @return the {@link BigDecimal} value
- */
- public BigDecimal toBigDecimal() {
- return value;
- }
-
- /**
- * Returns <code>this</code> value as a <code>double</code> value.
- *
- * @return the <code>double</code> value
- *
- * @see BigDecimal#doubleValue()
- */
- public double toDouble() {
- return value.doubleValue();
- }
-
- /**
- * Returns <code>this</code> value as a <code>long</code> value.
- *
- * @return the <code>long</code> value
- *
- * @see BigDecimal#longValue()
- */
- public long toLong() {
- return value.longValue();
- }
-
- /**
- * Returns <code>this</code> value as a <code>int</code> value.
- *
- * @return the <code>int</code> value
- *
- * @see BigDecimal#intValue()
- */
- public int toInt() {
- return value.intValue();
- }
-
- @Override
- public String toString() {
- return value.toString();
- }
-
- protected boolean isSpecial() {
- return false;
- }
-
- /**
- * return special type of a value
- * @return {@link SpecialBigFloat.Type}
- */
- protected SpecialBigFloat.Type type() {
- return SpecialBigFloat.Type.NORMAL;
- }
-
- public boolean isNaN() {
- return this == NaN;
- }
-
- public boolean isInfinity() {
- return this == POSITIVE_INFINITY || this == NEGATIVE_INFINITY;
- }
-
- /**
- * this class handle unrepresentable value in floating-point arithmetic
- *
- * @author Wireless4024
- */
- private static final class SpecialBigFloat extends BigFloat {
-
- private static final Context DUMMY_CONTEXT = BigFloat.context(MathContext.DECIMAL32);
-
- private final Type type;
-
- private SpecialBigFloat(Type type) {
- super(null, DUMMY_CONTEXT);
- this.type = type;
- }
-
- @Override
- protected boolean isSpecial() {
- return true;
- }
-
- @Override
- protected Type type() {
- return type;
- }
-
- @Override
- public BigFloat add(BigFloat x) {
- if (!x.isSpecial()) {
- return this;
- }
- if (this == POSITIVE_INFINITY && x == POSITIVE_INFINITY) {
- return POSITIVE_INFINITY;
- }
- if (this == NEGATIVE_INFINITY && x == NEGATIVE_INFINITY) {
- return NEGATIVE_INFINITY;
- }
- return NaN;
- }
-
- @Override
- public BigFloat subtract(BigFloat x) {
- if (!x.isSpecial()) {
- return this;
- }
- if (this == POSITIVE_INFINITY && x == NEGATIVE_INFINITY) {
- return POSITIVE_INFINITY;
- }
- if (this == NEGATIVE_INFINITY && x == POSITIVE_INFINITY) {
- return NEGATIVE_INFINITY;
- }
- return NaN;
- }
-
- @Override
- public BigFloat subtract(BigDecimal x) {
- return this;
- }
-
- @Override
- public BigFloat multiply(BigFloat x) {
- if (x.isZero() || x == NaN) {
- return NaN;
- } else if (x.isNegative()) {
- return negate(this);
- } else {
- return this;
- }
- }
-
- @Override
- public BigFloat divide(BigFloat x) {
- if (x == NaN || (this.isInfinity() && x.isInfinity())) {
- return NaN;
- } else if (x.isNegative()) {
- return negate(this);
- } else {
- return this;
- }
- }
-
- @Override
- public BigFloat remainder(BigFloat x) {
- return NaN;
- }
-
- @Override
- public BigFloat pow(BigFloat y) {
- if (y.isZero()) {
- return y.context.ONE;
- }
- if (y == NaN) {
- return NaN;
- }
- if (this.isInfinity() && y.isNegative()) {
- return y.context.ZERO;
- }
- if (this == NEGATIVE_INFINITY && y.isPositive()) {
- return POSITIVE_INFINITY;
- }
- return this;
- }
-
- @Override
- public BigFloat root(BigFloat y) {
- return this;
- }
-
- @Override
- public int hashCode() {
- return type.hashCode;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- return obj instanceof BigFloat && ((BigFloat) obj).isSpecial() && ((BigFloat) obj).type() == this.type;
- }
-
- @Override
- public int signum() {
- return type == Type.POSITIVE_INFINITY ? 1 : -1;
- }
-
- @Override
- public boolean isNegative() {
- return signum() < 0;
- }
-
- @Override
- public boolean isZero() {
- return false;//nan or infinity is not a zero
- }
-
- @Override
- public boolean isPositive() {
- return signum() > 0;
- }
-
- @Override
- public int compareTo(BigFloat other) {
- return Type.compare(type, other.type());
- }
-
- @Override
- public boolean isIntValue() {
- return false;
- }
-
- @Override
- public boolean isDoubleValue() {
- return false;
- }
-
- @Override
- public BigFloat getMantissa() {
- return this;
- }
-
- @Override
- public BigFloat getExponent() {
- return this;
- }
-
- @Override
- public BigFloat getIntegralPart() {
- return this;
- }
-
- @Override
- public BigFloat getFractionalPart() {
- return this;
- }
-
- @Override
- public Context getContext() {
- throw new UnsupportedOperationException(type + " has no context");
- }
-
- @Override
- public BigDecimal toBigDecimal() {
- throw new UnsupportedOperationException(type + " has no corresponding BigDecimal representation");
- }
-
- @Override
- public double toDouble() {
- return type.toDouble();
- }
-
- @Override
- public long toLong() {
- return (long) toDouble();
- }
-
- @Override
- public int toInt() {
- return (int) toDouble();
- }
-
- @Override
- public String toString() {
- return type.toString();
- }
-
- //optional static
- enum Type {
- NaN(Objects.hashCode(Double.NaN)),
- POSITIVE_INFINITY(Objects.hashCode(Double.POSITIVE_INFINITY)),
- NORMAL(Objects.hashCode(0)),
- NEGATIVE_INFINITY(Objects.hashCode(Double.NEGATIVE_INFINITY));
-
- final int hashCode;
-
- Type(int hashCode){
- this.hashCode=hashCode;
- }
-
- public static int compare(Type a, Type b) {
- //we can use double to compare
- //if (a == NaN && b == NaN)
- // return 0;//cuz NaN equals nothing even itself
- return Double.compare(a.toDouble(),b.toDouble());
- }
-
- /**
- * convert type to double
- * @return double value that equivalent to {@link Type}
- */
- public double toDouble() {
- switch (this) {
- case POSITIVE_INFINITY:
- return Double.POSITIVE_INFINITY;
- case NEGATIVE_INFINITY:
- return Double.NEGATIVE_INFINITY;
- case NaN:
- return Double.NaN;
- default:
- return 0;
- }
- }
- }
- }
-
- /**
- * Manages the {@link MathContext} and provides factory methods for {@link BigFloat} values.
- */
- public static class Context implements Serializable{
- private static final long serialVersionUID = -5787473786808803161L;
- public final BigFloat NEGATIVE_ONE;
- public final BigFloat ZERO;
- public final BigFloat ONE;
-
- private final MathContext mathContext;
-
- private Context(MathContext mathContext) {
- this.mathContext = mathContext;
- NEGATIVE_ONE = this.valueOf(-1);
- ZERO = this.valueOf(0);
- ONE = this.valueOf(1);
- }
-
- /**
- * Returns the {@link MathContext} of this context.
- *
- * @return the {@link MathContext}
- */
- public MathContext getMathContext() {
- return mathContext;
- }
-
- /**
- * Returns the precision of this context.
- * <p>
- * This is equivalent to calling <code>getMathContext().getPrecision()</code>.
- *
- * @return the precision
- */
- public int getPrecision() {
- return mathContext.getPrecision();
- }
-
- /**
- * Returns the {@link RoundingMode} of this context.
- * <p>
- * This is equivalent to calling <code>getMathContext().getRoundingMode()</code>.
- *
- * @return the {@link RoundingMode}
- */
- public RoundingMode getRoundingMode() {
- return mathContext.getRoundingMode();
- }
-
- /**
- * Creates a {@link BigFloat} value with this context.
- *
- * @param value the source {@link BigFloat} value
- *
- * @return the {@link BigFloat} value with this context (rounded to the precision of this context)
- */
- public BigFloat valueOf(BigFloat value) {
- return value.isSpecial() ? value : new BigFloat(value.value.round(mathContext), this);//they are final
- }
-
- /**
- * Creates a {@link BigFloat} value with this context.
- *
- * @param value the source {@link BigDecimal} value
- *
- * @return the {@link BigFloat} value with this context (rounded to the precision of this context)
- */
- public BigFloat valueOf(BigDecimal value) {
- return new BigFloat(value.round(mathContext), this);
- }
-
- /**
- * Creates a {@link BigFloat} value with this context.
- *
- * @param value the source int value
- *
- * @return the {@link BigFloat} value with this context (rounded to the precision of this context)
- */
- public BigFloat valueOf(int value) {
- return new BigFloat(new BigDecimal(value, mathContext), this);
- }
-
- /**
- * parse unsigned value with this logic <pre><code>value &amp; 4294967295</code></pre>
- * @param value an int value
- * @param unsigned if true value will parse as unsigned integer
- * @return the {@link BigFloat} value with this context (rounded to the precision of this context)
- */
- public BigFloat valueOf(int value, boolean unsigned) {
- if (!unsigned) {
- return new BigFloat(new BigDecimal(value, mathContext), this);
- } else {
- if (value > -1)
- return valueOf(value, false);
- return new BigFloat(new BigDecimal(Integer.MAX_VALUE)
- .add(new BigDecimal(value & Integer.MAX_VALUE))
- .add(BigDecimal.ONE), this);
- }
- }
-
- /**
- * Creates a {@link BigFloat} value with this context.
- *
- * @param value the source long value
- *
- * @return the {@link BigFloat} value with this context (rounded to the precision of this context)
- */
- public BigFloat valueOf(long value) {
- return new BigFloat(new BigDecimal(value, mathContext), this);
- }
-
- /**
- * parse unsigned value with this logic <pre><code>value &amp; 18446744073709551615</code></pre>
- * @param value an int value
- * @param unsigned if true value will parse as unsigned integer
- * @return the {@link BigFloat} value with this context (rounded to the precision of this context)
- */
- public BigFloat valueOf(long value, boolean unsigned) {
- if (!unsigned) {
- return new BigFloat(new BigDecimal(value, mathContext), this);
- } else {
- if (value > -1)
- return valueOf(value, false);
- return new BigFloat(new BigDecimal(Long.MAX_VALUE)
- .add(new BigDecimal(value & Long.MAX_VALUE))
- .add(BigDecimal.ONE), this);
- }
- }
-
- /**
- * Creates a {@link BigFloat} value with this context.
- *
- * @param value the source double value
- *
- * @return the {@link BigFloat} value with this context (rounded to the precision of this context)
- */
- public BigFloat valueOf(double value) {
- if (Double.isInfinite(value))
- return value == Double.POSITIVE_INFINITY ? POSITIVE_INFINITY : NEGATIVE_INFINITY;
- else if (Double.isNaN(value))
- return NaN;
- return new BigFloat(new BigDecimal(String.valueOf(value), mathContext), this);
- }
-
- /**
- * Creates a {@link BigFloat} value with this context.
- *
- * @param value the source String value
- *
- * @return the {@link BigFloat} value with this context (rounded to the precision of this context)
- *
- * @throws NumberFormatException if the value is not a valid number.
- */
- public BigFloat valueOf(String value) {
- return new BigFloat(new BigDecimal(value, mathContext), this);
- }
-
- /**
- * Returns the constant pi with this context.
- *
- * @return pi with this context (rounded to the precision of this context)
- *
- * @see BigDecimalMath#pi(MathContext)
- */
- public BigFloat pi() {
- return valueOf(BigDecimalMath.pi(mathContext));
- }
-
- /**
- * Returns the constant e with this context.
- *
- * @return e with this context (rounded to the precision of this context)
- *
- * @see BigDecimalMath#e(MathContext)
- */
- public BigFloat e() {
- return valueOf(BigDecimalMath.e(mathContext));
- }
-
- /**
- * Returns the factorial of n with this context.
- *
- * @param n the value to calculate
- *
- * @return the factorial of n with this context (rounded to the precision of this context)
- *
- * @see BigDecimalMath#factorial(int)
- */
- public BigFloat factorial(int n) {
- return valueOf(BigDecimalMath.factorial(n));
- }
-
- @Override
- public int hashCode() {
- return mathContext.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Context other = (Context) obj;
- return mathContext.equals(other.mathContext);
- }
-
- @Override
- public String toString() {
- return mathContext.toString();
- }
- }
- /**
- * Returns the {@link BigFloat} that is <code>- this</code>.
- *
- * @param x the value to negate
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#negate(MathContext)
- */
- public static BigFloat negate(BigFloat x) {
- if (x.isSpecial())
- if (x.isInfinity())
- return x == POSITIVE_INFINITY ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
- else
- return NaN;
- return x.context.valueOf(x.value.negate());
- }
-
- /**
- * Returns the {@link BigFloat} that is the <code>abs(this)</code> (absolute value).
- *
- * @param x the value to make absolute
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimal#abs(MathContext)
- */
- public static BigFloat abs(BigFloat x) {
- if (x.isSpecial())
- return x.isInfinity() ? POSITIVE_INFINITY : NaN;
- return x.context.valueOf(x.value.abs());
- }
-
- /**
- * Returns the the maximum of two {@link BigFloat} values.
- *
- * @param value1 the first {@link BigFloat} value to compare
- * @param value2 the second {@link BigFloat} value to compare
- *
- * @return the maximum {@link BigFloat} value
- */
- public static BigFloat max(BigFloat value1, BigFloat value2) {
- return value1.compareTo(value2) >= 0 ? value1 : value2;
- }
-
- /**
- * Returns the the maximum of n {@link BigFloat} values.
- *
- * @param value1 the first {@link BigFloat} value to compare
- * @param values the other {@link BigFloat}s value to compare
- *
- * @return the maximum {@link BigFloat} value
- */
- public static BigFloat max(BigFloat value1, BigFloat... values) {
- BigFloat result = value1;
-
- for (BigFloat other : values) {
- result = max(result, other);
- }
-
- return result;
- }
-
- /**
- * Returns the the minimum of two {@link BigFloat} values.
- *
- * @param value1 the first {@link BigFloat} value to compare
- * @param value2 the second {@link BigFloat} value to compare
- *
- * @return the minimum {@link BigFloat} value
- */
- public static BigFloat min(BigFloat value1, BigFloat value2) {
- return value1.compareTo(value2) < 0 ? value1 : value2;
- }
-
- /**
- * Returns the the minimum of n {@link BigFloat} values.
- *
- * @param value1 the first {@link BigFloat} value to compare
- * @param values the other {@link BigFloat}s value to compare
- *
- * @return the minimum {@link BigFloat} value
- */
- public static BigFloat min(BigFloat value1, BigFloat... values) {
- BigFloat result = value1;
-
- for (BigFloat other : values) {
- result = min(result, other);
- }
-
- return result;
- }
-
- private static BigFloat logSpecial(BigFloat val){
- if (val.isNaN() || val.isNegative())
- return NaN;
- if (val == POSITIVE_INFINITY)
- return POSITIVE_INFINITY;
- if (val.isZero())
- return NEGATIVE_INFINITY;
- return null;
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>log(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#log(BigDecimal, MathContext)
- */
- public static BigFloat log(BigFloat x) {
- BigFloat temp = logSpecial(x);
- return temp != null ? temp : x.context.valueOf(BigDecimalMath.log(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>log2(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#log2(BigDecimal, MathContext)
- */
- public static BigFloat log2(BigFloat x) {
- BigFloat temp = logSpecial(x);
- return temp != null ? temp : x.context.valueOf(BigDecimalMath.log2(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>log10(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#log10(BigDecimal, MathContext)
- */
- public static BigFloat log10(BigFloat x) {
- BigFloat temp = logSpecial(x);
- return temp != null ? temp : x.context.valueOf(BigDecimalMath.log10(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>exp(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#exp(BigDecimal, MathContext)
- */
- public static BigFloat exp(BigFloat x) {
- if(x.isSpecial())
- return x != NEGATIVE_INFINITY ? x : x.context.ZERO;
- return x.context.valueOf(BigDecimalMath.exp(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>sqrt(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#sqrt(BigDecimal, MathContext)
- */
- public static BigFloat sqrt(BigFloat x) {
- if (x.isNaN() || x.isNegative())
- return NaN;
- if (x.isZero() || x.isInfinity())
- return x;
- return x.context.valueOf(BigDecimalMath.sqrt(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>pow(x, y)</code>.
- *
- * <p>If the two values do not have the same {@link Context}, the result will contain the {@link Context} with the larger precision.</p>
- *
- * @param x the {@link BigFloat} value to take to the power
- * @param y the {@link BigFloat} value to serve as exponent
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#pow(BigDecimal, BigDecimal, MathContext)
- */
- public static BigFloat pow(BigFloat x, BigFloat y) {
- Context c = max(x.context, y.context);
- return c.valueOf(BigDecimalMath.pow(x.value, y.value, c.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>root(x, y)</code>.
- *
- * <p>If the two values do not have the same {@link Context}, the result will contain the {@link Context} with the larger precision.</p>
- *
- * @param x the {@link BigFloat} value to calculate the n'th root
- * @param y the {@link BigFloat} defining the root
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#pow(BigDecimal, BigDecimal, MathContext)
- */
- public static BigFloat root(BigFloat x, BigFloat y) {
- Context c = max(x.context, y.context);
- return c.valueOf(BigDecimalMath.root(x.value, y.value, c.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>sin(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#sin(BigDecimal, MathContext)
- */
- public static BigFloat sin(BigFloat x) {
- if(x.isSpecial())
- return NaN;
- if(x.isZero())
- return x;
- return x.context.valueOf(BigDecimalMath.sin(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>cos(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#cos(BigDecimal, MathContext)
- */
- public static BigFloat cos(BigFloat x) {
- if(x.isSpecial())
- return NaN;
- return x.context.valueOf(BigDecimalMath.cos(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>tan(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#tan(BigDecimal, MathContext)
- */
- public static BigFloat tan(BigFloat x) {
- if(x.isSpecial())
- return NaN;
- if(x.isZero())
- return x;
- return x.context.valueOf(BigDecimalMath.tan(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>cot(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#cot(BigDecimal, MathContext)
- */
- public static BigFloat cot(BigFloat x) {
- if(x.isSpecial())
- return x;
- if(x.isZero())
- return POSITIVE_INFINITY;
- return x.context.valueOf(BigDecimalMath.cot(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>asin(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#asin(BigDecimal, MathContext)
- */
- public static BigFloat asin(BigFloat x) {
- if (x.isZero())
- return x;
- return x.isNaN() || (!isRangeAbs1(x)) ? NaN :
- x.context.valueOf(BigDecimalMath.asin(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>acos(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#acos(BigDecimal, MathContext)
- */
- public static BigFloat acos(BigFloat x) {
- return x.isNaN() || (!isRangeAbs1(x)) ? NaN :
- x.context.valueOf(BigDecimalMath.acos(x.value, x.context.mathContext));
- }
-
- /**
- * @param x a bigfloat
- * @return if abs(x) <= 1
- */
- private static boolean isRangeAbs1(BigFloat x) {
- return isBetween(x.context.NEGATIVE_ONE, x.context.ONE, x);
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>atan(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#atan(BigDecimal, MathContext)
- */
- public static BigFloat atan(BigFloat x) {
- return x.isSpecial() || x.isZero() ? x : x.context.valueOf(BigDecimalMath.atan(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>acot(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#acot(BigDecimal, MathContext)
- */
- public static BigFloat acot(BigFloat x) {
- return x.isSpecial() ? x : x.context.valueOf(BigDecimalMath.acot(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>sinh(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#sinh(BigDecimal, MathContext)
- */
- public static BigFloat sinh(BigFloat x) {
- if (x.isSpecial() || x.isZero())
- return x;
- return x.context.valueOf(BigDecimalMath.sinh(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>cosh(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#cosh(BigDecimal, MathContext)
- */
- public static BigFloat cosh(BigFloat x) {
- if (x.isNaN())
- return NaN;
- if (x.isInfinity())
- return POSITIVE_INFINITY;
- if (x.isZero())
- return x.context.ONE;
- return x.context.valueOf(BigDecimalMath.cosh(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>tanh(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#tanh(BigDecimal, MathContext)
- */
- public static BigFloat tanh(BigFloat x) {
- if (x.isNaN() || x.isZero())
- return x;
- if (x.isInfinity())
- return x == POSITIVE_INFINITY ? x.context.ONE : x.context.NEGATIVE_ONE;
- return x.context.valueOf(BigDecimalMath.tanh(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>coth(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#coth(BigDecimal, MathContext)
- */
- public static BigFloat coth(BigFloat x) {
- if(x.isSpecial())
- return x;
- return x.context.valueOf(BigDecimalMath.coth(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>asinh(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#asinh(BigDecimal, MathContext)
- */
- public static BigFloat asinh(BigFloat x) {
- if(x.isSpecial())
- return x;
- return x.context.valueOf(BigDecimalMath.asinh(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>acosh(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#acosh(BigDecimal, MathContext)
- */
- public static BigFloat acosh(BigFloat x) {
- return x.context.valueOf(BigDecimalMath.acosh(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>atanh(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#atanh(BigDecimal, MathContext)
- */
- public static BigFloat atanh(BigFloat x) {
- if(x.isSpecial())
- return x;
- return x.context.valueOf(BigDecimalMath.atanh(x.value, x.context.mathContext));
- }
-
- /**
- * Returns the {@link BigFloat} that is <code>acoth(x)</code>.
- *
- * @param x the value
- *
- * @return the resulting {@link BigFloat}
- *
- * @see BigDecimalMath#acoth(BigDecimal, MathContext)
- */
- public static BigFloat acoth(BigFloat x) {
- if(x.isSpecial())
- return x;
- return x.context.valueOf(BigDecimalMath.acoth(x.value, x.context.mathContext));
- }
-
- public static boolean isBetween(BigFloat min, BigFloat max, BigFloat value) {
- return value.compareTo(min) >= 0 && value.compareTo(max) <= 0;
- }
-
- private static Context max(Context left, Context right) {
- return left.mathContext.getPrecision() > right.mathContext.getPrecision() ? left : right;
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/BigRational.java b/src/main/java/ch/obermuhlner/math/big/BigRational.java
deleted file mode 100644
index 2d7389c7de..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/BigRational.java
+++ /dev/null
@@ -1,1103 +0,0 @@
-package ch.obermuhlner.math.big;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.math.MathContext;
-import java.math.RoundingMode;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.IntStream;
-
-/**
- * A rational number represented as a quotient of two values.
- *
- * <p>Basic calculations with rational numbers (+ - * /) have no loss of precision.
- * This allows to use {@link BigRational} as a replacement for {@link BigDecimal} if absolute accuracy is desired.</p>
- *
- * <p><a href="http://en.wikipedia.org/wiki/Rational_number">Wikipedia: Rational number</a></p>
- *
- * <p>The values are internally stored as {@link BigDecimal} (for performance optimizations) but represented
- * as {@link BigInteger} (for mathematical correctness)
- * when accessed with {@link #getNumeratorBigInteger()} and {@link #getDenominatorBigInteger()}.</p>
- *
- * <p>The following basic calculations have no loss of precision:</p>
- * <ul>
- * <li>{@link #add(BigRational)}</li>
- * <li>{@link #subtract(BigRational)}</li>
- * <li>{@link #multiply(BigRational)}</li>
- * <li>{@link #divide(BigRational)}</li>
- * <li>{@link #pow(int)}</li>
- * </ul>
- *
- * <p>The following calculations are special cases of the ones listed above and have no loss of precision:</p>
- * <ul>
- * <li>{@link #negate()}</li>
- * <li>{@link #reciprocal()}</li>
- * <li>{@link #increment()}</li>
- * <li>{@link #decrement()}</li>
- * </ul>
- *
- * <p>Any {@link BigRational} value can be converted into an arbitrary {@link #withPrecision(int) precision} (number of significant digits)
- * or {@link #withScale(int) scale} (number of digits after the decimal point).</p>
- */
-public class BigRational implements Comparable<BigRational> {
-
- /**
- * The value 0 as {@link BigRational}.
- */
- public static final BigRational ZERO = new BigRational(0);
- /**
- * The value 1 as {@link BigRational}.
- */
- public static final BigRational ONE = new BigRational(1);
- /**
- * The value 2 as {@link BigRational}.
- */
- public static final BigRational TWO = new BigRational(2);
- /**
- * The value 10 as {@link BigRational}.
- */
- public static final BigRational TEN = new BigRational(10);
-
- private final BigDecimal numerator;
-
- private final BigDecimal denominator;
-
- private BigRational(int value) {
- this(BigDecimal.valueOf(value), BigDecimal.ONE);
- }
-
- private BigRational(BigDecimal num, BigDecimal denom) {
- BigDecimal n = num;
- BigDecimal d = denom;
-
- if (d.signum() == 0) {
- throw new ArithmeticException("Divide by zero");
- }
-
- if (d.signum() < 0) {
- n = n.negate();
- d = d.negate();
- }
-
- numerator = n;
- denominator = d;
- }
-
- /**
- * Returns the numerator of this rational number as BigInteger.
- *
- * @return the numerator as BigInteger
- */
- public BigInteger getNumeratorBigInteger() {
- return numerator.toBigInteger();
- }
-
- /**
- * Returns the numerator of this rational number as BigDecimal.
- *
- * @return the numerator as BigDecimal
- */
- public BigDecimal getNumerator() {
- return numerator;
- }
-
- /**
- * Returns the denominator of this rational number as BigInteger.
- *
- * <p>Guaranteed to not be 0.</p>
- * <p>Guaranteed to be positive.</p>
- *
- * @return the denominator as BigInteger
- */
- public BigInteger getDenominatorBigInteger() {
- return denominator.toBigInteger();
- }
-
- /**
- * Returns the denominator of this rational number as BigDecimal.
- *
- * <p>Guaranteed to not be 0.</p>
- * <p>Guaranteed to be positive.</p>
- *
- * @return the denominator as BigDecimal
- */
- public BigDecimal getDenominator() {
- return denominator;
- }
-
- /**
- * Reduces this rational number to the smallest numerator/denominator with the same value.
- *
- * @return the reduced rational number
- */
- public BigRational reduce() {
- BigInteger n = numerator.toBigInteger();
- BigInteger d = denominator.toBigInteger();
-
- BigInteger gcd = n.gcd(d);
- n = n.divide(gcd);
- d = d.divide(gcd);
-
- return valueOf(n, d);
- }
-
- /**
- * Returns the integer part of this rational number.
- *
- * <p>Examples:</p>
- * <ul>
- * <li><code>BigRational.valueOf(3.5).integerPart()</code> returns <code>BigRational.valueOf(3)</code></li>
- * </ul>
- *
- * @return the integer part of this rational number
- */
- public BigRational integerPart() {
- return of(numerator.subtract(numerator.remainder(denominator)), denominator);
- }
-
- /**
- * Returns the fraction part of this rational number.
- *
- * <p>Examples:</p>
- * <ul>
- * <li><code>BigRational.valueOf(3.5).integerPart()</code> returns <code>BigRational.valueOf(0.5)</code></li>
- * </ul>
- *
- * @return the fraction part of this rational number
- */
- public BigRational fractionPart() {
- return of(numerator.remainder(denominator), denominator);
- }
-
- /**
- * Negates this rational number (inverting the sign).
- *
- * <p>The result has no loss of precision.</p>
- *
- * <p>Examples:</p>
- * <ul>
- * <li><code>BigRational.valueOf(3.5).negate()</code> returns <code>BigRational.valueOf(-3.5)</code></li>
- * </ul>
- *
- * @return the negated rational number
- */
- public BigRational negate() {
- if (isZero()) {
- return this;
- }
-
- return of(numerator.negate(), denominator);
- }
-
- /**
- * Calculates the reciprocal of this rational number (1/x).
- *
- * <p>The result has no loss of precision.</p>
- *
- * <p>Examples:</p>
- * <ul>
- * <li><code>BigRational.valueOf(0.5).reciprocal()</code> returns <code>BigRational.valueOf(2)</code></li>
- * <li><code>BigRational.valueOf(-2).reciprocal()</code> returns <code>BigRational.valueOf(-0.5)</code></li>
- * </ul>
- *
- * @return the reciprocal rational number
- * @throws ArithmeticException if this number is 0 (division by zero)
- */
- public BigRational reciprocal() {
- return of(denominator, numerator);
- }
-
- /**
- * Returns the absolute value of this rational number.
- *
- * <p>The result has no loss of precision.</p>
- *
- * <p>Examples:</p>
- * <ul>
- * <li><code>BigRational.valueOf(-2).abs()</code> returns <code>BigRational.valueOf(2)</code></li>
- * <li><code>BigRational.valueOf(2).abs()</code> returns <code>BigRational.valueOf(2)</code></li>
- * </ul>
- *
- * @return the absolute rational number (positive, or 0 if this rational is 0)
- */
- public BigRational abs() {
- return isPositive() ? this : negate();
- }
-
- /**
- * Returns the signum function of this rational number.
- *
- * @return -1, 0 or 1 as the value of this rational number is negative, zero or positive.
- */
- public int signum() {
- return numerator.signum();
- }
-
- /**
- * Calculates the increment of this rational number (+ 1).
- *
- * <p>This is functionally identical to
- * <code>this.add(BigRational.ONE)</code>
- * but slightly faster.</p>
- *
- * <p>The result has no loss of precision.</p>
- *
- * @return the incremented rational number
- */
- public BigRational increment() {
- return of(numerator.add(denominator), denominator);
- }
-
- /**
- * Calculates the decrement of this rational number (- 1).
- *
- * <p>This is functionally identical to
- * <code>this.subtract(BigRational.ONE)</code>
- * but slightly faster.</p>
- *
- * <p>The result has no loss of precision.</p>
- *
- * @return the decremented rational number
- */
- public BigRational decrement() {
- return of(numerator.subtract(denominator), denominator);
- }
-
- /**
- * Calculates the addition (+) of this rational number and the specified argument.
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the rational number to add
- * @return the resulting rational number
- */
- public BigRational add(BigRational value) {
- if (denominator.equals(value.denominator)) {
- return of(numerator.add(value.numerator), denominator);
- }
-
- BigDecimal n = numerator.multiply(value.denominator).add(value.numerator.multiply(denominator));
- BigDecimal d = denominator.multiply(value.denominator);
- return of(n, d);
- }
-
- private BigRational add(BigDecimal value) {
- return of(numerator.add(value.multiply(denominator)), denominator);
- }
-
- /**
- * Calculates the addition (+) of this rational number and the specified argument.
- *
- * <p>This is functionally identical to
- * <code>this.add(BigRational.valueOf(value))</code>
- * but slightly faster.</p>
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the {@link BigInteger} to add
- * @return the resulting rational number
- */
- public BigRational add(BigInteger value) {
- if (value.equals(BigInteger.ZERO)) {
- return this;
- }
- return add(new BigDecimal(value));
- }
-
- /**
- * Calculates the addition (+) of this rational number and the specified argument.
- *
- * <p>This is functionally identical to
- * <code>this.add(BigRational.valueOf(value))</code>
- * but slightly faster.</p>
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the int value to add
- * @return the resulting rational number
- */
- public BigRational add(int value) {
- if (value == 0) {
- return this;
- }
- return add(BigInteger.valueOf(value));
- }
-
- /**
- * Calculates the subtraction (-) of this rational number and the specified argument.
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the rational number to subtract
- * @return the resulting rational number
- */
- public BigRational subtract(BigRational value) {
- if (denominator.equals(value.denominator)) {
- return of(numerator.subtract(value.numerator), denominator);
- }
-
- BigDecimal n = numerator.multiply(value.denominator).subtract(value.numerator.multiply(denominator));
- BigDecimal d = denominator.multiply(value.denominator);
- return of(n, d);
- }
-
- private BigRational subtract(BigDecimal value) {
- return of(numerator.subtract(value.multiply(denominator)), denominator);
- }
-
- /**
- * Calculates the subtraction (-) of this rational number and the specified argument.
- *
- * <p>This is functionally identical to
- * <code>this.subtract(BigRational.valueOf(value))</code>
- * but slightly faster.</p>
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the {@link BigInteger} to subtract
- * @return the resulting rational number
- */
- public BigRational subtract(BigInteger value) {
- if (value.equals(BigInteger.ZERO)) {
- return this;
- }
- return subtract(new BigDecimal(value));
- }
-
- /**
- * Calculates the subtraction (-) of this rational number and the specified argument.
- *
- * <p>This is functionally identical to
- * <code>this.subtract(BigRational.valueOf(value))</code>
- * but slightly faster.</p>
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the int value to subtract
- * @return the resulting rational number
- */
- public BigRational subtract(int value) {
- if (value == 0) {
- return this;
- }
- return subtract(BigInteger.valueOf(value));
- }
-
- /**
- * Calculates the multiplication (*) of this rational number and the specified argument.
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the rational number to multiply
- * @return the resulting rational number
- */
- public BigRational multiply(BigRational value) {
- if (isZero() || value.isZero()) {
- return ZERO;
- }
- if (equals(ONE)) {
- return value;
- }
- if (value.equals(ONE)) {
- return this;
- }
-
- BigDecimal n = numerator.multiply(value.numerator);
- BigDecimal d = denominator.multiply(value.denominator);
- return of(n, d);
- }
-
- // private, because we want to hide that we use BigDecimal internally
- private BigRational multiply(BigDecimal value) {
- BigDecimal n = numerator.multiply(value);
- BigDecimal d = denominator;
- return of(n, d);
- }
-
- /**
- * Calculates the multiplication (*) of this rational number and the specified argument.
- *
- * <p>This is functionally identical to
- * <code>this.multiply(BigRational.valueOf(value))</code>
- * but slightly faster.</p>
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the {@link BigInteger} to multiply
- * @return the resulting rational number
- */
- public BigRational multiply(BigInteger value) {
- if (isZero() || value.signum() == 0) {
- return ZERO;
- }
- if (equals(ONE)) {
- return valueOf(value);
- }
- if (value.equals(BigInteger.ONE)) {
- return this;
- }
-
- return multiply(new BigDecimal(value));
- }
-
- /**
- * Calculates the multiplication (*) of this rational number and the specified argument.
- *
- * <p>This is functionally identical to
- * <code>this.multiply(BigRational.valueOf(value))</code>
- * but slightly faster.</p>
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the int value to multiply
- * @return the resulting rational number
- */
- public BigRational multiply(int value) {
- return multiply(BigInteger.valueOf(value));
- }
-
- /**
- * Calculates the division (/) of this rational number and the specified argument.
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the rational number to divide (0 is not allowed)
- * @return the resulting rational number
- * @throws ArithmeticException if the argument is 0 (division by zero)
- */
- public BigRational divide(BigRational value) {
- if (value.equals(ONE)) {
- return this;
- }
-
- BigDecimal n = numerator.multiply(value.denominator);
- BigDecimal d = denominator.multiply(value.numerator);
- return of(n, d);
- }
-
- private BigRational divide(BigDecimal value) {
- BigDecimal n = numerator;
- BigDecimal d = denominator.multiply(value);
- return of(n, d);
- }
-
- /**
- * Calculates the division (/) of this rational number and the specified argument.
- *
- * <p>This is functionally identical to
- * <code>this.divide(BigRational.valueOf(value))</code>
- * but slightly faster.</p>
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the {@link BigInteger} to divide (0 is not allowed)
- * @return the resulting rational number
- * @throws ArithmeticException if the argument is 0 (division by zero)
- */
- public BigRational divide(BigInteger value) {
- if (value.equals(BigInteger.ONE)) {
- return this;
- }
-
- return divide(new BigDecimal(value));
- }
-
- /**
- * Calculates the division (/) of this rational number and the specified argument.
- *
- * <p>This is functionally identical to
- * <code>this.divide(BigRational.valueOf(value))</code>
- * but slightly faster.</p>
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param value the int value to divide (0 is not allowed)
- * @return the resulting rational number
- * @throws ArithmeticException if the argument is 0 (division by zero)
- */
- public BigRational divide(int value) {
- return divide(BigInteger.valueOf(value));
- }
-
- /**
- * Returns whether this rational number is zero.
- *
- * @return <code>true</code> if this rational number is zero (0), <code>false</code> if it is not zero
- */
- public boolean isZero() {
- return numerator.signum() == 0;
- }
-
- private boolean isPositive() {
- return numerator.signum() > 0;
- }
-
- /**
- * Returns whether this rational number is an integer number without fraction part.
- *
- * @return <code>true</code> if this rational number is an integer number, <code>false</code> if it has a fraction part
- */
- public boolean isInteger() {
- return isIntegerInternal() || reduce().isIntegerInternal();
- }
-
- /**
- * Returns whether this rational number is an integer number without fraction part.
- *
- * <p>Will return <code>false</code> if this number is not reduced to the integer representation yet (e.g. 4/4 or 4/2)</p>
- *
- * @return <code>true</code> if this rational number is an integer number, <code>false</code> if it has a fraction part
- * @see #isInteger()
- */
- private boolean isIntegerInternal() {
- return denominator.compareTo(BigDecimal.ONE) == 0;
- }
-
- /**
- * Calculates this rational number to the power (x<sup>y</sup>) of the specified argument.
- *
- * <p>The result has no loss of precision.</p>
- *
- * @param exponent exponent to which this rational number is to be raised
- * @return the resulting rational number
- */
- public BigRational pow(int exponent) {
- if (exponent == 0) {
- return ONE;
- }
- if (exponent == 1) {
- return this;
- }
-
- final BigInteger n;
- final BigInteger d;
- if (exponent > 0) {
- n = numerator.toBigInteger().pow(exponent);
- d = denominator.toBigInteger().pow(exponent);
- }
- else {
- n = denominator.toBigInteger().pow(-exponent);
- d = numerator.toBigInteger().pow(-exponent);
- }
- return valueOf(n, d);
- }
-
- /**
- * Finds the minimum (smaller) of two rational numbers.
- *
- * @param value the rational number to compare with
- * @return the minimum rational number, either <code>this</code> or the argument <code>value</code>
- */
- private BigRational min(BigRational value) {
- return compareTo(value) <= 0 ? this : value;
- }
-
- /**
- * Finds the maximum (larger) of two rational numbers.
- *
- * @param value the rational number to compare with
- * @return the minimum rational number, either <code>this</code> or the argument <code>value</code>
- */
- private BigRational max(BigRational value) {
- return compareTo(value) >= 0 ? this : value;
- }
-
- /**
- * Returns a rational number with approximatively <code>this</code> value and the specified precision.
- *
- * @param precision the precision (number of significant digits) of the calculated result, or 0 for unlimited precision
- * @return the calculated rational number with the specified precision
- */
- public BigRational withPrecision(int precision) {
- return valueOf(toBigDecimal(new MathContext(precision)));
- }
-
- /**
- * Returns a rational number with approximatively <code>this</code> value and the specified scale.
- *
- * @param scale the scale (number of digits after the decimal point) of the calculated result
- * @return the calculated rational number with the specified scale
- */
- public BigRational withScale(int scale) {
- return valueOf(toBigDecimal().setScale(scale, RoundingMode.HALF_UP));
- }
-
- private static int countDigits(BigInteger number) {
- double factor = Math.log(2) / Math.log(10);
- int digitCount = (int) (factor * number.bitLength() + 1);
- if (BigInteger.TEN.pow(digitCount - 1).compareTo(number) > 0) {
- return digitCount - 1;
- }
- return digitCount;
- }
-
- // TODO what is precision of a rational?
- private int precision() {
- return countDigits(numerator.toBigInteger()) + countDigits(denominator.toBigInteger());
- }
-
- /**
- * Returns this rational number as a double value.
- *
- * @return the double value
- */
- public double toDouble() {
- // TODO best accuracy or maybe bigDecimalValue().doubleValue() is better?
- return numerator.doubleValue() / denominator.doubleValue();
- }
-
- /**
- * Returns this rational number as a float value.
- *
- * @return the float value
- */
- public float toFloat() {
- return numerator.floatValue() / denominator.floatValue();
- }
-
- /**
- * Returns this rational number as a {@link BigDecimal}.
- *
- * @return the {@link BigDecimal} value
- */
- public BigDecimal toBigDecimal() {
- int precision = Math.max(precision(), MathContext.DECIMAL128.getPrecision());
- return toBigDecimal(new MathContext(precision));
- }
-
- /**
- * Returns this rational number as a {@link BigDecimal} with the precision specified by the {@link MathContext}.
- *
- * @param mc the {@link MathContext} specifying the precision of the calculated result
- * @return the {@link BigDecimal}
- */
- public BigDecimal toBigDecimal(MathContext mc) {
- return numerator.divide(denominator, mc);
- }
-
- @Override
- public int compareTo(BigRational other) {
- if (this == other) {
- return 0;
- }
- return numerator.multiply(other.denominator).compareTo(denominator.multiply(other.numerator));
- }
-
- @Override
- public int hashCode() {
- if (isZero()) {
- return 0;
- }
- return numerator.hashCode() + denominator.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
-
- if (!(obj instanceof BigRational)) {
- return false;
- }
-
- BigRational other = (BigRational) obj;
- if (!numerator.equals(other.numerator)) {
- return false;
- }
- return denominator.equals(other.denominator);
- }
-
- @Override
- public String toString() {
- if (isZero()) {
- return "0";
- }
- if (isIntegerInternal()) {
- return numerator.toString();
- }
- return toBigDecimal().toString();
- }
-
- /**
- * Returns a plain string representation of this rational number without any exponent.
- *
- * @return the plain string representation
- * @see BigDecimal#toPlainString()
- */
- public String toPlainString() {
- if (isZero()) {
- return "0";
- }
- if (isIntegerInternal()) {
- return numerator.toPlainString();
- }
- return toBigDecimal().toPlainString();
- }
-
- /**
- * Returns the string representation of this rational number in the form "numerator/denominator".
- *
- * <p>The resulting string is a valid input of the {@link #valueOf(String)} method.</p>
- *
- * <p>Examples:</p>
- * <ul>
- * <li><code>BigRational.valueOf(0.5).toRationalString()</code> returns <code>"1/2"</code></li>
- * <li><code>BigRational.valueOf(2).toRationalString()</code> returns <code>"2"</code></li>
- * <li><code>BigRational.valueOf(4, 4).toRationalString()</code> returns <code>"4/4"</code> (not reduced)</li>
- * </ul>
- *
- * @return the rational number string representation in the form "numerator/denominator", or "0" if the rational number is 0.
- * @see #valueOf(String)
- * @see #valueOf(int, int)
- */
- public String toRationalString() {
- if (isZero()) {
- return "0";
- }
- if (isIntegerInternal()) {
- return numerator.toString();
- }
- return numerator + "/" + denominator;
- }
-
- /**
- * Returns the string representation of this rational number as integer and fraction parts in the form "integerPart fractionNominator/fractionDenominator".
- *
- * <p>The integer part is omitted if it is 0 (when this absolute rational number is smaller than 1).</p>
- * <p>The fraction part is omitted it it is 0 (when this rational number is an integer).</p>
- * <p>If this rational number is 0, then "0" is returned.</p>
- *
- * <p>Example: <code>BigRational.valueOf(3.5).toIntegerRationalString()</code> returns <code>"3 1/2"</code>.</p>
- *
- * @return the integer and fraction rational string representation
- * @see #valueOf(int, int, int)
- */
- public String toIntegerRationalString() {
- BigDecimal fractionNumerator = numerator.remainder(denominator);
- BigDecimal integerNumerator = numerator.subtract(fractionNumerator);
- BigDecimal integerPart = integerNumerator.divide(denominator);
-
- StringBuilder result = new StringBuilder();
- if (integerPart.signum() != 0) {
- result.append(integerPart);
- }
- if (fractionNumerator.signum() != 0) {
- if (result.length() > 0) {
- result.append(' ');
- }
- result.append(fractionNumerator.abs());
- result.append('/');
- result.append(denominator);
- }
- if (result.length() == 0) {
- result.append('0');
- }
-
- return result.toString();
- }
-
- /**
- * Creates a rational number of the specified int value.
- *
- * @param value the int value
- * @return the rational number
- */
- public static BigRational valueOf(int value) {
- if (value == 0) {
- return ZERO;
- }
- if (value == 1) {
- return ONE;
- }
- return new BigRational(value);
- }
-
- /**
- * Creates a rational number of the specified numerator/denominator int values.
- *
- * @param numerator the numerator int value
- * @param denominator the denominator int value (0 not allowed)
- * @return the rational number
- * @throws ArithmeticException if the denominator is 0 (division by zero)
- */
- public static BigRational valueOf(int numerator, int denominator) {
- return of(BigDecimal.valueOf(numerator), BigDecimal.valueOf(denominator));
- }
-
- /**
- * Creates a rational number of the specified integer and fraction parts.
- *
- * <p>Useful to create numbers like 3 1/2 (= three and a half = 3.5) by calling
- * <code>BigRational.valueOf(3, 1, 2)</code>.</p>
- * <p>To create a negative rational only the integer part argument is allowed to be negative:
- * to create -3 1/2 (= minus three and a half = -3.5) call <code>BigRational.valueOf(-3, 1, 2)</code>.</p>
- *
- * @param integer the integer part int value
- * @param fractionNumerator the fraction part numerator int value (negative not allowed)
- * @param fractionDenominator the fraction part denominator int value (0 or negative not allowed)
- * @return the rational number
- * @throws ArithmeticException if the fraction part denominator is 0 (division by zero),
- * or if the fraction part numerator or denominator is negative
- */
- public static BigRational valueOf(int integer, int fractionNumerator, int fractionDenominator) {
- if (fractionNumerator < 0 || fractionDenominator < 0) {
- throw new ArithmeticException("Negative value");
- }
-
- BigRational integerPart = valueOf(integer);
- BigRational fractionPart = valueOf(fractionNumerator, fractionDenominator);
- return integerPart.isPositive() ? integerPart.add(fractionPart) : integerPart.subtract(fractionPart);
- }
-
- /**
- * Creates a rational number of the specified numerator/denominator BigInteger values.
- *
- * @param numerator the numerator {@link BigInteger} value
- * @param denominator the denominator {@link BigInteger} value (0 not allowed)
- * @return the rational number
- * @throws ArithmeticException if the denominator is 0 (division by zero)
- */
- public static BigRational valueOf(BigInteger numerator, BigInteger denominator) {
- return of(new BigDecimal(numerator), new BigDecimal(denominator));
- }
-
- /**
- * Creates a rational number of the specified {@link BigInteger} value.
- *
- * @param value the {@link BigInteger} value
- * @return the rational number
- */
- public static BigRational valueOf(BigInteger value) {
- if (value.compareTo(BigInteger.ZERO) == 0) {
- return ZERO;
- }
- if (value.compareTo(BigInteger.ONE) == 0) {
- return ONE;
- }
- return valueOf(value, BigInteger.ONE);
- }
-
- /**
- * Creates a rational number of the specified double value.
- *
- * @param value the double value
- * @return the rational number
- * @throws NumberFormatException if the double value is Infinite or NaN.
- */
- public static BigRational valueOf(double value) {
- if (value == 0.0) {
- return ZERO;
- }
- if (value == 1.0) {
- return ONE;
- }
- if (Double.isInfinite(value)) {
- throw new NumberFormatException("Infinite");
- }
- if (Double.isNaN(value)) {
- throw new NumberFormatException("NaN");
- }
- return valueOf(new BigDecimal(String.valueOf(value)));
- }
-
- /**
- * Creates a rational number of the specified {@link BigDecimal} value.
- *
- * @param value the double value
- * @return the rational number
- */
- public static BigRational valueOf(BigDecimal value) {
- if (value.compareTo(BigDecimal.ZERO) == 0) {
- return ZERO;
- }
- if (value.compareTo(BigDecimal.ONE) == 0) {
- return ONE;
- }
-
- int scale = value.scale();
- if (scale == 0) {
- return new BigRational(value, BigDecimal.ONE);
- } else if (scale < 0) {
- BigDecimal n = new BigDecimal(value.unscaledValue()).multiply(BigDecimal.ONE.movePointLeft(value.scale()));
- return new BigRational(n, BigDecimal.ONE);
- }
- else {
- BigDecimal n = new BigDecimal(value.unscaledValue());
- BigDecimal d = BigDecimal.ONE.movePointRight(value.scale());
- return new BigRational(n, d);
- }
- }
-
- /**
- * Creates a rational number of the specified string representation.
- *
- * <p>The accepted string representations are:</p>
- * <ul>
- * <li>Output of {@link BigRational#toString()} : "integerPart.fractionPart"</li>
- * <li>Output of {@link BigRational#toRationalString()} : "numerator/denominator"</li>
- * <li>Output of <code>toString()</code> of {@link BigDecimal}, {@link BigInteger}, {@link Integer}, ...</li>
- * <li>Output of <code>toString()</code> of {@link Double}, {@link Float} - except "Infinity", "-Infinity" and "NaN"</li>
- * </ul>
- *
- * @param string the string representation to convert
- * @return the rational number
- * @throws ArithmeticException if the denominator is 0 (division by zero)
- */
- public static BigRational valueOf(String string) {
- String[] strings = string.split("/");
- BigRational result = valueOfSimple(strings[0]);
- for (int i = 1; i < strings.length; i++) {
- result = result.divide(valueOfSimple(strings[i]));
- }
- return result;
- }
-
- private static BigRational valueOfSimple(String string) {
- return valueOf(new BigDecimal(string));
- }
-
- public static BigRational valueOf(boolean positive, String integerPart, String fractionPart, String fractionRepeatPart, String exponentPart) {
- BigRational result = ZERO;
-
- if (fractionRepeatPart != null && fractionRepeatPart.length() > 0) {
- BigInteger lotsOfNines = BigInteger.TEN.pow(fractionRepeatPart.length()).subtract(BigInteger.ONE);
- result = valueOf(new BigInteger(fractionRepeatPart), lotsOfNines);
- }
-
- if (fractionPart != null && fractionPart.length() > 0) {
- result = result.add(valueOf(new BigInteger(fractionPart)));
- result = result.divide(BigInteger.TEN.pow(fractionPart.length()));
- }
-
- if (integerPart != null && integerPart.length() > 0) {
- result = result.add(new BigInteger(integerPart));
- }
-
- if (exponentPart != null && exponentPart.length() > 0) {
- int exponent = Integer.parseInt(exponentPart);
- BigInteger powerOfTen = BigInteger.TEN.pow(Math.abs(exponent));
- result = exponent >= 0 ? result.multiply(powerOfTen) : result.divide(powerOfTen);
- }
-
- if (!positive) {
- result = result.negate();
- }
-
- return result;
- }
-
- /**
- * Creates a rational number of the specified numerator/denominator BigDecimal values.
- *
- * @param numerator the numerator {@link BigDecimal} value
- * @param denominator the denominator {@link BigDecimal} value (0 not allowed)
- * @return the rational number
- * @throws ArithmeticException if the denominator is 0 (division by zero)
- */
- public static BigRational valueOf(BigDecimal numerator, BigDecimal denominator) {
- return valueOf(numerator).divide(valueOf(denominator));
- }
-
- private static BigRational of(BigDecimal numerator, BigDecimal denominator) {
- if (numerator.signum() == 0 && denominator.signum() != 0) {
- return ZERO;
- }
- if (numerator.compareTo(BigDecimal.ONE) == 0 && denominator.compareTo(BigDecimal.ONE) == 0) {
- return ONE;
- }
- return new BigRational(numerator, denominator);
- }
-
- /**
- * Returns the smallest of the specified rational numbers.
- *
- * @param values the rational numbers to compare
- * @return the smallest rational number, 0 if no numbers are specified
- */
- public static BigRational min(BigRational... values) {
- if (values.length == 0) {
- return BigRational.ZERO;
- }
- BigRational result = values[0];
- for (int i = 1; i < values.length; i++) {
- result = result.min(values[i]);
- }
- return result;
- }
-
- /**
- * Returns the largest of the specified rational numbers.
- *
- * @param values the rational numbers to compare
- * @return the largest rational number, 0 if no numbers are specified
- * @see #max(BigRational)
- */
- public static BigRational max(BigRational... values) {
- if (values.length == 0) {
- return BigRational.ZERO;
- }
- BigRational result = values[0];
- for (int i = 1; i < values.length; i++) {
- result = result.max(values[i]);
- }
- return result;
- }
-
- private static List<BigRational> bernoulliCache = new ArrayList<>();
-
- /**
- * Calculates the Bernoulli number for the specified index.
- *
- * <p>This function calculates the <strong>first Bernoulli numbers</strong> and therefore <code>bernoulli(1)</code> returns -0.5</p>
- * <p>Note that <code>bernoulli(x)</code> for all odd x &gt; 1 returns 0</p>
- * <p>See: <a href="https://en.wikipedia.org/wiki/Bernoulli_number">Wikipedia: Bernoulli number</a></p>
- *
- * @param n the index of the Bernoulli number to be calculated (starting at 0)
- * @return the Bernoulli number for the specified index
- * @throws ArithmeticException if x is lesser than 0
- */
- public static BigRational bernoulli(int n) {
- if (n < 0) {
- throw new ArithmeticException("Illegal bernoulli(n) for n < 0: n = " + n);
- }
- if (n == 1) {
- return valueOf(-1, 2);
- } else if (n % 2 == 1) {
- return ZERO;
- }
-
- synchronized (bernoulliCache) {
- int index = n / 2;
-
- if (bernoulliCache.size() <= index) {
- for (int i = bernoulliCache.size(); i <= index; i++) {
- BigRational b = calculateBernoulli(i * 2);
- bernoulliCache.add(b);
- }
- }
-
- return bernoulliCache.get(index);
- }
- }
-
- private static BigRational calculateBernoulli(int n) {
- return IntStream.rangeClosed(0, n).parallel().mapToObj(k -> {
- BigRational jSum = ZERO ;
- BigRational bin = ONE ;
- for(int j=0 ; j <= k ; j++) {
- BigRational jPowN = valueOf(j).pow(n);
- if (j % 2 == 0) {
- jSum = jSum.add(bin.multiply(jPowN)) ;
- } else {
- jSum = jSum.subtract(bin.multiply(jPowN)) ;
- }
-
- bin = bin.multiply(valueOf(k-j).divide(valueOf(j+1)));
- }
- return jSum.divide(valueOf(k+1));
- }).reduce(ZERO, BigRational::add);
- }
-
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/DefaultBigDecimalMath.java b/src/main/java/ch/obermuhlner/math/big/DefaultBigDecimalMath.java
deleted file mode 100644
index d6dca31ecf..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/DefaultBigDecimalMath.java
+++ /dev/null
@@ -1,736 +0,0 @@
-package ch.obermuhlner.math.big;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.math.RoundingMode;
-import java.util.*;
-
-/**
- * A wrapper around {@link BigDecimalMath} that passes a current {@link MathContext} to the
- * functions that need a {@link MathContext} argument.
- *
- * <p>The initial default {@link MathContext} is equivalent to {@link MathContext#DECIMAL128}
- * but this can be overridden by setting the following system properties:</p>
- * <ul>
- * <li><code>ch.obermuhlner.math.big.default.precision</code> to a positive integer precision (default=34)</li>
- * <li><code>ch.obermuhlner.math.big.default.rounding</code> to a {@link RoundingMode} name (default=HALF_UP) </li>
- * </ul>
- *
- * <p>It is also possible to programmatically set the default {@link MathContext} using {@link #setDefaultMathContext(MathContext)}.
- * It is recommended to set the desired precision in the {@link MathContext} very early in the startup of the application and to not change it afterwards.</p>
- *
- * <p>Important: Avoid the pitfall of setting the precision temporarily using {@link #setDefaultMathContext(MathContext)} for a calculation.
- * This can lead to race conditions and calculations with the wrong precision
- * if other threads in your application do the same thing.</p>
- *
- * <p>To set a temporary {@link MathContext} you have to choice to use either:
- * <ul>
- * <li><code>DefaultBigDecimalMath.createLocalMathContext()</code> in a try-with-resources statement</li>
- * <li><code>DefaultBigDecimalMath.withLocalMathContext()</code> with a lambda function</li>
- * </ul>
- *
- * Example code using <code>DefaultBigDecimalMath.createLocalMathContext()</code>:
- * <pre>
-System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
-try (DefaultBigDecimalMath.LocalMathContext context = DefaultBigDecimalMath.createLocalMathContext(5)) {
- System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
- try (DefaultBigDecimalMath.LocalMathContext context2 = DefaultBigDecimalMath.createLocalMathContext(10)) {
- System.out.println("Pi[10]: " + DefaultBigDecimalMath.pi());
- }
- System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
-}
-System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
- </pre>
- *
- * Example code using <code>DefaultBigDecimalMath.withLocalMathContext()</code>:
- * <pre>
-System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
-DefaultBigDecimalMath.withPrecision(5, () -&gt; {
- System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
- DefaultBigDecimalMath.withPrecision(10, () -&gt; {
- System.out.println("Pi[10]: " + DefaultBigDecimalMath.pi());
- });
- System.out.println("Pi[5]: " + DefaultBigDecimalMath.pi());
-});
-System.out.println("Pi[default]: " + DefaultBigDecimalMath.pi());
-</pre>
- *
- * Both snippets with give the following ouput:
- * <pre>
-Pi[default]: 3.141592653589793238462643383279503
-Pi[5]: 3.1416
-Pi[10]: 3.141592654
-Pi[5]: 3.1416
-Pi[default]: 3.141592653589793238462643383279503
-</pre>
- * <p>The temporary {@link MathContext} are stored in {@link ThreadLocal} variables
- * and will therefore not conflict with each other when used in multi-threaded use case.</p>
- *
- * <p>Important: Due to the {@link ThreadLocal} variables the local {@link MathContext} will
- * <strong>not</strong> be available in other threads.
- * This includes streams using <code>parallel()</code>, thread pools and manually started threads.
- * If you need temporary {@link MathContext} for calculations then you <strong>must</strong>
- * set the local {@link MathContext} inside <strong>every</strong> separate thread.</p>
- *
- * <pre>
-try (DefaultBigDecimalMath.LocalMathContext context = DefaultBigDecimalMath.createLocalMathContext(5)) {
- BigDecimalStream.range(0.0, 1.0, 0.01, DefaultBigDecimalMath.currentMathContext())
- .map(b -&gt; DefaultBigDecimalMath.cos(b))
- .map(b -&gt; "sequential " + Thread.currentThread().getName() + " [5]: " + b)
- .forEach(System.out::println);
-
- BigDecimalStream.range(0.0, 1.0, 0.01, DefaultBigDecimalMath.currentMathContext())
- .parallel()
- .map(b -&gt; {
- try (DefaultBigDecimalMath.LocalMathContext context2 = DefaultBigDecimalMath.createLocalMathContext(5)) {
- return DefaultBigDecimalMath.cos(b);
- }
- })
- .map(b -&gt; "parallel " + Thread.currentThread().getName() + " [5]: " + b)
- .forEach(System.out::println);
-}
-</pre>
- */
-public class DefaultBigDecimalMath {
-
- private static MathContext defaultMathContext = createDefaultMathContext();
- private static ThreadLocal<Deque<MathContext>> mathContextStack = new ThreadLocal<>();
-
- private static MathContext createDefaultMathContext () {
- int precision = getIntSystemProperty("ch.obermuhlner.math.big.default.precision", MathContext.DECIMAL128.getPrecision());
- RoundingMode rounding = getRoundingModeSystemProperty("ch.obermuhlner.math.big.default.rounding", MathContext.DECIMAL128.getRoundingMode());
-
- return new MathContext(precision, rounding);
- }
-
- private static void pushMathContext(MathContext mathContext) {
- Deque<MathContext> mathContexts = mathContextStack.get();
- if (mathContexts == null) {
- mathContexts = new ArrayDeque<>();
- mathContextStack.set(mathContexts);
- };
- mathContexts.addLast(mathContext);
- }
-
- private static MathContext popMathContext() {
- Deque<MathContext> mathContexts = mathContextStack.get();
- MathContext poppedMathContext = mathContexts.removeLast();
- if (mathContexts.isEmpty()) {
- mathContextStack.remove();
- }
- return poppedMathContext;
- }
-
- private static int getIntSystemProperty(String propertyKey, int defaultValue) {
- String propertyValue = System.getProperty(propertyKey, Integer.toString(defaultValue));
- try {
- return Integer.parseInt(propertyValue);
- } catch(NumberFormatException ex) {
- return propertyException(propertyKey,propertyValue,defaultValue);
- }
- }
-
- private static RoundingMode getRoundingModeSystemProperty(String propertyKey, RoundingMode defaultValue) {
- String propertyValue = System.getProperty(propertyKey, defaultValue.name());
- try {
- return RoundingMode.valueOf(propertyValue);
- } catch(IllegalArgumentException ex) {
- return propertyException(propertyKey,propertyValue,defaultValue);
- }
- }
-
- private static <T> T propertyException(String propertyKey,String propertyValue,T defaultValue){
- System.err.println("Property '" + propertyKey + "' is not valid: " + propertyValue + " (using " + defaultValue + " instead)");
- return defaultValue;
- }
-
- /**
- * Sets the default {@link MathContext} used if no other {@link MathContext} is defined using {@link #withLocalMathContext(MathContext, Runnable)}.
- *
- * @param defaultMathContext the default {@link MathContext}
- * @see #currentMathContext()
- * @see #withLocalMathContext(int, Runnable)
- * @see #withLocalMathContext(int, RoundingMode, Runnable)
- * @see #withLocalMathContext(MathContext, Runnable)
- */
- public static void setDefaultMathContext(MathContext defaultMathContext) {
- Objects.requireNonNull(defaultMathContext);
- DefaultBigDecimalMath.defaultMathContext = defaultMathContext;
- }
-
- /**
- * Returns the default {@link MathContext} used for all mathematical functions in this class.
- *
- * @return the default {@link MathContext}
- */
- public static MathContext getDefaultMathContext() {
- return defaultMathContext;
- }
-
- /**
- * Executes the given {@link Runnable} using the specified precision.
- *
- * @param precision the precision to use for calculations in the <code>runnable</code>
- * @param runnable the {@link Runnable} to execute
- */
- public static void withLocalMathContext(int precision, Runnable runnable) {
- withLocalMathContext(new MathContext(precision), runnable);
- }
-
- /**
- * Executes the given {@link Runnable} using the specified precision and {@link RoundingMode}.
- *
- * @param precision the precision to use for calculations in the <code>runnable</code>
- * @param roundingMode the {@link RoundingMode} to use for calculations in the <code>runnable</code>
- * @param runnable the {@link Runnable} to execute
- */
- public static void withLocalMathContext(int precision, RoundingMode roundingMode, Runnable runnable) {
- withLocalMathContext(new MathContext(precision, roundingMode), runnable);
- }
-
- /**
- * Executes the given {@link Runnable} using the specified {@link MathContext}.
- *
- * @param mathContext the {@link MathContext} to use for calculations in the <code>runnable</code>
- * @param runnable the {@link Runnable} to execute
- */
- public static void withLocalMathContext(MathContext mathContext, Runnable runnable) {
- try (LocalMathContext context = createLocalMathContext(mathContext)) {
- runnable.run();
- }
- }
-
- /**
- * Executes the given {@link Runnable} using the specified precision.
- *
- * @param precision the precision to use for calculations
- * @return the created {@link LocalMathContext} to be used in a try-with-resources statement
- */
- public static LocalMathContext createLocalMathContext(int precision) {
- return createLocalMathContext(new MathContext(precision));
- }
-
- /**
- * Executes the given {@link Runnable} using the specified precision and {@link RoundingMode}.
- *
- * @param precision the precision to use for calculations
- * @param roundingMode the {@link RoundingMode} to use for calculations in the <code>runnable</code>
- * @return the created {@link LocalMathContext} to be used in a try-with-resources statement
- */
- public static LocalMathContext createLocalMathContext(int precision, RoundingMode roundingMode) {
- return createLocalMathContext(new MathContext(precision, roundingMode));
- }
-
- /**
- * Executes the given {@link Runnable} using the specified {@link MathContext}.
- *
- * @param mathContext the {@link MathContext} to use for calculations
- * @return the created {@link LocalMathContext} to be used in a try-with-resources statement
- */
- public static LocalMathContext createLocalMathContext(MathContext mathContext) {
- return new LocalMathContext(mathContext);
- }
-
- /**
- * Returns the current {@link MathContext} used for all mathematical functions in this class.
- *
- * <p>The current {@link MathContext} is the last {@link MathContext} specified
- * using {@link #withLocalMathContext(MathContext, Runnable)}
- * or the default {@link MathContext} if none was specified.</p>
- *
- * @return the current {@link MathContext}
- * @see #currentMathContext()
- * @see #withLocalMathContext(int, Runnable)
- * @see #withLocalMathContext(int, RoundingMode, Runnable)
- * @see #withLocalMathContext(MathContext, Runnable)
- */
- public static MathContext currentMathContext() {
- Deque<MathContext> mathContexts = mathContextStack.get();
- if (mathContexts == null || mathContexts.isEmpty()) {
- return defaultMathContext;
- }
-
- return mathContexts.getLast();
- }
-
- /**
- * Rounds the specified {@link BigDecimal} to the precision of the current {@link MathContext}.
- *
- * @param value the {@link BigDecimal} to round
- * @return the rounded {@link BigDecimal} value
- * @see #currentMathContext()
- * @see BigDecimalMath#round(BigDecimal, MathContext)
- */
- public static BigDecimal round(BigDecimal value) {
- return BigDecimalMath.round(value, defaultMathContext);
- }
-
- /**
- * Rounds the specified {@link BigDecimal} to the precision of the current {@link MathContext} including trailing zeroes.
- *
- * @param value the {@link BigDecimal} to round
- * @return the rounded {@link BigDecimal} value including trailing zeroes
- * @see #currentMathContext()
- * @see BigDecimalMath#roundWithTrailingZeroes(BigDecimal, MathContext)
- */
- public static BigDecimal roundWithTrailingZeroes(BigDecimal value) {
- return BigDecimalMath.roundWithTrailingZeroes(value, currentMathContext());
- }
-
- /**
- * Returns the {@link BigDecimal} that is <code>x + y</code> using the current {@link MathContext}.
- *
- * @param x the x value
- * @param y the y value to add
- * @return the resulting {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimal#add(BigDecimal, MathContext)
- */
- public static BigDecimal add(BigDecimal x, BigDecimal y) {
- return x.add(y, currentMathContext());
- }
-
- /**
- * Returns the {@link BigDecimal} that is <code>x - y</code> using the current {@link MathContext}.
- *
- * @param x the x value
- * @param y the y value to subtract
- * @return the resulting {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimal#subtract(BigDecimal, MathContext)
- */
- public static BigDecimal subtract(BigDecimal x, BigDecimal y) {
- return x.subtract(y, currentMathContext());
- }
-
- /**
- * Returns the {@link BigDecimal} that is <code>x * y</code> using the current {@link MathContext}.
- *
- * @param x the x value
- * @param y the y value to multiply
- * @return the resulting {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimal#multiply(BigDecimal, MathContext)
- */
- public static BigDecimal multiply(BigDecimal x, BigDecimal y) {
- return x.multiply(y, currentMathContext());
- }
-
- /**
- * Returns the {@link BigDecimal} that is <code>x / y</code> using the current {@link MathContext}.
- *
- * @param x the x value
- * @param y the y value to divide
- * @return the resulting {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimal#divide(BigDecimal, MathContext)
- */
- public static BigDecimal divide(BigDecimal x, BigDecimal y) {
- return x.divide(y, currentMathContext());
- }
-
- /**
- * Returns the {@link BigDecimal} that is <code>x % y</code> using the current {@link MathContext}.
- *
- * @param x the x value
- * @param y the y value to divide
- * @return the resulting {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimal#remainder(BigDecimal, MathContext)
- */
- public static BigDecimal remainder(BigDecimal x, BigDecimal y) {
- return x.remainder(y, currentMathContext());
- }
-
- /**
- * Calculates the reciprocal of the specified {@link BigDecimal} using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal}
- * @return the reciprocal {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#reciprocal(BigDecimal, MathContext)
- */
- public static BigDecimal reciprocal(BigDecimal x) {
- return BigDecimalMath.reciprocal(x, currentMathContext());
- }
-
- /**
- * Calculates the factorial of the specified {@link BigDecimal} using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal}
- * @return the factorial {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#factorial(BigDecimal, MathContext)
- */
- public static BigDecimal factorial(BigDecimal x) {
- return BigDecimalMath.factorial(x, currentMathContext());
- }
-
- /**
- * Calculates the gamma function of the specified {@link BigDecimal} using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal}
- * @return the gamma {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#gamma(BigDecimal, MathContext)
- */
- public static BigDecimal gamma(BigDecimal x) {
- return BigDecimalMath.gamma(x, currentMathContext());
- }
-
- /**
- * Calculates the Bernoulli number for the specified index using the current {@link MathContext}.
- *
- * @param n the index of the Bernoulli number to be calculated (starting at 0)
- * @return the Bernoulli number for the specified index with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#bernoulli(int, MathContext)
- */
- public static BigDecimal bernoulli(int n) {
- return BigDecimalMath.bernoulli(n, currentMathContext());
- }
-
- /**
- * Calculates {@link BigDecimal} x to the power of {@link BigDecimal} y (x<sup>y</sup>) using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} value to take to the power
- * @param y the {@link BigDecimal} value to serve as exponent
- * @return the calculated x to the power of y with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#pow(BigDecimal, BigDecimal, MathContext)
- */
- public static BigDecimal pow(BigDecimal x, BigDecimal y) {
- return BigDecimalMath.pow(x, y, currentMathContext());
- }
-
- /**
- * Calculates {@link BigDecimal} x to the power of <code>long</code> y (x<sup>y</sup>) using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} value to take to the power
- * @param y the <code>long</code> value to serve as exponent
- * @return the calculated x to the power of y with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#pow(BigDecimal, long, MathContext)
- */
- public static BigDecimal pow(BigDecimal x, long y) {
- return BigDecimalMath.pow(x, y, currentMathContext());
- }
-
- /**
- * Calculates the square root of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} value to calculate the square root
- * @return the calculated square root of x with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#sqrt(BigDecimal, MathContext)
- */
- public static BigDecimal sqrt(BigDecimal x) {
- return BigDecimalMath.sqrt(x, currentMathContext());
- }
-
- /**
- * Calculates the n'th root of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} value to calculate the n'th root
- * @param n the {@link BigDecimal} defining the root
- *
- * @return the calculated n'th root of x with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#root(BigDecimal, BigDecimal, MathContext)
- */
- public static BigDecimal root(BigDecimal x, BigDecimal n) {
- return BigDecimalMath.root(x, n, currentMathContext());
- }
-
- /**
- * Calculates the natural logarithm of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the natural logarithm for
- * @return the calculated natural logarithm {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#log(BigDecimal, MathContext)
- */
- public static BigDecimal log(BigDecimal x) {
- return BigDecimalMath.log(x, currentMathContext());
- }
-
- /**
- * Calculates the logarithm of {@link BigDecimal} x to the base 2 using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the logarithm base 2 for
- * @return the calculated natural logarithm {@link BigDecimal} to the base 2 with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#log2(BigDecimal, MathContext)
- */
- public static BigDecimal log2(BigDecimal x) {
- return BigDecimalMath.log2(x, currentMathContext());
- }
-
- /**
- * Calculates the logarithm of {@link BigDecimal} x to the base 10 using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the logarithm base 10 for
- * @return the calculated natural logarithm {@link BigDecimal} to the base 10 with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#log10(BigDecimal, MathContext)
- */
- public static BigDecimal log10(BigDecimal x) {
- return BigDecimalMath.log10(x, currentMathContext());
- }
-
- /**
- * Returns the number pi using the current {@link MathContext}.
- *
- * @return the number pi with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#pi(MathContext)
- */
- public static BigDecimal pi() {
- return BigDecimalMath.pi(currentMathContext());
- }
-
- /**
- * Returns the number e using the current {@link MathContext}.
- *
- * @return the number e with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#e(MathContext)
- */
- public static BigDecimal e() {
- return BigDecimalMath.e(currentMathContext());
- }
-
- /**
- * Calculates the natural exponent of {@link BigDecimal} x (e<sup>x</sup>) using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the exponent for
- * @return the calculated exponent {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#exp(BigDecimal, MathContext)
- */
- public static BigDecimal exp(BigDecimal x) {
- return BigDecimalMath.exp(x, currentMathContext());
- }
-
- /**
- * Calculates the sine (sinus) of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the sine for
- * @return the calculated sine {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#sin(BigDecimal, MathContext)
- */
- public static BigDecimal sin(BigDecimal x) {
- return BigDecimalMath.sin(x, currentMathContext());
- }
-
- /**
- * Calculates the arc sine (inverted sine) of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the arc sine for
- * @return the calculated arc sine {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#asin(BigDecimal, MathContext)
- */
- public static BigDecimal asin(BigDecimal x) {
- return BigDecimalMath.asin(x, currentMathContext());
- }
-
- /**
- * Calculates the cosine (cosinus) of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the cosine for
- * @return the calculated cosine {@link BigDecimal} with the precision specified in the current {@link MathContext}
- */
- public static BigDecimal cos(BigDecimal x) {
- return BigDecimalMath.cos(x, currentMathContext());
- }
-
- /**
- * Calculates the arc cosine (inverted cosine) of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the arc cosine for
- * @return the calculated arc sine {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#acos(BigDecimal, MathContext)
- */
- public static BigDecimal acos(BigDecimal x) {
- return BigDecimalMath.acos(x, currentMathContext());
- }
-
- /**
- * Calculates the tangens of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the tangens for
- * @return the calculated tangens {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#tan(BigDecimal, MathContext)
- */
- public static BigDecimal tan(BigDecimal x) {
- return BigDecimalMath.tan(x, currentMathContext());
- }
-
- /**
- * Calculates the arc tangens (inverted tangens) of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the arc tangens for
- * @return the calculated arc tangens {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#atan(BigDecimal, MathContext)
- */
- public static BigDecimal atan(BigDecimal x) {
- return BigDecimalMath.atan(x, currentMathContext());
- }
-
- /**
- * Calculates the arc tangens (inverted tangens) of {@link BigDecimal} y / x in the range -<i>pi</i> to <i>pi</i> using the current {@link MathContext}.
- *
- * @param y the {@link BigDecimal}
- * @param x the {@link BigDecimal}
- * @return the calculated arc tangens {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see #atan2(BigDecimal, BigDecimal)
- */
- public static BigDecimal atan2(BigDecimal y, BigDecimal x) {
- return BigDecimalMath.atan2(y, x, currentMathContext());
- }
-
- /**
- * Calculates the cotangens of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the cotangens for
- * @return the calculated cotanges {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#cot(BigDecimal, MathContext)
- */
- public static BigDecimal cot(BigDecimal x) {
- return BigDecimalMath.cot(x, currentMathContext());
- }
-
- /**
- * Calculates the inverse cotangens (arc cotangens) of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the arc cotangens for
- * @return the calculated arc cotangens {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#acot(BigDecimal, MathContext)
- */
- public static BigDecimal acot(BigDecimal x) {
- return BigDecimalMath.acot(x, currentMathContext());
- }
-
- /**
- * Calculates the hyperbolic sine of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the hyperbolic sine for
- * @return the calculated hyperbolic sine {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#sinh(BigDecimal, MathContext)
- */
- public static BigDecimal sinh(BigDecimal x) {
- return BigDecimalMath.sinh(x, currentMathContext());
- }
-
- /**
- * Calculates the hyperbolic cosine of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the hyperbolic cosine for
- * @return the calculated hyperbolic cosine {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#cosh(BigDecimal, MathContext)
- */
- public static BigDecimal cosh(BigDecimal x) {
- return BigDecimalMath.cosh(x, currentMathContext());
- }
-
- /**
- * Calculates the hyperbolic tangens of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the hyperbolic tangens for
- * @return the calculated hyperbolic tangens {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#tanh(BigDecimal, MathContext)
- */
- public static BigDecimal tanh(BigDecimal x) {
- return BigDecimalMath.tanh(x, currentMathContext());
- }
-
- /**
- * Calculates the hyperbolic cotangens of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the hyperbolic cotangens for
- * @return the calculated hyperbolic cotangens {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#coth(BigDecimal, MathContext)
- */
- public static BigDecimal coth(BigDecimal x) {
- return BigDecimalMath.coth(x, currentMathContext());
- }
-
- /**
- * Calculates the arc hyperbolic sine (inverse hyperbolic sine) of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the arc hyperbolic sine for
- * @return the calculated arc hyperbolic sine {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#asinh(BigDecimal, MathContext)
- */
- public static BigDecimal asinh(BigDecimal x) {
- return BigDecimalMath.asinh(x, currentMathContext());
- }
-
- /**
- * Calculates the arc hyperbolic cosine (inverse hyperbolic cosine) of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the arc hyperbolic cosine for
- * @return the calculated arc hyperbolic cosine {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#acosh(BigDecimal, MathContext)
- */
- public static BigDecimal acosh(BigDecimal x) {
- return BigDecimalMath.acosh(x, currentMathContext());
- }
-
- /**
- * Calculates the arc hyperbolic tangens (inverse hyperbolic tangens) of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the arc hyperbolic tangens for
- * @return the calculated arc hyperbolic tangens {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#atanh(BigDecimal, MathContext)
- */
- public static BigDecimal atanh(BigDecimal x) {
- return BigDecimalMath.atanh(x, currentMathContext());
- }
-
- /**
- * Calculates the arc hyperbolic cotangens (inverse hyperbolic cotangens) of {@link BigDecimal} x using the current {@link MathContext}.
- *
- * @param x the {@link BigDecimal} to calculate the arc hyperbolic cotangens for
- * @return the calculated arc hyperbolic cotangens {@link BigDecimal} with the precision specified in the current {@link MathContext}
- * @see #currentMathContext()
- * @see BigDecimalMath#acoth(BigDecimal, MathContext)
- */
- public static BigDecimal acoth(BigDecimal x) {
- return BigDecimalMath.acoth(x, currentMathContext());
- }
-
- /**
- * The local context used to push and pop a {@link MathContext} on the stack.
- *
- * <p>The recommended way to use this class is to use the try-with-resources.</p>
- */
- public static class LocalMathContext implements AutoCloseable {
- public final MathContext mathContext;
-
- LocalMathContext(MathContext mathContext) {
- this.mathContext = mathContext;
- pushMathContext(mathContext);
- }
-
- @Override
- public void close() {
- popMathContext();
- }
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/AsinCalculator.java b/src/main/java/ch/obermuhlner/math/big/internal/AsinCalculator.java
deleted file mode 100644
index f8bcd4837b..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/AsinCalculator.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-import ch.obermuhlner.math.big.BigRational;
-
-/**
- * Calculates arc sinus using the Maclaurin series.
- *
- * <p>See <a href="https://de.wikipedia.org/wiki/Taylorreihe">Wikipedia: Taylorreihe</a></p>
- *
- * <p>No argument checking or optimizations are done.
- * This implementation is <strong>not</strong> intended to be called directly.</p>
- */
-public class AsinCalculator extends SeriesCalculator {
-
- public static final AsinCalculator INSTANCE = new AsinCalculator();
-
- private int n = 0;
- private BigRational factorial2n = BigRational.ONE;
- private BigRational factorialN = BigRational.ONE;
- private BigRational fourPowerN = BigRational.ONE;
-
- private AsinCalculator() {
- }
-
- @Override
- protected BigRational getCurrentFactor() {
- BigRational factor = factorial2n.divide(fourPowerN.multiply(factorialN).multiply(factorialN).multiply(2 * n + 1));
- return factor;
- }
-
- @Override
- protected void calculateNextFactor() {
- n++;
- factorial2n = factorial2n.multiply(2 * n - 1).multiply(2 * n);
- factorialN = factorialN.multiply(n);
- fourPowerN = fourPowerN.multiply(4);
- }
-
- @Override
- protected PowerIterator createPowerIterator(BigDecimal x, MathContext mathContext) {
- return new PowerTwoNPlusOneIterator(x, mathContext);
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/AtanhCalculator.java b/src/main/java/ch/obermuhlner/math/big/internal/AtanhCalculator.java
deleted file mode 100644
index a2f844a094..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/AtanhCalculator.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import ch.obermuhlner.math.big.BigRational;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-/**
- * Calculates sinus hyperbolicus using the Taylor series.
- *
- * <p>See <a href="https://en.wikipedia.org/wiki/Taylor_series">Wikipedia: Taylor series</a></p>
- *
- * <p>No argument checking or optimizations are done.
- * This implementation is <strong>not</strong> intended to be called directly.</p>
- */
-public class AtanhCalculator extends SeriesCalculator {
-
- public static final AtanhCalculator INSTANCE = new AtanhCalculator();
-
- private int n = 0;
-
- private AtanhCalculator() {
- super(true);
- }
-
- @Override
- protected BigRational getCurrentFactor() {
- return BigRational.valueOf(1, 2 * n + 1);
- }
-
- @Override
- protected void calculateNextFactor() {
- n++;
- }
-
- @Override
- protected PowerIterator createPowerIterator(BigDecimal x, MathContext mathContext) {
- return new PowerTwoNPlusOneIterator(x, mathContext);
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/CosCalculator.java b/src/main/java/ch/obermuhlner/math/big/internal/CosCalculator.java
deleted file mode 100644
index bf9edbd691..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/CosCalculator.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-import ch.obermuhlner.math.big.BigRational;
-
-/**
- * Calculates cosinus using the Maclaurin series.
- *
- * <p>See <a href="https://de.wikipedia.org/wiki/Taylorreihe">Wikipedia: Taylorreihe</a></p>
- *
- * <p>No argument checking or optimizations are done.
- * This implementation is <strong>not</strong> intended to be called directly.</p>
- */
-public class CosCalculator extends SeriesCalculator {
-
- public static final CosCalculator INSTANCE = new CosCalculator();
-
- private int n = 0;
- private boolean negative = false;
- private BigRational factorial2n = BigRational.ONE;
-
- private CosCalculator() {
- super(true);
- }
-
- @Override
- protected BigRational getCurrentFactor() {
- BigRational factor = factorial2n.reciprocal();
- if (negative) {
- factor = factor.negate();
- }
- return factor;
- }
-
- @Override
- protected void calculateNextFactor() {
- n++;
- factorial2n = factorial2n.multiply(2 * n - 1).multiply(2 * n);
- negative = !negative;
- }
-
- @Override
- protected PowerIterator createPowerIterator(BigDecimal x, MathContext mathContext) {
- return new PowerTwoNIterator(x, mathContext);
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/CoshCalculator.java b/src/main/java/ch/obermuhlner/math/big/internal/CoshCalculator.java
deleted file mode 100644
index f22631e8ae..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/CoshCalculator.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-import ch.obermuhlner.math.big.BigRational;
-
-/**
- * Calculates cosinus hyperbolicus using the Taylor series.
- *
- * <p>See <a href="https://en.wikipedia.org/wiki/Taylor_series">Wikipedia: Taylor series</a></p>
- *
- * <p>No argument checking or optimizations are done.
- * This implementation is <strong>not</strong> intended to be called directly.</p>
- */
-public class CoshCalculator extends SeriesCalculator {
-
- public static final CoshCalculator INSTANCE = new CoshCalculator();
-
- private int n = 0;
-
- private BigRational factorial2n = BigRational.ONE;
-
- private CoshCalculator() {
- super(true);
- }
-
- @Override
- protected BigRational getCurrentFactor() {
- return factorial2n.reciprocal();
- }
-
- @Override
- protected void calculateNextFactor() {
- n++;
- factorial2n = factorial2n.multiply(2 * n - 1).multiply(2 * n);
- }
-
- @Override
- protected PowerIterator createPowerIterator(BigDecimal x, MathContext mathContext) {
- return new PowerTwoNIterator(x, mathContext);
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/ExpCalculator.java b/src/main/java/ch/obermuhlner/math/big/internal/ExpCalculator.java
deleted file mode 100644
index 16c6e6ac21..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/ExpCalculator.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-import ch.obermuhlner.math.big.BigRational;
-
-/**
- * Calculates exp using the Maclaurin series.
- *
- * <p>See <a href="https://de.wikipedia.org/wiki/Taylorreihe">Wikipedia: Taylorreihe</a></p>
- *
- * <p>No argument checking or optimizations are done.
- * This implementation is <strong>not</strong> intended to be called directly.</p>
- */
-public class ExpCalculator extends SeriesCalculator {
-
- public static final ExpCalculator INSTANCE = new ExpCalculator();
-
- private int n = 0;
- private BigRational oneOverFactorialOfN = BigRational.ONE;
-
- private ExpCalculator() {
- // prevent instances
- }
-
- @Override
- protected BigRational getCurrentFactor() {
- return oneOverFactorialOfN;
- }
-
- @Override
- protected void calculateNextFactor() {
- n++;
- oneOverFactorialOfN = oneOverFactorialOfN.divide(n);
- }
-
- @Override
- protected PowerIterator createPowerIterator(BigDecimal x, MathContext mathContext) {
- return new PowerNIterator(x, mathContext);
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/PowerIterator.java b/src/main/java/ch/obermuhlner/math/big/internal/PowerIterator.java
deleted file mode 100644
index def0f5f7ef..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/PowerIterator.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import java.math.BigDecimal;
-
-/**
- * Iterator over the powers of a value x.
- *
- * <p>This API allows to efficiently calculate the various powers of x in a taylor series by storing intermediate results.</p>
- * <p>For example x<sup>n</sup> can be calculated using one multiplication by storing the previously calculated x<sup>n-1</sup> and x.</p>
- *
- * <p>{@link #getCurrentPower()} will be called first to retrieve the initial value.</p>
- *
- * For later iterations {@link #calculateNextPower()} will be called before {@link #getCurrentPower()}.
- */
-public interface PowerIterator {
-
- /**
- * Returns the current power.
- *
- * @return the current power.
- */
- BigDecimal getCurrentPower();
-
- /**
- * Calculates the next power.
- */
- void calculateNextPower();
-} \ No newline at end of file
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/PowerNIterator.java b/src/main/java/ch/obermuhlner/math/big/internal/PowerNIterator.java
deleted file mode 100644
index d6ef34e01e..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/PowerNIterator.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-/**
- * {@link PowerIterator} to calculate x<sup>n</sup>.
- */
-public class PowerNIterator implements PowerIterator {
-
- private final BigDecimal x;
-
- private final MathContext mathContext;
-
- private BigDecimal powerOfX;
-
- public PowerNIterator(BigDecimal x, MathContext mathContext) {
- this.x = x;
- this.mathContext = mathContext;
-
- powerOfX = BigDecimal.ONE;
- }
-
- @Override
- public BigDecimal getCurrentPower() {
- return powerOfX;
- }
-
- @Override
- public void calculateNextPower() {
- powerOfX = powerOfX.multiply(x, mathContext);
- }
-} \ No newline at end of file
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNIterator.java b/src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNIterator.java
deleted file mode 100644
index 839d617e16..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNIterator.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-/**
- * {@link PowerIterator} to calculate x<sup>2*n</sup>.
- */
-public class PowerTwoNIterator implements PowerIterator {
-
- private final MathContext mathContext;
-
- private final BigDecimal xPowerTwo;
-
- private BigDecimal powerOfX;
-
- public PowerTwoNIterator(BigDecimal x, MathContext mathContext) {
- this.mathContext = mathContext;
-
- xPowerTwo = x.multiply(x, mathContext);
- powerOfX = BigDecimal.ONE;
- }
-
- @Override
- public BigDecimal getCurrentPower() {
- return powerOfX;
- }
-
- @Override
- public void calculateNextPower() {
- powerOfX = powerOfX.multiply(xPowerTwo, mathContext);
- }
-} \ No newline at end of file
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNMinusOneIterator.java b/src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNMinusOneIterator.java
deleted file mode 100644
index 15ad0168c0..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNMinusOneIterator.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import ch.obermuhlner.math.big.BigDecimalMath;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-/**
- * {@link PowerIterator} to calculate x<sup>2*n-1</sup>.
- */
-public class PowerTwoNMinusOneIterator implements PowerIterator {
-
- private final MathContext mathContext;
-
- private final BigDecimal xPowerTwo;
-
- private BigDecimal powerOfX;
-
- public PowerTwoNMinusOneIterator(BigDecimal x, MathContext mathContext) {
- this.mathContext = mathContext;
-
- xPowerTwo = x.multiply(x, mathContext);
- powerOfX = BigDecimalMath.reciprocal(x, mathContext);
- }
-
- @Override
- public BigDecimal getCurrentPower() {
- return powerOfX;
- }
-
- @Override
- public void calculateNextPower() {
- powerOfX = powerOfX.multiply(xPowerTwo, mathContext);
- }
-} \ No newline at end of file
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNPlusOneIterator.java b/src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNPlusOneIterator.java
deleted file mode 100644
index 57afa97634..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/PowerTwoNPlusOneIterator.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-/**
- * {@link PowerIterator} to calculate x<sup>2*n+1</sup>.
- */
-public class PowerTwoNPlusOneIterator implements PowerIterator {
-
- private final MathContext mathContext;
-
- private final BigDecimal xPowerTwo;
-
- private BigDecimal powerOfX;
-
- public PowerTwoNPlusOneIterator(BigDecimal x, MathContext mathContext) {
- this.mathContext = mathContext;
-
- xPowerTwo = x.multiply(x, mathContext);
- powerOfX = x;
- }
-
- @Override
- public BigDecimal getCurrentPower() {
- return powerOfX;
- }
-
- @Override
- public void calculateNextPower() {
- powerOfX = powerOfX.multiply(xPowerTwo, mathContext);
- }
-} \ No newline at end of file
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/SeriesCalculator.java b/src/main/java/ch/obermuhlner/math/big/internal/SeriesCalculator.java
deleted file mode 100644
index 117c2737d2..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/SeriesCalculator.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import ch.obermuhlner.math.big.BigRational;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.util.ArrayList;
-import java.util.List;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * Utility class to calculate taylor series efficiently until the maximum error (as defined by the precision in the {@link MathContext} is reached.
- *
- * <p>Stores the factors of the taylor series terms so that future calculations will be faster.</p>
- */
-public abstract class SeriesCalculator {
-
- private final boolean calculateInPairs;
-
- private final List<BigRational> factors = new ArrayList<>();
-
- /**
- * Constructs a {@link SeriesCalculator} that calculates single terms.
- */
- protected SeriesCalculator() {
- this(false);
- }
-
- /**
- * Constructs a {@link SeriesCalculator} with control over whether the sum terms are calculated in pairs.
- *
- * <p>Calculation of pairs is useful for taylor series where the terms alternate the sign.
- * In these cases it is more efficient to calculate two terms at once check then whether the acceptable error has been reached.</p>
- *
- * @param calculateInPairs <code>true</code> to calculate the terms in pairs, <code>false</code> to calculate single terms
- */
- protected SeriesCalculator(boolean calculateInPairs) {
- this.calculateInPairs = calculateInPairs;
- }
-
- /**
- * Calculates the series for the specified value x and the precision defined in the {@link MathContext}.
- *
- * @param x the value x
- * @param mathContext the {@link MathContext}
- * @return the calculated result
- */
- public BigDecimal calculate(BigDecimal x, MathContext mathContext) {
- BigDecimal acceptableError = BigDecimal.ONE.movePointLeft(mathContext.getPrecision() + 1);
-
- PowerIterator powerIterator = createPowerIterator(x, mathContext);
-
- BigDecimal sum = BigDecimal.ZERO;
- BigDecimal step;
- int i = 0;
- do {
- BigRational factor;
- BigDecimal xToThePower;
-
- factor = getFactor(i);
- xToThePower = powerIterator.getCurrentPower();
- powerIterator.calculateNextPower();
- step = factor.getNumerator().multiply(xToThePower).divide(factor.getDenominator(), mathContext);
- i++;
-
- if (calculateInPairs) {
- factor = getFactor(i);
- xToThePower = powerIterator.getCurrentPower();
- powerIterator.calculateNextPower();
- BigDecimal step2 = factor.getNumerator().multiply(xToThePower).divide(factor.getDenominator(), mathContext);
- step = step.add(step2);
- i++;
- }
-
- sum = sum.add(step);
- //System.out.println(sum + " " + step);
- } while (step.abs().compareTo(acceptableError) > 0);
-
- return sum.round(mathContext);
- }
-
- /**
- * Creates the {@link PowerIterator} used for this series.
- *
- * @param x the value x
- * @param mathContext the {@link MathContext}
- * @return the {@link PowerIterator}
- */
- protected abstract PowerIterator createPowerIterator(BigDecimal x, MathContext mathContext);
-
- /**
- * Returns the factor of the term with specified index.
- *
- * All mutable state of this class (and all its subclasses) must be modified in this method.
- * This method is synchronized to allow thread-safe usage of this class.
- *
- * @param index the index (starting with 0)
- * @return the factor of the specified term
- */
- protected synchronized BigRational getFactor(int index) {
- while (factors.size() <= index) {
- BigRational factor = getCurrentFactor();
- addFactor(factor);
- calculateNextFactor();
- }
- return factors.get(index);
- }
-
- private void addFactor(BigRational factor){
- factors.add(requireNonNull(factor, "Factor cannot be null"));
- }
-
- /**
- * Returns the factor of the highest term already calculated.
- * <p>When called for the first time will return the factor of the first term (index 0).</p>
- * <p>After this call the method {@link #calculateNextFactor()} will be called to prepare for the next term.</p>
- *
- * @return the factor of the highest term
- */
- protected abstract BigRational getCurrentFactor();
-
- /**
- * Calculates the factor of the next term.
- */
- protected abstract void calculateNextFactor();
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/SinCalculator.java b/src/main/java/ch/obermuhlner/math/big/internal/SinCalculator.java
deleted file mode 100644
index 471074fd6b..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/SinCalculator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-import ch.obermuhlner.math.big.BigRational;
-
-/**
- * Calculates sinus using the Maclaurin series.
- *
- * <p>See <a href="https://de.wikipedia.org/wiki/Taylorreihe">Wikipedia: Taylorreihe</a></p>
- *
- * <p>No argument checking or optimizations are done.
- * This implementation is <strong>not</strong> intended to be called directly.</p>
- */
-public class SinCalculator extends SeriesCalculator {
-
- public static final SinCalculator INSTANCE = new SinCalculator();
-
- private int n = 0;
- private boolean negative = false;
- private BigRational factorial2nPlus1 = BigRational.ONE;
-
- private SinCalculator() {
- super(true);
- }
-
- @Override
- protected BigRational getCurrentFactor() {
- BigRational factor = factorial2nPlus1.reciprocal();
- if (negative) {
- factor = factor.negate();
- }
- return factor;
- }
-
- @Override
- protected void calculateNextFactor() {
- n++;
- factorial2nPlus1 = factorial2nPlus1.multiply(2 * n);
- factorial2nPlus1 = factorial2nPlus1.multiply(2 * n + 1);
- negative = !negative;
- }
-
- @Override
- protected PowerIterator createPowerIterator(BigDecimal x, MathContext mathContext) {
- return new PowerTwoNPlusOneIterator(x, mathContext);
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/internal/SinhCalculator.java b/src/main/java/ch/obermuhlner/math/big/internal/SinhCalculator.java
deleted file mode 100644
index 9601735755..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/internal/SinhCalculator.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package ch.obermuhlner.math.big.internal;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-import ch.obermuhlner.math.big.BigRational;
-
-/**
- * Calculates sinus hyperbolicus using the Taylor series.
- *
- * <p>See <a href="https://en.wikipedia.org/wiki/Taylor_series">Wikipedia: Taylor series</a></p>
- *
- * <p>No argument checking or optimizations are done.
- * This implementation is <strong>not</strong> intended to be called directly.</p>
- */
-public class SinhCalculator extends SeriesCalculator {
-
- public static final SinhCalculator INSTANCE = new SinhCalculator();
-
- private int n = 0;
-
- private BigRational factorial2nPlus1 = BigRational.ONE;
-
- private SinhCalculator() {
- super(true);
- }
-
- @Override
- protected BigRational getCurrentFactor() {
- return factorial2nPlus1.reciprocal();
- }
-
- @Override
- protected void calculateNextFactor() {
- n++;
- factorial2nPlus1 = factorial2nPlus1.multiply(2 * n);
- factorial2nPlus1 = factorial2nPlus1.multiply(2 * n + 1);
- }
-
- @Override
- protected PowerIterator createPowerIterator(BigDecimal x, MathContext mathContext) {
- return new PowerTwoNPlusOneIterator(x, mathContext);
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/stream/BigDecimalStream.java b/src/main/java/ch/obermuhlner/math/big/stream/BigDecimalStream.java
deleted file mode 100644
index 05a45fd846..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/stream/BigDecimalStream.java
+++ /dev/null
@@ -1,219 +0,0 @@
-package ch.obermuhlner.math.big.stream;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.util.Comparator;
-import java.util.Spliterator;
-import java.util.Spliterators.AbstractSpliterator;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-import ch.obermuhlner.math.big.BigDecimalMath;
-
-/**
- * Provides constructor methods for streams of {@link BigDecimal} elements.
- */
-public class BigDecimalStream {
-
- /**
- * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
- * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
- *
- * <p>An equivalent sequence of increasing values can be produced
- * sequentially using a {@code for} loop as follows:
- * <pre>for (BigDecimal i = startInclusive; i.compareTo(endExclusive) &lt; 0; i = i.add(step, mathContext)) {
- // ...
-}</pre>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endExclusive the exclusive upper bound
- * @param step the step between elements
- * @param mathContext the {@link MathContext} used for all mathematical operations
- * @return a sequential {@code Stream<BigDecimal>}
- */
- public static Stream<BigDecimal> range(BigDecimal startInclusive, BigDecimal endExclusive, BigDecimal step, MathContext mathContext) {
- if (step.signum() == 0) {
- throw new IllegalArgumentException("invalid step: 0");
- }
- if (endExclusive.subtract(startInclusive).signum() != step.signum()) {
- return Stream.empty();
- }
- return StreamSupport.stream(new BigDecimalSpliterator(startInclusive, endExclusive, false, step, mathContext), false);
- }
-
- /**
- * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
- * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
- *
- * <p>The {@code long} arguments are converted using {@link BigDecimal#valueOf(long)}.</p>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endExclusive the exclusive upper bound
- * @param step the step between elements
- * @param mathContext the {@link MathContext} used for all mathematical operations
- * @return a sequential {@code Stream<BigDecimal>}
- * @see #range(BigDecimal, BigDecimal, BigDecimal, MathContext)
- */
- public static Stream<BigDecimal> range(long startInclusive, long endExclusive, long step, MathContext mathContext) {
- return range(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endExclusive), BigDecimal.valueOf(step), mathContext);
- }
-
- /**
- * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
- * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
- *
- * <p>The {@code double} arguments are converted using {@link BigDecimal#valueOf(double)}.</p>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endExclusive the exclusive upper bound
- * @param step the step between elements
- * @param mathContext the {@link MathContext} used for all mathematical operations
- * @return a sequential {@code Stream<BigDecimal>}
- * @see #range(BigDecimal, BigDecimal, BigDecimal, MathContext)
- */
- public static Stream<BigDecimal> range(double startInclusive, double endExclusive, double step, MathContext mathContext) {
- return range(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endExclusive), BigDecimal.valueOf(step), mathContext);
- }
-
- /**
- * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
- * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
- *
- * <p>An equivalent sequence of increasing values can be produced
- * sequentially using a {@code for} loop as follows:
- * <pre>for (BigDecimal i = startInclusive; i.compareTo(endInclusive) &lt;= 0; i = i.add(step, mathContext)) {
- // ...
-}</pre>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endInclusive the inclusive upper bound
- * @param step the step between elements
- * @param mathContext the {@link MathContext} used for all mathematical operations
- * @return a sequential {@code Stream<BigDecimal>}
- * @see #range(BigDecimal, BigDecimal, BigDecimal, MathContext)
- */
- public static Stream<BigDecimal> rangeClosed(BigDecimal startInclusive, BigDecimal endInclusive, BigDecimal step, MathContext mathContext) {
- if (step.signum() == 0) {
- throw new IllegalArgumentException("invalid step: 0");
- }
- if (endInclusive.subtract(startInclusive).signum() == -step.signum()) {
- return Stream.empty();
- }
- return StreamSupport.stream(new BigDecimalSpliterator(startInclusive, endInclusive, true, step, mathContext), false);
- }
-
- /**
- * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
- * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
- *
- * <p>The {@code long} arguments are converted using {@link BigDecimal#valueOf(long)}.</p>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endInclusive the inclusive upper bound
- * @param step the step between elements
- * @param mathContext the {@link MathContext} used for all mathematical operations
- * @return a sequential {@code Stream<BigDecimal>}
- * @see #rangeClosed(BigDecimal, BigDecimal, BigDecimal, MathContext)
- */
- public static Stream<BigDecimal> rangeClosed(long startInclusive, long endInclusive, long step, MathContext mathContext) {
- return rangeClosed(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endInclusive), BigDecimal.valueOf(step), mathContext);
- }
-
- /**
- * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
- * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
- *
- * <p>The {@code double} arguments are converted using {@link BigDecimal#valueOf(double)}.</p>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endInclusive the inclusive upper bound
- * @param step the step between elements
- * @param mathContext the {@link MathContext} used for all mathematical operations
- * @return a sequential {@code Stream<BigDecimal>}
- * @see #rangeClosed(BigDecimal, BigDecimal, BigDecimal, MathContext)
- */
- public static Stream<BigDecimal> rangeClosed(double startInclusive, double endInclusive, double step, MathContext mathContext) {
- return rangeClosed(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endInclusive), BigDecimal.valueOf(step), mathContext);
- }
-
- private static class BigDecimalSpliterator extends AbstractSpliterator<BigDecimal> {
-
- private BigDecimal value;
- private BigDecimal step;
- private long count;
- private MathContext mathContext;
-
- public BigDecimalSpliterator(BigDecimal startInclusive, BigDecimal step, long count, MathContext mathContext) {
- super(count,
- Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED | Spliterator.SORTED);
-
- this.value = startInclusive;
- this.step = step;
- this.count = count;
- this.mathContext = mathContext;
- }
-
- public BigDecimalSpliterator(BigDecimal startInclusive, BigDecimal end, boolean inclusive, BigDecimal step, MathContext mathContext) {
- this(startInclusive, step, estimatedCount(startInclusive, end, inclusive, step, mathContext), mathContext);
- }
-
- private static long estimatedCount(BigDecimal startInclusive, BigDecimal end, boolean inclusive, BigDecimal step, MathContext mathContext) {
- BigDecimal count = end.subtract(startInclusive).divide(step, mathContext);
- long result = count.longValue();
- if (BigDecimalMath.fractionalPart(count).signum() != 0) {
- result++;
- } else {
- if (inclusive) {
- result++;
- }
- }
- return result;
- }
-
- @Override
- public Comparator<? super BigDecimal> getComparator() {
- if (step.signum() < 0) {
- return Comparator.reverseOrder();
- }
- return null;
- }
-
- @Override
- public boolean tryAdvance(Consumer<? super BigDecimal> action) {
- if (count == 0) {
- return false;
- }
-
- action.accept(value);
- value = value.add(step, mathContext);
- count--;
- return true;
- }
-
- @Override
- public void forEachRemaining(Consumer<? super BigDecimal> action) {
- while (count > 0) {
- action.accept(value);
- value = value.add(step, mathContext);
- count--;
- }
- }
-
- @Override
- public Spliterator<BigDecimal> trySplit() {
- long firstHalfCount = count / 2;
-
- if (firstHalfCount == 0) {
- return null;
- }
-
- long secondHalfCount = count - firstHalfCount;
-
- count = firstHalfCount;
- BigDecimal startSecondHalf = value.add(step.multiply(new BigDecimal(firstHalfCount), mathContext), mathContext);
-
- return new BigDecimalSpliterator(startSecondHalf, step, secondHalfCount, mathContext);
- }
- }
-}
diff --git a/src/main/java/ch/obermuhlner/math/big/stream/BigFloatStream.java b/src/main/java/ch/obermuhlner/math/big/stream/BigFloatStream.java
deleted file mode 100644
index 1c982302a6..0000000000
--- a/src/main/java/ch/obermuhlner/math/big/stream/BigFloatStream.java
+++ /dev/null
@@ -1,214 +0,0 @@
-package ch.obermuhlner.math.big.stream;
-
-import java.util.Comparator;
-import java.util.Spliterator;
-import java.util.Spliterators.AbstractSpliterator;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-import ch.obermuhlner.math.big.BigFloat;
-import ch.obermuhlner.math.big.BigFloat.Context;
-
-/**
- * Provides constructor methods for streams of {@link BigFloat} elements.
- */
-public class BigFloatStream {
-
- /**
- * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
- * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
- *
- * <p>An equivalent sequence of increasing values can be produced
- * sequentially using a {@code for} loop as follows:
- * <pre>for (BigFloat i = startInclusive; i.isLessThan(endExclusive); i = i.add(step)) {
- // ...
-}</pre>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endExclusive the exclusive upper bound
- * @param step the step between elements
- * @return a sequential {@code Stream<BigFloat>}
- */
- public static Stream<BigFloat> range(BigFloat startInclusive, BigFloat endExclusive, BigFloat step) {
- if (step.isZero()) {
- throw new IllegalArgumentException("invalid step: 0");
- }
- if (endExclusive.subtract(startInclusive).signum() != step.signum()) {
- return Stream.empty();
- }
- return StreamSupport.stream(new BigFloatSpliterator(startInclusive, endExclusive, false, step), false);
- }
-
- /**
- * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
- * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
- *
- * <p>{@link Context#valueOf(long)} is used to convert the {@code long} values.</p>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endExclusive the exclusive upper bound
- * @param step the step between elements
- * @param context the {@link Context} used to convert the {@code long} values
- * @return a sequential {@code Stream<BigFloat>}
- * @see #range(BigFloat, BigFloat, BigFloat)
- */
- public static Stream<BigFloat> range(long startInclusive, long endExclusive, long step, Context context) {
- return range(context.valueOf(startInclusive), context.valueOf(endExclusive), context.valueOf(step));
- }
-
- /**
- * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
- * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
- *
- * <p>{@link Context#valueOf(double)} is used to convert the {@code double} values.</p>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endExclusive the exclusive upper bound
- * @param step the step between elements
- * @param context the {@link Context} used to convert the {@code double} values
- * @return a sequential {@code Stream<BigFloat>}
- * @see #range(BigFloat, BigFloat, BigFloat)
- */
- public static Stream<BigFloat> range(double startInclusive, double endExclusive, double step, Context context) {
- return range(context.valueOf(startInclusive), context.valueOf(endExclusive), context.valueOf(step));
- }
-
- /**
- * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
- * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
- *
- * <p>An equivalent sequence of increasing values can be produced
- * sequentially using a {@code for} loop as follows:
- * <pre>for (BigFloat i = startInclusive; i.isLessThanOrEqual(endInclusive); i = i.add(step)) {
- //...
-}
-</pre>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endInclusive the inclusive upper bound
- * @param step the step between elements
- * @return a sequential {@code Stream<BigFloat>}
- */
- public static Stream<BigFloat> rangeClosed(BigFloat startInclusive, BigFloat endInclusive, BigFloat step) {
- if (step.isZero()) {
- throw new IllegalArgumentException("invalid step: 0");
- }
- if (endInclusive.subtract(startInclusive).signum() == -step.signum()) {
- return Stream.empty();
- }
- return StreamSupport.stream(new BigFloatSpliterator(startInclusive, endInclusive, true, step), false);
- }
-
- /**
- * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
- * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
- *
- * <p>{@link Context#valueOf(long)} is used to convert the {@code long} values.</p>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endInclusive the inclusive upper bound
- * @param step the step between elements
- * @param context the {@link Context} used to convert the {@code long} values
- * @return a sequential {@code Stream<BigFloat>}
- * @see #rangeClosed(BigFloat, BigFloat, BigFloat)
- */
- public static Stream<BigFloat> rangeClosed(long startInclusive, long endInclusive, long step, Context context) {
- return rangeClosed(context.valueOf(startInclusive), context.valueOf(endInclusive), context.valueOf(step));
- }
-
- /**
- * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
- * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
- *
- * <p>{@link Context#valueOf(double)} is used to convert the {@code double} values.</p>
- *
- * @param startInclusive the (inclusive) initial value
- * @param endInclusive the inclusive upper bound
- * @param step the step between elements
- * @param context the {@link Context} used to convert the {@code double} values
- * @return a sequential {@code Stream<BigFloat>}
- * @see #rangeClosed(BigFloat, BigFloat, BigFloat)
- */
- public static Stream<BigFloat> rangeClosed(double startInclusive, double endInclusive, double step, Context context) {
- return rangeClosed(context.valueOf(startInclusive), context.valueOf(endInclusive), context.valueOf(step));
- }
-
- private static class BigFloatSpliterator extends AbstractSpliterator<BigFloat> {
-
- private BigFloat value;
- private BigFloat step;
- private long count;
-
- public BigFloatSpliterator(BigFloat startInclusive, BigFloat step, long count) {
- super(count,
- Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED | Spliterator.SORTED);
-
- this.value = startInclusive;
- this.step = step;
- this.count = count;
- }
-
- public BigFloatSpliterator(BigFloat startInclusive, BigFloat end, boolean inclusive, BigFloat step) {
- this(startInclusive, step, estimatedCount(startInclusive, end, inclusive, step));
- }
-
- private static long estimatedCount(BigFloat startInclusive, BigFloat end, boolean inclusive, BigFloat step) {
- BigFloat count = end.subtract(startInclusive).divide(step);
- long result = count.toLong();
- if (count.getFractionalPart().signum() != 0) {
- result++;
- } else {
- if (inclusive) {
- result++;
- }
- }
- return result;
- }
-
- @Override
- public Comparator<? super BigFloat> getComparator() {
- if (step.signum() < 0) {
- return Comparator.reverseOrder();
- }
- return null;
- }
-
- @Override
- public boolean tryAdvance(Consumer<? super BigFloat> action) {
- if (count == 0) {
- return false;
- }
-
- action.accept(value);
- value = value.add(step);
- count--;
- return true;
- }
-
- @Override
- public void forEachRemaining(Consumer<? super BigFloat> action) {
- while (count > 0) {
- action.accept(value);
- value = value.add(step);
- count--;
- }
- }
-
- @Override
- public Spliterator<BigFloat> trySplit() {
- long firstHalfCount = count / 2;
-
- if (firstHalfCount == 0) {
- return null;
- }
-
- long secondHalfCount = count - firstHalfCount;
-
- count = firstHalfCount;
- BigFloat startSecondHalf = value.add(step.multiply(firstHalfCount));
-
- return new BigFloatSpliterator(startSecondHalf, step, secondHalfCount);
- }
- }
-}