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) {
            
            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;
            
            BigDecimal xpowi = BigDecimal.ONE;
            
            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);
                


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


            }
            
            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 {
            
            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();
            
            BigDecimal xpowi = xhighpr;
            
            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.
The inverse trigonometric sine .