Skip to content
Snippets Groups Projects
Commit 91e86bdc authored by Cookiebowser's avatar Cookiebowser
Browse files

started lazy betypes

parent d0257c29
No related branches found
No related tags found
1 merge request!28Rust support
Showing
with 1580 additions and 0 deletions
[package]
name = "btypes"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.3"
im = "15.0.0"
lazy_static = "1.4.0"
\ No newline at end of file
use crate::bobject::BObject;
pub type BBoolean = bool;
pub trait IntoBool {
#![allow(non_snake_case)]
fn booleanValue(&self) -> bool;
}
pub trait BBooleanT: BObject + IntoBool + Copy {
fn new(val: bool) -> Self;
fn or(&self, other: &Self) -> Self;
fn xor(&self, other: &Self) -> Self;
fn and(&self, other: &Self) -> Self;
fn not(&self) -> Self;
fn implies(&self, other: &Self) -> Self;
fn equivalent(&self, other: &Self) -> Self;
fn equal(&self, other: &Self) -> Self;
fn unequal(&self, other: &Self) -> Self;
}
impl IntoBool for bool {
fn booleanValue(&self) -> bool {
return *self;
}
}
impl BObject for bool {}
impl BBooleanT for bool {
fn new(val: bool) -> Self { val }
fn or(&self, other: &Self) -> Self { *self || *other }
fn xor(&self, other: &Self) -> Self { *self ^ *other }
fn and(&self, other: &Self) -> Self { *self && *other }
fn not(&self) -> Self { !*self }
fn implies(&self, other: &Self) -> Self { !*self || *other }
fn equivalent(&self, other: &Self) -> Self { *self == *other }
fn equal(&self, other: &Self) -> Self { *self == *other }
fn unequal(&self, other: &Self) -> Self { *self != *other }
}
use std::convert::TryInto;
use crate::bboolean::{BBoolean, BBooleanT};
use crate::bobject::BObject;
use std::fmt;
use std::hash::Hash;
pub trait BInt: BObject { fn get_binteger_value(&self) -> BInteger { panic!("get_integer_value not implemented!"); }}
pub trait FromBInt { fn from<T: BInt>(value: &T) -> Self; }
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct BInteger {
val: i64,
}
impl BObject for BInteger {}
impl BInt for BInteger {
fn get_binteger_value(&self) -> BInteger { return *self; }
}
impl FromBInt for BInteger {
fn from<T: BInt>(value: &T) -> Self {
return value.get_binteger_value();
}
}
impl BInteger {
#![allow(non_snake_case, dead_code)]
pub const fn new(init: i64) -> BInteger {
return BInteger {
val: init,
}
}
pub fn get_val(&self) -> i64 { return self.val; }
pub fn compareTo(&self, o: &BInteger) -> i64 {
return self.val - o.val;
}
pub fn lessEqual(&self, o: &BInteger) -> BBoolean {
return BBoolean::new(self.val <= o.val);
}
pub fn greaterEqual(&self, o: &BInteger) -> BBoolean {
return BBoolean::new(self.val >= o.val);
}
pub fn less(&self, o: &BInteger) -> BBoolean {
return BBoolean::new(self.val < o.val);
}
pub fn greater(&self, o: &BInteger) -> BBoolean {
return BBoolean::new(self.val > o.val);
}
pub fn equal(&self, o: &BInteger) -> BBoolean {
return BBoolean::new(self.val == o.val);
}
pub fn unequal(&self, o: &BInteger) -> BBoolean {
return BBoolean::new(self.val != o.val);
}
pub fn plus(&self, v: &BInteger) -> BInteger {
return BInteger::new(self.val + v.val);
}
pub fn minus(&self, v: &BInteger) -> BInteger {
return BInteger::new(self.val - v.val);
}
pub fn multiply(&self, v: &BInteger) -> BInteger {
return BInteger::new(self.val * v.val);
}
pub fn power(&self, v: &BInteger) -> BInteger {
if v.val < 0 { panic!("Power with negative exponent!") }
let exp: u32 = v.val.unsigned_abs().try_into().unwrap();
return BInteger::new(self.val.pow(exp));
}
pub fn divide(&self, v: &BInteger) -> BInteger {
return BInteger::new(self.val / v.val);
}
pub fn modulo(&self, v: &BInteger) -> BInteger {
//return BInteger::new(self.val.rem_euclid(v.val));
return BInteger::new(self.val % v.val);
}
pub fn succ(&self) -> BInteger {
return BInteger::new(self.val + 1);
}
pub fn pred(&self) -> BInteger {
return BInteger::new(self.val - 1);
}
pub fn negative(&self) -> BInteger {
return BInteger::new(-self.val);
}
pub fn positive(&self) -> BInteger {
return *self;
}
pub fn isInteger(&self) -> BBoolean {
return BBoolean::new(true);
}
pub fn isNotInteger(&self) -> BBoolean {
return BBoolean::new(false);
}
pub fn isNatural(&self) -> BBoolean {
return BBoolean::new(self.val >= 0);
}
pub fn isNotNatural(&self) -> BBoolean {
return BBoolean::new(self.val < 0);
}
pub fn isNatural1(&self) -> BBoolean {
return BBoolean::new(self.val > 0);
}
pub fn isNotNatural1(&self) -> BBoolean {
return BBoolean::new(self.val < 1);
}
}
impl fmt::Display for BInteger {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.val)
}
}
\ No newline at end of file
use std::hash::Hash;
use std::clone::Clone;
use std::fmt::{Debug, Display};
use crate::bboolean::{BBoolean, BBooleanT};
pub trait BObject: Eq + Hash + Ord + Clone + Display + Debug {
fn is_struct(&self) -> BBoolean { BBoolean::new(false) }
}
\ No newline at end of file
This diff is collapsed.
#![ allow( dead_code, non_snake_case) ]
use crate::bboolean::{IntoBool, BBoolean, BBooleanT};
use crate::binteger::{BInt, BInteger};
use crate::bstring::BString;
use crate::bobject::BObject;
use crate::btuple::BTuple;
use crate::orderedhashset::OrderedHashSet as OrdSet;
use std::any::TypeId;
use std::borrow::Borrow;
use std::convert::TryInto;
use im::ordset::Iter;
use std::hash::{Hash, Hasher};
use std::collections::LinkedList;
use std::fmt;
use std::fmt::Debug;
use rand::Rng;
use crate::lazy_ops::set_ops::setops::{SetOp, SetOpTraits};
pub trait TBSet: BObject {
type Item: BObject;
fn as_ord_set(&self) -> OrdSet<Self::Item>;
fn as_bset(&self) -> &BSet<Self::Item>;
}
pub trait SetLike: BObject {
fn get_empty() -> Self;
fn _union(&self, other: &Self) -> Self;
fn intersect(&self, other: &Self) -> Self;
}
#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct BSet<T: BObject> {
set: OrdSet<T>,
transformation: Option<Box<dyn SetOp<Item = T>>>,
}
impl<T: BObject> SetOp for BSet<T> {
type Item = T;
fn compute(&self, _: &BSet<Self::Item>) -> BSet<Self::Item> {
match self.transformation.borrow() {
Some(trans) => trans.compute(&self) , //todo save computation?
None => self.clone(),
}
}
fn clone_box(&self) -> Box<dyn SetOp<Item=Self::Item>> {
todo!()
}
}
impl<T: BObject> SetOpTraits for BSet<T> {
}
impl<I: BObject> Hash for BSet<I> {
fn hash<H: Hasher>(self: &BSet<I>, state: &mut H) { self.set.hash(state); }
}
impl<T: BObject> BObject for BSet<T> {}
impl<T: BObject> TBSet for BSet<T> {
type Item = T;
fn as_ord_set(&self) -> OrdSet<Self::Item> { self.set.clone() }
fn as_bset(&self) -> &BSet<Self::Item> { self }
}
impl<T: BObject> fmt::Display for BSet<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut result = "{".to_owned();
let mut first = true;
for e in self.set.iter() {
if !first { result = result + ", " }
else { first = false; }
result = result + &format!("{}", e).to_string();
}
result = result + "}";
return write!(f, "{}", result);
}
}
impl<'a, T: 'static + BObject> IntoIterator for &'a BSet<T>
where
T: 'a + Ord,
{
type Item = &'a T;
type IntoIter = im::ordset::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
//TODO: check if replacing cache with mutex works and does not impact permormance too much
unsafe impl<T: BObject> Sync for BSet<T> {}
impl<T: 'static + BObject> BSet<T> {
pub fn new(mut args: Vec<T>) -> BSet<T> {
let mut ret: BSet<T> = BSet {
set: OrdSet::new(),
transformation: Option::None
};
while !args.is_empty() {
ret.set.insert(args.remove(0));
}
return ret;
}
pub fn fromOrdSet(set: OrdSet<T>) -> BSet<T> {
return BSet { set: set, transformation: Option::None };
}
pub fn iter(&self) -> Iter<'_, T> {
return self.set.iter();
}
pub fn size(&self) -> usize {
return self.set.len();
}
pub fn isEmpty(&self) -> bool {
return self.set.is_empty();
}
pub fn contains(&self, o: &T) -> bool {
return self.set.contains(o);
}
pub fn intersect(&self, set: &BSet<T>) -> BSet<T> {
return BSet{ set: self.set.clone().intersection(set.set.clone()), transformation: Option::None };
}
pub fn difference(&self, set: &BSet<T>) -> BSet<T> {
return BSet{ set: self.set.clone().relative_complement(set.set.clone()), transformation: Option::None };
}
pub fn _union(&self, set: &BSet<T>) -> BSet<T> {
return BSet{ set: self.set.clone().union(set.set.clone()), transformation: Option::None };
}
pub fn interval(a: &BInteger, b: &BInteger) -> BSet<BInteger> {
let mut result: BSet<BInteger> = BSet::new(vec![]);
for i in a.get_val()..b.get_val()+1 {
result.set.insert(BInteger::new(i));
}
return result;
}
pub fn card(&self) -> BInteger {
return self._size();
}
pub fn _size(&self) -> BInteger {
return BInteger::new(self.set.len().try_into().unwrap());
}
pub fn elementOf(&self, object: &T) -> BBoolean {
return BBoolean::new(self.contains(object));
}
pub fn notElementOf(&self, object: &T) -> BBoolean {
return BBoolean::new(!self.contains(object));
}
pub fn subset(&self, set: &BSet<T>) -> BBoolean {
return BBoolean::new(self.set.is_subset(&set.set));
}
pub fn notSubset(&self, set: &BSet<T>) -> BBoolean {
return BBoolean::new(!self.set.is_subset(&set.set));
}
pub fn strictSubset(&self, set: &BSet<T>) -> BBoolean {
return BBoolean::new(self.set.len() < set.set.len() && self.set.is_subset(&set.set));
}
pub fn strictNotSubset(&self, set: &BSet<T>) -> BBoolean {
return BBoolean::new(self.set.len() == set.set.len() || !self.set.is_subset(&set.set));
}
pub fn fin(&self) -> BSet<BSet<T>> {
return self.pow();
}
pub fn pow(&self) -> BSet<BSet<T>> {
return self._pow(true);
}
pub fn fin1(&self) -> BSet<BSet<T>> {
return self.pow1();
}
pub fn pow1(&self) -> BSet<BSet<T>> {
return self._pow(false);
}
fn _pow(&self, with_empty_set: bool) -> BSet<BSet<T>> {
let mut result: BSet<BSet<T>> = BSet::new(vec![]);
let start: BSet<T> = BSet::new(vec![]);
let mut queue: LinkedList<BSet<T>> = LinkedList::new();
queue.push_back(start.clone());
if with_empty_set { result = result._union(&BSet::new(vec![start])); }
while !queue.is_empty() {
let current_set: BSet<T> = queue.pop_front().unwrap();
for element in self.set.iter() {
let next_set: BSet<T> = current_set._union(&BSet::new(vec![element.clone()]));
let previous_size = result.size();
result = result._union(&BSet::new(vec![next_set.clone()]));
if previous_size < result.size() {
queue.push_back(next_set);
}
}
}
return result;
}
pub fn nondeterminism(&self) -> T {
let mut rng = rand::thread_rng();
return self.set.iter().nth(rng.gen_range(0..self.set.len())).unwrap().clone();
}
pub fn equal(&self, other: &BSet<T>) -> BBoolean {
return BBoolean::new(self.set.eq(&other.set));
}
pub fn unequal(&self, other: &BSet<T>) -> BBoolean {
return BBoolean::new(!self.set.eq(&other.set));
}
pub fn subsetOfInteger(&self) -> BBoolean {
return BBoolean::new(TypeId::of::<BInteger>() == TypeId::of::<T>());
}
pub fn strictSubsetOfInteger(&self) -> BBoolean {
return self.subsetOfInteger();
}
pub fn notSubsetOfInteger(&self) -> BBoolean {
return self.subsetOfInteger().not();
}
pub fn equalInteger(&self) -> BBoolean {
return BBoolean::new(false);
}
pub fn unequalInteger(&self) -> BBoolean {
return BBoolean::new(true);
}
pub fn equalNatural(&self) -> BBoolean {
return BBoolean::new(false);
}
pub fn unequalNatural(&self) -> BBoolean {
return BBoolean::new(true);
}
pub fn equalNatural1(&self) -> BBoolean {
return BBoolean::new(false);
}
pub fn unequalNatural1(&self) -> BBoolean {
return BBoolean::new(true);
}
pub fn equalString(&self) -> BBoolean {
return BBoolean::new(false);
}
pub fn unequalString(&self) -> BBoolean {
return BBoolean::new(true);
}
pub fn equalStruct(&self) -> BBoolean {
return BBoolean::new(false);
}
pub fn unequalStruct(&self) -> BBoolean {
return BBoolean::new(true);
}
pub fn subsetOfString(&self) -> BBoolean {
return BBoolean::new(TypeId::of::<BString>() == TypeId::of::<T>());
}
pub fn strictSubsetOfString(&self) -> BBoolean {
return self.subsetOfString();
}
pub fn notSubsetOfString(&self) -> BBoolean {
return self.subsetOfString().not();
}
pub fn notStrictSubsetOfString(&self) -> BBoolean {
return self.strictSubsetOfString().not();
}
pub fn subsetOfStruct(&self) -> BBoolean {
return self.is_struct();
}
pub fn strictsubsetOfStruct(&self) -> BBoolean {
return self.subsetOfStruct();
}
pub fn notsubsetOfStruct(&self) -> BBoolean {
return self.subsetOfStruct().not();
}
pub fn notStrictsubsetOfStruct(&self) -> BBoolean {
return self.strictsubsetOfStruct().not();
}
//rust specific
pub fn cartesian<T1: 'static + BObject, T2: 'static + BObject>(set_a: &OrdSet<T1>, set_b: &OrdSet<T2>) -> OrdSet<BTuple<T1, T2>> {
if set_a.is_empty() || set_b.is_empty() {return OrdSet::<BTuple<T1, T2>>::new();}
return set_a.iter()
.fold(OrdSet::<BTuple<T1, T2>>::new(),
|set, lhs| set_b.iter().cloned()
.fold(set,
|tset, rhs| tset.update(BTuple::new(lhs.clone(), rhs))))
}
}
impl<T: 'static + BInt> BSet<T> {
pub fn notStrictSubsetOfInteger(&self) -> BBoolean {
return self.strictSubsetOfInteger().not();
}
pub fn subsetOfNatural(&self) -> BBoolean {
if self.subsetOfInteger().booleanValue() {
return BBoolean::new(self.set.iter().find(|i| i.get_binteger_value().isNotNatural().booleanValue()).is_none());
}
return BBoolean::new(false);
}
pub fn strictSubsetOfNatural(&self) -> BBoolean {
return self.subsetOfNatural();
}
pub fn notSubsetOfNatural(&self) -> BBoolean {
return self.subsetOfNatural().not();
}
pub fn notStrictSubsetOfNatural(&self) -> BBoolean {
return self.strictSubsetOfNatural().not();
}
pub fn subsetOfNatural1(&self) -> BBoolean {
if self.subsetOfInteger().booleanValue() {
return BBoolean::new(self.set.iter().find(|i| i.get_binteger_value().isNotNatural1().booleanValue()).is_none());
}
return BBoolean::new(false);
}
pub fn strictSubsetOfNatural1(&self) -> BBoolean {
return self.subsetOfNatural();
}
pub fn notSubsetOfNatural1(&self) -> BBoolean {
return self.subsetOfNatural1().not();
}
pub fn notStrictSubsetOfNatural1(&self) -> BBoolean {
return self.strictSubsetOfNatural1().not();
}
pub fn _min(self: &BSet<T>) -> BInteger {
return self.set.get_min().unwrap().get_binteger_value();
}
pub fn _max(self: &BSet<T>) -> BInteger {
return self.set.get_max().unwrap().get_binteger_value();
}
}
impl<T: 'static + BObject> SetLike for BSet<T> {
fn get_empty() -> Self { BSet::<T>::new(vec![]) }
fn _union(&self, other: &Self) -> Self { self._union(other) }
fn intersect(&self, other: &Self) -> Self { self.intersect(other) }
}
impl<T: 'static + SetLike> BSet<T> {
pub fn unary__union(&self) -> T {
return self.iter().fold(T::get_empty(), |result, next| result._union(next));
}
pub fn unary_intersect(&self) -> T {
return self.iter().fold(T::get_empty(), |result, next| result.intersect(next));
}
}
\ No newline at end of file
use std::fmt::{Display, Formatter};
use crate::bobject::BObject;
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct BString {
val: String,
}
pub trait TBString {}
impl TBString for BString {}
impl Display for BString {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.val)
}
}
impl BObject for BString {}
\ No newline at end of file
use crate::bboolean::{BBoolean, BBooleanT};
use crate::bobject::BObject;
pub trait BStruct: BObject{
fn is_struct(&self) -> BBoolean { BBoolean::new(true) }
}
\ No newline at end of file
use crate::bobject::BObject;
use std::fmt;
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct BTuple<L: BObject, R: BObject>{
left_val: L,
right_val: R,
}
impl<L: BObject, R: BObject> fmt::Display for BTuple<L, R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
return write!(f, "({} |-> {})", self.left_val, self.right_val);
}
}
impl<L: BObject, R:BObject> BObject for BTuple<L, R>{}
impl<L: BObject, R: BObject> BTuple<L, R> {
pub fn new(left: L, right: R) -> BTuple<L, R> {
return BTuple {left_val: left, right_val: right,};
}
pub fn from_refs(left: &L, right: &R) -> BTuple<L, R> {
return BTuple {left_val: left.clone(), right_val: right.clone(),};
}
pub fn projection1(&self) -> L {
return self.left_val.clone();
}
pub fn projection2(&self) -> R {
return self.right_val.clone();
}
}
use crate::bboolean::{BBoolean, BBooleanT};
use crate::bset::BSet;
lazy_static! {
pub static ref BOOL: BSet<BBoolean> = BSet::new(vec![BBoolean::new(true), BBoolean::new(false)]);
}
\ No newline at end of file
pub mod set_ops;
\ No newline at end of file
pub mod setops;
\ No newline at end of file
use std::cmp::Ordering;
use std::fmt;
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
use crate::bobject::BObject;
use crate::bset::BSet;
pub trait SetOp: SetOpTraits + Debug {
type Item: BObject;
fn compute(&self, lhs: &BSet<Self::Item>) -> BSet<Self::Item>;
fn clone_box(&self) -> Box<dyn SetOp<Item = Self::Item>>;
//PartialEq
fn eq(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> bool;
//PartialOrd
fn partial_cmp(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> Option<Ordering>;
//Ord
fn cmp(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> Ordering;
fn max(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> Box<dyn SetOp<Item = Self::Item>>;
fn min(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> Box<dyn SetOp<Item = Self::Item>>;
fn clamp(&self, min: &Box<dyn SetOp<Item = Self::Item>>, max: &Box<dyn SetOp<Item = Self::Item>>) -> Box<dyn SetOp<Item = Self::Item>>;
}
pub trait SetOpTraits {
//type Bla: BObject;
//fn clone_box(&self) -> Box<dyn SetOp<Item = Self::Bla>>;
//fn default_box() -> Box<dyn SetOp>;
}
/*
impl<T> SetOpTraits for T
where T: 'static + SetOp + Clone,
{
fn clone_box<S: BObject>(&self) -> Box<dyn SetOp<Item = S>> {
Box::new(self.clone())
}
}
*/
impl<T: BObject> Clone for Box<dyn SetOp<Item = T>> {
fn clone(&self) -> Self {
self.clone_box()
}
}
impl<T: BObject> Eq for Box<dyn SetOp<Item=T>> {}
impl<T: BObject> PartialEq<Self> for Box<dyn SetOp<Item=T>> {
fn eq(&self, other: &Self) -> bool {
self.eq(other)
}
}
impl<T: BObject> PartialOrd<Self> for Box<dyn SetOp<Item=T>> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.partial_cmp(other)
}
}
impl<T: BObject> Ord for Box<dyn SetOp<Item = T>> {
fn cmp(&self, other: &Self) -> Ordering {
self.cmp(other)
}
}
impl<T: 'static + BObject> dyn SetOp<Item = T> {
fn default() -> Box<Self> {
Box::new(Identity {phantom: PhantomData})
}
}
#[derive(Clone)]
pub struct Identity<T: BObject> {
phantom: PhantomData<T>,
}
impl<T: BObject> Debug for Identity<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "Identity()")
}
}
impl<T: 'static + BObject> SetOp for Identity<T> {
type Item = T;
fn compute(&self, lhs: &BSet<T>) -> BSet<T> {
lhs.clone()
}
fn clone_box(&self) -> Box<dyn SetOp<Item=Self::Item>> {
Box::new(Identity{phantom: PhantomData})
}
}
impl<T: 'static + BObject> SetOpTraits for Identity<T>{}
\ No newline at end of file
#[macro_use]
extern crate lazy_static;
pub mod bboolean;
pub mod binteger;
pub mod bobject;
pub mod bstruct;
pub mod bset;
pub mod bstring;
pub mod btuple;
pub mod brelation;
pub mod butils;
pub mod orderedhashset;
pub mod lazy_ops;
use std::borrow::Borrow;
use std::collections::hash_map::DefaultHasher;
use std::cell::RefCell;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use im::OrdSet;
use im::ordset::Iter;
use crate::bobject::BObject;
#[derive(Default, Debug, Eq)]
pub struct OrderedHashSet<I: BObject> {
set: OrdSet<I>,
hash_cache: RefCell<Option<u64>>,
}
impl<I: BObject> Clone for OrderedHashSet<I> {
fn clone(&self) -> Self {
OrderedHashSet { set: self.set.clone(), hash_cache: RefCell::new(self.hash_cache.borrow().clone()) }
}
}
impl<I: BObject> PartialOrd for OrderedHashSet<I> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.set.partial_cmp(&other.set) }
fn lt(&self, other: &Self) -> bool { self.set.lt(&other.set) }
fn le(&self, other: &Self) -> bool { self.set.le(&other.set) }
fn gt(&self, other: &Self) -> bool { self.set.gt(&other.set) }
fn ge(&self, other: &Self) -> bool { self.set.ge(&other.set) }
}
impl<I: BObject> Ord for OrderedHashSet<I> {
fn cmp(&self, other: &Self) -> Ordering { self.set.cmp(&other.set) }
fn max(self, other: Self) -> Self {
match self.cmp(&other) {
Ordering::Less => other,
Ordering::Greater => self,
Ordering::Equal => other,
}
}
fn min(self, other: Self) -> Self {
match self.cmp(&other) {
Ordering::Less => self,
Ordering::Greater => other,
Ordering::Equal => self,
}
}
fn clamp(self, min: Self, max: Self) -> Self {
if self < min {
min
} else if self > max {
max
} else {
self
}
}
}
//TODO: check if replacing cache with mutex works and does not impact permormance too much
unsafe impl<T: BObject> Sync for OrderedHashSet<T> {}
impl<I: BObject> PartialEq for OrderedHashSet<I> {
fn eq(&self, other: &Self) -> bool {
self.set.eq(&other.set)
}
}
impl<I: BObject> Hash for OrderedHashSet<I> {
fn hash<H: Hasher>(self: &OrderedHashSet<I>, state: &mut H) {
let cache = self.hash_cache.borrow().clone();
let hash: u64;
if cache.is_none() {
let mut hasher = DefaultHasher::new();
self.set.hash(&mut hasher);
hash = hasher.finish();
self.hash_cache.replace(Option::Some(hash));
} else {
hash = cache.unwrap();
}
hash.hash(state);
}
}
impl<A: BObject> IntoIterator for OrderedHashSet<A> {
type Item = A;
type IntoIter = im::ordset::ConsumingIter<A>;
fn into_iter(self) -> Self::IntoIter {
self.set.into_iter()
}
}
impl<I: BObject> OrderedHashSet<I> {
pub fn new() -> Self { Self::from_set(OrdSet::new()) }
pub fn from_set(val: OrdSet<I>) -> Self { OrderedHashSet {set: val, hash_cache: RefCell::new(Option::None)} }
pub fn unit(item: I) -> Self { Self::from_set(OrdSet::unit(item)) }
pub fn from(items: Vec<I>) -> Self { Self::from_set(OrdSet::from(items)) }
pub fn update(&self, item: I) -> Self { Self::from_set(self.set.update(item)) }
pub fn unions<A: IntoIterator<Item = Self>>(a: A) -> Self {
a.into_iter().fold(Self::new(), Self::union)
}
pub fn iter(&self) -> Iter<'_, I> { self.set.iter() }
pub fn len(&self) -> usize { self.set.len() }
pub fn is_empty(&self) -> bool { self.set.is_empty() }
pub fn contains(&self, value: &I) -> bool { self.set.contains(value) }
pub fn is_subset<RS: Borrow<Self>>(&self, other: RS) -> bool {
let other = other.borrow();
self.set.is_subset(&other.set)
}
pub fn insert(&mut self, value: I) -> Option<I> {
self.hash_cache.replace(Option::None);
return self.set.insert(value);
}
pub fn remove_min(&mut self) -> Option<I> {
self.hash_cache.replace(Option::None);
return self.set.remove_min()
}
pub fn get_min(&self) -> Option<&I> { self.set.get_min() }
pub fn get_max(&self) -> Option<&I> { self.set.get_max() }
pub fn union(self, other: Self) -> Self {
self.hash_cache.replace(Option::None);
return Self::from_set(self.set.union(other.set));
}
pub fn intersection(self, other: Self) -> Self {
self.hash_cache.replace(Option::None);
return Self::from_set(self.set.intersection(other.set));
}
pub fn relative_complement(self, other: Self) -> Self {
self.hash_cache.replace(Option::None);
return Self::from_set(self.set.relative_complement(other.set));
}
pub fn get_set(self) -> OrdSet<I> { return self.set }
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment