r.sf 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #!/usr/bin/ruby
  2. # Daniel "Trizen" Șuteu
  3. # Date: 09 January 2019
  4. # https://github.com/trizen
  5. # Test if a large integer (>50 digits) is probably squarefree.
  6. # See also:
  7. # https://en.wikipedia.org/wiki/Square-free_integer
  8. # Tested up to 557
  9. func store_random_factor(a, f) {
  10. *a = f()
  11. (*a).len > 1
  12. }
  13. func find_random_factor(n, small=true, trial=false) {
  14. var e = []
  15. (trial && store_random_factor(\e, { n.trial_factor(1e6) })) ||
  16. (small && store_random_factor(\e, { n.pbrent_factor(1, 15000) })) ||
  17. (small && store_random_factor(\e, { n.pminus1_factor(50000, 500000) })) ||
  18. store_random_factor(\e, { n.pminus1_factor(1e6) }) ||
  19. store_random_factor(\e, { n.pplus1_factor(1e6) }) ||
  20. store_random_factor(\e, { n.ecm_factor(800, 10) }) ||
  21. store_random_factor(\e, { n.ecm_factor(8000, 20) }) ||
  22. #store_random_factor(\e, { n.ecm_factor(80000, 40) }) ||
  23. #store_random_factor(\e, { n.ecm_factor(320000, 40) }) ||
  24. #store_random_factor(\e, { n.ecm_factor(1000000, 80) }) ||
  25. store_random_factor(\e, { n.holf_factor(1e6) }) ||
  26. store_random_factor(\e, { n.squfof_factor(1e8) });
  27. return e
  28. }
  29. func is_prob_squarefree(r, tries=50) {
  30. if (r.len <= 50) {
  31. return r.is_square_free
  32. }
  33. return false if r.is_power
  34. loop {
  35. var f = r.trial_factor(1e6)
  36. break if (f.len == 1)
  37. r /= f[0]
  38. return false if (f[0] `divides` r)
  39. }
  40. tries.times { |k|
  41. var len = r.len
  42. if (len <= 50) {
  43. return r.is_square_free
  44. }
  45. if (len <= 10_000) {
  46. return true if r.is_prob_prime
  47. }
  48. var e = find_random_factor(r, k <= 3)
  49. e.len > 1 || break
  50. e.pop
  51. say "Factor: #{e[0]}"
  52. e.each {|p|
  53. if (p*p `divides` r) {
  54. return false
  55. }
  56. p.is_square_free || return false
  57. p.factor.each { |z|
  58. if (z*z `divides` r) {
  59. return false
  60. }
  61. }
  62. }
  63. e.each {|p| r /= p }
  64. if (r.is_power) {
  65. return false
  66. }
  67. }
  68. return true
  69. }
  70. func f(n) is cached {
  71. #return 1, 3, 9
  72. return 1 if (n == 0)
  73. return 3 if (n == 1)
  74. return 9 if (n == 2)
  75. 3*f(n-1) + 8*f(n-2)
  76. }
  77. for p in (primes(563, 1e6)) {
  78. say "Testing: #{p}"
  79. is_prob_squarefree(f(p)) || die "a(#{p}) is not squarefree!!!"
  80. }
  81. __END__
  82. # Example for testing several k such that 2^k + 1 is divisible by a square > 1.
  83. # See: https://oeis.org/A049096
  84. var a = [231, 234, 237, 243, 410, 411, 417, 891, 897, 903, 2370, 2373, 41390]
  85. a.each {|k|
  86. var t = is_prob_squarefree(2**k + 1)
  87. say "2^#{k} + 1 is #{t ? 'prob squarefree' : 'divisible by a square'}"
  88. }
  89. say "\nLarge non-squarefree tests:"
  90. say is_prob_squarefree(249860117627119815706149728420771785501032147277376706113) # false
  91. say is_prob_squarefree(1444134648503819781988817515640867565630266453262667463566673) # false
  92. say is_prob_squarefree(16240879415462221539256806220654226179619821855946633706672633593) # false
  93. say is_prob_squarefree(300973095636437173473855290756399701276460223130678583012549023809113) # false