use crate::common::diagnostics::NamErrorCode;
use crate::math::common::AlignedVec;
use crate::models::wavenet::conv1d_dyn::Conv1dDyn;
use super::grouped_conv1d::A2GroupedConv1d;
#[derive(Clone)]
pub enum A2Conv1d {
Standard(Conv1dDyn),
Grouped(A2GroupedConv1d),
}
impl A2Conv1d {
pub fn new(
weights: AlignedVec<f32>,
bias: AlignedVec<f32>,
do_bias: bool,
dilation: usize,
in_ch: usize,
out_ch: usize,
kernel_size: usize,
) -> Self {
debug_assert!(
kernel_size >= 1,
"A2 kernel size must be >= 1; got {}",
kernel_size
);
debug_assert!(
in_ch > 0 && out_ch > 0,
"channels must be > 0, got in_ch={} out_ch={}",
in_ch,
out_ch
);
let num_blocks = out_ch.div_ceil(4);
let total_padded = num_blocks * 4 * in_ch * kernel_size;
debug_assert!(
weights.len() >= total_padded,
"weights too short: expected >= {}, got {}",
total_padded,
weights.len()
);
debug_assert!(bias.len() >= out_ch);
Self::Standard(Conv1dDyn {
weights,
bias,
do_bias,
dilation,
in_ch,
out_ch,
num_blocks,
interleave_width: 4,
kernel: kernel_size,
})
}
#[expect(
clippy::too_many_arguments,
reason = "A2 grouped convolution kernel requiring many shape/stride/group parameters for efficient neural network inference"
)]
pub fn new_grouped(
raw_weights: &[f32],
raw_bias: &[f32],
do_bias: bool,
dilation: usize,
in_ch: usize,
out_ch: usize,
kernel: usize,
groups: usize,
) -> Result<Self, NamErrorCode> {
Ok(Self::Grouped(A2GroupedConv1d::new(
raw_weights,
raw_bias,
do_bias,
dilation,
in_ch,
out_ch,
kernel,
groups,
)?))
}
#[inline(always)]
pub fn groups(&self) -> usize {
match self {
Self::Standard(_) => 1,
Self::Grouped(g) => g.groups,
}
}
#[inline(always)]
pub fn is_depthwise(&self) -> bool {
match self {
Self::Standard(_) => false,
Self::Grouped(g) => g.groups == g.in_ch && g.groups == g.out_ch,
}
}
#[inline(always)]
pub fn kernel_size(&self) -> usize {
match self {
Self::Standard(c) => c.kernel,
Self::Grouped(g) => g.kernel,
}
}
#[inline(always)]
pub fn dilation(&self) -> usize {
match self {
Self::Standard(c) => c.dilation,
Self::Grouped(g) => g.dilation,
}
}
#[inline(always)]
pub fn in_ch(&self) -> usize {
match self {
Self::Standard(c) => c.in_ch,
Self::Grouped(g) => g.in_ch,
}
}
#[inline(always)]
pub fn out_ch(&self) -> usize {
match self {
Self::Standard(c) => c.out_ch,
Self::Grouped(g) => g.out_ch,
}
}
}
#[path = "conv1d_dispatch.rs"]
mod dispatch;
#[cfg(test)]
#[path = "conv1d_test.rs"]
mod tests;