short_pair* simpleSuffixSort(const usint* sequence, uint n, uint threads) { if(sequence == 0 || n == 0) { return 0; } skew_pair* pairs = (skew_pair*)new short_pair[n * sizeof(skew_pair) / sizeof(short_pair) + 1]; uint* keys = new uint[n]; // In text order. std::vector<ss_range> unsorted; threads = std::max(threads, (uint)1); #ifdef MULTITHREAD_SUPPORT omp_set_num_threads(threads); #endif // Initialize pairs. #pragma omp parallel for schedule(static) for(uint i = 0; i < n; i++) { pairs[i].first = i; pairs[i].second = sequence[i]; } // Sort according to first character. parallelSort(pairs, pairs + n, skew_comparator); unsorted.push_back(ss_range(0, n - 1)); uint total = setRanks(pairs, keys, n, unsorted, threads, 1); if(sizeof(usint) < 2 * sizeof(uint)) { return prefixDoubling(packPairs(pairs, n), keys, unsorted, n, threads, total, 1); } else { return prefixTripling(pairs, keys, unsorted, n, threads, total, 1); } }
short_pair* prefixDoubling(short_pair* pairs, uint* keys, std::vector<ss_range>& unsorted, uint n, uint threads, uint total, uint h) { // Double prefix length until sorted. while(total > 0) { uint chunk = std::max((size_t)1, unsorted.size() / (threads * threads)); #pragma omp parallel for schedule(dynamic, chunk) for(uint i = 0; i < unsorted.size(); i++) { // Set sort keys for the current range. short_pair* limit = pairs + unsorted[i].second; for(short_pair* curr = pairs + unsorted[i].first; curr <= limit; ++curr) { curr->second = keys[curr->first + h]; } sequentialSort(pairs + unsorted[i].first, pairs + unsorted[i].second + 1, key_comparator); } total = setRanks(pairs, keys, n, unsorted, threads, chunk); h *= 2; // std::cout << "Sorted with h = " << h << ", unsorted total = " << total << " (" << unsorted.size() << " ranges)" << std::endl; } #pragma omp parallel for schedule(static) for(uint i = 0; i < n; i++) { pairs[i].second = keys[i]; } delete[] keys; keys = 0; return pairs; }
short_pair* prefixTripling(skew_pair* pairs, uint* keys, std::vector<ss_range>& unsorted, uint n, uint threads, uint total, uint h) { const usint PACK_FACTOR = sizeof(usint) * CHAR_BIT / 2; // Triple prefix length until sorted. while(total > 0) { uint chunk = std::max((size_t)1, unsorted.size() / (threads * threads)); #pragma omp parallel for schedule(dynamic, chunk) for(uint i = 0; i < unsorted.size(); i++) { // Set sort keys for the current range. skew_pair* limit = pairs + unsorted[i].second; for(skew_pair* curr = pairs + unsorted[i].first; curr <= limit; ++curr) { curr->second = (usint)(keys[curr->first + h]) << PACK_FACTOR; if(n - h > curr->first + h) { curr->second += keys[curr->first + 2 * h]; } } sequentialSort(pairs + unsorted[i].first, pairs + unsorted[i].second + 1, skew_comparator); } total = setRanks(pairs, keys, n, unsorted, threads, chunk); h *= 3; // std::cout << "Sorted with h = " << h << ", unsorted total = " << total << " (" << unsorted.size() << " ranges)" << std::endl; } #pragma omp parallel for schedule(static) for(uint i = 0; i < n; i++) { pairs[i].second = keys[i]; } delete[] keys; keys = 0; return packPairs(pairs, n); }
uint initialSort(short_pair* pairs, uint* keys, std::vector<ss_range>& unsorted, uint n, uint threads, uint h) { // Sort according to first h characters. std::cout << "initialSort(short_pair* pairs, uint* keys, std::vector<ss_range>& unsorted, uint n, uint threads, uint h)" << std::endl; parallelSort(pairs, pairs + n, key_comparator); unsorted.push_back(ss_range(0, n - 1)); uint total = setRanks(pairs, keys, n, unsorted, threads, 1); // std::cout << "Sorted with h = " << h << ", unsorted total = " << total << " (" << unsorted.size() << " ranges)" << std::endl; std::cout << "done initialSort(short_pair* pairs, uint* keys, std::vector<ss_range>& unsorted, uint n, uint threads, uint h) -- Sorted with h = " << h << ", unsorted total = " << total << " (" << unsorted.size() << " ranges)" << std::endl; return total; }
/* dot1_rank: * asp != NULL => g is root */ static void dot1_rank(graph_t * g, aspect_t* asp) { point p; #ifdef ALLOW_LEVELS attrsym_t* N_level; #endif edgelabel_ranks(g); if (asp) { init_UF_size(g); initEdgeTypes(g); } collapse_sets(g,g); /*collapse_leaves(g); */ class1(g); p = minmax_edges(g); decompose(g, 0); if (asp && ((GD_comp(g).size > 1)||(GD_n_cluster(g) > 0))) { asp->badGraph = 1; asp = NULL; } acyclic(g); if (minmax_edges2(g, p)) decompose(g, 0); #ifdef ALLOW_LEVELS if ((N_level = agattr(g,AGNODE,"level",NULL))) setRanks(g, N_level); else #endif if (asp) rank3(g, asp); else rank1(g); expand_ranksets(g, asp); cleanup1(g); }