bn_s_mp_toom_sqr.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #include "tommath_private.h"
  2. #ifdef BN_S_MP_TOOM_SQR_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis */
  4. /* SPDX-License-Identifier: Unlicense */
  5. /* squaring using Toom-Cook 3-way algorithm */
  6. /*
  7. This file contains code from J. Arndt's book "Matters Computational"
  8. and the accompanying FXT-library with permission of the author.
  9. */
  10. /* squaring using Toom-Cook 3-way algorithm */
  11. /*
  12. Setup and interpolation from algorithm SQR_3 in
  13. Chung, Jaewook, and M. Anwar Hasan. "Asymmetric squaring formulae."
  14. 18th IEEE Symposium on Computer Arithmetic (ARITH'07). IEEE, 2007.
  15. */
  16. mp_err s_mp_toom_sqr(const mp_int *a, mp_int *b)
  17. {
  18. mp_int S0, a0, a1, a2;
  19. mp_digit *tmpa, *tmpc;
  20. int B, count;
  21. mp_err err;
  22. /* init temps */
  23. if ((err = mp_init(&S0)) != MP_OKAY) {
  24. return err;
  25. }
  26. /* B */
  27. B = a->used / 3;
  28. /** a = a2 * x^2 + a1 * x + a0; */
  29. if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0;
  30. a0.used = B;
  31. if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1;
  32. a1.used = B;
  33. if ((err = mp_init_size(&a2, B + (a->used - (3 * B)))) != MP_OKAY) goto LBL_ERRa2;
  34. tmpa = a->dp;
  35. tmpc = a0.dp;
  36. for (count = 0; count < B; count++) {
  37. *tmpc++ = *tmpa++;
  38. }
  39. tmpc = a1.dp;
  40. for (; count < (2 * B); count++) {
  41. *tmpc++ = *tmpa++;
  42. }
  43. tmpc = a2.dp;
  44. for (; count < a->used; count++) {
  45. *tmpc++ = *tmpa++;
  46. a2.used++;
  47. }
  48. mp_clamp(&a0);
  49. mp_clamp(&a1);
  50. mp_clamp(&a2);
  51. /** S0 = a0^2; */
  52. if ((err = mp_sqr(&a0, &S0)) != MP_OKAY) goto LBL_ERR;
  53. /** \\S1 = (a2 + a1 + a0)^2 */
  54. /** \\S2 = (a2 - a1 + a0)^2 */
  55. /** \\S1 = a0 + a2; */
  56. /** a0 = a0 + a2; */
  57. if ((err = mp_add(&a0, &a2, &a0)) != MP_OKAY) goto LBL_ERR;
  58. /** \\S2 = S1 - a1; */
  59. /** b = a0 - a1; */
  60. if ((err = mp_sub(&a0, &a1, b)) != MP_OKAY) goto LBL_ERR;
  61. /** \\S1 = S1 + a1; */
  62. /** a0 = a0 + a1; */
  63. if ((err = mp_add(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR;
  64. /** \\S1 = S1^2; */
  65. /** a0 = a0^2; */
  66. if ((err = mp_sqr(&a0, &a0)) != MP_OKAY) goto LBL_ERR;
  67. /** \\S2 = S2^2; */
  68. /** b = b^2; */
  69. if ((err = mp_sqr(b, b)) != MP_OKAY) goto LBL_ERR;
  70. /** \\ S3 = 2 * a1 * a2 */
  71. /** \\S3 = a1 * a2; */
  72. /** a1 = a1 * a2; */
  73. if ((err = mp_mul(&a1, &a2, &a1)) != MP_OKAY) goto LBL_ERR;
  74. /** \\S3 = S3 << 1; */
  75. /** a1 = a1 << 1; */
  76. if ((err = mp_mul_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR;
  77. /** \\S4 = a2^2; */
  78. /** a2 = a2^2; */
  79. if ((err = mp_sqr(&a2, &a2)) != MP_OKAY) goto LBL_ERR;
  80. /** \\ tmp = (S1 + S2)/2 */
  81. /** \\tmp = S1 + S2; */
  82. /** b = a0 + b; */
  83. if ((err = mp_add(&a0, b, b)) != MP_OKAY) goto LBL_ERR;
  84. /** \\tmp = tmp >> 1; */
  85. /** b = b >> 1; */
  86. if ((err = mp_div_2(b, b)) != MP_OKAY) goto LBL_ERR;
  87. /** \\ S1 = S1 - tmp - S3 */
  88. /** \\S1 = S1 - tmp; */
  89. /** a0 = a0 - b; */
  90. if ((err = mp_sub(&a0, b, &a0)) != MP_OKAY) goto LBL_ERR;
  91. /** \\S1 = S1 - S3; */
  92. /** a0 = a0 - a1; */
  93. if ((err = mp_sub(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR;
  94. /** \\S2 = tmp - S4 -S0 */
  95. /** \\S2 = tmp - S4; */
  96. /** b = b - a2; */
  97. if ((err = mp_sub(b, &a2, b)) != MP_OKAY) goto LBL_ERR;
  98. /** \\S2 = S2 - S0; */
  99. /** b = b - S0; */
  100. if ((err = mp_sub(b, &S0, b)) != MP_OKAY) goto LBL_ERR;
  101. /** \\P = S4*x^4 + S3*x^3 + S2*x^2 + S1*x + S0; */
  102. /** P = a2*x^4 + a1*x^3 + b*x^2 + a0*x + S0; */
  103. if ((err = mp_lshd(&a2, 4 * B)) != MP_OKAY) goto LBL_ERR;
  104. if ((err = mp_lshd(&a1, 3 * B)) != MP_OKAY) goto LBL_ERR;
  105. if ((err = mp_lshd(b, 2 * B)) != MP_OKAY) goto LBL_ERR;
  106. if ((err = mp_lshd(&a0, 1 * B)) != MP_OKAY) goto LBL_ERR;
  107. if ((err = mp_add(&a2, &a1, &a2)) != MP_OKAY) goto LBL_ERR;
  108. if ((err = mp_add(&a2, b, b)) != MP_OKAY) goto LBL_ERR;
  109. if ((err = mp_add(b, &a0, b)) != MP_OKAY) goto LBL_ERR;
  110. if ((err = mp_add(b, &S0, b)) != MP_OKAY) goto LBL_ERR;
  111. /** a^2 - P */
  112. LBL_ERR:
  113. mp_clear(&a2);
  114. LBL_ERRa2:
  115. mp_clear(&a1);
  116. LBL_ERRa1:
  117. mp_clear(&a0);
  118. LBL_ERRa0:
  119. mp_clear(&S0);
  120. return err;
  121. }
  122. #endif