#include <math.h>
static bool is_number(uint64_t bits) {
return is_smallint(bits) || is_largeint(bits) || is_fraction(bits) || is_real(bits);
}
static uint64_t number_add__smallint__smallint(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
int64_t l = unpack_smallint(lhs);
int64_t r = unpack_smallint(rhs);
int64_t c = l + r;
return pack_smallint(c);
}
static uint64_t number_add__smallint(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
assert(is_number(rhs));
switch(get_tag(rhs)) {
case Tag_SmallInt:
return number_add__smallint__smallint(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_SmallInt:
return number_add__smallint(a, lhs, rhs);
default:
return pack_undefined();
}
}
static uint64_t number_multiply(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs);
static uint64_t number_multiply__smallint__smallint(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
return pack_smallint(unpack_smallint(lhs) * unpack_smallint(rhs));
}
static uint64_t number_multiply__smallint__fraction(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
uint64_t n = get_car(a, rhs);
uint64_t d = get_cdr(a, rhs);
return solver_Algebra_fraction(a, number_multiply(a, lhs, n), d);
}
static uint64_t number_multiply__smallint(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
assert(is_number(rhs));
switch(get_tag(rhs)) {
case Tag_SmallInt:
return number_multiply__smallint__smallint(a, lhs, rhs);
case Tag_Fraction:
return number_multiply__smallint__fraction(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_SmallInt:
return number_multiply__smallint(a, lhs, rhs);
default:
return pack_undefined();
}
}
static uint64_t number_power__smallint__smallint(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
int64_t base = unpack_smallint(lhs);
int64_t exp = unpack_smallint(rhs);
bool n = exp < 0;
if(exp) {
exp = -exp;
}
int32_t result = 1;
for(;;) {
if(exp & 1) {
result *= base;
}
exp >>= 1;
if(exp == 0) {
break;
}
base *= base;
}
if(n) {
return solver_Algebra_fraction(a, LITERAL_ONE, pack_smallint(result));
} else {
return pack_smallint(result);
}
}
static uint64_t number_power__smallint(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
assert(is_number(rhs));
switch(get_tag(rhs)) {
case Tag_SmallInt:
return number_power__smallint__smallint(a, lhs, rhs);
default:
return pack_undefined();
}
}
static uint64_t number_power(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
assert(is_number(lhs));
assert(is_number(rhs));
switch(get_tag(lhs)) {
case Tag_SmallInt:
return number_power__smallint(a, lhs, rhs);
default:
return pack_undefined();
}
}
static int number_compare__smallint__smallint(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
return unpack_smallint(rhs) - unpack_smallint(lhs);
}
static int number_compare__smallint(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
assert(is_number(rhs));
switch(get_tag(rhs)) {
case Tag_SmallInt:
return number_compare__smallint__smallint(a, lhs, rhs);
default:
return -1;
}
}
static int number_compare(struct solver_Algebra *a, uint64_t lhs, uint64_t rhs) {
assert(is_number(lhs));
assert(is_number(rhs));
switch(get_tag(lhs)) {
case Tag_SmallInt:
return number_compare__smallint(a, lhs, rhs);
default:
return 0;
}
}
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);
}