Skip to content

Commit

Permalink
Simplify rca1 and benchmark it
Browse files Browse the repository at this point in the history
  • Loading branch information
pczarn authored and myrrlyn committed Oct 29, 2019
1 parent 778ba09 commit e1ac2c9
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 23 deletions.
45 changes: 45 additions & 0 deletions benches/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

extern crate test;

use core::ops::AddAssign;

use bitvec::prelude::*;
use test::Bencher;

Expand Down Expand Up @@ -138,3 +140,46 @@ fn at(b: &mut Bencher) {

}
}

#[bench]
fn add_assign(b: &mut Bencher) {
let mut src = [0u8; 16];
let bsb08a = src.as_mut_bitslice::<BigEndian>();
let bsb08b = [0u8; 16].as_bitslice::<BigEndian>();
let mut src = [0u8; 16];
let bsl08a = src.as_mut_bitslice::<LittleEndian>();
let bsl08b = [0u8; 16].as_bitslice::<LittleEndian>();
b.iter(|| bsb08a.add_assign(bsb08b));
b.iter(|| bsl08a.add_assign(bsl08b));

let mut src = [0u16; 8];
let bsb16a = src.as_mut_bitslice::<BigEndian>();
let bsb16b = [0u16; 8].as_bitslice::<BigEndian>();
let mut src = [0u16; 8];
let bsl16a = src.as_mut_bitslice::<LittleEndian>();
let bsl16b = [0u16; 8].as_bitslice::<LittleEndian>();
b.iter(|| bsb16a.add_assign(bsb16b));
b.iter(|| bsl16a.add_assign(bsl16b));

let mut src = [0u32; 4];
let bsb32a = src.as_mut_bitslice::<BigEndian>();
let bsb32b = [0u32; 4].as_bitslice::<BigEndian>();
let mut src = [0u32; 4];
let bsl32a = src.as_mut_bitslice::<LittleEndian>();
let bsl32b = [0u32; 4].as_bitslice::<LittleEndian>();
b.iter(|| bsb32a.add_assign(bsb32b));
b.iter(|| bsl32a.add_assign(bsl32b));

#[cfg(target_pointer_width = "64")] {

let mut src = [0u64; 2];
let bsb64a = src.as_mut_bitslice::<BigEndian>();
let bsb64b = [0u64; 2].as_bitslice::<BigEndian>();
let mut src = [0u64; 2];
let bsl64a = src.as_mut_bitslice::<LittleEndian>();
let bsl64b = [0u64; 2].as_bitslice::<LittleEndian>();
b.iter(|| bsb64a.add_assign(bsb64b));
b.iter(|| bsl64a.add_assign(bsl64b));

}
}
28 changes: 5 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,28 +107,10 @@ here for deduplication.
**/
#[inline]
fn rca1(a: bool, b: bool, c: bool) -> (bool, bool) {
/// Ripple-carry addition is a reduction operation from three bits of input
/// (a, b, carry-in) to two outputs (sum, carry-out). This table contains
/// the map of all possible inputs to their output.
// Note: I checked in Godbolt, and the jump table lookup comes out to ~ten
// simple instructions with the table baked in as immediate values. The
// more semantically clear match statement does not optimize nearly as
// well.
const RCA: [u8; 8] = [
// a + b + c => (y, z)
0, // 0 + 0 + 0 => (0, 0)
2, // 0 + 1 + 0 => (1, 0)
2, // 1 + 0 + 0 => (1, 0)
1, // 1 + 1 + 0 => (0, 1)
2, // 0 + 0 + 1 => (1, 0)
1, // 0 + 1 + 1 => (0, 1)
1, // 1 + 0 + 1 => (0, 1)
3, // 1 + 1 + 1 => (1, 1)
];
// Compute the lookup index from carry-in, left, and right
let jmp = ((c as u8) << 2) | ((a as u8) << 1) | (b as u8);
// Look up the output bits
let yz = RCA[jmp as usize];
// Ripple-carry addition is a reduction operation from three bits of input
// (a, b, carry-in) to two outputs (sum, carry-out).
// Compute the sum from left, right and carry-in
let yz = a as u8 + b as u8 + c as u8;
// Split them
(yz & 2 != 0, yz & 1 != 0)
(yz & 0b01 != 0, yz & 0b10 != 0)
}

0 comments on commit e1ac2c9

Please sign in to comment.