@@ -123,6 +123,13 @@ class async_decoder_result {
123123class decoder
124124 : public cudaqx::extension_point<decoder, const cudaqx::tensor<uint8_t > &,
125125 const cudaqx::heterogeneous_map &> {
126+ private:
127+ struct rt_impl ;
128+ struct rt_impl_deleter {
129+ void operator ()(rt_impl *p) const ;
130+ };
131+ std::unique_ptr<rt_impl, rt_impl_deleter> pimpl;
132+
126133public:
127134 decoder () = delete ;
128135
@@ -173,8 +180,59 @@ class decoder
173180 std::size_t get_block_size () { return block_size; }
174181 std::size_t get_syndrome_size () { return syndrome_size; }
175182
183+ // -- Begin realtime decoding API --
184+
185+ // Note: all of the current realtime decoding API is designed to be used with
186+ // hard syndromes.
187+
188+ // / @brief Get the number of measurement syndromes per decode call. This
189+ // / depends on D_sparse, so you must have called set_D_sparse() first.
190+ uint32_t get_num_msyn_per_decode () const ;
191+
192+ // / @brief Set the observable matrix.
193+ void set_O_sparse (const std::vector<std::vector<uint32_t >> &O_sparse);
194+
195+ // / @brief Set the observable matrix, using a single long vector with -1 as
196+ // / row terminators.
197+ void set_O_sparse (const std::vector<int64_t > &O_sparse);
198+
199+ // / @brief Set the D_sparse matrix.
200+ void set_D_sparse (const std::vector<std::vector<uint32_t >> &D_sparse);
201+
202+ // / @brief Set the D_sparse matrix, using a single long vector with -1 as row
203+ // / terminators.
204+ void set_D_sparse (const std::vector<int64_t > &D_sparse);
205+
206+ // / @brief Set the decoder id.
207+ void set_decoder_id (uint32_t decoder_id);
208+
209+ // / @brief Get the decoder id.
210+ uint32_t get_decoder_id () const ;
211+
212+ // / @brief Enqueue a syndrome for decoding (pointer version)
213+ // / @return True if enough syndromes have been enqueued to trigger a decode.
214+ bool enqueue_syndrome (const uint8_t *syndrome, std::size_t syndrome_length);
215+
216+ // / @brief Enqueue a syndrome for decoding (vector version)
217+ // / @return True if enough syndromes have been enqueued to trigger a decode.
218+ bool enqueue_syndrome (const std::vector<uint8_t > &syndrome);
219+
220+ // / @brief Get the current observable corrections.
221+ const uint8_t *get_obs_corrections () const ;
222+
223+ // / @brief Get the number of observables.
224+ std::size_t get_num_observables () const ;
225+
226+ // / @brief Clear any stored corrections.
227+ void clear_corrections ();
228+
229+ // / @brief Reset the decoder, clearing all per-shot memory and corrections.
230+ void reset_decoder ();
231+
232+ // -- End realtime decoding API --
233+
176234 // / @brief Destructor
177- virtual ~decoder () {}
235+ virtual ~decoder () = default ;
178236
179237 // / @brief Get the version of the decoder. Subclasses that are not part of the
180238 // / standard GitHub repo should override this to provide a more tailored
@@ -191,6 +249,12 @@ class decoder
191249
192250 // / @brief The decoder's parity check matrix
193251 cudaqx::tensor<uint8_t > H;
252+
253+ // / @brief The decoder's observable matrix in sparse format
254+ std::vector<std::vector<uint32_t >> O_sparse;
255+
256+ // / @brief The decoder's D matrix in sparse format
257+ std::vector<std::vector<uint32_t >> D_sparse;
194258};
195259
196260// / @brief Convert a vector of soft probabilities to a vector of hard
@@ -243,6 +307,7 @@ inline void convert_vec_soft_to_tensor_hard(const std::vector<t_soft> &in,
243307// / @brief Convert a vector of hard probabilities to a vector of soft
244308// / probabilities.
245309// / @param in Hard probability input vector containing only 0/false or 1/true.
310+ // / @param in_size The size of the input vector (in elements)
246311// / @param out Soft probability output vector in the range [0.0, 1.0]
247312// / @param true_val The soft probability value assigned when the input is 1
248313// / (default to 1.0)
@@ -253,15 +318,35 @@ template <typename t_soft, typename t_hard,
253318 (std::is_integral<t_hard>::value ||
254319 std::is_same<t_hard, bool >::value),
255320 int >::type = 0 >
256- inline void convert_vec_hard_to_soft (const std::vector<t_hard> &in ,
321+ inline void convert_vec_hard_to_soft (const t_hard *in, std::size_t in_size ,
257322 std::vector<t_soft> &out,
258323 const t_soft true_val = 1.0 ,
259324 const t_soft false_val = 0.0 ) {
260- out.resize (in. size () );
261- for (std::size_t i = 0 ; i < in. size () ; i++)
325+ out.resize (in_size );
326+ for (std::size_t i = 0 ; i < in_size ; i++)
262327 out[i] = static_cast <t_soft>(in[i] ? true_val : false_val);
263328}
264329
330+ // / @brief Convert a vector of hard probabilities to a vector of soft
331+ // / probabilities.
332+ // / @param in Hard probability input vector containing only 0/false or 1/true.
333+ // / @param out Soft probability output vector in the range [0.0, 1.0]
334+ // / @param true_val The soft probability value assigned when the input is 1
335+ // / (default to 1.0)
336+ // / @param false_val The soft probability value assigned when the input is 0
337+ // / (default to 0.0)
338+ template <typename t_soft, typename t_hard,
339+ typename std::enable_if<std::is_floating_point<t_soft>::value &&
340+ (std::is_integral<t_hard>::value ||
341+ std::is_same<t_hard, bool >::value),
342+ int >::type = 0 >
343+ inline void convert_vec_hard_to_soft (const std::vector<t_hard> &in,
344+ std::vector<t_soft> &out,
345+ const t_soft true_val = 1.0 ,
346+ const t_soft false_val = 0.0 ) {
347+ convert_vec_hard_to_soft (in.data (), in.size (), out, true_val, false_val);
348+ }
349+
265350// / @brief Convert a 2D vector of soft probabilities to a 2D vector of hard
266351// / probabilities.
267352// / @param in Soft probability input vector in range [0.0, 1.0]
0 commit comments