#ifndef _MULTIPLY_H #define _MULTIPLY_H #include "common.h" /** * Double-precision multiplication */ #if defined(HAVE_UINT128) #define DP_MULT(a,b,ol,oh) do { \ __uint128_t pr; \ pr = (__uint128_t)(a)*(b); \ ol = (uint64_t)pr; \ oh = (uint64_t)(pr >> 64); \ } while (0) #elif defined(_MSC_VER) && defined(_WIN64) #include #define DP_MULT(a,b,ol,oh) do { ol = UnsignedMultiply128(a,b,&oh); } while (0) #else uint64_t static inline dp_mult_128_32(uint64_t a, uint64_t b, uint64_t *oh); uint64_t static inline dp_mult_128_32(uint64_t a, uint64_t b, uint64_t *oh) { uint32_t al = (uint32_t) a; uint32_t ah = (uint32_t)(a >> 32); uint32_t bl = (uint32_t) b; uint32_t bh = (uint32_t)(b >> 32); uint64_t sum0, sum1a, sum1b, sum2, sum3; sum0 = (uint64_t)al*bl; sum1a = (uint64_t)al*bh; sum1b = (uint64_t)ah*bl; sum2 = (uint64_t)ah*bh; sum1a += sum0 >> 32; sum1b += sum1a; sum3 = sum1b < sum1a; sum2 += sum1b >> 32; sum3 += sum2 >> 32; *oh = (sum3 << 32) + (uint32_t)sum2; return (sum1b << 32) + (uint32_t)sum0; } #define DP_MULT(a,b,ol,oh) do { ol = dp_mult_128_32(a,b,&oh); } while (0) #endif /* * Square an integer a[]. * * @param t Location where the result is stored, 2*nw words. * @param scratchpad Temporary space, 3*nw words. * @param a Integer to square, nw words. * @param nw Size of the integer a[], in 64-bit words. */ void square(uint64_t *t, uint64_t *scratchpad, const uint64_t *a, size_t nw); /* * Multiply an integer a[] by a 128-bit scalar, and add the result to integer t[]. * * @param t Integer where the result of the multiplication is added * to, t_nw words. * @param scratchpad Temporary space, with t_nw+a_nw words. * @param a Integer to multiply by the scalar, a_nw words. * @param b0 Lower 64 bits of the scalar * @param b1 Higher 64 bits of the scalar * @param t_nw Size of integer t[], in 64-bit words. It must be at least a_nw+2. * @param a_nw Size of integer a[], in 64-bit words. */ void addmul128(uint64_t *t, uint64_t *scratchpad, const uint64_t * a, uint64_t b0, uint64_t b1, size_t t_nw, size_t a_nw); #endif