#include <inttypes.h>
#define PRECEDENCE_NUMBER 1000
#define PRECEDENCE_SUM 110
#define PRECEDENCE_PRODUCT 120
#define PRECEDENCE_POWER 130
static int precedence(uint64_t bits) {
switch(get_tag(bits)) {
case Tag_Real:
case Tag_Variable:
case Tag_SmallInt:
case Tag_LargeInt:
case Tag_Fraction:
return PRECEDENCE_NUMBER;
case Tag_Power:
return PRECEDENCE_POWER;
case Tag_Sum:
return PRECEDENCE_SUM;
case Tag_Product:
return PRECEDENCE_PRODUCT;
default:
return 0;
}
}
static void show(struct solver_Algebra *a, uint64_t bits);
static void show_real(struct solver_Algebra *a, uint64_t bits) {
printf("%f", unpack_real(bits));
}
static void show_variable(struct solver_Algebra *a, uint64_t bits) {
printf("%s", unpack_variable(bits));
}
static void show_boolean(struct solver_Algebra *a, uint64_t bits) {
bool v = unpack_boolean(bits);
printf("%s", v ? "true" : "false");
}
static void show_undefined(struct solver_Algebra *a, uint64_t bits) {
unpack_undefined(bits);
printf("undefined");
}
static void show__smallint(struct solver_Algebra *a, uint64_t bits) {
printf(PRId64, unpack_smallint(bits));
}
static void show__largeint(struct solver_Algebra *a, uint64_t bits) {
// TODO
}
static void show__fraction(struct solver_Algebra *a, uint64_t bits) {
uint32_t index = unpack_fraction(bits);
uint64_t numerator = a->values.data[index + 0];
uint64_t denominator = a->values.data[index + 1];
show(a, numerator);
printf("/");
show(a, denominator);
}
#define SURROUND(C, STMT) \
do { \
if(C) { \
printf("("); \
} \
STMT; \
if(C) { \
printf(")"); \
} \
} while(0)
static void show__power(struct solver_Algebra *a, uint64_t bits) {
uint32_t index = unpack_power(bits);
uint64_t base = a->values.data[index + 0];
uint64_t exponent = a->values.data[index + 1];
bool lhp = precedence(base) < PRECEDENCE_POWER;
bool rhp = precedence(exponent) < PRECEDENCE_POWER;
SURROUND(lhp, show(a, base));
printf("^");
SURROUND(rhp, show(a, exponent));
}
static void show__sum(struct solver_Algebra *a, uint64_t bits) {
struct EncodedList sum = unpack_sum(bits);
for(uint32_t i = 0; i < sum.count; i++) {
uint64_t operand = a->values.data[sum.index + i];
if(i > 0) {
printf(" + ");
}
bool p = precedence(operand) < PRECEDENCE_SUM;
SURROUND(p, show(a, operand));
}
}
static void show__product(struct solver_Algebra *a, uint64_t bits) {
struct EncodedList product = unpack_product(bits);
bool scale = product.count == 2 && is_number(a->values.data[product.index + 0]);
for(uint32_t i = 0; i < product.count; i++) {
uint64_t operand = a->values.data[product.index + i];
bool p = precedence(operand) < PRECEDENCE_PRODUCT;
if(!scale && i > 0) {
printf(" * ");
}
SURROUND(p, show(a, operand));
}
}
#undef SURROUND
static void show__equals(struct solver_Algebra *a, uint64_t bits) {
uint32_t index = unpack_equals(bits);
uint64_t lhs = a->values.data[index + 0];
uint64_t rhs = a->values.data[index + 1];
show(a, lhs);
printf(" == ");
show(a, rhs);
}
static void show__not_equals(struct solver_Algebra *a, uint64_t bits) {
uint32_t index = unpack_not_equals(bits);
uint64_t lhs = a->values.data[index + 0];
uint64_t rhs = a->values.data[index + 1];
show(a, lhs);
printf(" != ");
show(a, rhs);
}
static void show__less_than(struct solver_Algebra *a, uint64_t bits) {
uint32_t index = unpack_less_than(bits);
uint64_t lhs = a->values.data[index + 0];
uint64_t rhs = a->values.data[index + 1];
show(a, lhs);
printf(" < ");
show(a, rhs);
}
static void show__greater_than(struct solver_Algebra *a, uint64_t bits) {
uint32_t index = unpack_greater_than(bits);
uint64_t lhs = a->values.data[index + 0];
uint64_t rhs = a->values.data[index + 1];
show(a, lhs);
printf(" > ");
show(a, rhs);
}
static void show(struct solver_Algebra *a, uint64_t bits) {
switch(get_tag(bits)) {
case Tag_Real:
show_real(a, bits);
break;
case Tag_Variable:
show_variable(a, bits);
break;
case Tag_Boolean:
show_boolean(a, bits);
break;
case Tag_Undefined:
show_undefined(a, bits);
break;
case Tag_SmallInt:
show__smallint(a, bits);
break;
case Tag_LargeInt:
show__largeint(a, bits);
break;
case Tag_Fraction:
show__fraction(a, bits);
break;
case Tag_Power:
show__power(a, bits);
break;
case Tag_Sum:
show__sum(a, bits);
break;
case Tag_Product:
show__product(a, bits);
break;
case Tag_Equals:
show__equals(a, bits);
break;
case Tag_NotEquals:
show__not_equals(a, bits);
break;
case Tag_LessThan:
show__less_than(a, bits);
break;
case Tag_GreaterThan:
show__greater_than(a, bits);
break;
case Tag_Invalid:
break;
}
}
void solver_Algebra_show(struct solver_Algebra *a, uint64_t bits) {
show(a, bits);
printf("\n");
}