src/nt/pfactors/lib.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "../../edh/discretization/lib.hpp" | ||
| 4 | #include "../../math/mul_mod/lib.hpp" | ||
| 5 | #include "../../util/rand/lib.hpp" | ||
| 6 | #include "../gl/gcd/lib.hpp" | ||
| 7 | #include "../is_prime/lib.hpp" | ||
| 8 | |||
| 9 | namespace tifa_libs { | ||
| 10 | namespace pfactors_impl_ { | ||
| 11 | static rand_gen<u64> e; | ||
| 12 | 19055 | static auto __ = [] { e.seed(); return 0; }(); | |
| 13 | 98558 | CEXP u64 rho(u64 n) NE { | |
| 14 | 98558 | e.range(1, n - 1); | |
| 15 | 3080513223 | auto f = [n, r = e()](u64 x) NE { return (mul_mod_u(x, x, n) + r) % n; }; | |
| 16 | 98558 | u64 g = 1, x = 0, y = e(), yy = 0; | |
| 17 | 98558 | cu32 LIM = 128; | |
| 18 |
2/2✓ Branch 0 taken 215680 times.
✓ Branch 1 taken 98558 times.
|
314238 | for (u64 r = 1, q = 1; g == 1; r *= 2) { |
| 19 | 215680 | x = y; | |
| 20 |
2/2✓ Branch 1 taken 1869494050 times.
✓ Branch 2 taken 215680 times.
|
1869709730 | flt_ (u64, i, 0, r) y = f(y); |
| 21 |
4/4✓ Branch 0 taken 9770775 times.
✓ Branch 1 taken 98558 times.
✓ Branch 2 taken 9653653 times.
✓ Branch 3 taken 117122 times.
|
9869333 | for (u64 k = 0; g == 1 && k < r; k += LIM) { |
| 22 | 9653653 | yy = y; | |
| 23 |
4/4✓ Branch 2 taken 1211087758 times.
✓ Branch 3 taken 9453353 times.
✓ Branch 4 taken 1210887458 times.
✓ Branch 5 taken 200300 times.
|
1220541111 | for (u64 i = 0; i < LIM && i < r - k; ++i) q = mul_mod_u(q, (n - (y = f(y)) + x) % n, n); |
| 24 | 9653653 | g = gcd(q, n); | |
| 25 | } | ||
| 26 | } | ||
| 27 |
2/2✓ Branch 0 taken 25453 times.
✓ Branch 1 taken 73105 times.
|
98558 | if (g == n) do { |
| 28 | 33157 | g = gcd((x + (n - (yy = f(yy)))) % n, n); | |
| 29 |
2/2✓ Branch 0 taken 7704 times.
✓ Branch 1 taken 25453 times.
|
33157 | } while (g == 1); |
| 30 |
2/2✓ Branch 0 taken 16139 times.
✓ Branch 1 taken 82419 times.
|
98558 | retif_((g == n), rho(n), g); |
| 31 | } | ||
| 32 | 188127 | CEXP void run(u64 n, vecuu& p) NE { | |
| 33 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 188127 times.
|
188127 | if (n < 2) return; |
| 34 |
2/2✓ Branch 1 taken 105708 times.
✓ Branch 2 taken 82419 times.
|
188127 | if (is_prime(n)) return p.push_back(n); |
| 35 | 82419 | cu64 g = rho(n); | |
| 36 | 82419 | run(n / g, p), run(g, p); | |
| 37 | } | ||
| 38 | } // namespace pfactors_impl_ | ||
| 39 | |||
| 40 | template <bool unique = true> | ||
| 41 | 299582 | CEXP vecuu pfactors(u64 n) NE { | |
| 42 | 299582 | vecuu p; | |
| 43 |
4/4std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<false>(unsigned long):
✓ Branch 1 taken 2822 times.
✓ Branch 2 taken 4816 times.
std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<true>(unsigned long):
✓ Branch 1 taken 285964 times.
✓ Branch 2 taken 5980 times.
|
299582 | if (cu32 _ = (u32)std::countr_zero(n) & 63; _) { |
| 44 | 288786 | n >>= _; | |
| 45 | 285964 | if CEXP (unique) p.push_back(2); | |
| 46 | 2822 | else p.assign(_, 2); | |
| 47 | } | ||
| 48 |
4/4std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<false>(unsigned long):
✓ Branch 0 taken 1457 times.
✓ Branch 1 taken 6181 times.
std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<true>(unsigned long):
✓ Branch 0 taken 274836 times.
✓ Branch 1 taken 17108 times.
|
299582 | if (n < 1000'000) |
| 49 |
4/4std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<false>(unsigned long):
✓ Branch 0 taken 2515982 times.
✓ Branch 1 taken 1457 times.
std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<true>(unsigned long):
✓ Branch 0 taken 24555061 times.
✓ Branch 1 taken 274836 times.
|
27347336 | for (u32 i = 3; i <= n; ++i) { |
| 50 |
4/4std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<false>(unsigned long):
✓ Branch 0 taken 2514441 times.
✓ Branch 1 taken 1541 times.
std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<true>(unsigned long):
✓ Branch 0 taken 24474464 times.
✓ Branch 1 taken 80597 times.
|
27071043 | if (n % i) continue; |
| 51 | 80597 | if CEXP (unique) p.push_back(i); | |
| 52 | do { | ||
| 53 | 205940 | if CEXP (n /= i; !unique) p.push_back(i); | |
| 54 |
4/4std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<false>(unsigned long):
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 1541 times.
std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<true>(unsigned long):
✓ Branch 0 taken 123224 times.
✓ Branch 1 taken 80597 times.
|
205940 | } while (!(n % i)); |
| 55 | } | ||
| 56 |
4/4std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<false>(unsigned long):
✓ Branch 0 taken 1457 times.
✓ Branch 1 taken 6181 times.
std::vector<unsigned long, std::allocator<unsigned long> > tifa_libs::pfactors<true>(unsigned long):
✓ Branch 0 taken 274836 times.
✓ Branch 1 taken 17108 times.
|
299582 | if (n < 2) return p; |
| 57 | 23289 | pfactors_impl_::run(n, p); | |
| 58 | 17108 | if CEXP (unique) return uniq(p); | |
| 59 | 6181 | tifa_libs::sort(p); | |
| 60 | 6181 | return p; | |
| 61 | 291944 | } | |
| 62 | 4979 | CEXP vecp<u64, u32> pf_exp(u64 n) NE { | |
| 63 | 4979 | auto p = pfactors<false>(n); | |
| 64 | 4979 | vecp<u64, u32> ans; | |
| 65 |
2/2✓ Branch 5 taken 37544 times.
✓ Branch 6 taken 4979 times.
|
42523 | for (u64 lst = 0; cu64 i : p) |
| 66 |
2/2✓ Branch 0 taken 16535 times.
✓ Branch 1 taken 21009 times.
|
37544 | if (i != lst) ans.emplace_back(lst = i, 1); |
| 67 | 21009 | else ++ans.back().second; | |
| 68 | 4979 | return ans; | |
| 69 | 4979 | } | |
| 70 | |||
| 71 | } // namespace tifa_libs | ||
| 72 |