mgcd.cpp 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //-----------------------------------------------------------------------------
  2. //
  3. // Bignum GCD
  4. //
  5. // Uses the binary GCD algorithm.
  6. //
  7. // See "The Art of Computer Programming" p. 338.
  8. //
  9. // mgcd always returns a positive value
  10. //
  11. // mgcd(0, 0) = 0
  12. //
  13. // mgcd(u, 0) = |u|
  14. //
  15. // mgcd(0, v) = |v|
  16. //
  17. //-----------------------------------------------------------------------------
  18. #include "stdafx.h"
  19. #include "defs.h"
  20. unsigned int *
  21. mgcd(unsigned int *u, unsigned int *v)
  22. {
  23. int i, k, n;
  24. unsigned int *t;
  25. if (MZERO(u)) {
  26. t = mcopy(v);
  27. MSIGN(t) = 1;
  28. return t;
  29. }
  30. if (MZERO(v)) {
  31. t = mcopy(u);
  32. MSIGN(t) = 1;
  33. return t;
  34. }
  35. u = mcopy(u);
  36. v = mcopy(v);
  37. MSIGN(u) = 1;
  38. MSIGN(v) = 1;
  39. k = 0;
  40. while ((u[0] & 1) == 0 && (v[0] & 1) == 0) {
  41. mshiftright(u);
  42. mshiftright(v);
  43. k++;
  44. }
  45. if (u[0] & 1) {
  46. t = mcopy(v);
  47. MSIGN(t) *= -1;
  48. } else
  49. t = mcopy(u);
  50. while (1) {
  51. while ((t[0] & 1) == 0)
  52. mshiftright(t);
  53. if (MSIGN(t) == 1) {
  54. mfree(u);
  55. u = mcopy(t);
  56. } else {
  57. mfree(v);
  58. v = mcopy(t);
  59. MSIGN(v) *= -1;
  60. }
  61. mfree(t);
  62. t = msub(u, v);
  63. if (MZERO(t)) {
  64. mfree(t);
  65. mfree(v);
  66. n = (k / 32) + 1;
  67. v = mnew(n);
  68. MSIGN(v) = 1;
  69. MLENGTH(v) = n;
  70. for (i = 0; i < n; i++)
  71. v[i] = 0;
  72. mp_set_bit(v, k);
  73. t = mmul(u, v);
  74. mfree(u);
  75. mfree(v);
  76. return t;
  77. }
  78. }
  79. }