Skip to content
v1.0.0-zig0.15.2

Sort API Reference

Parallel PDQSort (Pattern-Defeating Quicksort).

// Via api.zig
blitz.sort(...)
blitz.sortAsc(...)
blitz.sortDesc(...)
blitz.sortByKey(...)
blitz.sortByCachedKey(...)

In-place parallel sort with custom comparator.

var data = [_]i64{ 5, 2, 8, 1, 9 };
blitz.sort(i64, &data, struct {
fn lt(a: i64, b: i64) bool { return a < b; }
}.lt);
// data is now [1, 2, 5, 8, 9]

Sort in ascending order using natural < comparison.

var data = [_]i64{ 5, 2, 8, 1, 9 };
blitz.sortAsc(i64, &data);
// data is now [1, 2, 5, 8, 9]

Sort in descending order.

var data = [_]i64{ 5, 2, 8, 1, 9 };
blitz.sortDesc(i64, &data);
// data is now [9, 8, 5, 2, 1]

Sort using a key extraction function. Key is computed for each comparison.

const Person = struct { name: []const u8, age: u32 };
var people: []Person = ...;
// Sort by age
blitz.sortByKey(Person, u32, people, struct {
fn key(p: Person) u32 { return p.age; }
}.key);

sortByCachedKey(T, K, allocator, slice, keyFn) !void

Section titled “sortByCachedKey(T, K, allocator, slice, keyFn) !void”

Two-phase sort: compute keys in parallel, then sort by cached keys.

When to use:

  • Key function is expensive (>100ns per call)
  • Large arrays (>10K elements)
  • Key computation parallelizes well
try blitz.sortByCachedKey(Person, u32, allocator, people, struct {
fn expensiveKey(p: Person) u32 {
return computeComplexScore(p); // Expensive!
}
}.expensiveKey);

Comparators must define a strict weak ordering:

// Valid comparator
fn lessThan(a: T, b: T) bool {
return a < b; // Strict: a < a is false
}
// Invalid (not strict)
fn badLessThan(a: T, b: T) bool {
return a <= b; // Wrong: a <= a is true
}

Properties:

  1. Irreflexive: lessThan(a, a) is false
  2. Asymmetric: if lessThan(a, b) then !lessThan(b, a)
  3. Transitive: if lessThan(a, b) and lessThan(b, c) then lessThan(a, c)

Array SizeExpected Performance
< 24Insertion sort (immediate)
24 - 8192Sequential PDQSort
> 8192Parallel PDQSort

Benchmark (10M random i64):

std.mem.sort: 4,644 ms
Blitz PDQSort: 430 ms (10.8x faster)

PDQSort automatically adapts:

Pattern DetectedStrategy
RandomQuicksort partitioning
Nearly sortedFew swaps, fast
Reverse sortedPattern breaking + quicksort
Many duplicatesThree-way partition
Bad pivotsFallback to heapsort

FunctionExtra Memory
sortO(log n) stack
sortAsc/sortDescO(log n) stack
sortByKeyO(log n) stack
sortByCachedKeyO(n) for keys + O(n) for indices

Blitz sort is NOT stable. Equal elements may be reordered.

For stable sorting:

// Use std library stable sort
std.mem.sort(T, data, {}, lessThanFn);

  • Sorting the same array from multiple threads: NOT SAFE
  • Sorting different arrays concurrently: SAFE

const Person = struct {
name: []const u8,
age: u32,
score: i32,
};
var people: []Person = ...;
// Sort by age (ascending)
blitz.sortByKey(Person, u32, people, struct {
fn key(p: Person) u32 { return p.age; }
}.key);
// Sort by score (descending) - negate for descending
blitz.sort(Person, people, struct {
fn lt(a: Person, b: Person) bool {
return a.score > b.score; // Note: > for descending
}
}.lt);
// Multi-field sort
blitz.sort(Person, people, struct {
fn lt(a: Person, b: Person) bool {
if (a.age != b.age) return a.age < b.age;
return a.score > b.score; // Secondary: score descending
}
}.lt);