blob: 6c1e82fee3835fbbacbc718bbe924a8dc1f7d33d [file] [log] [blame]
Yiming Jingcf21fc42021-07-16 13:23:26 -07001use num_bigint::{BigInt, Sign, ToBigInt};
2use num_traits::ToPrimitive;
3use std::{i32, i64, u32};
4
5enum ValueVec {
6 N,
7 P(&'static [u32]),
8 M(&'static [u32]),
9}
10
11use crate::ValueVec::*;
12
13impl ToBigInt for ValueVec {
14 fn to_bigint(&self) -> Option<BigInt> {
15 match self {
16 &N => Some(BigInt::from_slice(Sign::NoSign, &[])),
17 &P(s) => Some(BigInt::from_slice(Sign::Plus, s)),
18 &M(s) => Some(BigInt::from_slice(Sign::Minus, s)),
19 }
20 }
21}
22
23// a, !a
24const NOT_VALUES: &[(ValueVec, ValueVec)] = &[
25 (N, M(&[1])),
26 (P(&[1]), M(&[2])),
27 (P(&[2]), M(&[3])),
28 (P(&[!0 - 2]), M(&[!0 - 1])),
29 (P(&[!0 - 1]), M(&[!0])),
30 (P(&[!0]), M(&[0, 1])),
31 (P(&[0, 1]), M(&[1, 1])),
32 (P(&[1, 1]), M(&[2, 1])),
33];
34
35// a, b, a & b, a | b, a ^ b
36const BITWISE_VALUES: &[(ValueVec, ValueVec, ValueVec, ValueVec, ValueVec)] = &[
37 (N, N, N, N, N),
38 (N, P(&[1]), N, P(&[1]), P(&[1])),
39 (N, P(&[!0]), N, P(&[!0]), P(&[!0])),
40 (N, P(&[0, 1]), N, P(&[0, 1]), P(&[0, 1])),
41 (N, M(&[1]), N, M(&[1]), M(&[1])),
42 (N, M(&[!0]), N, M(&[!0]), M(&[!0])),
43 (N, M(&[0, 1]), N, M(&[0, 1]), M(&[0, 1])),
44 (P(&[1]), P(&[!0]), P(&[1]), P(&[!0]), P(&[!0 - 1])),
45 (P(&[!0]), P(&[!0]), P(&[!0]), P(&[!0]), N),
46 (P(&[!0]), P(&[1, 1]), P(&[1]), P(&[!0, 1]), P(&[!0 - 1, 1])),
47 (P(&[1]), M(&[!0]), P(&[1]), M(&[!0]), M(&[0, 1])),
48 (P(&[!0]), M(&[1]), P(&[!0]), M(&[1]), M(&[0, 1])),
49 (P(&[!0]), M(&[!0]), P(&[1]), M(&[1]), M(&[2])),
50 (P(&[!0]), M(&[1, 1]), P(&[!0]), M(&[1, 1]), M(&[0, 2])),
51 (P(&[1, 1]), M(&[!0]), P(&[1, 1]), M(&[!0]), M(&[0, 2])),
52 (M(&[1]), M(&[!0]), M(&[!0]), M(&[1]), P(&[!0 - 1])),
53 (M(&[!0]), M(&[!0]), M(&[!0]), M(&[!0]), N),
54 (M(&[!0]), M(&[1, 1]), M(&[!0, 1]), M(&[1]), P(&[!0 - 1, 1])),
55];
56
57const I32_MIN: i64 = i32::MIN as i64;
58const I32_MAX: i64 = i32::MAX as i64;
59const U32_MAX: i64 = u32::MAX as i64;
60
61// some corner cases
62const I64_VALUES: &[i64] = &[
63 i64::MIN,
64 i64::MIN + 1,
65 i64::MIN + 2,
66 i64::MIN + 3,
67 -U32_MAX - 3,
68 -U32_MAX - 2,
69 -U32_MAX - 1,
70 -U32_MAX,
71 -U32_MAX + 1,
72 -U32_MAX + 2,
73 -U32_MAX + 3,
74 I32_MIN - 3,
75 I32_MIN - 2,
76 I32_MIN - 1,
77 I32_MIN,
78 I32_MIN + 1,
79 I32_MIN + 2,
80 I32_MIN + 3,
81 -3,
82 -2,
83 -1,
84 0,
85 1,
86 2,
87 3,
88 I32_MAX - 3,
89 I32_MAX - 2,
90 I32_MAX - 1,
91 I32_MAX,
92 I32_MAX + 1,
93 I32_MAX + 2,
94 I32_MAX + 3,
95 U32_MAX - 3,
96 U32_MAX - 2,
97 U32_MAX - 1,
98 U32_MAX,
99 U32_MAX + 1,
100 U32_MAX + 2,
101 U32_MAX + 3,
102 i64::MAX - 3,
103 i64::MAX - 2,
104 i64::MAX - 1,
105 i64::MAX,
106];
107
108#[test]
109fn test_not() {
110 for &(ref a, ref not) in NOT_VALUES.iter() {
111 let a = a.to_bigint().unwrap();
112 let not = not.to_bigint().unwrap();
113
114 // sanity check for tests that fit in i64
115 if let (Some(prim_a), Some(prim_not)) = (a.to_i64(), not.to_i64()) {
116 assert_eq!(!prim_a, prim_not);
117 }
118
119 assert_eq!(!a.clone(), not, "!{:x}", a);
120 assert_eq!(!not.clone(), a, "!{:x}", not);
121 }
122}
123
124#[test]
125fn test_not_i64() {
126 for &prim_a in I64_VALUES.iter() {
127 let a = prim_a.to_bigint().unwrap();
128 let not = (!prim_a).to_bigint().unwrap();
129 assert_eq!(!a.clone(), not, "!{:x}", a);
130 }
131}
132
133#[test]
134fn test_bitwise() {
135 for &(ref a, ref b, ref and, ref or, ref xor) in BITWISE_VALUES.iter() {
136 let a = a.to_bigint().unwrap();
137 let b = b.to_bigint().unwrap();
138 let and = and.to_bigint().unwrap();
139 let or = or.to_bigint().unwrap();
140 let xor = xor.to_bigint().unwrap();
141
142 // sanity check for tests that fit in i64
143 if let (Some(prim_a), Some(prim_b)) = (a.to_i64(), b.to_i64()) {
144 if let Some(prim_and) = and.to_i64() {
145 assert_eq!(prim_a & prim_b, prim_and);
146 }
147 if let Some(prim_or) = or.to_i64() {
148 assert_eq!(prim_a | prim_b, prim_or);
149 }
150 if let Some(prim_xor) = xor.to_i64() {
151 assert_eq!(prim_a ^ prim_b, prim_xor);
152 }
153 }
154
155 assert_eq!(a.clone() & &b, and, "{:x} & {:x}", a, b);
156 assert_eq!(b.clone() & &a, and, "{:x} & {:x}", b, a);
157 assert_eq!(a.clone() | &b, or, "{:x} | {:x}", a, b);
158 assert_eq!(b.clone() | &a, or, "{:x} | {:x}", b, a);
159 assert_eq!(a.clone() ^ &b, xor, "{:x} ^ {:x}", a, b);
160 assert_eq!(b.clone() ^ &a, xor, "{:x} ^ {:x}", b, a);
161 }
162}
163
164#[test]
165fn test_bitwise_i64() {
166 for &prim_a in I64_VALUES.iter() {
167 let a = prim_a.to_bigint().unwrap();
168 for &prim_b in I64_VALUES.iter() {
169 let b = prim_b.to_bigint().unwrap();
170 let and = (prim_a & prim_b).to_bigint().unwrap();
171 let or = (prim_a | prim_b).to_bigint().unwrap();
172 let xor = (prim_a ^ prim_b).to_bigint().unwrap();
173 assert_eq!(a.clone() & &b, and, "{:x} & {:x}", a, b);
174 assert_eq!(a.clone() | &b, or, "{:x} | {:x}", a, b);
175 assert_eq!(a.clone() ^ &b, xor, "{:x} ^ {:x}", a, b);
176 }
177 }
178}