BJNMXUGSKSQWBHVMRW47WAQ7ZKJ7VKM3WQ3ITYKFU3COU6ILLFOQC #define TABULA_IMPLEMENTATION 1#include <tabula.h>
// 0x7 f f 8 | 7// <01111111 1111 12-bit nan header> <1-bit silent flag, 0 on most cpus> <3-bit tag> <48-bit payload>// 000 - variable - pointer to variable name// 001 - atom// 010 - integer - 32-bit integer// 011 - integer - pointer to big integer implementation// 100 - pair - <3-bit type> <21-bit unused> <24-bit index to first>// 000 - fraction// 001 - power// 010 - unused// 011 - unused// 100 - equals// 101 - not equals// 110 - less than// 111 - greater than// 101 - list - <1-bit type> <23-bit count> <24-bit index to first>// 0 - sum// 1 - product// 110 - unused// 111 - unused#define NAN_MASK 0xFFF0000000000000ull#define NAN_BITS 0x7FF0000000000000ull#define QUEIT_BITS 0x7FF0000000000000ull#define SIGNALING_BITS 0x7FF8000000000000ull#define TAG_MASK 0xFFF7000000000000ull#define TAG_VARIABLE_BITS 0x7FF0000000000000ull#define TAG_ATOM_BITS 0x7FF1000000000000ull#define TAG_INTEGER_BITS 0x7FF2000000000000ull#define TAG_BIGINT_BITS 0x7FF3000000000000ull#define TAG_PAIR_BITS 0x7FF4000000000000ull#define TAG_LIST_BITS 0x7FF5000000000000ull#define TAG_UNUSED1_BITS 0x7FF6000000000000ull#define TAG_UNUSED2_BITS 0x7FF7000000000000ull#define PAIR_MASK 0xFFF7e00000000000ull#define PAIR_FRACTION_BITS 0x7FF4000000000000ull#define PAIR_POWER_BITS 0x7FF4200000000000ull#define PAIR_UNUSED1_BITS 0x7FF4400000000000ull#define PAIR_UNUSED2_BITS 0x7FF4600000000000ull#define PAIR_EQUAL_BITS 0x7FF4800000000000ull#define PAIR_NOT_EQUAL_BITS 0x7FF4a00000000000ull#define PAIR_LESS_THAN_BITS 0x7FF4c00000000000ull#define PAIR_GREATER_THAN_BITS 0x7FF4e00000000000ull#define LIST_MASK 0xFFF7800000000000ull#define LIST_SUM_BITS 0x7FF5000000000000ull#define LIST_PRODUCT_BITS 0x7FF5800000000000ull#define PAYLOAD_MASK 0x0000FFFFFFFFFFFFull#define PAIR_INDEX_MASK 0x0000000000FFFFFFull#define LIST_COUNT_MASK 0x00007FFFFF000000ull#define LIST_INDEX_MASK 0x0000000000FFFFFFullstruct Unpacked {enum {Unpacked_Real,Unpacked_Variable,Unpacked_Boolean, // atom 0 and 1Unpacked_Undefined, // atom 2Unpacked_Integer,Unpacked_BigInteger,Unpacked_Fraction,Unpacked_Power,Unpacked_Sum,Unpacked_Product,Unpacked_Equals,Unpacked_NotEquals,Unpacked_LessThan,Unpacked_GreaterThan,Unpacked_Invalid} tag;union {double real;const char *variable;bool boolean;int64_t integer;void * big_integer;struct {uint32_t index;} pair, fraction, power, equals, not_equals, less_than, greater_than;struct {uint32_t count;uint32_t index;} list, sum, product;};};static inline uint64_t pack_real(double real) {union {uint64_t u;double d;} _;_.d = real;return _.u;}static inline uint64_t pack_variable(const char *name) {return TAG_VARIABLE_BITS | ((uint64_t)name & PAYLOAD_MASK);}static inline uint64_t pack_boolean(bool value) {return TAG_ATOM_BITS | !!value; // assumes ! returns either 0 or 1}static inline uint64_t pack_undefined(void) {return TAG_ATOM_BITS | 2;}static inline uint64_t pack_integer(int32_t integer) {union {uint64_t u;int32_t i[2];} _;_.i[1] = integer;return TAG_INTEGER_BITS | (_.u & PAYLOAD_MASK);}static inline uint64_t pack_big_integer(void * ptr) {return TAG_BIGINT_BITS | ((uint64_t)ptr & PAYLOAD_MASK);}static inline uint64_t pack_fraction(uint32_t index) {return PAIR_FRACTION_BITS | index;}static inline uint64_t pack_power(uint32_t index) {return PAIR_POWER_BITS | index;}static inline uint64_t pack_sum(uint32_t count, uint32_t index) {return LIST_SUM_BITS | ((uint64_t)count << 24) | index;}static inline uint64_t pack_product(uint32_t count, uint32_t index) {return LIST_PRODUCT_BITS | ((uint64_t)count << 24) | index;}static inline uint64_t pack_equals(uint32_t index) {return PAIR_EQUAL_BITS | index;}static inline uint64_t pack_not_equals(uint32_t index) {return PAIR_NOT_EQUAL_BITS | index;}static inline uint64_t pack_less_than(uint32_t index) {return PAIR_LESS_THAN_BITS | index;}static inline uint64_t pack_greater_than(uint32_t index) {return PAIR_GREATER_THAN_BITS | index;}static inline uint64_t pack(struct Unpacked unpacked) {switch(unpacked.tag) {case Unpacked_Real:return pack_real(unpacked.real);case Unpacked_Variable:return pack_variable(unpacked.variable);case Unpacked_Boolean:return pack_boolean(unpacked.boolean);case Unpacked_Undefined:return pack_undefined();case Unpacked_Integer:return pack_integer(unpacked.integer);case Unpacked_BigInteger:return pack_big_integer(unpacked.big_integer);case Unpacked_Fraction:return pack_fraction(unpacked.fraction.index);case Unpacked_Power:return pack_power(unpacked.power.index);case Unpacked_Sum:return pack_sum(unpacked.sum.count, unpacked.sum.index);case Unpacked_Product:return pack_product(unpacked.product.count, unpacked.product.index);case Unpacked_Equals:return pack_equals(unpacked.equals.index);case Unpacked_NotEquals:return pack_not_equals(unpacked.not_equals.index);case Unpacked_LessThan:return pack_not_equals(unpacked.less_than.index);case Unpacked_GreaterThan:return pack_not_equals(unpacked.greater_than.index);case Unpacked_Invalid:return SIGNALING_BITS;}}static inline bool is_real(uint64_t bits) {return (bits & NAN_MASK) != NAN_BITS;}static inline bool is_variable(uint64_t bits) {return (bits & TAG_MASK) == TAG_VARIABLE_BITS;}static inline bool is_boolean(uint64_t bits) {return (bits & TAG_MASK) == TAG_ATOM_BITS && (bits & (PAYLOAD_MASK ^ 1)) == 0;}static inline bool is_undefined(uint64_t bits) {return bits == TAG_ATOM_BITS | 2;}static inline bool is_integer(uint64_t bits) {return (bits & TAG_MASK) == TAG_INTEGER_BITS;}static inline bool is_big_integer(uint64_t bits) {return (bits & TAG_MASK) == TAG_BIGINT_BITS;}static inline bool is_fraction(uint64_t bits) {return (bits & PAIR_MASK) == PAIR_FRACTION_BITS;}static inline bool is_power(uint64_t bits) {return (bits & PAIR_MASK) == PAIR_POWER_BITS;}static inline bool is_sum(uint64_t bits) {return (bits & LIST_MASK) == LIST_SUM_BITS;}static inline bool is_product(uint64_t bits) {return (bits & LIST_MASK) == LIST_PRODUCT_BITS;}static inline bool is_equals(uint64_t bits) {return (bits & PAIR_MASK) == PAIR_EQUAL_BITS;}static inline bool is_not_equals(uint64_t bits) {return (bits & PAIR_MASK) == PAIR_NOT_EQUAL_BITS;}static inline bool is_less_than(uint64_t bits) {return (bits & PAIR_MASK) == PAIR_LESS_THAN_BITS;}static inline bool is_greater_than(uint64_t bits) {return (bits & PAIR_MASK) == PAIR_GREATER_THAN_BITS;}static inline double unpack_real(uint64_t bits) {union {uint64_t u;double d;} _;assert(is_real(bits));_.u = bits;return _.d;}static inline const char * unpack_variable(uint64_t bits) {assert(is_variable(bits));return (const char *)(bits & PAYLOAD_MASK);}static inline bool unpack_boolean(uint64_t bits) {assert(is_boolean(bits));return !!(bits & 1);}static inline void unpack_undefined(uint64_t bits) {assert(is_undefined(bits));}static inline int32_t unpack_integer(uint64_t bits) {union {uint64_t u;int32_t i[2];} _;assert(is_integer(bits));_.u = bits & PAYLOAD_MASK;return _.i[1];}static inline void * unpack_big_integer(uint64_t bits) {assert(is_big_integer(bits));return (void *)(bits & PAYLOAD_MASK);}static inline uint32_t unpack_fraction(uint64_t bits) {assert(is_fraction(bits));return bits & PAIR_INDEX_MASK;}static inline uint32_t unpack_power(uint64_t bits) {assert(is_power(bits));return bits & PAIR_INDEX_MASK;}static inline void unpack_sum(uint64_t bits, uint32_t *count, uint32_t *index) {assert(is_sum(bits));*count = (bits & LIST_COUNT_MASK) >> 24;*index = bits & LIST_INDEX_MASK;}static inline void unpack_product(uint64_t bits, uint32_t *count, uint32_t *index) {assert(is_product(bits));*count = (bits & LIST_COUNT_MASK) >> 24;*index = bits & LIST_INDEX_MASK;}static inline uint32_t unpack_equals(uint64_t bits) {assert(is_equals(bits));return bits & PAIR_INDEX_MASK;}static inline uint32_t unpack_not_equals(uint64_t bits) {assert(is_not_equals(bits));return bits & PAIR_INDEX_MASK;}static inline uint32_t unpack_less_than(uint64_t bits) {assert(is_less_than(bits));return bits & PAIR_INDEX_MASK;}static inline uint32_t unpack_greater_than(uint64_t bits) {assert(is_greater_than(bits));return bits & PAIR_INDEX_MASK;}static int unpack_tag(uint64_t bits) {if(is_real(bits)) {return Unpacked_Real;} else if(is_variable(bits)) {return Unpacked_Variable;} else if(is_boolean(bits)) {return Unpacked_Boolean;} else if(is_undefined(bits)) {return Unpacked_Undefined;} else if(is_integer(bits)) {return Unpacked_Integer;} else if(is_big_integer(bits)) {return Unpacked_BigInteger;} else if(is_fraction(bits)) {return Unpacked_Fraction;} else if(is_power(bits)) {return Unpacked_Power;} else if(is_equals(bits)) {return Unpacked_Equals;} else if(is_not_equals(bits)) {return Unpacked_NotEquals;} else if(is_less_than(bits)) {return Unpacked_LessThan;} else if(is_greater_than(bits)) {return Unpacked_GreaterThan;} else if(is_sum(bits)) {return Unpacked_Sum;} else if(is_product(bits)) {return Unpacked_Product;} else {return Unpacked_Invalid;}}static inline struct Unpacked unpack(uint64_t bits) {struct Unpacked result;switch(result.tag = unpack_tag(bits)) {case Unpacked_Real:result.real = unpack_real(bits);break;case Unpacked_Variable:result.variable = unpack_variable(bits);break;case Unpacked_Boolean:result.boolean = unpack_boolean(bits);break;case Unpacked_Undefined:unpack_undefined(bits);break;case Unpacked_Integer:result.integer = unpack_integer(bits);break;case Unpacked_BigInteger:result.big_integer = unpack_big_integer(bits);break;case Unpacked_Fraction:result.fraction.index = (bits & PAIR_INDEX_MASK);break;case Unpacked_Power:result.power.index = (bits & PAIR_INDEX_MASK);break;case Unpacked_Sum:unpack_sum(bits, &result.sum.count, &result.sum.index);break;case Unpacked_Product:unpack_product(bits, &result.product.count, &result.product.index);break;case Unpacked_Equals:result.equals.index = unpack_equals(bits);break;case Unpacked_NotEquals:result.not_equals.index = unpack_not_equals(bits);break;case Unpacked_LessThan:result.less_than.index = unpack_less_than(bits);break;case Unpacked_GreaterThan:result.greater_than.index = unpack_greater_than(bits);break;case Unpacked_Invalid:break;}return result;}
// --------------------------------------------------------------------------------------------------------------------// numericsstatic inline bool is_number(uint64_t bits) {return is_real(bits) || is_integer(bits) || is_big_integer(bits) || is_fraction(bits);}
#include "algebra-encoding.inc"
static inline bool is_exact(uint64_t bits) {return is_integer(bits) || is_big_integer(bits) || is_fraction(bits);}static inline bool is_inexact(uint64_t bits) {return is_real(bits);}// --------------------------------------------------------------------------------------------------------------------// lifetime
// --------------------------------------------------------------------------------------------------------------------// creation entry points , most go through simplification before being committed to memorystatic uint64_t simplify_real(struct solver_Algebra *a, double real);static uint64_t simplify_fraction(struct solver_Algebra *a, uint64_t numerator, uint64_t denominator);uint64_t solver_Algebra_boolean(struct solver_Algebra *a, bool value) {return pack_boolean(value);}uint64_t solver_Algebra_integer(struct solver_Algebra *a, int64_t value) {return pack_integer(value);}uint64_t solver_Algebra_fraction(struct solver_Algebra *a, int64_t numerator, int64_t denominator) {return simplify_fraction(numerator, denominator);}uint64_t solver_Algebra_real(struct solver_Algebra *a, double value) {return simplify_real(a, real);
uint64_t solver_Algebra_undefined(struct solver_Algebra *a) {return pack_undefined();
}uint64_t solver_Algebra_sum(struct solver_Algebra *a, uint32_t num_operands, const uint64_t *operands) {uint32_t index = embed(a, num_operands, operands);return pack_sum(num_operands, index);}uint64_t solver_Algebra_product(struct solver_Algebra *a, uint32_t num_operands, const uint64_t *operands) {uint32_t index = embed(a, num_operands, operands);return pack_product(num_operands, index);}uint64_t solver_Algebra_add(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {uint64_t operands[2] = {lhs, rhs};return solver_Algebra_sum(a, 2, operands);}uint64_t solver_Algebra_multiply(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {uint64_t operands[2] = {lhs, rhs};return solver_Algebra_product(a, 2, operands);}uint64_t solver_Algebra_negate(struct solver_Algebra *a, uint64_t expr) {if(is_number(expr)) {return number_negate(a, expr);}return solver_Algebra_multiply(a, solver_Algebra_integer(a, -1), expr);}uint64_t solver_Algebra_subtract(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {return solver_Algebra_add(a, lhs, solver_Algebra_negate(a, rhs));}uint64_t solver_Algebra_divide(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {return solver_Algebra_multiply(a, lhs, solver_Algebra_power(a, rhs, solver_Algebra_integer(a, -1)));}uint64_t solver_Algebra_power(struct solver_Algebra *a, uint64_t base, uint64_t exponent) {uint64_t values[2];values[0] = base;values[1] = exponent;uint32_t index = embed(a, 2, values);return pack_power(index);}uint64_t solver_Algebra_equals(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {uint64_t values[2];values[0] = lhs;values[1] = rhs;uint32_t index = embed(a, 2, values);return pack_equals(index);}uint64_t solver_Algebra_not_equals(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {uint64_t values[2];values[0] = lhs;values[1] = rhs;uint32_t index = embed(a, 2, values);return pack_not_equals(index);}uint64_t solver_Algebra_less_than(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {uint64_t values[2];values[0] = lhs;values[1] = rhs;uint32_t index = embed(a, 2, values);return pack_less_than(index);}uint64_t solver_Algebra_greater_than(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {uint64_t values[2];values[0] = lhs;values[1] = rhs;uint32_t index = embed(a, 2, values);return pack_greater_than(index);}// --------------------------------------------------------------------------------------------------------------------// solver_Algebra_show#define PRECEDENCE_NUMBER 1000#define PRECEDENCE_SUM 110#define PRECEDENCE_PRODUCT 120#define PRECEDENCE_POWER 130static int precedence(uint64_t bits) {struct Unpacked unpacked = unpack(bits);switch(unpacked.tag) {case Unpacked_Real:case Unpacked_Variable:case Unpacked_Integer:case Unpacked_BigInteger:case Unpacked_Fraction:return PRECEDENCE_NUMBER;case Unpacked_Power:return PRECEDENCE_POWER;case Unpacked_Sum:return PRECEDENCE_SUM;case Unpacked_Product:return PRECEDENCE_PRODUCT;default:return 0;}}static void show(struct solver_Algebra *a, uint64_t bits, bool parens);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_integer(struct solver_Algebra *a, uint64_t bits) {printf("%lu", unpack_integer(bits));}static void show_big_integer(struct solver_Algebra *a, uint64_t bits) {printf("%p", unpack_big_integer(bits));}static void show_fraction(struct solver_Algebra *a, uint64_t bits) {uint32_t index = unpack_fraction(bits);uint64_t car = a->values.data[index + 0];uint64_t cdr = a->values.data[index + 1];show(a, car, false);printf("/");show(a, cdr, false);}static void show_power(struct solver_Algebra *a, uint64_t bits) {uint32_t index = unpack_power(bits);uint64_t car = a->values.data[index + 0];uint64_t cdr = a->values.data[index + 1];show(a, car, precedence(car) < PRECEDENCE_POWER);printf("/");show(a, cdr, precedence(cdr) < PRECEDENCE_POWER);}static void show_sum(struct solver_Algebra *a, uint64_t bits) {uint32_t count;uint32_t index;unpack_sum(bits, &count, &index);for(uint32_t i = 0; i < count; i++) {uint64_t operand = a->values.data[index + i];if(i > 0) {printf(" + ");}show(a, operand, precedence(operand) < PRECEDENCE_SUM);}}static void show_product(struct solver_Algebra *a, uint64_t bits) {uint32_t count;uint32_t index;unpack_sum(bits, &count, &index);for(uint32_t i = 0; i < count; i++) {uint64_t operand = a->values.data[index + i];show(a, operand, precedence(operand) < PRECEDENCE_PRODUCT);if(i > 0) {printf(" * ");}}}static void show_equals(struct solver_Algebra *a, uint64_t bits) {uint32_t index = unpack_equals(bits);uint64_t car = a->values.data[index + 0];uint64_t cdr = a->values.data[index + 1];show(a, car, false);printf(" == ");show(a, cdr, false);}static void show_not_equals(struct solver_Algebra *a, uint64_t bits) {uint32_t index = unpack_not_equals(bits);uint64_t car = a->values.data[index + 0];uint64_t cdr = a->values.data[index + 1];show(a, car, false);printf(" != ");show(a, cdr, false);}static void show_less_than(struct solver_Algebra *a, uint64_t bits) {uint32_t index = unpack_less_than(bits);uint64_t car = a->values.data[index + 0];uint64_t cdr = a->values.data[index + 1];show(a, car, false);printf(" < ");show(a, cdr, false);}static void show_greater_than(struct solver_Algebra *a, uint64_t bits) {uint32_t index = unpack_greater_than(bits);uint64_t car = a->values.data[index + 0];uint64_t cdr = a->values.data[index + 1];show(a, car, false);printf(" > ");show(a, cdr, false);}static void show(struct solver_Algebra *a, uint64_t bits, bool parens) {if(parens) printf("(");switch(unpack_tag(bits)) {case Unpacked_Real:show_real(a, bits);break;case Unpacked_Variable:show_variable(a, bits);break;case Unpacked_Boolean:show_boolean(a, bits);break;case Unpacked_Undefined:show_undefined(a, bits);break;case Unpacked_Integer:show_integer(a, bits);break;case Unpacked_BigInteger:show_big_integer(a, bits);break;case Unpacked_Fraction:show_fraction(a, bits);break;case Unpacked_Power:show_power(a, bits);break;case Unpacked_Sum:show_sum(a, bits);break;case Unpacked_Product:show_product(a, bits);break;case Unpacked_Equals:show_equals(a, bits);break;case Unpacked_NotEquals:show_not_equals(a, bits);break;case Unpacked_LessThan:show_less_than(a, bits);break;case Unpacked_GreaterThan:show_greater_than(a, bits);break;case Unpacked_Invalid:break;}if(parens) printf(")");}void solver_Algebra_show(struct solver_Algebra *a, uint64_t bits) {show(a, bits, false);printf("\n");}// --------------------------------------------------------------------------------------------------------------------// boolean_notstatic uint64_t boolean_not(struct solver_Algebra *a, uint64_t expr_) {if(expr_ == TAG_ATOM_BITS | 0) return TAG_ATOM_BITS | 1;if(expr_ == TAG_ATOM_BITS | 1) return TAG_ATOM_BITS | 0;return TAG_ATOM_BITS | 2;}// --------------------------------------------------------------------------------------------------------------------// == !=static uint64_t equals(struct solver_Algebra *a, uint64_t lhs_, uint64_t rhs_);static uint64_t integer_integer_equals(struct solver_Algebra *a, uint64_t lhs_, uint64_t rhs_) {int64_t lhs = unpack_integer(lhs_);int64_t rhs = unpack_integer(rhs_);return pack_boolean(lhs == rhs);}// TODOstatic uint64_t equals(struct solver_Algebra *a, uint64_t lhs_, uint64_t rhs_) {int lhs_tag = unpack_tag(lhs_);int rhs_tag = unpack_tag(rhs_);if(lhs_tag == Unpacked_Integer && rhs_tag == Unpacked_Integer) {return integer_integer_equals(a, lhs_, rhs_);}if(lhs_tag != rhs_tag) {return pack_boolean(false);}return pack_undefined();}static uint64_t not_equals(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {return boolean_not(a, equals(lhs, rhs));}// --------------------------------------------------------------------------------------------------------------------// < >static uint64_t integer_integer_less_than(struct solver_Algebra *a, uint64_t lhs_, uint64_t rhs_) {int64_t lhs = unpack_integer(lhs_);int64_t rhs = unpack_integer(rhs_);return pack_boolean(lhs < rhs);}// TODOstatic uint64_t less_than(struct solver_Algebra *a, uint64_t lhs_, uint64_t rhs_) {int lhs_tag = unpack_tag(lhs_);int rhs_tag = unpack_tag(rhs_);if(lhs_tag == Unpacked_Integer && rhs_tag == Unpacked_Integer) {return integer_integer_less_than(a, lhs_, rhs_);}return pack_undefined();}static uint64_t greater_than(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {return boolean_not(a, less_than(lhs, rhs));
// --------------------------------------------------------------------------------------------------------------------// solver_Algebra_to_booleanuint64_t solver_Algebra_to_boolean(struct solver_Algebra *a, uint64_t expr_) {struct Unpacked expr = unpack(expr_);if(expr.tag == Unpacked_Boolean) {return expr_;}if(expr.tag == Unpacked_Equals || expr.tag == Unpacked_NotEquals || expr.tag == Unpacked_LessThan || expr.tag == Unpacked_GreaterThan) {uint64_t car, cdr;car = a->values.data[expr.pair.index + 0];cdr = a->values.data[expr.pair.index + 1];return expr.tag == Unpacked_Equals ? equals(a, car, cdr) :expr.tag == Unpacked_NotEquals ? not_equals(a, car, cdr) :expr.tag == Unpacked_LessThan ? less_than(a, car, cdr) :expr.tag == Unpacked_GreaterThan ? greater_than(a, car, cdr) :pack_undefined() ;} else {return pack_undefined();}}// --------------------------------------------------------------------------------------------------------------------// solver_Algebra_simplify// these actually create values into the algebrastatic uint64_t simplify(struct solver_Algebra *a, uint64_t expr);static uint32_t embed(struct solver_Algebra *a, uint32_t count, const uint64_t *values) {
static uint32_t embed_values(struct solver_Algebra *a, uint32_t count, const uint64_t *values) {
}static uint64_t simplify_real(struct solver_Algebra *a, double real) {if(real == floor(real)) return pack_integer((int64_t)real);return pack_real(real);}static uint64_t simplify_big_integer(struct solver_Algebra *a, void * big_integer) {return pack_big_integer(big_integer);}static uint64_t simplify_fraction(struct solver_Algebra *a, uint64_t numerator, uint64_t denominator) {uint64_t values[2];values[0] = numberator;values[1] = denominator;uint32_t index = embed(a, 2, values);return pack_fraction(index);}static uint64_t simplify_power(struct solver_Algebra *a, uint64_t base, uint64_t exponent) {uint64_t values[2];values[0] = simplify(a, base);values[1] = simplify(a, exponent);if(is_number(values[0]) && is_number(values[1])) {return number_pow(values[0], values[1]);}uint32_t index = embed(a, 2, values);return pack_fraction(index);}static uint64_t simplify_sum(struct solver_Algebra *a, uint32_t num_operands, const uint64_t * operands) {struct {uint32_t num_operands;const uint64_t * operands;} stack[3], *top = stack + 3;if(num_operands == 0) {return pack_integer(a, 0);}if(num_operands == 1) {return operands[0];}if(num_operands == 2) {if(is_number(operands[0]) && is_number(operands[1])) {return number_add(a, operands[0], operands[1]);}if(is_sum(operands[0])) || is_sum(operands[1])) {--top;if(is_sum(operands[0])) {uint32_t index;unpack_sum(operands[0], &top->num_operands, &index);top->operands = a->values.data + index;} else {top->num_operands = 1;top->operands = &operands[0];}--top;if(is_sum(operands[1])) {uint32_t index;unpack_sum(operands[1], &top->num_operands, &index);top->operands = a->values.data + index;} else {top->num_operands = 1;top->operands = &operands[1];}}}}static uint64_t simplify(struct solver_Algebra *a, uint64_t expr) {struct Unpacked unpacked = unpack(expr);switch(unpacked.tag) {case Unpacked_Real:return simplify_real(a, unpacked.real);case Unpacked_Variable:return expr;case Unpacked_Boolean:return expr;case Unpacked_Undefined:return expr;case Unpacked_Integer:return expr;case Unpacked_BigInteger:return simplify_big_integer(a, unpacked.big_integer);case Unpacked_Fraction:return simplify_fraction(a, a->values.data[unpacked.fraction.index + 0], a->values.data[unpacked.fraction.index + 1]);case Unpacked_Power:return simplify_power(a, a->values.data[unpacked.power.index + 0], a->values.data[unpacked.power.index + 1]);case Unpacked_Sum:return simplify_sum(a, unpacked.sum.count, a->values.data + unpacked.sum.index);case Unpacked_Product:return simplify_product(a, unpacked.sum.count, a->values.data + unpacked.sum.index);case Unpacked_Equals:return simplify_equals(a, a->values.data[unpacked.power.index + 0], a->values.data[unpacked.power.index + 1]);case Unpacked_NotEquals:return simplify_not_equals(a, a->values.data[unpacked.power.index + 0], a->values.data[unpacked.power.index + 1]);case Unpacked_LessThan:return simplify_less_than(a, a->values.data[unpacked.power.index + 0], a->values.data[unpacked.power.index + 1]);case Unpacked_GreaterThan:return simplify_greater_than(a, a->values.data[unpacked.power.index + 0], a->values.data[unpacked.power.index + 1]);case Unpacked_Invalid:break;}}uint64_t solver_Algebra_simplify(struct solver_Algebra *a, uint64_t expr) {return simplify(a, expr);}#if 0// -- numeratordouble solver_Algebra_numerator(struct solver_Algebra *a, double expr) {uint64_t payload;switch(_decode(expr, &payload)) {case FRACTION:return first(a, expr);default:return expr;}}// -- denominatordouble solver_Algebra_denominator(struct solver_Algebra *a, double expr) {uint64_t payload;switch(_decode(expr, &payload)) {case FRACTION:return second(a, expr);default:return one(a);}}// -- simplifystatic double _simplify_power(struct solver_Algebra *a, double base, double exponent) {base = solver_Algebra_simplify(base);exponent = solver_Algebra_simplify(exponent);if(is_integer(base, 0)) return integer(0);if(is_integer(base, 1)) return integer(1);if(is_integer(exponent, 0)) return integer(1);if(is_integer(exponent, 1)) return base;uint64_t base_payload;uint64_t exponent_payload;int base_tag = _decode(base, &base_payload);int exponent_tag = _decode(exponent, &exponent_payload);if(base_tag == INTEGER) {if(exponent_tag == INTEGER) {} else if(exponent_tag == BIG_INTEGER) {} else if(exponent_tag == FRACTION) {} else if(exponent_tag == REAL) {}} else if(base_tag == BIG_INTEGER) {if(exponent_tag == INTEGER) {} else if(exponent_tag == BIG_INTEGER) {} else if(exponent_tag == FRACTION) {} else if(exponent_tag == REAL) {}} else if(base_tag == FRACTION) {if(exponent_tag == INTEGER) {} else if(exponent_tag == BIG_INTEGER) {} else if(exponent_tag == FRACTION) {} else if(exponent_tag == REAL) {}} else if(base_tag == REAL) {if(exponent_tag == INTEGER) {} else if(exponent_tag == BIG_INTEGER) {} else if(exponent_tag == FRACTION) {} else if(exponent_tag == REAL) {return pow(base, exponent);}}return solver_Algebra_power(a, base, exponent);}// numbersstatic double _number_gcd(struct solver_Algebra *a, double lhs, double rhs);static double _number_add(struct solver_Algebra *a, double lhs, double rhs);static double _number_multiply(struct solver_Algebra *a, double lhs, double rhs);static double _integer_integer_add(struct solver_Algebra *a, double lhs, double rhs) {
static double _number_add(struct solver_Algebra *a, double lhs, double rhs) {uint64_t lhs_payload;int lhs_tag = _decode(lhs, &lhs_payload);uint64_t rhs_payload;int rhs_tag = _decode(rhs, &rhs_payload);if(lhs_tag == INTEGER) {int64_t lhs_value = _decode_integer(lhs);if(rhs_tag == INTEGER) {int64_t rhs_value = _decode_integer(rhs);return solver_Algebra_integer(a, lhs + rhs);} else if(rhs_tag == BIG_INTEGER) {// TODO} else if(rhs_tag == FRACTION) {double numerator = first(a, rhs);double denominator = second(a, rhs);lhs = _number_multiply(a, lhs, denominator);numerator = _number_add(a, lhs, numerator);return solver_Algebra_fraction(a, numerator, denominator);} else if(rhs_tag == REAL) {return lhs_value * rhs;}} else if(lhs_tag == BIG_INTEGER) {// TODOif(rhs_tag == INTEGER) {} else if(rhs_tag == BIG_INTEGER) {} else if(rhs_tag == FRACTION) {} else if(rhs_tag == REAL) {}} else if(lhs_tag == FRACTION) {double lhs_numerator = first(a, lhs);double lhs_denominator = second(a, lhs);if(rhs_tag == INTEGER) {int64_t rhs_value = _decode_integer(rhs);rhs = _number_multiply(a, rhs, lhs_denominator);lhs_numerator = _number_add(a, rhs, lhs_numerator);return solver_Algebra_fraction(a, lhs_numerator, lhs_denominator);} else if(rhs_tag == BIG_INTEGER) {// TODO} else if(rhs_tag == FRACTION) {double rhs_numerator = first(a, rhs);double rhs_denominator = second(a, rhs);double denominator = _number_gcd(a, lhs_denominator, rhs_denominator);
} else if(rhs_tag == REAL) {}} else if(lhs_tag == REAL) {if(rhs_tag == INTEGER) {} else if(rhs_tag == BIG_INTEGER) {// TODO} else if(rhs_tag == FRACTION) {} else if(rhs_tag == REAL) {return rhs + lhs;}}
static uint64_t get_car(struct solver_Algebra *a, uint64_t expr) {return a->values.data[get_pair_index(expr) + 0];
if(lhs_tag == INTEGER) {if(rhs_tag == INTEGER) {} else if(rhs_tag == BIG_INTEGER) {} else if(rhs_tag == FRACTION) {} else if(rhs_tag == REAL) {}} else if(lhs_tag == BIG_INTEGER) {if(rhs_tag == INTEGER) {} else if(rhs_tag == BIG_INTEGER) {} else if(rhs_tag == FRACTION) {} else if(rhs_tag == REAL) {}} else if(lhs_tag == FRACTION) {if(rhs_tag == INTEGER) {} else if(rhs_tag == BIG_INTEGER) {} else if(rhs_tag == FRACTION) {} else if(rhs_tag == REAL) {}} else if(lhs_tag == REAL) {if(rhs_tag == INTEGER) {} else if(rhs_tag == BIG_INTEGER) {} else if(rhs_tag == FRACTION) {} else if(rhs_tag == REAL) {return lhs * rhs;}}
static uint64_t get_cdr(struct solver_Algebra *a, uint64_t expr) {return a->values.data[get_pair_index(expr) + 1];
static void _simplify_sum_recursive(struct solver_Algebra *a, uint32_t num_operands, const double *operands, uint32_t *result_num_operands, double ** result_operands) {if(num_operands == 2) {uint64_t lhs_payload, rhs_payload;int lhs_tag = _decode(operands[0], &lhs_payload);int rhs_tag = _decode(operands[1], &rhs_payload);if(lhs_tag == SUM && rhs_tag == SUM) {_simplify_sum_merge(a,(lhs_payload >> 24) & 0x07FFull, a->values.data + (lhs_payload & 0x0FFFull),(rhs_payload >> 24) & 0x07FFull, a->values.data + (rhs_payload & 0x0FFFull),result_num_operands, result_operands);return;}
if(lhs_tag == SUM) {_simplify_sum_merge(a,(lhs_payload >> 24) & 0x07FFull, a->values.data + (lhs_payload & 0x0FFFull),1, &operands[1],result_num_operands, result_operands);return;}if(rhs_tag == SUM) {_simplify_sum_merge(a,1, &operands[0],(rhs_payload >> 24) & 0x07FFull, a->values.data + (rhs_payload & 0x0FFFull),result_num_operands, result_operands);return;}if(_precedence(operands[0]) == PRECEDENCE_NUMBER && _precedence(operands[1]) == PRECEDENCE_NUMBER) {}}
static uint64_t get_index(struct solver_Algebra *a, uint64_t expr, uint32_t index) {assert(index < get_list_count(expr));return a->values.data[get_list_index(expr) + index];
static double _simplify_sum(struct solver_Algebra *a, uint32_t num_operands, const double *operands) {if(num_operands == 1) {return operands[0];}uint32_t result_num_operands;double * result_operands;double result;_simplify_sum_recursive(a, num_operands, operands, &result_num_operands, &result_operands);
free(result_operands);return result;}double solver_Algebra_simplify(struct solver_Algebra *a, double expr) {uint64_t payload;switch(_decode(expr, &payload)) {case REAL: return expr;case VARIABLE: return expr;case UNDEFINED: return expr;case INTEGER: return expr;case BIG_INTEGER: return expr;case FRACTION: return expr;case POWER: return _simplify_power(a, a->values.data[(payload & 0x0FFFull) + 0], a->values.data[(payload & 0x0FFFull) + 1]);case SUM: return _simplify_sum(a, (payload >> 24) & 0x07FFull, a->values.data + (payload & 0x0FFFull));case PRODUCT: return _simplify_product(a, (payload >> 24) & 0x07FFull, a->values.data + (payload & 0x0FFFull));case INVALID: return expr;}}#endif
uint64_t solver_Algebra_to_boolean(struct solver_Algebra *a, uint64_t expr) {switch(get_tag(expr)) {case Tag_Boolean:return expr;case Tag_Equals:return pack_boolean(equals(a, get_car(a, expr), get_cdr(a, expr)));default:return pack_undefined();}}
static uint64_t embed_product(struct solver_Algebra *a, uint32_t count, const uint64_t *values);static uint64_t embed_sum(struct solver_Algebra *a, uint32_t count, const uint64_t *values) {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]);}// x + x -> 2xif(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);}// 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]}struct EncodedList sum;sum.count = count;sum.index = embed_values(a, count, values);return pack_sum(sum);}uint64_t solver_Algebra_sum(struct solver_Algebra *a, uint32_t count, const uint64_t *values) {return embed_sum(a, count, values);}
#include <alias/memory.h>static uint64_t simplify(struct solver_Algebra *a, uint64_t bits);#define SIMPLIFY(TYPE, FN) static uint64_t TYPE##_simplify(struct solver_Algebra *a, uint64_t bits) FN#define SIMPLE(TYPE) SIMPLIFY(TYPE, { return bits; })#define SIMPLE_PAIR(TYPE) \SIMPLIFY(TYPE, { \uint64_t values[2]; \values[0] = simplify(a, get_car(a, bits)); \values[1] = simplify(a, get_car(a, bits)); \if(values[0] == get_car(a, bits) && values[1] == get_cdr(a, bits)) { \return bits; \} \uint32_t index = embed_values(a, 2, values); \return pack_##TYPE(index); \})#define SIMPLIFY_EMBEDED_LIST(TYPE) \SIMPLIFY(TYPE, { \uint32_t count = get_list_count(bits); \uint32_t index = get_list_index(bits); \uint64_t * values = alias_malloc(NULL, sizeof(*values) * count, alignof(*values)); \bool change = false; \for(uint32_t i = 0; i < count; i++) { \values[i] = simplify(a, a->values.data[index + i]); \if(values[i] != a->values.data[index + i]) { \change = true; \} \} \uint64_t result = change ? embed_##TYPE(a, count, values) : bits; \alias_free(NULL, values, sizeof(*values) * count, alignof(*values)); \return result; \})SIMPLE(real)SIMPLE(variable)SIMPLE(boolean)SIMPLE(undefined)SIMPLE(integer)SIMPLE(big_integer)SIMPLIFY(fraction, {// TODOreturn bits;})SIMPLIFY(power, {// return embed_power(a, get_car(a, bits), get_cdr(a, bits));return bits;})SIMPLIFY_EMBEDED_LIST(sum)SIMPLIFY_EMBEDED_LIST(product)SIMPLE_PAIR(equals)SIMPLE_PAIR(not_equals)SIMPLE_PAIR(less_than)SIMPLE_PAIR(greater_than)#undef SIMPLIFY_EMBEDED_LIST#undef SIMPLE_PAIR#undef SIMPLE#undef SIMPLIFYstatic uint64_t simplify(struct solver_Algebra *a, uint64_t bits) {switch(get_tag(bits)) {case Tag_Real:return real_simplify(a, bits);case Tag_Variable:return variable_simplify(a, bits);case Tag_Boolean:return boolean_simplify(a, bits);case Tag_Undefined:return undefined_simplify(a, bits);case Tag_Integer:return integer_simplify(a, bits);case Tag_BigInteger:return big_integer_simplify(a, bits);case Tag_Fraction:return fraction_simplify(a, bits);case Tag_Power:return power_simplify(a, bits);case Tag_Sum:return sum_simplify(a, bits);case Tag_Product:return product_simplify(a, bits);case Tag_Equals:return equals_simplify(a, bits);case Tag_NotEquals:return not_equals_simplify(a, bits);case Tag_LessThan:return less_than_simplify(a, bits);case Tag_GreaterThan:return greater_than_simplify(a, bits);default:return pack_undefined();}}uint64_t solver_Algebra_simplify(struct solver_Algebra *a, uint64_t expr) {return simplify(a, expr);}
#define PRECEDENCE_NUMBER 1000#define PRECEDENCE_SUM 110#define PRECEDENCE_PRODUCT 120#define PRECEDENCE_POWER 130static int precedence(uint64_t bits) {switch(get_tag(bits)) {case Tag_Real:case Tag_Variable:case Tag_Integer:case Tag_BigInteger: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_integer(struct solver_Algebra *a, uint64_t bits) {printf("%i", unpack_integer(bits));}static void show_big_integer(struct solver_Algebra *a, uint64_t bits) {printf("%p", unpack_big_integer(bits));}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 SURROUNDstatic 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_Integer:show_integer(a, bits);break;case Tag_BigInteger:show_big_integer(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");}
static uint64_t embed_product(struct solver_Algebra *a, uint32_t count, const uint64_t *values) {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_multiply(a, values[0], values[1]);}}struct EncodedList product;product.count = count;product.index = embed_values(a, count, values);return pack_product(product);}uint64_t solver_Algebra_product(struct solver_Algebra *a, uint32_t count, const uint64_t *values) {return embed_product(a, count, values);}
uint64_t solver_Algebra_power(struct solver_Algebra *a, uint64_t base, uint64_t exponent) {uint64_t values[2] = {base, exponent};uint32_t index = embed_values(a, 2, values);return pack_power(index);}
%include{#include <string.h>#include <stdlib.h>#include <stdbool.h>#include <stdio.h>#include <solver/algebra.h>struct String {const char * start;const char * end;};struct Token {int kind;int location;struct String string;};struct Location {int file;int offset;int line;int column;};struct File {const char * name;const char * data;int data_length;int location;int num_newlines;int * newlines;int max_newline_added;};struct {int last_location;int num_files;struct File ** files;} _ = {.last_location = 1,.num_files = 0,.files = NULL};static void File_register_newline(struct File *file, int location) {if(location >= file->max_newline_added) {file->newlines = realloc(file->newlines, sizeof(*file->newlines) + (file->num_newlines + 1));file->newlines[file->num_newlines] + location;file->num_newlines++;file->max_newline_added = location + 1;}}static struct File * File_from_string(const char * name, const char * data) {int name_size = strlen(name) + 1;int data_size = strlen(data) + 1;struct File * file = calloc(1, sizeof(*file) + name_size + data_size);file->name = memcpy((char *)(file + 1), name, name_size);file->data = memcpy((char *)(file + 1) + name_size, data, data_size);file->data_length = data_size;file->location = _.last_location;_.last_location = file->location + data_size;_.files = realloc(_.files, sizeof(*_.files) * (_.num_files + 1));_.files[_.num_files] = file;_.num_files++;File_register_newline(file, 0);return file;}static struct Location File_get_location(int location) {struct Location result;for(int f = 0; f < _.num_files; f++) {if(location >= _.files[f]->location && location < _.files[f]->location + _.files[f]->data_length) {result.file = f;result.offset = location - _.files[f]->location;int low = 0;int high = _.files[f]->num_newlines - 1;while(high >= low) {result.line = (low + high) >> 1;result.column = result.offset - _.files[f]->newlines[result.line];if(result.column == 0) {break;} else if(result.column > 0) {low = result.line + 1;} else {high = result.line - 1;}}result.line++;result.column++;return result;}}result.file = -1;result.offset = -1;result.line = -1;result.column = -1;return result;}static int Location_show_file_line_column(FILE * output, struct Location l) {if(l.file < 0) {return fprintf(output, "<invalid location>");}return fprintf(output, "%s:%i:%i: ", _.files[l.file]->name, l.line, l.column);}static int Location_highlight_at(FILE *output, struct Location l) {const char spaces[33] = " \00";int count = Location_show_file_line_column(output, l);if(l.file < 0) {return count;}int num_spaces = l.column + count - 1;const char * start = _.files[l.file]->data + _.files[l.file]->newlines[l.line - 1];const char * end = strchr(start, '\n');count += fprintf(output, "%.*s", (int)(end == NULL ? strlen(start) : end - start + 1), start);while(num_spaces > 32) {fprintf(output, spaces);num_spaces -= 32;count += 32;}count += fprintf(output, "%.*s^", num_spaces, spaces);return count;}struct Values {uint64_t tiny[4];alias_Vector(uint64_t) vector;};#define VALUES_INIT ((struct Values){ .vector = ALIAS_VECTOR_INIT })void Values_add(struct Values *vs, uint64_t v) {if(vs->vector.length > 4) {alias_Vector_space_for(&vs->vector, NULL, 1);*alias_Vector_push(&vs->vector) = v;} else if(vs->vector.length == 4) {vs->vector.length = 0;alias_Vector_space_for(&vs->vector, NULL, 5);*alias_Vector_push(&vs->vector) = vs->tiny[0];*alias_Vector_push(&vs->vector) = vs->tiny[1];*alias_Vector_push(&vs->vector) = vs->tiny[2];*alias_Vector_push(&vs->vector) = vs->tiny[3];*alias_Vector_push(&vs->vector) = v;} else {vs->tiny[vs->vector.length++] = v;}}uint32_t Values_count(struct Values *vs) {return vs->vector.length;}uint64_t * Values_values(struct Values *vs) {if(vs->vector.length > 4) {return vs->vector.data;} else {return vs->tiny;}}void Values_free(struct Values *vs) {alias_Vector_free(&vs->vector, NULL);}struct ExtraState {struct File * file;int offset;struct solver_Algebra *a;struct Values *expressions;};}%extra_context {struct ExtraState extra}%token INVALID.%token END.%token WHITESPACE.%token_type {struct Token}document ::= expressions(L) nl. { *extra.expressions = L; alias_Vector_clear(&L.vector); }// INSERTED_TERMINATOR is done by lex before (, {, [, ], }, and )// requiredend_of_line_token ::= NEWLINE.end_of_line_token ::= SEMICOLON.end_of_line_token ::= INSERTED_TERMINATOR.end_of_line ::= end_of_line end_of_line_token.end_of_line ::= end_of_line_token.// optionalnl ::= end_of_line.nl ::= .left_parens ::= INSERTED_TERMINATOR LEFT_PARENTHESIS.right_parens ::= INSERTED_TERMINATOR RIGHT_PARENTHESIS.%type expressions { struct Values }%destructor expressions { (void)extra; Values_free(&$$); }expressions(O) ::= expressions(L) end_of_line expression(E). { O = L; Values_add(&O, E); }expressions(O) ::= expression(S). { O = VALUES_INIT; Values_add(&O, S); }%type real { uint64_t }real(O) ::= REAL(R). { O = solver_Algebra_real(extra.a, atof(R.string.start)); }%type variable { uint64_t }variable(O) ::= IDENTIFIER(I). { O = solver_Algebra_variable(extra.a, alias_str_format(NULL, "%.*s", I.string.end - I.string.start, I.string.start)); }%type boolean { uint64_t }boolean(O) ::= KEYWORD_FALSE. { O = solver_Algebra_boolean(extra.a, false); }boolean(O) ::= KEYWORD_TRUE. { O = solver_Algebra_boolean(extra.a, true); }%type undefined { uint64_t }undefined(O) ::= KEYWORD_UNDEFINED. { O = solver_Algebra_undefined(extra.a); }%type integer { uint64_t }integer(O) ::= INTEGER(I). { O = solver_Algebra_integer(extra.a, atoi(I.string.start)); }//integer(O) ::= big_integer%type fraction { uint64_t }fraction(O) ::= integer(N) SOLIDUS integer(D). { O = solver_Algebra_fraction(extra.a, N, D); }%type primary { uint64_t }primary(O) ::= left_parens expression(E) right_parens. { O = E; }primary(O) ::= real(R). { O = R; }primary(O) ::= variable(V). { O = V; }primary(O) ::= boolean(B). { O = B; }primary(O) ::= undefined(U). { O = U; }primary(O) ::= integer(I). { O = I; }primary(O) ::= fraction(F). { O = F; }%type power { uint64_t }power(O) ::= primary(E). { O = E; }power(O) ::= power(B) CIRCUMFLEX_ACCENT primary(E). { O = solver_Algebra_power(extra.a, B, E); }%type sum { uint64_t }sum(O) ::= sum_list(L). { O = solver_Algebra_sum(extra.a, Values_count(&L), Values_values(&L)); }%type sum_list { struct Values }%destructor sum_list { Values_free(&$$); }sum_list(O) ::= product(P). { O = VALUES_INIT; Values_add(&O, P); }sum_list(O) ::= sum_list(L) PLUS_SIGN product(R). { O = L; Values_add(&O, R); }sum_list(O) ::= sum_list(A) HYPHEN_MINUS product(B). { O = A; Values_add(&O, solver_Algebra_negate(extra.a, B)); }%type product { uint64_t }product(O) ::= product_list(L). { O = solver_Algebra_product(extra.a, Values_count(&L), Values_values(&L)); }%type product_list { struct Values }%destructor product_list { Values_free(&$$); }product_list(O) ::= power(P). { O = VALUES_INIT; Values_add(&O, P); }product_list(O) ::= product_list(L) ASTERISK power(R). { O = L; Values_add(&O, R); }%type equals { uint64_t }equals(O) ::= sum(L) EQUALS_SIGN sum(R). { O = solver_Algebra_equals(extra.a, L, R); }%type not_equals { uint64_t }not_equals(O) ::= sum(L) NOT_EQUAL_TO sum(R). { O = solver_Algebra_not_equals(extra.a, L, R); }%type less_than { uint64_t }less_than(O) ::= sum(L) LESS_THAN_SIGN sum(R). { O = solver_Algebra_less_than(extra.a, L, R); }%type greater_than { uint64_t }greater_than(O) ::= sum(L) GREATER_THAN_SIGN sum(R). { O = solver_Algebra_greater_than(extra.a, L, R); }%type expression { uint64_t }expression(O) ::= sum(S). { O = S; }expression(O) ::= equals(E). { O = E; }expression(O) ::= not_equals(N). { O = N; }expression(O) ::= less_than(L). { O = L; }expression(O) ::= greater_than(G). { O = G; }%syntax_error {// struct Location l = File_get_location(TOKEN.location);//// Location_show_file_line_column(stderr, l);// fprintf(stderr, "syntax error\n");//// Location_highlight_at(stderr, l);// fprintf(stderr, "\n");}%parse_accept {// printf("parsing accepted!\n");}%parse_failure {// fprintf(stderr, "parsing failure!\n");}%code{static void Parser_init(struct yyParser * parser, struct File * file, struct Values * values) {struct ExtraState extra;alias_memory_clear(&extra, sizeof(extra));extra.file = file;extra.expressions = values;ParseInit(parser, extra);}static struct Token Parser_next_token(struct yyParser * parser) {struct ExtraState * extra = &parser->extra;const char *YYCURSOR = extra->file->data + extra->offset;const char *YYMARKER;#define RETURN(KIND) \do { \struct Token _result; \_result.kind = KIND; \_result.location = extra->file->location + extra->offset; \_result.string.start = extra->file->data + extra->offset; \_result.string.end = YYCURSOR - 1; \extra->offset = YYCURSOR - extra->file->data; \return _result; \} while(0)/*!re2cre2c:yyfill:enable = 0;re2c:define:YYCTYPE = char;end = "\x00";* { RETURN(INVALID); }end { RETURN(END); }ws = [ \t]+;nl = [\n\r]+;line_comment = "#" [^\n]* nl;newline = ws? ((nl | line_comment) ws?)+;newline {for(int location = extra->offset; extra->file->data + location < YYCURSOR; location++) {if(extra->file->data[location] == '\n') {File_register_newline(extra->file, location);}}RETURN(NEWLINE);}whitespace = ws;whitespace { RETURN(WHITESPACE); }oct_number = [0] [0-7]*;dec_number = [1-9] [0-9]*;hex_number = "0x" [0-9a-fA-F]+;oct_number { RETURN(INTEGER); }dec_number { RETURN(INTEGER); }hex_number { RETURN(INTEGER); }decimal = [0-9]* "." [0-9]+ | [0-9]+ ".";decimal { RETURN(REAL); }//"and" { RETURN(KEYWORD_AND); }//"or" { RETURN(KEYWORD_OR); }"true" { RETURN(KEYWORD_TRUE); }"false" { RETURN(KEYWORD_FALSE); }identifier = [a-zA-Z_][a-zA-Z_0-9]*;full_identifier = identifier ("." identifier)*;full_identifier { RETURN(IDENTIFIER); }"(" { RETURN(LEFT_PARENTHESIS); }")" { RETURN(RIGHT_PARENTHESIS); }"<" { RETURN(LESS_THAN_SIGN); }">" { RETURN(GREATER_THAN_SIGN); }"=" { RETURN(EQUALS_SIGN); }"+" { RETURN(PLUS_SIGN); }"-" { RETURN(HYPHEN_MINUS); }"*" { RETURN(ASTERISK); }"/" { RETURN(SOLIDUS); }"!=" { RETURN(NOT_EQUAL_TO); }*/}static bool Parser_next(struct yyParser * parser) {struct Token t = Parser_next_token(parser);if(t.kind == END) {Parse(parser, 0, t);return false;}if(t.kind == INVALID) {fprintf(stderr, "invalid token encountered at %8s\n", t.string.start);return false;}if(t.kind == LEFT_PARENTHESIS || t.kind == RIGHT_PARENTHESIS) {Parse(parser, INSERTED_TERMINATOR, t);}if(t.kind != WHITESPACE) {Parse(parser, t.kind, t);}return true;}uint64_t solver_Algebra_parse(struct solver_Algebra *a, const char * string) {struct File * test_file = File_from_string("input", string);struct yyParser p;struct Values expressions = VALUES_INIT;Parser_init(&p, test_file, &expressions);while(Parser_next(&p)) ;assert(Values_count(&expressions) > 0);uint64_t result = Values_values(&expressions)[Values_count(&expressions) - 1];Values_free(&expressions);return result;}}
#include <math.h>static bool is_number(uint64_t bits) {return is_integer(bits) || is_big_integer(bits) || is_fraction(bits) || is_real(bits);}static uint64_t integer_integer_add(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {return pack_integer(unpack_integer(lhs) + unpack_integer(rhs));}static uint64_t integer_add(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {assert(is_number(rhs));switch(get_tag(rhs)) {case Tag_Integer:return integer_integer_add(a, lhs, rhs);default:return pack_undefined();}}static uint64_t number_add(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {assert(is_number(lhs));assert(is_number(rhs));switch(get_tag(lhs)) {case Tag_Integer:return integer_add(a, lhs, rhs);default:return pack_undefined();}}static uint64_t integer_integer_multiply(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {// TODO big integer upgradereturn pack_integer(unpack_integer(lhs) * unpack_integer(rhs));}static uint64_t integer_multiply(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {assert(is_number(rhs));switch(get_tag(rhs)) {case Tag_Integer:return integer_integer_multiply(a, lhs, rhs);default:return pack_undefined();}}static uint64_t number_multiply(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {assert(is_number(lhs));assert(is_number(rhs));switch(get_tag(lhs)) {case Tag_Integer:return integer_multiply(a, lhs, rhs);default:return pack_undefined();}}static uint64_t embed_fraction(struct solver_Algebra *a, uint64_t numerator, uint64_t denominator) {uint64_t values[2] = {numerator, denominator};uint32_t index = embed_values(a, 2, values);return pack_fraction(index);}uint64_t solver_Algebra_real(struct solver_Algebra *a, double value) {if(value == floor(value)) {return solver_Algebra_integer(a, (int64_t)value);}return pack_real(value);}uint64_t solver_Algebra_integer(struct solver_Algebra *a, int64_t value) {return pack_integer(value);}uint64_t solver_Algebra_fraction(struct solver_Algebra *a, uint64_t numerator, uint64_t denominator) {return embed_fraction(a, numerator, denominator);}
// 0x7 f f 8 | 7// <01111111 1111 12-bit nan header> <1-bit silent flag, 0 on most cpus> <3-bit tag> <48-bit payload>// 000 - variable - pointer to variable name// 001 - atom// 010 - integer - 32-bit integer// 011 - integer - pointer to big integer implementation// 100 - pair - <3-bit type> <21-bit unused> <24-bit index to first>// 000 - fraction// 001 - power// 010 - unused// 011 - unused// 100 - equals// 101 - not equals// 110 - less than// 111 - greater than// 101 - list - <1-bit type> <23-bit count> <24-bit index to first>// 0 - sum// 1 - product// 110 - unused// 111 - unused#define NAN_MASK 0xFFF0000000000000ull#define NAN_BITS 0x7FF0000000000000ull#define QUEIT_BITS 0x7FF0000000000000ull#define SIGNALING_BITS 0x7FF8000000000000ull#define TAG_MASK 0xFFF7000000000000ull#define TAG_VARIABLE_BITS 0x7FF0000000000000ull#define TAG_ATOM_BITS 0x7FF1000000000000ull#define TAG_INTEGER_BITS 0x7FF2000000000000ull#define TAG_BIGINT_BITS 0x7FF3000000000000ull#define TAG_PAIR_BITS 0x7FF4000000000000ull#define TAG_LIST_BITS 0x7FF5000000000000ull#define TAG_UNUSED1_BITS 0x7FF6000000000000ull#define TAG_UNUSED2_BITS 0x7FF7000000000000ull#define PAIR_MASK 0xFFF7e00000000000ull#define PAIR_FRACTION_BITS 0x7FF4000000000000ull#define PAIR_POWER_BITS 0x7FF4200000000000ull#define PAIR_UNUSED1_BITS 0x7FF4400000000000ull#define PAIR_UNUSED2_BITS 0x7FF4600000000000ull#define PAIR_EQUAL_BITS 0x7FF4800000000000ull#define PAIR_NOT_EQUAL_BITS 0x7FF4a00000000000ull#define PAIR_LESS_THAN_BITS 0x7FF4c00000000000ull#define PAIR_GREATER_THAN_BITS 0x7FF4e00000000000ull#define LIST_MASK 0xFFF7800000000000ull#define LIST_SUM_BITS 0x7FF5000000000000ull#define LIST_PRODUCT_BITS 0x7FF5800000000000ull#define PAYLOAD_MASK 0x0000FFFFFFFFFFFFull#define PAIR_INDEX_MASK 0x0000000000FFFFFFull#define LIST_COUNT_MASK 0x00007FFFFF000000ull#define LIST_INDEX_MASK 0x0000000000FFFFFFullstatic uint64_t get_pair_index(uint64_t expr) {assert((expr & TAG_MASK) == TAG_PAIR_BITS);return expr & LIST_INDEX_MASK;}static uint64_t get_list_count(uint64_t expr) {assert((expr & TAG_MASK) == TAG_LIST_BITS);return (expr & LIST_COUNT_MASK) >> 24;}static uint64_t get_list_index(uint64_t expr) {assert((expr & TAG_MASK) == TAG_LIST_BITS);return expr & LIST_INDEX_MASK;}// --------------------------------------------------------------------------------------------------------------------#define DEFINE_ENCODING(TYPE, CTYPE, IS_FN, PACK_FN, UNPACK_FN) \static inline bool is_##TYPE(uint64_t packed) IS_FN \static inline uint64_t pack_##TYPE(CTYPE unpacked) PACK_FN \static inline CTYPE unpack_##TYPE(uint64_t packed) { assert(is_##TYPE(packed)); UNPACK_FN }union DoubleBits {uint64_t u;double d;};DEFINE_ENCODING(real, double,{ return (packed & NAN_MASK) != NAN_BITS; },{union DoubleBits _;_.d = unpacked;return _.u;},{union DoubleBits _;_.u = packed;return _.d;})DEFINE_ENCODING(variable, const char *,{ return (packed & TAG_MASK) == TAG_VARIABLE_BITS; },{ return TAG_VARIABLE_BITS | ((uint64_t)unpacked & PAYLOAD_MASK); },{ return (const char *)(packed & PAYLOAD_MASK); })DEFINE_ENCODING(boolean, bool,{ return (packed & TAG_MASK) == TAG_ATOM_BITS && (packed & (PAYLOAD_MASK ^ 1)) == 0; },{ return TAG_ATOM_BITS | !!unpacked; },{ return packed ^ 1; })static inline bool is_undefined(uint64_t packed) { return packed == (TAG_ATOM_BITS | 2); }static inline uint64_t pack_undefined() { return TAG_ATOM_BITS | 2; }static inline void unpack_undefined(uint64_t packed) { assert(is_undefined(packed)); }union Int32x2 {int32_t i[2];uint64_t u;};DEFINE_ENCODING(integer, int32_t,{ return (packed & TAG_MASK) == TAG_INTEGER_BITS; },{union Int32x2 _;_.i[0] = unpacked;_.i[1] = unpacked;return TAG_INTEGER_BITS | (_.u & PAYLOAD_MASK);},{union Int32x2 _;_.u = packed & PAYLOAD_MASK;return _.i[0] | _.i[1];})struct BigInteger {int64_t big;};DEFINE_ENCODING(big_integer, struct BigInteger *,{ return (packed & TAG_MASK) == TAG_BIGINT_BITS; },{ return TAG_BIGINT_BITS | ((uint64_t)unpacked & PAYLOAD_MASK); },{ return (struct BigInteger *)(packed & PAYLOAD_MASK); })#define DEFINE_PAIR_ENCODING(TYPE, BITS) \DEFINE_ENCODING( \TYPE, uint32_t, \{ return (packed & PAIR_MASK) == BITS; }, \{ return BITS | (unpacked & PAIR_INDEX_MASK); }, \{ return packed & PAIR_INDEX_MASK; } \)DEFINE_PAIR_ENCODING(fraction, PAIR_FRACTION_BITS)DEFINE_PAIR_ENCODING(power, PAIR_POWER_BITS)struct EncodedList {uint32_t count;uint32_t index;};#define DEFINE_LIST_ENCODING(TYPE, BITS) \DEFINE_ENCODING( \TYPE, struct EncodedList, \{ return (packed & LIST_MASK) == BITS; }, \{ return BITS | (unpacked.count << 24) | unpacked.index; }, \{ struct EncodedList _; _.count = (packed & LIST_COUNT_MASK) >> 24; _.index = (packed & LIST_INDEX_MASK); return _; } \)DEFINE_LIST_ENCODING(sum, LIST_SUM_BITS)DEFINE_LIST_ENCODING(product, LIST_PRODUCT_BITS)DEFINE_PAIR_ENCODING(equals, PAIR_EQUAL_BITS)DEFINE_PAIR_ENCODING(not_equals, PAIR_NOT_EQUAL_BITS)DEFINE_PAIR_ENCODING(less_than, PAIR_LESS_THAN_BITS)DEFINE_PAIR_ENCODING(greater_than, PAIR_GREATER_THAN_BITS)enum Tag {Tag_Real,Tag_Variable,Tag_Boolean, // atom 0 and 1Tag_Undefined, // atom 2Tag_Integer,Tag_BigInteger,Tag_Fraction,Tag_Power,Tag_Sum,Tag_Product,Tag_Equals,Tag_NotEquals,Tag_LessThan,Tag_GreaterThan,Tag_Invalid};static enum Tag get_tag(uint64_t bits) {if(is_real(bits)) {return Tag_Real;} else if(is_variable(bits)) {return Tag_Variable;} else if(is_boolean(bits)) {return Tag_Boolean;} else if(is_undefined(bits)) {return Tag_Undefined;} else if(is_integer(bits)) {return Tag_Integer;} else if(is_big_integer(bits)) {return Tag_BigInteger;} else if(is_fraction(bits)) {return Tag_Fraction;} else if(is_power(bits)) {return Tag_Power;} else if(is_equals(bits)) {return Tag_Equals;} else if(is_not_equals(bits)) {return Tag_NotEquals;} else if(is_less_than(bits)) {return Tag_LessThan;} else if(is_greater_than(bits)) {return Tag_GreaterThan;} else if(is_sum(bits)) {return Tag_Sum;} else if(is_product(bits)) {return Tag_Product;} else {return Tag_Invalid;}}#undef DEFINE_LIST_ENCODING#undef DEFINE_PAIR_ENCODING#undef DEFINE_ENCODING
static uint64_t boolean_not(struct solver_Algebra *a, uint64_t expr_) {if(expr_ == (TAG_ATOM_BITS | 0)) return TAG_ATOM_BITS | 1;if(expr_ == (TAG_ATOM_BITS | 1)) return TAG_ATOM_BITS | 0;return TAG_ATOM_BITS | 2;}static bool equals(struct solver_Algebra *a, uint64_t lhs, uint64_t 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(); \} \}#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)) ; \})#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; \})BINARY_EQUALS(real, Tag_Real, { return unpack_real(lhs) == unpack_real(rhs); })#if 0BINARY_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, {// TODOreturn false;})BINARY_EQUALS(fraction, Tag_Fraction, {// TODOreturn 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)#endifstatic bool equals(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {if(lhs == rhs) return true;switch(get_tag(lhs)) {case Tag_Real:return real_equals(a, lhs, rhs);/* case Tag_Variable:return variable_equals(a, lhs, rhs);case Tag_Boolean:return boolean_equals(a, lhs, rhs);case Tag_Undefined:return undefined_equals(a, lhs, rhs);case Tag_Integer:return integer_equals(a, lhs, rhs);case Tag_BigInteger:return big_integer_equals(a, lhs, rhs);case Tag_Fraction:return fraction_equals(a, lhs, rhs);case Tag_Power:return power_equals(a, lhs, rhs);case Tag_Sum:return sum_equals(a, lhs, rhs);case Tag_Product:return product_equals(a, lhs, rhs);case Tag_Equals:return equals_equals(a, lhs, rhs);case Tag_NotEquals:return not_equals_equals(a, lhs, rhs);case Tag_LessThan:return less_than_equals(a, lhs, rhs);case Tag_GreaterThan:return greater_than_equals(a, lhs, rhs);case Tag_Invalid:*/default:return pack_undefined();}}uint64_t solver_Algebra_boolean(struct solver_Algebra *a, bool value) {return pack_boolean(value);}uint64_t solver_Algebra_equals(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {uint64_t values[2] = { lhs, rhs };uint32_t index = embed_values(a, 2, values);return pack_equals(index);}uint64_t solver_Algebra_not_equals(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {uint64_t values[2] = { lhs, rhs };uint32_t index = embed_values(a, 2, values);return pack_not_equals(index);}uint64_t solver_Algebra_less_than(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {uint64_t values[2] = { lhs, rhs };uint32_t index = embed_values(a, 2, values);return pack_less_than(index);}uint64_t solver_Algebra_greater_than(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {uint64_t values[2] = { lhs, rhs };uint32_t index = embed_values(a, 2, values);return pack_greater_than(index);}