use super::vector::Vector;
use crate::base::WORD_SIZE;
#[cfg(target_pointer_width = "64")]
type Unit = u64;
#[cfg(target_pointer_width = "32")]
type Unit = u32;
#[derive(Default)]
pub struct FlatVector {
units: Vector<Unit>,
value_size: usize,
mask: u32,
size: usize,
}
impl FlatVector {
#[inline]
pub fn new() -> Self {
FlatVector {
units: Vector::new(),
value_size: 0,
mask: 0,
size: 0,
}
}
pub fn build(&mut self, values: &Vector<u32>) {
let mut temp = FlatVector::new();
temp.build_internal(values);
self.swap(&mut temp);
}
#[inline]
pub fn get(&self, i: usize) -> u32 {
debug_assert!(i < self.size, "Index out of bounds");
let pos = i * self.value_size;
let unit_id = pos / WORD_SIZE;
let unit_offset = pos % WORD_SIZE;
let lo = self.units[unit_id] >> unit_offset;
let hi = if unit_offset != 0 && unit_id + 1 < self.units.size() {
self.units[unit_id + 1] << (WORD_SIZE - unit_offset)
} else {
0
};
((lo | hi) as u32) & self.mask
}
#[inline]
pub fn value_size(&self) -> usize {
self.value_size
}
#[inline]
pub fn mask(&self) -> u32 {
self.mask
}
#[inline]
pub fn empty(&self) -> bool {
self.size == 0
}
#[inline]
pub fn size(&self) -> usize {
self.size
}
#[inline]
pub fn total_size(&self) -> usize {
self.units.total_size()
}
#[inline]
pub fn io_size(&self) -> usize {
self.units.io_size() + std::mem::size_of::<u32>() * 2 + std::mem::size_of::<u64>()
}
#[inline]
pub fn clear(&mut self) {
*self = FlatVector::new();
}
pub fn swap(&mut self, other: &mut FlatVector) {
self.units.swap(&mut other.units);
std::mem::swap(&mut self.value_size, &mut other.value_size);
std::mem::swap(&mut self.mask, &mut other.mask);
std::mem::swap(&mut self.size, &mut other.size);
}
pub fn map(&mut self, mapper: &mut crate::grimoire::io::Mapper) -> std::io::Result<()> {
self.units.map(mapper)?;
let temp_value_size: u32 = mapper.map_value()?;
if temp_value_size > 32 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"value_size exceeds 32",
));
}
self.value_size = temp_value_size as usize;
let temp_mask: u32 = mapper.map_value()?;
self.mask = temp_mask;
let temp_size: u64 = mapper.map_value()?;
self.size = temp_size as usize;
Ok(())
}
pub fn read(&mut self, reader: &mut crate::grimoire::io::Reader) -> std::io::Result<()> {
self.units.read(reader)?;
let temp_value_size: u32 = reader.read()?;
if temp_value_size > 32 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"value_size exceeds 32",
));
}
self.value_size = temp_value_size as usize;
let temp_mask: u32 = reader.read()?;
self.mask = temp_mask;
let temp_size: u64 = reader.read()?;
self.size = temp_size as usize;
Ok(())
}
pub fn write(&self, writer: &mut crate::grimoire::io::Writer) -> std::io::Result<()> {
self.units.write(writer)?;
writer.write(&(self.value_size as u32))?;
writer.write(&self.mask)?;
writer.write(&(self.size as u64))?;
Ok(())
}
fn build_internal(&mut self, values: &Vector<u32>) {
let mut max_value = 0u32;
for i in 0..values.size() {
if values[i] > max_value {
max_value = values[i];
}
}
let mut value_size = 0usize;
let mut temp_max = max_value;
while temp_max != 0 {
value_size += 1;
temp_max >>= 1;
}
let num_units = if values.empty() {
0
} else if value_size == 0 {
64 / WORD_SIZE
} else {
let bits_needed = value_size as u64 * values.size() as u64;
let mut num_units =
((bits_needed + (WORD_SIZE as u64 - 1)) / WORD_SIZE as u64) as usize;
let alignment = 64 / WORD_SIZE;
num_units += num_units % alignment;
num_units
};
self.units.resize(num_units, 0);
if num_units > 0 {
self.units[num_units - 1] = 0;
}
self.value_size = value_size;
self.mask = if value_size != 0 {
u32::MAX >> (32 - value_size)
} else {
0
};
self.size = values.size();
for i in 0..values.size() {
self.set(i, values[i]);
}
}
fn set(&mut self, i: usize, value: u32) {
assert!(i < self.size, "Index out of bounds");
assert!(value <= self.mask, "Value exceeds maximum");
let pos = i * self.value_size;
let unit_id = pos / WORD_SIZE;
let unit_offset = pos % WORD_SIZE;
self.units[unit_id] &= !(Unit::from(self.mask) << unit_offset);
self.units[unit_id] |= Unit::from(value & self.mask) << unit_offset;
if (unit_offset + self.value_size) > WORD_SIZE {
let high_shift = WORD_SIZE - unit_offset;
self.units[unit_id + 1] &= !(Unit::from(self.mask) >> high_shift);
self.units[unit_id + 1] |= Unit::from(value & self.mask) >> high_shift;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_flat_vector_new() {
let fv = FlatVector::new();
assert_eq!(fv.size(), 0);
assert!(fv.empty());
assert_eq!(fv.value_size(), 0);
assert_eq!(fv.mask(), 0);
}
#[test]
fn test_flat_vector_build_small() {
let mut values = Vector::new();
values.push_back(0);
values.push_back(1);
values.push_back(2);
values.push_back(3);
let mut fv = FlatVector::new();
fv.build(&values);
assert_eq!(fv.size(), 4);
assert_eq!(fv.value_size(), 2); assert_eq!(fv.mask(), 0b11);
assert_eq!(fv.get(0), 0);
assert_eq!(fv.get(1), 1);
assert_eq!(fv.get(2), 2);
assert_eq!(fv.get(3), 3);
}
#[test]
fn test_flat_vector_build_powers_of_two() {
let mut values = Vector::new();
values.push_back(1);
values.push_back(2);
values.push_back(4);
values.push_back(8);
values.push_back(16);
let mut fv = FlatVector::new();
fv.build(&values);
assert_eq!(fv.size(), 5);
assert_eq!(fv.value_size(), 5);
assert_eq!(fv.get(0), 1);
assert_eq!(fv.get(1), 2);
assert_eq!(fv.get(2), 4);
assert_eq!(fv.get(3), 8);
assert_eq!(fv.get(4), 16);
}
#[test]
fn test_flat_vector_all_zeros() {
let mut values = Vector::new();
for _ in 0..10 {
values.push_back(0);
}
let mut fv = FlatVector::new();
fv.build(&values);
assert_eq!(fv.size(), 10);
assert_eq!(fv.value_size(), 0);
for i in 0..10 {
assert_eq!(fv.get(i), 0);
}
}
#[test]
fn test_flat_vector_large_values() {
let mut values = Vector::new();
values.push_back(255);
values.push_back(256);
values.push_back(1000);
values.push_back(65535);
let mut fv = FlatVector::new();
fv.build(&values);
assert_eq!(fv.size(), 4);
assert_eq!(fv.value_size(), 16);
assert_eq!(fv.get(0), 255);
assert_eq!(fv.get(1), 256);
assert_eq!(fv.get(2), 1000);
assert_eq!(fv.get(3), 65535);
}
#[test]
fn test_flat_vector_many_values() {
let mut values = Vector::new();
for i in 0..100 {
values.push_back(i % 16); }
let mut fv = FlatVector::new();
fv.build(&values);
assert_eq!(fv.size(), 100);
assert_eq!(fv.value_size(), 4);
for i in 0..100 {
assert_eq!(fv.get(i), (i % 16) as u32);
}
}
#[test]
fn test_flat_vector_clear() {
let mut values = Vector::new();
values.push_back(1);
values.push_back(2);
let mut fv = FlatVector::new();
fv.build(&values);
assert_eq!(fv.size(), 2);
fv.clear();
assert_eq!(fv.size(), 0);
assert!(fv.empty());
}
#[test]
fn test_flat_vector_swap() {
let mut values1 = Vector::new();
values1.push_back(1);
values1.push_back(2);
let mut values2 = Vector::new();
values2.push_back(10);
values2.push_back(20);
values2.push_back(30);
let mut fv1 = FlatVector::new();
let mut fv2 = FlatVector::new();
fv1.build(&values1);
fv2.build(&values2);
fv1.swap(&mut fv2);
assert_eq!(fv1.size(), 3);
assert_eq!(fv2.size(), 2);
assert_eq!(fv1.get(0), 10);
assert_eq!(fv2.get(0), 1);
}
#[test]
#[should_panic(expected = "Index out of bounds")]
fn test_flat_vector_out_of_bounds() {
let mut values = Vector::new();
values.push_back(1);
let mut fv = FlatVector::new();
fv.build(&values);
fv.get(1); }
#[test]
fn test_flat_vector_empty() {
let values = Vector::new();
let mut fv = FlatVector::new();
fv.build(&values);
assert_eq!(fv.size(), 0);
assert!(fv.empty());
}
#[test]
fn test_flat_vector_write_read() {
use crate::grimoire::io::{Reader, Writer};
let mut values = Vector::new();
for i in 0..100u32 {
values.push_back((i * 7) % 256); }
let mut fv = FlatVector::new();
fv.build(&values);
let mut writer = Writer::from_vec(Vec::new());
fv.write(&mut writer).unwrap();
let data = writer.into_inner().unwrap();
let mut reader = Reader::from_bytes(&data);
let mut fv2 = FlatVector::new();
fv2.read(&mut reader).unwrap();
assert_eq!(fv2.size(), 100);
for i in 0..100usize {
assert_eq!(fv2.get(i), ((i as u32 * 7) % 256));
}
}
#[test]
fn test_flat_vector_write_read_empty() {
use crate::grimoire::io::{Reader, Writer};
let fv = FlatVector::new();
let mut writer = Writer::from_vec(Vec::new());
fv.write(&mut writer).unwrap();
let data = writer.into_inner().unwrap();
let mut reader = Reader::from_bytes(&data);
let mut fv2 = FlatVector::new();
fv2.read(&mut reader).unwrap();
assert_eq!(fv2.size(), 0);
assert!(fv2.empty());
}
#[test]
fn test_flat_vector_read_invalid_value_size() {
use crate::grimoire::io::{Reader, Writer};
let mut writer = Writer::from_vec(Vec::new());
let empty_vec: crate::grimoire::vector::vector::Vector<u64> =
crate::grimoire::vector::vector::Vector::new();
empty_vec.write(&mut writer).unwrap();
writer.write(&40u32).unwrap();
writer.write(&0u32).unwrap();
writer.write(&0u64).unwrap();
let data = writer.into_inner().unwrap();
let mut reader = Reader::from_bytes(&data);
let mut fv = FlatVector::new();
let result = fv.read(&mut reader);
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
}
}