I would like to throw in my implementation that is inspired by `std::transform`
from c++.
proc genRangeswap[Coll](data: var Coll; s0, s1, N: Natural): void =
for i in 0 ..< N:
swap(data[s0+i], data[s1+i])
proc genTransform[Coll](data: var Coll; first, middle, last: Natural): void
=
assert(0 <= first and first <= middle and middle < last and last <=
data.len)
if first == middle:
return
let
N = middle - first
M = last - middle
if N < M:
genRangeswap(data, first , middle , N )
genTransform(data, first+N, middle+N, last)
else: # M >= N
genRangeswap(data, first , middle , M )
genTransform(data, first+M, middle, last)
proc transform*(data: var string; first, middle, last: Natural): void =
genTransform(data, first, middle, last)
proc transform*(data: var string; middle: Natural): void =
genTransform(data, 0, middle, data.len)
proc transform*[T](data: var openarray[T]; first, middle, last: Natural):
void =
genTransform(data, first, middle, last)
proc transform*[T](data: var openarray[T]; middle: Natural): void =
genTransform(data, 0, middle, data.len)
It has a generic core implementation that is not exported, and has a few
wrappers that are mostly there to prevent false positives in auto completion.
Everything is based on the rangeswap function that basically swaps two
subranges of the same sequence. It is implemented in a way that it could easily
be optimized for some sort of memswap on the string type. I don't know yet how
safe it is to use memory swapping on other types, but I have a positive feeling
that it is possible even though it sounds pretty dangerous to do so.