From a2ef183d91f7391b16eab628687e7755fd7530b7 Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Thu, 12 Dec 2024 13:22:09 +0100 Subject: [PATCH 1/3] Simplify and strengthen Miller-Rabin test --- math/wide_integer/uintwide_t.h | 44 ++++++++++++++++++++++++++-------- wide_integer_vs2022.vcxproj | 4 ++-- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index 1eef37d..4dc672d 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -7133,6 +7133,19 @@ const auto nm1 = static_cast(np - static_cast(UINT8_C(1))); + auto + isone + { + [](const local_wide_integer_type& t1) + { + return + ( + (static_cast(t1) == local_limb_type { UINT8_C(1) }) + && (t1 == unsigned { UINT8_C(1) }) + ); + } + }; + // Since we have already excluded all small factors // up to and including 227, n is greater than 227. @@ -7140,11 +7153,9 @@ // Perform a single Fermat test which will // exclude many non-prime candidates. - const local_wide_integer_type fn = powm(local_wide_integer_type(static_cast(228U)), nm1, np); + const local_wide_integer_type fn { powm(local_wide_integer_type(static_cast(228U)), nm1, np) }; - const auto fn0 = static_cast(fn); - - if((fn0 != static_cast(UINT8_C(1))) && (fn != 1U)) + if(!isone(fn)) { return false; } @@ -7158,8 +7169,8 @@ const local_param_type params(local_wide_integer_type(2U), np - 2U); - local_wide_integer_type x { }; - local_wide_integer_type y { }; + local_wide_integer_type x; + local_wide_integer_type y; // Assume the test will pass, even though it usually does not pass. bool result { true }; @@ -7171,16 +7182,20 @@ x = distribution(generator, params); y = powm(x, q, np); + using local_double_width_type = typename local_wide_integer_type::double_width_type; + + const local_double_width_type np_dbl { np }; + std::size_t jdx { 0U }; // Continue while y is not nm1, and while y is not 1, // and while the result is true. - while((y != nm1) && (y != 1U) && result) // NOLINT(altera-id-dependent-backward-branch) + while((y != nm1) && (!isone(y)) && result) // NOLINT(altera-id-dependent-backward-branch) { ++jdx; - if (std::size_t { jdx } == k) + if(std::size_t { jdx } == k) { // Mark failure if max iterations reached. result = false; @@ -7188,12 +7203,21 @@ else { // Continue with the next value of y. - y = powm(y, 2, np); + + // Manually calculate: + // y = powm(y, 2, np); + + local_double_width_type yd { y }; + + yd *= yd; + yd %= np_dbl; + + y = local_wide_integer_type { yd }; } } // Check for (y == 1) after the loop. - if((y == 1U) && (jdx != std::size_t { 0U })) + if(isone(y) && (jdx != std::size_t { 0U })) { // Mark failure if (y == 1) and (jdx != 0). result = false; diff --git a/wide_integer_vs2022.vcxproj b/wide_integer_vs2022.vcxproj index 9dbb0d3..1f605e0 100644 --- a/wide_integer_vs2022.vcxproj +++ b/wide_integer_vs2022.vcxproj @@ -77,7 +77,7 @@ true - $(ProjectDir);C:\boost\boost_1_85_0;$(IncludePath) + $(ProjectDir);C:\boost\boost_1_86_0;$(IncludePath) false @@ -85,7 +85,7 @@ false - $(ProjectDir);C:\boost\boost_1_85_0;$(IncludePath) + $(ProjectDir);C:\boost\boost_1_86_0;$(IncludePath) From 16458c621da2d6e784d231af71b26b0351a90162 Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Thu, 12 Dec 2024 14:15:13 +0100 Subject: [PATCH 2/3] Update syntax --- math/wide_integer/uintwide_t.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index 4dc672d..79a7d28 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -7161,13 +7161,18 @@ } } - const unsigned_fast_type k { lsb(nm1) }; + const unsigned k { static_cast(lsb(nm1)) }; const local_wide_integer_type q { nm1 >> k }; using local_param_type = typename DistributionType::param_type; - const local_param_type params(local_wide_integer_type(2U), np - 2U); + const local_param_type + params + { + local_wide_integer_type { unsigned { UINT8_C(2) } }, + np - unsigned { UINT8_C(2) } + }; local_wide_integer_type x; local_wide_integer_type y; @@ -7177,7 +7182,7 @@ // Loop over the trials to perform the primality testing. - for(std::size_t idx { 0U }; ((idx < number_of_trials) && result); ++idx) // NOLINT(altera-id-dependent-backward-branch) + for(std::size_t idx { UINT8_C(0) }; ((idx < number_of_trials) && result); ++idx) // NOLINT(altera-id-dependent-backward-branch) { x = distribution(generator, params); y = powm(x, q, np); @@ -7186,7 +7191,7 @@ const local_double_width_type np_dbl { np }; - std::size_t jdx { 0U }; + std::size_t jdx { UINT8_C(0) }; // Continue while y is not nm1, and while y is not 1, // and while the result is true. @@ -7195,7 +7200,7 @@ { ++jdx; - if(std::size_t { jdx } == k) + if(jdx == static_cast(k)) { // Mark failure if max iterations reached. result = false; @@ -7217,7 +7222,7 @@ } // Check for (y == 1) after the loop. - if(isone(y) && (jdx != std::size_t { 0U })) + if(isone(y) && (jdx != std::size_t { UINT8_C(0) })) { // Mark failure if (y == 1) and (jdx != 0). result = false; From 0cabd6d849f085930dcf55efd8519fc07f9ca6c9 Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Thu, 12 Dec 2024 15:27:10 +0100 Subject: [PATCH 3/3] Do a further logic simplification --- math/wide_integer/uintwide_t.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index 79a7d28..7bbeb89 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -7182,7 +7182,9 @@ // Loop over the trials to perform the primality testing. - for(std::size_t idx { UINT8_C(0) }; ((idx < number_of_trials) && result); ++idx) // NOLINT(altera-id-dependent-backward-branch) + std::size_t idx { UINT8_C(0) }; + + do { x = distribution(generator, params); y = powm(x, q, np); @@ -7227,7 +7229,10 @@ // Mark failure if (y == 1) and (jdx != 0). result = false; } + + ++idx; } + while((idx < number_of_trials) && result); return result; }