Skip to content

deduplicate Index fns #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 2 additions & 42 deletions src/double_priority_queue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ pub mod iterators;
#[cfg(not(feature = "std"))]
use std::vec::Vec;

use crate::better_to_rebuild;
use crate::core_iterators::*;
use crate::store::{left, level, parent, right};
use crate::store::{Index, Position, Store};
use crate::TryReserveError;
use iterators::*;
Expand Down Expand Up @@ -1218,48 +1220,6 @@ where
}
}

/// Compute the index of the left child of an item from its index
#[inline(always)]
const fn left(i: Position) -> Position {
Position((i.0 * 2) + 1)
}
/// Compute the index of the right child of an item from its index
#[inline(always)]
const fn right(i: Position) -> Position {
Position((i.0 * 2) + 2)
}
/// Compute the index of the parent element in the heap from its index
#[inline(always)]
const fn parent(i: Position) -> Position {
Position((i.0 - 1) / 2)
}

// Compute the level of a node from its index
#[inline(always)]
const fn level(i: Position) -> usize {
log2_fast(i.0 + 1)
}

#[inline(always)]
const fn log2_fast(x: usize) -> usize {
(usize::BITS - x.leading_zeros() - 1) as usize
}

// `rebuild` takes O(len1 + len2) operations
// and about 2 * (len1 + len2) comparisons in the worst case
// while `extend` takes O(len2 * log_2(len1)) operations
// and about 1 * len2 * log_2(len1) comparisons in the worst case,
// assuming len1 >= len2.
fn better_to_rebuild(len1: usize, len2: usize) -> bool {
// log(1) == 0, so the inequation always falsy
// log(0) is inapplicable and produces panic
if len1 <= 1 {
return false;
}

2 * (len1 + len2) < len2 * log2_fast(len1)
}

#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
mod serde {
Expand Down
16 changes: 16 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ mod store;

pub use crate::double_priority_queue::DoublePriorityQueue;
pub use crate::priority_queue::PriorityQueue;
use crate::store::log2_fast;

use indexmap::TryReserveError as IndexMapTryReserveError;
use std::collections::TryReserveError as StdTryReserveError;
Expand Down Expand Up @@ -161,3 +162,18 @@ impl From<IndexMapTryReserveError> for TryReserveError {
}
}
}

// `rebuild` takes O(len1 + len2) operations
// and about 2 * (len1 + len2) comparisons in the worst case
// while `extend` takes O(len2 * log_2(len1)) operations
// and about 1 * len2 * log_2(len1) comparisons in the worst case,
// assuming len1 >= len2.
fn better_to_rebuild(len1: usize, len2: usize) -> bool {
// log(1) == 0, so the inequation always falsy
// log(0) is inapplicable and produces panic
if len1 <= 1 {
return false;
}

2 * (len1 + len2) < len2 * log2_fast(len1)
}
38 changes: 2 additions & 36 deletions src/priority_queue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ pub mod iterators;
#[cfg(not(feature = "std"))]
use std::vec::Vec;

use crate::better_to_rebuild;
use crate::core_iterators::*;
use crate::store::{left, parent, right};
use crate::store::{Index, Position, Store};
use crate::TryReserveError;
use iterators::*;
Expand Down Expand Up @@ -977,42 +979,6 @@ where
}
}

/// Compute the index of the left child of an item from its index
#[inline(always)]
const fn left(i: Position) -> Position {
Position((i.0 * 2) + 1)
}
/// Compute the index of the right child of an item from its index
#[inline(always)]
const fn right(i: Position) -> Position {
Position((i.0 * 2) + 2)
}
/// Compute the index of the parent element in the heap from its index
#[inline(always)]
const fn parent(i: Position) -> Position {
Position((i.0 - 1) / 2)
}

#[inline(always)]
const fn log2_fast(x: usize) -> usize {
(usize::BITS - x.leading_zeros() - 1) as usize
}

// `rebuild` takes O(len1 + len2) operations
// and about 2 * (len1 + len2) comparisons in the worst case
// while `extend` takes O(len2 * log_2(len1)) operations
// and about 1 * len2 * log_2(len1) comparisons in the worst case,
// assuming len1 >= len2.
fn better_to_rebuild(len1: usize, len2: usize) -> bool {
// log(1) == 0, so the inequation always falsy
// log(0) is inapplicable and produces panic
if len1 <= 1 {
return false;
}

2 * (len1 + len2) < len2 * log2_fast(len1)
}

#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
mod serde {
Expand Down
28 changes: 28 additions & 0 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,38 @@ use indexmap::map::{IndexMap, MutableKeys};
/// The Index of the element in the Map
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
pub(crate) struct Index(pub usize);

/// The Position of the element in the Heap
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
pub(crate) struct Position(pub usize);

/// Compute the index of the left child of an item from its index
#[inline(always)]
pub(crate) const fn left(i: Position) -> Position {
Position((i.0 * 2) + 1)
}
/// Compute the index of the right child of an item from its index
#[inline(always)]
pub(crate) const fn right(i: Position) -> Position {
Position((i.0 * 2) + 2)
}
/// Compute the index of the parent element in the heap from its index
#[inline(always)]
pub(crate) const fn parent(i: Position) -> Position {
Position((i.0 - 1) / 2)
}

// Compute the level of a node from its index
#[inline(always)]
pub(crate) const fn level(i: Position) -> usize {
log2_fast(i.0 + 1)
}

#[inline(always)]
pub(crate) const fn log2_fast(x: usize) -> usize {
(usize::BITS - x.leading_zeros() - 1) as usize
}

/// Internal storage of PriorityQueue and DoublePriorityQueue
#[derive(Clone)]
#[cfg(feature = "std")]
Expand Down