@@ -23,9 +23,9 @@ bool Node::operator>(const Node& other) const {
2323}
2424
2525double TesseractDecoder::get_detcost (size_t d,
26- const std::vector<bool >& blocked_errs,
26+ const std::vector<char >& blocked_errs,
2727 const std::vector<size_t >& det_counts,
28- const std::vector<bool >& dets) const {
28+ const std::vector<char >& dets) const {
2929 double min_cost = INF;
3030 for (size_t ei : d2e[d]) {
3131 if (!blocked_errs[ei]) {
@@ -86,14 +86,16 @@ void TesseractDecoder::initialize_structures(size_t num_detectors) {
8686}
8787
8888struct VectorBoolHash {
89- size_t operator ()(const std::vector<bool >& v) const {
90- std::hash<bool > bool_hash;
91- size_t seed = 0 ;
92- for (bool b : v) {
93- // Combine hash values of individual booleans.
94- // A simple way is to use XOR and bit shifting,
95- // but you can use other combining strategies as well.
96- seed ^= bool_hash (b) + 0x9e3779b9 + (seed << 6 ) + (seed >> 2 );
89+ size_t operator ()(const std::vector<char >& v) const {
90+ size_t seed = v.size (); // Still good practice to incorporate vector size
91+
92+ // Iterate over char elements. Accessing 'b_val' is now a direct memory read.
93+ for (char b_val : v) {
94+ // The polynomial rolling hash with 31 (or another prime)
95+ // 'b_val' is already a char (an 8-bit integer).
96+ // static_cast<size_t>(b_val) ensures it's promoted to size_t before arithmetic.
97+ // This cast is efficient (likely a simple register extension/move).
98+ seed = seed * 31 + static_cast <size_t >(b_val);
9799 }
98100 return seed;
99101 }
@@ -151,7 +153,7 @@ bool QNode::operator>(const QNode& other) const {
151153}
152154
153155void TesseractDecoder::to_node (const QNode& qnode,
154- const std::vector<bool >& shot_dets,
156+ const std::vector<char >& shot_dets,
155157 size_t det_order, Node& node) const {
156158 node.cost = qnode.cost ;
157159 node.errs = qnode.errs ;
@@ -197,20 +199,20 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
197199 size_t det_beam = config.det_beam ;
198200 predicted_errors_buffer.clear ();
199201 low_confidence_flag = false ;
200- std::vector<bool > dets (num_detectors, false );
202+ std::vector<char > dets (num_detectors, false );
201203 for (size_t d : detections) {
202204 dets[d] = true ;
203205 }
204206
205207 std::priority_queue<QNode, std::vector<QNode>, std::greater<QNode>> pq;
206208 std::unordered_map<size_t ,
207- std::unordered_set<std::vector<bool >, VectorBoolHash>>
209+ std::unordered_set<std::vector<char >, VectorBoolHash>>
208210 discovered_dets;
209211
210212 size_t min_num_dets;
211213 {
212214 std::vector<size_t > errs;
213- std::vector<bool > blocked_errs (num_errors, false );
215+ std::vector<char > blocked_errs (num_errors, false );
214216 std::vector<size_t > det_counts (num_errors, 0 );
215217
216218 for (size_t d = 0 ; d < num_detectors; ++d) {
@@ -238,8 +240,8 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
238240 size_t max_num_dets = min_num_dets + det_beam;
239241 Node node;
240242 std::vector<size_t > next_det_counts;
241- std::vector<bool > next_next_blocked_errs;
242- std::vector<bool > next_dets;
243+ std::vector<char > next_next_blocked_errs;
244+ std::vector<char > next_dets;
243245 std::vector<size_t > next_errs;
244246 while (!pq.empty ()) {
245247 const QNode qnode = pq.top ();
@@ -311,7 +313,7 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
311313 }
312314 // We cache as we recompute the det costs
313315 std::vector<double > det_costs (num_detectors, -1 );
314- std::vector<bool > next_blocked_errs = node.blocked_errs ;
316+ std::vector<char > next_blocked_errs = node.blocked_errs ;
315317 if (config.at_most_two_errors_per_detector ) {
316318 for (int ei : d2e[min_det]) {
317319 // Block all errors of this detector -- note this is an approximation
0 commit comments