use std::fmt::{self, Display, Formatter};
use crate::engine::vector::scalar::VeScalar;
use furiosa_opt_macro::primitive;
#[derive(Debug, Clone, Copy)]
pub enum ArgMode {
Unary,
Binary(BinaryArgMode),
Ternary(TernaryArgMode),
}
#[primitive(op::BinaryArgMode)]
#[derive(Debug, Clone, Copy)]
pub enum BinaryArgMode {
Mode00,
Mode01,
Mode10,
Mode11,
}
impl Display for BinaryArgMode {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Mode00 => write!(f, "BinaryArgMode::Mode00"),
Self::Mode01 => write!(f, "BinaryArgMode::Mode01"),
Self::Mode10 => write!(f, "BinaryArgMode::Mode10"),
Self::Mode11 => write!(f, "BinaryArgMode::Mode11"),
}
}
}
impl BinaryArgMode {
pub(crate) fn apply<D: VeScalar>(self, op: impl Fn(D, D) -> D) -> impl Fn(D, D) -> D {
move |a, b| match self {
Self::Mode00 => op(a, a),
Self::Mode01 => op(a, b),
Self::Mode10 => op(b, a),
Self::Mode11 => op(b, b),
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum TernaryArgMode {
Mode012,
Mode002,
Mode102,
Mode112,
Mode020,
Mode021,
Mode120,
}
impl Display for TernaryArgMode {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Mode012 => write!(f, "TernaryArgMode::Mode012"),
Self::Mode002 => write!(f, "TernaryArgMode::Mode002"),
Self::Mode102 => write!(f, "TernaryArgMode::Mode102"),
Self::Mode112 => write!(f, "TernaryArgMode::Mode112"),
Self::Mode020 => write!(f, "TernaryArgMode::Mode020"),
Self::Mode021 => write!(f, "TernaryArgMode::Mode021"),
Self::Mode120 => write!(f, "TernaryArgMode::Mode120"),
}
}
}
impl TernaryArgMode {
pub(crate) fn apply<D: VeScalar>(self, op: impl Fn(D, D, D) -> D) -> impl Fn(D, D, D) -> D {
move |m, o0, o1| match self {
Self::Mode012 => op(m, o0, o1),
Self::Mode002 => op(m, m, o1),
Self::Mode102 => op(o0, m, o1),
Self::Mode112 => op(o0, o0, o1),
Self::Mode020 => op(m, o1, m),
Self::Mode021 => op(m, o1, o0),
Self::Mode120 => op(o0, o1, m),
}
}
}