## JavaScript Hardy-Ramanujan-Rademacher

This depends on [a BigNumber implementation](https://github.com/MikeMcl/bignumber.js/blob/v1.0.1/bignumber.js), but doesn't demand much of it.


	var partition = function(n) {
		// Hardy-Ramanujan estimate to set the precision with appropriate margin
		BigNumber.config((5 + 1.115 * Math.sqrt(n) + Math.log(n) / Math.log(100))|0, /* ROUND_EVEN */6);

		// Hardy-Ramanujan-Rademacher
		var zero = new BigNumber(0),
			// \sum_{i=0}^\infty 2^{i+1} i!^2 / {2i+1}!
			PI = function(){ var t = new BigNumber(2), s=t, i=1; while (!t.isZero()) s = s.plus(t = t.times(i).div((i+ ++i))); return s }(),
			A = new BigNumber(n).minus(new BigNumber(1).div(24)),
			B = A.times(2).div(3).sqrt().times(PI),
			ABsqrt12 = A.times(B).times(new BigNumber(12).sqrt()),
			sum = function(min, max, fn) { return min > max ? zero : fn(min).plus(sum(min + 1, max, fn)) },
			gcd = function(x, y) { return y ? gcd(y, x % y) : x },
			genexp = function(x, a, b, c, d) {
				// \sum_{i=0}^\infty ax^{4i}/(4i)! + bx^{4i+1}/(4i+1)! + cx^{4i+2}/(4i+2)! + dx^{4i+3}/(4i+3)!
				var res = new BigNumber(0), z = new BigNumber(1), i;
				for (i=0; !z.isZero(); i+=4) {
					res = res.plus(z.times(a)); z = z.times(x).div(i+1);
					res = res.plus(z.times(b)); z = z.times(x).div(i+2);
					res = res.plus(z.times(c)); z = z.times(x).div(i+3);
					res = res.plus(z.times(d)); z = z.times(x).div(i+4);
				}
				return res;
			},
			Psi_ = function(q) { var C = B.div(q); return genexp(C,C,-1,C,-1).times(new BigNumber(q).sqrt()) },
			// NB The .mod(4*q*q) is critical for performance
			s_ = function(h, q) { return sum(0, q-1, function(k) { return new BigNumber((2*(h*k %q) - q) * k - 4*h*n) }).mod(4*q*q) },
			L = function(q) { return sum(0, q-1, function(h) { return gcd(h,q)>1 ? zero : genexp(s_(h,q).div(2*q*q).times(PI),1,0,-1,0) }) };
		return sum(1, Math.max(5, Math.sqrt(n)/4+2), function(q) {
			// Adaptive precision calculation for performance
			if (q > 1) BigNumber.config((5 + 1.115 * Math.sqrt(n) / q + Math.log(n) / Math.log(100))|0);
			return L(q).times(Psi_(q))
		}).div(ABsqrt12).round();
	};

It computes `partition(10000)` in about 0.71 seconds using Node on a 3.5GHz PC.