28 std::vector<double> probabilities(statevector.size());
30 for (Eigen::Index i = 0; i < static_cast<Eigen::Index>(statevector.size());
32 probabilities[i] = std::norm(statevector[i]);
33 accum += probabilities[i];
34 if (accum > 1. - std::numeric_limits<double>::epsilon()) {
35 probabilities.resize(i + 1);
40 aliasTable.resize(probabilities.size());
42 std::vector<AliasEntry> under;
43 std::vector<AliasEntry> over;
46 under.reserve(probabilities.size());
47 over.reserve(probabilities.size());
49 for (Eigen::Index i = 0;
50 i < static_cast<Eigen::Index>(probabilities.size()); ++i) {
51 const double prob = probabilities[i] * probabilities.size();
53 under.emplace_back(prob, i);
55 over.emplace_back(prob, i);
58 while (!under.empty() && !over.empty()) {
59 const AliasEntry &u = under.back();
60 const AliasEntry &o = over.back();
62 const size_t index = o.alias;
64 aliasTable[u.alias] = AliasEntry(u.probability, index);
66 const double rem = o.probability + u.probability - 1.;
72 under.emplace_back(rem, index);
74 over.emplace_back(rem, index);
77 const AliasEntry one(1., -1);
79 for (; !under.empty(); under.pop_back())
80 aliasTable[under.back().alias] = one;
82 for (; !over.empty(); over.pop_back()) aliasTable[over.back().alias] = one;
86 static const double oneMinusEps =
87 1. - std::numeric_limits<double>::epsilon();
89 const double vadj = v * aliasTable.size();
90 const size_t offset = std::min<size_t>(vadj, aliasTable.size() - 1);
91 const double up = std::min<double>(vadj - offset, oneMinusEps);
93 return up < aliasTable[offset].probability ? offset
94 : aliasTable[offset].alias;