Skip to content

Commit

Permalink
improve interface for factoring to a vector
Browse files Browse the repository at this point in the history
  • Loading branch information
hurchalla committed Apr 19, 2022
1 parent ba19b35 commit 75bcd5e
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 24 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ It may help to see a simple [example](examples/example_without_cmake).
The API consists of five header files in total (all the headers that are not under the *detail* folder). These files are the three general purpose files *factorize.h*, *is_prime.h*, *greatest_common_divisor.h*, and in the resource_intensive_api folder, the two special purpose files *factorize_intensive_uint32.h* and *IsPrimeIntensive.h*. Please view these files for their documentation. A quick summary of the functions is provided below; in all cases T is a template parameter of integral type.

*hurchalla::factorize(T x, int& num_factors)*. Returns a std::array containing the factors of x.
*hurchalla::factorize_to_vector(T x)*. Returns a std::vector containing the factors of x.
*hurchalla::factorize(T x, std::vector& factors)*. Clears a std::vector and fills it with the factors of x.
*hurchalla::greatest_common_divisor(T a, T b)*. Returns the greatest common divisor of a and b.
*hurchalla::is_prime(T x)*. Returns true if x is prime. Otherwise returns false.

Expand Down
4 changes: 1 addition & 3 deletions include/hurchalla/factoring/detail/impl_factorize.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,12 @@ struct impl_factorize {


template <typename T, class PrimalityFunctor>
static std::vector<T> factorize_to_vector(T x,
static void factorize_to_vector(T x, std::vector<T>& vec,
const PrimalityFunctor& is_prime_mf)
{
static_assert(ut_numeric_limits<T>::is_integer, "");
using U = typename extensible_make_unsigned<T>::type;

std::vector<T> vec;
// The max possible vector size needed for factors is when all of them are 2
constexpr int max_num_factors = ut_numeric_limits<T>::digits;
vec.reserve(max_num_factors);
Expand All @@ -147,7 +146,6 @@ struct impl_factorize {
std::back_inserter(fva), static_cast<U>(x), is_prime_mf);
HPBC_POSTCONDITION(vec.size() > 0);
HPBC_POSTCONDITION(vec.size() <= max_num_factors);
return vec;
}

}; // end struct impl_factorize
Expand Down
28 changes: 14 additions & 14 deletions include/hurchalla/factoring/factorize.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,33 +81,33 @@ factorize(T x, int& num_factors)
}


// This version of factorize returns a std::vector (rather than a std::array).
// It may be preferable if you wish to save stack space, since vector is heap
// allocated. Note that if you used factorize(), the returned std::array for
// type T of uint32_t would take 128 bytes on the stack, uint64_t would take 512
// bytes, and __uint128_t would take 2kb.
// This version of factorize takes a std::vector, which it clears of any
// existing elements and then fills with the factors of x. When this function
// returns, the size of the vector is the number of factors.
// Note that this version might be preferable to the array version of factorize
// if you wish to save stack space; vector is heap allocated but the array
// version needs memory on the stack for its returned array (for example with
// type T of uint64_t, the array needs 512 bytes on stack).
//
// Returns a vector that contains all factors of x. The size of the vector is
// the number of factors.
// T can be any integral type <= 128 bits.
template <typename T>
std::vector<T> factorize_to_vector(T x)
void factorize(T x, std::vector<T>& factors)
{
static_assert(ut_numeric_limits<T>::is_integer, "");
static_assert(ut_numeric_limits<T>::digits <= 128, "");
HPBC_PRECONDITION(x >= 2); // 0 and 1 do not have prime factorizations
factors.clear();

namespace hd = ::hurchalla::detail;
std::vector<T> vec = hd::impl_factorize::factorize_to_vector(
x, hd::PollardRhoIsPrime());
HPBC_POSTCONDITION(vec.size() > 0);
hd::impl_factorize::factorize_to_vector(
x, factors, hd::PollardRhoIsPrime());
HPBC_POSTCONDITION(factors.size() > 0);
// The max possible vector size needed for factors is when all of them are 2
constexpr int max_num_factors = ut_numeric_limits<T>::digits;
HPBC_POSTCONDITION(vec.size() <= max_num_factors);
HPBC_POSTCONDITION(factors.size() <= max_num_factors);
// all the factors multiplied together should == x
HPBC_POSTCONDITION(x == std::accumulate(vec.begin(), vec.end(),
HPBC_POSTCONDITION(x == std::accumulate(factors.begin(), factors.end(),
static_cast<T>(1), std::multiplies<T>()));
return vec;
}


Expand Down
10 changes: 4 additions & 6 deletions test/test_factorize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,14 @@ using namespace hurchalla;

TEST(HurchallaFactoringFactorize, exhaustive_uint16_t) {
using T = std::uint16_t;
std::vector<T> factors;
for (T x = ut_numeric_limits<T>::max(); x >= 2; --x) {
std::vector<T> answer = factorize_bruteforce(x);
std::sort(answer.begin(), answer.end());
int num_factors;
auto arr = factorize(x, num_factors);
std::sort(arr.begin(), arr.begin()+num_factors);
factorize(x, factors);
std::sort(factors.begin(), factors.end());
SCOPED_TRACE(testing::Message() << "x == " << x);
EXPECT_TRUE(num_factors == static_cast<int>(answer.size()));
EXPECT_TRUE(std::equal(arr.begin(), arr.begin()+num_factors,
answer.begin()));
EXPECT_TRUE(factors == answer);
}
}

Expand Down

0 comments on commit 75bcd5e

Please sign in to comment.