struct StaticSearchTree<T, const B: usize> {
values: Vec<SearchBlock<T, B>>,
len: usize,
maximum: T,
levels: Vec<Vec<SearchBlock<T, B>>>,
backend: SimdBackend,
}Fields§
§values: Vec<SearchBlock<T, B>>§len: usize§maximum: T§levels: Vec<Vec<SearchBlock<T, B>>>§backend: SimdBackendImplementations§
Source§impl<T: Copy + Ord, const B: usize> StaticSearchTree<T, B>
impl<T: Copy + Ord, const B: usize> StaticSearchTree<T, B>
Sourcefn build<K>(
values: &[K],
sentinel: T,
maximum_encoded: u128,
convert: impl Fn(u128) -> T,
backend: SimdBackend,
) -> Selfwhere
K: SimdKey,
fn build<K>(
values: &[K],
sentinel: T,
maximum_encoded: u128,
convert: impl Fn(u128) -> T,
backend: SimdBackend,
) -> Selfwhere
K: SimdKey,
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 895-901)
885 fn build(values: &[K], backend: SimdBackend, direct: bool) -> Self {
886 assert!(matches!(K::BITS, 8 | 16 | 32 | 64 | 128));
887 assert!(values.windows(2).all(|pair| pair[0] <= pair[1]));
888 let len = values.len();
889 let storage = match K::BITS {
890 8 => StaticSearchStorage::Direct(DirectStaticSearch::build(values, K::BITS)),
891 16 => {
892 if direct {
893 StaticSearchStorage::Direct(DirectStaticSearch::build(values, K::BITS))
894 } else {
895 StaticSearchStorage::U16(StaticSearchTree::build(
896 values,
897 u16::MAX,
898 u16::MAX as u128,
899 |value| value as u16,
900 backend,
901 ))
902 }
903 }
904 32 => StaticSearchStorage::U32(StaticSearchTree::build(
905 values,
906 u32::MAX,
907 u32::MAX as u128,
908 |value| value as u32,
909 backend,
910 )),
911 64 => StaticSearchStorage::U64(StaticSearchTree::build(
912 values,
913 u64::MAX,
914 u64::MAX as u128,
915 |value| value as u64,
916 backend,
917 )),
918 128 => StaticSearchStorage::U128(StaticSearchTree::build(
919 values,
920 u128::MAX,
921 u128::MAX,
922 |value| value,
923 backend,
924 )),
925 _ => unreachable!(),
926 };
927 Self {
928 storage,
929 len,
930 marker: PhantomData,
931 }
932 }Sourcefn descend<F>(&self, value: T, position: F) -> usize
fn descend<F>(&self, value: T, position: F) -> usize
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 333-335)
332 fn lower_bound_scalar(&self, value: T) -> usize {
333 self.descend(value, |values, value| {
334 values.partition_point(|¤t| current < value)
335 })
336 }
337
338 #[inline(always)]
339 fn upper_bound_scalar(&self, value: T) -> usize {
340 self.descend(value, |values, value| {
341 values.partition_point(|¤t| current <= value)
342 })
343 }
344
345 #[inline(always)]
346 fn lower_bound_batch_scalar(&self, values: &[T; 16]) -> [usize; 16] {
347 self.descend_batch(values, |values, value| {
348 values.partition_point(|¤t| current < value)
349 })
350 }
351
352 #[inline(always)]
353 fn upper_bound_batch_scalar(&self, values: &[T; 16]) -> [usize; 16] {
354 self.descend_batch(values, |values, value| {
355 values.partition_point(|¤t| current <= value)
356 })
357 }
358}
359
360macro_rules! impl_static_search_tree {
361 (
362 $value:ty,
363 $branch:expr,
364 $first_ge_avx2:ident,
365 $first_gt_avx2:ident,
366 $first_ge_avx512:ident,
367 $first_gt_avx512:ident,
368 $avx512_features:literal
369 ) => {
370 impl StaticSearchTree<$value, $branch> {
371 #[inline]
372 fn lower_bound(&self, value: $value) -> usize {
373 if self.len == 0 || value > self.maximum {
374 return self.len;
375 }
376 #[cfg(target_arch = "x86_64")]
377 return match self.backend {
378 SimdBackend::Scalar => self.lower_bound_scalar(value),
379 // SAFETY: `simd_backend` only selects supported instruction sets. Tests and
380 // standalone benchmarks pass supported backends to the private constructor.
381 SimdBackend::Avx2 => unsafe { self.lower_bound_avx2(value) },
382 // SAFETY: same as above.
383 SimdBackend::Avx512 => unsafe { self.lower_bound_avx512(value) },
384 };
385 #[cfg(not(target_arch = "x86_64"))]
386 self.lower_bound_scalar(value)
387 }
388
389 #[inline]
390 fn upper_bound(&self, value: $value) -> usize {
391 if self.len == 0 {
392 return 0;
393 }
394 if value >= self.maximum {
395 return self.len;
396 }
397 #[cfg(target_arch = "x86_64")]
398 return match self.backend {
399 SimdBackend::Scalar => self.upper_bound_scalar(value),
400 // SAFETY: `simd_backend` only selects supported instruction sets. Tests and
401 // standalone benchmarks pass supported backends to the private constructor.
402 SimdBackend::Avx2 => unsafe { self.upper_bound_avx2(value) },
403 // SAFETY: same as above.
404 SimdBackend::Avx512 => unsafe { self.upper_bound_avx512(value) },
405 };
406 #[cfg(not(target_arch = "x86_64"))]
407 self.upper_bound_scalar(value)
408 }
409
410 #[inline]
411 fn contains(&self, value: $value) -> bool {
412 let index = self.lower_bound(value);
413 index < self.len && self.get(index) == value
414 }
415
416 #[inline]
417 fn lower_bound_batch(&self, values: &[$value; 16]) -> [usize; 16] {
418 #[cfg(target_arch = "x86_64")]
419 if self.backend == SimdBackend::Avx512 {
420 // SAFETY: construction selects a supported instruction set.
421 return unsafe { self.lower_bound_batch_avx512(values) };
422 }
423 bound_batch!(lower, self, values, {
424 #[cfg(target_arch = "x86_64")]
425 let result = if self.backend == SimdBackend::Avx2 {
426 // SAFETY: same as above.
427 unsafe { self.lower_bound_batch_avx2(&values) }
428 } else {
429 self.lower_bound_batch_scalar(&values)
430 };
431 #[cfg(not(target_arch = "x86_64"))]
432 let result = self.lower_bound_batch_scalar(&values);
433 result
434 })
435 }
436
437 #[inline]
438 fn upper_bound_batch(&self, values: &[$value; 16]) -> [usize; 16] {
439 #[cfg(target_arch = "x86_64")]
440 if self.backend == SimdBackend::Avx512 {
441 // SAFETY: construction selects a supported instruction set.
442 return unsafe { self.upper_bound_batch_avx512(values) };
443 }
444 bound_batch!(upper, self, values, {
445 #[cfg(target_arch = "x86_64")]
446 let result = if self.backend == SimdBackend::Avx2 {
447 // SAFETY: same as above.
448 unsafe { self.upper_bound_batch_avx2(&values) }
449 } else {
450 self.upper_bound_batch_scalar(&values)
451 };
452 #[cfg(not(target_arch = "x86_64"))]
453 let result = self.upper_bound_batch_scalar(&values);
454 result
455 })
456 }
457
458 #[cfg(target_arch = "x86_64")]
459 #[target_feature(enable = "avx2")]
460 unsafe fn lower_bound_avx2(&self, value: $value) -> usize {
461 self.descend(value, |values, value| unsafe {
462 simd::$first_ge_avx2(values, value)
463 })
464 }
465
466 #[cfg(target_arch = "x86_64")]
467 #[target_feature(enable = "avx2")]
468 unsafe fn upper_bound_avx2(&self, value: $value) -> usize {
469 self.descend(value, |values, value| unsafe {
470 simd::$first_gt_avx2(values, value)
471 })
472 }
473
474 #[cfg(target_arch = "x86_64")]
475 #[target_feature(enable = "avx2")]
476 unsafe fn lower_bound_batch_avx2(&self, values: &[$value; 16]) -> [usize; 16] {
477 self.descend_batch(values, |values, value| unsafe {
478 simd::$first_ge_avx2(values, value)
479 })
480 }
481
482 #[cfg(target_arch = "x86_64")]
483 #[target_feature(enable = "avx2")]
484 unsafe fn upper_bound_batch_avx2(&self, values: &[$value; 16]) -> [usize; 16] {
485 self.descend_batch(values, |values, value| unsafe {
486 simd::$first_gt_avx2(values, value)
487 })
488 }
489
490 #[cfg(target_arch = "x86_64")]
491 #[target_feature(enable = $avx512_features)]
492 unsafe fn lower_bound_avx512(&self, value: $value) -> usize {
493 self.descend(value, |values, value| unsafe {
494 simd::$first_ge_avx512(values, value)
495 })
496 }
497
498 #[cfg(target_arch = "x86_64")]
499 #[target_feature(enable = $avx512_features)]
500 unsafe fn upper_bound_avx512(&self, value: $value) -> usize {
501 self.descend(value, |values, value| unsafe {
502 simd::$first_gt_avx512(values, value)
503 })
504 }
505
506 #[cfg(target_arch = "x86_64")]
507 #[target_feature(enable = $avx512_features)]
508 unsafe fn lower_bound_batch_avx512(&self, values: &[$value; 16]) -> [usize; 16] {
509 bound_batch!(
510 lower,
511 self,
512 values,
513 self.descend_batch(&values, |values, value| unsafe {
514 simd::$first_ge_avx512(values, value)
515 })
516 )
517 }
518
519 #[cfg(target_arch = "x86_64")]
520 #[target_feature(enable = $avx512_features)]
521 unsafe fn upper_bound_batch_avx512(&self, values: &[$value; 16]) -> [usize; 16] {
522 bound_batch!(
523 upper,
524 self,
525 values,
526 self.descend_batch(&values, |values, value| unsafe {
527 simd::$first_gt_avx512(values, value)
528 })
529 )
530 }
531 }
532 };
533}
534
535impl_static_search_tree!(
536 u16,
537 32,
538 first_ge_u16x32_avx2,
539 first_gt_u16x32_avx2,
540 first_ge_u16x32_avx512,
541 first_gt_u16x32_avx512,
542 "avx512f,avx512bw"
543);
544impl_static_search_tree!(
545 u32,
546 16,
547 first_ge_u32x16_avx2,
548 first_gt_u32x16_avx2,
549 first_ge_u32x16_avx512,
550 first_gt_u32x16_avx512,
551 "avx512f"
552);
553impl_static_search_tree!(
554 u64,
555 8,
556 first_ge_u64x8_avx2,
557 first_gt_u64x8_avx2,
558 first_ge_u64x8_avx512,
559 first_gt_u64x8_avx512,
560 "avx512f"
561);
562
563impl StaticSearchTree<u128, 4> {
564 #[inline]
565 fn lower_bound(&self, value: u128) -> usize {
566 if self.len == 0 || value > self.maximum {
567 self.len
568 } else {
569 self.descend(value, |values, value| {
570 (values[0] < value) as usize
571 + (values[1] < value) as usize
572 + (values[2] < value) as usize
573 + (values[3] < value) as usize
574 })
575 }
576 }
577
578 #[inline]
579 fn upper_bound(&self, value: u128) -> usize {
580 if self.len == 0 || value >= self.maximum {
581 self.len
582 } else {
583 self.descend(value, |values, value| {
584 (values[0] <= value) as usize
585 + (values[1] <= value) as usize
586 + (values[2] <= value) as usize
587 + (values[3] <= value) as usize
588 })
589 }
590 }Sourcefn descend_batch<F>(&self, values: &[T; 16], position: F) -> [usize; 16]
fn descend_batch<F>(&self, values: &[T; 16], position: F) -> [usize; 16]
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 347-349)
346 fn lower_bound_batch_scalar(&self, values: &[T; 16]) -> [usize; 16] {
347 self.descend_batch(values, |values, value| {
348 values.partition_point(|¤t| current < value)
349 })
350 }
351
352 #[inline(always)]
353 fn upper_bound_batch_scalar(&self, values: &[T; 16]) -> [usize; 16] {
354 self.descend_batch(values, |values, value| {
355 values.partition_point(|¤t| current <= value)
356 })
357 }
358}
359
360macro_rules! impl_static_search_tree {
361 (
362 $value:ty,
363 $branch:expr,
364 $first_ge_avx2:ident,
365 $first_gt_avx2:ident,
366 $first_ge_avx512:ident,
367 $first_gt_avx512:ident,
368 $avx512_features:literal
369 ) => {
370 impl StaticSearchTree<$value, $branch> {
371 #[inline]
372 fn lower_bound(&self, value: $value) -> usize {
373 if self.len == 0 || value > self.maximum {
374 return self.len;
375 }
376 #[cfg(target_arch = "x86_64")]
377 return match self.backend {
378 SimdBackend::Scalar => self.lower_bound_scalar(value),
379 // SAFETY: `simd_backend` only selects supported instruction sets. Tests and
380 // standalone benchmarks pass supported backends to the private constructor.
381 SimdBackend::Avx2 => unsafe { self.lower_bound_avx2(value) },
382 // SAFETY: same as above.
383 SimdBackend::Avx512 => unsafe { self.lower_bound_avx512(value) },
384 };
385 #[cfg(not(target_arch = "x86_64"))]
386 self.lower_bound_scalar(value)
387 }
388
389 #[inline]
390 fn upper_bound(&self, value: $value) -> usize {
391 if self.len == 0 {
392 return 0;
393 }
394 if value >= self.maximum {
395 return self.len;
396 }
397 #[cfg(target_arch = "x86_64")]
398 return match self.backend {
399 SimdBackend::Scalar => self.upper_bound_scalar(value),
400 // SAFETY: `simd_backend` only selects supported instruction sets. Tests and
401 // standalone benchmarks pass supported backends to the private constructor.
402 SimdBackend::Avx2 => unsafe { self.upper_bound_avx2(value) },
403 // SAFETY: same as above.
404 SimdBackend::Avx512 => unsafe { self.upper_bound_avx512(value) },
405 };
406 #[cfg(not(target_arch = "x86_64"))]
407 self.upper_bound_scalar(value)
408 }
409
410 #[inline]
411 fn contains(&self, value: $value) -> bool {
412 let index = self.lower_bound(value);
413 index < self.len && self.get(index) == value
414 }
415
416 #[inline]
417 fn lower_bound_batch(&self, values: &[$value; 16]) -> [usize; 16] {
418 #[cfg(target_arch = "x86_64")]
419 if self.backend == SimdBackend::Avx512 {
420 // SAFETY: construction selects a supported instruction set.
421 return unsafe { self.lower_bound_batch_avx512(values) };
422 }
423 bound_batch!(lower, self, values, {
424 #[cfg(target_arch = "x86_64")]
425 let result = if self.backend == SimdBackend::Avx2 {
426 // SAFETY: same as above.
427 unsafe { self.lower_bound_batch_avx2(&values) }
428 } else {
429 self.lower_bound_batch_scalar(&values)
430 };
431 #[cfg(not(target_arch = "x86_64"))]
432 let result = self.lower_bound_batch_scalar(&values);
433 result
434 })
435 }
436
437 #[inline]
438 fn upper_bound_batch(&self, values: &[$value; 16]) -> [usize; 16] {
439 #[cfg(target_arch = "x86_64")]
440 if self.backend == SimdBackend::Avx512 {
441 // SAFETY: construction selects a supported instruction set.
442 return unsafe { self.upper_bound_batch_avx512(values) };
443 }
444 bound_batch!(upper, self, values, {
445 #[cfg(target_arch = "x86_64")]
446 let result = if self.backend == SimdBackend::Avx2 {
447 // SAFETY: same as above.
448 unsafe { self.upper_bound_batch_avx2(&values) }
449 } else {
450 self.upper_bound_batch_scalar(&values)
451 };
452 #[cfg(not(target_arch = "x86_64"))]
453 let result = self.upper_bound_batch_scalar(&values);
454 result
455 })
456 }
457
458 #[cfg(target_arch = "x86_64")]
459 #[target_feature(enable = "avx2")]
460 unsafe fn lower_bound_avx2(&self, value: $value) -> usize {
461 self.descend(value, |values, value| unsafe {
462 simd::$first_ge_avx2(values, value)
463 })
464 }
465
466 #[cfg(target_arch = "x86_64")]
467 #[target_feature(enable = "avx2")]
468 unsafe fn upper_bound_avx2(&self, value: $value) -> usize {
469 self.descend(value, |values, value| unsafe {
470 simd::$first_gt_avx2(values, value)
471 })
472 }
473
474 #[cfg(target_arch = "x86_64")]
475 #[target_feature(enable = "avx2")]
476 unsafe fn lower_bound_batch_avx2(&self, values: &[$value; 16]) -> [usize; 16] {
477 self.descend_batch(values, |values, value| unsafe {
478 simd::$first_ge_avx2(values, value)
479 })
480 }
481
482 #[cfg(target_arch = "x86_64")]
483 #[target_feature(enable = "avx2")]
484 unsafe fn upper_bound_batch_avx2(&self, values: &[$value; 16]) -> [usize; 16] {
485 self.descend_batch(values, |values, value| unsafe {
486 simd::$first_gt_avx2(values, value)
487 })
488 }
489
490 #[cfg(target_arch = "x86_64")]
491 #[target_feature(enable = $avx512_features)]
492 unsafe fn lower_bound_avx512(&self, value: $value) -> usize {
493 self.descend(value, |values, value| unsafe {
494 simd::$first_ge_avx512(values, value)
495 })
496 }
497
498 #[cfg(target_arch = "x86_64")]
499 #[target_feature(enable = $avx512_features)]
500 unsafe fn upper_bound_avx512(&self, value: $value) -> usize {
501 self.descend(value, |values, value| unsafe {
502 simd::$first_gt_avx512(values, value)
503 })
504 }
505
506 #[cfg(target_arch = "x86_64")]
507 #[target_feature(enable = $avx512_features)]
508 unsafe fn lower_bound_batch_avx512(&self, values: &[$value; 16]) -> [usize; 16] {
509 bound_batch!(
510 lower,
511 self,
512 values,
513 self.descend_batch(&values, |values, value| unsafe {
514 simd::$first_ge_avx512(values, value)
515 })
516 )
517 }
518
519 #[cfg(target_arch = "x86_64")]
520 #[target_feature(enable = $avx512_features)]
521 unsafe fn upper_bound_batch_avx512(&self, values: &[$value; 16]) -> [usize; 16] {
522 bound_batch!(
523 upper,
524 self,
525 values,
526 self.descend_batch(&values, |values, value| unsafe {
527 simd::$first_gt_avx512(values, value)
528 })
529 )
530 }
531 }
532 };
533}
534
535impl_static_search_tree!(
536 u16,
537 32,
538 first_ge_u16x32_avx2,
539 first_gt_u16x32_avx2,
540 first_ge_u16x32_avx512,
541 first_gt_u16x32_avx512,
542 "avx512f,avx512bw"
543);
544impl_static_search_tree!(
545 u32,
546 16,
547 first_ge_u32x16_avx2,
548 first_gt_u32x16_avx2,
549 first_ge_u32x16_avx512,
550 first_gt_u32x16_avx512,
551 "avx512f"
552);
553impl_static_search_tree!(
554 u64,
555 8,
556 first_ge_u64x8_avx2,
557 first_gt_u64x8_avx2,
558 first_ge_u64x8_avx512,
559 first_gt_u64x8_avx512,
560 "avx512f"
561);
562
563impl StaticSearchTree<u128, 4> {
564 #[inline]
565 fn lower_bound(&self, value: u128) -> usize {
566 if self.len == 0 || value > self.maximum {
567 self.len
568 } else {
569 self.descend(value, |values, value| {
570 (values[0] < value) as usize
571 + (values[1] < value) as usize
572 + (values[2] < value) as usize
573 + (values[3] < value) as usize
574 })
575 }
576 }
577
578 #[inline]
579 fn upper_bound(&self, value: u128) -> usize {
580 if self.len == 0 || value >= self.maximum {
581 self.len
582 } else {
583 self.descend(value, |values, value| {
584 (values[0] <= value) as usize
585 + (values[1] <= value) as usize
586 + (values[2] <= value) as usize
587 + (values[3] <= value) as usize
588 })
589 }
590 }
591
592 #[inline]
593 fn contains(&self, value: u128) -> bool {
594 let index = self.lower_bound(value);
595 index < self.len && self.get(index) == value
596 }
597
598 #[inline]
599 fn lower_bound_batch(&self, values: &[u128; 16]) -> [usize; 16] {
600 bound_batch!(
601 lower,
602 self,
603 values,
604 self.descend_batch(&values, |values, value| {
605 (values[0] < value) as usize
606 + (values[1] < value) as usize
607 + (values[2] < value) as usize
608 + (values[3] < value) as usize
609 })
610 )
611 }
612
613 #[inline]
614 fn upper_bound_batch(&self, values: &[u128; 16]) -> [usize; 16] {
615 bound_batch!(
616 upper,
617 self,
618 values,
619 self.descend_batch(&values, |values, value| {
620 (values[0] <= value) as usize
621 + (values[1] <= value) as usize
622 + (values[2] <= value) as usize
623 + (values[3] <= value) as usize
624 })
625 )
626 }fn lower_bound_scalar(&self, value: T) -> usize
fn upper_bound_scalar(&self, value: T) -> usize
fn lower_bound_batch_scalar(&self, values: &[T; 16]) -> [usize; 16]
fn upper_bound_batch_scalar(&self, values: &[T; 16]) -> [usize; 16]
Source§impl StaticSearchTree<u16, 32>
impl StaticSearchTree<u16, 32>
Sourcefn lower_bound(&self, value: u16) -> usize
fn lower_bound(&self, value: u16) -> usize
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 674-676)
671 fn lower_bound(&self, value: u128) -> usize {
672 match self {
673 Self::Direct(search) => search.lower_bound(value),
674 Self::U16(search) => search.lower_bound(
675 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
676 ),
677 Self::U32(search) => search.lower_bound(
678 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
679 ),
680 Self::U64(search) => search.lower_bound(
681 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
682 ),
683 Self::U128(search) => search.lower_bound(value),
684 }
685 }
686
687 #[inline(always)]
688 fn upper_bound(&self, value: u128) -> usize {
689 match self {
690 Self::Direct(search) => search.upper_bound(value),
691 Self::U16(search) => search.upper_bound(
692 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
693 ),
694 Self::U32(search) => search.upper_bound(
695 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
696 ),
697 Self::U64(search) => search.upper_bound(
698 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
699 ),
700 Self::U128(search) => search.upper_bound(value),
701 }
702 }
703
704 #[inline(always)]
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }
720
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }Sourcefn upper_bound(&self, value: u16) -> usize
fn upper_bound(&self, value: u16) -> usize
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 691-693)
688 fn upper_bound(&self, value: u128) -> usize {
689 match self {
690 Self::Direct(search) => search.upper_bound(value),
691 Self::U16(search) => search.upper_bound(
692 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
693 ),
694 Self::U32(search) => search.upper_bound(
695 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
696 ),
697 Self::U64(search) => search.upper_bound(
698 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
699 ),
700 Self::U128(search) => search.upper_bound(value),
701 }
702 }
703
704 #[inline(always)]
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }
720
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }
758
759 fn upper_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
760 match self {
761 Self::Direct(search) => {
762 for (&value, position) in values.iter().zip(output) {
763 *position = search.upper_bound(value.encode());
764 }
765 }
766 Self::U16(search) => search_batch(
767 values,
768 output,
769 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
770 |value| search.upper_bound(value),
771 |values| search.upper_bound_batch(values),
772 ),
773 Self::U32(search) => search_batch(
774 values,
775 output,
776 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
777 |value| search.upper_bound(value),
778 |values| search.upper_bound_batch(values),
779 ),
780 Self::U64(search) => search_batch(
781 values,
782 output,
783 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
784 |value| search.upper_bound(value),
785 |values| search.upper_bound_batch(values),
786 ),
787 Self::U128(search) => search_batch(
788 values,
789 output,
790 |value| value,
791 |value| search.upper_bound(value),
792 |values| search.upper_bound_batch(values),
793 ),
794 }
795 }Sourcefn contains(&self, value: u16) -> bool
fn contains(&self, value: u16) -> bool
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 708-710)
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }Sourcefn lower_bound_batch(&self, values: &[u16; 16]) -> [usize; 16]
fn lower_bound_batch(&self, values: &[u16; 16]) -> [usize; 16]
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 733)
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }Sourcefn upper_bound_batch(&self, values: &[u16; 16]) -> [usize; 16]
fn upper_bound_batch(&self, values: &[u16; 16]) -> [usize; 16]
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 771)
759 fn upper_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
760 match self {
761 Self::Direct(search) => {
762 for (&value, position) in values.iter().zip(output) {
763 *position = search.upper_bound(value.encode());
764 }
765 }
766 Self::U16(search) => search_batch(
767 values,
768 output,
769 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
770 |value| search.upper_bound(value),
771 |values| search.upper_bound_batch(values),
772 ),
773 Self::U32(search) => search_batch(
774 values,
775 output,
776 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
777 |value| search.upper_bound(value),
778 |values| search.upper_bound_batch(values),
779 ),
780 Self::U64(search) => search_batch(
781 values,
782 output,
783 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
784 |value| search.upper_bound(value),
785 |values| search.upper_bound_batch(values),
786 ),
787 Self::U128(search) => search_batch(
788 values,
789 output,
790 |value| value,
791 |value| search.upper_bound(value),
792 |values| search.upper_bound_batch(values),
793 ),
794 }
795 }unsafe fn lower_bound_avx2(&self, value: u16) -> usize
unsafe fn upper_bound_avx2(&self, value: u16) -> usize
unsafe fn lower_bound_batch_avx2(&self, values: &[u16; 16]) -> [usize; 16]
unsafe fn upper_bound_batch_avx2(&self, values: &[u16; 16]) -> [usize; 16]
unsafe fn lower_bound_avx512(&self, value: u16) -> usize
unsafe fn upper_bound_avx512(&self, value: u16) -> usize
unsafe fn lower_bound_batch_avx512(&self, values: &[u16; 16]) -> [usize; 16]
unsafe fn upper_bound_batch_avx512(&self, values: &[u16; 16]) -> [usize; 16]
Source§impl StaticSearchTree<u32, 16>
impl StaticSearchTree<u32, 16>
Sourcefn lower_bound(&self, value: u32) -> usize
fn lower_bound(&self, value: u32) -> usize
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 677-679)
671 fn lower_bound(&self, value: u128) -> usize {
672 match self {
673 Self::Direct(search) => search.lower_bound(value),
674 Self::U16(search) => search.lower_bound(
675 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
676 ),
677 Self::U32(search) => search.lower_bound(
678 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
679 ),
680 Self::U64(search) => search.lower_bound(
681 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
682 ),
683 Self::U128(search) => search.lower_bound(value),
684 }
685 }
686
687 #[inline(always)]
688 fn upper_bound(&self, value: u128) -> usize {
689 match self {
690 Self::Direct(search) => search.upper_bound(value),
691 Self::U16(search) => search.upper_bound(
692 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
693 ),
694 Self::U32(search) => search.upper_bound(
695 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
696 ),
697 Self::U64(search) => search.upper_bound(
698 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
699 ),
700 Self::U128(search) => search.upper_bound(value),
701 }
702 }
703
704 #[inline(always)]
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }
720
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }Sourcefn upper_bound(&self, value: u32) -> usize
fn upper_bound(&self, value: u32) -> usize
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 694-696)
688 fn upper_bound(&self, value: u128) -> usize {
689 match self {
690 Self::Direct(search) => search.upper_bound(value),
691 Self::U16(search) => search.upper_bound(
692 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
693 ),
694 Self::U32(search) => search.upper_bound(
695 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
696 ),
697 Self::U64(search) => search.upper_bound(
698 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
699 ),
700 Self::U128(search) => search.upper_bound(value),
701 }
702 }
703
704 #[inline(always)]
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }
720
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }
758
759 fn upper_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
760 match self {
761 Self::Direct(search) => {
762 for (&value, position) in values.iter().zip(output) {
763 *position = search.upper_bound(value.encode());
764 }
765 }
766 Self::U16(search) => search_batch(
767 values,
768 output,
769 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
770 |value| search.upper_bound(value),
771 |values| search.upper_bound_batch(values),
772 ),
773 Self::U32(search) => search_batch(
774 values,
775 output,
776 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
777 |value| search.upper_bound(value),
778 |values| search.upper_bound_batch(values),
779 ),
780 Self::U64(search) => search_batch(
781 values,
782 output,
783 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
784 |value| search.upper_bound(value),
785 |values| search.upper_bound_batch(values),
786 ),
787 Self::U128(search) => search_batch(
788 values,
789 output,
790 |value| value,
791 |value| search.upper_bound(value),
792 |values| search.upper_bound_batch(values),
793 ),
794 }
795 }Sourcefn contains(&self, value: u32) -> bool
fn contains(&self, value: u32) -> bool
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 711-713)
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }Sourcefn lower_bound_batch(&self, values: &[u32; 16]) -> [usize; 16]
fn lower_bound_batch(&self, values: &[u32; 16]) -> [usize; 16]
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 740)
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }Sourcefn upper_bound_batch(&self, values: &[u32; 16]) -> [usize; 16]
fn upper_bound_batch(&self, values: &[u32; 16]) -> [usize; 16]
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 778)
759 fn upper_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
760 match self {
761 Self::Direct(search) => {
762 for (&value, position) in values.iter().zip(output) {
763 *position = search.upper_bound(value.encode());
764 }
765 }
766 Self::U16(search) => search_batch(
767 values,
768 output,
769 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
770 |value| search.upper_bound(value),
771 |values| search.upper_bound_batch(values),
772 ),
773 Self::U32(search) => search_batch(
774 values,
775 output,
776 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
777 |value| search.upper_bound(value),
778 |values| search.upper_bound_batch(values),
779 ),
780 Self::U64(search) => search_batch(
781 values,
782 output,
783 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
784 |value| search.upper_bound(value),
785 |values| search.upper_bound_batch(values),
786 ),
787 Self::U128(search) => search_batch(
788 values,
789 output,
790 |value| value,
791 |value| search.upper_bound(value),
792 |values| search.upper_bound_batch(values),
793 ),
794 }
795 }unsafe fn lower_bound_avx2(&self, value: u32) -> usize
unsafe fn upper_bound_avx2(&self, value: u32) -> usize
unsafe fn lower_bound_batch_avx2(&self, values: &[u32; 16]) -> [usize; 16]
unsafe fn upper_bound_batch_avx2(&self, values: &[u32; 16]) -> [usize; 16]
unsafe fn lower_bound_avx512(&self, value: u32) -> usize
unsafe fn upper_bound_avx512(&self, value: u32) -> usize
unsafe fn lower_bound_batch_avx512(&self, values: &[u32; 16]) -> [usize; 16]
unsafe fn upper_bound_batch_avx512(&self, values: &[u32; 16]) -> [usize; 16]
Source§impl StaticSearchTree<u64, 8>
impl StaticSearchTree<u64, 8>
Sourcefn lower_bound(&self, value: u64) -> usize
fn lower_bound(&self, value: u64) -> usize
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 680-682)
671 fn lower_bound(&self, value: u128) -> usize {
672 match self {
673 Self::Direct(search) => search.lower_bound(value),
674 Self::U16(search) => search.lower_bound(
675 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
676 ),
677 Self::U32(search) => search.lower_bound(
678 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
679 ),
680 Self::U64(search) => search.lower_bound(
681 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
682 ),
683 Self::U128(search) => search.lower_bound(value),
684 }
685 }
686
687 #[inline(always)]
688 fn upper_bound(&self, value: u128) -> usize {
689 match self {
690 Self::Direct(search) => search.upper_bound(value),
691 Self::U16(search) => search.upper_bound(
692 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
693 ),
694 Self::U32(search) => search.upper_bound(
695 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
696 ),
697 Self::U64(search) => search.upper_bound(
698 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
699 ),
700 Self::U128(search) => search.upper_bound(value),
701 }
702 }
703
704 #[inline(always)]
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }
720
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }Sourcefn upper_bound(&self, value: u64) -> usize
fn upper_bound(&self, value: u64) -> usize
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 697-699)
688 fn upper_bound(&self, value: u128) -> usize {
689 match self {
690 Self::Direct(search) => search.upper_bound(value),
691 Self::U16(search) => search.upper_bound(
692 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
693 ),
694 Self::U32(search) => search.upper_bound(
695 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
696 ),
697 Self::U64(search) => search.upper_bound(
698 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
699 ),
700 Self::U128(search) => search.upper_bound(value),
701 }
702 }
703
704 #[inline(always)]
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }
720
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }
758
759 fn upper_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
760 match self {
761 Self::Direct(search) => {
762 for (&value, position) in values.iter().zip(output) {
763 *position = search.upper_bound(value.encode());
764 }
765 }
766 Self::U16(search) => search_batch(
767 values,
768 output,
769 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
770 |value| search.upper_bound(value),
771 |values| search.upper_bound_batch(values),
772 ),
773 Self::U32(search) => search_batch(
774 values,
775 output,
776 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
777 |value| search.upper_bound(value),
778 |values| search.upper_bound_batch(values),
779 ),
780 Self::U64(search) => search_batch(
781 values,
782 output,
783 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
784 |value| search.upper_bound(value),
785 |values| search.upper_bound_batch(values),
786 ),
787 Self::U128(search) => search_batch(
788 values,
789 output,
790 |value| value,
791 |value| search.upper_bound(value),
792 |values| search.upper_bound_batch(values),
793 ),
794 }
795 }Sourcefn contains(&self, value: u64) -> bool
fn contains(&self, value: u64) -> bool
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (lines 714-716)
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }Sourcefn lower_bound_batch(&self, values: &[u64; 16]) -> [usize; 16]
fn lower_bound_batch(&self, values: &[u64; 16]) -> [usize; 16]
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 747)
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }Sourcefn upper_bound_batch(&self, values: &[u64; 16]) -> [usize; 16]
fn upper_bound_batch(&self, values: &[u64; 16]) -> [usize; 16]
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 785)
759 fn upper_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
760 match self {
761 Self::Direct(search) => {
762 for (&value, position) in values.iter().zip(output) {
763 *position = search.upper_bound(value.encode());
764 }
765 }
766 Self::U16(search) => search_batch(
767 values,
768 output,
769 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
770 |value| search.upper_bound(value),
771 |values| search.upper_bound_batch(values),
772 ),
773 Self::U32(search) => search_batch(
774 values,
775 output,
776 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
777 |value| search.upper_bound(value),
778 |values| search.upper_bound_batch(values),
779 ),
780 Self::U64(search) => search_batch(
781 values,
782 output,
783 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
784 |value| search.upper_bound(value),
785 |values| search.upper_bound_batch(values),
786 ),
787 Self::U128(search) => search_batch(
788 values,
789 output,
790 |value| value,
791 |value| search.upper_bound(value),
792 |values| search.upper_bound_batch(values),
793 ),
794 }
795 }unsafe fn lower_bound_avx2(&self, value: u64) -> usize
unsafe fn upper_bound_avx2(&self, value: u64) -> usize
unsafe fn lower_bound_batch_avx2(&self, values: &[u64; 16]) -> [usize; 16]
unsafe fn upper_bound_batch_avx2(&self, values: &[u64; 16]) -> [usize; 16]
unsafe fn lower_bound_avx512(&self, value: u64) -> usize
unsafe fn upper_bound_avx512(&self, value: u64) -> usize
unsafe fn lower_bound_batch_avx512(&self, values: &[u64; 16]) -> [usize; 16]
unsafe fn upper_bound_batch_avx512(&self, values: &[u64; 16]) -> [usize; 16]
Source§impl StaticSearchTree<u128, 4>
impl StaticSearchTree<u128, 4>
Sourcefn lower_bound(&self, value: u128) -> usize
fn lower_bound(&self, value: u128) -> usize
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 594)
593 fn contains(&self, value: u128) -> bool {
594 let index = self.lower_bound(value);
595 index < self.len && self.get(index) == value
596 }
597
598 #[inline]
599 fn lower_bound_batch(&self, values: &[u128; 16]) -> [usize; 16] {
600 bound_batch!(
601 lower,
602 self,
603 values,
604 self.descend_batch(&values, |values, value| {
605 (values[0] < value) as usize
606 + (values[1] < value) as usize
607 + (values[2] < value) as usize
608 + (values[3] < value) as usize
609 })
610 )
611 }
612
613 #[inline]
614 fn upper_bound_batch(&self, values: &[u128; 16]) -> [usize; 16] {
615 bound_batch!(
616 upper,
617 self,
618 values,
619 self.descend_batch(&values, |values, value| {
620 (values[0] <= value) as usize
621 + (values[1] <= value) as usize
622 + (values[2] <= value) as usize
623 + (values[3] <= value) as usize
624 })
625 )
626 }
627}
628
629fn search_batch<K, T>(
630 values: &[K],
631 output: &mut [usize],
632 convert: impl Fn(u128) -> T,
633 single: impl Fn(T) -> usize,
634 batch: impl Fn(&[T; 16]) -> [usize; 16],
635) where
636 K: SimdKey,
637 T: Copy,
638{
639 let mut offset = 0;
640 while offset + 16 <= values.len() {
641 let values = std::array::from_fn(|index| convert(values[offset + index].encode()));
642 output[offset..offset + 16].copy_from_slice(&batch(&values));
643 offset += 16;
644 }
645 let remaining = values.len() - offset;
646 if remaining >= 8 {
647 let mut encoded = [convert(values[offset].encode()); 16];
648 for index in 1..remaining {
649 encoded[index] = convert(values[offset + index].encode());
650 }
651 let positions = batch(&encoded);
652 output[offset..].copy_from_slice(&positions[..remaining]);
653 } else {
654 for (&value, position) in values[offset..].iter().zip(&mut output[offset..]) {
655 *position = single(convert(value.encode()));
656 }
657 }
658}
659
660#[derive(Clone, Debug)]
661enum StaticSearchStorage {
662 Direct(DirectStaticSearch),
663 U16(StaticSearchTree<u16, 32>),
664 U32(StaticSearchTree<u32, 16>),
665 U64(StaticSearchTree<u64, 8>),
666 U128(StaticSearchTree<u128, 4>),
667}
668
669impl StaticSearchStorage {
670 #[inline(always)]
671 fn lower_bound(&self, value: u128) -> usize {
672 match self {
673 Self::Direct(search) => search.lower_bound(value),
674 Self::U16(search) => search.lower_bound(
675 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
676 ),
677 Self::U32(search) => search.lower_bound(
678 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
679 ),
680 Self::U64(search) => search.lower_bound(
681 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
682 ),
683 Self::U128(search) => search.lower_bound(value),
684 }
685 }
686
687 #[inline(always)]
688 fn upper_bound(&self, value: u128) -> usize {
689 match self {
690 Self::Direct(search) => search.upper_bound(value),
691 Self::U16(search) => search.upper_bound(
692 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
693 ),
694 Self::U32(search) => search.upper_bound(
695 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
696 ),
697 Self::U64(search) => search.upper_bound(
698 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
699 ),
700 Self::U128(search) => search.upper_bound(value),
701 }
702 }
703
704 #[inline(always)]
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }
720
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }Sourcefn upper_bound(&self, value: u128) -> usize
fn upper_bound(&self, value: u128) -> usize
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 700)
688 fn upper_bound(&self, value: u128) -> usize {
689 match self {
690 Self::Direct(search) => search.upper_bound(value),
691 Self::U16(search) => search.upper_bound(
692 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
693 ),
694 Self::U32(search) => search.upper_bound(
695 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
696 ),
697 Self::U64(search) => search.upper_bound(
698 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
699 ),
700 Self::U128(search) => search.upper_bound(value),
701 }
702 }
703
704 #[inline(always)]
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }
720
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }
758
759 fn upper_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
760 match self {
761 Self::Direct(search) => {
762 for (&value, position) in values.iter().zip(output) {
763 *position = search.upper_bound(value.encode());
764 }
765 }
766 Self::U16(search) => search_batch(
767 values,
768 output,
769 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
770 |value| search.upper_bound(value),
771 |values| search.upper_bound_batch(values),
772 ),
773 Self::U32(search) => search_batch(
774 values,
775 output,
776 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
777 |value| search.upper_bound(value),
778 |values| search.upper_bound_batch(values),
779 ),
780 Self::U64(search) => search_batch(
781 values,
782 output,
783 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
784 |value| search.upper_bound(value),
785 |values| search.upper_bound_batch(values),
786 ),
787 Self::U128(search) => search_batch(
788 values,
789 output,
790 |value| value,
791 |value| search.upper_bound(value),
792 |values| search.upper_bound_batch(values),
793 ),
794 }
795 }Sourcefn contains(&self, value: u128) -> bool
fn contains(&self, value: u128) -> bool
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 717)
705 fn contains(&self, value: u128) -> bool {
706 match self {
707 Self::Direct(search) => search.contains(value),
708 Self::U16(search) => search.contains(
709 u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
710 ),
711 Self::U32(search) => search.contains(
712 u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
713 ),
714 Self::U64(search) => search.contains(
715 u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
716 ),
717 Self::U128(search) => search.contains(value),
718 }
719 }Sourcefn lower_bound_batch(&self, values: &[u128; 16]) -> [usize; 16]
fn lower_bound_batch(&self, values: &[u128; 16]) -> [usize; 16]
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 754)
721 fn lower_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
722 match self {
723 Self::Direct(search) => {
724 for (&value, position) in values.iter().zip(output) {
725 *position = search.lower_bound(value.encode());
726 }
727 }
728 Self::U16(search) => search_batch(
729 values,
730 output,
731 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
732 |value| search.lower_bound(value),
733 |values| search.lower_bound_batch(values),
734 ),
735 Self::U32(search) => search_batch(
736 values,
737 output,
738 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
739 |value| search.lower_bound(value),
740 |values| search.lower_bound_batch(values),
741 ),
742 Self::U64(search) => search_batch(
743 values,
744 output,
745 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
746 |value| search.lower_bound(value),
747 |values| search.lower_bound_batch(values),
748 ),
749 Self::U128(search) => search_batch(
750 values,
751 output,
752 |value| value,
753 |value| search.lower_bound(value),
754 |values| search.lower_bound_batch(values),
755 ),
756 }
757 }Sourcefn upper_bound_batch(&self, values: &[u128; 16]) -> [usize; 16]
fn upper_bound_batch(&self, values: &[u128; 16]) -> [usize; 16]
Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 792)
759 fn upper_bound_batch<K: SimdKey>(&self, values: &[K], output: &mut [usize]) {
760 match self {
761 Self::Direct(search) => {
762 for (&value, position) in values.iter().zip(output) {
763 *position = search.upper_bound(value.encode());
764 }
765 }
766 Self::U16(search) => search_batch(
767 values,
768 output,
769 |value| u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),
770 |value| search.upper_bound(value),
771 |values| search.upper_bound_batch(values),
772 ),
773 Self::U32(search) => search_batch(
774 values,
775 output,
776 |value| u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),
777 |value| search.upper_bound(value),
778 |values| search.upper_bound_batch(values),
779 ),
780 Self::U64(search) => search_batch(
781 values,
782 output,
783 |value| u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),
784 |value| search.upper_bound(value),
785 |values| search.upper_bound_batch(values),
786 ),
787 Self::U128(search) => search_batch(
788 values,
789 output,
790 |value| value,
791 |value| search.upper_bound(value),
792 |values| search.upper_bound_batch(values),
793 ),
794 }
795 }Trait Implementations§
Auto Trait Implementations§
impl<T, const B: usize> Freeze for StaticSearchTree<T, B>
impl<T, const B: usize> RefUnwindSafe for StaticSearchTree<T, B>where
Vec<SearchBlock<T, B>>: RefUnwindSafe,
T: RefUnwindSafe,
Vec<Vec<SearchBlock<T, B>>>: RefUnwindSafe,
impl<T, const B: usize> Send for StaticSearchTree<T, B>
impl<T, const B: usize> Sync for StaticSearchTree<T, B>
impl<T, const B: usize> Unpin for StaticSearchTree<T, B>
impl<T, const B: usize> UnsafeUnpin for StaticSearchTree<T, B>where
Vec<SearchBlock<T, B>>: UnsafeUnpin,
T: UnsafeUnpin,
Vec<Vec<SearchBlock<T, B>>>: UnsafeUnpin,
impl<T, const B: usize> UnwindSafe for StaticSearchTree<T, B>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more