Last active
March 7, 2025 06:58
-
-
Save assyrianic/43782a430b5567c248fad3da8bf16922 to your computer and use it in GitHub Desktop.
truth table printer for binary logic functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
/// a*b = min(a,b) | |
int min(int const a, int const b) { | |
return a < b? a : b; | |
} | |
void print_and(size_t const n, int const set[const static n]) { | |
for( size_t a=0; a < n; a++ ) { | |
for( size_t b=0; b < n; b++ ) { | |
int const A = set[a]; | |
int const B = set[b]; | |
printf("a(%2i) & b(%2i) == %2i\n", A, B, min(A, B)); | |
} | |
} | |
} | |
/// a+b = max(a,b) | |
int max(int const a, int const b) { | |
return a > b? a : b; | |
} | |
void print_or(size_t const n, int const set[const static n]) { | |
for( size_t a=0; a < n; a++ ) { | |
for( size_t b=0; b < n; b++ ) { | |
int const A = set[a]; | |
int const B = set[b]; | |
printf("a(%2i) + b(%2i) == %2i\n", A, B, max(A, B)); | |
} | |
} | |
} | |
/// ~a = -a | |
/// (a + 1) mod (n) | |
int neg(int const a, int const n, int const is_unbalanced) { | |
return is_unbalanced? n - a : -a; | |
} | |
void print_neg(size_t const n, int const set[const static n]) { | |
for( size_t a=0; a < n; a++ ) { | |
int const A = set[a]; | |
printf("!a(%2i) == %2i\n", A, neg(A, n, 0)); | |
} | |
} | |
int main(void) { | |
int const tern_set[] = { -1, 0, 1 }; | |
size_t const tern_len = sizeof tern_set / sizeof tern_set[0]; | |
print_and(tern_len, tern_set); | |
puts("\n"); | |
print_or(tern_len, tern_set); | |
puts("\n"); | |
print_neg(tern_len, tern_set); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <inttypes.h> | |
#include <stdlib.h> | |
#include <math.h> | |
typedef int LogicFunc(int a, int b, int set_len, int balanced); | |
static inline int min(int const x, int const y) { return x < y? x : y; } | |
static inline int max(int const x, int const y) { return x < y? y : x; } | |
static inline int neg1(int const x) { return -x; } | |
static inline int neg2(int const x, int const n) { return (n-1) - x; } | |
static inline int neg3(int const x, int const n, int const balanced) { | |
return balanced? neg1(x) : neg2(x, n); | |
} | |
static inline int False(int a, int b, int set_len, int balanced) { return 0; } | |
static inline int AND(int a, int b, int set_len, int balanced) { return min(a,b); } | |
static inline int AND_NOTB(int a, int b, int set_len, int balanced) { | |
return min(a, neg3(b, set_len, balanced)); | |
} | |
static inline int A(int a, int b, int set_len, int balanced) { return a; } | |
static inline int AND_NOTA(int a, int b, int set_len, int balanced) { return min(neg3(a, set_len, balanced), b); } | |
static inline int B(int a, int b, int set_len, int balanced) { return b; } | |
static inline int XOR(int a, int b, int set_len, int balanced) { | |
/// x ^ y = x*!y + !x*y | |
int const x_ny = min(a, neg3(b, set_len, balanced)); | |
int const nx_y = min(neg3(a, set_len, balanced), b); | |
return max(x_ny, nx_y); | |
} | |
static inline int OR(int a, int b, int set_len, int balanced) { return max(a,b); } | |
static inline int NOR(int a, int b, int set_len, int balanced) { | |
/// !(a+b) = !a*!b | |
return neg3(max(a,b), set_len, balanced); | |
} | |
static inline int XNOR(int a, int b, int set_len, int balanced) { | |
/// x ~^ y = !x*!y + x*y | |
int const nx_ny = min(neg3(a, set_len, balanced), neg3(b, set_len, balanced)); | |
int const x_y = min(a, b); | |
return max(nx_ny, x_y); | |
} | |
static inline int NB(int a, int b, int set_len, int balanced) { return neg3(b, set_len, balanced); } | |
static inline int IMPLIESB(int a, int b, int set_len, int balanced) { return max(neg3(a, set_len, balanced), b); } | |
static inline int NA(int a, int b, int set_len, int balanced) { return neg3(a, set_len, balanced); } | |
static inline int IMPLIESA(int a, int b, int set_len, int balanced) { return max(a, neg3(b, set_len, balanced)); } | |
static inline int NAND(int a, int b, int set_len, int balanced) { return neg3(min(a,b), set_len, balanced); } | |
static inline int Truth(int a, int b, int set_len, int balanced) { return 1; } | |
void idx_to_set(size_t const size, int8_t vars[const restrict static size], size_t const setlen, int const set[const static setlen], size_t idx) { | |
for( size_t i = size - 1; i < size; i-- ) { | |
vars[i] = set[idx % setlen]; | |
idx /= setlen; | |
} | |
} | |
void print_truth_table(FILE *stream, size_t const num_vars, size_t const set_len, int const set[const static set_len], LogicFunc logic_func) { | |
/// for each variable, we need to print a power-of-2 set of operations. | |
/// 2 vars = truth table of 4 values. 3 vars = 8 values, etc. | |
int const is_balanced = set[0] < 0; | |
int8_t *vars = calloc(num_vars, sizeof *vars); | |
size_t const loops = ( size_t )( lround(pow(set_len, num_vars)) ); | |
for( size_t i=0; i < loops; i++ ) { | |
idx_to_set(num_vars, vars, set_len, set, i); | |
int logic_result = logic_func(vars[0], vars[1], set_len, is_balanced); | |
for( size_t j=0; j < (num_vars - 2); j++ ) { | |
logic_result = logic_func(vars[j+2], logic_result, set_len, is_balanced); | |
} | |
fprintf(stream, "%3zu -- ", i); | |
for( size_t j=0; j < num_vars; j++ ) { | |
fprintf(stream, "var%zu(%2i) | ", j+1, vars[j]); | |
} | |
fprintf(stream, "result: %2i\n", logic_result); | |
} | |
free(vars); | |
} | |
int main() { | |
FILE *stream = stdout; | |
enum { | |
MIN_VARS = 2, | |
MAX_VARS = 1 << 3, | |
}; | |
size_t num_vars = 0; | |
do { | |
printf("enter how many variables you'd like a truth table of (min: 2, max: %i):\n", MAX_VARS); | |
scanf(" %zu", &num_vars); | |
} while( num_vars < MIN_VARS ); | |
if( num_vars > MAX_VARS ) { | |
num_vars = MAX_VARS; | |
} | |
char const *logic_names[] = { | |
"FALSE", "AND", "A AND NOT B", "A", | |
"NOT A AND B","B","XOR","OR","NOR","XNOR","NOT B","A IMPLIES B", | |
"NOT A","B IMPLIES A","NAND","TRUE", | |
}; | |
LogicFunc *const logic_funcs[] = { | |
False, AND, AND_NOTB, A, AND_NOTA, | |
B, XOR, OR, NOR, XNOR, NB, IMPLIESB, NA, | |
IMPLIESA, NAND, Truth, | |
}; | |
int const binary_set[] = { 0, 1 }; | |
int const balanced_ternary_set[] = { -1, 0, 1 }; | |
int const ternary_set[] = { 0, 1, 2 }; | |
int const quaternary_set[] = { 0, 1, 2, 3 }; | |
#define ARR_LEN(a) (sizeof (a) / sizeof (a)[0]) | |
for( size_t i=0; i < ARR_LEN(logic_funcs); i++ ) { | |
fprintf(stream, "%s:::\n", logic_names[i]); | |
print_truth_table(stream, num_vars, ARR_LEN(quaternary_set), quaternary_set, logic_funcs[i]); | |
fputs("", stream); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment