Double Buffers & Storage Utilities
Reuse state instead of rebuilding it. Double buffers keep the last pass readable while the next one is written, and the array helpers grow, resize, refill and compare arrays you already own.
Double buffers
IntDoubleBuffer and FloatDoubleBuffer keep two arrays, current and previous. swap() exchanges their references in O(1), keeps the completed pass as previous, and clears the new current for reuse. Nothing is copied and no new array is created; the clear still costs O(N).
This is useful when one pass must stay readable while the next is built: graph searches, flood fills, iterative clustering and simulations.
Example: a search frontier
In this small search, node n has children 2n and 2n + 1. Each pass reads the active level and writes the next one:
var op.IntDoubleBuffer searchFrontier = op.intDoubleBuffer()
if barstate.isfirst
searchFrontier.current.push(1)
for depth = 1 to 3
[nextFrontier, activeFrontier] = searchFrontier.swap()
for nodeId in activeFrontier
nextFrontier.push(nodeId * 2)
nextFrontier.push(nodeId * 2 + 1)
// Output: current contains [8, 9, 10, 11, 12, 13, 14, 15].
// previous contains [4, 5, 6, 7].swap() returns [current, previous]: the other retained array, already empty, as nextFrontier, and the completed level as activeFrontier.
Swap rules
swapSized(size, fillValue)swaps and then sizes the new current array to exactlysize, every element set tofillValue. Use it when every pass writes a fixed-size output by index.clear()empties both arrays and keeps their allocations.- Both arrays belong to the buffer and may be written freely between swaps.
current taken before a swap now points at previous. Use the arrays swap() returns, or read the fields again.Reusing arrays
A var array that is resized and refilled in place costs no allocation. Four helper families do this for arrays you own, with one version per type: Int, Float, Bool, Color and String.
| Helper | What it does |
|---|---|
op.ensureSizeFloat(values, minimumSize, fillValue) | Grows the array to at least minimumSize by appending fillValue. Never shrinks, never touches existing elements. |
op.resizeFloat(values, size, fillValue) | Makes the array exactly size long, appending fillValue or removing from the end. |
op.refillFloat(values, size, fillValue) | Makes the array exactly size long with every element set to fillValue. |
op.sameExactFloat(left, right) | True when both arrays hold exactly the same elements in order. |
The size helpers return the resulting size, raise when the array is na, and raise when the size would exceed 100,000 elements. The fill value defaults to 0, false or na, depending on the type. ensureSize*() pairs naturally with a StablePool: grow each payload array when acquire() reports a new key.
[slot, created] = zonePool.acquire(zoneId)
if created
op.ensureSizeFloat(zonePrices, slot + 1, na)
zonePrices.set(slot, zonePrice)Exact comparison
sameExact*() compares two arrays element by element, without the rounding Pine applies to float comparisons, so a tiny real difference counts. na equals na, and an na array counts as empty. It compares the way a Watch does; call it directly when you hold both arrays yourself.
Flat arrays and matrices
Row rings and ring helpers return flat arrays, row by row. These helpers move that data to and from Pine's matrix type:
op.matrixFromFlat(source, rows, columns, startIndex = 0)builds a new float matrix from a contiguous range of a flat array. When the range is not fully present, it returns a zero-filled matrix of the requested shape.op.intMatrixFromFlat()is the int version.op.flatFromFloatMatrix(source, output = na)andop.flatFromIntMatrix()copy a matrix into a flat array, row by row.op.transposeFlatFloat(source, rows, columns, output = na)andop.transposeFlatInt()transpose a flat matrix without building a matrix object. The output must not be the source.
var op.FloatRowRing history = op.floatRowRing(200, 3)
var array<float> flatHistory = array.new<float>()
// Every retained row, oldest first, then one matrix with a row per bar.
history.chronological(flatHistory)
matrix<float> features = op.matrixFromFlat(flatHistory, history.rowCount(), 3)Constants
| Constant | Value |
|---|---|
op.MAX_ARRAY_ELEMENTS | 100,000. The most elements one Pine array or matrix can hold. |
op.MAX_MAP_PAIRS | 50,000. The most pairs one Pine map can hold. |
op.MAX_GENERATION | 2,000,000,000. The highest generation or revision value before a structure starts again from 0. |
Calls
| Call | What it does |
|---|---|
op.intDoubleBuffer(), op.floatDoubleBuffer() | Create a double buffer with two empty arrays. |
buffer.current, buffer.previous | The two arrays, as fields. |
buffer.swap() | Swaps, clears the new current array, and returns [current, previous]. |
buffer.swapSized(size, fillValue) | Swaps and refills the new current array to a fixed size. |
buffer.clear() | Empties both arrays. |
op.ensureSize*(), op.resize*(), op.refill*(), op.sameExact*() | Array helpers for Int, Float, Bool, Color and String. |
op.matrixFromFlat(), op.intMatrixFromFlat(), op.flatFromFloatMatrix(), op.flatFromIntMatrix() | Convert between flat arrays and matrices. |
op.transposeFlatFloat(), op.transposeFlatInt() | Transpose a flat matrix. |
Every signature is in the API Reference. Next: Weighted Sampling.