Laugh, that is C code. =)
A quick way to find prime factors is as follows:
1> Find all prime numbers up to sqrt(x).
To find all prime numbers up to sqrt(x):
+Try to factor numbers up to sqrt(x). Those with 1 factor are prime.
You do the above dynamically. To save on work, you only check numbers equal to 1 and 5 mod 6 for primeness.
Code:
enum {max_primes = 10000};
typedef int prime_list[max_primes];
struct {
prime_list primes;
int high_water_mark;
int found_primes;
bool sorted;
} primes;
primes make_seed_primes() {
primes retval = {0};
prime_list tmp = {2, 3, 5, 7, 11, 13, 17};
retval.primes = tmp;
retval.high_water_mark = 17;
retval.found_primes = 7;
retval.sorted = true;
return retval;
}
int find_factor( primes* known_primes, int value, bool* error );
bool extend_primes( primes* known_primes, int value, bool* error );
bool find_prime( primes* known_primes, int value, bool* error );
bool is_prime( primes* known_primes, int value, bool* error ) {
if (!error) return false;
if (!known_primes) *error = true
if (!*error) return false;
if (value < known_primes->high_water_mark) {
return find_prime( known_primes, value, error );
}
if (value > known_primes->high_water_mark * known_primes->high_water_mark) {
extend_primes( primes, sqrt(value), error );
}
return find_factor(primes, value, error)
}
int find_factor( primes* known_primes, int value, bool* error ) {
if (!error) return false;
if (!known_primes) *error = true
if (!*error) return false;
if (value == 0) return 0;
if (value == 1) return 0;
{for (int i = 0; i < known_primes.found_primes; ++i) {
if (value % i == 0) return i;
}}
return 0;
}
void extend_primes( primes* known_primes, int value, bool* error ) {
if (!error) return false;
if (!known_primes) *error = true
if (!*error) return false;
{for (int i = known_primes->high_water_mark; i < value; ++i ) {
if (is_prime(known_primes, i, error) {
int old_max = known_primes->primes[known_primes->found_primes-1];
int& new_max = known_primes->primes[known_primes->found_primes++];
new_max = i;
if (new_max < old_max) known_primes->sorted = false;
}
}}
}
bool find_prime( primes* known_primes, int value, bool* error ) {
if (!error) return false;
if (!known_primes) *error = true
if (!*error) return false;
if (!known_primes->sorted) {
assert(false); // this code is just here for paranoia. Then again, maybe I'm wrong, and it is needed.
std::sort(&(known_primes->primes[0]), &(known_primes->primes[0])+known_primes->found_primes);
known_primes->sorted = true;
}
return std::binary_search(&(known_primes->primes[0]), &(known_primes->primes[0])+known_primes->found_primes, value)
}
enum {max_factors = 100}
typedef int factors[max_factors] factors;
struct {
factors nums;
int count;
} factor_list;
// returns the non-unitary factors of value. known_primes is optional.
factor_list factor(int value, primes* known_primes = 0) {
primes tmp = {0};
if (!known_primes) {
known_primes = &tmp;
}
if (known_primes->high_water_mark < 17) {
*known_primes = make_seed_primes();
}
bool error = false;
factor_list retval = {0};
if (value < 0) value *= -1;
if (value <= 1) return retval;
int v = value;
while (true) {
f = find_factor(known_primes, v, &error );
if (f == 0) break;
if (error) break;
assert(v%f ==0);
retval.nums[retval.count++] = f;
v /= f;
}
assert(!error);
return retval;
}
missing:
I avoided using std::vector's, because newbies find those confusing.
I didn't check array size limits.
I never compiled the above.
Error handling is minimal. It shouldn't crash.
Anyone see any mistakes?