├── .gitignore ├── Cargo.toml ├── src ├── lib.rs ├── test.rs ├── unadorned.rs ├── soa.rs ├── soa2.rs ├── soa3.rs └── soa4.rs ├── README.md ├── .travis.yml └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "soa" 4 | version = "0.9.2" 5 | authors = ["Clark Gaebel "] 6 | 7 | documentation = "https://cgaebel.github.io/soa/" 8 | homepage = "https://github.com/cgaebel/soa" 9 | repository = "https://github.com/cgaebel/soa" 10 | 11 | readme = "README.md" 12 | 13 | keywords = [ "soa", "columnar" ] 14 | 15 | license = "MIT" 16 | 17 | description = "Struct-of-Array vector types" 18 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Growable struct-of-array types with 16-byte aligned heap allocated contents. 2 | #![feature(alloc)] 3 | #![feature(collections)] 4 | #![feature(core)] 5 | 6 | #![feature(unsafe_no_drop_flag)] 7 | #![feature(filling_drop)] 8 | 9 | extern crate alloc; 10 | extern crate collections; 11 | extern crate core; 12 | 13 | pub mod soa2; 14 | pub mod soa3; 15 | pub mod soa4; 16 | 17 | mod unadorned; 18 | #[cfg(test)] mod test; 19 | 20 | pub use soa2::Soa2; 21 | pub use soa3::Soa3; 22 | pub use soa4::Soa4; 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SoA 2 | ===== 3 | 4 | Vector types, but instead of being represented as Array-Of-Struct, data is stored 5 | as a Struct-Of-Arrays, or SoA. 6 | 7 | [![crates.io](https://img.shields.io/crates/v/soa.svg)](https://crates.io/crates/soa/) 8 | 9 | [![Build Status](https://travis-ci.org/cgaebel/soa.svg?branch=master)](https://travis-ci.org/cgaebel/soa) 10 | 11 | Data stored in SoA is meant to be processed with SIMD operations, and as such, 12 | all arrays are aligned to 16 bytes. 13 | 14 | A large subset of the `std::Vec` interface is supported, as well as some extras 15 | to make writing efficient code more natural. 16 | 17 | Documentation 18 | -------------- 19 | 20 | See the very thorough [API Docs](https://cgaebel.github.io/soa/). -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | sudo: false 3 | os: 4 | - linux 5 | env: 6 | global: 7 | - secure: "VCp7FEaYou4v6AXAzFkpaAevFHKJMLMunLptjqKO0vP+dIp99YulsMWxjHq2nrGnu9Q0EvvFNQ3dSclyjRZDHlefOyV3mAp1Ei3fj6vK7gcT5nAWK/Lq7/uG0bZMfBitqbVjSx253RVvs9XC1N33KseVcjBbdYzm2rSuwnZ9Lhc=" 8 | script: 9 | - cargo build --verbose 10 | - cargo test --verbose 11 | - cargo bench --verbose 12 | - cargo doc --verbose 13 | after_script: 14 | - | 15 | [ $TRAVIS_BRANCH = master ] && 16 | [ $TRAVIS_PULL_REQUEST = false ] && 17 | echo '' > target/doc/index.html && 18 | git clone --depth 1 https://github.com/davisp/ghp-import && 19 | ./ghp-import/ghp-import -n target/doc && 20 | git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Clark Gaebel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /src/test.rs: -------------------------------------------------------------------------------- 1 | use Soa2; 2 | 3 | struct DropCounter<'a> { 4 | count: &'a mut i32, 5 | } 6 | 7 | impl<'a> Drop for DropCounter<'a> { 8 | fn drop(&mut self) { 9 | *self.count += 1; 10 | } 11 | } 12 | 13 | #[test] 14 | fn test_double_drop() { 15 | struct TwoVec { 16 | x: Soa2, 17 | y: Soa2, 18 | } 19 | 20 | let (mut c0, mut c1, mut c2, mut c3) = (0, 0, 0, 0); 21 | 22 | { 23 | let mut tv = 24 | TwoVec { 25 | x: Soa2::new(), 26 | y: Soa2::new(), 27 | }; 28 | 29 | tv.x.push( 30 | (DropCounter { count: &mut c0 }, 31 | DropCounter { count: &mut c1 })); 32 | tv.y.push( 33 | (DropCounter { count: &mut c2 }, 34 | DropCounter { count: &mut c3 })); 35 | 36 | drop(tv.x); 37 | } 38 | 39 | assert_eq!(c0, 1); 40 | assert_eq!(c1, 1); 41 | assert_eq!(c2, 1); 42 | assert_eq!(c3, 1); 43 | } 44 | 45 | #[test] 46 | fn test_reserve() { 47 | let mut v = Soa2::new(); 48 | assert_eq!(v.capacity(), 0); 49 | 50 | v.reserve(2); 51 | assert!(v.capacity() >= 2); 52 | 53 | for i in 0..16 { 54 | v.push((i, i)); 55 | } 56 | 57 | assert!(v.capacity() >= 16); 58 | v.reserve(16); 59 | assert!(v.capacity() >= 32); 60 | 61 | v.push((16, 16)); 62 | 63 | v.reserve(16); 64 | assert!(v.capacity() >= 33); 65 | } 66 | 67 | #[test] 68 | fn test_extend() { 69 | let mut v = Soa2::new(); 70 | let mut w = Soa2::new(); 71 | 72 | v.extend(0..3, 4..7); 73 | for i in (0..3).zip(4..7) { 74 | w.push(i); 75 | } 76 | 77 | assert_eq!(v, w); 78 | 79 | v.extend(3..10, 7..14); 80 | for i in (3..10).zip(7..14) { 81 | w.push(i); 82 | } 83 | 84 | assert_eq!(v, w); 85 | } 86 | 87 | #[test] 88 | fn test_clone() { 89 | let v: Soa2 = Soa2::new(); 90 | let mut w: Soa2 = Soa2::new(); 91 | 92 | let elems = [ 1, 2, 3 ]; 93 | w.push_all(&elems, &elems); 94 | 95 | assert_eq!(v, v.clone()); 96 | let z = w.clone(); 97 | assert_eq!(w, z); 98 | assert!(w.as_slices().0.as_ptr() != z.as_slices().0.as_ptr()); 99 | assert!(w.as_slices().1.as_ptr() != z.as_slices().1.as_ptr()); 100 | } 101 | 102 | #[test] 103 | fn test_clone_from() { 104 | let mut v = Soa2::new(); 105 | let mut three = Soa2::new(); 106 | let three_elems = [ Box::new(1), Box::new(2), Box::new(3) ]; 107 | three.push_all(&three_elems, &three_elems); 108 | let mut two = Soa2::new(); 109 | let two_elems = [ Box::new(4), Box::new(5) ]; 110 | two.push_all(&two_elems, &two_elems); 111 | 112 | v.clone_from(&three); 113 | assert_eq!(v, three); 114 | 115 | v.clone_from(&three); 116 | assert_eq!(v, three); 117 | 118 | v.clone_from(&two); 119 | assert_eq!(v, two); 120 | 121 | v.clone_from(&three); 122 | assert_eq!(v, three); 123 | } 124 | 125 | #[test] 126 | fn test_retain() { 127 | let vs = [ 1i32, 2, 3, 4 ]; 128 | let mut v = Soa2::new(); 129 | v.push_all(&vs, &vs); 130 | v.retain(|(&x, _)| x % 2i32 == 0); 131 | assert_eq!(v.as_slices(), (&[2, 4][..], &[2, 4][..])); 132 | } 133 | 134 | #[test] 135 | fn test_zero_sized_values() { 136 | let mut v = Soa2::new(); 137 | assert_eq!(v.len(), 0); 138 | v.push(((), ())); 139 | assert_eq!(v.len(), 1); 140 | v.push(((), ())); 141 | assert_eq!(v.len(), 2); 142 | assert_eq!(v.pop(), Some(((), ()))); 143 | assert_eq!(v.pop(), Some(((), ()))); 144 | assert_eq!(v.pop(), None); 145 | 146 | assert_eq!(v.iters().0.count(), 0); 147 | v.push(((), ())); 148 | assert_eq!(v.iters().1.count(), 1); 149 | v.push(((), ())); 150 | assert_eq!(v.iters().0.count(), 2); 151 | 152 | for (&(), &()) in v.iters().0.zip(v.iters().1) {} 153 | 154 | assert_eq!(v.iters_mut().0.count(), 2); 155 | v.push(((), ())); 156 | assert_eq!(v.iters_mut().1.count(), 3); 157 | v.push(((), ())); 158 | assert_eq!(v.iters_mut().0.count(), 4); 159 | 160 | for (&mut (), &mut ()) in { let (a, b) = v.iters_mut(); a.zip(b) } {} 161 | unsafe { v.set_len(0); } 162 | assert_eq!(v.iters_mut().0.count(), 0); 163 | } 164 | 165 | #[test] 166 | fn test_zip_unzip() { 167 | let (z1x, z1y) = ([ 1i32, 2, 3 ], [ 4i32, 5, 6 ]); 168 | let mut z1 = Soa2::new(); 169 | z1.push_all(&z1x[..], &z1y[..]); 170 | 171 | let (left, right) = z1.into_vecs(); 172 | assert_eq!(&left[..], &z1x[..]); 173 | assert_eq!(&right[..], &z1y[..]); 174 | } 175 | 176 | #[test] 177 | fn test_unsafe_ptrs() { 178 | unsafe { 179 | let a = [1i32, 2, 3]; 180 | let ptr = a.as_ptr(); 181 | let b = Soa2::from_raw_bufs(ptr, ptr, 3); 182 | assert_eq!(b.as_slices(), (&[1, 2, 3][..], &[1, 2, 3][..])); 183 | 184 | let c = [1i32, 2, 3, 4, 5]; 185 | let ptr = c.as_ptr(); 186 | let d = Soa2::from_raw_bufs(ptr, ptr, 5); 187 | assert_eq!(d.as_slices(), (&c[..], &c[..])); 188 | } 189 | } 190 | 191 | #[test] 192 | fn test_vec_truncate_drop() { 193 | static mut drops: usize = 0; 194 | #[derive(Clone)] 195 | struct Elem(usize); 196 | impl Drop for Elem { 197 | fn drop(&mut self) { 198 | unsafe { drops += 1; } 199 | } 200 | } 201 | 202 | let mut v = Soa2::new(); 203 | v.push_all( 204 | &[Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)][..], 205 | &[Elem(10), Elem(20), Elem(30), Elem(40), Elem(50)][..]); 206 | 207 | assert_eq!(unsafe { drops }, 10 + 0); 208 | v.truncate(3); 209 | assert_eq!(unsafe { drops }, 10 + 4); 210 | v.truncate(0); 211 | assert_eq!(unsafe { drops }, 10 + 10); 212 | } 213 | 214 | #[test] 215 | #[should_panic] 216 | fn test_swap_remove_empty() { 217 | let mut v: Soa2 = Soa2::new(); 218 | v.swap_remove(0); 219 | } 220 | 221 | #[test] 222 | fn test_move_iter_unwrap() { 223 | let mut v: Soa2 = Soa2::with_capacity(7); 224 | v.push((1, 10)); 225 | v.push((2, 20)); 226 | let (p0, p1) = v.as_ptrs(); 227 | let (v0, v1) = v.into_iters(); 228 | let v0 = v0.into_inner(); 229 | let v1 = v1.into_inner(); 230 | 231 | assert_eq!(v0.as_ptr(), p0); 232 | assert_eq!(v1.as_ptr(), p1); 233 | 234 | assert_eq!(v0.capacity(), 7); 235 | assert_eq!(v1.capacity(), 7); 236 | 237 | assert_eq!(v0.len(), 0); 238 | assert_eq!(v1.len(), 0); 239 | } 240 | -------------------------------------------------------------------------------- /src/unadorned.rs: -------------------------------------------------------------------------------- 1 | use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; 2 | use collections::vec; 3 | use core::cmp::max; 4 | use core::mem; 5 | use core::nonzero::NonZero; 6 | use core::ptr; 7 | use core::slice; 8 | use core::usize; 9 | 10 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] 11 | pub struct Extent { 12 | pub len: usize, 13 | pub cap: usize, 14 | } 15 | 16 | /// Rust has the wrong parameter order. 17 | /// > http://internals.rust-lang.org/t/memcpy-is-backwards/1797 18 | #[inline(always)] 19 | unsafe fn memcpy(dst: *mut T, src: *const T, n: usize) { 20 | ptr::copy_nonoverlapping(src, dst, n) 21 | } 22 | 23 | /// Rust has the wrong parameter order. 24 | /// > http://internals.rust-lang.org/t/memcpy-is-backwards/1797 25 | #[inline(always)] 26 | unsafe fn memmove(dst: *mut T, src: *const T, n: usize) { 27 | ptr::copy(src, dst, n) 28 | } 29 | 30 | fn byte_length_of(capacity: usize) -> usize { 31 | mem::size_of::().checked_mul(capacity).expect("capacity overflow") 32 | } 33 | 34 | unsafe fn my_alloc(capacity: usize) -> NonZero<*mut A> { 35 | if mem::size_of::() == 0 { 36 | NonZero::new(EMPTY as *mut A) 37 | } else { 38 | let desired_alignment = mem::min_align_of::(); 39 | assert!(desired_alignment.is_power_of_two()); 40 | assert!(desired_alignment <= 16); 41 | 42 | let ptr = allocate(byte_length_of::(capacity), 16); 43 | if ptr.is_null() { ::alloc::oom() } 44 | NonZero::new(ptr as *mut A) 45 | } 46 | } 47 | 48 | #[inline(never)] 49 | unsafe fn alloc_or_realloc(ptr: *mut A, old_size: usize, size: usize) -> NonZero<*mut A> { 50 | let ret = 51 | if old_size == 0 { 52 | allocate(size, 16) 53 | } else { 54 | reallocate(ptr as *mut u8, old_size, size, 16) 55 | }; 56 | 57 | if ret.is_null() { ::alloc::oom() } 58 | 59 | NonZero::new(ret as *mut A) 60 | } 61 | 62 | #[inline] 63 | unsafe fn dealloc(ptr: *mut A, cap: usize) { 64 | if mem::size_of::() == 0 { return } 65 | 66 | deallocate(ptr as *mut u8, cap * mem::size_of::(), 16); 67 | } 68 | 69 | #[must_use] 70 | pub struct NewUpdate; 71 | 72 | #[inline] 73 | pub fn new_update(_: &[NewUpdate]) -> Extent { 74 | Extent { len: 0, cap: 0 } 75 | } 76 | 77 | #[must_use] 78 | pub struct WithCapUpdate; 79 | 80 | #[inline] 81 | pub fn with_capacity_update(_: &[WithCapUpdate], is_boring: bool, new_cap: usize) -> Extent { 82 | let len = 0; 83 | let cap = 84 | if is_boring { 85 | usize::MAX 86 | } else { 87 | new_cap 88 | }; 89 | 90 | Extent { len: len, cap: cap } 91 | } 92 | 93 | #[must_use] 94 | pub struct FromRawPartsUpdate; 95 | 96 | #[inline] 97 | pub fn from_raw_parts_update(_: &[FromRawPartsUpdate], len: usize, cap: usize) -> Extent { 98 | Extent { len: len, cap: cap } 99 | } 100 | 101 | #[must_use] 102 | pub struct FromRawBufsUpdate; 103 | 104 | #[inline] 105 | pub fn from_raw_bufs_update(_: &[FromRawBufsUpdate], elts: usize) -> Extent { 106 | Extent { len: elts, cap: elts } 107 | } 108 | 109 | #[must_use] 110 | #[derive(Clone)] 111 | pub struct ReserveCalc(usize); 112 | 113 | #[inline] 114 | pub fn calc_reserve_space(e: &Extent, additional: usize) -> Option { 115 | if e.cap - e.len >= additional { return None } 116 | 117 | Some(ReserveCalc( 118 | e.len 119 | .checked_add(additional) 120 | .and_then(|base_len| base_len.checked_next_power_of_two()) 121 | .expect("`usize` overflow"))) 122 | } 123 | 124 | #[must_use] 125 | pub struct ReserveUpdate; 126 | 127 | #[inline] 128 | pub fn reserve_update(_: &[ReserveUpdate], calc: ReserveCalc, e: &mut Extent) { 129 | e.cap = calc.0; 130 | } 131 | 132 | #[inline] 133 | pub fn calc_reserve_exact_space(e: &Extent, additional: usize) -> Option { 134 | if e.cap - e.len >= additional { return None } 135 | 136 | Some(ReserveCalc( 137 | e.len 138 | .checked_add(additional) 139 | .expect("`usize` overflow"))) 140 | } 141 | 142 | #[must_use] 143 | pub struct ShrinkToFitUpdate; 144 | 145 | #[inline] 146 | pub fn shrink_to_fit_update(_: &[ShrinkToFitUpdate], e: &mut Extent) { 147 | e.cap = e.len; 148 | } 149 | 150 | #[must_use] 151 | pub struct TruncateUpdate; 152 | 153 | #[inline] 154 | pub fn truncate_update(_: &[TruncateUpdate], new_len: usize, e: &mut Extent) { 155 | e.len = new_len; 156 | } 157 | 158 | #[must_use] 159 | pub struct InsertUpdate; 160 | 161 | #[inline] 162 | pub fn insert_update(_: &[InsertUpdate], calc: Option, e: &mut Extent) { 163 | e.len += 1; 164 | calc.map(|calc| { e.cap = calc.0; }); 165 | } 166 | 167 | #[must_use] 168 | pub struct RemoveUpdate; 169 | 170 | #[inline] 171 | pub fn remove_update(_: &[RemoveUpdate], e: &mut Extent) { 172 | e.len -= 1; 173 | } 174 | 175 | #[must_use] 176 | pub struct PushUpdate; 177 | 178 | #[inline] 179 | pub fn push_update(_: &[PushUpdate], e: &mut Extent) { 180 | if e.len == e.cap { 181 | e.cap = max(e.cap, 2) * 2; 182 | } 183 | 184 | e.len += 1; 185 | } 186 | 187 | #[must_use] 188 | pub struct AppendUpdate; 189 | 190 | #[inline] 191 | pub fn append_update(_: &[AppendUpdate], e: &mut Extent, other_e: &mut Extent, space: Option) { 192 | e.len += other_e.len; 193 | space.map(|calc| { e.cap = calc.0 }); 194 | 195 | other_e.len = 0; 196 | } 197 | 198 | #[must_use] 199 | pub struct PushAllUpdate; 200 | 201 | #[inline] 202 | pub fn push_all_update(_: &[PushAllUpdate], e: &mut Extent, len: usize, space: Option) { 203 | e.len += len; 204 | space.map(|calc| { e.cap = calc.0 }); 205 | } 206 | 207 | #[must_use] 208 | #[derive(Debug)] 209 | pub struct ExtendUpdate(Extent); 210 | 211 | pub fn extend_update(extents: &[ExtendUpdate], e: &mut Extent) { 212 | let first_ext = extents[0].0; 213 | 214 | if extents.iter().any(|e| e.0 != first_ext) { 215 | // TODO: Clean up the excess elements added. This is a little tricky, since 216 | // the pointers need to be passed to extend_update, without slowing down 217 | // the fast path. 218 | panic!("`extend` called with iterators with unequal size: {:?}. Memory has been leaked!", extents); 219 | } 220 | 221 | *e = first_ext; 222 | } 223 | 224 | pub struct Unadorned { 225 | ptr: NonZero<*mut T>, 226 | } 227 | 228 | unsafe impl Send for Unadorned {} 229 | unsafe impl Sync for Unadorned {} 230 | 231 | impl Unadorned { 232 | pub fn is_boring(&self) -> bool { 233 | mem::size_of::() == 0 234 | } 235 | 236 | #[inline] 237 | pub fn shallow_copy(&self) -> Self { 238 | Unadorned { ptr: self.ptr } 239 | } 240 | 241 | #[inline] 242 | pub unsafe fn new() -> (Unadorned, NewUpdate) { 243 | (Unadorned { 244 | ptr: NonZero::new(EMPTY as *mut T), 245 | }, NewUpdate) 246 | } 247 | 248 | #[inline] 249 | pub unsafe fn with_capacity(cap: usize) -> (Unadorned, WithCapUpdate) { 250 | (Unadorned { 251 | ptr: my_alloc::(cap), 252 | }, WithCapUpdate) 253 | } 254 | 255 | #[inline] 256 | pub unsafe fn from_raw_parts(ptr: *mut T) -> (Unadorned, FromRawPartsUpdate) { 257 | assert!(!ptr.is_null()); 258 | (Unadorned { 259 | ptr: NonZero::new(ptr), 260 | }, FromRawPartsUpdate) 261 | } 262 | 263 | #[inline] 264 | pub unsafe fn as_vec(&self, e: &Extent) -> Vec { 265 | Vec::from_raw_parts(*self.ptr, e.len, e.cap) 266 | } 267 | 268 | #[inline] 269 | pub fn as_ptr(&self) -> *const T { 270 | *self.ptr as *const T 271 | } 272 | 273 | #[inline] 274 | pub fn as_mut_ptr(&mut self) -> *mut T { 275 | *self.ptr 276 | } 277 | 278 | pub unsafe fn from_raw_bufs(src: *const T, elts: usize) -> (Unadorned, FromRawBufsUpdate) { 279 | let dst = my_alloc::(elts); 280 | memcpy(*dst, src, elts); 281 | (Unadorned { 282 | ptr: dst, 283 | }, FromRawBufsUpdate) 284 | } 285 | 286 | #[inline] 287 | pub unsafe fn reserve(&mut self, e: &Extent, space_needed: &ReserveCalc) -> ReserveUpdate { 288 | let old_cap = e.cap; 289 | let new_cap = space_needed.0; 290 | 291 | if self.is_boring() { return ReserveUpdate } 292 | 293 | let size = byte_length_of::(new_cap); 294 | self.ptr = alloc_or_realloc(*self.ptr, old_cap * mem::size_of::(), size); 295 | 296 | ReserveUpdate 297 | } 298 | 299 | pub unsafe fn shrink_to_fit(&mut self, e: &Extent) -> ShrinkToFitUpdate { 300 | if self.is_boring() { return ShrinkToFitUpdate } 301 | 302 | if e.len == 0 { 303 | if e.cap != 0 { 304 | dealloc(*self.ptr, e.cap); 305 | } 306 | } else { 307 | let new_ptr = 308 | reallocate(*self.ptr as *mut u8, 309 | e.cap * mem::size_of::(), 310 | e.len * mem::size_of::(), 311 | mem::min_align_of::()) as *mut T; 312 | if new_ptr.is_null() { ::alloc::oom() } 313 | self.ptr = NonZero::new(new_ptr); 314 | } 315 | 316 | ShrinkToFitUpdate 317 | } 318 | 319 | pub unsafe fn truncate(&mut self, len: usize, e: &Extent) -> TruncateUpdate { 320 | if self.is_boring() { return TruncateUpdate } 321 | 322 | let mut real_len = e.len; 323 | 324 | while len < real_len { 325 | real_len -= 1; 326 | ptr::read(self.ptr.offset(real_len as isize)); 327 | } 328 | 329 | TruncateUpdate 330 | } 331 | 332 | #[inline] 333 | pub unsafe fn as_slice<'a>(&'a self, len: usize) -> &'a [T] { 334 | let p: &'a *const T = mem::transmute(&*self.ptr); 335 | slice::from_raw_parts(*p, len) 336 | } 337 | 338 | #[inline] 339 | pub unsafe fn as_mut_slice<'a>(&'a mut self, len: usize) -> &'a mut [T] { 340 | slice::from_raw_parts_mut(*self.ptr, len) 341 | } 342 | 343 | #[inline] 344 | pub unsafe fn into_iter(self, e: &Extent) -> vec::IntoIter { 345 | let r = Vec::from_raw_parts(*self.ptr, e.len, e.cap); 346 | r.into_iter() 347 | } 348 | 349 | pub unsafe fn insert(&mut self, 350 | index: usize, x: T, 351 | e: &Extent, space_needed: &Option) -> InsertUpdate { 352 | let _ = space_needed.as_ref().map(|space| self.reserve(e, space)); 353 | 354 | let p = self.ptr.offset(index as isize); 355 | memmove(p.offset(1), &*p, e.len - index); 356 | ptr::write(&mut *p, x); 357 | 358 | InsertUpdate 359 | } 360 | 361 | pub unsafe fn remove(&mut self, index: usize, e: &Extent) -> (T, RemoveUpdate) { 362 | let ptr = self.ptr.offset(index as isize); 363 | let ret = ptr::read(ptr); 364 | memmove(ptr, &*ptr.offset(1), e.len - index - 1); 365 | (ret, RemoveUpdate) 366 | } 367 | 368 | unsafe fn make_room_for_one(&mut self, e: &Extent) { 369 | if self.is_boring() { return } 370 | 371 | let old_size = e.cap * mem::size_of::(); 372 | let size = max(old_size, 2 * mem::size_of::()) * 2; 373 | if old_size > size { panic!("capacity overflow") } 374 | self.ptr = alloc_or_realloc(*self.ptr, old_size, size); 375 | } 376 | 377 | #[inline] 378 | pub unsafe fn push(&mut self, value: T, e: &Extent) -> PushUpdate { 379 | if e.len == e.cap { 380 | self.make_room_for_one(e); 381 | } 382 | 383 | ptr::write(self.ptr.offset(e.len as isize), value); 384 | PushUpdate 385 | } 386 | 387 | #[inline] 388 | pub unsafe fn append(&mut self, self_e: &Extent, other: &Self, other_e: &Extent, space: &Option) -> AppendUpdate { 389 | space.as_ref().map(|space| self.reserve(self_e, space)); 390 | ptr::copy_nonoverlapping(*self.ptr, *other.ptr, other_e.len); 391 | 392 | AppendUpdate 393 | } 394 | 395 | pub unsafe fn extend>(&mut self, e: &Extent, space: &Option, i: I) -> ExtendUpdate { 396 | let mut this_extent: Extent = *e; 397 | 398 | space.as_ref().map(|space| { 399 | let ru = self.reserve(e, space); 400 | reserve_update(&[ru], (*space).clone(), &mut this_extent); 401 | }); 402 | 403 | for x in i { 404 | let u = self.push(x, &this_extent); 405 | push_update(&[u], &mut this_extent); 406 | } 407 | 408 | ExtendUpdate(this_extent) 409 | } 410 | 411 | pub unsafe fn drop(&self, e: &Extent) { 412 | for x in self.as_slice(e.len) { 413 | drop(ptr::read(x)); 414 | } 415 | dealloc(*self.ptr, e.cap); 416 | } 417 | } 418 | 419 | impl Unadorned { 420 | #[inline] 421 | pub unsafe fn push_all(&mut self, x: &[T], e: &Extent, space: &Option) -> PushAllUpdate { 422 | space.as_ref().map(|space| self.reserve(e, space)); 423 | 424 | let mut len = e.len; 425 | 426 | for i in 0..x.len() { 427 | // LLVM is easily confused. This is carefully constructed such that 428 | // Copy types get a memcpy. 429 | ptr::write(self.ptr.offset(len as isize), x.get_unchecked(i).clone()); 430 | len += 1; 431 | } 432 | 433 | PushAllUpdate 434 | } 435 | } 436 | -------------------------------------------------------------------------------- /src/soa.rs: -------------------------------------------------------------------------------- 1 | use collections::vec; 2 | 3 | use core::cmp::Ordering; 4 | use core::default::Default; 5 | use core::fmt::{Debug, Formatter, Result}; 6 | use core::hash::{self, Hash}; 7 | use core::iter::{self, repeat}; 8 | use core::mem; 9 | use core::num::Int; 10 | use core::ptr; 11 | use core::slice; 12 | 13 | use unadorned::{self, Unadorned, Extent}; 14 | 15 | macro_rules! first { 16 | ($x:expr, $($xs:expr),*) => { $x } 17 | } 18 | 19 | 20 | macro_rules! anyrest { 21 | ($x:expr, $($xs:expr),*) => { $($xs)||* } 22 | } 23 | 24 | macro_rules! tupleup { 25 | ($a:expr, $b:expr) => { ($a, $b) }; 26 | ($a:expr, $b:expr, $($rest:expr),*) => { tupleup!(($a, $b), $($rest),*) } 27 | } 28 | macro_rules! zip_up { 29 | ($l:ident, $a:expr, $b:expr) => { Iter::Zip<$a, $b> }; 30 | ($l:ident, $a:expr, $b:expr, $($rest:expr),*) => { zip_up!($l,Iter::Zip, slice::Iter<$l, $b>>, $($rest),*) } 31 | } 32 | 33 | macro_rules! toits { 34 | ($($t:ident),*) => { $(Iterator),* } 35 | } 36 | 37 | macro_rules! gen_soa { 38 | ($soa:ident $soa_zip:ident $soa_mut_zip:ident | $($ty:ident),+ | $($nm:ident),+ | $($nmu:ident),+) => { 39 | #[unsafe_no_drop_flag] 40 | pub struct $soa<$($ty),+> { 41 | $($nm: Unadorned<$ty>),+, 42 | e: Extent, 43 | } 44 | 45 | pub struct $soa_zip<'a, $($ty: 'a),+> { 46 | parent: &'a $soa<$($ty),+>, 47 | i: usize, 48 | } 49 | 50 | impl<'a, $($ty),+> Iterator for $soa_zip<'a, $($ty),+> { 51 | type Item = ($(&'a $ty),+); 52 | 53 | #[inline] 54 | fn next(&mut self) -> Option<($(&'a $ty),+)> { 55 | let i = self.i; 56 | if i == self.parent.e.len { return None; } 57 | 58 | self.i += 1; 59 | 60 | unsafe { 61 | Some(($(&*self.parent.$nm.as_ptr().offset(i as isize)),+)) 62 | } 63 | } 64 | } 65 | 66 | pub struct $soa_mut_zip<'a, $($ty: 'a),+> { 67 | parent: &'a mut $soa<$($ty),+>, 68 | i: usize, 69 | } 70 | 71 | impl<'a, $($ty),+> Iterator for $soa_mut_zip<'a, $($ty),+> { 72 | type Item = ($(&'a mut $ty),+); 73 | 74 | #[inline] 75 | fn next(&mut self) -> Option<($(&'a mut $ty),+)> { 76 | let i = self.i; 77 | if i == self.parent.e.len { return None; } 78 | 79 | self.i += 1; 80 | 81 | unsafe { 82 | Some(($(&mut *self.parent.$nm.as_mut_ptr().offset(i as isize)),+)) 83 | } 84 | } 85 | } 86 | 87 | pub struct $soa_into_iter<$($ty),+> { 88 | } 89 | 90 | impl<$($ty),+> $soa<$($ty),+> { 91 | fn new() -> $soa<$($ty),+> { 92 | unsafe { 93 | $(let ($nm, $nmu) = Unadorned::new());+; 94 | let e = unadorned::new_update(&[$($nmu),+]); 95 | $soa { $($nm: $nm),+ , e: e} 96 | } 97 | } 98 | 99 | #[inline] 100 | fn is_boring(&self) -> bool { 101 | $(self.$nm.is_boring())&&+ 102 | } 103 | 104 | #[inline] 105 | pub fn with_capacity(capacity: usize) -> $soa<$($ty),+> { 106 | unsafe { 107 | $(let ($nm, $nmu) = Unadorned::with_capacity(capacity));+; 108 | let is_boring = $(mem::size_of::<$ty>() == 0)&&+; 109 | let e = unadorned::with_capacity_update(&[$($nmu),+], is_boring, capacity); 110 | $soa { $($nm: $nm),+, e: e} 111 | } 112 | } 113 | 114 | #[inline] 115 | pub unsafe fn from_raw_parts( 116 | // this re-use of $nm is hacky and gross. 117 | $($nm: *mut $ty),+, len: usize, cap: usize) -> $soa<$($ty),+> { 118 | $(let ($nm, $nmu) = Unadorned::from_raw_parts($nm));+; 119 | let e = unadorned::from_raw_parts_update(&[$($nmu),+], len, cap); 120 | $soa { $($nm: $nm),+, e: e} 121 | } 122 | 123 | #[inline] 124 | pub unsafe fn from_raw_bufs($($nm: *const $ty),+, elts: usize) -> $soa<$($ty),+> { 125 | $(let ($nm, $nmu) = Unadorned::from_raw_bufs($nm, elts));+; 126 | let e = unadorned::from_raw_bufs_update(&[$($nmu),+], elts); 127 | $soa { $($nm: $nm),+, e: e} 128 | } 129 | 130 | pub fn from_vecs($(mut $nm: Vec<$ty>),+) -> $soa<$($ty),+> { 131 | let firstlen = first!($($nm.len()),+); 132 | if anyrest!($(firstlen != $nm.len()),+ ) { 133 | panic!("unequal lengths"); 134 | } 135 | let firstcap = first!($($nm.capacity()),+); 136 | if anyrest!($(firstcap != $nm.capacity()),+) { 137 | $($nm.shrink_to_fit());+; 138 | } 139 | let cap = first!($($nm.capacity()),+); 140 | unsafe { 141 | let ret = $soa::from_raw_parts( 142 | $($nm.as_ptr() as *mut $ty),+, 143 | firstlen, cap); 144 | $(mem::forget($nm));+; 145 | ret 146 | } 147 | } 148 | 149 | #[inline] 150 | pub fn len(&self) -> usize { self.e.len } 151 | 152 | #[inline] 153 | pub fn is_empty(&self) -> bool { self.len() == 0 } 154 | 155 | #[inline] 156 | pub fn capacity(&self) -> usize { self.e.cap } 157 | 158 | pub fn reserve(&mut self, additional: usize) { 159 | let space = match unadorned::calc_reserve_space(&self.e, additional) { 160 | None => return, 161 | Some(space) => space 162 | }; 163 | 164 | unsafe { 165 | $(let $nmu = self.$nm.reserve(&self.e, &space));+; 166 | unadorned::reserve_update(&[$($nmu),+], space, &mut self.e) 167 | } 168 | } 169 | pub fn reserve_exact(&mut self, additional: usize) { 170 | let space = match unadorned::calc_reserve_exact_space(&self.e, additional) { 171 | None => return, 172 | Some(space) => space 173 | }; 174 | 175 | unsafe { 176 | $(let $nmu = self.$nm.reserve(&self.e, &space));+; 177 | unadorned::reserve_update(&[$($nmu),+], space, &mut self.e) 178 | } 179 | } 180 | 181 | pub fn shrink_to_fit(&mut self) { 182 | if self.is_boring() { return } 183 | unsafe { 184 | $(let $nmu = self.$nm.shrink_to_fit(&self.e));+; 185 | unadorned::shrink_to_fit_update(&[$($nmu),+], &mut self.e); 186 | } 187 | } 188 | 189 | pub fn truncate(&mut self, len: usize) { 190 | if self.is_boring() { return } 191 | unsafe { 192 | $(let $nmu = self.$nm.truncate(len, &self.e));+; 193 | unadorned::truncate_update(&[$($nmu),+], len, &mut self.e); 194 | } 195 | } 196 | 197 | #[inline] 198 | pub fn as_mut_slices<'a> (&'a mut self) -> ($(&'a mut [$ty]),+) { 199 | unsafe { 200 | let len = self.e.len; 201 | ($(self.$nm.as_mut_slice(len)),+) 202 | } 203 | } 204 | 205 | #[inline] 206 | pub fn as_slices<'a>(&'a self) -> ($(&'a [$ty]),+) { 207 | unsafe { let len = self.e.len; 208 | ($(self.$nm.as_slice(len)),+) } 209 | } 210 | 211 | #[inline] 212 | pub fn iters(&self) -> ($(slice::Iter<$ty>),+) { 213 | let ($($nm),+) = self.as_slices(); 214 | ($($nm.iter()),+) 215 | } 216 | 217 | #[inline] 218 | pub fn iters_mut(&mut self) -> ($(slice::IterMut<$ty>),+) { 219 | let ($($nm),+) = self.as_mut_slices(); 220 | ($($nm.iter_mut()),+) 221 | } 222 | 223 | #[inline] 224 | pub fn into_iters(mut self) -> ($(vec::IntoIter<$ty>),+) { 225 | unsafe { 226 | let e_copy = self.e; 227 | self.e.cap = 0; 228 | ($(self.$nm.shallow_copy().into_iter(&e_copy)),+) 229 | } 230 | } 231 | 232 | #[inline] 233 | pub fn into_vecs(mut self) -> ($(Vec<$ty>),+) { 234 | unsafe { 235 | let e_copy = self.e; 236 | self.e.cap = 0; 237 | ($(self.$nm.shallow_copy().as_vec(&e_copy)),+) 238 | } 239 | } 240 | 241 | #[inline] 242 | pub fn as_ptrs(&self) -> ($(*const $ty),+) { 243 | let ($($nm),+) = self.as_slices(); 244 | ($($nm.as_ptr()),+) 245 | } 246 | 247 | #[inline] 248 | pub fn as_mut_ptrs(&mut self) -> ($(*mut $ty),+) { 249 | let ($($nm),+) = self.as_mut_slices(); 250 | ($($nm.as_mut_ptr()),+) 251 | } 252 | 253 | #[inline] 254 | pub fn swap_remove(&mut self, index: usize) -> ($($ty),+) { 255 | let length = self.e.len; 256 | { 257 | let ($($nm),+) = self.as_mut_slices(); 258 | $($nm.swap(index, length - 1));+; 259 | } 260 | self.pop().unwrap() 261 | } 262 | 263 | pub fn insert(&mut self, index: usize, element: ($($ty),+)) { 264 | unsafe { 265 | assert!(index < self.e.len); 266 | let space = unadorned::calc_reserve_space(&self.e, 1); 267 | let ($($nm),+) = element; 268 | $(let $nmu = self.$nm.insert(index, $nm, &self.e, &space));+; 269 | unadorned::insert_update(&[$($nmu),+], space, &mut self.e); 270 | } 271 | } 272 | 273 | pub fn remove(&mut self, index: usize) -> ($($ty),+) { 274 | unsafe { 275 | assert!(index < self.e.len); 276 | $(let ($nm, $nmu) = self.$nm.remove(index, &self.e));+; 277 | unadorned::remove_update(&[$($nmu),+], &mut self.e); 278 | ($($nm),+) 279 | } 280 | } 281 | 282 | pub fn retain(&mut self, mut f: Fun) where Fun: FnMut(($(&$ty),+)) -> bool { 283 | let len = self.len(); 284 | let mut del = 0us; 285 | 286 | { 287 | let ($($nm),+) = self.as_mut_slices(); 288 | for i in range(0us, len) { 289 | if !f(($(&$nm[i]),+)) { 290 | del += 1; 291 | } else if del > 0 { 292 | $($nm.swap(i-del, i));+; 293 | } 294 | } 295 | } 296 | 297 | self.truncate(len - del); 298 | } 299 | 300 | #[inline] 301 | pub fn push(&mut self, value: ($($ty),+)) { 302 | if self.is_boring() { 303 | self.e.len = self.e.len.checked_add(1).expect("length overflow"); 304 | unsafe { mem::forget(value) } 305 | return 306 | } 307 | unsafe { 308 | let ($($nm),+) = value; 309 | $(let $nmu = self.$nm.push($nm, &self.e));+; 310 | unadorned::push_update(&[$($nmu),+], &mut self.e); 311 | } 312 | } 313 | 314 | #[inline] 315 | pub fn pop(&mut self) -> Option<($($ty),+)> { 316 | if self.e.len == 0 { 317 | None 318 | } else { 319 | unsafe { 320 | self.e.len -= 1; 321 | let len = self.e.len; 322 | let ($($nm),+) = self.as_mut_slices(); 323 | Some(($(ptr::read($nm.get_unchecked(len))),+)) 324 | } 325 | } 326 | } 327 | 328 | #[inline] 329 | pub fn append(&mut self, other: &mut Self) { 330 | if self.is_boring() { 331 | self.e.len = self.e.len.checked_add(other.len()).expect("length overflow"); 332 | other.e.len = 0; 333 | return ; 334 | } 335 | unsafe { 336 | let space = unadorned::calc_reserve_space(&self.e, 1); 337 | $(let $nmu = self.$nm.append(&self.e, &other.$nm, &other.e, &space));+; 338 | unadorned::append_update(&[$($nmu),+], &mut self.e, &mut other.e, space); 339 | } 340 | } 341 | 342 | #[inline] 343 | pub fn clear(&mut self) { self.truncate(0) } 344 | 345 | // abusing type/value namespace separation. 346 | // nothing else works, for serious. 347 | // in particular, "extend<$(Iterator),+>" and 348 | // "extend<$(concat_idents!(I,$ty),+)>" both don't work. 349 | #[allow(non_camel_case_types)] 350 | pub fn extend<$($nm),+>(&mut self, $($nm: $nm),+) 351 | where $($nm: Iterator),+ 352 | { 353 | unsafe { 354 | let (lower, _) = first!($($nm.size_hint()),+); 355 | let space = unadorned::calc_reserve_space(&self.e, lower); 356 | $(let $nmu = self.$nm.extend(&self.e, &space, $nm));+; 357 | unadorned::extend_update(&[$($nmu),+], &mut self.e); 358 | } 359 | } 360 | 361 | #[allow(non_camel_case_types)] 362 | pub fn from_iters<$($nm),+>($($nm:$nm),+) -> $soa<$($ty),+> 363 | where $($nm: Iterator),+ 364 | { 365 | let mut v = $soa::new(); 366 | v.extend($($nm),+); 367 | v 368 | } 369 | } 370 | 371 | impl<$($ty: Clone),+> $soa<$($ty),+> { 372 | #[inline] 373 | pub fn resize(&mut self, new_len: usize, value: ($($ty),+)) { 374 | let len = self.len(); 375 | if new_len > len { 376 | let ($($nm),+) = value; 377 | self.extend($(repeat($nm).take(new_len - len)),+); 378 | } else { 379 | self.truncate(new_len) 380 | } 381 | } 382 | 383 | #[inline] 384 | pub fn push_all(&mut self, $($nm: &[$ty]),+) { 385 | unsafe { 386 | let firstlen = first!($($nm.len()),+); 387 | if anyrest!($(firstlen != $nm.len()),+) { 388 | panic!("lengths not equal") 389 | } 390 | let space = unadorned::calc_reserve_space(&self.e, firstlen); 391 | $(let $nmu = self.$nm.push_all($nm, &self.e, &space));+; 392 | unadorned::push_all_update(&[$($nmu),+], &mut self.e, firstlen, space); 393 | } 394 | } 395 | } 396 | 397 | impl<$($ty: Clone),+> Clone for $soa<$($ty),+> { 398 | #[inline] 399 | fn clone(&self) -> $soa<$($ty),+> { 400 | let mut ret = $soa::new(); 401 | let ($($nm),+) = self.as_slices(); 402 | ret.push_all($($nm),+); 403 | ret 404 | } 405 | // clone_from requires figuring out zip 406 | } 407 | impl),+> Hash for $soa<$($ty),+> { 408 | #[inline] 409 | fn hash(&self, state: &mut S) { 410 | self.as_slices().hash(state) 411 | } 412 | } 413 | 414 | #[allow(non_camel_case_types)] 415 | impl<$($nm),+, $($nmu),+> PartialEq<$soa<$($nmu),+>> for $soa<$($nm),+> 416 | where $($nm: PartialEq<$nmu>),+ 417 | { 418 | #[inline] 419 | fn eq(&self, other: &$soa<$($nmu),+>) -> bool { 420 | let ($($nm),+) = self.as_slices(); 421 | let ($($nmu),+) = other.as_slices(); 422 | $(PartialEq::eq($nm, $nmu))&&+ 423 | } 424 | #[inline] 425 | fn ne(&self, other: &$soa<$($nmu),+>) -> bool { 426 | let ($($nm),+) = self.as_slices(); 427 | let ($($nmu),+) = other.as_slices(); 428 | $(PartialEq::ne($nm, $nmu))||+ 429 | } 430 | } 431 | } 432 | } 433 | 434 | 435 | // the need to write out these names is also gross. 436 | gen_soa!(Soa5 Soa5ZipIter Soa5ZipIterMut | A, B, C, D, E | d1, d2, d3, d4, d5 | d1u, d2u, d3u, d4u, d5u); 437 | gen_soa!(Soa6 Soa6ZipIter Soa6ZipIterMut | A, B, C, D, E, F | d1, d2, d3, d4, d5, d6 | du1, du2, du3, du4, du5, du6); 438 | 439 | // couldn't quite figure out a way to get the macro transcriber to like doing 440 | // complicated things to iter::Map's template in zip_iter, on which a number of further 441 | // things depend---oh well! 442 | -------------------------------------------------------------------------------- /src/soa2.rs: -------------------------------------------------------------------------------- 1 | use collections::vec; 2 | 3 | use core::cmp::Ordering; 4 | use core::default::Default; 5 | use core::fmt::{Debug, Formatter, Result}; 6 | use core::hash::{Hash, Hasher}; 7 | use core::iter::{self, repeat}; 8 | use core::mem; 9 | use core::ptr; 10 | use core::slice; 11 | 12 | use unadorned::{self, Unadorned, Extent}; 13 | 14 | /// A growable struct-of-2-arrays type, with heap allocated contents. 15 | /// 16 | /// This structure is analogous to a `Vec<(A, B)>`, but instead of laying out 17 | /// the tuples sequentially in memory, each row gets its own allocation. For 18 | /// example, an `Soa2` will contain two inner arrays: one of `f32`s, 19 | /// and one of `i64`s. 20 | /// 21 | /// All data is aligned to 16-bytes. Feel free to do SIMD operations with array 22 | /// contents. 23 | #[unsafe_no_drop_flag] 24 | pub struct Soa2 { 25 | d0: Unadorned, 26 | d1: Unadorned, 27 | e: Extent, 28 | } 29 | 30 | impl Soa2 { 31 | /// Constructs a new, empty `Soa2`. 32 | /// 33 | /// The SoA will not allocate until elements are pushed onto it. 34 | pub fn new() -> Soa2 { 35 | unsafe { 36 | let (d0, d0u) = Unadorned::new(); 37 | let (d1, d1u) = Unadorned::new(); 38 | 39 | let e = unadorned::new_update(&[d0u, d1u]); 40 | 41 | Soa2 { d0: d0, d1: d1, e: e } 42 | } 43 | } 44 | 45 | /// Returns `true` if all our elements are zero-sized types. 46 | #[inline] 47 | fn is_boring(&self) -> bool { 48 | self.d0.is_boring() && self.d1.is_boring() 49 | } 50 | 51 | /// Constructs a new, empty `Soa2` with the specified capacity. 52 | /// 53 | /// The SoA will be able to hold exactly `capacity` tuples of elements 54 | /// without reallocating. 55 | /// 56 | /// If `capacity` is 0, the SoA will not allocate. 57 | /// 58 | /// It is important to note that this function does not specify the *length* 59 | /// of the soa, but only the *capacity*. 60 | #[inline] 61 | pub fn with_capacity(capacity: usize) -> Soa2 { 62 | unsafe { 63 | let (d0, d0u) = Unadorned::with_capacity(capacity); 64 | let (d1, d1u) = Unadorned::with_capacity(capacity); 65 | 66 | let is_boring = 67 | mem::size_of::() == 0 68 | && mem::size_of::() == 0; 69 | 70 | let e = unadorned::with_capacity_update(&[d0u, d1u], is_boring, capacity); 71 | 72 | Soa2 { d0: d0, d1: d1, e: e } 73 | } 74 | } 75 | 76 | /// Constructs a `Soa2` directly from the raw components of another. 77 | /// 78 | /// This is highly unsafe, and no invariants are checked. 79 | #[inline] 80 | pub unsafe fn from_raw_parts( 81 | ptra: *mut A, ptrb: *mut B, len: usize, cap: usize) -> Soa2 { 82 | let (d0, d0u) = Unadorned::from_raw_parts(ptra); 83 | let (d1, d1u) = Unadorned::from_raw_parts(ptrb); 84 | 85 | let e = unadorned::from_raw_parts_update(&[d0u, d1u], len, cap); 86 | 87 | Soa2 { d0: d0, d1: d1, e: e } 88 | } 89 | 90 | /// Constructs a `Soa2` by copying the elements from raw pointers. 91 | /// 92 | /// This function will copy `elts` contiguous elements from each of the 93 | /// pointers into a new allocation owned by the returned `Soa2`. The elements 94 | /// of the buffer are copied without cloning, as if `ptr::read()` were called 95 | /// on them. 96 | #[inline] 97 | pub unsafe fn from_raw_bufs(ptra: *const A, ptrb: *const B, elts: usize) -> Soa2 { 98 | let (d0, d0u) = Unadorned::from_raw_bufs(ptra, elts); 99 | let (d1, d1u) = Unadorned::from_raw_bufs(ptrb, elts); 100 | 101 | let e = unadorned::from_raw_bufs_update(&[d0u, d1u], elts); 102 | 103 | Soa2 { d0: d0, d1: d1, e: e } 104 | } 105 | 106 | /// Constructs a `Soa2` directly from vectors of its components. 107 | /// 108 | /// This function will panic if the lengths of the vectors don't match. 109 | /// 110 | /// If the capacity of the vectors don't match they will be reallocated to 111 | /// have matching capacities. 112 | /// 113 | /// Otherwise, no allocation will be performed and the SoA will only take 114 | /// ownership of the elements in the vectors. 115 | pub fn from_vecs(mut v0: Vec, mut v1: Vec) -> Soa2 { 116 | assert_eq!(v0.len(), v1.len()); 117 | if v0.capacity() != v1.capacity() { 118 | v0.shrink_to_fit(); 119 | v1.shrink_to_fit(); 120 | } 121 | let len = v0.len(); 122 | let cap = v0.capacity(); 123 | 124 | unsafe { 125 | let ret = Soa2::from_raw_parts( 126 | v0.as_ptr() as *mut A, 127 | v1.as_ptr() as *mut B, 128 | len, cap); 129 | mem::forget(v0); 130 | mem::forget(v1); 131 | ret 132 | } 133 | } 134 | 135 | /// Returns the number of tuples stored in the SoA. 136 | #[inline] 137 | pub fn len(&self) -> usize { 138 | self.e.len 139 | } 140 | 141 | /// Returns `true` if the SoA contains no elements. 142 | #[inline] 143 | pub fn is_empty(&self) -> bool { 144 | self.len() == 0 145 | } 146 | 147 | /// Sets the length of a vector. 148 | /// 149 | /// This will explicitly set the size of the soa, without actually 150 | /// modifying its buffers, so it is up to the caller to ensure that the 151 | /// SoA is actually the specified size. 152 | #[inline] 153 | pub unsafe fn set_len(&mut self, len: usize) { 154 | self.e.len = len; 155 | } 156 | 157 | /// Returns the number of elements the SoA can hold without reallocating. 158 | #[inline] 159 | pub fn capacity(&self) -> usize { 160 | self.e.cap 161 | } 162 | 163 | /// Reserves capacity for at least `additional` more elements to be inserted 164 | /// in the given SoA. The collection may reserve more space to avoid frequent 165 | /// reallocations. 166 | /// 167 | /// Panics if the new capacity overflows `usize`. 168 | pub fn reserve(&mut self, additional: usize) { 169 | let space = 170 | match unadorned::calc_reserve_space(&self.e, additional) { 171 | None => return, 172 | Some(space) => space, 173 | }; 174 | 175 | unsafe { 176 | let d0u = self.d0.reserve(&self.e, &space); 177 | let d1u = self.d1.reserve(&self.e, &space); 178 | 179 | unadorned::reserve_update(&[d0u, d1u], space, &mut self.e); 180 | } 181 | } 182 | 183 | /// Reserves the minimum capacity for exactly `additional` more elements to 184 | /// be inserted in the given SoA. Does nothing if the capacity is already 185 | /// sufficient. 186 | /// 187 | /// Note that the allocator may give the collection more space than it 188 | /// requests. Therefore, capacity can not be relied upon to be precisely 189 | /// minimal. Prefer `reserve` if future insertions are expected. 190 | /// 191 | /// Panics if the new capacity overflows `usize`. 192 | pub fn reserve_exact(&mut self, additional: usize) { 193 | let space = 194 | match unadorned::calc_reserve_exact_space(&self.e, additional) { 195 | None => return, 196 | Some(space) => space, 197 | }; 198 | 199 | unsafe { 200 | let d0u = self.d0.reserve(&self.e, &space); 201 | let d1u = self.d1.reserve(&self.e, &space); 202 | 203 | unadorned::reserve_update(&[d0u, d1u], space, &mut self.e); 204 | } 205 | } 206 | 207 | /// Shrinks the capacity of the SoA as much as possible. 208 | /// 209 | /// It will drop down as close as possible to the length, but the allocator 210 | /// may still inform the SoA that there is space for a few more elements. 211 | pub fn shrink_to_fit(&mut self) { 212 | if self.is_boring() { return } 213 | 214 | unsafe { 215 | let d0u = self.d0.shrink_to_fit(&self.e); 216 | let d1u = self.d1.shrink_to_fit(&self.e); 217 | 218 | unadorned::shrink_to_fit_update(&[d0u, d1u], &mut self.e); 219 | } 220 | } 221 | 222 | /// Shorten a SoA, dropping excess elements. 223 | /// 224 | /// If `len` is greater than the soa's current length, this has no effect. 225 | pub fn truncate(&mut self, len: usize) { 226 | if self.is_boring() { return } 227 | 228 | unsafe { 229 | let d0u = self.d0.truncate(len, &self.e); 230 | let d1u = self.d1.truncate(len, &self.e); 231 | 232 | unadorned::truncate_update(&[d0u, d1u], len, &mut self.e); 233 | } 234 | } 235 | 236 | /// Returns mutable slices over the SoA's elements. 237 | #[inline] 238 | pub fn as_mut_slices<'a>(&'a mut self) -> (&'a mut [A], &'a mut [B]) { 239 | unsafe { 240 | let len = self.e.len; 241 | (self.d0.as_mut_slice(len), self.d1.as_mut_slice(len)) 242 | } 243 | } 244 | 245 | /// Returns slices over the SoA's elements. 246 | #[inline] 247 | pub fn as_slices<'a>(&'a self) -> (&'a [A], &'a [B]) { 248 | unsafe { 249 | let len = self.e.len; 250 | (self.d0.as_slice(len), self.d1.as_slice(len)) 251 | } 252 | } 253 | 254 | /// Returns iterators over the SoA's elements. 255 | #[inline] 256 | pub fn iters(&self) -> (slice::Iter, slice::Iter) { 257 | let (d0, d1) = self.as_slices(); 258 | (d0.iter(), d1.iter()) 259 | } 260 | 261 | /// Returns a single iterator over the SoA's elements, zipped up. 262 | #[inline] 263 | pub fn zip_iter(&self) -> iter::Zip, slice::Iter> { 264 | let (d0, d1) = self.iters(); 265 | d0.zip(d1) 266 | } 267 | 268 | /// Returns mutable iterators over the SoA's elements. 269 | #[inline] 270 | pub fn iters_mut(&mut self) -> (slice::IterMut, slice::IterMut) { 271 | let (d0, d1) = self.as_mut_slices(); 272 | (d0.iter_mut(), d1.iter_mut()) 273 | } 274 | 275 | /// Returns a single iterator over the SoA's elements, zipped up. 276 | #[inline] 277 | pub fn zip_iter_mut(&mut self) -> iter::Zip, slice::IterMut> { 278 | let (d0, d1) = self.iters_mut(); 279 | d0.zip(d1) 280 | } 281 | 282 | /// Converts an SoA into iterators for each of its arrays. 283 | #[inline] 284 | pub fn into_iters(mut self) -> (vec::IntoIter, vec::IntoIter) { 285 | unsafe { 286 | let e_copy = self.e; 287 | self.e.cap = 0; // Will skip the drop. into_iter will handle it. 288 | (self.d0.shallow_copy().into_iter(&e_copy), 289 | self.d1.shallow_copy().into_iter(&e_copy)) 290 | } 291 | } 292 | 293 | /// Converts an SoA into a pair of `Vec`s. This will neither allocator nor 294 | /// copy. 295 | #[inline] 296 | pub fn into_vecs(mut self) -> (Vec, Vec) { 297 | unsafe { 298 | let e_copy = self.e; 299 | self.e.cap = 0; 300 | (self.d0.shallow_copy().as_vec(&e_copy), 301 | self.d1.shallow_copy().as_vec(&e_copy)) 302 | } 303 | } 304 | 305 | /// Returns a pair of pointers to the start of the data in an SoA. 306 | #[inline] 307 | pub fn as_ptrs(&self) -> (*const A, *const B) { 308 | (self.d0.as_ptr(), self.d1.as_ptr()) 309 | } 310 | 311 | /// Returns a pair of pointers to the start of the mutable data in an SoA. 312 | #[inline] 313 | pub fn as_mut_ptrs(&mut self) -> (*mut A, *mut B) { 314 | (self.d0.as_mut_ptr(), self.d1.as_mut_ptr()) 315 | } 316 | 317 | /// Removes an element from anywhere in the SoA and returns it, replacing it 318 | /// with the last element. 319 | /// 320 | /// This does not preserve ordering, but is O(1). 321 | /// 322 | /// Panics if `index` is out of bounds. 323 | #[inline] 324 | pub fn swap_remove(&mut self, index: usize) -> (A, B) { 325 | let length = self.e.len; 326 | { 327 | let (d0, d1) = self.as_mut_slices(); 328 | d0.swap(index, length - 1); 329 | d1.swap(index, length - 1); 330 | } 331 | self.pop().unwrap() 332 | } 333 | 334 | /// Inserts an element at position `index` within the vector, shifting all 335 | /// elements after position `index` one position to the right. 336 | /// 337 | /// Panics if `index` is not between `0` and the SoA's length, inclusive. 338 | pub fn insert(&mut self, index: usize, element: (A, B)) { 339 | unsafe { 340 | assert!(index < self.e.len); 341 | 342 | let space = unadorned::calc_reserve_space(&self.e, 1); 343 | 344 | let d0u = self.d0.insert(index, element.0, &self.e, &space); 345 | let d1u = self.d1.insert(index, element.1, &self.e, &space); 346 | 347 | unadorned::insert_update(&[d0u, d1u], space, &mut self.e); 348 | } 349 | } 350 | 351 | /// Removes and returns the elements at position `index` within the SoA, 352 | /// shifting all elements after position `index` one position to the left. 353 | /// 354 | /// Panics if `index` is out of bounds. 355 | pub fn remove(&mut self, index: usize) -> (A, B) { 356 | unsafe { 357 | assert!(index < self.e.len); 358 | 359 | let (x0, d0u) = self.d0.remove(index, &self.e); 360 | let (x1, d1u) = self.d1.remove(index, &self.e); 361 | 362 | unadorned::remove_update(&[d0u, d1u], &mut self.e); 363 | (x0, x1) 364 | } 365 | } 366 | 367 | /// Returns only the element specified by the predicate. 368 | /// 369 | /// In other words, remove all elements `e` such that `f(&e)` returns false. 370 | /// This method operates in place and preserves the order of the retained 371 | /// elements. 372 | pub fn retain(&mut self, mut f: F) where F: FnMut((&A, &B)) -> bool { 373 | let len = self.len(); 374 | let mut del = 0; 375 | 376 | { 377 | let (d0, d1) = self.as_mut_slices(); 378 | 379 | for i in 0..len { 380 | if !f((&d0[i], &d1[i])) { 381 | del += 1; 382 | } else if del > 0 { 383 | d0.swap(i-del, i); 384 | d1.swap(i-del, i); 385 | } 386 | } 387 | } 388 | 389 | self.truncate(len - del); 390 | } 391 | 392 | /// Appends an element to the back of a collection. 393 | /// 394 | /// Panics if the number of elements in the SoA overflows a `usize`. 395 | #[inline] 396 | pub fn push(&mut self, value: (A, B)) { 397 | if self.is_boring() { 398 | // zero-size types consume no memory, so we can't rely on the 399 | // address space running out 400 | self.e.len = self.e.len.checked_add(1).expect("length overflow"); 401 | unsafe { mem::forget(value) } 402 | return 403 | } 404 | 405 | unsafe { 406 | let d0u = self.d0.push(value.0, &self.e); 407 | let d1u = self.d1.push(value.1, &self.e); 408 | 409 | unadorned::push_update(&[d0u, d1u], &mut self.e); 410 | } 411 | } 412 | 413 | /// Removes the last element from a SoA and returns it, or `None` if empty. 414 | #[inline] 415 | pub fn pop(&mut self) -> Option<(A, B)> { 416 | if self.e.len == 0 { 417 | None 418 | } else { 419 | unsafe { 420 | self.e.len -= 1; 421 | let len = self.e.len; 422 | 423 | let (d0, d1) = self.as_mut_slices(); 424 | 425 | Some((ptr::read(d0.get_unchecked(len)), 426 | ptr::read(d1.get_unchecked(len)))) 427 | } 428 | } 429 | } 430 | 431 | /// Moves all the elements of `other` into `self`, leaving `other` empty. 432 | /// 433 | /// Panics if the number of elements in the SoA overflows a `usize`. 434 | #[inline] 435 | pub fn append(&mut self, other: &mut Self) { 436 | if self.is_boring() { 437 | // zero-size types consume no memory, so we can't rely on the address 438 | // space running out 439 | self.e.len = self.e.len.checked_add(other.len()).expect("length overflow"); 440 | other.e.len = 0; 441 | return; 442 | } 443 | 444 | unsafe { 445 | let space = unadorned::calc_reserve_space(&self.e, 1); 446 | 447 | let d0u = self.d0.append(&self.e, &other.d0, &other.e, &space); 448 | let d1u = self.d1.append(&self.e, &other.d1, &other.e, &space); 449 | 450 | unadorned::append_update(&[d0u, d1u], &mut self.e, &mut other.e, space); 451 | } 452 | } 453 | 454 | // TODO: drain 455 | 456 | /// Clears the SoA, removing all values. 457 | #[inline] 458 | pub fn clear(&mut self) { 459 | self.truncate(0); 460 | } 461 | 462 | // TODO: map_in_place 463 | 464 | /// Extends the SoA with the elements yielded by arbitrary iterators. 465 | /// 466 | /// Panics (and leaks memory!) if the iterators yield a different number of 467 | /// elements. 468 | pub fn extend(&mut self, i0: I0, i1: I1) 469 | where I0: Iterator, I1: Iterator { 470 | unsafe { 471 | let (lower, _) = i0.size_hint(); 472 | let space = unadorned::calc_reserve_space(&self.e, lower); 473 | 474 | let d0u = self.d0.extend(&self.e, &space, i0); 475 | let d1u = self.d1.extend(&self.e, &space, i1); 476 | 477 | unadorned::extend_update(&[d0u, d1u], &mut self.e); 478 | } 479 | } 480 | 481 | /// Constructs an `Soa2` with elements yielded by arbitrary iterators. 482 | /// 483 | /// Panics (and leaks memory!) if the iterators yield a different number of 484 | /// elements. 485 | pub fn from_iters(i0: I0, i1: I1) -> Soa2 486 | where I0: Iterator, I1: Iterator { 487 | let mut v = Soa2::new(); 488 | v.extend(i0, i1); 489 | v 490 | } 491 | 492 | // TODO: dedup 493 | } 494 | 495 | impl Soa2 { 496 | /// Resizes the SoA in-place so that `len()` is equal to `new_len`. 497 | /// 498 | /// Calls either `extend()` or `truncate()` depending on whether `new_len` is 499 | /// larger than the current value of `len()` or not. 500 | #[inline] 501 | pub fn resize(&mut self, new_len: usize, value: (A, B)) { 502 | let len = self.len(); 503 | 504 | if new_len > len { 505 | self.extend(repeat(value.0).take(new_len - len), repeat(value.1).take(new_len - len)); 506 | } else { 507 | self.truncate(new_len); 508 | } 509 | } 510 | 511 | /// Appends all elements in slices to the SoA. 512 | /// 513 | /// Iterates over the slices, clones each element, and then appends them to 514 | /// this SoA. The slices are traversed one at a time, in order. 515 | /// 516 | /// Panics if the slices are of different lengths. 517 | #[inline] 518 | pub fn push_all(&mut self, x0: &[A], x1: &[B]) { 519 | unsafe { 520 | assert_eq!(x0.len(), x1.len()); 521 | 522 | let space = unadorned::calc_reserve_space(&self.e, x0.len()); 523 | 524 | let d0u = self.d0.push_all(x0, &self.e, &space); 525 | let d1u = self.d1.push_all(x1, &self.e, &space); 526 | 527 | unadorned::push_all_update(&[d0u, d1u], &mut self.e, x0.len(), space); 528 | } 529 | } 530 | } 531 | 532 | impl Clone for Soa2 { 533 | #[inline] 534 | fn clone(&self) -> Soa2 { 535 | let mut ret = Soa2::new(); 536 | let (d0, d1) = self.as_slices(); 537 | ret.push_all(d0, d1); 538 | ret 539 | } 540 | 541 | fn clone_from(&mut self, other: &Soa2) { 542 | // TODO: cleanup 543 | 544 | if self.len() > other.len() { 545 | self.truncate(other.len()); 546 | } 547 | 548 | let (od0, od1) = other.as_slices(); 549 | 550 | let (s0, s1) = { 551 | let self_len = self.len(); 552 | let (sd0, sd1) = self.iters_mut(); 553 | 554 | for (place, thing) in sd0.zip(od0.iter()) { 555 | place.clone_from(thing); 556 | } 557 | 558 | for (place, thing) in sd1.zip(od1.iter()) { 559 | place.clone_from(thing); 560 | } 561 | 562 | let s0 = &od0[self_len..]; 563 | let s1 = &od1[self_len..]; 564 | 565 | (s0, s1) 566 | }; 567 | 568 | self.push_all(s0, s1); 569 | } 570 | } 571 | 572 | impl Hash for Soa2 { 573 | #[inline] 574 | fn hash(&self, state: &mut H) { 575 | self.as_slices().hash(state) 576 | } 577 | } 578 | 579 | impl PartialEq> for Soa2 580 | where A0: PartialEq, B0: PartialEq { 581 | #[inline] 582 | fn eq(&self, other: &Soa2) -> bool { 583 | let (a0, b0) = self.as_slices(); 584 | let (a1, b1) = other.as_slices(); 585 | 586 | PartialEq::eq(a0, a1) && PartialEq::eq(b0, b1) 587 | } 588 | 589 | #[inline] 590 | fn ne(&self, other: &Soa2) -> bool { 591 | let (a0, b0) = self.as_slices(); 592 | let (a1, b1) = other.as_slices(); 593 | 594 | PartialEq::ne(a0, a1) || PartialEq::ne(b0, b1) 595 | } 596 | } 597 | 598 | impl PartialEq> for Soa2 599 | where A0: PartialEq, B0: PartialEq { 600 | #[inline] 601 | fn eq(&self, other: &Vec<(A1, B1)>) -> bool { 602 | self.len() == other.len() 603 | && self.zip_iter().zip(other.iter()).all( 604 | |((a0, b0), &(ref a1, ref b1))| a0 == a1 && b0 == b1) 605 | } 606 | 607 | #[inline] 608 | fn ne(&self, other: &Vec<(A1, B1)>) -> bool { 609 | self.len() != other.len() 610 | || self.zip_iter().zip(other.iter()).any( 611 | |((a0, b0), &(ref a1, ref b1))| a0 != a1 || b0 != b1) 612 | } 613 | } 614 | 615 | impl<'b, A0, B0, A1, B1> PartialEq<&'b [(A1, B1)]> for Soa2 616 | where A0: PartialEq, B0: PartialEq { 617 | #[inline] 618 | fn eq(&self, other: &&'b [(A1, B1)]) -> bool { 619 | self.len() == other.len() 620 | && self.zip_iter().zip(other.iter()).all( 621 | |((a0, b0), &(ref a1, ref b1))| a0 == a1 && b0 == b1) 622 | } 623 | 624 | #[inline] 625 | fn ne(&self, other: &&'b [(A1, B1)]) -> bool { 626 | self.len() != other.len() 627 | || self.zip_iter().zip(other.iter()).any( 628 | |((a0, b0), &(ref a1, ref b1))| a0 != a1 || b0 != b1) 629 | } 630 | } 631 | 632 | impl<'b, A0, B0, A1, B1> PartialEq<&'b mut [(A1, B1)]> for Soa2 633 | where A0: PartialEq, B0: PartialEq { 634 | #[inline] 635 | fn eq(&self, other: &&'b mut [(A1, B1)]) -> bool { 636 | self.len() == other.len() 637 | && self.zip_iter().zip(other.iter()).all( 638 | |((a0, b0), &(ref a1, ref b1))| a0 == a1 && b0 == b1) 639 | } 640 | 641 | #[inline] 642 | fn ne(&self, other: &&'b mut [(A1, B1)]) -> bool { 643 | self.len() != other.len() 644 | || self.zip_iter().zip(other.iter()).any( 645 | |((a0, b0), &(ref a1, ref b1))| a0 != a1 || b0 != b1) 646 | } 647 | } 648 | 649 | impl PartialOrd for Soa2 { 650 | #[inline] 651 | fn partial_cmp(&self, other: &Soa2) -> Option { 652 | iter::order::partial_cmp(self.zip_iter(), other.zip_iter()) 653 | } 654 | } 655 | 656 | impl Eq for Soa2 {} 657 | 658 | impl Ord for Soa2 { 659 | #[inline] 660 | fn cmp(&self, other: &Soa2) -> Ordering { 661 | iter::order::cmp(self.zip_iter(), other.zip_iter()) 662 | } 663 | } 664 | 665 | impl Default for Soa2 { 666 | fn default() -> Soa2 { Soa2::new() } 667 | } 668 | 669 | impl Debug for Soa2 { 670 | fn fmt(&self, f: &mut Formatter) -> Result { 671 | Debug::fmt(&self.as_slices(), f) 672 | } 673 | } 674 | 675 | impl Drop for Soa2 { 676 | #[inline] 677 | fn drop(&mut self) { 678 | if self.e.cap != 0 && self.e.cap != mem::POST_DROP_USIZE { 679 | unsafe { 680 | self.d0.drop(&self.e); 681 | self.d1.drop(&self.e); 682 | } 683 | self.e.cap = 0; 684 | } 685 | } 686 | } 687 | -------------------------------------------------------------------------------- /src/soa3.rs: -------------------------------------------------------------------------------- 1 | use collections::vec; 2 | 3 | use core::cmp::Ordering; 4 | use core::default::Default; 5 | use core::fmt::{Debug, Formatter, Result}; 6 | use core::hash::{Hash, Hasher}; 7 | use core::iter::{self, repeat}; 8 | use core::mem; 9 | use core::ptr; 10 | use core::slice; 11 | 12 | use unadorned::{self, Unadorned, Extent}; 13 | 14 | /// A growable struct-of-3-arrays type, with heap allocated contents. 15 | /// 16 | /// This structure is analogous to a `Vec<(A, B, C)>`, but instead of laying out 17 | /// the tuples sequentially in memory, each row gets its own allocation. For 18 | /// example, an `Soa3` will contain three inner arrays: one of 19 | /// `f32`s, one of `i64`s, and one of `u8`. 20 | /// 21 | /// All data is aligned to 16-bytes. Feel free to do SIMD operations with array 22 | /// contents. 23 | #[unsafe_no_drop_flag] 24 | pub struct Soa3 { 25 | d0: Unadorned, 26 | d1: Unadorned, 27 | d2: Unadorned, 28 | e: Extent, 29 | } 30 | 31 | impl Soa3 { 32 | /// Constructs a new, empty `Soa3`. 33 | /// 34 | /// The SoA will not allocate until elements are pushed onto it. 35 | pub fn new() -> Soa3 { 36 | unsafe { 37 | let (d0, d0u) = Unadorned::new(); 38 | let (d1, d1u) = Unadorned::new(); 39 | let (d2, d2u) = Unadorned::new(); 40 | 41 | let e = unadorned::new_update(&[d0u, d1u, d2u]); 42 | 43 | Soa3 { d0: d0, d1: d1, d2: d2, e: e } 44 | } 45 | } 46 | 47 | /// Returns `true` if all our elements are zero-sized types. 48 | #[inline] 49 | fn is_boring(&self) -> bool { 50 | self.d0.is_boring() && self.d1.is_boring() && self.d2.is_boring() 51 | } 52 | 53 | /// Constructs a new, empty `Soa3` with the specified capacity. 54 | /// 55 | /// The SoA will be able to hold exactly `capacity` tuples of elements 56 | /// without reallocating. 57 | /// 58 | /// If `capacity` is 0, the SoA will not allocate. 59 | /// 60 | /// It is important to note that this function does not specify the *length* 61 | /// of the soa, but only the *capacity*. 62 | #[inline] 63 | pub fn with_capacity(capacity: usize) -> Soa3 { 64 | unsafe { 65 | let (d0, d0u) = Unadorned::with_capacity(capacity); 66 | let (d1, d1u) = Unadorned::with_capacity(capacity); 67 | let (d2, d2u) = Unadorned::with_capacity(capacity); 68 | 69 | let is_boring = 70 | mem::size_of::() == 0 71 | && mem::size_of::() == 0 72 | && mem::size_of::() == 0; 73 | 74 | let e = unadorned::with_capacity_update(&[d0u, d1u, d2u], is_boring, capacity); 75 | 76 | Soa3 { d0: d0, d1: d1, d2: d2, e: e } 77 | } 78 | } 79 | 80 | /// Constructs a `Soa3` directly from the raw components of another. 81 | /// 82 | /// This is highly unsafe, and no invariants are checked. 83 | #[inline] 84 | pub unsafe fn from_raw_parts( 85 | ptra: *mut A, ptrb: *mut B, ptrc: *mut C, len: usize, cap: usize) -> Soa3 { 86 | let (d0, d0u) = Unadorned::from_raw_parts(ptra); 87 | let (d1, d1u) = Unadorned::from_raw_parts(ptrb); 88 | let (d2, d2u) = Unadorned::from_raw_parts(ptrc); 89 | 90 | let e = unadorned::from_raw_parts_update(&[d0u, d1u, d2u], len, cap); 91 | 92 | Soa3 { d0: d0, d1: d1, d2: d2, e: e } 93 | } 94 | 95 | /// Constructs a `Soa3` by copying the elements from raw pointers. 96 | /// 97 | /// This function will copy `elts` contiguous elements from each of the 98 | /// pointers into a new allocation owned by the returned `Soa3`. The elements 99 | /// of the buffer are copied without cloning, as if `ptr::read()` were called 100 | /// on them. 101 | #[inline] 102 | pub unsafe fn from_raw_bufs(ptra: *const A, ptrb: *const B, ptrc: *const C, elts: usize) -> Soa3 { 103 | let (d0, d0u) = Unadorned::from_raw_bufs(ptra, elts); 104 | let (d1, d1u) = Unadorned::from_raw_bufs(ptrb, elts); 105 | let (d2, d2u) = Unadorned::from_raw_bufs(ptrc, elts); 106 | 107 | let e = unadorned::from_raw_bufs_update(&[d0u, d1u, d2u], elts); 108 | 109 | Soa3 { d0: d0, d1: d1, d2: d2, e: e } 110 | } 111 | 112 | /// Constructs a `Soa3` directly from vectors of its components. 113 | /// 114 | /// This function will panic if the lengths of the vectors don't match. 115 | /// 116 | /// If the capacity of the vectors don't match they will be reallocated to 117 | /// have matching capacities. 118 | /// 119 | /// Otherwise, no allocation will be performed and the SoA will only take 120 | /// ownership of the elements in the vectors. 121 | pub fn from_vecs(mut v0: Vec, mut v1: Vec, mut v2: Vec) -> Soa3 { 122 | assert_eq!(v0.len(), v1.len()); 123 | assert_eq!(v0.len(), v2.len()); 124 | 125 | if v0.capacity() != v1.capacity() || v0.capacity() != v2.capacity() { 126 | v0.shrink_to_fit(); 127 | v1.shrink_to_fit(); 128 | v2.shrink_to_fit(); 129 | } 130 | let len = v0.len(); 131 | let cap = v0.capacity(); 132 | 133 | unsafe { 134 | let ret = Soa3::from_raw_parts( 135 | v0.as_ptr() as *mut A, 136 | v1.as_ptr() as *mut B, 137 | v2.as_ptr() as *mut C, 138 | len, cap); 139 | mem::forget(v0); 140 | mem::forget(v1); 141 | mem::forget(v2); 142 | ret 143 | } 144 | } 145 | 146 | /// Returns the number of tuples stored in the SoA. 147 | #[inline] 148 | pub fn len(&self) -> usize { 149 | self.e.len 150 | } 151 | 152 | /// Returns `true` if the SoA contains no elements. 153 | #[inline] 154 | pub fn is_empty(&self) -> bool { 155 | self.len() == 0 156 | } 157 | 158 | /// Sets the length of a vector. 159 | /// 160 | /// This will explicitly set the size of the soa, without actually 161 | /// modifying its buffers, so it is up to the caller to ensure that the 162 | /// SoA is actually the specified size. 163 | #[inline] 164 | pub unsafe fn set_len(&mut self, len: usize) { 165 | self.e.len = len; 166 | } 167 | 168 | /// Returns the number of elements the SoA can hold without reallocating. 169 | #[inline] 170 | pub fn capacity(&self) -> usize { 171 | self.e.cap 172 | } 173 | 174 | /// Reserves capacity for at least `additional` more elements to be inserted 175 | /// in the given SoA. The collection may reserve more space to avoid frequent 176 | /// reallocations. 177 | /// 178 | /// Panics if the new capacity overflows `usize`. 179 | pub fn reserve(&mut self, additional: usize) { 180 | let space = 181 | match unadorned::calc_reserve_space(&self.e, additional) { 182 | None => return, 183 | Some(space) => space, 184 | }; 185 | 186 | unsafe { 187 | let d0u = self.d0.reserve(&self.e, &space); 188 | let d1u = self.d1.reserve(&self.e, &space); 189 | let d2u = self.d2.reserve(&self.e, &space); 190 | 191 | unadorned::reserve_update(&[d0u, d1u, d2u], space, &mut self.e); 192 | } 193 | } 194 | 195 | /// Reserves the minimum capacity for exactly `additional` more elements to 196 | /// be inserted in the given SoA. Does nothing if the capacity is already 197 | /// sufficient. 198 | /// 199 | /// Note that the allocator may give the collection more space than it 200 | /// requests. Therefore, capacity can not be relied upon to be precisely 201 | /// minimal. Prefer `reserve` if future insertions are expected. 202 | /// 203 | /// Panics if the new capacity overflows `usize`. 204 | pub fn reserve_exact(&mut self, additional: usize) { 205 | let space = 206 | match unadorned::calc_reserve_exact_space(&self.e, additional) { 207 | None => return, 208 | Some(space) => space, 209 | }; 210 | 211 | unsafe { 212 | let d0u = self.d0.reserve(&self.e, &space); 213 | let d1u = self.d1.reserve(&self.e, &space); 214 | let d2u = self.d2.reserve(&self.e, &space); 215 | 216 | unadorned::reserve_update(&[d0u, d1u, d2u], space, &mut self.e); 217 | } 218 | } 219 | 220 | /// Shrinks the capacity of the SoA as much as possible. 221 | /// 222 | /// It will drop down as close as possible to the length, but the allocator 223 | /// may still inform the SoA that there is space for a few more elements. 224 | pub fn shrink_to_fit(&mut self) { 225 | if self.is_boring() { return } 226 | 227 | unsafe { 228 | let d0u = self.d0.shrink_to_fit(&self.e); 229 | let d1u = self.d1.shrink_to_fit(&self.e); 230 | let d2u = self.d2.shrink_to_fit(&self.e); 231 | 232 | unadorned::shrink_to_fit_update(&[d0u, d1u, d2u], &mut self.e); 233 | } 234 | } 235 | 236 | /// Shorten a SoA, dropping excess elements. 237 | /// 238 | /// If `len` is greater than the soa's current length, this has no effect. 239 | pub fn truncate(&mut self, len: usize) { 240 | if self.is_boring() { return } 241 | 242 | unsafe { 243 | let d0u = self.d0.truncate(len, &self.e); 244 | let d1u = self.d1.truncate(len, &self.e); 245 | let d2u = self.d2.truncate(len, &self.e); 246 | 247 | unadorned::truncate_update(&[d0u, d1u, d2u], len, &mut self.e); 248 | } 249 | } 250 | 251 | /// Returns mutable slices over the SoA's elements. 252 | #[inline] 253 | pub fn as_mut_slices<'a>(&'a mut self) -> (&'a mut [A], &'a mut [B], &'a mut [C]) { 254 | unsafe { 255 | let len = self.e.len; 256 | (self.d0.as_mut_slice(len), 257 | self.d1.as_mut_slice(len), 258 | self.d2.as_mut_slice(len)) 259 | } 260 | } 261 | 262 | /// Returns slices over the SoA's elements. 263 | #[inline] 264 | pub fn as_slices<'a>(&'a self) -> (&'a [A], &'a [B], &'a [C]) { 265 | unsafe { 266 | let len = self.e.len; 267 | (self.d0.as_slice(len), 268 | self.d1.as_slice(len), 269 | self.d2.as_slice(len)) 270 | } 271 | } 272 | 273 | /// Returns iterators over the SoA's elements. 274 | #[inline] 275 | pub fn iters(&self) -> (slice::Iter, slice::Iter, slice::Iter) { 276 | let (d0, d1, d2) = self.as_slices(); 277 | (d0.iter(), d1.iter(), d2.iter()) 278 | } 279 | 280 | /// Returns a single iterator over the SoA's elements, zipped up. 281 | #[inline] 282 | pub fn zip_iter<'a>(&'a self) -> iter::Map, slice::Iter<'a, B>>, slice::Iter<'a, C>>, fn(((&'a A, &'a B), &'a C)) -> (&'a A, &'a B, &'a C)> { 283 | let (d0, d1, d2) = self.iters(); 284 | fn repack(((x, y), z): ((A, B), C)) -> (A, B, C) { (x, y, z) } 285 | let repack: fn(((&'a A, &'a B), &'a C)) -> (&'a A, &'a B, &'a C) = repack; 286 | d0.zip(d1).zip(d2).map(repack) 287 | } 288 | 289 | /// Returns mutable iterators over the SoA's elements. 290 | #[inline] 291 | pub fn iters_mut(&mut self) -> (slice::IterMut, slice::IterMut, slice::IterMut) { 292 | let (d0, d1, d2) = self.as_mut_slices(); 293 | (d0.iter_mut(), d1.iter_mut(), d2.iter_mut()) 294 | } 295 | 296 | /// Returns a single iterator over the SoA's elements, zipped up. 297 | #[inline] 298 | pub fn zip_iter_mut<'a>(&'a mut self) -> iter::Map, slice::IterMut<'a, B>>, slice::IterMut<'a, C>>, fn(((&'a mut A, &'a mut B), &'a mut C)) -> (&'a mut A, &'a mut B, &'a mut C)> { 299 | let (d0, d1, d2) = self.iters_mut(); 300 | fn repack(((x, y), z): ((A, B), C)) -> (A, B, C) { (x, y, z) } 301 | let repack: fn(((&'a mut A, &'a mut B), &'a mut C)) -> (&'a mut A, &'a mut B, &'a mut C) = repack; 302 | d0.zip(d1).zip(d2).map(repack) 303 | } 304 | 305 | /// Converts an SoA into iterators for each of its arrays. 306 | #[inline] 307 | pub fn into_iters(mut self) -> (vec::IntoIter, vec::IntoIter, vec::IntoIter) { 308 | unsafe { 309 | let e_copy = self.e; 310 | self.e.cap = 0; // Will skip the drop. into_iter will handle it. 311 | (self.d0.shallow_copy().into_iter(&e_copy), 312 | self.d1.shallow_copy().into_iter(&e_copy), 313 | self.d2.shallow_copy().into_iter(&e_copy)) 314 | } 315 | } 316 | 317 | /// Converts an SoA into `Vec`s. This will neither allocator nor copy. 318 | #[inline] 319 | pub fn into_vecs(mut self) -> (Vec, Vec, Vec) { 320 | unsafe { 321 | let e_copy = self.e; 322 | self.e.cap = 0; 323 | (self.d0.shallow_copy().as_vec(&e_copy), 324 | self.d1.shallow_copy().as_vec(&e_copy), 325 | self.d2.shallow_copy().as_vec(&e_copy)) 326 | } 327 | } 328 | 329 | /// Returns to the start of the data in an SoA. 330 | #[inline] 331 | pub fn as_ptrs(&self) -> (*const A, *const B, *const C) { 332 | (self.d0.as_ptr(), 333 | self.d1.as_ptr(), 334 | self.d2.as_ptr()) 335 | } 336 | 337 | /// Returns a pair of pointers to the start of the mutable data in an SoA. 338 | #[inline] 339 | pub fn as_mut_ptrs(&mut self) -> (*mut A, *mut B, *mut C) { 340 | (self.d0.as_mut_ptr(), 341 | self.d1.as_mut_ptr(), 342 | self.d2.as_mut_ptr()) 343 | } 344 | 345 | /// Removes an element from anywhere in the SoA and returns it, replacing it 346 | /// with the last element. 347 | /// 348 | /// This does not preserve ordering, but is O(1). 349 | /// 350 | /// Panics if `index` is out of bounds. 351 | #[inline] 352 | pub fn swap_remove(&mut self, index: usize) -> (A, B, C) { 353 | let length = self.e.len; 354 | { 355 | let (d0, d1, d2) = self.as_mut_slices(); 356 | d0.swap(index, length - 1); 357 | d1.swap(index, length - 1); 358 | d2.swap(index, length - 1); 359 | } 360 | self.pop().unwrap() 361 | } 362 | 363 | /// Inserts an element at position `index` within the vector, shifting all 364 | /// elements after position `index` one position to the right. 365 | /// 366 | /// Panics if `index` is not between `0` and the SoA's length, inclusive. 367 | pub fn insert(&mut self, index: usize, element: (A, B, C)) { 368 | unsafe { 369 | assert!(index < self.e.len); 370 | 371 | let space = unadorned::calc_reserve_space(&self.e, 1); 372 | 373 | let d0u = self.d0.insert(index, element.0, &self.e, &space); 374 | let d1u = self.d1.insert(index, element.1, &self.e, &space); 375 | let d2u = self.d2.insert(index, element.2, &self.e, &space); 376 | 377 | unadorned::insert_update(&[d0u, d1u, d2u], space, &mut self.e); 378 | } 379 | } 380 | 381 | /// Removes and returns the elements at position `index` within the SoA, 382 | /// shifting all elements after position `index` one position to the left. 383 | /// 384 | /// Panics if `index` is out of bounds. 385 | pub fn remove(&mut self, index: usize) -> (A, B, C) { 386 | unsafe { 387 | assert!(index < self.e.len); 388 | 389 | let (x0, d0u) = self.d0.remove(index, &self.e); 390 | let (x1, d1u) = self.d1.remove(index, &self.e); 391 | let (x2, d2u) = self.d2.remove(index, &self.e); 392 | 393 | unadorned::remove_update(&[d0u, d1u, d2u], &mut self.e); 394 | (x0, x1, x2) 395 | } 396 | } 397 | 398 | /// Returns only the element specified by the predicate. 399 | /// 400 | /// In other words, remove all elements `e` such that `f(&e)` returns false. 401 | /// This method operates in place and preserves the order of the retained 402 | /// elements. 403 | pub fn retain(&mut self, mut f: F) where F: FnMut((&A, &B, &C)) -> bool { 404 | let len = self.len(); 405 | let mut del = 0; 406 | 407 | { 408 | let (d0, d1, d2) = self.as_mut_slices(); 409 | 410 | for i in 0..len { 411 | if !f((&d0[i], &d1[i], &d2[i])) { 412 | del += 1; 413 | } else if del > 0 { 414 | d0.swap(i-del, i); 415 | d1.swap(i-del, i); 416 | d2.swap(i-del, i); 417 | } 418 | } 419 | } 420 | 421 | self.truncate(len - del); 422 | } 423 | 424 | /// Appends an element to the back of a collection. 425 | /// 426 | /// Panics if the number of elements in the SoA overflows a `usize`. 427 | #[inline] 428 | pub fn push(&mut self, value: (A, B, C)) { 429 | if self.is_boring() { 430 | // zero-size types consume no memory, so we can't rely on the 431 | // address space running out 432 | self.e.len = self.e.len.checked_add(1).expect("length overflow"); 433 | unsafe { mem::forget(value) } 434 | return 435 | } 436 | 437 | unsafe { 438 | let d0u = self.d0.push(value.0, &self.e); 439 | let d1u = self.d1.push(value.1, &self.e); 440 | let d2u = self.d2.push(value.2, &self.e); 441 | 442 | unadorned::push_update(&[d0u, d1u, d2u], &mut self.e); 443 | } 444 | } 445 | 446 | /// Removes the last element from a SoA and returns it, or `None` if empty. 447 | #[inline] 448 | pub fn pop(&mut self) -> Option<(A, B, C)> { 449 | if self.e.len == 0 { 450 | None 451 | } else { 452 | unsafe { 453 | self.e.len -= 1; 454 | let len = self.e.len; 455 | 456 | let (d0, d1, d2) = self.as_mut_slices(); 457 | 458 | Some((ptr::read(d0.get_unchecked(len)), 459 | ptr::read(d1.get_unchecked(len)), 460 | ptr::read(d2.get_unchecked(len)))) 461 | } 462 | } 463 | } 464 | 465 | /// Moves all the elements of `other` into `self`, leaving `other` empty. 466 | /// 467 | /// Panics if the number of elements in the SoA overflows a `usize`. 468 | #[inline] 469 | pub fn append(&mut self, other: &mut Self) { 470 | if self.is_boring() { 471 | // zero-size types consume no memory, so we can't rely on the address 472 | // space running out 473 | self.e.len = self.e.len.checked_add(other.len()).expect("length overflow"); 474 | other.e.len = 0; 475 | return; 476 | } 477 | 478 | unsafe { 479 | let space = unadorned::calc_reserve_space(&self.e, 1); 480 | 481 | let d0u = self.d0.append(&self.e, &other.d0, &other.e, &space); 482 | let d1u = self.d1.append(&self.e, &other.d1, &other.e, &space); 483 | let d2u = self.d2.append(&self.e, &other.d2, &other.e, &space); 484 | 485 | unadorned::append_update(&[d0u, d1u, d2u], &mut self.e, &mut other.e, space); 486 | } 487 | } 488 | 489 | // TODO: drain 490 | 491 | /// Clears the SoA, removing all values. 492 | #[inline] 493 | pub fn clear(&mut self) { 494 | self.truncate(0); 495 | } 496 | 497 | // TODO: map_in_place 498 | 499 | /// Extends the SoA with the elements yielded by arbitrary iterators. 500 | /// 501 | /// Panics (and leaks memory!) if the iterators yield a different number of 502 | /// elements. 503 | pub fn extend(&mut self, i0: I0, i1: I1, i2: I2) 504 | where I0: Iterator, I1: Iterator, I2: Iterator { 505 | unsafe { 506 | let (lower, _) = i0.size_hint(); 507 | let space = unadorned::calc_reserve_space(&self.e, lower); 508 | 509 | let d0u = self.d0.extend(&self.e, &space, i0); 510 | let d1u = self.d1.extend(&self.e, &space, i1); 511 | let d2u = self.d2.extend(&self.e, &space, i2); 512 | 513 | unadorned::extend_update(&[d0u, d1u, d2u], &mut self.e); 514 | } 515 | } 516 | 517 | /// Constructs an `Soa3` with elements yielded by arbitrary iterators. 518 | /// 519 | /// Panics (and leaks memory!) if the iterators yield a different number of 520 | /// elements. 521 | pub fn from_iters(i0: I0, i1: I1, i2: I2) -> Soa3 522 | where I0: Iterator, I1: Iterator, I2: Iterator { 523 | let mut v = Soa3::new(); 524 | v.extend(i0, i1, i2); 525 | v 526 | } 527 | 528 | // TODO: dedup 529 | } 530 | 531 | impl Soa3 { 532 | /// Resizes the SoA in-place so that `len()` is equal to `new_len`. 533 | /// 534 | /// Calls either `extend()` or `truncate()` depending on whether `new_len` is 535 | /// larger than the current value of `len()` or not. 536 | #[inline] 537 | pub fn resize(&mut self, new_len: usize, value: (A, B, C)) { 538 | let len = self.len(); 539 | 540 | if new_len > len { 541 | self.extend( 542 | repeat(value.0).take(new_len - len), 543 | repeat(value.1).take(new_len - len), 544 | repeat(value.2).take(new_len - len)); 545 | } else { 546 | self.truncate(new_len); 547 | } 548 | } 549 | 550 | /// Appends all elements in slices to the SoA. 551 | /// 552 | /// Iterates over the slices, clones each element, and then appends them to 553 | /// this SoA. The slices are traversed one at a time, in order. 554 | /// 555 | /// Panics if the slices are of different lengths. 556 | #[inline] 557 | pub fn push_all(&mut self, x0: &[A], x1: &[B], x2: &[C]) { 558 | unsafe { 559 | assert_eq!(x0.len(), x1.len()); 560 | assert_eq!(x0.len(), x2.len()); 561 | 562 | let space = unadorned::calc_reserve_space(&self.e, x0.len()); 563 | 564 | let d0u = self.d0.push_all(x0, &self.e, &space); 565 | let d1u = self.d1.push_all(x1, &self.e, &space); 566 | let d2u = self.d2.push_all(x2, &self.e, &space); 567 | 568 | unadorned::push_all_update(&[d0u, d1u, d2u], &mut self.e, x0.len(), space); 569 | } 570 | } 571 | } 572 | 573 | impl Clone for Soa3 { 574 | #[inline] 575 | fn clone(&self) -> Soa3 { 576 | let mut ret = Soa3::new(); 577 | let (d0, d1, d2) = self.as_slices(); 578 | ret.push_all(d0, d1, d2); 579 | ret 580 | } 581 | 582 | fn clone_from(&mut self, other: &Soa3) { 583 | // TODO: cleanup 584 | 585 | if self.len() > other.len() { 586 | self.truncate(other.len()); 587 | } 588 | 589 | let (od0, od1, od2) = other.as_slices(); 590 | 591 | let (s0, s1, s2) = { 592 | let self_len = self.len(); 593 | let (sd0, sd1, sd2) = self.iters_mut(); 594 | 595 | for (place, thing) in sd0.zip(od0.iter()) { 596 | place.clone_from(thing); 597 | } 598 | 599 | for (place, thing) in sd1.zip(od1.iter()) { 600 | place.clone_from(thing); 601 | } 602 | 603 | for (place, thing) in sd2.zip(od2.iter()) { 604 | place.clone_from(thing); 605 | } 606 | 607 | let s0 = &od0[self_len..]; 608 | let s1 = &od1[self_len..]; 609 | let s2 = &od2[self_len..]; 610 | 611 | (s0, s1, s2) 612 | }; 613 | 614 | self.push_all(s0, s1, s2); 615 | } 616 | } 617 | 618 | impl Hash for Soa3 { 619 | #[inline] 620 | fn hash(&self, state: &mut H) { 621 | self.as_slices().hash(state) 622 | } 623 | } 624 | 625 | impl PartialEq> for Soa3 626 | where A0: PartialEq, B0: PartialEq, C0: PartialEq { 627 | #[inline] 628 | fn eq(&self, other: &Soa3) -> bool { 629 | let (a0, b0, c0) = self.as_slices(); 630 | let (a1, b1, c1) = other.as_slices(); 631 | 632 | PartialEq::eq(a0, a1) && PartialEq::eq(b0, b1) && PartialEq::eq(c0, c1) 633 | } 634 | 635 | #[inline] 636 | fn ne(&self, other: &Soa3) -> bool { 637 | let (a0, b0, c0) = self.as_slices(); 638 | let (a1, b1, c1) = other.as_slices(); 639 | 640 | PartialEq::ne(a0, a1) || PartialEq::ne(b0, b1) || PartialEq::ne(c0, c1) 641 | } 642 | } 643 | 644 | impl PartialEq> for Soa3 645 | where A0: PartialEq, B0: PartialEq, C0: PartialEq { 646 | #[inline] 647 | fn eq(&self, other: &Vec<(A1, B1, C1)>) -> bool { 648 | self.len() == other.len() 649 | && self.zip_iter().zip(other.iter()).all( 650 | |((a0, b0, c0), &(ref a1, ref b1, ref c1))| a0 == a1 && b0 == b1 && c0 == c1) 651 | } 652 | 653 | #[inline] 654 | fn ne(&self, other: &Vec<(A1, B1, C1)>) -> bool { 655 | self.len() != other.len() 656 | || self.zip_iter().zip(other.iter()).any( 657 | |((a0, b0, c0), &(ref a1, ref b1, ref c1))| a0 != a1 || b0 != b1 || c0 != c1) 658 | } 659 | } 660 | 661 | impl<'b, A0, B0, C0, A1, B1, C1> PartialEq<&'b [(A1, B1, C1)]> for Soa3 662 | where A0: PartialEq, B0: PartialEq, C0: PartialEq { 663 | #[inline] 664 | fn eq(&self, other: &&'b [(A1, B1, C1)]) -> bool { 665 | self.len() == other.len() 666 | && self.zip_iter().zip(other.iter()).all( 667 | |((a0, b0, c0), &(ref a1, ref b1, ref c1))| a0 == a1 && b0 == b1 && c0 == c1) 668 | } 669 | 670 | #[inline] 671 | fn ne(&self, other: &&'b [(A1, B1, C1)]) -> bool { 672 | self.len() != other.len() 673 | || self.zip_iter().zip(other.iter()).any( 674 | |((a0, b0, c0), &(ref a1, ref b1, ref c1))| a0 != a1 || b0 != b1 || c0 != c1) 675 | } 676 | } 677 | 678 | impl<'b, A0, B0, C0, A1, B1, C1> PartialEq<&'b mut [(A1, B1, C1)]> for Soa3 679 | where A0: PartialEq, B0: PartialEq, C0: PartialEq { 680 | #[inline] 681 | fn eq(&self, other: &&'b mut [(A1, B1, C1)]) -> bool { 682 | self.len() == other.len() 683 | && self.zip_iter().zip(other.iter()).all( 684 | |((a0, b0, c0), &(ref a1, ref b1, ref c1))| a0 == a1 && b0 == b1 && c0 == c1) 685 | } 686 | 687 | #[inline] 688 | fn ne(&self, other: &&'b mut [(A1, B1, C1)]) -> bool { 689 | self.len() != other.len() 690 | || self.zip_iter().zip(other.iter()).any( 691 | |((a0, b0, c0), &(ref a1, ref b1, ref c1))| a0 != a1 || b0 != b1 || c0 != c1) 692 | } 693 | } 694 | 695 | impl PartialOrd for Soa3 { 696 | #[inline] 697 | fn partial_cmp(&self, other: &Soa3) -> Option { 698 | iter::order::partial_cmp(self.zip_iter(), other.zip_iter()) 699 | } 700 | } 701 | 702 | impl Eq for Soa3 {} 703 | 704 | impl Ord for Soa3 { 705 | #[inline] 706 | fn cmp(&self, other: &Soa3) -> Ordering { 707 | iter::order::cmp(self.zip_iter(), other.zip_iter()) 708 | } 709 | } 710 | 711 | impl Default for Soa3 { 712 | fn default() -> Soa3 { Soa3::new() } 713 | } 714 | 715 | impl Debug for Soa3 { 716 | fn fmt(&self, f: &mut Formatter) -> Result { 717 | Debug::fmt(&self.as_slices(), f) 718 | } 719 | } 720 | 721 | impl Drop for Soa3 { 722 | #[inline] 723 | fn drop(&mut self) { 724 | if self.e.cap != 0 && self.e.cap != mem::POST_DROP_USIZE { 725 | unsafe { 726 | self.d0.drop(&self.e); 727 | self.d1.drop(&self.e); 728 | self.d2.drop(&self.e); 729 | } 730 | self.e.cap = 0; 731 | } 732 | } 733 | } 734 | -------------------------------------------------------------------------------- /src/soa4.rs: -------------------------------------------------------------------------------- 1 | use collections::vec; 2 | 3 | use core::cmp::Ordering; 4 | use core::default::Default; 5 | use core::fmt::{Debug, Formatter, Result}; 6 | use core::hash::{Hash, Hasher}; 7 | use core::iter::{self, repeat}; 8 | use core::mem; 9 | use core::ptr; 10 | use core::slice; 11 | 12 | use unadorned::{self, Unadorned, Extent}; 13 | 14 | /// A growable struct-of-4-arrays type, with heap allocated contents. 15 | /// 16 | /// This structure is analogous to a `Vec<(A, B, C, D)>`, but instead of laying out 17 | /// the tuples sequentially in memory, each row gets its own allocation. For 18 | /// example, an `Soa4` will contain four inner arrays: one of 19 | /// `f32`s, one of `i64`s, one of `u8`, and one of `u16`. 20 | /// 21 | /// All data is aligned to 16-bytes. Feel free to do SIMD operations with array 22 | /// contents. 23 | #[unsafe_no_drop_flag] 24 | pub struct Soa4 { 25 | d0: Unadorned, 26 | d1: Unadorned, 27 | d2: Unadorned, 28 | d3: Unadorned, 29 | e: Extent, 30 | } 31 | 32 | impl Soa4 { 33 | /// Constructs a new, empty `Soa4`. 34 | /// 35 | /// The SoA will not allocate until elements are pushed onto it. 36 | pub fn new() -> Soa4 { 37 | unsafe { 38 | let (d0, d0u) = Unadorned::new(); 39 | let (d1, d1u) = Unadorned::new(); 40 | let (d2, d2u) = Unadorned::new(); 41 | let (d3, d3u) = Unadorned::new(); 42 | 43 | let e = unadorned::new_update(&[d0u, d1u, d2u, d3u]); 44 | 45 | Soa4 { d0: d0, d1: d1, d2: d2, d3: d3, e: e } 46 | } 47 | } 48 | 49 | /// Returns `true` if all our elements are zero-sized types. 50 | #[inline] 51 | fn is_boring(&self) -> bool { 52 | self.d0.is_boring() 53 | && self.d1.is_boring() 54 | && self.d2.is_boring() 55 | && self.d3.is_boring() 56 | } 57 | 58 | /// Constructs a new, empty `Soa4` with the specified capacity. 59 | /// 60 | /// The SoA will be able to hold exactly `capacity` tuples of elements 61 | /// without reallocating. 62 | /// 63 | /// If `capacity` is 0, the SoA will not allocate. 64 | /// 65 | /// It is important to note that this function does not specify the *length* 66 | /// of the soa, but only the *capacity*. 67 | #[inline] 68 | pub fn with_capacity(capacity: usize) -> Soa4 { 69 | unsafe { 70 | let (d0, d0u) = Unadorned::with_capacity(capacity); 71 | let (d1, d1u) = Unadorned::with_capacity(capacity); 72 | let (d2, d2u) = Unadorned::with_capacity(capacity); 73 | let (d3, d3u) = Unadorned::with_capacity(capacity); 74 | 75 | let is_boring = 76 | mem::size_of::() == 0 77 | && mem::size_of::() == 0 78 | && mem::size_of::() == 0 79 | && mem::size_of::() == 0; 80 | 81 | let e = unadorned::with_capacity_update(&[d0u, d1u, d2u, d3u], is_boring, capacity); 82 | 83 | Soa4 { d0: d0, d1: d1, d2: d2, d3: d3, e: e } 84 | } 85 | } 86 | 87 | /// Constructs a `Soa4` directly from the raw components of another. 88 | /// 89 | /// This is highly unsafe, and no invariants are checked. 90 | #[inline] 91 | pub unsafe fn from_raw_parts( 92 | ptra: *mut A, ptrb: *mut B, ptrc: *mut C, ptrd: *mut D, len: usize, cap: usize) -> Soa4 { 93 | let (d0, d0u) = Unadorned::from_raw_parts(ptra); 94 | let (d1, d1u) = Unadorned::from_raw_parts(ptrb); 95 | let (d2, d2u) = Unadorned::from_raw_parts(ptrc); 96 | let (d3, d3u) = Unadorned::from_raw_parts(ptrd); 97 | 98 | let e = unadorned::from_raw_parts_update(&[d0u, d1u, d2u, d3u], len, cap); 99 | 100 | Soa4 { d0: d0, d1: d1, d2: d2, d3: d3, e: e } 101 | } 102 | 103 | /// Constructs a `Soa4` by copying the elements from raw pointers. 104 | /// 105 | /// This function will copy `elts` contiguous elements from each of the 106 | /// pointers into a new allocation owned by the returned `Soa4`. The elements 107 | /// of the buffer are copied without cloning, as if `ptr::read()` were called 108 | /// on them. 109 | #[inline] 110 | pub unsafe fn from_raw_bufs(ptra: *const A, ptrb: *const B, ptrc: *const C, ptrd: *const D, elts: usize) -> Soa4 { 111 | let (d0, d0u) = Unadorned::from_raw_bufs(ptra, elts); 112 | let (d1, d1u) = Unadorned::from_raw_bufs(ptrb, elts); 113 | let (d2, d2u) = Unadorned::from_raw_bufs(ptrc, elts); 114 | let (d3, d3u) = Unadorned::from_raw_bufs(ptrd, elts); 115 | 116 | let e = unadorned::from_raw_bufs_update(&[d0u, d1u, d2u, d3u], elts); 117 | 118 | Soa4 { d0: d0, d1: d1, d2: d2, d3: d3, e: e } 119 | } 120 | 121 | /// Constructs a `Soa4` directly from vectors of its components. 122 | /// 123 | /// This function will panic if the lengths of the vectors don't match. 124 | /// 125 | /// If the capacity of the vectors don't match they will be reallocated to 126 | /// have matching capacities. 127 | /// 128 | /// Otherwise, no allocation will be performed and the SoA will only take 129 | /// ownership of the elements in the vectors. 130 | pub fn from_vecs(mut v0: Vec, mut v1: Vec, mut v2: Vec, mut v3: Vec) -> Soa4 { 131 | assert_eq!(v0.len(), v1.len()); 132 | assert_eq!(v0.len(), v2.len()); 133 | assert_eq!(v0.len(), v3.len()); 134 | 135 | if v0.capacity() != v1.capacity() || v0.capacity() != v2.capacity() || v0.capacity() != v3.capacity() { 136 | v0.shrink_to_fit(); 137 | v1.shrink_to_fit(); 138 | v2.shrink_to_fit(); 139 | v3.shrink_to_fit(); 140 | } 141 | let len = v0.len(); 142 | let cap = v0.capacity(); 143 | 144 | unsafe { 145 | let ret = Soa4::from_raw_parts( 146 | v0.as_ptr() as *mut A, 147 | v1.as_ptr() as *mut B, 148 | v2.as_ptr() as *mut C, 149 | v3.as_ptr() as *mut D, 150 | len, cap); 151 | mem::forget(v0); 152 | mem::forget(v1); 153 | mem::forget(v2); 154 | mem::forget(v3); 155 | ret 156 | } 157 | } 158 | 159 | /// Returns the number of tuples stored in the SoA. 160 | #[inline] 161 | pub fn len(&self) -> usize { 162 | self.e.len 163 | } 164 | 165 | /// Returns `true` if the SoA contains no elements. 166 | #[inline] 167 | pub fn is_empty(&self) -> bool { 168 | self.len() == 0 169 | } 170 | 171 | /// Sets the length of a vector. 172 | /// 173 | /// This will explicitly set the size of the soa, without actually 174 | /// modifying its buffers, so it is up to the caller to ensure that the 175 | /// SoA is actually the specified size. 176 | #[inline] 177 | pub unsafe fn set_len(&mut self, len: usize) { 178 | self.e.len = len; 179 | } 180 | 181 | /// Returns the number of elements the SoA can hold without reallocating. 182 | #[inline] 183 | pub fn capacity(&self) -> usize { 184 | self.e.cap 185 | } 186 | 187 | /// Reserves capacity for at least `additional` more elements to be inserted 188 | /// in the given SoA. The collection may reserve more space to avoid frequent 189 | /// reallocations. 190 | /// 191 | /// Panics if the new capacity overflows `usize`. 192 | pub fn reserve(&mut self, additional: usize) { 193 | let space = 194 | match unadorned::calc_reserve_space(&self.e, additional) { 195 | None => return, 196 | Some(space) => space, 197 | }; 198 | 199 | unsafe { 200 | let d0u = self.d0.reserve(&self.e, &space); 201 | let d1u = self.d1.reserve(&self.e, &space); 202 | let d2u = self.d2.reserve(&self.e, &space); 203 | let d3u = self.d3.reserve(&self.e, &space); 204 | 205 | unadorned::reserve_update(&[d0u, d1u, d2u, d3u], space, &mut self.e); 206 | } 207 | } 208 | 209 | /// Reserves the minimum capacity for exactly `additional` more elements to 210 | /// be inserted in the given SoA. Does nothing if the capacity is already 211 | /// sufficient. 212 | /// 213 | /// Note that the allocator may give the collection more space than it 214 | /// requests. Therefore, capacity can not be relied upon to be precisely 215 | /// minimal. Prefer `reserve` if future insertions are expected. 216 | /// 217 | /// Panics if the new capacity overflows `usize`. 218 | pub fn reserve_exact(&mut self, additional: usize) { 219 | let space = 220 | match unadorned::calc_reserve_exact_space(&self.e, additional) { 221 | None => return, 222 | Some(space) => space, 223 | }; 224 | 225 | unsafe { 226 | let d0u = self.d0.reserve(&self.e, &space); 227 | let d1u = self.d1.reserve(&self.e, &space); 228 | let d2u = self.d2.reserve(&self.e, &space); 229 | let d3u = self.d3.reserve(&self.e, &space); 230 | 231 | unadorned::reserve_update(&[d0u, d1u, d2u, d3u], space, &mut self.e); 232 | } 233 | } 234 | 235 | /// Shrinks the capacity of the SoA as much as possible. 236 | /// 237 | /// It will drop down as close as possible to the length, but the allocator 238 | /// may still inform the SoA that there is space for a few more elements. 239 | pub fn shrink_to_fit(&mut self) { 240 | if self.is_boring() { return } 241 | 242 | unsafe { 243 | let d0u = self.d0.shrink_to_fit(&self.e); 244 | let d1u = self.d1.shrink_to_fit(&self.e); 245 | let d2u = self.d2.shrink_to_fit(&self.e); 246 | let d3u = self.d3.shrink_to_fit(&self.e); 247 | 248 | unadorned::shrink_to_fit_update(&[d0u, d1u, d2u, d3u], &mut self.e); 249 | } 250 | } 251 | 252 | /// Shorten a SoA, dropping excess elements. 253 | /// 254 | /// If `len` is greater than the soa's current length, this has no effect. 255 | pub fn truncate(&mut self, len: usize) { 256 | if self.is_boring() { return } 257 | 258 | unsafe { 259 | let d0u = self.d0.truncate(len, &self.e); 260 | let d1u = self.d1.truncate(len, &self.e); 261 | let d2u = self.d2.truncate(len, &self.e); 262 | let d3u = self.d3.truncate(len, &self.e); 263 | 264 | unadorned::truncate_update(&[d0u, d1u, d2u, d3u], len, &mut self.e); 265 | } 266 | } 267 | 268 | /// Returns mutable slices over the SoA's elements. 269 | #[inline] 270 | pub fn as_mut_slices<'a>(&'a mut self) -> (&'a mut [A], &'a mut [B], &'a mut [C], &'a mut [D]) { 271 | unsafe { 272 | let len = self.e.len; 273 | (self.d0.as_mut_slice(len), 274 | self.d1.as_mut_slice(len), 275 | self.d2.as_mut_slice(len), 276 | self.d3.as_mut_slice(len)) 277 | } 278 | } 279 | 280 | /// Returns slices over the SoA's elements. 281 | #[inline] 282 | pub fn as_slices<'a>(&'a self) -> (&'a [A], &'a [B], &'a [C], &'a [D]) { 283 | unsafe { 284 | let len = self.e.len; 285 | (self.d0.as_slice(len), 286 | self.d1.as_slice(len), 287 | self.d2.as_slice(len), 288 | self.d3.as_slice(len)) 289 | } 290 | } 291 | 292 | /// Returns iterators over the SoA's elements. 293 | #[inline] 294 | pub fn iters(&self) -> (slice::Iter, slice::Iter, slice::Iter, slice::Iter) { 295 | let (d0, d1, d2, d3) = self.as_slices(); 296 | (d0.iter(), d1.iter(), d2.iter(), d3.iter()) 297 | } 298 | 299 | /// Returns a single iterator over the SoA's elements, zipped up. 300 | #[inline] 301 | pub fn zip_iter<'a>(&'a self) -> iter::Map, slice::Iter<'a, B>>, slice::Iter<'a, C>>, slice::Iter<'a, D>>, fn((((&'a A, &'a B), &'a C), &'a D)) -> (&'a A, &'a B, &'a C, &'a D)> { 302 | let (d0, d1, d2, d3) = self.iters(); 303 | fn repack((((w, x), y), z): (((A, B), C), D)) -> (A, B, C, D) { (w, x, y, z) } 304 | let repack: fn((((&'a A, &'a B), &'a C), &'a D)) -> (&'a A, &'a B, &'a C, &'a D) = repack; 305 | d0.zip(d1).zip(d2).zip(d3).map(repack) 306 | } 307 | 308 | /// Returns mutable iterators over the SoA's elements. 309 | #[inline] 310 | pub fn iters_mut(&mut self) -> (slice::IterMut, slice::IterMut, slice::IterMut, slice::IterMut) { 311 | let (d0, d1, d2, d3) = self.as_mut_slices(); 312 | (d0.iter_mut(), d1.iter_mut(), d2.iter_mut(), d3.iter_mut()) 313 | } 314 | 315 | /// Returns a single iterator over the SoA's elements, zipped up. 316 | #[inline] 317 | pub fn zip_iter_mut<'a>(&'a mut self) -> iter::Map, slice::IterMut<'a, B>>, slice::IterMut<'a, C>>, slice::IterMut<'a, D>>, fn((((&'a mut A, &'a mut B), &'a mut C), &'a mut D)) -> (&'a mut A, &'a mut B, &'a mut C, &'a mut D)> { 318 | let (d0, d1, d2, d3) = self.iters_mut(); 319 | fn repack((((w, x), y), z): (((A, B), C), D)) -> (A, B, C, D) { (w, x, y, z) } 320 | let repack: fn((((&'a mut A, &'a mut B), &'a mut C), &'a mut D)) -> (&'a mut A, &'a mut B, &'a mut C, &'a mut D) = repack; 321 | d0.zip(d1).zip(d2).zip(d3).map(repack) 322 | } 323 | 324 | /// Converts an SoA into iterators for each of its arrays. 325 | #[inline] 326 | pub fn into_iters(mut self) -> (vec::IntoIter, vec::IntoIter, vec::IntoIter, vec::IntoIter) { 327 | unsafe { 328 | let e_copy = self.e; 329 | self.e.cap = 0; // Will skip the drop. into_iter will handle it. 330 | (self.d0.shallow_copy().into_iter(&e_copy), 331 | self.d1.shallow_copy().into_iter(&e_copy), 332 | self.d2.shallow_copy().into_iter(&e_copy), 333 | self.d3.shallow_copy().into_iter(&e_copy)) 334 | } 335 | } 336 | 337 | /// Converts an SoA into `Vec`s. This will neither allocator nor copy. 338 | #[inline] 339 | pub fn into_vecs(mut self) -> (Vec, Vec, Vec, Vec) { 340 | unsafe { 341 | let e_copy = self.e; 342 | self.e.cap = 0; 343 | (self.d0.shallow_copy().as_vec(&e_copy), 344 | self.d1.shallow_copy().as_vec(&e_copy), 345 | self.d2.shallow_copy().as_vec(&e_copy), 346 | self.d3.shallow_copy().as_vec(&e_copy)) 347 | } 348 | } 349 | 350 | /// Returns to the start of the data in an SoA. 351 | #[inline] 352 | pub fn as_ptrs(&self) -> (*const A, *const B, *const C, *const D) { 353 | (self.d0.as_ptr(), 354 | self.d1.as_ptr(), 355 | self.d2.as_ptr(), 356 | self.d3.as_ptr()) 357 | } 358 | 359 | /// Returns a pair of pointers to the start of the mutable data in an SoA. 360 | #[inline] 361 | pub fn as_mut_ptrs(&mut self) -> (*mut A, *mut B, *mut C, *mut D) { 362 | (self.d0.as_mut_ptr(), 363 | self.d1.as_mut_ptr(), 364 | self.d2.as_mut_ptr(), 365 | self.d3.as_mut_ptr()) 366 | } 367 | 368 | /// Removes an element from anywhere in the SoA and returns it, replacing it 369 | /// with the last element. 370 | /// 371 | /// This does not preserve ordering, but is O(1). 372 | /// 373 | /// Panics if `index` is out of bounds. 374 | #[inline] 375 | pub fn swap_remove(&mut self, index: usize) -> (A, B, C, D) { 376 | let length = self.e.len; 377 | { 378 | let (d0, d1, d2, d3) = self.as_mut_slices(); 379 | d0.swap(index, length - 1); 380 | d1.swap(index, length - 1); 381 | d2.swap(index, length - 1); 382 | d3.swap(index, length - 1); 383 | } 384 | self.pop().unwrap() 385 | } 386 | 387 | /// Inserts an element at position `index` within the vector, shifting all 388 | /// elements after position `index` one position to the right. 389 | /// 390 | /// Panics if `index` is not between `0` and the SoA's length, inclusive. 391 | pub fn insert(&mut self, index: usize, element: (A, B, C, D)) { 392 | unsafe { 393 | assert!(index < self.e.len); 394 | 395 | let space = unadorned::calc_reserve_space(&self.e, 1); 396 | 397 | let d0u = self.d0.insert(index, element.0, &self.e, &space); 398 | let d1u = self.d1.insert(index, element.1, &self.e, &space); 399 | let d2u = self.d2.insert(index, element.2, &self.e, &space); 400 | let d3u = self.d3.insert(index, element.3, &self.e, &space); 401 | 402 | unadorned::insert_update(&[d0u, d1u, d2u, d3u], space, &mut self.e); 403 | } 404 | } 405 | 406 | /// Removes and returns the elements at position `index` within the SoA, 407 | /// shifting all elements after position `index` one position to the left. 408 | /// 409 | /// Panics if `index` is out of bounds. 410 | pub fn remove(&mut self, index: usize) -> (A, B, C, D) { 411 | unsafe { 412 | assert!(index < self.e.len); 413 | 414 | let (x0, d0u) = self.d0.remove(index, &self.e); 415 | let (x1, d1u) = self.d1.remove(index, &self.e); 416 | let (x2, d2u) = self.d2.remove(index, &self.e); 417 | let (x3, d3u) = self.d3.remove(index, &self.e); 418 | 419 | unadorned::remove_update(&[d0u, d1u, d2u, d3u], &mut self.e); 420 | (x0, x1, x2, x3) 421 | } 422 | } 423 | 424 | /// Returns only the element specified by the predicate. 425 | /// 426 | /// In other words, remove all elements `e` such that `f(&e)` returns false. 427 | /// This method operates in place and preserves the order of the retained 428 | /// elements. 429 | pub fn retain(&mut self, mut f: F) where F: FnMut((&A, &B, &C, &D)) -> bool { 430 | let len = self.len(); 431 | let mut del = 0; 432 | 433 | { 434 | let (d0, d1, d2, d3) = self.as_mut_slices(); 435 | 436 | for i in 0..len { 437 | if !f((&d0[i], &d1[i], &d2[i], &d3[i])) { 438 | del += 1; 439 | } else if del > 0 { 440 | d0.swap(i-del, i); 441 | d1.swap(i-del, i); 442 | d2.swap(i-del, i); 443 | d3.swap(i-del, i); 444 | } 445 | } 446 | } 447 | 448 | self.truncate(len - del); 449 | } 450 | 451 | /// Appends an element to the back of a collection. 452 | /// 453 | /// Panics if the number of elements in the SoA overflows a `usize`. 454 | #[inline] 455 | pub fn push(&mut self, value: (A, B, C, D)) { 456 | if self.is_boring() { 457 | // zero-size types consume no memory, so we can't rely on the 458 | // address space running out 459 | self.e.len = self.e.len.checked_add(1).expect("length overflow"); 460 | unsafe { mem::forget(value) } 461 | return 462 | } 463 | 464 | unsafe { 465 | let d0u = self.d0.push(value.0, &self.e); 466 | let d1u = self.d1.push(value.1, &self.e); 467 | let d2u = self.d2.push(value.2, &self.e); 468 | let d3u = self.d3.push(value.3, &self.e); 469 | 470 | unadorned::push_update(&[d0u, d1u, d2u, d3u], &mut self.e); 471 | } 472 | } 473 | 474 | /// Removes the last element from a SoA and returns it, or `None` if empty. 475 | #[inline] 476 | pub fn pop(&mut self) -> Option<(A, B, C, D)> { 477 | if self.e.len == 0 { 478 | None 479 | } else { 480 | unsafe { 481 | self.e.len -= 1; 482 | let len = self.e.len; 483 | 484 | let (d0, d1, d2, d3) = self.as_mut_slices(); 485 | 486 | Some((ptr::read(d0.get_unchecked(len)), 487 | ptr::read(d1.get_unchecked(len)), 488 | ptr::read(d2.get_unchecked(len)), 489 | ptr::read(d3.get_unchecked(len)))) 490 | } 491 | } 492 | } 493 | 494 | /// Moves all the elements of `other` into `self`, leaving `other` empty. 495 | /// 496 | /// Panics if the number of elements in the SoA overflows a `usize`. 497 | #[inline] 498 | pub fn append(&mut self, other: &mut Self) { 499 | if self.is_boring() { 500 | // zero-size types consume no memory, so we can't rely on the address 501 | // space running out 502 | self.e.len = self.e.len.checked_add(other.len()).expect("length overflow"); 503 | other.e.len = 0; 504 | return; 505 | } 506 | 507 | unsafe { 508 | let space = unadorned::calc_reserve_space(&self.e, 1); 509 | 510 | let d0u = self.d0.append(&self.e, &other.d0, &other.e, &space); 511 | let d1u = self.d1.append(&self.e, &other.d1, &other.e, &space); 512 | let d2u = self.d2.append(&self.e, &other.d2, &other.e, &space); 513 | let d3u = self.d3.append(&self.e, &other.d3, &other.e, &space); 514 | 515 | unadorned::append_update(&[d0u, d1u, d2u, d3u], &mut self.e, &mut other.e, space); 516 | } 517 | } 518 | 519 | // TODO: drain 520 | 521 | /// Clears the SoA, removing all values. 522 | #[inline] 523 | pub fn clear(&mut self) { 524 | self.truncate(0); 525 | } 526 | 527 | // TODO: map_in_place 528 | 529 | /// Extends the SoA with the elements yielded by arbitrary iterators. 530 | /// 531 | /// Panics (and leaks memory!) if the iterators yield a different number of 532 | /// elements. 533 | pub fn extend(&mut self, i0: I0, i1: I1, i2: I2, i3: I3) 534 | where I0: Iterator, I1: Iterator, I2: Iterator, I3: Iterator { 535 | unsafe { 536 | let (lower, _) = i0.size_hint(); 537 | let space = unadorned::calc_reserve_space(&self.e, lower); 538 | 539 | let d0u = self.d0.extend(&self.e, &space, i0); 540 | let d1u = self.d1.extend(&self.e, &space, i1); 541 | let d2u = self.d2.extend(&self.e, &space, i2); 542 | let d3u = self.d3.extend(&self.e, &space, i3); 543 | 544 | unadorned::extend_update(&[d0u, d1u, d2u, d3u], &mut self.e); 545 | } 546 | } 547 | 548 | /// Constructs an `Soa4` with elements yielded by arbitrary iterators. 549 | /// 550 | /// Panics (and leaks memory!) if the iterators yield a different number of 551 | /// elements. 552 | pub fn from_iters(i0: I0, i1: I1, i2: I2, i3: I3) -> Soa4 553 | where I0: Iterator, I1: Iterator, I2: Iterator, I3: Iterator { 554 | let mut v = Soa4::new(); 555 | v.extend(i0, i1, i2, i3); 556 | v 557 | } 558 | 559 | // TODO: dedup 560 | } 561 | 562 | impl Soa4 { 563 | /// Resizes the SoA in-place so that `len()` is equal to `new_len`. 564 | /// 565 | /// Calls either `extend()` or `truncate()` depending on whether `new_len` is 566 | /// larger than the current value of `len()` or not. 567 | #[inline] 568 | pub fn resize(&mut self, new_len: usize, value: (A, B, C, D)) { 569 | let len = self.len(); 570 | 571 | if new_len > len { 572 | self.extend( 573 | repeat(value.0).take(new_len - len), 574 | repeat(value.1).take(new_len - len), 575 | repeat(value.2).take(new_len - len), 576 | repeat(value.3).take(new_len - len)); 577 | } else { 578 | self.truncate(new_len); 579 | } 580 | } 581 | 582 | /// Appends all elements in slices to the SoA. 583 | /// 584 | /// Iterates over the slices, clones each element, and then appends them to 585 | /// this SoA. The slices are traversed one at a time, in order. 586 | /// 587 | /// Panics if the slices are of different lengths. 588 | #[inline] 589 | pub fn push_all(&mut self, x0: &[A], x1: &[B], x2: &[C], x3: &[D]) { 590 | unsafe { 591 | assert_eq!(x0.len(), x1.len()); 592 | assert_eq!(x0.len(), x2.len()); 593 | assert_eq!(x0.len(), x3.len()); 594 | 595 | let space = unadorned::calc_reserve_space(&self.e, x0.len()); 596 | 597 | let d0u = self.d0.push_all(x0, &self.e, &space); 598 | let d1u = self.d1.push_all(x1, &self.e, &space); 599 | let d2u = self.d2.push_all(x2, &self.e, &space); 600 | let d3u = self.d3.push_all(x3, &self.e, &space); 601 | 602 | unadorned::push_all_update(&[d0u, d1u, d2u, d3u], &mut self.e, x0.len(), space); 603 | } 604 | } 605 | } 606 | 607 | impl Clone for Soa4 { 608 | #[inline] 609 | fn clone(&self) -> Soa4 { 610 | let mut ret = Soa4::new(); 611 | let (d0, d1, d2, d3) = self.as_slices(); 612 | ret.push_all(d0, d1, d2, d3); 613 | ret 614 | } 615 | 616 | fn clone_from(&mut self, other: &Soa4) { 617 | // TODO: cleanup 618 | 619 | if self.len() > other.len() { 620 | self.truncate(other.len()); 621 | } 622 | 623 | let (od0, od1, od2, od3) = other.as_slices(); 624 | 625 | let (s0, s1, s2, s3) = { 626 | let self_len = self.len(); 627 | let (sd0, sd1, sd2, sd3) = self.iters_mut(); 628 | 629 | for (place, thing) in sd0.zip(od0.iter()) { 630 | place.clone_from(thing); 631 | } 632 | 633 | for (place, thing) in sd1.zip(od1.iter()) { 634 | place.clone_from(thing); 635 | } 636 | 637 | for (place, thing) in sd2.zip(od2.iter()) { 638 | place.clone_from(thing); 639 | } 640 | 641 | for (place, thing) in sd3.zip(od3.iter()) { 642 | place.clone_from(thing); 643 | } 644 | 645 | let s0 = &od0[self_len..]; 646 | let s1 = &od1[self_len..]; 647 | let s2 = &od2[self_len..]; 648 | let s3 = &od3[self_len..]; 649 | 650 | (s0, s1, s2, s3) 651 | }; 652 | 653 | self.push_all(s0, s1, s2, s3); 654 | } 655 | } 656 | 657 | impl Hash for Soa4 { 658 | #[inline] 659 | fn hash(&self, state: &mut H) { 660 | self.as_slices().hash(state) 661 | } 662 | } 663 | 664 | impl PartialEq> for Soa4 665 | where A0: PartialEq, B0: PartialEq, C0: PartialEq, D0: PartialEq { 666 | #[inline] 667 | fn eq(&self, other: &Soa4) -> bool { 668 | let (a0, b0, c0, d0) = self.as_slices(); 669 | let (a1, b1, c1, d1) = other.as_slices(); 670 | 671 | PartialEq::eq(a0, a1) && PartialEq::eq(b0, b1) && PartialEq::eq(c0, c1) && PartialEq::eq(d0, d1) 672 | } 673 | 674 | #[inline] 675 | fn ne(&self, other: &Soa4) -> bool { 676 | let (a0, b0, c0, d0) = self.as_slices(); 677 | let (a1, b1, c1, d1) = other.as_slices(); 678 | 679 | PartialEq::ne(a0, a1) || PartialEq::ne(b0, b1) || PartialEq::ne(c0, c1) || PartialEq::ne(d0, d1) 680 | } 681 | } 682 | 683 | impl PartialEq> for Soa4 684 | where A0: PartialEq, B0: PartialEq, C0: PartialEq, D0: PartialEq { 685 | #[inline] 686 | fn eq(&self, other: &Vec<(A1, B1, C1, D1)>) -> bool { 687 | self.len() == other.len() 688 | && self.zip_iter().zip(other.iter()).all( 689 | |((a0, b0, c0, d0), &(ref a1, ref b1, ref c1, ref d1))| a0 == a1 && b0 == b1 && c0 == c1 && d0 == d1) 690 | } 691 | 692 | #[inline] 693 | fn ne(&self, other: &Vec<(A1, B1, C1, D1)>) -> bool { 694 | self.len() != other.len() 695 | || self.zip_iter().zip(other.iter()).any( 696 | |((a0, b0, c0, d0), &(ref a1, ref b1, ref c1, ref d1))| a0 != a1 || b0 != b1 || c0 != c1 || d0 != d1) 697 | } 698 | } 699 | 700 | impl<'b, A0, B0, C0, D0, A1, B1, C1, D1> PartialEq<&'b [(A1, B1, C1, D1)]> for Soa4 701 | where A0: PartialEq, B0: PartialEq, C0: PartialEq, D0: PartialEq { 702 | #[inline] 703 | fn eq(&self, other: &&'b [(A1, B1, C1, D1)]) -> bool { 704 | self.len() == other.len() 705 | && self.zip_iter().zip(other.iter()).all( 706 | |((a0, b0, c0, d0), &(ref a1, ref b1, ref c1, ref d1))| a0 == a1 && b0 == b1 && c0 == c1 && d0 == d1) 707 | } 708 | 709 | #[inline] 710 | fn ne(&self, other: &&'b [(A1, B1, C1, D1)]) -> bool { 711 | self.len() != other.len() 712 | || self.zip_iter().zip(other.iter()).any( 713 | |((a0, b0, c0, d0), &(ref a1, ref b1, ref c1, ref d1))| a0 != a1 || b0 != b1 || c0 != c1 || d0 != d1) 714 | } 715 | } 716 | 717 | impl<'b, A0, B0, C0, D0, A1, B1, C1, D1> PartialEq<&'b mut [(A1, B1, C1, D1)]> for Soa4 718 | where A0: PartialEq, B0: PartialEq, C0: PartialEq, D0: PartialEq { 719 | #[inline] 720 | fn eq(&self, other: &&'b mut [(A1, B1, C1, D1)]) -> bool { 721 | self.len() == other.len() 722 | && self.zip_iter().zip(other.iter()).all( 723 | |((a0, b0, c0, d0), &(ref a1, ref b1, ref c1, ref d1))| a0 == a1 && b0 == b1 && c0 == c1 && d0 == d1) 724 | } 725 | 726 | #[inline] 727 | fn ne(&self, other: &&'b mut [(A1, B1, C1, D1)]) -> bool { 728 | self.len() != other.len() 729 | || self.zip_iter().zip(other.iter()).any( 730 | |((a0, b0, c0, d0), &(ref a1, ref b1, ref c1, ref d1))| a0 != a1 || b0 != b1 || c0 != c1 || d0 != d1) 731 | } 732 | } 733 | 734 | impl PartialOrd for Soa4 { 735 | #[inline] 736 | fn partial_cmp(&self, other: &Soa4) -> Option { 737 | iter::order::partial_cmp(self.zip_iter(), other.zip_iter()) 738 | } 739 | } 740 | 741 | impl Eq for Soa4 {} 742 | 743 | impl Ord for Soa4 { 744 | #[inline] 745 | fn cmp(&self, other: &Soa4) -> Ordering { 746 | iter::order::cmp(self.zip_iter(), other.zip_iter()) 747 | } 748 | } 749 | 750 | impl Default for Soa4 { 751 | fn default() -> Soa4 { Soa4::new() } 752 | } 753 | 754 | impl Debug for Soa4 { 755 | fn fmt(&self, f: &mut Formatter) -> Result { 756 | Debug::fmt(&self.as_slices(), f) 757 | } 758 | } 759 | 760 | impl Drop for Soa4 { 761 | #[inline] 762 | fn drop(&mut self) { 763 | if self.e.cap != 0 && self.e.cap != mem::POST_DROP_USIZE { 764 | unsafe { 765 | self.d0.drop(&self.e); 766 | self.d1.drop(&self.e); 767 | self.d2.drop(&self.e); 768 | self.d3.drop(&self.e); 769 | } 770 | self.e.cap = 0; 771 | } 772 | } 773 | } 774 | --------------------------------------------------------------------------------