42 const std::vector<double>& logWeights,
44 std::vector<size_t>& outIndexes,
45 size_t outCount = 0) {
46 const size_t M = logWeights.size();
56 double maxLog = logWeights.front();
57 for (
const double lw : logWeights) {
58 maxLog = std::max(maxLog, lw);
60 std::vector<double> linW(M);
62 for (
size_t i = 0; i < M; ++i) {
63 linW[i] = std::exp(logWeights[i] - maxLog);
68 outIndexes.assign(outCount, 0);
69 std::uniform_int_distribution<size_t> uniDist(0, M - 1);
70 for (
auto& idx : outIndexes) {
75 const double inv = 1.0 / sum;
76 for (
auto& w : linW) {
80 std::uniform_real_distribution<double> uni01(0.0, 1.0);
82 auto cumulativeWalk = [&](
const std::vector<double>& T) {
84 std::vector<double> Q(M);
86 for (
size_t i = 0; i < M; ++i) {
92 outIndexes.resize(outCount);
95 while (i < outCount) {
98 }
else if (j + 1 < M) {
108 std::vector<double> T(outCount);
112 std::sort(T.begin(), T.end());
118 std::vector<uint32_t> N(M, 0);
120 for (
size_t i = 0; i < M; ++i) {
121 N[i] =
static_cast<uint32_t
>(
static_cast<double>(outCount) * linW[i]);
124 outIndexes.resize(outCount);
126 for (
size_t i = 0; i < M && j < outCount; ++i) {
127 for (uint32_t k = 0; k < N[i] && j < outCount; ++k) {
131 const size_t residualCount = outCount - j;
132 if (residualCount == 0) {
136 std::vector<double> linWmod(M);
137 const double invRes = 1.0 /
static_cast<double>(residualCount);
138 for (
size_t i = 0; i < M; ++i) {
140 invRes * (
static_cast<double>(outCount) * linW[i] -
static_cast<double>(N[i]));
142 std::vector<double> Qres(M);
144 for (
size_t i = 0; i < M; ++i) {
149 std::vector<double> T(residualCount);
153 std::sort(T.begin(), T.end());
156 while (walk < residualCount) {
157 if (T[walk] < Qres[k]) {
158 outIndexes[j + walk] = k;
160 }
else if (k + 1 < M) {
163 outIndexes[j + walk] = k;
171 std::vector<double> T(outCount);
172 const double step = 1.0 /
static_cast<double>(outCount);
173 for (
size_t i = 0; i < outCount; ++i) {
174 T[i] = (
static_cast<double>(i) + uni01(rng)) * step;
181 std::vector<double> T(outCount);
182 const double step = 1.0 /
static_cast<double>(outCount);
183 const double offset = uni01(rng) * step;
184 for (
size_t i = 0; i < outCount; ++i) {
185 T[i] = offset +
static_cast<double>(i) * step;
200 const size_t M = logWeights.size();
204 double maxLog = logWeights.front();
205 for (
const double lw : logWeights) {
206 maxLog = std::max(maxLog, lw);
209 for (
const double lw : logWeights) {
210 sumLin += std::exp(lw - maxLog);
212 if (!(sumLin > 0.0)) {
216 for (
const double lw : logWeights) {
217 const double w = std::exp(lw - maxLog) / sumLin;
220 if (!(sumSq > 0.0)) {
223 return 1.0 / (
static_cast<double>(M) * sumSq);