use std::{collections::HashMap, hash::BuildHasher};
use crate::traits::*;
macro_rules! impl_acmap_base {
($($seg:ident)::+) => {
impl<'a, V, Hasher, W> crate::traits::ACMapBase for $($seg)::+<W, V, Hasher>
where
V: Coefficient,
Hasher: Clone + BuildHasher + Default,
W:,
{
fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_and_hasher(capacity, Hasher::default())
}
fn len(&self) -> usize {
$($seg)::+::len(self)
}
fn clear(&mut self) {
$($seg)::+::clear(self)
}
}
};
}
macro_rules! impl_acmap_add_assign {
($($seg:ident)::+) => {
impl<'a, S, V, Hasher, W> crate::traits::ACMapAddAssign<S, V, Hasher, W> for $($seg)::+<W, V, Hasher>
where
S: PauliStorage + 'a,
V: Coefficient + 'a,
Hasher: Default + Clone + BuildHasher + 'a,
W: PauliWordTrait + 'a,
{
fn add_assign(&mut self, key: W, value: V) {
self.entry(key)
.and_modify(|v| *v += value.clone())
.or_insert(value);
}
fn map_add_assign<F>(&self, dest: &mut Self, f: F)
where
F: Fn(&W, &V) -> (W, V) + Sync + Send,
{
for (k, v) in self.iter() {
let (new_k, new_v) = f(k, v);
<Self as ACMapAddAssign<S, V, Hasher, W>>::add_assign(dest, new_k, new_v);
}
}
}
};
}
macro_rules! impl_acmap_mul_assign {
($($seg:ident)::+) => {
impl<'a, V, Hasher, W> crate::traits::ACMapMulAssign<V, Hasher> for $($seg)::+<W, V, Hasher>
where
V: Coefficient + 'a,
Hasher: Default + Clone + BuildHasher + 'a,
W:,
{
fn mul_assign(&mut self, value: V) {
for v in self.values_mut() {
*v *= value.clone();
}
}
}
};
}
macro_rules! impl_acmap_iter {
($($seg:ident)::+) => {
impl<'a, V, Hasher, W> crate::traits::ACMapIter<'a> for $($seg)::+<W, V, Hasher>
where
V: Coefficient + 'a,
Hasher: Default + Clone + BuildHasher + 'a,
W: 'a,
{
type Item = (&'a W, &'a V);
type Iter = std::collections::hash_map::Iter<'a, W, V>;
fn iter(&'a self) -> Self::Iter {
Self::iter(self)
}
}
};
}
macro_rules! impl_acmap_trace {
($($seg:ident)::+) => {
impl<'a, P, C, Hasher, W> crate::traits::Trace<'a, P> for $($seg)::+<W, C, Hasher>
where
P: crate::traits::Trace<'a, W, Output = bool> + 'a,
C: Coefficient + 'a,
Hasher: Default + Clone + BuildHasher + 'a,
W: 'a,
{
type Output = C;
fn trace(&'a self, value: &'a P) -> Self::Output {
let sum = C::zero();
self.iter().fold(sum, |mut acc, (k, v)| {
value.trace(k).then(|| acc += v.clone());
acc
})
}
}
};
}
macro_rules! impl_acmap_combine_unique {
($($seg:ident)::+) => {
impl<C, Hasher, W> ACMapConsume for $($seg)::+<W, C, Hasher>
where
C: Coefficient,
Hasher: Default + Clone + BuildHasher,
W: std::hash::Hash + std::cmp::Eq,
{
fn consume(&mut self, dest: &mut Self) {
for (k, v) in dest.drain() {
self.entry(k)
.and_modify(|val| *val += v.clone())
.or_insert(v);
}
}
}
};
}
macro_rules! impl_acmap_insert {
($($seg:ident)::+) => {
impl<'a, S, C, Hasher, W> ACMapInsert<S, C, Hasher, W> for $($seg)::+<W, C, Hasher>
where
S: PauliStorage + 'a,
C: Coefficient + 'a,
Hasher: Default + Clone + BuildHasher + 'a,
W: PauliWordTrait + 'a,
{
fn map_insert_vec<F>(&mut self, dest: &mut Vec<(W, C)>, f: F)
where
F: Fn(&W, &mut C) -> Option<(W, C)> + Sync + Send,
{
for (k, v) in self.iter_mut() {
if let Some(entry) = f(k, v) {
dest.push(entry);
}
}
}
fn map_insert_multiple<F>(&mut self, dest: &mut Self, f: F)
where
F: Fn(&W, &mut C) -> Option<Vec<(W, C)>> + Sync + Send,
{
for (k, v) in self.iter_mut() {
if let Some(entries) = f(k, v) {
for (new_k, new_v) in entries {
dest.entry(new_k)
.and_modify(|val| *val += new_v.clone())
.or_insert(new_v);
}
}
}
}
}
};
}
macro_rules! impl_acmap_contains {
($($seg:ident)::+) => {
impl<S, C, H, W> ACMapContains<S, C, H, W> for $($seg)::+<W, C, H>
where
S: PauliStorage,
C: Coefficient,
H: Default + Clone + BuildHasher,
W: PauliWordTrait,
{
fn contains_with<F>(&self, key: &W, f: F) -> bool
where
F: Fn(&C) -> bool,
{
match self.get(key) {
Some(v) => f(v),
None => false,
}
}
}
};
}
macro_rules! impl_acmap_scale {
($($seg:ident)::+) => {
impl<S, V, H, W> ACMapScale<S, V, H, W> for $($seg)::+<W, V, H>
where
S: PauliStorage,
V: Coefficient,
H: BuildHasher + Clone + Default,
W: PauliWordTrait,
{
fn scale<F>(&mut self, f: F)
where
F: Fn(&W, &mut V) + Sync + Send,
{
for (k, v) in self.iter_mut() {
f(k, v);
}
}
}
};
}
macro_rules! impl_acmap_retain {
($($seg:ident)::+) => {
impl<S, V, H, W> ACMapRetain<S, V, H, W> for $($seg)::+<W, V, H>
where
S: PauliStorage,
V: Coefficient,
H: BuildHasher + Clone + Default,
W: PauliWordTrait,
{
fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&W, &V) -> bool,
{
Self::retain(self, |k, v| f(k, v));
}
}
};
}
macro_rules! impl_acmap {
($($seg:ident)::+) => {
impl_acmap_base!($($seg)::+);
impl_acmap_add_assign!($($seg)::+);
impl_acmap_mul_assign!($($seg)::+);
impl_acmap_iter!($($seg)::+);
impl_acmap_trace!($($seg)::+);
impl_acmap_combine_unique!($($seg)::+);
impl_acmap_insert!($($seg)::+);
impl_acmap_contains!($($seg)::+);
impl_acmap_scale!($($seg)::+);
impl_acmap_retain!($($seg)::+);
};
}
impl_acmap!(HashMap);
#[cfg(feature = "indexmap")]
mod indexmap_impl {
use super::*;
impl<'a, V, H, W> crate::traits::ACMapIter<'a> for indexmap::IndexMap<W, V, H>
where
V: Coefficient + 'a,
H: Default + Clone + BuildHasher + 'a,
W: 'a,
{
type Item = (&'a W, &'a V);
type Iter = indexmap::map::Iter<'a, W, V>;
fn iter(&'a self) -> Self::Iter {
Self::iter(self)
}
}
impl<C, H, W> ACMapConsume for indexmap::IndexMap<W, C, H>
where
C: Coefficient,
H: Default + Clone + BuildHasher,
W: std::hash::Hash + std::cmp::Eq,
{
fn consume(&mut self, dest: &mut Self) {
for (k, v) in dest.drain(..) {
self.entry(k)
.and_modify(|val| *val += v.clone())
.or_insert(v);
}
}
}
impl_acmap_base!(indexmap::IndexMap);
impl_acmap_add_assign!(indexmap::IndexMap);
impl_acmap_mul_assign!(indexmap::IndexMap);
impl_acmap_trace!(indexmap::IndexMap);
impl_acmap_insert!(indexmap::IndexMap);
impl_acmap_contains!(indexmap::IndexMap);
impl_acmap_scale!(indexmap::IndexMap);
impl_acmap_retain!(indexmap::IndexMap);
}
#[cfg(all(feature = "ahash", not(target_arch = "wasm32")))]
mod ahash_impl {
use super::*;
impl<V, H, W> crate::traits::ACMapBase for ahash::AHashMap<W, V, H>
where
V: Coefficient,
H: Clone + BuildHasher + Default,
W:,
{
fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_and_hasher(capacity, H::default())
}
fn len(&self) -> usize {
HashMap::len(self)
}
fn clear(&mut self) {
HashMap::clear(self)
}
}
impl<'a, V, H, W> crate::traits::ACMapIter<'a> for ahash::AHashMap<W, V, H>
where
V: Coefficient + 'a,
H: Default + Clone + BuildHasher + 'a,
W: 'a,
{
type Item = (&'a W, &'a V);
type Iter = std::collections::hash_map::Iter<'a, W, V>;
fn iter(&'a self) -> Self::Iter {
HashMap::iter(self)
}
}
impl<S, V, H, W> ACMapRetain<S, V, H, W> for ahash::AHashMap<W, V, H>
where
S: PauliStorage,
V: Coefficient,
H: BuildHasher + Clone + Default,
W: PauliWordTrait,
{
fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&W, &V) -> bool,
{
HashMap::retain(self, |k, v| f(k, v));
}
}
impl_acmap_add_assign!(ahash::AHashMap);
impl_acmap_mul_assign!(ahash::AHashMap);
impl_acmap_trace!(ahash::AHashMap);
impl_acmap_combine_unique!(ahash::AHashMap);
impl_acmap_insert!(ahash::AHashMap);
impl_acmap_contains!(ahash::AHashMap);
impl_acmap_scale!(ahash::AHashMap);
}