| ... | ... | @@ -36,6 +36,8 @@ pub fn insertion( |
| 36 | 36 | /// O(1) memory (no allocator required). |
| 37 | 37 | /// Sorts in ascending order with respect to the given `lessThan` function. |
| 38 | 38 | pub fn insertionContext(a: usize, b: usize, context: anytype) void { |
| 39 | assert(a <= b); |
| 40 | |
| 39 | 41 | var i = a + 1; |
| 40 | 42 | while (i < b) : (i += 1) { |
| 41 | 43 | var j = i; |
| ... | ... | @@ -73,6 +75,7 @@ pub fn heap( |
| 73 | 75 | /// O(1) memory (no allocator required). |
| 74 | 76 | /// Sorts in ascending order with respect to the given `lessThan` function. |
| 75 | 77 | pub fn heapContext(a: usize, b: usize, context: anytype) void { |
| 78 | assert(a <= b); |
| 76 | 79 | // build the heap in linear time. |
| 77 | 80 | var i = a + (b - a) / 2; |
| 78 | 81 | while (i > a) { |
| ... | ... | @@ -89,22 +92,33 @@ pub fn heapContext(a: usize, b: usize, context: anytype) void { |
| 89 | 92 | } |
| 90 | 93 | } |
| 91 | 94 | |
| 92 | | fn siftDown(a: usize, root: usize, n: usize, context: anytype) void { |
| 93 | | var node = root; |
| 95 | fn siftDown(a: usize, target: usize, b: usize, context: anytype) void { |
| 96 | var cur = target; |
| 94 | 97 | while (true) { |
| 95 | | var child = a + 2 * (node - a) + 1; |
| 96 | | if (child >= n) break; |
| 98 | // When we don't overflow from the multiply below, the following expression equals (2*cur) - (2*a) + a + 1 |
| 99 | // The `+ a + 1` is safe because: |
| 100 | // for `a > 0` then `2a >= a + 1`. |
| 101 | // for `a = 0`, the expression equals `2*cur+1`. `2*cur` is an even number, therefore adding 1 is safe. |
| 102 | var child = (math.mul(usize, cur - a, 2) catch break) + a + 1; |
| 103 | |
| 104 | // stop if we overshot the boundary |
| 105 | if (!(child < b)) break; |
| 97 | 106 | |
| 98 | | // choose the greater child. |
| 99 | | child += @intFromBool(child + 1 < n and context.lessThan(child, child + 1)); |
| 107 | // `next_child` is at most `b`, therefore no overflow is possible |
| 108 | const next_child = child + 1; |
| 109 | |
| 110 | // store the greater child in `child` |
| 111 | if (next_child < b and context.lessThan(child, next_child)) { |
| 112 | child = next_child; |
| 113 | } |
| 100 | 114 | |
| 101 | | // stop if the invariant holds at `node`. |
| 102 | | if (!context.lessThan(node, child)) break; |
| 115 | // stop if the Heap invariant holds at `cur`. |
| 116 | if (context.lessThan(child, cur)) break; |
| 103 | 117 | |
| 104 | | // swap `node` with the greater child, |
| 118 | // swap `cur` with the greater child, |
| 105 | 119 | // move one step down, and continue sifting. |
| 106 | | context.swap(node, child); |
| 107 | | node = child; |
| 120 | context.swap(child, cur); |
| 121 | cur = child; |
| 108 | 122 | } |
| 109 | 123 | } |
| 110 | 124 | |