nd4j-common/src/main/java/org/nd4j/linalg/util/BigDecimalMath.java
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);
        }
    }
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);
        }
    }
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 ) ; } }
The natural logarithm.

@param x the argument.
@return ln(x).
The precision of the result is implicitly defined by the precision in the argument.
The natural logarithm .