View Single Post
Old 02-23-2005, 09:46 PM   #5 (permalink)
Yakk
Wehret Den Anfängen!
 
Location: Ontario, Canada
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?
__________________
Last edited by JHVH : 10-29-4004 BC at 09:00 PM. Reason: Time for a rest.
Yakk is offline  
 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62