List of usage examples for java.math BigDecimal round
public BigDecimal round(MathContext mc)
From source file:org.nd4j.linalg.util.BigDecimalMath.java
/** * Reduce value to the interval [0,2*Pi]. * * @param x the original value// w w w . ja v a 2 s . c o m * @return the value modulo 2*pi in the interval from 0 to 2*pi. */ static public BigDecimal mod2pi(BigDecimal x) { /* write x= 2*pi*k+r with the precision in r defined by the precision of x and not * compromised by the precision of 2*pi, so the ulp of 2*pi*k should match the ulp of x. * First getFloat a guess of k to figure out how many digits of 2*pi are needed. */ int k = (int) (0.5 * x.doubleValue() / Math.PI); /* want to have err(2*pi*k)< err(x)=0.5*x.ulp, so err(pi) = err(x)/(4k) with two safety digits */ double err2pi; if (k != 0) { err2pi = 0.25 * Math.abs(x.ulp().doubleValue() / k); } else { err2pi = 0.5 * Math.abs(x.ulp().doubleValue()); } MathContext mc = new MathContext(2 + err2prec(6.283, err2pi)); BigDecimal twopi = pi(mc).multiply(new BigDecimal(2)); /* Delegate the actual operation to the BigDecimal class, which may return * a negative value of x was negative . */ BigDecimal res = x.remainder(twopi); if (res.compareTo(BigDecimal.ZERO) < 0) { res = res.add(twopi); } /* The actual precision is set by the input value, its absolute value of x.ulp()/2. */ mc = new MathContext(err2prec(res.doubleValue(), x.ulp().doubleValue() / 2.)); return res.round(mc); }
From source file:org.nd4j.linalg.util.BigDecimalMath.java
/** * The inverse hyperbolic sine./*from ww w . ja v a 2 s .co m*/ * * @param x The argument. * @return The arcsinh(x) . */ static public BigDecimal asinh(final BigDecimal x) { if (x.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } else { BigDecimal xhighpr = scalePrec(x, 2); /* arcsinh(x) = log(x+hypot(1,x)) */ BigDecimal logx = log(hypot(1, xhighpr).add(xhighpr)); /* The absolute error in arcsinh x is err(x)/sqrt(1+x^2) */ double xDbl = x.doubleValue(); double eps = 0.5 * x.ulp().doubleValue() / Math.hypot(1., xDbl); MathContext mc = new MathContext(err2prec(logx.doubleValue(), eps)); return logx.round(mc); } }
From source file:org.nd4j.linalg.util.BigDecimalMath.java
/** * The inverse trigonometric tangent.// w w w . jav a 2 s. c om * * @param x the argument. * @return the principal value of arctan(x) in radians in the range -pi/2 to +pi/2. */ static public BigDecimal atan(final BigDecimal x) { if (x.compareTo(BigDecimal.ZERO) < 0) { return atan(x.negate()).negate(); } else if (x.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } else if (x.doubleValue() > 0.7 && x.doubleValue() < 3.0) { /* Abramowitz-Stegun 4.4.34 convergence acceleration * 2*arctan(x) = arctan(2x/(1-x^2)) = arctan(y). x=(sqrt(1+y^2)-1)/y * This maps 0<=y<=3 to 0<=x<=0.73 roughly. Temporarily with 2 protectionist digits. */ BigDecimal y = scalePrec(x, 2); BigDecimal newx = divideRound(hypot(1, y).subtract(BigDecimal.ONE), y); /* intermediate result with too optimistic error estimate*/ BigDecimal resul = multiplyRound(atan(newx), 2); /* absolute error in the result is errx/(1+x^2), where errx = half of the ulp. */ double eps = x.ulp().doubleValue() / (2.0 * Math.hypot(1.0, x.doubleValue())); MathContext mc = new MathContext(err2prec(resul.doubleValue(), eps)); return resul.round(mc); } else if (x.doubleValue() < 0.71) { /* Taylor expansion around x=0; Abramowitz-Stegun 4.4.42 */ final BigDecimal xhighpr = scalePrec(x, 2); final BigDecimal xhighprSq = multiplyRound(xhighpr, xhighpr).negate(); BigDecimal resul = xhighpr.plus(); /* signed x^(2i+1) */ BigDecimal xpowi = xhighpr; /* absolute error in the result is errx/(1+x^2), where errx = half of the ulp. */ double eps = x.ulp().doubleValue() / (2.0 * Math.hypot(1.0, x.doubleValue())); for (int i = 1;; i++) { xpowi = multiplyRound(xpowi, xhighprSq); BigDecimal c = divideRound(xpowi, 2 * i + 1); resul = resul.add(c); if (Math.abs(c.doubleValue()) < 0.1 * eps) { break; } } MathContext mc = new MathContext(err2prec(resul.doubleValue(), eps)); return resul.round(mc); } else { /* Taylor expansion around x=infinity; Abramowitz-Stegun 4.4.42 */ /* absolute error in the result is errx/(1+x^2), where errx = half of the ulp. */ double eps = x.ulp().doubleValue() / (2.0 * Math.hypot(1.0, x.doubleValue())); /* start with the term pi/2; gather its precision relative to the expected result */ MathContext mc = new MathContext(2 + err2prec(3.1416, eps)); BigDecimal onepi = pi(mc); BigDecimal resul = onepi.divide(new BigDecimal(2)); final BigDecimal xhighpr = divideRound(-1, scalePrec(x, 2)); final BigDecimal xhighprSq = multiplyRound(xhighpr, xhighpr).negate(); /* signed x^(2i+1) */ BigDecimal xpowi = xhighpr; for (int i = 0;; i++) { BigDecimal c = divideRound(xpowi, 2 * i + 1); resul = resul.add(c); if (Math.abs(c.doubleValue()) < 0.1 * eps) { break; } xpowi = multiplyRound(xpowi, xhighprSq); } mc = new MathContext(err2prec(resul.doubleValue(), eps)); return resul.round(mc); } }
From source file:org.nd4j.linalg.util.BigDecimalMath.java
/** * The inverse hyperbolic cosine.// w w w . j a va2 s. co m * * @param x The argument. * @return The arccosh(x) . */ static public BigDecimal acosh(final BigDecimal x) { if (x.compareTo(BigDecimal.ONE) < 0) { throw new ArithmeticException("Out of range argument cosh " + x.toString()); } else if (x.compareTo(BigDecimal.ONE) == 0) { return BigDecimal.ZERO; } else { BigDecimal xhighpr = scalePrec(x, 2); /* arccosh(x) = log(x+sqrt(x^2-1)) */ BigDecimal logx = log(sqrt(xhighpr.pow(2).subtract(BigDecimal.ONE)).add(xhighpr)); /* The absolute error in arcsinh x is err(x)/sqrt(x^2-1) */ double xDbl = x.doubleValue(); double eps = 0.5 * x.ulp().doubleValue() / Math.sqrt(xDbl * xDbl - 1.); MathContext mc = new MathContext(err2prec(logx.doubleValue(), eps)); return logx.round(mc); } }
From source file:org.nd4j.linalg.util.BigDecimalMath.java
/** * Power function.//from w w w. j a va 2 s. co m * * @param x Base of the power. * @param y Exponent of the power. * @return x^y. * The estimation of the relative error in the result is |log(x)*err(y)|+|y*err(x)/x| */ static public BigDecimal pow(final BigDecimal x, final BigDecimal y) { if (x.compareTo(BigDecimal.ZERO) < 0) { throw new ArithmeticException("Cannot power negative " + x.toString()); } else if (x.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } else { /* return x^y = exp(y*log(x)) ; */ BigDecimal logx = log(x); BigDecimal ylogx = y.multiply(logx); BigDecimal resul = exp(ylogx); /* The estimation of the relative error in the result is |log(x)*err(y)|+|y*err(x)/x| */ double errR = Math.abs(logx.doubleValue() * y.ulp().doubleValue() / 2.) + Math.abs(y.doubleValue() * x.ulp().doubleValue() / 2. / x.doubleValue()); MathContext mcR = new MathContext(err2prec(1.0, errR)); return resul.round(mcR); } }
From source file:org.nd4j.linalg.util.BigDecimalMath.java
/** * The hypotenuse.//from w w w. j a v a 2 s.co m * * @param x the first argument. * @param y the second argument. * @return the square root of the sum of the squares of the two arguments, sqrt(x^2+y^2). */ static public BigDecimal hypot(final BigDecimal x, final BigDecimal y) { /* compute x^2+y^2 */ BigDecimal z = x.pow(2).add(y.pow(2)); /* truncate to the precision set by x and y. Absolute error = 2*x*xerr+2*y*yerr, * where the two errors are 1/2 of the ulps. Two intermediate protectio digits. */ BigDecimal zerr = x.abs().multiply(x.ulp()).add(y.abs().multiply(y.ulp())); MathContext mc = new MathContext(2 + err2prec(z, zerr)); /* Pull square root */ z = sqrt(z.round(mc)); /* Final rounding. Absolute error in the square root is (y*yerr+x*xerr)/z, where zerr holds 2*(x*xerr+y*yerr). */ mc = new MathContext(err2prec(z.doubleValue(), 0.5 * zerr.doubleValue() / z.doubleValue())); return z.round(mc); }
From source file:org.nd4j.linalg.util.BigDecimalMath.java
/** * Reduce value to the interval [-Pi/2,Pi/2]. * * @param x The original value/* ww w .j a v a 2 s . com*/ * @return The value modulo pi, shifted to the interval from -Pi/2 to Pi/2. */ static public BigDecimal modpi(BigDecimal x) { /* write x= pi*k+r with the precision in r defined by the precision of x and not * compromised by the precision of pi, so the ulp of pi*k should match the ulp of x. * First getFloat a guess of k to figure out how many digits of pi are needed. */ int k = (int) (x.doubleValue() / Math.PI); /* want to have err(pi*k)< err(x)=x.ulp/2, so err(pi) = err(x)/(2k) with two safety digits */ double errpi; if (k != 0) { errpi = 0.5 * Math.abs(x.ulp().doubleValue() / k); } else { errpi = 0.5 * Math.abs(x.ulp().doubleValue()); } MathContext mc = new MathContext(2 + err2prec(3.1416, errpi)); BigDecimal onepi = pi(mc); BigDecimal pihalf = onepi.divide(new BigDecimal(2)); /* Delegate the actual operation to the BigDecimal class, which may return * a negative value of x was negative . */ BigDecimal res = x.remainder(onepi); if (res.compareTo(pihalf) > 0) { res = res.subtract(onepi); } else if (res.compareTo(pihalf.negate()) < 0) { res = res.add(onepi); } /* The actual precision is set by the input value, its absolute value of x.ulp()/2. */ mc = new MathContext(err2prec(res.doubleValue(), x.ulp().doubleValue() / 2.)); return res.round(mc); }
From source file:org.nd4j.linalg.util.BigDecimalMath.java
/** * The hypotenuse.// w w w . jav a2 s . c om * * @param n the first argument. * @param x the second argument. * @return the square root of the sum of the squares of the two arguments, sqrt(n^2+x^2). */ static public BigDecimal hypot(final int n, final BigDecimal x) { /* compute n^2+x^2 in infinite precision */ BigDecimal z = (new BigDecimal(n)).pow(2).add(x.pow(2)); /* Truncate to the precision set by x. Absolute error = in z (square of the result) is |2*x*xerr|, * where the error is 1/2 of the ulp. Two intermediate protection digits. * zerr is a signed value, but used only in conjunction with err2prec(), so this feature does not harm. */ double zerr = x.doubleValue() * x.ulp().doubleValue(); MathContext mc = new MathContext(2 + err2prec(z.doubleValue(), zerr)); /* Pull square root */ z = sqrt(z.round(mc)); /* Final rounding. Absolute error in the square root is x*xerr/z, where zerr holds 2*x*xerr. */ mc = new MathContext(err2prec(z.doubleValue(), 0.5 * zerr / z.doubleValue())); return z.round(mc); }
From source file:org.nd4j.linalg.util.BigDecimalMath.java
/** * The natural logarithm./*from w w w .ja va 2s . c o m*/ * * @param x the argument. * @return ln(x). * The precision of the result is implicitly defined by the precision in the argument. */ static public BigDecimal log(BigDecimal x) { /* the value is undefined if x is negative. */ if (x.compareTo(BigDecimal.ZERO) < 0) { throw new ArithmeticException("Cannot take log of negative " + x.toString()); } else if (x.compareTo(BigDecimal.ONE) == 0) { /* log 1. = 0. */ return scalePrec(BigDecimal.ZERO, x.precision() - 1); } else if (Math.abs(x.doubleValue() - 1.0) <= 0.3) { /* The standard Taylor series around x=1, z=0, z=x-1. Abramowitz-Stegun 4.124. * The absolute error is err(z)/(1+z) = err(x)/x. */ BigDecimal z = scalePrec(x.subtract(BigDecimal.ONE), 2); BigDecimal zpown = z; double eps = 0.5 * x.ulp().doubleValue() / Math.abs(x.doubleValue()); BigDecimal resul = z; for (int k = 2;; k++) { zpown = multiplyRound(zpown, z); BigDecimal c = divideRound(zpown, k); if (k % 2 == 0) { resul = resul.subtract(c); } else { resul = resul.add(c); } if (Math.abs(c.doubleValue()) < eps) { break; } } MathContext mc = new MathContext(err2prec(resul.doubleValue(), eps)); return resul.round(mc); } else { final double xDbl = x.doubleValue(); final double xUlpDbl = x.ulp().doubleValue(); /* Map log(x) = log root[r](x)^r = r*log( root[r](x)) with the aim * to move roor[r](x) near to 1.2 (that is, below the 0.3 appearing above), where log(1.2) is roughly 0.2. */ int r = (int) (Math.log(xDbl) / 0.2); /* Since the actual requirement is a function of the value 0.3 appearing above, * we avoid the hypothetical case of endless recurrence by ensuring that r >= 2. */ r = Math.max(2, r); /* Compute r-th root with 2 additional digits of precision */ BigDecimal xhighpr = scalePrec(x, 2); BigDecimal resul = root(r, xhighpr); resul = log(resul).multiply(new BigDecimal(r)); /* error propagation: log(x+errx) = log(x)+errx/x, so the absolute error * in the result equals the relative error in the input, xUlpDbl/xDbl . */ MathContext mc = new MathContext(err2prec(resul.doubleValue(), xUlpDbl / xDbl)); return resul.round(mc); } }
From source file:org.nd4j.linalg.util.BigDecimalMath.java
/** * The hyperbolic sine./* w ww . j a v a 2 s . c o m*/ * * @param x the argument. * @return the sinh(x) = (exp(x)-exp(-x))/2 . */ static public BigDecimal sinh(final BigDecimal x) { if (x.compareTo(BigDecimal.ZERO) < 0) { return sinh(x.negate()).negate(); } else if (x.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } else { if (x.doubleValue() > 2.4) { /* Move closer to zero with sinh(2x)= 2*sinh(x)*cosh(x). */ BigDecimal two = new BigDecimal(2); BigDecimal xhalf = x.divide(two); BigDecimal resul = sinh(xhalf).multiply(cosh(xhalf)).multiply(two); /* The error in the result is set by the error in x itself. * The first derivative of sinh(x) is cosh(x), so the absolute error * in the result is cosh(x)*errx, and the relative error is coth(x)*errx = errx/tanh(x) */ double eps = Math.tanh(x.doubleValue()); MathContext mc = new MathContext(err2prec(0.5 * x.ulp().doubleValue() / eps)); return resul.round(mc); } else { BigDecimal xhighpr = scalePrec(x, 2); /* Simple Taylor expansion, sum_{i=0..infinity} x^(2i+1)/(2i+1)! */ BigDecimal resul = xhighpr; /* x^i */ BigDecimal xpowi = xhighpr; /* 2i+1 factorial */ BigInteger ifac = BigInteger.ONE; /* The error in the result is set by the error in x itself. */ double xUlpDbl = x.ulp().doubleValue(); /* The error in the result is set by the error in x itself. * We need at most k terms to squeeze x^(2k+1)/(2k+1)! below this value. * x^(2k+1) < x.ulp; (2k+1)*log10(x) < -x.precision; 2k*log10(x)< -x.precision; * 2k*(-log10(x)) > x.precision; 2k*log10(1/x) > x.precision */ int k = (int) (x.precision() / Math.log10(1.0 / xhighpr.doubleValue())) / 2; MathContext mcTay = new MathContext(err2prec(x.doubleValue(), xUlpDbl / k)); for (int i = 1;; i++) { /* TBD: at which precision will 2*i or 2*i+1 overflow? */ ifac = ifac.multiply(new BigInteger("" + (2 * i))); ifac = ifac.multiply(new BigInteger("" + (2 * i + 1))); xpowi = xpowi.multiply(xhighpr).multiply(xhighpr); BigDecimal corr = xpowi.divide(new BigDecimal(ifac), mcTay); resul = resul.add(corr); if (corr.abs().doubleValue() < 0.5 * xUlpDbl) { break; } } /* The error in the result is set by the error in x itself. */ MathContext mc = new MathContext(x.precision()); return resul.round(mc); } } }