Skip to main content

ppvm_traits/map/
dashmap.rs

1// SPDX-FileCopyrightText: 2026 The PPVM Authors
2// SPDX-License-Identifier: Apache-2.0
3
4use std::hash::BuildHasher;
5
6use crate::traits::*;
7use dashmap::DashMap;
8use rayon::prelude::*;
9
10impl<V, Hasher, T> ACMapBase for DashMap<T, V, Hasher>
11where
12    T: std::hash::Hash + Eq,
13    V: Coefficient,
14    Hasher: Clone + BuildHasher + Default,
15{
16    fn with_capacity(capacity: usize) -> Self {
17        DashMap::with_capacity_and_hasher(capacity, Hasher::default())
18    }
19
20    fn len(&self) -> usize {
21        self.len()
22    }
23
24    fn clear(&mut self) {
25        Self::clear(self);
26    }
27}
28
29impl<S, V, Hasher, W> ACMapAddAssign<S, V, Hasher, W> for DashMap<W, V, Hasher>
30where
31    S: PauliStorage,
32    V: Coefficient + Sync + Send,
33    Hasher: Default + Clone + BuildHasher + Sync + Send,
34    W: PauliWordTrait + Sync + Send,
35{
36    fn add_assign(&mut self, key: W, value: V) {
37        self.entry(key)
38            .and_modify(|v| *v += value.clone())
39            .or_insert(value);
40    }
41
42    fn map_add_assign<F>(&self, dest: &mut Self, f: F)
43    where
44        F: Fn(&W, &V) -> (W, V) + Sync + Send,
45    {
46        self.par_iter().for_each(|entry| {
47            let (new_k, new_v) = f(entry.key(), entry.value());
48            dest.entry(new_k)
49                .and_modify(|v| *v += new_v.clone())
50                .or_insert(new_v);
51        });
52    }
53}
54
55impl<V, Hasher, W> ACMapMulAssign<V, Hasher> for DashMap<W, V, Hasher>
56where
57    V: Coefficient + Send + Sync,
58    Hasher: Default + Clone + BuildHasher + Sync + Send,
59    W: std::hash::Hash + std::cmp::Eq + Send + Sync,
60{
61    fn mul_assign(&mut self, value: V) {
62        self.par_iter_mut()
63            .for_each(|mut v| *v.value_mut() *= value.clone());
64    }
65}
66
67impl<'a, V, Hasher, W> ACMapIter<'a> for DashMap<W, V, Hasher>
68where
69    V: Coefficient + 'a,
70    Hasher: Default + Clone + BuildHasher + 'a,
71    W: std::hash::Hash + std::cmp::Eq + 'a,
72{
73    type Item = dashmap::mapref::multiple::RefMulti<'a, W, V>;
74    type Iter = dashmap::iter::Iter<'a, W, V, Hasher, DashMap<W, V, Hasher>>;
75
76    fn iter(&'a self) -> Self::Iter {
77        DashMap::iter(self)
78    }
79}
80
81impl<'a, P, C, Hasher, W> Trace<'a, P> for DashMap<W, C, Hasher>
82where
83    P: Sync + 'a,
84    for<'b> P: Trace<'b, W, Output = bool>,
85    C: Coefficient + Send + Sync + 'a,
86    Hasher: Clone + std::hash::BuildHasher + Default + Send + Sync + 'a,
87    W: std::hash::Hash + std::cmp::Eq + Sync + Send + 'a,
88{
89    type Output = C;
90    fn trace(&'a self, value: &'a P) -> Self::Output {
91        self.par_iter()
92            .filter(|entry| value.trace(entry.key()))
93            .map(|entry| entry.value().clone())
94            .sum()
95    }
96}
97
98impl<C, H, W> ACMapConsume for DashMap<W, C, H>
99where
100    C: Coefficient + Send + Sync,
101    H: Clone + BuildHasher + Send + Sync,
102    W: std::hash::Hash + std::cmp::Eq + Clone + Sync + Send,
103{
104    fn consume(&mut self, dest: &mut Self) {
105        dest.par_iter().for_each(|entry| {
106            self.entry(entry.key().clone())
107                .and_modify(|v| *v += entry.value().clone())
108                .or_insert_with(|| entry.value().clone());
109        });
110
111        dest.clear();
112    }
113}
114
115impl<S, C, H, W> ACMapInsert<S, C, H, W> for DashMap<W, C, H>
116where
117    S: PauliStorage,
118    C: Coefficient + Send + Sync,
119    H: Default + Clone + BuildHasher + Send + Sync,
120    W: PauliWordTrait + Send + Sync,
121{
122    fn map_insert_vec<F>(&mut self, dest: &mut Vec<(W, C)>, f: F)
123    where
124        F: Fn(&W, &mut C) -> Option<(W, C)> + Sync + Send,
125    {
126        use rayon::iter::ParallelExtend;
127        dest.par_extend(self.par_iter_mut().filter_map(|mut entry| {
128            let (k, v) = entry.pair_mut();
129            f(k, v)
130        }));
131    }
132
133    fn map_insert_multiple<F>(&mut self, dest: &mut Self, f: F)
134    where
135        F: Fn(&W, &mut C) -> Option<Vec<(W, C)>> + Sync + Send,
136    {
137        self.par_iter_mut().for_each(|mut entry| {
138            let (k, v) = entry.pair_mut();
139            if let Some(new_entries) = f(k, v) {
140                for (new_k, new_v) in new_entries {
141                    dest.insert(new_k, new_v);
142                }
143            }
144        })
145    }
146}
147
148impl<S, C, H, W> ACMapContains<S, C, H, W> for DashMap<W, C, H>
149where
150    S: PauliStorage,
151    C: Coefficient + PartialEq,
152    H: BuildHasher + Clone + Default,
153    W: PauliWordTrait,
154{
155    fn contains_with<F>(&self, key: &W, f: F) -> bool
156    where
157        F: Fn(&C) -> bool,
158    {
159        self.get(key).is_some_and(|v| f(v.value()))
160    }
161}
162
163impl<S, C, H, W> ACMapScale<S, C, H, W> for DashMap<W, C, H>
164where
165    S: PauliStorage,
166    C: Coefficient + Send + Sync,
167    H: BuildHasher + Clone + Default + Sync + Send,
168    W: PauliWordTrait + Send + Sync,
169{
170    fn scale<F>(&mut self, f: F)
171    where
172        F: Fn(&W, &mut C) + Sync + Send,
173    {
174        self.par_iter_mut().for_each(|mut entry| {
175            let (k, v) = entry.pair_mut();
176            f(k, v);
177        });
178    }
179}
180
181impl<S, C, H, W> ACMapRetain<S, C, H, W> for DashMap<W, C, H>
182where
183    S: PauliStorage,
184    C: Coefficient,
185    H: BuildHasher + Clone + Default + Sync + Send,
186    W: PauliWordTrait,
187{
188    fn retain<F>(&mut self, mut f: F)
189    where
190        F: FnMut(&W, &C) -> bool,
191    {
192        Self::retain(self, |k, v| f(k, v));
193    }
194}