lightweight-simd 0.1.1

Lightweight generic fixed-array vector types relying on compiler auto-vectorization
Documentation
// Most or all contents generated by AI (model glm-5.3)

//! Horizontal reductions for the vector types ([`Simd`] and its
//! [`aligned`](crate::aligned) siblings).

use core::ops::{Add, Mul};
use num_traits::{One, Zero};

use crate::{Aligned4, Aligned8, Aligned16, Aligned32, Aligned64, Simd};

#[duplicate::duplicate_item(
    _mod_        _vec_;
    [simd_impls] [Simd];
    [impls_a4]   [Aligned4];
    [impls_a8]   [Aligned8];
    [impls_a16]  [Aligned16];
    [impls_a32]  [Aligned32];
    [impls_a64]  [Aligned64];
)]
mod _mod_ {
    use super::*;

    impl<T, const N: usize> _vec_<T, N>
    where
        T: Zero + Add<Output = T> + Copy,
    {
        /// Sums all lanes, accumulating in lane order.
        #[inline(always)]
        pub fn reduce_sum(self) -> T {
            let mut acc = T::zero();
            for x in self.0 {
                acc = acc + x;
            }
            acc
        }

        /// Sums the first `n` lanes.
        ///
        /// # Panics
        ///
        /// Panics if `n > N`.
        #[inline(always)]
        pub fn reduce_sum_n(self, n: usize) -> T {
            assert!(n <= N, "reduce_sum_n: n = {n} exceeds lane count {N}");
            let mut acc = T::zero();
            for x in self.0.iter().take(n) {
                acc = acc + *x;
            }
            acc
        }
    }

    impl<T, const N: usize> _vec_<T, N>
    where
        T: One + Mul<Output = T> + Copy,
    {
        /// Multiplies all lanes, accumulating in lane order.
        #[inline(always)]
        pub fn reduce_product(self) -> T {
            let mut acc = T::one();
            for x in self.0 {
                acc = acc * x;
            }
            acc
        }

        /// Multiplies the first `n` lanes.
        ///
        /// # Panics
        ///
        /// Panics if `n > N`.
        #[inline(always)]
        pub fn reduce_product_n(self, n: usize) -> T {
            assert!(n <= N, "reduce_product_n: n = {n} exceeds lane count {N}");
            let mut acc = T::one();
            for x in self.0.iter().take(n) {
                acc = acc * *x;
            }
            acc
        }
    }
}