From ab73461496489a2ab564c4d8f30e7f25de1f7644 Mon Sep 17 00:00:00 2001 From: Cookiebowser <lucas.doering@live.de> Date: Sat, 26 Feb 2022 14:29:46 +0100 Subject: [PATCH] added caching of hash for BRelation --- .../src/main/rust/btypes/src/brelation.rs | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/btypes_primitives/src/main/rust/btypes/src/brelation.rs b/btypes_primitives/src/main/rust/btypes/src/brelation.rs index 43dca53a0..fc4b023d9 100644 --- a/btypes_primitives/src/main/rust/btypes/src/brelation.rs +++ b/btypes_primitives/src/main/rust/btypes/src/brelation.rs @@ -1,6 +1,8 @@ #![ allow( dead_code, non_snake_case) ] +use std::collections::hash_map::DefaultHasher; use std::collections::LinkedList; +use std::cell::RefCell; use crate::bobject::BObject; use crate::binteger::{BInt, BInteger, FromBInt}; use crate::btuple::BTuple; @@ -23,19 +25,43 @@ enum CombiningType { UNION } -#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Default, Debug, Eq, PartialOrd, Ord)] pub struct BRelation<L: BObject, R: BObject> { map: HashMap<L, OrdSet<R>>, + hash_cache: RefCell<Option<u64>>, +} + +impl <L: BObject, R: BObject> Clone for BRelation<L, R> { + fn clone(&self) -> Self { + BRelation { map: self.map.clone(), hash_cache: RefCell::new(Option::None) } + } +} + +impl<L: BObject, R: BObject> PartialEq for BRelation<L, R> { + fn eq(&self, other: &BRelation<L, R>) -> bool { + self.map.eq(&other.map) + } } impl<L: BObject, R: BObject> Hash for BRelation<L, R> { - fn hash<H: Hasher>(&self, state: &mut H) { - let mut kvs = self.map.iter().collect::<Vec<(&L, &OrdSet<R>)>>(); - kvs.sort_by(|(k1, _v1), (k2, _v2)| k1.cmp(k2)); - for (key, value) in kvs { - key.hash(state); - value.iter().for_each(|v| v.hash(state)); + fn hash<H: Hasher>(self: &BRelation<L, R>, state: &mut H) { + let cache = self.hash_cache.clone().take(); + let hash: u64; + + if cache.is_none() { + let mut hasher = DefaultHasher::new(); + let mut kvs = self.map.iter().collect::<Vec<(&L, &OrdSet<R>)>>(); + kvs.sort_by(|(k1, _v1), (k2, _v2)| k1.cmp(k2)); + for (key, value) in kvs { + key.hash(&mut hasher); + value.iter().for_each(|v| v.hash(&mut hasher)); + } + hash = hasher.finish(); + self.hash_cache.replace(Option::Some(hash)); + } else { + hash = cache.unwrap(); } + hash.hash(state); } } @@ -86,7 +112,7 @@ impl<L: BObject, R: BObject> BObject for BRelation<L, R> {} impl<L: 'static + BObject, R: 'static + BObject> BRelation<L, R> { pub fn new(mut args: Vec<BTuple<L, R>>) -> BRelation<L,R> { - let mut ret: BRelation<L, R> = BRelation {map: HashMap::new() }; + let mut ret: BRelation<L, R> = BRelation {map: HashMap::new(), hash_cache: RefCell::new(Option::None) }; while !args.is_empty() { let current_tuple = args.remove(0); ret.insert(¤t_tuple); @@ -95,7 +121,7 @@ impl<L: 'static + BObject, R: 'static + BObject> BRelation<L, R> { } pub fn fromSet(set: BSet<BTuple<L, R>>) -> BRelation<L, R> { - let mut ret: BRelation<L, R> = BRelation {map: HashMap::new()}; + let mut ret: BRelation<L, R> = BRelation {map: HashMap::new(), hash_cache: RefCell::new(Option::None)}; set.iter().for_each(|current_tuple| ret.insert(current_tuple)); return ret; } @@ -112,7 +138,7 @@ impl<L: 'static + BObject, R: 'static + BObject> BRelation<L, R> { } fn update(&self, key: L, value: OrdSet<R>) -> Self { - BRelation{ map: self.map.update(key, value) } + BRelation{ map: self.map.update(key, value), hash_cache: RefCell::new(Option::None) } } fn update_unit(&self, key: L, value: R) -> Self { @@ -159,7 +185,7 @@ impl<L: 'static + BObject, R: 'static + BObject> BRelation<L, R> { } let empty_map = OrdSet::new(); - let mut result_map = BRelation{map: self.map.clone()}; + let mut result_map = BRelation{map: self.map.clone(), hash_cache: RefCell::new(Option::None)}; for domain_element in loop1_set { let this_range_set = self.map.get(&domain_element).unwrap_or(&empty_map).clone(); let other_range_set = other_map.get(&domain_element).unwrap_or(&empty_map).clone(); @@ -279,7 +305,7 @@ impl<L: 'static + BObject, R: 'static + BObject> BRelation<L, R> { } pub fn domainSubstraction(&self, arg: &BSet<L>) -> BRelation<L, R> { - return BRelation {map: arg.iter().fold(self.map.clone(), |map, e| map.without(e))} + return BRelation {map: arg.iter().fold(self.map.clone(), |map, e| map.without(e)), hash_cache: RefCell::new(Option::None)} } pub fn rangeRestriction(&self, arg: &BSet<R>) -> BRelation<L, R> { @@ -311,7 +337,7 @@ impl<L: 'static + BObject, R: 'static + BObject> BRelation<L, R> { } pub fn _override(&self, arg: &BRelation<L, R>) -> BRelation<L, R> { - return BRelation { map: arg.map.clone().union(self.map.clone())} + return BRelation { map: arg.map.clone().union(self.map.clone()), hash_cache: RefCell::new(Option::None)} } pub fn directProduct<ArgR: 'static + BObject>(&self, arg: &BRelation<L, ArgR>) -> BRelation<L, BTuple<R, ArgR>> { @@ -474,6 +500,7 @@ where L: 'static + BInt + FromBInt, map: self.map.iter().fold(HashMap::<L, OrdSet<R>>::new(), |result, (k, v)| result.update(L::from(&size.minus(&k.get_binteger_value())), v.clone())), + hash_cache: RefCell::new(Option::None) } } -- GitLab