Reputation: 1749
Is there a good general pattern for implementing truth tables?
I am re-working some legacy code (C++) and just realized that the function I am working with amounts to a truth table with 3 binary inputs and 8 possible outputs. Here is an example of two of the eight tests and corresponding outputs:
// - + +
if ( (prevdst5 < 0.0) && (dst5 > 0.0) && (nextdst5 > 0.0) ){
thawpct = (dst5 / (dst5 - prevdst5));
}
// - - +
if ( (prevdst5 < 0.0) && (dst5 < 0.0) && (nextdst5 > 0.0) ){
thawpct = (nextdst5 / (nextdst5 - dst5));
}
// other cases...
return thawpct;
Basically I am wondering if there is a cleaner, more maintainable/extensible* way to set this up.
*The codebase is an ecosystem model used in academia, so maintenance and extension amount to similar things depending on the perspective of the coder.
Upvotes: 9
Views: 2951
Reputation: 30351
int condition = ( prev >= 0 ? ( 1<<0 ) : 0 ) +
( cur >= 0 ? ( 1<<1 ) : 0 ) +
( next >= 0 ? ( 1<<2 ) : 0 );
switch (condition) {
case 0: // - - -
case 1: // + - -
case 2: // - + -
case 3: // + + -
case 4: // - - +
case 5: // + - +
case 6: // - + +
case 7: // + + +
}
Upvotes: 9
Reputation: 171453
An array is a table.
A sequence of boolean truth values is a binary number.
Arrays are indexed by number.
Sooooo .....
You could define a function for each calculation:
// - + + == 0 1 1 == 3
inline double f3(double prev, double curr, double next)
{
return curr / (curr - prev);
}
// - - + == 0 0 1 == 1
inline double f1(double prev, double curr, double next)
{
return next / (next - curr);
}
// ...
Then declare an array of function pointers:
typedef double (*func_type)(double, double, double);
func_type funcs[8] = {
f1, f2, // ...
};
Then index into the array using the boolean conditions as binary digits:
func_type f = funcs[ (int(prevdst5 < 0.0)<<2) | (int(dst5 < 0.0)<<1) | int(nextdst5 > 0.0) ];
thawpct = f(prevdst5, dst5, nextdst5);
- What if another input is added? (Then the number of tests would be 16, which in my view would be cumbersome to manage with the current pattern)
You double the size of the array and add f8
, f9
etc. if different calculations are needed, but you only add the new test once, in the array index:
func_type f = funcs[ (cond<<3) | (int(prevdst5 < 0.0)<<2) | (int(dst5 < 0.0)<<1) | int(nextdst5 > 0.0) ];
- What if several of the input combos should map to the same output?
Store the same function pointer at several elements of the array:
func_type funcs[8] = {
f1, f2, f3, f1, f1, // ...
};
Upvotes: 4
Reputation: 28802
You could keep a mapping of 3 (or n
) values to the appropriate function that needs to be performed. Then loop up the function in this map based on the true
/false
state of the conditons and execute that.
This way you would have an 3 dimentional map (with size 2 in all dimentions)
Upvotes: 0