Support ^ exponentiation for integers
This commit is contained in:
parent
aaac5dff28
commit
e0223a4c20
@ -291,6 +291,17 @@ public Int_t Int$abs(Int_t x)
|
||||
return Int$from_mpz(result);
|
||||
}
|
||||
|
||||
public Int_t Int$power(Int_t base, Int_t exponent)
|
||||
{
|
||||
int64_t exp = Int$as_i64(exponent);
|
||||
if (__builtin_expect(exp < 0, 0))
|
||||
fail("Cannot take a negative power of an integer!");
|
||||
mpz_t result;
|
||||
mpz_init_set_int(result, base);
|
||||
mpz_pow_ui(result, result, exp);
|
||||
return Int$from_mpz(result);
|
||||
}
|
||||
|
||||
public Int_t Int$random(Int_t min, Int_t max) {
|
||||
int32_t cmp = Int$compare(&min, &max, &$Int);
|
||||
if (cmp > 0)
|
||||
|
@ -59,6 +59,7 @@ Int_t Int$random(Int_t min, Int_t max);
|
||||
Range_t Int$to(Int_t from, Int_t to);
|
||||
Int_t Int$from_text(CORD text);
|
||||
Int_t Int$abs(Int_t x);
|
||||
Int_t Int$power(Int_t base, Int_t exponent);
|
||||
|
||||
#define BIGGEST_SMALL_INT ((1<<29)-1)
|
||||
|
||||
@ -72,11 +73,13 @@ Int_t Int$abs(Int_t x);
|
||||
}))
|
||||
|
||||
#define mpz_init_set_int(mpz, i) do { \
|
||||
if ((i).small & 1) mpz_init_set_si(mpz, (i).small >> 2); \
|
||||
if (__builtin_expect((i).small & 1, 1)) mpz_init_set_si(mpz, (i).small >> 2); \
|
||||
else mpz_init_set(mpz, *(i).big); \
|
||||
} while (0)
|
||||
|
||||
#define Int$as_i64(i) (((i).small & 1) ? (int64_t)((i).small >> 2) : mpz_get_si(*(i).big))
|
||||
#define Int$as_i64(i) (__builtin_expect((i).small & 1, 1) ? (int64_t)((i).small >> 2) : \
|
||||
({ if (!__builtin_expect(mpz_fits_slong_p(*(i).big), 1)) fail("Integer is too big to fit in a 64-bit integer!"); \
|
||||
mpz_get_si(*(i).big); }))
|
||||
Int_t Int$from_i64(int64_t i);
|
||||
Int_t Int$from_num(double n);
|
||||
double Int$as_num(Int_t i);
|
||||
|
@ -1351,7 +1351,7 @@ CORD compile_math_method(env_t *env, binop_e op, ast_t *lhs, ast_t *rhs, type_t
|
||||
break;
|
||||
}
|
||||
case BINOP_POWER: {
|
||||
if (rhs_t->tag == NumType) {
|
||||
if (rhs_t->tag == NumType || rhs_t->tag == IntType) {
|
||||
binding_t *b = get_namespace_binding(env, lhs, binop_method_names[op]);
|
||||
if (binding_works(b, lhs_t, rhs_t, lhs_t))
|
||||
return CORD_all(b->code, "(", compile(env, lhs), ", ", compile(env, rhs), ")");
|
||||
|
@ -107,6 +107,7 @@ env_t *new_compilation_unit(CORD *libname)
|
||||
{"negative", "Int$negative", "func(x:Int)->Int"},
|
||||
{"negated", "Int$negated", "func(x:Int)->Int"},
|
||||
{"abs", "Int$abs", "func(x:Int)->Int"},
|
||||
{"power", "Int$power", "func(base:Int,exponent:Int)->Int"},
|
||||
)},
|
||||
{"Int64", Type(IntType, .bits=64), "Int64_t", "$Int64", TypedArray(ns_entry_t,
|
||||
{"format", "Int64$format", "func(i:Int64, digits=0)->Text"},
|
||||
|
@ -899,7 +899,7 @@ type_t *get_type(env_t *env, ast_t *ast)
|
||||
break;
|
||||
}
|
||||
case BINOP_POWER: {
|
||||
if (rhs_t->tag == NumType && binding_works(binop_method_names[binop->op], binop->lhs, lhs_t, rhs_t, lhs_t))
|
||||
if ((rhs_t->tag == NumType || rhs_t->tag == IntType) && binding_works(binop_method_names[binop->op], binop->lhs, lhs_t, rhs_t, lhs_t))
|
||||
return lhs_t;
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user