bn_mp_toom_sqr.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #include <tommath.h>
  2. #ifdef BN_MP_TOOM_SQR_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4. *
  5. * LibTomMath is a library that provides multiple-precision
  6. * integer arithmetic as well as number theoretic functionality.
  7. *
  8. * The library was designed directly after the MPI library by
  9. * Michael Fromberger but has been written from scratch with
  10. * additional optimizations in place.
  11. *
  12. * The library is free for all purposes without any express
  13. * guarantee it works.
  14. *
  15. * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
  16. */
  17. /* squaring using Toom-Cook 3-way algorithm */
  18. int
  19. mp_toom_sqr(mp_int *a, mp_int *b)
  20. {
  21. mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
  22. int res, B;
  23. /* init temps */
  24. if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
  25. return res;
  26. }
  27. /* B */
  28. B = a->used / 3;
  29. /* a = a2 * B**2 + a1 * B + a0 */
  30. if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
  31. goto ERR;
  32. }
  33. if ((res = mp_copy(a, &a1)) != MP_OKAY) {
  34. goto ERR;
  35. }
  36. mp_rshd(&a1, B);
  37. mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
  38. if ((res = mp_copy(a, &a2)) != MP_OKAY) {
  39. goto ERR;
  40. }
  41. mp_rshd(&a2, B*2);
  42. /* w0 = a0*a0 */
  43. if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
  44. goto ERR;
  45. }
  46. /* w4 = a2 * a2 */
  47. if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
  48. goto ERR;
  49. }
  50. /* w1 = (a2 + 2(a1 + 2a0))**2 */
  51. if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
  52. goto ERR;
  53. }
  54. if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
  55. goto ERR;
  56. }
  57. if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
  58. goto ERR;
  59. }
  60. if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
  61. goto ERR;
  62. }
  63. if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
  64. goto ERR;
  65. }
  66. /* w3 = (a0 + 2(a1 + 2a2))**2 */
  67. if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
  68. goto ERR;
  69. }
  70. if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
  71. goto ERR;
  72. }
  73. if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
  74. goto ERR;
  75. }
  76. if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
  77. goto ERR;
  78. }
  79. if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
  80. goto ERR;
  81. }
  82. /* w2 = (a2 + a1 + a0)**2 */
  83. if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
  84. goto ERR;
  85. }
  86. if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
  87. goto ERR;
  88. }
  89. if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
  90. goto ERR;
  91. }
  92. /* now solve the matrix
  93. 0 0 0 0 1
  94. 1 2 4 8 16
  95. 1 1 1 1 1
  96. 16 8 4 2 1
  97. 1 0 0 0 0
  98. using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
  99. */
  100. /* r1 - r4 */
  101. if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
  102. goto ERR;
  103. }
  104. /* r3 - r0 */
  105. if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
  106. goto ERR;
  107. }
  108. /* r1/2 */
  109. if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
  110. goto ERR;
  111. }
  112. /* r3/2 */
  113. if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
  114. goto ERR;
  115. }
  116. /* r2 - r0 - r4 */
  117. if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
  118. goto ERR;
  119. }
  120. if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
  121. goto ERR;
  122. }
  123. /* r1 - r2 */
  124. if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
  125. goto ERR;
  126. }
  127. /* r3 - r2 */
  128. if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
  129. goto ERR;
  130. }
  131. /* r1 - 8r0 */
  132. if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
  133. goto ERR;
  134. }
  135. if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
  136. goto ERR;
  137. }
  138. /* r3 - 8r4 */
  139. if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
  140. goto ERR;
  141. }
  142. if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
  143. goto ERR;
  144. }
  145. /* 3r2 - r1 - r3 */
  146. if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
  147. goto ERR;
  148. }
  149. if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
  150. goto ERR;
  151. }
  152. if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
  153. goto ERR;
  154. }
  155. /* r1 - r2 */
  156. if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
  157. goto ERR;
  158. }
  159. /* r3 - r2 */
  160. if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
  161. goto ERR;
  162. }
  163. /* r1/3 */
  164. if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
  165. goto ERR;
  166. }
  167. /* r3/3 */
  168. if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
  169. goto ERR;
  170. }
  171. /* at this point shift W[n] by B*n */
  172. if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
  173. goto ERR;
  174. }
  175. if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
  176. goto ERR;
  177. }
  178. if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
  179. goto ERR;
  180. }
  181. if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
  182. goto ERR;
  183. }
  184. if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
  185. goto ERR;
  186. }
  187. if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
  188. goto ERR;
  189. }
  190. if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
  191. goto ERR;
  192. }
  193. if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
  194. goto ERR;
  195. }
  196. ERR:
  197. mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
  198. return res;
  199. }
  200. #endif
  201. /* $Source: /cvs/libtom/libtommath/bn_mp_toom_sqr.c,v $ */
  202. /* $Revision: 1.3 $ */
  203. /* $Date: 2006/03/31 14:18:44 $ */