1pub fn bitonic_sort(data: &mut Vec<f32>) {
26 let orig = data.len();
27 if orig <= 1 {
28 return;
29 }
30 let padded = next_pow2(orig);
31 data.resize(padded, f32::MAX);
32 bitonic_sort_slice_f32(data);
33 data.truncate(orig);
34}
35
36pub fn bitonic_sort_by_key<T: Clone>(data: &mut [T], key_fn: impl Fn(&T) -> u32) {
41 let orig = data.len();
42 if orig <= 1 {
43 return;
44 }
45 let padded = next_pow2(orig);
46 let mut pairs: Vec<(u32, usize)> = data
48 .iter()
49 .enumerate()
50 .map(|(i, v)| (key_fn(v), i))
51 .collect();
52 pairs.resize(padded, (u32::MAX, usize::MAX));
53
54 let n = pairs.len();
56 let mut k = 2;
57 while k <= n {
58 let mut j = k / 2;
59 while j >= 1 {
60 for i in 0..n {
61 let l = i ^ j;
62 if l > i {
63 let ascending = (i & k) == 0;
64 let should_swap = if ascending {
65 pairs[i].0 > pairs[l].0
66 } else {
67 pairs[i].0 < pairs[l].0
68 };
69 if should_swap {
70 pairs.swap(i, l);
71 }
72 }
73 }
74 j /= 2;
75 }
76 k *= 2;
77 }
78
79 let old: Vec<T> = data.to_vec();
81 let mut out: Vec<T> = pairs
82 .iter()
83 .filter(|&&(_, idx)| idx < orig)
84 .map(|&(_, idx)| old[idx].clone())
85 .collect();
86 out.truncate(orig);
87 for (i, v) in out.into_iter().enumerate().take(orig) {
89 data[i] = v;
90 }
91}
92
93fn bitonic_sort_slice_f32(data: &mut [f32]) {
95 let n = data.len();
96 let mut k = 2;
97 while k <= n {
98 let mut j = k / 2;
99 while j >= 1 {
100 for i in 0..n {
101 let l = i ^ j;
102 if l > i {
103 let ascending = (i & k) == 0;
104 let should_swap = if ascending {
105 data[i] > data[l]
106 } else {
107 data[i] < data[l]
108 };
109 if should_swap {
110 data.swap(i, l);
111 }
112 }
113 }
114 j /= 2;
115 }
116 k *= 2;
117 }
118}
119
120pub fn radix_sort_u32(data: &mut Vec<u32>) {
128 if data.len() <= 1 {
129 return;
130 }
131 let n = data.len();
132 let mut buf = vec![0u32; n];
133 for pass in 0..4u32 {
134 let shift = pass * 8;
135 let mut counts = [0usize; 256];
136 for &v in data.iter() {
137 counts[((v >> shift) & 0xFF) as usize] += 1;
138 }
139 let mut offsets = [0usize; 256];
140 let mut total = 0;
141 for i in 0..256 {
142 offsets[i] = total;
143 total += counts[i];
144 }
145 for &v in data.iter() {
146 let b = ((v >> shift) & 0xFF) as usize;
147 buf[offsets[b]] = v;
148 offsets[b] += 1;
149 }
150 std::mem::swap(data, &mut buf);
151 }
152}
153
154pub fn radix_sort_f32(data: &mut [f32]) {
159 if data.len() <= 1 {
160 return;
161 }
162 let mut keys: Vec<u32> = data.iter().map(|&v| f32_to_sort_key(v)).collect();
164 radix_sort_u32(&mut keys);
165 for (dst, k) in data.iter_mut().zip(keys.iter()) {
166 *dst = sort_key_to_f32(*k);
167 }
168}
169
170#[inline]
173fn f32_to_sort_key(v: f32) -> u32 {
174 let bits = v.to_bits();
175 if bits >> 31 == 0 {
176 bits | 0x8000_0000 } else {
178 !bits }
180}
181
182#[inline]
184fn sort_key_to_f32(key: u32) -> f32 {
185 let bits = if key >> 31 != 0 {
186 key & 0x7FFF_FFFF } else {
188 !key };
190 f32::from_bits(bits)
191}
192
193pub fn prefix_sum(data: &[u32]) -> Vec<u32> {
202 let mut result = Vec::with_capacity(data.len());
203 let mut acc = 0u32;
204 for &v in data {
205 result.push(acc);
206 acc = acc.wrapping_add(v);
207 }
208 result
209}
210
211pub fn histogram(data: &[u32], n_bins: usize) -> Vec<u32> {
224 assert!(n_bins > 0, "n_bins must be > 0");
225 if data.is_empty() {
226 return vec![0u32; n_bins];
227 }
228 let max_val = *data.iter().max().unwrap_or(&0) as u64 + 1;
229 let mut bins = vec![0u32; n_bins];
230 for &v in data {
231 let idx = ((v as u64 * n_bins as u64) / max_val) as usize;
232 let idx = idx.min(n_bins - 1);
233 bins[idx] += 1;
234 }
235 bins
236}
237
238pub fn counting_sort(data: &mut [u32], max_val: u32) {
247 if data.len() <= 1 {
248 return;
249 }
250 let size = (max_val as usize).saturating_add(1);
251 let mut counts = vec![0u32; size];
252 for &v in data.iter() {
253 let idx = (v as usize).min(size - 1);
254 counts[idx] += 1;
255 }
256 let mut pos = 0usize;
257 for (val, &cnt) in counts.iter().enumerate() {
258 for _ in 0..cnt {
259 data[pos] = val as u32;
260 pos += 1;
261 }
262 }
263}
264
265pub fn morton_sort_3d(points: &mut [[f32; 3]]) {
274 if points.len() <= 1 {
275 return;
276 }
277 let mut lo = [f32::INFINITY; 3];
279 let mut hi = [f32::NEG_INFINITY; 3];
280 for p in points.iter() {
281 for d in 0..3 {
282 lo[d] = lo[d].min(p[d]);
283 hi[d] = hi[d].max(p[d]);
284 }
285 }
286 let scale: Vec<f32> = (0..3)
287 .map(|d| {
288 let range = hi[d] - lo[d];
289 if range > 0.0 { 1023.0 / range } else { 0.0 }
290 })
291 .collect();
292
293 let mut pairs: Vec<(u32, usize)> = points
294 .iter()
295 .enumerate()
296 .map(|(i, p)| {
297 let ix = ((p[0] - lo[0]) * scale[0]) as u32;
298 let iy = ((p[1] - lo[1]) * scale[1]) as u32;
299 let iz = ((p[2] - lo[2]) * scale[2]) as u32;
300 (morton3(ix.min(1023), iy.min(1023), iz.min(1023)), i)
301 })
302 .collect();
303
304 pairs.sort_unstable_by_key(|&(code, _)| code);
305
306 let old: Vec<[f32; 3]> = points.to_vec();
307 for (i, &(_, idx)) in pairs.iter().enumerate() {
308 points[i] = old[idx];
309 }
310}
311
312fn morton3(x: u32, y: u32, z: u32) -> u32 {
314 spread_bits(x) | (spread_bits(y) << 1) | (spread_bits(z) << 2)
315}
316
317fn spread_bits(mut v: u32) -> u32 {
319 v &= 0x3FF; v = (v | (v << 16)) & 0x030000FF;
321 v = (v | (v << 8)) & 0x0300F00F;
322 v = (v | (v << 4)) & 0x030C30C3;
323 v = (v | (v << 2)) & 0x09249249;
324 v
325}
326
327#[derive(Debug, Clone)]
335pub struct GpuSortBuffer {
336 pub keys: Vec<u32>,
338 pub values: Vec<u32>,
340}
341
342impl GpuSortBuffer {
343 pub fn new(keys: Vec<u32>, values: Vec<u32>) -> Self {
348 assert_eq!(
349 keys.len(),
350 values.len(),
351 "keys and values must have equal length"
352 );
353 Self { keys, values }
354 }
355
356 pub fn empty() -> Self {
358 Self {
359 keys: Vec::new(),
360 values: Vec::new(),
361 }
362 }
363
364 pub fn len(&self) -> usize {
366 self.keys.len()
367 }
368
369 pub fn is_empty(&self) -> bool {
371 self.keys.is_empty()
372 }
373
374 pub fn sort_pairs(&mut self) {
376 if self.len() <= 1 {
377 return;
378 }
379 let n = self.len();
380 let mut key_buf = vec![0u32; n];
381 let mut val_buf = vec![0u32; n];
382 for pass in 0..4u32 {
383 let shift = pass * 8;
384 let mut counts = [0usize; 256];
385 for &k in self.keys.iter() {
386 counts[((k >> shift) & 0xFF) as usize] += 1;
387 }
388 let mut offsets = [0usize; 256];
389 let mut total = 0;
390 for i in 0..256 {
391 offsets[i] = total;
392 total += counts[i];
393 }
394 for (i, &k) in self.keys.iter().enumerate() {
395 let b = ((k >> shift) & 0xFF) as usize;
396 let dest = offsets[b];
397 key_buf[dest] = k;
398 val_buf[dest] = self.values[i];
399 offsets[b] += 1;
400 }
401 std::mem::swap(&mut self.keys, &mut key_buf);
402 std::mem::swap(&mut self.values, &mut val_buf);
403 }
404 }
405
406 pub fn push(&mut self, key: u32, value: u32) {
408 self.keys.push(key);
409 self.values.push(value);
410 }
411}
412
413pub fn parallel_merge(left: &[f32], right: &[f32]) -> Vec<f32> {
422 let mut result = Vec::with_capacity(left.len() + right.len());
423 let (mut i, mut j) = (0, 0);
424 while i < left.len() && j < right.len() {
425 if left[i] <= right[j] {
426 result.push(left[i]);
427 i += 1;
428 } else {
429 result.push(right[j]);
430 j += 1;
431 }
432 }
433 result.extend_from_slice(&left[i..]);
434 result.extend_from_slice(&right[j..]);
435 result
436}
437
438fn next_pow2(n: usize) -> usize {
444 if n == 0 {
445 return 1;
446 }
447 let mut p = 1usize;
448 while p < n {
449 p <<= 1;
450 }
451 p
452}
453
454#[cfg(test)]
459mod tests {
460 use super::*;
461
462 #[test]
465 fn test_next_pow2_zero() {
466 assert_eq!(next_pow2(0), 1);
467 }
468
469 #[test]
470 fn test_next_pow2_one() {
471 assert_eq!(next_pow2(1), 1);
472 }
473
474 #[test]
475 fn test_next_pow2_exact() {
476 assert_eq!(next_pow2(8), 8);
477 }
478
479 #[test]
480 fn test_next_pow2_non_exact() {
481 assert_eq!(next_pow2(9), 16);
482 }
483
484 #[test]
487 fn test_bitonic_sort_power_of_two() {
488 let mut data = vec![4.0f32, 2.0, 7.0, 1.0, 8.0, 3.0, 6.0, 5.0];
489 bitonic_sort(&mut data);
490 assert_eq!(data, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);
491 }
492
493 #[test]
494 fn test_bitonic_sort_non_power_of_two() {
495 let mut data = vec![5.0f32, 3.0, 1.0, 4.0, 2.0];
496 bitonic_sort(&mut data);
497 assert_eq!(data, vec![1.0, 2.0, 3.0, 4.0, 5.0]);
498 }
499
500 #[test]
501 fn test_bitonic_sort_empty() {
502 let mut data: Vec<f32> = vec![];
503 bitonic_sort(&mut data);
504 assert!(data.is_empty());
505 }
506
507 #[test]
508 fn test_bitonic_sort_single() {
509 let mut data = vec![42.0f32];
510 bitonic_sort(&mut data);
511 assert_eq!(data, vec![42.0]);
512 }
513
514 #[test]
515 fn test_bitonic_sort_already_sorted() {
516 let mut data = vec![1.0f32, 2.0, 3.0, 4.0];
517 bitonic_sort(&mut data);
518 assert_eq!(data, vec![1.0, 2.0, 3.0, 4.0]);
519 }
520
521 #[test]
522 fn test_bitonic_sort_reverse() {
523 let mut data = vec![8.0f32, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0];
524 bitonic_sort(&mut data);
525 assert_eq!(data, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);
526 }
527
528 #[test]
529 fn test_bitonic_sort_duplicates() {
530 let mut data = vec![3.0f32, 1.0, 3.0, 2.0, 1.0];
531 bitonic_sort(&mut data);
532 assert_eq!(data, vec![1.0, 1.0, 2.0, 3.0, 3.0]);
533 }
534
535 #[test]
536 fn test_bitonic_sort_large_non_pow2() {
537 let mut data: Vec<f32> = (0..100).map(|i| (100 - i) as f32).collect();
538 bitonic_sort(&mut data);
539 for i in 0..data.len() - 1 {
540 assert!(data[i] <= data[i + 1]);
541 }
542 }
543
544 #[test]
547 fn test_bitonic_sort_by_key_u32() {
548 let mut data = vec![30u32, 10, 20, 40];
549 bitonic_sort_by_key(&mut data, |x| *x);
550 assert_eq!(data, vec![10, 20, 30, 40]);
551 }
552
553 #[test]
554 fn test_bitonic_sort_by_key_empty() {
555 let mut data: Vec<u32> = vec![];
556 bitonic_sort_by_key(&mut data, |x| *x);
557 assert!(data.is_empty());
558 }
559
560 #[test]
561 fn test_bitonic_sort_by_key_single() {
562 let mut data = vec![42u32];
563 bitonic_sort_by_key(&mut data, |x| *x);
564 assert_eq!(data, vec![42]);
565 }
566
567 #[test]
570 fn test_radix_sort_u32_basic() {
571 let mut data = vec![5u32, 3, 8, 1, 9, 2, 7, 4, 6];
572 radix_sort_u32(&mut data);
573 assert_eq!(data, vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
574 }
575
576 #[test]
577 fn test_radix_sort_u32_empty() {
578 let mut data: Vec<u32> = vec![];
579 radix_sort_u32(&mut data);
580 assert!(data.is_empty());
581 }
582
583 #[test]
584 fn test_radix_sort_u32_single() {
585 let mut data = vec![42u32];
586 radix_sort_u32(&mut data);
587 assert_eq!(data, vec![42]);
588 }
589
590 #[test]
591 fn test_radix_sort_u32_large_values() {
592 let mut data = vec![u32::MAX, 0u32, u32::MAX / 2, 1u32];
593 radix_sort_u32(&mut data);
594 assert_eq!(data[0], 0);
595 assert_eq!(data[3], u32::MAX);
596 }
597
598 #[test]
599 fn test_radix_sort_u32_duplicates() {
600 let mut data = vec![3u32, 1, 3, 2, 1];
601 radix_sort_u32(&mut data);
602 assert_eq!(data, vec![1, 1, 2, 3, 3]);
603 }
604
605 #[test]
608 fn test_radix_sort_f32_positive_only() {
609 let mut data = vec![3.0f32, 1.0, 4.0, 1.5, 0.5];
610 radix_sort_f32(&mut data);
611 for i in 0..data.len() - 1 {
612 assert!(data[i] <= data[i + 1]);
613 }
614 }
615
616 #[test]
617 fn test_radix_sort_f32_with_negatives() {
618 let mut data = vec![1.0f32, -2.0, 0.5, -0.5, 3.0, -1.0];
619 radix_sort_f32(&mut data);
620 for i in 0..data.len() - 1 {
621 assert!(
622 data[i] <= data[i + 1],
623 "not sorted at {i}: {} > {}",
624 data[i],
625 data[i + 1]
626 );
627 }
628 }
629
630 #[test]
631 fn test_radix_sort_f32_empty() {
632 let mut data: Vec<f32> = vec![];
633 radix_sort_f32(&mut data);
634 assert!(data.is_empty());
635 }
636
637 #[test]
638 fn test_f32_sort_key_roundtrip_positive() {
639 let v = 3.125f32;
640 assert_eq!(sort_key_to_f32(f32_to_sort_key(v)), v);
641 }
642
643 #[test]
644 fn test_f32_sort_key_roundtrip_negative() {
645 let v = -2.719f32;
646 assert_eq!(sort_key_to_f32(f32_to_sort_key(v)), v);
647 }
648
649 #[test]
652 fn test_prefix_sum_basic() {
653 let data = [1u32, 2, 3, 4];
654 let result = prefix_sum(&data);
655 assert_eq!(result, vec![0, 1, 3, 6]);
656 }
657
658 #[test]
659 fn test_prefix_sum_empty() {
660 let result = prefix_sum(&[]);
661 assert!(result.is_empty());
662 }
663
664 #[test]
665 fn test_prefix_sum_single() {
666 let result = prefix_sum(&[5u32]);
667 assert_eq!(result, vec![0]);
668 }
669
670 #[test]
671 fn test_prefix_sum_all_ones() {
672 let data = vec![1u32; 5];
673 let result = prefix_sum(&data);
674 assert_eq!(result, vec![0, 1, 2, 3, 4]);
675 }
676
677 #[test]
680 fn test_histogram_basic() {
681 let data = [0u32, 1, 2, 3, 4, 5, 6, 7, 8, 9];
682 let h = histogram(&data, 5);
683 assert_eq!(h.len(), 5);
684 let total: u32 = h.iter().sum();
685 assert_eq!(total, 10);
686 }
687
688 #[test]
689 fn test_histogram_empty_data() {
690 let h = histogram(&[], 4);
691 assert_eq!(h, vec![0, 0, 0, 0]);
692 }
693
694 #[test]
695 fn test_histogram_all_same() {
696 let data = vec![5u32; 10];
697 let h = histogram(&data, 3);
698 assert_eq!(h.iter().sum::<u32>(), 10);
699 }
700
701 #[test]
704 fn test_counting_sort_basic() {
705 let mut data = vec![3u32, 1, 4, 1, 5, 9, 2, 6];
706 counting_sort(&mut data, 9);
707 for i in 0..data.len() - 1 {
708 assert!(data[i] <= data[i + 1]);
709 }
710 }
711
712 #[test]
713 fn test_counting_sort_empty() {
714 let mut data: Vec<u32> = vec![];
715 counting_sort(&mut data, 10);
716 assert!(data.is_empty());
717 }
718
719 #[test]
720 fn test_counting_sort_single() {
721 let mut data = vec![7u32];
722 counting_sort(&mut data, 10);
723 assert_eq!(data, vec![7]);
724 }
725
726 #[test]
727 fn test_counting_sort_duplicates() {
728 let mut data = vec![2u32, 2, 2, 1, 1];
729 counting_sort(&mut data, 2);
730 assert_eq!(data, vec![1, 1, 2, 2, 2]);
731 }
732
733 #[test]
734 fn test_counting_sort_all_zero() {
735 let mut data = vec![0u32; 5];
736 counting_sort(&mut data, 0);
737 assert_eq!(data, vec![0u32; 5]);
738 }
739
740 #[test]
743 fn test_morton_sort_3d_basic() {
744 let mut points = vec![
745 [1.0f32, 0.0, 0.0],
746 [0.0, 0.0, 0.0],
747 [0.0, 1.0, 0.0],
748 [1.0, 1.0, 0.0],
749 ];
750 morton_sort_3d(&mut points);
751 assert_eq!(points[0], [0.0, 0.0, 0.0]);
753 }
754
755 #[test]
756 fn test_morton_sort_3d_empty() {
757 let mut points: Vec<[f32; 3]> = vec![];
758 morton_sort_3d(&mut points);
759 assert!(points.is_empty());
760 }
761
762 #[test]
763 fn test_morton_sort_3d_single() {
764 let mut points = vec![[1.0f32, 2.0, 3.0]];
765 morton_sort_3d(&mut points);
766 assert_eq!(points, vec![[1.0, 2.0, 3.0]]);
767 }
768
769 #[test]
770 fn test_morton3_origin() {
771 assert_eq!(morton3(0, 0, 0), 0);
772 }
773
774 #[test]
775 fn test_morton3_unit_x() {
776 let code = morton3(1, 0, 0);
778 assert_ne!(code, 0);
779 }
780
781 #[test]
782 fn test_spread_bits_zero() {
783 assert_eq!(spread_bits(0), 0);
784 }
785
786 #[test]
787 fn test_spread_bits_one() {
788 assert_eq!(spread_bits(1) & 1, 1);
790 }
791
792 #[test]
795 fn test_gpu_sort_buffer_sort_pairs_basic() {
796 let keys = vec![3u32, 1, 4, 1, 5, 9, 2, 6];
797 let values: Vec<u32> = (0..keys.len() as u32).collect();
798 let mut buf = GpuSortBuffer::new(keys, values);
799 buf.sort_pairs();
800 for i in 0..buf.keys.len() - 1 {
801 assert!(buf.keys[i] <= buf.keys[i + 1]);
802 }
803 }
804
805 #[test]
806 fn test_gpu_sort_buffer_empty() {
807 let mut buf = GpuSortBuffer::empty();
808 buf.sort_pairs();
809 assert!(buf.is_empty());
810 }
811
812 #[test]
813 fn test_gpu_sort_buffer_push() {
814 let mut buf = GpuSortBuffer::empty();
815 buf.push(5, 100);
816 buf.push(2, 200);
817 assert_eq!(buf.len(), 2);
818 buf.sort_pairs();
819 assert_eq!(buf.keys[0], 2);
820 assert_eq!(buf.values[0], 200);
821 }
822
823 #[test]
824 fn test_gpu_sort_buffer_values_follow_keys() {
825 let keys = vec![30u32, 10, 20];
826 let values = vec![3u32, 1, 2];
827 let mut buf = GpuSortBuffer::new(keys, values);
828 buf.sort_pairs();
829 assert_eq!(buf.keys, vec![10, 20, 30]);
830 assert_eq!(buf.values, vec![1, 2, 3]);
831 }
832
833 #[test]
834 fn test_gpu_sort_buffer_len_is_empty() {
835 let buf = GpuSortBuffer::empty();
836 assert_eq!(buf.len(), 0);
837 assert!(buf.is_empty());
838 }
839
840 #[test]
843 fn test_parallel_merge_basic() {
844 let left = vec![1.0f32, 3.0, 5.0];
845 let right = vec![2.0f32, 4.0, 6.0];
846 let merged = parallel_merge(&left, &right);
847 assert_eq!(merged, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
848 }
849
850 #[test]
851 fn test_parallel_merge_empty_left() {
852 let merged = parallel_merge(&[], &[1.0f32, 2.0]);
853 assert_eq!(merged, vec![1.0, 2.0]);
854 }
855
856 #[test]
857 fn test_parallel_merge_empty_right() {
858 let merged = parallel_merge(&[1.0f32, 2.0], &[]);
859 assert_eq!(merged, vec![1.0, 2.0]);
860 }
861
862 #[test]
863 fn test_parallel_merge_both_empty() {
864 let merged: Vec<f32> = parallel_merge(&[], &[]);
865 assert!(merged.is_empty());
866 }
867
868 #[test]
869 fn test_parallel_merge_unequal_lengths() {
870 let left = vec![1.0f32, 10.0];
871 let right = vec![2.0f32, 3.0, 4.0, 5.0];
872 let merged = parallel_merge(&left, &right);
873 assert_eq!(merged.len(), 6);
874 for i in 0..merged.len() - 1 {
875 assert!(merged[i] <= merged[i + 1]);
876 }
877 }
878
879 #[test]
880 fn test_parallel_merge_duplicates() {
881 let left = vec![1.0f32, 2.0, 2.0];
882 let right = vec![2.0f32, 3.0];
883 let merged = parallel_merge(&left, &right);
884 assert_eq!(merged.len(), 5);
885 for i in 0..merged.len() - 1 {
886 assert!(merged[i] <= merged[i + 1]);
887 }
888 }
889}