66 * @brief Functions for factorizing numbers using Pollard's Rho algorithm
77 */
88
9+ #include " ../const_rand.hpp"
910#include " mod_utility.hpp"
1011#include " prime.hpp"
1112#include < algorithm>
@@ -27,6 +28,7 @@ namespace weilycoder {
2728template <bool bit32 = false > constexpr uint64_t pollard_rho (uint64_t x, uint64_t c) {
2829 if (x % 2 == 0 )
2930 return 2 ;
31+ c = c % (x - 1 ) + 1 ;
3032 uint32_t step = 0 , goal = 1 ;
3133 uint64_t s = 0 , t = 0 ;
3234 uint64_t value = 1 ;
@@ -57,11 +59,10 @@ template <bool bit32 = false> constexpr uint64_t pollard_rho(uint64_t x, uint64_
5759 * @return A non-trivial factor of x
5860 */
5961template <bool bit32 = false > uint64_t pollard_rho (uint64_t x) {
60- static std::minstd_rand rng{};
6162 if (x % 2 == 0 )
6263 return 2 ;
63- uint64_t c = rng () % (x - 1 ) + 1 ;
64- return pollard_rho<bit32>(x, c );
64+ static std::minstd_rand rng{} ;
65+ return pollard_rho<bit32>(x, rng () );
6566}
6667
6768/* *
@@ -106,30 +107,41 @@ template <bool bit32 = false> std::vector<uint64_t> factorize(uint64_t x) {
106107 */
107108template <size_t N = 64 , bool bit32 = false >
108109constexpr std::array<uint64_t , N> factorize_fixed (uint64_t x) {
110+ uint32_t random_state = 1 ;
109111 size_t factor_idx = 0 , stk_idx = 0 ;
110112 std::array<uint64_t , N> factors{};
111- std::array<std::pair<uint64_t , size_t >, 64 > stk{};
112- stk[stk_idx++] = {x, 1 };
113+ std::array<uint64_t , 64 > stk_val{};
114+ std::array<size_t , 64 > stk_cnt{};
115+ stk_val[stk_idx] = x, stk_cnt[stk_idx++] = 1 ;
113116 while (stk_idx > 0 ) {
114- auto [cur, cnt] = stk[--stk_idx];
117+ uint64_t cur = stk_val[--stk_idx];
118+ size_t cnt = stk_cnt[stk_idx];
115119 if (cur == 1 )
116120 continue ;
117- if (is_prime (cur))
118- std::fill (factors. begin () + factor_idx, factors. begin () + factor_idx + cnt, cur),
119- factor_idx += cnt ;
120- else {
121+ if (is_prime (cur)) {
122+ for ( size_t i = 0 ; i < cnt; ++i)
123+ factors[ factor_idx++] = cur ;
124+ } else {
121125 uint64_t factor = cur;
122126 do
123- factor = pollard_rho<bit32>(cur);
127+ factor = pollard_rho<bit32>(cur, lcg_nr (random_state) );
124128 while (factor == cur);
125129 size_t factor_count = 0 ;
126130 while (cur % factor == 0 )
127131 cur /= factor, ++factor_count;
128- stk[stk_idx++] = {cur, cnt};
129- stk[stk_idx++] = {factor, factor_count * cnt};
132+ stk_val[stk_idx] = cur, stk_cnt[stk_idx++] = cnt;
133+ stk_val[stk_idx] = factor, stk_cnt[stk_idx++] = factor_count * cnt;
134+ }
135+ }
136+ for (size_t i = 1 ; i < factor_idx; ++i) {
137+ uint64_t key = factors[i];
138+ size_t j = i;
139+ while (j > 0 && factors[j - 1 ] > key) {
140+ factors[j] = factors[j - 1 ];
141+ --j;
130142 }
143+ factors[j] = key;
131144 }
132- std::sort (factors.begin (), factors.begin () + factor_idx);
133145 return factors;
134146}
135147} // namespace weilycoder
0 commit comments