bn_s_mp_karatsuba_sqr.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #include "tommath_private.h"
  2. #ifdef BN_S_MP_KARATSUBA_SQR_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis */
  4. /* SPDX-License-Identifier: Unlicense */
  5. /* Karatsuba squaring, computes b = a*a using three
  6. * half size squarings
  7. *
  8. * See comments of karatsuba_mul for details. It
  9. * is essentially the same algorithm but merely
  10. * tuned to perform recursive squarings.
  11. */
  12. mp_err s_mp_karatsuba_sqr(const mp_int *a, mp_int *b)
  13. {
  14. mp_int x0, x1, t1, t2, x0x0, x1x1;
  15. int B;
  16. mp_err err = MP_MEM;
  17. /* min # of digits */
  18. B = a->used;
  19. /* now divide in two */
  20. B = B >> 1;
  21. /* init copy all the temps */
  22. if (mp_init_size(&x0, B) != MP_OKAY)
  23. goto LBL_ERR;
  24. if (mp_init_size(&x1, a->used - B) != MP_OKAY)
  25. goto X0;
  26. /* init temps */
  27. if (mp_init_size(&t1, a->used * 2) != MP_OKAY)
  28. goto X1;
  29. if (mp_init_size(&t2, a->used * 2) != MP_OKAY)
  30. goto T1;
  31. if (mp_init_size(&x0x0, B * 2) != MP_OKAY)
  32. goto T2;
  33. if (mp_init_size(&x1x1, (a->used - B) * 2) != MP_OKAY)
  34. goto X0X0;
  35. {
  36. int x;
  37. mp_digit *dst, *src;
  38. src = a->dp;
  39. /* now shift the digits */
  40. dst = x0.dp;
  41. for (x = 0; x < B; x++) {
  42. *dst++ = *src++;
  43. }
  44. dst = x1.dp;
  45. for (x = B; x < a->used; x++) {
  46. *dst++ = *src++;
  47. }
  48. }
  49. x0.used = B;
  50. x1.used = a->used - B;
  51. mp_clamp(&x0);
  52. /* now calc the products x0*x0 and x1*x1 */
  53. if (mp_sqr(&x0, &x0x0) != MP_OKAY)
  54. goto X1X1; /* x0x0 = x0*x0 */
  55. if (mp_sqr(&x1, &x1x1) != MP_OKAY)
  56. goto X1X1; /* x1x1 = x1*x1 */
  57. /* now calc (x1+x0)**2 */
  58. if (s_mp_add(&x1, &x0, &t1) != MP_OKAY)
  59. goto X1X1; /* t1 = x1 - x0 */
  60. if (mp_sqr(&t1, &t1) != MP_OKAY)
  61. goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */
  62. /* add x0y0 */
  63. if (s_mp_add(&x0x0, &x1x1, &t2) != MP_OKAY)
  64. goto X1X1; /* t2 = x0x0 + x1x1 */
  65. if (s_mp_sub(&t1, &t2, &t1) != MP_OKAY)
  66. goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */
  67. /* shift by B */
  68. if (mp_lshd(&t1, B) != MP_OKAY)
  69. goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
  70. if (mp_lshd(&x1x1, B * 2) != MP_OKAY)
  71. goto X1X1; /* x1x1 = x1x1 << 2*B */
  72. if (mp_add(&x0x0, &t1, &t1) != MP_OKAY)
  73. goto X1X1; /* t1 = x0x0 + t1 */
  74. if (mp_add(&t1, &x1x1, b) != MP_OKAY)
  75. goto X1X1; /* t1 = x0x0 + t1 + x1x1 */
  76. err = MP_OKAY;
  77. X1X1:
  78. mp_clear(&x1x1);
  79. X0X0:
  80. mp_clear(&x0x0);
  81. T2:
  82. mp_clear(&t2);
  83. T1:
  84. mp_clear(&t1);
  85. X1:
  86. mp_clear(&x1);
  87. X0:
  88. mp_clear(&x0);
  89. LBL_ERR:
  90. return err;
  91. }
  92. #endif