26 template <
class T = Eigen::VectorXcd>
Alias(
const T &statevector) {
27 std::vector<double> probabilities(statevector.size());
29 for (Eigen::Index i = 0; i < static_cast<Eigen::Index>(statevector.size());
31 probabilities[i] = std::norm(statevector[i]);
32 accum += probabilities[i];
33 if (accum > 1. - std::numeric_limits<double>::epsilon()) {
34 probabilities.resize(i + 1);
39 aliasTable.resize(probabilities.size());
41 std::vector<AliasEntry> under;
42 std::vector<AliasEntry> over;
45 under.reserve(probabilities.size());
46 over.reserve(probabilities.size());
48 for (Eigen::Index i = 0;
49 i < static_cast<Eigen::Index>(probabilities.size()); ++i) {
50 const double prob = probabilities[i] * probabilities.size();
52 under.emplace_back(prob, i);
54 over.emplace_back(prob, i);
57 while (!under.empty() && !over.empty()) {
58 const AliasEntry &u = under.back();
59 const AliasEntry &o = over.back();
61 const size_t index = o.alias;
63 aliasTable[u.alias] = AliasEntry(u.probability, index);
65 const double rem = o.probability + u.probability - 1.;
71 under.emplace_back(rem, index);
73 over.emplace_back(rem, index);
76 const AliasEntry one(1., -1);
78 for (; !under.empty(); under.pop_back())
79 aliasTable[under.back().alias] = one;
81 for (; !over.empty(); over.pop_back())
82 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;