Skip to main content

lightweight_simd/
reduce.rs

1// Most or all contents generated by AI (model glm-5.3)
2
3//! Horizontal reductions for the vector types ([`Simd`] and its
4//! [`aligned`](crate::aligned) siblings).
5
6use core::ops::{Add, Mul};
7use num_traits::{One, Zero};
8
9use crate::{Aligned4, Aligned8, Aligned16, Aligned32, Aligned64, Simd};
10
11#[duplicate::duplicate_item(
12    _mod_        _vec_;
13    [simd_impls] [Simd];
14    [impls_a4]   [Aligned4];
15    [impls_a8]   [Aligned8];
16    [impls_a16]  [Aligned16];
17    [impls_a32]  [Aligned32];
18    [impls_a64]  [Aligned64];
19)]
20mod _mod_ {
21    use super::*;
22
23    impl<T, const N: usize> _vec_<T, N>
24    where
25        T: Zero + Add<Output = T> + Copy,
26    {
27        /// Sums all lanes, accumulating in lane order.
28        #[inline(always)]
29        pub fn reduce_sum(self) -> T {
30            let mut acc = T::zero();
31            for x in self.0 {
32                acc = acc + x;
33            }
34            acc
35        }
36
37        /// Sums the first `n` lanes.
38        ///
39        /// # Panics
40        ///
41        /// Panics if `n > N`.
42        #[inline(always)]
43        pub fn reduce_sum_n(self, n: usize) -> T {
44            assert!(n <= N, "reduce_sum_n: n = {n} exceeds lane count {N}");
45            let mut acc = T::zero();
46            for x in self.0.iter().take(n) {
47                acc = acc + *x;
48            }
49            acc
50        }
51    }
52
53    impl<T, const N: usize> _vec_<T, N>
54    where
55        T: One + Mul<Output = T> + Copy,
56    {
57        /// Multiplies all lanes, accumulating in lane order.
58        #[inline(always)]
59        pub fn reduce_product(self) -> T {
60            let mut acc = T::one();
61            for x in self.0 {
62                acc = acc * x;
63            }
64            acc
65        }
66
67        /// Multiplies the first `n` lanes.
68        ///
69        /// # Panics
70        ///
71        /// Panics if `n > N`.
72        #[inline(always)]
73        pub fn reduce_product_n(self, n: usize) -> T {
74            assert!(n <= N, "reduce_product_n: n = {n} exceeds lane count {N}");
75            let mut acc = T::one();
76            for x in self.0.iter().take(n) {
77                acc = acc * *x;
78            }
79            acc
80        }
81    }
82}