#[cfg(test)]
use proptest::prelude::*;
use std;
use std::marker::PhantomData;
pub trait Fits64: Copy {
unsafe fn from_u64(x: u64) -> Self;
fn to_u64(self) -> u64;
}
pub fn test_fits64<T: Fits64 + Eq + std::fmt::Debug>(x: T) {
let x64 = x.to_u64();
let y = unsafe { T::from_u64(x64) };
let y64 = y.to_u64();
assert_eq!(x, y);
assert_eq!(x64, y64);
}
macro_rules! define_fits {
($ty: ty, $test_name: ident) => {
impl Fits64 for $ty {
#[inline]
unsafe fn from_u64(x: u64) -> Self {
x as $ty
}
#[inline]
fn to_u64(self) -> u64 {
self as u64
}
}
#[cfg(test)]
proptest! {
#[test]
fn $test_name(x: $ty) {
test_fits64(x);
}
}
};
}
define_fits!(u64, fits_u64);
define_fits!(u32, fits_u32);
define_fits!(u16, fits_u16);
define_fits!(u8, fits_u8);
define_fits!(usize, fits_usize);
impl Fits64 for char {
#[inline]
unsafe fn from_u64(x: u64) -> Self {
std::char::from_u32(x as u32).unwrap()
}
#[inline]
fn to_u64(self) -> u64 {
self as u64
}
}
const USE_BRANCHES: bool = false;
macro_rules! define_ifits {
($ty: ty, $uty: ty, $test_name: ident) => {
impl Fits64 for $ty {
#[inline]
unsafe fn from_u64(x: u64) -> Self {
let pos_val = (x >> 1) as $ty;
let neg_val = !(x >> 1) as $ty;
if USE_BRANCHES {
if x & 1 == 1 {
neg_val
} else {
pos_val
}
} else {
let pos_mask = (x & 1) as $ty - 1;
(pos_val & pos_mask) | (neg_val & !pos_mask)
}
}
#[inline]
fn to_u64(self) -> u64 {
let neg_rep = ((!self as u64) << 1) | 1;
let pos_rep = (self as u64) << 1;
if USE_BRANCHES {
if self < 0 {
neg_rep
} else {
pos_rep
}
} else {
let neg_mask = ((self >= 0) as i64 - 1) as u64;
(neg_rep & neg_mask) | (pos_rep & !neg_mask)
}
}
}
#[cfg(test)]
proptest! {
#[test]
fn $test_name(x: $ty) {
println!("\ntesting {}", x);
test_fits64(x);
}
}
};
}
define_ifits!(i8, u8, fits_i8);
define_ifits!(i16, u16, fits_i16);
define_ifits!(i32, u32, fits_i32);
define_ifits!(i64, u64, fits_i64);
define_ifits!(isize, usize, fits_isize);
#[derive(Debug, Clone)]
pub struct Set64<T: Fits64>(crate::setu64::SetU64, PhantomData<T>);
impl<T: Fits64> Default for Set64<T> {
fn default() -> Self {
Set64(crate::setu64::SetU64::new(), PhantomData)
}
}
impl<T: Fits64> Set64<T> {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(_cap: usize) -> Self {
Self::new()
}
pub fn insert(&mut self, elem: T) -> bool {
self.0.insert(elem.to_u64())
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn contains<R: std::borrow::Borrow<T>>(&self, value: R) -> bool {
let x = value.borrow().clone().to_u64();
self.0.contains(x)
}
pub fn remove(&mut self, value: &T) -> bool {
let x = value.clone().to_u64();
self.0.remove(x)
}
pub fn iter<'a>(&'a self) -> impl Iterator<Item = T> + 'a {
self.0.iter().map(|x| unsafe { T::from_u64(x) })
}
pub fn drain<'a>(&'a mut self) -> impl Iterator<Item = T> + 'a {
self.0.drain().map(|x| unsafe { T::from_u64(x) })
}
}
impl<T: Fits64> PartialEq for Set64<T> {
fn eq(&self, other: &Set64<T>) -> bool {
if self.len() != other.len() {
return false;
}
for k in other.0.iter() {
if !self.0.contains(k) {
return false;
}
}
true
}
}
impl<T: Fits64> Eq for Set64<T> {}
impl<T: Fits64> std::hash::Hash for Set64<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let mut membs: Vec<u64> = self.iter().map(|i| i.to_u64()).collect();
membs.sort();
for memb in membs {
memb.hash(state);
}
}
}
impl<T: Fits64> std::iter::FromIterator<T> for Set64<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let (sz, _) = iter.size_hint();
let mut c = Set64::with_capacity(sz);
for i in iter {
c.insert(i);
}
c
}
}
#[derive(Clone)]
pub struct IntoIter<T: Fits64>(crate::setu64::IntoIter, PhantomData<T>);
impl<T: Fits64> Iterator for IntoIter<T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
self.0.next().map(|x| unsafe { T::from_u64(x) })
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
#[inline]
fn count(self) -> usize {
self.0.count()
}
#[inline]
fn last(self) -> Option<T> {
self.0.last().map(|x| unsafe { T::from_u64(x) })
}
}
impl<T: Fits64> IntoIterator for Set64<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
IntoIter(self.0.into_iter(), PhantomData)
}
}
impl<'a, 'b, T: Fits64> std::ops::Sub<&'b Set64<T>> for &'a Set64<T> {
type Output = Set64<T>;
fn sub(self, rhs: &Set64<T>) -> Set64<T> {
let mut s = Set64::with_capacity(self.len());
for v in self.iter() {
if !rhs.contains(&v) {
s.insert(v);
}
}
s
}
}
impl<T: Fits64> Extend<T> for Set64<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
let iter = iter.into_iter();
for i in iter {
self.insert(i);
}
}
}
#[cfg(feature = "serde")]
mod serde {
use crate::{Fits64, Set64};
use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
use serde::ser::{Serialize, SerializeSeq, Serializer};
use std::marker::PhantomData;
impl<T: Fits64 + Serialize> Serialize for Set64<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.len()))?;
for e in self.iter() {
seq.serialize_element(&e)?;
}
seq.end()
}
}
struct SetVisitor<T> {
phantom: PhantomData<T>,
}
impl<T> SetVisitor<T> {
fn new() -> Self {
SetVisitor {
phantom: PhantomData,
}
}
}
impl<'de, T: Fits64 + Deserialize<'de>> Visitor<'de> for SetVisitor<T> {
type Value = Set64<T>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a set of usize")
}
fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: SeqAccess<'de>,
{
let mut set = Set64::new();
while let Some(elem) = access.next_element()? {
set.insert(elem);
}
Ok(set)
}
}
impl<'de, T: Fits64 + Deserialize<'de>> Deserialize<'de> for Set64<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(SetVisitor::new())
}
}
#[test]
fn serialize_deserialize() {
use std::iter::FromIterator;
let set = Set64::<usize>::from_iter([0]);
let s = serde_json::to_string(&set).unwrap();
assert_eq!(set, serde_json::from_str(&s).unwrap());
let set = Set64::<usize>::from_iter([]);
let s = serde_json::to_string(&set).unwrap();
assert_eq!(set, serde_json::from_str(&s).unwrap());
let set = Set64::<usize>::from_iter([usize::MAX, usize::MAX - 100]);
let s = serde_json::to_string(&set).unwrap();
assert_eq!(set, serde_json::from_str(&s).unwrap());
let set = Set64::<usize>::from_iter(0..10000);
let s = serde_json::to_string(&set).unwrap();
assert_eq!(set, serde_json::from_str(&s).unwrap());
}
}
impl<'a, 'b, T: Fits64> std::ops::BitOr<&'b Set64<T>> for &'a Set64<T> {
type Output = Set64<T>;
fn bitor(self, rhs: &Set64<T>) -> Set64<T> {
let mut s: Set64<T> = Set64::with_capacity(self.len() + rhs.len());
for x in self.iter() {
s.insert(x);
}
for x in rhs.iter() {
s.insert(x);
}
s
}
}
#[cfg(test)]
impl<T: Fits64 + Eq + Ord + std::fmt::Debug + std::fmt::Display> crate::copyset::CopySet
for Set64<T>
{
type Item = T;
type Iter = IntoIter<T>;
fn ins(&mut self, e: Self::Item) -> bool {
self.insert(e)
}
fn rem(&mut self, e: Self::Item) -> bool {
self.remove(&e)
}
fn con(&self, e: Self::Item) -> bool {
self.contains(&e)
}
fn vec(&self) -> Vec<Self::Item> {
self.iter().collect()
}
fn ln(&self) -> usize {
self.len()
}
fn it(self) -> Self::Iter {
self.into_iter()
}
}
#[cfg(test)]
proptest! {
#[test]
fn copycheck_random_sets(slice in prop::collection::vec(1u64..5, 1usize..10)) {
crate::copyset::check_set::<Set64<u64>>(&slice);
}
#[test]
fn copycheck_medium_sets(slice in prop::collection::vec(1u64..255, 1usize..100)) {
crate::copyset::check_set::<Set64<u64>>(&slice);
}
#[test]
fn copycheck_big_sets(slice: Vec<u64>) {
crate::copyset::check_set::<Set64<u64>>(&slice);
}
#[test]
fn copycheck_u8_sets(slice: Vec<u8>) {
crate::copyset::check_set::<Set64<u8>>(&slice);
}
}