I am keeping an efficient circular buffer buf
as an array and two total read and write counts bufRead
and bufWrite
such that bufRead % buf.length
and bufWrite % buf.length
are correct indices into buffer for current operations.
Now I might need to "grow" the array at some point because the buffer size expands. So I want to replace buf
with a new, larger array, but preserve all the previous contents of the buffer while preserving the above modulus properties. So if at bufRead % buf.length
in the old buffer we find element X, then I want this element X to be found again at the same index bufRead % buf.length
after buf
has been updated.
Example:
trait Algorithm {
var buf: Array[Double]
var bufRead : Long // this won't be needed in `resize`
var bufWrite: Long // this won't be needed in `resize`
def resize(newLength: Int): Unit = {
val newBuf = new Array[Double](newLength)
???
buf = newBuf
}
}
A test procedure:
def test(in: Algorithm): Unit = {
import in._
import math.{min, random}
val avail = buf.length // (bufWrite - bufRead).toInt
val data0 = Array.fill(avail)(random)
val off0 = (bufRead % buf.length).toInt
val chunk0 = min(avail, buf.length - off0)
val off1 = (off0 + chunk0) % buf.length
val chunk1 = avail - chunk0
System.arraycopy(data0, 0 , buf, off0, chunk0)
System.arraycopy(data0, chunk0, buf, off1, chunk1)
resize(avail * 2) // arbitrary growth
val data1 = new Array[Double](avail)
val off2 = (bufRead % buf.length).toInt
val chunk2 = min(avail, buf.length - off2)
val off3 = (off2 + chunk2) % buf.length
val chunk3 = avail - chunk2
System.arraycopy(buf, off2, data1, 0 , chunk2)
System.arraycopy(buf, off3, data1, chunk2, chunk3)
assert(data0 sameElements data1)
}