fibonacci_factorization_method.pl 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. #!/usr/bin/perl
  2. # Author: Daniel "Trizen" Șuteu
  3. # Date: 09 September 2018
  4. # https://github.com/trizen
  5. # A new integer factorization method, using the Fibonacci numbers.
  6. # It uses the smallest divisor `d` of `p - legendre(p, 5)`, for which `Fibonacci(d) = 0 (mod p)`.
  7. # By selecting a small bound B, we compute `k = lcm(1..B)`, hoping that `k` is a
  8. # multiple of `d`, then `gcd(Fibonacci(k) (mod n), n)` in a non-trivial factor of `n`.
  9. # This method is similar in flavor to Pollard's p-1 and Williams's p+1 methods.
  10. use 5.020;
  11. use warnings;
  12. use experimental qw(signatures);
  13. use Math::AnyNum qw(:overload gcd ilog2 is_prime);
  14. use Math::Prime::Util::GMP qw(consecutive_integer_lcm random_prime lucas_sequence);
  15. sub fibonacci_factorization ($n, $B = 10000) {
  16. my $k = consecutive_integer_lcm($B); # lcm(1..B)
  17. my $F = (lucas_sequence($n, 1, -1, $k))[0]; # Fibonacci(k) (mod n)
  18. return gcd($F, $n);
  19. }
  20. say fibonacci_factorization(257221 * 470783, 700); #=> 470783 (p+1 is 700-smooth)
  21. say fibonacci_factorization(333732865481 * 1632480277613, 3000); #=> 333732865481 (p-1 is 3000-smooth)
  22. # Example of a larger number that can be factorized fast with this method
  23. say fibonacci_factorization(203544696384073367670016326770637347800169508950125910682353, 19); #=> 5741461760879844361
  24. foreach my $k (1 .. 50) {
  25. my $n = Math::AnyNum->new(random_prime(1 << $k)) * random_prime(1 << $k);
  26. my $p = fibonacci_factorization($n, 2 * ilog2($n)**2);
  27. if (is_prime($p)) {
  28. say "$n = $p * ", $n / $p;
  29. }
  30. }