diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-01-29 00:27:09 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-01-29 00:27:09 -0800 |
commit | 09010c1509a30cdd042f1b31a1ecd84922adbba2 (patch) | |
tree | 631c9050f8ee41ac8131ea8ee1f6a3df2be0ffb7 | |
parent | aeae4fc3dcfbb4b5376515e5660134e79a4f54c3 (diff) | |
download | txr-09010c1509a30cdd042f1b31a1ecd84922adbba2.tar.gz txr-09010c1509a30cdd042f1b31a1ecd84922adbba2.tar.bz2 txr-09010c1509a30cdd042f1b31a1ecd84922adbba2.zip |
random-sample: replace algorithm R.
* rand.c (random_sample): The brnach of the code for lists is
converted from the naive algorithm R which requires a random
integer for each element of the sequence to a list adaptation
of the smarter algorithm L used for vector. We don't have
random access through the list being sampled, but we can step
to new positions without generating random numbers.
-rw-r--r-- | rand.c | 17 |
1 files changed, 13 insertions, 4 deletions
@@ -543,10 +543,19 @@ static val random_sample(val size, val seq, val state_in) } } } else { - for (; seq_get(&iter, &elem) && i <= INT_PTR_MAX; i++) { - cnum r = c_n(random(state, unum(i))); - if (r < sz) - samp->v.vec[r] = elem; + double weight = elrd(sz, state); + + for (;;) { + cnum nx = i + flrd(weight, state) + 1; + for (; seq_get(&iter, &elem) && i < nx; i++) + ; /* nothing */ + + if (i < nx) + break; + + samp->v.vec[c_n(random(state, size))] = elem; + mut(samp); + weight *= elrd(sz, state); } } |