Skip to main content

stim_cxx/
lib.rs

1#![allow(clippy::too_many_arguments)]
2
3#[allow(unused_imports)]
4use core::pin::Pin;
5use cxx::UniquePtr;
6
7pub use ffi::{
8    BitTableData, CircuitErrorLocationData, CircuitErrorLocationStackFrameData,
9    CircuitTargetsInsideInstructionData, CircuitTopLevelItemData, CoordinateEntryData,
10    DemSampleBatch, DemTargetWithCoordsData, DemTopLevelItemData, DetectingRegionEntryData,
11    ExplainedErrorData, FlippedMeasurementData, GateTargetWithCoordsData,
12};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct BuildMetadata {
16    pub crate_name: &'static str,
17    pub cxx_standard: &'static str,
18    pub target: &'static str,
19    pub vendor_stim_mode: &'static str,
20    pub vendor_stim_dir: &'static str,
21}
22
23pub fn build_metadata() -> BuildMetadata {
24    BuildMetadata {
25        crate_name: env!("CARGO_PKG_NAME"),
26        cxx_standard: env!("STIM_RS_CXX_STANDARD"),
27        target: env!("STIM_RS_TARGET"),
28        vendor_stim_mode: env!("STIM_RS_VENDOR_STIM_MODE"),
29        vendor_stim_dir: env!("STIM_RS_VENDOR_STIM_DIR"),
30    }
31}
32
33pub fn pinned_stim_commit() -> &'static str {
34    env!("STIM_RS_PINNED_STIM_COMMIT")
35}
36
37pub fn read_shot_data_file_bit_packed(
38    filepath: &str,
39    format_name: &str,
40    num_measurements: u64,
41    num_detectors: u64,
42    num_observables: u64,
43) -> Result<Vec<u8>, cxx::Exception> {
44    ffi::read_shot_data_file_bit_packed(
45        filepath,
46        format_name,
47        num_measurements,
48        num_detectors,
49        num_observables,
50    )
51}
52
53pub fn write_shot_data_file_bit_packed(
54    data: &[u8],
55    shots: u64,
56    filepath: &str,
57    format_name: &str,
58    num_measurements: u64,
59    num_detectors: u64,
60    num_observables: u64,
61) -> Result<(), cxx::Exception> {
62    ffi::write_shot_data_file_bit_packed(
63        data,
64        shots,
65        filepath,
66        format_name,
67        num_measurements,
68        num_detectors,
69        num_observables,
70    )
71}
72
73pub fn all_gate_names() -> Vec<String> {
74    ffi::all_gate_names()
75}
76
77pub fn canonicalize_flow_text(text: &str) -> Result<String, cxx::Exception> {
78    ffi::canonicalize_flow_text(text)
79}
80
81pub fn multiply_flow_texts(left: &str, right: &str) -> Result<String, cxx::Exception> {
82    ffi::multiply_flow_texts(left, right)
83}
84
85pub struct Circuit {
86    inner: UniquePtr<ffi::CircuitHandle>,
87}
88
89pub struct DetectorErrorModel {
90    inner: UniquePtr<ffi::DetectorErrorModelHandle>,
91}
92
93pub struct Tableau {
94    inner: UniquePtr<ffi::TableauHandle>,
95}
96
97pub struct TableauSimulator {
98    inner: UniquePtr<ffi::TableauSimulatorHandle>,
99}
100
101pub struct FlipSimulator {
102    inner: UniquePtr<ffi::FrameSimulatorHandle>,
103}
104
105pub struct PauliString {
106    inner: UniquePtr<ffi::PauliStringHandle>,
107}
108
109pub struct CliffordString {
110    inner: UniquePtr<ffi::CliffordStringHandle>,
111}
112
113pub struct PauliStringIterator {
114    inner: UniquePtr<ffi::PauliStringIteratorHandle>,
115}
116
117pub struct TableauIterator {
118    inner: UniquePtr<ffi::TableauIteratorHandle>,
119}
120
121pub struct MeasurementSampler {
122    inner: UniquePtr<ffi::MeasurementSamplerHandle>,
123}
124
125pub struct DetectorSampler {
126    inner: UniquePtr<ffi::DetectorSamplerHandle>,
127}
128
129pub struct DemSampler {
130    inner: UniquePtr<ffi::DemSamplerHandle>,
131}
132
133pub struct MeasurementsToDetectionEventsConverter {
134    inner: UniquePtr<ffi::MeasurementsToDetectionEventsConverterHandle>,
135}
136
137pub struct GateData {
138    inner: UniquePtr<ffi::GateDataHandle>,
139}
140
141impl MeasurementSampler {
142    #[must_use]
143    pub fn num_measurements(&self) -> u64 {
144        ffi::measurement_sampler_num_measurements(self.inner())
145    }
146
147    #[must_use]
148    pub fn sample_bit_packed(&mut self, shots: u64) -> Vec<u8> {
149        ffi::measurement_sampler_sample_bit_packed(self.inner.pin_mut(), shots)
150    }
151
152    pub fn sample_write(
153        &mut self,
154        shots: u64,
155        filepath: &str,
156        format_name: &str,
157    ) -> Result<(), cxx::Exception> {
158        ffi::measurement_sampler_sample_write(self.inner.pin_mut(), shots, filepath, format_name)
159    }
160
161    fn inner(&self) -> &ffi::MeasurementSamplerHandle {
162        self.inner
163            .as_ref()
164            .expect("stim-cxx measurement sampler construction returned null")
165    }
166}
167
168impl DetectorSampler {
169    #[must_use]
170    pub fn num_detectors(&self) -> u64 {
171        ffi::detector_sampler_num_detectors(self.inner())
172    }
173
174    #[must_use]
175    pub fn num_observables(&self) -> u64 {
176        ffi::detector_sampler_num_observables(self.inner())
177    }
178
179    #[must_use]
180    pub fn sample_bit_packed(&mut self, shots: u64) -> Vec<u8> {
181        ffi::detector_sampler_sample_bit_packed(self.inner.pin_mut(), shots)
182    }
183
184    #[must_use]
185    pub fn sample_observables_bit_packed(&mut self, shots: u64) -> Vec<u8> {
186        ffi::detector_sampler_sample_observables_bit_packed(self.inner.pin_mut(), shots)
187    }
188
189    #[must_use]
190    pub fn sample_bit_packed_separate_observables(&mut self, shots: u64) -> (Vec<u8>, Vec<u8>) {
191        let batch = ffi::detector_sampler_sample_bit_packed_separate_observables(
192            self.inner.pin_mut(),
193            shots,
194        );
195        (batch.detectors, batch.observables)
196    }
197
198    pub fn sample_write(
199        &mut self,
200        shots: u64,
201        filepath: &str,
202        format_name: &str,
203    ) -> Result<(), cxx::Exception> {
204        ffi::detector_sampler_sample_write(self.inner.pin_mut(), shots, filepath, format_name)
205    }
206
207    pub fn sample_write_separate_observables(
208        &mut self,
209        shots: u64,
210        dets_filepath: &str,
211        dets_format_name: &str,
212        obs_filepath: &str,
213        obs_format_name: &str,
214    ) -> Result<(), cxx::Exception> {
215        ffi::detector_sampler_sample_write_separate_observables(
216            self.inner.pin_mut(),
217            shots,
218            dets_filepath,
219            dets_format_name,
220            obs_filepath,
221            obs_format_name,
222        )
223    }
224
225    fn inner(&self) -> &ffi::DetectorSamplerHandle {
226        self.inner
227            .as_ref()
228            .expect("stim-cxx detector sampler construction returned null")
229    }
230}
231
232impl DemSampler {
233    #[must_use]
234    pub fn num_detectors(&self) -> u64 {
235        ffi::dem_sampler_num_detectors(self.inner())
236    }
237
238    #[must_use]
239    pub fn num_observables(&self) -> u64 {
240        ffi::dem_sampler_num_observables(self.inner())
241    }
242
243    #[must_use]
244    pub fn num_errors(&self) -> u64 {
245        ffi::dem_sampler_num_errors(self.inner())
246    }
247
248    #[must_use]
249    pub fn sample_bit_packed(&mut self, shots: u64) -> ffi::DemSampleBatch {
250        ffi::dem_sampler_sample_bit_packed(self.inner.pin_mut(), shots)
251    }
252
253    pub fn sample_bit_packed_replay(
254        &mut self,
255        recorded_errors: &[u8],
256        shots: u64,
257    ) -> ffi::DemSampleBatch {
258        ffi::dem_sampler_sample_bit_packed_replay(self.inner.pin_mut(), recorded_errors, shots)
259    }
260
261    pub fn sample_write(
262        &mut self,
263        shots: u64,
264        dets_filepath: &str,
265        dets_format_name: &str,
266        obs_filepath: &str,
267        obs_format_name: &str,
268        err_filepath: &str,
269        err_format_name: &str,
270        write_errors: bool,
271    ) -> Result<(), cxx::Exception> {
272        ffi::dem_sampler_sample_write(
273            self.inner.pin_mut(),
274            shots,
275            dets_filepath,
276            dets_format_name,
277            obs_filepath,
278            obs_format_name,
279            err_filepath,
280            err_format_name,
281            write_errors,
282            "",
283            "01",
284            false,
285        )
286    }
287
288    pub fn sample_write_replay(
289        &mut self,
290        shots: u64,
291        dets_filepath: &str,
292        dets_format_name: &str,
293        obs_filepath: &str,
294        obs_format_name: &str,
295        err_filepath: &str,
296        err_format_name: &str,
297        write_errors: bool,
298        replay_err_filepath: &str,
299        replay_err_format_name: &str,
300    ) -> Result<(), cxx::Exception> {
301        ffi::dem_sampler_sample_write(
302            self.inner.pin_mut(),
303            shots,
304            dets_filepath,
305            dets_format_name,
306            obs_filepath,
307            obs_format_name,
308            err_filepath,
309            err_format_name,
310            write_errors,
311            replay_err_filepath,
312            replay_err_format_name,
313            true,
314        )
315    }
316
317    fn inner(&self) -> &ffi::DemSamplerHandle {
318        self.inner
319            .as_ref()
320            .expect("stim-cxx DEM sampler construction returned null")
321    }
322}
323
324impl MeasurementsToDetectionEventsConverter {
325    fn inner(&self) -> &ffi::MeasurementsToDetectionEventsConverterHandle {
326        self.inner
327            .as_ref()
328            .expect("stim-cxx M2D converter construction returned null")
329    }
330
331    #[must_use]
332    pub fn num_measurements(&self) -> u64 {
333        ffi::m2d_converter_num_measurements(self.inner())
334    }
335
336    #[must_use]
337    pub fn num_detectors(&self) -> u64 {
338        ffi::m2d_converter_num_detectors(self.inner())
339    }
340
341    #[must_use]
342    pub fn num_observables(&self) -> u64 {
343        ffi::m2d_converter_num_observables(self.inner())
344    }
345
346    #[must_use]
347    pub fn num_sweep_bits(&self) -> u64 {
348        ffi::m2d_converter_num_sweep_bits(self.inner())
349    }
350
351    pub fn convert_measurements_bit_packed(
352        &mut self,
353        measurements: &[u8],
354        shots: u64,
355        append_observables: bool,
356    ) -> Vec<u8> {
357        ffi::m2d_converter_convert_measurements_bit_packed(
358            self.inner.pin_mut(),
359            measurements,
360            shots,
361            append_observables,
362        )
363    }
364
365    pub fn convert_measurements_and_sweep_bits_bit_packed(
366        &mut self,
367        measurements: &[u8],
368        sweep_bits: &[u8],
369        shots: u64,
370        append_observables: bool,
371    ) -> Vec<u8> {
372        ffi::m2d_converter_convert_measurements_and_sweep_bits_bit_packed(
373            self.inner.pin_mut(),
374            measurements,
375            sweep_bits,
376            shots,
377            append_observables,
378        )
379    }
380
381    pub fn convert_observables_with_sweep_bits_bit_packed(
382        &mut self,
383        measurements: &[u8],
384        sweep_bits: &[u8],
385        shots: u64,
386    ) -> Vec<u8> {
387        ffi::m2d_converter_convert_observables_with_sweep_bits_bit_packed(
388            self.inner.pin_mut(),
389            measurements,
390            sweep_bits,
391            shots,
392        )
393    }
394
395    pub fn convert_observables_bit_packed(&mut self, measurements: &[u8], shots: u64) -> Vec<u8> {
396        ffi::m2d_converter_convert_observables_bit_packed(self.inner.pin_mut(), measurements, shots)
397    }
398
399    pub fn convert_file(
400        &mut self,
401        measurements_filepath: &str,
402        measurements_format: &str,
403        sweep_bits_filepath: &str,
404        sweep_bits_format: &str,
405        detection_events_filepath: &str,
406        detection_events_format: &str,
407        append_observables: bool,
408        obs_out_filepath: &str,
409        obs_out_format: &str,
410    ) -> Result<(), cxx::Exception> {
411        ffi::m2d_converter_convert_file(
412            self.inner.pin_mut(),
413            measurements_filepath,
414            measurements_format,
415            sweep_bits_filepath,
416            sweep_bits_format,
417            detection_events_filepath,
418            detection_events_format,
419            append_observables,
420            obs_out_filepath,
421            obs_out_format,
422        )
423    }
424}
425
426impl GateData {
427    #[must_use]
428    pub fn name(&self) -> String {
429        self.inner().name()
430    }
431
432    #[must_use]
433    pub fn aliases(&self) -> Vec<String> {
434        self.inner().aliases()
435    }
436
437    #[must_use]
438    pub fn num_parens_arguments_range(&self) -> Vec<u8> {
439        self.inner().num_parens_arguments_range()
440    }
441
442    #[must_use]
443    pub fn is_noisy_gate(&self) -> bool {
444        self.inner().is_noisy_gate()
445    }
446
447    #[must_use]
448    pub fn is_reset(&self) -> bool {
449        self.inner().is_reset()
450    }
451
452    #[must_use]
453    pub fn is_single_qubit_gate(&self) -> bool {
454        self.inner().is_single_qubit_gate()
455    }
456
457    #[must_use]
458    pub fn is_symmetric_gate(&self) -> bool {
459        self.inner().is_symmetric_gate()
460    }
461
462    #[must_use]
463    pub fn is_two_qubit_gate(&self) -> bool {
464        self.inner().is_two_qubit_gate()
465    }
466
467    #[must_use]
468    pub fn is_unitary(&self) -> bool {
469        self.inner().is_unitary()
470    }
471
472    #[must_use]
473    pub fn produces_measurements(&self) -> bool {
474        self.inner().produces_measurements()
475    }
476
477    #[must_use]
478    pub fn takes_measurement_record_targets(&self) -> bool {
479        self.inner().takes_measurement_record_targets()
480    }
481
482    #[must_use]
483    pub fn takes_pauli_targets(&self) -> bool {
484        self.inner().takes_pauli_targets()
485    }
486
487    pub fn flows(&self) -> Vec<String> {
488        self.inner().flows()
489    }
490
491    #[must_use]
492    pub fn tableau(&self) -> Option<Tableau> {
493        let inner = self.inner().tableau();
494        if inner.is_null() {
495            None
496        } else {
497            Some(Tableau { inner })
498        }
499    }
500
501    #[must_use]
502    pub fn clone_handle(&self) -> Self {
503        Self {
504            inner: self.inner().clone_handle(),
505        }
506    }
507
508    #[must_use]
509    pub fn inverse(&self) -> Option<Self> {
510        let inner = self.inner().inverse();
511        if inner.is_null() {
512            None
513        } else {
514            Some(Self { inner })
515        }
516    }
517
518    #[must_use]
519    pub fn generalized_inverse(&self) -> Self {
520        Self {
521            inner: self.inner().generalized_inverse(),
522        }
523    }
524
525    #[must_use]
526    pub fn hadamard_conjugated(&self, unsigned_only: bool) -> Option<Self> {
527        let inner = self.inner().hadamard_conjugated(unsigned_only);
528        if inner.is_null() {
529            None
530        } else {
531            Some(Self { inner })
532        }
533    }
534
535    fn inner(&self) -> &ffi::GateDataHandle {
536        self.inner
537            .as_ref()
538            .expect("stim-cxx gate data construction returned null")
539    }
540}
541
542pub fn gate_data(name: &str) -> Result<GateData, cxx::Exception> {
543    ffi::gate_data_by_name(name).map(|inner| GateData { inner })
544}
545
546impl Circuit {
547    #[must_use]
548    pub fn new() -> Self {
549        Self {
550            inner: ffi::new_circuit(),
551        }
552    }
553
554    pub fn from_stim_program_text(text: &str) -> Result<Self, cxx::Exception> {
555        ffi::circuit_from_stim_program_text(text).map(|inner| Self { inner })
556    }
557
558    pub fn generated(
559        code_task: &str,
560        distance: usize,
561        rounds: usize,
562        after_clifford_depolarization: f64,
563        before_round_data_depolarization: f64,
564        before_measure_flip_probability: f64,
565        after_reset_flip_probability: f64,
566    ) -> Result<Self, cxx::Exception> {
567        ffi::circuit_generated(
568            code_task,
569            distance,
570            rounds,
571            after_clifford_depolarization,
572            before_round_data_depolarization,
573            before_measure_flip_probability,
574            after_reset_flip_probability,
575        )
576        .map(|inner| Self { inner })
577    }
578
579    pub fn has_flow(&self, flow: &str, unsigned: bool) -> Result<bool, cxx::Exception> {
580        ffi::circuit_has_flow_text(self.inner(), flow, unsigned)
581    }
582
583    pub fn has_all_flows(
584        &self,
585        flows: Vec<String>,
586        unsigned: bool,
587    ) -> Result<bool, cxx::Exception> {
588        ffi::circuit_has_all_flows_text(self.inner(), flows, unsigned)
589    }
590
591    pub fn flow_generators(&self) -> Vec<String> {
592        ffi::circuit_flow_generators_texts(self.inner())
593    }
594
595    pub fn solve_flow_measurements(
596        &self,
597        flows: Vec<String>,
598    ) -> Result<Vec<String>, cxx::Exception> {
599        ffi::circuit_solve_flow_measurements_text(self.inner(), flows)
600    }
601
602    pub fn time_reversed_for_flows(
603        &self,
604        flows: Vec<String>,
605        dont_turn_measurements_into_resets: bool,
606    ) -> Result<(String, Vec<String>), cxx::Exception> {
607        let mut out_flow_texts = Vec::new();
608        let circuit_text = ffi::circuit_time_reversed_for_flows_text(
609            &mut out_flow_texts,
610            self.inner(),
611            flows,
612            dont_turn_measurements_into_resets,
613        )?;
614        Ok((circuit_text, out_flow_texts))
615    }
616
617    pub fn detector_error_model(
618        &self,
619        decompose_errors: bool,
620        flatten_loops: bool,
621        allow_gauge_detectors: bool,
622        approximate_disjoint_errors: f64,
623        ignore_decomposition_failures: bool,
624        block_decomposition_from_introducing_remnant_edges: bool,
625    ) -> Result<DetectorErrorModel, cxx::Exception> {
626        ffi::circuit_detector_error_model(
627            self.inner(),
628            decompose_errors,
629            flatten_loops,
630            allow_gauge_detectors,
631            approximate_disjoint_errors,
632            ignore_decomposition_failures,
633            block_decomposition_from_introducing_remnant_edges,
634        )
635        .map(|inner| DetectorErrorModel { inner })
636    }
637
638    #[must_use]
639    pub fn missing_detectors(&self, unknown_input: bool) -> Self {
640        Self {
641            inner: ffi::circuit_missing_detectors(self.inner(), unknown_input),
642        }
643    }
644
645    pub fn to_tableau(
646        &self,
647        ignore_noise: bool,
648        ignore_measurement: bool,
649        ignore_reset: bool,
650    ) -> Result<Tableau, cxx::Exception> {
651        ffi::circuit_to_tableau(self.inner(), ignore_noise, ignore_measurement, ignore_reset)
652            .map(|inner| Tableau { inner })
653    }
654
655    #[must_use]
656    pub fn add(&self, other: &Self) -> Self {
657        Self {
658            inner: ffi::circuit_add(self.inner(), other.inner()),
659        }
660    }
661
662    pub fn add_assign(&mut self, other: &Self) {
663        ffi::circuit_add_assign(self.inner.pin_mut(), other.inner());
664    }
665
666    #[must_use]
667    pub fn repeat(&self, repetitions: u64) -> Self {
668        Self {
669            inner: ffi::circuit_mul(self.inner(), repetitions),
670        }
671    }
672
673    pub fn repeat_assign(&mut self, repetitions: u64) {
674        ffi::circuit_mul_assign(self.inner.pin_mut(), repetitions);
675    }
676
677    #[must_use]
678    pub fn to_stim_program_text(&self) -> String {
679        ffi::circuit_to_stim_program_text(self.inner())
680    }
681
682    #[must_use]
683    pub fn num_qubits(&self) -> usize {
684        ffi::circuit_num_qubits(self.inner())
685    }
686
687    #[must_use]
688    pub fn len(&self) -> usize {
689        ffi::circuit_len(self.inner())
690    }
691
692    #[must_use]
693    pub fn top_level_item(&self, index: usize) -> ffi::CircuitTopLevelItemData {
694        ffi::circuit_get_top_level_item(self.inner(), index)
695    }
696
697    #[must_use]
698    pub fn top_level_repeat_block_body(&self, index: usize) -> Self {
699        Self {
700            inner: ffi::circuit_get_top_level_repeat_block_body(self.inner(), index),
701        }
702    }
703
704    #[must_use]
705    pub fn get_slice(&self, start: i64, step: i64, slice_length: i64) -> Self {
706        Self {
707            inner: ffi::circuit_get_slice(self.inner(), start, step, slice_length),
708        }
709    }
710
711    pub fn remove_top_level(&mut self, index: usize) {
712        ffi::circuit_remove_top_level(self.inner.pin_mut(), index);
713    }
714
715    #[must_use]
716    pub fn is_empty(&self) -> bool {
717        self.len() == 0
718    }
719
720    #[must_use]
721    pub fn num_measurements(&self) -> u64 {
722        ffi::circuit_num_measurements(self.inner())
723    }
724
725    #[must_use]
726    pub fn count_determined_measurements(&self, unknown_input: bool) -> u64 {
727        ffi::circuit_count_determined_measurements(self.inner(), unknown_input)
728    }
729
730    #[must_use]
731    pub fn num_detectors(&self) -> u64 {
732        ffi::circuit_num_detectors(self.inner())
733    }
734
735    #[must_use]
736    pub fn num_observables(&self) -> u64 {
737        ffi::circuit_num_observables(self.inner())
738    }
739
740    #[must_use]
741    pub fn num_ticks(&self) -> u64 {
742        ffi::circuit_num_ticks(self.inner())
743    }
744
745    #[must_use]
746    pub fn num_sweep_bits(&self) -> usize {
747        ffi::circuit_num_sweep_bits(self.inner())
748    }
749
750    pub fn clear(&mut self) {
751        ffi::circuit_clear(self.inner.pin_mut());
752    }
753
754    pub fn append_from_stim_program_text(&mut self, text: &str) -> Result<(), cxx::Exception> {
755        ffi::circuit_append_from_stim_program_text(self.inner.pin_mut(), text)
756    }
757
758    pub fn append(
759        &mut self,
760        gate_name: &str,
761        targets: &[u32],
762        args: &[f64],
763    ) -> Result<(), cxx::Exception> {
764        self.append_with_tag(gate_name, targets, args, "")
765    }
766
767    pub fn append_with_tag(
768        &mut self,
769        gate_name: &str,
770        targets: &[u32],
771        args: &[f64],
772        tag: &str,
773    ) -> Result<(), cxx::Exception> {
774        ffi::circuit_append_gate(self.inner.pin_mut(), gate_name, targets, args, tag)
775    }
776
777    pub fn append_repeat_block(
778        &mut self,
779        repeat_count: u64,
780        body: &Self,
781        tag: &str,
782    ) -> Result<(), cxx::Exception> {
783        ffi::circuit_append_repeat_block(self.inner.pin_mut(), repeat_count, body.inner(), tag)
784    }
785
786    pub fn insert_with_tag(
787        &mut self,
788        index: usize,
789        gate_name: &str,
790        targets: &[u32],
791        args: &[f64],
792        tag: &str,
793    ) -> Result<(), cxx::Exception> {
794        ffi::circuit_insert_gate(self.inner.pin_mut(), index, gate_name, targets, args, tag)
795    }
796
797    pub fn insert_repeat_block(
798        &mut self,
799        index: usize,
800        repeat_count: u64,
801        body: &Self,
802        tag: &str,
803    ) -> Result<(), cxx::Exception> {
804        ffi::circuit_insert_repeat_block(
805            self.inner.pin_mut(),
806            index,
807            repeat_count,
808            body.inner(),
809            tag,
810        )
811    }
812
813    pub fn insert_circuit(&mut self, index: usize, circuit: &Self) {
814        ffi::circuit_insert_circuit(self.inner.pin_mut(), index, circuit.inner());
815    }
816
817    #[must_use]
818    pub fn approx_equals(&self, other: &Self, atol: f64) -> bool {
819        ffi::circuit_approx_equals(self.inner(), other.inner(), atol)
820    }
821
822    #[must_use]
823    pub fn equals(&self, other: &Self) -> bool {
824        ffi::circuit_equals(self.inner(), other.inner())
825    }
826
827    #[must_use]
828    pub fn without_noise(&self) -> Self {
829        Self {
830            inner: ffi::circuit_without_noise(self.inner()),
831        }
832    }
833
834    #[must_use]
835    pub fn with_inlined_feedback(&self) -> Self {
836        Self {
837            inner: ffi::circuit_with_inlined_feedback(self.inner()),
838        }
839    }
840
841    #[must_use]
842    pub fn without_tags(&self) -> Self {
843        Self {
844            inner: ffi::circuit_without_tags(self.inner()),
845        }
846    }
847
848    #[must_use]
849    pub fn flattened(&self) -> Self {
850        Self {
851            inner: ffi::circuit_flattened(self.inner()),
852        }
853    }
854
855    #[must_use]
856    pub fn decomposed(&self) -> Self {
857        Self {
858            inner: ffi::circuit_decomposed(self.inner()),
859        }
860    }
861
862    pub fn inverse(&self) -> Result<Self, cxx::Exception> {
863        ffi::circuit_inverse(self.inner()).map(|inner| Self { inner })
864    }
865
866    pub fn to_qasm(
867        &self,
868        open_qasm_version: i32,
869        skip_dets_and_obs: bool,
870    ) -> Result<String, cxx::Exception> {
871        ffi::circuit_to_qasm(self.inner(), open_qasm_version, skip_dets_and_obs)
872    }
873
874    pub fn to_quirk_url(&self) -> Result<String, cxx::Exception> {
875        ffi::circuit_to_quirk_url(self.inner())
876    }
877
878    pub fn to_crumble_url(&self, skip_detectors: bool) -> Result<String, cxx::Exception> {
879        ffi::circuit_to_crumble_url(self.inner(), skip_detectors)
880    }
881
882    pub fn shortest_error_sat_problem(&self, format_name: &str) -> Result<String, cxx::Exception> {
883        ffi::circuit_shortest_error_sat_problem(self.inner(), format_name)
884    }
885
886    pub fn likeliest_error_sat_problem(
887        &self,
888        quantization: i32,
889        format_name: &str,
890    ) -> Result<String, cxx::Exception> {
891        ffi::circuit_likeliest_error_sat_problem(self.inner(), quantization, format_name)
892    }
893
894    pub fn detecting_regions(&self) -> Result<Vec<ffi::DetectingRegionEntryData>, cxx::Exception> {
895        ffi::circuit_detecting_regions(self.inner())
896    }
897
898    pub fn detecting_regions_with_options(
899        &self,
900        target_texts: Vec<String>,
901        ticks: Vec<u64>,
902        ignore_anticommutation_errors: bool,
903    ) -> Result<Vec<ffi::DetectingRegionEntryData>, cxx::Exception> {
904        ffi::circuit_detecting_regions_with_options(
905            self.inner(),
906            target_texts,
907            ticks,
908            ignore_anticommutation_errors,
909        )
910    }
911
912    pub fn explain_detector_error_model_errors(
913        &self,
914        dem_filter_text: &str,
915        has_dem_filter: bool,
916        reduce_to_one_representative_error: bool,
917    ) -> Result<Vec<ffi::ExplainedErrorData>, cxx::Exception> {
918        ffi::circuit_explain_detector_error_model_errors(
919            self.inner(),
920            dem_filter_text,
921            has_dem_filter,
922            reduce_to_one_representative_error,
923        )
924    }
925
926    pub fn flattened_operation_texts(&self) -> Vec<String> {
927        ffi::circuit_flattened_operation_texts(self.inner())
928    }
929
930    pub fn shortest_graphlike_error(
931        &self,
932        ignore_ungraphlike_errors: bool,
933        canonicalize_circuit_errors: bool,
934    ) -> Result<Vec<ffi::ExplainedErrorData>, cxx::Exception> {
935        ffi::circuit_shortest_graphlike_error(
936            self.inner(),
937            ignore_ungraphlike_errors,
938            canonicalize_circuit_errors,
939        )
940    }
941
942    pub fn search_for_undetectable_logical_errors(
943        &self,
944        dont_explore_detection_event_sets_with_size_above: u64,
945        dont_explore_edges_with_degree_above: u64,
946        dont_explore_edges_increasing_symptom_degree: bool,
947        canonicalize_circuit_errors: bool,
948    ) -> Result<Vec<ffi::ExplainedErrorData>, cxx::Exception> {
949        ffi::circuit_search_for_undetectable_logical_errors(
950            self.inner(),
951            dont_explore_detection_event_sets_with_size_above,
952            dont_explore_edges_with_degree_above,
953            dont_explore_edges_increasing_symptom_degree,
954            canonicalize_circuit_errors,
955        )
956    }
957
958    pub fn get_detector_coordinates(
959        &self,
960        included_detector_indices: &[u64],
961    ) -> Result<Vec<ffi::CoordinateEntryData>, cxx::Exception> {
962        ffi::circuit_get_detector_coordinates(self.inner(), included_detector_indices)
963    }
964
965    pub fn get_final_qubit_coordinates(
966        &self,
967    ) -> Result<Vec<ffi::CoordinateEntryData>, cxx::Exception> {
968        ffi::circuit_get_final_qubit_coordinates(self.inner())
969    }
970
971    pub fn diagram(&self, type_name: &str) -> Result<String, cxx::Exception> {
972        ffi::circuit_diagram(self.inner(), type_name)
973    }
974
975    pub fn diagram_with_options(
976        &self,
977        type_name: &str,
978        tick_range: Option<(u64, u64)>,
979        rows: Option<usize>,
980    ) -> Result<String, cxx::Exception> {
981        ffi::circuit_diagram_with_options(
982            self.inner(),
983            type_name,
984            tick_range.is_some(),
985            tick_range.map(|(start, _)| start).unwrap_or(0),
986            tick_range.map(|(_, count)| count).unwrap_or(0),
987            rows.is_some(),
988            rows.unwrap_or(0),
989        )
990    }
991
992    pub fn diagram_with_options_and_filters(
993        &self,
994        type_name: &str,
995        tick_range: Option<(u64, u64)>,
996        rows: Option<usize>,
997        filter_coords: Vec<String>,
998    ) -> Result<String, cxx::Exception> {
999        ffi::circuit_diagram_with_options_and_filters(
1000            self.inner(),
1001            type_name,
1002            tick_range.is_some(),
1003            tick_range.map(|(start, _)| start).unwrap_or(0),
1004            tick_range.map(|(_, count)| count).unwrap_or(0),
1005            rows.is_some(),
1006            rows.unwrap_or(0),
1007            filter_coords,
1008        )
1009    }
1010
1011    #[must_use]
1012    pub fn reference_sample_bit_packed(&self) -> Vec<u8> {
1013        ffi::circuit_reference_sample_bit_packed(self.inner())
1014    }
1015
1016    #[must_use]
1017    pub fn reference_detector_signs_bit_packed(&self) -> Vec<u8> {
1018        ffi::circuit_reference_detector_signs_bit_packed(self.inner())
1019    }
1020
1021    #[must_use]
1022    pub fn reference_observable_signs_bit_packed(&self) -> Vec<u8> {
1023        ffi::circuit_reference_observable_signs_bit_packed(self.inner())
1024    }
1025
1026    #[must_use]
1027    pub fn compile_sampler(&self, skip_reference_sample: bool) -> MeasurementSampler {
1028        self.compile_sampler_with_seed(skip_reference_sample, 0)
1029    }
1030
1031    #[must_use]
1032    pub fn compile_sampler_with_seed(
1033        &self,
1034        skip_reference_sample: bool,
1035        seed: u64,
1036    ) -> MeasurementSampler {
1037        MeasurementSampler {
1038            inner: ffi::circuit_compile_sampler(self.inner(), skip_reference_sample, seed),
1039        }
1040    }
1041
1042    #[must_use]
1043    pub fn compile_detector_sampler_with_seed(&self, seed: u64) -> DetectorSampler {
1044        DetectorSampler {
1045            inner: ffi::circuit_compile_detector_sampler(self.inner(), seed),
1046        }
1047    }
1048
1049    pub fn compile_m2d_converter(
1050        &self,
1051        skip_reference_sample: bool,
1052    ) -> MeasurementsToDetectionEventsConverter {
1053        MeasurementsToDetectionEventsConverter {
1054            inner: ffi::circuit_compile_m2d_converter(self.inner(), skip_reference_sample),
1055        }
1056    }
1057
1058    fn inner(&self) -> &ffi::CircuitHandle {
1059        self.inner
1060            .as_ref()
1061            .expect("stim-cxx circuit construction returned null")
1062    }
1063}
1064
1065impl DetectorErrorModel {
1066    #[must_use]
1067    pub fn new() -> Self {
1068        Self {
1069            inner: ffi::new_detector_error_model(),
1070        }
1071    }
1072
1073    pub fn from_dem_text(text: &str) -> Result<Self, cxx::Exception> {
1074        ffi::detector_error_model_from_dem_text(text).map(|inner| Self { inner })
1075    }
1076
1077    pub fn diagram(&self, type_name: &str) -> Result<String, cxx::Exception> {
1078        ffi::detector_error_model_diagram(self.inner(), type_name)
1079    }
1080
1081    #[must_use]
1082    pub fn add(&self, other: &Self) -> Self {
1083        Self {
1084            inner: ffi::detector_error_model_add(self.inner(), other.inner()),
1085        }
1086    }
1087
1088    pub fn add_assign(&mut self, other: &Self) {
1089        ffi::detector_error_model_add_assign(self.inner.pin_mut(), other.inner());
1090    }
1091
1092    #[must_use]
1093    pub fn repeat(&self, repetitions: u64) -> Self {
1094        Self {
1095            inner: ffi::detector_error_model_mul(self.inner(), repetitions),
1096        }
1097    }
1098
1099    pub fn repeat_assign(&mut self, repetitions: u64) {
1100        ffi::detector_error_model_mul_assign(self.inner.pin_mut(), repetitions);
1101    }
1102
1103    #[must_use]
1104    pub fn to_dem_text(&self) -> String {
1105        ffi::detector_error_model_to_dem_text(self.inner())
1106    }
1107
1108    #[must_use]
1109    pub fn len(&self) -> usize {
1110        ffi::detector_error_model_len(self.inner())
1111    }
1112
1113    #[must_use]
1114    pub fn top_level_item(&self, index: usize) -> ffi::DemTopLevelItemData {
1115        ffi::detector_error_model_get_top_level_item(self.inner(), index)
1116    }
1117
1118    #[must_use]
1119    pub fn top_level_repeat_block_body(&self, index: usize) -> Self {
1120        Self {
1121            inner: ffi::detector_error_model_get_top_level_repeat_block_body(self.inner(), index),
1122        }
1123    }
1124
1125    #[must_use]
1126    pub fn get_slice(&self, start: i64, step: i64, slice_length: i64) -> Self {
1127        Self {
1128            inner: ffi::detector_error_model_get_slice(self.inner(), start, step, slice_length),
1129        }
1130    }
1131
1132    #[must_use]
1133    pub fn is_empty(&self) -> bool {
1134        self.len() == 0
1135    }
1136
1137    #[must_use]
1138    pub fn num_detectors(&self) -> u64 {
1139        ffi::detector_error_model_num_detectors(self.inner())
1140    }
1141
1142    #[must_use]
1143    pub fn num_errors(&self) -> u64 {
1144        ffi::detector_error_model_num_errors(self.inner())
1145    }
1146
1147    #[must_use]
1148    pub fn num_observables(&self) -> u64 {
1149        ffi::detector_error_model_num_observables(self.inner())
1150    }
1151
1152    pub fn get_detector_coordinates(
1153        &self,
1154        included_detector_indices: &[u64],
1155    ) -> Result<Vec<ffi::CoordinateEntryData>, cxx::Exception> {
1156        ffi::detector_error_model_get_detector_coordinates(self.inner(), included_detector_indices)
1157    }
1158
1159    pub fn clear(&mut self) {
1160        ffi::detector_error_model_clear(self.inner.pin_mut());
1161    }
1162
1163    #[must_use]
1164    pub fn approx_equals(&self, other: &Self, atol: f64) -> bool {
1165        ffi::detector_error_model_approx_equals(self.inner(), other.inner(), atol)
1166    }
1167
1168    #[must_use]
1169    pub fn equals(&self, other: &Self) -> bool {
1170        ffi::detector_error_model_equals(self.inner(), other.inner())
1171    }
1172
1173    #[must_use]
1174    pub fn without_tags(&self) -> Self {
1175        Self {
1176            inner: ffi::detector_error_model_without_tags(self.inner()),
1177        }
1178    }
1179
1180    #[must_use]
1181    pub fn flattened(&self) -> Self {
1182        Self {
1183            inner: ffi::detector_error_model_flattened(self.inner()),
1184        }
1185    }
1186
1187    #[must_use]
1188    pub fn rounded(&self, digits: u8) -> Self {
1189        Self {
1190            inner: ffi::detector_error_model_rounded(self.inner(), digits),
1191        }
1192    }
1193
1194    pub fn append_instruction(
1195        &mut self,
1196        instruction_type: &str,
1197        args: &[f64],
1198        targets: &[u64],
1199        tag: &str,
1200    ) -> Result<(), cxx::Exception> {
1201        ffi::detector_error_model_append_instruction(
1202            self.inner.pin_mut(),
1203            instruction_type,
1204            args,
1205            targets,
1206            tag,
1207        )
1208    }
1209
1210    pub fn append_repeat_block(
1211        &mut self,
1212        repeat_count: u64,
1213        body: &Self,
1214    ) -> Result<(), cxx::Exception> {
1215        ffi::detector_error_model_append_repeat_block(
1216            self.inner.pin_mut(),
1217            repeat_count,
1218            body.inner(),
1219        )
1220    }
1221
1222    #[must_use]
1223    pub fn compile_sampler(&self) -> DemSampler {
1224        self.compile_sampler_with_seed(0)
1225    }
1226
1227    #[must_use]
1228    pub fn compile_sampler_with_seed(&self, seed: u64) -> DemSampler {
1229        DemSampler {
1230            inner: ffi::detector_error_model_compile_sampler(self.inner(), seed),
1231        }
1232    }
1233
1234    pub fn shortest_graphlike_error(
1235        &self,
1236        ignore_ungraphlike_errors: bool,
1237    ) -> Result<Self, cxx::Exception> {
1238        ffi::detector_error_model_shortest_graphlike_error(self.inner(), ignore_ungraphlike_errors)
1239            .map(|inner| Self { inner })
1240    }
1241
1242    pub fn shortest_error_sat_problem(&self, format_name: &str) -> Result<String, cxx::Exception> {
1243        ffi::detector_error_model_shortest_error_sat_problem(self.inner(), format_name)
1244    }
1245
1246    pub fn likeliest_error_sat_problem(
1247        &self,
1248        quantization: i32,
1249        format_name: &str,
1250    ) -> Result<String, cxx::Exception> {
1251        ffi::detector_error_model_likeliest_error_sat_problem(
1252            self.inner(),
1253            quantization,
1254            format_name,
1255        )
1256    }
1257
1258    fn inner(&self) -> &ffi::DetectorErrorModelHandle {
1259        self.inner
1260            .as_ref()
1261            .expect("stim-cxx detector error model construction returned null")
1262    }
1263}
1264
1265impl Tableau {
1266    #[must_use]
1267    pub fn new(num_qubits: usize) -> Self {
1268        Self {
1269            inner: ffi::new_tableau(num_qubits),
1270        }
1271    }
1272
1273    #[must_use]
1274    pub fn random(num_qubits: usize) -> Self {
1275        Self {
1276            inner: ffi::tableau_random(num_qubits),
1277        }
1278    }
1279
1280    #[must_use]
1281    pub fn iter_all(num_qubits: usize, unsigned: bool) -> TableauIterator {
1282        TableauIterator {
1283            inner: ffi::tableau_iter_all(num_qubits, unsigned),
1284        }
1285    }
1286
1287    pub fn from_named_gate(name: &str) -> Result<Self, cxx::Exception> {
1288        ffi::tableau_from_named_gate(name).map(|inner| Self { inner })
1289    }
1290
1291    pub fn from_state_vector_data(
1292        state_vector: Vec<f32>,
1293        endian: &str,
1294    ) -> Result<Self, cxx::Exception> {
1295        ffi::tableau_from_state_vector_data(state_vector, endian).map(|inner| Self { inner })
1296    }
1297
1298    pub fn from_unitary_matrix_data(
1299        matrix: Vec<f32>,
1300        endian: &str,
1301    ) -> Result<Self, cxx::Exception> {
1302        ffi::tableau_from_unitary_matrix_data(matrix, endian).map(|inner| Self { inner })
1303    }
1304
1305    pub fn from_conjugated_generator_texts(
1306        xs: Vec<String>,
1307        zs: Vec<String>,
1308    ) -> Result<Self, cxx::Exception> {
1309        ffi::tableau_from_conjugated_generator_texts(xs, zs).map(|inner| Self { inner })
1310    }
1311
1312    pub fn from_stabilizer_texts(
1313        stabilizers: Vec<String>,
1314        allow_redundant: bool,
1315        allow_underconstrained: bool,
1316    ) -> Result<Self, cxx::Exception> {
1317        ffi::tableau_from_stabilizer_texts(stabilizers, allow_redundant, allow_underconstrained)
1318            .map(|inner| Self { inner })
1319    }
1320
1321    pub fn then(&self, second: &Self) -> Result<Self, cxx::Exception> {
1322        ffi::tableau_then(self.inner(), second.inner()).map(|inner| Self { inner })
1323    }
1324
1325    fn inner(&self) -> &ffi::TableauHandle {
1326        self.inner
1327            .as_ref()
1328            .expect("stim-cxx tableau construction returned null")
1329    }
1330
1331    fn inner_mut(self: Pin<&mut Self>) -> Pin<&mut ffi::TableauHandle> {
1332        self.get_mut().inner.pin_mut()
1333    }
1334
1335    #[must_use]
1336    pub fn num_qubits(&self) -> usize {
1337        ffi::tableau_num_qubits(self.inner())
1338    }
1339
1340    #[must_use]
1341    pub fn add(&self, other: &Self) -> Self {
1342        Self {
1343            inner: ffi::tableau_add(self.inner(), other.inner()),
1344        }
1345    }
1346
1347    pub fn add_assign(&mut self, other: &Self) {
1348        ffi::tableau_add_assign(self.inner.pin_mut(), other.inner());
1349    }
1350
1351    pub fn append(
1352        self: Pin<&mut Self>,
1353        gate: &Self,
1354        targets: &[usize],
1355    ) -> Result<(), cxx::Exception> {
1356        ffi::tableau_append(self.inner_mut(), gate.inner(), targets)
1357    }
1358
1359    pub fn prepend(
1360        self: Pin<&mut Self>,
1361        gate: &Self,
1362        targets: &[usize],
1363    ) -> Result<(), cxx::Exception> {
1364        ffi::tableau_prepend(self.inner_mut(), gate.inner(), targets)
1365    }
1366
1367    #[must_use]
1368    pub fn inverse(&self, unsigned_only: bool) -> Self {
1369        Self {
1370            inner: ffi::tableau_inverse(self.inner(), unsigned_only),
1371        }
1372    }
1373
1374    #[must_use]
1375    pub fn raised_to(&self, exponent: i64) -> Self {
1376        Self {
1377            inner: ffi::tableau_raised_to(self.inner(), exponent),
1378        }
1379    }
1380
1381    pub fn x_sign(&self, target: usize) -> Result<i32, cxx::Exception> {
1382        ffi::tableau_x_sign(self.inner(), target)
1383    }
1384
1385    pub fn y_sign(&self, target: usize) -> Result<i32, cxx::Exception> {
1386        ffi::tableau_y_sign(self.inner(), target)
1387    }
1388
1389    pub fn z_sign(&self, target: usize) -> Result<i32, cxx::Exception> {
1390        ffi::tableau_z_sign(self.inner(), target)
1391    }
1392
1393    pub fn x_output_pauli(
1394        &self,
1395        input_index: usize,
1396        output_index: usize,
1397    ) -> Result<u8, cxx::Exception> {
1398        ffi::tableau_x_output_pauli(self.inner(), input_index, output_index)
1399    }
1400
1401    pub fn y_output_pauli(
1402        &self,
1403        input_index: usize,
1404        output_index: usize,
1405    ) -> Result<u8, cxx::Exception> {
1406        ffi::tableau_y_output_pauli(self.inner(), input_index, output_index)
1407    }
1408
1409    pub fn z_output_pauli(
1410        &self,
1411        input_index: usize,
1412        output_index: usize,
1413    ) -> Result<u8, cxx::Exception> {
1414        ffi::tableau_z_output_pauli(self.inner(), input_index, output_index)
1415    }
1416
1417    pub fn x_output(&self, target: usize) -> PauliString {
1418        PauliString {
1419            inner: ffi::tableau_x_output(self.inner(), target),
1420        }
1421    }
1422
1423    pub fn y_output(&self, target: usize) -> PauliString {
1424        PauliString {
1425            inner: ffi::tableau_y_output(self.inner(), target),
1426        }
1427    }
1428
1429    pub fn z_output(&self, target: usize) -> PauliString {
1430        PauliString {
1431            inner: ffi::tableau_z_output(self.inner(), target),
1432        }
1433    }
1434
1435    pub fn inverse_x_output(&self, target: usize, unsigned_only: bool) -> PauliString {
1436        PauliString {
1437            inner: ffi::tableau_inverse_x_output(self.inner(), target, unsigned_only),
1438        }
1439    }
1440
1441    pub fn inverse_y_output(&self, target: usize, unsigned_only: bool) -> PauliString {
1442        PauliString {
1443            inner: ffi::tableau_inverse_y_output(self.inner(), target, unsigned_only),
1444        }
1445    }
1446
1447    pub fn inverse_z_output(&self, target: usize, unsigned_only: bool) -> PauliString {
1448        PauliString {
1449            inner: ffi::tableau_inverse_z_output(self.inner(), target, unsigned_only),
1450        }
1451    }
1452
1453    pub fn conjugate_pauli_string(&self, pauli_string: &PauliString) -> PauliString {
1454        PauliString {
1455            inner: ffi::tableau_conjugate_pauli_string(self.inner(), pauli_string.inner()),
1456        }
1457    }
1458
1459    pub fn conjugate_pauli_string_within(
1460        &self,
1461        pauli_string: &PauliString,
1462        targets: &[usize],
1463        inverse: bool,
1464    ) -> Result<PauliString, cxx::Exception> {
1465        ffi::tableau_conjugate_pauli_string_within(
1466            self.inner(),
1467            pauli_string.inner(),
1468            targets,
1469            inverse,
1470        )
1471        .map(|inner| PauliString { inner })
1472    }
1473
1474    pub fn to_stabilizer_texts(&self, canonicalize: bool) -> Vec<String> {
1475        ffi::tableau_to_stabilizer_texts(self.inner(), canonicalize)
1476    }
1477
1478    pub fn to_circuit(&self, method: &str) -> Result<Circuit, cxx::Exception> {
1479        ffi::tableau_to_circuit(self.inner(), method).map(|inner| Circuit { inner })
1480    }
1481
1482    pub fn to_pauli_string(&self) -> Result<PauliString, cxx::Exception> {
1483        ffi::tableau_to_pauli_string(self.inner()).map(|inner| PauliString { inner })
1484    }
1485
1486    pub fn inverse_x_output_pauli(
1487        &self,
1488        input_index: usize,
1489        output_index: usize,
1490    ) -> Result<u8, cxx::Exception> {
1491        ffi::tableau_inverse_x_output_pauli(self.inner(), input_index, output_index)
1492    }
1493
1494    pub fn inverse_y_output_pauli(
1495        &self,
1496        input_index: usize,
1497        output_index: usize,
1498    ) -> Result<u8, cxx::Exception> {
1499        ffi::tableau_inverse_y_output_pauli(self.inner(), input_index, output_index)
1500    }
1501
1502    pub fn inverse_z_output_pauli(
1503        &self,
1504        input_index: usize,
1505        output_index: usize,
1506    ) -> Result<u8, cxx::Exception> {
1507        ffi::tableau_inverse_z_output_pauli(self.inner(), input_index, output_index)
1508    }
1509
1510    #[must_use]
1511    pub fn to_text(&self) -> String {
1512        ffi::tableau_to_string(self.inner())
1513    }
1514
1515    #[must_use]
1516    pub fn to_repr_text(&self) -> String {
1517        ffi::tableau_to_repr(self.inner())
1518    }
1519
1520    pub fn to_unitary_matrix_data(&self, endian: &str) -> Result<Vec<f32>, cxx::Exception> {
1521        ffi::tableau_to_unitary_matrix_data(self.inner(), endian)
1522    }
1523
1524    pub fn to_state_vector_data(&self, endian: &str) -> Result<Vec<f32>, cxx::Exception> {
1525        ffi::tableau_to_state_vector_data(self.inner(), endian)
1526    }
1527}
1528
1529impl TableauSimulator {
1530    #[must_use]
1531    pub fn new(num_qubits: usize, seed: u64) -> Self {
1532        Self {
1533            inner: ffi::new_tableau_simulator(seed, num_qubits),
1534        }
1535    }
1536
1537    fn inner(&self) -> &ffi::TableauSimulatorHandle {
1538        self.inner
1539            .as_ref()
1540            .expect("stim-cxx tableau simulator construction returned null")
1541    }
1542
1543    fn inner_mut(&mut self) -> Pin<&mut ffi::TableauSimulatorHandle> {
1544        self.inner.pin_mut()
1545    }
1546
1547    #[must_use]
1548    pub fn num_qubits(&self) -> usize {
1549        ffi::tableau_simulator_num_qubits(self.inner())
1550    }
1551
1552    pub fn set_num_qubits(&mut self, new_num_qubits: usize) {
1553        ffi::tableau_simulator_set_num_qubits(self.inner_mut(), new_num_qubits);
1554    }
1555
1556    #[must_use]
1557    pub fn current_inverse_tableau(&self) -> Tableau {
1558        Tableau {
1559            inner: ffi::tableau_simulator_current_inverse_tableau(self.inner()),
1560        }
1561    }
1562
1563    pub fn set_inverse_tableau(&mut self, tableau: &Tableau) {
1564        ffi::tableau_simulator_set_inverse_tableau(self.inner_mut(), tableau.inner());
1565    }
1566
1567    #[must_use]
1568    pub fn current_measurement_record(&self) -> Vec<bool> {
1569        ffi::tableau_simulator_current_measurement_record(self.inner())
1570            .into_iter()
1571            .map(|bit| bit != 0)
1572            .collect()
1573    }
1574
1575    pub fn do_circuit(&mut self, circuit: &Circuit) {
1576        ffi::tableau_simulator_do_circuit(self.inner_mut(), circuit.inner());
1577    }
1578
1579    pub fn do_pauli_string(&mut self, pauli_string: &PauliString) {
1580        ffi::tableau_simulator_do_pauli_string(self.inner_mut(), pauli_string.inner());
1581    }
1582
1583    pub fn do_tableau(&mut self, tableau: &Tableau, targets: &[usize]) {
1584        ffi::tableau_simulator_do_tableau(self.inner_mut(), tableau.inner(), targets);
1585    }
1586
1587    #[must_use]
1588    pub fn peek_bloch(&mut self, target: usize) -> PauliString {
1589        PauliString {
1590            inner: ffi::tableau_simulator_peek_bloch(self.inner_mut(), target),
1591        }
1592    }
1593
1594    pub fn peek_x(&mut self, target: usize) -> i32 {
1595        ffi::tableau_simulator_peek_x(self.inner_mut(), target)
1596    }
1597
1598    pub fn peek_y(&mut self, target: usize) -> i32 {
1599        ffi::tableau_simulator_peek_y(self.inner_mut(), target)
1600    }
1601
1602    pub fn peek_z(&mut self, target: usize) -> i32 {
1603        ffi::tableau_simulator_peek_z(self.inner_mut(), target)
1604    }
1605
1606    pub fn measure(&mut self, target: usize) -> bool {
1607        ffi::tableau_simulator_measure(self.inner_mut(), target)
1608    }
1609
1610    #[must_use]
1611    pub fn measure_many(&mut self, targets: &[usize]) -> Vec<bool> {
1612        ffi::tableau_simulator_measure_many(self.inner_mut(), targets)
1613            .into_iter()
1614            .map(|bit| bit != 0)
1615            .collect()
1616    }
1617
1618    pub fn peek_observable_expectation(
1619        &self,
1620        observable: &PauliString,
1621    ) -> Result<i32, cxx::Exception> {
1622        ffi::tableau_simulator_peek_observable_expectation(self.inner(), observable.inner())
1623    }
1624
1625    pub fn measure_observable(
1626        &mut self,
1627        observable: &PauliString,
1628        flip_probability: f64,
1629    ) -> Result<bool, cxx::Exception> {
1630        ffi::tableau_simulator_measure_observable(
1631            self.inner_mut(),
1632            observable.inner(),
1633            flip_probability,
1634        )
1635    }
1636
1637    pub fn postselect_observable(
1638        &mut self,
1639        observable: &PauliString,
1640        desired_value: bool,
1641    ) -> Result<(), cxx::Exception> {
1642        ffi::tableau_simulator_postselect_observable(
1643            self.inner_mut(),
1644            observable.inner(),
1645            desired_value,
1646        )
1647    }
1648
1649    pub fn postselect_x(
1650        &mut self,
1651        targets: &[usize],
1652        desired_value: bool,
1653    ) -> Result<(), cxx::Exception> {
1654        ffi::tableau_simulator_postselect_x(self.inner_mut(), targets, desired_value)
1655    }
1656
1657    pub fn postselect_y(
1658        &mut self,
1659        targets: &[usize],
1660        desired_value: bool,
1661    ) -> Result<(), cxx::Exception> {
1662        ffi::tableau_simulator_postselect_y(self.inner_mut(), targets, desired_value)
1663    }
1664
1665    pub fn postselect_z(
1666        &mut self,
1667        targets: &[usize],
1668        desired_value: bool,
1669    ) -> Result<(), cxx::Exception> {
1670        ffi::tableau_simulator_postselect_z(self.inner_mut(), targets, desired_value)
1671    }
1672
1673    pub fn measure_kickback(&mut self, target: usize) -> (bool, Option<PauliString>) {
1674        let data = ffi::tableau_simulator_measure_kickback(self.inner_mut(), target);
1675        let kickback = if data.has_kickback {
1676            Some(
1677                PauliString::from_text(&data.kickback_text)
1678                    .expect("kickback text from stim-cxx should parse as a PauliString"),
1679            )
1680        } else {
1681            None
1682        };
1683        (data.result, kickback)
1684    }
1685}
1686
1687impl FlipSimulator {
1688    #[must_use]
1689    pub fn new(
1690        batch_size: usize,
1691        disable_stabilizer_randomization: bool,
1692        num_qubits: usize,
1693        seed: u64,
1694    ) -> Self {
1695        Self {
1696            inner: ffi::new_frame_simulator(
1697                batch_size,
1698                disable_stabilizer_randomization,
1699                num_qubits,
1700                seed,
1701            ),
1702        }
1703    }
1704
1705    fn inner(&self) -> &ffi::FrameSimulatorHandle {
1706        self.inner
1707            .as_ref()
1708            .expect("stim-cxx frame simulator construction returned null")
1709    }
1710
1711    fn inner_mut(&mut self) -> Pin<&mut ffi::FrameSimulatorHandle> {
1712        self.inner.pin_mut()
1713    }
1714
1715    #[must_use]
1716    pub fn batch_size(&self) -> usize {
1717        ffi::frame_simulator_batch_size(self.inner())
1718    }
1719
1720    #[must_use]
1721    pub fn num_qubits(&self) -> usize {
1722        ffi::frame_simulator_num_qubits(self.inner())
1723    }
1724
1725    #[must_use]
1726    pub fn num_measurements(&self) -> usize {
1727        ffi::frame_simulator_num_measurements(self.inner())
1728    }
1729
1730    #[must_use]
1731    pub fn num_detectors(&self) -> usize {
1732        ffi::frame_simulator_num_detectors(self.inner())
1733    }
1734
1735    #[must_use]
1736    pub fn num_observables(&self) -> usize {
1737        ffi::frame_simulator_num_observables(self.inner())
1738    }
1739
1740    pub fn clear(&mut self) {
1741        ffi::frame_simulator_clear(self.inner_mut());
1742    }
1743
1744    pub fn do_circuit(&mut self, circuit: &Circuit) {
1745        ffi::frame_simulator_do_circuit(self.inner_mut(), circuit.inner());
1746    }
1747
1748    pub fn set_pauli_flip(
1749        &mut self,
1750        pauli: u8,
1751        qubit_index: i64,
1752        instance_index: i64,
1753    ) -> Result<(), cxx::Exception> {
1754        ffi::frame_simulator_set_pauli_flip(self.inner_mut(), pauli, qubit_index, instance_index)
1755    }
1756
1757    pub fn peek_pauli_flips(&self) -> Result<Vec<PauliString>, cxx::Exception> {
1758        ffi::frame_simulator_peek_pauli_flips(self.inner())
1759            .into_iter()
1760            .map(|text| PauliString::from_text(&text))
1761            .collect()
1762    }
1763
1764    pub fn peek_pauli_flip(&self, instance_index: i64) -> Result<PauliString, cxx::Exception> {
1765        ffi::frame_simulator_peek_pauli_flip(self.inner(), instance_index)
1766            .and_then(|text| PauliString::from_text(&text))
1767    }
1768
1769    pub fn broadcast_pauli_errors(
1770        &mut self,
1771        pauli: u8,
1772        mask: Vec<u8>,
1773        mask_num_qubits: usize,
1774        p: f32,
1775    ) -> Result<(), cxx::Exception> {
1776        ffi::frame_simulator_broadcast_pauli_errors(
1777            self.inner_mut(),
1778            pauli,
1779            mask,
1780            mask_num_qubits,
1781            p,
1782        )
1783    }
1784
1785    pub fn generate_bernoulli_samples(
1786        &mut self,
1787        num_samples: usize,
1788        p: f32,
1789        bit_packed: bool,
1790    ) -> Result<Vec<u8>, cxx::Exception> {
1791        ffi::frame_simulator_generate_bernoulli_samples(
1792            self.inner_mut(),
1793            num_samples,
1794            p,
1795            bit_packed,
1796        )
1797    }
1798
1799    pub fn append_measurement_flips(
1800        &mut self,
1801        data: Vec<u8>,
1802        num_measurements: usize,
1803        bit_packed: bool,
1804    ) -> Result<(), cxx::Exception> {
1805        ffi::frame_simulator_append_measurement_flips(
1806            self.inner_mut(),
1807            data,
1808            num_measurements,
1809            bit_packed,
1810        )
1811    }
1812
1813    pub fn get_measurement_flips(&self, bit_packed: bool) -> ffi::BitTableData {
1814        ffi::frame_simulator_get_measurement_flips(self.inner(), bit_packed)
1815    }
1816
1817    pub fn get_detector_flips(&self, bit_packed: bool) -> ffi::BitTableData {
1818        ffi::frame_simulator_get_detector_flips(self.inner(), bit_packed)
1819    }
1820
1821    pub fn get_observable_flips(&self, bit_packed: bool) -> ffi::BitTableData {
1822        ffi::frame_simulator_get_observable_flips(self.inner(), bit_packed)
1823    }
1824}
1825
1826impl PauliString {
1827    #[must_use]
1828    pub fn new(num_qubits: usize) -> Self {
1829        Self {
1830            inner: ffi::new_pauli_string(num_qubits),
1831        }
1832    }
1833
1834    pub fn from_text(text: &str) -> Result<Self, cxx::Exception> {
1835        ffi::pauli_string_from_text(text).map(|inner| Self { inner })
1836    }
1837
1838    #[must_use]
1839    pub fn random(num_qubits: usize) -> Self {
1840        Self {
1841            inner: ffi::pauli_string_random(num_qubits),
1842        }
1843    }
1844
1845    #[must_use]
1846    pub fn iter_all(
1847        num_qubits: usize,
1848        min_weight: usize,
1849        max_weight: usize,
1850        allow_x: bool,
1851        allow_y: bool,
1852        allow_z: bool,
1853    ) -> PauliStringIterator {
1854        PauliStringIterator {
1855            inner: ffi::pauli_string_iter_all(
1856                num_qubits, min_weight, max_weight, allow_x, allow_y, allow_z,
1857            ),
1858        }
1859    }
1860
1861    fn inner(&self) -> &ffi::PauliStringHandle {
1862        self.inner
1863            .as_ref()
1864            .expect("stim-cxx pauli string construction returned null")
1865    }
1866
1867    #[must_use]
1868    pub fn num_qubits(&self) -> usize {
1869        ffi::pauli_string_num_qubits(self.inner())
1870    }
1871
1872    #[must_use]
1873    pub fn weight(&self) -> usize {
1874        ffi::pauli_string_weight(self.inner())
1875    }
1876
1877    pub fn get_item(&self, index: i64) -> Result<u8, cxx::Exception> {
1878        ffi::pauli_string_get_item(self.inner(), index)
1879    }
1880
1881    pub fn set_item(&mut self, index: i64, new_pauli: u8) -> Result<(), cxx::Exception> {
1882        ffi::pauli_string_set_item(self.inner.pin_mut(), index, new_pauli)
1883    }
1884
1885    pub fn get_slice(&self, start: i64, step: i64, slice_length: i64) -> PauliString {
1886        PauliString {
1887            inner: ffi::pauli_string_get_slice(self.inner(), start, step, slice_length),
1888        }
1889    }
1890
1891    #[must_use]
1892    pub fn commutes(&self, other: &Self) -> bool {
1893        ffi::pauli_string_commutes(self.inner(), other.inner())
1894    }
1895
1896    pub fn pauli_indices(&self, included_paulis: &str) -> Result<Vec<u64>, cxx::Exception> {
1897        ffi::pauli_string_pauli_indices(self.inner(), included_paulis)
1898    }
1899
1900    pub fn sign_code(&self) -> i32 {
1901        ffi::pauli_string_sign_code(self.inner())
1902    }
1903
1904    pub fn to_tableau(&self) -> Tableau {
1905        Tableau {
1906            inner: ffi::pauli_string_to_tableau(self.inner()),
1907        }
1908    }
1909
1910    #[must_use]
1911    pub fn to_text(&self) -> String {
1912        ffi::pauli_string_to_string(self.inner())
1913    }
1914
1915    #[must_use]
1916    pub fn to_repr_text(&self) -> String {
1917        ffi::pauli_string_to_repr(self.inner())
1918    }
1919}
1920
1921impl CliffordString {
1922    #[must_use]
1923    pub fn new(num_qubits: usize) -> Self {
1924        Self {
1925            inner: ffi::new_clifford_string(num_qubits),
1926        }
1927    }
1928
1929    pub fn from_text(text: &str) -> Result<Self, cxx::Exception> {
1930        ffi::clifford_string_from_text(text).map(|inner| Self { inner })
1931    }
1932
1933    #[must_use]
1934    pub fn from_pauli_string(pauli_string: &PauliString) -> Self {
1935        Self {
1936            inner: ffi::clifford_string_from_pauli_string(pauli_string.inner()),
1937        }
1938    }
1939
1940    pub fn from_circuit(circuit: &Circuit) -> Result<Self, cxx::Exception> {
1941        ffi::clifford_string_from_circuit(circuit.inner()).map(|inner| Self { inner })
1942    }
1943
1944    #[must_use]
1945    pub fn random(num_qubits: usize) -> Self {
1946        Self {
1947            inner: ffi::clifford_string_random(num_qubits),
1948        }
1949    }
1950
1951    #[must_use]
1952    pub fn all_cliffords_string() -> Self {
1953        Self {
1954            inner: ffi::clifford_string_all_cliffords_string(),
1955        }
1956    }
1957
1958    fn inner(&self) -> &ffi::CliffordStringHandle {
1959        self.inner
1960            .as_ref()
1961            .expect("stim-cxx clifford string construction returned null")
1962    }
1963
1964    #[must_use]
1965    pub fn num_qubits(&self) -> usize {
1966        ffi::clifford_string_num_qubits(self.inner())
1967    }
1968
1969    pub fn get_item_name(&self, index: i64) -> Result<String, cxx::Exception> {
1970        ffi::clifford_string_get_item_name(self.inner(), index)
1971    }
1972
1973    #[must_use]
1974    pub fn get_slice(&self, start: i64, step: i64, slice_length: i64) -> Self {
1975        Self {
1976            inner: ffi::clifford_string_get_slice(self.inner(), start, step, slice_length),
1977        }
1978    }
1979
1980    #[must_use]
1981    pub fn add(&self, other: &Self) -> Self {
1982        Self {
1983            inner: ffi::clifford_string_add(self.inner(), other.inner()),
1984        }
1985    }
1986
1987    pub fn add_assign(&mut self, other: &Self) {
1988        ffi::clifford_string_add_assign(self.inner.pin_mut(), other.inner());
1989    }
1990
1991    #[must_use]
1992    pub fn mul_clifford(&self, other: &Self) -> Self {
1993        Self {
1994            inner: ffi::clifford_string_mul(self.inner(), other.inner()),
1995        }
1996    }
1997
1998    pub fn mul_assign_clifford(&mut self, other: &Self) {
1999        ffi::clifford_string_mul_assign(self.inner.pin_mut(), other.inner());
2000    }
2001
2002    pub fn repeat(&self, repetitions: u64) -> Result<Self, cxx::Exception> {
2003        ffi::clifford_string_repeat(self.inner(), repetitions).map(|inner| Self { inner })
2004    }
2005
2006    pub fn repeat_assign(&mut self, repetitions: u64) -> Result<(), cxx::Exception> {
2007        ffi::clifford_string_repeat_assign(self.inner.pin_mut(), repetitions)
2008    }
2009
2010    #[must_use]
2011    pub fn pow(&self, exponent: i64) -> Self {
2012        Self {
2013            inner: ffi::clifford_string_pow(self.inner(), exponent),
2014        }
2015    }
2016
2017    pub fn ipow(&mut self, exponent: i64) {
2018        ffi::clifford_string_ipow(self.inner.pin_mut(), exponent);
2019    }
2020
2021    #[must_use]
2022    pub fn x_outputs(&self) -> PauliString {
2023        PauliString {
2024            inner: ffi::clifford_string_x_outputs(self.inner()),
2025        }
2026    }
2027
2028    #[must_use]
2029    pub fn x_signs_bit_packed(&self) -> Vec<u8> {
2030        ffi::clifford_string_x_signs_bit_packed(self.inner())
2031    }
2032
2033    #[must_use]
2034    pub fn y_outputs(&self) -> PauliString {
2035        PauliString {
2036            inner: ffi::clifford_string_y_outputs(self.inner()),
2037        }
2038    }
2039
2040    #[must_use]
2041    pub fn y_signs_bit_packed(&self) -> Vec<u8> {
2042        ffi::clifford_string_y_signs_bit_packed(self.inner())
2043    }
2044
2045    #[must_use]
2046    pub fn z_outputs(&self) -> PauliString {
2047        PauliString {
2048            inner: ffi::clifford_string_z_outputs(self.inner()),
2049        }
2050    }
2051
2052    #[must_use]
2053    pub fn z_signs_bit_packed(&self) -> Vec<u8> {
2054        ffi::clifford_string_z_signs_bit_packed(self.inner())
2055    }
2056
2057    #[must_use]
2058    pub fn to_text(&self) -> String {
2059        ffi::clifford_string_to_string(self.inner())
2060    }
2061
2062    #[must_use]
2063    pub fn to_repr_text(&self) -> String {
2064        ffi::clifford_string_to_repr(self.inner())
2065    }
2066}
2067
2068impl Clone for Circuit {
2069    fn clone(&self) -> Self {
2070        Self {
2071            inner: ffi::circuit_clone(self.inner()),
2072        }
2073    }
2074}
2075
2076impl Clone for DetectorErrorModel {
2077    fn clone(&self) -> Self {
2078        Self {
2079            inner: ffi::detector_error_model_clone(self.inner()),
2080        }
2081    }
2082}
2083
2084impl Clone for Tableau {
2085    fn clone(&self) -> Self {
2086        Self {
2087            inner: ffi::tableau_clone(self.inner()),
2088        }
2089    }
2090}
2091
2092impl Clone for TableauSimulator {
2093    fn clone(&self) -> Self {
2094        Self {
2095            inner: ffi::tableau_simulator_clone(self.inner()),
2096        }
2097    }
2098}
2099
2100impl Clone for FlipSimulator {
2101    fn clone(&self) -> Self {
2102        Self {
2103            inner: ffi::frame_simulator_clone(self.inner()),
2104        }
2105    }
2106}
2107
2108impl TableauIterator {
2109    fn inner(&self) -> &ffi::TableauIteratorHandle {
2110        self.inner
2111            .as_ref()
2112            .expect("stim-cxx tableau iterator construction returned null")
2113    }
2114
2115    fn inner_mut(&mut self) -> Pin<&mut ffi::TableauIteratorHandle> {
2116        self.inner.pin_mut()
2117    }
2118}
2119
2120impl Clone for TableauIterator {
2121    fn clone(&self) -> Self {
2122        Self {
2123            inner: ffi::tableau_iterator_clone(self.inner()),
2124        }
2125    }
2126}
2127
2128impl Iterator for TableauIterator {
2129    type Item = Tableau;
2130
2131    fn next(&mut self) -> Option<Self::Item> {
2132        let inner = ffi::tableau_iterator_next(self.inner_mut());
2133        if inner.is_null() {
2134            None
2135        } else {
2136            Some(Tableau { inner })
2137        }
2138    }
2139}
2140
2141impl PartialEq for Tableau {
2142    fn eq(&self, other: &Self) -> bool {
2143        ffi::tableau_equals(self.inner(), other.inner())
2144    }
2145}
2146
2147impl Eq for Tableau {}
2148
2149impl Clone for PauliString {
2150    fn clone(&self) -> Self {
2151        Self {
2152            inner: ffi::pauli_string_clone(self.inner()),
2153        }
2154    }
2155}
2156
2157impl PauliStringIterator {
2158    fn inner(&self) -> &ffi::PauliStringIteratorHandle {
2159        self.inner
2160            .as_ref()
2161            .expect("stim-cxx pauli string iterator construction returned null")
2162    }
2163
2164    fn inner_mut(&mut self) -> Pin<&mut ffi::PauliStringIteratorHandle> {
2165        self.inner.pin_mut()
2166    }
2167}
2168
2169impl Clone for PauliStringIterator {
2170    fn clone(&self) -> Self {
2171        Self {
2172            inner: ffi::pauli_string_iterator_clone(self.inner()),
2173        }
2174    }
2175}
2176
2177impl Iterator for PauliStringIterator {
2178    type Item = PauliString;
2179
2180    fn next(&mut self) -> Option<Self::Item> {
2181        let inner = ffi::pauli_string_iterator_next(self.inner_mut());
2182        if inner.is_null() {
2183            None
2184        } else {
2185            Some(PauliString { inner })
2186        }
2187    }
2188}
2189
2190impl PartialEq for PauliString {
2191    fn eq(&self, other: &Self) -> bool {
2192        ffi::pauli_string_equals(self.inner(), other.inner())
2193    }
2194}
2195
2196impl Eq for PauliString {}
2197
2198impl Clone for CliffordString {
2199    fn clone(&self) -> Self {
2200        Self {
2201            inner: ffi::clifford_string_clone(self.inner()),
2202        }
2203    }
2204}
2205
2206impl PartialEq for CliffordString {
2207    fn eq(&self, other: &Self) -> bool {
2208        ffi::clifford_string_equals(self.inner(), other.inner())
2209    }
2210}
2211
2212impl Eq for CliffordString {}
2213
2214impl Clone for GateData {
2215    fn clone(&self) -> Self {
2216        self.clone_handle()
2217    }
2218}
2219
2220impl Default for Circuit {
2221    fn default() -> Self {
2222        Self::new()
2223    }
2224}
2225
2226impl Default for DetectorErrorModel {
2227    fn default() -> Self {
2228        Self::new()
2229    }
2230}
2231
2232pub struct SmokeProbe {
2233    inner: UniquePtr<ffi::SmokeProbe>,
2234}
2235
2236impl SmokeProbe {
2237    #[must_use]
2238    pub fn new() -> Self {
2239        Self {
2240            inner: ffi::new_smoke_probe(),
2241        }
2242    }
2243
2244    #[must_use]
2245    pub fn describe(&self) -> String {
2246        self.inner().describe().to_string()
2247    }
2248
2249    #[must_use]
2250    pub fn weighted_checksum(&self, values: &[u64]) -> u64 {
2251        self.inner().weighted_checksum(values)
2252    }
2253
2254    fn inner(&self) -> &ffi::SmokeProbe {
2255        self.inner
2256            .as_ref()
2257            .expect("stim-cxx smoke probe construction returned null")
2258    }
2259}
2260
2261impl Default for SmokeProbe {
2262    fn default() -> Self {
2263        Self::new()
2264    }
2265}
2266
2267#[cxx::bridge(namespace = "stimrs::bridge")]
2268mod ffi {
2269    struct DemSampleBatch {
2270        detectors: Vec<u8>,
2271        observables: Vec<u8>,
2272        errors: Vec<u8>,
2273    }
2274
2275    struct DetectorSampleBatch {
2276        detectors: Vec<u8>,
2277        observables: Vec<u8>,
2278    }
2279
2280    struct CircuitTopLevelItemData {
2281        is_repeat_block: bool,
2282        name: String,
2283        tag: String,
2284        gate_args: Vec<f64>,
2285        targets: Vec<u32>,
2286        repeat_count: u64,
2287    }
2288
2289    struct DemTopLevelItemData {
2290        is_repeat_block: bool,
2291        instruction_type: String,
2292        tag: String,
2293        args: Vec<f64>,
2294        targets: Vec<u64>,
2295        repeat_count: u64,
2296    }
2297
2298    struct TableauMeasureKickbackData {
2299        result: bool,
2300        has_kickback: bool,
2301        kickback_text: String,
2302    }
2303
2304    struct BitTableData {
2305        data: Vec<u8>,
2306        rows: u64,
2307        cols: u64,
2308        bit_packed: bool,
2309    }
2310
2311    struct CoordinateEntryData {
2312        index: u64,
2313        coords: Vec<f64>,
2314    }
2315
2316    struct DetectingRegionEntryData {
2317        target_index: u64,
2318        target_is_observable: bool,
2319        tick: u64,
2320        pauli: String,
2321    }
2322
2323    struct GateTargetWithCoordsData {
2324        raw_target: u32,
2325        coords: Vec<f64>,
2326    }
2327
2328    struct DemTargetWithCoordsData {
2329        dem_target: String,
2330        coords: Vec<f64>,
2331    }
2332
2333    struct CircuitErrorLocationStackFrameData {
2334        instruction_offset: u64,
2335        iteration_index: u64,
2336        instruction_repetitions_arg: u64,
2337    }
2338
2339    struct CircuitTargetsInsideInstructionData {
2340        gate: String,
2341        tag: String,
2342        args: Vec<f64>,
2343        target_range_start: u64,
2344        target_range_end: u64,
2345        targets_in_range: Vec<GateTargetWithCoordsData>,
2346    }
2347
2348    struct FlippedMeasurementData {
2349        record_index: u64,
2350        observable: Vec<GateTargetWithCoordsData>,
2351    }
2352
2353    struct CircuitErrorLocationData {
2354        tick_offset: u64,
2355        flipped_pauli_product: Vec<GateTargetWithCoordsData>,
2356        flipped_measurement: FlippedMeasurementData,
2357        instruction_targets: CircuitTargetsInsideInstructionData,
2358        stack_frames: Vec<CircuitErrorLocationStackFrameData>,
2359        noise_tag: String,
2360    }
2361
2362    struct ExplainedErrorData {
2363        dem_error_terms: Vec<DemTargetWithCoordsData>,
2364        circuit_error_locations: Vec<CircuitErrorLocationData>,
2365    }
2366
2367    unsafe extern "C++" {
2368        include!("stim-cxx/include/stim_rs_bridge.h");
2369
2370        fn read_shot_data_file_bit_packed(
2371            filepath: &str,
2372            format_name: &str,
2373            num_measurements: u64,
2374            num_detectors: u64,
2375            num_observables: u64,
2376        ) -> Result<Vec<u8>>;
2377        fn write_shot_data_file_bit_packed(
2378            data: &[u8],
2379            shots: u64,
2380            filepath: &str,
2381            format_name: &str,
2382            num_measurements: u64,
2383            num_detectors: u64,
2384            num_observables: u64,
2385        ) -> Result<()>;
2386        fn all_gate_names() -> Vec<String>;
2387        fn canonicalize_flow_text(text: &str) -> Result<String>;
2388        fn multiply_flow_texts(left: &str, right: &str) -> Result<String>;
2389
2390        type CircuitHandle;
2391        type DetectorErrorModelHandle;
2392        type TableauHandle;
2393        type TableauSimulatorHandle;
2394        type FrameSimulatorHandle;
2395        type TableauIteratorHandle;
2396        type PauliStringHandle;
2397        type CliffordStringHandle;
2398        type PauliStringIteratorHandle;
2399        type DetectorSamplerHandle;
2400        type GateDataHandle;
2401        type MeasurementSamplerHandle;
2402        type MeasurementsToDetectionEventsConverterHandle;
2403        type DemSamplerHandle;
2404        type SmokeProbe;
2405
2406        fn gate_data_by_name(name: &str) -> Result<UniquePtr<GateDataHandle>>;
2407        fn name(self: &GateDataHandle) -> String;
2408        fn aliases(self: &GateDataHandle) -> Vec<String>;
2409        fn num_parens_arguments_range(self: &GateDataHandle) -> Vec<u8>;
2410        fn is_noisy_gate(self: &GateDataHandle) -> bool;
2411        fn is_reset(self: &GateDataHandle) -> bool;
2412        fn is_single_qubit_gate(self: &GateDataHandle) -> bool;
2413        fn is_symmetric_gate(self: &GateDataHandle) -> bool;
2414        fn is_two_qubit_gate(self: &GateDataHandle) -> bool;
2415        fn is_unitary(self: &GateDataHandle) -> bool;
2416        fn produces_measurements(self: &GateDataHandle) -> bool;
2417        fn takes_measurement_record_targets(self: &GateDataHandle) -> bool;
2418        fn takes_pauli_targets(self: &GateDataHandle) -> bool;
2419        fn flows(self: &GateDataHandle) -> Vec<String>;
2420        fn tableau(self: &GateDataHandle) -> UniquePtr<TableauHandle>;
2421        fn clone_handle(self: &GateDataHandle) -> UniquePtr<GateDataHandle>;
2422        fn inverse(self: &GateDataHandle) -> UniquePtr<GateDataHandle>;
2423        fn generalized_inverse(self: &GateDataHandle) -> UniquePtr<GateDataHandle>;
2424        fn hadamard_conjugated(
2425            self: &GateDataHandle,
2426            unsigned_only: bool,
2427        ) -> UniquePtr<GateDataHandle>;
2428
2429        fn new_circuit() -> UniquePtr<CircuitHandle>;
2430        fn circuit_from_stim_program_text(text: &str) -> Result<UniquePtr<CircuitHandle>>;
2431        fn circuit_clone(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2432        fn circuit_add(left: &CircuitHandle, right: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2433        fn circuit_add_assign(left: Pin<&mut CircuitHandle>, right: &CircuitHandle);
2434        fn circuit_mul(handle: &CircuitHandle, repetitions: u64) -> UniquePtr<CircuitHandle>;
2435        fn circuit_mul_assign(handle: Pin<&mut CircuitHandle>, repetitions: u64);
2436        fn circuit_generated(
2437            code_task: &str,
2438            distance: usize,
2439            rounds: usize,
2440            after_clifford_depolarization: f64,
2441            before_round_data_depolarization: f64,
2442            before_measure_flip_probability: f64,
2443            after_reset_flip_probability: f64,
2444        ) -> Result<UniquePtr<CircuitHandle>>;
2445        fn circuit_has_flow_text(
2446            handle: &CircuitHandle,
2447            flow_text: &str,
2448            unsigned_only: bool,
2449        ) -> Result<bool>;
2450        fn circuit_has_all_flows_text(
2451            handle: &CircuitHandle,
2452            flow_texts: Vec<String>,
2453            unsigned_only: bool,
2454        ) -> Result<bool>;
2455        fn circuit_flow_generators_texts(handle: &CircuitHandle) -> Vec<String>;
2456        fn circuit_solve_flow_measurements_text(
2457            handle: &CircuitHandle,
2458            flow_texts: Vec<String>,
2459        ) -> Result<Vec<String>>;
2460        fn circuit_time_reversed_for_flows_text(
2461            out_flow_texts: &mut Vec<String>,
2462            handle: &CircuitHandle,
2463            flow_texts: Vec<String>,
2464            dont_turn_measurements_into_resets: bool,
2465        ) -> Result<String>;
2466        fn circuit_diagram_with_options(
2467            handle: &CircuitHandle,
2468            type_name: &str,
2469            has_tick_range: bool,
2470            tick_start: u64,
2471            tick_count: u64,
2472            has_rows: bool,
2473            rows: usize,
2474        ) -> Result<String>;
2475        fn circuit_diagram_with_options_and_filters(
2476            handle: &CircuitHandle,
2477            type_name: &str,
2478            has_tick_range: bool,
2479            tick_start: u64,
2480            tick_count: u64,
2481            has_rows: bool,
2482            rows: usize,
2483            filter_coords: Vec<String>,
2484        ) -> Result<String>;
2485        fn circuit_to_stim_program_text(handle: &CircuitHandle) -> String;
2486        fn circuit_num_qubits(handle: &CircuitHandle) -> usize;
2487        fn circuit_len(handle: &CircuitHandle) -> usize;
2488        fn circuit_get_top_level_item(
2489            handle: &CircuitHandle,
2490            index: usize,
2491        ) -> CircuitTopLevelItemData;
2492        fn circuit_get_top_level_repeat_block_body(
2493            handle: &CircuitHandle,
2494            index: usize,
2495        ) -> UniquePtr<CircuitHandle>;
2496        fn circuit_get_slice(
2497            handle: &CircuitHandle,
2498            start: i64,
2499            step: i64,
2500            slice_length: i64,
2501        ) -> UniquePtr<CircuitHandle>;
2502        fn circuit_remove_top_level(handle: Pin<&mut CircuitHandle>, index: usize);
2503        fn circuit_num_measurements(handle: &CircuitHandle) -> u64;
2504        fn circuit_count_determined_measurements(
2505            handle: &CircuitHandle,
2506            unknown_input: bool,
2507        ) -> u64;
2508        fn circuit_num_detectors(handle: &CircuitHandle) -> u64;
2509        fn circuit_num_observables(handle: &CircuitHandle) -> u64;
2510        fn circuit_num_ticks(handle: &CircuitHandle) -> u64;
2511        fn circuit_num_sweep_bits(handle: &CircuitHandle) -> usize;
2512        fn circuit_append_from_stim_program_text(
2513            handle: Pin<&mut CircuitHandle>,
2514            text: &str,
2515        ) -> Result<()>;
2516        fn circuit_append_gate(
2517            handle: Pin<&mut CircuitHandle>,
2518            gate_name: &str,
2519            targets: &[u32],
2520            args: &[f64],
2521            tag: &str,
2522        ) -> Result<()>;
2523        fn circuit_append_repeat_block(
2524            handle: Pin<&mut CircuitHandle>,
2525            repeat_count: u64,
2526            body: &CircuitHandle,
2527            tag: &str,
2528        ) -> Result<()>;
2529        fn circuit_insert_gate(
2530            handle: Pin<&mut CircuitHandle>,
2531            index: usize,
2532            gate_name: &str,
2533            targets: &[u32],
2534            args: &[f64],
2535            tag: &str,
2536        ) -> Result<()>;
2537        fn circuit_insert_repeat_block(
2538            handle: Pin<&mut CircuitHandle>,
2539            index: usize,
2540            repeat_count: u64,
2541            body: &CircuitHandle,
2542            tag: &str,
2543        ) -> Result<()>;
2544        fn circuit_insert_circuit(
2545            handle: Pin<&mut CircuitHandle>,
2546            index: usize,
2547            circuit: &CircuitHandle,
2548        );
2549        fn circuit_clear(handle: Pin<&mut CircuitHandle>);
2550        fn circuit_equals(left: &CircuitHandle, right: &CircuitHandle) -> bool;
2551        fn circuit_approx_equals(left: &CircuitHandle, right: &CircuitHandle, atol: f64) -> bool;
2552        fn circuit_without_noise(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2553        fn circuit_with_inlined_feedback(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2554        fn circuit_without_tags(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2555        fn circuit_flattened(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2556        fn circuit_decomposed(handle: &CircuitHandle) -> UniquePtr<CircuitHandle>;
2557        fn circuit_inverse(handle: &CircuitHandle) -> Result<UniquePtr<CircuitHandle>>;
2558        fn circuit_to_qasm(
2559            handle: &CircuitHandle,
2560            open_qasm_version: i32,
2561            skip_dets_and_obs: bool,
2562        ) -> Result<String>;
2563        fn circuit_to_quirk_url(handle: &CircuitHandle) -> Result<String>;
2564        fn circuit_to_crumble_url(handle: &CircuitHandle, skip_detectors: bool) -> Result<String>;
2565        fn circuit_shortest_error_sat_problem(
2566            handle: &CircuitHandle,
2567            format_name: &str,
2568        ) -> Result<String>;
2569        fn circuit_likeliest_error_sat_problem(
2570            handle: &CircuitHandle,
2571            quantization: i32,
2572            format_name: &str,
2573        ) -> Result<String>;
2574        fn circuit_detecting_regions(
2575            handle: &CircuitHandle,
2576        ) -> Result<Vec<DetectingRegionEntryData>>;
2577        fn circuit_detecting_regions_with_options(
2578            handle: &CircuitHandle,
2579            target_texts: Vec<String>,
2580            ticks: Vec<u64>,
2581            ignore_anticommutation_errors: bool,
2582        ) -> Result<Vec<DetectingRegionEntryData>>;
2583        fn circuit_explain_detector_error_model_errors(
2584            handle: &CircuitHandle,
2585            dem_filter_text: &str,
2586            has_dem_filter: bool,
2587            reduce_to_one_representative_error: bool,
2588        ) -> Result<Vec<ExplainedErrorData>>;
2589        fn circuit_shortest_graphlike_error(
2590            handle: &CircuitHandle,
2591            ignore_ungraphlike_errors: bool,
2592            canonicalize_circuit_errors: bool,
2593        ) -> Result<Vec<ExplainedErrorData>>;
2594        fn circuit_flattened_operation_texts(handle: &CircuitHandle) -> Vec<String>;
2595        fn circuit_search_for_undetectable_logical_errors(
2596            handle: &CircuitHandle,
2597            dont_explore_detection_event_sets_with_size_above: u64,
2598            dont_explore_edges_with_degree_above: u64,
2599            dont_explore_edges_increasing_symptom_degree: bool,
2600            canonicalize_circuit_errors: bool,
2601        ) -> Result<Vec<ExplainedErrorData>>;
2602        fn circuit_get_detector_coordinates(
2603            handle: &CircuitHandle,
2604            included_detector_indices: &[u64],
2605        ) -> Result<Vec<CoordinateEntryData>>;
2606        fn circuit_get_final_qubit_coordinates(
2607            handle: &CircuitHandle,
2608        ) -> Result<Vec<CoordinateEntryData>>;
2609        fn circuit_reference_sample_bit_packed(handle: &CircuitHandle) -> Vec<u8>;
2610        fn circuit_reference_detector_signs_bit_packed(handle: &CircuitHandle) -> Vec<u8>;
2611        fn circuit_reference_observable_signs_bit_packed(handle: &CircuitHandle) -> Vec<u8>;
2612        fn new_detector_error_model() -> UniquePtr<DetectorErrorModelHandle>;
2613        fn circuit_detector_error_model(
2614            handle: &CircuitHandle,
2615            decompose_errors: bool,
2616            flatten_loops: bool,
2617            allow_gauge_detectors: bool,
2618            approximate_disjoint_errors: f64,
2619            ignore_decomposition_failures: bool,
2620            block_decomposition_from_introducing_remnant_edges: bool,
2621        ) -> Result<UniquePtr<DetectorErrorModelHandle>>;
2622        fn circuit_missing_detectors(
2623            handle: &CircuitHandle,
2624            unknown_input: bool,
2625        ) -> UniquePtr<CircuitHandle>;
2626        fn circuit_to_tableau(
2627            handle: &CircuitHandle,
2628            ignore_noise: bool,
2629            ignore_measurement: bool,
2630            ignore_reset: bool,
2631        ) -> Result<UniquePtr<TableauHandle>>;
2632        fn new_tableau(num_qubits: usize) -> UniquePtr<TableauHandle>;
2633        fn tableau_random(num_qubits: usize) -> UniquePtr<TableauHandle>;
2634        fn tableau_iter_all(
2635            num_qubits: usize,
2636            unsigned_only: bool,
2637        ) -> UniquePtr<TableauIteratorHandle>;
2638        fn tableau_iterator_clone(
2639            handle: &TableauIteratorHandle,
2640        ) -> UniquePtr<TableauIteratorHandle>;
2641        fn tableau_iterator_next(
2642            handle: Pin<&mut TableauIteratorHandle>,
2643        ) -> UniquePtr<TableauHandle>;
2644        fn tableau_from_named_gate(name: &str) -> Result<UniquePtr<TableauHandle>>;
2645        fn tableau_from_state_vector_data(
2646            state_vector: Vec<f32>,
2647            endian: &str,
2648        ) -> Result<UniquePtr<TableauHandle>>;
2649        fn tableau_from_unitary_matrix_data(
2650            matrix: Vec<f32>,
2651            endian: &str,
2652        ) -> Result<UniquePtr<TableauHandle>>;
2653        fn tableau_from_conjugated_generator_texts(
2654            xs: Vec<String>,
2655            zs: Vec<String>,
2656        ) -> Result<UniquePtr<TableauHandle>>;
2657        fn tableau_from_stabilizer_texts(
2658            stabilizers: Vec<String>,
2659            allow_redundant: bool,
2660            allow_underconstrained: bool,
2661        ) -> Result<UniquePtr<TableauHandle>>;
2662        fn tableau_then(
2663            handle: &TableauHandle,
2664            second: &TableauHandle,
2665        ) -> Result<UniquePtr<TableauHandle>>;
2666        fn new_tableau_simulator(seed: u64, num_qubits: usize)
2667        -> UniquePtr<TableauSimulatorHandle>;
2668        fn new_clifford_string(num_qubits: usize) -> UniquePtr<CliffordStringHandle>;
2669        fn clifford_string_from_text(text: &str) -> Result<UniquePtr<CliffordStringHandle>>;
2670        fn clifford_string_from_pauli_string(
2671            handle: &PauliStringHandle,
2672        ) -> UniquePtr<CliffordStringHandle>;
2673        fn clifford_string_from_circuit(
2674            handle: &CircuitHandle,
2675        ) -> Result<UniquePtr<CliffordStringHandle>>;
2676        fn clifford_string_random(num_qubits: usize) -> UniquePtr<CliffordStringHandle>;
2677        fn clifford_string_all_cliffords_string() -> UniquePtr<CliffordStringHandle>;
2678        fn new_pauli_string(num_qubits: usize) -> UniquePtr<PauliStringHandle>;
2679        fn pauli_string_from_text(text: &str) -> Result<UniquePtr<PauliStringHandle>>;
2680        fn detector_error_model_from_dem_text(
2681            text: &str,
2682        ) -> Result<UniquePtr<DetectorErrorModelHandle>>;
2683        fn circuit_diagram(handle: &CircuitHandle, type_name: &str) -> Result<String>;
2684        fn detector_error_model_diagram(
2685            handle: &DetectorErrorModelHandle,
2686            type_name: &str,
2687        ) -> Result<String>;
2688        fn detector_error_model_clone(
2689            handle: &DetectorErrorModelHandle,
2690        ) -> UniquePtr<DetectorErrorModelHandle>;
2691        fn detector_error_model_add(
2692            left: &DetectorErrorModelHandle,
2693            right: &DetectorErrorModelHandle,
2694        ) -> UniquePtr<DetectorErrorModelHandle>;
2695        fn detector_error_model_add_assign(
2696            left: Pin<&mut DetectorErrorModelHandle>,
2697            right: &DetectorErrorModelHandle,
2698        );
2699        fn detector_error_model_mul(
2700            handle: &DetectorErrorModelHandle,
2701            repetitions: u64,
2702        ) -> UniquePtr<DetectorErrorModelHandle>;
2703        fn detector_error_model_mul_assign(
2704            handle: Pin<&mut DetectorErrorModelHandle>,
2705            repetitions: u64,
2706        );
2707        fn detector_error_model_to_dem_text(handle: &DetectorErrorModelHandle) -> String;
2708        fn detector_error_model_len(handle: &DetectorErrorModelHandle) -> usize;
2709        fn detector_error_model_get_top_level_item(
2710            handle: &DetectorErrorModelHandle,
2711            index: usize,
2712        ) -> DemTopLevelItemData;
2713        fn detector_error_model_get_top_level_repeat_block_body(
2714            handle: &DetectorErrorModelHandle,
2715            index: usize,
2716        ) -> UniquePtr<DetectorErrorModelHandle>;
2717        fn detector_error_model_get_slice(
2718            handle: &DetectorErrorModelHandle,
2719            start: i64,
2720            step: i64,
2721            slice_length: i64,
2722        ) -> UniquePtr<DetectorErrorModelHandle>;
2723        fn detector_error_model_num_detectors(handle: &DetectorErrorModelHandle) -> u64;
2724        fn detector_error_model_num_errors(handle: &DetectorErrorModelHandle) -> u64;
2725        fn detector_error_model_num_observables(handle: &DetectorErrorModelHandle) -> u64;
2726        fn detector_error_model_get_detector_coordinates(
2727            handle: &DetectorErrorModelHandle,
2728            included_detector_indices: &[u64],
2729        ) -> Result<Vec<CoordinateEntryData>>;
2730        fn detector_error_model_clear(handle: Pin<&mut DetectorErrorModelHandle>);
2731        fn detector_error_model_equals(
2732            left: &DetectorErrorModelHandle,
2733            right: &DetectorErrorModelHandle,
2734        ) -> bool;
2735        fn detector_error_model_approx_equals(
2736            left: &DetectorErrorModelHandle,
2737            right: &DetectorErrorModelHandle,
2738            atol: f64,
2739        ) -> bool;
2740        fn detector_error_model_without_tags(
2741            handle: &DetectorErrorModelHandle,
2742        ) -> UniquePtr<DetectorErrorModelHandle>;
2743        fn detector_error_model_flattened(
2744            handle: &DetectorErrorModelHandle,
2745        ) -> UniquePtr<DetectorErrorModelHandle>;
2746        fn detector_error_model_rounded(
2747            handle: &DetectorErrorModelHandle,
2748            digits: u8,
2749        ) -> UniquePtr<DetectorErrorModelHandle>;
2750        fn detector_error_model_append_instruction(
2751            handle: Pin<&mut DetectorErrorModelHandle>,
2752            instruction_type: &str,
2753            args: &[f64],
2754            targets: &[u64],
2755            tag: &str,
2756        ) -> Result<()>;
2757        fn detector_error_model_append_repeat_block(
2758            handle: Pin<&mut DetectorErrorModelHandle>,
2759            repeat_count: u64,
2760            body: &DetectorErrorModelHandle,
2761        ) -> Result<()>;
2762        fn detector_error_model_shortest_graphlike_error(
2763            handle: &DetectorErrorModelHandle,
2764            ignore_ungraphlike_errors: bool,
2765        ) -> Result<UniquePtr<DetectorErrorModelHandle>>;
2766        fn detector_error_model_shortest_error_sat_problem(
2767            handle: &DetectorErrorModelHandle,
2768            format_name: &str,
2769        ) -> Result<String>;
2770        fn detector_error_model_likeliest_error_sat_problem(
2771            handle: &DetectorErrorModelHandle,
2772            quantization: i32,
2773            format_name: &str,
2774        ) -> Result<String>;
2775        fn tableau_clone(handle: &TableauHandle) -> UniquePtr<TableauHandle>;
2776        fn tableau_equals(left: &TableauHandle, right: &TableauHandle) -> bool;
2777        fn tableau_add(left: &TableauHandle, right: &TableauHandle) -> UniquePtr<TableauHandle>;
2778        fn tableau_add_assign(left: Pin<&mut TableauHandle>, right: &TableauHandle);
2779        fn tableau_append(
2780            handle: Pin<&mut TableauHandle>,
2781            gate: &TableauHandle,
2782            targets: &[usize],
2783        ) -> Result<()>;
2784        fn tableau_prepend(
2785            handle: Pin<&mut TableauHandle>,
2786            gate: &TableauHandle,
2787            targets: &[usize],
2788        ) -> Result<()>;
2789        fn tableau_inverse(handle: &TableauHandle, unsigned_only: bool)
2790        -> UniquePtr<TableauHandle>;
2791        fn tableau_raised_to(handle: &TableauHandle, exponent: i64) -> UniquePtr<TableauHandle>;
2792        fn tableau_x_sign(handle: &TableauHandle, target: usize) -> Result<i32>;
2793        fn tableau_y_sign(handle: &TableauHandle, target: usize) -> Result<i32>;
2794        fn tableau_z_sign(handle: &TableauHandle, target: usize) -> Result<i32>;
2795        fn tableau_x_output_pauli(
2796            handle: &TableauHandle,
2797            input_index: usize,
2798            output_index: usize,
2799        ) -> Result<u8>;
2800        fn tableau_y_output_pauli(
2801            handle: &TableauHandle,
2802            input_index: usize,
2803            output_index: usize,
2804        ) -> Result<u8>;
2805        fn tableau_z_output_pauli(
2806            handle: &TableauHandle,
2807            input_index: usize,
2808            output_index: usize,
2809        ) -> Result<u8>;
2810        fn tableau_inverse_x_output_pauli(
2811            handle: &TableauHandle,
2812            input_index: usize,
2813            output_index: usize,
2814        ) -> Result<u8>;
2815        fn tableau_inverse_y_output_pauli(
2816            handle: &TableauHandle,
2817            input_index: usize,
2818            output_index: usize,
2819        ) -> Result<u8>;
2820        fn tableau_inverse_z_output_pauli(
2821            handle: &TableauHandle,
2822            input_index: usize,
2823            output_index: usize,
2824        ) -> Result<u8>;
2825        fn tableau_x_output(handle: &TableauHandle, target: usize) -> UniquePtr<PauliStringHandle>;
2826        fn tableau_y_output(handle: &TableauHandle, target: usize) -> UniquePtr<PauliStringHandle>;
2827        fn tableau_z_output(handle: &TableauHandle, target: usize) -> UniquePtr<PauliStringHandle>;
2828        fn tableau_inverse_x_output(
2829            handle: &TableauHandle,
2830            target: usize,
2831            unsigned_only: bool,
2832        ) -> UniquePtr<PauliStringHandle>;
2833        fn tableau_inverse_y_output(
2834            handle: &TableauHandle,
2835            target: usize,
2836            unsigned_only: bool,
2837        ) -> UniquePtr<PauliStringHandle>;
2838        fn tableau_inverse_z_output(
2839            handle: &TableauHandle,
2840            target: usize,
2841            unsigned_only: bool,
2842        ) -> UniquePtr<PauliStringHandle>;
2843        fn tableau_conjugate_pauli_string(
2844            handle: &TableauHandle,
2845            pauli_string: &PauliStringHandle,
2846        ) -> UniquePtr<PauliStringHandle>;
2847        fn tableau_conjugate_pauli_string_within(
2848            handle: &TableauHandle,
2849            pauli_string: &PauliStringHandle,
2850            targets: &[usize],
2851            inverse: bool,
2852        ) -> Result<UniquePtr<PauliStringHandle>>;
2853        fn tableau_to_stabilizer_texts(handle: &TableauHandle, canonicalize: bool) -> Vec<String>;
2854        fn tableau_to_circuit(
2855            handle: &TableauHandle,
2856            method: &str,
2857        ) -> Result<UniquePtr<CircuitHandle>>;
2858        fn tableau_to_pauli_string(handle: &TableauHandle) -> Result<UniquePtr<PauliStringHandle>>;
2859        fn tableau_simulator_clone(
2860            handle: &TableauSimulatorHandle,
2861        ) -> UniquePtr<TableauSimulatorHandle>;
2862        fn tableau_simulator_num_qubits(handle: &TableauSimulatorHandle) -> usize;
2863        fn tableau_simulator_set_num_qubits(
2864            handle: Pin<&mut TableauSimulatorHandle>,
2865            new_num_qubits: usize,
2866        );
2867        fn tableau_simulator_current_inverse_tableau(
2868            handle: &TableauSimulatorHandle,
2869        ) -> UniquePtr<TableauHandle>;
2870        fn tableau_simulator_set_inverse_tableau(
2871            handle: Pin<&mut TableauSimulatorHandle>,
2872            tableau: &TableauHandle,
2873        );
2874        fn tableau_simulator_current_measurement_record(handle: &TableauSimulatorHandle)
2875        -> Vec<u8>;
2876        fn tableau_simulator_do_circuit(
2877            handle: Pin<&mut TableauSimulatorHandle>,
2878            circuit: &CircuitHandle,
2879        );
2880        fn tableau_simulator_do_pauli_string(
2881            handle: Pin<&mut TableauSimulatorHandle>,
2882            pauli_string: &PauliStringHandle,
2883        );
2884        fn tableau_simulator_do_tableau(
2885            handle: Pin<&mut TableauSimulatorHandle>,
2886            tableau: &TableauHandle,
2887            targets: &[usize],
2888        );
2889        fn tableau_simulator_peek_bloch(
2890            handle: Pin<&mut TableauSimulatorHandle>,
2891            target: usize,
2892        ) -> UniquePtr<PauliStringHandle>;
2893        fn tableau_simulator_peek_x(handle: Pin<&mut TableauSimulatorHandle>, target: usize)
2894        -> i32;
2895        fn tableau_simulator_peek_y(handle: Pin<&mut TableauSimulatorHandle>, target: usize)
2896        -> i32;
2897        fn tableau_simulator_peek_z(handle: Pin<&mut TableauSimulatorHandle>, target: usize)
2898        -> i32;
2899        fn tableau_simulator_measure(
2900            handle: Pin<&mut TableauSimulatorHandle>,
2901            target: usize,
2902        ) -> bool;
2903        fn tableau_simulator_measure_many(
2904            handle: Pin<&mut TableauSimulatorHandle>,
2905            targets: &[usize],
2906        ) -> Vec<u8>;
2907        fn tableau_simulator_peek_observable_expectation(
2908            handle: &TableauSimulatorHandle,
2909            observable: &PauliStringHandle,
2910        ) -> Result<i32>;
2911        fn tableau_simulator_measure_observable(
2912            handle: Pin<&mut TableauSimulatorHandle>,
2913            observable: &PauliStringHandle,
2914            flip_probability: f64,
2915        ) -> Result<bool>;
2916        fn tableau_simulator_postselect_observable(
2917            handle: Pin<&mut TableauSimulatorHandle>,
2918            observable: &PauliStringHandle,
2919            desired_value: bool,
2920        ) -> Result<()>;
2921        fn tableau_simulator_postselect_x(
2922            handle: Pin<&mut TableauSimulatorHandle>,
2923            targets: &[usize],
2924            desired_value: bool,
2925        ) -> Result<()>;
2926        fn tableau_simulator_postselect_y(
2927            handle: Pin<&mut TableauSimulatorHandle>,
2928            targets: &[usize],
2929            desired_value: bool,
2930        ) -> Result<()>;
2931        fn tableau_simulator_postselect_z(
2932            handle: Pin<&mut TableauSimulatorHandle>,
2933            targets: &[usize],
2934            desired_value: bool,
2935        ) -> Result<()>;
2936        fn tableau_simulator_measure_kickback(
2937            handle: Pin<&mut TableauSimulatorHandle>,
2938            target: usize,
2939        ) -> TableauMeasureKickbackData;
2940        fn new_frame_simulator(
2941            batch_size: usize,
2942            disable_stabilizer_randomization: bool,
2943            num_qubits: usize,
2944            seed: u64,
2945        ) -> UniquePtr<FrameSimulatorHandle>;
2946        fn frame_simulator_clone(handle: &FrameSimulatorHandle) -> UniquePtr<FrameSimulatorHandle>;
2947        fn frame_simulator_batch_size(handle: &FrameSimulatorHandle) -> usize;
2948        fn frame_simulator_num_qubits(handle: &FrameSimulatorHandle) -> usize;
2949        fn frame_simulator_num_measurements(handle: &FrameSimulatorHandle) -> usize;
2950        fn frame_simulator_num_detectors(handle: &FrameSimulatorHandle) -> usize;
2951        fn frame_simulator_num_observables(handle: &FrameSimulatorHandle) -> usize;
2952        fn frame_simulator_clear(handle: Pin<&mut FrameSimulatorHandle>);
2953        fn frame_simulator_do_circuit(
2954            handle: Pin<&mut FrameSimulatorHandle>,
2955            circuit: &CircuitHandle,
2956        );
2957        fn frame_simulator_set_pauli_flip(
2958            handle: Pin<&mut FrameSimulatorHandle>,
2959            pauli: u8,
2960            qubit_index: i64,
2961            instance_index: i64,
2962        ) -> Result<()>;
2963        fn frame_simulator_peek_pauli_flips(handle: &FrameSimulatorHandle) -> Vec<String>;
2964        fn frame_simulator_peek_pauli_flip(
2965            handle: &FrameSimulatorHandle,
2966            instance_index: i64,
2967        ) -> Result<String>;
2968        fn frame_simulator_broadcast_pauli_errors(
2969            handle: Pin<&mut FrameSimulatorHandle>,
2970            pauli: u8,
2971            mask: Vec<u8>,
2972            mask_num_qubits: usize,
2973            p: f32,
2974        ) -> Result<()>;
2975        fn frame_simulator_generate_bernoulli_samples(
2976            handle: Pin<&mut FrameSimulatorHandle>,
2977            num_samples: usize,
2978            p: f32,
2979            bit_packed: bool,
2980        ) -> Result<Vec<u8>>;
2981        fn frame_simulator_append_measurement_flips(
2982            handle: Pin<&mut FrameSimulatorHandle>,
2983            data: Vec<u8>,
2984            num_measurements: usize,
2985            bit_packed: bool,
2986        ) -> Result<()>;
2987        fn frame_simulator_get_measurement_flips(
2988            handle: &FrameSimulatorHandle,
2989            bit_packed: bool,
2990        ) -> BitTableData;
2991        fn frame_simulator_get_detector_flips(
2992            handle: &FrameSimulatorHandle,
2993            bit_packed: bool,
2994        ) -> BitTableData;
2995        fn frame_simulator_get_observable_flips(
2996            handle: &FrameSimulatorHandle,
2997            bit_packed: bool,
2998        ) -> BitTableData;
2999        fn clifford_string_clone(handle: &CliffordStringHandle) -> UniquePtr<CliffordStringHandle>;
3000        fn clifford_string_equals(
3001            left: &CliffordStringHandle,
3002            right: &CliffordStringHandle,
3003        ) -> bool;
3004        fn clifford_string_num_qubits(handle: &CliffordStringHandle) -> usize;
3005        fn clifford_string_get_item_name(
3006            handle: &CliffordStringHandle,
3007            index: i64,
3008        ) -> Result<String>;
3009        fn clifford_string_get_slice(
3010            handle: &CliffordStringHandle,
3011            start: i64,
3012            step: i64,
3013            slice_length: i64,
3014        ) -> UniquePtr<CliffordStringHandle>;
3015        fn clifford_string_add(
3016            left: &CliffordStringHandle,
3017            right: &CliffordStringHandle,
3018        ) -> UniquePtr<CliffordStringHandle>;
3019        fn clifford_string_add_assign(
3020            left: Pin<&mut CliffordStringHandle>,
3021            right: &CliffordStringHandle,
3022        );
3023        fn clifford_string_mul(
3024            left: &CliffordStringHandle,
3025            right: &CliffordStringHandle,
3026        ) -> UniquePtr<CliffordStringHandle>;
3027        fn clifford_string_mul_assign(
3028            left: Pin<&mut CliffordStringHandle>,
3029            right: &CliffordStringHandle,
3030        );
3031        fn clifford_string_repeat(
3032            handle: &CliffordStringHandle,
3033            repetitions: u64,
3034        ) -> Result<UniquePtr<CliffordStringHandle>>;
3035        fn clifford_string_repeat_assign(
3036            handle: Pin<&mut CliffordStringHandle>,
3037            repetitions: u64,
3038        ) -> Result<()>;
3039        fn clifford_string_pow(
3040            handle: &CliffordStringHandle,
3041            exponent: i64,
3042        ) -> UniquePtr<CliffordStringHandle>;
3043        fn clifford_string_ipow(handle: Pin<&mut CliffordStringHandle>, exponent: i64);
3044        fn clifford_string_x_outputs(handle: &CliffordStringHandle)
3045        -> UniquePtr<PauliStringHandle>;
3046        fn clifford_string_x_signs_bit_packed(handle: &CliffordStringHandle) -> Vec<u8>;
3047        fn clifford_string_y_outputs(handle: &CliffordStringHandle)
3048        -> UniquePtr<PauliStringHandle>;
3049        fn clifford_string_y_signs_bit_packed(handle: &CliffordStringHandle) -> Vec<u8>;
3050        fn clifford_string_z_outputs(handle: &CliffordStringHandle)
3051        -> UniquePtr<PauliStringHandle>;
3052        fn clifford_string_z_signs_bit_packed(handle: &CliffordStringHandle) -> Vec<u8>;
3053        fn clifford_string_to_string(handle: &CliffordStringHandle) -> String;
3054        fn clifford_string_to_repr(handle: &CliffordStringHandle) -> String;
3055        fn pauli_string_clone(handle: &PauliStringHandle) -> UniquePtr<PauliStringHandle>;
3056        fn pauli_string_equals(left: &PauliStringHandle, right: &PauliStringHandle) -> bool;
3057        fn pauli_string_num_qubits(handle: &PauliStringHandle) -> usize;
3058        fn pauli_string_weight(handle: &PauliStringHandle) -> usize;
3059        fn pauli_string_get_item(handle: &PauliStringHandle, index: i64) -> Result<u8>;
3060        fn pauli_string_set_item(
3061            handle: Pin<&mut PauliStringHandle>,
3062            index: i64,
3063            new_pauli: u8,
3064        ) -> Result<()>;
3065        fn pauli_string_get_slice(
3066            handle: &PauliStringHandle,
3067            start: i64,
3068            step: i64,
3069            slice_length: i64,
3070        ) -> UniquePtr<PauliStringHandle>;
3071        fn pauli_string_random(num_qubits: usize) -> UniquePtr<PauliStringHandle>;
3072        fn pauli_string_iter_all(
3073            num_qubits: usize,
3074            min_weight: usize,
3075            max_weight: usize,
3076            allow_x: bool,
3077            allow_y: bool,
3078            allow_z: bool,
3079        ) -> UniquePtr<PauliStringIteratorHandle>;
3080        fn pauli_string_iterator_clone(
3081            handle: &PauliStringIteratorHandle,
3082        ) -> UniquePtr<PauliStringIteratorHandle>;
3083        fn pauli_string_iterator_next(
3084            handle: Pin<&mut PauliStringIteratorHandle>,
3085        ) -> UniquePtr<PauliStringHandle>;
3086        fn pauli_string_commutes(handle: &PauliStringHandle, other: &PauliStringHandle) -> bool;
3087        fn pauli_string_pauli_indices(
3088            handle: &PauliStringHandle,
3089            included_paulis: &str,
3090        ) -> Result<Vec<u64>>;
3091        fn pauli_string_sign_code(handle: &PauliStringHandle) -> i32;
3092        fn pauli_string_to_tableau(handle: &PauliStringHandle) -> UniquePtr<TableauHandle>;
3093        fn pauli_string_to_string(handle: &PauliStringHandle) -> String;
3094        fn pauli_string_to_repr(handle: &PauliStringHandle) -> String;
3095        fn tableau_num_qubits(handle: &TableauHandle) -> usize;
3096        fn tableau_to_string(handle: &TableauHandle) -> String;
3097        fn tableau_to_repr(handle: &TableauHandle) -> String;
3098        fn tableau_to_unitary_matrix_data(handle: &TableauHandle, endian: &str)
3099        -> Result<Vec<f32>>;
3100        fn tableau_to_state_vector_data(handle: &TableauHandle, endian: &str) -> Result<Vec<f32>>;
3101        fn circuit_compile_sampler(
3102            handle: &CircuitHandle,
3103            skip_reference_sample: bool,
3104            seed: u64,
3105        ) -> UniquePtr<MeasurementSamplerHandle>;
3106        fn measurement_sampler_num_measurements(handle: &MeasurementSamplerHandle) -> u64;
3107        fn measurement_sampler_sample_bit_packed(
3108            handle: Pin<&mut MeasurementSamplerHandle>,
3109            shots: u64,
3110        ) -> Vec<u8>;
3111        fn measurement_sampler_sample_write(
3112            handle: Pin<&mut MeasurementSamplerHandle>,
3113            shots: u64,
3114            filepath: &str,
3115            format_name: &str,
3116        ) -> Result<()>;
3117        fn circuit_compile_detector_sampler(
3118            handle: &CircuitHandle,
3119            seed: u64,
3120        ) -> UniquePtr<DetectorSamplerHandle>;
3121        fn detector_error_model_compile_sampler(
3122            handle: &DetectorErrorModelHandle,
3123            seed: u64,
3124        ) -> UniquePtr<DemSamplerHandle>;
3125        fn detector_sampler_num_detectors(handle: &DetectorSamplerHandle) -> u64;
3126        fn detector_sampler_num_observables(handle: &DetectorSamplerHandle) -> u64;
3127        fn dem_sampler_num_detectors(handle: &DemSamplerHandle) -> u64;
3128        fn dem_sampler_num_observables(handle: &DemSamplerHandle) -> u64;
3129        fn dem_sampler_num_errors(handle: &DemSamplerHandle) -> u64;
3130        fn detector_sampler_sample_bit_packed(
3131            handle: Pin<&mut DetectorSamplerHandle>,
3132            shots: u64,
3133        ) -> Vec<u8>;
3134        fn detector_sampler_sample_observables_bit_packed(
3135            handle: Pin<&mut DetectorSamplerHandle>,
3136            shots: u64,
3137        ) -> Vec<u8>;
3138        fn detector_sampler_sample_bit_packed_separate_observables(
3139            handle: Pin<&mut DetectorSamplerHandle>,
3140            shots: u64,
3141        ) -> DetectorSampleBatch;
3142        fn dem_sampler_sample_bit_packed(
3143            handle: Pin<&mut DemSamplerHandle>,
3144            shots: u64,
3145        ) -> DemSampleBatch;
3146        fn dem_sampler_sample_bit_packed_replay(
3147            handle: Pin<&mut DemSamplerHandle>,
3148            recorded_errors: &[u8],
3149            shots: u64,
3150        ) -> DemSampleBatch;
3151        fn dem_sampler_sample_write(
3152            handle: Pin<&mut DemSamplerHandle>,
3153            shots: u64,
3154            dets_filepath: &str,
3155            dets_format_name: &str,
3156            obs_filepath: &str,
3157            obs_format_name: &str,
3158            err_filepath: &str,
3159            err_format_name: &str,
3160            write_errors: bool,
3161            replay_err_filepath: &str,
3162            replay_err_format_name: &str,
3163            replay_errors: bool,
3164        ) -> Result<()>;
3165        fn detector_sampler_sample_write(
3166            handle: Pin<&mut DetectorSamplerHandle>,
3167            shots: u64,
3168            filepath: &str,
3169            format_name: &str,
3170        ) -> Result<()>;
3171        fn detector_sampler_sample_write_separate_observables(
3172            handle: Pin<&mut DetectorSamplerHandle>,
3173            shots: u64,
3174            dets_filepath: &str,
3175            dets_format_name: &str,
3176            obs_filepath: &str,
3177            obs_format_name: &str,
3178        ) -> Result<()>;
3179        fn circuit_compile_m2d_converter(
3180            handle: &CircuitHandle,
3181            skip_reference_sample: bool,
3182        ) -> UniquePtr<MeasurementsToDetectionEventsConverterHandle>;
3183        fn m2d_converter_num_measurements(
3184            handle: &MeasurementsToDetectionEventsConverterHandle,
3185        ) -> u64;
3186        fn m2d_converter_num_detectors(
3187            handle: &MeasurementsToDetectionEventsConverterHandle,
3188        ) -> u64;
3189        fn m2d_converter_num_observables(
3190            handle: &MeasurementsToDetectionEventsConverterHandle,
3191        ) -> u64;
3192        fn m2d_converter_num_sweep_bits(
3193            handle: &MeasurementsToDetectionEventsConverterHandle,
3194        ) -> u64;
3195        fn m2d_converter_convert_measurements_bit_packed(
3196            handle: Pin<&mut MeasurementsToDetectionEventsConverterHandle>,
3197            measurements: &[u8],
3198            shots: u64,
3199            append_observables: bool,
3200        ) -> Vec<u8>;
3201        fn m2d_converter_convert_measurements_and_sweep_bits_bit_packed(
3202            handle: Pin<&mut MeasurementsToDetectionEventsConverterHandle>,
3203            measurements: &[u8],
3204            sweep_bits: &[u8],
3205            shots: u64,
3206            append_observables: bool,
3207        ) -> Vec<u8>;
3208        fn m2d_converter_convert_observables_with_sweep_bits_bit_packed(
3209            handle: Pin<&mut MeasurementsToDetectionEventsConverterHandle>,
3210            measurements: &[u8],
3211            sweep_bits: &[u8],
3212            shots: u64,
3213        ) -> Vec<u8>;
3214        fn m2d_converter_convert_observables_bit_packed(
3215            handle: Pin<&mut MeasurementsToDetectionEventsConverterHandle>,
3216            measurements: &[u8],
3217            shots: u64,
3218        ) -> Vec<u8>;
3219        fn m2d_converter_convert_file(
3220            handle: Pin<&mut MeasurementsToDetectionEventsConverterHandle>,
3221            measurements_filepath: &str,
3222            measurements_format: &str,
3223            sweep_bits_filepath: &str,
3224            sweep_bits_format: &str,
3225            detection_events_filepath: &str,
3226            detection_events_format: &str,
3227            append_observables: bool,
3228            obs_out_filepath: &str,
3229            obs_out_format: &str,
3230        ) -> Result<()>;
3231
3232        fn new_smoke_probe() -> UniquePtr<SmokeProbe>;
3233        fn describe(self: &SmokeProbe) -> String;
3234        fn weighted_checksum(self: &SmokeProbe, values: &[u64]) -> u64;
3235    }
3236}