// **Test `test`**. static char * test() { mpz_array in1, in2, out, array_expect; mpz_t b; mpz_pool pool; pool_init(&pool, 0); array_init(&in1, 2); array_init(&in2, 2); array_init(&out, 5); array_init(&array_expect, 5); mpz_init_set_str(b, "317", 10); array_add(&array_expect, b); mpz_set_str(b, "577", 10); array_add(&array_expect, b); mpz_set_str(b, "727", 10); array_add(&array_expect, b); mpz_set_str(b, "196463", 10); array_add(&array_expect, b); mpz_set_str(b, "346063", 10); array_add(&array_expect, b); // primes: 401, [577], 727, 863 // `a = 727 * 577 = 419479` // `b = 401 * 863 = 346063` mpz_set_str(b, "419479", 10); array_add(&in1, b); mpz_set_str(b, "346063", 10); array_add(&in1, b); // primes: 317, 223, [577], 881 // `a = 317 * 577 = 182909` // `b = 223 * 881 = 196463` mpz_set_str(b, "182909", 10); array_add(&in2, b); mpz_set_str(b, "196463", 10); array_add(&in2, b); cbmerge(&pool, &out, &in1, &in2); array_msort(&out); if (!array_equal(&array_expect, &out)) { return "out and array_expect differ!"; } array_clear(&in1); array_clear(&in2); array_clear(&out); array_clear(&array_expect); mpz_clear(b); pool_clear(&pool); return 0; }
// This algorithm computes the natural coprime base for any finite subset of a free coid. // It uses `cbmerge` to merge coprime bases for halves of the set. // // Algorithm 18.1 [PDF page 24](http://cr.yp.to/lineartime/dcba-20040404.pdf) // // See [cb test](test-cb.html) for basic usage. void cb(mpz_array *ret, mpz_t *s, size_t from, size_t to) { size_t n = to - from; mpz_array p, q; // If #S = 1: Find a ∈ S. Print a if a != 1. Stop. if (n == 0) { if (mpz_cmp_ui(s[from], 0) == 0) { fprintf(stderr, "warning adding 0 in cb\n"); } else { if (mpz_cmp_ui(s[from], 1) != 0) { array_add(ret, s[from]); } } return; } // ## OpenMP multithreading // Execute both recrusive `cb` calls in parallel. // // `export OMP_NUM_THREADS=4` to set the maximal thread number. array_init(&p, n); array_init(&q, n); #if USE_OPENMP #pragma omp parallel sections { #pragma omp section { cb(&p, s, from, to - n/2 - 1); } #pragma omp section { cb(&q, s, to - n/2, to); } } #else cb(&p, s, from, to - n/2 - 1); cb(&q, s, to - n/2, to); #endif // Print cbmerge(P∪Q) if (q.used && p.used) { cbmerge(ret, &p, &q); } else if(!q.used && p.used) { array_copy(ret, &p); fprintf(stderr, "warning: q is empty in cb\n"); } else if(q.used && !p.used) { array_copy(ret, &q); fprintf(stderr, "warning: p is empty in cb\n"); } else { fprintf(stderr, "warning: p an q are empty in cb\n"); } // Free the memory. array_clear(&p); array_clear(&q); }