paulistrings 0.1.2

Classical simulation of quantum circuits in the Pauli basis, parallel across threads, NUMA domains, MPI ranks and GPUs
Documentation
use super::PauliSum;
use num_complex::Complex64;

use crate::pauli_string::PauliString;

impl<const W: usize> PauliSum<W> {
    /// A sum from `(label, coeff)` pairs, character `i` being qubit `i`, via `BuildAccumulator`.
    pub(crate) fn from_strings(terms: &[(&str, Complex64)]) -> Self {
        assert!(!terms.is_empty(), "from_strings requires at least one term");
        let num_qubits = terms[0].0.len();
        assert!(num_qubits <= 64 * W, "num_qubits must fit in W*64 bits");
        let mut accumulator = crate::pauli_sum::accumulator::BuildAccumulator::<W>::new(num_qubits);
        for (s, c) in terms {
            assert_eq!(s.len(), num_qubits, "all pauli strings must have the same length",);
            let mut x = [0u64; W];
            let mut z = [0u64; W];
            for (i, label) in s.chars().enumerate() {
                let word = i / 64;
                let bit = 1u64 << (i % 64);
                match label {
                    'I' => {}
                    'X' => x[word] |= bit,
                    'Z' => z[word] |= bit,
                    'Y' => {
                        x[word] |= bit;
                        z[word] |= bit;
                    }
                    other => panic!("unexpected Pauli char {:?} (expected I/X/Y/Z)", other),
                }
            }
            let p = PauliString::<W> { x, z };
            accumulator.add_term(p, *c);
        }
        accumulator.finalize()
    }
}