#![allow(dead_code)]
use aligned_vec::{AVec, ConstAlign};
pub type Align32 = ConstAlign<32>;
pub type AlignedVec<T> = AVec<T, Align32>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AllocError {
OutOfMemory,
Overflow,
}
impl core::fmt::Display for AllocError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::OutOfMemory => write!(f, "out of memory"),
Self::Overflow => write!(f, "allocation size overflow"),
}
}
}
impl std::error::Error for AllocError {}
#[inline]
pub fn try_alloc_zeroed(count: usize) -> Result<AlignedVec<f32>, AllocError> {
let mut vec = AVec::new(0);
vec.try_reserve_exact(count)
.map_err(|_| AllocError::OutOfMemory)?;
vec.resize(count, 0.0);
Ok(vec)
}
#[inline]
pub fn try_alloc<T: Copy + Default>(count: usize) -> Result<AlignedVec<T>, AllocError> {
let mut vec = AVec::new(0);
vec.try_reserve_exact(count)
.map_err(|_| AllocError::OutOfMemory)?;
vec.resize(count, T::default());
Ok(vec)
}
#[inline]
pub fn try_alloc_image(
width: usize,
height: usize,
) -> Result<(AlignedVec<f32>, usize), AllocError> {
let stride = (width + 7) & !7; let count = stride.checked_mul(height).ok_or(AllocError::Overflow)?;
let buffer = try_alloc_zeroed(count)?;
Ok((buffer, stride))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_aligned_vec_is_32_byte_aligned() {
let vec = try_alloc_zeroed(64).unwrap();
let addr = vec.as_ptr() as usize;
assert_eq!(addr % 32, 0, "AlignedVec should be 32-byte aligned");
}
#[test]
fn test_simd_align_to_has_no_prefix() {
let vec = try_alloc_zeroed(128).unwrap();
let addr = vec.as_ptr() as usize;
assert_eq!(
addr % 32,
0,
"32-byte aligned vec should have no unaligned prefix"
);
}
#[test]
fn test_image_buffer_rows_aligned() {
let (buffer, stride) = try_alloc_image(100, 4).unwrap();
assert_eq!(stride, 104);
let base_addr = buffer.as_ptr() as usize;
assert_eq!(base_addr % 32, 0, "Base buffer should be 32-byte aligned");
assert_eq!(
(stride * 4) % 32,
0,
"Row stride in bytes should be 32-byte aligned"
);
}
#[test]
fn test_image_buffer_stride_multiple_of_8() {
for width in [1, 7, 8, 9, 15, 16, 17, 100, 1000, 1920] {
let (_buffer, stride) = try_alloc_image(width, 1).unwrap();
assert_eq!(
stride % 8,
0,
"Stride for width {} should be multiple of 8",
width
);
assert!(stride >= width, "Stride should be >= width");
}
}
}