General window
A state to represent a window of arbitrarily variable capacity.
We push new values onto the window with Base.push!. We can remove old values from the window with Base.popfirst!.
AssociativeWindowAggregation.WindowedAssociativeOp — TypeWindowedAssociativeOp{T,Op,Op!,V<:AbstractVector{T}}(previous_cumsum::V, values::V)
WindowedAssociativeOp{T,Op,Op!}()
WindowedAssociativeOp{T,Op}()State associated with a windowed aggregation of a binary associative operator.
If Op! is not specified, it will default to Op. However, for non-bitstypes, it can be beneficial to provide this method to reduce memory allocations.
V will default to a Vector{T}. For windows of a fixed and known length, a circular buffer will be more efficient — see FixedWindowAssociativeOp.
Method
Wherever summation is discussed, we can consider any alternative binary, associative, operator. For example: +, *, max, min, &&, union
NB. It is interesting to observe that commutativity is not required by this algorithm.
Conceptually the window is maintained in two buffers:
[---- A ---)[----- B ------)
< > <-- current window finishes at the end of B, and
starts somewhere in A.A is stored as a sequence of cumulative sums, such that as the "<" advances we merely pick out the correct element:
x_i, x_i-1 + x_i, x_i-2 + x_i-1 + x_iB is stored as both:
- The sequence of values seen:
x_i+1, x_i+2, x_i+3, ... - The total of that sequence:
x_i+1 + x_i+2 + x_i+3 + ...
When the "<" advances from A to B, we discard A, and the subset of B remaining after < becomes the new A. In becoming A, we transform its representation into that of the cumulative sums. We create a new, empty, B.
O(1) amortized runtime complexity, and O(L) space complexity, where L is the typical window length.
Type parameters
T: The type of the values in the window.Op: Any binary, associative, function.Op!:Op!(x, y)will performx + y, storing the result inx.V: The subtype ofAbstractVector{T}used for internal state.
Fields (for internal use only)
previous_cumsum::Vector{T}: Corresponds to arrayAabove.ri_previous_cumsum::Int: A reverse index intoprevious_cumsum, once it contains values. It should be subtracted fromendin order to obtain the appropriate index.values::Vector{T}: Corresponds to arrayBabove.sum::T: The sum of the elements in values.
AssociativeWindowAggregation.window_size — Methodfunction window_size(state::WindowedAssociativeOp)::IntGet the current size of the window in state.
Arguments:
state::WindowedAssociativeOp: The state to query.
Returns:
Int: The current size of the window.
AssociativeWindowAggregation.window_value — Methodwindow_value(state::WindowedAssociativeOp{T})::T where TGet the value currently represented by the state.
Behaviour is undefined if this is called when the window is empty.
Arguments:
state::WindowedAssociativeOp{T}: The state to query.
Returns:
T: The result of aggregating over the values in the window.
Base.popfirst! — Methodpopfirst!(state::WindowedAssociativeOp, n::Integer=1) -> stateDrop n values from the start of state.
Base.push! — Methodpush!(state::WindowedAssociativeOp{T}, value) -> statePush value onto the end of state.
Arguments
state::WindowedAssociativeOp: The state to update (will be mutated).value: The value to add to the end of the window - must be convertible to aT.