multiply.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #ifndef _MULTIPLY_H
  2. #define _MULTIPLY_H
  3. #include "common.h"
  4. /**
  5. * Double-precision multiplication
  6. */
  7. #if defined(HAVE_UINT128)
  8. #define DP_MULT(a,b,ol,oh) do { \
  9. __uint128_t pr; \
  10. pr = (__uint128_t)(a)*(b); \
  11. ol = (uint64_t)pr; \
  12. oh = (uint64_t)(pr >> 64); \
  13. } while (0)
  14. #elif defined(_MSC_VER) && defined(_WIN64)
  15. #include <windows.h>
  16. #define DP_MULT(a,b,ol,oh) do { ol = UnsignedMultiply128(a,b,&oh); } while (0)
  17. #else
  18. uint64_t static inline dp_mult_128_32(uint64_t a, uint64_t b, uint64_t *oh);
  19. uint64_t static inline dp_mult_128_32(uint64_t a, uint64_t b, uint64_t *oh)
  20. {
  21. uint32_t al = (uint32_t) a;
  22. uint32_t ah = (uint32_t)(a >> 32);
  23. uint32_t bl = (uint32_t) b;
  24. uint32_t bh = (uint32_t)(b >> 32);
  25. uint64_t sum0, sum1a, sum1b, sum2, sum3;
  26. sum0 = (uint64_t)al*bl;
  27. sum1a = (uint64_t)al*bh;
  28. sum1b = (uint64_t)ah*bl;
  29. sum2 = (uint64_t)ah*bh;
  30. sum1a += sum0 >> 32;
  31. sum1b += sum1a;
  32. sum3 = sum1b < sum1a;
  33. sum2 += sum1b >> 32;
  34. sum3 += sum2 >> 32;
  35. *oh = (sum3 << 32) + (uint32_t)sum2;
  36. return (sum1b << 32) + (uint32_t)sum0;
  37. }
  38. #define DP_MULT(a,b,ol,oh) do { ol = dp_mult_128_32(a,b,&oh); } while (0)
  39. #endif
  40. /*
  41. * Square an integer a[].
  42. *
  43. * @param t Location where the result is stored, 2*nw words.
  44. * @param scratchpad Temporary space, 3*nw words.
  45. * @param a Integer to square, nw words.
  46. * @param nw Size of the integer a[], in 64-bit words.
  47. */
  48. void square(uint64_t *t, uint64_t *scratchpad, const uint64_t *a, size_t nw);
  49. /*
  50. * Multiply an integer a[] by a 128-bit scalar, and add the result to integer t[].
  51. *
  52. * @param t Integer where the result of the multiplication is added
  53. * to, t_nw words.
  54. * @param scratchpad Temporary space, with t_nw+a_nw words.
  55. * @param a Integer to multiply by the scalar, a_nw words.
  56. * @param b0 Lower 64 bits of the scalar
  57. * @param b1 Higher 64 bits of the scalar
  58. * @param t_nw Size of integer t[], in 64-bit words. It must be at least a_nw+2.
  59. * @param a_nw Size of integer a[], in 64-bit words.
  60. */
  61. 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);
  62. #endif