Skip to content

Commit

Permalink
Add FactorByTable32. Change FactorizeStage2 to not store a reference …
Browse files Browse the repository at this point in the history
…to the primality functor. Improve gcd.
  • Loading branch information
hurchalla committed Jun 12, 2024
1 parent e57ab55 commit eed8738
Show file tree
Hide file tree
Showing 12 changed files with 1,139 additions and 57 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ target_sources(hurchalla_factoring INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/factorize.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/greatest_common_divisor.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/is_prime.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/resource_intensive_api/FactorByTable32.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/resource_intensive_api/factorize_intensive_uint32.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/resource_intensive_api/IsPrimeIntensive.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/detail/DualMontgomeryForm.h>
Expand All @@ -80,6 +81,7 @@ target_sources(hurchalla_factoring INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/detail/impl_factorize.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/detail/impl_greatest_common_divisor.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/detail/impl_is_prime.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/detail/ImplFactorByTable32.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/detail/ImplIsPrimeIntensive.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/detail/is_prime_bruteforce.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/factoring/detail/is_prime_miller_rabin.h>
Expand Down
58 changes: 23 additions & 35 deletions include/hurchalla/factoring/detail/FactorizeStage2.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,51 +49,38 @@ namespace hurchalla { namespace detail {
// all factors get written to the output iterator.


template <int EcmMinBits, int MaxBitsX, class T, class PrimalityFunctor>
template <int EcmMinBits, int MaxBitsX, class T>
class FactorizeStage2 {
const PrimalityFunctor& is_prime_func;
const T always_prime_limit;
bool expect_arbitrary_size_factors;
T base_c; // for Pollard-Rho
T expected_iterations; // for Pollard-Rho
std::uint64_t loc_lcg; // for ECM

// The current client code for this class doesn't need this class to provide
// copy construction/assignment. We delete the copy constructor/assignment
// functions so that future callers will not accidentally cause
// 'is_prime_func' to become an invalid reference (which would happen if the
// referred object's lifetime ended after the copy was made, but the copy
// was kept alive).
// If needed, this class could be changed so that 'is_prime_func' is not a
// class member, but is instead passed by reference to all of this class's
// member functions. Copy construction/assignment would become safe.
FactorizeStage2& operator=(const FactorizeStage2&) = delete;
FactorizeStage2(const FactorizeStage2&) = delete;

public:
static_assert(ut_numeric_limits<T>::is_integer);
static_assert(!ut_numeric_limits<T>::is_signed);

FactorizeStage2(const PrimalityFunctor& isprime_func, T alwaysprime_limit,
bool expect_arbitrarysize_factors)
: is_prime_func(isprime_func), always_prime_limit(alwaysprime_limit),
FactorizeStage2(T alwaysprime_limit, bool expect_arbitrarysize_factors)
: always_prime_limit(alwaysprime_limit),
expect_arbitrary_size_factors(expect_arbitrarysize_factors),
base_c(1), expected_iterations(0), loc_lcg(0)
{
}

template <class OutputIt>
OutputIt operator()(OutputIt iter, T x)
template <class OutputIt, class PrimalityFunctor>
OutputIt operator()(OutputIt iter, const PrimalityFunctor& is_prime_func,
T x)
{
base_c = 1;
expected_iterations = 0;
return dispatch(iter, x);
return dispatch(iter, is_prime_func, x);
}


private:
template <class OutputIt>
OutputIt dispatch(OutputIt iter, T x)
template <class OutputIt, class PrimalityFunctor>
OutputIt dispatch(OutputIt iter, const PrimalityFunctor& is_prime_func, T x)
{
HPBC_PRECONDITION2(x >= 2); // 0 and 1 do not have prime factorizations
HPBC_PRECONDITION2(x % 2 == 1); // x odd is required for montgomery form
Expand All @@ -108,7 +95,7 @@ class FactorizeStage2 {
T, S>::type;
#if defined(HURCHALLA_FACTORIZE_NEVER_USE_MONTGOMERY_MATH)
using MF = MontgomeryStandardMathWrapper<U>;
return factorize2<MF>(iter, x);
return factorize2<MF>(iter, is_prime_func, x);
#else
static_assert(ut_numeric_limits<U>::digits >= 2);
constexpr U Udiv4 = static_cast<U>(static_cast<U>(1) <<
Expand All @@ -117,10 +104,10 @@ class FactorizeStage2 {
(ut_numeric_limits<U>::digits - 1));
if (x < Udiv4) {
using MF = MontgomeryQuarter<U>;
return factorize2<MF>(iter, x);
return factorize2<MF>(iter, is_prime_func, x);
} else if (x < Udiv2) {
using MF = MontgomeryHalf<U>;
return factorize2<MF>(iter, x);
return factorize2<MF>(iter, is_prime_func, x);
} else {
constexpr bool limited_to_halfrange =
(MaxBitsX == ut_numeric_limits<T>::digits - 1);
Expand All @@ -138,7 +125,7 @@ class FactorizeStage2 {
return iter;
} else {
using MF = MontgomeryForm<U>;
return factorize2<MF>(iter, x);
return factorize2<MF>(iter, is_prime_func, x);
}
}
#endif
Expand All @@ -150,17 +137,17 @@ class FactorizeStage2 {
if constexpr (ut_numeric_limits<T>::digits > HURCHALLA_TARGET_BIT_WIDTH) {
#if defined(HURCHALLA_FACTORIZE_NEVER_USE_MONTGOMERY_MATH)
using MF = MontgomeryStandardMathWrapper<T>;
return factorize2<MF>(iter, x);
return factorize2<MF>(iter, is_prime_func, x);
#else
static_assert(ut_numeric_limits<T>::digits >= 2);
T Rdiv4 = static_cast<T>(
static_cast<T>(1) << (ut_numeric_limits<T>::digits - 2));
if (x < Rdiv4) {
using MF = MontgomeryQuarter<T>;
return factorize2<MF>(iter, x);
return factorize2<MF>(iter, is_prime_func, x);
} else {
using MF = MontgomeryForm<T>;
return factorize2<MF>(iter, x);
return factorize2<MF>(iter, is_prime_func, x);
}
#endif
} else {
Expand All @@ -177,8 +164,9 @@ class FactorizeStage2 {



template <class MF, class OutputIt>
OutputIt factorize2(OutputIt iter, T x)
template <class MF, class OutputIt, class PrimalityFunctor>
OutputIt factorize2(OutputIt iter,
const PrimalityFunctor& is_prime_func, T x)
{
using U = typename MF::IntegerType;
using P = typename safely_promote_unsigned<T>::type;
Expand Down Expand Up @@ -212,12 +200,12 @@ class FactorizeStage2 {
expect_arbitrary_size_factors, loc_lcg);
if (tmp_factor >= 2) { // we found a factor
// Try to factor the factor (fyi, it is usually prime)
iter = dispatch(iter, tmp_factor);
iter = dispatch(iter, is_prime_func, tmp_factor);
// Next try to factor the quotient.
// since 1 < tmp_factor < x,
// we know 1 < (x/tmp_factor) < x
T quotient = static_cast<T>(x/tmp_factor);
iter = dispatch(iter, quotient);
iter = dispatch(iter, is_prime_func, quotient);
return iter;
}
}
Expand Down Expand Up @@ -252,11 +240,11 @@ class FactorizeStage2 {
// efficiency that it didn't, but any T value would be valid.
base_c = static_cast<T>(base_c + static_cast<P>(i) + 1);
// Try to factor the factor (fyi, it is usually prime)
iter = dispatch(iter, tmp_factor);
iter = dispatch(iter, is_prime_func, tmp_factor);
// Next try to factor the quotient.
// since 1 < tmp_factor < x, we know 1 < (x/tmp_factor) < x
T quotient = static_cast<T>(x/tmp_factor);
iter = dispatch(iter, quotient);
iter = dispatch(iter, is_prime_func, quotient);
return iter;
}
else {
Expand Down
Loading

0 comments on commit eed8738

Please sign in to comment.