npsimd 0.3.0

An ergonomic library for architecture-specific vectorization.
Documentation
#[doc(inline)]
pub use crate::intel_imm as imm;

/// A type carrying a constant value.
///
/// This can be used in place of a run-time value (e.g. in a function parameter
/// or on the right-hand side of an overloaded operation) when it is required to
/// be known at compile-time.
///
/// This is preferred to using `const` parameters, which are difficult to work
/// with (even with the `generic_const_exprs` feature) and which are limited to
/// primitive types.
pub trait Imm<T>: Copy {
    /// The associated constant.
    const VAL: T;
}

/// Construct a constant value.
///
/// The resulting expression is a new anonymous type that implements [`Imm`],
/// where the associated constant is set to the given `const` expression.  It
/// can only be used if the expression does not rely on the generic parameters
/// of the outer item -- in that case, implement [`Imm`] manually.
///
/// # Examples
///
/// ```
/// use npsimd::intel::{Imm, imm};
///
/// fn foo<Y: Imm<u8>>(x: u8, y: Y) -> u8 {
///     x + Y::VAL
/// }
///
/// assert_eq!(foo(1, imm!(2, u8)), 3u8);
/// ```
#[doc(hidden)]
#[macro_export]
macro_rules! intel_imm {
    ($expr:expr, $type:ty) => {
        {
            #[derive(Copy, Clone)]
            struct Imm;

            impl $crate::intel::Imm<$type> for Imm {
                const VAL: $type = $expr;
            }

            Imm
        }
    };

    { $(
        $vis:vis type $name:ident
        $(<$($gname:ident $(: $gtype:path)?),* $(,)?>)?
        : $type:ty
        = $expr:expr;
    )+ } => { $(
        #[derive(Copy, Clone)]
        $vis struct $name
        $(<$($gname $(: $gtype)?),*>)?
        ($($($crate::__core::marker::PhantomData<$gname>),*)?);

        impl
        $(<$($gname $(: $gtype)?),*>)?
        $name $(<$($gname),*>)? {
            pub const fn new() -> Self {
                Self($($($crate::__core::marker::PhantomData::<$gname>),*)?)
            }
        }

        impl
        $(<$($gname $(: $gtype)?),*>)?
        $crate::intel::value::Imm<$type>
        for $name $(<$($gname),*>)? {
            const VAL: $type = const {
                const fn compute
                $(<$($gname $(: $gtype)?),*>)?
                () -> $type {
                    $expr
                }

                compute $(::<$($gname),*>)? ()
            };
        }
    )+ };
}