docs: function fp_inv(r, n, p, l) {
  	if (mpn_zero_p(n, l)) {
  		throw new RangeError("not invertible");
  	}
  	var u = _fp_u, v = _fp_v, s = _fp_s;
  	mpn_copyi(u, n, l), mpn_copyi(v, p, l);
  	mpn_zero(r, l), mpn_zero(s, l);
  	r[0] = 1;
  	for (;;) {
  		if (mpn_one_p(u, l)) {
  			return r;
  		}
  		if (mpn_one_p(v, l)) {
  			mpn_copyi(r, s, l);
  			return r;
  		}
  		while (mpn_even_p(u, l)) {
  			mpn_shr1(u, u, l);
  			if (mpn_even_p(r, l)) {
  				mpn_shr1(r, r, l);
  			}
  			else {
  				var c = mpn_add(r, r, p, l) << 30;
  				mpn_shr1(r, r, l);
  				r[l - 1] |= c;
  			}
  		}
  		while (mpn_even_p(v, l)) {
  			mpn_shr1(v, v, l);
  			if (mpn_even_p(s, l)) {
  				mpn_shr1(s, s, l);
  			}
  			else {
  				var c = mpn_add(s, s, p, l) << 30;
  				mpn_shr1(s, s, l);
  				s[l - 1] |= c;
  			}
  		}
  		if (mpn_cmp(u, v, l) >= 0) {
  			mpn_sub(u, u, v, l);
  			fp_sub(r, r, s, p, l);
  		}
  		else {
  			mpn_sub(v, v, u, l);
  			fp_sub(s, s, r, p, l);
  		}
  	}
  }