1use std::mem::size_of;
5use num_traits::{AsPrimitive, Bounded, NumCast, Unsigned};
6
7pub fn fast_bool_anf_transform_unsigned<
22 U: Unsigned
23 + std::ops::Shr<U, Output = U>
24 + std::ops::Shl<U, Output = U>
25 + std::ops::BitOr<U, Output = U>
26 + std::ops::BitAnd<U, Output = U>
27 + PartialOrd<U>
28 + std::ops::Not<Output = U>
29 + NumCast
30 + Bounded
31 + AsPrimitive<usize>
32 + Copy,
33>(
34 rule_number: U,
35 num_variables_function: usize,
36) -> U
37{
38 let u0: U = U::from(0).unwrap();
39 let u1: U = U::from(1).unwrap();
40 let unum_variables_function = U::from(num_variables_function).unwrap();
41
42 #[cfg(debug_assertions)]
43 if (size_of::<U>() << 3) < (1 << num_variables_function) {
44 panic!("Unsigned type is not large enough to hold the rule number, please use a larger unsigned type");
45 }
46
47 #[cfg(debug_assertions)]
48 if rule_number > (U::max_value() >> U::from((size_of::<U>() << 3) - (1 << num_variables_function)).unwrap()) {
49 panic!("The rule number must be less than 2^(2^n), n being the number of variables in the function");
50 }
51
52 let mut blocksize = u1;
53 let mut final_f = rule_number;
54 for _ in 0..num_variables_function {
55 let mut source = u0;
56 while source < (u1 << unum_variables_function) {
57 let target = source + blocksize;
58 for i in 0..blocksize.as_() {
59 let i = U::from(i).unwrap();
60 let f_target_i: bool = ((final_f >> (target + i)) & u1) != u0;
61 let f_source_i: bool = ((final_f >> (source + i)) & u1) != u0;
62 let f_target_i_xor_f_source_i = f_target_i ^ f_source_i;
63 if f_target_i_xor_f_source_i {
64 final_f = final_f | (u1 << (target + i));
65 } else {
66 final_f = final_f & !(u1 << (target + i));
67 }
68 }
69 source = source + (blocksize << u1);
70 }
71 blocksize = blocksize << u1;
72 }
73 final_f
74}
75
76pub fn fast_bool_anf_transform_bool_array(rule_truth_table: &mut [bool]) {
90 let mut blocksize = 1;
91 let input_size = rule_truth_table.len().trailing_zeros() as usize;
92
93 #[cfg(debug_assertions)]
94 if rule_truth_table.len() != 1 << input_size {
95 panic!("The input truth table must have a size of 2^n, n being the number of variables in the function");
96 }
97
98 for _ in 0..input_size {
99 let mut source = 0;
100 while source < (1<<input_size) {
101 let target = source + blocksize;
102 for i in 0..blocksize {
103 rule_truth_table[target + i] ^= rule_truth_table[source + i];
104 }
105 source = source + (blocksize << 1);
106 }
107 blocksize = blocksize << 1;
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::{fast_bool_anf_transform_bool_array, fast_bool_anf_transform_unsigned};
114 #[test]
115 fn test_fast_bool_anf_transform_unsigned() {
116 assert_eq!(fast_bool_anf_transform_unsigned(0u32, 2), 0);
117 assert_eq!(fast_bool_anf_transform_unsigned(1u32, 2), 15);
118 assert_eq!(fast_bool_anf_transform_unsigned(2u32, 2), 10);
119 assert_eq!(fast_bool_anf_transform_unsigned(3u32, 2), 5);
120 assert_eq!(fast_bool_anf_transform_unsigned(4u32, 2), 12);
121 assert_eq!(fast_bool_anf_transform_unsigned(5u32, 2), 3);
122 assert_eq!(fast_bool_anf_transform_unsigned(6u32, 2), 6);
123 assert_eq!(fast_bool_anf_transform_unsigned(7u32, 2), 9);
124 assert_eq!(fast_bool_anf_transform_unsigned(8u32, 2), 8);
125 assert_eq!(fast_bool_anf_transform_unsigned(9u32, 2), 7);
126 assert_eq!(fast_bool_anf_transform_unsigned(10u32, 2), 2);
127 assert_eq!(fast_bool_anf_transform_unsigned(11u32, 2), 13);
128 assert_eq!(fast_bool_anf_transform_unsigned(12u32, 2), 4);
129 assert_eq!(fast_bool_anf_transform_unsigned(13u32, 2), 11);
130 assert_eq!(fast_bool_anf_transform_unsigned(14u32, 2), 14);
131 assert_eq!(fast_bool_anf_transform_unsigned(15u32, 2), 1);
132
133 assert_eq!(fast_bool_anf_transform_unsigned(240u32, 3), 16);
134 assert_eq!(fast_bool_anf_transform_unsigned(30u32, 3), 30);
135 assert_eq!(fast_bool_anf_transform_unsigned(30u8, 3), 30);
136 }
137
138 #[test]
139 #[should_panic]
140 fn test_fast_bool_anf_transform_unsigned_rule_number_too_large() {
141 let _ = fast_bool_anf_transform_unsigned(16 as u32, 2);
142 }
143
144 #[test]
145 #[should_panic]
146 fn test_fast_bool_anf_transform_unsigned_not_enough_bits() {
147 let _ = fast_bool_anf_transform_unsigned(16 as u16, 5);
148 }
149
150 #[test]
151 fn test_fast_bool_anf_transform_bool_array() {
152 let mut rule_truth_table = [false, false, false, false];
153 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
154 assert_eq!(rule_truth_table, [false, false, false, false]);
155
156 rule_truth_table = [true, false, false, false];
157 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
158 assert_eq!(rule_truth_table, [true, true, true, true]);
159
160 rule_truth_table = [false, true, false, false];
161 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
162 assert_eq!(rule_truth_table, [false, true, false, true]);
163
164 rule_truth_table = [true, true, false, false];
165 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
166 assert_eq!(rule_truth_table, [true, false, true, false]);
167
168 let mut rule_truth_table = [false, false, true, false];
169 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
170 assert_eq!(rule_truth_table, [false, false, true, true]);
171
172 rule_truth_table = [true, false, true, false];
173 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
174 assert_eq!(rule_truth_table, [true, true, false, false]);
175
176 rule_truth_table = [false, true, true, false];
177 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
178 assert_eq!(rule_truth_table, [false, true, true, false]);
179
180 rule_truth_table = [true, true, true, false];
181 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
182 assert_eq!(rule_truth_table, [true, false, false, true]);
183
184 let mut rule_truth_table = [false, false, false, true];
185 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
186 assert_eq!(rule_truth_table, [false, false, false, true]);
187
188 rule_truth_table = [true, false, false, true];
189 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
190 assert_eq!(rule_truth_table, [true, true, true, false]);
191
192 rule_truth_table = [false, true, false, true];
193 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
194 assert_eq!(rule_truth_table, [false, true, false, false]);
195
196 rule_truth_table = [true, true, false, true];
197 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
198 assert_eq!(rule_truth_table, [true, false, true, true]);
199
200 let mut rule_truth_table = [false, false, true, true];
201 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
202 assert_eq!(rule_truth_table, [false, false, true, false]);
203
204 rule_truth_table = [true, false, true, true];
205 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
206 assert_eq!(rule_truth_table, [true, true, false, true]);
207
208 rule_truth_table = [false, true, true, true];
209 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
210 assert_eq!(rule_truth_table, [false, true, true, true]);
211
212 rule_truth_table = [true, true, true, true];
213 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
214 assert_eq!(rule_truth_table, [true, false, false, false]);
215
216 let mut rule_truth_table = [false, false, false, false, true, true, true, true]; fast_bool_anf_transform_bool_array(&mut rule_truth_table);
218 assert_eq!(rule_truth_table, [false, false, false, false, true, false, false, false]);
219
220 let mut rule_truth_table = [false, true, true, true, true, false, false, false]; fast_bool_anf_transform_bool_array(&mut rule_truth_table);
222 assert_eq!(rule_truth_table, [false, true, true, true, true, false, false, false]);
223 }
224
225 #[test]
226 #[should_panic]
227 fn test_fast_bool_anf_transform_bool_array_wrong_input_size() {
228 let mut rule_truth_table = [false, false, false, false, true, true, true];
229 fast_bool_anf_transform_bool_array(&mut rule_truth_table);
230 }
231}