Example usage for java.math BigDecimal round

List of usage examples for java.math BigDecimal round

Introduction

In this page you can find the example usage for java.math BigDecimal round.

Prototype

public BigDecimal round(MathContext mc) 

Source Link

Document

Returns a BigDecimal rounded according to the MathContext settings.

Usage

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);

        }
    }
}