| ... | @@ -175,17 +175,78 @@ fn partition(a: usize, b: usize, pivot: *usize, context: anytype) bool { | ... | @@ -175,17 +175,78 @@ fn partition(a: usize, b: usize, pivot: *usize, context: anytype) bool { |
| 175 | i += 1; | 175 | i += 1; |
| 176 | j -= 1; | 176 | j -= 1; |
| 177 | | 177 | |
| 178 | while (true) { | 178 | const block_size = 64; |
| 179 | while (i <= j and context.lessThan(i, a)) i += 1; | 179 | var offsets_l: [block_size]u8 align(std.atomic.cache_line) = undefined; |
| 180 | while (i <= j and !context.lessThan(j, a)) j -= 1; | 180 | var offsets_r: [block_size]u8 align(std.atomic.cache_line) = undefined; |
| 181 | if (i > j) break; | 181 | |
| | 182 | var offsets_l_base = i; |
| | 183 | var offsets_r_base = j; |
| | 184 | var num_l: usize = 0; |
| | 185 | var num_r: usize = 0; |
| | 186 | var start_l: usize = 0; |
| | 187 | var start_r: usize = 0; |
| | 188 | |
| | 189 | while (i <= j) { |
| | 190 | const num_unknown = j + 1 - i; |
| | 191 | const left_split = if (num_l == 0) |
| | 192 | @min(block_size, if (num_r == 0) num_unknown / 2 else num_unknown) |
| | 193 | else |
| | 194 | 0; |
| | 195 | const right_split = if (num_r == 0) |
| | 196 | @min(block_size, num_unknown - left_split) |
| | 197 | else |
| | 198 | 0; |
| | 199 | |
| | 200 | for (0..left_split) |k| { |
| | 201 | offsets_l[num_l] = @intCast(k); |
| | 202 | num_l += @intFromBool(!context.lessThan(i + k, a)); |
| | 203 | } |
| | 204 | i += left_split; |
| 182 | | 205 | |
| 183 | context.swap(i, j); | 206 | for (0..right_split) |k| { |
| 184 | i += 1; | 207 | offsets_r[num_r] = @intCast(k); |
| 185 | j -= 1; | 208 | num_r += @intFromBool(context.lessThan(j - k, a)); |
| | 209 | } |
| | 210 | j -= right_split; |
| | 211 | |
| | 212 | const num = @min(num_l, num_r); |
| | 213 | for (0..num) |m| { |
| | 214 | context.swap( |
| | 215 | offsets_l_base + offsets_l[start_l + m], |
| | 216 | offsets_r_base - offsets_r[start_r + m], |
| | 217 | ); |
| | 218 | } |
| | 219 | num_l -= num; |
| | 220 | num_r -= num; |
| | 221 | start_l += num; |
| | 222 | start_r += num; |
| | 223 | |
| | 224 | if (num_l == 0) { |
| | 225 | start_l = 0; |
| | 226 | offsets_l_base = i; |
| | 227 | } |
| | 228 | if (num_r == 0) { |
| | 229 | start_r = 0; |
| | 230 | offsets_r_base = j; |
| | 231 | } |
| 186 | } | 232 | } |
| 187 | | 233 | |
| 188 | // TODO: Enable the BlockQuicksort optimization | 234 | if (num_l > 0) { |
| | 235 | while (num_l > 0) { |
| | 236 | num_l -= 1; |
| | 237 | context.swap(offsets_l_base + offsets_l[start_l + num_l], j); |
| | 238 | j -= 1; |
| | 239 | } |
| | 240 | i = j + 1; |
| | 241 | } |
| | 242 | if (num_r > 0) { |
| | 243 | while (num_r > 0) { |
| | 244 | num_r -= 1; |
| | 245 | context.swap(offsets_r_base - offsets_r[start_r + num_r], i); |
| | 246 | i += 1; |
| | 247 | } |
| | 248 | j = i - 1; |
| | 249 | } |
| 189 | | 250 | |
| 190 | context.swap(j, a); | 251 | context.swap(j, a); |
| 191 | pivot.* = j; | 252 | pivot.* = j; |