Skip to content

Commit

Permalink
wip: interner
Browse files Browse the repository at this point in the history
  • Loading branch information
ekiwi committed May 29, 2024
1 parent d1bfe11 commit 131c450
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 15 deletions.
82 changes: 80 additions & 2 deletions src/value/indexed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
// Access a slice of `Word` as a bit-vector.

use super::borrowed::{BitVecValueMutRef, BitVecValueRef};
use crate::{WidthInt, Word};
use crate::{BitVecOps, WidthInt, Word};
use std::collections::HashMap;

type WordIndex = u32;

Expand Down Expand Up @@ -209,10 +210,80 @@ fn split_borrow_2(
(dst_words, a_words, b_words)
}

/// Ensures that each bit vector value gets a unique index. And each combination of value and
/// width will get a unique BitVecValueIndex
pub struct BitVecValueInterner {
words: Vec<Word>,
small: HashMap<Word, WordIndex>,
large: HashMap<Box<[Word]>, WordIndex>,
}

impl BitVecValueInterner {
pub fn new() -> Self {
// initialize with some important constants
let words = vec![0, 1, 2, 3, 4, 5, 6, 7];
let small = HashMap::new();
let large = HashMap::new();
Self {
words,
small,
large,
}
}

pub fn get_index<I: BitVecOps>(&mut self, value: I) -> BitVecValueIndex {
let (words, width) = (value.words(), value.width());
if let &[word] = words {
debug_assert!(width <= Word::BITS);
if word < 8 {
BitVecValueIndex::new(word as WordIndex, width)
} else {
if let Some(index) = self.small.get(&word) {
BitVecValueIndex::new(*index, width)
} else {
let index = self.words.len() as WordIndex;
self.words.push(word);
self.small.insert(word, index);
BitVecValueIndex::new(index, width)
}
}
} else {
debug_assert!(width > Word::BITS);
if let Some(index) = self.large.get(words) {
BitVecValueIndex::new(*index, width)
} else {
let index = self.words.len() as WordIndex;
self.words.extend_from_slice(words);
self.large.insert(Box::from(words), index);
BitVecValueIndex::new(index, width)
}
}
}
}

impl<'a, I> GetBitVecRef<I, BitVecValueRef<'a>> for &'a BitVecValueInterner
where
I: AsRef<BitVecValueIndex>,
{
fn get_ref(self, index: I) -> BitVecValueRef<'a> {
(&self.words).get_ref(index)
}
}

impl<'a, I> GetBitVecRef<(I, I), (BitVecValueRef<'a>, BitVecValueRef<'a>)>
for &'a BitVecValueInterner
where
I: AsRef<BitVecValueIndex>,
{
fn get_ref(self, index: (I, I)) -> (BitVecValueRef<'a>, BitVecValueRef<'a>) {
(&self.words).get_ref(index)
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::BitVecMutOps;
use crate::{BitVecMutOps, BitVecValue};

#[test]
fn type_size() {
Expand Down Expand Up @@ -247,4 +318,11 @@ mod tests {
assert_eq!(src_a_3, &[1]);
assert_eq!(src_b_3, &[0, 1]);
}

#[test]
fn test_interner() {
let mut i = BitVecValueInterner::new();
assert_eq!(i.get_index(BitVecValue::tru()).index, 1);
assert_eq!(i.get_index(BitVecValue::fals()).index, 0);
}
}
17 changes: 4 additions & 13 deletions src/value/owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@ pub struct BitVecValue {
pub(crate) words: ValueVec,
}

const OWNED_TRUE: BitVecValue = BitVecValue {
width: 1,
words: SmallVec::from_const([1, 0]),
};
const OWNED_FALSE: BitVecValue = BitVecValue {
width: 1,
words: SmallVec::from_const([0, 0]),
};

impl BitVecValue {
/// Parse a string of 1s and 0s. The width of the resulting value is the number of digits.
pub fn from_bit_str(value: &str) -> Self {
Expand Down Expand Up @@ -64,10 +55,10 @@ impl BitVecValue {
}

pub fn tru() -> Self {
OWNED_TRUE
Self::from_u64(1, 1)
}
pub fn fals() -> Self {
OWNED_FALSE
Self::from_u64(0, 1)
}

#[cfg(feature = "bigint")]
Expand Down Expand Up @@ -99,13 +90,13 @@ impl BitVecValue {
/// Owned dense bit-vector array.
#[derive(Clone)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct DenseArrayValue {
pub struct ArrayValue {
pub(crate) index_width: WidthInt,
pub(crate) data_width: WidthInt,
pub(crate) words: Vec<Word>,
}

impl ArrayOps for DenseArrayValue {
impl ArrayOps for ArrayValue {
fn index_width(&self) -> WidthInt {
self.index_width
}
Expand Down

0 comments on commit 131c450

Please sign in to comment.