-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
split folder hierachy into bv and array
- Loading branch information
Showing
19 changed files
with
486 additions
and
419 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[package] | ||
name = "baa" | ||
version = "0.9.5" | ||
version = "0.10.0" | ||
edition = "2021" | ||
authors = ["Kevin Laeufer <[email protected]>"] | ||
description = "BitVector and Array Arithmetic" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,11 @@ | ||
// Copyright 2023-2024 The Regents of the University of California | ||
// Copyright 2024 Cornell University | ||
// released under BSD 3-Clause License | ||
// author: Kevin Laeufer <[email protected]> | ||
// | ||
// Borrowed bit-vector and array values. | ||
|
||
use crate::{ | ||
ArrayMutOps, ArrayOps, ArrayValue, BitVecMutOps, BitVecOps, BitVecValue, WidthInt, Word, | ||
}; | ||
|
||
/// Bit-vector value that does not own its storage. | ||
#[derive(Clone, Copy)] | ||
pub struct BitVecValueRef<'a> { | ||
pub(crate) width: WidthInt, | ||
pub(crate) words: &'a [Word], | ||
} | ||
|
||
impl<'a> BitVecValueRef<'a> { | ||
pub(crate) fn new(width: WidthInt, words: &'a [Word]) -> Self { | ||
Self { width, words } | ||
} | ||
} | ||
|
||
impl<'a> From<&'a BitVecValue> for BitVecValueRef<'a> { | ||
fn from(value: &'a BitVecValue) -> Self { | ||
Self::new(value.width, value.words.as_ref()) | ||
} | ||
} | ||
|
||
impl<'a> std::fmt::Debug for BitVecValueRef<'a> { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "BitVecValueRef({})", self.to_bit_str()) | ||
} | ||
} | ||
|
||
pub struct BitVecValueMutRef<'a> { | ||
pub(crate) width: WidthInt, | ||
pub(crate) words: &'a mut [Word], | ||
} | ||
|
||
impl<'a> BitVecValueMutRef<'a> { | ||
pub(crate) fn new(width: WidthInt, words: &'a mut [Word]) -> Self { | ||
Self { width, words } | ||
} | ||
} | ||
|
||
impl<'a> From<&'a mut BitVecValue> for BitVecValueMutRef<'a> { | ||
fn from(value: &'a mut BitVecValue) -> Self { | ||
Self::new(value.width, value.words.as_mut()) | ||
} | ||
} | ||
impl<'a> std::fmt::Debug for BitVecValueMutRef<'a> { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "BitVecValueMutRef({})", self.to_bit_str()) | ||
} | ||
} | ||
// author: Kevin Laeufer <[email protected]> | ||
|
||
impl<'a> BitVecOps for BitVecValueRef<'a> { | ||
fn width(&self) -> WidthInt { | ||
self.width | ||
} | ||
|
||
fn words(&self) -> &[Word] { | ||
self.words | ||
} | ||
} | ||
|
||
impl<'a> BitVecOps for BitVecValueMutRef<'a> { | ||
fn width(&self) -> WidthInt { | ||
self.width | ||
} | ||
|
||
fn words(&self) -> &[Word] { | ||
self.words | ||
} | ||
} | ||
|
||
impl<'a> BitVecMutOps for BitVecValueMutRef<'a> { | ||
fn words_mut(&mut self) -> &mut [Word] { | ||
self.words | ||
} | ||
} | ||
use crate::array::ops::{ArrayMutOps, ArrayOps}; | ||
use crate::array::owned::ArrayValue; | ||
use crate::{WidthInt, Word}; | ||
|
||
/// Bit-vector array value that does not own its storage. | ||
#[derive(Clone)] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// Copyright 2023-2024 The Regents of the University of California | ||
// Copyright 2024 Cornell University | ||
// released under BSD 3-Clause License | ||
// author: Kevin Laeufer <[email protected]> | ||
|
||
use crate::array::borrowed::{ArrayValueMutRef, ArrayValueRef}; | ||
use crate::{BitVecValueIndex, IndexToMutRef, IndexToRef, WidthInt, Word}; | ||
use std::borrow::Borrow; | ||
|
||
/// Index of an array value in a shared value store. | ||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||
pub struct ArrayValueIndex { | ||
pub(super) first: BitVecValueIndex, | ||
pub(super) index_width: WidthInt, | ||
} | ||
|
||
impl ArrayValueIndex { | ||
pub fn new(first: BitVecValueIndex, index_width: WidthInt) -> Self { | ||
Self { first, index_width } | ||
} | ||
} | ||
|
||
impl ArrayValueIndex { | ||
#[inline] | ||
pub fn num_elements(&self) -> usize { | ||
1usize << self.index_width | ||
} | ||
|
||
#[inline] | ||
pub fn words(&self) -> usize { | ||
self.first.words() * self.num_elements() | ||
} | ||
|
||
#[inline] | ||
pub fn to_range(&self) -> std::ops::Range<usize> { | ||
let start = self.first.index as usize; | ||
let end = start + self.words(); | ||
start..end | ||
} | ||
|
||
#[inline] | ||
pub fn first_element_index(&self) -> BitVecValueIndex { | ||
self.first | ||
} | ||
} | ||
|
||
impl<'a, I> IndexToRef<I, ArrayValueRef<'a>> for &'a [Word] | ||
where | ||
I: Borrow<ArrayValueIndex>, | ||
{ | ||
fn get_ref(self, index: I) -> ArrayValueRef<'a> { | ||
ArrayValueRef { | ||
index_width: index.borrow().index_width, | ||
data_width: index.borrow().first.width(), | ||
words: &self[index.borrow().to_range()], | ||
} | ||
} | ||
} | ||
|
||
impl<'a, I> IndexToMutRef<I, ArrayValueMutRef<'a>> for &'a mut [Word] | ||
where | ||
I: Borrow<ArrayValueIndex>, | ||
{ | ||
fn get_mut_ref(self, index: I) -> ArrayValueMutRef<'a> { | ||
ArrayValueMutRef { | ||
index_width: index.borrow().index_width, | ||
data_width: index.borrow().first.width(), | ||
words: &mut self[index.borrow().to_range()], | ||
} | ||
} | ||
} | ||
|
||
impl<'a, I1, I2> IndexToMutRef<(I1, I2), (ArrayValueMutRef<'a>, ArrayValueRef<'a>)> | ||
for &'a mut [Word] | ||
where | ||
I1: Borrow<ArrayValueIndex>, | ||
I2: Borrow<ArrayValueIndex>, | ||
{ | ||
fn get_mut_ref(self, (a, b): (I1, I2)) -> (ArrayValueMutRef<'a>, ArrayValueRef<'a>) { | ||
let (a_words, b_words) = | ||
crate::bv::split_borrow_1(self, a.borrow().to_range(), b.borrow().to_range()); | ||
|
||
( | ||
ArrayValueMutRef { | ||
index_width: a.borrow().index_width, | ||
data_width: a.borrow().first.width(), | ||
words: a_words, | ||
}, | ||
ArrayValueRef { | ||
index_width: b.borrow().index_width, | ||
data_width: b.borrow().first.width(), | ||
words: b_words, | ||
}, | ||
) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use crate::{ArrayMutOps, BitVecValue}; | ||
|
||
#[test] | ||
fn type_size() { | ||
assert_eq!(std::mem::size_of::<WidthInt>(), 4); | ||
assert_eq!(std::mem::size_of::<ArrayValueIndex>(), 12); | ||
} | ||
|
||
#[test] | ||
fn test_array_index() { | ||
let mut backend = [0; 32]; | ||
|
||
// a four element array with 2-word entries | ||
let a0 = BitVecValueIndex::new(1, 65); | ||
let a = a0.to_array_index(2); | ||
assert_eq!(a.num_elements(), 4); | ||
assert_eq!(a.words(), 8); | ||
assert_eq!(a.to_range(), 1..9); | ||
|
||
// another array of the same size | ||
let b = BitVecValueIndex::new(9, 65).to_array_index(2); | ||
|
||
// set some elements | ||
{ | ||
let mut a = backend.get_mut_ref(a); | ||
a.store( | ||
&BitVecValue::from_u64(1, 2), | ||
&BitVecValue::from_u64(1234, 65), | ||
); | ||
a.store( | ||
&BitVecValue::from_u64(3, 2), | ||
&BitVecValue::from_u64(555555, 65), | ||
); | ||
} | ||
assert_eq!(backend[2 + 1], 1234); | ||
assert_eq!(backend[3 + 1], 0); | ||
assert_eq!(backend[6 + 1], 555555); | ||
assert_eq!(backend[7 + 1], 0); | ||
|
||
// check b array storage and initialize to magic value | ||
for ii in 9..(9 + 2 * 4) { | ||
assert_eq!(backend[ii], 0); | ||
backend[ii] = 99999; | ||
} | ||
|
||
// assign b := a | ||
{ | ||
let (mut b, a) = backend.get_mut_ref((b, a)); | ||
b.assign(a); | ||
} | ||
|
||
// check new b values | ||
assert_eq!(backend[2 + 9], 1234); | ||
assert_eq!(backend[3 + 9], 0); | ||
assert_eq!(backend[6 + 9], 555555); | ||
assert_eq!(backend[7 + 9], 0); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Copyright 2024 Cornell University | ||
// released under BSD 3-Clause License | ||
// author: Kevin Laeufer <[email protected]> | ||
|
||
mod borrowed; | ||
mod indexed; | ||
mod ops; | ||
mod owned; | ||
|
||
pub use borrowed::{ArrayValueMutRef, ArrayValueRef}; | ||
pub use indexed::ArrayValueIndex; | ||
pub use ops::{ArrayMutOps, ArrayOps}; | ||
pub use owned::ArrayValue; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright 2023-2024 The Regents of the University of California | ||
// Copyright 2024 Cornell University | ||
// released under BSD 3-Clause License | ||
// author: Kevin Laeufer <[email protected]> | ||
// | ||
// Traits for operations on arrays. | ||
|
||
use crate::{ | ||
ArrayValueRef, BitVecMutOps, BitVecOps, BitVecValueMutRef, BitVecValueRef, WidthInt, Word, | ||
}; | ||
|
||
pub const DENSE_ARRAY_MAX_INDEX_WIDTH: WidthInt = 48; | ||
|
||
/// Operations implemented by read-only array values with a dense representation. | ||
pub trait ArrayOps { | ||
fn index_width(&self) -> WidthInt; | ||
fn data_width(&self) -> WidthInt; | ||
fn words(&self) -> &[Word]; | ||
#[inline] | ||
fn words_per_element(&self) -> usize { | ||
self.data_width().div_ceil(Word::BITS) as usize | ||
} | ||
#[inline] | ||
fn num_elements(&self) -> usize { | ||
1usize << self.index_width() | ||
} | ||
fn select<'a>(&self, index: impl Into<BitVecValueRef<'a>>) -> BitVecValueRef { | ||
let index = index.into(); | ||
debug_assert!(self.index_width() <= DENSE_ARRAY_MAX_INDEX_WIDTH); | ||
debug_assert_eq!(self.index_width(), index.width()); | ||
debug_assert_eq!(index.words().len(), 1); | ||
let start = self.words_per_element() * index.words()[0] as usize; | ||
let end = start + self.words_per_element(); | ||
BitVecValueRef::new(self.data_width(), &self.words()[start..end]) | ||
} | ||
fn is_equal<R: ArrayOps + ?Sized>(&self, rhs: &R) -> bool { | ||
debug_assert_eq!(self.index_width(), rhs.index_width()); | ||
debug_assert_eq!(self.data_width(), rhs.data_width()); | ||
self.words() == rhs.words() | ||
} | ||
} | ||
|
||
/// Operations implemented by mutable array values with a dense representation. | ||
pub trait ArrayMutOps: ArrayOps { | ||
fn words_mut(&mut self) -> &mut [Word]; | ||
fn store<'a, 'b>( | ||
&mut self, | ||
index: impl Into<BitVecValueRef<'a>>, | ||
data: impl Into<BitVecValueRef<'b>>, | ||
) { | ||
let index = index.into(); | ||
debug_assert!(self.index_width() <= DENSE_ARRAY_MAX_INDEX_WIDTH); | ||
debug_assert_eq!(self.index_width(), index.width()); | ||
debug_assert_eq!(index.words().len(), 1); | ||
let start = self.words_per_element() * index.words()[0] as usize; | ||
let end = start + self.words_per_element(); | ||
let mut element = | ||
BitVecValueMutRef::new(self.data_width(), &mut self.words_mut()[start..end]); | ||
element.assign(data); | ||
} | ||
fn select_mut<I: BitVecOps>(&mut self, index: I) -> BitVecValueMutRef { | ||
debug_assert!(self.index_width() <= DENSE_ARRAY_MAX_INDEX_WIDTH); | ||
debug_assert_eq!(self.index_width(), index.width()); | ||
debug_assert_eq!(index.words().len(), 1); | ||
let start = self.words_per_element() * index.words()[0] as usize; | ||
let end = start + self.words_per_element(); | ||
BitVecValueMutRef::new(self.data_width(), &mut self.words_mut()[start..end]) | ||
} | ||
fn assign<'a>(&mut self, value: impl Into<ArrayValueRef<'a>>) { | ||
let value = value.into(); | ||
debug_assert_eq!(self.index_width(), value.index_width()); | ||
debug_assert_eq!(self.data_width(), value.data_width()); | ||
debug_assert_eq!(self.words_mut().len(), value.words().len()); | ||
self.words_mut().copy_from_slice(value.words()); | ||
} | ||
/// sets all bits to zero | ||
fn clear(&mut self) { | ||
self.words_mut().iter_mut().for_each(|w| { | ||
*w = 0; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright 2023-2024 The Regents of the University of California | ||
// Copyright 2024 Cornell University | ||
// released under BSD 3-Clause License | ||
// author: Kevin Laeufer <[email protected]> | ||
|
||
use crate::array::ops::{ArrayMutOps, ArrayOps}; | ||
use crate::{WidthInt, Word}; | ||
|
||
/// Owned dense bit-vector array. | ||
#[derive(Clone)] | ||
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] | ||
pub struct ArrayValue { | ||
pub(crate) index_width: WidthInt, | ||
pub(crate) data_width: WidthInt, | ||
pub(crate) words: Vec<Word>, | ||
} | ||
|
||
impl ArrayOps for ArrayValue { | ||
fn index_width(&self) -> WidthInt { | ||
self.index_width | ||
} | ||
|
||
fn data_width(&self) -> WidthInt { | ||
self.data_width | ||
} | ||
|
||
fn words(&self) -> &[Word] { | ||
&self.words | ||
} | ||
} | ||
|
||
impl ArrayMutOps for ArrayValue { | ||
fn words_mut(&mut self) -> &mut [Word] { | ||
&mut self.words | ||
} | ||
} |
Oops, something went wrong.