1pub mod serde;
3
4use std::{alloc::{alloc, dealloc, realloc, Layout}, fmt, marker::PhantomData, mem, ptr::{self, NonNull}};
5use std::ops::Index;
6use std::fmt::Debug;
7
8use num_traits::Num;
9pub struct ZeroSpVec<N>
16where N: Num
17{
18 buf: RawZeroSpVec<N>,
19 len: usize,
20 nnz: usize,
21 zero: N,
22}
23
24pub trait ZeroSpVecTrait<N>: Clone + Default + Index<usize, Output = N>
25where N: Num
26{
27 unsafe fn ind_ptr(&self) -> *mut u32;
28 unsafe fn val_ptr(&self) -> *mut N;
29 unsafe fn raw_push(&mut self, index: usize, value: N);
30 fn ind_binary_search(&self, index: usize, cut_down: usize) -> Result<usize, usize>;
31 fn new() -> Self;
32 fn with_capacity(cap: usize) -> Self;
33 fn reserve(&mut self, additional: usize);
34 fn shrink_to_fit(&mut self);
35 fn is_empty(&self) -> bool;
36 fn len(&self) -> usize;
37 unsafe fn set_len(&mut self, len: usize);
38 fn capacity(&self) -> usize;
39 fn nnz(&self) -> usize;
40 fn add_dim(&mut self, dim: usize);
41 fn clear(&mut self);
42 fn push(&mut self, elem: N);
43 fn pop(&mut self) -> Option<N>;
44 fn get(&self, index: usize) -> Option<&N>;
45 fn raw_get(&self, index: usize) -> Option<ValueWithIndex<'_, N>>;
46 fn get_with_cut_down(&self, index: usize, cut_down: usize) -> Option<&N>;
47 fn raw_get_with_cut_down(&self, index: usize, cut_down: usize) -> Option<ValueWithIndex<'_, N>>;
48 fn get_ind(&self, index: usize) -> Option<usize>;
49 fn remove(&mut self, index: usize) -> N;
50 fn from_vec(vec: Vec<N>) -> Self;
51 unsafe fn from_raw_iter(iter: impl Iterator<Item = (usize, N)>, len: usize) -> Self;
52 unsafe fn from_sparse_iter(iter: impl Iterator<Item = (usize, N)>, len: usize) -> Self;
53 fn iter(&self) -> ZeroSpVecIter<'_, N>;
54 fn raw_iter(&self) -> ZeroSpVecRawIter<'_, N>;
55}
56
57pub struct ValueWithIndex<'a, N>
58where N: Num
59{
60 pub index: usize,
61 pub value: &'a N,
62}
63
64impl<N> ZeroSpVecTrait<N> for ZeroSpVec<N>
65where N: Num
66{
67 #[inline]
68 unsafe fn ind_ptr(&self) -> *mut u32 {
69 self.buf.ind_ptr.as_ptr()
70 }
71
72 #[inline]
73 unsafe fn val_ptr(&self) -> *mut N {
74 self.buf.val_ptr.as_ptr()
75 }
76
77 #[inline]
84 unsafe fn raw_push(&mut self, index: usize, value: N) {
85 if self.nnz == self.buf.cap {
86 self.buf.grow();
87 }
88 unsafe {
89 let val_ptr = self.val_ptr().add(self.nnz);
90 let ind_ptr = self.ind_ptr().add(self.nnz);
91 ptr::write(val_ptr, value);
92 debug_assert!(index <= u32::MAX as usize, "index overflow for u32 storage");
93 ptr::write(ind_ptr, index as u32);
94 }
95 self.nnz += 1;
96 }
97
98 #[inline]
99 fn ind_binary_search(&self, index: usize, cut_down: usize) -> Result<usize, usize> {
100 if self.nnz == 0 {
102 return Err(0);
103 }
104 let mut left = cut_down;
105 let mut right = self.nnz - 1;
106 while left < right {
107 let mid = left + (right - left) / 2;
108 let mid_index = unsafe { *self.ind_ptr().add(mid) as usize };
110 if mid_index == index {
111 return Ok(mid);
112 } else if mid_index < index {
113 left = mid + 1;
114 } else {
115 right = mid;
116 }
117 }
118
119 let final_index = unsafe { *self.ind_ptr().add(left) as usize };
120 if final_index == index {
121 Ok(left)
122 } else if final_index < index {
123 Err(left + 1)
124 } else {
125 Err(left)
126 }
127 }
128
129 #[inline]
130 fn new() -> Self {
131 ZeroSpVec {
132 buf: RawZeroSpVec::new(),
133 len: 0,
134 nnz: 0,
135 zero: N::zero(),
136 }
137 }
138
139 #[inline]
140 fn with_capacity(cap: usize) -> Self {
141 let mut buf = RawZeroSpVec::new();
142 buf.cap = cap;
143 buf.cap_set();
144 ZeroSpVec {
145 buf: buf,
146 len: 0,
147 nnz: 0,
148 zero: N::zero(),
149 }
150 }
151
152 #[inline]
154 fn reserve(&mut self, additional: usize) {
155 let new_cap = self.nnz + additional;
156 if new_cap > self.buf.cap {
157 self.buf.cap = new_cap;
158 self.buf.re_cap_set();
159 }
160 }
161
162 #[inline]
164 fn shrink_to_fit(&mut self) {
165 if self.len < self.buf.cap {
166 let new_cap = self.nnz;
167 self.buf.cap = new_cap;
168 self.buf.re_cap_set();
169 }
170 }
171
172 #[inline]
173 fn is_empty(&self) -> bool {
174 self.len == 0
175 }
176
177 #[inline]
178 fn len(&self) -> usize {
179 self.len
180 }
181
182 #[inline]
183 unsafe fn set_len(&mut self, len: usize) {
184 self.len = len;
185 }
186
187 #[inline]
189 fn capacity(&self) -> usize {
190 self.buf.cap
191 }
192
193 #[inline]
195 fn nnz(&self) -> usize {
196 self.nnz
197 }
198
199 #[inline]
201 fn add_dim(&mut self, dim: usize) {
202 self.len += dim;
203 }
204
205 #[inline]
208 fn clear(&mut self) {
209 while let Some(_) = self.pop() {
210 }
212 }
213
214 #[inline]
215 fn push(&mut self, elem: N) {
216 if self.nnz == self.buf.cap {
217 self.buf.grow();
218 }
219 if elem != N::zero() {
220 unsafe {
221 let val_ptr = self.val_ptr().add(self.nnz);
222 let ind_ptr = self.ind_ptr().add(self.nnz);
223 ptr::write(val_ptr, elem);
224 debug_assert!(self.len <= u32::MAX as usize, "index overflow for u32 storage");
225 ptr::write(ind_ptr, self.len as u32);
226 }
227 self.nnz += 1;
228 }
229 self.len += 1;
230 }
231
232 #[inline]
233 fn pop(&mut self) -> Option<N> {
234 if self.nnz == 0 {
235 return None;
236 }
237 let pop_element = if self.nnz == self.len {
238 self.nnz -= 1;
239 unsafe {
240 Some(ptr::read(self.val_ptr().add(self.nnz)))
241 }
242 } else {
243 Some(N::zero())
244 };
245 self.len -= 1;
246 pop_element
247 }
248
249 #[inline]
250 fn get(&self, index: usize) -> Option<&N> {
251 if index >= self.len {
252 return None;
253 }
254 match self.ind_binary_search(index, 0) {
255 Ok(idx) => {
256 unsafe {
257 Some(&*self.val_ptr().add(idx))
258 }
259 },
260 Err(_) => {
261 Some(&self.zero)
262 }
263 }
264 }
265
266 #[inline]
267 fn raw_get(&self, index: usize) -> Option<ValueWithIndex<'_, N>> {
268 if index >= self.len {
269 return None;
270 }
271 match self.ind_binary_search(index, 0) {
272 Ok(idx) => {
273 unsafe {
274 Some(ValueWithIndex {
275 index,
276 value: &*self.val_ptr().add(idx),
277 })
278 }
279 },
280 Err(_) => {
281 Some(ValueWithIndex {
282 index,
283 value: &self.zero,
284 })
285 }
286 }
287 }
288
289 #[inline]
290 fn get_with_cut_down(&self, index: usize, cut_down: usize) -> Option<&N> {
291 if index >= self.len {
292 return None;
293 }
294 match self.ind_binary_search(index, cut_down) {
295 Ok(idx) => {
296 unsafe {
297 Some(&*self.val_ptr().add(idx))
298 }
299 },
300 Err(_) => {
301 Some(&self.zero)
302 }
303 }
304 }
305
306 #[inline]
307 fn raw_get_with_cut_down(&self, index: usize, cut_down: usize) -> Option<ValueWithIndex<'_, N>> {
308 if index >= self.len || cut_down >= self.nnz {
309 return None;
310 }
311 match self.ind_binary_search(index, cut_down) {
312 Ok(idx) => {
313 unsafe {
314 Some(ValueWithIndex {
315 index,
316 value: &*self.val_ptr().add(idx),
317 })
318 }
319 },
320 Err(_) => {
321 Some(ValueWithIndex {
322 index,
323 value: &self.zero,
324 })
325 }
326 }
327 }
328
329 #[inline]
330 fn get_ind(&self, index: usize) -> Option<usize> {
331 if index >= self.nnz {
332 return None;
333 }
334 unsafe {
335 Some(ptr::read(self.ind_ptr().add(index)) as usize)
336 }
337 }
338
339
340
341 #[inline]
353 fn remove(&mut self, index: usize) -> N {
354 debug_assert!(index < self.len, "index out of bounds");
355
356 self.len -= 1;
358
359 match self.ind_binary_search(index, 0) {
360 Ok(i) => {
361 let removed_val = unsafe {
363 ptr::read(self.val_ptr().add(i))
364 };
365
366 let count = self.nnz - i - 1;
368 if count > 0 {
369 unsafe {
370 ptr::copy(
372 self.val_ptr().add(i + 1),
373 self.val_ptr().add(i),
374 count
375 );
376 ptr::copy(
378 self.ind_ptr().add(i + 1),
379 self.ind_ptr().add(i),
380 count
381 );
382 for offset in i..(self.nnz - 1) {
384 *self.ind_ptr().add(offset) -= 1;
385 }
386 }
387 }
388 self.nnz -= 1;
390
391 removed_val
393 }
394 Err(i) => {
395 if i < self.nnz {
399 unsafe {
400 for offset in i..self.nnz {
401 *self.ind_ptr().add(offset) -= 1;
402 }
403 }
404 }
405
406 N::zero()
408 }
409 }
410 }
411
412 #[inline]
414 fn from_vec(vec: Vec<N>) -> Self {
415 let mut zero_sp_vec = ZeroSpVec::with_capacity(vec.len());
416 for entry in vec {
417 zero_sp_vec.push(entry);
418 }
419 zero_sp_vec
420 }
421
422 #[inline]
425 unsafe fn from_raw_iter(iter: impl Iterator<Item = (usize, N)>, len: usize) -> Self {
426 let mut zero_sp_vec = ZeroSpVec::with_capacity(iter.size_hint().0);
427 for (index, value) in iter {
428 unsafe {
429 zero_sp_vec.raw_push(index, value);
430 }
431 }
432 zero_sp_vec.len = len;
433 zero_sp_vec
434 }
435
436 #[inline]
439 unsafe fn from_sparse_iter(iter: impl Iterator<Item = (usize, N)>, len: usize) -> Self {
440 let mut zero_sp_vec = ZeroSpVec::new();
441 for (index, value) in iter {
442 if value != N::zero() {
443 unsafe {
444 zero_sp_vec.raw_push(index, value);
445 }
446 }
447 }
448 zero_sp_vec.len = len;
449 zero_sp_vec
450 }
451
452 #[inline]
455 fn iter(&self) -> ZeroSpVecIter<'_, N> {
456 ZeroSpVecIter {
457 vec: self,
458 pos: 0,
459 }
460 }
461
462 #[inline]
465 fn raw_iter(&self) -> ZeroSpVecRawIter<'_, N> {
466 ZeroSpVecRawIter {
467 vec: self,
468 pos: 0,
469 }
470 }
471}
472
473unsafe impl <N: Num + Send> Send for ZeroSpVec<N> {}
474unsafe impl <N: Num + Sync> Sync for ZeroSpVec<N> {}
475
476impl<N> Clone for ZeroSpVec<N>
477where N: Num
478{
479 #[inline]
480 fn clone(&self) -> Self {
481 ZeroSpVec {
482 buf: self.buf.clone(),
483 len: self.len,
484 nnz: self.nnz,
485 zero: N::zero(),
486 }
487 }
488}
489
490impl<N> Drop for ZeroSpVec<N>
491where N: Num
492{
493 #[inline]
494 fn drop(&mut self) {
495 }
497}
498
499impl<N> Default for ZeroSpVec<N>
500where N: Num
501{
502 #[inline]
503 fn default() -> Self {
504 ZeroSpVec::new()
505 }
506}
507
508impl<N> Index<usize> for ZeroSpVec<N>
509where N: Num
510{
511 type Output = N;
512
513 #[inline]
514 fn index(&self, index: usize) -> &Self::Output {
515 self.get(index).expect("index out of bounds")
516 }
517}
518
519impl<N: Num + Debug> Debug for ZeroSpVec<N> {
520 #[inline]
521 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522 if f.sign_plus() {
523 f.debug_struct("DefaultSparseVec")
524 .field("buf", &self.buf)
525 .field("nnz", &self.nnz)
526 .field("len", &self.len)
527 .field("zero", &self.zero)
528 .finish()
529 } else if f.alternate() {
530 write!(f, "ZeroSpVec({:?})", self.iter().collect::<Vec<&N>>())
531 } else {
532 f.debug_list().entries((0..self.len).map(|i| self.get(i).unwrap())).finish()
533 }
534 }
535}
536
537#[derive(Clone, Copy)]
538pub struct ZeroSpVecIter<'a, N>
539where N: Num
540{
541 vec: &'a ZeroSpVec<N>,
542 pos: usize,
543}
544
545impl<'a, N> Iterator for ZeroSpVecIter<'a, N>
546where N: Num
547{
548 type Item = &'a N;
549
550 #[inline]
551 fn next(&mut self) -> Option<Self::Item> {
552 self.vec.get(self.pos).map(|val| {
553 self.pos += 1;
554 val
555 })
556 }
557}
558
559#[derive(Clone, Copy)]
560pub struct ZeroSpVecRawIter<'a, N>
561where N: Num
562{
563 vec: &'a ZeroSpVec<N>,
564 pos: usize,
565}
566
567impl<'a, N> Iterator for ZeroSpVecRawIter<'a, N>
568where N: Num
569{
570 type Item = (usize, &'a N);
571
572 #[inline]
573 fn next(&mut self) -> Option<Self::Item> {
574 if self.pos < self.vec.nnz() {
575 let index = unsafe { *self.vec.ind_ptr().add(self.pos) as usize };
576 let value = unsafe { &*self.vec.val_ptr().add(self.pos) };
577 self.pos += 1;
578 Some((index, value))
579 } else {
580 None
581 }
582 }
583
584 #[inline]
585 fn nth(&mut self, n: usize) -> Option<Self::Item> {
586 let nnz = self.vec.nnz();
587 match self.pos.checked_add(n) {
588 Some(new_pos) if new_pos < nnz => {
589 self.pos = new_pos;
590 self.next()
591 }
592 _ => {
593 self.pos = nnz;
594 None
595 }
596 }
597 }
598
599 #[inline]
600 fn size_hint(&self) -> (usize, Option<usize>) {
601 let remaining = self.vec.nnz().saturating_sub(self.pos);
602 (remaining, Some(remaining))
603 }
604
605}
606
607impl<'a, N> ExactSizeIterator for ZeroSpVecRawIter<'a, N>
608where
609 N: Num,
610{
611 #[inline]
612 fn len(&self) -> usize {
613 self.vec.nnz().saturating_sub(self.pos)
614 }
615}
616
617impl<'a, N> std::iter::FusedIterator for ZeroSpVecRawIter<'a, N>
618where
619 N: Num,
620{
621}
622
623impl<T> From<Vec<T>> for ZeroSpVec<T>
624where T: Num
625{
626 #[inline]
627 fn from(vec: Vec<T>) -> Self {
628 ZeroSpVec::from_vec(vec)
629 }
630}
631
632impl<'a, N> From<ZeroSpVecRawIter<'a, N>> for ZeroSpVec<N>
633where
634 N: Num + Copy,
635{
636 #[inline]
637 fn from(iter: ZeroSpVecRawIter<'a, N>) -> Self {
638 let mut vec = ZeroSpVec::new();
639 for (idx, val) in iter {
640 unsafe {
641 vec.raw_push(idx, *val);
642 }
643 vec.len += 1;
644 }
645 vec
646 }
647}
648
649
650
651
652
653
654
655
656
657#[derive(Debug)]
659struct RawZeroSpVec<N>
660where N: Num
661{
662 val_ptr: NonNull<N>,
663 ind_ptr: NonNull<u32>,
664 cap: usize,
669 _marker: PhantomData<N>, }
671
672impl<N> RawZeroSpVec<N>
673where N: Num
674{
675 #[inline]
676 fn new() -> Self {
677 let cap = if mem::size_of::<N>() == 0 { std::usize::MAX } else { 0 };
679
680 RawZeroSpVec {
681 val_ptr: NonNull::dangling(),
683 ind_ptr: NonNull::dangling(),
685 cap: cap,
686 _marker: PhantomData,
687 }
688 }
689
690 #[inline]
691 fn grow(&mut self) {
692 unsafe {
693 let val_elem_size = mem::size_of::<N>();
694 let ind_elem_size = mem::size_of::<u32>();
695
696 debug_assert!(val_elem_size != 0, "capacity overflow");
699
700 let t_align = mem::align_of::<N>();
702 let usize_align = mem::align_of::<u32>();
703
704 let (new_cap, val_ptr, ind_ptr): (usize, *mut N, *mut u32) =
706 if self.cap == 0 {
707 let new_val_layout = Layout::from_size_align(val_elem_size, t_align).expect("Failed to create memory layout");
708 let new_ind_layout = Layout::from_size_align(ind_elem_size, usize_align).expect("Failed to create memory layout");
709 (
710 1,
711 alloc(new_val_layout) as *mut N,
712 alloc(new_ind_layout) as *mut u32,
713 )
714 } else {
715 let new_cap = self.cap * 2;
717 let new_val_layout = Layout::from_size_align(val_elem_size * self.cap, t_align).expect("Failed to create memory layout for reallocation");
718 let new_ind_layout = Layout::from_size_align(ind_elem_size * self.cap, usize_align).expect("Failed to create memory layout for reallocation");
719 (
720 new_cap,
721 realloc(self.val_ptr.as_ptr() as *mut u8, new_val_layout, val_elem_size * new_cap) as *mut N,
722 realloc(self.ind_ptr.as_ptr() as *mut u8, new_ind_layout, ind_elem_size * new_cap) as *mut u32,
723 )
724 };
725
726 if val_ptr.is_null() || ind_ptr.is_null() {
728 oom();
729 }
730
731 self.val_ptr = NonNull::new_unchecked(val_ptr);
733 self.ind_ptr = NonNull::new_unchecked(ind_ptr);
734 self.cap = new_cap;
735 }
736 }
737
738 #[inline]
739 fn cap_set(&mut self) {
740 unsafe {
741 let val_elem_size = mem::size_of::<N>();
742 let ind_elem_size = mem::size_of::<u32>();
743
744 let t_align = mem::align_of::<N>();
745 let usize_align = mem::align_of::<u32>();
746
747 let new_val_layout = Layout::from_size_align(val_elem_size * self.cap, t_align).expect("Failed to create memory layout");
748 let new_ind_layout = Layout::from_size_align(ind_elem_size * self.cap, usize_align).expect("Failed to create memory layout");
749 let new_val_ptr = alloc(new_val_layout) as *mut N;
750 let new_ind_ptr = alloc(new_ind_layout) as *mut u32;
751 if new_val_ptr.is_null() || new_ind_ptr.is_null() {
752 oom();
753 }
754 self.val_ptr = NonNull::new_unchecked(new_val_ptr);
755 self.ind_ptr = NonNull::new_unchecked(new_ind_ptr);
756 }
757 }
758
759 #[inline]
760 fn re_cap_set(&mut self) {
761 unsafe {
762 let val_elem_size = mem::size_of::<N>();
763 let ind_elem_size = mem::size_of::<u32>();
764
765 let t_align = mem::align_of::<N>();
766 let usize_align = mem::align_of::<u32>();
767
768 let new_val_layout = Layout::from_size_align(val_elem_size * self.cap, t_align).expect("Failed to create memory layout");
769 let new_ind_layout = Layout::from_size_align(ind_elem_size * self.cap, usize_align).expect("Failed to create memory layout");
770 let new_val_ptr = realloc(self.val_ptr.as_ptr() as *mut u8, new_val_layout, val_elem_size * self.cap) as *mut N;
771 let new_ind_ptr = realloc(self.ind_ptr.as_ptr() as *mut u8, new_ind_layout, ind_elem_size * self.cap) as *mut u32;
772 if new_val_ptr.is_null() || new_ind_ptr.is_null() {
773 oom();
774 }
775 self.val_ptr = NonNull::new_unchecked(new_val_ptr);
776 self.ind_ptr = NonNull::new_unchecked(new_ind_ptr);
777 }
778 }
779}
780
781impl<N> Clone for RawZeroSpVec<N>
782where N: Num
783{
784 #[inline]
785 fn clone(&self) -> Self {
786 unsafe {
787 if self.cap == 0 || self.cap == usize::MAX {
790 return RawZeroSpVec {
791 val_ptr: NonNull::dangling(),
792 ind_ptr: NonNull::dangling(),
793 cap: self.cap,
794 _marker: PhantomData,
795 };
796 }
797
798 let val_elem_size = mem::size_of::<N>();
799 let ind_elem_size = mem::size_of::<u32>();
800
801 let t_align = mem::align_of::<N>();
802 let usize_align = mem::align_of::<u32>();
803
804 let new_val_layout = Layout::from_size_align(val_elem_size * self.cap, t_align).expect("Failed to create memory layout");
805 let new_ind_layout = Layout::from_size_align(ind_elem_size * self.cap, usize_align).expect("Failed to create memory layout");
806 let new_val_ptr = alloc(new_val_layout) as *mut N;
807 let new_ind_ptr = alloc(new_ind_layout) as *mut u32;
808 if new_val_ptr.is_null() || new_ind_ptr.is_null() {
809 oom();
810 }
811 ptr::copy_nonoverlapping(self.val_ptr.as_ptr(), new_val_ptr, self.cap);
812 ptr::copy_nonoverlapping(self.ind_ptr.as_ptr(), new_ind_ptr, self.cap);
813
814 RawZeroSpVec {
815 val_ptr: NonNull::new_unchecked(new_val_ptr),
816 ind_ptr: NonNull::new_unchecked(new_ind_ptr),
817 cap: self.cap,
818 _marker: PhantomData,
819 }
820 }
821 }
822}
823
824unsafe impl<N: Num + Send> Send for RawZeroSpVec<N> {}
825unsafe impl<N: Num + Sync> Sync for RawZeroSpVec<N> {}
826
827impl<N> Drop for RawZeroSpVec<N>
828where N: Num
829{
830 #[inline]
831 fn drop(&mut self) {
832 unsafe {
833 if self.cap == 0 || self.cap == usize::MAX {
835 return;
836 }
837
838 let val_elem_size = mem::size_of::<N>();
839 let ind_elem_size = mem::size_of::<u32>();
840
841 let t_align = mem::align_of::<N>();
842 let usize_align = mem::align_of::<u32>();
843
844 let new_val_layout = Layout::from_size_align(val_elem_size * self.cap, t_align).expect("Failed to create memory layout");
845 let new_ind_layout = Layout::from_size_align(ind_elem_size * self.cap, usize_align).expect("Failed to create memory layout");
846 dealloc(self.val_ptr.as_ptr() as *mut u8, new_val_layout);
847 dealloc(self.ind_ptr.as_ptr() as *mut u8, new_ind_layout);
848 }
849 }
850}
851
852#[cold]
859fn oom() {
860 ::std::process::exit(-9999);
861}