Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
add nqp::div_In opcode
It smart-ish-ly divides two big integers and returns a double.
  • Loading branch information
moritz committed Feb 13, 2012
1 parent fd864b6 commit 7f521e3
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/PAST/NQP.pir
Expand Up @@ -450,6 +450,7 @@ entry to produce the node to be returned.
maphash['mul_n'] = 'mul__Nnn'
maphash['div_i'] = 'div__Iii'
maphash['div_I'] = 'nqp_bigint_div__PPPP'
maphash['div_In'] = 'nqp_bigint_div_num__NPP'
maphash['div_n'] = 'div__Nnn'
maphash['mod_i'] = 'mod__Iii'
maphash['mod_I'] = 'nqp_bigint_mod__PPPP'
Expand Down
19 changes: 19 additions & 0 deletions src/ops/nqp_bigint.ops
Expand Up @@ -304,6 +304,25 @@ inline op nqp_bigint_from_num(out PMC, in NUM, in PMC) :base_core {
from_num($2, get_bigint(interp, $1));
}

inline op nqp_bigint_div_num(out NUM, in PMC, in PMC) :base_core {
mp_int *a = get_bigint(interp, $2);
mp_int *b = get_bigint(interp, $3);

int max_size = DIGIT_BIT * MAX(USED(a), USED(b));
if (max_size > 1023) {
mp_int reduced_a, reduced_b;
mp_init(&reduced_a);
mp_init(&reduced_b);
mp_div_2d(a, max_size - 1023, &reduced_a, NULL);
mp_div_2d(b, max_size - 1023, &reduced_b, NULL);
$1 = mp_get_double(&reduced_a) / mp_get_double(&reduced_b);
mp_clear(&reduced_a);
mp_clear(&reduced_b);
} else {
$1 = mp_get_double(a) / mp_get_double(b);
}
}

inline op nqp_bigint_shr(out PMC, in PMC, in INT, in PMC) :base_core {
mp_int *a = get_bigint(interp, $2);
$1 = REPR($4)->allocate(interp, STABLE($4));
Expand Down
9 changes: 8 additions & 1 deletion t/nqp/60-bigint.t
@@ -1,7 +1,7 @@
#! nqp
use nqpmo;

plan(32);
plan(34);

my $knowhow := pir::get_knowhow__P();
my $bi_type := $knowhow.new_type(:name('TestBigInt'), :repr('P6bigint'));
Expand Down Expand Up @@ -93,3 +93,10 @@ ok(str(nqp::expmod_I(
nqp::fromstr_I('10000000000000000000000000000000000000000', $bi_type),
$bi_type,
)) eq '1527229998585248450016808958343740453059', 'nqp::expmod_I');

ok(nqp::div_In(box(1234500), box(100)) == 12345, 'div_In santiy');
my $n := nqp::div_In(
nqp::pow_I(box(203), box(200), $bi_type, $bi_type),
nqp::pow_I(box(200), box(200), $bi_type, $bi_type),
);
ok(nqp::abs_n($n - 19.6430286394751) < 1e-10, 'div_In with big numbers');

0 comments on commit 7f521e3

Please sign in to comment.