Skip to content
Snippets Groups Projects
Commit 9d2d98c8 authored by Cookiebowser's avatar Cookiebowser
Browse files

removed btypes lazy, since they dont work

parent aa973831
Branches
No related tags found
1 merge request!28Rust support
Showing
with 0 additions and 1885 deletions
[package]
name = "bmachine"
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"
threadpool = "1.8.1"
derivative = "2.2.0"
dashmap = "5.1.0"
btypes = { path = "../btypes" }
[profile.release]
opt-level = 3
[profile.dev]
opt-level = 0
[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 crate::lazy_ops::set_ops::setops::{IterWrapper, SetOp, SetOpTraits};
use crate::lazy_ops::set_ops::union::Union;
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;
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, Eq, PartialOrd, Ord, Clone)]
pub struct BSet<T: BObject> {
set: OrdSet<T>,
transformation: Option<Box<dyn SetOp<Item = T>>>,
}
impl<T: BObject> BSet<T> {
const OP_NAME: &'static str = "set";
}
impl<T: 'static + BObject> SetOp for BSet<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>> {
Box::new(self.clone())
}
fn get_op_name(&self) -> &str {
return BSet::<T>::OP_NAME;
}
fn get_rhs(&self) -> Option<Box<dyn SetOp<Item=Self::Item>>> {
return self.transformation.clone();
}
fn to_string(&self, _lhs: Option<&str>) -> String {
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 + "}";
match &self.transformation {
Some(op) => return op.to_string(Option::Some(result.as_str())),
None => return result,
}
}
}
impl<T: BObject> SetOpTraits for BSet<T> {
type Item = T;
fn iter_lazy<'a>(&'a self, _lhs: &BSet<Self::Item>) -> IterWrapper<T> {
match &self.transformation {
Some(op) => op.iter_lazy(self),
None => IterWrapper::single(self.iter_directly()),
}
}
fn contains_lazy(&self, _lhs: &BSet<Self::Item>, o: &Self::Item) -> bool {
match &self.transformation {
Some(op) => op.contains_lazy(self, o),
None => self.contains_directly(o),
}
}
fn is_empty_lazy(&self, _lhs: &BSet<Self::Item>) -> bool {
match &self.transformation {
Some(op) => op.is_empty_lazy(self),
None => self.is_empty_directly(),
}
}
fn size_lazy(&self, _lhs: &BSet<Self::Item>) -> usize {
let self_clone = self.clone();
match self.transformation {
Some(ref op) => op.size_lazy(&self_clone),
None => self.size_directly(),
}
}
}
impl<I: BObject> Hash for BSet<I> {
fn hash<H: Hasher>(self: &BSet<I>, state: &mut H) { self.set.hash(state); }
}
impl<I: BObject> PartialEq for BSet<I> {
fn eq(&self, other: &BSet<I>) -> bool {
if self.size() != other.size() { return false; }
for i in self.iter() {
if !other.contains(i) { return false; }
}
return true;
}
}
impl<T: 'static + BObject> BObject for BSet<T> {}
impl<T: 'static + 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: 'static + BObject> fmt::Display for BSet<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
return write!(f, "{}", <BSet<T> as SetOp>::to_string(self, Option::None));
}
}
/*
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: BObject> BSet<T> {
pub fn size(&self) -> usize { self.size_lazy(self) }
pub fn iter(&self) -> impl Iterator<Item = &T> + '_ { self.iter_lazy(self) }
pub fn iter_directly(&self) -> Iter<T> { self.set.iter() }
pub fn contains(&self, o: &T) -> bool { self.contains_lazy(self, o) }
pub fn contains_directly(&self, o: &T) -> bool { return self.set.contains(o); }
pub fn size_directly(&self) -> usize { return self.set.len(); }
pub fn is_empty_directly(&self) -> bool { return self.set.is_empty() }
}
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 get_direct_set(&self) -> Self {
return BSet { set: self.set.clone(), transformation: Option::None }
}
pub fn iter_complete<'a>(&'a self) -> IterWrapper<T> { self.iter_lazy(self) }
pub fn isEmpty(&self) -> bool { return self.is_empty_lazy(self); }
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> {
let result: OrdSet<T> = self.iter().fold(OrdSet::new(), |r_set, element| if set.contains(element) { r_set } else { r_set.update(element.clone()) });
return BSet::fromOrdSet(result);
}
pub fn _union(&self, set: &BSet<T>) -> BSet<T> {
return BSet { set: self.set.clone(), transformation: Option::Some(Box::new(Union::new(set.clone())))}
}
pub fn real_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(&mut self) -> BInteger {
return self._size();
}
pub fn _size(&mut self) -> BInteger {
return BInteger::new(self.size().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 self.subset(set).not();
}
pub fn strictSubset(&mut self, set: &mut BSet<T>) -> BBoolean {
return BBoolean::new(self.size() < set.size() && self.subset(set));
}
pub fn strictNotSubset(&mut self, set: &mut BSet<T>) -> BBoolean {
return BBoolean::new(self.size() >= set.size() || !self.subset(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.iter().nth(rng.gen_range(0..self.set.len())).unwrap().clone();
}
pub fn equal(&self, other: &BSet<T>) -> BBoolean {
return BBoolean::new(self.eq(other));
}
pub fn unequal(&self, other: &BSet<T>) -> BBoolean {
return BBoolean::new(!self.eq(other));
}
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
use crate::bobject::BObject;
use crate::bset::BSet;
use crate::lazy_ops::set_ops::setops::{SetOp, SetOpTraits};
use std::fmt;
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
#[derive(Clone)]
pub struct Identity<T: BObject> {
phantom: PhantomData<T>,
}
impl<T: BObject> Identity<T> {
const OP_NAME: &'static str = "Identity";
}
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> {
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})
}
fn get_op_name(&self) -> &str {
return Identity::<T>::OP_NAME;
}
fn get_rhs(&self) -> Option<Box<dyn SetOp<Item=Self::Item>>> {
return Option::None;
}
}
impl<T: 'static + BObject> SetOpTraits for Identity<T>{
type Item = T;
fn contains_lazy(&self, lhs: &BSet<Self::Item>, o: &Self::Item) -> bool { lhs.contains_directly(o) }
fn is_empty_lazy(&self, lhs: &BSet<Self::Item>) -> bool { lhs.is_empty_directly() }
fn size_lazy(&self, lhs: &BSet<Self::Item>) -> usize { lhs.size_directly() }
}
\ No newline at end of file
pub mod setops;
//pub mod identity;
pub mod union;
\ No newline at end of file
use std::hash::{Hasher};
use std::cmp::Ordering;
use std::fmt::{Debug};
use im::ordset::Iter;
use crate::bobject::BObject;
use crate::bset::BSet;
pub trait SetOp: SetOpTraits + Debug {
fn compute(&self, lhs: &BSet<Self::Item>) -> BSet<Self::Item>;
fn clone_box(&self) -> Box<dyn SetOp<Item = Self::Item>>;
fn get_op_name(&self) -> &str;
fn get_rhs(&self) -> Option<Box<dyn SetOp<Item = Self::Item>>>;
fn to_string(&self, lhs: Option<&str>) -> String {
let mut result = format!("{}(", self.get_op_name());
let mut has_lhs = false;
if lhs.is_some() {
result.push_str(lhs.unwrap());
has_lhs = true;
}
match self.get_rhs() {
Some(v) => {
if has_lhs { result.push_str(", "); }
result.push_str(format!("{}", v.to_string(Option::None)).as_str())
},
None => {},
}
result.push_str(")");
return result;
}
//PartialEq
fn eq_box(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> bool {
self.get_op_name().eq(other.get_op_name()) && self.get_rhs().eq(&other.get_rhs())
}
//PartialOrd
fn partial_cmp_box(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> Option<Ordering> {
let mut result = self.get_op_name().partial_cmp(other.get_op_name());
if result.is_some() {
if result.clone().unwrap().eq(&Ordering::Equal) {
result = self.get_rhs().partial_cmp(&other.get_rhs());
}
}
return result;
}
//Ord
fn cmp_box(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> Ordering {
let mut result = self.get_op_name().cmp(other.get_op_name());
if result.eq(&Ordering::Equal) {
result = self.get_rhs().cmp(&other.get_rhs());
}
return result;
}
fn lt(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> bool { self.cmp_box(other).eq(&Ordering::Less) }
fn le(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> bool { [Ordering::Less, Ordering::Equal].contains(&self.cmp_box(other)) }
fn gt(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> bool { self.cmp_box(other).eq(&Ordering::Greater) }
fn ge(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> bool { [Ordering::Greater, Ordering::Equal].contains(&self.cmp_box(other)) }
fn max(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> Box<dyn SetOp<Item = Self::Item>> {
match self.cmp_box(other) {
Ordering::Less => other.clone(),
Ordering::Equal => other.clone(),
Ordering::Greater => self.clone_box(),
}
}
fn min(&self, other: &Box<dyn SetOp<Item = Self::Item>>) -> Box<dyn SetOp<Item = Self::Item>> {
match self.cmp_box(other) {
Ordering::Less => self.clone_box(),
Ordering::Equal => self.clone_box(),
Ordering::Greater => other.clone(),
}
}
fn clamp(&self, min: &Box<dyn SetOp<Item = Self::Item>>, max: &Box<dyn SetOp<Item = Self::Item>>) -> Box<dyn SetOp<Item = Self::Item>> {
if self.lt(min) {
return min.clone()
} else if self.gt(max) {
max.clone()
} else {
self.clone_box()
}
}
}
pub trait SetOpTraits {
type Item: BObject;
fn iter_lazy<'a>(&'a self, lhs: &'a BSet<Self::Item>) -> IterWrapper<'a, Self::Item>;
fn contains_lazy(&self, lhs: &BSet<Self::Item>, o:&Self::Item) -> bool;
fn is_empty_lazy(&self, lhs: &BSet<Self::Item>) -> bool;
fn size_lazy(&self, lhs: &BSet<Self::Item>) -> usize;
//fn hash_val(&self) -> u64;
}
pub enum IterWrapperE<'a, T: BObject> {
Empty,
Single(Iter<'a, T>),
Chain(Box<IterWrapper<'a, T>>, Box<IterWrapper<'a, T>>),
Filtered(Box<IterWrapper<'a, T>>, BSet<T>),
}
pub struct IterWrapper<'a, T: BObject> {
iter: IterWrapperE<'a, T>,
}
impl<'a, T: BObject> IterWrapper<'a, T> {
pub fn empty() -> IterWrapper<'a, T> { IterWrapper { iter: IterWrapperE::Empty }}
pub fn single(iter: Iter<'a, T>) -> IterWrapper<'a, T> { IterWrapper { iter: IterWrapperE::Single(iter)} }
pub fn chain(iter_a: IterWrapper<'a, T>, iter_b: IterWrapper<'a, T>) -> IterWrapper<'a, T> {
IterWrapper { iter: IterWrapperE::Chain(Box::new(iter_a),
Box::new(iter_b))}
}
pub fn filtered(iter: IterWrapper<'a, T>, filter: BSet<T>) -> IterWrapper<'a, T> {
IterWrapper { iter: IterWrapperE::Filtered(Box::new(iter), filter)}
}
}
impl<'a, T: BObject> Iterator for IterWrapper<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
match self.iter {
IterWrapperE::Empty => Option::None,
IterWrapperE::Single(ref mut s) => s.next(),
IterWrapperE::Chain(ref mut a, ref mut b) => {
let option_a = a.next();
match option_a {
Some(result) => Some(result),
None => b.next(),
}
},
IterWrapperE::Filtered(ref mut i, ref filter) => {
let mut option = i.next();
while option.is_some() {
let val = option.unwrap();
if !filter.contains(val) { return Option::Some(val); }
option = i.next();
}
return option;
}
}
}
}
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_box(other)
}
}
impl<T: BObject> PartialOrd<Self> for Box<dyn SetOp<Item=T>> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.partial_cmp_box(other)
}
}
impl<T: BObject> Ord for Box<dyn SetOp<Item = T>> {
fn cmp(&self, other: &Self) -> Ordering {
self.cmp_box(other)
}
}
/*
impl<T: 'static + BObject> Default for Box<dyn SetOp<Item = T>> {
fn default() -> Box<Self> {
Box::new(Identity {phantom: PhantomData})
}
}
*/
\ No newline at end of file
use std::cell::RefCell;
use crate::bobject::BObject;
use crate::bset::BSet;
use crate::lazy_ops::set_ops::setops::{IterWrapper, SetOp, SetOpTraits};
use std::fmt;
use std::fmt::{Debug, Formatter};
use std::ops::Not;
#[derive(Clone)]
pub struct Union<T: BObject> {
rhs: BSet<T>,
rhs_is_reduced: bool,
}
impl<T: BObject> Union<T> {
const OP_NAME: &'static str = "Union";
}
impl<T: 'static + BObject> Debug for Union<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "Union({})", self.rhs)
}
}
impl<T: BObject> Union<T> {
pub fn new(rhs: BSet<T>) -> Union<T> {
Union {rhs: rhs, rhs_is_reduced: false}
}
}
impl<T: 'static + BObject> Union<T> {
fn check_reduced(&mut self, lhs: &BSet<T>) {
if !self.rhs_is_reduced {
let new_rhs = self.rhs.difference(&lhs.get_direct_set());
self.rhs = new_rhs;
self.rhs_is_reduced = true;
}
}
}
impl<T: 'static + BObject> SetOpTraits for Union<T>{
type Item = T;
fn iter_lazy<'a>(&'a self, lhs: &'a BSet<Self::Item>) -> IterWrapper<'a, T> {
//self.check_reduced(lhs); <-- would need me to make this function take &mut self, which would propagate to BSet::iter, which would break everything...
let iter_a = IterWrapper::single(lhs.iter_directly());
let iter_b = self.rhs.iter_complete();
if self.rhs_is_reduced {
return IterWrapper::chain(iter_a, iter_b);
}
return IterWrapper::chain(iter_a, IterWrapper::filtered(iter_b, lhs.get_direct_set()));
}
fn contains_lazy(&self, lhs: &BSet<Self::Item>, o: &Self::Item) -> bool {
lhs.contains_directly(o) || self.rhs.contains(o)
}
fn is_empty_lazy(&self, lhs: &BSet<Self::Item>) -> bool {
lhs.is_empty_directly() && self.rhs.isEmpty()
}
fn size_lazy(&self, lhs: &BSet<Self::Item>) -> usize {
if self.rhs_is_reduced {
return lhs.size_directly() + self.rhs.size();
}
return lhs.size_directly() + self.rhs.difference(&lhs.get_direct_set()).size();
}
}
impl<T: 'static + BObject> SetOp for Union<T> {
fn compute(&self, lhs: &BSet<T>) -> BSet<T> {
lhs.real_union(&self.rhs)
}
fn clone_box(&self) -> Box<dyn SetOp<Item=Self::Item>> {
Box::new(Union{rhs: self.rhs.clone(),
rhs_is_reduced: self.rhs_is_reduced})
}
fn get_op_name(&self) -> &str {
return Union::<T>::OP_NAME;
}
fn get_rhs(&self) -> Option<Box<dyn SetOp<Item=Self::Item>>> {
return Option::Some(self.rhs.clone_box());
}
}
\ 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<'a>(&'a self) -> Iter<'a, 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