| 153 | } |
| 154 | |
| 155 | int64 |
| 156 | RowSampler_Next(RowSampler rs) |
| 157 | { |
| 158 | int64 K = rs->N - rs->t; /* remaining objects */ |
| 159 | int64 k = rs->n - rs->m; /* objects still to sample */ |
| 160 | double p; /* probability to skip object */ |
| 161 | double V; /* random */ |
| 162 | |
| 163 | Assert(RowSampler_HasMore(rs)); /* hence K > 0 and k > 0 */ |
| 164 | |
| 165 | if (k >= K) |
| 166 | { |
| 167 | /* need all the rest */ |
| 168 | rs->m++; |
| 169 | return rs->t++; |
| 170 | } |
| 171 | |
| 172 | /* |
| 173 | * It is not obvious that this code matches Knuth's Algorithm S. |
| 174 | * Refer to BlockSampler_Next() for detail. |
| 175 | */ |
| 176 | V = sampler_random_fract(rs->randstate); |
| 177 | /* |
| 178 | * Don't bother overflow of conversion from int64 K (N) as it was |
| 179 | * already converted to "double" range value when initialized. |
| 180 | */ |
| 181 | p = 1.0 - (double) k / (double) K; |
| 182 | while (V < p) |
| 183 | { |
| 184 | /* skip */ |
| 185 | rs->t++; |
| 186 | K--; /* keep K == N - t */ |
| 187 | |
| 188 | /* adjust p to be new cutoff point in reduced range */ |
| 189 | p *= 1.0 - (double) k / (double) K; |
| 190 | } |
| 191 | |
| 192 | /* select */ |
| 193 | rs->m++; |
| 194 | return rs->t++; |
| 195 | } |
| 196 | |
| 197 | /* |
| 198 | * These two routines embody Algorithm Z from "Random sampling with a |
no test coverage detected