authorgravatar for git@zander.xyzZander Khan <git@zander.xyz> 2021-01-17 14:41:20+00:00
committergravatar for git@zander.xyzZander Khan <git@zander.xyz> 2021-01-17 14:41:20+00:00
log9a09ebb1b92f33913bdcc16e9d978fb6e5a820f1
tree1a178892bfa500026b16a4a3434d1cc243142d9a
parente1ab425bcead727a73e4512aeca1ba9112b2c88e

Replace `shrink` with `shrinkAndFree` and `shrinkRetainingCapacity`


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 }
384384
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 semantics386 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 }
390410
...@@ -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}
800820
821test "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
801test "std.PriorityDequeue: fuzz testing min" {848test "std.PriorityDequeue: fuzz testing min" {
802 var prng = std.rand.DefaultPrng.init(0x12345678);849 var prng = std.rand.DefaultPrng.init(0x12345678);
803850
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 }
194194
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 semantics196 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 }
200220
...@@ -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}
479499
500test "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
480test "std.PriorityQueue: update min heap" {527test "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();