bn_mp_mul.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. #include "tommath_private.h"
  2. #ifdef BN_MP_MUL_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis */
  4. /* SPDX-License-Identifier: Unlicense */
  5. /* high level multiplication (handles sign) */
  6. mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
  7. {
  8. mp_err err;
  9. int min_len = MP_MIN(a->used, b->used),
  10. max_len = MP_MAX(a->used, b->used),
  11. digs = a->used + b->used + 1;
  12. mp_sign neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
  13. if (MP_HAS(S_MP_BALANCE_MUL) &&
  14. /* Check sizes. The smaller one needs to be larger than the Karatsuba cut-off.
  15. * The bigger one needs to be at least about one MP_KARATSUBA_MUL_CUTOFF bigger
  16. * to make some sense, but it depends on architecture, OS, position of the
  17. * stars... so YMMV.
  18. * Using it to cut the input into slices small enough for fast_s_mp_mul_digs
  19. * was actually slower on the author's machine, but YMMV.
  20. */
  21. (min_len >= MP_KARATSUBA_MUL_CUTOFF) &&
  22. ((max_len / 2) >= MP_KARATSUBA_MUL_CUTOFF) &&
  23. /* Not much effect was observed below a ratio of 1:2, but again: YMMV. */
  24. (max_len >= (2 * min_len))) {
  25. err = s_mp_balance_mul(a,b,c);
  26. } else if (MP_HAS(S_MP_TOOM_MUL) &&
  27. (min_len >= MP_TOOM_MUL_CUTOFF)) {
  28. err = s_mp_toom_mul(a, b, c);
  29. } else if (MP_HAS(S_MP_KARATSUBA_MUL) &&
  30. (min_len >= MP_KARATSUBA_MUL_CUTOFF)) {
  31. err = s_mp_karatsuba_mul(a, b, c);
  32. } else if (MP_HAS(S_MP_MUL_DIGS_FAST) &&
  33. /* can we use the fast multiplier?
  34. *
  35. * The fast multiplier can be used if the output will
  36. * have less than MP_WARRAY digits and the number of
  37. * digits won't affect carry propagation
  38. */
  39. (digs < MP_WARRAY) &&
  40. (min_len <= MP_MAXFAST)) {
  41. err = s_mp_mul_digs_fast(a, b, c, digs);
  42. } else if (MP_HAS(S_MP_MUL_DIGS)) {
  43. err = s_mp_mul_digs(a, b, c, digs);
  44. } else {
  45. err = MP_VAL;
  46. }
  47. c->sign = (c->used > 0) ? neg : MP_ZPOS;
  48. return err;
  49. }
  50. #endif