diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2026-01-16 18:22:00 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2026-01-16 18:22:00 -0500 |
| commit | c64fa0d256ffdba8052580001a34da13157672fd (patch) | |
| tree | b7d145d81957d2b30ec37f94ed67d0d5c1d6621f | |
| parent | de7c686bd5ae30fe229d1a4e200cbd7b56e3a91c (diff) | |
Fix everything up real good
| -rw-r--r-- | src/compile/expressions.c | 18 | ||||
| -rw-r--r-- | src/parse/numbers.c | 4 | ||||
| -rw-r--r-- | src/stdlib/datatypes.h | 32 | ||||
| -rw-r--r-- | src/stdlib/reals.c | 426 |
4 files changed, 156 insertions, 324 deletions
diff --git a/src/compile/expressions.c b/src/compile/expressions.c index f86786be..05ea938f 100644 --- a/src/compile/expressions.c +++ b/src/compile/expressions.c @@ -119,10 +119,8 @@ Text_t compile_real(ast_t *ast, Real_t num) { // Check if denominator is 1 (integer) if (mpz_cmp_ui(mpq_denref(&r->value), 1) == 0) { - Int_t b = Int$from_mpz(mpq_numref(&r->value)); - Real_t b_real; - b_real.bigint = &b; - b_real.bits |= REAL_TAG_BIGINT; + Int_t *b = heap(Int$from_mpz(mpq_numref(&r->value))); + Real_t b_real = {.bits = (uint64_t)b | REAL_TAG_BIGINT}; return compile_real(ast, b_real); } @@ -138,15 +136,11 @@ Text_t compile_real(ast_t *ast, Real_t num) { char *den_str = mpz_get_str(NULL, 10, mpq_denref(&r->value)); return Texts("Real$from_rational(", num_str, ", ", den_str, ")"); } else { - Int_t numerator = Int$from_mpz(mpq_numref(&r->value)); - Real_t num_real; - num_real.bigint = &numerator; - num_real.bits |= REAL_TAG_BIGINT; + Int_t *numerator = heap(Int$from_mpz(mpq_numref(&r->value))); + Real_t num_real = {.bits = (uint64_t)numerator | REAL_TAG_BIGINT}; - Int_t denominator = Int$from_mpz(mpq_denref(&r->value)); - Real_t den_real; - den_real.bigint = &denominator; - den_real.bits |= REAL_TAG_BIGINT; + Int_t *denominator = heap(Int$from_mpz(mpq_denref(&r->value))); + Real_t den_real = {.bits = (uint64_t)denominator | REAL_TAG_BIGINT}; return Texts("Real$divided_by(", compile_real(ast, num_real), ", ", compile_real(ast, den_real), ")"); } diff --git a/src/parse/numbers.c b/src/parse/numbers.c index 5aa5c287..b992b133 100644 --- a/src/parse/numbers.c +++ b/src/parse/numbers.c @@ -100,5 +100,9 @@ ast_t *parse_num(parse_ctx_t *ctx, const char *pos) { if (!Real$is_zero(real)) real = Real$times(Real$divided_by(real, Real$from_float64(360.)), Real$tau); } + if (Real$tag(real) == REAL_TAG_SYMBOLIC && REAL_SYMBOLIC(real)->op == SYM_INVALID) { + parser_err(ctx, start, pos, "Failed to convert this to a real number"); + } + return NewAST(ctx->file, start, pos, Number, .n = real); } diff --git a/src/stdlib/datatypes.h b/src/stdlib/datatypes.h index 951a9433..e8848e9a 100644 --- a/src/stdlib/datatypes.h +++ b/src/stdlib/datatypes.h @@ -50,17 +50,15 @@ typedef union { #define REAL_TAG_SYMBOLIC 4ULL #define REAL_DOUBLE(r) \ - ({ \ - ((union { \ - double d; \ - uint64_t bits; \ - }){.bits = (r).bits ^ QNAN_MASK}) \ - .d; \ - }) -#define REAL_BIGINT(r) ((Int_t *)((uint64_t)(r).bigint & ~0x7ULL)) -#define REAL_RATIONAL(r) ((rational_t *)((uint64_t)(r).rational & ~0x7ULL)) -#define REAL_CONSTRUCTIVE(r) ((constructive_t *)((uint64_t)(r).constructive & ~0x7ULL)) -#define REAL_SYMBOLIC(r) ((symbolic_t *)((uint64_t)(r).symbolic & ~0x7ULL)) + (((union { \ + double d; \ + uint64_t bits; \ + }){.bits = (r).bits ^ QNAN_MASK}) \ + .d) +#define REAL_BIGINT(r) ((Int_t *)((r).bits & ~0x7ULL)) +#define REAL_RATIONAL(r) ((rational_t *)((r).bits & ~0x7ULL)) +#define REAL_CONSTRUCTIVE(r) ((constructive_t *)((r).bits & ~0x7ULL)) +#define REAL_SYMBOLIC(r) ((symbolic_t *)((r).bits & ~0x7ULL)) typedef struct { __mpq_struct value; @@ -99,13 +97,11 @@ typedef enum { } sym_op_t; typedef union { - // These are marked as volatile because we will sometimes - // set one flag to tinker with the others. - volatile struct symbolic *symbolic; - volatile Int_t *bigint; - volatile rational_t *rational; - volatile constructive_t *constructive; - volatile uint64_t bits; + uint64_t bits; + struct symbolic *symbolic; + rational_t *rational; + constructive_t *constructive; + Int_t *bigint; } Real_t; typedef struct symbolic { diff --git a/src/stdlib/reals.c b/src/stdlib/reals.c index b97f5027..27630c3d 100644 --- a/src/stdlib/reals.c +++ b/src/stdlib/reals.c @@ -33,22 +33,33 @@ static inline Real_t R(double d) { return (Real_t){.bits = input.bits ^ QNAN_MASK}; } +static inline Real_t mpq_to_real(__mpq_struct mpq) { + volatile rational_t *r = GC_MALLOC(sizeof(rational_t)); + r->value = mpq; + return (Real_t){.rational = (void *)r + REAL_TAG_RATIONAL}; +} + +static inline Real_t _sym_to_real(symbolic_t sym) { + volatile symbolic_t *s = GC_MALLOC(sizeof(symbolic_t)); + *s = sym; + return (Real_t){.symbolic = (void *)s + REAL_TAG_SYMBOLIC}; +} +#define sym_to_real(...) _sym_to_real((symbolic_t){__VA_ARGS__}) + public Real_t Real$from_int64(int64_t i) { double d = (double)i; if ((int64_t)d == i) return R(d); - Int_t *b = GC_MALLOC(sizeof(Int_t)); + volatile Int_t *b = GC_MALLOC(sizeof(Int_t)); *b = I(i); - Real_t ret = {.bigint = b}; - ret.bits |= REAL_TAG_BIGINT; - return ret; + return (Real_t){.bigint = (void *)b + REAL_TAG_BIGINT}; } public Real_t Real$from_rational(int64_t num, int64_t den) { - rational_t *r = GC_MALLOC(sizeof(rational_t)); - mpq_init(&r->value); + __mpq_struct ret; + mpq_init(&ret); if (den == INT64_MIN) fail("Domain error"); if (den < 0) { if (num == INT64_MIN) fail("Domain error"); @@ -56,11 +67,9 @@ Real_t Real$from_rational(int64_t num, int64_t den) { den = -den; } if (den == 0) fail("Division by zero"); - mpq_set_si(&r->value, num, (unsigned long)den); - mpq_canonicalize(&r->value); - Real_t ret = {.rational = r}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + mpq_set_si(&ret, num, (unsigned long)den); + mpq_canonicalize(&ret); + return mpq_to_real(ret); } public @@ -83,16 +92,14 @@ bool Real$get_rational(Real_t x, int64_t *num, int64_t *den) { } // Promote double to exact type if needed -static Real_t Real$as_rational(double d) { +static inline Real_t Real$as_rational(double d) { if (!isfinite(d)) { return R(d); } - rational_t *r = GC_MALLOC(sizeof(rational_t)); - mpq_init(&r->value); - mpq_set_d(&r->value, d); - Real_t ret = {.rational = r}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + __mpq_struct ret; + mpq_init(&ret); + mpq_set_d(&ret, d); + return mpq_to_real(ret); } public @@ -105,11 +112,9 @@ Real_t Real$from_int(Int_t i) { double d = Float64$from_int(i, true); if (Int$equal_value(i, Int$from_float64(d, true))) return R(d); - Int_t *b = GC_MALLOC(sizeof(Int_t)); + volatile Int_t *b = GC_MALLOC(sizeof(Int_t)); *b = i; - Real_t ret = {.bigint = b}; - ret.bits |= REAL_TAG_BIGINT; - return ret; + return (Real_t){.bigint = (void *)b + REAL_TAG_BIGINT}; } public @@ -168,15 +173,15 @@ double Real$as_float64(Real_t n, bool truncate) { symbolic_t pi_symbol = {.op = SYM_PI}; public -Real_t Real$pi = {.symbolic = (void *)&pi_symbol + (ptrdiff_t)REAL_TAG_SYMBOLIC}; +Real_t Real$pi = {.symbolic = (void *)&pi_symbol + REAL_TAG_SYMBOLIC}; symbolic_t tau_symbol = {.op = SYM_TAU}; public -Real_t Real$tau = {.symbolic = (void *)&tau_symbol + (ptrdiff_t)REAL_TAG_SYMBOLIC}; +Real_t Real$tau = {.symbolic = (void *)&tau_symbol + REAL_TAG_SYMBOLIC}; symbolic_t e_symbol = {.op = SYM_E}; public -Real_t Real$e = {.symbolic = (void *)&e_symbol + (ptrdiff_t)REAL_TAG_SYMBOLIC}; +Real_t Real$e = {.symbolic = (void *)&e_symbol + REAL_TAG_SYMBOLIC}; public Real_t Real$plus(Real_t a, Real_t b) { @@ -196,23 +201,14 @@ Real_t Real$plus(Real_t a, Real_t b) { // Handle exact rational arithmetic if (Real$tag(a) == REAL_TAG_RATIONAL && Real$tag(b) == REAL_TAG_RATIONAL) { - rational_t *result = GC_MALLOC(sizeof(rational_t)); - mpq_init(&result->value); - mpq_add(&result->value, &REAL_RATIONAL(a)->value, &REAL_RATIONAL(b)->value); - Real_t ret = {.rational = result}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + __mpq_struct ret; + mpq_init(&ret); + mpq_add(&ret, &REAL_RATIONAL(a)->value, &REAL_RATIONAL(b)->value); + return mpq_to_real(ret); } // Fallback: create symbolic expression - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_ADD; - sym->left = a; - sym->right = b; - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_ADD, .left = a, .right = b); } public @@ -232,22 +228,13 @@ Real_t Real$minus(Real_t a, Real_t b) { if (!Real$is_boxed(b)) b = Real$as_rational(REAL_DOUBLE(b)); if (Real$tag(a) == REAL_TAG_RATIONAL && Real$tag(b) == REAL_TAG_RATIONAL) { - rational_t *result = GC_MALLOC(sizeof(rational_t)); - mpq_init(&result->value); - mpq_sub(&result->value, &REAL_RATIONAL(a)->value, &REAL_RATIONAL(b)->value); - Real_t ret = {.rational = result}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + __mpq_struct ret; + mpq_init(&ret); + mpq_sub(&ret, &REAL_RATIONAL(a)->value, &REAL_RATIONAL(b)->value); + return mpq_to_real(ret); } - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_SUB; - sym->left = a; - sym->right = b; - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_SUB, .left = a, .right = b); } public @@ -269,13 +256,10 @@ Real_t Real$times(Real_t a, Real_t b) { if (Real$tag(a) == REAL_TAG_RATIONAL && Real$tag(b) == REAL_TAG_RATIONAL) { rational_t *ra = REAL_RATIONAL(a); rational_t *rb = REAL_RATIONAL(b); - rational_t *result = GC_MALLOC(sizeof(rational_t)); - mpq_init(&result->value); - mpq_mul(&result->value, &ra->value, &rb->value); - - Real_t ret = {.rational = result}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + __mpq_struct ret; + mpq_init(&ret); + mpq_mul(&ret, &ra->value, &rb->value); + return mpq_to_real(ret); } // Check for sqrt(x) * sqrt(x) = x @@ -290,13 +274,7 @@ Real_t Real$times(Real_t a, Real_t b) { } } - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_MUL; - sym->left = a; - sym->right = b; - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_MUL, .left = a, .right = b); } public @@ -317,23 +295,24 @@ Real_t Real$divided_by(Real_t a, Real_t b) { if (Real$tag(a) == REAL_TAG_RATIONAL && Real$tag(b) == REAL_TAG_RATIONAL) { rational_t *ra = REAL_RATIONAL(a); rational_t *rb = REAL_RATIONAL(b); - rational_t *result = GC_MALLOC(sizeof(rational_t)); - mpq_init(&result->value); - mpq_div(&result->value, &ra->value, &rb->value); - - Real_t ret = {.rational = result}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + __mpq_struct ret; + mpq_init(&ret); + mpq_div(&ret, &ra->value, &rb->value); + return mpq_to_real(ret); } - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_DIV; - sym->left = a; - sym->right = b; - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; + // volatile Real_t ret = sym_to_real(.op = SYM_DIV, .left = a, .right = b); + volatile Real_t ret = {}; + volatile symbolic_t *s = GC_MALLOC(sizeof(symbolic_t)); + s->op = SYM_DIV; + s->left = a; + s->right = b; + ret.symbolic = (void *)s + REAL_TAG_SYMBOLIC; + assert(REAL_SYMBOLIC(ret)->op == SYM_DIV); + // return (Real_t){.symbolic = (void *)s + REAL_TAG_SYMBOLIC}; + print("sym: ", ret); return ret; + // return sym_to_real(.op = SYM_DIV, .left = a, .right = b); } public @@ -380,29 +359,19 @@ Real_t Real$mod(Real_t n, Real_t modulus) { } } - rational_t *res = GC_MALLOC(sizeof(rational_t)); - mpq_init(&res->value); - mpq_set(&res->value, result); + __mpq_struct ret; + mpq_init(&ret); + mpq_set(&ret, result); mpq_clear(quotient); mpq_clear(floored); mpq_clear(result); mpz_clear(floor_z); - - Real_t ret = {.rational = res}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + return mpq_to_real(ret); } // Fallback to symbolic - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_MOD; - sym->left = n; - sym->right = modulus; - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_MOD, .left = n, .right = modulus); } public @@ -455,31 +424,21 @@ Real_t Real$sqrt(Real_t a) { mpz_sqrt(num_sqrt, mpq_numref(&r->value)); mpz_sqrt(den_sqrt, mpq_denref(&r->value)); - rational_t *result = GC_MALLOC(sizeof(rational_t)); - mpq_init(&result->value); - mpq_set_num(&result->value, num_sqrt); - mpq_set_den(&result->value, den_sqrt); - mpq_canonicalize(&result->value); + __mpq_struct ret; + mpq_init(&ret); + mpq_set_num(&ret, num_sqrt); + mpq_set_den(&ret, den_sqrt); + mpq_canonicalize(&ret); mpz_clear(num_sqrt); mpz_clear(den_sqrt); - - Real_t ret = {.rational = result}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + return mpq_to_real(ret); } mpz_clear(num_sqrt); mpz_clear(den_sqrt); } - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_SQRT; - sym->left = a; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_SQRT, .left = a, .right = R(0)); } // Because the libm implementation of pow() is often inexact for common @@ -519,14 +478,7 @@ Real_t Real$power(Real_t base, Real_t exp) { } } - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_POW; - sym->left = base; - sym->right = exp; - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_POW, .left = base, .right = exp); } // Helper function for binary functions @@ -752,7 +704,7 @@ OptionalReal_t Real$parse(Text_t text, Text_t *remainder) { } if (digits > 0) { - // n = int_part + 10^digits * fractional_part + // n = int_part + fractional_part / 10^digits OptionalInt_t fractional_part = Int$parse(text, I(10), &after_decimal); if (fractional_part.small != 0 && !Int$is_zero(fractional_part)) { Real_t frac = Real$from_int(fractional_part); @@ -863,13 +815,11 @@ Real_t Real$negative(Real_t a) { if (!Real$is_boxed(a)) return R(-REAL_DOUBLE(a)); if (Real$tag(a) == REAL_TAG_RATIONAL) { - rational_t *r = REAL_RATIONAL(a); - rational_t *result = GC_MALLOC(sizeof(rational_t)); - mpq_init(&result->value); - mpq_neg(&result->value, &r->value); - Real_t ret = {.rational = result}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + rational_t *rat = REAL_RATIONAL(a); + __mpq_struct ret; + mpq_init(&ret); + mpq_neg(&ret, &rat->value); + return mpq_to_real(ret); } return Real$times(R(-1.0), a); @@ -878,33 +828,33 @@ Real_t Real$negative(Real_t a) { public Real_t Real$rounded_to(Real_t x, Real_t round_to) { // Convert to rationals for exact computation - rational_t *rx = GC_MALLOC(sizeof(rational_t)); - rational_t *rr = GC_MALLOC(sizeof(rational_t)); - mpq_init(&rx->value); - mpq_init(&rr->value); + __mpq_struct rx; + mpq_init(&rx); // Convert x to rational if (!Real$is_boxed(x)) { - mpq_set_d(&rx->value, REAL_DOUBLE(x)); + mpq_set_d(&rx, REAL_DOUBLE(x)); } else if (Real$tag(x) == REAL_TAG_RATIONAL) { - mpq_set(&rx->value, &REAL_RATIONAL(x)->value); + mpq_set(&rx, &REAL_RATIONAL(x)->value); } else { - mpq_set_d(&rx->value, Real$as_float64(x, true)); + mpq_set_d(&rx, Real$as_float64(x, true)); } + __mpq_struct rr; + mpq_init(&rr); // Convert round_to to rational if (!Real$is_boxed(round_to)) { - mpq_set_d(&rr->value, REAL_DOUBLE(round_to)); + mpq_set_d(&rr, REAL_DOUBLE(round_to)); } else if (Real$tag(round_to) == REAL_TAG_RATIONAL) { - mpq_set(&rr->value, &REAL_RATIONAL(round_to)->value); + mpq_set(&rr, &REAL_RATIONAL(round_to)->value); } else { - mpq_set_d(&rr->value, Real$as_float64(round_to, true)); + mpq_set_d(&rr, Real$as_float64(round_to, true)); } // Compute x / round_to mpq_t quotient; mpq_init(quotient); - mpq_div(quotient, &rx->value, &rr->value); + mpq_div(quotient, &rx, &rr); // Round to nearest integer using mpz_fdiv_qr for exact rounding mpz_t rounded, remainder; @@ -922,21 +872,18 @@ Real_t Real$rounded_to(Real_t x, Real_t round_to) { mpz_fdiv_q(rounded, doubled_num, remainder); // Multiply back: rounded * round_to - rational_t *result = GC_MALLOC(sizeof(rational_t)); - mpq_init(&result->value); - mpq_set_z(&result->value, rounded); - mpq_mul(&result->value, &result->value, &rr->value); + __mpq_struct ret; + mpq_init(&ret); + mpq_set_z(&ret, rounded); + mpq_mul(&ret, &ret, &rr); - mpq_clear(&rx->value); - mpq_clear(&rr->value); + mpq_clear(&rx); + mpq_clear(&rr); mpq_clear(quotient); mpz_clear(rounded); mpz_clear(remainder); mpz_clear(doubled_num); - - Real_t ret = {.rational = result}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + return mpq_to_real(ret); } // Trigonometric functions - return symbolic expressions @@ -949,16 +896,7 @@ Real_t Real$sin(Real_t x) { return R(result); } } - - // Create symbolic expression - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_SIN; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_SIN, .left = x, .right = R(0)); } public @@ -969,15 +907,7 @@ Real_t Real$cos(Real_t x) { return R(result); } } - - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_COS; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_COS, .left = x, .right = R(0)); } public @@ -986,15 +916,7 @@ Real_t Real$tan(Real_t x) { double result = tan(REAL_DOUBLE(x)); if (result == 0.0) return R(0.0); } - - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_TAN; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_TAN, .left = x, .right = R(0)); } public @@ -1003,15 +925,7 @@ Real_t Real$asin(Real_t x) { double result = asin(REAL_DOUBLE(x)); if (result == 0.0) return R(0.0); } - - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_ASIN; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_ASIN, .left = x, .right = R(0)); } public @@ -1020,15 +934,7 @@ Real_t Real$acos(Real_t x) { double result = acos(REAL_DOUBLE(x)); if (result == 0.0) return R(0.0); } - - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_ACOS; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_ACOS, .left = x, .right = R(0)); } public @@ -1037,15 +943,7 @@ Real_t Real$atan(Real_t x) { double result = atan(REAL_DOUBLE(x)); if (result == 0.0) return R(0.0); } - - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_ATAN; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_ATAN, .left = x, .right = R(0)); } public @@ -1054,15 +952,7 @@ Real_t Real$atan2(Real_t y, Real_t x) { double result = atan2(REAL_DOUBLE(y), REAL_DOUBLE(x)); if (result == 0.0) return R(0.0); } - - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_ATAN2; - sym->left = y; - sym->right = x; - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_ATAN2, .left = y, .right = x); } public @@ -1074,15 +964,7 @@ Real_t Real$exp(Real_t x) { return R(result); } } - - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_EXP; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_EXP, .left = x, .right = R(0)); } public @@ -1094,15 +976,7 @@ Real_t Real$log(Real_t x) { return R(result); } } - - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_LOG; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_LOG, .left = x, .right = R(0)); } public @@ -1114,15 +988,7 @@ Real_t Real$log10(Real_t x) { return R(result); } } - - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_LOG10; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_LOG10, .left = x, .right = R(0)); } public @@ -1133,22 +999,12 @@ Real_t Real$abs(Real_t x) { if (Real$tag(x) == REAL_TAG_RATIONAL) { rational_t *r = REAL_RATIONAL(x); - rational_t *result = GC_MALLOC(sizeof(rational_t)); - mpq_init(&result->value); - mpq_abs(&result->value, &r->value); - Real_t ret = {.rational = result}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + __mpq_struct ret; + mpq_init(&ret); + mpq_abs(&ret, &r->value); + return mpq_to_real(ret); } - - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_ABS; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_ABS, .left = x, .right = R(0)); } public @@ -1160,27 +1016,18 @@ Real_t Real$floor(Real_t x) { if (Real$tag(x) == REAL_TAG_RATIONAL) { rational_t *r = REAL_RATIONAL(x); - mpz_t result; - mpz_init(result); - mpz_fdiv_q(result, mpq_numref(&r->value), mpq_denref(&r->value)); - - rational_t *rat = GC_MALLOC(sizeof(rational_t)); - mpq_init(&rat->value); - mpq_set_z(&rat->value, result); - mpz_clear(result); - Real_t ret = {.rational = rat}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + mpz_t quotient; + mpz_init(quotient); + mpz_fdiv_q(quotient, mpq_numref(&r->value), mpq_denref(&r->value)); + + __mpq_struct ret; + mpq_init(&ret); + mpq_set_z(&ret, quotient); + mpz_clear(quotient); + return mpq_to_real(ret); } - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_FLOOR; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_FLOOR, .left = x, .right = R(0)); } public @@ -1191,27 +1038,18 @@ Real_t Real$ceil(Real_t x) { if (Real$tag(x) == REAL_TAG_RATIONAL) { rational_t *r = REAL_RATIONAL(x); - mpz_t result; - mpz_init(result); - mpz_cdiv_q(result, mpq_numref(&r->value), mpq_denref(&r->value)); - - rational_t *rat = GC_MALLOC(sizeof(rational_t)); - mpq_init(&rat->value); - mpq_set_z(&rat->value, result); - mpz_clear(result); - Real_t ret = {.rational = rat}; - ret.bits |= REAL_TAG_RATIONAL; - return ret; + mpz_t quotient; + mpz_init(quotient); + mpz_cdiv_q(quotient, mpq_numref(&r->value), mpq_denref(&r->value)); + + __mpq_struct ret; + mpq_init(&ret); + mpq_set_z(&ret, quotient); + mpz_clear(quotient); + return mpq_to_real(ret); } - symbolic_t *sym = GC_MALLOC(sizeof(symbolic_t)); - sym->op = SYM_CEIL; - sym->left = x; - sym->right = R(0); - - Real_t ret = {.symbolic = sym}; - ret.bits |= REAL_TAG_SYMBOLIC; - return ret; + return sym_to_real(.op = SYM_CEIL, .left = x, .right = R(0)); } public |
