use dashmap::DashMap;
use ndarray::Array2;
use num::Complex;
use rayon::prelude::*;
use crate::state_vector;
#[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 }
}
}
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
}
}
unsafe impl Send for SQS {}
unsafe impl Sync for SQS {}