pollard-strassen_factorization_method_no_polynomials.sf 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. #!/usr/bin/ruby
  2. # Pollard-Strassen O(n^(1/4)) factorization algorithm.
  3. # Without using polynomials.
  4. # Illustrated by David Harvey in the following video:
  5. # https://yewtu.be/watch?v=_53s-0ZLxbQ
  6. func pollard_strassen_factorization(n, d = min(500, 1+n.ilog2), tries = min(1000, 100*d)) {
  7. # In the original algorithm, d = ceil(n^(1/4))
  8. # d = 1+n.iroot(4)
  9. var a = random_prime(n)
  10. var baby_steps = @(1..d).map_reduce {|b|
  11. mulmod(b, a, n)
  12. }
  13. #var x = Poly(1)
  14. #var f = baby_steps.map {|k| (x-k) % n }.binsplit {|a,b| a * b }
  15. var b = powmod(a, d, n)
  16. for k in (2 .. tries) {
  17. #b = powmod(a, k*d, n) # original operation
  18. b = powmod(b, k, n) # p-1 smooth approach
  19. var t = baby_steps.map {|k| submod(b, k, n) }.reduce {|a,b|
  20. mulmod(a, b, n)
  21. }
  22. var g = gcd(t, n)
  23. if (g.is_between(2, n-1)) {
  24. return g
  25. }
  26. }
  27. return 1
  28. }
  29. say pollard_strassen_factorization(503*863)
  30. say pollard_strassen_factorization(2**64 + 1)
  31. say pollard_strassen_factorization(2.of { 1e7.random_prime }.prod)