/* umul.c -- reference unsigned multiply. See umul.h. * * Schoolbook multiplication on half-cells, in v4_ucell only. No wider type is * used, so the same code is correct at both cell widths and builds on a host * with no 128-bit integer (ARMv7 is one, and is a v4 host). */ #include "v4/umul.h" #define HALF_BITS (V4_CELL_BITS / 2) #define HALF_MASK ((((v4_ucell)1) << HALF_BITS) - 1u) void v4_umul(v4_ucell u1, v4_ucell u2, v4_ucell *ulo, v4_ucell *uhi) { v4_ucell a0 = u1 & HALF_MASK, a1 = u1 >> HALF_BITS; v4_ucell b0 = u2 & HALF_MASK, b1 = u2 >> HALF_BITS; v4_ucell p00 = a0 * b0; v4_ucell p10 = a1 * b0; v4_ucell p01 = a0 * b1; v4_ucell p11 = a1 * b1; /* Cannot overflow: at most (2^h - 1) + (2^h - 1) + (2^h - 1)^2 = 2^2h - 1. */ v4_ucell mid = (p00 >> HALF_BITS) + (p10 & HALF_MASK) + p01; if (ulo) *ulo = (mid << HALF_BITS) | (p00 & HALF_MASK); if (uhi) *uhi = p11 + (p10 >> HALF_BITS) + (mid >> HALF_BITS); }