From b259ce8435b00b4925acaa2f6f8f795d2a135796 Mon Sep 17 00:00:00 2001 From: FreePhoenix888 Date: Thu, 25 May 2023 22:31:35 +0600 Subject: [PATCH] Remove inner folder and its dependencies --- Cargo.toml | 25 +- benches/bench.rs | 11 + rustfmt.toml | 6 + src/lib.rs | 34 ++- src/lists/absolute_circular_linked_list.rs | 15 +- src/lists/absolute_linked_list.rs | 7 +- src/lists/linked_list.rs | 2 +- src/lists/relative_circular_linked_list.rs | 15 +- src/lists/relative_doubly_linked_list.rs | 7 +- src/trees/mod.rs | 14 +- src/trees/new_v2.rs | 332 +++++++++++++++++++++ src/trees/no_recur_szb_tree.rs | 52 ++-- src/trees/szb_tree.rs | 41 +-- tests/prop.rs | 37 +++ 14 files changed, 506 insertions(+), 92 deletions(-) create mode 100644 benches/bench.rs create mode 100644 rustfmt.toml create mode 100644 src/trees/new_v2.rs create mode 100644 tests/prop.rs diff --git a/Cargo.toml b/Cargo.toml index c0504cd..f3d1007 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,14 +2,27 @@ name = "platform-trees" version = "0.1.0-beta.1" edition = "2018" -authors = ["uselesssgoddess", "Linksplatform Team "] -license = "LGPL-3.0" +authors = [ + "uselesssgoddess", + "Linksplatform Team " +] +license = "Unlicense" repository = "https://github.com/linksplatform/Collections.Methods" homepage = "https://github.com/linksplatform/Collections.Methods/rust" -description = """ -Trees methods for linksplatform -""" [dependencies] +tap = "1.0.1" funty = "2.0" -platform-data = { version = "0.1.0-beta.3", path = "../data-rs" } + +[dependencies.platform-data] +version = "0.1.0-beta.3" +git = "https://github.com/linksplatform/core-rs" +branch = "feature/f-oriented" + +[dev-dependencies] +criterion = "0.4.0" +proptest = "1.0.0" + +[[bench]] +name = "bench" +harness = false diff --git a/benches/bench.rs b/benches/bench.rs new file mode 100644 index 0000000..8c7c175 --- /dev/null +++ b/benches/bench.rs @@ -0,0 +1,11 @@ +use { + criterion::{criterion_group, criterion_main, Criterion, Throughput}, +}; + +pub fn bench(c: &mut Criterion) { + const MAGIC: usize = 1_000_000; + +} + +criterion_group!(benches, bench); +criterion_main!(benches); diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..e60c8f9 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,6 @@ +error_on_line_overflow = true +error_on_unformatted = true +version = "Two" + +imports_granularity = "One" +use_small_heuristics = "Max" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 514f1e5..e489982 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,37 @@ +#![feature(default_free_fn)] +#![feature(let_else)] + // fixme: #![no_std] +#![deny(unused_must_use)] mod lists; mod trees; -pub use lists::{ - AbsoluteCircularLinkedList, AbsoluteLinkedList, LinkedList, RelativeCircularLinkedList, - RelativeLinkedList, +pub use { + lists::{ + AbsoluteCircularLinkedList, AbsoluteLinkedList, LinkedList, RelativeCircularLinkedList, + RelativeLinkedList, + }, + trees::{new_v2, NoRecurSzbTree, SzbTree}, }; -pub use trees::{NoRecurSzbTree, SzbTree}; +macro_rules! named { + ($($name:ident => $val:expr)*) => { + $( + fn $name() -> Self { + Self::from_addr($val) + } + )* + }; +} + +// bridge to old api +pub trait LinkType: platform_data::LinkType + funty::Unsigned { + named! { + zero => 0 + one => 1 + two => 2 + } +} + +impl LinkType for All where All: platform_data::LinkType + funty::Unsigned {} diff --git a/src/lists/absolute_circular_linked_list.rs b/src/lists/absolute_circular_linked_list.rs index ee278f8..d3f9d6c 100644 --- a/src/lists/absolute_circular_linked_list.rs +++ b/src/lists/absolute_circular_linked_list.rs @@ -1,5 +1,4 @@ -use crate::AbsoluteLinkedList; -use platform_data::LinkType; +use crate::{AbsoluteLinkedList, LinkType}; pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { fn attach_before(&mut self, base_element: T, new_element: T) { @@ -28,7 +27,7 @@ pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { fn attach_as_first(&mut self, element: T) { let first = self.get_first(); - if first == T::funty(0) { + if first == T::zero() { self.set_first(element); self.set_last(element); self.set_previous(element, element); @@ -41,7 +40,7 @@ pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { fn attach_as_last(&mut self, element: T) { let last = self.get_last(); - if last == T::funty(0) { + if last == T::zero() { self.attach_as_first(element); } else { self.attach_after(last, element); @@ -52,8 +51,8 @@ pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { let element_previous = self.get_previous(element); let element_next = self.get_next(element); if element_next == element { - self.set_first(T::funty(0)); - self.set_last(T::funty(0)); + self.set_first(T::zero()); + self.set_last(T::zero()); } else { self.set_next(element_previous, element_next); self.set_previous(element_next, element_previous); @@ -64,8 +63,8 @@ pub trait AbsoluteCircularLinkedList: AbsoluteLinkedList { self.set_last(element_previous); } } - self.set_previous(element, T::funty(0)); - self.set_next(element, T::funty(0)); + self.set_previous(element, T::zero()); + self.set_next(element, T::zero()); self.dec_size(); } } diff --git a/src/lists/absolute_linked_list.rs b/src/lists/absolute_linked_list.rs index 6f91c59..feedc05 100644 --- a/src/lists/absolute_linked_list.rs +++ b/src/lists/absolute_linked_list.rs @@ -1,5 +1,4 @@ -use crate::LinkedList; -use platform_data::LinkType; +use crate::{LinkType, LinkedList}; pub trait AbsoluteLinkedList: LinkedList { fn get_first(&self) -> T; @@ -11,9 +10,9 @@ pub trait AbsoluteLinkedList: LinkedList { fn set_size(&mut self, size: T); fn inc_size(&mut self) { - self.set_size(self.get_size() + T::funty(1)) + self.set_size(self.get_size() + T::one()) } fn dec_size(&mut self) { - self.set_size(self.get_size() - T::funty(1)) + self.set_size(self.get_size() - T::one()) } } diff --git a/src/lists/linked_list.rs b/src/lists/linked_list.rs index 771f378..ebb6eac 100644 --- a/src/lists/linked_list.rs +++ b/src/lists/linked_list.rs @@ -1,4 +1,4 @@ -use platform_data::LinkType; +use crate::LinkType; pub trait LinkedList { fn get_previous(&self, element: T) -> T; diff --git a/src/lists/relative_circular_linked_list.rs b/src/lists/relative_circular_linked_list.rs index a161e33..b6b2d6f 100644 --- a/src/lists/relative_circular_linked_list.rs +++ b/src/lists/relative_circular_linked_list.rs @@ -1,5 +1,4 @@ -use crate::RelativeLinkedList; -use platform_data::LinkType; +use crate::{LinkType, RelativeLinkedList}; pub trait RelativeCircularLinkedList: RelativeLinkedList { fn attach_before(&mut self, head: T, base_element: T, new_element: T) { @@ -28,7 +27,7 @@ pub trait RelativeCircularLinkedList: RelativeLinkedList { fn attach_as_first(&mut self, head: T, element: T) { let first = self.get_first(head); - if first == T::funty(0) { + if first == T::zero() { self.set_first(head, element); self.set_last(head, element); self.set_previous(element, element); @@ -41,7 +40,7 @@ pub trait RelativeCircularLinkedList: RelativeLinkedList { fn attach_as_last(&mut self, head: T, element: T) { let last = self.get_last(head); - if last == T::funty(0) { + if last == T::zero() { self.attach_as_first(head, element); } else { self.attach_after(head, last, element); @@ -52,8 +51,8 @@ pub trait RelativeCircularLinkedList: RelativeLinkedList { let element_previous = self.get_previous(element); let element_next = self.get_next(element); if element_next == element { - self.set_first(head, T::funty(0)); - self.set_last(head, T::funty(0)); + self.set_first(head, T::zero()); + self.set_last(head, T::zero()); } else { self.set_next(element_previous, element_next); self.set_previous(element_next, element_previous); @@ -64,8 +63,8 @@ pub trait RelativeCircularLinkedList: RelativeLinkedList { self.set_last(head, element_previous); } } - self.set_previous(element, T::funty(0)); - self.set_next(element, T::funty(0)); + self.set_previous(element, T::zero()); + self.set_next(element, T::zero()); self.dec_size(head); } } diff --git a/src/lists/relative_doubly_linked_list.rs b/src/lists/relative_doubly_linked_list.rs index d7c7052..3fef8d8 100644 --- a/src/lists/relative_doubly_linked_list.rs +++ b/src/lists/relative_doubly_linked_list.rs @@ -1,5 +1,4 @@ -use crate::LinkedList; -use platform_data::LinkType; +use crate::{LinkType, LinkedList}; pub trait RelativeLinkedList: LinkedList { fn get_first(&self, head: T) -> T; @@ -11,9 +10,9 @@ pub trait RelativeLinkedList: LinkedList { fn set_size(&mut self, head: T, size: T); fn inc_size(&mut self, head: T) { - self.set_size(head, self.get_size(head) + T::funty(1)) + self.set_size(head, self.get_size(head) + T::one()) } fn dec_size(&mut self, head: T) { - self.set_size(head, self.get_size(head) - T::funty(1)) + self.set_size(head, self.get_size(head) - T::one()) } } diff --git a/src/trees/mod.rs b/src/trees/mod.rs index cf576da..f563ad3 100644 --- a/src/trees/mod.rs +++ b/src/trees/mod.rs @@ -1,5 +1,15 @@ mod no_recur_szb_tree; mod szb_tree; -pub use no_recur_szb_tree::NoRecurSzbTree; -pub use szb_tree::SzbTree; +macro_rules! tri { + ($expr:expr) => { + match $expr { + Some(x) => x, + None => return false, + } + }; +} + +pub use {no_recur_szb_tree::NoRecurSzbTree, szb_tree::SzbTree}; + +pub mod new_v2; diff --git a/src/trees/new_v2.rs b/src/trees/new_v2.rs new file mode 100644 index 0000000..d8614ef --- /dev/null +++ b/src/trees/new_v2.rs @@ -0,0 +1,332 @@ +use tap::Pipe; + +#[derive(Debug)] +pub struct Node { + pub size: usize, + pub left: Option, + pub right: Option, +} + +macro_rules! fn_set { + ($($name:ident => $set:ident: $ty:ty)*) => { + $( + fn $name(slice: &mut [Self::Item], idx: usize, $set: $ty) { + Self::_get(slice, idx).map(|node| Self::_set(slice, idx, Node { $set, ..node })); + } + )* + }; +} + +pub trait Tree { + type Item; + + fn get(item: &Self::Item) -> Node; + fn set(item: &mut Self::Item, val: Node); + + fn _get(slice: &[Self::Item], idx: usize) -> Option { + slice.get(idx).map(Self::get) + } + + fn _set(slice: &mut [Self::Item], idx: usize, node: Node) { + if let Some(val) = slice.get_mut(idx) { + Self::set(val, node) + } + } + + fn size(slice: &[Self::Item], idx: usize) -> Option { + Self::_get(slice, idx)?.size.pipe(Some) + } + + fn left(slice: &[Self::Item], idx: usize) -> Option { + Self::_get(slice, idx)?.left + } + + fn right(slice: &[Self::Item], idx: usize) -> Option { + Self::_get(slice, idx)?.right + } + + fn_set! { + set_size => size: usize + set_left => left: Option + set_right => right: Option + } + + fn is_left_of(slice: &[Self::Item], first: usize, second: usize) -> bool; + fn is_right_of(slice: &[Self::Item], first: usize, second: usize) -> bool { + first != second && !Self::is_left_of(slice, first, second) + } + + fn left_size(slice: &[Self::Item], idx: usize) -> Option { + Self::left(slice, idx).and_then(|idx| Self::size(slice, idx)) + } + + fn right_size(slice: &[Self::Item], idx: usize) -> Option { + Self::right(slice, idx).and_then(|idx| Self::size(slice, idx)) + } + + fn rightest(slice: &[Self::Item], mut current: usize) -> usize { + while let Some(next) = Self::right(slice, current) { + current = next; + } + current + } + + fn leftest(slice: &[Self::Item], mut current: usize) -> usize { + while let Some(next) = Self::left(slice, current) { + current = next; + } + current + } + + fn next(slice: &[Self::Item], idx: usize) -> Option { + Self::right(slice, idx).map(|idx| Self::leftest(slice, idx)) + } + + fn prev(slice: &[Self::Item], idx: usize) -> Option { + Self::left(slice, idx).map(|idx| Self::rightest(slice, idx)) + } + + fn is_contains(slice: &[Self::Item], mut root: usize, idx: usize) -> bool { + loop { + // match ( + // Self::is_left_of(slice, idx, root), + // Self::is_right_of(slice, idx, root), + // ) { + // (true, _) => root = tri!(Self::left(slice, root)), + // (_, true) => root = tri!(Self::right(slice, root)), + // (_, _) => return false, + // } + if Self::is_left_of(slice, idx, root) { + root = tri!(Self::left(slice, root)); + } else if Self::is_right_of(slice, idx, root) { + root = tri!(Self::right(slice, root)); + } else { + return true; + } + } + } + + fn inc_size(slice: &mut [Self::Item], idx: usize) { + if let Some(size) = Self::size(slice, idx) { + Self::set_size(slice, idx, size + 1) + } + } + + fn dec_size(slice: &mut [Self::Item], idx: usize) { + if let Some(size) = Self::size(slice, idx) { + Self::set_size(slice, idx, size - 1) + } + } + + fn fix_size(slice: &mut [Self::Item], idx: usize) { + Self::set_size( + slice, + idx, + Self::left_size(slice, idx).unwrap_or_default() + + Self::right_size(slice, idx).unwrap_or_default() + + 1, + ) + } + + fn clear(slice: &mut [Self::Item], idx: usize) { + Self::_set(slice, idx, Node { size: 0, left: None, right: None }) + } + + #[must_use] + fn rotate_left(slice: &mut [Self::Item], root: usize) -> Option { + let right = Self::right(slice, root)?; + Self::set_right(slice, root, Self::left(slice, right)); + Self::set_left(slice, right, Some(root)); + Self::set_size(slice, right, Self::size(slice, root)?); + Self::fix_size(slice, root); + Some(right) + } + + #[must_use] + fn rotate_right(slice: &mut [Self::Item], root: usize) -> Option { + let left = Self::left(slice, root)?; + Self::set_left(slice, root, Self::right(slice, left)); + Self::set_right(slice, left, Some(root)); + Self::set_size(slice, left, Self::size(slice, root)?); + Self::fix_size(slice, root); + Some(left) + } +} + +fn attach_impl(slice: &mut [Tree::Item], mut root: usize, idx: usize) -> Option +where + Tree: self::Tree, +{ + loop { + if Tree::is_left_of(slice, idx, root) { + let Some(left) = Tree::left(slice, root) else { + Tree::inc_size(slice, root); + Tree::set_size(slice, idx, 1); + Tree::set_left(slice, root, Some(idx)); + return Some(root); + }; + + let left_size = Tree::size(slice, left)?; + let right_size = Tree::right_size(slice, root).unwrap_or_default(); + + if Tree::is_left_of(slice, idx, left) { + if left_size >= right_size { + root = Tree::rotate_right(slice, root)?; + } else { + Tree::inc_size(slice, root); + root = left; + } + } else { + let lr_size = Tree::right(slice, left) + .and_then(|right| Tree::size(slice, right)) + .unwrap_or_default(); // or zero + if lr_size >= right_size { + if lr_size == 0 && right_size == 0 { + Tree::set_left(slice, idx, Some(left)); + Tree::set_right(slice, idx, Some(root)); + Tree::set_size(slice, idx, left_size + 2); + Tree::set_left(slice, root, None); + Tree::set_size(slice, root, 1); + return Some(idx); + } else { + let new = Tree::rotate_left(slice, left)?; + Tree::set_left(slice, root, Some(new)); + root = Tree::rotate_right(slice, root)?; + } + } else { + Tree::inc_size(slice, idx); + root = left; + } + } + } else { + let Some(right) = Tree::right(slice, root) else { + Tree::inc_size(slice, root); + Tree::set_size(slice, idx, 1); + Tree::set_right(slice, root, Some(idx)); + return Some(root); + }; + + let right_size = Tree::size(slice, right)?; + let left_size = Tree::left_size(slice, root).unwrap_or_default(); + + if Tree::is_right_of(slice, idx, right) { + if right_size >= left_size { + root = Tree::rotate_left(slice, root)?; + } else { + Tree::inc_size(slice, root); + root = right; + } + } else { + let rl_size = Tree::left(slice, right) + .and_then(|left| Tree::size(slice, left)) + .unwrap_or_default(); // or zero + if rl_size >= left_size { + if rl_size == 0 && left_size == 0 { + Tree::set_left(slice, idx, Some(root)); + Tree::set_right(slice, idx, Some(right)); + Tree::set_size(slice, idx, right_size + 2); + Tree::set_left(slice, root, None); + Tree::set_size(slice, root, 1); + return Some(idx); + } else { + let new = Tree::rotate_right(slice, right)?; + Tree::set_right(slice, root, Some(new)); + root = Tree::rotate_left(slice, root)?; + } + } else { + Tree::inc_size(slice, root); + root = right; + } + } + } + } +} + +fn detach_impl(slice: &mut [Tree::Item], mut root: usize, idx: usize) -> Option +where + Tree: self::Tree + ?Sized, +{ + loop { + let left = Tree::left(slice, idx); + let right = Tree::right(slice, idx); + + if Tree::is_left_of(slice, idx, root) { + let rl_size = + Tree::right(slice, idx).and_then(|right| Tree::left_size(slice, right))?; + let rr_size = + Tree::right(slice, idx).and_then(|right| Tree::right_size(slice, right))?; + let left_size = Tree::left_size(slice, idx).unwrap_or_default(); + + if rr_size >= left_size { + root = Tree::rotate_left(slice, root)?; + } else if rl_size >= left_size { + let new = Tree::rotate_right(slice, Tree::right(slice, root).expect("..."))?; + Tree::set_right(slice, root, Some(new)); + root = Tree::rotate_left(slice, root)?; + } else { + Tree::dec_size(slice, root); + root = left.expect("..."); + } + } else if Tree::is_right_of(slice, idx, root) { + let ll_size = Tree::left(slice, idx).and_then(|right| Tree::left_size(slice, right))?; + let lr_size = + Tree::left(slice, idx).and_then(|right| Tree::right_size(slice, right))?; + let right_size = Tree::right_size(slice, idx).unwrap_or_default(); + + if ll_size >= right_size { + root = Tree::rotate_left(slice, root)?; + } else if lr_size >= right_size { + let new = Tree::rotate_left(slice, Tree::left(slice, root).expect("..."))?; + Tree::set_left(slice, root, Some(new)); + root = Tree::rotate_right(slice, root)?; + } else { + Tree::dec_size(slice, root); + root = right.expect("..."); + } + } else { + println!("{left:?}, {right:?}"); + root = match (left, right) { + (Some(left), Some(right)) => { + let replacement; + let (left_size, right_size) = + (Tree::left_size(slice, idx)?, Tree::right_size(slice, idx)?); + + if left_size != 0 && right_size != 0 { + replacement = Tree::rightest(slice, left); + root = detach_impl::(slice, left, replacement)?; + } else { + replacement = Tree::leftest(slice, right); + root = detach_impl::(slice, right, replacement)?; + } // `root` is never read :( + Tree::set_left(slice, replacement, Some(left)); + Tree::set_right(slice, replacement, Some(right)); + Tree::set_size(slice, replacement, left_size + right_size); + replacement + } + (Some(left), _) => left, + (_, Some(right)) => right, + _ => { + Tree::clear(slice, idx); + return None; + } + }; + Tree::clear(slice, idx); + return Some(root); + } + } +} + +pub trait NoRecur: Tree { + fn attach(slice: &mut [Self::Item], root: Option, idx: usize) -> Option { + if let Some(root) = root { + attach_impl::(slice, root, idx) + } else { + Self::set_size(slice, idx, 1); + Some(idx) + } + } + + fn detach(slice: &mut [Self::Item], root: Option, idx: usize) -> Option { + if let Some(root) = root { detach_impl::(slice, root, idx) } else { None } + } +} diff --git a/src/trees/no_recur_szb_tree.rs b/src/trees/no_recur_szb_tree.rs index 526ec7f..de26a41 100644 --- a/src/trees/no_recur_szb_tree.rs +++ b/src/trees/no_recur_szb_tree.rs @@ -1,11 +1,9 @@ -use platform_data::LinkType; - -use crate::SzbTree; +use crate::{LinkType, SzbTree}; pub trait NoRecurSzbTree: SzbTree { unsafe fn attach(&mut self, root: *mut T, node: T) { - if *root == T::funty(0) { - self.set_size(node, T::funty(1)); + if *root == T::zero() { + self.set_size(node, T::one()); *root = node; return; } @@ -22,14 +20,14 @@ pub trait NoRecurSzbTree: SzbTree { let right = self.get_mut_right_reference(*root); let right_size = self.get_size_or_zero(*right); if self.first_is_to_the_left_of_second(node, *root) { - if *left == T::funty(0) { + if *left == T::zero() { self.inc_size(*root); - self.set_size(node, T::funty(1)); + self.set_size(node, T::one()); *left = node; return; } if self.first_is_to_the_left_of_second(node, *left) { - if (left_size + T::funty(1)) > right_size { + if (left_size + T::one()) > right_size { self.right_rotate(root); } else { self.inc_size(*root); @@ -37,13 +35,13 @@ pub trait NoRecurSzbTree: SzbTree { } } else { let left_right_size = self.get_size_or_zero(self.get_right(*left)); - if (left_right_size + T::funty(1)) > right_size { - if left_right_size == T::funty(0) && right_size == T::funty(0) { + if (left_right_size + T::one()) > right_size { + if left_right_size == T::zero() && right_size == T::zero() { self.set_left(node, *left); self.set_right(node, *root); - self.set_size(node, left_size + T::funty(1) + T::funty(1)); - self.set_left(*root, T::funty(0)); - self.set_size(*root, T::funty(1)); + self.set_size(node, left_size + T::one() + T::one()); + self.set_left(*root, T::zero()); + self.set_size(*root, T::one()); *root = node; return; } @@ -55,14 +53,14 @@ pub trait NoRecurSzbTree: SzbTree { } } } else { - if *right == T::funty(0) { + if *right == T::zero() { self.inc_size(*root); - self.set_size(node, T::funty(1)); + self.set_size(node, T::one()); *right = node; return; } if self.first_is_to_the_right_of_second(node, *right) { - if (right_size + T::funty(1)) > left_size { + if (right_size + T::one()) > left_size { self.left_rotate(root); } else { self.inc_size(*root); @@ -70,13 +68,13 @@ pub trait NoRecurSzbTree: SzbTree { } } else { let right_left_size = self.get_size_or_zero(self.get_left(*right)); - if (right_left_size + T::funty(1)) > left_size { - if right_left_size == T::funty(0) && left_size == T::funty(0) { + if (right_left_size + T::one()) > left_size { + if right_left_size == T::zero() && left_size == T::zero() { self.set_left(node, *root); self.set_right(node, *right); - self.set_size(node, right_size + T::funty(1) + T::funty(1)); - self.set_right(*root, T::funty(0)); - self.set_size(*root, T::funty(1)); + self.set_size(node, right_size + T::one() + T::one()); + self.set_right(*root, T::zero()); + self.set_size(*root, T::one()); *root = node; return; } @@ -98,7 +96,7 @@ pub trait NoRecurSzbTree: SzbTree { let right = self.get_mut_right_reference(*root); let right_size = self.get_size_or_zero(*right); if self.first_is_to_the_left_of_second(node, *root) { - let decremented_left_size = left_size - T::funty(1); + let decremented_left_size = left_size - T::one(); if self.get_size_or_zero(self.get_right_or_default(*right)) > decremented_left_size { self.left_rotate(root); @@ -112,7 +110,7 @@ pub trait NoRecurSzbTree: SzbTree { root = left; } } else if self.first_is_to_the_right_of_second(node, *root) { - let decremented_right_size = right_size - T::funty(1); + let decremented_right_size = right_size - T::one(); if self.get_size_or_zero(self.get_left_or_default(*left)) > decremented_right_size { self.right_rotate(root); } else if self.get_size_or_zero(self.get_right_or_default(*left)) @@ -125,7 +123,7 @@ pub trait NoRecurSzbTree: SzbTree { root = right; } } else { - if left_size > T::funty(0) && right_size > T::funty(0) { + if left_size > T::zero() && right_size > T::zero() { let replacement; if left_size > right_size { replacement = self.get_rightest(*left); @@ -138,12 +136,12 @@ pub trait NoRecurSzbTree: SzbTree { self.set_right(replacement, *right); self.set_size(replacement, left_size + right_size); *root = replacement; - } else if left_size > T::funty(0) { + } else if left_size > T::zero() { *root = *left; - } else if right_size > T::funty(0) { + } else if right_size > T::zero() { *root = *right; } else { - *root = T::funty(0); + *root = T::zero(); } self.clear_node(node); return; diff --git a/src/trees/szb_tree.rs b/src/trees/szb_tree.rs index dc82d81..714edac 100644 --- a/src/trees/szb_tree.rs +++ b/src/trees/szb_tree.rs @@ -1,4 +1,4 @@ -use platform_data::LinkType; +use crate::LinkType; pub trait SzbTree { unsafe fn get_mut_left_reference(&mut self, node: T) -> *mut T; @@ -26,35 +26,23 @@ pub trait SzbTree { unsafe fn first_is_to_the_right_of_second(&self, first: T, second: T) -> bool; unsafe fn get_left_or_default(&self, node: T) -> T { - if node == T::funty(0) { - T::funty(0) - } else { - self.get_left(node) - } + if node == T::zero() { T::zero() } else { self.get_left(node) } } unsafe fn get_right_or_default(&self, node: T) -> T { - if node == T::funty(0) { - T::funty(0) - } else { - self.get_right(node) - } + if node == T::zero() { T::zero() } else { self.get_right(node) } } unsafe fn get_size_or_zero(&self, node: T) -> T { - if node == T::funty(0) { - T::funty(0) - } else { - self.get_size(node) - } + if node == T::zero() { T::zero() } else { self.get_size(node) } } unsafe fn inc_size(&mut self, node: T) { - self.set_size(node, self.get_size(node) + T::funty(1)); + self.set_size(node, self.get_size(node) + T::one()); } unsafe fn dec_size(&mut self, node: T) { - self.set_size(node, self.get_size(node) - T::funty(1)); + self.set_size(node, self.get_size(node) - T::one()); } unsafe fn get_left_size(&self, node: T) -> T { @@ -66,10 +54,7 @@ pub trait SzbTree { } unsafe fn fix_size(&mut self, node: T) { - self.set_size( - node, - (self.get_left_size(node) + self.get_right_size(node)) + T::funty(1), - ); + self.set_size(node, (self.get_left_size(node) + self.get_right_size(node)) + T::one()); } unsafe fn left_rotate(&mut self, root: *mut T) { @@ -100,7 +85,7 @@ pub trait SzbTree { unsafe fn get_rightest(&self, mut current: T) -> T { let mut current_right = self.get_right(current); - while current_right != T::funty(0) { + while current_right != T::zero() { current = current_right; current_right = self.get_right(current); } @@ -109,7 +94,7 @@ pub trait SzbTree { unsafe fn get_leftest(&self, mut current: T) -> T { let mut current_left = self.get_left(current); - while current_left != T::funty(0) { + while current_left != T::zero() { current = current_left; current_left = self.get_left(current); } @@ -125,7 +110,7 @@ pub trait SzbTree { } unsafe fn contains(&self, node: T, mut root: T) -> bool { - while root != T::funty(0) { + while root != T::zero() { if self.first_is_to_the_left_of_second(node, root) { root = self.get_left(root); } else if self.first_is_to_the_right_of_second(node, root) { @@ -138,8 +123,8 @@ pub trait SzbTree { } unsafe fn clear_node(&mut self, node: T) { - self.set_left(node, T::funty(0)); - self.set_right(node, T::funty(0)); - self.set_size(node, T::funty(0)); + self.set_left(node, T::zero()); + self.set_right(node, T::zero()); + self.set_size(node, T::zero()); } } diff --git a/tests/prop.rs b/tests/prop.rs new file mode 100644 index 0000000..3e72c74 --- /dev/null +++ b/tests/prop.rs @@ -0,0 +1,37 @@ +use { + std::collections::HashSet, +}; + +use proptest::prelude::*; + +prop_compose! { + fn seq_inner(vec: Vec) + (set in prop::collection::hash_set(1..vec.len(), 0..50)) -> HashSet { + set + } +} + +prop_compose! { + fn seq_strategy() + (len in 2..100_usize) + (len in Just(len), set in prop::collection::hash_set(1..len, 0..100)) + -> (HashSet, usize) { + (set, len) + } +} + +use proptest::test_runner::FileFailurePersistence; + +proptest! { + #![proptest_config(ProptestConfig { + failure_persistence: Some(Box::new(FileFailurePersistence::WithSource("regressions"))), + ..Default::default() + })] + + #[test] + fn prop_new(seq in seq_strategy()) { + // fixme: does not support `detach` + // inner::(seq) + } + +}