use crate::{Arc, BTreeSet, Data, HashMap, Rc, RefCell};
#[cfg(any(debug_assertions, not(feature = "unsafe-optim")))]
macro_rules! unsafe_assert {
( $cond: expr ) => {
debug_assert!($cond)
};
}
#[cfg(all(not(debug_assertions), feature = "unsafe-optim"))]
macro_rules! unsafe_assert {
( $cond: expr ) => {
if !$cond {
unsafe { std::hint::unreachable_unchecked() }
}
};
}
#[cfg(any(debug_assertions, not(feature = "unsafe-optim")))]
macro_rules! unsafe_panic {
() => {
panic!()
};
}
#[cfg(all(not(debug_assertions), feature = "unsafe-optim"))]
macro_rules! unsafe_panic {
() => {{
unsafe { std::hint::unreachable_unchecked() }
}};
}
pub fn new<T>(x: T) -> std::rc::Rc<std::cell::RefCell<T>> {
Rc::new(RefCell::new(x))
}
pub fn nd() -> Data {
Arc::new(Vec::new())
}
pub fn newmap<K, T>() -> RefCell<HashMap<K, T>> {
RefCell::new(HashMap::default())
}
pub fn getu64(data: &[u8], off: usize) -> u64 {
unsafe_assert!(off + 8 <= data.len());
let data = &data[off..off + 8];
u64::from_le_bytes(data.try_into().unwrap())
}
pub fn setu64(data: &mut [u8], val: u64) {
unsafe_assert!(data.len() >= 8);
data[0..8].copy_from_slice(&val.to_le_bytes());
}
pub fn getf64(data: &[u8], off: usize) -> f64 {
let data = &data[off..off + 8];
f64::from_le_bytes(data.try_into().unwrap())
}
pub fn getf32(data: &[u8], off: usize) -> f32 {
let data = &data[off..off + 4];
f32::from_le_bytes(data.try_into().unwrap())
}
pub fn get(data: &[u8], off: usize, n: usize) -> u64 {
let mut buf = [0_u8; 8];
unsafe_assert!(off + n <= data.len());
buf[0..n].copy_from_slice(&data[off..off + n]);
u64::from_le_bytes(buf)
}
pub fn iget(data: &[u8], off: usize, n: usize) -> i64 {
let mut x: u64 = get(data, off, n);
if n < 8 {
let sign_bit = 1 << (n * 8 - 1);
if (sign_bit & x) != 0 {
x += u64::MAX << (n * 8);
}
}
x as i64
}
pub fn iset(data: &mut [u8], off: usize, val: i64, n: usize) {
if n < 8 {
let chk = val + (1 << ((n * 8) - 1));
if chk < 0 || chk >= (1 << (n * 8)) {
panic!("overflow storing value {} in {} bytes", val, n);
}
}
let bytes = val.to_le_bytes();
data[off..off + n].copy_from_slice(&bytes[0..n]);
}
pub fn set(data: &mut [u8], off: usize, val: u64, n: usize) {
let bytes = val.to_le_bytes();
data[off..off + n].copy_from_slice(&bytes[0..n]);
}
macro_rules! bitmask {
( $off: expr, $len: expr ) => {
((1 << $len) - 1) << $off
};
}
macro_rules! getbits {
( $val: expr, $off: expr, $len: expr ) => {
($val & bitmask!($off, $len)) >> $off
};
}
macro_rules! setbits {
( $var: expr, $off: expr, $len: expr, $val: expr ) => {
$var = ($var & !bitmask!($off, $len)) | (($val << $off) & bitmask!($off, $len))
};
}
pub fn hex(c: u8) -> u8 {
match c {
b'0'..=b'9' => c - b'0',
b'A'..=b'F' => c + 10 - b'A',
b'a'..=b'f' => c + 10 - b'a',
_ => {
panic!()
}
}
}
pub fn parse_hex(s: &[u8]) -> Vec<u8> {
let n = s.len() / 2;
let mut result = Vec::<u8>::with_capacity(n);
for i in 0..n {
result.push(hex(s[i * 2]) * 16 + hex(s[i * 2 + 1]));
}
result
}
pub fn to_hex(bytes: &[u8]) -> String {
const HEX: &[u8; 16] = b"0123456789abcdef";
let mut s = vec![b'0', b'x'];
for b in bytes {
let b = *b as usize;
s.push(HEX[b / 16]);
s.push(HEX[b % 16]);
}
String::from_utf8(s).unwrap()
}
#[derive(Default)]
pub struct SmallSet {
bitset: u64,
overflow: BTreeSet<usize>,
}
impl SmallSet {
pub fn insert(&mut self, x: usize) {
if x < 64 {
self.bitset |= 1 << x;
} else {
self.overflow.insert(x);
}
}
pub fn contains(&self, x: usize) -> bool {
if x < 64 {
self.bitset & (1 << x) != 0
} else {
self.overflow.contains(&x)
}
}
pub fn remove(&mut self, x: usize) -> bool {
if x < 64 {
let bit: u64 = 1 << x;
let result = self.bitset & bit != 0;
self.bitset &= u64::MAX - bit;
result
} else {
self.overflow.remove(&x)
}
}
}
pub fn diff<F>(a: &[u8], b: &[u8], min_eq: usize, mut d: F)
where
F: FnMut(usize, usize),
{
let mut check = 0;
let mut i = 0;
let n = a.len();
while i < n && a[i] == b[i] {
i += 1;
}
while i < n {
let start = i;
let mut end;
loop {
loop {
i += 1;
if i == n || a[i] == b[i] {
break;
}
}
end = i;
while i < n && a[i] == b[i] {
i += 1;
}
if i - end >= min_eq || i == n {
break;
}
}
assert_eq!(a[check..start], b[check..start]);
check = end;
d(start, end - start);
}
assert_eq!(a[check..n], b[check..n]);
}
#[test]
fn difftest() {
use rand::Rng;
let mut rng = rand::thread_rng();
for _ in 0..1000 {
let mut v = Vec::new();
for _i in 0..100 {
v.push(0);
}
let mut v2 = v.clone();
for _ in 0..rng.gen::<usize>() % 50 {
v2[rng.gen::<usize>() % 100] = 1;
}
let mut x = 0;
diff(&v, &v2, 2, |off, len| {
assert_eq!(v[x..off], v2[x..off]);
x = off + len;
});
assert_eq!(v[x..], v2[x..]);
}
}