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 0x0000000000FFFFFFull
struct Unpacked {
enum {
Unpacked_Real,
Unpacked_Variable,
Unpacked_Boolean, // atom 0 and 1
Unpacked_Undefined, // atom 2
Unpacked_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;
}
// --------------------------------------------------------------------------------------------------------------------
// numerics
static 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 memory
static 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 130
static 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_not
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 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);
}
// TODO
static 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);
}
// TODO
static 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_boolean
uint64_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 algebra
static 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
// -- numerator
double 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;
}
}
// -- denominator
double 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);
}
}
// -- simplify
static 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);
}
// numbers
static 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) {
// TODO
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) {
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 -> 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);
}
// 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, {
// TODO
return 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 SIMPLIFY
static 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 130
static 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 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_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 )
// required
end_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.
// optional
nl ::= 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)
/*!re2c
re2c: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 upgrade
return 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 0x0000000000FFFFFFull
static 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 1
Tag_Undefined, // atom 2
Tag_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 0
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;
})
BINARY_EQUALS(fraction, Tag_Fraction, {
// TODO
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)
#endif
static 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);
}