Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

Commit

Permalink
Improved perf of binary unary op.
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgecarleitao committed Sep 2, 2021
1 parent 3b987e3 commit 0151e4b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 12 deletions.
35 changes: 24 additions & 11 deletions src/bitmap/bitmap_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use std::ops::{BitAnd, BitOr, Not};

use crate::buffer::MutableBuffer;

use super::Bitmap;
use super::{
utils::{BitChunkIterExact, BitChunksExact},
Bitmap,
};

/// Apply a bitwise operation `op` to four inputs and return the result as a [`Bitmap`].
pub fn quaternary<F>(a1: &Bitmap, a2: &Bitmap, a3: &Bitmap, a4: &Bitmap, op: F) -> Bitmap
Expand Down Expand Up @@ -100,23 +103,33 @@ where
Bitmap::from_u8_buffer(buffer, length)
}

/// Apply a bitwise operation `op` to one input and return the result as a [`Bitmap`].
pub fn unary<F>(lhs: &Bitmap, op: F) -> Bitmap
fn unary_impl<F, I>(iter: I, op: F, length: usize) -> Bitmap
where
I: BitChunkIterExact<u64>,
F: Fn(u64) -> u64,
{
let mut lhs_chunks = lhs.chunks();
let rem = op(iter.remainder());

let chunks = lhs_chunks.by_ref().map(|left| op(left));
let mut buffer = unsafe { MutableBuffer::from_chunk_iter_unchecked(chunks) };
let iterator = iter.map(|left| op(left)).chain(std::iter::once(rem));

let remainder_bytes = lhs_chunks.remainder_len().saturating_add(7) / 8;
let rem = op(lhs_chunks.remainder());
let buffer = MutableBuffer::from_trusted_len_iter(iterator);

let rem = &rem.to_ne_bytes()[..remainder_bytes];
buffer.extend_from_slice(rem);
Bitmap::from_u8_buffer(buffer.into(), length)
}

Bitmap::from_u8_buffer(buffer, lhs.len())
/// Apply a bitwise operation `op` to one input and return the result as a [`Bitmap`].
pub fn unary<F>(lhs: &Bitmap, op: F) -> Bitmap
where
F: Fn(u64) -> u64,
{
let (slice, offset, length) = lhs.as_slice();
if offset == 0 {
let iter = BitChunksExact::<u64>::new(slice, length);
unary_impl(iter, op, lhs.len())
} else {
let iter = lhs.chunks::<u64>();
unary_impl(iter, op, lhs.len())
}
}

fn and(lhs: &Bitmap, rhs: &Bitmap) -> Bitmap {
Expand Down
4 changes: 4 additions & 0 deletions src/bitmap/utils/chunk_iterator/chunks_exact.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::{convert::TryInto, slice::ChunksExact};

use crate::trusted_len::TrustedLen;

use super::{BitChunk, BitChunkIterExact};

/// An iterator over a slice of bytes in [`BitChunk`]s.
Expand Down Expand Up @@ -84,6 +86,8 @@ impl<T: BitChunk> Iterator for BitChunksExact<'_, T> {
}
}

unsafe impl<T: BitChunk> TrustedLen for BitChunksExact<'_, T> {}

impl<T: BitChunk> BitChunkIterExact<T> for BitChunksExact<'_, T> {
#[inline]
fn remainder(&self) -> T {
Expand Down
2 changes: 1 addition & 1 deletion src/bitmap/utils/chunk_iterator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{trusted_len::TrustedLen, types::BitChunkIter};
pub(crate) use merge::merge_reversed;

/// Trait representing an exact iterator over bytes in [`BitChunk`].
pub trait BitChunkIterExact<B: BitChunk>: Iterator<Item = B> {
pub trait BitChunkIterExact<B: BitChunk>: TrustedLen<Item = B> {
/// The remainder of the iterator.
fn remainder(&self) -> B;
}
Expand Down

0 comments on commit 0151e4b

Please sign in to comment.