- if (d == a || d == b)
- d = MP_NEW;
- MP_MODIFY(d, MP_LEN(a) + MP_LEN(b));
- mpx_umul(d->v, d->vl, a->v, a->vl, b->v, b->vl);
+ size_t m = MAX(MP_LEN(a), MP_LEN(b)) * 2 + KARATSUBA_SLOP;
+
+ a = MP_COPY(a);
+ b = MP_COPY(b);
+
+ if (MP_LEN(a) <= KARATSUBA_CUTOFF || MP_LEN(b) <= KARATSUBA_CUTOFF) {
+ MP_MODIFY(d, MP_LEN(a) + MP_LEN(b));
+ mpx_umul(d->v, d->vl, a->v, a->vl, b->v, b->vl);
+ } else {
+ mpw *s;
+ m += 32;
+ s = MP_ALLOC(m);
+ MP_MODIFY(d, 2 * m + 2);
+ mpx_kmul(d->v, d->vl, a->v, a->vl, b->v, b->vl, s, s + m);
+ MP_FREE(s);
+ }
+