Skip to content

Commit

Permalink
added pow_I
Browse files Browse the repository at this point in the history
  • Loading branch information
FROGGS committed Jul 14, 2013
1 parent 4577ad3 commit 3ed32f9
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 4 deletions.
1 change: 1 addition & 0 deletions lib/MAST/Ops.nqp
Expand Up @@ -2087,6 +2087,7 @@ class MAST::Ops {
$MVM_operand_write_reg +| $MVM_operand_obj,
$MVM_operand_read_reg +| $MVM_operand_obj,
$MVM_operand_read_reg +| $MVM_operand_obj,
$MVM_operand_read_reg +| $MVM_operand_obj,
$MVM_operand_read_reg +| $MVM_operand_obj
]
),
Expand Down
2 changes: 1 addition & 1 deletion nqp-cc/src/QASTOperationsMAST.nqp
Expand Up @@ -1328,7 +1328,7 @@ QAST::MASTOperations.add_core_moarop_mapping('neg_i', 'neg_i');
QAST::MASTOperations.add_core_moarop_mapping('neg_I', 'neg_I');
QAST::MASTOperations.add_core_moarop_mapping('neg_n', 'neg_n');
QAST::MASTOperations.add_core_moarop_mapping('pow_n', 'pow_n');
#QAST::MASTOperations.add_core_moarop_mapping('pow_I', 'nqp_bigint_pow', 'PPPPP');
QAST::MASTOperations.add_core_moarop_mapping('pow_I', 'pow_I');
QAST::MASTOperations.add_core_moarop_mapping('abs_i', 'abs_i');
QAST::MASTOperations.add_core_moarop_mapping('abs_I', 'abs_I');
QAST::MASTOperations.add_core_moarop_mapping('abs_n', 'abs_n');
Expand Down
14 changes: 14 additions & 0 deletions src/core/interp.c
Expand Up @@ -1611,6 +1611,20 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
cur_op += 8;
break;
}
case MVM_OP_pow_I: {
MVMObject *a = GET_REG(cur_op, 2).o, *b = GET_REG(cur_op, 4).o, *type = GET_REG(cur_op, 6).o;
MVMROOT(tc, a, {
MVMROOT(tc, b, {
MVMROOT(tc, type, {
MVMObject *c = MVM_repr_alloc_init(tc, type);
MVM_bigint_pow(c, a, b);
GET_REG(cur_op, 0).o = c;
});
});
});
cur_op += 10;
break;
}
case MVM_OP_cmp_I: {
MVMObject *a = GET_REG(cur_op, 2).o, *b = GET_REG(cur_op, 4).o;
GET_REG(cur_op, 0).i64 = MVM_bigint_cmp(a, b);
Expand Down
2 changes: 1 addition & 1 deletion src/core/oplist
Expand Up @@ -272,7 +272,7 @@ BANK 3 math
0x24 bnot_I w(obj) r(obj) r(obj)
0x25 blshift_I w(obj) r(obj) r(int64) r(obj)
0x26 brshift_I w(obj) r(obj) r(int64) r(obj)
0x27 pow_I w(obj) r(obj) r(obj) r(obj)
0x27 pow_I w(obj) r(obj) r(obj) r(obj) r(obj)
0x28 gcd_I w(obj) r(obj) r(obj) r(obj)
0x29 lcm_I w(obj) r(obj) r(obj) r(obj)
0x2A expmod_I w(obj) r(obj) r(obj) r(obj) r(obj)
Expand Down
4 changes: 2 additions & 2 deletions src/core/ops.c
Expand Up @@ -1619,8 +1619,8 @@ static MVMOpInfo MVM_op_info_math[] = {
{
MVM_OP_pow_I,
"pow_I",
4,
{ MVM_operand_write_reg | MVM_operand_obj, MVM_operand_read_reg | MVM_operand_obj, MVM_operand_read_reg | MVM_operand_obj, MVM_operand_read_reg | MVM_operand_obj }
5,
{ MVM_operand_write_reg | MVM_operand_obj, MVM_operand_read_reg | MVM_operand_obj, MVM_operand_read_reg | MVM_operand_obj, MVM_operand_read_reg | MVM_operand_obj, MVM_operand_read_reg | MVM_operand_obj }
},
{
MVM_OP_gcd_I,
Expand Down
71 changes: 71 additions & 0 deletions src/math/bigintops.c
@@ -1,4 +1,34 @@
#include "moarvm.h"
#include <math.h>

static double mp_get_double(mp_int *a) {
double d = 0.0;
double sign = SIGN(a) == MP_NEG ? -1.0 : 1.0;
int i;
if (USED(a) == 0)
return d;
if (USED(a) == 1)
return sign * (double) DIGIT(a, 0);

mp_clamp(a);
i = USED(a) - 1;
d = (double) DIGIT(a, i);
i--;
if (i == -1) {
return sign * d;
}
d *= pow(2.0, DIGIT_BIT);
d += (double) DIGIT(a, i);

if (USED(a) > 2) {
i--;
d *= pow(2.0, DIGIT_BIT);
d += (double) DIGIT(a, i);
}

d *= pow(2.0, DIGIT_BIT * i);
return sign * d;
}

static mp_int * MVM_get_bigint(MVMObject *obj) {
return &((P6bigint *)obj)->body.i;
Expand Down Expand Up @@ -52,6 +82,47 @@ void MVM_bigint_div(MVMObject *c, MVMObject *a, MVMObject *b) {
mp_div(ia, ib, ic, NULL);
}

void MVM_bigint_pow(MVMObject *c, MVMObject *a, MVMObject *b) {
mp_int *base = MVM_get_bigint(a);
mp_int *exponent = MVM_get_bigint(b);
mp_int *ic = MVM_get_bigint(c);
mp_digit exponent_d = 0;
int cmp = mp_cmp_d(exponent, 0);
mp_init(ic);

if (((cmp == MP_EQ) || (MP_EQ == mp_cmp_d(base, 1)))) {
mp_set_int(ic, 1);
}
else {
if ((cmp == MP_GT)) {
exponent_d = mp_get_int(exponent);
if ((MP_GT == mp_cmp_d(exponent, exponent_d))) {
cmp = mp_cmp_d(base, 0);
if (((MP_EQ == cmp) || (MP_EQ == mp_cmp_d(base, 1)))) {
mp_copy(base, ic);
}
else {
double ZERO = 0.0;
if ((MP_GT == cmp)) {
mp_set_int(ic, (double)1.0 / ZERO);
}
else {
mp_set_int(ic, (double)(-1.0) / ZERO);
}
}
}
else {
mp_expt_d(base, exponent_d, ic);
}
}
else {
double f_base = mp_get_double(base);
double f_exp = mp_get_double(exponent);
mp_set_int(ic, pow(f_base, f_exp));
}
}
}

void MVM_bigint_shl(MVMObject *b, MVMObject *a, MVMint64 n) {
mp_int *ia = MVM_get_bigint(a);
mp_int *ib = MVM_get_bigint(b);
Expand Down
1 change: 1 addition & 0 deletions src/math/bigintops.h
Expand Up @@ -9,6 +9,7 @@ void MVM_bigint_sub(MVMObject *c, MVMObject *a, MVMObject *b);
void MVM_bigint_mul(MVMObject *c, MVMObject *a, MVMObject *b);
void MVM_bigint_div(MVMObject *c, MVMObject *a, MVMObject *b);
void MVM_bigint_mod(MVMObject *c, MVMObject *a, MVMObject *b);
void MVM_bigint_pow(MVMObject *c, MVMObject *a, MVMObject *b);
void MVM_bigint_gcd(MVMObject *c, MVMObject *a, MVMObject *b);
void MVM_bigint_lcm(MVMObject *c, MVMObject *a, MVMObject *b);

Expand Down

0 comments on commit 3ed32f9

Please sign in to comment.