 ### CompactQueue: comments and stylistic improvements.

parent c83d9513
 (** This module implements a mutable FIFO queue, like [Queue]. However it has a more compact representation, storing elements contiguously in an array. *) (* A queue [q] is represented as a circular array of elements, [q.buffer]. The slots whose logical index lies between [q.first] (inclusive) and [q.first + q.size] (exclusive) contain the elements of the queue. A logical index must be normalized modulo [n], where [n] is the length of the array [buffer], to obtain a physical index. *) (* We maintain the following invariants: - [n] is zero or a power of two, so as to speed up the [modulo] operation. - [0 <= q.size <= n] holds. *) type 'a t = { (* The array that stores the elements (as well as empty slots). *) mutable buffer: 'a array; (* The array that stores all elements. *) (* The logical index of the first element. *) mutable first: int; (* Index of the first element in the queue, if any (the one that will be popped next). It has to be taken modulo (Array.length buffer). *) (* The number of elements. *) mutable size: int; (* The number of elements in the queue. *) (* Invariants: - [Array.length q.buffer] is a power of 2, to speed up modulo - [0 <= q.size <= Array.length q.buffer] *) } (* The following code iterates on all queued elements: (* The following code iterates on all queued elements: for i = 0 to q.size - 1 do f q.buffer.((q.first + i) mod (Array.length q.buffer)) done let n = Array.length q.buffer in for i = 0 to q.size - 1 do f q.buffer.((q.first + i) mod n) done Since length is a power of 2, it is equivalent to: Because [n] is a power of 2, this is equivalent to: for i = 0 to q.size - 1 do f q.buffer.((q.first + i) land (Array.length q.buffer - 1)) done *) } let n = Array.length q.buffer in for i = 0 to q.size - 1 do f q.buffer.((q.first + i) land (n - 1)) done *) (* The buffer is initially an empty array. Another array is allocated when an element is inserted. *) let create () = { (* The buffer is initially an empty array. It will be re-allocated when a first element is pushed. *) buffer = [||]; first = 0; size = 0; ... ... @@ -45,26 +53,26 @@ let is_empty q = let add x q = let buffer = q.buffer in let length = Array.length buffer in if q.size < length then begin (* Queue still has some room left *) buffer.((q.first + q.size) land (length - 1)) <- x; q.size <- q.size + 1 let n = Array.length buffer in if q.size < n then begin (* The queue still has room left. *) buffer.((q.first + q.size) land (n - 1)) <- x; q.size <- q.size + 1; end else if length > 0 then begin (* Buffer is full *) (* 1. Reallocate a buffer twice the size *) let buffer' = Array.make (length * 2) x in (* 2. Move existing elements *) let first = q.first land (length - 1) in Array.blit buffer first buffer' 0 (length - first); Array.blit buffer 0 buffer' (length - first) first; else if n > 0 then begin (* The buffer is nonempty, and is full. *) (* Allocate a new buffer that is twice larger. *) let buffer' = Array.make (n * 2) x in (* Move all existing elements. *) let first = q.first land (n - 1) in Array.blit buffer first buffer' 0 (n - first); Array.blit buffer 0 buffer' (n - first) first; q.buffer <- buffer'; q.first <- 0; q.size <- length + 1; q.size <- n + 1; end else begin (* Queue has a buffer of size 0. Allocate an initial array. *) (* The queue has a buffer of size 0. Allocate an array. *) q.buffer <- Array.make 8 x; q.size <- 1; end ... ... @@ -74,9 +82,10 @@ exception Empty let take q = if q.size = 0 then raise Empty else ( else begin q.size <- q.size - 1; let result = q.buffer.(q.first land (Array.length q.buffer - 1)) in let n = Array.length q.buffer in let result = q.buffer.(q.first land (n - 1)) in q.first <- q.first + 1; result ) end
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!