1#![no_std]
2#![doc = include_str!("../README.md")]
3
4pub trait TernLog {
11 fn ternlog(self, b: Self, c: Self, lut: u8) -> Self;
34 fn const_ternlog<const LUT: u8>(self, b: Self, c: Self) -> Self;
43}
44
45macro_rules! impl_ternlog {
46 ($($ty:ident)*) => {
47 $(impl TernLog for $ty {
48 fn ternlog(self, b: Self, c: Self, lut: u8) -> Self {
49 ternlog(self as _, b as _, c as _, lut) as _
50 }
51 fn const_ternlog<const LUT: u8>(self, b: Self, c: Self) -> Self {
52 ternlog(self as _, b as _, c as _, LUT) as _
53 }
54 })*
55 };
56}
57
58impl_ternlog![u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize];
59
60impl TernLog for bool {
61 fn ternlog(self, b: Self, c: Self, lut: u8) -> Self {
62 ternlog(self as _, b as _, c as _, lut) & 1 != 0
63 }
64 fn const_ternlog<const LUT: u8>(self, b: Self, c: Self) -> Self {
65 ternlog(self as _, b as _, c as _, LUT) & 1 != 0
66 }
67}
68
69#[inline(always)]
70fn ternlog(a: u128, b: u128, c: u128, lut: u8) -> u128 {
71 match lut {
72 0b00000000 => c ^ c,
73 0b00000001 => !c ^ (!c & (b | a)),
74 0b00000010 => c ^ (c & (b | a)),
75 0b00000011 => !b & !a,
76 0b00000100 => b ^ (b & (c | a)),
77 0b00000101 => !c & !a,
78 0b00000110 => !a & (c ^ b),
79 0b00000111 => !a & (!c | !b),
80 0b00001000 => !a & (c & b),
81 0b00001001 => !c ^ ((c & a) ^ (b | a)),
82 0b00001010 => c & !a,
83 0b00001011 => a ^ (!b | (c | a)),
84 0b00001100 => b & !a,
85 0b00001101 => a ^ (!c | (b | a)),
86 0b00001110 => !a & (c | b),
87 0b00001111 => !a,
88 0b00010000 => a ^ (a & (c | b)),
89 0b00010001 => !c & !b,
90 0b00010010 => !b & (c ^ a),
91 0b00010011 => !b & (!c | !a),
92 0b00010100 => !c & (b ^ a),
93 0b00010101 => !c ^ (!c & (b & a)),
94 0b00010110 => c ^ ((c & b) | (b ^ a)),
95 0b00010111 => !c ^ ((c ^ b) & (c ^ a)),
96 0b00011000 => (c ^ a) & (b ^ a),
97 0b00011001 => c ^ (!b | (c & a)),
98 0b00011010 => a ^ (c | (b & a)),
99 0b00011011 => !c ^ ((c | b) ^ (c & a)),
100 0b00011100 => a ^ (b | (c & a)),
101 0b00011101 => !c ^ (b & (c ^ a)),
102 0b00011110 => a ^ (c | b),
103 0b00011111 => a ^ (!a | (c | b)),
104 0b00100000 => !b & (c & a),
105 0b00100001 => !c ^ ((c & b) ^ (b | a)),
106 0b00100010 => c & !b,
107 0b00100011 => b ^ (!a | (c | b)),
108 0b00100100 => (c ^ b) & (b ^ a),
109 0b00100101 => c ^ (!a | (c & b)),
110 0b00100110 => b ^ (c | (b & a)),
111 0b00100111 => !c ^ ((c & b) ^ (c | a)),
112 0b00101000 => c & (b ^ a),
113 0b00101001 => (c | !b) & (!c ^ (b ^ a)),
114 0b00101010 => c ^ (c & (b & a)),
115 0b00101011 => !c ^ ((c ^ b) | (c ^ a)),
116 0b00101100 => (c | b) & (b ^ a),
117 0b00101101 => c ^ (!a ^ (c & b)),
118 0b00101110 => (c | b) ^ (b & a),
119 0b00101111 => !a | (c & !b),
120 0b00110000 => b ^ (b | a),
121 0b00110001 => b ^ (!c | (b | a)),
122 0b00110010 => !b & (c | a),
123 0b00110011 => !b,
124 0b00110100 => b ^ (a | (c & b)),
125 0b00110101 => !c ^ (a & (c ^ b)),
126 0b00110110 => b ^ (c | a),
127 0b00110111 => b ^ (!b | (c | a)),
128 0b00111000 => (c | a) & (b ^ a),
129 0b00111001 => c ^ (!b ^ (c & a)),
130 0b00111010 => (c | a) ^ (b & a),
131 0b00111011 => !b | (c & !a),
132 0b00111100 => b ^ a,
133 0b00111101 => !b ^ (!a & (c | b)),
134 0b00111110 => (c ^ b) ^ ((c ^ a) & (b | a)),
135 0b00111111 => !b | !a,
136 0b01000000 => !c & (b & a),
137 0b01000001 => !c & (b ^ !a),
138 0b01000010 => (c ^ b) & (c ^ a),
139 0b01000011 => b ^ (!a | (c & b)),
140 0b01000100 => c ^ (c | b),
141 0b01000101 => c ^ (!a | (c | b)),
142 0b01000110 => c ^ (b | (c & a)),
143 0b01000111 => !c ^ (!b & (c ^ a)),
144 0b01001000 => b & (c ^ a),
145 0b01001001 => (c | a) ^ (!b | (c & a)),
146 0b01001010 => (c | b) & (c ^ a),
147 0b01001011 => c ^ (!a ^ (c | b)),
148 0b01001100 => c ^ ((c ^ b) | (c & a)),
149 0b01001101 => !c ^ ((c ^ a) & (b ^ a)),
150 0b01001110 => (c | b) ^ (c & a),
151 0b01001111 => !a | (c ^ (c | b)),
152 0b01010000 => c ^ (c | a),
153 0b01010001 => c ^ (!b | (c | a)),
154 0b01010010 => c ^ (a | (c & b)),
155 0b01010011 => !c ^ (!a & (c ^ b)),
156 0b01010100 => !c & (b | a),
157 0b01010101 => !c,
158 0b01010110 => c ^ (b | a),
159 0b01010111 => c ^ (!c | (b | a)),
160 0b01011000 => (c ^ a) & (b | a),
161 0b01011001 => c ^ (a | !b),
162 0b01011010 => c ^ a,
163 0b01011011 => !c ^ (!a & (c | b)),
164 0b01011100 => (c & a) ^ (b | a),
165 0b01011101 => !c | (b & !a),
166 0b01011110 => (c ^ b) ^ ((c | a) & (b ^ a)),
167 0b01011111 => !c | !a,
168 0b01100000 => a & (c ^ b),
169 0b01100001 => (c | b) ^ (!a | (c & b)),
170 0b01100010 => (c ^ b) & (c | a),
171 0b01100011 => c ^ (!b ^ (c | a)),
172 0b01100100 => (c ^ b) & (b | a),
173 0b01100101 => c ^ (b | !a),
174 0b01100110 => c ^ b,
175 0b01100111 => !c ^ (!b & (c | a)),
176 0b01101000 => (c & b) ^ (a & (c | b)),
177 0b01101001 => !c ^ (b ^ a),
178 0b01101010 => c ^ (b & a),
179 0b01101011 => !b ^ ((c ^ a) & (b | a)),
180 0b01101100 => b ^ (c & a),
181 0b01101101 => !c ^ ((c | a) & (b ^ a)),
182 0b01101110 => (c & b) ^ ((c ^ b) | (c & a)),
183 0b01101111 => !a | (c ^ b),
184 0b01110000 => c ^ ((c & b) | (c ^ a)),
185 0b01110001 => !c ^ ((c ^ b) & (b ^ a)),
186 0b01110010 => (c & b) ^ (c | a),
187 0b01110011 => !b | (c ^ (c | a)),
188 0b01110100 => (c & b) ^ (b | a),
189 0b01110101 => !c | (b ^ (b | a)),
190 0b01110110 => (c & b) ^ (c | (b | a)),
191 0b01110111 => !c | !b,
192 0b01111000 => a ^ (c & b),
193 0b01111001 => !c ^ ((c | b) & (b ^ a)),
194 0b01111010 => (c & a) ^ ((c & b) | (c ^ a)),
195 0b01111011 => !b | (c ^ a),
196 0b01111100 => (c ^ (c | b)) | (b ^ a),
197 0b01111101 => !c | (b ^ a),
198 0b01111110 => (c ^ b) | (c ^ a),
199 0b01111111 => c ^ (!c | (b & a)),
200 0b10000000 => c & (b & a),
201 0b10000001 => (c | b) ^ (!a | (c ^ b)),
202 0b10000010 => c ^ (c & (b ^ a)),
203 0b10000011 => (c | !b) & (b ^ !a),
204 0b10000100 => c ^ ((c | b) ^ (b & a)),
205 0b10000101 => (c & !a) ^ (!a | (c & b)),
206 0b10000110 => c ^ ((c | b) & (b ^ a)),
207 0b10000111 => !a ^ (c & b),
208 0b10001000 => c & b,
209 0b10001001 => (c ^ b) ^ (!a | (c | b)),
210 0b10001010 => c & (b | !a),
211 0b10001011 => a ^ (!b | (c ^ a)),
212 0b10001100 => b & (c | !a),
213 0b10001101 => a ^ (!c | (b ^ a)),
214 0b10001110 => c ^ ((c ^ b) & (b ^ a)),
215 0b10001111 => !a | (c & b),
216 0b10010000 => c ^ ((c | a) ^ (b & a)),
217 0b10010001 => (c & !b) ^ (!b | (c & a)),
218 0b10010010 => c ^ ((c | a) & (b ^ a)),
219 0b10010011 => !b ^ (c & a),
220 0b10010100 => b ^ ((c ^ a) & (b | a)),
221 0b10010101 => !c ^ (b & a),
222 0b10010110 => c ^ (b ^ a),
223 0b10010111 => (c | !b) ^ ((c | b) & (b ^ a)),
224 0b10011000 => c ^ (!b & (c | a)),
225 0b10011001 => c ^ !b,
226 0b10011010 => (c ^ b) ^ (b | a),
227 0b10011011 => !b ^ (c & (b | a)),
228 0b10011100 => (c ^ b) ^ (c | a),
229 0b10011101 => !c ^ (b & (c | a)),
230 0b10011110 => (c & b) | (c ^ (b ^ a)),
231 0b10011111 => a ^ (!a | (c ^ b)),
232 0b10100000 => c & a,
233 0b10100001 => (c ^ a) ^ (!b | (c | a)),
234 0b10100010 => c & (a | !b),
235 0b10100011 => b ^ (!a | (c ^ b)),
236 0b10100100 => c ^ (!a & (c | b)),
237 0b10100101 => c ^ !a,
238 0b10100110 => (c ^ b) ^ (b & a),
239 0b10100111 => !a ^ (c & (b | a)),
240 0b10101000 => c & (b | a),
241 0b10101001 => !c ^ (b | a),
242 0b10101010 => c,
243 0b10101011 => c | (!c ^ (b | a)),
244 0b10101100 => c ^ (!a & (c ^ b)),
245 0b10101101 => !c ^ (a | (c & b)),
246 0b10101110 => c | (b & !a),
247 0b10101111 => c | !a,
248 0b10110000 => a & (c | !b),
249 0b10110001 => b ^ (!c | (b ^ a)),
250 0b10110010 => c ^ ((c ^ a) & (b ^ a)),
251 0b10110011 => !b | (c & a),
252 0b10110100 => (c & b) ^ (b ^ a),
253 0b10110101 => !c ^ (a & (c | b)),
254 0b10110110 => (c | b) ^ ((c ^ a) & (b | a)),
255 0b10110111 => b ^ (!b | (c ^ a)),
256 0b10111000 => c ^ (!b & (c ^ a)),
257 0b10111001 => !c ^ (b | (c & a)),
258 0b10111010 => c | (b ^ (b | a)),
259 0b10111011 => c | !b,
260 0b10111100 => (c & b) | (b ^ a),
261 0b10111101 => (c | !c) ^ ((c ^ b) & (c ^ a)),
262 0b10111110 => c | (b ^ a),
263 0b10111111 => c | (!c ^ (b & a)),
264 0b11000000 => b & a,
265 0b11000001 => (c ^ !b) ^ ((c ^ a) & (b | a)),
266 0b11000010 => b ^ (!a & (c | b)),
267 0b11000011 => b ^ !a,
268 0b11000100 => b & (a | !c),
269 0b11000101 => c ^ (!a | (c ^ b)),
270 0b11000110 => (c ^ b) ^ (c & a),
271 0b11000111 => !a ^ (b & (c | a)),
272 0b11001000 => b & (c | a),
273 0b11001001 => !b ^ (c | a),
274 0b11001010 => c ^ (a & (c ^ b)),
275 0b11001011 => !b ^ (a | (c & b)),
276 0b11001100 => b,
277 0b11001101 => b | (!c & !a),
278 0b11001110 => c ^ ((c ^ b) & (b | a)),
279 0b11001111 => b | !a,
280 0b11010000 => a & (b | !c),
281 0b11010001 => c ^ (!b | (c ^ a)),
282 0b11010010 => (c & b) ^ (c ^ a),
283 0b11010011 => !b ^ (a & (c | b)),
284 0b11010100 => c ^ ((c ^ b) | (c ^ a)),
285 0b11010101 => !c | (b & a),
286 0b11010110 => (c | b) ^ ((c | a) & (b ^ a)),
287 0b11010111 => c ^ (!c | (b ^ a)),
288 0b11011000 => c ^ ((c & b) ^ (c | a)),
289 0b11011001 => !b ^ (c | (b & a)),
290 0b11011010 => (c & b) | (c ^ a),
291 0b11011011 => (c & a) ^ (!b | (c ^ a)),
292 0b11011100 => b | (c ^ (c | a)),
293 0b11011101 => b | !c,
294 0b11011110 => b | (c ^ a),
295 0b11011111 => b | (!c | !a),
296 0b11100000 => a & (c | b),
297 0b11100001 => !a ^ (c | b),
298 0b11100010 => c ^ (b & (c ^ a)),
299 0b11100011 => !a ^ (b | (c & a)),
300 0b11100100 => c ^ ((c | b) ^ (c & a)),
301 0b11100101 => !a ^ (c | (b & a)),
302 0b11100110 => (c ^ b) | (c & a),
303 0b11100111 => (c & b) ^ (!a | (c ^ b)),
304 0b11101000 => c ^ ((c ^ b) & (c ^ a)),
305 0b11101001 => !c ^ ((c & b) | (b ^ a)),
306 0b11101010 => c | (b & a),
307 0b11101011 => c | (b ^ !a),
308 0b11101100 => b | (c & a),
309 0b11101101 => b | (c ^ !a),
310 0b11101110 => c | b,
311 0b11101111 => !a | (c | b),
312 0b11110000 => a,
313 0b11110001 => a | (!c & !b),
314 0b11110010 => c ^ ((c ^ a) & (b | a)),
315 0b11110011 => a | !b,
316 0b11110100 => b ^ ((c | a) & (b ^ a)),
317 0b11110101 => a | !c,
318 0b11110110 => a | (c ^ b),
319 0b11110111 => a | (!c | !b),
320 0b11111000 => a | (c & b),
321 0b11111001 => a | (c ^ !b),
322 0b11111010 => c | a,
323 0b11111011 => !b | (c | a),
324 0b11111100 => b | a,
325 0b11111101 => !c | (b | a),
326 0b11111110 => c | (b | a),
327 0b11111111 => c | !c,
328 }
329}
330
331#[cfg(test)]
332mod test {
333 use super::TernLog;
334
335 #[test]
336 fn all_boolean() {
337 for tbl in 0..=255 {
338 for i in 0..8 {
339 let a = i & 4 != 0;
340 let b = i & 2 != 0;
341 let c = i & 1 != 0;
342 let r = tbl & 1 << i != 0;
343 assert_eq!(r, a.ternlog(b, c, tbl), "{tbl:#010b}:{i} -> {a}{b}{c} {r}");
344 }
345 }
346 }
347}