use crate::{Error, Matrix, Result};
use super::super::{Module, ModuleRegistry, matrix};
pub struct AvgPool2d {
kernel_size: usize,
stride: usize,
padding: usize,
registry: ModuleRegistry,
}
impl AvgPool2d {
pub fn new(kernel_size: usize) -> Result<Self> {
Self::with_options(kernel_size, kernel_size, 0)
}
pub fn with_options(kernel_size: usize, stride: usize, padding: usize) -> Result<Self> {
if kernel_size == 0 || stride == 0 {
return Err(Error::invalid_argument(
"AvgPool2d kernel size and stride must be nonzero",
));
}
Ok(Self {
kernel_size,
stride,
padding,
registry: ModuleRegistry::new(),
})
}
pub const fn kernel_size(&self) -> usize {
self.kernel_size
}
pub const fn stride(&self) -> usize {
self.stride
}
pub const fn padding(&self) -> usize {
self.padding
}
pub fn forward(&self, input: &Matrix) -> Result<Matrix> {
matrix::avg_pool_2d(input, self.kernel_size, self.stride, self.padding)
}
}
impl Module for AvgPool2d {
fn forward(&self, input: &Matrix) -> Result<Matrix> {
AvgPool2d::forward(self, input)
}
fn registry(&self) -> &ModuleRegistry {
&self.registry
}
}
pub struct MaxPool2d {
kernel_size: usize,
stride: usize,
padding: usize,
registry: ModuleRegistry,
}
impl MaxPool2d {
pub fn new(kernel_size: usize) -> Result<Self> {
Self::with_options(kernel_size, kernel_size, 0)
}
pub fn with_options(kernel_size: usize, stride: usize, padding: usize) -> Result<Self> {
if kernel_size == 0 || stride == 0 {
return Err(Error::invalid_argument(
"MaxPool2d kernel size and stride must be nonzero",
));
}
Ok(Self {
kernel_size,
stride,
padding,
registry: ModuleRegistry::new(),
})
}
pub const fn kernel_size(&self) -> usize {
self.kernel_size
}
pub const fn stride(&self) -> usize {
self.stride
}
pub const fn padding(&self) -> usize {
self.padding
}
pub fn forward(&self, input: &Matrix) -> Result<Matrix> {
Ok(matrix::max_pool_2d(input, self.kernel_size, self.stride, self.padding)?.output)
}
}
impl Module for MaxPool2d {
fn forward(&self, input: &Matrix) -> Result<Matrix> {
MaxPool2d::forward(self, input)
}
fn registry(&self) -> &ModuleRegistry {
&self.registry
}
}
pub struct AdaptiveAvgPool2d {
output_height: usize,
output_width: usize,
registry: ModuleRegistry,
}
impl AdaptiveAvgPool2d {
pub fn new(output_size: usize) -> Result<Self> {
Self::with_output_size(output_size, output_size)
}
pub fn with_output_size(output_height: usize, output_width: usize) -> Result<Self> {
if output_height == 0 || output_width == 0 {
return Err(Error::invalid_argument(
"AdaptiveAvgPool2d output extents must be nonzero",
));
}
Ok(Self {
output_height,
output_width,
registry: ModuleRegistry::new(),
})
}
pub const fn output_height(&self) -> usize {
self.output_height
}
pub const fn output_width(&self) -> usize {
self.output_width
}
pub fn forward(&self, input: &Matrix) -> Result<Matrix> {
matrix::adaptive_avg_pool_2d(input, self.output_height, self.output_width)
}
}
impl Module for AdaptiveAvgPool2d {
fn forward(&self, input: &Matrix) -> Result<Matrix> {
AdaptiveAvgPool2d::forward(self, input)
}
fn registry(&self) -> &ModuleRegistry {
&self.registry
}
}