Skip to main content

hermes_simd_core/ops/
scan.rs

1//! Associative prefix-scan operation strategies and inclusion-mode ZSTs.
2//!
3//! `ScanOp<T>` is a sealed ZST trait for prefix scan operations (cumulative sum,
4//! cumulative product, running min/max). `ScanMode` is a sealed ZST trait for
5//! inclusive vs exclusive scan variants.
6
7use crate::scalar::Scalar;
8
9// ---------------------------------------------------------------------------
10// ScanOp — associative binary prefix-scan operation
11// ---------------------------------------------------------------------------
12
13/// Sealed ZST trait for prefix scan operations.
14pub trait ScanOp<T: Scalar>: crate::private::Sealed + Copy + 'static {
15    /// Returns the identity element of the operation.
16    fn identity() -> T;
17    /// Combine two values using the operation: `a op b`.
18    fn combine(a: T, b: T) -> T;
19}
20
21/// Addition scan strategy ZST marker.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub struct ScanAdd;
24
25/// Multiplication scan strategy ZST marker.
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub struct ScanMul;
28
29/// Minimum scan strategy ZST marker.
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct ScanMin;
32
33/// Maximum scan strategy ZST marker.
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub struct ScanMax;
36
37impl crate::private::Sealed for ScanAdd {}
38impl crate::private::Sealed for ScanMul {}
39impl crate::private::Sealed for ScanMin {}
40impl crate::private::Sealed for ScanMax {}
41
42impl<T: Scalar> ScanOp<T> for ScanAdd {
43    #[inline(always)]
44    fn identity() -> T {
45        T::ZERO
46    }
47    #[inline(always)]
48    fn combine(a: T, b: T) -> T {
49        a + b
50    }
51}
52
53impl<T: Scalar> ScanOp<T> for ScanMul {
54    #[inline(always)]
55    fn identity() -> T {
56        T::ONE
57    }
58    #[inline(always)]
59    fn combine(a: T, b: T) -> T {
60        a * b
61    }
62}
63
64impl<T: Scalar> ScanOp<T> for ScanMin {
65    #[inline(always)]
66    fn identity() -> T {
67        T::MAX_VALUE
68    }
69    #[inline(always)]
70    fn combine(a: T, b: T) -> T {
71        a.min_scalar(b)
72    }
73}
74
75impl<T: Scalar> ScanOp<T> for ScanMax {
76    #[inline(always)]
77    fn identity() -> T {
78        T::MIN_VALUE
79    }
80    #[inline(always)]
81    fn combine(a: T, b: T) -> T {
82        a.max_scalar(b)
83    }
84}
85
86// ---------------------------------------------------------------------------
87// ScanMode — prefix-scan inclusion mode
88// ---------------------------------------------------------------------------
89
90/// Sealed ZST trait for prefix scan inclusion modes.
91pub trait ScanMode: crate::private::Sealed + Copy + 'static {
92    /// Whether the scan is inclusive of the current element.
93    const IS_INCLUSIVE: bool;
94}
95
96/// Inclusive scan ZST marker.
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub struct Inclusive;
99
100/// Exclusive scan ZST marker.
101#[derive(Debug, Clone, Copy, PartialEq, Eq)]
102pub struct Exclusive;
103
104impl crate::private::Sealed for Inclusive {}
105impl crate::private::Sealed for Exclusive {}
106
107impl ScanMode for Inclusive {
108    const IS_INCLUSIVE: bool = true;
109}
110
111impl ScanMode for Exclusive {
112    const IS_INCLUSIVE: bool = false;
113}