diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..806d114 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,58 @@ +name: Rust + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + toolchain: ["stable"] + + steps: + - uses: actions/checkout@v4 + + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.toolchain }} + + - name: Install 32bit target + run: rustup target add i686-unknown-linux-musl + - name: Install wasm target + run: rustup target add wasm32v1-none + - name: Install miri + run: rustup component add --toolchain nightly-x86_64-unknown-linux-gnu miri + - name: Install no-std-check + run: cargo install cargo-no-std-check + + - name: Build + run: cargo build --verbose --features impl_all + - name: Build-32bit + run: cargo build --verbose --target i686-unknown-linux-musl + - name: Build-wasm + run: cargo build --verbose --no-default-features --target wasm32v1-none + + - name: Test + run: cargo test --verbose --features impl_all + - name: Test-32bit + run: cargo test --verbose --target i686-unknown-linux-musl + - name: Check-wasm + run: cargo check --verbose --no-default-features --target wasm32v1-none + + - name: Clippy + run: cargo clippy --features impl_all -- -D warnings --verbose + + - name: Miri + run: cargo +nightly miri test --verbose + + - name: NoStd + run: cargo +nightly no-std-check --no-default-features diff --git a/Cargo.toml b/Cargo.toml index d64bd3e..b422d51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,9 @@ [package] name = "orx-priority-queue" version = "1.7.0" -edition = "2021" +edition = "2024" authors = ["orxfun "] +readme = "README.md" description = "Priority queue traits and high performance d-ary heap implementations." license = "MIT OR Apache-2.0" repository = "https://github.com/orxfun/orx-priority-queue/" @@ -13,9 +14,10 @@ categories = ["algorithms", "data-structures", "mathematics", "no-std"] default = ["std"] std = [] impl_priority_queue = ["priority-queue"] +impl_all = ["impl_priority_queue"] [dependencies] -priority-queue = { version = "2.1", optional = true } +priority-queue = { version = "2.3", optional = true } [[bench]] diff --git a/README.md b/README.md index 6c74739..9497351 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Priority queue traits and high performance d-ary heap implementations. +> **no-std**: This crate supports **no-std**; however, *std* is added as a default feature. Please include with **no-default-features** for no-std use cases: `cargo add orx-priority-queue --no-default-features`. + ## A. Priority Queue Traits This crate aims to provide algorithms with the abstraction over priority queues. In order to achieve this, two traits are defined: **`PriorityQueue`** and **`PriorityQueueDecKey`**. The prior is a simple queue while the latter extends it by providing additional methods to change priorities of the items that already exist in the queue. @@ -52,6 +54,7 @@ In addition, queue implementations are provided in this crate for the following * `std::collections::BinaryHeap<(N, K)>` implements only `PriorityQueue`, * `priority_queue:PriorityQueue` implements both `PriorityQueue` and `PriorityQueueDecKey` * requires `--features impl_priority_queue` + * or `--features impl_all` This allows to use all the queue implementations interchangeably and pick the one fitting best to the use case. diff --git a/benches/basic_queue.rs b/benches/basic_queue.rs index 0beea82..df00be1 100644 --- a/benches/basic_queue.rs +++ b/benches/basic_queue.rs @@ -1,6 +1,6 @@ use criterion::{ - black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, BenchmarkId, - Criterion, + BenchmarkGroup, BenchmarkId, Criterion, black_box, criterion_group, criterion_main, + measurement::WallTime, }; use orx_priority_queue::*; use rand::prelude::*; @@ -16,12 +16,12 @@ impl TestData { let mut first_push = Vec::new(); for node in 0..n_first { - first_push.push((node, rng.gen())); + first_push.push((node, rng.random())); } let mut second_push = Vec::new(); for node in n_first..(n_first + n_second) { - second_push.push((node, rng.gen())); + second_push.push((node, rng.random())); } Self { diff --git a/benches/deckey_queue.rs b/benches/deckey_queue.rs index 2c75e22..b645899 100644 --- a/benches/deckey_queue.rs +++ b/benches/deckey_queue.rs @@ -1,6 +1,6 @@ use criterion::{ - black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, BenchmarkId, - Criterion, + BenchmarkGroup, BenchmarkId, Criterion, black_box, criterion_group, criterion_main, + measurement::WallTime, }; use orx_priority_queue::*; use rand::prelude::*; @@ -17,19 +17,19 @@ impl TestData { let mut push = Vec::new(); for node in 0..n_push { - push.push((node, rng.gen())); + push.push((node, rng.random())); } let mut first_deckey = Vec::new(); for _ in 0..n_deckey1 { - let node = rng.gen_range(0..n_push); - first_deckey.push((node, rng.gen())); + let node = rng.random_range(0..n_push); + first_deckey.push((node, rng.random())); } let mut second_deckey = Vec::new(); for _ in 0..n_deckey2 { - let node = rng.gen_range(0..n_push); - second_deckey.push((node, rng.gen())); + let node = rng.random_range(0..n_push); + second_deckey.push((node, rng.random())); } Self { diff --git a/benches/push_then_pop.rs b/benches/push_then_pop.rs index d5086af..d2ce93d 100644 --- a/benches/push_then_pop.rs +++ b/benches/push_then_pop.rs @@ -1,6 +1,6 @@ use criterion::{ - black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, BenchmarkId, - Criterion, + BenchmarkGroup, BenchmarkId, Criterion, black_box, criterion_group, criterion_main, + measurement::WallTime, }; use orx_priority_queue::*; use rand::prelude::*; @@ -16,12 +16,12 @@ impl TestData { let mut first_push = Vec::new(); for node in 0..n_first { - first_push.push((node, rng.gen())); + first_push.push((node, rng.random())); } let mut second_push_pop = Vec::new(); for node in n_first..(n_first + n_second) { - second_push_pop.push((node, rng.gen())); + second_push_pop.push((node, rng.random())); } Self { diff --git a/tests/daryheap.rs b/tests/daryheap.rs index d99acbb..f29104b 100644 --- a/tests/daryheap.rs +++ b/tests/daryheap.rs @@ -1,7 +1,6 @@ -mod priority_queue_tests; +#![cfg(not(miri))] -use orx_priority_queue::DaryHeap; -use priority_queue_tests::*; +mod priority_queue_tests; #[test] fn test_dary_forall() { @@ -17,6 +16,9 @@ fn test_dary_forall() { } fn test_dary_for() { + use orx_priority_queue::DaryHeap; + use priority_queue_tests::*; + let new_heap = DaryHeap::::default; test_len(new_heap()); diff --git a/tests/daryheap_of_indices.rs b/tests/daryheap_of_indices.rs index df55402..b0b9159 100644 --- a/tests/daryheap_of_indices.rs +++ b/tests/daryheap_of_indices.rs @@ -1,10 +1,8 @@ +#![cfg(not(miri))] + mod priority_queue_deckey_tests; mod priority_queue_tests; -use orx_priority_queue::DaryHeapOfIndices; -use priority_queue_deckey_tests::*; -use priority_queue_tests::*; - #[test] fn test_dary_forall() { test_dary_for::<2>(); @@ -19,6 +17,10 @@ fn test_dary_forall() { } fn test_dary_for() { + use orx_priority_queue::DaryHeapOfIndices; + use priority_queue_deckey_tests::*; + use priority_queue_tests::*; + let new_heap = || DaryHeapOfIndices::::with_index_bound(125); let change_key = [ diff --git a/tests/daryheap_with_map.rs b/tests/daryheap_with_map.rs index c41587b..46a2a52 100644 --- a/tests/daryheap_with_map.rs +++ b/tests/daryheap_with_map.rs @@ -1,10 +1,8 @@ +#![cfg(not(miri))] + mod priority_queue_deckey_tests; mod priority_queue_tests; -use orx_priority_queue::DaryHeapWithMap; -use priority_queue_deckey_tests::*; -use priority_queue_tests::*; - #[test] fn test_dary_forall() { test_dary_for::<2>(); @@ -19,6 +17,10 @@ fn test_dary_forall() { } fn test_dary_for() { + use orx_priority_queue::DaryHeapWithMap; + use priority_queue_deckey_tests::*; + use priority_queue_tests::*; + let new_heap = DaryHeapWithMap::::default; let change_key = [ diff --git a/tests/priority_queue_deckey_tests/change_key.rs b/tests/priority_queue_deckey_tests/change_key.rs index 0c440de..ed0ca61 100644 --- a/tests/priority_queue_deckey_tests/change_key.rs +++ b/tests/priority_queue_deckey_tests/change_key.rs @@ -19,23 +19,23 @@ where pq.clear(); assert!(pq.is_empty()); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let mut vec = Vec::new(); // push 100 for node in 0..LEN { - let priority = rng.gen(); + let priority = rng.random(); pq.push(node, priority); vec.push((node, priority)); } // change keys 100 times for _ in 0..LEN { - let node = rng.gen_range(0..LEN); + let node = rng.random_range(0..LEN); let old_key = vec[node].1; assert_eq!(Some(old_key), pq.key_of(&node)); - let new_key = rng.gen::() + let new_key = rng.random::() * match change_key { ChangeKeyMethod::Decrease => old_key, _ => 1.0, @@ -47,10 +47,10 @@ where vec[node] = (node, new_key); } ChangeKeyMethod::Update => { - let res_updkey = pq.update_key(&node, new_key); + let res_upd_key = pq.update_key(&node, new_key); assert_eq!( new_key < old_key, - matches!(res_updkey, ResUpdateKey::Decreased) + matches!(res_upd_key, ResUpdateKey::Decreased) ); vec[node] = (node, new_key); } diff --git a/tests/priority_queue_deckey_tests/change_key_or_push.rs b/tests/priority_queue_deckey_tests/change_key_or_push.rs index 4d00bca..339907c 100644 --- a/tests/priority_queue_deckey_tests/change_key_or_push.rs +++ b/tests/priority_queue_deckey_tests/change_key_or_push.rs @@ -18,13 +18,13 @@ where pq.clear(); assert!(pq.is_empty()); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let mut vec = (0..100).map(|_| None).collect_vec(); // push 100 for (node, vec_elem) in vec.iter_mut().enumerate() { if push_at_first_pass(node) { - let priority = rng.gen(); + let priority = rng.random(); pq.push(node, priority); *vec_elem = Some(priority); } @@ -32,11 +32,11 @@ where // change keys or push 300 times for _ in 0..300 { - let node = rng.gen_range(0..100); + let node = rng.random_range(0..100); let old_key = vec[node]; assert_eq!(old_key, pq.key_of(&node)); - let new_key = rng.gen::() + let new_key = rng.random::() * match change_key { ChangeKeyMethod::Decrease => old_key.unwrap_or(1.0), _ => 1.0, @@ -48,10 +48,10 @@ where vec[node] = Some(new_key); } ChangeKeyMethod::Update => { - let res_updkey_push = pq.update_key_or_push(&node, new_key); + let res_upd_key_push = pq.update_key_or_push(&node, new_key); assert_eq!( old_key.map(|old_key| new_key < old_key).unwrap_or(false), - matches!(res_updkey_push, ResUpdateKeyOrPush::Decreased) + matches!(res_upd_key_push, ResUpdateKeyOrPush::Decreased) ); vec[node] = Some(new_key); } diff --git a/tests/priority_queue_deckey_tests/key_of.rs b/tests/priority_queue_deckey_tests/key_of.rs index 37c8ddb..9a7f12a 100644 --- a/tests/priority_queue_deckey_tests/key_of.rs +++ b/tests/priority_queue_deckey_tests/key_of.rs @@ -9,11 +9,11 @@ where assert!(pq.is_empty()); assert_eq!(None, pq.key_of(&0)); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let mut vec = Vec::new(); for node in 0..100 { - let priority = rng.gen(); + let priority = rng.random(); pq.push(node, priority); vec.push(priority); } diff --git a/tests/priority_queue_deckey_tests/mixed.rs b/tests/priority_queue_deckey_tests/mixed.rs index 4d40a97..abda1e2 100644 --- a/tests/priority_queue_deckey_tests/mixed.rs +++ b/tests/priority_queue_deckey_tests/mixed.rs @@ -9,14 +9,14 @@ where { const INITIAL_LEN: usize = 10; const LEN: usize = 125; - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); pq.clear(); assert!(pq.is_empty()); for _ in 0..INITIAL_LEN { - let push = rng.gen_range(0..LEN); - let priority = rng.gen(); + let push = rng.random_range(0..LEN); + let priority = rng.random(); if !pq.contains(&push) { pq.push(push, priority); } @@ -25,21 +25,21 @@ where let num_drop = if pq.is_empty() { 0 } else { - rng.gen_range(0..5) + rng.random_range(0..5) }; let enqueued = pq.iter().map(|x| *x.node()).collect_vec(); let mut to_drop = HashSet::new(); for _ in 0..num_drop { - let ind = rng.gen_range(0..enqueued.len()); + let ind = rng.random_range(0..enqueued.len()); to_drop.insert(enqueued[ind]); } let mut to_push = vec![]; for _ in 0..to_drop.len() { - let num_push = rng.gen_range(0..5); + let num_push = rng.random_range(0..5); let mut to_push_for = vec![]; for _ in 0..num_push { - let ind = rng.gen_range(0..LEN); + let ind = rng.random_range(0..LEN); if !pq.contains(&ind) { to_push_for.push(ind); } @@ -54,7 +54,7 @@ where if pq.len() == LEN { break; } - let priority = rng.gen(); + let priority = rng.random(); if !pq.contains(push) { pq.push(*push, priority); } diff --git a/tests/priority_queue_deckey_tests/remove.rs b/tests/priority_queue_deckey_tests/remove.rs index e06a391..6aac159 100644 --- a/tests/priority_queue_deckey_tests/remove.rs +++ b/tests/priority_queue_deckey_tests/remove.rs @@ -11,11 +11,11 @@ where pq.clear(); assert!(pq.is_empty()); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let mut vec = Vec::new(); for node in 0..LEN { - let priority = rng.gen(); + let priority = rng.random(); pq.push(node, priority); vec.push(priority); } @@ -25,7 +25,7 @@ where // remove randomly ~60% let mut removed = HashSet::new(); for (node_to_rmv, key) in vec.iter().enumerate() { - let do_remove = rng.gen::() < 0.6; + let do_remove = rng.random::() < 0.6; if do_remove { let key_removed = pq.remove(&node_to_rmv); assert_eq!(key, &key_removed); diff --git a/tests/priority_queue_tests/as_slice.rs b/tests/priority_queue_tests/as_slice.rs index 6049b73..ba9952c 100644 --- a/tests/priority_queue_tests/as_slice.rs +++ b/tests/priority_queue_tests/as_slice.rs @@ -21,9 +21,9 @@ pub fn test_as_slice(mut pq: DaryHeap) { assert!(pq.is_empty()); let mut vec = vec![]; - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); for node in 0..N { - let priority = rng.gen(); + let priority = rng.random(); pq.push(node, priority); vec.push((node, priority)); } diff --git a/tests/priority_queue_tests/push_pop.rs b/tests/priority_queue_tests/push_pop.rs index e5a89e5..7a592a9 100644 --- a/tests/priority_queue_tests/push_pop.rs +++ b/tests/priority_queue_tests/push_pop.rs @@ -41,7 +41,7 @@ pub fn test_push_pop_randomized

(mut pq: P) where P: PriorityQueue, { - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); pq.clear(); assert!(pq.is_empty()); @@ -50,7 +50,7 @@ where // push 100 -> 0, ..., 99 for node in 0..100 { - let priority = rng.gen(); + let priority = rng.random(); pq.push(node, priority); vec.push((node, priority)); } @@ -78,7 +78,7 @@ where // push 25 -> 100, ..., 124 for node in 100..125 { - let priority = rng.gen(); + let priority = rng.random(); pq.push(node, priority); vec_remaining40.push((node, priority)); } diff --git a/tests/priority_queue_tests/push_then_pop.rs b/tests/priority_queue_tests/push_then_pop.rs index f9563b3..60cdab4 100644 --- a/tests/priority_queue_tests/push_then_pop.rs +++ b/tests/priority_queue_tests/push_then_pop.rs @@ -49,16 +49,16 @@ where pq.clear(); assert!(pq.is_empty()); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); for node in 0..N { - let priority = rng.gen(); + let priority = rng.random(); pq.push(node, priority); } let mut pq_pll = pq.clone(); // push & pull randomly for node in N..2 * N { - let key = rng.gen(); + let key = rng.random(); pq_pll.push(node, key); let popped_pll = pq_pll.pop().unwrap();