annotate foosdk/sdk/foobar2000/SDK/foosort.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #include "foobar2000-sdk-pch.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2 #include "foosort.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include "threadPool.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 #include "genrand.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 #define FOOSORT_PROFILING 0
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 namespace {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 #if FOOSORT_PROFILING
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 typedef pfc::hires_timer foosort_timer;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 class foosort {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 foosort(pfc::sort_callback & cb, abort_callback & a) : m_abort(a), p_callback(cb) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 foosort fork() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 foosort ret ( * this );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 ret.genrand = genrand_service::g_create();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 size_t myrand(size_t cnt) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 PFC_ASSERT(cnt == (uint32_t)cnt);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 return genrand->genrand((uint32_t)cnt);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 void squaresort(t_size const p_base, t_size const p_count) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 const t_size max = p_base + p_count;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 for (t_size walk = p_base + 1; walk < max; ++walk) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 for (t_size prev = p_base; prev < walk; ++prev) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 p_callback.swap_check(prev, walk);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 void _sort_2elem_helper(t_size & p_elem1, t_size & p_elem2) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 if (p_callback.compare(p_elem1, p_elem2) > 0) pfc::swap_t(p_elem1, p_elem2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 t_size _pivot_helper(t_size const p_base, t_size const p_count) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 PFC_ASSERT(p_count > 2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 //t_size val1 = p_base, val2 = p_base + (p_count / 2), val3 = p_base + (p_count - 1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 t_size val1 = myrand(p_count), val2 = myrand(p_count - 1), val3 = myrand(p_count - 2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 if (val2 >= val1) val2++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 if (val3 >= val1) val3++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 if (val3 >= val2) val3++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 val1 += p_base; val2 += p_base; val3 += p_base;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 _sort_2elem_helper(val1, val2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 _sort_2elem_helper(val1, val3);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 _sort_2elem_helper(val2, val3);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 return val2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 void newsort(t_size const p_base, t_size const p_count, size_t concurrency) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 if (p_count <= 4) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 squaresort(p_base, p_count);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 this->m_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 #if FOOSORT_PROFILING
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 foosort_timer t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 if ( concurrency > 1 ) t.start();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 t_size pivot = _pivot_helper(p_base, p_count);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 const t_size target = p_base + p_count - 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 if (pivot != target) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 p_callback.swap(pivot, target); pivot = target;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 t_size partition = p_base;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 bool asdf = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 for (t_size walk = p_base; walk < pivot; ++walk) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 const int comp = p_callback.compare(walk, pivot);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 bool trigger = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 if (comp == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 trigger = asdf;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 asdf = !asdf;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 } else if (comp < 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 trigger = true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 if (trigger) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 if (partition != walk) p_callback.swap(partition, walk);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 partition++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 if (pivot != partition) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 p_callback.swap(pivot, partition); pivot = partition;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 const auto base1 = p_base, count1 = pivot - p_base;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 const auto base2 = pivot + 1, count2 = p_count - (pivot + 1 - p_base);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 if (concurrency > 1) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 size_t total = count1 + count2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 size_t con1 = (size_t)((uint64_t)count1 * (uint64_t)concurrency / (uint64_t)total);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 if (con1 < 1) con1 = 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 if (con1 > concurrency - 1) con1 = concurrency - 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 size_t con2 = concurrency - con1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 #if FOOSORT_PROFILING
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 FB2K_console_formatter() << "foosort pass: " << p_base << "+" << p_count << "(" << concurrency << ") took " << t.queryString();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 FB2K_console_formatter() << "foosort forking: " << base1 << "+" << count1 << "(" << con1 << ") + " << base2 << "+" << count2 << "(" << con2 << ")";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 pfc::counter cnt;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 fb2k::cpuThreadPool::runMultiHelper([&] {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 switch (cnt++) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 case 0:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 { foosort subsort = fork(); subsort.newsort(base1, count1, con1); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 case 1:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 newsort(base2, count2, con2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 } catch (exception_aborted const &) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 }, 2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 m_abort.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 newsort(base1, count1, 1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 newsort(base2, count2, 1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 abort_callback & m_abort;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 pfc::sort_callback & p_callback;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 genrand_service::ptr genrand = genrand_service::g_create();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 namespace fb2k {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 void sort(pfc::sort_callback & cb, size_t count, size_t concurrency, abort_callback & aborter) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 #ifdef FOOSORT_LIMIT_THREADS
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 if (concurrency > FOOSORT_LIMIT_THREADS) concurrency = FOOSORT_LIMIT_THREADS;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 #if FOOSORT_PROFILING
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 foosort_timer t; t.start();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156 foosort theFooSort(cb, aborter);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 theFooSort.newsort(0, count, concurrency);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 #if FOOSORT_PROFILING
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 FB2K_console_formatter() << "foosort took: " << t.queryString();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 }