From 74321fe63c2a031f9f5996a3da068ee0fd3990e6 Mon Sep 17 00:00:00 2001 From: Cookiebowser <lucas.doering@live.de> Date: Mon, 12 Jun 2023 14:38:54 +0200 Subject: [PATCH] optimizations for bitvec implementation --- .../btypes_bitvec/src/brelation.rs | 124 ++++++++++-------- .../rust_embedded/btypes_bitvec/src/bset.rs | 11 +- 2 files changed, 74 insertions(+), 61 deletions(-) diff --git a/btypes_primitives/src/main/rust_embedded/btypes_bitvec/src/brelation.rs b/btypes_primitives/src/main/rust_embedded/btypes_bitvec/src/brelation.rs index 3922a8a6e..9f0f2b673 100644 --- a/btypes_primitives/src/main/rust_embedded/btypes_bitvec/src/brelation.rs +++ b/btypes_primitives/src/main/rust_embedded/btypes_bitvec/src/brelation.rs @@ -2,7 +2,7 @@ use core::convert::TryInto; use core::marker::PhantomData; -use core::ops::{BitAnd, BitOrAssign}; +use core::ops::{BitAnd, BitOr, BitOrAssign}; use bitvec::mem; use bitvec::array::BitArray; use bitvec::prelude::Lsb0; @@ -12,8 +12,8 @@ use crate::bset::{BSet, PowSetItem, Set, SetItem}; #[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] pub struct BRelation<L: SetItem<LS>, const LS: usize, R: SetItem<RS>, const RS: usize, const REL_SIZE: usize> -where [usize; mem::elts::<usize>(LS*RS)]: Sized { - rel: BitArray<[usize; mem::elts::<usize>(LS*RS)], Lsb0>, // indexing: rel[l_idx*RS + r_idx] +where [usize; mem::elts::<usize>(RS)]: Sized { + rel: [BitArray<[usize; mem::elts::<usize>(RS)], Lsb0>; LS], // indexing: rel[l_idx][r_idx] _p: core::marker::PhantomData<L>, _p2: core::marker::PhantomData<R>, } @@ -21,9 +21,9 @@ where [usize; mem::elts::<usize>(LS*RS)]: Sized { impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> Default for BRelation<L, LS, R, RS, REL_SIZE> where L: SetItem<LS>, R: SetItem<RS>, - [usize; mem::elts::<usize>(LS*RS)]: Sized { + [usize; mem::elts::<usize>(RS)]: Sized { fn default() -> Self { - BRelation { rel: BitArray::ZERO, _p: PhantomData, _p2: PhantomData } + BRelation { rel: [BitArray::ZERO; LS], _p: PhantomData, _p2: PhantomData } } } @@ -55,25 +55,23 @@ pub trait RelLeftItem<const LEFT_SIZE: usize, RightItem: SetItem<RIGHT_SIZE>, co impl<L, const LS: usize, R, const RS: usize, const SIZE: usize, const REL_SIZE: usize> SetItem<SIZE> for BRelation<L, LS, R, RS, REL_SIZE> where L: SetItem<LS> + RelLeftItem<LS, R, RS, SIZE, REL_SIZE>, R: SetItem<RS>, - [usize; mem::elts::<usize>(LS*RS)]: Sized { + [usize; mem::elts::<usize>(RS)]: Sized { fn as_idx(&self) -> usize { let mut rel_arr: [[bool; RS]; LS] = [[false; RS]; LS]; for l_idx in 0..LS { - let left_idx = l_idx * RS; for r_idx in 0..RS { - rel_arr[l_idx][r_idx] = self.rel[left_idx + r_idx]; + rel_arr[l_idx][r_idx] = self.rel[l_idx][r_idx]; } } return L::rel_to_idx(rel_arr); } fn from_idx(idx: usize) -> Self { - let mut res = BitArray::<[usize; mem::elts::<usize>(LS*RS)], Lsb0>::ZERO; + let mut res = [BitArray::<[usize; mem::elts::<usize>(RS)], Lsb0>::ZERO; LS]; let rel_arr: [[bool; RS]; LS] = L::idx_to_rel(idx); for l_idx in 0..LS { - let left_idx = l_idx * RS; for r_idx in 0..RS { - res.set(left_idx + r_idx, rel_arr[l_idx][r_idx]); + res[l_idx].set(r_idx, rel_arr[l_idx][r_idx]); } } return BRelation { rel: res, _p: PhantomData, _p2: PhantomData }; @@ -133,17 +131,18 @@ pub trait TBRelation { } impl<L: SetItem<LS>, const LS: usize, R: SetItem<RS>, const RS: usize, const REL_SIZE: usize> TBRelation for BRelation<L, LS, R, RS, REL_SIZE> -where [usize; mem::elts::<usize>(LS*RS)]: Sized {} +where [usize; mem::elts::<usize>(RS)]: Sized {} impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, LS, R, RS, REL_SIZE> where L: SetItem<LS>, R: SetItem<RS>, [usize; mem::elts::<usize>(LS)]: Sized, [usize; mem::elts::<usize>(RS)]: Sized, - [usize; mem::elts::<usize>(LS*RS)]: Sized { +// [usize; mem::elts::<usize>(LS*RS)]: Sized + { pub const fn empty() -> Self { - BRelation { rel: BitArray::ZERO, _p: PhantomData, _p2: PhantomData } + BRelation { rel: [BitArray::ZERO; LS], _p: PhantomData, _p2: PhantomData } } pub const fn copy(&self) -> Self { @@ -151,9 +150,8 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, } pub fn slice_as_array(&self, left_idx: usize) -> [bool; RS] { - let l_idx = left_idx*RS; let mut result = [false; RS]; - for i in 0..RS { result[i] = self.rel[l_idx+i]; } + for i in 0..RS { result[i] = self.rel[left_idx][i]; } return result; } @@ -163,21 +161,21 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, let mut result = self.copy(); let left_idx = left_item.as_idx(); let right_idx = right_item.as_idx(); - result.rel[left_idx*RS .. (left_idx*RS + RS-1)].fill(false); - result.rel.set(left_idx*RS + right_idx, true); + result.rel[left_idx].fill(false); + result.rel[left_idx].set(right_idx, true); return result; } pub fn add_tuple(&mut self, left_item: &L, right_item: &R) { //println!("adding tuple ({:?},{:?}), idx = [{}][{}]", left_item, right_item, left_item.as_idx(), right_item.as_idx()); - self.rel.set(left_item.as_idx()*RS + right_item.as_idx(), true); + self.rel[left_item.as_idx()].set(right_item.as_idx(), true); } //b2program has this name hardcoded... pub fn functionCall(&self, key: &L) -> R { - let l_idx = key.as_idx()*RS; + let l_idx = key.as_idx(); for i in 0..RS { - if self.rel[l_idx+i] { return R::from_idx(i) } + if self.rel[l_idx][i] { return R::from_idx(i) } } panic!("ERROR: key {:?} not found in set!", key); } @@ -192,14 +190,14 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, } */ pub fn card(&self) -> BInteger { - return self.rel[0 .. RS*LS].count_ones().try_into().unwrap(); + return self.rel.iter().fold(0, |val, vec| val + vec.count_ones()).try_into().unwrap(); } //this name is also hard-coded... //checks if self.domain is a subset of the given set pub fn checkDomain(&self, domain: &BSet<L, LS>) -> bool { for left_idx in 0..LS { - if !domain.contains_idx(left_idx) && self.rel[left_idx * RS..(left_idx + 1) * RS].any() { + if !domain.contains_idx(left_idx) && self.rel[left_idx].any() { return false; } } @@ -211,7 +209,7 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, pub fn isTotal(&self, domain: &BSet<L, LS>) -> bool { for left_idx in 0..LS { // self.domain.contains(left_idx) <=> domain.contains(left_idx) - if domain.contains_idx(left_idx) != self.rel[left_idx * RS..(left_idx + 1) * RS].any() { + if domain.contains_idx(left_idx) != self.rel[left_idx].any() { return false; } } @@ -223,8 +221,8 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, pub fn checkRange(&self, range: &BSet<R, RS>) -> bool { let range_arr = range.as_bitarray(); for left_idx in 0..LS { - let current_range = &self.rel[left_idx * RS..(left_idx + 1) * RS]; - if (range_arr & current_range) != current_range { + let current_range = &self.rel[left_idx]; + if !range_arr.bitor(current_range).eq(current_range) { return false; } } @@ -235,7 +233,7 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, //checks if for each L there is at most one R pub fn isFunction(&self) -> bool { for left_idx in 0..LS { - if self.rel[left_idx*RS .. (left_idx+1)*RS].count_ones() > 1 { return false; } + if self.rel[left_idx].count_ones() > 1 { return false; } } return true; } @@ -244,7 +242,7 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, pub fn isInjection(&self) -> bool { let mut checked = BitArray::<[usize; mem::elts::<usize>(RS)], Lsb0>::ZERO; //stores all the R's that were already 'used' for i in 0..LS { - let current_slice = &self.rel[i*RS .. (i+1)*RS]; + let current_slice = &self.rel[i]; if checked.bitand(current_slice).any() { return false; } // one R of current slice is already in checked -> no injection checked |= current_slice; } @@ -254,19 +252,33 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, pub fn domain(&self) -> BSet<L, LS> { let mut result = BitArray::<[usize; mem::elts::<usize>(LS)], Lsb0>::ZERO; for i in 0..LS { - result.set(i, self.rel[i*RS .. (i+1)*RS].any()); + result.set(i, self.rel[i].any()); } return BSet::<L, LS>::from_bitarray(result); } + /* + pub fn range(&self) -> BSet<R, RS> { + let mut result = BitArray::<[usize; mem::elts::<usize>(RS)], Lsb0>::ZERO; + for left_idx in 0..LS { + for right_idx in 0..RS { + result.set(right_idx, self.rel[left_idx*RS + right_idx]); + } + } + return BSet::<R, RS>::from_bitarray(result); + } + */ + + pub fn range(&self) -> BSet<R, RS> { let mut result = BitArray::<[usize; mem::elts::<usize>(RS)], Lsb0>::ZERO; for left_idx in 0..LS { - result |= &self.rel[left_idx*RS .. (left_idx+1)*RS]; + result |= &self.rel[left_idx]; } return BSet::<R, RS>::from_bitarray(result); } + pub fn cartesian_product<TL, TR>(left_set: &TL, right_set: &TR) -> Self where TL: Set<LS, ItemType = L>, TR: Set<RS, ItemType = R> { @@ -274,8 +286,8 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, let mut bit_mask = BitArray::<[usize; mem::elts::<usize>(RS)], Lsb0>::ZERO; let mut result = Self::empty(); for l_idx in 0..LS { - bit_mask.fill(left_set.contains_idx(l_idx)); - result.rel[l_idx*RS .. (l_idx+1)*RS].copy_from_bitslice(&(right_arr & bit_mask)); + bit_mask.fill(left_set.contains_idx(l_idx)); // avoids branching + result.rel[l_idx].copy_from_bitslice(&(right_arr & bit_mask)); } return result; } @@ -285,7 +297,7 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, let mut result = BRelation::<R, RS, L, LS, REL_SIZE>::empty(); for left_idx in 0..LS { for right_idx in 0..RS { - result.rel.set(right_idx*LS + left_idx, self.rel[left_idx*RS + right_idx]); + result.rel[right_idx].set(left_idx, self.rel[left_idx][right_idx]); } } return result; @@ -294,7 +306,7 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, pub fn domainRestriction(&self, domain_set: &BSet<L, LS>) -> Self { let mut result = self.copy(); for left_idx in 0..LS { - if !domain_set.contains_idx(left_idx) { result.rel[left_idx*RS .. (left_idx+1)*RS].fill(false); } + if !domain_set.contains_idx(left_idx) { result.rel[left_idx].fill(false); } } return result; } @@ -302,7 +314,7 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, pub fn domainSubstraction(&self, domain_set: &BSet<L, LS>) -> Self { let mut result = self.copy(); for left_idx in 0..LS { - if domain_set.contains_idx(left_idx) { result.rel[left_idx*RS .. (left_idx+1)*RS].fill(false); } + if domain_set.contains_idx(left_idx) { result.rel[left_idx].fill(false); } } return result; } @@ -312,7 +324,7 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, let range_arr = range_set.as_bitarray(); for left_idx in 0..LS { //retain only elements that are in self *and* in range_set - result.rel[left_idx*RS .. (left_idx+1)*RS] &= range_arr; + result.rel[left_idx] &= range_arr; } return result; } @@ -322,7 +334,7 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, let not_range_arr = !range_set.as_bitarray(); for left_idx in 0..LS { //retain only elements that are in self *but not* in range_set - result.rel[left_idx*RS .. (left_idx+1)*RS] &= not_range_arr; + result.rel[left_idx] &= not_range_arr; } return result; } @@ -331,7 +343,7 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, let mut result_arr = BitArray::<[usize; mem::elts::<usize>(RS)], Lsb0>::ZERO; for left_idx in 0..LS { if result_domain.contains_idx(left_idx) { - result_arr.bitor_assign(&self.rel[left_idx*RS .. (left_idx+1)*RS]); + result_arr.bitor_assign(&self.rel[left_idx]); } } return BSet::<R, RS>::from_bitarray(result_arr); @@ -339,19 +351,25 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, pub fn intersect(&self, other: &Self) -> Self { let mut result = self.copy(); - result.rel &= other.rel; + for l_idx in 0..LS { + result.rel[l_idx] &= other.rel[l_idx]; + } return result; } pub fn difference(&self, other: &Self) -> Self { let mut result = self.copy(); - result.rel &= !other.rel; + for l_idx in 0..LS { + result.rel[l_idx] &= !other.rel[l_idx]; + } return result; } pub fn union(&self, other: &Self) -> Self { let mut result = self.copy(); - result.rel |= other.rel; + for l_idx in 0..LS { + result.rel[l_idx] |= other.rel[l_idx]; + } return result; } @@ -364,16 +382,19 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, } pub fn elementOf(&self, (k, v): &(L, R)) -> BBoolean { - return self.rel[k.as_idx()*RS + v.as_idx()]; + return self.rel[k.as_idx()][v.as_idx()]; } pub fn noElementOf(&self, (k, v): &(L, R)) -> BBoolean { - return !self.rel[k.as_idx()*RS + v.as_idx()]; + return !self.rel[k.as_idx()][v.as_idx()]; } //subset or equal pub fn subset(&self, other: &Self) -> BBoolean { - return (other.rel & self.rel) == self.rel; + for l_idx in 0..LS { + if (other.rel[l_idx] & self.rel[l_idx]) != self.rel[l_idx] { return false } + } + return true; } pub fn notSubset(&self, other: &Self) -> BBoolean { @@ -383,8 +404,8 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, pub fn _override(&self, other: &Self) -> Self { let mut result = self.copy(); for left_idx in 0..LS { - let other_slice = &other.rel[left_idx*RS .. (left_idx+1)*RS]; - if other_slice.any() { result.rel[left_idx*RS .. (left_idx+1)*RS].copy_from_bitslice(other_slice); } + let other_slice = &other.rel[left_idx]; + if other_slice.any() { result.rel[left_idx].copy_from_bitslice(other_slice); } } return result; } @@ -398,12 +419,9 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, [usize; mem::elts::<usize>(LS*NEW_RS)]: Sized { let mut result = BRelation::<L, LS, NewR, NEW_RS, NEW_TOTAL>::empty(); for left_idx in 0..LS { - let l_idx = left_idx*NEW_RS; - //let mut foo: BitArray<[usize; mem::elts::<usize>(NEW_RS)], Lsb0> = BitArray::ZERO; for r_idx in 0..RS { - if self.rel[l_idx+r_idx] { result.rel[l_idx .. l_idx+NEW_RS] |= &arg.rel[r_idx*NEW_RS .. (r_idx+1)*NEW_RS]; } + if self.rel[left_idx][r_idx] { result.rel[left_idx] |= &arg.rel[r_idx]; } } - //result.rel[l_idx .. l_idx+NEW_RS].copy_from_bitslice(&foo); } return result; } @@ -422,7 +440,7 @@ impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, for left_idx in 0..LS { let result_set: [bool; RS] = self.slice_as_array(left_idx); if !result_set.contains(&true) { continue; } // dont create mappings to empty set - result.rel.set(left_idx*LS + NewR::from_arr(result_set).as_idx(), true); + result.rel[left_idx].set(NewR::from_arr(result_set).as_idx(), true); } return result; } @@ -458,7 +476,7 @@ where L: SetItem<LS>, pub fn identity(set: &BSet<L, LS>) -> Self { let mut result = Self::empty(); for i in 0..LS { - if set.contains_idx(i) { result.rel.set(i*(LS+1), true); } + if set.contains_idx(i) { result.rel[i].set(i, true); } } return result; } @@ -539,7 +557,7 @@ where L: SetItem<LS> + BInt, let mut result = self.copy(); for i in (*n+1)..=self.size() { let i_as_l = L::from(i); - result.rel.set(i_as_l.as_idx()*RS + self.functionCall(&i_as_l).as_idx(), false); + result.rel[i_as_l.as_idx()].set(self.functionCall(&i_as_l).as_idx(), false); } return result; } diff --git a/btypes_primitives/src/main/rust_embedded/btypes_bitvec/src/bset.rs b/btypes_primitives/src/main/rust_embedded/btypes_bitvec/src/bset.rs index 0210c71bf..949475ad5 100644 --- a/btypes_primitives/src/main/rust_embedded/btypes_bitvec/src/bset.rs +++ b/btypes_primitives/src/main/rust_embedded/btypes_bitvec/src/bset.rs @@ -367,11 +367,6 @@ where [usize; mem::elts::<usize>(SIZE)]: Sized { } } -/* -EINT: SetItem<4> + PowSetItem<16, 4> -BSet<EINT, 4>: Set<4> + SetItem<16> -BSet<BSet<Enit, 4>, 16>: Set<16> -*/ pub trait NestedSet<const OUTER_SIZE: usize, const INNER_SIZE: usize> where Self: Set<OUTER_SIZE>, @@ -440,11 +435,11 @@ impl<I: SetItem<SIZE>, const SIZE: usize> Iterator for BSetIter<I, SIZE> { macro_rules! bset { ($set_type:ty$(, $e:expr )* ) => { { - let mut __temp_gen_arr__ = [false; <$set_type>::VARIANTS]; + let mut __temp_gen_arr__ = BSet::<$set_type, { <$set_type>::VARIANTS }>::empty(); $( - __temp_gen_arr__[($e).as_idx()] = true; + __temp_gen_arr__.add_idx(($e).as_idx()); )* - BSet::<$set_type, { <$set_type>::VARIANTS }>::from_arr(__temp_gen_arr__) + __temp_gen_arr__ } }; } -- GitLab