* @param x
     * @param decimalPlaces
     * @param a_RoundingMode
     * @return The log of x to the base base to decimalPlace precision
     */
    public static BigDecimal log(
            BigDecimal base,
            BigDecimal x,
            int decimalPlaces,
            RoundingMode a_RoundingMode) {
        BigDecimal result;// = BigDecimal.ZERO;
        // Deal with special cases
        if (x.compareTo(BigDecimal.ZERO) != 1) {
            throw new IllegalArgumentException("x <= 0");
        }
        if (x.compareTo(BigDecimal.ONE) == 0) {
            return BigDecimal.ZERO;
        }
        if (base.compareTo(x) == 0) {
            return BigDecimal.ONE;
        }
        if (x.compareTo(BigDecimal.ONE) == -1) {
            int xprecision = x.precision();
            BigInteger unscaledx = x.unscaledValue();
            int unscaledxprecision = unscaledx.toString().length();
            int index = xprecision - unscaledxprecision;
            BigDecimal unscaledxmajor = new BigDecimal(unscaledx, index);
            //System.out.print(unscaledxmajor);
            BigDecimal logunscaledxmajor = log(
                    base,
                    unscaledxmajor,
                    decimalPlaces + index,
                    a_RoundingMode);
            result = logunscaledxmajor.subtract(BigDecimal.valueOf(index));
            return roundIfNecessary(result, decimalPlaces, a_RoundingMode);
        }
        result = BigDecimal.ZERO;
        BigDecimal input = new BigDecimal(x.toString());
        int scale = input.precision() + decimalPlaces;
        BigInteger maxite = Generic_BigInteger.max(
                x.toBigInteger(),
                BigInteger.valueOf(10000));
        BigInteger ite = BigInteger.ZERO;
        BigDecimal maxError_BigDecimal = new BigDecimal(
                BigInteger.ONE,
                decimalPlaces + 1);
        //System.out.println("epsilon_BigDecimal " + epsilon_BigDecimal);
        //System.out.println("scale " + scale);
        while (input.compareTo(base) == 1) {
            result = result.add(BigDecimal.ONE);
            input = input.divide(base, scale, a_RoundingMode);
        }
        BigDecimal fraction = new BigDecimal("0.5");
        input = input.multiply(input);
        BigDecimal resultplusfraction = result.add(fraction);
        int decimalPlacesSafer = Math.max(decimalPlaces * 2, decimalPlaces + 10); // Safe in terms of precision? Maybe log(base_int,maxite,0) would be more appropriate?
        while (((resultplusfraction).compareTo(result) == 1)
                && (input.compareTo(BigDecimal.ONE) == 1)) {
            if (input.compareTo(base) == 1) {
                input = input.divide(base, scale, a_RoundingMode);
                result = result.add(fraction);
            }
            input = multiplyRoundIfNecessary(
                    input,
                    input,
                    decimalPlacesSafer,
                    a_RoundingMode);
            fraction = fraction.divide(TWO, scale, a_RoundingMode);
            resultplusfraction = result.add(fraction);
            if (fraction.abs().compareTo(maxError_BigDecimal) == -1) {
                break;
            }
            if (maxite.compareTo(ite) == 0) {
                System.out.println(
                        "Warning: maxite reached in "
                        + Generic_BigDecimal.class.getName()
                        + ".log(BigDecimal,BigDecimal,int,RoundingMode) "
                        + " log("
                        + base + ", "
                        + x + ", "
                        + decimalPlaces + ", "
                        + a_RoundingMode.toString() + ") "
                        + result.toString());
                break;
            }
            ite = ite.add(BigInteger.ONE);
        }
        return roundIfNecessary(result, decimalPlaces, a_RoundingMode);
    }