/* test_umul.c -- the reference unsigned multiply. * * v4_umul is what the capsule-level UM* is checked against, so it is checked * here against things that do not depend on it: algebraic identities that hold * at any width, and at 32-bit cells the host's own 64-bit product. */ #include "v4/umul.h" #include static int failures = 0, checks = 0; #define CHECK(c,...) do{checks++; if(!(c)){failures++; printf("FAIL %s:%d: ",__FILE__,__LINE__); printf(__VA_ARGS__); printf("\n");}}while(0) #define MAXU ((v4_ucell)~(v4_ucell)0) static const v4_ucell vec[] = { 0u, 1u, 2u, 3u, 7u, 255u, 256u, 65535u, 65536u, 0x12345678u, (v4_ucell)0x9E3779B97F4A7C15ULL, (v4_ucell)0xDEADBEEFCAFEF00DULL, V4_MSB - 1u, V4_MSB, V4_MSB + 1u, MAXU - 1u, MAXU }; #define NVEC (sizeof vec / sizeof vec[0]) int main(void) { v4_ucell lo, hi, lo2, hi2; printf("v4 umul tests: V4_CELL_BITS=%d\n", V4_CELL_BITS); v4_umul(3, 7, &lo, &hi); CHECK(lo == 21 && hi == 0, "3*7"); /* (2^n - 1)^2 = 2^2n - 2^(n+1) + 1 */ v4_umul(MAXU, MAXU, &lo, &hi); CHECK(lo == 1 && hi == MAXU - 1u, "max*max"); /* 2^(n-1) * 2^(n-1) = 2^(2n-2) */ v4_umul(V4_MSB, V4_MSB, &lo, &hi); CHECK(lo == 0 && hi == (V4_MSB >> 1), "msb*msb"); for (unsigned i = 0; i < NVEC; i++) { v4_ucell x = vec[i]; v4_umul(x, 0, &lo, &hi); CHECK(lo == 0 && hi == 0, "x*0 [%u]", i); v4_umul(x, 1, &lo, &hi); CHECK(lo == x && hi == 0, "x*1 [%u]", i); /* x * (2^n - 1) = x*2^n - x */ v4_umul(x, MAXU, &lo, &hi); CHECK(lo == (v4_ucell)(0u - x) && hi == (x ? x - 1u : 0u), "x*max [%u]", i); for (unsigned k = 0; k < V4_CELL_BITS; k++) { /* x * 2^k is x shifted across the double cell */ v4_umul(x, ((v4_ucell)1) << k, &lo, &hi); CHECK(lo == (v4_ucell)(x << k), "x<<%u lo [%u]", k, i); CHECK(hi == (k ? x >> (V4_CELL_BITS - k) : 0u), "x<<%u hi [%u]", k, i); } for (unsigned j = 0; j < NVEC; j++) { v4_ucell y = vec[j]; v4_umul(x, y, &lo, &hi); v4_umul(y, x, &lo2, &hi2); CHECK(lo == lo2 && hi == hi2, "commutes [%u,%u]", i, j); CHECK(lo == (v4_ucell)(x * y), "low cell [%u,%u]", i, j); #if V4_CELL_BITS == 32 { uint64_t p = (uint64_t)x * (uint64_t)y; CHECK(lo == (uint32_t)p && hi == (uint32_t)(p >> 32), "host product [%u,%u]", i, j); } #endif } } printf(" %d checks, %d failures\n", checks, failures); return failures ? 1 : 0; }