public static double ln(double a) {

		double aminus1 = a - 1.0;
		boolean gt1 = (sqrt(aminus1 * aminus1) <= 1) ? false : true;

		final int iteration_count = 300;

		double lnsum = 0.0;

		if (gt1) {
			// use trick for fast convergence:
			// ln(123.456) = ln(1.23456*10^2)
			// ln(123.456) = ln(1.23456) + 2*ln(10)
			int j = 0;
			while (a / 10 > 1) {
				a /= 10;
				j++;
			}
			aminus1 = a - 1.0;

			double denominator = 1.0;
			for (int i = 1; i < iteration_count; i++) {
				denominator *= a / aminus1;
				lnsum += (1.0 / (denominator * ((double) i)));
			}
			if (j > 0) {
				lnsum += j * ln(10);
			}
		} else {

			int j = 0;
			while (a * 10 < 1) {
				a *= 10;
				j++;
			}
			aminus1 = a - 1.0;

			double numerator = 1.0;
			for (int i = 1; i < iteration_count; i++) {
				double sign = (i % 2 == 0) ? -1.0 : 1.0;
				numerator *= aminus1;
				lnsum += sign * (numerator / ((double) i));
			}

			if (j > 0) {
				lnsum += -1.0 * j * ln(10);
			}
		}

		return lnsum;
	}