1use crate::tests::arithmetic::{run_binary_u64, BINARY_U64_CASES};
13use crate::{read_u32, read_u64, write_u64};
14
15const SHIFT_CASES: &[(u64, u32)] = &[
18 (0, 0),
19 (1, 1),
20 (0xFFFF_FFFF_FFFF_FFFF, 0),
21 (0xFFFF_FFFF_FFFF_FFFF, 63),
22 (0xDEAD_BEEF_DEAD_BEEF, 7),
23 (0x8000_0000_0000_0000, 1),
24 (0x1, 63),
25];
26
27const UNARY_U64_CASES: &[u64] = &[
28 0,
29 1,
30 0xFFFF_FFFF_FFFF_FFFF,
31 0x8000_0000_0000_0000,
32 0x0000_0000_0000_0001,
33 0xDEAD_BEEF_DEAD_BEEF,
34];
35
36fn run_shift(op: fn(&[u8], &mut [u8]) -> usize) -> u64 {
37 let mut acc = 0u64;
38 let mut input = [0u8; 12];
39 let mut output = [0u8; 8];
40 for (val, amt) in SHIFT_CASES {
41 input[0..8].copy_from_slice(&val.to_le_bytes());
42 input[8..12].copy_from_slice(&amt.to_le_bytes());
43 let len = op(&input, &mut output);
44 debug_assert!(len == 8);
45 acc ^= u64::from_le_bytes(output);
46 }
47 acc
48}
49
50fn run_unary(op: fn(&[u8], &mut [u8]) -> usize) -> u64 {
51 let mut acc = 0u64;
52 let mut input = [0u8; 8];
53 let mut output = [0u8; 8];
54 for val in UNARY_U64_CASES {
55 input.copy_from_slice(&val.to_le_bytes());
56 let len = op(&input, &mut output);
57 debug_assert!(len == 8);
58 acc ^= u64::from_le_bytes(output);
59 }
60 acc
61}
62
63pub fn shift_left(input: &[u8], output: &mut [u8]) -> usize {
66 let (mut off, mut out) = (0, 0);
67 let val = read_u64(input, &mut off);
68 let amt = read_u32(input, &mut off);
69 write_u64(output, &mut out, val.wrapping_shl(amt));
70 out
71}
72
73pub fn shift_right_logical(input: &[u8], output: &mut [u8]) -> usize {
74 let (mut off, mut out) = (0, 0);
75 let val = read_u64(input, &mut off);
76 let amt = read_u32(input, &mut off);
77 write_u64(output, &mut out, val.wrapping_shr(amt));
78 out
79}
80
81pub fn shift_right_arithmetic(input: &[u8], output: &mut [u8]) -> usize {
82 let (mut off, mut out) = (0, 0);
83 let val = read_u64(input, &mut off) as i64;
84 let amt = read_u32(input, &mut off);
85 write_u64(output, &mut out, val.wrapping_shr(amt) as u64);
86 out
87}
88
89pub fn rotate_right(input: &[u8], output: &mut [u8]) -> usize {
90 let (mut off, mut out) = (0, 0);
91 let val = read_u64(input, &mut off);
92 let amt = read_u32(input, &mut off);
93 write_u64(output, &mut out, val.rotate_right(amt));
94 out
95}
96
97pub fn and(input: &[u8], output: &mut [u8]) -> usize {
98 let (mut off, mut out) = (0, 0);
99 let a = read_u64(input, &mut off);
100 let b = read_u64(input, &mut off);
101 write_u64(output, &mut out, a & b);
102 out
103}
104
105pub fn or(input: &[u8], output: &mut [u8]) -> usize {
106 let (mut off, mut out) = (0, 0);
107 let a = read_u64(input, &mut off);
108 let b = read_u64(input, &mut off);
109 write_u64(output, &mut out, a | b);
110 out
111}
112
113pub fn xor(input: &[u8], output: &mut [u8]) -> usize {
114 let (mut off, mut out) = (0, 0);
115 let a = read_u64(input, &mut off);
116 let b = read_u64(input, &mut off);
117 write_u64(output, &mut out, a ^ b);
118 out
119}
120
121pub fn clz(input: &[u8], output: &mut [u8]) -> usize {
122 let (mut off, mut out) = (0, 0);
123 let val = read_u64(input, &mut off);
124 write_u64(output, &mut out, val.leading_zeros() as u64);
125 out
126}
127
128pub fn ctz(input: &[u8], output: &mut [u8]) -> usize {
129 let (mut off, mut out) = (0, 0);
130 let val = read_u64(input, &mut off);
131 write_u64(output, &mut out, val.trailing_zeros() as u64);
132 out
133}
134
135pub fn set_lt_u(input: &[u8], output: &mut [u8]) -> usize {
136 let (mut off, mut out) = (0, 0);
137 let a = read_u64(input, &mut off);
138 let b = read_u64(input, &mut off);
139 write_u64(output, &mut out, if a < b { 1 } else { 0 });
140 out
141}
142
143pub fn set_lt_s(input: &[u8], output: &mut [u8]) -> usize {
144 let (mut off, mut out) = (0, 0);
145 let a = read_u64(input, &mut off) as i64;
146 let b = read_u64(input, &mut off) as i64;
147 write_u64(output, &mut out, if a < b { 1 } else { 0 });
148 out
149}
150
151pub fn shift_left_suite() -> u64 {
154 run_shift(shift_left)
155}
156pub fn shift_right_logical_suite() -> u64 {
157 run_shift(shift_right_logical)
158}
159pub fn shift_right_arithmetic_suite() -> u64 {
160 run_shift(shift_right_arithmetic)
161}
162pub fn rotate_right_suite() -> u64 {
163 run_shift(rotate_right)
164}
165pub fn and_suite() -> u64 {
166 run_binary_u64(BINARY_U64_CASES, and)
167}
168pub fn or_suite() -> u64 {
169 run_binary_u64(BINARY_U64_CASES, or)
170}
171pub fn xor_suite() -> u64 {
172 run_binary_u64(BINARY_U64_CASES, xor)
173}
174pub fn clz_suite() -> u64 {
175 run_unary(clz)
176}
177pub fn ctz_suite() -> u64 {
178 run_unary(ctz)
179}
180pub fn set_lt_u_suite() -> u64 {
181 run_binary_u64(BINARY_U64_CASES, set_lt_u)
182}
183pub fn set_lt_s_suite() -> u64 {
184 run_binary_u64(BINARY_U64_CASES, set_lt_s)
185}