Skip to content

Commit 544cf11

Browse files
authored
cmov: signed integer support (#1280)
Adds impls of `Cmov`/`CmovEq` for `i8`, `i16`, `i32`, `i164`, and `i128`
1 parent 76c4511 commit 544cf11

2 files changed

Lines changed: 106 additions & 0 deletions

File tree

cmov/src/lib.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,44 @@ impl CmovEq for u128 {
135135
}
136136
}
137137

138+
// Impl `Cmov*` by first casting to unsigned then using the unsigned `Cmov` impls
139+
// TODO(tarcieri): use `cast_unsigned`/`cast_signed` to get rid of the `=> u*`
140+
macro_rules! impl_cmov_traits_for_signed_ints {
141+
( $($int:ty => $uint:ty),+ ) => {
142+
$(
143+
impl Cmov for $int {
144+
#[inline]
145+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
146+
let mut tmp = *self as $uint;
147+
tmp.cmovnz(&(*value as $uint), condition);
148+
*self = tmp as $int;
149+
}
150+
151+
#[inline]
152+
fn cmovz(&mut self, value: &Self, condition: Condition) {
153+
let mut tmp = *self as $uint;
154+
tmp.cmovz(&(*value as $uint), condition);
155+
*self = tmp as $int;
156+
}
157+
}
158+
159+
impl CmovEq for $int {
160+
#[inline]
161+
fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) {
162+
(*self as $uint).cmoveq(&(*rhs as $uint), input, output);
163+
}
164+
165+
#[inline]
166+
fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) {
167+
(*self as $uint).cmovne(&(*rhs as $uint), input, output);
168+
}
169+
}
170+
)+
171+
};
172+
}
173+
174+
impl_cmov_traits_for_signed_ints!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128);
175+
138176
impl<T: CmovEq> CmovEq for [T] {
139177
fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) {
140178
let mut tmp = 1u8;

cmov/tests/lib.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,71 @@
1+
// TODO(tarcieri): test other `i*` types
2+
mod i64 {
3+
use cmov::{Cmov, CmovEq};
4+
5+
pub const I64_A: i64 = 0x1111_1111_1111_1111;
6+
pub const I64_B: i64 = -0x2222_2222_2222_2222;
7+
8+
#[test]
9+
fn cmovz_works() {
10+
let mut n = I64_A;
11+
12+
for cond in 1..0xFF {
13+
n.cmovz(&I64_B, cond);
14+
assert_eq!(n, I64_A);
15+
}
16+
17+
n.cmovz(&I64_B, 0);
18+
assert_eq!(n, I64_B);
19+
}
20+
21+
#[test]
22+
fn cmovnz_works() {
23+
let mut n = I64_A;
24+
n.cmovnz(&I64_B, 0);
25+
assert_eq!(n, I64_A);
26+
27+
for cond in 1..0xFF {
28+
let mut n = I64_A;
29+
n.cmovnz(&I64_B, cond);
30+
assert_eq!(n, I64_B);
31+
}
32+
}
33+
34+
#[test]
35+
fn cmoveq_works() {
36+
let mut o = 0u8;
37+
38+
for cond in 1..0xFFi64 {
39+
cond.cmoveq(&cond, cond as u8, &mut o);
40+
assert_eq!(o, cond as u8);
41+
cond.cmoveq(&0, 0, &mut o);
42+
assert_eq!(o, cond as u8);
43+
}
44+
45+
I64_A.cmoveq(&I64_A, 43u8, &mut o);
46+
assert_eq!(o, 43u8);
47+
I64_A.cmoveq(&I64_B, 55u8, &mut o);
48+
assert_eq!(o, 43u8);
49+
}
50+
51+
#[test]
52+
fn cmovne_works() {
53+
let mut o = 0u8;
54+
55+
for cond in 1..0xFFi64 {
56+
cond.cmovne(&0, cond as u8, &mut o);
57+
assert_eq!(o, cond as u8);
58+
cond.cmovne(&cond, 0, &mut o);
59+
assert_eq!(o, cond as u8);
60+
}
61+
62+
I64_A.cmovne(&I64_B, 55u8, &mut o);
63+
assert_eq!(o, 55u8);
64+
I64_A.cmovne(&I64_A, 12u8, &mut o);
65+
assert_eq!(o, 55u8);
66+
}
67+
}
68+
169
mod u8 {
270
use cmov::{Cmov, CmovEq};
371

0 commit comments

Comments
 (0)