@@ -47,68 +47,106 @@ data:
4747 \ weilycoder\n\n\n #line 1 \" weilycoder/number-theory/mod_utility.hpp\"\n\n\n\n \
4848 /**\n * @file mod_utility.hpp\n * @brief Modular Arithmetic Utilities\n */\n\n \
4949 #line 10 \" weilycoder/number-theory/mod_utility.hpp\"\n\n namespace weilycoder\
50- \ {\n using u128 = unsigned __int128;\n\n template <bool bit32 = false>\n constexpr\
51- \ uint64_t mod_add(uint64_t a, uint64_t b, uint64_t modulus) {\n if constexpr\
52- \ (bit32) {\n uint64_t res = a + b;\n if (res >= modulus)\n res -=\
53- \ modulus;\n return res;\n } else {\n u128 res = static_cast<u128>(a) +\
54- \ b;\n if (res >= modulus)\n res -= modulus;\n return res;\n }\n }\n \
55- \n template <bool bit32 = false>\n constexpr uint64_t mod_sub(uint64_t a, uint64_t\
56- \ b, uint64_t modulus) {\n if constexpr (bit32) {\n uint64_t res = (a >= b)\
57- \ ? (a - b) : (modulus + a - b);\n return res;\n } else {\n u128 res =\
58- \ (a >= b) ? (a - b) : (static_cast<u128>(modulus) + a - b);\n return res;\n \
59- \ }\n }\n\n /**\n * @brief Perform modular multiplication for 64-bit integers.\n \
60- \ * @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that\n \
61- \ * all inputs are small enough to avoid overflow (i.e. bit-32).\n * @param\
62- \ a The first multiplicand.\n * @param b The second multiplicand.\n * @param modulus\
63- \ The modulus.\n * @return (a * b) % modulus\n */\n template <bool bit32 = false>\n \
64- constexpr uint64_t mod_mul(uint64_t a, uint64_t b, uint64_t modulus) {\n if constexpr\
65- \ (bit32)\n return a * b % modulus;\n else\n return static_cast<u128>(a)\
66- \ * b % modulus;\n }\n\n /**\n * @brief Perform modular multiplication for 64-bit\
50+ \ {\n using u128 = unsigned __int128;\n\n /**\n * @brief Perform modular addition\
51+ \ for 64-bit integers.\n * @tparam bit32 If true, won't use 128-bit arithmetic.\
52+ \ You should ensure that\n * all inputs are small enough to avoid overflow\
53+ \ (i.e. bit-32).\n * @param a The first addend.\n * @param b The second addend.\n \
54+ \ * @param modulus The modulus.\n * @return (a + b) % modulus\n */\n template <bool\
55+ \ bit32 = false>\n constexpr uint64_t mod_add(uint64_t a, uint64_t b, uint64_t\
56+ \ modulus) {\n if constexpr (bit32) {\n uint64_t res = a + b;\n if (res\
57+ \ >= modulus)\n res -= modulus;\n return res;\n } else {\n u128 res\
58+ \ = static_cast<u128>(a) + b;\n if (res >= modulus)\n res -= modulus;\n \
59+ \ return res;\n }\n }\n\n /**\n * @brief Perform modular addition for 64-bit\
6760 \ integers with a compile-time\n * modulus.\n * @tparam Modulus The modulus.\n \
68- \ * @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that\n \
69- \ * all inputs are small enough to avoid overflow (i.e. bit-32).\n * @param\
70- \ a The first multiplicand.\n * @param b The second multiplicand.\n * @return\
71- \ (a * b) % Modulus\n */\n template <uint64_t Modulus, bool bit32 = false>\n constexpr\
72- \ uint64_t mod_mul(uint64_t a, uint64_t b) {\n if constexpr (bit32)\n return\
73- \ a * b % Modulus;\n else\n return static_cast<u128>(a) * b % Modulus;\n }\n \
74- \n /**\n * @brief Perform modular exponentiation for 64-bit integers.\n * @tparam\
75- \ bit32 If true, won't use 128-bit arithmetic. You should ensure that\n * \
76- \ all inputs are small enough to avoid overflow (i.e. bit-32).\n * @param\
77- \ base The base number.\n * @param exponent The exponent.\n * @param modulus The\
78- \ modulus.\n * @return (base^exponent) % modulus\n */\n template <bool bit32 =\
79- \ false>\n constexpr uint64_t mod_pow(uint64_t base, uint64_t exponent, uint64_t\
80- \ modulus) {\n uint64_t result = 1 % modulus;\n base %= modulus;\n while (exponent\
81- \ > 0) {\n if (exponent & 1)\n result = mod_mul<bit32>(result, base, modulus);\n \
82- \ base = mod_mul<bit32>(base, base, modulus);\n exponent >>= 1;\n }\n \
83- \ return result;\n }\n } // namespace weilycoder\n\n\n #line 1 \" weilycoder/number-theory/prime.hpp\" \
84- \n\n\n\n /**\n * @file prime.hpp\n * @brief Prime Number Utilities\n */\n\n #line\
85- \ 11 \" weilycoder/number-theory/prime.hpp\"\n #include <type_traits>\n\n namespace\
86- \ weilycoder {\n /**\n * @brief Miller-Rabin primality test for a given base.\n \
87- \ * @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that\n \
88- \ * all inputs are small enough to avoid overflow (i.e. bit-32).\n * @tparam\
89- \ base The base to test.\n * @param n The number to test for primality.\n * @param\
90- \ d An odd component of n-1 (n-1 = d * 2^s).\n * @param s The exponent of 2 in\
91- \ the factorization of n-1.\n * @return true if n is probably prime for the given\
92- \ base, false if composite.\n */\n template <bool bit32, uint64_t base>\n constexpr\
93- \ bool miller_rabin_test(uint64_t n, uint64_t d, uint32_t s) {\n uint64_t x =\
94- \ mod_pow<bit32>(base, d, n);\n if (x == 0 || x == 1 || x == n - 1)\n return\
95- \ true;\n for (uint32_t r = 1; r < s; ++r) {\n x = mod_mul<bit32>(x, x, n);\n \
96- \ if (x == n - 1)\n return true;\n }\n return false;\n }\n\n /**\n * @brief\
97- \ Variadic template to test multiple bases in Miller-Rabin test.\n * @tparam bit32\
98- \ If true, won't use 128-bit arithmetic. You should ensure that\n * all\
99- \ inputs are small enough to avoid overflow (i.e. bit-32).\n * @tparam base The\
100- \ first base to test.\n * @tparam Rest The remaining bases to test.\n * @param\
61+ \ * @param a The first addend.\n * @param b The second addend.\n * @return (a\
62+ \ + b) % Modulus\n */\n template <uint64_t Modulus> constexpr uint64_t mod_add(uint64_t\
63+ \ a, uint64_t b) {\n if constexpr (Modulus <= UINT32_MAX) {\n uint64_t res\
64+ \ = a + b;\n if (res >= Modulus)\n res -= Modulus;\n return res;\n \
65+ \ } else {\n u128 res = static_cast<u128>(a) + b;\n if (res >= Modulus)\n \
66+ \ res -= Modulus;\n return res;\n }\n }\n\n /**\n * @brief Perform modular\
67+ \ subtraction for 64-bit integers.\n * @tparam bit32 If true, won't use 128-bit\
68+ \ arithmetic. You should ensure that\n * all inputs are small enough to\
69+ \ avoid overflow (i.e. bit-32).\n * @param a The minuend.\n * @param b The subtrahend.\n \
70+ \ * @param modulus The modulus.\n * @return (a - b) % modulus\n */\n template <bool\
71+ \ bit32 = false>\n constexpr uint64_t mod_sub(uint64_t a, uint64_t b, uint64_t\
72+ \ modulus) {\n if constexpr (bit32) {\n uint64_t res = (a >= b) ? (a - b)\
73+ \ : (modulus + a - b);\n return res;\n } else {\n u128 res = (a >= b) ?\
74+ \ (a - b) : (static_cast<u128>(modulus) + a - b);\n return res;\n }\n }\n\n \
75+ /**\n * @brief Perform modular subtraction for 64-bit integers with a compile-time\n \
76+ \ * modulus.\n * @tparam Modulus The modulus.\n * @param a The minuend.\n \
77+ \ * @param b The subtrahend.\n * @return (a - b) % Modulus\n */\n template <uint64_t\
78+ \ Modulus> constexpr uint64_t mod_sub(uint64_t a, uint64_t b) {\n if constexpr\
79+ \ (Modulus <= UINT32_MAX) {\n uint64_t res = (a >= b) ? (a - b) : (Modulus\
80+ \ + a - b);\n return res;\n } else {\n u128 res = (a >= b) ? (a - b) :\
81+ \ (static_cast<u128>(Modulus) + a - b);\n return res;\n }\n }\n\n /**\n * @brief\
82+ \ Perform modular multiplication for 64-bit integers.\n * @tparam bit32 If true,\
83+ \ won't use 128-bit arithmetic. You should ensure that\n * all inputs\
84+ \ are small enough to avoid overflow (i.e. bit-32).\n * @param a The first multiplicand.\n \
85+ \ * @param b The second multiplicand.\n * @param modulus The modulus.\n * @return\
86+ \ (a * b) % modulus\n */\n template <bool bit32 = false>\n constexpr uint64_t mod_mul(uint64_t\
87+ \ a, uint64_t b, uint64_t modulus) {\n if constexpr (bit32)\n return a * b\
88+ \ % modulus;\n else\n return static_cast<u128>(a) * b % modulus;\n }\n\n /**\n \
89+ \ * @brief Perform modular multiplication for 64-bit integers with a compile-time\n \
90+ \ * modulus.\n * @tparam Modulus The modulus.\n * @param a The first multiplicand.\n \
91+ \ * @param b The second multiplicand.\n * @return (a * b) % Modulus\n */\n template\
92+ \ <uint64_t Modulus> constexpr uint64_t mod_mul(uint64_t a, uint64_t b) {\n if\
93+ \ constexpr (Modulus <= UINT32_MAX)\n return a * b % Modulus;\n else\n \
94+ \ return static_cast<u128>(a) * b % Modulus;\n }\n\n /**\n * @brief Perform modular\
95+ \ exponentiation for 64-bit integers.\n * @tparam bit32 If true, won't use 128-bit\
96+ \ arithmetic. You should ensure that\n * all inputs are small enough to\
97+ \ avoid overflow (i.e. bit-32).\n * @param base The base number.\n * @param exponent\
98+ \ The exponent.\n * @param modulus The modulus.\n * @return (base^exponent) %\
99+ \ modulus\n */\n template <bool bit32 = false>\n constexpr uint64_t mod_pow(uint64_t\
100+ \ base, uint64_t exponent, uint64_t modulus) {\n uint64_t result = 1 % modulus;\n \
101+ \ base %= modulus;\n while (exponent > 0) {\n if (exponent & 1)\n result\
102+ \ = mod_mul<bit32>(result, base, modulus);\n base = mod_mul<bit32>(base, base,\
103+ \ modulus);\n exponent >>= 1;\n }\n return result;\n }\n\n /**\n * @brief Perform\
104+ \ modular exponentiation for 64-bit integers with a compile-time\n * modulus.\n \
105+ \ * @tparam Modulus The modulus.\n * @param base The base number.\n * @param exponent\
106+ \ The exponent.\n * @return (base^exponent) % Modulus\n */\n template <uint64_t\
107+ \ Modulus>\n constexpr uint64_t mod_pow(uint64_t base, uint64_t exponent) {\n \
108+ \ uint64_t result = 1 % Modulus;\n base %= Modulus;\n while (exponent > 0) {\n \
109+ \ if (exponent & 1)\n result = mod_mul<Modulus>(result, base);\n base\
110+ \ = mod_mul<Modulus>(base, base);\n exponent >>= 1;\n }\n return result;\n \
111+ }\n\n /**\n * @brief Compute the modular inverse of a 64-bit integer using Fermat's\
112+ \ Little\n * Theorem.\n * @tparam Modulus The modulus (must be prime).\n \
113+ \ * @param a The number to find the modular inverse of.\n * @return The modular\
114+ \ inverse of a modulo Modulus.\n */\n template <uint64_t Modulus> constexpr uint64_t\
115+ \ mod_inv(uint64_t a) {\n return mod_pow<Modulus>(a, Modulus - 2);\n }\n\n /**\n \
116+ \ * @brief Compute the modular inverse of a compile-time 64-bit integer using\n \
117+ \ * Fermat's Little Theorem.\n * @tparam Modulus The modulus (must be prime).\n \
118+ \ * @tparam a The number to find the modular inverse of.\n * @return The modular\
119+ \ inverse of a modulo Modulus.\n */\n template <uint64_t Modulus, uint64_t a> constexpr\
120+ \ uint64_t mod_inv() {\n return mod_pow<Modulus>(a, Modulus - 2);\n }\n } // namespace\
121+ \ weilycoder\n\n\n #line 1 \" weilycoder/number-theory/prime.hpp\"\n\n\n\n /**\n \
122+ \ * @file prime.hpp\n * @brief Prime Number Utilities\n */\n\n #line 11 \" weilycoder/number-theory/prime.hpp\" \
123+ \n #include <type_traits>\n\n namespace weilycoder {\n /**\n * @brief Miller-Rabin\
124+ \ primality test for a given base.\n * @tparam bit32 If true, won't use 128-bit\
125+ \ arithmetic. You should ensure that\n * all inputs are small enough to\
126+ \ avoid overflow (i.e. bit-32).\n * @tparam base The base to test.\n * @param\
101127 \ n The number to test for primality.\n * @param d An odd component of n-1 (n-1\
102128 \ = d * 2^s).\n * @param s The exponent of 2 in the factorization of n-1.\n *\
103- \ @return true if n is probably prime for all given bases, false if composite.\n \
104- \ */\n template <bool bit32, uint64_t base, uint64_t... Rest>\n constexpr std::enable_if_t<(sizeof...(Rest)\
105- \ != 0), bool>\n miller_rabin_test(uint64_t n, uint64_t d, uint32_t s) {\n return\
106- \ miller_rabin_test<bit32, base>(n, d, s) &&\n miller_rabin_test<bit32,\
107- \ Rest...>(n, d, s);\n }\n\n /**\n * @brief Miller-Rabin primality test using multiple\
108- \ bases.\n * @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure\
109- \ that\n * all inputs are small enough to avoid overflow (i.e. bit-32).\n \
110- \ * @tparam bases The bases to test.\n * @param n The number to test for primality.\n \
111- \ * @return true if n is probably prime, false if composite.\n */\n template <bool\
129+ \ @return true if n is probably prime for the given base, false if composite.\n \
130+ \ */\n template <bool bit32, uint64_t base>\n constexpr bool miller_rabin_test(uint64_t\
131+ \ n, uint64_t d, uint32_t s) {\n uint64_t x = mod_pow<bit32>(base, d, n);\n \
132+ \ if (x == 0 || x == 1 || x == n - 1)\n return true;\n for (uint32_t r = 1;\
133+ \ r < s; ++r) {\n x = mod_mul<bit32>(x, x, n);\n if (x == n - 1)\n \
134+ \ return true;\n }\n return false;\n }\n\n /**\n * @brief Variadic template to\
135+ \ test multiple bases in Miller-Rabin test.\n * @tparam bit32 If true, won't use\
136+ \ 128-bit arithmetic. You should ensure that\n * all inputs are small\
137+ \ enough to avoid overflow (i.e. bit-32).\n * @tparam base The first base to test.\n \
138+ \ * @tparam Rest The remaining bases to test.\n * @param n The number to test\
139+ \ for primality.\n * @param d An odd component of n-1 (n-1 = d * 2^s).\n * @param\
140+ \ s The exponent of 2 in the factorization of n-1.\n * @return true if n is probably\
141+ \ prime for all given bases, false if composite.\n */\n template <bool bit32, uint64_t\
142+ \ base, uint64_t... Rest>\n constexpr std::enable_if_t<(sizeof...(Rest) != 0),\
143+ \ bool>\n miller_rabin_test(uint64_t n, uint64_t d, uint32_t s) {\n return miller_rabin_test<bit32,\
144+ \ base>(n, d, s) &&\n miller_rabin_test<bit32, Rest...>(n, d, s);\n }\n \
145+ \n /**\n * @brief Miller-Rabin primality test using multiple bases.\n * @tparam\
146+ \ bit32 If true, won't use 128-bit arithmetic. You should ensure that\n * \
147+ \ all inputs are small enough to avoid overflow (i.e. bit-32).\n * @tparam\
148+ \ bases The bases to test.\n * @param n The number to test for primality.\n *\
149+ \ @return true if n is probably prime, false if composite.\n */\n template <bool\
112150 \ bit32, uint64_t... bases> constexpr bool miller_rabin(uint64_t n) {\n if (n\
113151 \ < 2)\n return false;\n if (n == 2 || n == 3)\n return true;\n if (n\
114152 \ % 2 == 0)\n return false;\n\n uint64_t d = n - 1, s = 0;\n for (; d % 2\
@@ -201,7 +239,7 @@ data:
201239 isVerificationFile : true
202240 path : test/factorize.test.cpp
203241 requiredBy : []
204- timestamp : ' 2025-11-07 09:14:02 +08:00'
242+ timestamp : ' 2025-11-07 22:54:43 +08:00'
205243 verificationStatus : TEST_ACCEPTED
206244 verifiedWith : []
207245documentation_of : test/factorize.test.cpp
0 commit comments