Skip to main content

shape_value/
aligned_vec.rs

1//! SIMD-aligned vector implementation for high-performance time series operations
2//!
3//! This module provides AlignedVec, a vector type that guarantees memory alignment
4//! suitable for SIMD operations (AVX2: 32-byte alignment).
5
6use std::alloc::{Layout, alloc, dealloc, realloc};
7use std::marker::PhantomData;
8use std::mem;
9use std::ops::{Deref, DerefMut};
10use std::ptr::{self, NonNull};
11use std::slice;
12
13/// Alignment for AVX2 operations (32 bytes)
14const SIMD_ALIGNMENT: usize = 32;
15
16/// A vector with SIMD-aligned memory allocation
17#[derive(Debug)]
18pub struct AlignedVec<T> {
19    ptr: NonNull<T>,
20    len: usize,
21    capacity: usize,
22    _phantom: PhantomData<T>,
23}
24
25impl<T> AlignedVec<T> {
26    /// Creates a new empty AlignedVec
27    pub fn new() -> Self {
28        AlignedVec {
29            ptr: NonNull::dangling(),
30            len: 0,
31            capacity: 0,
32            _phantom: PhantomData,
33        }
34    }
35
36    /// Creates a new AlignedVec with the specified capacity
37    pub fn with_capacity(capacity: usize) -> Self {
38        if capacity == 0 {
39            return Self::new();
40        }
41
42        let layout = Self::layout_for_capacity(capacity).expect("Failed to create layout");
43
44        let ptr = unsafe {
45            let raw_ptr = alloc(layout);
46            if raw_ptr.is_null() {
47                std::alloc::handle_alloc_error(layout);
48            }
49            NonNull::new_unchecked(raw_ptr as *mut T)
50        };
51
52        AlignedVec {
53            ptr,
54            len: 0,
55            capacity,
56            _phantom: PhantomData,
57        }
58    }
59
60    /// Returns the number of elements in the vector
61    pub fn len(&self) -> usize {
62        self.len
63    }
64
65    /// Returns true if the vector contains no elements
66    pub fn is_empty(&self) -> bool {
67        self.len == 0
68    }
69
70    /// Returns the capacity of the vector
71    pub fn capacity(&self) -> usize {
72        self.capacity
73    }
74
75    /// Appends an element to the back of the vector
76    pub fn push(&mut self, value: T) {
77        if self.len == self.capacity {
78            self.grow();
79        }
80
81        unsafe {
82            let end = self.ptr.as_ptr().add(self.len);
83            ptr::write(end, value);
84            self.len += 1;
85        }
86    }
87
88    /// Removes the last element from the vector and returns it
89    pub fn pop(&mut self) -> Option<T> {
90        if self.len == 0 {
91            None
92        } else {
93            unsafe {
94                self.len -= 1;
95                Some(ptr::read(self.ptr.as_ptr().add(self.len)))
96            }
97        }
98    }
99
100    /// Returns a reference to an element at the given index
101    pub fn get(&self, index: usize) -> Option<&T> {
102        if index < self.len {
103            unsafe { Some(&*self.ptr.as_ptr().add(index)) }
104        } else {
105            None
106        }
107    }
108
109    /// Returns a mutable reference to an element at the given index
110    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
111        if index < self.len {
112            unsafe { Some(&mut *self.ptr.as_ptr().add(index)) }
113        } else {
114            None
115        }
116    }
117
118    /// Clears the vector, removing all values
119    pub fn clear(&mut self) {
120        unsafe {
121            // Drop all elements
122            for i in 0..self.len {
123                ptr::drop_in_place(self.ptr.as_ptr().add(i));
124            }
125        }
126        self.len = 0;
127    }
128
129    /// Returns a slice containing the entire vector
130    pub fn as_slice(&self) -> &[T] {
131        unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
132    }
133
134    /// Returns a mutable slice containing the entire vector
135    pub fn as_mut_slice(&mut self) -> &mut [T] {
136        unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
137    }
138
139    /// Creates a layout for the given capacity
140    fn layout_for_capacity(capacity: usize) -> Option<Layout> {
141        let size = capacity.checked_mul(mem::size_of::<T>())?;
142
143        // Ensure size is non-zero and properly aligned
144        let size = size.max(1);
145        Layout::from_size_align(size, SIMD_ALIGNMENT).ok()
146    }
147
148    /// Grows the vector's capacity
149    fn grow(&mut self) {
150        let new_capacity = if self.capacity == 0 {
151            4
152        } else {
153            self.capacity.saturating_mul(2)
154        };
155
156        self.resize_to_capacity(new_capacity);
157    }
158
159    /// Resizes the vector to the specified capacity
160    fn resize_to_capacity(&mut self, new_capacity: usize) {
161        if new_capacity <= self.capacity {
162            return;
163        }
164
165        let new_layout = Self::layout_for_capacity(new_capacity).expect("Failed to create layout");
166
167        let new_ptr = if self.capacity == 0 {
168            unsafe {
169                let raw_ptr = alloc(new_layout);
170                if raw_ptr.is_null() {
171                    std::alloc::handle_alloc_error(new_layout);
172                }
173                NonNull::new_unchecked(raw_ptr as *mut T)
174            }
175        } else {
176            let old_layout =
177                Self::layout_for_capacity(self.capacity).expect("Failed to create old layout");
178
179            unsafe {
180                let raw_ptr = realloc(self.ptr.as_ptr() as *mut u8, old_layout, new_layout.size());
181                if raw_ptr.is_null() {
182                    std::alloc::handle_alloc_error(new_layout);
183                }
184                NonNull::new_unchecked(raw_ptr as *mut T)
185            }
186        };
187
188        self.ptr = new_ptr;
189        self.capacity = new_capacity;
190    }
191
192    /// Creates an AlignedVec from a regular Vec
193    pub fn from_vec(mut vec: Vec<T>) -> Self {
194        let len = vec.len();
195        let capacity = vec.capacity();
196
197        if len == 0 {
198            return Self::new();
199        }
200
201        let mut aligned = Self::with_capacity(capacity);
202
203        unsafe {
204            // Move elements from vec to aligned storage
205            ptr::copy_nonoverlapping(vec.as_ptr(), aligned.ptr.as_ptr(), len);
206            aligned.len = len;
207
208            // Prevent vec from dropping the elements
209            vec.set_len(0);
210        }
211
212        aligned
213    }
214
215    /// Converts the AlignedVec into a regular Vec
216    pub fn into_vec(mut self) -> Vec<T> {
217        let mut vec = Vec::with_capacity(self.len);
218
219        unsafe {
220            // Copy elements to vec
221            ptr::copy_nonoverlapping(self.ptr.as_ptr(), vec.as_mut_ptr(), self.len);
222            vec.set_len(self.len);
223
224            // Prevent self from dropping the elements
225            self.len = 0;
226        }
227
228        vec
229    }
230}
231
232impl<T> Drop for AlignedVec<T> {
233    fn drop(&mut self) {
234        if self.capacity != 0 {
235            unsafe {
236                // Drop all elements
237                for i in 0..self.len {
238                    ptr::drop_in_place(self.ptr.as_ptr().add(i));
239                }
240
241                // Deallocate memory
242                let layout =
243                    Self::layout_for_capacity(self.capacity).expect("Failed to create layout");
244                dealloc(self.ptr.as_ptr() as *mut u8, layout);
245            }
246        }
247    }
248}
249
250impl<T> Deref for AlignedVec<T> {
251    type Target = [T];
252
253    fn deref(&self) -> &Self::Target {
254        self.as_slice()
255    }
256}
257
258impl<T> DerefMut for AlignedVec<T> {
259    fn deref_mut(&mut self) -> &mut Self::Target {
260        self.as_mut_slice()
261    }
262}
263
264impl<T: Clone> Clone for AlignedVec<T> {
265    fn clone(&self) -> Self {
266        let mut cloned = Self::with_capacity(self.capacity);
267
268        for item in self.as_slice() {
269            cloned.push(item.clone());
270        }
271
272        cloned
273    }
274}
275
276impl<T> Default for AlignedVec<T> {
277    fn default() -> Self {
278        Self::new()
279    }
280}
281
282// Safety: AlignedVec has the same safety properties as Vec
283unsafe impl<T: Send> Send for AlignedVec<T> {}
284unsafe impl<T: Sync> Sync for AlignedVec<T> {}