RGJW3YTXML556YLAFHZSTEONWXRJ23PGW7Z6SKT3BV63ZEPWDTXAC
uint64_t value = solver_Algebra_parse(&a, input);
printf("'%s' =? ", input);
solver_Algebra_show(&a, value);
solver_Algebra_free(&a);
static void assert_is_true(struct solver_Algebra *a, const char *input) {
uint64_t expr = solver_Algebra_parse(a, input);
if(solver_Algebra_to_boolean(a, expr) != solver_Algebra_boolean(a, true)) {
printf("assert_is_true\n");
printf("input: %s\n", input);
printf("parsed: ");
solver_Algebra_show(a, expr);
fprintf(stderr, "failed\n");
exit(1);
}
static void test_parse(void) {
echo_test("2");
echo_test("2 + 2");
echo_test("2 + x");
}
static void assert_is_true(struct solver_Algebra *a, uint64_t expr) {
expr = solver_Algebra_simplify(a, expr);
if(!solver_Algebra_to_boolean(a, expr)) {
static void assert_is_false(struct solver_Algebra *a, const char *input) {
uint64_t expr = solver_Algebra_parse(a, input);
if(solver_Algebra_to_boolean(a, expr) != solver_Algebra_boolean(a, false)) {
printf("assert_is_false\n");
printf("input: %s\n", input);
printf("parsed: ");
static int qsort_term_compare(const void *lhs_, const void *rhs_, void *ud) {
return term_compare((struct solver_Algebra *)ud, *(uint64_t *)lhs_, *(uint64_t *)rhs_);
}
static bool sum_merge_single_term(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs, uint64_t *merged) {
if(is_number(lhs) && is_number(rhs)) {
*merged = number_add(a, lhs, rhs);
return true;
}
// x + x -> 2x
if(is_variable(lhs) && is_variable(rhs) && alias_str_same(unpack_variable(lhs), unpack_variable(rhs))) {
uint64_t product_values[2] = { pack_integer(2), lhs };
*merged = embed_product(a, 2, product_values);
return true;
}
return false;
}
if(count == 0) return pack_integer(0);
if(count == 1) return values[0];
if(count == 2) {
if(is_number(values[0]) && is_number(values[1])) {
return number_add(a, values[0], values[1]);
uint64_t merged;
if(count == 0) {
return pack_integer(0);
} else if(count == 1) {
return values[0];
} else if(count == 2) {
if(sum_merge_single_term(a, values[0], values[1], &merged)) {
return merged;
// x + x -> 2x
if(is_variable(values[0]) && values[0] == values[1]) {
uint64_t product_values[2] = { pack_integer(2), values[0] };
return embed_product(a, 2, product_values);
// break open any immediate child sums and merge
uint32_t total_count = 0;
for(uint32_t i = 0; i < count; i++) {
if(is_sum(values[i])) {
total_count += get_list_count(values[i]);
} else {
total_count++;
// 2x + x -> 3x
// if(is_product(values[0]) && get_count(a, values[0]) == 2 && is_number(get_index(a, values[0], 0)) && is_equal(get_index(a, values[0]
uint32_t new_count = 0;
uint64_t * new_values = alias_stack_allocation(sizeof(*new_values) * total_count, alignof(*new_values));
#define MERGE_INTO_NEW(TO_MERGE) do { \
uint32_t k; \
for(k = 0; k < new_count; k++) { \
if(sum_merge_single_term(a, new_values[k], TO_MERGE, &merged)) { \
new_values[k] = merged; \
break; \
} \
} \
if(k == new_count) { \
new_values[new_count++] = TO_MERGE; \
} \
} while(0)
// for each item
for(uint32_t i = 0; i < count; i++) {
if(is_sum(values[i])) {
uint32_t inner_count = get_list_count(values[i]);
for(uint32_t j = 0; j < inner_count; j++) {
uint64_t to_merge = get_index(a, values[i], j);
MERGE_INTO_NEW(to_merge);
}
} else {
MERGE_INTO_NEW(values[i]);
}
variable(O) ::= IDENTIFIER(I). { O = solver_Algebra_variable(extra.a, alias_str_format(NULL, "%.*s", I.string.end - I.string.start, I.string.start)); }
variable(O) ::= IDENTIFIER(I). { O = solver_Algebra_variable(extra.a, alias_str_clone_substring(NULL, I.string.start, I.string.end - I.string.start)); }
}
}
static int integer_integer_compare(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
// TODO big integer upgrade
return unpack_integer(rhs) - unpack_integer(lhs);
}
static int integer_compare(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
assert(is_number(rhs));
switch(get_tag(rhs)) {
case Tag_Integer:
return integer_integer_compare(a, lhs, rhs);
default:
return -1;
static bool equals__real_real(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
return unpack_real(lhs) == unpack_real(rhs);
}
static bool equals__real(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_Real:
return equals__real_real(a, lhs, rhs);
default:
return false;
}
}
static bool equals__variable_variable(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
return alias_str_same(unpack_variable(lhs), unpack_variable(rhs));
}
#define BINARY_EQUALS(TYPE, TAG, FN) \
static bool TYPE##_##TYPE##_equals(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) FN \
static bool TYPE##_equals(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) { \
switch(get_tag(rhs)) { \
case TAG: \
return TYPE##_##TYPE##_equals(a, lhs, rhs); \
default: \
return pack_undefined(); \
} \
static bool equals__variable(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_Variable:
return equals__variable_variable(a, lhs, rhs);
default:
return false;
}
}
static bool equals__boolean_boolean(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
return unpack_boolean(lhs) == unpack_boolean(rhs);
}
static bool equals__boolean(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_Boolean:
return equals__boolean_boolean(a, lhs, rhs);
default:
return false;
}
}
static bool equals__undefined_undefined(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
unpack_undefined(lhs);
unpack_undefined(rhs);
return true;
}
static bool equals__undefined(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_Undefined:
return equals__undefined_undefined(a, lhs, rhs);
default:
return false;
}
}
static bool equals__integer_integer(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
return unpack_integer(lhs) == unpack_integer(rhs);
}
static bool equals__integer(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_Integer:
return equals__integer_integer(a, lhs, rhs);
default:
return false;
}
}
static bool equals__big_integer_big_integer(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) { return false; }
static bool equals__big_integer(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_BigInteger:
return equals__big_integer_big_integer(a, lhs, rhs);
default:
return false;
}
}
static bool equals__fraction_fraction(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) { return false; }
static bool equals__fraction(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_Fraction:
return equals__fraction_fraction(a, lhs, rhs);
default:
return false;
}
}
static bool equals__power_power(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
return equals(a, get_car(a, lhs), get_car(a, rhs)) && equals(a, get_cdr(a, lhs), get_cdr(a, rhs));
}
static bool equals__power(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_Power:
return equals__power_power(a, lhs, rhs);
default:
return false;
}
}
static bool equals__sum_sum(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
uint32_t count = get_list_count(lhs);
if(count != get_list_count(rhs)) {
return false;
}
for(uint32_t i = 0; i < count; i++) {
if(!equals(a, get_index(a, lhs, i), get_index(a, rhs, i))) {
return false;
}
}
return true;
}
static bool equals__sum(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_Sum:
return equals__sum_sum(a, lhs, rhs);
default:
return false;
}
}
static bool equals__product_product(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
uint32_t count = get_list_count(lhs);
if(count != get_list_count(rhs)) {
return false;
}
for(uint32_t i = 0; i < count; i++) {
if(!equals(a, get_index(a, lhs, i), get_index(a, rhs, i))) {
return false;
}
}
return true;
#define BINARY_PAIR_EQUALS(TYPE, TAG) \
BINARY_EQUALS(TYPE, TAG, { \
return equals(a, get_car(a, lhs), get_car(a, rhs)) && \
equals(a, get_cdr(a, lhs), get_cdr(a, rhs)) ; \
})
static bool equals__product(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_Product:
return equals__product_product(a, lhs, rhs);
default:
return false;
}
}
#define BINARY_LIST_EQUALS(TYPE, TAG) \
BINARY_EQUALS(TYPE, TAG, { \
uint32_t count = get_count(a, lhs); \
if(count != get_count(a, rhs)) { \
return false; \
} \
for(uint32_t i = 0; i < count; i++) { \
if(!equals(a, get_index(a, lhs, i), get_index(a, rhs, i))) { \
return false; \
} \
} \
return true; \
})
static bool equals__equals(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_Equals:
return equals__equals_equals(a, lhs, rhs);
default:
return false;
}
}
BINARY_EQUALS(real, Tag_Real, { return unpack_real(lhs) == unpack_real(rhs); })
static bool equals__not_equals_not_equals(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
return equals(a, get_car(a, lhs), get_car(a, rhs)) && equals(a, get_cdr(a, lhs), get_cdr(a, rhs));
}
BINARY_EQUALS(variable, Tag_Variable, { return unpack_variable(lhs) == unpack_variable(rhs); })
BINARY_EQUALS(boolean, Tag_Boolean, { return unpack_boolean(lhs) == unpack_boolean(rhs); })
BINARY_EQUALS(undefined, Tag_Undefined, { unpack_undefined(); unpack_undefined(); return true; })
BINARY_EQUALS(integer, Tag_Integer, { return unpack_integer(lhs) == unpack_integer(rhs); })
BINARY_EQUALS(big_integer, Tag_BigInteger, {
// TODO
return false;
})
static bool equals__less_than_less_than(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
return equals(a, get_car(a, lhs), get_car(a, rhs)) && equals(a, get_cdr(a, lhs), get_cdr(a, rhs));
}
BINARY_EQUALS(fraction, Tag_Fraction, {
// TODO
return false;
})
static bool equals__less_than(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
switch(get_tag(rhs)) {
case Tag_LessThan:
return equals__less_than_less_than(a, lhs, rhs);
default:
return false;
}
}
BINARY_PAIR_EQUALS(power, Tag_Power)
BINARY_LIST_EQUALS(sum, Tag_Sum)
BINARY_LIST_EQUALS(product, Tag_Sum)
BINARY_PAIR_EQUALS(equals, Tag_Equals)
BINARY_PAIR_EQUALS(not_equals, Tag_NotEquals)
BINARY_PAIR_EQUALS(less_than, Tag_LessThan)
BINARY_PAIR_EQUALS(greater_than, Tag_GreaterThan)
static bool equals__greater_than_greater_than(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
return equals(a, get_car(a, lhs), get_car(a, rhs)) && equals(a, get_cdr(a, lhs), get_cdr(a, rhs));
}
alias_str alias_str_clone_substring(alias_MemoryCB *mcb, alias_str s, uint32_t length) {
uintmax_t l = strlen(s);
if(l > length) {
uint8_t * result = alias_memory_clone(mcb, s, length + 1, 1);
result[length] = 0;
return (alias_str)result;
} else {
return alias_str_clone(mcb, s);
}
}