Skip to main content

StaticSearchTree

Struct StaticSearchTree 

Source
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: SimdBackend

Implementations§

Source§

impl<T: Copy + Ord, const B: usize> StaticSearchTree<T, B>

Source

fn build<K>( values: &[K], sentinel: T, maximum_encoded: u128, convert: impl Fn(u128) -> T, backend: SimdBackend, ) -> Self
where 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    }
Source

fn descend<F>(&self, value: T, position: F) -> usize
where F: FnMut(&[T; B], T) -> 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(|&current| 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(|&current| 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(|&current| 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(|&current| 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    }
Source

fn get(&self, index: usize) -> T

Examples found in repository?
crates/competitive/src/data_structure/static_search.rs (line 595)
593    fn contains(&self, value: u128) -> bool {
594        let index = self.lower_bound(value);
595        index < self.len && self.get(index) == value
596    }
Source

fn descend_batch<F>(&self, values: &[T; 16], position: F) -> [usize; 16]
where F: FnMut(&[T; B], T) -> usize,

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(|&current| 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(|&current| 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    }
Source

fn lower_bound_scalar(&self, value: T) -> usize

Source

fn upper_bound_scalar(&self, value: T) -> usize

Source

fn lower_bound_batch_scalar(&self, values: &[T; 16]) -> [usize; 16]

Source

fn upper_bound_batch_scalar(&self, values: &[T; 16]) -> [usize; 16]

Source§

impl StaticSearchTree<u16, 32>

Source

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    }
Source

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    }
Source

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    }
Source

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    }
Source

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    }
Source

unsafe fn lower_bound_avx2(&self, value: u16) -> usize

Source

unsafe fn upper_bound_avx2(&self, value: u16) -> usize

Source

unsafe fn lower_bound_batch_avx2(&self, values: &[u16; 16]) -> [usize; 16]

Source

unsafe fn upper_bound_batch_avx2(&self, values: &[u16; 16]) -> [usize; 16]

Source

unsafe fn lower_bound_avx512(&self, value: u16) -> usize

Source

unsafe fn upper_bound_avx512(&self, value: u16) -> usize

Source

unsafe fn lower_bound_batch_avx512(&self, values: &[u16; 16]) -> [usize; 16]

Source

unsafe fn upper_bound_batch_avx512(&self, values: &[u16; 16]) -> [usize; 16]

Source§

impl StaticSearchTree<u32, 16>

Source

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    }
Source

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    }
Source

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    }
Source

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    }
Source

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    }
Source

unsafe fn lower_bound_avx2(&self, value: u32) -> usize

Source

unsafe fn upper_bound_avx2(&self, value: u32) -> usize

Source

unsafe fn lower_bound_batch_avx2(&self, values: &[u32; 16]) -> [usize; 16]

Source

unsafe fn upper_bound_batch_avx2(&self, values: &[u32; 16]) -> [usize; 16]

Source

unsafe fn lower_bound_avx512(&self, value: u32) -> usize

Source

unsafe fn upper_bound_avx512(&self, value: u32) -> usize

Source

unsafe fn lower_bound_batch_avx512(&self, values: &[u32; 16]) -> [usize; 16]

Source

unsafe fn upper_bound_batch_avx512(&self, values: &[u32; 16]) -> [usize; 16]

Source§

impl StaticSearchTree<u64, 8>

Source

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    }
Source

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    }
Source

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    }
Source

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    }
Source

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    }
Source

unsafe fn lower_bound_avx2(&self, value: u64) -> usize

Source

unsafe fn upper_bound_avx2(&self, value: u64) -> usize

Source

unsafe fn lower_bound_batch_avx2(&self, values: &[u64; 16]) -> [usize; 16]

Source

unsafe fn upper_bound_batch_avx2(&self, values: &[u64; 16]) -> [usize; 16]

Source

unsafe fn lower_bound_avx512(&self, value: u64) -> usize

Source

unsafe fn upper_bound_avx512(&self, value: u64) -> usize

Source

unsafe fn lower_bound_batch_avx512(&self, values: &[u64; 16]) -> [usize; 16]

Source

unsafe fn upper_bound_batch_avx512(&self, values: &[u64; 16]) -> [usize; 16]

Source§

impl StaticSearchTree<u128, 4>

Source

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    }
Source

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    }
Source

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    }
Source

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    }
Source

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§

Source§

impl<T: Clone, const B: usize> Clone for StaticSearchTree<T, B>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug, const B: usize> Debug for StaticSearchTree<T, B>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T, const B: usize> Freeze for StaticSearchTree<T, B>
where Vec<SearchBlock<T, B>>: Freeze, T: Freeze, Vec<Vec<SearchBlock<T, B>>>: Freeze,

§

impl<T, const B: usize> RefUnwindSafe for StaticSearchTree<T, B>

§

impl<T, const B: usize> Send for StaticSearchTree<T, B>
where Vec<SearchBlock<T, B>>: Send, T: Send, Vec<Vec<SearchBlock<T, B>>>: Send,

§

impl<T, const B: usize> Sync for StaticSearchTree<T, B>
where Vec<SearchBlock<T, B>>: Sync, T: Sync, Vec<Vec<SearchBlock<T, B>>>: Sync,

§

impl<T, const B: usize> Unpin for StaticSearchTree<T, B>
where Vec<SearchBlock<T, B>>: Unpin, T: Unpin, Vec<Vec<SearchBlock<T, B>>>: Unpin,

§

impl<T, const B: usize> UnsafeUnpin for StaticSearchTree<T, B>

§

impl<T, const B: usize> UnwindSafe for StaticSearchTree<T, B>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToArrayVecScalar for T

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.