|
1 | 1 | /////////////////////////////////////////////////////////////////////////////// |
2 | | -// Copyright Christopher Kormanyos 2020 - 2024. |
| 2 | +// Copyright Christopher Kormanyos 2020 - 2025. |
3 | 3 | // Distributed under the Boost Software License, |
4 | 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt |
5 | 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) |
|
8 | 8 | #ifndef MILLER_RABIN_BASE_2020_05_30_H_ |
9 | 9 | #define MILLER_RABIN_BASE_2020_05_30_H_ |
10 | 10 |
|
| 11 | + // Note that -DWIDE_INTEGER_NAMESPACE=ckormanyos is defined |
| 12 | + // on the compiler command line. |
| 13 | + |
11 | 14 | #include <math/wide_integer/miller_rabin/miller_rabin_digits.h> |
| 15 | + #include <math/wide_integer/uintwide_t.h> |
12 | 16 |
|
13 | 17 | WIDE_INTEGER_NAMESPACE_BEGIN |
14 | 18 |
|
|
30 | 34 |
|
31 | 35 | virtual ~miller_rabin_base() = default; |
32 | 36 |
|
33 | | - virtual auto search() -> bool = 0; |
| 37 | + virtual bool search() = 0; |
34 | 38 |
|
35 | | - auto get_n_is_probably_prime() const -> bool |
| 39 | + bool get_n_is_probably_prime() const |
36 | 40 | { |
37 | 41 | return my_n_is_probably_prime; |
38 | 42 | } |
39 | 43 |
|
40 | | - auto get_n() const -> const wide_integer_type& |
| 44 | + const wide_integer_type& get_n() const |
41 | 45 | { |
42 | 46 | return my_n; |
43 | 47 | } |
44 | 48 |
|
45 | | - auto reseed1(const typename generator1_type::result_type seed1) -> void { my_generator1.seed(seed1); } |
46 | | - auto reseed2(const typename generator2_type::result_type seed2) -> void { my_generator2.seed(seed2); } |
| 49 | + void reseed1(const typename generator1_type::result_type seed1) { my_generator1.seed(seed1); } |
| 50 | + void reseed2(const typename generator2_type::result_type seed2) { my_generator2.seed(seed2); } |
47 | 51 |
|
48 | | - static auto get_n_total_mul_10() -> std::uint64_t { return my_n_total_mul_10; } |
| 52 | + static std::uint64_t get_n_total_mul_10() { return my_n_total_mul_10; } |
49 | 53 |
|
50 | 54 | protected: |
51 | 55 | using distribution_param_type = typename distribution_type::param_type; |
52 | 56 |
|
53 | | - static constexpr std::uint_fast32_t my_number_of_trials { UINT8_C(25) }; |
| 57 | + static constexpr std::uint_fast32_t my_number_of_trials = UINT32_C(25); |
54 | 58 |
|
55 | 59 | wide_integer_type my_n_trial; |
56 | 60 | bool my_n_trial_is_probably_prime; |
|
59 | 63 | wide_integer_type my_n_m1; |
60 | 64 | generator1_type my_generator1; |
61 | 65 | generator2_type my_generator2; |
62 | | - distribution_type my_distribution { }; |
63 | | - std::uint_fast32_t my_k { }; |
64 | | - wide_integer_type my_q { }; |
| 66 | + distribution_type my_distribution; |
| 67 | + std::uint_fast32_t my_k; |
| 68 | + wide_integer_type my_q; |
65 | 69 |
|
66 | 70 | constexpr miller_rabin_base(const typename generator1_type::result_type seed1 = typename generator1_type::result_type(), |
67 | 71 | const typename generator2_type::result_type seed2 = typename generator2_type::result_type()) |
|
71 | 75 | my_n_is_probably_prime (false), |
72 | 76 | my_n_m1 (), |
73 | 77 | my_generator1 (seed1), |
74 | | - my_generator2 (seed2) { } |
| 78 | + my_generator2 (seed2), |
| 79 | + my_distribution (), |
| 80 | + my_k (0U), |
| 81 | + my_q () { } |
75 | 82 |
|
76 | | - auto set_n() -> bool |
| 83 | + bool set_n() |
77 | 84 | { |
78 | 85 | my_distribution.param(distribution_param_type()); |
79 | 86 |
|
|
89 | 96 | { |
90 | 97 | const limb_type lo_limb = my_n_trial.crepresentation().front(); |
91 | 98 |
|
92 | | - const std::uint8_t |
93 | | - lo_bit |
94 | | - { |
95 | | - static_cast<std::uint8_t> |
96 | | - ( |
97 | | - static_cast<std::uint8_t>(lo_limb) & std::uint8_t { UINT8_C(1) } |
98 | | - ) |
99 | | - }; |
| 99 | + const std::uint8_t lo_bit = std::uint8_t(std::uint8_t(lo_limb) & 1U); |
100 | 100 |
|
101 | 101 | // Remove all even candidates since they are non-prime. |
102 | | - if(lo_bit != std::uint8_t { UINT8_C(0) }) |
| 102 | + if(lo_bit != 0U) |
103 | 103 | { |
104 | | - const std::uint8_t |
105 | | - lo_digit10 |
106 | | - { |
107 | | - static_cast<std::uint8_t>(my_n_trial % std::uint8_t { UINT8_C(10) }) |
108 | | - }; |
| 104 | + const std::uint8_t lo_digit10 = std::uint8_t(my_n_trial % std::uint8_t(10U)); |
109 | 105 |
|
110 | 106 | // Continue by removing candidates having trailing digit 5. |
111 | 107 | // The result is all candidates have trailing digit 1,3,7,9 |
112 | | - |
113 | | - if(lo_digit10 != std::uint8_t { UINT8_C(5) }) |
| 108 | + if(lo_digit10 != 5U) |
114 | 109 | { |
115 | 110 | // Now remove candidates having digital root 3, 6 or 9 |
116 | 111 | // because these are divisible by 3 and thus non-prime. |
117 | 112 |
|
118 | 113 | // To compute the digital root of n dr(n), use |
119 | 114 | // dr(n) = 1 + (n - 1) % 9. |
120 | | - wide_integer_type n_minus_one { my_n_trial }; |
| 115 | + wide_integer_type n_minus_one(my_n_trial); |
121 | 116 |
|
122 | 117 | --n_minus_one; |
123 | 118 |
|
124 | | - const std::uint8_t |
125 | | - digital_root |
126 | | - { |
127 | | - static_cast<std::uint8_t> |
128 | | - ( |
129 | | - std::uint8_t { UINT8_C(1) } |
130 | | - + static_cast<std::uint8_t>(n_minus_one % std::uint8_t { UINT8_C(9) }) |
131 | | - ) |
132 | | - }; |
133 | | - |
134 | | - const bool |
135 | | - has_digital_root_of_3_6_or_9 |
136 | | - { |
137 | | - (digital_root == std::uint8_t { UINT8_C(3) }) |
138 | | - || (digital_root == std::uint8_t { UINT8_C(6) }) |
139 | | - || (digital_root == std::uint8_t { UINT8_C(9) }) |
140 | | - }; |
141 | | - |
142 | | - if(!has_digital_root_of_3_6_or_9) |
143 | | - { |
144 | | - // We have found a viable prime candidate. Use this prime |
145 | | - // candidate to start a new Miller-Rabin primality test. |
| 119 | + const std::uint8_t dr = |
| 120 | + std::uint8_t(UINT8_C(1) + (std::uint8_t(n_minus_one % std::uint8_t(9U)))); |
146 | 121 |
|
| 122 | + if((dr != UINT8_C(3)) && (dr != UINT8_C(6)) && (dr != UINT8_C(9))) |
| 123 | + { |
147 | 124 | set_n_is_ok = true; |
148 | 125 |
|
149 | | - // Reset the prime-search variables. |
150 | | - |
151 | 126 | my_n_trial_is_probably_prime = false; |
152 | 127 | my_n = my_n_trial; |
153 | 128 | my_n_is_probably_prime = false; |
154 | 129 |
|
155 | | - my_n_total_mul_10 = |
156 | | - static_cast<std::uint64_t> |
157 | | - ( |
158 | | - my_n_total_mul_10 + std::uint_fast8_t { UINT8_C(10) } |
159 | | - ); |
| 130 | + my_n_total_mul_10 += 10U; |
160 | 131 | } |
161 | 132 | } |
162 | 133 | } |
|
165 | 136 | return set_n_is_ok; |
166 | 137 | } |
167 | 138 |
|
168 | | - auto exclude_small_factors_1_0() -> bool { return do_exclude_small_factors_from_ppn({ 3U, 5U, 7U, 11U, 13U, 17U, 19U, 23U }, UINT32_C( 223092870)); } |
169 | | - auto exclude_small_factors_2_0() -> bool { return do_exclude_small_factors_from_ppn({ 29U, 31U, 37U, 41U, 43U, 47U }, UINT32_C(2756205443)); } |
170 | | - auto exclude_small_factors_3_0() -> bool { return do_exclude_small_factors_from_ppn({ 53U, 59U, 61U, 67U, 71U }, UINT32_C( 907383479)); } |
171 | | - auto exclude_small_factors_4_0() -> bool { return do_exclude_small_factors_from_ppn({ 73U, 79U, 83U, 89U, 97U }, UINT32_C(4132280413)); } |
172 | | - auto exclude_small_factors_5_0() -> bool { return do_exclude_small_factors_from_ppn({ 101U, 103U, 107U, 109U }, UINT32_C( 121330189)); } |
173 | | - auto exclude_small_factors_5_1() -> bool { return do_exclude_small_factors_from_ppn({ 113U, 127U, 131U, 137U }, std::uint32_t(113ULL * 127ULL * 131ULL * 137ULL)); } |
174 | | - auto exclude_small_factors_5_2() -> bool { return do_exclude_small_factors_from_ppn({ 139U, 149U, 151U, 157U }, std::uint32_t(139ULL * 149ULL * 151ULL * 157ULL)); } |
175 | | - auto exclude_small_factors_5_3() -> bool { return do_exclude_small_factors_from_ppn({ 163U, 167U, 173U, 179U }, std::uint32_t(163ULL * 167ULL * 173ULL * 179ULL)); } |
176 | | - auto exclude_small_factors_5_4() -> bool { return do_exclude_small_factors_from_ppn({ 181U, 191U, 193U, 197U }, std::uint32_t(181ULL * 191ULL * 193ULL * 197ULL)); } |
177 | | - auto exclude_small_factors_5_5() -> bool { return do_exclude_small_factors_from_ppn({ 199U, 211U, 223U, 227U }, std::uint32_t(199ULL * 211ULL * 223ULL * 227ULL)); } |
178 | | - |
179 | | - auto prepare_random_trials() -> void |
| 139 | + bool exclude_small_factors_1_0() { return do_exclude_small_factors_from_ppn({ 3U, 5U, 7U, 11U, 13U, 17U, 19U, 23U }, UINT32_C( 223092870)); } |
| 140 | + bool exclude_small_factors_2_0() { return do_exclude_small_factors_from_ppn({ 29U, 31U, 37U, 41U, 43U, 47U }, UINT32_C(2756205443)); } |
| 141 | + bool exclude_small_factors_3_0() { return do_exclude_small_factors_from_ppn({ 53U, 59U, 61U, 67U, 71U }, UINT32_C( 907383479)); } |
| 142 | + bool exclude_small_factors_4_0() { return do_exclude_small_factors_from_ppn({ 73U, 79U, 83U, 89U, 97U }, UINT32_C(4132280413)); } |
| 143 | + bool exclude_small_factors_5_0() { return do_exclude_small_factors_from_ppn({ 101U, 103U, 107U, 109U }, UINT32_C( 121330189)); } |
| 144 | + bool exclude_small_factors_5_1() { return do_exclude_small_factors_from_ppn({ 113U, 127U, 131U, 137U }, std::uint32_t(113ULL * 127ULL * 131ULL * 137ULL)); } |
| 145 | + bool exclude_small_factors_5_2() { return do_exclude_small_factors_from_ppn({ 139U, 149U, 151U, 157U }, std::uint32_t(139ULL * 149ULL * 151ULL * 157ULL)); } |
| 146 | + bool exclude_small_factors_5_3() { return do_exclude_small_factors_from_ppn({ 163U, 167U, 173U, 179U }, std::uint32_t(163ULL * 167ULL * 173ULL * 179ULL)); } |
| 147 | + bool exclude_small_factors_5_4() { return do_exclude_small_factors_from_ppn({ 181U, 191U, 193U, 197U }, std::uint32_t(181ULL * 191ULL * 193ULL * 197ULL)); } |
| 148 | + bool exclude_small_factors_5_5() { return do_exclude_small_factors_from_ppn({ 199U, 211U, 223U, 227U }, std::uint32_t(199ULL * 211ULL * 223ULL * 227ULL)); } |
| 149 | + |
| 150 | + void prepare_random_trials() |
180 | 151 | { |
181 | 152 | my_k = lsb(my_n_m1); |
182 | 153 |
|
|
188 | 159 | my_n_trial_is_probably_prime = true; |
189 | 160 | } |
190 | 161 |
|
191 | | - virtual auto execute_one_trial() -> bool |
| 162 | + virtual bool execute_one_trial() |
192 | 163 | { |
193 | 164 | wide_integer_type y = powm(my_distribution(my_generator2), my_q, my_n_trial); |
194 | 165 |
|
|
228 | 199 | private: |
229 | 200 | static std::uint64_t my_n_total_mul_10; |
230 | 201 |
|
231 | | - auto do_exclude_small_factors_from_ppn(std::initializer_list<std::uint8_t> small_factors, const std::uint32_t& ppn) -> bool |
| 202 | + bool do_exclude_small_factors_from_ppn(std::initializer_list<std::uint8_t> small_factors, const std::uint32_t& ppn) |
232 | 203 | { |
233 | 204 | bool exclude_does_terminate_prime_candidate = false; |
234 | 205 |
|
|
0 commit comments