nd4j-common/src/main/java/org/nd4j/linalg/util/BigDecimalMath.java
static public BigDecimal asin(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ONE) > 0 || x.compareTo(BigDecimal.ONE.negate()) < 0) {
            throw new ArithmeticException("Out of range argument " + x.toString() + " of asin");


        } else if (x.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        } else if (x.compareTo(BigDecimal.ONE) == 0) {
            /* arcsin(1) = pi/2
             */
            double errpi = Math.sqrt(x.ulp().doubleValue());
            MathContext mc = new MathContext(err2prec(3.14159, errpi));


            return pi(mc).divide(new BigDecimal(2));


        } else if (x.compareTo(BigDecimal.ZERO) < 0) {
            return asin(x.negate()).negate();


        } else if (x.doubleValue() > 0.7) {
            final BigDecimal xCompl = BigDecimal.ONE.subtract(x);
            final double xDbl = x.doubleValue();
            final double xUlpDbl = x.ulp().doubleValue() / 2.;
            final double eps = xUlpDbl / 2. / Math.sqrt(1. - Math.pow(xDbl, 2.));


            final BigDecimal xhighpr = scalePrec(xCompl, 3);
            final BigDecimal xhighprV = divideRound(xhighpr, 4);
            BigDecimal resul = BigDecimal.ONE;
            /* x^(2i+1) */
            BigDecimal xpowi = BigDecimal.ONE;
            /* i factorial */
            BigInteger ifacN = BigInteger.ONE;
            BigInteger ifacD = BigInteger.ONE;


            for (int i = 1;; i++) {
                ifacN = ifacN.multiply(BigInteger.valueOf(2 * i - 1));
                ifacD = ifacD.multiply(BigInteger.valueOf(i));


                if (i == 1) {
                    xpowi = xhighprV;
                } else {
                    xpowi = multiplyRound(xpowi, xhighprV);
                }
                BigDecimal c = divideRound(multiplyRound(xpowi, ifacN), ifacD.multiply(BigInteger.valueOf(2 * i + 1)));
                resul = resul.add(c);
                /* series started 1+x/12+... which yields an estimate of the sum’s error
                 */


                if (Math.abs(c.doubleValue()) < xUlpDbl / 120.) {
                    break;
                }


            }
            /* sqrt(2*z)*(1+...)
             */
            xpowi = sqrt(xhighpr.multiply(new BigDecimal(2)));
            resul = multiplyRound(xpowi, resul);
            MathContext mc = new MathContext(resul.precision());
            BigDecimal pihalf = pi(mc).divide(new BigDecimal(2));
            mc = new MathContext(err2prec(resul.doubleValue(), eps));


            return pihalf.subtract(resul, mc);


        } else {
            /* absolute error in the result is err(x)/sqrt(1-x^2) to lowest order
             */
            final double xDbl = x.doubleValue();
            final double xUlpDbl = x.ulp().doubleValue() / 2.;
            final double eps = xUlpDbl / 2. / Math.sqrt(1. - Math.pow(xDbl, 2.));
            final BigDecimal xhighpr = scalePrec(x, 2);
            final BigDecimal xhighprSq = multiplyRound(xhighpr, xhighpr);
            BigDecimal resul = xhighpr.plus();
            /* x^(2i+1) */
            BigDecimal xpowi = xhighpr;
            /* i factorial */
            BigInteger ifacN = BigInteger.ONE;
            BigInteger ifacD = BigInteger.ONE;


            for (int i = 1;; i++) {
                ifacN = ifacN.multiply(BigInteger.valueOf(2 * i - 1));
                ifacD = ifacD.multiply(BigInteger.valueOf(2 * i));
                xpowi = multiplyRound(xpowi, xhighprSq);
                BigDecimal c = divideRound(multiplyRound(xpowi, ifacN), ifacD.multiply(BigInteger.valueOf(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);


        }
    }
static public BigDecimal asin(final BigDecimal x) {
        if (x.compareTo(BigDecimal.ONE) > 0 || x.compareTo(BigDecimal.ONE.negate()) < 0) {
            throw new ArithmeticException("Out of range argument " + x.toString() + " of asin");


        } else if (x.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        } else if (x.compareTo(BigDecimal.ONE) == 0) {
            /* arcsin(1) = pi/2
             */
            double errpi = Math.sqrt(x.ulp().doubleValue());
            MathContext mc = new MathContext(err2prec(3.14159, errpi));


            return pi(mc).divide(new BigDecimal(2));


        } else if (x.compareTo(BigDecimal.ZERO) < 0) {
            return asin(x.negate()).negate();


        } else if (x.doubleValue() > 0.7) {
            final BigDecimal xCompl = BigDecimal.ONE.subtract(x);
            final double xDbl = x.doubleValue();
            final double xUlpDbl = x.ulp().doubleValue() / 2.;
            final double eps = xUlpDbl / 2. / Math.sqrt(1. - Math.pow(xDbl, 2.));


            final BigDecimal xhighpr = scalePrec(xCompl, 3);
            final BigDecimal xhighprV = divideRound(xhighpr, 4);
            BigDecimal resul = BigDecimal.ONE;
            /* x^(2i+1) */
            BigDecimal xpowi = BigDecimal.ONE;
            /* i factorial */
            BigInteger ifacN = BigInteger.ONE;
            BigInteger ifacD = BigInteger.ONE;


            for (int i = 1;; i++) {
                ifacN = ifacN.multiply(BigInteger.valueOf(2 * i - 1));
                ifacD = ifacD.multiply(BigInteger.valueOf(i));


                if (i == 1) {
                    xpowi = xhighprV;
                } else {
                    xpowi = multiplyRound(xpowi, xhighprV);
                }
                BigDecimal c = divideRound(multiplyRound(xpowi, ifacN), ifacD.multiply(BigInteger.valueOf(2 * i + 1)));
                resul = resul.add(c);
                /* series started 1+x/12+... which yields an estimate of the sum’s error
                 */


                if (Math.abs(c.doubleValue()) < xUlpDbl / 120.) {
                    break;
                }


            }
            /* sqrt(2*z)*(1+...)
             */
            xpowi = sqrt(xhighpr.multiply(new BigDecimal(2)));
            resul = multiplyRound(xpowi, resul);
            MathContext mc = new MathContext(resul.precision());
            BigDecimal pihalf = pi(mc).divide(new BigDecimal(2));
            mc = new MathContext(err2prec(resul.doubleValue(), eps));


            return pihalf.subtract(resul, mc);


        } else {
            /* absolute error in the result is err(x)/sqrt(1-x^2) to lowest order
             */
            final double xDbl = x.doubleValue();
            final double xUlpDbl = x.ulp().doubleValue() / 2.;
            final double eps = xUlpDbl / 2. / Math.sqrt(1. - Math.pow(xDbl, 2.));
            final BigDecimal xhighpr = scalePrec(x, 2);
            final BigDecimal xhighprSq = multiplyRound(xhighpr, xhighpr);
            BigDecimal resul = xhighpr.plus();
            /* x^(2i+1) */
            BigDecimal xpowi = xhighpr;
            /* i factorial */
            BigInteger ifacN = BigInteger.ONE;
            BigInteger ifacD = BigInteger.ONE;


            for (int i = 1;; i++) {
                ifacN = ifacN.multiply(BigInteger.valueOf(2 * i - 1));
                ifacD = ifacD.multiply(BigInteger.valueOf(2 * i));
                xpowi = multiplyRound(xpowi, xhighprSq);
                BigDecimal c = divideRound(multiplyRound(xpowi, ifacN), ifacD.multiply(BigInteger.valueOf(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);


        }
    }
The inverse trigonometric sine.

@param x the argument.
@return the arcsin(x) in radians.