binary_gcd_algorithm_mpz.pl 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 12 August 2017
  4. # https://github.com/trizen
  5. # Algorithm invented by J. Stein in 1967, described in the
  6. # book "Algorithmic Number Theory" by Eric Bach and Jeffrey Shallit.
  7. use 5.010;
  8. use strict;
  9. use warnings;
  10. use Math::GMPz;
  11. sub binary_gcd {
  12. my ($u, $v) = @_;
  13. $u = Math::GMPz::Rmpz_init_set($u);
  14. $v = Math::GMPz::Rmpz_init_set($v);
  15. my $g = Math::GMPz::Rmpz_init_set_ui(1);
  16. while (Math::GMPz::Rmpz_even_p($u) and Math::GMPz::Rmpz_even_p($v)) {
  17. Math::GMPz::Rmpz_div_2exp($v, $v, 1);
  18. Math::GMPz::Rmpz_div_2exp($u, $u, 1);
  19. Math::GMPz::Rmpz_mul_2exp($g, $g, 1);
  20. }
  21. while (Math::GMPz::Rmpz_sgn($u)) {
  22. if (Math::GMPz::Rmpz_even_p($u)) {
  23. Math::GMPz::Rmpz_div_2exp($u, $u, 1);
  24. }
  25. elsif (Math::GMPz::Rmpz_even_p($v)) {
  26. Math::GMPz::Rmpz_div_2exp($v, $v, 1);
  27. }
  28. elsif (Math::GMPz::Rmpz_cmp($u, $v) >= 0) {
  29. Math::GMPz::Rmpz_sub($u, $u, $v);
  30. Math::GMPz::Rmpz_div_2exp($u, $u, 1);
  31. }
  32. else {
  33. Math::GMPz::Rmpz_sub($v, $v, $u);
  34. Math::GMPz::Rmpz_div_2exp($v, $v, 1);
  35. }
  36. }
  37. Math::GMPz::Rmpz_mul($g, $g, $v);
  38. return $g;
  39. }
  40. my $u = Math::GMPz->new('484118311800307409686872049018968526148964320406131317406564776592214983358038627898935326228550128722261905040875508300794183477624832000000000000000000000000');
  41. my $v = Math::GMPz->new('93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000');
  42. say binary_gcd($u, $v); #=> 33464469725118339932738475939854523519700805708105926500308251028510111778609255576238987149312000000000000000000000000
  43. say binary_gcd($v, $u); #=> 33464469725118339932738475939854523519700805708105926500308251028510111778609255576238987149312000000000000000000000000