- 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);
+ a = MP_COPY(a);
+ b = MP_COPY(b);
+
+ if (MP_LEN(a) <= KARATSUBA_CUTOFF || MP_LEN(b) <= KARATSUBA_CUTOFF) {
+ MP_DEST(d, MP_LEN(a) + MP_LEN(b), a->f | b->f | MP_UNDEF);
+ mpx_umul(d->v, d->vl, a->v, a->vl, b->v, b->vl);
+ } else {
+ size_t m = 2 * MAX(MP_LEN(a), MP_LEN(b)) + 2;
+ mpw *s;
+ MP_DEST(d, m, a->f | b->f | MP_UNDEF);
+ m += KARATSUBA_SLOP;
+ s = mpalloc(d->a, m);
+ mpx_kmul(d->v, d->vl, a->v, a->vl, b->v, b->vl, s, s + m);
+ mpfree(d->a, s);
+ }
+