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

Speedup/simplify bitwise operations (avoid extra allocation) #586

Merged
merged 5 commits into from
Nov 8, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benches/bitwise.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::ops::{BitOr, BitXor, Not};
use std::ops::{BitAnd, BitOr, BitXor, Not};

use criterion::{criterion_group, criterion_main, Criterion};
use num_traits::NumCast;
Expand Down
54 changes: 27 additions & 27 deletions src/bitmap/bitmap_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,23 @@ where
let mut a3_chunks = a3.chunks();
let mut a4_chunks = a4.chunks();

let rem_a1 = a1_chunks.remainder();
let rem_a2 = a2_chunks.remainder();
let rem_a3 = a3_chunks.remainder();
let rem_a4 = a4_chunks.remainder();

let chunks = a1_chunks
.by_ref()
.zip(a2_chunks.by_ref())
.zip(a3_chunks.by_ref())
.zip(a4_chunks.by_ref())
.map(|(((a1, a2), a3), a4)| op(a1, a2, a3, a4));
// Soundness: `BitChunks` is a trusted len iterator
let mut buffer = unsafe { MutableBuffer::from_chunk_iter_unchecked(chunks) };

let remainder_bytes = a1_chunks.remainder_len().saturating_add(7) / 8;
let rem = op(
a1_chunks.remainder(),
a2_chunks.remainder(),
a3_chunks.remainder(),
a4_chunks.remainder(),
);
let rem = &rem.to_ne_bytes()[..remainder_bytes];
buffer.extend_from_slice(rem);
let buffer = unsafe {
MutableBuffer::from_chunk_iter_unchecked(
chunks.chain(std::iter::once(op(rem_a1, rem_a2, rem_a3, rem_a4))),
)
};

let length = a1.len();

Expand All @@ -55,22 +54,21 @@ where
let mut a2_chunks = a2.chunks();
let mut a3_chunks = a3.chunks();

let rem_a1 = a1_chunks.remainder();
let rem_a2 = a2_chunks.remainder();
let rem_a3 = a3_chunks.remainder();

let chunks = a1_chunks
.by_ref()
.zip(a2_chunks.by_ref())
.zip(a3_chunks.by_ref())
.map(|((a1, a2), a3)| op(a1, a2, a3));
// Soundness: `BitChunks` is a trusted len iterator
let mut buffer = unsafe { MutableBuffer::from_chunk_iter_unchecked(chunks) };

let remainder_bytes = a1_chunks.remainder_len().saturating_add(7) / 8;
let rem = op(
a1_chunks.remainder(),
a2_chunks.remainder(),
a3_chunks.remainder(),
);
let rem = &rem.to_ne_bytes()[..remainder_bytes];
buffer.extend_from_slice(rem);
let buffer = unsafe {
MutableBuffer::from_chunk_iter_unchecked(
chunks.chain(std::iter::once(op(rem_a1, rem_a2, rem_a3))),
)
};

let length = a1.len();

Expand All @@ -85,18 +83,20 @@ where
assert_eq!(lhs.len(), rhs.len());
let mut lhs_chunks = lhs.chunks();
let mut rhs_chunks = rhs.chunks();
let rem_lhs = lhs_chunks.remainder();
let rem_rhs = rhs_chunks.remainder();

let chunks = lhs_chunks
.by_ref()
.zip(rhs_chunks.by_ref())
.map(|(left, right)| op(left, right));
// Soundness: `BitChunks` is a trusted len iterator
let mut buffer = unsafe { MutableBuffer::from_chunk_iter_unchecked(chunks) };

let remainder_bytes = lhs_chunks.remainder_len().saturating_add(7) / 8;
let rem = op(lhs_chunks.remainder(), rhs_chunks.remainder());
let rem = &rem.to_ne_bytes()[..remainder_bytes];
buffer.extend_from_slice(rem);
// Soundness: `BitChunks` is a trusted len iterator
let buffer = unsafe {
MutableBuffer::from_chunk_iter_unchecked(
chunks.chain(std::iter::once(op(rem_lhs, rem_rhs))),
)
};
Dandandan marked this conversation as resolved.
Show resolved Hide resolved

let length = lhs.len();

Expand Down