rqism 0.3.3

A multi-backend quantum circuit simulator
Documentation
//use std::collections::HashMap;
use dashmap::DashMap;

use ndarray::Array2;
use num::Complex;
use rayon::prelude::*;

use crate::state_vector;

/// A sparse quantum state that stores only non-zero components of the state
#[derive(Debug, Clone)]
pub struct SQS {
    reals: DashMap<usize, f32>,
    imaginaries: DashMap<usize, f32>,
    pub n: usize,
}

impl SQS {
    pub fn new(n: usize) -> Self {
        let reals = DashMap::new();
        let imaginaries = DashMap::new();

        Self {
            reals,
            imaginaries,
            n,
        }
    }

    pub fn set(&self, i: usize, v: Complex<f32>) {
        if i > self.n {
            panic!(
                "attempting to set value at index {} but length is {}",
                i, self.n
            );
        }

        if v.re != 0.0 {
            self.reals.insert(i, v.re);
        } else {
            self.reals.remove(&i);
        }

        if v.im != 0.0 {
            self.imaginaries.insert(i, v.im);
        } else {
            self.imaginaries.remove(&i);
        }
    }

    pub fn get(&self, i: usize) -> Complex<f32> {
        if i > self.n {
            panic!(
                "attempting to get value at index {} but length is {}",
                i, self.n
            );
        }

        Complex::new(
            if let Some(re) = self.reals.get(&i) {
                *re
            } else {
                0.0
            },
            if let Some(im) = self.imaginaries.get(&i) {
                *im
            } else {
                0.0
            },
        )
    }

    pub fn dot(&self, rhs: &Array2<Complex<f32>>) -> Self {
        let c = Self::new(self.n);

        if self.n > state_vector::MULTITHREADING_THRESHOLD {
            rhs.rows()
                .into_iter()
                .enumerate()
                .par_bridge()
                .for_each(|(i, row)| {
                    c.set(
                        i,
                        row.iter()
                            .enumerate()
                            .par_bridge()
                            .map(|(j, x)| x * self.get(j))
                            .sum(),
                    )
                });
        } else {
            for (i, row) in rhs.rows().into_iter().enumerate() {
                c.set(
                    i,
                    row.iter().enumerate().map(|(j, x)| x * self.get(j)).sum(),
                );
            }
        }

        c
    }

    pub fn to_vec(&self) -> Vec<Complex<f32>> {
        (0..self.n).map(|x| self.get(x)).collect()
    }

    pub fn fill_zero(&mut self) {
        *self = Self::new(self.n);
    }

    pub fn iter(&self) -> SQSIterator {
        SQSIterator { sqs: self, n: 0 }
    }
}

/// iterator over a sparse quantum state
pub struct SQSIterator<'a> {
    sqs: &'a SQS,
    n: usize,
}

impl Iterator for SQSIterator<'_> {
    type Item = Complex<f32>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.n >= self.sqs.n {
            return None;
        }

        let r = Some(self.sqs.get(self.n));

        self.n += 1;

        r
    }
}

// not sure if this implementation is proper, but it works without UB
unsafe impl Send for SQS {}
unsafe impl Sync for SQS {}