9
my $knowhow := nqp::knowhow();
10
my $bi_type := $knowhow.new_type(:name('TestBigInt'), :repr('P6bigint'));
11
$bi_type.HOW.compose($bi_type);
12
sub str($x) { nqp::tostr_I($x) };
13
sub iseq($x, $y) { nqp::iseq_I($x, nqp::box_i($y, $bi_type)) }
14
sub box($x) { nqp::box_i($x, $bi_type) }
18
my $b := nqp::fromstr_I('-123', $one);
21
ok(str($b) eq '-123', 'can round-trip negative number (string)');
22
ok(str($c) eq '-123', 'can round-trip negative number (string) by boxing');
23
ok(nqp::unbox_i($b) == -123, 'can round-trip negative number by unboxing');
24
ok(!nqp::iseq_I($one, $b), 'nqp::iseq_I can return false');
25
ok(nqp::iseq_I($one, $one), 'nqp::iseq_I can return true');
26
ok(iseq(nqp::mul_I($b, $b, $b), 15129,), 'multiplication');
27
ok(iseq(nqp::add_I($b, $b, $b), -246,), 'addition');
28
ok(nqp::iseq_I(nqp::sub_I($b, $b, $b), nqp::box_i(0, $bi_type)), 'subtraction');
29
ok(nqp::iseq_I(nqp::div_I($b, $b, $b), $one), 'division');
31
ok(iseq(nqp::bitshiftl_I($one, 3, $one), 8), 'bitshift left');
32
ok(iseq($one, 1), 'original not modified by bitshift left');
33
ok(iseq(nqp::bitshiftr_I(box(16), 4, $one), 1), 'bitshift right');
35
ok(iseq(nqp::bitand_I(box(0xdead), box(0xbeef), $one), 0x9ead), 'bit and');
36
ok(iseq(nqp::bitor_I( box(0xdead), box(0xbeef), $one), 0xfeef), 'bit or');
37
ok(iseq(nqp::bitxor_I(box(0xdead), box(0xbeef), $one), 0x6042), 'bit xor');
39
ok(iseq(nqp::bitneg_I(box(-123), $one), 122), 'bit negation');
41
ok(iseq(nqp::bitand_I(nqp::fromstr_I('-1073741825', $one), $one, $one), 1),
42
'Bit ops (RT 109740)');
44
# Now we'll create a type that boxes a P6bigint.
45
my $bi_boxer := NQPClassHOW.new_type(:name('TestPerl6Int'), :repr('P6opaque'));
46
$bi_boxer.HOW.add_attribute($bi_boxer, NQPAttribute.new(
47
:name('$!value'), :type($bi_type), :box_target(1)
49
$bi_boxer.HOW.add_parent($bi_boxer, NQPMu);
50
$bi_boxer.HOW.compose($bi_boxer);
52
# Try some basic operations with it.
53
my $box_val_1 := nqp::box_i(4, $bi_boxer);
54
ok(iseq($box_val_1, 4), 'can box to a complex type with a P6bigint target');
55
my $box_val_2 := nqp::fromstr_I('38', $bi_boxer);
56
ok(iseq($box_val_2, 38), 'can get a bigint from a string with boxing type');
57
ok(iseq(nqp::add_I($box_val_1, $box_val_2, $bi_boxer), 42), 'addition works on boxing type');
60
# Note that the last argument to pow_I should be capable of boxing a num,
61
# so $bi_type is wrong here. But so far we only test the integer case,
62
# so we can get away with it.
63
my $big := nqp::pow_I($c, box(42), $bi_type, $bi_type);
64
ok(str($big) eq '5970554685064519004265641008828923248442340700473500698131071806779372733915289638628729', 'pow (int, positive)');
65
ok(iseq(nqp::pow_I(box(0), $big, $bi_type, $bi_type), 0), 'pow 0 ** large_number');
66
ok(iseq(nqp::pow_I($one, $big, $bi_type, $bi_type), 1), 'pow 1 ** large_number');
68
# test conversion to float
69
# try it with 2 ** 100, because that's big enough not to fit into a single
70
# int, but can be represented exactly in a double
71
$big := nqp::pow_I(box(2), box(100), $bi_type, $bi_type);
72
ok(nqp::iseq_n(nqp::tonum_I($big), nqp::pow_n(2, 100)), '2**100 to float');
73
$big := nqp::pow_I(box(-2), box(101), $bi_type, $bi_type);
74
ok(nqp::iseq_n(nqp::tonum_I($big), nqp::pow_n(-2, 101)), '(-2)**101 to float');
75
# the mantissa can hold much information accurately, so test that too
76
my $factor := 123456789;
77
$big := nqp::mul_I($big, box($factor), $bi_type);
78
ok(nqp::iseq_n(nqp::tonum_I($big), nqp::mul_n($factor, nqp::pow_n(-2, 101))), "$factor * (-2)**101 to float");
81
my $converted := nqp::tonum_I(nqp::fromstr_I('10000000000000000', $bi_type));
82
ok(nqp::abs_n($big - $converted) / $big < 1e-4, 'bigint -> float, 1e16');
84
my $float := 123456789e240;
85
ok(nqp::iseq_n($float, nqp::tonum_I(nqp::fromnum_I($float, $bi_type))),
86
'to_num and from_num round-trip');
87
my $small_float := 1e3;
88
ok(nqp::iseq_n($small_float, nqp::tonum_I(nqp::fromnum_I($small_float, $bi_type))),
89
'to_num and from_num round-trip on small floats');
90
my $medium_float := 1e14;
91
ok(nqp::iseq_n($medium_float, nqp::tonum_I(nqp::fromnum_I($medium_float, $bi_type))),
92
'to_num and from_num round-trip on medium sized floats');
94
ok(nqp::iseq_n($float, nqp::tonum_I(nqp::fromnum_I($float, $bi_type))),
95
'to_num and from_num round-trip (negative number)');
97
ok(nqp::base_I(box(-1234), 10) eq '-1234', 'base_I with base 10');
98
ok(nqp::base_I(box(-1234), 16) eq '-4D2', 'base_I with base 16');
100
ok(str(nqp::expmod_I(
101
nqp::fromstr_I('2988348162058574136915891421498819466320163312926952423791023078876139', $bi_type),
102
nqp::fromstr_I('2351399303373464486466122544523690094744975233415544072992656881240319', $bi_type),
103
nqp::fromstr_I('10000000000000000000000000000000000000000', $bi_type),
105
)) eq '1527229998585248450016808958343740453059', 'nqp::expmod_I');
107
ok(nqp::div_In(box(1234500), box(100)) == 12345, 'div_In santiy');
108
my $n := nqp::div_In(
109
nqp::pow_I(box(203), box(200), $bi_type, $bi_type),
110
nqp::pow_I(box(200), box(200), $bi_type, $bi_type),
112
ok(nqp::abs_n($n - 19.6430286394751) < 1e-10, 'div_In with big numbers');
114
my $maxRand := nqp::fromstr_I('10000000000000000000000000000000000000000', $bi_type);
115
my $rand := nqp::rand_I($maxRand, $bi_type);
116
ok(nqp::isle_I(box(0), $rand) && nqp::islt_I($rand, $maxRand), 'nqp::rand_I');
118
ok(nqp::isprime_I(box(-4), 1) == 0, 'is -4 prime');
119
ok(nqp::isprime_I(box(0), 1) == 0, 'is 0 prime');
120
ok(nqp::isprime_I(box(1), 1) == 0, 'is 1 prime');
121
ok(nqp::isprime_I(box(2), 1) == 1, 'is 2 prime');
122
ok(nqp::isprime_I(box(4), 1) == 0, 'is 4 prime');
123
ok(nqp::isprime_I(box(17), 1) == 1, 'is 17 prime');
125
ok(nqp::iseq_I(nqp::gcd_I(box(18), box(12), $bi_type), box(6)), 'nqp::gcd_I');
126
ok(nqp::iseq_I(nqp::lcm_I(box(18), box(12), $bi_type), box(36)), 'nqp::lcm_I');
128
ok(nqp::bool_I(box(42)), 'bool_I(42)');
129
ok(!nqp::bool_I(box(0)), 'bool_I(0)');