Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
38 changes: 38 additions & 0 deletions cmov/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,44 @@ impl CmovEq for u128 {
}
}

// Impl `Cmov*` by first casting to unsigned then using the unsigned `Cmov` impls
// TODO(tarcieri): use `cast_unsigned`/`cast_signed` to get rid of the `=> u*`
macro_rules! impl_cmov_traits_for_signed_ints {
( $($int:ty => $uint:ty),+ ) => {
$(
impl Cmov for $int {
#[inline]
fn cmovnz(&mut self, value: &Self, condition: Condition) {
let mut tmp = *self as $uint;
tmp.cmovnz(&(*value as $uint), condition);
*self = tmp as $int;
}

#[inline]
fn cmovz(&mut self, value: &Self, condition: Condition) {
let mut tmp = *self as $uint;
tmp.cmovz(&(*value as $uint), condition);
*self = tmp as $int;
}
}

impl CmovEq for $int {
#[inline]
fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) {
(*self as $uint).cmoveq(&(*rhs as $uint), input, output);
}

#[inline]
fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) {
(*self as $uint).cmovne(&(*rhs as $uint), input, output);
}
}
)+
};
}

impl_cmov_traits_for_signed_ints!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128);

impl<T: CmovEq> CmovEq for [T] {
fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) {
let mut tmp = 1u8;
Expand Down
68 changes: 68 additions & 0 deletions cmov/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,71 @@
// TODO(tarcieri): test other `i*` types
mod i64 {
use cmov::{Cmov, CmovEq};

pub const I64_A: i64 = 0x1111_1111_1111_1111;
pub const I64_B: i64 = -0x2222_2222_2222_2222;

#[test]
fn cmovz_works() {
let mut n = I64_A;

for cond in 1..0xFF {
n.cmovz(&I64_B, cond);
assert_eq!(n, I64_A);
}

n.cmovz(&I64_B, 0);
assert_eq!(n, I64_B);
}

#[test]
fn cmovnz_works() {
let mut n = I64_A;
n.cmovnz(&I64_B, 0);
assert_eq!(n, I64_A);

for cond in 1..0xFF {
let mut n = I64_A;
n.cmovnz(&I64_B, cond);
assert_eq!(n, I64_B);
}
}

#[test]
fn cmoveq_works() {
let mut o = 0u8;

for cond in 1..0xFFi64 {
cond.cmoveq(&cond, cond as u8, &mut o);
assert_eq!(o, cond as u8);
cond.cmoveq(&0, 0, &mut o);
assert_eq!(o, cond as u8);
}

I64_A.cmoveq(&I64_A, 43u8, &mut o);
assert_eq!(o, 43u8);
I64_A.cmoveq(&I64_B, 55u8, &mut o);
assert_eq!(o, 43u8);
}

#[test]
fn cmovne_works() {
let mut o = 0u8;

for cond in 1..0xFFi64 {
cond.cmovne(&0, cond as u8, &mut o);
assert_eq!(o, cond as u8);
cond.cmovne(&cond, 0, &mut o);
assert_eq!(o, cond as u8);
}

I64_A.cmovne(&I64_B, 55u8, &mut o);
assert_eq!(o, 55u8);
I64_A.cmovne(&I64_A, 12u8, &mut o);
assert_eq!(o, 55u8);
}
}

mod u8 {
use cmov::{Cmov, CmovEq};

Expand Down