Skip to main content

apache_datasketches/tuple/
a_not_b.rs

1use super::input::ArrayOfDoublesInput;
2use super::CompactArrayOfDoublesSketch;
3use crate::error::SketchError;
4use apache_datasketches_sys::array_of_doubles_a_not_b::ffi as sys;
5use apache_datasketches_sys::array_of_doubles_input::ArrayOfDoublesInputRef;
6use cxx::UniquePtr;
7
8/// Computes the set difference ("A not B": keys in `a` but not `b`) of two
9/// ArrayOfDoubles sketches via [`Self::compute`]. Retained entries keep `a`'s
10/// values unchanged. Stateless between calls — unlike
11/// [`super::ArrayOfDoublesUnion`]/[`super::ArrayOfDoublesIntersection`], there
12/// is no accumulation across repeated calls.
13pub struct ArrayOfDoublesAnotB {
14    inner: UniquePtr<sys::ArrayOfDoublesAnotBShim>,
15}
16
17unsafe impl Send for ArrayOfDoublesAnotB {}
18
19impl Default for ArrayOfDoublesAnotB {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25impl ArrayOfDoublesAnotB {
26    /// Creates a new, reusable a-not-b calculator.
27    pub fn new() -> Self {
28        Self {
29            inner: sys::new_array_of_doubles_a_not_b(),
30        }
31    }
32
33    /// Computes the set difference `a - b` (keys in `a` that are not in `b`)
34    /// as a [`CompactArrayOfDoublesSketch`]. `a` and `b` may independently be
35    /// a [`super::ArrayOfDoublesSketch`] or a
36    /// [`CompactArrayOfDoublesSketch`]. If `ordered` is `true`, the result's
37    /// entries are sorted by hash value.
38    ///
39    /// Returns [`SketchError::InvalidConfig`] if `a` and `b` disagree on
40    /// `num_values` — upstream does not validate this itself, and mismatched
41    /// widths would read out of bounds.
42    pub fn compute(
43        &self,
44        a: &impl ArrayOfDoublesInput,
45        b: &impl ArrayOfDoublesInput,
46        ordered: bool,
47    ) -> Result<CompactArrayOfDoublesSketch, SketchError> {
48        let (a_num, b_num) = (a.get_num_values(), b.get_num_values());
49        if a_num != b_num {
50            return Err(SketchError::InvalidConfig(format!(
51                "num_values mismatch: a has {a_num}, b has {b_num}"
52            )));
53        }
54        let inner = match (a.as_input(), b.as_input()) {
55            (ArrayOfDoublesInputRef::Sketch(a), ArrayOfDoublesInputRef::Sketch(b)) => {
56                self.inner.compute_sketch_sketch(a, b, ordered)
57            }
58            (ArrayOfDoublesInputRef::Sketch(a), ArrayOfDoublesInputRef::Compact(b)) => {
59                self.inner.compute_sketch_compact(a, b, ordered)
60            }
61            (ArrayOfDoublesInputRef::Compact(a), ArrayOfDoublesInputRef::Sketch(b)) => {
62                self.inner.compute_compact_sketch(a, b, ordered)
63            }
64            (ArrayOfDoublesInputRef::Compact(a), ArrayOfDoublesInputRef::Compact(b)) => {
65                self.inner.compute_compact_compact(a, b, ordered)
66            }
67        };
68        Ok(CompactArrayOfDoublesSketch::from_shim(inner))
69    }
70}