@@ -69,14 +69,33 @@ constexpr uint64_t prime_primitive_root(uint64_t p) {
6969 if (!is_prime (p))
7070 return 0 ;
7171 auto factors = factorize_fixed<N, bit32>(p - 1 );
72- auto factor_end = std::unique (factors.begin (), factors.end ());
73- if (factor_end != factors.end ())
74- *factor_end = 0 ;
72+ auto factors_set = std::array<uint64_t , N>{};
73+ size_t factor_count = 0 ;
74+ for (size_t i = 0 ; i < N; ++i) {
75+ uint64_t q = factors[i];
76+ if (q == 0 )
77+ break ;
78+ if (i == 0 || q != factors[i - 1 ])
79+ factors_set[factor_count++] = q;
80+ }
7581 for (uint64_t g = 2 ; g < p; ++g)
76- if (is_primitive_root<64 , bit32>(g, p, factors ))
82+ if (is_primitive_root<N , bit32>(g, p, factors_set ))
7783 return g;
7884 return 0 ;
7985}
86+
87+ /* *
88+ * @brief Find a primitive root modulo a prime (compile-time version)
89+ * @tparam prime The prime modulus
90+ * @return A primitive root modulo prime.
91+ */
92+ template <uint64_t prime> constexpr uint64_t prime_primitive_root () {
93+ if constexpr (prime == 2 )
94+ return 1 ;
95+ if (prime < UINT32_MAX)
96+ return prime_primitive_root<true , 32 >(prime);
97+ return prime_primitive_root<false , 64 >(prime);
98+ }
8099} // namespace weilycoder
81100
82101#endif
0 commit comments