- /* --- Perform the precomputation --- */
-
- {
- size_t i, j;
- size_t mask;
-
- /* --- Fill in the rest of the array --- *
- *
- * Zero never gets used.
- */
-
- j = 0;
- mask = 0;
- for (i = 1; i < vn; i++) {
-
- /* --- Check for a new bit entering --- *
- *
- * If a bit gets set that wasn't set before, then all the lower bits
- * are zeroes and I've got to introduce a new base into the array.
- */
-
- if ((i & mask) == 0) {
- v[i] = mpmont_mul(mm, MP_NEW, f[j++].base, mm->r2);
- mask = i;
- }
-
- /* --- Otherwise I can get away with a single multiplication --- *
- *
- * In particular, if %$i$% has more than one bit set, then I only need
- * to calculate %$v_i = v_{\mathit{mask}} v_{i - \mathit{mask}}$%.
- * Since both are less than %$i$%, they must have already been
- * computed.
- */
-
- else
- v[i] = mpmont_mul(mm, MP_NEW, v[mask], v[i & ~mask]);
- }
- }
-
- /* --- Set up the bitscanners --- *
- *
- * I must scan the exponents from left to right, which is a shame. It
- * means that I can't use the standard @mpscan@ stuff, in particular.
- */
-
- {
- size_t i;
-
- s = xmalloc(n * sizeof(scan));
- o = 0;
- for (i = 0; i < n; i++) {
- s[i].len = MP_LEN(f[i].exp);
- if (s[i].len > o)
- o = s[i].len;
- }
- b = 0;
- }
-
- /* --- Now do the actual calculation --- */
-
- b = 0;
- for (;;) {
- size_t i;
- size_t j;
- mp *dd;
-
- /* --- If no more bits, get some more --- */
-
- if (!b) {
- if (!o)
- break;
- o--;
- b = MPW_BITS;
- }
-
- /* --- Work out the next index --- */
-
- j = 0;
- b--;
- for (i = 0; i < n; i++) {
- if (o < s[i].len)
- j |= (((f[i].exp->v[o] >> b) & 1) << i);
- }
-
- /* --- Accumulate the result --- */
-
- if (spare) {
- dd = mp_sqr(spare, a);
- dd = mpmont_reduce(mm, dd, dd);
- spare = a;
- a = dd;
- }
-
- if (j) {
- dd = mpmont_mul(mm, spare, a, v[j]);
- spare = a;
- a = dd;
+ for (i = 0; i < n; i++) {
+ mp *t;
+ if (f[i].exp->f & MP_BURN)
+ spare = MP_NEWSEC;
+ if (MP_NEGP(f[i].exp)) {
+ t = mpmont_reduce(mm, f[i].base, f[i].base);
+ t = mp_modinv(t, t, mm->m);
+ f[i].base = mpmont_mul(mm, t, t, mm->r2);