use crate::bitmap::store::array_store::visitor::BinaryOperationVisitor;
use core::cmp::Ordering::*;
#[inline]
pub fn or(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) {
let mut i = 0;
let mut j = 0;
while i < lhs.len() && j < rhs.len() {
let a = unsafe { lhs.get_unchecked(i) };
let b = unsafe { rhs.get_unchecked(j) };
match a.cmp(b) {
Less => {
visitor.visit_scalar(*a);
i += 1;
}
Greater => {
visitor.visit_scalar(*b);
j += 1;
}
Equal => {
visitor.visit_scalar(*a);
i += 1;
j += 1;
}
}
}
visitor.visit_slice(&lhs[i..]);
visitor.visit_slice(&rhs[j..]);
}
#[inline]
pub fn and(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) {
let mut i = 0;
let mut j = 0;
while i < lhs.len() && j < rhs.len() {
let a = unsafe { lhs.get_unchecked(i) };
let b = unsafe { rhs.get_unchecked(j) };
match a.cmp(b) {
Less => i += 1,
Greater => j += 1,
Equal => {
visitor.visit_scalar(*a);
i += 1;
j += 1;
}
}
}
}
#[inline(never)]
pub fn and_skewed(small: &[u16], large: &[u16], visitor: &mut impl BinaryOperationVisitor) {
let mut large = large;
let (chunks, remainder) = small.as_chunks::<4>();
for &targets in chunks {
if large.is_empty() {
return;
}
let indexes = lower_bounds(large, targets);
for (target, index) in targets.into_iter().zip(indexes) {
if large.get(index) == Some(&target) {
visitor.visit_scalar(target);
}
}
large = &large[indexes[3]..];
}
for &a in remainder {
match large.binary_search(&a) {
Ok(i) => {
visitor.visit_scalar(a);
large = &large[i + 1..];
}
Err(i) => large = &large[i..],
}
}
}
#[inline]
fn lower_bounds(array: &[u16], targets: [u16; 4]) -> [usize; 4] {
let mut bases = [0; 4];
let mut n = array.len();
while n > 1 {
let half = n / 2;
for (base, target) in bases.iter_mut().zip(targets) {
if array[*base + half] < target {
*base += half;
}
}
n -= half;
}
core::array::from_fn(|i| bases[i] + (array[bases[i]] < targets[i]) as usize)
}
#[inline]
pub fn sub(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) {
let mut i = 0;
let mut j = 0;
while i < lhs.len() && j < rhs.len() {
let a = unsafe { lhs.get_unchecked(i) };
let b = unsafe { rhs.get_unchecked(j) };
match a.cmp(b) {
Less => {
visitor.visit_scalar(*a);
i += 1;
}
Greater => j += 1,
Equal => {
i += 1;
j += 1;
}
}
}
visitor.visit_slice(&lhs[i..]);
}
#[inline]
pub fn xor(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) {
let mut i = 0;
let mut j = 0;
while i < lhs.len() && j < rhs.len() {
let a = unsafe { lhs.get_unchecked(i) };
let b = unsafe { rhs.get_unchecked(j) };
match a.cmp(b) {
Less => {
visitor.visit_scalar(*a);
i += 1;
}
Greater => {
visitor.visit_scalar(*b);
j += 1;
}
Equal => {
i += 1;
j += 1;
}
}
}
visitor.visit_slice(&lhs[i..]);
visitor.visit_slice(&rhs[j..]);
}