partial_sums_of_jordan_totient_function.pl 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #!/usr/bin/perl
  2. # Author: Daniel "Trizen" Șuteu
  3. # Date: 21 November 2018
  4. # https://github.com/trizen
  5. # A new algorithm for computing the partial-sums of the Jordan totient function `J_m(k)`, for `1 <= k <= n`:
  6. #
  7. # Sum_{k=1..n} J_m(k)
  8. #
  9. # for any fixed integer m >= 1.
  10. # Based on the formula:
  11. # Sum_{k=1..n} J_m(k) = Sum_{k=1..n} moebius(k) * F(m, floor(n/k))
  12. #
  13. # where F(n,x) is Faulhaber's formula for `Sum_{k=1..x} k^n`, defined in terms of Bernoulli polynomials as:
  14. # F(n, x) = (Bernoulli(n+1, x+1) - Bernoulli(n+1, 1)) / (n+1)
  15. # Example for a(n) = Sum_{k=1..n} J_2(k):
  16. # a(10^1) = 312
  17. # a(10^2) = 280608
  18. # a(10^3) = 277652904
  19. # a(10^4) = 277335915120
  20. # a(10^5) = 277305865353048
  21. # a(10^6) = 277302780859485648
  22. # a(10^7) = 277302491422450102032
  23. # a(10^8) = 277302460845902192282712
  24. # a(10^9) = 277302457878113251222146576
  25. # Asymptotic formula:
  26. # Sum_{k=1..n} J_2(k) ~ n^3 / (3*zeta(3))
  27. # In general, for m>=1:
  28. # Sum_{k=1..n} J_m(k) ~ n^(m+1) / ((m+1) * zeta(m+1))
  29. # See also:
  30. # https://oeis.org/A321879
  31. # https://en.wikipedia.org/wiki/Mertens_function
  32. # https://en.wikipedia.org/wiki/M%C3%B6bius_function
  33. # https://en.wikipedia.org/wiki/Jordan%27s_totient_function
  34. # https://trizenx.blogspot.com/2018/11/partial-sums-of-arithmetical-functions.html
  35. use 5.020;
  36. use strict;
  37. use warnings;
  38. use experimental qw(signatures);
  39. use Math::AnyNum qw(faulhaber_sum ipow);
  40. use ntheory qw(jordan_totient moebius mertens vecsum sqrtint forsquarefree is_square_free);
  41. sub jordan_totient_partial_sum ($n, $m) {
  42. my $total = 0;
  43. my $s = sqrtint($n);
  44. my $u = int($n / ($s + 1));
  45. my $prev = mertens($n);
  46. for my $k (1 .. $s) {
  47. my $curr = mertens(int($n / ($k + 1)));
  48. $total += ($prev - $curr) * faulhaber_sum($k, $m);
  49. $prev = $curr;
  50. }
  51. forsquarefree {
  52. $total += moebius($_) * faulhaber_sum(int($n / $_), $m);
  53. } $u;
  54. return $total;
  55. }
  56. sub jordan_totient_partial_sum_2 ($n, $m) {
  57. my $total = 0;
  58. my $s = sqrtint($n);
  59. for my $k (1 .. $s) {
  60. $total += ipow($k, $m) * mertens(int($n/$k));
  61. $total += moebius($k) * faulhaber_sum(int($n/$k), $m) if is_square_free($k);
  62. }
  63. $total -= faulhaber_sum($s, $m) * mertens($s);
  64. return $total;
  65. }
  66. sub jordan_totient_partial_sum_test ($n, $m) { # just for testing
  67. vecsum(map { jordan_totient($m, $_) } 1 .. $n);
  68. }
  69. for my $m (0 .. 10) {
  70. my $n = int rand 10000;
  71. my $t1 = jordan_totient_partial_sum($n, $m);
  72. my $t2 = jordan_totient_partial_sum_2($n, $m);
  73. my $t3 = jordan_totient_partial_sum_test($n, $m);
  74. die "error: $t1 != $t2" if ($t1 != $t2);
  75. die "error: $t1 != $t3" if ($t1 != $t3);
  76. say "Sum_{k=1..$n} J_$m(k) = $t1";
  77. }
  78. __END__
  79. Sum_{k=1..3244} J_0(k) = 1
  80. Sum_{k=1..5688} J_1(k) = 9834896
  81. Sum_{k=1..9961} J_2(k) = 274117576704
  82. Sum_{k=1..2548} J_3(k) = 9743111756724
  83. Sum_{k=1..1147} J_4(k) = 383774380194000
  84. Sum_{k=1..9985} J_5(k) = 162406071542610636006836
  85. Sum_{k=1..8677} J_6(k) = 524873561219508820442845176
  86. Sum_{k=1..3594} J_7(k) = 3469354096873688451827581144
  87. Sum_{k=1..6424} J_8(k) = 2067471378951107437291216947429120
  88. Sum_{k=1..5169} J_9(k) = 1361614000750853225756775763744598788
  89. Sum_{k=1..7785} J_10(k) = 578821237542299170578127992588067328813064