| author | |
| committer | |
| log | 9a09ebb1b92f33913bdcc16e9d978fb6e5a820f1 |
| tree | 1a178892bfa500026b16a4a3434d1cc243142d9a |
| parent | e1ab425bcead727a73e4512aeca1ba9112b2c88e |
2 files changed, 100 insertions(+), 6 deletions(-)
lib/std/priority_dequeue.zig+50-3| ... | @@ -382,9 +382,29 @@ pub fn PriorityDequeue(comptime T: type) type { | ... | @@ -382,9 +382,29 @@ pub fn PriorityDequeue(comptime T: type) type { |
| 382 | self.len = new_len; | 382 | self.len = new_len; |
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | pub fn shrink(self: *Self, new_len: usize) void { | 385 | /// Reduce allocated capacity to `new_len`. |
| 386 | // TODO take advantage of the new realloc semantics | 386 | pub fn shrinkAndFree(self: *Self, new_len: usize) void { |
| 387 | assert(new_len <= self.len); | 387 | assert(new_len <= self.items.len); |
| 388 | |||
| 389 | // Cannot shrink to smaller than the current queue size without invalidating the heap property | ||
| 390 | assert(new_len >= self.len); | ||
| 391 | |||
| 392 | self.items = self.allocator.realloc(self.items[0..], new_len) catch |e| switch (e) { | ||
| 393 | error.OutOfMemory => { // no problem, capacity is still correct then. | ||
| 394 | self.items.len = new_len; | ||
| 395 | return; | ||
| 396 | }, | ||
| 397 | }; | ||
| 398 | self.len = new_len; | ||
| 399 | } | ||
| 400 | |||
| 401 | /// Reduce length to `new_len`. | ||
| 402 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { | ||
| 403 | assert(new_len <= self.items.len); | ||
| 404 | |||
| 405 | // Cannot shrink to smaller than the current queue size without invalidating the heap property | ||
| 406 | assert(new_len >= self.len); | ||
| 407 | |||
| 388 | self.len = new_len; | 408 | self.len = new_len; |
| 389 | } | 409 | } |
| 390 | 410 | ||
| ... | @@ -798,6 +818,33 @@ test "std.PriorityDequeue: iterator while empty" { | ... | @@ -798,6 +818,33 @@ test "std.PriorityDequeue: iterator while empty" { |
| 798 | expectEqual(it.next(), null); | 818 | expectEqual(it.next(), null); |
| 799 | } | 819 | } |
| 800 | 820 | ||
| 821 | test "std.PriorityDequeue: shrinkRetainingCapacity and shrinkAndFree" { | ||
| 822 | var queue = PDQ.init(testing.allocator, lessThanComparison); | ||
| 823 | defer queue.deinit(); | ||
| 824 | |||
| 825 | try queue.ensureCapacity(4); | ||
| 826 | expect(queue.capacity() >= 4); | ||
| 827 | |||
| 828 | try queue.add(1); | ||
| 829 | try queue.add(2); | ||
| 830 | try queue.add(3); | ||
| 831 | expect(queue.capacity() >= 4); | ||
| 832 | expectEqual(@as(usize, 3), queue.len); | ||
| 833 | |||
| 834 | queue.shrinkRetainingCapacity(3); | ||
| 835 | expect(queue.capacity() >= 4); | ||
| 836 | expectEqual(@as(usize, 3), queue.len); | ||
| 837 | |||
| 838 | queue.shrinkAndFree(3); | ||
| 839 | expectEqual(@as(usize, 3), queue.capacity()); | ||
| 840 | expectEqual(@as(usize, 3), queue.len); | ||
| 841 | |||
| 842 | expectEqual(@as(u32, 3), queue.removeMax()); | ||
| 843 | expectEqual(@as(u32, 2), queue.removeMax()); | ||
| 844 | expectEqual(@as(u32, 1), queue.removeMax()); | ||
| 845 | expect(queue.removeMaxOrNull() == null); | ||
| 846 | } | ||
| 847 | |||
| 801 | test "std.PriorityDequeue: fuzz testing min" { | 848 | test "std.PriorityDequeue: fuzz testing min" { |
| 802 | var prng = std.rand.DefaultPrng.init(0x12345678); | 849 | var prng = std.rand.DefaultPrng.init(0x12345678); |
| 803 | 850 |
lib/std/priority_queue.zig+50-3| ... | @@ -192,9 +192,29 @@ pub fn PriorityQueue(comptime T: type) type { | ... | @@ -192,9 +192,29 @@ pub fn PriorityQueue(comptime T: type) type { |
| 192 | self.len = new_len; | 192 | self.len = new_len; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | pub fn shrink(self: *Self, new_len: usize) void { | 195 | /// Reduce allocated capacity to `new_len`. |
| 196 | // TODO take advantage of the new realloc semantics | 196 | pub fn shrinkAndFree(self: *Self, new_len: usize) void { |
| 197 | assert(new_len <= self.len); | 197 | assert(new_len <= self.items.len); |
| 198 | |||
| 199 | // Cannot shrink to smaller than the current queue size without invalidating the heap property | ||
| 200 | assert(new_len >= self.len); | ||
| 201 | |||
| 202 | self.items = self.allocator.realloc(self.items[0..], new_len) catch |e| switch (e) { | ||
| 203 | error.OutOfMemory => { // no problem, capacity is still correct then. | ||
| 204 | self.items.len = new_len; | ||
| 205 | return; | ||
| 206 | }, | ||
| 207 | }; | ||
| 208 | self.len = new_len; | ||
| 209 | } | ||
| 210 | |||
| 211 | /// Reduce length to `new_len`. | ||
| 212 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { | ||
| 213 | assert(new_len <= self.items.len); | ||
| 214 | |||
| 215 | // Cannot shrink to smaller than the current queue size without invalidating the heap property | ||
| 216 | assert(new_len >= self.len); | ||
| 217 | |||
| 198 | self.len = new_len; | 218 | self.len = new_len; |
| 199 | } | 219 | } |
| 200 | 220 | ||
| ... | @@ -477,6 +497,33 @@ test "std.PriorityQueue: iterator while empty" { | ... | @@ -477,6 +497,33 @@ test "std.PriorityQueue: iterator while empty" { |
| 477 | expectEqual(it.next(), null); | 497 | expectEqual(it.next(), null); |
| 478 | } | 498 | } |
| 479 | 499 | ||
| 500 | test "std.PriorityQueue: shrinkRetainingCapacity and shrinkAndFree" { | ||
| 501 | var queue = PQ.init(testing.allocator, lessThan); | ||
| 502 | defer queue.deinit(); | ||
| 503 | |||
| 504 | try queue.ensureCapacity(4); | ||
| 505 | expect(queue.capacity() >= 4); | ||
| 506 | |||
| 507 | try queue.add(1); | ||
| 508 | try queue.add(2); | ||
| 509 | try queue.add(3); | ||
| 510 | expect(queue.capacity() >= 4); | ||
| 511 | expectEqual(@as(usize, 3), queue.len); | ||
| 512 | |||
| 513 | queue.shrinkRetainingCapacity(3); | ||
| 514 | expect(queue.capacity() >= 4); | ||
| 515 | expectEqual(@as(usize, 3), queue.len); | ||
| 516 | |||
| 517 | queue.shrinkAndFree(3); | ||
| 518 | expectEqual(@as(usize, 3), queue.capacity()); | ||
| 519 | expectEqual(@as(usize, 3), queue.len); | ||
| 520 | |||
| 521 | expectEqual(@as(u32, 1), queue.remove()); | ||
| 522 | expectEqual(@as(u32, 2), queue.remove()); | ||
| 523 | expectEqual(@as(u32, 3), queue.remove()); | ||
| 524 | expect(queue.removeOrNull() == null); | ||
| 525 | } | ||
| 526 | |||
| 480 | test "std.PriorityQueue: update min heap" { | 527 | test "std.PriorityQueue: update min heap" { |
| 481 | var queue = PQ.init(testing.allocator, lessThan); | 528 | var queue = PQ.init(testing.allocator, lessThan); |
| 482 | defer queue.deinit(); | 529 | defer queue.deinit(); |