bn_mp_gcd.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include <tommath.h>
  2. #ifdef BN_MP_GCD_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. /* Greatest Common Divisor using the binary method */
  18. int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
  19. {
  20. mp_int u, v;
  21. int k, u_lsb, v_lsb, res;
  22. /* either zero than gcd is the largest */
  23. if (mp_iszero (a) == MP_YES) {
  24. return mp_abs (b, c);
  25. }
  26. if (mp_iszero (b) == MP_YES) {
  27. return mp_abs (a, c);
  28. }
  29. /* get copies of a and b we can modify */
  30. if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
  31. return res;
  32. }
  33. if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
  34. goto LBL_U;
  35. }
  36. /* must be positive for the remainder of the algorithm */
  37. u.sign = v.sign = MP_ZPOS;
  38. /* B1. Find the common power of two for u and v */
  39. u_lsb = mp_cnt_lsb(&u);
  40. v_lsb = mp_cnt_lsb(&v);
  41. k = MIN(u_lsb, v_lsb);
  42. if (k > 0) {
  43. /* divide the power of two out */
  44. if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
  45. goto LBL_V;
  46. }
  47. if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
  48. goto LBL_V;
  49. }
  50. }
  51. /* divide any remaining factors of two out */
  52. if (u_lsb != k) {
  53. if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
  54. goto LBL_V;
  55. }
  56. }
  57. if (v_lsb != k) {
  58. if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
  59. goto LBL_V;
  60. }
  61. }
  62. while (mp_iszero(&v) == 0) {
  63. /* make sure v is the largest */
  64. if (mp_cmp_mag(&u, &v) == MP_GT) {
  65. /* swap u and v to make sure v is >= u */
  66. mp_exch(&u, &v);
  67. }
  68. /* subtract smallest from largest */
  69. if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
  70. goto LBL_V;
  71. }
  72. /* Divide out all factors of two */
  73. if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
  74. goto LBL_V;
  75. }
  76. }
  77. /* multiply by 2**k which we divided out at the beginning */
  78. if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
  79. goto LBL_V;
  80. }
  81. c->sign = MP_ZPOS;
  82. res = MP_OKAY;
  83. LBL_V:mp_clear (&u);
  84. LBL_U:mp_clear (&v);
  85. return res;
  86. }
  87. #endif
  88. /* $Source: /cvs/libtom/libtommath/bn_mp_gcd.c,v $ */
  89. /* $Revision: 1.4 $ */
  90. /* $Date: 2006/03/31 14:18:44 $ */